[comment {-*- flibs -*- doctools manpage}]
[manpage_begin flibs/tools n 1.0]
[copyright {2008 Arjen Markus <arjenmarkus@sourceforge.net>}]
[moddesc flibs]
[titledesc {Modify program code}]

[description]
The [term editcode] program is a specialised preprocessor for Fortran code:
its purpose is to transform
the code according to certain simple rules:

[list_begin bullet]
[bullet]
Add an "IMPLICIT NONE" statement at the beginning of a module or
routine.

[bullet]
Replace one type by another (for instance: real ==> real(dp)).

[bullet]
Instrument the code (add extra statements).

[bullet]
Enable preconditions/postconditions/assertions.

[list_end]

It reads an input file called "editcode.inp" which should contain
keywords and possibly parameters, steering the transformation of
the code.

[para]
Here is a list of the keywords and their parameters:
[list_begin bullet]
[bullet]
[term "INPUT-DIRECTORY dirname"] - Directory to expect the input source files
[bullet]
[term "OUTPUT-DIRECTORY dirname"] - Directory to put the output source files in
[bullet]
[term "FILE filename"] - Name of the source file to process
[bullet]
[term "ADD-CODE-START code"] - Line of code to add at the start of a routine.
[bullet]
If more than one line is required, then just use several such keywords
[term "ADD-CODE-END code"] - Ditto at the end of a routine (this includes: RETURN, STOP and END)
[bullet]
[term "ADD-CODE-STATEMENT code"] - Line of code to add _after_ each statement
[bullet]
[term "ADD-USE code"] - Add a USE statement
[bullet]
[term "REPLACE-TYPE old new"] - Replace variable type "old" by variable type "new"
[bullet]
[term "REPLACE-STRING old new"] - Replace any string "old" by string "new"
[bullet]
[term "ENABLE-IMPLICIT-NONE yes/no"] - Add an IMPLICIT NONE statement if none is present
[bullet]
[term "ENABLE-PRECONDITIONS yes/no"] - Enable preconditions
[bullet]
[term "ENABLE-POSTCONDITIONS yes/no"] - Ditto for postconditions
[bullet]
[term "ENABLE-ASSERTIONS yes/no"] - Ditto for assertions
[bullet]
[term "CLEAR-ALL-SETTINGS"] - Re-initialise the preprocessing information (everything is set to the default again)
[bullet]
[term "INCLUDE filename"] - Read keywords from the given file before processing the rest
of this input file (multiple levels possible)
[bullet]
[term "__FILE__"] - Macro replaced by the name of the current source file
[bullet]
[term "__LINE__"] - Macro replaced by the current line number
[bullet]
[term "__ROUTINE__"] - Macro replaced by the current routine name
[bullet]
[term "__MODULE__"] - Macro replaced by the current module name

[list_end]

Preconditions, postconditions and assertions are implemented as
special comments:
[example {
    ! pre: x > 0.0
    ! post: x > 0.0
    ! assert: x > 0.0
}]

If a condition is longer than one line, simply use & like any
ordinary continuation line:
[example {
    ! assert: x > 0.0 .and. &
    !         y < 0.0
}]

If the condition type is enabled, the condition is transformed
into code like this:
[example {
if ( .not. ( &
    x > 0.0 .and. &
    y > 0.0 &
) then
    write(*,*) 'Assertion failed at line 10 in file myprog.f90:'
    write(*,*) 'x > 0.0 .and. &'
    write(*,*) 'y > 0.0'
endif}]

The program also handles a simple form of exceptions via
try/catch statements:
[example {
    try
        ... code to handle the ordinary case ...
    catch
        ... code to handle an exception ...
    endtry
}]
(Within a catch section you can use the routines of the
[term exception_handling] module)
[para]
[strong Note:]
[list_begin bullet]
[bullet]
Each argument must be surrounded by " or ' if it contains spaces.
(The lines are read via list-directed input)
[bullet]
The INCLUDE statement is treated in the main program, all the
others are treated by the preprocessor module.
[bullet]
Comment lines begin with !
[bullet]
The default settings are such that _nothing_ is done.
[list_end]

To make this preprocessing facility flexible, it consists of a
main program and a module that does the actual work:
[list_begin bullet]
[bullet]
preprocess_init sets or resets the preprocessor data
[bullet]
preprocess_input takes a line of code and handles the
information it contains
[bullet]
preprocess_file processes the given input file
[list_end]

[section EXAMPLES]
The [term tests/tools] directory contains several examples and a
detailed explanation, but here is the input file [term editcode.inp]
for these examples:

[example {
INPUT-DIRECTORY   in
OUTPUT-DIRECTORY  out
ADD-CODE-START    "write(*,*) 'In __ROUTINE__ (__MODULE__)'"
ADD-CODE-END      "write(*,*) 'Leaving __ROUTINE__'"
ADD-CODE-STATEMENT "write(*,*) 'At __LINE__'"
ADD-USE            "use exceptions"
REPLACE-TYPE       "real"  real(dp)
REPLACE-STRING     X Y
ENABLE-IMPLICIT-NONE  yes
!
! Does this cause an error?
ENABLE-PRECONDITIONS

ENABLE-PRECONDITIONS yes

FILE              example.f90

!
! Now the check_init/check_reals example
!
CLEAR-ALL-SETTINGS

INPUT-DIRECTORY   in
OUTPUT-DIRECTORY  out
REPLACE-TYPE real type(checked_real)
ADD-USE "use check_reals"
ADD-CODE-STATEMENT "call check_assignment( __LINE__, '__FILE__' )"
!
! List of files to treat
!
FILE "check_init.f90"
}]

While mainly meant to test the correct working of the program, it does
in fact illustrate its capabilities. The README file contains more
information.
[manpage_end]
