Previous Next Contents Index Doc Set Home


Separate Compilation

5


This chapter describes how to compile Pascal programs in separate units. Chapter 4, "Program Construction and Management," gives an introduction to the concepts in this chapter. Following are the sections:

Working with Units

page 79

Sharing Variables and Routines Across Multiple Units

page 80

Sharing Declarations in Multiple Units

page 91

In separate compilation, a program is divided into several units that can be separately compiled into object (.o) files. The object files are then linked using pc, which invokes pc3 to check for the consistent use of global names and declarations across the different units, and then invokes ld(1) to link and load the units. You can also give pc the names of all the units at once, in which case pc compiles all the units, checks for consistency, and links the units in one step.

Separate compilation is different from independent compilation. In independent compilation, you invoke ld directly, so there is no consistency checking. Independent compilation is not addressed in this guide.


Working with Units

Pascal provides two types of source files or units: the program unit and the module unit.

Using Program Units

The program unit is the source program with the program header. It has the following syntax:

<program unit> ::= <program heading> <declaration list> <program body>
Each program you write can have only one program unit. The program body is the first code that Pascal executes.

Using Module Units

A module unit is a source program that does not have a program header. It has the following syntax:

<module unit> ::= [ <module heading> ] <declaration list>
The module heading contains the reserved word module followed by an identifier:

<module heading> ::= [ 'module' <identifier> ';' ]
For example:

module sum;

This is a legal module heading. The module heading is optional.


Sharing Variables and Routines Across Multiple Units

Pascal supports three methods of sharing variables and routines between units:

These methods are not mutually exclusive; for example, you can declare a variable as either extern or define in an include file.

The following sections describe these methods.

Compiling without the -xl Option

There are three ways of sharing variables and routines across units when you compile your program without the -xl option.

Sharing Public Variables

If you declare a variable in two or more separate units and the variable is public in both places, that variable is shared between units. Variables are public by default, unless you compile with the -xl option, in which case variables are private by default. In this example, the variable global is public by default, and thus shared between the program and the module.

The program unit, shrvar_prog.p

program shrvar_prog;

var
    global: integer;

procedure proc; external;

begin { program body }
    global := 1;
    writeln('From MAIN, before PROC: ', global);
    proc;
    writeln('From MAIN,  after PROC: ', global)
end. { shrvar_prog }

The module unit, shrvar_mod.p. The assignment of a new value to global and max_array in the procedure proc in shrvar_prog.p is repeated in shrvar_mod.p.

module shrvar_mod;

var
   global: integer;

procedure proc; 

begin		
	writeln('From PROC: ',global);
	global := global + 1
end; { proc }

The commands to compile and execute shrvar_prog.p and shrvar_mod.p

hostname% pc shrvar_prog.p shrvar_mod.p
shrvar_prog.p:
shrvar_mod.p:
Linking:
hostname% a.out 
From MAIN, before PROC: 	1
From PROC             : 	1
From MAIN, after PROC : 	2

Using extern Option to Share Routines

If a program or module calls a procedure not defined in that unit, you must declare it with either the extern or external routine option. For instance, in the previous example, the procedure proc is defined in shrvar_mod.p, but used in shrvar_prog.p. Thus, it is declared as external in shrvar_prog.p. Also, proc must also be defined as public in shrvar_mod.p, which is the default.

Using include Files to Share Variables and Routines

The include file contains the declarations for the program. Placing all program declarations in a single file makes your program more consistent and easier to maintain.

To use this feature, place the number sign character (#) in the first position of a line immediately followed by the word include, and then a file name enclosed in angle brackets (< and >) or double quotation marks ("). The different enclosures (<> and "") affect the search order for files. The syntax for the #include directive is determined by cpp(1).

When the compiler encounters the #include in the input, it inserts the lines from the included file into the input stream.

The program unit, inc_prog.p, which includes the file include.h

program inc_prog;

#include "include.h"

begin { program body}
    global := 1;
    writeln('From MAIN, before PROC: ', global);
    proc;
    writeln('From MAIN,  after PROC: ', global)
end. { inc_prog }

The module unit, inc_mod.p, which also includes the file include.h

module inc_mod;

#include "include.h"

procedure proc;

begin
    writeln('From PROC             : ', global);
    global := global + 1
end; { proc }

The include file, include.h

var
    global : integer;

procedure proc; extern;

The commands to compile and execute inc_prog.p and inc_mod.p

hostname% pc inc_prog.p inc_mod.p 
inc_prog.p:
inc_mod.p:
Linking:
hostname% a.out 
From MAIN, before PROC:     1
From PROC :                 1
From MAIN, after PROC:      2

Using the -xl Option

When you use the -xl option, variables and top-level procedures and functions declared in the program unit default to private. Look at the difference when you compile and execute shrvar_prog.p and shrvar_mod.p with -xl. See the source code in "Sharing Public Variables" on page 81.

The commands to compile and execute shrvar_prog.p and shrvar_mod.p with the -xl option

hostname% pc -xl shrvar_prog.p shrvar_mod.p
shrvar_prog.p:
shrvar_mod.p:
Linking:
hostname% a.out
From MAIN, before PROC: 1
From PROC : 0
From MAIN, after PROC: 1

Without -xl, the variable global in shrvar_mod.p is treated as public; here, global is treated as private. Thus, the assignment:

global := global + 1;
is not reflected in shrvar_prog.p; instead, each file uses its own private copy of global.

The following sections describe five ways of sharing variables and routines across units when you compile your program with -xl.

Using public var Declarations

The following examples uses the public attribute in the var declaration to make global public when you compile your program with -xl.

The program unit, pubvar_prog.p, which declares global as public

program pubvar_prog;

public var
    global: integer;

procedure proc;
    external;

begin
    global := 1;
    writeln('From MAIN, before PROC: ', global);
    proc;
    writeln('From MAIN,  after PROC: ', global)
end. { pubvar_prog }

 

The module unit, pubvar_mod.p, which also declares global as public

module pubvar_mod;

public var
    global : integer;

procedure proc;

begin
    writeln('From PROC             :',global);
    global := global + 1;
end; { proc }

The commands to compile and execute pubvar_prog.p and pubvar_mod.p

hostname% pc -xl pubvar_prog.p pubvar_mod.p
pubvar_prog.p:
pubvar_mod.p:
Linking:
hostname% a.out
From MAIN, before PROC: 1
From PROC : 1 
From MAIN, after PROC: 2

Using the define Variable Attribute

This example makes global public using the define attribute of the variable declaration.

The program unit,
defvar_prog.p

program defvar_prog;

var
    global: extern integer;

procedure proc;
    external;

begin
    global := 1;
    writeln('From MAIN, before PROC: ', global);
    proc;
    writeln('From MAIN,  after PROC: ', global);
end. { defvar_prog }

The module unit, defvar_mod.p, which makes global public using the define attribute

module defvar_mod;

var
    global : define integer;

procedure proc;

begin
    writeln('From PROC             : ',global);
    global := global + 1;
end; { proc }

The commands to compile and execute defvar_prog.p and defvar_mod.p

hostname% pc -xl defvar_prog.p defvar_mod.p
defvar_prog.p:
defvar_mod.p:
Linking:
hostname% a.out
From MAIN, before PROC:     1
From PROC             :     1
From MAIN, after PROC :     2

Using the define Declaration

This example defines global in the module defvar_mod2 using the define declaration. The advantage of using the define declaration over the define variable attribute is that the define declaration can be easily converted to use include files.

The program unit, defvar_prog.p

program defvar_prog;

var
    global: extern integer;

procedure proc;
    external;

begin
    global := 1;
    writeln('From MAIN, before PROC: ', global);
    proc;
    writeln('From MAIN,  after PROC: ', global)
end. { defvar_prog }

The module unit, defvar_mod2.p, which defines global in a define declaration

module defvar_mod2;

var
    global : extern integer;

define
    global;

procedure proc;

begin
    writeln('From PROC             : ',global);
    global := global + 1;
end; { proc }

The commands to compile and execute defvar_prog.p and defvar_mod2.p

hostname% pc -xl defvar_prog.p defvar_mod2.p
defvar_prog.p:
defvar_mod2.p:
Linking:
hostname% a.out
From MAIN, before PROC:     1
From PROC             :     1
From MAIN, after PROC :     2

Using include Files

In the following example, the extern declaration for the variable global is in the include file, inc_prog2.p, and is therefore included in both files. The define declaration in file inc_mod2.p cancels the extern definition.

The program unit, inc_prog2.p

program inc_prog2;

%include "include2.h";

procedure proc; extern;

begin
    global := 1;
    writeln('From MAIN, before PROC: ',global);
    proc;
    writeln('From MAIN,  after PROC: ',global);
end. { proc }

The module unit, inc_mod2.p

module inc_mod2;

define
    global;

%include "include2.h";

procedure proc;

begin
    writeln('From PROC             : ',global);
    global := global + 1;
end; { proc }

The include file, include2.h

var
    global : extern integer;

The commands to compile and execute inc_prog2.p and inc_mod2.p

hostname% pc -xl inc_prog2.p inc_mod2.p
inc_prog2.p:
inc_mod2.p:
Linking:
hostname% a.out
From MAIN, before PROC:  1
From PROC             :  1
From MAIN, after PROC :  2

Using extern

In the previous example, the extern definition for variables is put into an include file and then shared. You can do the same for the extern procedure definition. In doing so, you must also declare the variable with a define declaration in the module that defines the procedure. This declaration nullifies the effect of the extern declaration.

The program unit, ext_prog.p

program ext_prog;

%include "extern.h";

begin
    global := 1;
    writeln('From MAIN, before PROC: ',global);
    proc;
    writeln('From MAIN,  after PROC: ',global);
end. { ext_prog }

The module unit, ext_mod.p

module ext_mod;

define
    global, proc;

%include "extern.h";

procedure proc;

begin
    writeln('From PROC : ',global);
    global := global + 1;
end; { proc }

The include file, extern.h

var
    global : extern integer;

procedure proc; extern;

The commands to compile and execute ext_prog.p and ext_mod.p

hostname% pc -xl ext_prog.p ext_mod.p
ext_prog.p:
ext_mod.p:
Linking:
hostname% a.out
From MAIN, before PROC: 1
From PROC : 1
From MAIN, after PROC: 2


Sharing Declarations in Multiple Units

Using extern and external directives for procedure and function declarations, you can optionally specify the source language of a separately compiled procedure or function. For example, extern fortran directs the compiler to generate calling sequences compatible with the FORTRAN compiler from SunSoft. Then, external c directs the compiler to generate calling sequences compatible with SunSoft C compiler.

For routines declared extern fortran or external fortran, the changes in the calling sequence are as follows:

For routines declared extern c or external c, a warning is generated if you attempt to pass a nested function.

When you compile your program with the -xl option, you can also use nonpascal to declare non-Pascal routines when porting DOMAIN programs written in DOMAIN Pascal, FORTRAN, and C.


Previous Next Contents Index Doc Set Home