3-5 PREPROCESSORS
******************
(Thanks to Timothy Prince for the important comments)
Preprocessors are programs that transform the source code BEFORE
compilation. The strange name stems from the fact that compilers
are sometimes called language processors, so it is natural to call
such programs preprocessors.
Pre-processors execute "pre-processor commands" imbedded in the text,
and so must have a way to recognize what part of the text is a command
and what should be "data" to be transformed.
One method is using special character combinations and/or putting
the commands at special places e.g. the C pre-processor looks for
'#' at the first column, RDBPRE looks for '_&RDB_&'.
Another method is shifting the responsibility to the user, he
shouldn't use in his program strings that the pre-processor may
consider as commands.
Typical pre-processor commands
------------------------------
Preprocessors can replace every occurrence of some string in the
program with another pre-determined string, expand MACRO calls,
include files etc.
FORTRAN's statement-functions are a kind of macros!
---------------------------------------------------
FORTRAN compilers can do some of the things that are usually done
by pre-processors. FORTRAN compiles each procedure separately,
and the pre-processing is also done separately for each procedure.
When doing such "local" pre-processing there is not much use for
dumb string replacements, the PARAMETER statement performs this
function in a better way.
Macro expansions on the other hand are still useful, as the
following example will show:
REAL MATRIX(10, 10), TRSH
C ------------------------------------------------------------------
LOGICAL NOQUAD
C ------------------------------------------------------------------
NOQUAD(M,N) = ((MATRIX(M,N) .LT. TRSH) .AND.
* (MATRIX(M,N+1) .LT. TRSH) .AND.
* (MATRIX(M+1,N) .LT. TRSH) .AND.
* (MATRIX(M+1,N+1) .LT. TRSH))
C ==================================================================
.............................................................
IF (NOQUAD(I,J+2) .OR. NOQUAD(I,J-2) .OR.
* NOQUAD(I-2,J) .OR. NOQUAD(I+2,J)) THEN
Without the statement-function NOQUAD this code fragment would
have been a real monster. By the way, it is part of a program
that computes (rather badly) the fractal dimension of unspecified
number of geometric figures embedded in MATRIX.
Note that the compiler will process statement-functions correctly
even if a direct substitution would have made the line longer than
72 columns. A non-FORTRAN oriented preprocessor (e.g. cpp) wouldn't
generate in this case the required continuation-lines.
Possible uses
-------------
A good preprocessor is a useful tool, e.g. you can define a constant
with an appropriate value at the beginning of the source file and
all the occurrences of the constant will be replaced by the value.
Such an ability is useful because the FORTRAN compiler compiles each
procedure separately, and a constant that is used in several routines
has to be redefined by each, which is a very unmodular practice.
Like many other FORTRAN 77 problems this was solved in Fortran 90.
C Pre-Processor (cpp)
---------------------
There are a lot of preprocessors for FORTRAN, when they are not
available you can use the C pre-processor:
$ CC/DECC/PREPROCESS_ONLY=New-name Source-file (VMS)
On most UNIX implementations, the FORTRAN compiler automatically
processes files with extension '.F' (e.g. myprog.F) with the help of
the C pre-processor, see your compiler documentation (or 'man page').
RATional FORtran (ratfor)
-------------------------
ratfor is more than just a pre-processor, it translates a C-like
extension of FORTRAN to ugly FORTRAN 77.
There is a pretty-printing version. For g77 it uses DOWHILE()...ENDDO,
CYCLE and EXIT so it can eliminate most label targets even from
existing code. As a result, its indenting feature is indispensable.
The standard ratfor is more f66 than f77 although it is able to pass
much f77 through. It requires another preprocessor (written by
Timothy Prince) to be able to accept nearly all reasonable f77.
m4 pre-processor
----------------
KAP (Kuck & Associates Pre-processor ?)
---------------------------------------
KAP is an optimizing pre-processor specially designed for a certain
compiler/machine combination, it does various transformations on the
source code (introduces temporary variables etc) in anticipation of
the code generation and optimizations done by the native compiler.
KAP's preprocessor is an integral part of HP's Fortran compiling system,
and, if used with thorough application of directives, achieves typically
a 10% performance improvement on computational intensive work. To do
this requires a lot of work profiling and examining the quality of code
generated by the preprocessor. One of the problems is lack of task
division between preprocessor and core compiler, with both of them doing
loop unrolling and the like. HP provides partial documentation on KAP.
SGI has adopted KAP "technology" as part of their compiler, with most of
the pre-processing features integrated into the main compiler. Their
compiler also relies to some extent on directives, which are mostly
undocumented but resemble the HP ones. Contacting Kuck Associates in
the hope of getting some documentation so that they could be given more
favorable treatment, have got only a few unkept promises.
Timothy Prince have written quite a bit of stuff about how to use the
directives, what kind of code to try to generate, but it should be noted
that the vendors make no promises of continuity in their products.
Experimental evaluation of FORTRAN and C with and without Kuck Fortran
pre-processor on the HP was performed by Timothy Prince. He says that
sometimes it is possible to achieve better performance with KAP and C
than with FORTRAN; and KAP with manual intervention is more effective
with C than with a good FORTRAN compiler. It is possible to make scripts
which usually allow the KAP code to be processed by f2c.
Return to contents page