Professional Documents
Culture Documents
SPAG
SPAG
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.
(DOS/Windows, VMS)
(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.
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=
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
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.
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
3=3
Clutter Checks
SPAG
tof90.fig
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.
Item 2
Symbol Tables
Specifies whether the symbol tables generated by SPAG are to be
written to files - possible values are:
0
SPAG
Item 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
SPAG
Declaration Standardization
Specifies whether and how SPAG should reorganize the declarations
in a subprogram. Possible values are:
0
No change to declarations.
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.
SPAG
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
SPAG
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
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
SPAG
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)
! 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.
SPAG
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
! After conversion
DO WHILE ( i.GE.0 )
READ * , I
CALL sub(i)
ENDDO
! After conversion
DO WHILE ( i.GE.0 )
READ * , i
CALL sub(i)
IF ( .NOT.q ) THEN
CALL sub(i+1)
EXIT
ENDIF
SPAG
ENDDO
Item 25
! After conversion
DO
READ(9,END=100) z
PRINT * , z
ENDDO
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
! 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
! Item 27 = 1
DO 10 i = 1 , 100
IF ( q1 ) THEN
CALL sub1
GOTO 20
ENDIF
10
ENDDO
20
CALL sub2
! 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
Item 30
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
SPAG
print * , today.ddmmyy(1)
Item 35
PRINT * , today%ddmmyy(1)
Item 36
Item 40
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
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
Item 43
! Item 42 = 2
IF ( Q1 ) X = Y
should be converted to
IF ( a.NE.b ) THEN
X = Y
..
ENDIF
SPAG
Item 44
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
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
Use the standard Fortran 77 relational operators .LT., .LE., .EQ., .NE., .GE., and .GT.).
Any
SPAG
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
Item 49
Item 51
Item 52
SPAG
Item 54
may be interpreted as
PARAMETERVDIM = 10
SPAG
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
Item 61
Tab Characters
Specifies whether SPAG should use tab characters in the output
file. If this option is activated, SPAG
SPAG
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
Item 65
Item 66
SPAG
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
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)
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 =.
SPAG
Item 69
-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
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
SPAG
Item 73
Item 79
SPAG
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
Item 89
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,
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
SPAG
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
SPAG
SPAG
SPAG
SPAG
SPAG
10
I0 = 0
DO 10 i = 1.100
READ *,j
IO = I0 + j
CONTINUE
SPAG
XX(N),I,J,K
SPAG
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
&
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.
SPAG
where the type and value of n are defined in dims.inc (which must itself be self-contained).
SPAG
mod
min
'test1.prv'
fchsta
zsyst
/pkchAR/
firstc
zzzsys
/pkcomm/
SPAG
swstx2
ityp
jtyp
lopbr
lclbr
jtyp
ityp
lclbr
lopbr
swfrag
oxo
xox
&
&
1 , 0 , 1
0 , 1 , 0
1 , 0 , 1 /
SPAG
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.
SPAG
IF ( A1*FUNC(X) ) 100,200,300
becomes
TEMP = A1*FUNC(X)
IF ( TEMP ) 100,200,300
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
SPAG
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
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.
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.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.
SPAG
SPAG
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
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)