Go to the first, previous, next, last section, table of contents.

# GPI files -- GNU Pascal Interfaces

This file documents the mechanism how information is transferred from the exporting Modules and Units to the Program, Module or Unit which imports (uses) the information.

The GPI mechanism is not (yet :-) as stable as it should be. If you encounter problems with your Modules or Units, please do the following:

- To work around, include the module interface (or the whole Unit) via a preprocessor directive #include "myfile.pas" or (*$i MyFile *) into the source of the main program, *prior* to the "Program foo" headline. Do not use #include or $i in a Module using another Module; use them in the main program, instead -- and in the correct order.
- To help the problem being solved, please report the bug in the following way:
  - Construct the *smallest possible* combination of Modules (Units) and Programs which still produces the error.
  - Send the bug report and your (small!) example programs via e-mail to Peter Gerwinski <peter.gerwinski@uni-esen.de>.
- To solve the problem by yourself (requires experience with `C'), get the source of the GNU Pascal Compiler (GPC) from ftp://kampi.hut.fi/jtv/gnu-pascal, make sure that you can compile it on your system and go on reading.

## The GPI mechanism

A GPI file contains a precompiled GNU Pascal Interface. "Precompiled" means in this context that the Interface already has been parsed (i.e the front-end has done its work), but that no assembler output has been produced yet.

The GPI file format is an implementation-dependent (but not too implementation-dependent ;-) file format for storing GNU Pascal Interfaces to be exported--Extended Pascal and PXSC module interfaces as well as interface parts of Borland Pascal Units compiled with GNU Pascal.

To see what information is stored in or loaded from a GPI file, run GPC with an additional command-line option `--debug-gpi`. Then, GPC will write a human-readable version of what is being stored/loaded to stderr.

While parsing an Interface, GPC stores the names of exported objects in tree lists--in gpc-parse.y, the bison (yacc) source of GPC's parser, search for `handle_autoexport`. At the end of the Interface, everything is stored in one or more GPI files. This is called in gpc-parse.y--search for `create_gpi_files ()`.

Everything else is done in gpc-module.c. Here you can find the source of create_gpi_files () which documents the file format: First, a header of 33 bytes containing the string `GNU Pascal Module/Unit Interface\n` is stored, then the name of the primary source file of the module as a string, then the name of the exported interface as a tree node (see below), after that all exported names in the order as they were stored while parsing.

The names and the objects (i.e. constants, data types, variables and functions) they refer to are internally represented as so-called tree nodes as defined in the files tree.h and tree.def from the GCC source (i.e. the source of the GNU C compiler). The names are stored as `IDENTIFIER_NODE`s, their meanings as `IDENTIFIER_GLOBAL_VALUE`s of these nodes. The main problem when storing tree nodes is that they form a complicated tree in memory with a lot of circular references making it hard to decide which information must be stored and which mustn't.

The functions load_tree and store_tree are intended to load/store a tree node in a GPI file.

Each tree node has a `TREE_CODE` indicating what kind of information it contains. Each different tree node must be stored in a different way. See the source of `load_tree` and `store_tree` for details.

Most tree nodes contain pointers to other tree nodes; therefore `load_tree` and `store_tree` are recursive functions. The `--debug-gpi` debugging informations contains the recursion level in parantheses, e.g. `loaded (2):` means that the loaded information was requested by a pointer contained in a tree node requested by a pointer contained in a tree node representing an exported symbol.

Since this recursion can be circular (think of a record containing a pointer to a record of the same type), we must resolve references to tree nodes which already have been loaded. For this reason, and for saving disk space, I have introduced a `gpi_contents` list containing pointers to all nodes so far loaded from / stored in the GPI file under consideration. When storing a node which already is in the gpi_contents list, a (normally invalid) `TREE_CODE` of 255 ``(0xFF)'` followed by the (int) index of the node in the `gpi_contents` list is stored instead. Like this, the reference uses 1 byte plus the size of an int (normally 4) in the GPI file. In the debugging information, this method of storing/loading is indicated as `via gpi_contents`.

There are some special tree_nodes (e.g. `integer_type_node` or `NULL_TREE`) which are used very often. I have assigned (normally invalid) unique `TREE_CODES` for them, so they can be stored in a single byte.

That's it. Now you should be able to "read" GPI files using GPC's `--debug-gpi` option. If you encounter a case where the loaded information differs too much from the stored information, you have found a bug--congratulations! What "too much" means, depends on the object being stored in / loaded from the GPI file. Remind that the order things are loaded from a GPI file is the reversed order things are stored when considering different recursion levels, but the same order when considering ths same recursion level.

Go to the first, previous, next, last section, table of contents.