Previous Next Contents Index Doc Set Home


Program Construction and Management

4


This chapter is an introduction to the methods generally used to construct and manage programs using Pascal. It describes units and libraries in two separate sections:

Units

page 71

Libraries

page 78


Units

For many reasons, it is often inconvenient to store a program in a single file, as in the case of a very large program.

You can break up a program in several ways. Perhaps the simplest way is to use an include file. An include file is a separate file that is copied in by the compiler when it encounters an include compiler directive. For example, in the following program:

program include (output);
#include "includefile"

the line #include "includefile" is a compiler directive to cpp(1), the Pascal compiler's preprocessor. The directive instructs cpp(1) to find the file includefile and copy it into the stream before continuing.

The actual includefile looks like this:

begin
	writeln ('Hello, world.')
end.

In this example, the include file contains the entire program. In reality, an include file probably contains a set of variable or procedure declarations. include files are often used when a set of declarations needs to be shared among a number of programs.

However, suppose your program is very large and takes a long time to compile. Using include files may make editing more convenient, but when you make a change in one part of your program, you still must recompile the entire program. As another example, suppose you want to be able to share compiled code with other people, but for reasons of security or convenience, do not want to share the source code.

Both of these problems are solved by separately compiled units, generally called units. A unit is a part of a program stored in its own file and linked with the rest of the program after compilation.

Using Program Units and Module Units

There are two kinds of units:

Here is an example:

program program_unit (output);
procedure say_hello; extern;
begin
	say_hello
end.

The body of the procedure say_hello is not defined in this program unit, but the program unit does contain a declaration of the interface to the procedure. The keyword extern declares that say_hello is declared in a module unit.1

Here is an example:

module module_unit;
procedure say_hello;
begin
	writeln ('Hello, world.')
end;

Every program must have one and only one program unit; a program can have any number of module units. Any unit can call procedures declared in any other unit; each unit must have external declarations for every procedure it uses that is not defined in that unit.

A module unit can also be used as a library, that is, as a collection of useful routines that is shared among a number of programs.

Compiling with Units

Consider the units given in the previous section, "Using Program Units and Module Units." You can compile and link these units on a single line by executing the following command, which then produces the executable, a.out.

hostname% pc program_unit.p module_unit.p
You can also separate the compilation and linking or loading steps, as follows:

hostname% pc program_unit.p -c
hostname% pc module_unit.p -c
hostname% pc program_unit.o module_unit.o
In this case, you call pc on each unit with the "compile only" option (-c), which produces an object file with the extension .o. When you use this option, the compiler driver does not call the linker, ld. You then call pc a second time, giving the names of the object files, and pc calls pc3 to check for name and type conflicts before calling the linker.

Calling the linker or loader ld(1) directly does not have the same effect as calling pc; when you call ld(1) directly, the files are linked and loaded, but they are not checked for conflicts.

Using Units and Header Files

A complex program may have many routines defined in modules. Each routine must have a declaration (for example, procedure proc; extern;) in each file that calls the routine. The easiest way to be sure that you have a correct and consistent set of declarations is to create a header file.

A header file is a file that contains a set of declarations, nothing else. You use a header file by using an include directive to include the header file in the compilation.

For example, here is a modified version of the program, program_unit2, that uses a header file:

program program_unit2 (output);
#include "header.h"
begin
	say_hello
end.

In this case, the content of header.h is very simple:

procedure say_hello; extern;

In a real program, header.h would probably contain many declarations and would be included in several modules. Aside from routine declarations, header files often contain constant, type, and variable declarations.

Sharing Variables Between Units

Variables that are global across a unit (that is, not declared locally in a routine) can be public or private. A public variable can be shared by any unit that is linked to the unit that declares the variable. A private variable cannot be shared.

You can use the public and private reserved words to declare that a var section declares public or private variables. For example:

program program_unit3 (output);
public var
	x : integer;
private var
	y : integer;

When you do not use public or private, variables are public by default. However, when you compile with the -xl option, variables are private by default.

To share a public variable, simply declare it in each unit where you want to share it. As long as the variable is public, each reference to that variable accesses the same data.

Here is a program unit that declares a variable:

program program_unit3 (output);
var
	x : integer;

procedure say_hello; external;

begin
	for x := 1 to 5 do say_hello
end.

Here is a module unit that declares a variable with the same name:

module module_unit3;
var
	x : integer;

procedure say_hello;

begin
	writeln ('Hello, world for the', x, ' time.')
end;

By default, both definitions of variable x are public. Thus, when you compile and link the program and module units, references to x refer to the same variable, as follows:

hostname% pc program_unit3.p module_unit3.p
program_unit.p:
module_unit.p:
Linking:
hostname% a.out
Hello, world for the 1 time.
Hello, world for the 2 time.
Hello, world for the 3 time.
Hello, world for the 4 time.
Hello, world for the 5 time.

If you compile the program giving the -xl option, the variables are private by default, as follows:

hostname% pc -xl program_unit.p module_unit.p
program_unit.p:
module_unit.p:
Linking:
hostname% a.out
Hello, world for the 0 time.
Hello, world for the 0 time.
Hello, world for the 0 time.
Hello, world for the 0 time.
Hello, world for the 0 time.

You can get the same effect by explicitly declaring the variable in a private var section. Similarly, when you use -xl, you can create public variables by declaring them in a public var section.

As with routine declarations, it is often a good idea to declare public variables in an include file. Doing so makes it easier to keep your declarations consistent.

There are other methods for making variables visible to different units. See Chapter 5, "Separate Compilation," for more information.


Libraries

You can use a module unit as a library of useful functions. The simplest way to do so is to create a source file containing the definitions of your library routines and then compile it using the -c option. You can then link the resulting .o file to any number of files. For convenience, you probably should create a header file containing the routine declarations for the library.

A simple library as described above has two problems:

On the other hand, it would be inconvenient to have to name many library modules on the command-line when you link your program. Thus, it would be helpful to be able to combine a number of library modules.

Both problems have solutions. First, you can combine or archive modules together. Secondly, you can create a shared library.

See the Solaris documentation on the linker and libraries for information on creating archived and shared libraries.


Previous Next Contents Index Doc Set Home


1 A statement that shows the interface of a routine is called a declaration, because it declares the name and parameters of the routine. The set of statements that shows the entire routine, including the body, is called the definition of the routine. There can be only one definition for a given routine, but every routine must be declared in every module or program unit that uses it.