You are on page 1of 48

SPAG

2 SPAG - Renovation & Analysis


2.1 Introduction
2.1.1 What does it do?
SPAG is a multi-purpose tool for analyzing and improving Fortran
programs. It combines restructuring and reformatting with translation to
Fortran 95, and both static and dynamic analysis in a single powerful
package. But SPAG
offers facilities which go beyond the sum of these parts.
For example:
SPAG can restructure 'rats-nest' Fortran 66 to modern and
structured Fortran (77 or 95), or apply a final polish to
well written
modern code. Progress can be monitored using 'Before and After'
complexity metrics.
SPAG can create Fortran 95 modules to replace Fortran 77 COMMON
blocks and INCLUDE files. It can also
create Fortran 95 interface blocks
to facilitate compiler argument checking.
SPAG can insert explicit type declarations for IMPLICITly typed
variables, or rewrite the declarations from
scratch using either Fortran
77 or Fortran 95 declaration style.
SPAG can translate VAX structures to Fortran 95 derived types.
SPAG can identify, and optionally remove unused variables and code
fragments.
SPAG can change variable names in a simple and safe way.
SPAG can convert back and forth between Fortran 77, and code with
Fortran 95 extensions such as DO WHILE,
ENDDO, CYCLE, EXIT and SELECT
CASE. SPAG can also convert between the new and old source forms,
and the
new and old declaration styles.
SPAG can make re-formatted code even clearer by using upper and lower
case to distinguish different types of
symbol.
SPAG can insert probes to perform a dynamic analysis of your program
as it runs. Dynamic analysis can identify
many bugs which are not
apparent to a static analyzer.
SPAG can use dynamic analysis to identify variables by their contents
at run-time. This facility can, for example,
be used to identify variables
containing dates, as an aid to Year 2000 compliance testing.
SPAG can insert probes to identify untested code and computational
hot-spots. The results can be inserted, as
comments, back into the
original code.
SPAG can write out symbol table files for reference, or for input to
other QA and analysis programs, such as
GXCHK (see chapter 3).
SPAG understands Fortran 77, VAX Fortran, and almost all Fortran 95, together with many common extensions,
such as Cray pointers, ENCODE/DECODE etc.
2.1.2 Code Restructuring
SPAG can unscramble spaghetti Fortran 66 code, and convert it to modern
and structured Fortran 77 or Fortran 95.
When SPAG restructures a program, it does not change its meaning, or
even the order in which statements are executed;
it does change the way the
program logic is written down, making it much easier to understand and
maintain. Oldfashioned control constructs (such as GOTO, arithmetic IF,
computed GOTO etc.) are eliminated, but that is only the
beginning. SPAG
also rearranges blocks of code so that logically related sections are
physically close, and jumps in
control flow are minimized. The algorithms
used to do this draw on a deep analysis of the program structure.
2.1.3 Code Replication
Sometimes, rearrangement is not enough. Spaghetti programmers often made
their programs more complex in order to
re-use a few bytes of code -
perhaps to avoid putting 'N=0' more than once! SPAG can undo the
damage by replicating
small code fragments where this improves the
restructured code.
SPAG does not always remove all GOTOs. Sometimes, this could only be
done by replicating large tracts of code, with
a consequent reduction in
readability and maintainability. SPAG concentrates on code rearrangement,
with occasional

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

replication of small code fragments. This is the approach


programmers invariably take when faced with the task of
restructuring by
hand, and it works well in practice.
2.1.4 Translation to Fortran 95
In addition to translating source form, declaration style, and control
constructs to Fortran 95, SPAG can also translate
COMMON blocks and INCLUDE
files to Fortran 95 modules. SPAG can also create a module containing an
INTERFACE block for each subprogram, and insert appropriate USE statements
in calling subprograms. Fortran 95
compilers can use these constructs to
perform argument checking.
2.1.5 Adding or Rewriting Declarations
Most older Fortran programs use IMPLICIT typing. That is to say that
variables are not formally declared at the head of
each subprogram, as they
are in Pascal or C, but are simply assigned a type according to their
initial letter when they
are first used. SPAG provides the means to convert
such programs to explicit typing, which in Fortran is usually
enforced
using the IMPLICIT NONE statement. It does this by adding explicit
declarations for all undeclared variables
at the head of each subprogram
and INCLUDE file. Explicit typing allows your compiler to detect errors
which might
otherwise remain undetected for years.
SPAG can also rewrite your declarations from scratch using either
Fortran 77 or Fortran 95 declaration style. When
SPAG does this, it groups
declarations in a logical order. For example, dummy argument declarations
form a separate
section. When using the Fortran 95 declaration style,
arrays with the same dimension are grouped together.
2.1.6 Translation of VAX Structures
Fortran 95 provides an ANSI standard alternative to the VAX Fortran
STRUCTURE and RECORD statements. SPAG
can translate between the two forms.
Features, such as UNIONs, which are not available in standard Fortran 95
are left
unchanged, in a form suitable for a compiler which provides them
as an extension.
2.1.7 Clutter Removal
Old programs often contain 'dead code' which can never be
executed, and variables which are declared but never used.
SPAG identifies
and, optionally, removes this clutter.
2.1.8 Renaming Variables
SPAG provides a simple and safe method for systematically changing the
names of symbols within a program. SPAG
guards against the danger of
choosing a new name which is already in use, and re-formats the source code
as required.
2.1.9 Define a Corporate Style
SPAG contains a powerful code beautifier, with dozens of options
controlling spacing, labels, indentation, use of
CONTINUE etc. There is
also an 'AS-IS' option for preserving the
format of painstakingly hand-formatted declaration
statements. SPAG can
help make programs self-documenting, by using case to distinguish different
types of symbol.
For example, local variables may be lower case, PARAMETERs
upper case, dummy arguments capitalized etc. (e.g.
local, PARAM, Dummyarg,
COMvar). All this gives project leaders a powerful tool for defining and
enforcing a
corporate 'house programming style', making it easier
for your programmers to work with each other's code, and with
code from
other sources.
SPAG also allows you to use many VAX and Fortran 95 features in your
programs, and then, when necessary, to
convert back to Fortran 77. This allows you to benefit from the use of DO WHILE, DO ENDDO, SELECT CASE etc.

without compromising portability.


2.1.10 Dynamic Analysis

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

If a bug is defined as 'an incorrect value in a storage


location', then there is a large subset (perhaps 30%) which can be
defined as 'an undefined value in a storage location', and many of
the remainder may cause that condition as a knock-on
effect. The
'Dynamic Analysis' option of plusFORT is a tool for
diagnosing these errors at run-time. Probes are
inserted in the source code
before any operation which depends on the value of a data item. If the data
item is
undefined, the probes write details of the error to a log-file for
later analysis. Source code for the probes is supplied.
A static analyzer such as GXCHK can detect a few of these errors, but
the majority can only be detected at run-time. In
fact static and dynamic
analysis complement each other well - each excels where the other is
deficient.
The Dynamic Analysis feature of plusFORT was inspired by
the /UNDEF option in the FTN77 compiler from Salford
Software. A similar
facility was also implemented in the WATFIV run-time system on IBM
mainframe computers.
Other implementations are surprisingly rare.
2.1.11 Dynamic Memory Monitoring
SPAG implements a form of dynamic analysis which is geared toward
finding variables with a particular type of content
at run-time. For example, variables containing dates can be identified, even if their
name provides no clue as to their
function. This unique capability
makes SPAG an ideal tool for Year 2000 compliance and similar testing. A more
conventional Year 2000 date variable scan is implemented in GXCHK.
2.1.12 Coverage Analysis
In addition to testing for the definition status of variables and
arrays, SPAG can insert probes to monitor what code is
executed, and over a
series of runs, to identify untested code blocks and computational
hot-spots. The CVRANAL
utility produces a report which summarizes these
results, and, if required, inserts usage counts back into the original
code
as comments (e.g. in columns 73-80).
2.1.13 Symbol Table Files
SPAG optionally generates symbol table files which provide valuable
information about data usage within subprograms.
These files are used by
GXCHK, the global cross check program (see Chapter
3), to generate an overview of data usage
within an entire program.
Symbol tables are plain ASCII text files, the format of which is
described in detail in Appendix A.
Users are encouraged
to develop their own applications using these files as
input. For example it would be a simple matter to write a program
to check
conformance to local variable naming conventions.

2.2 Source Language


SPAG fully supports ANSI standard Fortran 77, DEC VAX Fortran and IBM VS
Fortran. In addition, almost all the
extensions supported by the major UNIX
and PC compilers are supported.
Two minor exceptions to the above are:
SPAG does not recognize the PDP style representation of octal
constants (e.g. "36). However SPAG does
recognize the newer and
preferred form ('36'O).
SPAG does not recognize hexadecimal constants of the form Z01FC233A
('Z' followed by hex digits). IBM's VS
Fortran allows this
form in DATA initialization statements. This extension pre-dates Fortran
77 and can result in
ambiguity (e.g. ZABCD in a DATA statement could be a
hex constant or a PARAMETER value).
In addition, SPAG supports almost all of Fortran 90 and 95. A summary of Fortran 95 features known to be unsupported
may be found
in the READ.ME file in the plusFORT installation release directory.
The following useful Fortran 95 features are almost universally
available even in Fortran 77 compilers, and their use can
be wholeheartedly
recommended even to those not intending to switch to Fortran 95.
http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

The INCLUDE statement. Probably the most important for large programs
- INCLUDE statements are vital for
COMMON block definitions and globally
used PARAMETERs.
IMPLICIT NONE. Enforces the crucial discipline of declaring all
variables explicitly.
DO..ENDDO and DO WHILE. These extensions to the DO statement make
labels redundant, except in FORMAT
statements.
Lower case in symbol names. Can greatly improve the readability of
code.
The use of symbol names with more than six characters.

2.3 Organizational Considerations


SPAG is designed to fit into any Fortran programming environment.
However, in order to get the most from it, you may
find it advantageous to
observe the following guidelines:
Keep the source and object code for each program or library in a
separate directory, and avoid putting anything
else in that directory.
This makes it easy to identify all the code for a given program. If you have several
versions
of a program, keep them in separate directories.
In Fortran 77 code, use INCLUDE files for declarations of COMMON
variables and global PARAMETERs.
Avoid using INCLUDE files for anything
else. INCLUDE files should not contain IMPLICIT statements. Select
a
file-naming convention which allows you to distinguish easily between
subprogram files and INCLUDE files
(e.g. give INCLUDE files a different
extension).
Declare every COMMON block (via an INCLUDE file) in the main program,
even if they are not used there. This
is a necessary step if you wish to
perform a dynamic analysis, but is desirable in any case. Note that
according to
the ANSI standard, a COMMON block which is not declared in
the main program may become undefined.
Keep each subprogram in a separate file whose name is the same as the
subprogram name. Use QMERGE and
QSPLIT if you want to combine several
subprograms in a single file.
Give all subprograms a name. In particular, make sure that all main
programs begin with a PROGRAM statement
and that all BLOCK DATA segments
are given a name.

2.4 The SPAG Command Line


To start a run, simply type spag followed
by the name of the file(s) you wish to process. You can use wild-cards to
specify more than one file. For example:
SPAG A*.FOR B*.f90

(DOS/Windows, VMS)

spag a*.f b*.f90

(UNIX)

processes the contents of all files in the current directory which fit
either wildcard.
Under DOS/Windows and VMS, .for is assumed
if no extension is specified (b* is treated as
b*.for). The default file
name is *.for. Thus, if you just type SPAG, all .for files in the current directory are processed.
Under UNIX, the extension must be specified, and there is no default
file name.
The operation of SPAG may be modified by command line switches.
Currently the following switches are available:
FIG= specifies the configuration file name (see section
2.5). If you don't specify the configuration file name in
this

way, SPAG looks for a file called spag.fig. In either case, the search rules defined in section 1.4 are followed.
SPAG halts with an appropriate message if no configuration file can be found.
If a '?' is appended (e.g. FIG=TOF90.FIG? or
FIG=?), SPAG lists the contents of the active configuration
file to the screen, with a pause after each screen full.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

LOG= specifies the name of a file to which a copy of all screen output
is routed. If you don't specify a log-file name

in this way,
output is sent to a file called spag.log.
nnn= specifies the value of item nnn of the SPAG configuration data
(see 2.6). Leading zeros should be omitted

from the item number (enter 1=2 rather than 001=2). Items specified
in this way over-ride those read from the
configuration file.
TO=

specifies the name of a single file for output of all modified


source code. If TO= is not set, output may
be
routed to a single large file, to an output file for each input
file, or to an output file for every sub-program,
depending on items
10, 230 and 231 of the configuration data.

SYM= specifies the name of a single file for output of all symbol
tables. If SYM= is not set, output may be
routed to a

single large file, to an output file for each input file,


or to an output file for every sub-program, depending on
items 10, 232 and 233 of the configuration data.
IFC= specifies the name of a single file for output of all Fortran 95
INTERFACE modules. If IFC= is not set,
output

may be routed to a single large file, to an output file for


each input file, or to an output file for every subprogram,
depending on items 11, 236 and 237 of the configuration data.
For example
spag a*.f log=NEW.log fig=MARY.fig 1=1 60=1 sym=NEW.smb

This command causes SPAG to analyze all files in the current directory
whose name fits the template a*.f. A copy of
all
screen output is sent to NEW.log.
Configuration options are read from MARY.fig,
but the controls on records 1 and 60
are both set to 1 (re-format only, and
leave specification statements unchanged). All symbol tables are written to
the file
NEW.smb. The way modified source code
is output depends on items 10, 231 and 232 of the configuration data.

2.5 The SPAG Configuration File


The configuration file is a plain text file which provides the means by
which users may customize SPAG to their own
requirements and preferences.
You can use an installation default configuration file, or create your own
by copying one
of the supplied versions and editing it using your standard
editor.
The file consists of data records and comment records. Any record with a
space in column 1 is a comment record; all
others are data records. Data
records consist of an integer item number, followed by an '=' character and a value. They
are terminated by a space
character (optionally followed by a comment) or by the end-of-record. For
items 1 to 199, the
value is a simple integer. For items 200 to 299, the
value is a text string. Records may appear in any order. Items 300
and up
are ignored.
A small section from a typical configuration file is shown below. The significant parts are 1=3, 2=2 and 3=3, which set
configuration items 1, 2 and 3 to 3, 2 and 3 respectively. The reaminder is commentary.
#====================================#
#======== Global Run Control ========#
#====================================#
1=3

Type of Run
0=no source output
1=beautify only
2=and relabel
3=and restructure
4=dynamic analysis
5=Dynamic Memory Monitoring

2=2

Symbol Table Ouptut


-1=no symbol table
0=generate table
1=write to file
3=Verbose

3=3

Clutter Checks

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

0=no clutter checks


1=checks only
2-5=remove clutter

There are three sample configuration files in the plusFORT


installation directory:
spag.fig

may be used to process fixed format input code, and to produce


restructured output which should be
acceptable to a modern Fortran 77 compiler.

tof90.fig

may be used to process fixed format input code, and to produce


restructured output which should be
acceptable to a modern Fortran 90/95 compiler. SPAG uses Fortran 90/95 features wherever
appropriate

spag90.fig may be used to process free format Fortran 90/95 input code, and to produce restructured Fortran 90/95
output.
The meaning of each data item is explained in detail in the next section.

2.6 SPAG Configuration Data


Item 1

Source Code Output


Specifies what source code output is required - possible values
are:
0 No source code output. This option may be useful if SPAG is
used to produce symbol tables and
diagnostic output.
1 Reformat only. SPAG reformats the program, according to the
controls in the remainder of the file,
but does not restructure
it or change any statement labels.
2 Reformat and re-label. SPAG reformats the program and
reassigns statement labels according to the
controls in items
80 to 90. It does not restructure the program.
3 Reformat, re-label and restructure. Restructuring is a far
more radical procedure than reformatting or
re-labelling; it
can change the appearance of code completely. See section 2.1 for a discussion of the
subject.
4 Dynamic analysis. SPAG produces code which contains probes
to check for errors as the program
runs. The code produced
using this option is intended to be passed straight to a
compiler. It will not
be easy to understand or maintain. SPAG
may override other configuration settings if this option is
selected. See section2.8 for further
discussion of dynamic analysis.
5 Dynamic memory monitoring. SPAG prepares source code for a special sort of dynamic analysis,
geared towards spotting
specified types of data in memory as the program runs. For
example, the
program can be instrumented to detect variables
containing dates, with a view to spotting Year 2000
rollover
problems. The instrumented program executes normally, but
as it runs, every variable or
array element, used in any way,
is checked for data which could be date related. See section 2.10 for
further discussion.

Item 2

Symbol Tables
Specifies whether the symbol tables generated by SPAG are to be
written to files - possible values are:
0

No symbol table output. SPAG generates symbol tables for its


own use, but does not write them to
an output file.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

-1 SPAG does not generate symbol tables. If this option is


selected, some other options will be
unavailable. In
particular, the declaration standardization, clutter removal
and symbol renaming
facilities cannot be used, and the case of
variable names in restructured output cannot depend on
their
usage. SPAG does not read the contents of INCLUDEd files if
this option is activated.

Item 3

Write symbol tables to file. The names of the output files


are determined by items 10, 232 and 233.
Their format is described in Appendix A. If this option
is selected, symbol tables for SUBROUTINE
and FUNCTION segments
are made as small as possible. In particular variables and
PARAMETERs which are defined in an INCLUDE file, but which are
not otherwise referenced, are
excluded from the output symbol
table. This can reduce their size very considerably. GXCHK (see
chapter 3) will work with this setting, but it may be unable to
spot globally unreferenced
PARAMETERs and COMMON variables.
This problem can be overcome by ensuring that every
INCLUDEd
file appears either in the main program, or in a BLOCKDATA
segment.

As above, but, where possible, additional information is


appended to the symbol name. For example,
a list of COMMON
variables is appended to COMMON block names, and precise
dimensioning
information is appended to array names. The extra
information is sufficient to allow regeneration of
the
declaration section using only data from the symbol table. This
increases the size of the symbol
tables somewhat, but has no
effect on the operation of GXCHK. Further details may be found
in
Appendix A.

As above, but all symbols are included in the output file,


including unreferenced COMMON
variables and PARAMETERs from
INCLUDE files. This is the safest option, but if it is
selected,
the symbol tables may be much larger than otherwise,
and GXCHK may take longer to analyze
them. If every INCLUDEd
file appears in the main program or a BLOCKDATA segment, there
is
no advantage, and some disadvantage to setting item 2 to 3.

Clutter Checks
Specifies how SPAG should deal with clutter (unused variables,
PARAMETERs, COMMON blocks etc.).
Possible values are:
0 No clutter checks.
1 Check for unused local variables, dummy arguments,
PARAMETERs, COMMON blocks and
INCLUDE files. It is to be
expected that there may be unused COMMON blocks and
PARAMETERs
defined within INCLUDE files, and such instances are not
reported. INCLUDE files
are reported as unused only if
everything in them is unused.
In addition to finding variables which are totally unused,
SPAG reports variables which are assigned
a value, but are
otherwise unused, and variables which are used in calculations
even though they
have not been assigned a value.
2 SPAG reports clutter and removes all references to unused,
un-initialized local variables.
3 SPAG reports clutter and removes all references to unused
local variables (except those initialized in
a DATA statement)
and PARAMETERs.
4 SPAG reports clutter and removes all references to unused
local variables, PARAMETERs and
COMMON blocks. SPAG does not
remove COMMON blocks from the main PROGRAM or from a
BLOCKDATA.
5 SPAG reports clutter and removes all references to unused
local variables, PARAMETERs,
COMMON blocks and INCLUDE files.
SPAG does not remove COMMON blocks or INCLUDE
files from the
main PROGRAM or from a BLOCKDATA. This option should not be
selected if
INCLUDE files might contain IMPLICIT statements, or
any other statement which affects

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

declarations made elsewhere.


For example, if a variable appears in a type statement in one
file and a
COMMON statement in another.
See section 2.7.7 for further discussion
of clutter removal.
Item 4

Declaration Standardization
Specifies whether and how SPAG should reorganize the declarations
in a subprogram. Possible values are:
0

No change to declarations.

Insert explicit type declarations for variables which would


otherwise be assigned a type by the
Fortran IMPLICIT mechanism.
Other declarations remain unchanged.

As above, but in addition an IMPLICIT NONE statement is


inserted. Any existing IMPLICIT
statement is removed, unless it
occurs in an INCLUDE file.

The declaration section is rewritten from scratch using


Fortran 77 declaration syntax.
PARAMETERs, Dummy arguments,
COMMON variables and local variables are placed in
separate
commented sections.

As above, but in addition an IMPLICIT NONE statement is


inserted. Any existing IMPLICIT
statement is removed, unless it
occurs in an INCLUDE file.

The declaration section is rewritten from scratch using


Fortran 95 declaration syntax.
PARAMETERs, Dummy arguments,
COMMON variables and local variables are placed in
separate
commented sections. Identically dimensioned declarations are
grouped together where
possible.

As above, but in addition an IMPLICIT NONE statement is


inserted. Any existing IMPLICIT
statement is removed, unless it
occurs in an INCLUDE file.

+10 If 10 is added to the above value, then SPAG creates


interfaces for referenced subprograms. If
Fortran 77 style
declarations are being written, these take the form of EXTERNAL
and
INTRINSIC statements. For Fortran 95 style declarations,
SPAG creates a module containing an
INTERFACE definition for
every subprogram (see Item 11 for details of
file output). In addition
SPAG inserts USE statements in the
calling subprograms as necessary.
+20 If 20 is added to the above value, SPAG inserts Fortran 95
INTENT statements for all dummy
arguments, based on how the
argument is actually used.
+40 If 40 is added to the above value, SPAG replaces COMMON
blocks and INCLUDE files with
Fortran 95 modules.
99

The most complete translation to Fortran 95 may be achieved


by setting this item to 99 (or to any
value above 75).

Note that SPAG does not insert or modify type declarations for
variables which are defined in INCLUDEd
files, unless it is
converting them to modules. It does not insert declarations for
INTRINSIC functions
(item 210).
See section 2.7.3 for more discussion of
declaration standardization, and 2.7.5-6 for a
description of the
conversion of COMMON blocks and INCLUDE files to
modules.
Item 5

Variable Renaming
Specifies whether SPAG should change the name of symbols before
writing the restructured output file.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Possible values are:


0 No name changes.
1 Change symbol names as specified in the 'renames
file'. The name of the renames file is specified by
item 211, and its format is described in section 2.7.8.
Item 6

Test Coverage and Hot-spot Analysis


Specifies whether SPAG should insert the statements specified in
items 243-247 in such a way as to trace
entries to and exits from
subprograms and code blocks. The trace statements may be used to
analyze test
coverage (i.e. to identify parts of the program that
have not been tested) and execution hot-spots. Possible
values
are:
0 Do not insert trace statements.
1 Insert trace statements as the first executable statement of
every subprogram, and immediately before
every RETURN or STOP.
Trace statements are also inserted before END statements which
act as
RETURN or STOP.
2 In addition, insert trace statements (as specified using item 247) at the start of every linear code
block. If this option is selected, item 234
(coverage data directory) must also be set, as SPAG creates

coverage data files in the specified directory.


See section 2.9 for further discussion of
coverage analysis.

Item 7

Complexity Metrics
Specifies whether SPAG should compute complexity metrics for each
subprogram. Possible values are:
0 Do not compute complexity metrics
1 Compute complexity metrics for each subprogram. If SPAG is
restructuring the code, it computes
'before and after'
values.
SPAG computes three metrics, each of which ranges in value from 0
to 100, with higher values indicating
greater complexity. A target
value is suggested for each metric, but it is accepted that there are
circumstances when well written code exceeds the targets. The three
metrics reported by SPAG are:
LOGICAL CONTENT. This is a measure of the number of decision
points (such as IF or ELSEIF
statements) in the subprogram. The
target value is 50 (corresponding to a McCabe Cyclomatic
Complexity
of around 10). This metric can be reduced by splitting up large
subprograms.
Restructuring has little effect on it.
ALL CONTROL JUMPS. This is a measure of how discontinuous
control flow is in the subprogram.
Any GOTO or other command which
transfers control to a different point in the source code
contributes to this metric. The target value is 20. Restructuring
often reduces this metric
appreciably.
UNSTRUCTURED JUMPS. Similar to ALL CONTROL JUMPS except that
jumps from within a
DO loop to or just past the terminal statement
(using GOTO, CYCLE or EXIT), and jumps to a
RETURN, STOP or END
statement are excluded. The target value is 0. Restructuring often
reduces
this metric appreciably.

Item 8

Interface Summary Reports

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Specifies whether SPAG should prepare the ground for GXCHK to


embed an interface summary as
comments in the restructured source
code. This summary enumerates calls in and out of each subprogram,
and details arguments and COMMON data shared with the remainder of
the program. SPAG inserts a
marker in output code which GXCHK
subsequently replaces with the interface summary. Interface
summaries
are described in detail in section 3.6. Possible values are:
0 No interface summary reports
1 Prepare for summary reports by inserting a marker comment in
the restructured code.
Item 10

Output Files
Specifies how output files (both restructured source and symbol
tables) are to be created. Possible values
are:
0 Send all output to a single file. By default, the file name
is spag.out for restructured
source and
spag.smb for symbol
tables. These defaults can be over-ridden using the TO= and SYM=
keywords on
the command line.
1 Create new output files for each input file. For example, if
your input file is called main.for, the
output files would use the same filename
(main), but with different
extensions (e.g. main.new and
main.smb). This is the recommended
option.
2 Create new output files for each subprogram. For example, if
your input file contains two
subprograms called MAIN and CALC,
there would be separate restructured source and symbol table
files for each, perhaps called main.new, calc.new, main.smb and calc.smb. If this option is used, it is
important to
ensure that PROGRAM and BLOCKDATA subprograms are assigned a
unique name.
For the last two options, you may specify the directory in which
the new files are created (see items 230
and 232) as well as the extensions used (see items 231 and 233).

Item 11

Interface Module Output


Specifies how newly created subprogram interface modules are to be
written (item 4 controls whether
SPAG creates new
interface modules). Possible values are:
0 Send all output to a single file. By default, the file name
is intfaces.xyz (where .xyz is the extension
specified in item 237 of spag.fig). This default can be over-ridden using the
IFC= keyword on the
command line.
1 Create new output files for each input file. For example, if
your input file is called main.for, the
output would be sent to a file called
s_main.xyz.
2 Create new output files for each subprogram. For example, if
your input file contains two
subprograms called MAIN and CALC,
there would be separate restructured source and symbol table
files for each, perhaps called s_main.xyz and s_calc.xyz.
For the last two options, you may specify the directory in which
the new files are created and the extension
used (see items 236 and 237).

Item 12

Safe Functions
Specifies whether functions whose names do not appear in the file
specified using item 210 can be
regarded as
'safe'. A 'safe' function is one which simply returns
a value, dependent on its arguments; it
does not modify its arguments
or any COMMON or SAVEd variable, or perform any input or output

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

operation. The file specified using item 210


contains a list of INTRINSIC functions, and a user specified
list of
safe functions.
One point of the distinction is that the static analysis in SPAG
and GXCHK is more informative if
functions are known to be safe.
Another is that, if SPAG restructuring produces code which executes a
function more often than the original unstructured code, it can only
be sure that the program logic is
correct if the functions involved
are 'safe'. This situation arises rarely in practice, and
SPAG issues a
warning message if there is any danger.
Possible values are:
0 Functions are regarded as unsafe unless their name appears
in the INTRINSIC and safe functions file
whose name is
specified using item 210.
1 All functions are regarded as safe.
Item 18

Configuration Options in Header


Specifies whether a header section containing a summary of options
specified in spag.fig is to be inserted
at the head of each subprogram in the restructured output file.
Possible values are:
0 No header section.
1 Insert header section. Please use this option when sending material to our
technical support
department.

Item 20

Computed GOTO
Specifies whether computed GOTOs are to be converted to
IF..THEN..ELSE or SELECT CASE
constructs. Possible values are:
0 Leave computed GOTOs unchanged.
1 Change computed GOTOs into block IFs. If you choose this
option, the test expression may be
evaluated more than once;
this could have two undesirable effects:
If the construct is inside a tight time-sensitive loop,
the SPAG output program may run slower.
However this effect
is much more often imagined than real.
If the test expression in the computed GOTO statement
accesses an 'unsafe' FUNCTION
subprogram (see items
12 and 210) then the SPAG output program may be logically
changed.
SPAG issues a warning when this possibility
arises.
2 Change computed GOTOs into Fortran 95 SELECT CASE constructs. Note that you can also use
SPAG to convert most SELECT CASE constructs back to Fortran 77 (see item 21).
Computed GOTO Example
! item 20 = 0
GOTO (10,20,30),i
10
x = a
GOTO 40
20
x = b
GOTO 40
30
x = c
40
CONTINUE
! item 20 = 2
SELECT CASE (i)

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

! item 20 = 1
IF ( i.EQ.2 ) THEN
x = b
ELSEIF( i.EQ.3 ) THEN
x = c
ELSE
x = a
ENDIF

SPAG

CASE (2)
x = b
CASE (3)
x = c
CASE DEFAULT
x = a
END SELECT

Note that the translations deal correctly with the case where i is
less than 1 or greater than 3.
Item 21

SELECT CASE
Specifies whether SPAG should convert SELECT CASE constructs to
equivalent standard Fortran 77
block IF constructs. SELECT CASE is a
Fortran 95 construct which is also supported by some Fortran 77
compilers.
Possible values are:
0 No changes.
1 Convert SELECT CASE constructs to standard Fortran 77 using
block IF constructs. SPAG
guarantees to convert SELECT CASE
constructs which were created by it, and many that were not.
It
will not convert constructs where the case expression is not of
type INTEGER, or where any
CASE statement contains a range
specification (e.g. CASE (5:10) ).

Item 22

Arithmetic IF
Specifies whether arithmetic IFs are to be converted to
IF..THEN..ELSE constructs. Possible values are:
0 Leave arithmetic IFs unchanged.
1 Change arithmetic IFs into block IFs. If you choose this
option, and if the three labels in the
arithmetic IF are all
different, the test expression will be evaluated twice (instead
of once); this could
have two undesirable effects:
If the construct is inside a tight time-sensitive loop,
the SPAG output program may run slower.
However this effect
is much more often imagined than real.
If the test expression in the arithmetic IF statement
accesses an 'unsafe' FUNCTION
subprogram (see items
12 and 210) then the SPAG output program may be logically changed.
SPAG issues a warning when this possibility arises.
Arithmetic IF Translation Example
! item 22 = 0
IF ( i ) 10,20,30
10
x = a
GOTO 40
20
x = b
GOTO 40
30
x = c
40
CONTINUE

Item 23

! item 22 = 1
IF ( i.LT.0 ) THEN
x = a
ELSEIF ( i.EQ.0 ) THEN
x = b
ELSE
x = c
ENDIF

Logical IF + GOTO
Specifies whether logical IF followed by GOTO is to be converted
to a block IF..THEN..ELSE construct.
Possible values are:
0 Leave logical IF + GOTO unchanged.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

1 Change logical IF + GOTO into block IF. Depending on the


precise nature of the program logic, the
new block IF may have
ELSE or ELSEIF clauses, or may itself become a subsidiary
ELSEIF clause
of another block IF. SPAG may also need to
reverse the sense of the logical expression in the IF
statement
(e.g. A.LT.B becomes A.GE.B). If item 24 is set
appropriately, and if the program logic is
in the appropriate
form, the logical IF may be converted to a Fortran 95 style DO
WHILE block.
Logical IF + GOTO Example
! item 23 = 0
IF ( q1 ) GOTO 10
x = a
y = b
GOTO 20
10
x = b
y = a
20
CONTINUE

Item 24

! item 23 = 1
IF ( q1 ) THEN
x = b
y = a
ELSE
x = a
y = b
ENDIF

DO WHILE
Specifies whether SPAG should make use of the DO WHILE construct
to unscramble code containing
backward pointing GOTOs. DO WHILE is a
Fortran 95 construct which is also supported by almost all
Fortran 77
compilers. SPAG can also convert the DO WHILE construct back to standard Fortran 77.
Possible values are:
-3 Convert all existing DO WHILE constructs to standard Fortran
77 using backward pointing GOTO
statements.
-2 Convert existing DO WHILE constructs to standard Fortran 77
if the DO statement is
"DO WHILE
(.TRUE.)" OR if the conversion does not require
that a new GOTO statement be
introduced.
-1 Convert existing DO WHILE (.TRUE.) constructs only.
0

Don't change either way. Existing DO WHILE blocks and


backward pointing GOTOs remain
unchanged.

Convert backward pointing GOTOs to DO WHILE constructs if


the change can be made simply by
converting a block IF to a DO
loop, and no new statements are required.
DO WHILE Example 1
! Before conversion
10
IF ( i.GE.0 ) THEN
READ * , I
CALL sub(i)
GOTO 10
ENDIF

! After conversion
DO WHILE ( i.GE.0 )
READ * , I
CALL sub(i)
ENDDO

Convert backward pointing GOTOs to DO WHILE constructs if


the change can be made simply by
converting a block IF to a DO
loop, and no more than one new statement (a GOTO, CYCLE or
EXIT) is required.
DO WHILE Example 2
! Before conversion
5
IF ( i.GE.0 ) THEN
READ * , i
CALL sub(i)
IF ( q ) GOTO 5
CALL sub(i+1)
ENDIF

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

! After conversion
DO WHILE ( i.GE.0 )
READ * , i
CALL sub(i)
IF ( .NOT.q ) THEN
CALL sub(i+1)
EXIT
ENDIF

SPAG

ENDDO

Convert backward pointing GOTOs to DO WHILE constructs, even


if this involves inserting bare
DO (i.e. DO forever) and other
statements.
DO WHILE Example 3
! Before conversion
10
READ(9,END=100) z
PRINT * , z
GOTO 10

Item 25

! After conversion
DO
READ(9,END=100) z
PRINT * , z
ENDDO

EXIT and CYCLE


Specifies whether SPAG should use the Fortran 95 style EXIT (GOTO
statement after DO loop
terminator) and CYCLE (GOTO end of loop)
statements. Possible values are:
0 Don't use EXIT or CYCLE. Replace any existing EXIT or
CYCLE with an equivalent GOTO.
1 Use EXIT but not CYCLE. Where possible convert GOTO to EXIT.
Replace any existing CYCLE
with an equivalent GOTO.
2 Use CYCLE but not EXIT. Where possible convert GOTO to
CYCLE. Replace any existing EXIT
with an equivalent GOTO.
3 Use both EXIT and CYCLE. Where possible convert GOTO to EXIT
or CYCLE.
EXIT and CYCLE Example
! Item 25 = 0
DO i = 1 , 80
ch = str(i:i)
IF ( ch.EQ.' ' ) THEN
IF ( lt.LE.0 ) GOTO 10
GOTO 99999
ELSEIF ( alp(ch) ) THEN
nalp = nalp + 1
ENDIF
lt = lt + 1
10
ENDDO
99999 END

Item 26

! Item 25 = 3
DO i = 1 , 80
ch = str(i:i)
IF ( ch.EQ.' ' ) THEN
IF ( lt.LE.0 ) CYCLE
EXIT
ELSEIF ( alp(ch) ) THEN
nalp = nalp + 1
ENDIF
lt = lt + 1
ENDDO
END

Statement Replication
Specifies whether SPAG may replicate individual statements if this
improves the readability of a section of
code. Possible values
are:
0 Disallow code replication.
1 SPAG replicates statements as required. It does not prompt
for permission, or insert explanatory
comments in the output
code.
2 SPAG replicates statements as required, and inserts an
explanatory comment in front of each
replicated statement.
3 SPAG prompts for permission before replicating a statement.
If the replication is permitted, SPAG
inserts an explanatory
comment in front of each replicated statement.
Statement Replication Example
! original
GOTO (10,20,30),i

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

! item 26 = 0
IF ( i.EQ.1 ) THEN

SPAG

10
20
30
40
50

goto 50
x = a
GOTO 40
x = b
GOTO 40
n = 0
GOTO 50
n = n + 1
end

x = a
GOTO 100
ELSEIF ( i.EQ.2 ) THEN
x = b
GOTO 100
ELSEIF ( i.EQ.3 ) THEN
n = 0
ENDIF
GOTO 99999
100 n = n + 1
99999 END

! item 26 = 1
IF ( i.EQ.1 ) THEN
x = a
n = n + 1
ELSEIF ( i.EQ.2 ) THEN
x = b
n = n + 1
ELSEIF ( i.EQ.3 ) THEN
n = 0
ENDIF
END

In this example, structure is improved by duplicating the


statement n = n + 1.
Item 27

Relocation into DO loop


Specifies whether blocks of code can be relocated into a DO loop
from outside. This control does not apply
to DO WHILE loops.
Relocation into a DO WHILE loop is always allowed. Possible values
are:
0 Do not relocate code into a DO loop.
1 Allow relocation into a DO loop.
Relocation Into a DO loop Example
! Item 27 = 0
DO 10 i = 1 , 100
IF ( q1 ) GOTO 20
10
CONTINUE
GOTO 30
20
CALL sub1
30
CALL sub2

! Item 27 = 1
DO 10 i = 1 , 100
IF ( q1 ) THEN
CALL sub1
GOTO 20
ENDIF
10
ENDDO
20
CALL sub2

If you activate this option, and if the relocated code re-defines


the DO loop variable (e.g. i = 0 instead
of
CALL sub1), then the resulting code
violates the ANSI standard (code within a DO loop is not allowed
to
redefine the DO loop variable). This should not cause any errors at
run time, as the DO loop
redefinition is followed immediately by a
GOTO which exits the DO loop. However, many compilers
will, quite
properly, report an error. To avoid this eventuality, set item 27 to
0, or hand check the output
code.
Item 28

Relocate RETURN or STOP followed by END


Specifies whether a block of code terminated by RETURN or STOP and
followed by END may be
relocated. Activating this option prevents
SPAG from moving a RETURN or STOP which is the last
executable
statement in a subprogram. Possible values are:
0 Always allow relocation of blocks terminated by RETURN or
STOP.
1 Disallow relocation of blocks terminated by RETURN or STOP
and followed by END.
Relocation of RETURN Example
! original code

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

! Item 28 = 0

SPAG

11

10

call sub0
If ( q1) then
goto 10
else
call sub1
call sub2
goto 11
endif
return
end

100

CALL sub0
IF ( q1 ) THEN
RETURN
ELSE
CALL sub1
CALL sub2
GOTO 100
ENDIF
END

! Item 28 = 1
100 CALL sub0
IF ( .NOT.q1 ) THEN
CALL sub1
CALL sub2
GOTO 100
ENDIF
RETURN
END

Item 29

Remove Unreachable Code


Specifies whether blocks of code which could never be executed are
to be removed. Possible values are:
0 Do not remove unreachable code, but issue a message
detailing the problem.
1 Remove unreachable code.
Unreachable Code Example
GOTO 200
! The following statement could never be executed
WRITE(22,100) a,b,c
100
FORMAT(3F5.3)
200
PRINT *,a,b,c

Item 30

Convert VAX Structures


Specifies whether SPAG should translate VAX STRUCTURE and RECORD
statements, and the
corresponding structure references, to Fortran 95
derived types. Possible values are:
0 Leave VAX structures alone.
1 Convert VAX structures to Fortran 95 derived types.
Fortran 95 has no equivalent to the VAX MAP and UNION constructs,
which are used make different
elements of a structure share the same
memory. When SPAG encounters a MAP or UNION construct, it
leaves it
intact, in a form acceptable to compilers which provide MAP and UNION
as an extension to
standard derived types. An example of this
follows:
VAX Structure Example
!

VAX Structures
structure /date/
union
map
integer d , m , y
end map
map
integer ddmmyy(3)
end map
end union
end structure
record /date/ today
today.d = 20

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

Fortran 95 Derived Types


TYPE DATE
UNION
MAP
INTEGER D , M , Y
ENDMAP
MAP
INTEGER DDMMYY(3)
ENDMAP
ENDUNION
END TYPE DATE
TYPE (DATE) today
today%d = 20

SPAG

print * , today.ddmmyy(1)

Item 35

PRINT * , today%ddmmyy(1)

Dynamic Analysis Element Size


Specifies the minimum element size (in bytes) for dynamic
analysis. SPAG will not insert probes to check
the definition status
of numeric data items which are smaller than the specified minimum
size. If this item
is set to a small value (e.g. 1) there is a
possibility of 'false positives' (i.e. the probe logs an
error even
though there is none). If it is set to a large value (e.g.
4), the probes may miss errors which could be found
with a smaller
value.
The best approach is probably to set item 35 to 1, but to increase
it to 2 or 4 if false positives are a
problem.
Note that this control applies to numeric and logical data, and
NOT to character data. See section 2.8 for
further
discussion of dynamic analysis.

Item 36

Static Local Variables


Specifies whether local variables should be assumed to be static.
The ANSI standard specifies that local
data which is not specified in
a SAVE or DATA statement becomes undefined when control is returned
to
the calling subprogram. However many compilers allocate local data
statically, and many non-standard
programs depend on static
allocation of local data. Dynamic analysis of such programs is only
possible if
this item is set to 1.
Possible values are:
0 Assume local variables are dynamically allocated. In a
dynamic analysis version of the code, local
variables are set
to the undefined value every time a subprogram is invoked.
1 Assume local variables are statically allocated. In a
dynamic analysis version of the code, local
variables are set
to the undefined value the first time a subprogram is invoked,
and are assumed to
retain their value thereafter.
See section 2.8 for further discussion of
dynamic analysis.

Item 40

Relocate FORMAT statements


Specifies whether FORMAT statements are to be grouped together
just before the END statement of each
subprogram. Possible values
are:
0 Leave FORMAT statements in place.
1 Move all FORMAT statements to the end of the subprogram.
2 FORMAT statements are relocated at the end of subprogram if
they are used more than once.
FORMATs which are used only once
are left in place.

Item 41

Use of CONTINUE
Specifies whether CONTINUE statements should be inserted whenever
a label is required (except on
FORMAT statements). Possible values
are:
0 Remove all CONTINUEs other than DO loop terminators.
1 Insert a CONTINUE wherever a label is needed. Only CONTINUE
and FORMAT statements have

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

labels.
In general a value of 0 leads to code which is easier to
understand, while a value of 1 gives code which is
easier to modify.
CONTINUE Example
! item 41 = 0
DO 10 i = 100 , 1 , -1
IF ( qa(i) ) GOTO 12
10
CONTINUE
12
last = i

! item 41 = 1
DO 10 i = 100 , 1, -1
IF ( qa(i) ) GOTO 12
10
CONTINUE
12
CONTINUE
last = i

This control is effective only for re-structuring runs (Item 1).


Item 42

Single statement block IFs


Specifies whether block IFs are to be converted to logical IFs if
the block contains only one statement.
Possible values are:
-1 All logical IF statements are converted to single statement
block IFs.
0

Convert logical IF () GOTO statements to single statement


block IFs.

Convert single statement block IFs to logical IFs if the


statement is a GOTO.

All single statement block IFs are converted to logical


IFs.
Single Statement block IF Example
! Item 42 = 1
IF ( Q1 ) THEN
X = Y
ENDIF

Item 43

! Item 42 = 2
IF ( Q1 ) X = Y

Logic Reversal in block IF


Specifies whether constructs of the form
IF ( a.EQ.b ) THEN
ELSE
X = Y
..
ENDIF

should be converted to
IF ( a.NE.b ) THEN
X = Y
..
ENDIF

Possible values are:


0 Leave the code unchanged.
1 Convert by removing the ELSE statement and reversing the
sense of the IF statement test expression.
Where possible, SPAG reverses the sense of the test
expression by changing logical and relational
operators
appropriately. In other cases, for example where a simple
logical variable is used as the test
expression, SPAG uses the
.NOT. operator.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Item 44

Insert Redundant ELSE


Specifies whether SPAG should add a null ELSE block to block IFs
that have an ELSEIF but no ELSE.
Possible values are:
0 Do not insert redundant ELSE.
1 inserts a blank ELSE block in block IFs that contain ELSEIF
block(s) but no ELSE. SPAG also
ensures that SELECT CASE blocks
include a CASE DEFAULT block.

Item 45

DO loops
Specifies which style of DO loop is to be used. Possible values
are:
0 Always use CONTINUE as the DO loop terminator (in
conformance with standard Fortran 77)
1 Use CONTINUE for indexed DO loops, and ENDDO for DO WHILE
loops.
2 Always use ENDDO as the DO loop terminator.
DO loop Example
! Item 45 = 1
DO 100 i = 1 , n
sum = sum + x(i)
100 CONTINUE

! Item 45 = 3
DO i = 1 , n
sum = sum + x(i)
ENDDO

DO..ENDDO is a Fortran 95 feature which is also supported by most


current Fortran 77 compilers.
Item 46

Character Constants
Specifies whether character constants are to be converted to a different format.
In addition to the standard
apostrophe delimited form (e.g. 'word'), SPAG recognizes
Hollerith constants (of the form 4Hword),
and quoted strings (of the form "word"). Hollerith constants need not be supported
by an ANSI Fortran
77 (or 95) compiler, though in practice, most do. Quoted
strings are standard Fortran 95, and are widely
supported by newer Fortran 77
compilers. Possible values are:
0 Convert Holleriths, but not quoted strings. Thus, 4Hword is converted to 'word', but "word" is left
unchanged.
1 Convert both Holleriths and quoted strings to F77 standard
form. Both 4Hword and "word" are
converted to 'word'.
2 Convert quoted strings, but not Holleriths. Thus "word" is converted to 'word', but 4Hword is left
unchanged.
Note that SPAG deals correctly with apostrophes within Holleriths
and quoted strings. Thus "can't" and
5Hcan't are converted to 'can''t'.

Item 47

Fortran 95 Relational Operators


Specifies whether the new Fortran 95 style relational operators
are to be used. Possible values are:
-1 Relational operators are left unchanged.
0

Use the standard Fortran 77 relational operators .LT., .LE., .EQ., .NE., .GE., and .GT.).
Any

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Fortran 95 relational operators are converted to this


form.
1

Use the new Fortran 95 relational operators (<, <=, ==, \=, >= and >).
Any Fortran 77 relational
operators are converted to this
form.

Note that both styles of operator are permitted by the Fortran 95 standard.
Item 48

Fortran 95 END SUBROUTINE statements


Specifies whether SPAG should translate END statements to Fortran
95 END SUBROUTINE, END
PROGRAM, END FUNCTION etc. Possible values
are:
0 Use a simple Fortran 77 style END statement
1 Use END SUBROUTINE, END PROGRAM, END FUNCTION etc.
2 In addition, append the subprogram name (END SUBROUTINE SUB1
etc.)

Item 49

Remove Redundant RETURN and STOP


Specifies whether SPAG should remove redundant RETURN statements
which occur before the END
statement in subprograms, and redundant
STOP statements which occur before the END statement in a
main
program. Possible values are:
0 Leave RETURN and STOP alone.
1 Remove redundant RETURN and STOP before END.

Item 51

Input Statement Length


Specifies the input statement length. Any text after the specified
position on input statement lines is
discarded. A value of 72 is
required if the input code contains sequence numbers in columns
73-80. Note
that comments are not truncated. The maximum permitted
value is 512.
If you want to retain the sequence numbers in your restructured
code, there are two approaches you might
take. The first is to use item 60 and the *-ASIS
directive to force SPAG to leave statements alone.
However, this is
not a safe procedure when applied to executable statements (see section 2.7.9). The
second alternative is to convert
sequence numbers to end-of-line comments by inserting a '!' in column 72
using a text editor.
End-of-line comments using '!' are
permitted in standard Fortran 95 but not in standard
Fortran 77
though most current Fortran 77 compilers accept them.

Item 52

Continued Character Constants


Specifies whether input records should be padded with spaces to
the input statement length (item 51). This
item
only has an effect when a character or Hollerith literal is
continued over more than one line in a fixed
format source file. Possible values are:
0 Do not pad input records with spaces. This value is required
for compatibility with VAX Fortran.
1 Pad input records with spaces to the input record length.
This value is required for strict adherence to
the ANSI
standard.
For example, given
DATA zalph/'ABCDEFGHIJKLM
&NOPQRSTUVWXYZ'/

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

If item 52 is 1, and the input statement length is 72, SPAG


assumes that there are 41 spaces between the M
and N characters. If
item 52 is 0, the number of spaces may be between 0 and 41 depending
on the
position of the end-of-line marker (carriage return) on the
first record.
Item 53

Old-style Direct Access


Specifies whether unpaired apostrophes as used in old-style direct
access (using DEFINE FILE, FIND etc.)
are to be allowed. Possible
values are:
0 Disallow unpaired apostrophes. This setting is recommended
unless you know that old-style direct
access is used.
1 Allow unpaired apostrophes in old-style direct access
statements.

Item 54

PDP style PARAMETER


Specifies whether PDP style PARAMETER statements, with no
enclosing brackets, are to be allowed.
Note that many compilers will
interpret PDP style PARAMETER statements as assignment
statements.
PARAMETER vdim=10

may be interpreted as
PARAMETERVDIM = 10

Possible values are:


0 Interpret PDP style PARAMETER statements as assignment
statements. This setting is recommended
unless you know that
PDP style PARAMETERs are used.
1 Allow PDP style PARAMETER statements.
PDP style PARAMETERs also differ from standard PARAMETERs in that
the type of the constant
determines the type of the PARAMETER. Thus
in the above example, VDIM is of type INTEGER,
because 10 is an
integer. It would be an error to declare VDIM to be of a different
type.
If item 54 is set to 1, SPAG recognizes PDP style PARAMETER
statements, but it treats them as entirely
equivalent to standard
Fortran PARAMETERs. This can lead to problems if SPAG is asked to
insert
declarations for IMPLICITly declared variables. For example,
in the above case, SPAG might deduce,
wrongly, that VDIM was REAL.
The resulting output code will not compile. Currently, the only cure
for
this is to correct the inserted declarations, and convert the PDP
style PARAMETERs to standard Fortran
by hand.
Item 55

FUNCTION with no Arguments


Specifies whether FUNCTIONs may be declared with no argument list.
Note that many compilers will
misinterpret such FUNCTION
statements.
INTEGER FUNCTION random

may be interpreted as a declaration of an INTEGER variable


INTEGER functionrandom

Possible values are:

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

0 Disallow FUNCTION statements without arguments.


1 Allow FUNCTION statements without arguments.
Item 56

INCLUDE file Search Rule (1)


Specifies the default search rule for INCLUDE files. This is
relevant when SPAG is processing files which
are not in the current
directory and which INCLUDE files with no specified path. Possible
values are:
0 INCLUDE files with no specified path are assumed to be in
the current directory.
1 INCLUDE files with no specified path are assumed to be in
the same directory as the source file.
For most compilers, a value of 0 should be specified. However,
others, including Microsoft Fortran,
require a value of 1.
If the INCLUDE file is not found using the above rule, the list of
directories specified using item 215 is
searched.

Item 59

SQL Statements
Specifies whether embedded EXEC SQL statements, as used with
IBM's DB2 database are permitted.
Possible values are:
0 EXEC SQL statements are not recognized.
1 EXEC SQL statements are recognized, and processed as
follows:
The layout of the statements is preserved, but SPAG
attempts to indent them to match
surrounding statements. If,
after indentation, the statement would extend beyond the
right
margin, SPAG reduces the indentation as necessary.
SPAG recognizes labels in the label field of EXEC SQL
statements, and changes them as
required. Statement labels
may not appear within the body of an EXEC SQL statement.
SPAG parses the statement to determine which variables
are modified and/or used and updates
the symbol table
accordingly.
SPAG converts the case of variable names which appear
within an EXEC SQL statement using
the controls in items 100 to 104.

Item 60

Reformat Declaration Statements


Specifies whether SPAG should preserve the format of all
statements in the declaration section of each
subprogram (i.e. before
the first executable statement). Possible values are:
0 Reformat declaration statements. The same statements appear
in the declaration section, but spacing
and case will probably
be different.
1 Do not reformat declaration statements. The declaration
section is completely unchanged in the
restructured code. This
option is appropriate if some declaration statements have been
carefully
hand-formatted. An alternative approach is to use the
*-ASIS directive to preserve the
format of
selected single declaration statements (see section 2.7.9).

Item 61

Tab Characters
Specifies whether SPAG should use tab characters in the output
file. If this option is activated, SPAG

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

replaces repeated space


characters by tabs where possible. Possible values are:
0 Do not use tab characters.
n Use tab characters where possible. There are assumed to be
tab stops at columns n, 2*n, 3*n etc.
The use of tabs is an extension to ANSI standard Fortran which is
supported by most, but not all, Fortran
77 compilers. Note that SPAG
never replaces tab characters which are within character
constants.
Item 62

GOTO or GO TO
Specifies whether GOTO should be spelled with a space in the restructured output code. Possible values
are:
0 for GOTO.
1 for GO TO.

Item 63

ENDIF or END IF
Specifies whether ELSEIF, ENDIF and
ENDDO should be spelled with a space in the restructured output
code. Possible values are:
0 for ELSEIF, ENDIF and ENDDO.
1 for ELSE IF, END IF and END DO.
The second usage (with spaces) often causes confusion to
programmers more familiar with Pascal or C
than Fortran. Both these
languages lack an ELSEIF statement, and, unlike Fortran, both treat
spaces as
significant syntactic elements. As a result, ELSE IF is
often read as an ELSE statement followed by an IF
statement. This
leads to confusion both over the number of ENDIF statements required
to terminate a
block IF, and over the way the code should be
indented. The Fortran ELSEIF statement is in fact more like
the elsif
statements in ADA and Modula 2.

Item 64

BLOCKDATA or BLOCK DATA


Specifies whether BLOCKDATA should be spelled with a space in the restructured output code. Possible
values are:
0 for BLOCKDATA.
1 for BLOCK DATA.

Item 65

DOUBLEPRECISION or DOUBLE PRECISION


Specifies whether DOUBLEPRECISION should be spelled with a space in the restructured output code.
Possible values are:
0 for DOUBLEPRECISION.
1 for DOUBLE PRECISION.

Item 66

Space after Fortran Keywords

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Specifies whether a space is required after Fortran keywords.


Possible values are:
0 No space.
IF(a.GT.b)CALLsub

1 Space except where keyword is followed immediately by a


bracket. (e.g. FORMAT, IF, OPEN).
IF(a.GT.b)CALL sub

With this setting, spaces are also inserted after the label
in a DO statement, after the second '/' in a
labelled
COMMON statement and after the label in an ASSIGN
statement.
COMMON /abc/ a,b,c
ASSIGN 22 TO xx

2 Always put a space after a keyword


IF (a.GT.b) CALL sub

With this setting, spaces are also inserted after the


closing ')' in an IF statement and after the
')' which
terminates a bracketed control list in an I/O
statement.
IF (c.GT.d) THEN
WRITE (*,*) a,b,c

Item 67

Spaces around + and Specifies whether a space is to be placed on either side of + or - operators.
Possible values are:
0 No space either side of + or -.
n Space either side of + or - if fewer than n brackets are
open.
For example
! Item 67 = 0
Y = X+(A*B-C)
! Item 67 = 1
Y = X + (A*B-C)
! Item 67 = 2
Y = X + (A*B - C)

SPAG does not place spaces around arithmetic operators (such as


*, / and **) which bind more strongly
than + and -. This ensures that
spacing reinforces the Fortran standard precedence of arithmetic
operators.
For example, if SPAG were to produce
! Misleading use of spacing
Y = X+(A * B-C)

it would appear that (B-C) was multiplied by A and the result


added to X.
Item 68

Spaces around =
Specifies whether a space is to be placed on either side of =
(mainly in assignment and DO statements).
Possible values are:
0 No space either side of =.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

n Put spaces on either side of = if fewer than n brackets are


open.
For example:
! Item 68 = 0
Z=X*Y
! Item 68 = 1
Z = X*Y

Item 69

Spaces around Logical Operators


Specifies whether a space is required on either side of logical
operators (.AND.,
.OR., .EQV.,
.NEQV.,
.XOR. etc.). Possible values
are:
0

No space either side of logical operators.

Spaces either side of logical operators if fewer than n


brackets are open.

-n Spaces either side of both relational and logical operators if fewer than n
brackets are open.
For example
! Item 69 = 0
QSW = b.GT.a.AND.b.LT.c
!

Item 69 = 1
QSW = b.GT.a .AND. b.LT.c

Item 69 = -1
QSW = b .GT. a .AND. b .LT. c

In Fortran, relational operators (such as


.LT., .EQ. etc.)
bind more strongly than logical operators
(.AND., .OR. etc.), and a value of n>0 makes this
precedence clearer.
Item 70

Spaces around Commas


Specifies whether a space is required on either side of commas.
Possible values are:
0 No space either side of commas.
n Spaces either side of commas if fewer than n brackets are
open. If n is negative, a space is placed
after the comma, but
not before.

Item 71

Spaces in IF statement
Specifies whether a space should be inserted on either side of the
test expression in IF statements. Possible
values are:
0 No extra spaces.
1 Insert extra spaces.
For Example
! Item 71 = 0
IF (Q1) THEN
! Item 71 = 1
IF ( Q1 ) THEN

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Item 73

Spaces around Concatenation Operator


Specifies whether a space is required on either side of the
concatenation operator ('//').
Possible values are:
0 No space either side of //.
n Spaces either side of concatenation operators if fewer than
n brackets are open.
For example
! item 73 = 0
zname = '*.'//zextn
! item 73 = 1
zname = '*.' // zextn

Item 79

Separate Declaration for every variable


Specifies whether SPAG is to create a separate type declaration
statement for every variable. This option is
active only if item 4 is set to 3 or 4 (to invoke the declaration rewriting
option). Possible values are:
0 Multiple variables on a single declaration.
INTEGER i , j

1 One variable per declaration.


INTEGER i
INTEGER j

2 Similarly for SAVE, EXTERNAL and INTRINSIC statements.


Item 80

Preserve Statement Labels


Specifies whether statement labels are to be preserved. Possible
values are:
0

Discard all pre-existing labels and start re-labelling from


scratch.

Preserve labels with a value greater than or equal to n.


Other labels are discarded. Labels which are
redundant in the
unscrambled code are removed.

-n Preserve labels with a value greater than or equal to n,


even if they are redundant in the unscrambled
code. Some
compilers object to this, particularly if the redundant label
is on an ELSE or ELSEIF
statement.
For example a value of -8000 would allow SPAG to discard all
labels with a value of less than 8000, and
where necessary, invent
new ones according to the rules specified below. Labels with a value
of 8000 or
more are preserved in the unscrambled code, even if they
are not referenced.
The most commonly used values are 0 (to discard all pre-existing
labels) and 1 (to preserve all nonredundant labels). Note that, in
some circumstances, for example when several DO loops terminate at
the
same statement, SPAG may have to invent new labels, whatever
setting is used.
Item 81

New Label Base


Initial base counter for new labels (except those on FORMAT
statements). When SPAG needs to generate

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

a new label, it increments


the base counter to the next higher multiple of the increment
appropriate to the
current indentation level (i.e. the number of open
DO, IF or SELECT CASE blocks). For example, if the
current base
counter is 945, and a label is required on a statement which is
indented 3 times, and if the
increment for this degree of indentation
is 20, then the label will be 960 (the next higher multiple of
20).
Item 82

Label Increment 0
Label increment for un-indented code - i.e. labelled statements
which are not inside any DO or block IF
constructs.

Item 83

Label Increment 1
Label increment for code at indentation level 1 - i.e. labelled
statements inside only one DO or block IF
construct.

Item 84

Label Increment 2
Label increment for code at indentation level 2.

Item 85

Label Increment 3
Label increment for code at indentation level 3.

Item 86

Label Increment 4
Label increment for code at indentation level 4.

Item 87

Label Increment 5
Label increment for code at indentation level 5 or above.

Item 88

Format Label Base


Initial base counter for re-labelling FORMAT statements. When SPAG
needs to generate a new label for a
FORMAT statement, it increments
the FORMAT statement base counter to the next higher multiple of the

FORMAT statement increment. For example, if the current FORMAT


statement base counter is 99010,
and the FORMAT statement increment
is 2, then the next FORMAT statement will have the label 99012.

Item 89

Format Label Increment


FORMAT statement label increment to be used in conjunction with
the FORMAT statement base counter
as described above.
If the FORMAT statement increment is set to 0, FORMAT statement
labels are not treated specially, but
are calculated using the base
counter and increments defined in items 81 to 87.

Item 90

Label Justification
Specifies how statement labels are to be formatted. Possible
values are:
0 Right justified at column 5.
n Left justified at column n.
In fixed format code, a value of 2 (left justified at column 2) has the advantage of
separating labels visually
both from comments (C or * in column 1)
and continuation markers (column 6).
SPAG will over-ride the specified rule if the label will not
otherwise fit. For example if the label is 99001,

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

it will start in
column 1 regardless of how this control is set.
Item 100 Case of Local Variables
Specifies what case conversion is done for local variable names.
Possible values are:
-1 Leave case unchanged.
0

Convert to lower case.

(n<9) Convert first n characters to upper case, and the


remainder to lower case.

Convert to upper case.

If SPAG has to insert new occurrences of the symbol (for example,


when inserting declarations for
implicitly typed variables), it will
use upper case if the corresponding control is set to -1.
Note that the use of lower case in variable names is not strictly
standard Fortran 77, though all recent
compilers accept it.
Item 101 Case of COMMON variables
Specifies what case conversion is done for COMMON variable names.
Possible values are as detailed for
item 100.
Item 102 Case of Dummy Arguments
Specifies what case conversion is done for dummy argument names.
Possible values are as detailed for
item 100.
Item 103 Case of PARAMETERs
Specifies what case conversion is done for PARAMETER names.
Possible values are as detailed for item
100.
Item 104 Case of other Symbols
Specifies what case conversion is done for other user-defined
symbols (COMMON block names,
NAMELIST names, subprogram names etc.).
If item 2 is set to -1 (no symbol tables generated),
then this
control applies to all user-defined symbols. Possible
values are as detailed for item 100.
Item 106 CASE of logical and relational operators
Specifies what case conversion is done for logical and relational
operators (.AND.,
.NE. etc.). Possible
values are:
0 Convert logical and relational operators to lower case.
1 Convert logical and relational operators to upper case.
Item 107 Case of Fortran keywords
Specifies what case conversion is done for Fortran keywords (READ,
THEN, INTEGER etc.). Possible
values are:
0 Convert Fortran keywords to lower case.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

1 Convert Fortran keywords to upper case.


An unusual feature of Fortran is that it does not have reserved
names. Thus 'INTEGER' is a perfectly valid
variable name,
even though it is also a Fortran keyword. SPAG recognizes this
distinction, and uses item
107 only if the context confirms that a
word is used as a keyword.
Item 108 Case of Character Strings
Specifies what case conversion is done for character strings.
Possible values are:
0

Leave the case of character strings unchanged


(recommended).

-1 Convert character strings to lower case.


1

Convert character strings to upper case.

Item 109 Case of Comments


Specifies what case conversion is done for comments (from column 2
onwards). Possible values are:
0

Leave the case of comments unchanged.

-1 Convert comments to lower case.


1

Convert comments to upper case.

Item 121 Right Margin for Output


The right margin for source code - normally set to 72 for fixed format code. SPAG
ensures that source
code is not written past the right margin; if
necessary, SPAG inserts continuation lines to hold the extra
code.
For conformance to the ANSI 77 standard, set the right margin to 72
or less. Most Fortran 77
compilers ignore any text after column 72,
though some can be configured to accept it. The maximum
permitted
value for the right margin is 132.
Note that comments are NOT truncated at the right margin.
Item 122 Left Margin for Output
The left margin for un-indented statements (excluding labels).
Fortran 77 reserves the first six columns of
each record for labels
and continuation markers, so the value specified here must be at
least 7, unless the
new Fortran 95 source form is used (see item 141).
Item 123 Unit of Indentation
The number of characters by which statements within active DO
loop, block IF or SELECT CASE
constructs are to be indented. For
example if a value of 3 is specified, and un-indented statements
start at
column 7 (item 122) then statements which
are inside 4 open block constructs will be started at column 19
(7 +
4x3).
Item 124 Maximum Indentation
The maximum permitted left margin (after indentation). This item
places a limit on the amount of
indentation. Without it, programs
with a lot of open blocks could be placed beyond the right
margin.
Item 125 Continuation Character
The character code of the continuation character. SPAG inserts
CHAR(n) at column 6 of all continuation
http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

lines of fixed format source code. Use of the '&' character is recommended for
compatibility with Fortran
95. If you specify that output is to be
written using the free format Fortran 95 source form (see item 141),
'&' is
used as the continuation character, and this control has no effect.
The character code for '&' is
38 on
ASCII based machines (the vast majority), and 80 on EBCDIC
machines (IBM mainframes).
Item 126 Comment Character
The character code of the comment character. SPAG inserts CHAR(n)
at column 1 of all comment lines
(excluding lines with end of line
comments).
Suitable ASCII values for n are 33 (!),
42 (*), 67 (C)
and 99(c). If the item is set to 0, the
pre-existing
comment character is retained. If you specify that output is to be
written using the free format Fortran 95
source form (see item 141), '!' is
used as the continuation character, and this control has no effect.
Item 127 Comment Justification
Specifies whether SPAG should reformat the text of comments.
Possible values are:
0

Do not reformat comments

Left justify the comment text to column n. The comment


character in column 1 is not moved. SPAG
attempts to preserve
existing indentations within comment blocks.

81 Comments are aligned with the surrounding code, and text is


word-wrapped so that comments do
not extend beyond column 80.
Comments before an IMPLICIT statement are not changed. Set this
control to 82 or 83 causes other comments within the
declaration section to be preserved.
Item 130 COMMON Block Alignment Tests
Specifies whether SPAG should check the alignment of variables in
COMMON blocks. Possible values
are:
0 No COMMON block alignment checks.
1 SPAG reports cases where the offset of a COMMON variable
from the start of a COMMON block is
not a multiple of the
variable element size. For example, if an 8 byte variable is
offset 36 bytes from
the start of a COMMON block, SPAG issues a
warning, because 36 is not a multiple of 8.
Item 131 Floating Point Equality Test
Specifies whether SPAG should report the existence of unsafe tests
for equality of floating point data.
Possible values are:
0 No checks for floating point equality tests.
1 SPAG reports cases where a relational expression depends on
a test for equality (or inequality)
between REAL or DOUBLE
PRECISION data. Such tests may produce irreproducible results,
because floating point numbers are not represented exactly.
Item 132 Variable Name Checks
Specifies whether SPAG should issue a warning if a variable or
array name is the same as a Fortran
keyword or INTRINSIC function.
Possible values are:
0 No checks on variable names.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

1 SPAG issues a warning if any variable or array name is the


same as a Fortran keyword or
INTRINSIC function.
Item 133 Subprogram Argument Checks
Specifies whether SPAG should check for consistency of subprogram arguments. If this option is selected,
SPAG warns if the number or type of arguments varies between invocations of a subprogram.
This is
appropriate for
Fortran 77 source code, but in Fortran 95 the number of arguments may vary if the callee
has optional arguments, and the type may vary if
the callee is overloaded. For this reason, it is
recommended that this
check be switched off when processing Fortran 95 input code.
Possible values are:
0 No checks on subprogram argument consistency (recommended for Fortran 95 input code).
1 SPAG issues a warning if the number and/or type of arguments
varies between invocations of a
subprogram.
Item 138 Conversion of #include to INCLUDE
Specifies whether SPAG should convert C preoprocessor includes (using #include) to standard Fortran
95 format (using an INCLUDE statement). Possible values are:
0 Convert #include to a standard
Fortran INCLUDE statement.
1 Leave #include unchanged.
Item 140 Input Source Form
Specifies the format of the input source code. Possible values
are:
0 input code is fixed format (F77 source form).
1 input code is free format (F95 source form).
Item 141 Output Source Form
Specifies the required format of the output source code. Possible
values are:
0 output code is fixed format (F77 source form).
1 output code is free format (F95 source form).
2 output code is F77 and F95 compatible. The output code is in
the Fortran 95 free format source form,
but is compatible with
the fixed Fortran 77 source form, provided that the compiler
recognizes lines
beginning with '!' as comments.
If this control is set greater than 0, item 125
(the continuation character) is set to '&' and item 126
(the
comment character) is set to '!'. In addition the first characters of items 220-223 (various comments
inserted by SPAG) are changed to '!'.
Item 210 File containing Intrinsic Function Names
The name of a file containing a list of INTRINSIC and
'safe' functions. The file is plain text and consists of
a
list of function names separated by spaces and/or new lines. Three
sample files containing lists of
intrinsic functions in standard
Fortran 95 (f95func.txt), Fortran 77
(f77func.txt) and VAX Fortran

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

(vaxfunc.txt) are supplied with SPAG. If


the file contains a '/' character
on a line by itself, then names
before it are interpreted as
intrinsic functions, and names after it are interpreted as
non-intrinsic safe
functions (see item 12).
Item 211 File containing Renames
The name of a file containing a list of renames for the current
run. This file is read only if item 5 is set to 1
or
more. See section 2.7.8 for further
discussion.
Item 213 Module for Translation INTEGER*2 etc.
Specifies the name of a Fortran 95 source file containing a module
(normally called F77KINDS) which is
used to allow translation of
non-standard Fortran types, such as INTEGER*2 and REAL*4 to standard
Fortran 95 types. For example, INTEGER*2 is normally translated as
INTEGER(I2KIND) where I2KIND
is a PARAMETER, declared in F77KINDS
with the appropriate value.
Because different compilers use different KIND values, it is
necessary to create a version of F77KINDS
for the compiler in use.
The program mkkind.f90, supplied with
plusFORT does this automatically.
Simply compile and
run mkkind.f90 with your target compiler
to create a version of f77kinds.f90 for
use
with SPAG.
You will also need to use the module when compiling the
restructured code.
Item 212 is now redundant, and the kind.txt file included with version 5.00 of SPAG is no longer
used. It's
function is assumed by item 213.
Item 215 INCLUDE file Search Path (2)
A list of directories, separated by semicolons, which are to be
searched if an INCLUDE file which is
specified without a path is not
found in the current directory (or the source directory - see item 56). For
example, if, on a DOS/Windows system the
list is C:\INCLUDE;C:\SYSIN, and if an
included file name
does not specify a path, SPAG looks first in the
current directory (but see item 56), then in C:\INCLUDE
and finally in C:\SYSIN. If it is not found in any of these
directories, SPAG reports an error. For UNIX
and VMS systems, the
file naming conventions are different, but otherwise the mechanism is
the same.
Item 220 Header Record Identifier
Four characters used as header record identifiers in the output
file. SPAG writes a header record before
each subprogram in the
output file. The header record consists of a 4 character identifier,
followed by a
file name. QSPLIT uses these file names to split output
files created by SPAG into a single file for each
subprogram. The
default header record identifier is !*==.
Standard Fortran 77 does not recognise lines
beginning with ! as comments, though, in practice, most recent
compilers do. If your compiler does not
recognise !
as a comment character, it will be necessary to change the header record identifier (e.g. to
**==). If the header record
identifier is blank, no header records are written.
For example:
!*==TEST1.NEW

It is very important to ensure that the header record identifier


is not used in any other context, as SPAG
removes pre-existing header
records when it writes the output file. For example, it would be very
unwise
to use the character 'C' as
the header record identifier, as SPAG would then delete any line
which begins
with a 'C' followed by
three spaces.
Item 221 Interface Description Header Marker
When GXCHK inserts an Interface Description block into the
restructured source code (see Section 3.6), it
http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

inserts header and


trailer marker comments. This is done so that it can remove any
pre-existing interface
description block before inserting a new one.
This item specifies the four characters at the beginning of
the
header marker. The default is !*--. If your compiler does not recognise !
as a comment character, it
will be necessary to change this item (e.g. to **--).
As with item 220, it is very important to
ensure that the marker is not used in any other context, or
GXCHK might
then remove comments which are not part of an old interface description
block.
Item 222 Interface Description Trailer Marker
Specifies the four characters at the beginning of the Interface
Description Trailer Marker (see item 221).
The default is !*++. If your compiler does not recognise !
as a comment character, it will be necessary to
change this item (e.g. to **++).
Item 223 Marker for First Executable Statement
If this item is set, it is treated as a comment to be inserted
before the first executable statement in every
subprogram. For
example:
!***_Start_of_Executable_Program

Before output, SPAG translates any underscore characters in the


value to spaces.
Item 230 Output File Directory (or prefix)
Specifies a prefix for the names of restructured output files.
This could be a directory name (the directory
must exist), or simply
a prefix to the filename. Under UNIX and DOS/Windows, a closing
'/' or '\' is
required if a directory is
specified.
If no prefix is specified, restructured source files are
written in the same directory as the input source code.
Item 231 Output File Extension
The filename extension to be used for restructured output files
(e.g. .spg). The extension is also used
as the
filename extension on header records in the output file (see
item 220). SPAG constructs the file name on
the
header records by appending the extension specified here to the
subprogram name.
Item 232 Symbol File Directory (or prefix)
Specifies a prefix for the names of symbol table files. This could
be a directory name (the directory must
exist), or simply a prefix to
the filename. Under UNIX and DOS/Windows, a closing '/' or '\' is
required
if a directory is specified.
If no prefix is specified, symbol table files are
written in the same directory as the input source code.
Item 233 Symbol File Extension
The filename extension to be used for symbol table files (e.g.
.smb ).
Item 234 Coverage Data File Directory (or prefix)
Specifies a prefix for the names of coverage data files. This
could be a directory name (the directory must
exist), or simply a
prefix to the filename. Under UNIX and DOS/Windows, a closing
'/' or '\' is required
if a directory is specified. It is
strongly recommended that an absolute path rather than a relative
path be
specified (e.g. C:\myprog\cover\
rather than ..\cover\), as this will
allow the instrumented program to find
the coverage data files in all
cases.
This item must be specified if item 6 is set to
2.
http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Item 235 Coverage Data File Extension


The filename extension to be used for coverage data files. This is
normally set to .cvr.
Item 236 Module File Directory (or prefix)
Specifies a prefix for the names of module files created by SPAG
(includes INTERFACE modules, and
modules to replace COMMON blocks and
INCLUDE files). This could be a directory name (the directory
must
exist), or simply a prefix to the filename. Under UNIX and
DOS/Windows, a closing '/' or
'\' is
required if a directory is
specified.
Item 237 Module File Extension
The filename extension (e.g. .ifc or .f90) to be used for the output files containing the
source code for
modules created by SPAG
(includes INTERFACE modules, and modules to replace COMMON blocks
and
INCLUDE files).
Item 240 Dynamic Analysis Probe Routine Root 1
A 3 character root used at the start of the names of the dynamic
analysis probe routines which check
whether variables are defined or
not. The three characters should be chosen so as to avoid clashes
with
other routines. If you change this item from the default value (QD$), you will also have to change the
source for the probe routines (in the
file probes.for or probes.f). See section 2.8 for further
discussion of dynamic analysis.
Item 241 Dynamic Analysis Probe Routine Root 2
A 3 character root used at the start of the names of additional
dynamic analysis probe routines. The three
characters should be
chosen so as to avoid clashes with other routines. Currently, this
item is not used.
Item 242 Dynamic Analysis Undefine Routine Root
A 3 character root used at the start of the names of the dynamic
analysis probe routines which set variables
to the undefined value.
The three characters should be chosen so as to avoid clashes with
other routines. If
you change this item from the default value (UD$), you will also have to change the source for the probe
routines (in the
file probes.for or probes.f).
See section 2.8 for further discussion of dynamic
analysis.
Item 243 Program Entry Trace Routine
If item 6 is set greater than 0, a statement is
inserted in the output code so that it is executed immediately
after
the program starts. Item 243 specifies the main part of the text of
the statement. Note that the text
may not include spaces, because the
first space marks the start of the comment field. However, you may
include the underscore character '_'; SPAG translates underscores to spaces before
writing the statement.
If you change this item from the default value (CALL_PR$ENT), you will also have to change the source
for the probe routines (in the
file probes.for or probes.f).
See section 2.9 for further discussion of
coverage analysis.
Item 244 Program Exit Trace Routine
If item 6 is set greater than 0, a statement is
inserted in the output code so that it is executed immediately
before
the program stops. Item 244 specifies the main part of the text of
the statement. Use the underscore
character '_', to mark the position of spaces. If you change this item from the default value
(CALL_PR$EXI), you will also have to change the source for the probe routines (in the
file probes.for
or probes.f).

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

See section 2.9 for further discussion of


coverage analysis.
Item 245 Subprogram Entry Trace Routine
If item 6 is set greater than 0, a statement is
inserted in the output code so that it is executed whenever a
subprogram is invoked. Item 245 specifies the main part of the text
of the statement. Use the underscore
character '_', to mark the position of spaces. If you change this item from the default value
(CALL_SB$ENT), you will also have to change the source for the probe routines (in the
file probes.for
or probes.f).
See section 2.9 for further discussion of
coverage analysis.
Item 246 Subprogram Exit Trace Routine
If item 6 is set greater than 0, a statement is
inserted in the output code so that it is executed whenever
control
is returned from a subprogram. Item 246 specifies the main part of
the text of the statement. Use
the underscore character '_', to mark the position of spaces. If you change this item from the default value
(CALL_SB$EXI), you will also have to change the source for the probe routines (in the
file probes.for
or probes.f).
See section 2.9 for further discussion of
coverage analysis.
Item 247 Code Block Entry Trace Routine
If item 6 is set greater than 1, statements are
inserted in the output code at the start of every code block.
These
statements may be used to provide test coverage and execution
hot-spot analysis. Item 247 specifies
the main part of the text of
the statement. Use the underscore character '_', to mark the position of spaces.
If you change this item from the default value (CALL_BL$ENT), you will also have to change the source
for the probe routines (in the
file probes.for or probes.f).
See section 2.9 for further discussion of
coverage analysis.

2.7 Using SPAG


2.7.1 Adding Declarations
Most older Fortran programs are written in an 'implicitly typed'
environment. That is to say that variables are not
formally declared at the
head of each procedure as they are in Pascal or C; instead, variables are
implicitly declared
simply by using them. The compiler determines the type
of the variable from the first letter of its name. For example,
variables
whose name begins with the letter 'I' are normally of type
INTEGER.
No doubt this appeared to the pioneers who created Fortran as an
advantage, and at first sight it may appear that the
compiler is simply
doing automatically what the programmer would otherwise have to do by hand.
We now know
better; the problem is that it is all too easy for the compiler
to create variables in a way not intended by the programmer.
A simple
example illustrates the point:

10

I0 = 0
DO 10 i = 1.100
READ *,j
IO = I0 + j
CONTINUE

In this example, the variable I0 is mis-typed as IO on line 4, and as a


result a spurious new variable IO is created.
Moreover, the second
statement is, despite appearances, an assignment to the spurious REAL
variable DO10I (spaces
are not significant in Fortran). A language which
requires explicit declarations would have spotted that IO and DO10I
had not
been declared, and reported an error at compile-time. But mis-spelling is
not the only problem. Even commoner
http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

is confusion between local and COMMON


variables. For example, if you INCLUDE a file which declares a
COMMON
variable named K, in a routine which has a local variable called K, all
manner of obscure symptoms are
possible.
Fortran can be made to require explicit typing. The IMPLICIT NONE
statement, which disables implicit typing, is
standard Fortran 95, but even
Fortran 77 compilers generally accept it. Its use can be thoroughly recommended. As an
alternative, some compilers have a
compiler switch to disable implicit typing without resort to IMPLICIT NONE.
SPAG provides the means for converting existing, implicitly typed
programs to explicitly typed programs for use with
IMPLICIT NONE. It does
this by adding explicit declarations for all undeclared variables at the
head of each
subprogram and INCLUDE file. Doing this by hand on a large
program could take weeks - enough to make the switch
impractical. However,
the fact that SPAG can do it quickly doesn't mean it should be done
carelessly; for example,
there would be little point in doing it as a
regular routine, as the benefits of explicit typing are then lost. Ideally,
the
declarations inserted by SPAG should be checked for spurious entries
caused by past mistakes. However, explicit
typing will help prevent future
errors even if some past errors remain.
The 'auto-declarer' feature of SPAG is activated by setting item 4 of spag.fig greater than
0. If it is set to 1, declarations
are inserted for all undeclared
variables, parameters, dummy arguments and functions other than intrinsic
functions
(whose names are read from a file - see item
210 of spag.fig). Intrinsic functions are
excluded because their type may
vary (e.g. MIN may be REAL in one place and
INTEGER in another). If item 4 of spag.fig is set to 2, SPAG also
inserts an IMPLICIT NONE statement,
and removes any pre-existing IMPLICITs (provided that they are not in an
INCLUDEd file).

2.7.2 Adding Declarations to INCLUDEd files


Declarations must be added to INCLUDEd files in a separate run. SPAG can
process isolated INCLUDE files, though
some warnings will be generated (no
END statement, variables not used etc.).
When SPAG adds declarations to a subprogram, it has all the information
required to determine the type and nature of
every symbol in it. Some of
this information may be contained in INCLUDEd files. However, when SPAG
adds
declarations to an incomplete source code, such as an INCLUDE file, it
may find that some information is missing.
For example, if an INCLUDE file contains the single statement
COMMON /ABC/

XX(N),I,J,K

we cannot determine the type of any of the variables. We know that XX is


an array, but I, J and K may be too. We can
infer that N is an INTEGER
PARAMETER, but we don't know its value, or whether it is a 1, 2 or 4
byte INTEGER. It
is even possible that the same INCLUDE file means
different things in different places.
In cases like this, it is best to insert extra statements to fill in the
missing information. For example, if you insert the two
lines:
IMPLICIT LOGICAL(A-J,O-Z),INTEGER*2 (K-N)
INCLUDE 'dims.inc'

where dims.inc contains PARAMETER


definitions (including one for N), then SPAG will be able to do a much
better
job. You should remove the redundant IMPLICIT statement when SPAG
has finished (we recommend that IMPLICIT
statements should never be placed
in INCLUDE files).
The objective is to ensure that before processing, each INCLUDE file is
self-contained, and not reliant on context to
define its meaning. In fact
this is a good principle in general: if all INCLUDE files are constructed
this way, many
subtle bugs are eliminated (e.g. the size of XX varies
because there are multiple non-identical definitions of N).

2.7.3 Rewriting Declarations


http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

SPAG can also rewrite the declaration section of a subprogram from


scratch, using either Fortran 77 or Fortran 95
declaration style. This is
done by setting item 4 of the configuration data to 4 or 6
respectively. For example, given the
following code fragment:

PARAMETER (MXOB=50)
PARAMETER (MXAT=MXOB)
PARAMETER (MXANG=80)
COMMON /ODDS / NNOBS,NATOMS,NANGLS,SC(2)
comment 1
REAL*8 X(MXAT),Y(MXAT),Z(MXAT),CHGE(MXAT)
INTEGER IP(MXOB),IQ(MXOB),NAT(MXAT),ITYP(MXAT)
INTEGER ITA(3,MXANG)
REAL*8 AKT(MXOB),ALO(MXOB),AKA(MXANG),AAO(MXANG)
INTEGER IWORK(MXAT)
! comment 2
INTEGER*2 TOSPN(MXAT)
INTEGER MXIT,I
REAL*8 RMSMIN,ENGMIN,RMS,ENERG1,ENERGY
RMSMIN = 0.0

then, if item 4 is set to 4, SPAG produces:


C*** Start of declarations rewritten by SPAG
C
C PARAMETER definitions
C
INTEGER MXOB , MXAT , MXANG
PARAMETER (MXOB=50,MXAT=MXOB,MXANG=80)
C
C COMMON variables
C
INTEGER NANgls , NAToms , NNObs
REAL*8 SC(2)
COMMON /ODDS / NNObs , NAToms , NANgls , SC
C
C Dummy arguments
C
REAL*8 Energy , Engmin , Rmsmin
REAL*8 Alo(MXOB)
C
C Local variables
C
REAL*8 aao(MXANG) , aka(MXANG) , akt(MXOB) ,
&
chge(MXAT) , energ1 , rms , x(MXAT) ,
&
y(MXAT) , z(MXAT)
INTEGER i , ip(MXOB) , iq(MXOB) , ita(3,MXANG) ,
&
ityp(MXAT) , iwork(MXAT) , mxit , nat(MXAT)
INTEGER*2 tospn(MXAT)
C
C*** End of declarations rewritten by SPAG
C
C comment 1
! comment 2
Rmsmin = 0.0

If item 4 is set to 36, SPAG produces:


!*** Start of declarations rewritten by SPAG
!
! PARAMETER definitions
!
INTEGER , PARAMETER :: MXOB = 50 , MXAT = MXOB , &
!
! COMMON variables
!
INTEGER :: NANgls , NAToms , NNObs
REAL(R8KIND) , DIMENSION(2) :: SC
COMMON /ODDS / NNObs , NAToms , NANgls , SC
!
! Dummy arguments
!
REAL(R8KIND) :: Energy , Engmin , Rmsmin
REAL(R8KIND) , DIMENSION(MXOB) :: Alo
INTENT (OUT) Rmsmin
!

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

&

MXANG = 80

SPAG

! Local variables
!
REAL(R8KIND) , DIMENSION(MXANG) :: aao , aka
REAL(R8KIND) , DIMENSION(MXOB) :: akt
REAL(R8KIND) , DIMENSION(MXAT) :: chge , x , y , z
REAL(R8KIND) :: energ1 , rms
INTEGER :: i , mxit
INTEGER , DIMENSION(MXOB) :: ip , iq
INTEGER , DIMENSION(3,MXANG) :: ita
INTEGER , DIMENSION(MXAT) :: ityp , iwork , nat
INTEGER(I2KIND) , DIMENSION(MXAT) :: tospn
!
!*** End of declarations rewritten by SPAG
!
! comment 1
! comment 2
Rmsmin = 0.0

SPAG breaks the declarations into four labelled sections, any of which
may be absent:
PARAMETERs. These are placed at the start of the declaration section,
and remain in their original order (in case
the definitions are
interdependent). Here and elsewhere, constant expressions are not
evaluated, but are preserved
in their original forms.
COMMON variables. If necessary, dimensioning information is moved
from the COMMON statement to the type
declaration.
Dummy Arguments. In the Fortran 95 version, SPAG optionally adds
INTENT statements based on how the
argument is actually used in the
subprogram. For example arguments which are never modified are specified
in
an INTENT(IN) statement.
Local variables. In the Fortran 95 version, arrays with identical
type and dimension information are grouped
together so that the dimension
data is specified only once.
Because of the fundamental nature of the rewriting process, it is not
possible to retain comments in their original
relation to declarations.
Thus, in the above example, comments which were attached to the old
declarations are grouped
together after the rewritten code.
INCLUDE statements from the original code are, depending on item 4 of spag.fig, rewritten as
modules, or placed
before the first rewritten declaration. As a result:
Declarations in the INCLUDEd file may not depend on local
declarations. In particular, a local PARAMETER
may not be referenced in
an INCLUDEd file. However, PARAMETERs from INCLUDEd files may be used in
local declarations.
INCLUDEd files should not contain executable statements, statement
functions or DATA statements, or Fortran
statement ordering rules may be
violated.

2.7.4 Interface Modules


If item 4 of spag.fig is
set appropriately, SPAG creates modules containing interfaces for every
subroutine or function it
processes. It also inserts appropriate USE
statements at the head of the calling subprograms. Together, these changes
make it possible for a Fortran 95 compiler to check that the arguments in
every subprogram reference match the
corresponding dummy arguments.
At first sight, this may seem a pointless exercise, as plusFORT manages the same checks, and more, without any help
from the user! However the modules can also be passed to others, and this
will allow them to check interfaces without
having access to the source
code.
If the called subprogram name is abc, the
interface module name will be s_abc, and it
will be stored in a file as specified
by items 11, 236 and 237 of spag.fig.
If the program calls a subprogram that has not been processed by SPAG,
there is no interface module to satisfy the

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

reference in the calling


subprogram's USE statement. In this case, the user must either provide
an interface module to
satisfy the reference, or remove the USE
statement.

2.7.5 Include File Modules


SPAG can also translate INCLUDE files to Fortran 95 modules. Each
INCLUDE file is translated the first time it is
encountered in a run,.
SPAG derives the module name from the INCLUDE file name by discarding
the directory and extension, and prefacing
the two characters i_. For example, an INCLUDE file called f:\include\abc.inc will be translated to a module called
i_abc. This module is written to a file called
\moddir\i_abc.xyz, where \moddir\ is the directory specified in item
236,
and .xyz is the extension specified
in item 237.
To be translated correctly, an INCLUDE file must:
Contain only INCLUDE, PARAMETER and COMMON statements, together with
associated type and dimension
statements. SPAG will issue an error
message if this rule is violated.
Be self-contained. For example an INCLUDE file which contains the
single statement:
COMMON /aaa/ x(n)

is not self-contained, because the type of


x, and the type and value of n are undefined. In one context, x may be
REAL, and n may be an INTEGER PARAMETER with a value of 100. In
another, x may be a LOGICAL array,
and n may be 2000. The module
written by SPAG will assume that the context in the first occurrence of
the
INCLUDE file is universal.
To make the above INCLUDE file self-contained, one might add two
statements as shown below:
REAL x
INCLUDE 'dims.inc'
COMMON /aaa/ x(n)

where the type and value of n are defined in dims.inc (which must itself be self-contained).

2.7.6 COMMON block Modules


SPAG can also translate COMMON blocks which are not contained in an
INCLUDE file to Fortran 95 modules.
However it is strongly recommended that
COMMON blocks be put into INCLUDE files before translation is
attempted.
This is because the conditions required for correct translation of an
isolated COMMON are stricter than for
INCLUDE files. For a COMMON block to
be translated correctly:
Every definition of the COMMON must be identical - not only the
variable types and array sizes, but also the
variable names.
PARAMETERs may not be used in COMMON array declarations.
SPAG derives the module name from the COMMON block name by discarding
the '/'s, and prefacing the two characters
c_. For example, an INCLUDE file called /HELLO/ will be translated
to a module called c_hello. This module is
written to a file called \moddir\c_hello.xyz,
where \moddir\ is the directory specified in
item 236, and .xyz is the
extension specified in item 237.

2.7.7 Removing Clutter


As programs are developed, variables, parameters, COMMON blocks and code
fragments fall into disuse. Programmers
are often reluctant to remove such
'clutter' because of the possibility of un-looked for side effects.
However over a

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

period, clutter can make programs more obscure and difficult


to maintain than they need be. SPAG can remove many
types of clutter, and
identify many others. Specifically, SPAG can remove the following (provided
they are not defined
in an INCLUDEd file):
unused and uninitialized local variables (if item 3
of spag.fig > 1).
unused PARAMETERs and local variables initialized in a type statement
(if item 3 of spag.fig >
2).
unused COMMON blocks (if item 3 of spag.fig > 3).
unused INCLUDE files (if item 3 of spag.fig > 4).
inaccessible code fragments (if item 29 of spag.fig > 0).
If item 3 is set to 1, and item 29 to
0, SPAG identifies, but does not remove the above.
ANSI standard Fortran allows compilers to allocate memory for COMMON
blocks dynamically. Theoretically, a
COMMON block becomes undefined if it
is not referenced by any executing subprogram. In practice, most, if not
all
current compilers treat COMMON blocks as static, and many users would
be confused and dismayed if they did not!
If SPAG removes an unreferenced COMMON block, the point at which the
COMMON theoretically becomes
undefined may also be altered. If you wish to
avoid this possibility, specify the COMMON block name in a SAVE
statement,
set item 3 of the SPAG configuration data to 3 or less, or
ensure that all COMMONs are specified in the
main PROGRAM (SPAG never
removes COMMONs or INCLUDEs from a main program or BLOCK DATA).
SPAG identifies, but cannot remove
unused dummy arguments.
local variables which are assigned a value or initialized in a DATA
statement, but never referenced.
local variables which are used, but never assigned a value.
The GXCHK program which uses the symbol tables written by SPAG to
construct a global symbol table for an entire
program identifies clutter on
a program-wide basis (e.g. globally unused COMMON variables).

2.7.8 Renaming Symbols


SPAG provides a simple and safe method for systematically changing the
names of symbols within a program. SPAG
guards against the danger of
choosing a new name which is already in use, and re-formats the source code
appropriately. The rename facility is activated by setting item 5 of spag.fig to 1, and specifying
the name of a file
containing details of the required changes in item 211.
A sample rename file is shown below. The file consists of a series of
sections, separated by blank lines. The first line of
each section
specifies the scope of the following instructions. The remaining lines in
the section specify the before and
after names, separated by spaces, of the
symbol to be renamed. If the scope is '*', the changes are applied without
restriction. This
could be used, for example, to change specific function names, such as
AMAX0, to the generic form
(MAX). If the scope is a file-name surrounded by
apostrophes, the changes are made only if the specified file is
INCLUDEd in
the current subprogram. Note that the INCLUDE file itself is not changed -
only the references to it in
the current subprogram. If the scope is a
subprogram name, the changes are made only within the specified
subprogram.
Example Rename File
*
AMOD10
AMIN1

mod
min

'test1.prv'
fchsta
zsyst
/pkchAR/

firstc
zzzsys
/pkcomm/

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

swstx2
ityp
jtyp
lopbr
lclbr

jtyp
ityp
lclbr
lopbr

swfrag
oxo

xox

2.7.9 The 'ASIS' Directive


In some circumstances, it may be desirable to suppress the re-formatting
of statements. This is particularly true when a
long declaration has been
carefully aligned by hand to give a particular visual effect. SPAG allows
you to suppress reformatting by inserting a directive of the form
!-ASIS

in the source code. This directive governs only the immediately


following statement. Note that compilers treat the
directive as a comment.
C-ASIS and *-ASIS are
accepted as alternatives in fixed format source code.
For example
!-ASIS
DATA XOX /
,
,

&
&

1 , 0 , 1
0 , 1 , 0
1 , 0 , 1 /

!-ASIS can be used safely with any declaration


statement. However it is, in general, not safe to use !-ASIS with

executable statements or others, such as FORMAT, which


may be labelled. In such cases SPAG leaves the statement
label unchanged,
even if the code is re-labelled. In other cases the original code may no
longer be appropriate. For
example, SPAG may reverse the logic in a block
IF statement, or convert it to an ELSEIF. These changes will not be
apparent in the output code if !-ASIS is used on
executable statements. Despite these problems, we have, because of
user
demand, decided to retain the option of using
!-ASIS on executable statements. SPAG issues a warning for every

unsafe usage; it is up to the user to hand-check code when such a warning


is issued.
Item 60 of the configuration file allows you to
specify that all declaration statements should be treated as though
prefaced by !-ASIS This switch is suppressed if
item 4 specifies that declarations are to be
rewritten.

2.7.10 The ANCHOR Directive


Occasionally, it may be desirable to force SPAG to leave a particular
statement in position. This can be done by
inserting a !-ANCHOR directive immediately before the statement in question.
C-ANCHOR and *-ANCHOR
are accepted
as alternatives in fixed format source code. The anchored statement must be an executable
statement, and must have a
label. Note that even when a statement is
anchored, it is possible that surrounding code may be relocated in such a
way
that it appears to move.

2.7.11 Comments in Restructured Code


Comments are presumed to be attached to the statement that follows them,
and as the code is restructured, are moved
around in the same way as that
statement. End-of-line comments are an exception, and are attached to the
statement
with which they share a line. Another exception is comments
preceding statements which are removed from the
program (e.g. CONTINUE or
GOTO statements which are not needed in the unscrambled code). These are
attached to
the statement following the redundant statement. The net result
is that SPAG preserves comments and usually puts
them in the right
place.

2.7.12 Using Case to make Programs more


Readable

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Because of its antiquity, Fortran has always been an upper-case


language. Even today, many Fortran programmers stick
entirely to
upper-case, even though mixed case is permitted by every major compiler (and is standard Fortran 95).
This
is a shame, because an important opportunity to make programs
self-documenting is being missed. SPAG can be
configured to make full use
of case to distinguish different types of symbol. For example you can make
special symbols
(such as PARAMETERs and subprogram names) upper case;
symbols which refer to global data (such as COMMON
variables and dummy
arguments) could be capitalized (e.g. Arg); and local variables could be
lower case. A scheme
like this helps programmers to know what they are
looking at without constant reference to the declaration section.

2.7.13 Symbol Table Output


If item 2 of spag.fig is
set to 2, SPAG generates symbol table files which provide valuable
information about data usage
within subprograms. These files are used by
GXCHK, the global cross check program, to generate an overview of data
usage within an entire program. The process is analogous to the more
familiar procedure of compiling and linking. The
symbol tables are
analogous to object files, and GXCHK works like a linker to combine them
into a single global
report. Indeed, the AUTOMAKE tool, which automates
compiling and linking can also be used to rebuild the global
report
file.
Symbol tables are plain ASCII text files, the format of which is
described in detail in Appendix A. Users are encouraged
to develop
their own applications using these files as input. For example it would be
a simple matter to write a program
to check conformance to local variable
naming conventions.

2.7.14 VMS Text Libraries


VMS VAX Fortran permits source code to be INCLUDEd from VMS text
libraries, using an INCLUDE statement of
the form:
INCLUDE 'LIBNAME(MEMBER)'

Although SPAG cannot read text libraries, INCLUDE statements of this


form can be used. SPAG interprets the above
example as being equivalent
to
INCLUDE 'MEMBER.FOR'

Thus, if the VMS command


LIBRARY/EXTRACT=MEMBER
/OUTPUT=MEMBER.FOR LIBNAME.TLB

is used before SPAG is run, SPAG will behave correctly. Note that the
files containing the extracted library members
may be in a separate
directory, provided that the directory is specified in the INCLUDE file
search list (see item 215 of
the SPAG configuration
data). Note too that a leading '$' in
the member name is removed. Thus ($foriosdef)
is treated
as foriosdef.for.

2.7.15 Some Pitfalls


When SPAG converts an arithmetic IF or computed GOTO into an equivalent
block IF, it may produce code
which can execute a FUNCTION reference
more often than in the original code. Apart from efficiency
considerations, this is undesirable because the function may have side
effects which alter the results obtained.
SPAG issues a warning message
when this possibility arises. Note that functions which are identified
as safe (see
items 12 and 210 of the configuration file) will not
trigger a warning. A simple and safe fix is to place the result
of the
function reference in a local temporary variable, which is used in the
following arithmetic IF or computed
GOTO.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

IF ( A1*FUNC(X) ) 100,200,300

becomes
TEMP = A1*FUNC(X)
IF ( TEMP ) 100,200,300

SPAG leaves some Fortran flow control structures unmodified (apart


from re-labelling). These include ASSIGN
and assigned GOTO, END= and ERR=
in I/O statements, and alternate returns in CALL statements.
When SPAG re-formats long statements, it may increase the number of
continuation lines. In extreme cases, this
could result in a statement
having more than the 39 continuation lines allowed by the ANSI
standard (19 for
Fortran 77).
Some versions of the IBM mainframe VS Fortran compiler do not allow
block IF statements to be nested more
than 25 deep, and count each ELSEIF
statement as an extra level of nesting. SPAG sometimes produces code
which exceeds this limit, particularly when translating computed GOTO
statements into block IFs. Translation of
computed GOTOs can be
suppressed by changing item 20 in the configuration
file.

2.8 Dynamic Analysis


2.8.1 What is it?
Dynamic analysis is a simple procedure for validating the operation of a
program at run-time. It involves setting up a
test version of your program
containing extra checking code. This test program is compiled and linked in
the normal
way. The executable code appears to the user to operate in
exactly the same way as the original, though it is larger and
slower. If
the checking code detects an error, it writes details to a log-file, and
continues execution. The programmer
can then view the log-file at leisure
after the run completes.

2.8.2 Worked Example


The example below shows how dynamic analysis works:

100

SUBROUTINE QKNUM(Ival,Pos)
INTEGER Ival , Pos , vals(50) , ios
READ(11,*,IOSTAT=ios) vals
IF ( ios.EQ.0 ) THEN
DO Pos = 1 , 50
IF ( Ival.EQ.vals(Pos) ) RETURN
ENDDO
ENDIF
Pos = 0
END

QKNUM is a simple routine which reads a list of 50 integers from a data


file; the position of the first in the list with
value Ival is returned in
Pos. If none is equal to Ival, or if an error or end-of-line condition
occurs while reading the list,
Pos is returned as 0.
Most of the time, QKNUM will probably work well. Compilers and static
analyzers are unlikely to find anything wrong
with it, but nevertheless, it
does contain a logical flaw. If the data file contains:
2,9,,11,20*44,26*

Then items 1, 2 and 4 to 24 are assigned values. Items 3 and 25 to 50


remain unchanged from their initial (undefined)
value. The result of the
test on line 6
IF ( Ival.EQ.vals(Pos) ) RETURN

is therefore undefined, and the program will behave unpredictably.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

Whilst this particular bug is not common, it does illustrate, in a


compact example, two features which are common to
many bugs, and which
defeat static analysis:
Dependence on external data. The way a program executes depends on
what data it gets. A static analyzer cannot
know that.
Use of arrays. Static analyzers normally treat arrays as amorphous
blobs of data: if any part of an array is defined,
then the whole array
is assumed to be defined.
A version of QKNUM modified to perform a dynamic analysis might appear
as follows:
SUBROUTINE QKNUM(Ival,Pos)
INTEGER Ival , Pos , vals(50) , ios
! insert 'undefined' value in ios
CALL UNDFI(ios)
! insert 'undefined' value in every element of vals
CALL UNDFIA(vals,50)
READ(11,*,IOSTAT=ios) vals
! check that ios is defined
IF ( ios.EQ.UNDEF ) CALL ERROR
IF ( ios.EQ.0 ) THEN
DO Pos = 1 , 50
! check that Ival and vals(Pos) are defined
IF ( Ival.EQ.UNDEF ) CALL ERROR
IF ( vals(pos).EQ.UNDEF ) CALL ERROR
IF ( Ival.EQ.vals(Pos) ) RETURN
ENDDO
ENDIF
100 Pos = 0
END

The modified code contains a new section which initializes all local
variables to a special 'undefined' value. This section
is executed
immediately after QKNUM is entered. Note that dummy arguments and COMMON
variables are NOT
initialized - they are assumed to be initialized higher
up the call tree.
In addition a test is inserted wherever the value of a variable is used.
For example, the test
IF ( Ival.EQ.vals(Pos) ) RETURN

is meaningless if either Ival or vals(Pos) is undefined. The code


therefore contains tests for both items. The variable Pos
is also used,
and, at first sight it may appear necessary to check Pos before testing
vals(Pos). However, in this case we
can deduce that Pos must be defined because it is a DO loop variable.
A version of QKNUM modified in this way will log an error when the input
data leaves elements of vals undefined.

2.8.3 Dynamic Analysis using SPAG


When the dynamic analysis option of SPAG is activated (by setting item 1 of the configuration data to 4), it modifies the

program to perform a dynamic analysis. The details differ from the above
example, but the principles are identical. The
modifications are automatic
and require no user intervention. SPAG knows about variables initialized in
DATA or type
statements, and does not re-initialize them. It also
distinguishes static variables (specified using SAVE) from others.
Static
variables are initialized only once - when first entering the subprogram
that defines them. Other local variables
are re-initialized to the
undefined value every time a subprogram is entered. If item
36 of the configuration data is set to
1, all local variables are
assumed to be static. This is probably the safest starting point for
programs of unknown
history.
The SPAG Dynamic analysis tool works with Fortran 77 input code, and with
some Fortran 95 extensions. Most
programs which use Fortran 90 or 95 features cannot be instrumented.
In particular, SPAG does not (in this context)
deal correctly with derived types,
pointers, allocatable arrays, and array language.

2.8.4 COMMON Variables

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

One area which may require a little attention from the user is the
initialization of COMMON variables to the undefined
value.
SPAG inserts code to initialize COMMON variables at the start of the
main program immediately after the program
starts. It follows that all
COMMON variables must be available within the main program. This may
require some handedits to your program, perhaps to insert some INCLUDE
statements in the main program. SPAG does not do this
automatically, but
GXCHK (see Chapter 3) will tell you of any COMMON
blocks which are not specified in the main
program.

2.8.5 Initialized COMMON Variables


One final precaution is necessary: COMMON variables may be initialized
using DATA statements in a BLOCKDATA
subprogram. Many compilers also allow
COMMON variables to be initialized in other ways, for example, in type
statements within a subprogram. We must ensure that the initialization code
generated by SPAG does not overwrite
these genuine initializations in
BLOCKDATAs or elsewhere.
This is achieved by running GXCHK (see Chapter
3) after SPAG has finished. If COMMON variables are initialized
anywhere in the source code, GXCHK modifies the dynamic analysis version of
the main program to remove the
statements which would overwrite the
initialization. This process is automatic, and requires no user
intervention.

2.8.6 Summary
The steps required to perform a dynamic analysis of a Fortran program
using SPAG and GXCHK are as follows:
Make sure that every COMMON variable is specified in the main
program.
Run SPAG with the dynamic analysis option activated.
Run GXCHK on the symbol tables produced by this SPAG run. Check the
output for error messages.
Compile and link the SPAGged code and the source code for the probes
(taken from the plusFORT release
directory).
Run the program in the normal way, on as many test data sets as
possible. After each run, review the contents of
the log-file probes.log.

2.8.7 False Positives


It is possible, though extremely rare in practice, for the probes to
report an error when there is none. This happens if the
'undefined'
bit pattern occurs as the normal result of a calculation within the
program. For 32 and 64 bit data items, this
possibility is vanishingly
small. Even for 8 and 16 bit data, it happens so infrequently that, for
most users, the benefits
of the test will outweigh the inconvenience of
checking for false positives.
Item 35 of the SPAG configuration data specifies the
minimum size (in bytes) of numeric and logical data items to be
tested
using dynamic analysis.
Item 35 does not apply to CHARACTER strings, because
their length is not generally known until run-time. Instead,
there is a
test within the probe itself. Users may modify the source code of the probe
as required (see Appendix B).

2.8.8 Mixed Code


Code containing dynamic analysis probes can be mixed freely with normal
code. Similarly, the use of external object
files and libraries presents no
problems. The only restriction is that GXCHK must process the source code
of all
subprograms that initialize COMMON data.

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

2.8.9 EQUIVALENCE & Dynamic Analysis


Dynamic analysis is not put off by EQUIVALENCEd data, or by COMMON
blocks whose structure varies from one
subprogram to another (provided that
the version which appears in the main program includes the entire data
area).

2.8.10 Static or Dynamic?


SPAG and GXCHK offer facilities for both static and dynamic analysis,
and we are often asked which is best. The
answer is that the two are
complimentary. Each excels where the other is deficient.
A static analyzer checks all your code, whether it executes or not; it
produces useful results without the need to perform
test runs; it produces
documentation which is of general use to managers and staff working on the
program. On the
other hand, a static analyzer cannot hope to predict the
effect of external data on your program's execution, or to
monitor the
status of every byte of memory.
Dynamic analysis, on the other hand, operates when your program is
running with real data, and can monitor memory at
the byte level. The main
disadvantage of dynamic analysis is that, unlike static analysis, it does
not check all your code,
only the parts that execute in a given run.
This disadvantage can be removed by using coverage analysis (see Section 2.9 and Chapter 4) to
ensure that your test
program exercises all of your source code.
Working together, static, dynamic, and coverage analysis provide an
unrivalled health check for your programs.

2.9 Coverage Analysis


SPAG contains facilities for inserting probes into Fortran source code
for the purpose of analyzing the run-time
performance. These probes may be
used to detect execution hot-spots, identify untested code-blocks, or
provide a
profile of CPU usage.
If item 6 of the configuration data is set to 2, SPAG
prepares your code for coverage analysis testing by:
Writing a special test version of your program which contains probes
to monitor control flow. The test version
should be compiled in the
normal way, and linked with the plusFORT probe routines
(see Appendix B). The
program will execute
normally, albeit somewhat more slowly.
Writing files containing a coverage information block for each
subprogram. The coverage information block
specifies the start line
number of every linear code block, and how many times it has been
executed. At the end
of every coverage analysis run, these files are
updated to show the cumulative usage of every code block. A
separate
program called CVRANAL (see Chapter 4) may be
used to annotate the source code (so that usage
counts appear as comments
in columns 73-80), and produce a concise summary of hot-spots and
untested code.
In addition to setting item 6, you should also use
item 234 to specify the name of the directory where
SPAG will
store the coverage analysis data files. It is recommended that
you create a directory especially for this purpose
before running SPAG.
The directory should be specified using an absolute path (not a relative
one). This ensures
that the test program can always find the data
files.
A weaker form of program tracing is invoked by setting item
6 of the SPAG configuration data to 1. With this setting,
tracing takes
place only at the subprogram level, and no coverage analysis data files are
produced. In conjunction with
the plusFORT probe routines
this is sufficient to produce a profile of CPU usage by subprogram (see
Appendix B).
Either form of coverage analysis depends on data written when the test
program finishes. If the program is interrupted,
or if execution is halted
by a routine which does not contain probes, the required data is not
written, and coverage
analysis fails for this run (though no damage is done
to the data files). This can happen if you call a system routine (e.g.
CALL
EXIT) to halt execution. The problem may be avoided by inserting a call to
the program termination probe,
http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

PR$EXI, just before the call to EXIT.


CALL PR$EXI
CALL EXIT(16)

If dynamic analysis (section 2.8) is activated, item 6 is automatically set to 1.

2.10 Dynamic Memory Monitoring


If SPAG Configuration item 1 is set to 5, SPAG prepares
source code for a special sort of dynamic analysis, originally
geared towards finding
the date associated problems which were expected to occur on or around the
year 2000. The
instrumented program executes normally, but as it runs,
every variable or array element, used in any way, is checked
for data which
could be date related. A report is written to the file probes.log. The same technique can be used for other
similar
tasks - for example, to find the parts of a program that deal with with currency transactions
Most tools for detecting Year 2000 problems rely largely on finding date
references in the source code, for example in
the form of variable or
subprogram names such as IDATE or LEAP. This approach, which is implemented
in GXCHK,
may fail if the programmer has not chosen names which reflect the
variable's usage. SPAG's analysis is different, and
can detect date
variables, even if their name is unrelated to their function. For example,
if the programmer has used a
variable called K2 to store a 2 digit year,
SPAG will spot it, because it looks at the contents of the variable at
run-time,
rather than at the source code.
All that's required to perform a Year 2000 check is to instrument
the source code using SPAG (with item 1 of the
configuration data set to 5), and then compile and run the program as
normal. An additional source file called
probes.y2k must be compiled and linked with the instrumented
code.
This form of dynamic analysis is much simpler than the standard type,
because variables do not have to be initialized,
and there is no need to
run GXCHK before starting the analysis.
When the run is complete the file probes.log contains a summary of the variables which could be date
related, together
with their values, and the line in the source code where
they are set. The probe routines contain logic to ensure that
multiple
reports of the same type are condensed to a single report.
Inevitably, many of the reports will be false positives; a variable may
contain the value 1998, and yet not be a date
variable. In practice,
you'll probably need to do several runs, tuning the criteria to isolate
problem code. There are two
ways to eliminate these false positives:
Modify the code in probes.y2k which
checks for date related values. The relevant code is in subroutines QD$CH,
QD$I2 and QD$I4 at the start of the file. The logic of these
routines is very simple.
Modify the instrumented code by removing calls to QD$CH, QD$I2 and QD$I4 which have proved to be the
source of false positives. The
reports in probes.log should enable you to
find the required line.

2.11 Processing Fortran 95 Modules


The USE statement in Fortran 95 allows a subprogram to import data and interfaces from a separately compiled module.
It is in many ways analagous to an INCLUDE statement, and is generally recommended as a
superior replacement for
both INCLUDE and COMMON. In order to interpret
USE correctly, SPAG must import information about the external
module. It does this by reading the symbol table generated when SPAG processed the module. This gives rise to 2
problems:SPAG needs to know the location of the symbol file.
To do this, SPAG maintains a ASCII text file called PFMODULE.KEY. This file contains records which specify
the location of each module USEd by source code in the current directory. For example

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

SPAG

TRAJECTORY : traject.smb

specifies that the symbol table for module TRAJECTORY is in the file traject.smb.
As SPAG processes source code, it automatically inserts records in
PFMODULE.KEY for every module it
encounters. When SPAG encounters a USE
statement, it consults this file to find the module data.
An exception to this rule is that SPAG will not automatically find modules from a different directory. In this case
it is recommended that
the locations of modules be inserted in PFMODULE.KEY using a text editor.
GPS_COORDS : gps\coordmod.smb

The module must already have been processed by SPAG.


When SPAG looks in PFMODULE.KEY to find the location of the symbol data for a particular module, it may

find that there is no entry, because the module has not been processed yet. In this case SPAG reports an error.
This is similar to the problem, familiar to most Fortran 90/95 programmers, that occurs when modules are not
compiled before code that USEs them.
It is possible to overcome this problem by repeatedly re-running SPAG until the modules are all processed.
However this can
take some time, particularly if USEs are nested to any depth. In addition
if a module is
changed, SPAG may use an obselete symbol table, and produce
incorrect results while appearing to work
correctly.
The plusFORT AUTOMAKE tool provides a solution to this problem (just as it does for compilers). The
plusFORT installation directory contains a batch/shell file called Autospag, which uses AUTOMAKE to run
SPAG in such a way that the processing order requirements are satisfied. A small configuration file called
autospag.fig should be placed in the source directory. A typical case, in which all .F90 files are to be processed,
and the symbol table files have the .smb extension would be handled by the following configuration file:
COMPILE=@spag %fi
OBJEXT=SMB
FILES=*.f90
NOQUITONERROR

Then to run SPAG on all .F90 files in the current directory, simply type Autospag. More complicated cases can be
handled
with suitable changes to autospag.fig (see the AUTOMAKE documentation)

http://www.fortran.uk/plusfortmanual/spag.html[1/18/2016 7:39:33 PM]

You might also like