Dan Nagle's Technical Site

Program CoCo

Home --> Fact Sheet --> Free Source Code --> CoCo

About the Program CoCo

Go directly to Downloads

Go directly to Standard CoCo

Go directly to The CoCo Set File

Go directly to Using CoCo

Go directly to Using CoCo Topics

Go directly to Extensions to the Standard CoCo

Go directly to An Example of Using CoCo

CoCo provides preprocessing as per Part 3 of the Fortran Standard (CoCo is short for "conditional compilation"). It implements the auxiliary third part of ISO/IEC 1539 (better known as Programming Languages- Fortran), and supports several extensions. (Part 1 of the standard defines the Fortran Language proper. Part 2 is the ISO_VARYING_STRINGS standard, which is sometimes implemented as a module.) A restore program, similar to that described in the CoCo standard, is also available for download.

Note that Part 3 of the Fortran Standard has been withdrawn, and Part 2 very likely will be withdrawn within a few years. At least some of the functionality of Part 2 is available via allocatable character entities, whether all of it will be made available is not yet decided.

Generally, CoCo programs are interpreted line by line. A line is either a CoCo line or a source line. Lines with the characters "??" in columns 1 and 2 are CoCo lines. All other lines are expected to be Fortran source lines (of course, the other lines need not actually be Fortran source lines, but they are called source lines in the discussion on this page). Except for the "??" characters in columns 1 and 2, CoCo lines follow the same rules as Fortran free form source lines. Like Fortran free form lines, CoCo lines are continued by placing an "&" as the last character of the line to be continued. A CoCo comment is any text following a "!" following the "??" characters. A CoCo comment may not follow the "&" used to continue a quoted string onto the next line. Text in CoCo lines may appear in upper case or lower case interchangeably, CoCo preserves case in CoCo lines written to the output file and ignores case in source lines. Either single quotes or double quotes may be used to delimit strings. CoCo directives are rendered in upper case on this page for clarity, and because the standard document uses upper case.

CoCo directives may define integer constants and variables, and logical constants and variables. CoCo uses a strong type system, which means that all symbols must be declared and that integer symbols and logical symbols are not interchangeable. The distinction between constants and variables provides a further level of control. Conditional compilation is expressed by CoCo IF blocks, which start with CoCo IF directives. The conditions are determined by CoCo logical expressions, which may include relational operations between CoCo integer expressions. CoCo IF-blocks function analogously to Fortran IF-blocks, with IF, ELSE IF, ELSE and END IF directives. CoCo IF-blocks select which lines will be passed to the output source file for compilation. An INCLUDE directive is also available so preprocessing may be applied to the included lines as well. The complete set of standard directives is listed further down this page.

As implemented here, a one invocation of CoCo reads one or more input source files and writes one output source file to be compiled. A short example of a CoCo program follows, the lines with initial "??" are the CoCo lines, lines without the initial "??" are Fortran source lines:

?? ! used to choose whether the intrinsic module sets stdout
?? logical, parameter :: has_intrinsic_module = .false.

program hello_world

?? ! use number or asterisk
?? if( has_intrinsic_module )then
!  output_unit is stdout
use, intrinsic :: iso_fortran_env, only: output_unit

write( unit= output_unit, fmt= *) 'Hello, world!'
?? else
!  * is stdout
write( unit= *, fmt= *) 'Hello, world!'
?? endif

stop

end program hello_world

Above, lines starting with "?? !" are CoCo comments (lines starting with "!" are, of course, Fortran comments), has_intrinsic_module is a CoCo logical constant given the value false, and the CoCo IF block is used to select which of two sets of source lines supplies the Fortran comment and write statement. If the above example is contained in a file named hello_world.fpp, then a command line coco hello_world produces hello_world.f90 with unit * written. A command line coco -Dhas_intrinsic_module hello_world produces hello_world.f90 with unit output_unit written. (The -D option changes the value of has_intrinsic_module. See command line options for more.)

The Portability Project and CoCo

The Portability Project has been largely superseded by improvements to the standard-defined ISO_FORTRAN_ENV intrinsic module. There is a env2inc program to write the type kind values provided in ISO_FORTRAN_ENV to a CoCo include file for use when preprocessing programs. Of course, env2inc must be compiled by the same processor to be used with the preprocessed program.

Back to the Top

Standard CoCo

A CoCo program consists of CoCo lines and source lines. The source lines comprise the Fortran program proper. The CoCo lines direct CoCo in preprocessing the program. A CoCo program may have an optional set file associated with it. The set file may be used to control what CoCo does with CoCo lines and with source lines which are not intended to be part of the output source code. Some directives may appear only in the set file, some may appear only with the source code, and some may appear in either. The set file may declare CoCo symbols and if so, the set file values override the value contained in the program declaration. The declarations must match, however, as far as type and whether the symbol is a constant (this keeps a CoCo program self-contained and self-consistent). As an extension, the set file also allows the programmer to set some values that may also be set by command line options in case CoCo doesn't have access to the command line (if the processor used to compile CoCo does not support command line access).

The standard CoCo directives are the INCLUDE directive, INTEGER and LOGICAL declarations and assignments, IF/ELSE IF/ELSE/END IF directives, and MESSAGE and STOP directives. An integer or logical variable may be given a value where declared, and if so, it may be declared to be a constant. Any directive may appear in upper case or lower case interchangeably. Names of CoCo symbols are interpreted without regard to case.

A source line in the input is said to be active when it is selected to appear in the output as a source line (that is, not as a comment). A line not selected to appear in the output as a source line is said to be inactive. The fate of inactive source lines and CoCo lines is controlled by the ALTER directive in the set file. Active lines and inactive lines are selected by CoCo IF blocks, analogously to the selection of executed statements by Fortran IF blocks.

The standard CoCo directives are described on the list below:

The name and name = expression forms of the integer variable and logical variable declarations may be mixed; a name declared to be a constant, of course, must be supplied with a value. A declaration in the set file must have a value, the purpose of the set file declarations (or a command line values) is to supply alternative initial values.

All the statements comprising an IF construct must appear in the same source file and CoCo directives in blocks not appearing in the output must be well formed directives. This implementation does minimal checking of directives in inactive lines. Input lines in TEXT blocks are treated similarly. An IF block within a TEXT block is interpreted during execution of the COPY directive.

An example CoCo program follows. As in the example above, there are CoCo comments, CoCo lines, Fortran comments and Fortran source lines:

?? ! the logical variable will be used
?? ! to choose whether to use array syntax
?? ! or explicit loops
?? logical :: array_syntax

?? ! suppose the compiler is either v1.0 or v2.0
?? ! the integer variable here supplies
?? ! the default value here and might be overridden
?? ! by a value from the set file or command line
?? integer, parameter :: version = 20

?? ! which version selects whether array syntax is used
?? if( version == 20 )then       ! efficient array code
??    array_syntax = .true.      ! so use array syntax
?? else if( version == 10 )then  ! inefficient array code
??    array_syntax = .false.     ! so no array syntax
?? else                          ! unknown version
??    message 'error: unknown version: ', version
??    stop                       ! go no further
?? end if

program sum_arrays
implicit none

real, dimension( 100) :: a, b, c

?? ! need loop index when using explicit loops
?? if( .not. array_syntax )then
integer :: i              ! loop index
?? endif

read( unit= *, fmt= *) b, c

! element-wise sum
?? if( array_syntax )then
a = b + c
?? else
do i = 1, 100
   a(i) = b(i) + c(i)
end do
?? end if

! evaluate the final sum and print it
write( unit= *, fmt= *) 'sum of a: ', sum(a)
stop

end program sum_arrays

Above, a CoCo integer, version, is used to choose a value for a CoCo logical variable, array_syntax. If version has been set incorrectly (the CoCo else clause), CoCo will print the explanatory message and stop. The CoCo logical variable is then used to choose whether an auxiliary integer is compiled into the Fortran program to serve as the index of the explicit loop. Then the CoCo logical variable is used to select either explicit loops or array syntax.

Note the strong typing CoCo uses: the value of the logical symbol can be true or false, while the value of the integer is numeric. This provides a degree of error checking. As extensions, macros, TEXT blocks, and file variables also have distinct declarations and uses.

Back to the Top

The CoCo Set File

The programmer may use a separate file, called a set file, which permits the programmer to change the values of variables and constants outside the CoCo program, and to specify what happens to inactive source text and CoCo directives. At most one set file is read and processed for each invocation of CoCo. Within the set file, variable declarations and constant definitions may appear, the values supplied override those of the same name which appear in any of the input files. There must be a declaration of the same variable or constant within one of the input files and the declaration must appear before any use of the name, only the value may be changed by the set file. See also the set file extensions for more directives which may appear in the set file. A declaration in a set file must supply a value. The value can differ from that in a source file. Other attributes of a set file declaration must match those in the source file. A declaration is unknown to CoCo until the declaration in a source file is found. This keeps a CoCo program self-consistent and self-contained.

Note that while CoCo can't tell that a symbol defined in the set file or command line isn't defined within a source file until it's finished processing, CoCo complains if the symbol is referenced before a definition appears in a source file. It's required to declare a CoCo variable in the source file before using it, otherwise a missing set file or forgotten command line option would cause the preprocessor to operate unexpectedly. The set file is appended, following a message, to the end of the output file, the command line options are available via cmdline predefined macro and the CMDLINE directive. The effects of the command line and set file may also be checked via the OPTIONS directive.

The set file is appended to the end of the CoCo program's output (depending on the mode set by the ALTER directive). If visible, its contents are separated from the program source by a standard-specified Fortran comment (thus, the set file may be the cause of several blank lines after the last line of source).

The set file is named according to the -s command line option. If there isn't one, the name is set according to the output file name. The file name suffix, if any, is discarded and ".set" is appended to make the set file name. If a file with that name is not found, the value of the environment variable COCO_SET_FILE is checked. If a file with that name is not found, a file with the default name of "coco.set" is sought. This allows a programmer to have a default set file for a project or directory, or to control the preprocessing on a file-by-file basis. There is only one set file read for a multi-input file invocation of CoCo. See Using CoCo for more on the command line.

The ALTER Directive

The fate of inactive source lines and of CoCo directives (that is, of all lines not appearing in the output file as active source lines) is controlled by the ALTER directive. At most one alter directive may appear in a set file. The -a command line option overrides the alter directive. The possible alter modes and their effects are described in the following list:

The following table summarizes the effects of the alter modes:

ALTER Mode Preserve Line Numbers? Preserve Lengthen Line? Undo?
DELETE NO N/A NO
BLANK YES N/A NO
SHIFT0 YES YES NO
SHIFT1 YES NO NO
SHIFT3 YES NO YES

A good default set file contains the line ?? ALTER: DELETE, which overrides the standard specified default of SHIFT3. The same effect may be had by adding -ad to the CoCo command line. An example set file follows:

?? ! no CoCo lines or inactive source lines
?? ! appear in the source to be compiled
?? alter: delete
?? ! no debugging (unless -Ddebug is on the command line)
?? ! debug should also be declared as a logical constant
?? ! in a source file before being used in a source file
?? logical, parameter :: debug = .false.

The alter line causes CoCo lines and inactive source lines to disappear from the output source file, and the declaration of the logical constant in the set file may override or confirm the declaration of the same name appearing in the source input file. (There should be a declaration named 'debug' as a logical constant in the source input.)

Back to the Top

Using CoCo

CoCo is distributed as source code and is written in standard Fortran 2003. You will have to find a replacement for the command line access routines if your processor does not support them (but most compilers do support them), or code them yourself using the command line routines your processor does support (for example, iargc() and getarg()). Procedures mimicking the standard procedures are available from I.S.S. Ltd. via their free F2KCLI Module for a very wide variety of compilers.

SYNOPSIS:

coco -V

coco -h

coco [ [options] [--] ] [ base-name | output input [...] ]

CoCo responds to the "-V" option by printing its version information and quitting. CoCo responds to the "-h" option by printing its command line options and quitting. If it finds no file name arguments on its command line, CoCo reads its input from stdin and writes its output to stdout (but see the input set file directive and the output file set file directive extensions). A lone file name command line argument is a file basename: it has ".fpp" appended to it and used as the single input file name, ".f90" is appended and used as the output file name. If more than one file name argument appears on the command line the first is taken to be the output file name, the rest are treated, in the order of occurrence, as input file names. Examples of CoCo usage follow:

The specification of input and output file names has a number of effects. In addition to setting the name of the set file, several macros are predefined by CoCo. The input file name and the set file name are available as macros. Also, there are date and time macros to document the preprocessing. See the predefined macros for more information about CoCo's predefined macros.

Options

Generally, the option on the command line overrides the set file directive controlling the same behavior. However, some options are cumulative or must have a matching directive, see the description of each option and directive for specifics. The following command line options are recognized:

In general, the value of a command line option is used in preference to a value in the set file; the value in the set file is used in preference to a value in a source file.

Topics on Using CoCo

About the -D rules

The following rules apply to the -D option: if the "=" is present, it must be followed by an integer literal value in which case the name is defined to be an integer name with the value specified. This value overrides an integer with the same name declared within the set file, if there is one, and within (one of) the input source file(s) (or an include file). If no "=" is present, then name is defined to be a logical name with a value of ".true.". This value overrides a logical with the same name declared within the set file, if there is one, and within (one of) the input source file(s) (or an include file). Definitions from the command line override those in the set file, but like definitions in the set file they must match definitions in (one of) the source file(s). There is no way to give a value to a text variable or macro, or a file variable directly via -D. A name is effectively undefined until the declaration is seen in a source file. The set file value or command line value supersedes the value (if there is one) defined in the source file. A declaration is the set file must supply a value, even for declarations of variables.

About the INCLUDE search rules

The rules for directories specified by the -I command line option and the DIRECTORY directive are that the directories specified by the -I command line option are searched first in the order they appear on the command line. Then directories appearing in DIRECTORY directives are searched in the order the directives appear in the set file. This way, the command line may override the set file. DIRECTORY directives may not appear in the source file(s) proper so all include files with the same name are known to come from the same directory, and thus each occurrence of any one named include file will be the same file. CoCo guesses what the file separator character (between directory names in an absolute file name) by examining the value found for the CWD predefined macro. CoCo gets this value from the PWD environment variable. If this fails, CoCo doesn't know what appropriate separator is, in that case, the appropriate separator (for example, "/", "\" or ":") must be appended after the directory name, whether it appears in the -I command line option, or in a DIRECTORY directive.

About Line Numbering and Wrapping

By default, source lines are wrapped starting at column 132 for free form source, and starting at column 72 for fixed form source. This position is called the wrap length. Wrapping means that if text extends beyond the wrap length, text beyond the wrap length on the line is ended, a continuation character is added (in free form source), and the remainder of the line is written as a continuation line following the wrapped line. This can be defeated with the -w option, or with the WRAP directive. CoCo does not attempt to wrap comments.

When lines are numbered, the file name and line number are added to the end of the source line. Line numbering occurs starting past the end of the line whether the source form is free form (after column 132) or fixed form (after column 72). If the source line extends longer than the standard-specified length, the number appears after all text on the line. Line numbering adds, after the end of a line, a comment character, a blank, the file name, a colon and blank, and the line number of the source input file. This may help tracing a compiler message back to the original source file if CoCo is deleting inactive lines from the file seen by the compiler, or when macro expansion or assert directives lengthen lines too much, causing extra lines in the output, or when copy directives write text blocks or include files add source lines, or when lines are diverted to different output files via OUTPUT directives in source files.

About Multi-File versus Single-File Invocation

The value of CoCo variables change whenever a new value is assigned. CoCo constants, of course, do not change value during execution. When several input files are processed in sequence to make a single output file, the values of CoCo variables seen for each subsequent source file depend upon values that might be changed by previous input files. This allows, for example, the programmer to count the number of times a text block is copied throughout the entire preprocessing run. However, it also means that not all source input files are preprocessed in identical environments. Thus, the programmer must choose whether a given quantity should be represented by a CoCo variable or a CoCo constant, and whether a single input file or a multiple input file run is appropriate for a given purpose.

CoCo assumes a single invocation is for source files of either free form source or fixed form source, but that source form is never mixed. Since there is a single output file, it is difficult to mix the two. Automatic conversion utilities exist and some Fortran IDEs support reformatting but CoCo does not. Without due care, mixing free form source and fixed form source in a single CoCo execution may not work as intended. In any case, free form source is preferred for many reasons, so conversion of fixed form source files to free form source files is a good idea. CoCo only supports fixed form source to permit preprocessing of legacy codes.

As discussed above, CoCo may be used to make a single output source file from one or several input source files. The advantage of one input source file making one output source file is that one has a clear set of CoCo symbols in use. One may use several runs to preprocess several input source files, so a different set file can be used for each input file allowing customization. The disadvantage is that to conveniently have the same set of CoCo symbols used to preprocess several input source files, one must prepare a set file and/or an include file to contain the CoCo symbol declarations, and use the same set file for each. This might be done by using the default set file name for all input files. Alternatively, one may use a freeze file to capture symbol declarations and values and read that file as an include file. See the freeze directive for more. The advantage of making one output file from several input files is that one set of CoCo symbols may be used to control the preprocessing of all input files, and the compiler may be able to do a better job of optimization if it can see more of the program at one time. The disadvantage is that one may have a symbol present when CoCo processes a subsequent input file which is unneeded and possibly confusing or having a value giving unexpected effects. Of course, an include file may be used to reset a set of integer or logical variables to a desired initial value for each source input file.

Back to the Top

Extensions to Standard CoCo

This implementation supports some extensions to standard CoCo. Extensions to the standard CoCo include editing extensions, file handling extensions, and diagnostic extensions. These directives may appear in source files. Other extensions may appear only in the set file.

Editing Extensions

A name of an integer, logical, macro, or file variable, when it appears between the argument key characters without embedded blanks, is replaced by the value of the name, as described in the following. Source lines may be edited, CoCo directives are not edited.

Integers and Logicals as Macros

The string ?name? is checked to see if name is the name of a CoCo integer or logical constant or variable. If it is, it is replaced by the value of the CoCo integer (as a possibly signed digit string) literal or logical (as ".true." or ".false.") literal. The name may be in either case. The following example illustrates the use of CoCo integers. The repeat count in the character declaration of the format must be a character substring, which is provided by the string substituted in place of ?size?:

?? ! set problem size
?? integer :: size = 10
integer, parameter :: nmax = ?size?
real, dimension( nmax) :: a
character, parameter :: my_fmt = '(?size?es18.9)'

Macros

Macros are another extension. A macro is a name whose value is a string. There may be arguments to the macro, which are strings replaced by the strings used in place of the arguments when the macro is referenced. The macro is used by surrounding its name with the argument key characters, ?name?. If the macro has arguments, the arguments follow the trailing key character thus, ?name?( args). Take care if a macro name appears within another macro's string. A previously declared macro name may not appear in a macro value, subsequent macro names are not checked. This is a basic measure to prevent recursive macro definitions.

The programmer may define macros via the MACRO directive. There are some predefined macros, they are listed in the following table:

Predefined Macros

The predefined macros may not be redefined, they may be considered to be constants (even if their value changes during execution). These names cannot be used for any purpose, they cannot be dummy argument names to macros or text blocks.

name definition set by
file input file name input file
line input file line number count input lines per file
date date preprocessing wall clock
time time preprocessing wall clock
coco coco's RCS Id string CoCo RCS check-out
setfile set file name set file
logfile log file name log file
output output file name output file
cmdline CoCo command line O/S shell
user user identifier USER or LOGNAME environment variables
cwd directory where CoCo is run PWD environment variable
incpath directories searched for include files command line and set file
freeze set file freeze or -f command line command line or set file
null a null string constant
blank a blank character constant

The MACRO directive defines a macro. If a ?name? is found which is the name of a macro, it is replaced with the value of the macro. Arguments may be present, if so, they are substituted in the value. There is one name space for all symbol names, but macro dummy argument names have a scope of the macro only.

The following table summarizes CoCo substitutions where a symbol's name appears between the argument key characters.

CoCo Symbol Replacement
Integer Literal Value
Logical Literal Value
Macro String Value
File Variable File Name

Take care with integers; a negative value could result in two Fortran operators appearing consecutively.

Text Blocks

The TEXT and COPY directives define a text block (that is, one or more lines), and copy it into the source. A text block may be considered a multi-line macro (note that Fortran distinguishes lines and statements). The text block is defined by the TEXT and END TEXT directives. The COPY directive copies a text block of the same name. Arguments may be present, if so, they are substituted in the value. Conditional compilation applies within text blocks, it is effective during the copy operation. Editing of names also applies during the copy operation. Text blocks must be nested correctly within IF blocks.

Source File Directives

The following directives edit the source code:

There is one name space for all integer names, logical names, macro names, text block names, and file variable names. A dummy argument on one macro or text block may have the same name as a dummy argument on another macro or text block, but must not be the same as an integer, logical, macro, text block, or file variable. This also avoids ambiguity when expanding macros and copying text blocks. Note that dummy arguments are substituted within a macro value or a text block, but not within CoCo directives contained within text blocks. Therefore, conditional compilation of text blocks during copying can be a function of variables, but not actual arguments. A string enclosed in parenthesis or brackets (for example, array constructors) is treated as a unit when used as an actual argument.

Only the following directives may appear between the TEXT and END TEXT directives: the ASSERT, IF, ELSE IF, ELSE, END IF, MESSAGE, STOP and assignment directives. While a text block may appear in an include file, an INCLUDE directive may not appear within a text block. Declaration directives may not appear because each declaration may only occur once per program. Text blocks may not be nested.

An example of a macro declaration and use follows. Note the lack of parenthesis around the actual arguments (the parentheses are added by the PARENS on the macro statement), and the lack of space between the macro name and opening parenthesis of the actual argument list:

?? ! used to compute radius
?? macro, parens :: hypot( x, y) = sqrt( ?x?*?x?+?y?*?y?)
?? ! r1, r2, s1, s2 are variables
! r = sqrt( (r2-r1)*(r2-r1) + (s2-s1)*(s2-s1) )
r = ?hypot?( r2-r1, s2-s1)

An example of a text block follows:

?? ! define stack operations as a text block
?? ! with 'type' as an argument

?? text :: stackops( type)
subroutine push_?type?( item)
type( ?type?_t), intent( in) :: item
?type?_stack( next_?type?) = item
next_?type? = next_?type? + 1
return
end subroutine push_?type?

subroutine pop_?type?( item)
type( ?type?_t), intent( out) :: item
next_?type? = next_?type? - 1
item = ?type?_stack( next_?type?)
return
end subroutine pop_?type?
?? end text stackops

?? ! write stack ops for type fermion_t
?? copy :: stackops( fermion)

?? ! write stack ops for type boson_t
?? copy :: stackops( boson)

An interface block could be provided to allow the push and pop routines to be called with a generic name, if desired. The stack arrays and stack indexes must be declared outside the routines, as defined here.

Back to the Top

File Handling Extensions

These directives allow some limited control over files.

In the example that follows, a module contains several functions. A separate file is to contain a procedure with tests, one for each function. The OPEN and OUTPUT directives solve this as follows:

module functions
contains

?? ! open the file for output
?? open :: t = 'testfunctions.f90'

?? ! write to testfunctions.f90 via the file variable t
?? ! this might be visible in the regular output file,
?? ! depending upon the alter mode
?? output: t
subroutine test_functions()
! declarations
?? ! resume writing to the regular output file
?? output

?? ! this is the test reference wanted for each function
?? text :: call( cond)
call testit( ?cond?)
?? end text call

?? ! add the test for first
?? output: t
?? copy :: call( first( x) == x+1 )
?? output

function first( x)
! rest of first
end function first

?? ! add the test for second
?? output: t
?? copy :: call( second( x) == x-1 )
?? output

function second( x)
! rest of second
end function second

!  other functions

?? ! finish the test procedure
?? output: t
end subroutine test_functions
?? output

end module functions

When the file containing the module is preprocessed, the file containing the test procedure is automatically written. It may be easier to keep the tests synchronized with the functions this way. The alternate output file need not be Fortran, of course. Any documentation, or even mathematics, perhaps written in LaTeX, might be considered for similar treatment.

Back to the Top

Diagnostic Extensions

These directives allow the programmer to monitor and debug the processing of source files:

If CoCo is being used along with the env2inc program to capture the processor-supported kinds, the fortran_env.inc file can be used to define CoCo symbols for the compiler used to compile the env2inc program. The env2inc program must be compiled by the same compiler as will be used to compile the program to be preprocessed, including any compiler options affecting the available kinds (for example, -r8), otherwise, unexpected, suboptimal, or incorrect results may occur. The fortran_env.inc file includes the results of the compiler_version and the compiler_options intrinsic module procedures to allow checking that this is so.

Back to the Top

Set File Extensions

Some extension directives may appear only in the set file, and are intended to allow the programmer to control modes of CoCo otherwise controlled from the command line (for example, in case the program was compiled without the f2kcli module, or other access to the command line). An option on the command line generally overrides the corresponding directive in the set file. These directives are listed below:

Since the set file is copied to the end of the output file, a record may be kept within the source of the CoCo options used to generate the output file. If the options specified in the set file are overridden by command line options, the command line could be present in the output file via the ?cmdline? predefined macro or a ?? CMDLINE directive.

Back to the Top

An Example of Using CoCo

Statement of the problem to be solved: A single source file is to be prepared which will specify a Fortran module containing a cube root function to support all real kinds on any processor at a computing center. Using the program env2inc (compiled and executed separately for each compiler at the computer center), to provide kind parameters in separate fortran_env.inc include files, this module may be written as follows:

?? ! define the coco integer constants
?? ! real32, real64, real128 (among others)
?? include 'fortran_env.inc'

module cube_root

!  import Fortran kind parameters
!  real32, real64, real128
use, intrinsic :: iso_fortran_env, only: real32, real64, real128

implicit none

private

interface cbrt
?? if( real32 > 0 )then
   module procedure real32_cbrt
?? endif
?? if( real64 > 0 )then
   module procedure real64_cbrt
?? endif
?? if( real128 > 0 )then
   module procedure real128_cbrt
?? endif
end interface

public :: cbrt

contains

?? if( real32 > 0 )then
elemental real( kind= real32) function real32_cbrt( x)
real( kind= real32), intent( in) :: x

   real32_cbrt = sign( exp( log( abs( x)) / 3.0_real32), x)

end function real32_cbrt
?? endif

?? if( real64 > 0 )then
elemental real( kind= real64) function real64_cbrt( x)
real( kind= real64), intent( in) :: x

   real64_cbrt = sign( exp( log( abs( x)) / 3.0_real64), x)

end function real64_cbrt
?? endif

?? if( real128 > 0 )then
elemental real( kind= real128) function real128_cbrt( x)
real( kind= real128), intent( in) :: x

   real128_cbrt = sign( exp( log( abs( x)) / 3.0_real128), x)

end function real128_cbrt
?? endif

end module cube_root

Note that the real32, real64, and real128 which appear in the Fortran source proper are the three kind parameters which are defined in the intrinsic module iso_fortran_env. The real32, real64 and real128 appearing in the CoCo IF directives are CoCo integer constants which are defined in the fortran_env.inc CoCo include file. They have the same values as the Fortran named constants but are available to CoCo to control the preprocessing of the source file. The fortran_env.inc is made automatically by the env2inc program. All the Fortran kind parameters actually appearing in the output source file are valid on the processor, because if the kind isn't supported, the corresponding CoCo integer constant is set to a negative value, thereby preventing the code from being present in the version of the source for that processor. The relational expression in the IF-statements could be assigned to logical constants if desired.

Solving the same problem, but this time using the text-copy mechanism, is shown below:

?? ! define the coco logical symbols
?? ! real32, real64, real128 (among others)
?? include 'fortran_env.inc'

module cube_root

?? text :: cbrt( kind)
elemental real( kind= ?kind?) function ?kind?_cbrt( x)
real( kind= ?kind?), intent( in) :: x

   ?kind?_cbrt = sign( exp( log( abs( x)) / 3.0_?kind?), x)

end function ?kind?_cbrt
?? end text cbrt

!  define Fortran kind parameters
!  real32, real64, real128
use, intrinsic :: iso_fortran_env, only: real32, real64, real128

implicit none

private

! define the generic name cbrt
interface cbrt
?? if( real32 > 0 )then
   module procedure real32_cbrt
?? endif
?? if( real64 > 0 )then
   module procedure real64_cbrt
?? endif
?? if( real128 > 0 )then
   module procedure real128_cbrt
?? endif
end interface

public :: cbrt

contains

?? if( real32 > 0 )then
?? copy :: cbrt( real32)
?? endif

?? if( real64 > 0 )then
?? copy :: cbrt( real64)
?? endif

?? if( real128 > 0 )then
?? copy :: cbrt( real128)
?? endif

end module cube_root

Note that this time, the source for the cbrt() function need be specified only once, the text-copy mechanism performs the copy-paste-substitute operation as needed.

One advantage of using the values of processor kind values as CoCo integers is that the value may be used within the program (perhaps in a Fortran comment). Below, a CoCo logical constant is made from one of the integer values found in the fortran_env.inc include file. Of course, this may be done with any of them, if this style is desired.

?? logical, parameter :: has_real128 = real128 > 0

Back to the Top

An Example Using a freeze-file

This example involves two executions of CoCo, the first to prepare the freeze file, the second to use it. The first execution reads an input file with no source lines. The input file simply includes the fortran_env.inc file, which may be modified by command line options and/or set file directives. Other declarations and processing logic may be present as well, but for simplicity, very little is shown.

?? ! prepare the freeze-file

?? ! fortran_env.inc was made by env2inc
?? ! env2inc must have been compiled by the same compiler
?? ! to be used to compile this program !!

?? include 'fortran_env.inc'

?? ! what to do when no 128-bit real

?? if( real128 <= 0 )then
?? !  setup for life without real128
?? end if

?? ! debugging is enabled via the command line or set file
?? ! the actual value of debug at the time of the freeze statement
?? ! will be written to the freeze-file configure.inc

?? logical, parameter :: debug = .false.

?? freeze 'configure.inc'

In the second execution of CoCo, the source file intended to be compiled is preprocessed. It merely includes the freeze file, containing the declaration of all symbols needed. Using this technique, CoCo may taylor one configuration of definitions for use in many source files.

?? ! use the prepared freeze-file

?? include 'configure.inc'

?? ! no more coco variables are needed
?? freeze

?? ! the rest of the program to be compiled follows

The FREEZE directive in the second file does not write a freeze file, it only serves to prevent further declarations. Auxiliary variables must be declared before this directive appears. A FREEZE directive appearing in the set file would not allow further declarations in any input source file.

Back to the Top

Some Known Bugs and Limitations

CoCo does not read Fortran source beyond the minimum necessary for macro replacement. This is done both for efficiency, and to increase CoCo's reliability by allowing a simpler design. However, some limitations are a result of this choice.

During source line editing, CoCo makes several passes through its list of macro names for each line to be edited. A symbol to be replaced by its value must appear entirely on one line, the name cannot be broken across a continuation line. CoCo checks that a macro value does not contain a reference to a previously-declared macro (this tries to prevents recursion). Thus, a macro may appear in the value of another macro if the macro to appear is declared later than the macro in whose value it is to appear. One may conditionally define a macro to have the desired macro value. The integers, logical, and predefined macros are replaced after the explicitly declared macros. When editing a line causes the line to become too long, it is broken into several lines and each new line is output. This may cause line numbers to disagree between the input file and the output file, if so, enabling line numbering may help trace compiler error messages back to the original source line. Better, when tracing a compiler error message read the file compiled rather than the file input to the preprocessor.

The actual arguments supplied to macro expansion and text block copying should contain either no parenthesis, or balanced parenthesis. CoCo attempts to skip commas intended as part of format specifications, array subscript sets, and procedure argument lists by skipping commas appearing between parentheses. Unbalanced parentheses within actual arguments can foil this process.

CoCo attempts to glean the directory separation character by scanning the value of the ?cwd? macro, which is gotten from the PWD environment variable. If this fails, the directory separation character must be appended to directory names specified on ??directory set file directives and on -I command line options. If a simple directory separator is inappropriate (for example, with VMS), the directory names must be specified so that simply appending the include file name produces a value that will allow the include file to be used.

CoCo accesses its command line via the usual methods. Since file indirection is ordinarily handled by the shell as part of program startup processing, CoCo cannot distinguish the case where files have been redirected to stdin and stdout from the case where there are no source files on the command line. Therefore, CoCo will honor input and output directives in its set file even in the case where files have been redirected from the command line. Care should be taken to use a set file without input or output directives when file indirection is intended, and, for clarity, to shun file indirection when input or output set file directives are intended. To document CoCo's idea of its command line, see the CMDLINE directive, the ?cmdline? predefined macro, and the DOCUMENT directive. Also, if there are no input or output file names on the command line (either because stdin and stdout are redirected, or because ??INPUT and ??OUTPUT set file directives are being used, and there is no set file named on the command line, the only set file that can be read is coco.set, the default.

If verbose mode is on, and a log file is named, the closing of the log file is reported on stderr, because after the log file is closed the log file can no longer receive comments. Likewise, if verbose mode is switched on in the set file, the opening of the set file will not be reported, unless verbose mode is also switched on by the command line.

As with all CoCo statements and inactive source lines, the set file, its standard-defined separation line, and lines marking subsequent input files are invisible when the alter state is set to delete or blank. If you want to see these lines, set the alter state to one of the shift values.

Back to the Top

Downloads

To download a source code for the CoCo program, click CoCo preprocessor. As CoCo has grown in size and complexity, it is now desirable to maintain CoCo as several modules rather than one large program. Thus, CoCo is now a gzipped tarfile containing the source files and a makefile. The makefile is set to use gfortran as the compiler, but also has macros for ifort and nagfor. You should be able to configure it for other compilers as well. You may want to use the free F2KCLI Module from I.S.S. Ltd. to compile the CoCo program if your compiler doesn't support the Fortran 2003 command line access intrinsic procedures. Download the restore program which can undo CoCo processing under limited circumstances. The env2inc program is also available.

For more information about the fortran_env.inc file, click here.

Back to the Top

Please see our Fact Sheet, or E-mail us for more information.


Home - Fact Sheet - Free Source Code - Fortran Links - Email us

Back to the Top