2-14 FORTRAN carriage control
******************************
(Thanks to Clive Page for a clear discussion of this topic)
Many users find FORTRAN carriage control a confusing issue.
The origin and history of carriage control
------------------------------------------
Files intended to be displayed on a terminal screen or printed are
composed of lines, technically, these lines are records - sub-units
of data with well-defined boundaries, separated from each other.
On byte-oriented file systems (e.g. UNIX) lines are separated by a
line-feed character, i.e. each line is really a stream/LF record.
On record-oriented file systems (e.g. VMS) each line is a variable-size
or fixed-size record (see the chapter on Files and records).
When a terminal/printer receives a sequence of records, it usually
starts a new line after processing each record, so each of them is
displayed/printed on a separate line.
Generally, an output device may act in different ways upon reaching
the end of a line (in formatted I/O), for example:
1) Do nothing special and continue printing (No carriage control)
this is not very useful
2) Start a new line (Carriage-return carriage control),
this is the usual behaviour
3) Perform a user-selected action, one of the following:
a) Start a new line
b) Skip one line and start a new line (double space printing)
c) Start a new page
d) Over-write the previous line for special effects, e.g. create
the not-equal sign by superimposing the '=' and '/' signs
Option #3 is more general, and gives more control over the output,
you may say it supplements the horizontal formatting capabilities
of formatted I/O with 'vertical formatting'.
Note that carriage-control is supposed to be implemented by means
external to Fortran, i.e. the I/O sub-system itself (see below on VMS),
as it is supposed to apply also in non-FORTRAN contexts, i.e. viewing
a file written by a FORTRAN program.
The problem with #3 is that it requires support from the I/O subsystem
that some operating systems (e.g. UNIX, DOS) can't provide. Typically
record-oriented filesystems can support #3, and byte-oriented ones can't.
We will call option #3 Fortran Carriage Control (FCC), as it is now
used only in the context of Fortran, you might say that being included
into the Fortran standards artificially prolonged its life.
FORTRAN was designed on systems implementing FCC, as systems with
byte-oriented filesystems (e.g. UNIX) became more and more common,
it was impractical to require vendors to implement FCC for all devices,
and the FORTRAN 77 standard evaded the issue by requiring an implementation
(by the ASA method) only for "printers", but intentionally left the
device specification vague.
The ASA (American Standards Association) method
-----------------------------------------------
In this old carriage-control method (approved by ASA) the first
character in every line is not considered a part of the line,
but is used to control printing and screen display.
Using ASA you 'waste' one character (the first) in each record,
you can't use it for data, it is a "vertical formatting command".
List directed output sends an extra space character prepended
to the data to avoid truncation of the first data character.
Note that when you display a file and get to the end of
a line, two independent actions takes place:
Action Name CODE ASCII Action
--------------- ---- ----- ------------------------------------------
Carriage return CR 13 Go to the beginning of the current line
Line feed LF 10 Go down to the next line, at same column
A table of ASA codes:
Control character Effect
----------------- ------
Space Normal behaviour - printing/CR/LF
0 Double spacing - LF/printing/CR/LF
1 Next page - m*LF/CR/LF/n*LF/printing/CR/LF
+ Overwrite mode - CR/printing/CR/LF
m,n are implementation-defined integers
On program startup an extra CR is sent
When the ASA I/O scheme is in effect, the first character in the
line will be extracted and used to control the output, and will
not be displayed. For example, if the first character happened
to be a '+' the line will be written on top of the previous line.
The classical workaround for carriage-control
---------------------------------------------
Fortran carriage-control is a vertical "extension" of the ordinary
formats, Few programmers use it today, probably because UNIX systems
provide incomplete support, and the feature turned into a 'bug'.
You should begin 'output formats' that require no special processing
with a '1X', so a space character will be written at the beginning
of each line, and the 'normal' behavior will be produced.
'Input formats' reading files written with such format, should also
have an '1X', so on reading the extra space will be ignored.
By the way, list-directed I/O gives reasonable results on systems
that supports FCC by emulating Fortran carriage control (adding an
extra blank at the beginning of each record).
Another view of carriage-control
--------------------------------
The Fortran Standards (F77 and regrettably F90) both specify that
the first character has to be chopped off for any formatted record
sent to a 'printer' but don't define what a printer is (see the
table in the chapter: 'formatted/List-directed/unformatted I/O').
Unix and DOS systems don't have the VMS luxury of defining a special
file type for Fortran output (no file type concept at all, really),
so they have problems with this. Some define the user's terminal
screen as a printer, others do not. Indeed some systems like those
made by SUN seem to define all devices as being not a printer,
and never remove the first character. But they usually provide
a utility which chops the first char off each line and converts
it to a form-feed, or whatever. This utility may be called 'asa'
(posix standard spelling) or 'fpr' on BSD flavored/influenced systems.
Operating | Terminal | Printers | Converter |
System | affected | affected | utility |
------------|------------|------------|-------------|
VMS | Yes | Yes | Not needed |
------------|------------|------------|-------------|
SunOS | No | No | |
------------|------------|------------|-------------|
IRIX | | | asa |
------------|------------|------------|-------------|
------------|------------|------------|-------------|
The VMS implementation of ASA
-----------------------------
On a VMS machine, you usually meet the FORTRAN carriage control, when
you 'type' a file written by a FORTRAN program on the screen or print
it, and in some mysterious way the first character in every line is
missing, and/or some lines are completely missing or mixed up.
The VMS operating system knows that the file was written by a FORTRAN
program, and so has to be treated in a different way, if it has the
FORTRAN CARRIAGE CONTROL ATTRIBUTE that is kept with other information
on the file.
On VMS the default carriage control for files written by a FORTRAN
program is FORTRAN carriage control, you can make FORTRAN programs write
'normal' files if you OPEN them with:
CARRIAGECONTROL = 'LIST'
A small example program
-----------------------
PROGRAM CRCTRL
C ------------------------------------------------------------------
WRITE(*,*)
WRITE(*,*) ' LIST DIRECTED FORMAT '
WRITE(*,*) ' ==================== '
C ------------------------------------------------------------------
WRITE(*,*) ' line = "+x123456789" (seems the same): '
WRITE(*,*) '+x123456789'
WRITE(*,*)
C ------------------------------------------------------------------
WRITE(*,*) ' WITH A FORMAT '
WRITE(*,*) ' ============= '
C ------------------------------------------------------------------
WRITE(*,*) ' line = "x123456789" (nothing special): '
WRITE(*,'(A)') 'x123456789'
WRITE(*,*)
C ------------------------------------------------------------------
WRITE(*,*) ' line = "+x123456789" (overwrite): '
WRITE(*,'(A)') '+x123456789'
WRITE(*,*)
C ------------------------------------------------------------------
WRITE(*,*) ' line = "0x123456789" (double-space): '
WRITE(*,'(A)') '0x123456789'
WRITE(*,*)
C ------------------------------------------------------------------
WRITE(*,*) ' line = "1x123456789" (new-page): '
WRITE(*,'(A)') '1x123456789'
WRITE(*,*)
C ------------------------------------------------------------------
END
Return to contents page