
Use_cpp

Memo for using the C preprocessor in the ABINIT package.

Copyright (C) 1999-2007 ABINIT group (XG,LSI,DCA) 
This file is distributed under the terms of the
GNU General Public License, see ~abinit/COPYING
or http://www.gnu.org/copyleft/gpl.txt .
For the initials of contributors, see ~abinit/doc/developers/contributors.txt .



Note : the C preprocessor is used at a rudimentary level,
but at least it seems to be sufficiently portable at that level !!


1. Usage at compile time
------------------------

Suppose the c preprocessor's location is 
/lib/cpp

A file  file.f  will be preprocessed to file_cpp.f 
by the following command :

/lib/cpp file.f > file_cpp.f

The file file_cpp.f is a fortran file without cpp additions,
thus appropriate for compilation. It is the one for which
the compiler indicates a line number in case of error.
(Usually, there is however little problem in using directly 
file.f for the understanding of the compiler messages)

Additional options to be used :

/lib/cpp -P -C -Ddefined1 -Ddefined2 file.f > file_cpp.f

The option -P is for preprocessing only
The option -C keeps "comments" in, which keeps // intact for
fortran character string concatenation
The "defined" arguments defined1 or defined2 (or more if needed)
are often used for the C preprocessor to know which version of 
the code it must generate.

Example of defined arguments :
MPI  (for the parallel version)
ibm  (for the IBM version)
P6   (for the PPro version) 
FFTW (for the fftw non multithreaded version)
FFTWTHREADS ( for the fftw multithreaded version)
CACHE=1024 (for cache optimization)
...


2. Usage in the body of the routines.
-------------------------------------


A. Version maintenance using if ... elif ... endif construct


In the body of the routine, appearance of

#if defined IBM
    ...
   codeibm
    ...
#elif defined SGI
    ...
   codesgi
    ...
#endif

when preprocessed with the -DIBM argument, will give
 
    ...
   codeibm
    ...

The similar effect is true with the -DSGI argument

Other information about this construct :

1) It seems that the 
#else 
  instruction has a bug on the SGI, so avoid it.

2) The logical operators are as follows :
   !     for logical negation
   ||    for logical or
   &&    for logical and

For example
#if defined IBM || defined SGI
 ...
#elif !defined P6
 ...
#endif

3) On HP machines, cpp directives are only recognized if # is the first
character of the line; any number of blanks or tabs are allowed between the #
and the directive. e.g.
#	ifdef HP
 ...
#  endif



B. Replacement of variable at preprocess time


Appearance of
#define FNLEN 132
at the beginning of the routine
will cause replacements of the occurences of
FNLEN
by 
132
in the body of the routine.


3. WARNINGS
-----------

3.1.
Do not use comments at the end of a C-processed line, 
like the following :
#define FNLEN 132    /* THIS is a forbidden comment */
It is NOT portable.

Use instead
!THIS is an allowed comment
#define FNLEN 132


3.2.
CPP does not recognize Fortran comments sign. Inside
comments, you MUST use ' or " signs in pairs.

!It's forbidden
!It''s allowed

3.3.
Inside CPP sections, // might be treated as the end of the
code to be removed on each line, despite being the
concatenation sign in FORTRAN (this behaviour can be
avoided on some machines, if the flag -traditional is used).
Thus, avoid concatenating strings inside CPP sections.
(Note easy, sometimes ...)
