# Using the compiler

- Invoking the compiler
- XDS compilers operation modes
- Files generated during compilation
- Control file preprocessing
- Project files
- Make strategy
- Smart recompilation
- Template files

## Invoking the compiler

The XDS Modula-2 and Oberon-2 compilers are combined together with the make subsystem and an Oberon-2 browser into a single utility, `xc`. When invoked without parameters, the utility outputs a brief help information.

`xc` is invoked from the command line of the following form

`` `xc``{ mode | option | name }`

where `name`, depending on the operation `mode` can be a module name, a source file name, or a project file name. See XDS compilers operation modes for a full description of operation modes.

`option` is a compiler setup directive (See Options). All options are applied to all operands, notwithstanding their relative order on the command line. On some platforms, it may be necessary to enclose setup directives in quotation marks:

`` `xc` `hello.mod '-checkindex+'`

See Chapter Compiler options and equations for the list of all compiler options and equations.

- Precedence of compiler options

### Precedence of compiler options

The `xc` utility receives its options in the following order:

1. from a configuration file xc.cfg (See Configuration file)
2. from the command line (See XDS compilers operation modes)
3. from a project file (if present) (See Project files)
4. from a source text (not all options can be used there) (See Source code directives)

At any point during operation, the last value of an option is in effect. Thus, if the equation OBERON was set to .ob2 in a configuration file, but then set to .o2 on the command line, the compiler will use .o2 as the default Oberon-2 extension.

## XDS compilers operation modes

XDS Modula-2/Oberon-2 compilers have the following operation modes:

Mode | Meaning
COMPILE | Compile all modules given on the command line
PROJECT | Make all projects given on the command line
MAKE | Check dependencies and recompile
GEN | Generate makefile for all projects
BROWSE | Extract definitions from symbol files
HELP | Print help and terminate

Both the PROJECT and MAKE modes have two optional operation submodes: BATCH and ALL. Two auxiliary operation submodes --- options and EQUATIONS can be used to inspect the set of compiler options and equations and their values.

On the command line, the compiler mode is specified with the "`=`" symbol followed by a mode name. Mode names are not case sensitive, and specifying an unique portion of a mode name is sufficient, thus

`=PROJECT` is equivalent to `=p`
`=BROWSE` is equivalent to `=Bro`

Operation modes and options can be placed on the command line in arbitrary order, so the following two command lines are equivalent:

`` `xc``=make hello.mod =all -checknil+`
`` `xc``-checknil+ =a =make hello.mod`

- COMPILE mode
- MAKE mode
- PROJECT mode
- GEN mode
- BROWSE mode
- ALL submode
- BATCH submode
- OPTIONS submode
- EQUATIONS submode

### COMPILE mode

`` `xc``[=compile] { FILENAME | OPTION }`

COMPILE is the default mode, and can be invoked simply by supplying `xc` with a source module(s) to compile. If `xc` is invoked without a given mode, COMPILE mode is assumed. In order to determine which compiler should be used, `xc` looks at the extensions of the given source files. The default mapping of extensions is given below :

.mod | - | Modula-2 implementation module
.def | - | Modula-2 definition module
.ob2 | - | Oberon-2 module

For example:

`` `xc` `hello.mod`

will invoke the Modula-2 compiler, whereas:

`` `xc` `hello.ob2`

will invoke the Oberon-2 compiler.

The user is able to reconfigure the extension mapping (See Filename extensions). It is also possible to override it from the command line using the options M2 and O2:

`` `xc` `hello.mod +o2 (* invokes O2 compiler *)`
`` `xc` `hello.ob2 +m2 (* invokes M2 compiler *)`

Note: In the rest of this manual, the COMPILE mode also refers to any case in which the compiler compiles a source file, regardless of the actually specified mode (which can be COMPILE, MAKE, or PROJECT). For instance, an option or equation, which is stated to affect the compiler behaviour in the COMPILE mode, is relevant to MAKE and PROJECT modes as well.

### MAKE mode

`` `xc``=make [=batch] [=all] { FILENAME | OPTION }`

In the MAKE mode the compiler determines module dependencies using `IMPORT` clauses and then recompiles all necessary modules. Starting from the files on the command line, it tries to find an Oberon-2 module or a definition and implementaion module for each imported module. It then does the same for each of the imported modules until all modules are located. Note that a search is made for source files only. If a source file is not found, the imported modules will not be appended to the recompile list. See section Make strategy for more details.

When all modules are gathered, the compiler performs an action according to the operation submode. If the BATCH submode was specified, it creates a batch file of all necessary compilations, rather than actually compiling the source code.

If the ALL submode was specified, all gathered files are recompiled, otherwise XDS recompiles only the necessary files. The smart recompilation algorithm is described in Smart recompilation.

Usually, a Modula-2 program module or an Oberon-2 top-level module is specified on the command line. In this case, if the LINK equation is set in either configuration file or `xc` command line, the linker will be invoked automatically in case of successful compilation. This feature allows you to build simple programs without creating project files.

### PROJECT mode

`` `xc``=project [=batch] [=all] { PROJECTFILE | OPTION }`

The PROJECT mode is essentially the same as the MAKE mode except that the modules to be `made' are provided in a project file. A project file specifies a set of options and a list of modules. See Project files for further details. As in the MAKE mode, ALL and BATCH submodes can be used.

If a file extension of a project file is omitted, XDS will use an extension given by the equation PRJEXT (.prj by default).

It may be necessary to compile a single module in the environment specified in a project file. It can be accomplished in the COMPILE operation mode using with the PRJ equation:

`` `xc``-prj=myproject MyModule.mod`

See also

- MAKE operation mode: MAKE mode
- Make strategy: Make strategy
- Smart recompilation: Smart recompilation

### GEN mode

`` `xc``=gen { PROJECTFILE | OPTION }`

The GEN operation mode allows one to generate a file containing information about your project. The most important usage is to generate a linker response file (See Building a program).

This operation mode can also be used to obtain additional information about your project, e.g. a list of all modules, import lists, etc.

A so-called template file, specified by the TEMPLATE equation, is used in this mode. A template file is a text file, some lines of which are marked with a certain symbol. All the lines which are not marked are copied to the output file verbatim. The marked lines are processed in a special way. See Template files for more information.

The compiler creates a file with a name specified by the equation MKFNAME. If the equation is empty, the project file name is used. A file name is then concatenated with the extension specified by the equation MKFEXT.

### BROWSE mode

`` `xc``=browse { MODULENAME | OPTION }`

The BROWSE operation mode allows one to generate a pseudo definition module for an Oberon-2 module. In this mode, the compiler reads a symbol file and produces a file which contains declarations of all objects exported from the Oberon-2 module, if a format resembling Modula-2 definition modules.

The configuration option BSDEF specifies the extension of a generated file. If this option is not set, then the default extension (.odf) will be used.

Options BSCLOSURE and BSREDEFINE can be used to control the form of a generated file. Note: the BSTYLE equation (described in Creating a definition) is ignored in this operation mode, and the browse style is always set to DEF.

The MAKEDEF option (See Creating a definition) provides an alternative method of producing pseudo definition modules, preserving so-called exported comments if necessary.

### ALL submode

In both PROJECT and MAKE modes, the compiler checks the time stamps of the files concerned and recompiles only those files that are necessary (See Smart recompilation). If the ALL submode was specified, the time stamps are ignored, and all files are compiled.

### BATCH submode

In the BATCH submode, the compiler creates a batch file of all necessary compilations, rather than actually calling the compilers and compiling the source code.

A batch file is a sequence of lines beginning with the compiler name, followed by module names to recompile.

The compiler creates a batch file with a name determined by either:

1. The compiler option BATNAME
2. The project file name (if given)
3. The name out (if the name could not be determined by the above).

The name is then concatenated with the batch file extension specified by the equation BATEXT (.bat by default).

See also

- option LONGNAME (Options)
- equation BATWIDTH (Equations)

### OPTIONS submode

The OPTIONS submode allows you to inspect the values of options which are set in the configuration file, project file and on the command line. It can be used together with COMPILE, MAKE, and PROJECT modes.

The following command line prints (to the standard output) the list of all defined options, including all pre-declared options, all options declared in the configuration file, in the project file `my.prj` and on the command line (`xyz` option):

`` `xc``=options -prj=my.prj -xyz:+`

In the PROJECT mode options are listed for each project file given on the command line.

See also the EQUATIONS submode.

### EQUATIONS submode

The EQUATIONS submode allows you to inspect the values of equations which are set in the configuration file, project file and on the command line. It can be used together with COMPILE, MAKE, and PROJECT modes.

See also the OPTIONS submode.

## Files generated during compilation

When applied to a file which contains a module name, the compilers produce the following files.

- Modula-2 compiler
- Oberon-2 compiler

### Modula-2 compiler

When applied to a definition module, the Modula-2 compiler produces a symbol file(name.sym). The symbol file contains information required during compilation of a module which imports the module name.

When applied to an implementation module or a top level module, the Modula-2 compiler produces an object file (name.o).

### Oberon-2 compiler

For all compiled modules, the Oberon-2 compiler produces a symbol file (name.sym) and an object file (name.o). The symbol file(name.sym) contains information required during compilation of a module which imports the module name. If the compiler needs to overwrite an existing symbol file, it will only do so if the CHANGESYM option is set ON.

##### Examples

Command line | Generated files
`xc Example.def` | `Example.sym`
`xc Example.mod` | `Example.o`
`xc Win.ob2 +CHANGESYM` | `Win.sym`
| `Win.o`

## Control file preprocessing

An XDS compiler may read the following control files during execution:

- a redirection file
- a configuration file
- a project file
- a template file

All these files are preprocessed during read according to the following rules:

A control file is a plain text file containing a sequence of lines. The backslash character (`"\"`) at the end of a line denotes its continuation.

The following constructs are handled during control file preprocessing:

- macros of the kind `$(`name`)`. A macro expands to the value of the equation name or, if it does not exist, to the value of the environment variable name.
- the base directory macro (`$!`) This macro expands to the directory in which the file containing it resides.
- a set of directives, denoted by the exclamation mark (`"!"`) as a first non-whitespace character on a line.

A directive has the following syntax (all keywords are case independent):

    Directive = "!" "NEW" SetOption | SetEquation
              | "!" "SET" SetOption | SetEquation
              | "!" "MESSAGE" Expression
              | "!" "IF" Expression "THEN"
              | "!" "ELSIF" Expression "THEN"
              | "!" "ELSE"
              | "!" "END".
    SetOption   = name ( "+" | "-" ).
    SetEquation = name "=" string.

The `NEW` directive declares a new option or equation. The `SET` directive changes the value of an existent option or equation. The `MESSAGE` directive prints `Expression` value to the standard output. The `IF` directive allows to process or skip portions of files according to the value of `Expression`. `IF` directives may be nested.

    Expression  = Simple [ Relation Simple ].
    Simple      = Term { "+" | OR Term }.
    Relation    = "=" | "#" | "<" | ">".
    Term        = Factor { AND Factor }.
    Factor      = "(" Expression ")".
                | String
                | NOT Factor
                | DEFINED name
                | name.
    String      = "'" { character } "'"
                | '"' { character } '"'.

An operand in an expression is either string, equation name, or option name. In the case of equation, the value of equation is used. In the case of option, a string `"TRUE"` or `"FALSE"` is used. The `"+"` operator denotes string concatenation. Relation operators perform case insensitive string comparison. The `NOT` operator may be applied to a string with value `"TRUE"` or `"FALSE"`. The `DEFINED` operator yields `"TRUE"` if an option or equation `name` is declared and `"FALSE"` otherwise.

See also section The system module COMPILER.

## Project files

A project file has the following structure:

`{SetupDirective}`
`{!module {FileName}}`

Setup directives define options and equations that all modules which constitute the project should be compiled with. See also Options and Control file preprocessing.

Every line in a project file can contain only one setup directive. The character "`%`" indicated a comment; it causes the rest of a line to be discarded. Note: the comment character can not be used in a string containing equation setting.

Each `FileName` is a name of a file which should be compiled, linked, or otherwise processed when a project is being built, e.g. a source file, an additional library, a resource file (on Windows), etc. The compiler processes only Modula-2 and Oberon-2 source files. The type of a file is determined by its extension (by default Modula-2/Oberon-2 source files extension is assumed). Files of other types are taken into account only when a template file is processed (see Template files).

The compiler recursively scans import lists of all specified Modula-2/Oberon-2 source modules and builds the full list of modules used in the project. Thus, usually, a project file for an executable program would contain a single `!module` directive for the file which contains the main program module and, optionally, several `!module` directives for non-source files.

At least one `!module` directive should be specified in a project file.

A project file can contain several LOOKUP equations, which allow you to define additional search paths.

XDS compilers give you complete freedom over where to set options, equations and redirection directives. However, it is recommended to specify only those settings in the configuration and redirection files which are applied to all your projects, and use project files for all project-specific options and redirection directives.

Figure 2. A Sample Project File

        -lookup = *.mod = mod
        -lookup = *.sym = sym; $(XDSDIR)/sym/C
        % check project mode
        !if not defined mode then
          % by default use debug mode
          !new mode = debug
        !end
        % report the project mode
        !message "Making project in the " + mode + " mode"
        % set options according to the mode
        !if mode = debug then
           - gendebug+
           - checkrange+
        !else
           - gendebug-
        !fi
        % specify template file
        - template = $!/templates/watcom.tem
        !module hello
        !module hello.res

Given the sample project file shown on Figure 2. A Sample Project File, the compiler will search for files with `.mod` and `.sym` extensions using search paths specified in the project file before paths specified in a redirection file.

A project file is specified explicitly in the PROJECT and GEN operation modes. In these modes, all options and equations are set and then the compiler proceeds through the module list to gather all modules constituting a project (See Make strategy).

In the MAKE and COMPILE operation modes, a project file can be specified using the PRJ equation. In this case, the module list is ignored, but all options and equations from the project file are set.

The following command line forces the compiler to compile the module `hello.mod` using options and equations specified in the project file `hello.prj`:

`` `xc` `hello.mod -prj=hello.prj`

## Make strategy

This section concerns MAKE, PROJECT, and GEN, operation modes. In these modes, an XDS compiler builds a set of all modules that constitute the project, starting from the modules specified in a project file (PROJECT and GEN) or on the command line (MAKE).

The MAKE mode is used in the following examples, but the comments also apply to the PROJECT and GEN modes.

First, the compiler tries to find all given modules according to the following strategy:

- If both filename extension and path are present, the compiler checks if the given file exists.

  `` `xc``=make mod`/`hello.mod`

- If only an extension is specified, the compiler seeks the given file using search paths.

  `` `xc``=make hello.mod`

- If no extension is specified, the compiler searches for files with the given name and the Oberon-2 module extension, Modula-2 implementation module extension, and Modula-2 definition module extension.

  `` `xc``=make hello`

  An error is raised if more than one file was found, e.g. if both `hello.ob2` and `hello.mod` files exist.

Starting from the given files, the compiler tries to find an Oberon-2 source module or Modula-2 definition and implementation modules for each imported module. It then tries to do the same for each of the imported modules until all the possible modules are located. For each module, the compiler checks correspondence between the file name extension and the kind of the module.

## Smart recompilation

In the MAKE and PROJECT modes, if the ALL submode was not specified, an XDS compiler performs smart recompilation of modules which are inconsistent with the available source code files. The complier uses file modification time to determine which file has been changed. For each module the decision (to recompile or not) is made only after the decision is made for all modules on which it depends. A source file is (re)compiled if one or more of the following conditions is true:

Modula-2 definition module

  - the symbol file is missing
  - the symbol file is present but its modification date is earlier than that of the source file or one of the imported symbol files

Modula-2 implementation module

  - the code file is missing
  - the code file is present but the file modification date is earlier than that of the source file or one of the imported symbol files (including its own symbol file)

Modula-2 program module

  - the code file is missing
  - the code file is present but the file modification date is earlier than that of the source file or one of the imported symbol files

Oberon-2 module

  - the symbol file is missing
  - the symbol file is present but the modification date is earlier than that of one of the imported symbol files
  - the code file is missing
  - the code file is present but the file modification date is earlier than that of the source file or one of the imported symbol files

When the VERBOSE option is set ON, the compiler reports a reason for recompilation of each module. Note: if an error occured during compilation of a Modula-2 definition module or an Oberon-2 module, all its client modules are not compiled at all.

## Template files

A template file is used to build a "makefile" in the PROJECT and GEN operation modes, if the option MAKEFILE is ON "MAKEFILE" is a historical name; a linker or library manager response file may be built as well..

The compiler copies lines from a template file into the output file verbatim, except lines marked as requiring further attention. A single character (attention mark) is specified by the equation ATTENTION (default is '!')

A template file is also subject to preprocessing.

A marked line (or template) has the following formatThe same syntax is used in the LINK equation.:

        Template  = { Sentence }.
        Sentence  = Item { "," Item } ";" | Iterator.
        Item      = Atom | [ Atom | "^" ] "#" [ Extension ].
        Atom      = String | name.
        String    = '"' { character } '"'
                  | "'" { character } "'".
        Extension = [ ">" ] Atom.
        Iterator  = "{" Set ":" { Sentence } "}".
        Set       = { Keyword | String }
        Keyword   = DEF | IMP | OBERON | MAIN
                  | C | HEADER | ASM | OBJ.

`name` should be a name of an equation. Not more than three items may be used in a sentence. A first item in a sentence is a format string, while others are arguments.

The XDS distribution contains a template file `xc.tem` which can be used to produce a linker response file.

- Using equation values
- File name construction
- Iterators
- Examples

### Using equation values

In the simplest form, a template line may be used to output a value of an equation. For example, if the template file contains the line

`! "The current project is %s.\n",prj;`

and the project `prj/test.prj` is processed, the output will contain the line

`The current project is prj``/test.prj.`

Note: the line

`! prj;`

is valid, but may produce unexpected results under systems in which the backslash character ("`\`") is used as a directory names separator (e.g. OS/2 or Windows):

`prj est.prj`

because `"\t"` in a format string is replaced with the tab character. Use the following form instead:

`! "%s",prj;`

### File name construction

The `"#"` operator constructs a file name from a name and an extension, each specified as an equation name or literal string. A file is then searched for according to XDS search paths and the resulting name is substituted. For example, if the file `useful.lib` resides in the directory '../mylibs' and the redirection file contains the following line:

`*.lib = /xds/lib;../mylibs`

the line

`! "useful"#"lib"`

will produce

`../mylibs/useful.lib`

If the modifier `">"` is specified, the compiler assumes that the file being constructed is an output file and creates its name according to the strategy for output files (See Redirection file and the OVERWRITE option).

The `"#"` operator is also used to represent the current value of an iterator. The form in which a name or extension is omitted can be used in an iterator only.

The form `"^#"` may be used in a second level iterator to represent the current value of the first level iterator.

### Iterators

Iterators are used to generate some text for all modules from a given set. Sentences inside the first level of braces are repeated for all modules of the project, while sentences inside the second level are repeated for all modules imported into the module currently iterated at the first level. A set is a sequence of keywords and strings. Each string denotes a specific module, while a keyword denotes all modules of specific kind.

The meaning of keywords is as follows:

Keyword | Meaning
`DEF` | Modula-2 definition module
`IMP` | Modula-2 implementation module
`MAIN` | Modula-2 program module or Oberon-2 module marked as MAIN
`OBERON` | Oberon module
`ASM` | assembler source text
`OBJ` | object file

A keyword not listed above is treated as filename extension. Sentences are repeated for all files with that extension which are explicitly specified in the project file using `!module` directives (see Project files). This allows, for instance, additional libraries to be specified in a project file:

    sample.prj:

        -template = mytem.tem
        !module Sample.mod
        !module mylib.lib

    mytem.tem:
          .  .  .
        ! "%s","libxds"#"lib"
        ! { lib: "+%s",#; }
        ! "\n"
          .  .  .

    generated file:
          .  .  .
        d:\xds\lib\x86\libxds.lib+mylib.lib
          .  .  .

### Examples

Consider a sample project which consists of a program module `A`, which imports modules `B` and `C`, and `B`, in turn, imports `D` (all modules are written in Modula-2):

                    A
                   / \
                  B   C
                  |
                  D

The following examples illustrate template files usage:

This template line lists all project modules for which source files are available:

`! { imp oberon main: "%s ",#; }`

For the sample project, it would generate the following line:

`A.mod B.mod C.mod D.mod`

To output both definition and implementation modules, the following lines may be used:

`! { def : "%s ",#; }`
`! { imp oberon main: "%s ",#; }`

The output would be:

`B.def C.def D.def A.mod B.mod C.mod D.mod`

The last template line may be used to list all modules along with their import:

`! { imp main: "%s\n",#; { def: " %s\n",#; } }`

The output:

        A.mod
          B.def
          C.def
        B.mod
          D.def
        C.mod
        D.mod