                 Static Error Checker OSA

     Overview 
     The OSA environment 
     Starting OSA 
     Analysed configuration 
     Analysis phases and stages 
     Procedure call graph output 
     How to speedup OSA analysis 
     OSA messages 
     OSA options 
     OSA equations 


       

Overview

The static error checker OSA checks Oberon-2 and Modula-2
programs for run-time errors. by analysing the source code. The checker
is able to detect all kinds of violations of Modula-2 and Oberon-2
dynamic semantics, which are typically found (or not found) during
debugging and testing stages of development. 

OSA also checks the analysed program for violations of well organized
program criteria. Of course, violations of these criteria are not errors but
they often indicate other program weaknesses that may be errors. 

Some (but not all) of the erroneous situation types in a program that
OSA is able to detect are listed below: 

     usage of an uninitialized variable 
     dereference of a pointer whose value is NIL in "<designator>^"
        constructs 
     assignment of a variable whose value is never used 
     type guard violation 
     usage of a dead variable (a variable that was already deallocated) 
     unreachable branches in statements IF, CASE, and Oberon-2 WITH 
        always true (or always false) operands in constructs like
        "<Expr1> OR <Expr2>" and "<Expr1> AND <Expr2>" 
     procedure without exit 
     ASSERT condition is always false 
     overflow (underflow) in arithmetic operators and type transfers 
     array index is out of bounds 
     division by zero 
     FOR loop repeats zero times 
     ALLOCATE or NEW is used to create an array whose length is less
     than or equal to zero 

Actually, this is a typical list of erroneous situations that an ordinary error
checker, e.g. for the C language, can detect. But OSA has two
important advantages: 

   1.OSA distinguishes between definite errors and doubtful situations.
     In the latter case, OSA produces messages called "conditional
     errors" that appear to be errors in approximately one case from
     five. 

   2.OSA performs context-sensitive data flow analysis, so it can
     recognize an erroneous situation which happens for one call of a
     procedure and does not happen for another call. Thus, OSA
     detects situations of high complexity. 

Data-flow analysis performed by OSA requires a considerable amount
of time and memory. If your program causes OSA to exhaust the
resources of your computer, you may wish to read the section How to
speedup OSA analysis, which describes how to speedup analysis in
exchange for its quality. 

Note: In this version of the manual it is assumed that the host platform is
OS/2 or Windows NT/95, but not Unix. 

OSA was originally developed at the Institute of Informatics Systems,
Novosibirsk, Russia, by Vladimir I. Shelekhov (vshel@iis.nsk.su)
and Sergey V. Kuksenko (sergic@iis.nsk.su). 


       

The OSA environment

OSA is based on the XDS compiler construction framework, and
inherits the user interface of XDS compilers. XDS compiler
configuration, control files, operation modes, options and equations, etc.,
are fully applicable to OSA. Refer to chapters Configuring the compiler,
Using the compiler, and Compiler Options and Equations in 
The Native XDS-x68 User's Guide for more information. 

Similarly to an XDS compiler environment, the OSA environment
consists of the executable file and a set of system files: osa.red,
osa.cfg, and osa.msg. The showmsg.exe utility may be used to
transmit OSA messages into XDS environment (Windows NT/95 and
OS/2 only). 

We recommend you to create subdirectories msg, sym, irf, and lst
for analyser output files in your working directory. You may continue to
translate programs that reside in that directory with an XDS compiler. 

A redirection file, osa.red, defines directories in which OSA seeks and creates
files of variuos types. The most important are your program source files
and XDS library files. osa.red must reside in the directory which is the
current directory when you start OSA. If it is not present there, the
master redirection file is read from the directory in which the OSA
executable resides. 

An OSA redirection file example is shown below: 

*.msg  = c:\xds\bin
*.cfg  = c:\xds\bin
*.prj  = prj 
*.sym  = sym;
*.def  = def; c:\xds\def\iso; c:\xds\def\ts
*.mod  = mod
*.ob2  = oberon; appl
*.mes  = msg
*.lst  = lst
*.grf  = lst
*.irf  = irf

According to this file, OSA will search for Oberon-2 modules in the
subdirectories oberon and appl of the current directory, for Modula-2
definition modules --- in the def subdirectory and in XDS system
directories, C:\XDS\DEF\ISO and C:\XDS\DEF\TS, and so on. The
OSA message listing for a program will be written to the file msg\<main
module name>.mes. 

The analyser may be set up so that it will save the partially analysed
intermediate representation of the program to file and then will terminate
(see Saving a partially analysed program to file). The default extension
for these files is irf, so this redirection file tells OSA that these files
have to be placed into the subdirectory irf. 

The procedure call graph of a program is written to the lst subdirectory
if the option GRAPH is ON. 



     Symbol files 

Symbol files

Symbol files for program modules are created and/or read when a
program is translated by the XDS Modula-2/Oberon-2 front-end, which
is part of OSA. As a result, the analyzer may read symbol files that were
created by an XDS compiler, provided that the compiler is built in the same
mode (normal, trial, or demo) and uses the same version of the front-end. 

The equation SYM (sybmol file extension) may be used to help you
better distinguish between OSA symbol files and your XDS compiler
symbol files. For instance, to have the extension osm to be used for
OSA symbol files, add the line 

-sym=osm 

to your osa.cfg file. Now, to have these files placed into the osa_sym
subdirectory, add the line 

*.osm = osa_sym; 

to your osa.red file. 


       

Starting OSA

Generally, OSA is invoked like an XDS compiler. All XDS operation
modes, except GEN, BROWSE, and BATCH, may be used. OSA
recognizes all XDS options and equations that are not specific to a
particular code generator. 

Note: The option MAIN has to be set ON (inline or in the command
line) for the main Oberon-2 module. 

If your program consists of a single module, OSA can be invoked in the
COMPILE mode: 

osa [=c] <name of program file> [<options and equations>] 

If your program includes several modules but has no project file, use the
MAKE mode: 

osa =m <top-level module file> [<options and equations>] 

Finally, if your program includes several modules and has a project file,
use the PROJECT mode: 

osa =p <name of project file> [<options and equations>] 

A project file example is presented below: 

-graph+         % OSA option
-o2extensions+  % XDS options
-m2extensions+
-m2addtypes+
!module Start.mod

Given the main module of a program, OSA searches for other modules
according to XDS make strategy, using paths specified in the redirection
file and LOOKUP equations. If the source text of a module cannot be
found using search paths, then at least the correspondent symbol file
must be present. To produce a symbol file for a module, use the
command line like 

osa <module name> +msym 


       

Analysed configuration

Upon startup, the analyser builds the analysed configuration of the
specified program, using the redirection file and LOOKUP equations.
An analysed configuration may be the whole program or some part of it
and includes procedures (and module bodies) called from the main
module or from top procedures (see section Analysing part of a
program). If the source code of a module is not available to OSA, then
procedures of this module are called external procedures and variables
exported from this module are called external variables. 

An analysed configuration should have the least possible number of
external entities, because data flow analysis of external entities has to be
very rough to be true. 

Note: In Oberon-2 programs, if the analysed configuration includes a
call of a method for the object Obj, then all procedures, bodies of which
contain calls include calls NEW(Obj) or assignment statements that assign
values to Obj, must be also included in the analysed configuration.
Otherwise data flow analysis results will be incorrect. 


       

Analysis phases and stages

The analyser processes your program in several passes: 

   1.Creation of the XDS intermediate representation of your program
     by the XDS Modula-2/Oberon-2 front-end. 
   2.Conversion of the XDS intermediate representation to the OSA
     intermediate representation. 
   3.Data flow analysis 
   4.Error analysis 

In turn, data flow analysis in OSA consists of the following phases: 

 CI   context-insensitive analysis 

 CIF  CI phase finalization 

 CS   context-sensitive analysis 

 CSF  CS phase finalization 

 VC   value calculation 


Each phase consists of a sequence of stages. A stage is a minimal
independent step of analysis. Stages are sequentially numbered through
all phases. 

You may explicitly terminate an analysis phase at a specific stage by
substituting the number of that stage into the CUT equation, or
interactively by pressing the Esc key (see section How to speedup OSA
analysis). This will cut off parts of the program that were not analysed
yet for the remaining phases. 

Finalization phases were introduced for correct cleanup after an explicit
cutoff of an analysis phase. If the analysis phase was not cut off, the
respective finalization phase is not invoked. So it is recommended not to
cut off a finalization phase. 

Sometimes, if the CI phase was failed due to lack of resources, the
option CI can be of help. If this option is set OFF, data flow analysis is
started with the CS phase. 

If the VC option is set OFF, the VC phase will be omitted. This feature
may be used, for instance, if OSA crashes during this phase. 


       

Procedure call graph output

If the option GRAPH is set ON, the analyser outputs the procedure call
graph when data flow analysis finishes or is terminated using one of the
equations CUT, SAVE, or SAVE_MEM, or intercatively. 

If the program being passed through OSA is large or complicated, data
flow analysis may slow down drastically at some stage due to lack of
resources. The procedure call graph may help you understand which
procedures cause the difficulties. 

There are two sections in a procedure call graph file. The first part
shows, for each procedure, which procedures are called in its body. The
second part shows, for each procedure, from what procedures it may be
called. 

Each procedure belongs to a certain layer. Procedures in the layer 0 call
no other procedures. A procedure P that belong to the layer N, may call
a procedure belonging to a layer whose number is less than N (or is
equal to N if the procedure P is recursive). 

A procedure layer in the first section of a procedure call graph has the
following structure: 

 ----------------------- LAYER N ----------------------
 <list of procedure names>
 <calls in the body of the first procedure>
 ............................................ and so on
 <calls in the body of the last procedure>

In the <list of procedure names> the name of a procedure that is
already processed by OSA is followed by two numbers: the number of
contexts and the number of variables in the collected data flow
information for this procedure. The second number strongly correlates
with the amount of memory required for analysis of the procedure. If the
number of contexts is in the range 200-400 or above (this may happen
for a recursive procedure) then, as a rule, the analysis of such procedure
is slow. The equation ONE may be used to speedup analysis of such
procedures (see subsection Simplified analysis of procedures). 

In the second section of a procedure call graph each line has the
following structure: 

<procedure name> <-- <list of calling procedures> 

Each call in the <list of calling procedures> is 

<procedure name> ( <line number>, <column number> ) 

A fragment of a procedure call graph is shown below. 

 ----------------------- LAYER 7 ----------------------
 slP.openOut(15,121) slP.boolExpr(4,455)! 
     slP.openOut-->slP.warning,ManagerDesc:xiFi.Open;  
     slP.boolExpr-->slP.Value!,slK.push,slK.fatal!;  

It shows which procedures are called from procedures slP.openOut
and slP.boolExpr, which belong to layer 7 of the call graph. The
number of contexts for slP.openOut is 15; the number of variable
definitions (assignments) is 121. The respective values for
slP.boolExpr are 4 and 455. 

The token "!" indicates procedures whose analysis has not been
finished yet. In the above fragment, procedures slP.Value,
slK.fatal, and, as a result, slP.boolExpr are still processed by data
flow analysis. This may give you some idea on the progress of data flow
analysis. 

In the second part of a procedure call graph file, calls to each procedure
are shown. For instance, if you want to find out from where the
procedure Value is called, search for the string "Value<--" in the call
graph file. You might find a string like: 

slP.Value<--slP.boolExpr(351,14), slP.Cbra(341,4),
slH.Binar() 

which indicates that procedures slP.boolExpr, slP.Cbra, and
slH.Binar have calls to Value in their bodies, but only procedures
slP.boolExpr and slP.Cbra were processed by data flow analysis,
because coordinates of calls are shown in brackets only for these two
procedures. The procedure slH.Binar did not undergo data flow
analysis yet. 


       

How to speedup OSA analysis

If data flow analysis exhausts the resources of your system, or takes too
much time, you may use one or more of the following techniques: 

   Use the equation SAVE to have OSA save the partially analysed
     program to file after the given analysis stage is finished. Then,
     invoke OSA again specifying the equation READ to continue
     analysis (see section Saving a partially analysed program to file). 
   Any analysis phase may be explicitly terminated after the given
     stage is finished using the equation CUT. The remaining phases
     will work only on the program part that has been processed by
     the terminated phase (see section Excluding program parts from
     subsequent phases). 
   A well closed part of a program (based on one or a few
     procedures) may be independently passed through OSA (see
     section Analysing part of a program). 
   Use the equation ONE to analyse specific procedures
     context-insensitive mode only (see section Simplified analysis of
     procedures). 

To have the names of procedures processed in data flow analysis
displayed on the screen, use the option SHOW. 

These features may be activated interactively by pressing the Esc key
during OSA execution (OS/2, Windows 95/NT only) when analysis
phases are working. If you press Esc when data flow analysis is
working, then after the end of the current analysis stage the following
menu will be written to the screen: 

ANALYSIS INTERRUPTED!
(S) - save intermediate file and terminate
(C) - cut off non-analysed part of the program and skip to next phase
(G) - output procedure call graph to file
(H) - toggle progress indicator
(N) - continue analysis
(F) - terminate immediately

If you type "g", OSA outputs the current procedure call graph to a
file  <project name>.grf, and then redisplays the menu. 
You may now look at the call call graph in another window and 
then make your choice. 

If you type "h", OSA triggers the option SHOW, and then redisplays the
menu. To see the names of procedures processed by data flow analysis,
switch this option ON. 

OSA is written in the Oberon-2 language, which integral memory
management relies on garbage collection. However, the garbage
collector is off by default, so that it does not slow down the analyser. If
you notice increased swapping activity during analysis, terminate OSA
and turn on garbage collection by specifying the equations
COLLECTMIN and COLLECTMAX in the OSA configuration file,
osa.cfg: 

-CollectMin = 110 
-CollectMax = 127 

In this example, garbage collection will be invoked after the current
analysis stage is finished, if the amount of memory allocated by the
analyser is in the range 110-127 megabytes. This range is close to
optimal for a system with 128M RAM running under OS/2 Warp
version 3. We recommend to put this range close to the amount of
available physical memory before you start OSA, but you'll have to
experiment until you find suitable values for your system. 



     Analysing part of a program 
     Saving a partially analysed program to file 
     Excluding program parts from subsequent phases 
     Simplified analysis of procedures 
     Turning off context-insensitive analysis 


       

Analysing part of a program

Part of a program, defined by one or more procedures, may be
independently analysed by using the equation TOP. 

Type 

osa =p <project file name> -top=<procedure list>, 

where 

<procedure list> ::= 
          <procedure> |
          <procedure list>;<procedure>
<procedure> ::= 
          <ordinary procedure> |
          <type-bound procedure>
<ordinary procedure> ::= 
          <module name>.<procedure name>
<type-bound procedure> ::= 
          <module name>.<type name>::<procedure name>

Note that blanks and commas are not permitted inside a <procedure
list>. For Oberon-2 type-bound procedures the name of the
respective pointer type or the name of the record type may be used. 

When the equation TOP is specified, the analysed configuration is built
as if the top-level module of the program contained only calls to the
given procedures, with unknown values of parameters, so it consists of
these procedures and all procedures that may be reached from them
during execution. 

Note: It is a user's responsibility to ensure that the resulting analysed
configuration is well closed. This means that variables declared in
imported modules are not changed by modules that are not included in
the analysed configuration. 


       

Saving a partially analysed program to file


A partially analysed intermediate representation of a program may be
saved to file after any stage using the SAVE equation. To continue
analysis, the READ equation shall be used when the analyser is invoked
next time. 

For instance, if the main program module is named Main, and the
project name is MainProj, the command line 

osa =p MainProj -save=456 

would save the intermediate representation to file Main_456.irf after
completion of the analysis stage number 456. To continue analysis, type 

osa -read=Main_456 

The amount of memory required to load a previously saved partially
analysed program is typically much less than was allocated before it was
saved. So this feature may be used to decrease OSA memory
requirements. 

There are two special values of the SAVE equation. Specifying
-save=last causes the analysed program to be saved after competion
of data flow analysis. -save=first, caused it to be saved right before
data flow analysis. 

The equation SAVE_MEM may be used to save a partially analysed
program to file if the amount of allocated memory exceeds the given
value (in megabytes) after completion of the current analysis stage. 


       

Excluding program parts from subsequent phases


An analysis phase may be explicitly terminated using the equation CUT
or interactively by pressing the Esc key. The current phase will be
terminated after completion of the specified stage. The part of the
program that has not been processed during this stage is cut off; the
subsequent phases will process only the remaining part. 

There is one special value of the CUT equation. If you type 

osa -read=<file> -cut=now 

then after reading the partially program from "file", the current phase
will be terminated, and the next analysis phase will be started. 


       

Simplified analysis of procedures

It may happen that data flow analysis works a very long time at some
stage. A possible cause is the constantly growing number of contexts for
some (usually recursive) procedures. This may be confirmed by studying
the procedure call graph after the current analysis stage (see section
Procedure call graph output). 

If the above appears to be the case, the equation ONE may be used in
the next invocation of OSA to specify the list of procedures that have to
be analysed context-insensitively. The structure of a procedure list is
described in section Analysing part of a program. Analysis will be faster
but rough for listed procedures. 

To have the names of procedures processed in data flow analysis
displayed on the screen, use the option SHOW. 


       

Turning off context-insensitive analysis

If the option CI option is set OFF, the CI analysis phase will be skipped
and data flow analysis will be started from the CS phase. ??? This may
help if the CI phase fails due to lack of resources. 


       

OSA messages

Let's run the example program weak2 (below) through OSA by typing
the following string: 

osa weak2.ob2 

This will produce a message file weak2.mes in the approriate directory. 

1  MODULE weak2;
2    IMPORT M;
3    TYPE p_rec= POINTER TO RECORD field: INTEGER END;
4    VAR X,Y:   p_rec;
5    VAR i,j,k: INTEGER;
6    PROCEDURE F(Z:p_rec);
7    BEGIN  Z^.field:=k+1  END F;
8  BEGIN
9    NEW(X); NEW(Y);
10   M.G(i,i+1);
11   IF i=0 THEN F(X); M.G(j,j+1) ELSIF i>0 THEN F(Y) END;
12 END weak2.

     Message modes 
     Variables 
     Contexts 
     Variable denotations 


       

Message modes

A message listing produced by OSA includes error messages,
conditional error messages and warnings. An error message corresponds
to an absolute error; the error site in source code is reached for every
execution of a program. An error site for a conditional error is nested
inside a control statement that may alter execution flow, such as IF,
CASE, or WHILE. A conditional error turns to the actual error if error site
is reached for any execution of program. This depends on the values of
conditions in the IF, CASE, etc. statements that lead to error site. 

The resulting OSA message listing includes the following messages: 

################### Unassigned Variables (ABSOLUTE ERRORS) #################

[E] (t/weak2.ob2 10,9) variable i not assigned
      M.G(i,i$+1);

################# Unassigned Variables (CONDITIONAL ERRORS) ################

[C] (t/weak2.ob2 7,20) variable k not assigned
      BEGIN  Z^.field:=k$+1  END F;
[C] (t/weak2.ob2 11,27) variable j not assigned
      IF i=0 THEN F(X); M.G(j,j$+1) ELSIF i>0 THEN F(Y) END;

The first message reports an absolute error because the expression i=0
is always calculated when the program is executed. The third message
indicates a conditional error, because the condition j>0 is inside an IF
statement so it is possible that it will not be calculated during program
execution (if the value of i is zero). The second message is also
conditional. Even though the statement Z^.field:=k+1 in the body of
the procedure F is not nested inside an IF, CASE, or another control
statement, both calls to F are nested inside an IF statement. So this is an
actual error only if (i=0) OR (j>0) is true during execution of weak2. 


       

Variables

The message listing for the above example program weak2 also includes
the following message: 

######################## UNUSABLE VARIABLES (Strong) #######################

[W] (t/weak2.ob2 7,17) variables $new0.field,$new1.field assigned but not
   used
      BEGIN  Z^.field$:=k+1  END F;
  #DEREFERENCES Z^=$new0,$new1!
  #DECLARATIONS $new0:(9,2) $new1:(9,10) Z:(6,14)

This warning reports that the values of variables $new0.field and
$new1.field are not used in program weak2, and so the assignment
Z^.field := k+1 to these variables is superfluous. 

Variables $new0 and $new1 denote heap variables generated after
execution of statements NEW(X) and NEW(Y), respectively. That is,
X^=$new0 and Y^=$new1. 

The section #DEREFERENCES in the message shows the values of
dereferenced variables which constitute target variable of the assignment
statement. For the target variable Z^.field, variables $new0 and
$new1 are showed as the values of variable Z. 

The symbol "!", located at the end of the #DEREFERENCES section,
indicates that both variables $new0 and $new1 were recognized as
obligatory (must-) values of Z. The symbol "?" in that position would
mean that variables after the symbol "?" were recognized as possible
(may-) values of Z. 

In the #DECLARATIONS section, coordinates (line and column numbers)
of the variable declaration in the source code are shown for each
variable from the #DEREFERENCES section. 


       

Contexts

A context of a procedure F is a subset of the full set of call chains to the
procedure F from the body of the main program module or entry
procedures. Let us illustrate the notion of context on the example
program weak3 below. 

1  MODULE weak3;
2    TYPE p_rec= POINTER TO RECORD field: INTEGER END;
3    VAR X,Y,U:   p_rec;
4    VAR i,k:     INTEGER; 
5 
6    PROCEDURE F(Z:p_rec);
7    BEGIN  Z^.field:=k+1  END F;
8
9    PROCEDURE G(R:p_rec);
10   BEGIN  IF k#0 THEN F(R) END END G;
11 BEGIN
12   NEW(X); NEW(Y);
13   IF i=0 THEN F(X) ELSE G(Y) END;
14   G(U);
15 END weak3.

The full set of call chains to the procedure F (that is the full context) is 
the following: 

$body_weak3(13,14) ?F 
$body_weak3(13,24) ?G(10,21) ?F 
$body_weak3(14,2) ?G(10,21) ?F 

Each OSA message holds only within the context given in the #CONTEXT
section of the message. If the #CONTEXT section is not present, the
message holds for all possible call chains. 

A context containing a single call chain 

$body_weak3(14,2) -> G(10,21) -> F 

is used in the following message: 

######## NIL pointer dereference & type guard (CONDITIONAL ERRORS) #########

[C] (t/weak3.ob2 7,10) NIL pointer dereference for variable Z
      BEGIN  Z$^.field:=k+1  END F;
  #CONTEXT F(7,10) <- G(10,21?) <- $body_weak3(14,2)

It means that this message is valid when the procedure F is called from
the procedure G at position (10,21), and G, in turn, is called from the
body of the module weak3 at position (14,2). 

The symbol "?" in G(10,21?) means that the indicated call of F in the
body of G is under condition. 

A context including two call chains is defined in the message below. 

[W] (t/weak3.ob2 7,17) variable $new0.field,$new1.field assigned but not used
      BEGIN  Z^.field$:=k+1  END F;
  #DEREFERENCES Z^=$new0,$new1!
  #DECLARATIONS $new0:(12,2) $new1:(12,10) Z:(6,14) 
  #CONTEXT F(7,17) <- G(10,21?) <- $body_weak3(13,24?)
      # F(7,17) <- $body_weak3(13,14?)

re 

In general case, a context is described by a tree-like chain of calls. Each
new branch of the tree begins with the symbol '#" followed by a
procedure call entered before. 


       

Variable denotations

The variable name modes used in OSA message list are described
below. 

<variable name> ::= 
          <variable identifier> |
          <heap variable> |
          <variable name>.<field name> |
          <variable name>[] |
          <previous instance of variable> |
          <external variable denotation> |
          ~<variable name> |
          <temporary variable>

If A is a name of an array variable. A[] denotes an arbitrary element or
the array A. ~A denotes a local variable A after return from from the
procedure containing it, when the address of A is the value of a pointer
variable which is global relative to that procedure. 

<heap variable> ::= 
          $new<number of NEW or ALLOCATE statement>
<number of NEW or ALLOCATE statement> ::=  <integer> 
<previous instance of variable> ::= 
          <variable identifier>' |
          <heap variable>' 

Name $newK denotes a variable generated by the K-th occurrence of a
call to the ALLOCATE procedure (when the option ALLOCATE is ON)
or to the NEW procedure in source code. Any previous instance of a
variable generated before by the same NEW or ALLOCATE statement is
denoted by $newK'. 

In the example program below, after execution of the statement NEW(n),
the variable n points to a heap variable $new0 (n^=$new0). If the
variable list is not equal to NIL on line 10 (that is when i is greater
than one), the variable list points to $new0 generated in the previous
call of the procedure to_list, and hence list^=$new0'. 

1  MODULE previous;
2  TYPE pList = POINTER TO List;
3       List = RECORD elem:INTEGER; next:pList END;
4  VAR list: pList; i: INTEGER;
5
6  PROCEDURE to_list(elem:INTEGER);
7    VAR n: pList;
8  BEGIN
9    NEW(n); n.elem:=elem;
10   IF list#NIL THEN n.next:=list END;
11   list:=n;
12 END to_list;
13
14 BEGIN FOR i:=1 TO 8 DO to_list(i) END
15 END previous.

If z be a variable identifier declared in a recursive procedure F, then z
denotes that variable for the current call of F and z' denotes the same
variable in any previous recursive call. 

<external variable denotation> ::= #<type name>

A variable declared beyond the analysed configuration of a program is
called an external variable. A pointer variable that receives its value as a
result of execution of an external procedure (a procedure whose body is
not included in the analysed configuration), is assumed to point to an an
external variable. Such variables are denoted by #T where T is the name
of the pointer base type. 

<temporary variable> ::= 
          $temp_<number of WITH statement> |
          $agr_<number of array or record constructor> 

A temporary variable is created by data flow analyser for each
Modula-2 WITH statement, and for each occurrence of an array or
record constructor in the source code. 


       

OSA options

All XDS compiler options not specific to a particular back-end may be
used with OSA. See Chapter Compiler Options and Equations for more
information. 

 Option       Meaning 

 GRAPH        enable procedure call graph output 
 CLOSED       assume well closed configuration 
 ALLOCATE     assume standard heap manager 
 SHOW         print names of analysed procedures 
 MSYM         only make symbol files 
 FIELD_ALIAS  assume variant field aliasing 
 CI           start analysis from first phase CI
 CV           enable value calculation phase CV



GRAPH - enable procedure call graph output

Setting this option ON enables procedure call graph output after end of
the data flow analysis. See section Procedure call graph output for more
information. 

This option is OFF by default. 


       

CLOSED - assume well closed configuration

If this option is set ON, OSA assumes that the part of the program being
analysed is well closed for used Modula-2 modules. 

This option is ON by default. 

See section Analysing part of a program for more information. 


       

ALLOCATE - assume standard heap manager

If this options is set ON, the analyser assumes that the procedure
ALLOCATE used in the program is declared in the standard module
Storage. This may significantly improve analysis results. 

This option is ON by default. 


       

SHOW - print names of analysed procedures

Setting this option ON enables output of the names of procedures
processed by data flow analysis to the screen. 

This option is OFF by default. 

See sections Excluding program parts from subsequent phases and How
to speedup OSA analysis. 


       

MSYM - only make symbol files

This option, when set ON, causes OSA to terminate immediately after
creation of the XDS internal representation of your program. Use it if
you only need to create a symbol file for some module. 

This option is OFF by default. 

See section Starting OSA. 


       

FIELD_ALIAS - assume variant field aliasing

(inline) 

If this option is set OFF, the analyser treats fields of variant parts of
Modula-2 record types as if they were non-overlapping. This does not
affect analysis correctness, provided that in no event the program
accesses a variant field different from what was assigned last, and the
quality of analysis is better. Set this option ON inline for types that do
not fall into the above category. 

This option is OFF by default. 


       

CI - enable context-insensitive phase

Setting this option OFF forces the analyser to omit the
context-insensitive phase of analysis and proceed directly to the
context-sensitive phase, like it was in OSA versions 0.33 and below. 

This option is ON by default. 

See section Analysis phases and stages. 


       

VC - enable value calculation phase

Setting this option OFF disables the value calculation phase of analysis. 

This option is ON by default. 

See section Analysis phases and stages. 


       

OSA equations

All XDS compiler equations not specific to a particular back-end may
be used with OSA. See chapter Compiler Options and Equations for
more information. 

     TOP - fake top-level module 
     SAVE_MEM - memory limit 
     CUT - data flow analysis stop stage number 
     SAVE - data flow analysis save stage number 
     READ - continue a prefiously saved analysis 
     ONE - analyse given procedures context-insensitively 
     INIT - default value for variables 
     COLLECTMIN - minimal amount of memory for garbage collection 
     COLLECTMAX - maximum amount of memory for garbage collection 
     MSGEXT - message file extension 
     IRFEXT - intermediate file extension 
     GRFEXT - call graph file extension 


       

TOP - fake top-level module

Use this equation to specify a list of procedures that are to be used as
starting call graph nodes when selecting the part of program to analyse.
By default, the main module body is the starting node of the call graph. 

See section Analysing part of a program for more information. 


       

SAVE_MEM - memory limit

The analysed program is saved after the stage that caused OSA to
exceed the specified amount of memory. Then, the READ equation can
be used then to continue analysis. 

See section Saving a partially analysed program to file for more
information. 


       

CUT - data flow analysis stop stage number

If specified, this equation causes data flow analysis to stop after stage
with the given number. Have to write something here. 

See section Saving a partially analysed program to file for more
information. 


       

SAVE - data flow analysis save stage number

When the analysis stage with the specified number is finished, the
analysed program is saved into a file. 

See sections The OSA environment and Saving a partially analysed
program to file. 


       

READ - continue a prefiously saved analysis

If specified, this equation forces OSA to read a partially analysed
program from the given file, previously saved by using the SAVE
equation or the SAVE_MEM equation. The data-flow analysis is then
continued 

See also section Saving a partially analysed program to file. 


       

ONE - analyse given procedures context-insensitively

Only the context-insensitive data flow analysis is applied to listed
procedures, if any. Use this feature to speedup analysis in exchange for
its accuracy. 

See also section How to speedup OSA analysis. 


       

INIT - default value for variables

By default the initial values of all variables are undefined. Using this
equation, you may significantly improve the value calculation analysis
done by OSA. 


       

COLLECTMIN - minimal amount of memory for
garbage collection

The minimal amount of allocated memory, in megabytes, that causes the
garbage collector to be invoked after the current analysis stage is
completed. 

See section How to speedup OSA analysis. 


       

COLLECTMAX - maximum amount of memory for
garbage collection

The maximum amount of allocated memory, in megabytes, that causes
the garbage collector to be invoked after the current analysis stage is
completed. 

See section How to speedup OSA analysis. 


       

MSGEXT - message file extension

Specifies an extension for OSA message list files. By default, the
extension mes is used. 


       

IRFEXT - intermediate file extension

Specifies an extension for intermediate analysis files. By default, the
extension irf is used. 


       

GRFEXT - call graph file extension

Specifies an extension for output files that contain procedure call graphs.
By default, the extension grf is used. 
