UNIX Alternatives to the CMS Filedef

File attributes (lrecl, recfm, xtent, disp mod)

Under VS FORTRAN, the "filedef" statement is used to define certain file attributes prior to running a FORTRAN program. This is in place of using the FORTRAN "open" statement or the "fileinf" utility routine to define these attributes inside the program. Under UNIX, there is no command equivalent to the filedef and in most cases it is not needed. The filedef parameters typically used with the filedef statement under VS FORTRAN are the file name, lrecl, recfm, xtent,and disp mod.

Most computer systems require users to organize their files into records and blocks which reflect the way data is stored on disk. For example, on UDelVM, the default record size is 80 bytes. If you attempt to write a sequential file with records longer than 80 bytes you will get an error message indicating you have written beyond the end of the record. In UNIX, there is no default record size and no similar requirement exists for sequential files on UNIX. Sequential files are the most typical type of file used in FORTRAN programs.

For random access files (also called "direct access" files), you do need to define the record length under both VS FORTRAN and UNIX FORTRAN. In both cases, this is done in the open statement by using the "recl" parameter. This record length information is needed by the system to locate individual records in the file.

On UDelVM, your files may have fixed-length records or variable-length records. These are the two common "record formats" you are used to on UDelVM. On UNIX disk systems, records are always variable-length, so a UNIX parameter equivalent to the IBM "recfm" is not used.

For random access files under VS FORTRAN, the default number of records is 50. To reduce or increase the number of records below or above 50, one must use the filedef parameter "xtent". Under UNIX, a random access file will contain as few or as many logical records as the program generates and no parameter equivalent to xtent is required.

The "disp mod" filedef parameter is used in VS FORTRAN to append records to a sequential file. Under UNIX FORTRAN one uses the open statement's "access" parameter (access='append').


Naming an input or output file

Under VS FORTRAN, the name of a file that is associated with a unit number can be defined using the filedef command instead of the FORTRAN open statement. The filedef allows the file name to be defined external to the program, just prior to running the program. Under UNIX, the same thing can be accomplished in several ways.

The most straightforward solution is to use the "file" parameter to link an I/O unit with a file. For example, to associate the file "mydata" with unit 5, add the following statement to your FORTRAN program:

   open(5,file='mydata')
This can be done with any I/O unit number. However, since the statement is part of the source code, it cannot be changed at execution time. Several alternatives are next illustrated that give you execution-time flexibility.


I/O Units 5 and 6 - a special case

Units 5 and 6 are special cases. By default, unit 5 reads from UNIX's stdin, typically the terminal keyboard. However, a file's contents can be read instead by using the "<" redirection symbol. Unit 6 is defined to be UNIX's stdout, typically the terminal screen. Results sent to stdout can be redirected instead to a file by using the ">" redirection symbol. For example, if prog.exe reads from unit 5 and writes to unit 6, you can redirect the input and output from the terminal to files "in" and "out" by typing

   prog.exe   < in    > out 

Of the four alternatives described below, we recommend the first two over the second two.


Alternative 1

The program can prompt for the file name to be used in an open statement. First display a prompt for information. Then read the filename into a character variable. Finally, assign that value to the file parameter "file" in the open statement. For example,

   character filename*30
                  .
   print *, 'Enter the name of your input file'
   read(5,'(a)')) filename
   open(10,file=filename,.......)

Alternative 2

You can enter the names of files on the command line directing the program to be executed. The FORTRAN function "iargc", which computes the number of values on the command line, and the subroutine "getarg", which reads the values on the command line, can pull the file name(s) into the program to be used in an open statement.

   character*30 argv
           .
           .
           .
   m = iargc()
   i = 1
   do while (i.le.m)
     call getarg(i,argv)
     open(unit=i,file=argv,....)
     i=i+1
   end do
           .
           .
           .
For example, if the executable file "myprog.exe" contains this program segment, then the command

      
   myprog.exe   one.dat two.dat three.dat
will connect the files one.dat, two.dat and three.dat to I/O units 1, 2 and 3 at execution time.

CAUTION: This particular example works when the I/O unit numbers are 5 or lower.

Alternative 3

This method allows you to associate a filename of your choice with the default filename for a specific I/O unit. The syntax is similar to the UDelVM filedef statement. For example, to associate the file "myfile.dat" with I/O unit 3, type

 
   ln -s myfile.dat fort.3
This makes a "symbolic link" between your file "myfile.dat" and the default filename "fort.3" that UNIX FORTRAN creates for I/O unit 3. Thus, "fort.3" functions as an pointer to the real file "myfile.dat."

Once this "ln" command is issued, all subsequent I/O using unit 3 is associated with "myfile.dat". You can eliminate this link by erasing the symbolic link file. For example, type

 
   rm fort.3

NOTES:

We recommend that you remove these link files after you are finished using them to avoid possible unwanted results. For example, if a second program which directs output to unit 3 is run after the first program, the second output will be directed to the file to which unit 3 is linked and overwrite the contents of that file written by the first program.

This alternative does not work for units 5 and 6.

Alternative 4

Environment variables provide an alternative to the symbolic links described in alternative 3. Instead of associating the actual file (input.dat) with a symbolic link file (fort.1), you use an environment variable to associate the actual file (input.dat) with the name of the I/O unit.

As an example, the following program segment reads from unit 1 and writes to unit 2.

      .         
      .
   call ioinit(.true.,.false.,.false.,'fort.',.false.)
      .
      . 
   read(1,*)....
      .
   write(2,10)....
      .

Note:

The FORTRAN ioinit subroutine must be used exactly as specified. This usage is completely independent of how many or which I/O are used. Type

   man ioinit
for more information about the routine.

Before running the executable code, type the following statements to associate the file "input.data" with I/O unit 1 and "output.data" with I/O unit 2. Note that this alternative uses the naming convention fort.01, fort.02, etc. rather than the convention fort.1, fort.2, etc. used in alternative 3.

   setenv fort.01 input.dat
   setenv fort.02 output.dat
 
The advantage of using environment variables over the symbolic link is that a link file is not created in your directory. The disadvantage is that you must add the call to the FORTRAN ioinit subprogram.


Complete example

VS FORTRAN

The following program reads data from unit 1 and writes to units 2 and 3. The name of these files are defined through filedefs. Because the output to unit 2 consists of 140-byte records, the filedef for unit 2 contains the lrecl option. Also, we want output data to unit 2 to be appended to the file in successive runs. Therefore, we put the file in append mode by using the filedef option disp mod. Data written to unit 3 is unformatted and the file is random access. Because unit 3 is random access, and the size of the file will build up in successive runs beyond the default maximum of 50 records to have 100 records, the filedef for unit 3 also contains the xtent option.

VS FORTRAN Program Listing:

                                                              
   dimension x(1000),alpha(3), beta(3), gamma(3)
   print *, 'Enter the Run Number'
   read(5,*) nrun
   read(1,*) n,(x(i),i=1,n)
   call xcalc(x,n,alpha,beta,gamma)
   write(2,'(1x,i4,9(e12.5,3x))') nrun,alpha,beta,gamma
   open(3,recl=40,access='direct',form='unformatted')
   write(3,rec=nrun) alpha, beta, gamma
   end
Filedefs:


   filedef 1 disk input file 
   filedef 2 disk output1 file (lrecl 140 disp mod
   filedef 3 disk output2 file (xtent 100

UNIX

The same result can be accomplished in UNIX with the following program:

   dimension x(1000),alpha(3), beta(3), gamma(3)
   character filename(3)*20
   print *, 'Enter the Run Number'
   read(5,*) nrun
   print *, 'Enter the filenames for files 1,2 and 3'
   read(5,'(a)') (filename(i),i=1,3)
   open(1,file=filename(1))
   open(2,file=filename(2),access='append'))
   open(3,file=filename(3),access='direct',recl=40,
   1  form='unformatted')
   read(1,*) n,(x(i),i=1,n)
   call xcalc(x,n,alpha,beta,gamma)
   write(2,'(1x,i4,9(e12.5,3x))') nrun,alpha,beta,gamma
   write(3,rec=nrun) alpha, beta, gamma
   end


                                                            
 ****************************************************************
 *                                                              *
 *                Correspondence to VS FORTRAN                  *
 *                                                              *
 ****************************************************************
 *                                                              *
 *            VS FORTRAN                          UNIX          *
 *            ==========                          ====          *
 *                                                              *
 *                                                              *       
 *          Defining the Record Length for A Sequential File    *
 *          ================================================    *
 *                                                              *
 * filedef 3 disk (lrecl 200     Unnecessary under UNIX FORTRAN *   
 *                                                              *
 *                                                              *
 *                   Defining the Record Format                 *
 *                   ==========================                 *
 *                                                              *
 * filedef 1 disk (recfm f       Unnecessary under UNIX FORTRAN *
 *                                                              *
 *                                                              *
 *                         Append Mode                          *
 *                         ============                         *
 *                                                              *
 * filedef 2 disk (disp mod       Use a FORTRAN Open statement  *
 *                                                              *
 *                             open(......,access='append',...) *
 *                                                              *
 *                                                              *       
 *               Number of Random Access Records                *
 *               ===============================                *
 *                                                              *
 * filedef 3 disk (xtent 100     Unnecessary under UNIX FORTRAN *
 *                                                              *
 *                                                              *
 *                    Naming the Input/Output File              *
 *                    ============================              *
 *                                                              *
 * filedef 2 disk input data a   print *, 'Enter filename'      *
 *                               read (5,'(a)')filename         *
 *                               open(unit=2,file=filename,...) *
 *                               read(2,12)......               *
 *                                                              *
 *                                       or                     *
 *                                                              *
 *                               Use the iargc and getarg       *
 *                               subprograms to get filenames   * 
 *                               from the command line.  See    *
 *                               text above.                    *
 *                                                              *
 *                                       or                     *
 *                                                              *
 *                               Issue a symbolic link prior    *
 *                               to running the program:        *
 *                                                              *
 *                                ln -s  input.data fort.2      *
 *                                                              *
 *                                       or                     *
 *                                                              *
 *                               Use environment variables.     *
 *                               See the text above.            *
 *                                                              *
 ****************************************************************

University of Delaware
June 19, 1994