Recon Instrumentor for Fortran - SRS

@(#)r3fisrs.htm 1.1 - 03/12/01

Table of Contents:

1.0 Introduction

1.1 Purpose

1.2 Scope

1.3 Definitions, Acronyms and Abbreviations

1.4 References

1.5 Overview

2.0 General Description

2.1 Product Perspective

2.2 Product Functions

2.3 User Characteristics

2.4 General Constraints

2.5 Assumptions and Dependencies

3.0 Specific Requirement

3.1 Functional Requirements

3.1.0 General Instrumentation Requirements

3.1.1 Instrument Subprogram Entry Points

3.1.2 Instrument Subprogram Return Points

3.1.3 Instrument Decisions

3.1.4 Instrument Basic Blocks

3.1.5 Processing of INCLUDE Directives

3.1.6 Processing of Unrecognized Statements

3.2 External Interface Requirements

3.2.1 Command Line

3.2.2 Source Format

3.2.3 Error Handling Policy

3.3 Performance Requirements

3.4 Design Constraints

3.5 Attributes

3.6 Other Requirements

Appendixes

1.0 Introduction

1.1 Purpose

This SRS states the requirements for the Recon Instrumentor for Fortran. It is intended as a guide for developers, testers, and maintainers of this software component.

The Recon Instrumentor for Fortran will first be developed in an initial version, and then progressively enhanced. Requirements in this SRS are annotated with v1.0 if they are expected to be provided in the initial version or vX.X if they are tentative requirements for inclusion in later versions. (Assume v1.0 for requirements that are not annotated.) These tentative requirements are described here since developers may wish to design their code to facilitate the probable enhancements.

1.2 Scope

The Recon Instrumentor for Fortran, r3finst, is part of the Recon3 tool set for dynamic analysis of software [AR3] which is, in turn, a major upgrade and extension of the Recon2 software reconnaissance tool [Recon2].

Each time it is called, r3finst reads one of the Fortran 77 source files making up the user's target program, and writes an instrumented copy of that source file. This instrumented target program file contains instrumentation statements so that, when compiled and executed, the instrumented target program will produce traces of execution.

The main benefit of r3finst is to facilitate the understanding or debugging of Fortran programs using techniques such as software reconnaissance [SR95].

Major differences between the initial version of r3finst and later versions are as follows:

  1. The initial version of r3finst will focus on target source files that follow the Fortran 77 standard. Statement types or formats that occur only in certain Fortran 77 implementations, in Fortran 90 or in Fortran 95, will be handled at developer discretion if they can be easily included (v1.0). Later versions of r3finst may extend to Fortran 90 or Fortran 95 (vX.X).
  2. In the initial version of r3finst, the instrumentation statements will call subprograms in the file r3fisubs.c. An initial version of r3fisubs.c is described in Appendix A. These subprograms will write the trace of execution directly to a file named unknown.r2t. (This is the default behavior of Recon2). This file will have the trace file format expected by the r2analyz component of Recon2. (See [Recon2, file userman.htm] for a description of this format.) Later versions will call the more sophisticated C trace interface being developed for Recon3 [AR3] or possibly will use a native Fortran interface providing similar capabilities (vX.X).
[Note: Fortran 77 is generally a subset of Fortran 90 and Fortran 95, though with some exceptions. In anticipation of future enhancement of r3finst, this SRS has been written working from the Fortran 90 and 95 standards. However it excludes Fortran 90/95 constructs which are not in Fortran 77 and which would complicate the v.10 implementation. Main references have been [For95] and [For90], to which the reader is referred for more precise language explanations.]

1.3 Definitions, Acronyms and Abbreviations

Basic Block, Decision, Subprogram Entry and Return

See [AR3 section 2.2.1] for definitions of these different kinds of trace event.

Instrumentation Statements, Instrumented Target Program, Target Program, Trace Event, Trace of Execution, Trace Record

See [AR3 section 1.3]

Developer

The individual or organization that is implementing r3finst.

Program Unit

a Fortran program unit is either: a main program, an external subprogram, or a block data unit. See [For95, Section 1].

Subprogram

A Fortran SUBROUTINE or FUNCTION.

 

1.4 References

[AR3]

"Architecture of Recon3" Norman Wilde, Laura White, Aaron Tarnosky (Version is TBD. This document should be finalized before Aug. 31/99)

[For90]

"Fortran 90: A Reference Guide", Luc Chamberland, Prentice Hall, 1995.

[For95]

"Fortran 95 Language Guide", Wilhelm Gehrke, Springer, 1996.

[Recon2]

Code and documents for the Recon2 system available at http://www.cs.uwf.edu/~wilde/recon.

[SR95]

"Software Reconnaissance: Mapping Program Features to Code", N. Wilde and M. Scully, Journal of Software Maintenance, Vol. 7, pp. 49-62, (1995).

1.5 Overview

This SRS follows roughly the ANSI/830 standard. Section 2 gives an overview of r3finst and its functional and other requirements. Section 3 gives the requirements more specifically. Appendix A describes briefly the Fortran subroutines that will be called by the instrumentation statements and Appendix B gives examples of instrumentation.

Terms defined in section 1.3 will appear in emphasis, like this.

Program names, file names, and Fortran language constructs will appear in CODE format like this.

[Brief explanations of the rationale for certain requirements are given in block quotes like this one.]

 

2.0 General Description

2.1 Product Perspective

As previously mentioned in section 1.2, r3finst is the component of the Recon3 tool set that creates instrumented copies of Fortran source files by inserting instrumentation statements.

Figure 1 - Product Perspective for V1.0

Figure 1 shows how r3finst will work with other components in the initial version (v1.0). The user invokes r3finst using a command line interface. Each time it is invoked, r3finst instruments one Fortran source file. When the user has instrumented all the Fortran files making up his target program, he uses his Fortran compiler to produce the instrumented target executable. He runs the instrumented target executable using appropriate test data. The instrumentation statements create a file named unknown.r2t containing a trace of execution. The user normally renames this file to something meaningful. Several traces of execution are then fed to the r2analyz trace analysis program.

See [AR3, section 2.1] for a block diagram showing how the different components of Recon3 will be related in later versions (vX.X).

2.2 Product Functions

2.2.1 Instrument Subprogram Entry Points

r3finst will introduce instrumentation for the following trace events:

  1. Target program begins execution of the main program
  2. Target program begins execution of a subprogram at its first executable statement
  3. Target program begins execution of a subprogram at some other defined ENTRY statement.
[Note: Arithmetic statement functions are not instrumented. Since they consist of a single statement there is no way to add instrumentation.]

2.2.2 Instrument Subprogram Return Points

r3finst will introduce instrumentation for the following trace events:

  1. Target program performs a STOP
  2. Target program arrives at a RETURN statement in a subprogram
  3. Target program arrives at an END, END PROGRAM, END FUNCTION or END SUBROUTINE statement in a subprogram or main program.
[Note: The instrumentation does not distinguish different alternate returns from a subprogram. It is not clear how this kind of interprocedural control flow can most usefully be traced.]

2.2.3 Instrument Decisions

In general, decisions are instrumented by writing the value of the logical expression of an IF or of the integer expression of a computed GOTO. r3finst will introduce instrumentation for the following trace events:

  1. Target program executes a computed GOTO statement.
  2. Target program takes the TRUE or FALSE branch in a logical IF statement.
  3. Target program takes the TRUE or FALSE branch in an IF-THEN construct or in the ELSE IF part of such a construct.
[Note: The loop decision taken on every iteration of a DO or DO WHILE is not instrumented. Experience using Recon2 for software reconnaissance has yet to find a functionality that was distinguishable by such a decision; both branches of the loop decision are almost always executed in every test case. Thus loop decision instrumentation adds greatly to the size of the trace of execution while providing little help for software reconnaissance. However, if experience shows that Recon3 traces are used for other purposes than software reconnaissance this decision may need to be revisited.]
[Assigned GOTO statements and arithmetic IF statements are not instrumented in decision instrumentation in v1.0. If the user needs to trace them, he may request basic block instrumentation, which is much more easily implemented.]

2.2.4 Instrument Basic Blocks

In general, instrumentation of basic blocks is done at every statement that can be the target of a transfer of control. r3finst will introduce instrumentation for the following trace events:

  1. The target program executes any labeled executable statement that is not the termination of a DO. The instrumentation statement is inserted before the labeled statement and the label is moved to it.
  2. The target program executes any labeled executable statement that is the termination of a DO. The instrumentation statement is inserted before the labeled statement and the label is moved to it. The DO is modified to use a new label which is also placed on the original statement.
  3. The target program "drops through" a computed GOTO and executes the following executable statement.
  4. The target program executes the statement contained in a logical IF or the executable statement following a logical IF.
  5. The target program executes the first executable statement in the THEN part, in an ELSE IF ... THEN part, or in the ELSE part of an IF construct
[Note: For the reasons given in the previous section, the beginnings of DO and DO WHILE loops are not instrumented, unless they are also labeled.]
[Note: FORMAT and other non-executable statements, although labeled, cannot be the target of a transfer of control and so are not instrumented.]

2.2.5 Processing of INCLUDE Directives

INCLUDE directives vary in form and processing from compiler to compiler. r3finst will attempt to process only directives having the following, more or less standard, form:

INCLUDE 'file-path'

r3finst will copy the contents of the specified file to the instrumented target program, replacing the INCLUDE directive.

[Note: If the file path in the INCLUDE statement is relative (i.e. does not start with "/" in Unix or with the equivalent in other operating systems) r3finst will look for the file in the directory that was the current working directory when r3finst was started. Some compilers look instead in the directory containing the file that has the INCLUDE statement. Users of r3finst may need to "cd" to that directory before running, or else they may need to modify the INCLUDE directives.]

2.2.6 Processing of Unrecognized Statements

Fortran implementations differ considerably; most compilers provide extensions that go beyond the language standards. A priority for r3finst is that it should be usable for as many Fortran programs as possible. Whenever possible it should produce an instrumented target program that will compile and run in the same environment as the original target program.

Thus if r3finst encounters statements that it does not recognize, it will copy them to the instrumented target program with as few changes as possible. It may produce a warning message at developer discretion.

2.3 User Characteristics

The user is expected to be an experienced programmer. He will be familiar particularly with how to compile and run the target program.

2.4 General Constraints

To facilitate portability and maintenance by the University of West Florida project team, r3finst will be implemented using standard only ANSI C to the greatest extent possible.

Code that depends on operating system, path lengths, file name formats, etc. should be avoided for portability. However is the developer really needs such things, r3finst should include the r2.h header file of Recon2 and make use of the preprocessor directives it contains.

The instrumentation statements introduced by r3finst shall consist of calls to the FORTRAN external subprograms in the file r3fisubs.f described in Appendix A to this document.

2.5 Assumptions and Dependencies

None.

3.0 Specific Requirement

3.1 Functional Requirements

3.1.0 General Instrumentation Requirements

At the beginning of every Fortran program unit, r3finst will define a variable named R3PATH to identify the target source file being instrumented. It will also declare the instrumentation functions R3SWIT and R3LOGI which may be used in decision instrumentation. The following instrumentation statements will be inserted before any executable statement, at a location in the program unit where type declaration statements are valid:

      CHARACTER *<pathlen> R3PATH
      DATA R3PATH /'<path>'/
      INTEGER R3SWIT
      LOGICAL R3LOGI

where <path> is the source path string specified on the command line (see 3.2.1) and <pathlen> is the length of the path string.

[See [For95, section 1.5] for the permitted ordering of Fortran statements. This ordering determines exactly where the instrumentation may be inserted. Section 1.4 of [For95] gives a list of the executable statements of Fortran.]

Before instrumenting, r3finst will convert all logical IF statements to IF-THEN constructs as in the following example:

      IF ( ... ) stmt1
      stmt2
becomes:
      IF ( ... ) THEN
        stmt1
      ENDIF
      stmt2
Fortran's logical IF statements can only occupy one line, so it is difficult to introduce instrumentation. It is simpler to just convert them all.]

3.1.1 Instrument Subprogram Entry Points

If the user has selected instrumentation of subprogram entry points on the command line (see 3.2.1), r3finst will introduce instrumentation for the following trace events:

3.1.1.1 Target program begins execution of the main program

An instrumentation statement is inserted in the first basic block of the main program, of the form:

      CALL R3ENTR( R3PATH, <lineno>, 'MAIN')

where <lineno> is the line number of the first executable statement in the main program. If a PROGRAM statement has been encountered giving the name of the target program, then that name will be used in the call to R3ENTR. If no such statement has been encountered, the name 'MAIN' will be used as shown above.

3.1.1.2 Target program begins execution of a subprogram at its first executable statement

An instrumentation statement is inserted in the first basic block of the subprogram, of the form:

      CALL R3ENTR( R3PATH, <lineno>, '<name>')

where <lineno> is the line number of the first executable statement in the subprogram and <name> is the name of the subprogram.

3.1.1.3 Target program begins execution of a subprogram at some other defined ENTRY statement.

An instrumentation statement is inserted just after the ENTRY statement, of the form:

      CALL R3ENTR( R3PATH, <lineno>, '<name>')

where <lineno> is the line number of the ENTRY statement and <name> is the name of the subprogram (not the name of the entry).

ENTRY statements at the very beginning of a subroutine are instrumented according to (3.1.1.2). This rule applies only to ENTRY statements appearing after the first executable statement of the subroutine.

[Note: Normally subprogram entry and return events are paired; for every entry there is a corresponding return. However if non-structured ENTRY statements are present, there may appear to be more entry events than returns. For example, the following subroutine may, when instrumented and executed, generate two entry trace events and only one return:
      SUBROUTINE SUB1
      PRINT *, 'A'
      ENTRY ENT1
      PRINT *, 'B'
      RETURN
      END
If SUB1 is called, control "falls through" the entry point ENT1 so that both SUB1 and ENT1 will appear to be executed before the RETURN is executed.
Paired entry and return events provide a more meaningful trace that allows the user to see the call hierarchy of the target program. In v1.0, however, r3finst will allow the unpaired events. Possibly vX.X may address this problem.]
3.1.1.4 Example

See Appendix B.1 for an example.

3.1.2 Instrument Subprogram Return Points

If the user has selected instrumentation of subprogram return points on the command line (see 3.2.1), r3finst will introduce instrumentation for the following trace events:

3.1.2.1 Target program performs a STOP

An instrumentation statement is inserted immediately before the STOP statement, of the form:

      CALL R3RETN( R3PATH, <lineno>, 'MAIN')

where <lineno> is the line number of the STOP statement.

Note that if the STOP statement was on a one-line logical IF statement, of the following form:

      IF (expr) STOP

the IF is first converted into an IF-THEN construct as described in (3.1.0), and so is instrumented as follows:

      IF (expr) THEN
        CALL R3RETN( R3PATH, <lineno>, 'MAIN')
        STOP
      END IF
3.1.2.2 Target program arrives at a RETURN statement in a subprogram

An instrumentation statement is inserted just before the RETURN statement, of the form:

      CALL R3RETN( R3PATH, <lineno>, '<name>')

where <lineno> is the line number of the RETURN statement and <name> is the name of the subprogram.

If the RETURN statement is on a one-line logical IF statement, the IF is first converted into an IF-THEN construct, as described in (3.1.0).

3.1.2.3 Target program arrives at an END, END PROGRAM, END FUNCTION or END SUBROUTINE statement in a subprogram or main program.

An instrumentation statement is inserted just before the END, END PROGRAM, END FUNCTION or END SUBROUTINE statement, of the form:

      CALL R3RETN( R3PATH, <lineno>, '<name>')

where <lineno> is the line number of the statement and <name> is the name of the subprogram, or 'MAIN' if this is the end of the main program.

3.1.2.4 Example

See Appendix B.2 for an example.

3.1.3 Instrument Decisions

If the user has selected instrumentation of decisions on the command line (see 3.2.1), r3finst will introduce instrumentation for the following trace events:

3.1.3.1 Target program executes a computed GOTO statement.

A switch instrumentation function "wrapper" is inserted around the integer expression in the GOTO statement, of the form:

      GO TO (lab1, ...) R3SWIT(R3PATH, <lineno>, integer_exp)

where <lineno> is the line number of the GOTO statement.

3.1.3.2 Target program takes the TRUE or FALSE branch in a logical IF statement.

The logical IF is first converted into an IF-THEN construct as described in (3.1.0), and then is instrumented as described in the following section.

3.1.3.3 Target program takes the TRUE or FALSE branch in an IF-THEN construct or in the ELSE IF part of such a construct.

A logical instrumentation function "wrapper" is inserted around the logical expression in the IF and ELSE IF statement, of the form:

      IF (R3LOGI(R3PATH, <lineno>, logical_exp)) THEN
      ...
      ELSE IF (R3LOGI(R3PATH, <lineno>, logical_exp)) THEN
      ...

where <lineno> is the line number of the IF or ELSE IF statement.

3.1.3.4 Example

See Appendix B.3 for an example.

3.1.4 Instrument Basic Blocks

If the user has selected instrumentation of basic blocks on the command line (see 3.2.1), r3finst will introduce instrumentation for the following trace events:

3.1.4.1 The target program executes any labeled executable statement that is not the termination of a DO.

Instrumentation is inserted before the labeled executable statement and the label is moved to the instrumentation. Thus a statement of the form:

  nnn stmt

is instrumented as:

  nnn CALL R3BLOC(R3PATH, <lineno>)
      stmt

where <lineno> is the line number of the labeled statement in the original source file.

3.1.4.2 The target program executes any labeled executable statement that is the termination of a DO.

The instrumentation statement is inserted before the labeled executable statement and the label is moved to it. The DO is modified to use a new label which is also placed on the original DO statement. Thus the following code fragment:

      DO nnn ...
      ...
  nnn stmt

is instrumented as:

      DO mmm ...
      ...
  nnn CALL R3BLOC(R3PATH, <lineno>)
  mmm stmt

where <lineno> is the line number of the labeled statement in the original source file and mmm is a newly generated statement label that does not occur elsewhere in the program unit.

3.1.4.3 The target program "drops through" a computed GOTO and executes the following executable statement.

The instrumentation is inserted between the GOTO and the executable statement. Thus a code fragment of the form:

      GOTO ( ....) expr
      stmt

is instrumented as:

      GOTO ( ....) expr
      CALL R3BLOC(R3PATH, <lineno>)
      stmt

where <lineno> is the line number of the statement in the original source file.

Non-executable statements following the GOTO, such as FORMAT's, are skipped and this rule is applied to the first executable statement.

If the executable statement following the GOTO has a label, then paragraph 3.1.4.1 or 3.1.4.2 applies instead of this one.

3.1.4.4 The target program executes the statement contained in a logical IF or the statement following a logical IF.

A logical IF is converted to an IF-THEN construct as specified in (3.1.0) and is then instrumented as described in the following section.

3.1.4.5 The target program executes the first statement in the THEN part, in an ELSE IF ... THEN part, or in the ELSE part of an IF construct.

Instrumentation is inserted before the first executable statement of each part of the IF construct. A code fragment of the form:

      IF ( ... ) THEN
        stmt1
      ELSE IF ( ... ) THEN
        stmt2
      ELSE
        stmt3
      END IF

is instrumented as:

      IF ( ... ) THEN
        CALL R3BLOC(R3PATH, <lineno1>)
        stmt1
      ELSE IF ( ... ) THEN
        CALL R3BLOC(R3PATH, <lineno2>)
        stmt2
      ELSE
        CALL R3BLOC(R3PATH, <lineno3>)
        stmt3
      END IF

where <lineno1> , <lineno2> and <lineno3> are the line numbers of the stmt1, stmt2 and stmt3 respectively. The statements stmt1, stmt2 and stmt3 represent the first executable statement in the block. If any of these statements has a label, then paragraph 3.1.4.1 or 3.1.4.2 applies and the corresponding call to R3BLOC is not inserted.

3.1.4.6 Example

See Appendix B.4 for an example.

3.1.5 Processing of INCLUDE Directives

r3finst will attempt to process only INCLUDE directives having the following form:

INCLUDE 'file-path'

r3finst will copy the contents of the specified file to the instrumented target program, replacing the INCLUDE directive and will then instrument the resulting code.

3.1.6 Processing of Unrecognized Statements

When r3finst encounters statements that do not match the instrumentation requirements specified in the previous sections, it will copy them to the instrumented target program with as few changes as possible.

3.2 External Interface Requirements

3.2.1 Command Line

To instrument a single source file, the user invokes r3finst using a command line of the following form:

r3finst source dest [-bder] [-v[level]]

where source is the path of the Fortran source file to be instrumented, and dest is the path for the instrumented copy of the source file. The instrumentation flags 'b', 'd', 'e' and 'r' may be present in any combination to indicate the kinds of trace events to be instrumented:

b - denotes basic block instrumentation

d - denotes decision instrumentation

e - denotes subprogram entry instrumentation

r - denotes subprogram return instrumentation

If no instrumentation flags are specified, the assumed default is '-ber'.

The -v flag specifies the "verbosity level" for warning and progress messages. The different possibilities may be determined by the developer.

If the command line does not have the form given above, a "usage" message is printed and r3finst exits.

[Note: For consistency, the external interface of r3finst is as similar as possible to that of r2inst, the current C instrumentor.]

3.2.2 Source Format

The target program source file is expected to consist of one or more Fortran program units.

r3finst will only process target programs that are in fixed source form as defined in section 1.1 of [For95]. Exceptions to the guidelines stated there are as follows:

  1. Multiple statements on a line may not be instrumented correctly.
  2. Input lines may exceed 72 characters, but the additional characters are discarded.
  3. Tab in first column is interpreted as six blanks for Microsoft Visual Fortran compatibility.

3.2.3 Error Handling Policy

The exact list of error conditions and messages may be determined by the developer, in accordance with the following general policy:

  1. If r3finst encounters an error that will probably impede it from producing a valid Fortran program, equivalent to the input program, it will write a meaningful error message to standard output and exit.
  2. If r3finst encounters an input that is dubious, but that may not impede it from producing a working program as described above, it may write a warning message to standard output, depending on the verbosity level set on the command line (see 3.2.1).

3.3 Performance Requirements

r3finst has no critical performance requirements. However as a general guideline, the developers should keep in mind that it is intended for use on large Fortran programs of, at least, tens of thousands of lines. The time required to instrument a file should normally be not significantly greater than the compile time for the same file in the same environment.

3.4 Design Constraints

See section (2.4).

3.5 Attributes

None.

3.6 Other Requirements

None

Appendixes

Appendix A - Fortran Subprograms Used in Instrumentation Statements

The instrumentation subroutines currently provided for v1.0 have the following restrictions:

  1. The trace file name is set as unknown.r2t and it is written to the current working directory. The user may change this by modifying subroutine R3OPEN.
  2. The trace file format is that expected by the current version (99/06) of r2analyz. Since that version only handles subroutine entry, decision (T and F) and switch value trace records, subroutine return and basic block trace events produce "T" decision trace records.
  3. The unit number used in writing to the trace file is set arbitrarily in file r3ficomm.f to 48. The user may need to change this number to make it acceptable to his Fortran environment and to avoid conflicts with the unit numbers used in the target program
  4. It is assumed that the operating system will automatically close the trace file when the instrumented target program exits. (Most modern operating systems do this, but old systems may not.)
  5. These instrumentation subroutines will not work in a multi-process or multi-thread target system.
  6. If the target system includes code instrumented by other instrumentors (e.g. a mixed C and Fortran system), then the C code needs to use a different trace file name and the trace files must be merged manually before analysis.

The subprograms to be used in v1.0 are in file r3fisubs.f, which includes the statements in r3ficomm.f.

Appendix B - Instrumentation Examples

B.1 Instrumentation of Subprogram Entry Points

Uninstrumented file:

C ex01U.f - Example for
C  "Instrument Subprogram Entry Points"
C
C Main program
      REAL Y
      DATA Y /10.0/
      CALL ENT(Y)
      CALL ENT1(Y)
      END
C
C Subroutine with two entry points, ENT and ENT1
      SUBROUTINE ENT(X)
      REAL X, PI
      DATA PI /3.14/
      PRINT 1001, PI*X
      RETURN
      ENTRY ENT1(X)
      PRINT 1001, 2*PI*X
      RETURN
 1001 FORMAT(' Result: ', F8.2)
      END

Instrumented file:

C ex01U.f - Example for
C  "Instrument Subprogram Entry Points"
C
C Main program
      REAL Y 
      DATA Y / 10.0 / 
      CHARACTER * 7 R3PATH 
      DATA R3PATH / 'ex01u.f' / 
      INTEGER R3SWIT 
      LOGICAL R3LOGI 
      CALL R3ENTR ( R3PATH , 7 , 'MAIN' ) 
      CALL ENT ( Y ) 
      CALL ENT1 ( Y ) 
      END 
C
C Subroutine with two entry points, ENT and ENT1
      SUBROUTINE ENT ( X ) 
      REAL X , PI 
      DATA PI / 3.14 / 
      CHARACTER * 7 R3PATH 
      DATA R3PATH / 'ex01u.f' / 
      INTEGER R3SWIT 
      LOGICAL R3LOGI 
      CALL R3ENTR ( R3PATH , 15 , 'ENT' ) 
      PRINT 1001 , PI * X 
      RETURN 
      ENTRY ENT1 ( X ) 
      CALL R3ENTR ( R3PATH , 18 , 'ENT' ) 
      PRINT 1001 , 2 * PI * X 
      RETURN 
01001 FORMAT ( ' Result: ' , F8 .2 ) 
      END 

B.2 Instrumentation of Subprogram Return Points

Uninstrumented file:

C ex02U.f - Example for
C  "Instrument Subprogram Return Points"
C
C Main program
      REAL Y
      DATA Y /10.0/
C An arithmetic statement function,
C  which is NOT instrumented.
      SQ(Z) = Z*Z
      CALL SUB(-2.0)
      CALL SUB(SQ(Y))
      END
C
C Subroutine
      SUBROUTINE SUB(X)
      REAL X, PI
      DATA PI /3.14/
      IF ( X .LT. 0 ) RETURN
      PRINT 1001, PI*X
      STOP
 1001 FORMAT(' Result: ', F8.2)
      END SUBROUTINE SUB

Instrumented file:

C ex02U.f - Example for
C  "Instrument Subprogram Return Points"
C
C Main program
      REAL Y 
      DATA Y / 10.0 / 
C An arithmetic statement function,
C  which is NOT instrumented.
      CHARACTER * 7 R3PATH 
      DATA R3PATH / 'ex02u.f' / 
      INTEGER R3SWIT 
      LOGICAL R3LOGI 
      SQ ( Z ) = Z * Z 
      CALL SUB ( - 2.0 ) 
      CALL SUB ( SQ ( Y ) ) 
      CALL R3RETN ( R3PATH , 12 , 'MAIN' ) 
      END 
C
C Subroutine
      SUBROUTINE SUB ( X ) 
      REAL X , PI 
      DATA PI / 3.14 / 
      CHARACTER * 7 R3PATH 
      DATA R3PATH / 'ex02u.f' / 
      INTEGER R3SWIT 
      LOGICAL R3LOGI 
      IF ( X .LT. 0 ) THEN 
      CALL R3RETN ( R3PATH , 18 , 'SUB' ) 
      RETURN 
      ENDIF 
      PRINT 1001 , PI * X 
      CALL R3RETN ( R3PATH , 20 , 'MAIN' ) 
      STOP 
01001 FORMAT ( ' Result: ' , F8 .2 ) 
      CALL R3RETN ( R3PATH , 22 , 'SUB' ) 
      ENDSUBROUTINE SUB 

B.3 Instrumentation of Decisions

Uninstrumented file:

C ex03u.f - Example for
C  "Instrument Decisions"
C
C Computed GOTO statement
      DO 100 J=1,3
      GOTO (20, 10) J
      PRINT 1001, 'C'
      GOTO 100
   10 PRINT 1001, 'B'
      GOTO 100
   20 PRINT 1001, 'A'
  100 CONTINUE
C GOTO on a logical IF
      DO 200 J=1,3
      IF (J .GT. 1) GOTO (120, 110) J - 1
      PRINT 1001, 'D'
      GOTO 200
  110 PRINT 1001, 'F'
      GOTO 200
  120 PRINT 1001, 'E'
  200 CONTINUE
C Logical IF
      DO 300 J=1,3
      IF ( J .LT. 2 ) PRINT 1001, 'G'
  300 CONTINUE
C IF THEN ELSE construct
      DO 400 J=1,3
      IF ( J .EQ. 1 ) THEN
        PRINT 1001, 'h'
      ELSE IF (J .EQ. 2) THEN
        PRINT 1001, 'i'
      ELSE
        PRINT 1001, 'j'
      ENDIF
  400 CONTINUE

 1001 FORMAT(' Result: ', A)
      END

Instrumented file:

C ex03u.f - Example for
C  "Instrument Decisions"
C
C Computed GOTO statement
      CHARACTER * 7 R3PATH 
      DATA R3PATH / 'ex03u.f' / 
      INTEGER R3SWIT 
      LOGICAL R3LOGI 
      DO 100 J = 1 , 3 
      GOTO ( 20 , 10 ) R3SWIT ( R3PATH , 7 , J ) 
      PRINT 1001 , 'C' 
      GOTO 100 
00010 PRINT 1001 , 'B' 
      GOTO 100 
00020 PRINT 1001 , 'A' 
00100 CONTINUE 
C GOTO on a logical IF
      DO 200 J = 1 , 3 
      IF ( R3LOGI ( R3PATH , 16 , J .GT. 1 ) ) THEN 
      GOTO ( 120 , 110 ) R3SWIT ( R3PATH , 16 , J - 1 ) 
      ENDIF 
      PRINT 1001 , 'D' 
      GOTO 200 
00110 PRINT 1001 , 'F' 
      GOTO 200 
00120 PRINT 1001 , 'E' 
00200 CONTINUE 
C Logical IF
      DO 300 J = 1 , 3 
      IF ( R3LOGI ( R3PATH , 25 , J .LT. 2 ) ) THEN 
      PRINT 1001 , 'G' 
      ENDIF 
00300 CONTINUE 
C IF THEN ELSE construct
      DO 400 J = 1 , 3 
      IF ( R3LOGI ( R3PATH , 29 , J .EQ. 1 ) ) THEN 
      PRINT 1001 , 'h' 
      ELSEIF ( R3LOGI ( R3PATH , 31 , J .EQ. 2 ) ) THEN 
      PRINT 1001 , 'i' 
      ELSE 
      PRINT 1001 , 'j' 
      ENDIF 
00400 CONTINUE 

01001 FORMAT ( ' Result: ' , A ) 
      END 

B.4 Instrumentation of Basic Blocks

Uninstrumented file:

C ex04u.f - Example for
C  "Instrument Basic Blocks"
C
C Computed GOTO statement
      DO 100 J=1,3
      GOTO (20, 10) J
 1001 FORMAT(' Result: ', A)
      PRINT 1001, 'C'
      GOTO 100
   10 PRINT 1001, 'B'
      GOTO 100
   20 PRINT 1001, 'A'
  100 CONTINUE
C GOTO on a logical IF
      DO 200 J=1,3
      IF (J .GT. 1) GOTO (120, 110) J - 1
  101 PRINT 1001, 'D'
      GOTO 200
  110 PRINT 1001, 'F'
      GOTO 200
  120 PRINT 1001, 'E'
  200 CONTINUE
C Logical IF
      DO 300 J=1,3
      IF ( J .LT. 2 ) PRINT 1001, 'G'
  300 CONTINUE
C IF THEN ELSE construct
      DO 400 J=1,3
      IF ( J .EQ. 1 ) THEN
        PRINT 1002, 'h'
      ELSE IF (J .EQ. 2) THEN
 1002 FORMAT(' Result: ', A)
        PRINT 1002, 'i'
      ELSE
        PRINT 1002, 'j'
      ENDIF
  400 CONTINUE
      END

Instrumented file:

C ex04u.f - Example for
C  "Instrument Basic Blocks"
C
C Computed GOTO statement
      CHARACTER * 7 R3PATH 
      DATA R3PATH / 'ex04u.f' / 
      INTEGER R3SWIT 
      LOGICAL R3LOGI 
      DO 8800 J = 1 , 3 
      GOTO ( 20 , 10 ) J 
01001 FORMAT ( ' Result: ' , A ) 
      CALL R3BLOC ( R3PATH , 8 ) 
      PRINT 1001 , 'C' 
      GOTO 100 
00010 CALL R3BLOC ( R3PATH , 10 ) 
      PRINT 1001 , 'B' 
      GOTO 100 
00020 CALL R3BLOC ( R3PATH , 12 ) 
      PRINT 1001 , 'A' 
00100 CALL R3BLOC ( R3PATH , 13 ) 
08800 CONTINUE 
C GOTO on a logical IF
      DO 8801 J = 1 , 3 
      IF ( J .GT. 1 ) THEN 
      CALL R3BLOC ( R3PATH , 16 ) 
      GOTO ( 120 , 110 ) J - 1 
      ENDIF 
00101 CALL R3BLOC ( R3PATH , 17 ) 
      PRINT 1001 , 'D' 
      GOTO 200 
00110 CALL R3BLOC ( R3PATH , 19 ) 
      PRINT 1001 , 'F' 
      GOTO 200 
00120 CALL R3BLOC ( R3PATH , 21 ) 
      PRINT 1001 , 'E' 
00200 CALL R3BLOC ( R3PATH , 22 ) 
08801 CONTINUE 
C Logical IF
      DO 8802 J = 1 , 3 
      IF ( J .LT. 2 ) THEN 
      CALL R3BLOC ( R3PATH , 25 ) 
      PRINT 1001 , 'G' 
      ENDIF 
00300 CALL R3BLOC ( R3PATH , 26 ) 
08802 CONTINUE 
C IF THEN ELSE construct
      DO 8803 J = 1 , 3 
      IF ( J .EQ. 1 ) THEN 
      CALL R3BLOC ( R3PATH , 30 ) 
      PRINT 1002 , 'h' 
      ELSEIF ( J .EQ. 2 ) THEN 
01002 FORMAT ( ' Result: ' , A ) 
      CALL R3BLOC ( R3PATH , 33 ) 
      PRINT 1002 , 'i' 
      ELSE 
      CALL R3BLOC ( R3PATH , 35 ) 
      PRINT 1002 , 'j' 
      ENDIF 
00400 CALL R3BLOC ( R3PATH , 37 ) 
08803 CONTINUE 
      END