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 control character, UNIX uses the line-feed character (ASCII 10),
 Macs use carriage-control (ASCII 13), PCs use a carriage-control/
 line-feed combination. Technically, each line is a delimited record. 

 On record-oriented file systems (e.g. VMS, IBM mainframes) each line 
 is a variable-size or fixed-size record. See the chapter on Files 
 and records for more details on the subject.

 When a terminal/printer receives a sequence of records, it is supposed
 to start a new line after processing each record, so each of them will
 be displayed/printed on a separate line. 

 Theoretically 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,
          this may be possible with a printers. 

 Option #3 is the most general, and gives maximal 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, e.g. viewing 
 a file written by a FORTRAN program. The FORTRAN compiler can only 
 affect I/O performed by a running FORTRAN program, i.e. interactive I/O.

 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 that implemented FCC (IBM mainframes). 
 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 the devices, and the FORTRAN 77 standard evaded the issue by 
 requiring an implementation (by the ASA method) only for "printers", 
 but intentionally left the 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 must take 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              Possible implementation
   -----------------    ----------------    -----------------------
        Space           Normal behaviour    printing/CR/LF
          0             Double spacing      LF/printing/CR/LF
          +             Overwrite mode      CR/printing/CR/LF
          1             Next page           m*LF/CR/LF/n*LF/printing/CR/LF

 Remarks:

   1) m,n  are integers dependant on the number of lines in the "page", 
      and subject to bounds that are implementation defined.

   2) On program startup an extra CR is sent

   3) You can check the behaviour of your system with a terminal that 
      have a "display controls mode" (e.g. VTs), in this mode the 
      control characters are displayed instead of being interpreted.

 In summary, 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. 


 Using and working around Fortran carriage-control
 -------------------------------------------------
 Fortran carriage-control (FCC) 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".

 If your system supports FCC, and you want to use it, and don't 
 mind being old-fashioned, you may do:

      WRITE(UNIT=*, FMT='(A/)')  '1 This is a page header'

 or maybe:

      CHARACTER   FF*1
      PARAMETER   (FF = '1')
      ......................
      WRITE(UNIT=*, FMT='(A1,A/)')  FF, ' This is a page header'

 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).

 What about programs that do use Fortran Carriage Control, but the
 operating system doesn't support it?  There is usually a "filter" 
 utility to handle this, for example:

   UNIX-prompt>  a.out | asa 

 In System V derived UNIX systems the name "asa" is used, BSD derived
 systems use the name "fpr".

    Operating  | Interactive |  Viewing   |  Printing  |  Converter  |
     System    |  session    |   files    |   files    |   utility   |
               |  support    |  support   |  support   |             |
   ------------|-------------|------------|------------|-------------|
    VMS        |  Yes        |  Yes       |  Yes       | Not needed  |
   ------------|-------------|------------|------------|-------------|
    SunOS      |             |  No        |  No        |  fpr        |
    Solaris    |             |            |            |             |
   ------------|-------------|------------|------------|-------------|
    IRIX       |             |            |            |  asa        |
   ------------|-------------|------------|------------|-------------|
    AIX        |             |            |            |  asa        |
   ------------|-------------|------------|------------|-------------|


 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.


 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 I/O '
      WRITE(*,*)     ' ================= '
C     ------------------------------------------------------------------
      WRITE(*,*)     ' Writing line:  "+abcd"  (Overwrite Mode): '
      WRITE(*,*)     '+abcd'
      WRITE(*,*)
C     ------------------------------------------------------------------
      WRITE(*,*)     ' FORMATTED I/O '
      WRITE(*,*)     ' ============= '
C     ------------------------------------------------------------------
      WRITE(*,*)     ' Writing line = "xabcd"  (A non-control char): '
      WRITE(*,'(A)') 'xabcd'
      WRITE(*,*)
C     ------------------------------------------------------------------
      WRITE(*,*)     ' Writing line = " abcd"  (Normal Mode): '
      WRITE(*,'(A)') ' abcd'
      WRITE(*,*)
C     ------------------------------------------------------------------
      WRITE(*,*)     ' Writing line = "+abcd"  (Overwrite Mode): '
      WRITE(*,'(A)') '+abcd'
      WRITE(*,*)
C     ------------------------------------------------------------------
      WRITE(*,*)     ' Writing line = "0abcd"  (Double-spacing): '
      WRITE(*,'(A)') '0abcd'
      WRITE(*,*)
C     ------------------------------------------------------------------
      WRITE(*,*)     ' Writing line = "1abcd"  (New-page): '
      WRITE(*,'(A)') '1abcd'
      WRITE(*,*)
C     ------------------------------------------------------------------
      END



Return to contents page