NAME

ufpp - pre-process FORTRAN source files

SYNOPSIS

   ufpp [define_list]
        [-i input_file(s)]
        [-o output_file]
        [-I include_directories]
        [-keeptabs]
        [-width n]
        [-html]
        [-system]
        [-prefix_character_ADE]
        [-version]
        [-help [-html]]
        [-verbose]
define_list
An optional space-delimited list of expressions used to define variables before file processing commences.
-i input_files
The default input file is stdin. Filenames are space-delimited. In a list, @ represents stdin.
-o output_file
The default output file is stdout.
-I include_directories
The directories to search for files specified on $INCLUDE directives.
-prefix ADE_value_of_prefix_character
The default directive prefix character is "$". Alternatives may be specified by providing an ASCII Decimal Equivalent. Common values are 37=% 42=* 35=# 36=$.
-html
Assumes the input file is HTML that follows the following rules: 1) Input lines are not output until a simple < XMP> directive is found. 2) Output stops when a simple < /XMP> directive is encountered. This allows code to be maintained as part of an HTML document.
-help [-html]
Display documentation and exit. If "-html" is present, write documentation as basic HTML, instead of as a text file.
-verbose
Text following the string "@(#)" is printed to stderr similar to the Unix command what(1) but is otherwise treated as other text input.
-system
Allow system commands on $SYSTEM directives to be executed.
-keeptabs
By default tab characters are expanded assuming a stop has been set every eight columns; and trailing carriage-return characters are removed. Use this flag to prevent this processing from occurring.
-d ignore|remove|blank
Enable special treatment for lines beginning with "d" or "D" The letter will be left as-is (the default); removed; or replaced with a blank character. This non-standard syntax has been used to support the optional compilation of "debug" code by many Fortran compilers.
-version
Display version and exit
-width n
Maximum line length of the output file. Default is 1024. Typically used to trim fixed-format FORTRAN code to line 72 that contains comments or "ident" labels past column 72.

DEFINITION

By default the stand-alone pre-processor ufpp(1) will interpret lines with "$" in column one, and will output no such lines. Other input is conditionally written to the output file based on the directives encountered in the input.

The syntax for the control lines is as follows:

     $DEFINE   variable_name[=expression]                 [! comment ]
     $ERROR    message_to_stderr                          [! comment ]
     $IF       {constant LOGICAL expression}              [! comment ]
               { sequence of FORTRAN source statements}
     [$ELSEIF  {constant LOGICAL expression}              [! comment ]
               { sequence of FORTRAN source statements}]
     [$ELSE                                               [! comment ]
               { sequence of FORTRAN source statements}]
     $ENDIF                                               [! comment ]
     $INCLUDE  filename                                   [! comment ]
     $OUTPUT   filename                                   [! comment ]
     $PRINTENV predefined_name|environment_variable_name  [! comment ]
     $SHOW                                                [! comment ]
     $STOP {stop_value}                                   [! comment ]
     $SYSTEM system_command                               [! comment ]
     $UNDEFINE variable_name                              [! comment ]
     $WARNING  message_to_stderr                          [! comment ]

Compiler directives are specified by a "$" in column one, followed by a keyword. The syntax and parsing rules of the text following the "$" are essentially like FORTRAN 77 source; eg. spaces (blanks) are ignored, and upper and lower case are equivalent except for filenames and system commands.

An exclamation character on a valid directive begins an in-line comment that is terminated by an end-of-line.

Any LOGICAL expression composed of integer constants, parameters and operators, is valid. Logical operators are ".NOT.",".AND.",".OR.",".EQV.", ".NEQV."; and ".EQ.",".NE.",".GE.",".GT.",".LE.", and ".LT.", and "+,"-","*","/","(",")" and "**".

$DEFINE variable_name [=expression]

A $DEFINE may appear anywhere in a source file. If the value is ".TRUE." or ".FALSE." then the parameter is of type LOGICAL, otherwise the parameter is of type INTEGER and the value must be an INTEGER. If no value is supplied, the parameter is of type INTEGER and is given the value 1.

Constant parameters are defined from the point they are encountered in a $DEFINE directive until program termination unless explicitly undefined with a $UNDEFINE directive.

Example:

   $define A=1
   $define B=1
   $define C=2
   $if ( A + B ) / C .eq. 1
      (a+b)/c is one
   $endif

$ERROR message

Write message to stderr and display program condition and exit program.

$IF/$ELSEIF/$ELSE/$ENDIF directives

Each of the control lines delineates a block of FORTRAN source. If the expression following the $IF is ".TRUE.", then the lines of FORTRAN source following are output. If it is ".FALSE.", and an $ELSEIF follows, the expression is evaluated and treated the same as the $IF. If the $IF and all $ELSEIF expressions are ".FALSE.", then the lines of source following the $ELSE are output. A matching $ENDIF ends the conditional block.

$INCLUDE filename

Nested read of specified input file. Fifty (50) nesting levels are allowed.

$OUTPUT filename

Specify the output file to write to. Overrides the initial output file specified with command line options. If no output filename is given revert back to initial output file. @ is a synonym for stdout.

$PRINTENV NAME

If the name of an uppercase environment variable is given the value of the variable will be placed in the output file. If the value is a null string or if the variable is undefined output will be stopped. This allows the system shell to generate code lines. This is usually used to pass in information about the compiler environment. For example:

  # If the following command were executed in the bash(1) shell...

   export STAMP="      write(*,*)'COMPILED ON:`uname -s`;AT `date`'"

the environment variable STAMP would be set to something like

     write(*,*)'COMPILED ON:Eureka;AT Wed, Jun 12, 2013  8:12:06 PM'

A version number would be another possibility

     export VERSION="      program_version=2.2"

Special predefined variable names are:

     Variable Name      Output
     UFPP_DATE  ......  UFPP_DATE="12:58 14Jun2013"
   Where code is assumed to have defined UFPP_DATE as CHARACTER(LEN=15)
     UFPP_FILE  ......  UFPP_FILE="current filename"
   Where code is assumed to have defined UFPP_FILE as CHARACTER(LEN=1024)
     UFPP_LINE  ......  UFPP_LINE=    nnnnnn
   Where code is assumed to have defined UFPP_LINE as INTEGER

$SHOW

Shows current state of ufpp(1); including variable names and values; and the name of the current input files. All output is preceded by an exclamation character.

Example:

   ufpp A=10 B C D -o paper
   $define z=22
   $show
   $stop
   !============================================================================
   ! *ufpp* CURRENT STATE
   ! *ufpp*    TOTAL LINES READ ............          2
   ! *ufpp*    CONDITIONAL_NESTING_LEVEL....   0
   ! *ufpp*    DATE......................... 11:18 21Jun2013
   ! *ufpp*    ARGUMENTS ................... A=10 B C D -o paper
   ! *ufpp* VARIABLES:
   ! *ufpp*    ! A                               !          10
   ! *ufpp*    ! B                               !           1
   ! *ufpp*    ! C                               !           1
   ! *ufpp*    ! D                               !           1
   ! *ufpp*    ! Z                               !          22
   ! *ufpp* OPEN FILES:
   ! *ufpp*    ! ---- ! UNIT ! LINE NUMBER ! FILENAME
   ! *ufpp*    !    1 !    5 !           2 !
   !============================================================================

$STOP [stop-value]

Stops input file processing. An optional integer value of 1 to 20 will be returned as a status value to the system where supported. A value of zero is returned if no value is specified.

$SYSTEM system_command

If system command processing is enabled using the -system switch system commands can be executed to create files to be read or to execute test programs, for example. $SYSTEM directives are ignored by default; as you clearly need to ensure the input file is trusted before allowing commands to be executed. Examples: $! build variable definitions using GNU/Linux commands $SYSTEM echo system=`hostname` > compiled.h $SYSTEM echo compile_time="`date`" >> compiled.h $INCLUDE compiled.h $! obtain up-to-date copy of source file from HTTP server: $SYSTEM wget http://repository.net/src/func.f90 -O -|cpp -P -C -traditional >tmp.f90 $INCLUDE tmp.f90 $SYSTEM rm tmp.f90

$UNDEFINE variable_name

A symbol defined with $DEFINE can be removed with the $UNDEFINE directive.

DEFINED(variable_name)

A special function called DEFINED() may appear only in a $IF or $ELSEIF. If "variable_name" has been defined at that point in the source code, then the function value is ".TRUE.", otherwise it is ".FALSE.". A name is defined only if it has appeared in the source previously in a $DEFINE directive or been declared on the command line. The names used in compiler directives are district from names in the FORTRAN source, which means that "a" in a $DEFINE and "a" in a FORTRAN source statement are totally unrelated. The DEFINED() parameter is NOT valid in a $DEFINE directive.

Example:

            Program test
     $IF .NOT. DEFINED (inc)
            INCLUDE 'comm.inc'
     $ELSE
            INCLUDE 'comm2.inc'
     $ENDIF
            END

The file, "comm.inc" will be INCLUDEd in the source if the parameter, "inc", has not been previously defined, while INCLUDE "comm2.inc" will be included in the source if "inc" has been previously defined. This is useful for setting up a default inclusion.

$WARNING message

Write message to stderr.

LIMITATIONS

$IF constructs can be nested up to 20 levels deep. Note that using more than two levels typically makes input files less readable.

Input files

Variable names

Major cpp(1) features not present in ufpp(1):

There are no predefined preprocessor symbols. Use a directive input file instead. The predefined variables such as UFPP_DATE can be used as a substitute in some cases.

This program does not provide string (macro) substitution in output lines. See cpp(1) and m4(1) and related utilities if macro expansion is required.

While cpp(1) is the de-facto standard for preprocessing Fortran code, Part 3 of the Fortran 95 standard (ISO/IEC 1539-3:1998) defines Conditional Compilation, but it is (currently) not widely supported (See coco(1)).

ENVIRONMENT:

The environment variable $DEFAULT_ufpp can change command defaults. The values for -i, -I, and defined variables from $DEFAULT_ufpp will be prepended to the list defined on the command line. Other switches will be replaced by values on the command line. For example: env DEFAULT_ufpp="CRAY 64BIT -html -d -I CRAY_DIR" ufpp A=10 -i f90.html would run the same as the command ufpp CRAY 64BIT A=10 -html -d -I CRAY_DIR -i f90.html Overriding command defaults can be very useful when builds are done using make(1) files and/or scripts; as platform-specific and debug options can be evoked without changing the build-related files.

EXAMPLES:

Define variables on command line:

Typically, variables are defined on the command line when ufpp(1) is invoked or are grouped together into small files that are included with a $INCLUDE or as input files.


     ufpp HP size=64 -i hp_directives.dirs @ test.F90 -o test_out.f90

defines variables HP and SIZE as if the expressions had been on a $DEFINE and reads file "hp_directives.dirs" and then stdin and then test.F90. Output is directed to test_out.f90

Basic conditionals:

   $DEFINE a=1  ! define only the first version of SUB1(3f)
         PROGRAM conditional_compile
         CALL sub1
         END
   $IF a .EQ. 1
          SUBROUTINE sub1
          PRINT*, "This is the first SUB1"
          END
   $ELSEIF a .eq. 2
          SUBROUTINE sub1
          PRINT*, "This is the second SUB1"
          END
   $ELSE
          SUBROUTINE sub1
          PRINT*, "This is the third SUB1"
          END
   $ENDIF