Scroll to navigation

gm2(1) GNU Modula-2 gm2(1)

NAME

gm2 - The GNU Modula-2 compiler.
gm2l - GNU Modula-2 linker subcomponent.
gm2lcc - GNU Modula-2 linker subcomponent.
gm2lgen - GNU Modula-2 linker subcomponent.
gm2lsub - GNU Modula-2 linker subcomponent.
gm2m - GNU Modula-2 makefile generator.
h2def - Transform a 'C' header file into a Modula-2 definition file.

DESCRIPTION

NOTE: This document manual page may be out of date, check the texinfo file.

GNU Modula-2 is a front end for GCC (the GNU Compiler Collection). GCC contains a retargetable C compiler which has been ported to a large number of architectures and operating systems. GNU Modula-2 utilizes the back end of GCC and replaces the C language front end with a Modula-2 one.

The GNU Modula-2 front end can perform a substantial amount of static analysis of the source code (see `-Wpedantic', `-Wpedantic-param-names', `-Wstudents', and `-Wpedantic-cast').

Finally runtime checking has been implemented and can check: bounds of subranges and array indexes, functions execute a 'RETURN' statement, a pointer does not dereference a 'NIL' pointer value, and that the expression within a 'CASE' statement is correctly matched.

There are currently three sets of libraries. The 'Programming in Modula-2' libraries, the 'University of ULM libraries' and the ISO libraries. The ISO libraries are still being written, however all definition modules for the three library sets are contained within this document.

GNU Modula-2 also has the advantage of being closely tied to GCC (the GNU Compiler Collection.) Not only does this produce excellent code and excellent architectural and operating system coverage, but it also utilizes many of the GCC features. For example, GNU Modula-2 can invoke the C preprocessor to manage conditional compilation; inlining of `SYSTEM' procedures, intrinsic functions, memory copying routines are also exploited; access to assembly language using GCC syntax is also provided. GNU Modula-2 also supports sets of any ordinal type (memory permitting).

GNU Modula-2 Reads source code from files containing either: (1) definition modules, (2) implementation modules, (3) main body module. Definition modules usually use the standard extension '.def'. Whereas, implementation and main body modules use the standard extension '.mod'. When using legacy code which worked with a different compiler, other extensions may have been used. GNU Modula-2 can be told to search for those extension first , before defaulting to the standard extensions. For example, use the command line options: '-fdef=.d2 -fmod=.m2'.

GNU Modula-2 imports definition modules by reading the definition module file every time (similar to C including .h header files). Traditional Modula-2 compilers would require the compilation of every definition module into a symbol file before any import of symbols from that definition module.

Purpose

It is expected that the primary purpose of GNU Modula-2 will be to compile legacy code. Currently there are only a few commercial Modula-2 compilers being actively maintained. Code which was written ten or fifteen years ago may still be compiled by older commercial (possibly unmaintained) compilers.

While the 32 bit x86 remains these compilers presumably can be run in compatibility mode (some compilers only produced 16 bit code). Time is running out as the computing industry is switching to 64 microprocessors. While x86 emulation or 16 bit backwards compatibility is always possible it has some serious drawbacks.

In order for the older source to run natively the source code will either have to be translated into another high level language or alternatively a Modula-2 compiler which can target these new generation of microprocessors will have to be acquired.

Current State

Currently GNU Modula-2 (0.49) implements all PIM dialects of the language, eventually GNU Modula-2 will be fully compliant with ISO Modula-2. It has been built on i[3456]86 GNU/Linux, i[3456]86 BSD, Opteron LP64 GNU/Linux and sparc GNU/Linux systems. It has also been built as a cross compiler for MinGW and StrongARM GNU/Linux.

GNU Modula-2 builds and passes all its regression tests on Debian Pure 64 (LP64 architecture), 64 bit Solaris, 32 bit x86 GNU/Linux (Suse 9.1, Debian, stable and unstable) and 32 bit x86 FreeBSD.

Work is underway to build and test it on DARWIN/i386, and DARWIN/powerpc.

There is even a project to extend GNU Modula-2 with object oriented constructs similar to Objective-C called 'Objective Modula-2' , or objM2 for short.

OPTIONS

This section describes the compiler's command line options specific to GNU Modula-2, although many of the standard options are documented here. For details on generic options see the manual page for gcc (The GNU C Compiler), and other members of the GNU Compiler Collection.

Overall Options

--help
Print (on the standard output) a description of the command line options understood by gm2 If the -v option is also specified then --help will also be passed on to the various processes invoked by gm2, so that they can display the command line options they accept. If the -f option is also specified then command line options which have no documentation associated with them will also be displayed.

--target-help
Print (on the standard output) a description of target specific command line options for each tool.

--version
Display the version number and copyrights of the invoked GCC.

-c
Compile and assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.

-E
Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output.

-g
Insert debugging symbols into the object files, and executable. NOTE: When using the debugger, it may be useful to not optimize at a high level.

-Ipath
Adds an include path. The GNU Modula-2 compiler needs to import symbols from definition module files. It include's the definition file, rather than reading a symbol file.

-On
Set the optimization level and kind. -Os optimizes for size (desiring small executables). -O,-O1,-O2, ..., -O6 optimize for speed, with increasingly powerful techniques, such as loop unrolling and reordering of code. When debugging, only use -O or at the most -O1.

-o file
Place output in file file. This applies regardless to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file, or preprocessed C code.

Since only one output file can be specified, it does not make sense to use -o when compiling more than one input file, unless you are producing an executable file as output.

If -o is not specified, the default is to put an executable file in a.out, the object file for source.suffix in source.o, its assembly language file in source.s, and all preprocessed C source on standard output.

-S
Preprocess and compile the source code, but to not assemble. Do not delete the temporary assembly language file. Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembly language code file for each non-assembler input file specified.

-v
Verbosely display all calls to subsidiary programs, such as the C preprocessor, the GNU Modula-2 compiler and linker. Also print the version of the compiler, and which specs file it is using.

-fcpp
Preprocess the source with `cpp -lang-asm -traditional-cpp'. If -fcpp is supplied then all definition modules and implementation modules which are parsed will be preprocessed by `cpp'.

-fdef=
Recognize the specified suffix as a definition module filename. The default definition module filename suffix is `.def'. If this option is used GNU Modula-2 will still fall back to this default if a requested definition module is not found.

-fmod=
Recognize the specified suffix as implementation and module filenames. The default implementation and module filename suffix is `.mod'. If this option is used GNU Modula-2 will still fall back to this default if it needs to read an implementation module and the specified suffixed filename does not exist. Both this option and -fdef= also work with the -fmakeall option.

-fextended-opaque
Allows opaque types to be implemented as any type. This is a GNU Modula-2 extension and it requires that the implementation module defining the opaque type is available so that it can be resolved when compiling the module which imports the opaque type.

-fmakeall
Generate a temporary makefile and build all dependent modules and link.

-fmakelist
This option is only applicable when linking a program module. The compiler will generate a `modulename.lst' file which contains a list indicating the initialization order of all modules which are to be linked. The actual link does not occur. The GNU Modula-2 linker scans all IMPORT's , generates a list of dependencies and produces an ordered list for initialization. It will probably get the order wrong if your project has cyclic dependencies, but the `.lst' file is plain text and can be modified if required. Once the `.lst' file is created it can be used by the compiler to link your project via the `-fuselist' option. It has no effect if the `-c' option is present.

-fsources
Displays the path to the source of each module.

-fstatistics
Generates quadruple information: number of quadruples generated, number of quadruples remaining after optimization. Quadruples are the intermediate language used internally by the GNU Modula-2 compiler.

-fuselist
Providing `gm2' has been told to link the program module this option uses the file `modulename.lst' for the initialization order of modules.

-Wverbose-unbounded
Inform the user which non `VAR' unbounded parameters will be passed by reference. This only produces output if the option -funbounded-by-reference is also supplied on the command line.

-funbounded-by-reference
Enable optimization of unbounded parameters by attempting to pass non `VAR' unbounded parameters by reference. This optimization avoids the implicit copy inside the callee procedure. GNU Modula-2 will only allow unbounded parameters to be passed by reference if, inside the callee procedure, they are not written to, no address is calculated on the array and it is not passed as a `VAR' parameter.

NOTE: That it is possible to write code to break this optimization, therefore this option should be used carefully. For example, it would be possible to take the address of an array, pass the address and the array to a procedure, read from the array in the procedure and write to the location using the address parameter.

Due to the dangerous nature of this option it is not enabled when the -O option is specified.

Runtime Checking Options

-fbounds
Generate code to check the bounds of subranges and array indexes.

-freturn
Generate code to check that functions always exit with a 'RETURN' and do not fall out at the end.

-fnil
Generate code to detect at runtime any attempt to access data through a 'NIL' value pointer.

-fcase
Generate code to detect at runtime whether a 'CASE' statement requires an 'ELSE' clause when one was not specified. This generates an implicit 'ELSE' for 'CASE' statements which do not define one. It simply prints an error message, and exits with an error code.

-fsoft-check-all
Turns on all runtime checks. This is the same as invoking GNU Modula-2 using the command options -fbounds, -freturn, -fnil, -fcase, -frange, ,-findex, -fwholediv

Style Checking Options

-Wstudents
Checks for bad programming style. This option is aimed at new users of Modula-2 in that it checks for situations which might cause confusion and thus mistakes. It checks whether variables of the same name are declared in different scopes and whether variables look like keywords. Experienced users might find this option too aggressive.

-Wpedantic
Forces the compiler to reject nested 'WITH' statements referencing the same record type. Does not allow multiple imports of the same item from a module. It also checks that: procedure variables are written to before being read; variables are not only written to but read from; variables are declared and used. If the compiler encounters a variable being read before written it will terminate with a message. It will check that 'FOR' loop indices are not used outside the end of this loop without being reset.

-Wpedantic-param-names
Procedure parameter names are checked in the definition module against their implementation module counterpart. This is not necessary in ISO or PIM versions of Modula-2, but it can be extremely useful, as long as code is intentionally written in this way.

-Wpedantic-cast
Warns if the ISO system function is used and if the size of the variable is different from that of the type. This is legal in ISO Modula-2, however it can be dangerous. Some users may prefer to use 'VAL' instead in these situations and use 'CAST' exclusively for changes in type on objects which have the same size.

Language Dialect Options

-fiso
Turn on ISO standard features. Currently this enables the ISO SYSTEM module and alters the default library search path so that the ISO libraries are searched before the PIM libraries. It also effects the behavior of 'DIV' and 'MOD' operators.

-fpim
Turn on PIM standard features. Currently this enables the PIM SYSTEM module and determines which identifiers are pervasive (declared in the base module). If no other -fpim[234] switch is used then division and modulus operators behave as defined in PIM4. (See LANGUAGE DIALECTS.)

-fpim2
Turn on PIM-2 standard features. Currently this removes SIZE from being a pervasive identifier (declared in the base module). It places SIZE in the SYSTEM module. It also effects the behavior of 'DIV' and 'MOD' operators.

-fpim3
Turn on PIM-3 standard features. Currently this only effects the behavior of `DIV' and `MOD' operators.

-fpim4
Turn on PIM-4 standard features. Currently this only effects the behavior of `DIV' and `MOD' operators.

-fpositive-mod-floor-div
Forces the `DIV' and `MOD' operators to behave as defined by PIM4. All modulus results are positive and the results from the division are rounded to the floor.
NOTE: See the section LANGUAGE DIALECTS for a table describing these results.

Library Search Path Options

-flibs=ulm
Modifies the default library search path so that the University of Ulm libraries are searched before the other PIM libraries.

-flibs=pim
Modifies the default library search path so that the PIM libraries are searched before any others (the default).

-flibs=pim-coroutine
Modifies the default libraries search path so that the PIM `SYSTEM' module providing coroutine support is searched before the base PIM libraries. This directory also includes many coroutine related libraries.

-flibs=iso
Modifies the default library search path so that the ISO libraries are searched before any others (not needed if `-fiso' was specified).

-flibs=logitech
Modifies the default library search path so that the Logitech compatible libraries are searched before the base PIM libraries.

-flibs=min
Modifies the default library search path so that the minimal set of runtime libraries are searched before any others. Useful if targetting a small memory embedded device.

LANGUAGE DIALECTS

This section describes the dialects understood by GNU Modula-2. It also describes the differences between the dialects and any command line switches which determine dialect behavior.

The GNU Modula-2 compiler is based on the language as defined in:

PIM2
´Programming in Modula-2´, 2nd Edition, Springer Verlag, 1982, 1983 by Niklaus Wirth,
PIM3
´Programming in Modula-2´, 3rd Corrected Edition, Springer Verlag, 1985 by Niklaus Wirth, and
PIM4
´Programming in Modula-2´, 4th Edition, Springer Verlag, 1988, by Niklaus Wirth.
ISO
The International Standards Organization's ISO/IEC 10514-1:1996 Information Technology -- Programming Languages -- Part-1: Modula-2, Base Language

It also includes ISO M2 features and GNU Modula-2 extensions. Currently GNU Modula-2 (0.49) implements all PIM dialects of the language, eventually GNU Modula-2 will be fully compliant with ISO Modula-2 Base Language. It supports neither ISO Modula-2 Generics, nor ISO Object Oriented Modula-2.

The command line switches -fpim2, -fpim3, -fpim4, and -fiso can be used to force mutually exclusive features. However by default the compiler will not aggressively fail if a non mutually exclusive feature is used from another dialect. For example it is possible to specify -fpim2 and still utilize DEFINITION MODULES which have no export list.

Some dialect differences will force a compile time error, for example in PIM2 the user must IMPORT SIZE from the module SYSTEM , whereas in PIM3 and PIM4 SIZE is a pervasive function. Thus compiling PIM4 source code with the -fpim2 switch will cause a compile time error. This can be fixed quickly with an additional IMPORT or alternatively by compiling with the -fpim4 switch.

However there are some very important differences between the dialects which are mutually exclusive and therefore it is vital that users choose the dialects with care when these language features are used.

Integer Division, Remainder and Modulus

The most dangerous set of mutually exclusive features found in the four dialects supported by GNU Modula-2 are the `INTEGER' division, remainder and modulus arithmetic operators. It is important to note that the same source code can be compiled to give different runtime results depending upon these switches! The reference manual for the various dialects of Modula-2 are quite clear about this behavior and sadly there are three distinct definitions.

The table below illustrates the problem when a negative operand is used.

                      Pim2/3          Pim4                ISO
                   -----------    -----------    ----------------------
    lval    rval   DIV     MOD    DIV     MOD    DIV    MOD    /    REM
    31      10      3       1      3       1      3      1     3     1
   -31      10     -3      -1     -4       9     -4      9    -3    -1
    31     -10     -3       1     -3       1     Exception    -3     1
   -31     -10      3      -1      4       9     Exception     3    -1

See also pg24 of PIM2, pg27 of PIM3, pg29 of PIM4, and pg201 of the ISO Standard. At present all dialect division, remainder and modulus are implemented as above, apart from the exception calling in the ISO dialect. Instead of exception handling the results are the same as the PIM4 dialect. This is a temporary implementation situation.

The PIM SYSTEM Module

The different dialects of Modula-2 PIM-[234] and ISO Modula-2 declare the function `SIZE' in different places. PIM-[34] and ISO Modula-2 declare `SIZE' as a pervasive function (declared in the base module). PIM-2 defined `SIZE' in the `SYSTEM' module.

     DEFINITION MODULE SYSTEM ;
     EXPORT QUALIFIED (* the following are built into the compiler: *)
                      ADDRESS, WORD, BYTE, BITSET, ADR, TSIZE, SIZE ;
     END SYSTEM.

The ISO SYSTEM Module

DEFINITION MODULE SYSTEM;

(* Gives access to system programming facilities that are probably non portable. *)

(* The constants and types define underlying properties of storage *)

EXPORT QUALIFIED BITSPERLOC, LOCSPERWORD, LOC, BYTE, WORD, BITSET, ADDRESS, ADDADR, SUBADR, DIFADR, MAKEADR, ADR, ROTATE, SHIFT, CAST, TSIZE,

(* Internal GM2 compiler functions *) ShiftVal, ShiftLeft, ShiftRight, RotateVal, RotateLeft, RotateRight ;

CONST (* <implementation-defined constant> ; *) BITSPERLOC = __ATTRIBUTE__ __BUILTIN__ ((BITS_PER_UNIT)) ; (* <implementation-defined constant> ; *) LOCSPERWORD = __ATTRIBUTE__ __BUILTIN__ ((UNITS_PER_WORD)) ; (* <implementation-defined constant> ; *) LOCSPERBYTE = 8 DIV BITSPERLOC ; (* all the objects below are declared internally to gm2 ====================================================

TYPE LOC; (* A system basic type. Values are the uninterpreted contents of the smallest addressable unit of storage *) ADDRESS = POINTER TO LOC; WORD = ARRAY [0 .. LOCSPERWORD-1] OF LOC;

(* BYTE and LOCSPERBYTE are provided if appropriate for machine *)

TYPE BYTE = ARRAY [0 .. LOCSPERBYTE-1] OF LOC;

PROCEDURE ADDADR (addr: ADDRESS; offset: CARDINAL): ADDRESS; (* Returns address given by (addr + offset), or may raise an exception if this address is not valid. *)

PROCEDURE SUBADR (addr: ADDRESS; offset: CARDINAL): ADDRESS; (* Returns address given by (addr - offset), or may raise an exception if this address is not valid. *)

PROCEDURE DIFADR (addr1, addr2: ADDRESS): INTEGER; (* Returns the difference between addresses (addr1 - addr2), or may raise an exception if the arguments are invalid or address space is non-contiguous. *)

PROCEDURE MAKEADR (high: <some type>; ...): ADDRESS; (* Returns an address constructed from a list of values whose types are implementation-defined, or may raise an exception if this address is not valid.

In GNU Modula-2, MAKEADR can take any number of arguments which are mapped onto the type ADDRESS. The first parameter maps onto the high address bits and subsequent parameters map onto lower address bits. For example: a := MAKEADR(BYTE(0FEH), BYTE(0DCH), BYTE(0BAH), BYTE(098H), BYTE(076H), BYTE(054H), BYTE(032H), BYTE(010H)) ;

then the value of, a, on a 64 bit machine is: 0FEDCBA9876543210H

The parameters do not have to have the same type, but constants _must_ be typed. *)

PROCEDURE ADR (VAR v: <anytype>): ADDRESS; (* Returns the address of variable v. *)

PROCEDURE ROTATE (val: <a packedset type>; num: INTEGER): <type of first parameter>; (* Returns a bit sequence obtained from val by rotating up or down (left or right) by the absolute value of num. The direction is down if the sign of num is negative, otherwise the direction is up. *)

PROCEDURE SHIFT (val: <a packedset type>; num: INTEGER): <type of first parameter>; (* Returns a bit sequence obtained from val by shifting up or down (left or right) by the absolute value of num, introducing zeros as necessary. The direction is down if the sign of num is negative, otherwise the direction is up. *)

PROCEDURE CAST (<targettype>; val: <anytype>): <targettype>; (* CAST is a type transfer function. Given the expression denoted by val, it returns a value of the type <targettype>. An invalid value for the target value or a physical address alignment problem may raise an exception. *)

PROCEDURE TSIZE (<type>; ... ): CARDINAL; (* Returns the number of LOCS used to store a value of the specified <type>. The extra parameters, if present, are used to distinguish variants in a variant record. *) *)

(* The following procedures are invoked by GNU Modula-2 to shift non word set types. They are not part of ISO Modula-2 but are used by GNU Modula-2 to implement the SHIFT procedure defined above. *)

(* ShiftVal - is a runtime procedure whose job is to implement the SHIFT procedure of ISO SYSTEM. GNU Modula-2 will inline a SHIFT of a single WORD sized set and will only call this routine for larger sets. *)

PROCEDURE ShiftVal (VAR s, d: ARRAY OF BITSET; SetSizeInBits: CARDINAL; ShiftCount: INTEGER) ;

(* ShiftLeft - performs the shift left for a multi word set. This procedure might be called by the back end of GNU Modula-2 depending whether amount is known at compile time. *)

PROCEDURE ShiftLeft (VAR s, d: ARRAY OF BITSET; SetSizeInBits: CARDINAL; ShiftCount: INTEGER) ;

(* ShiftRight - performs the shift left for a multi word set. This procedure might be called by the back end of GNU Modula-2 depending whether amount is known at compile time. *)

PROCEDURE ShiftRight (VAR s, d: ARRAY OF BITSET; SetSizeInBits: CARDINAL; ShiftCount: INTEGER) ;

(* RotateVal - is a runtime procedure whose job is to implement the ROTATE procedure of ISO SYSTEM. GNU Modula-2 will inline a ROTATE of a single WORD (or less) sized set and will only call this routine for larger sets. *)

PROCEDURE RotateVal (VAR s, d: ARRAY OF BITSET; SetSizeInBits: CARDINAL; RotateCount: INTEGER) ;

(* RotateLeft - performs the rotate left for a multi word set. This procedure might be called by the back end of GNU Modula-2 depending whether amount is known at compile time. *) PROCEDURE RotateLeft (VAR s, d: ARRAY OF BITSET; SetSizeInBits: CARDINAL; RotateCount: INTEGER) ;

(* RotateRight - performs the rotate right for a multi word set. This procedure might be called by the back end of GNU Modula-2 depending whether amount is known at compile time. *)

PROCEDURE RotateRight (VAR s, d: ARRAY OF BITSET; SetSizeInBits: CARDINAL; RotateCount: INTEGER) ;

END SYSTEM.

GM2 LANGUAGE EXTENSIONS

This section introduces the GNU Modula-2 language extensions.

Abstract Types

The GNU Modula-2 compiler allows abstract data types to be any type, not just restricted to a pointer type providing the -fextended-opaque command line option is supplied.

Declaration Order

Declarations can be made in any order, whether they are types, constants, procedures, nested modules or variables.

Interfacing to C

GNU Modula-2 also allows programmers to interface to `C' and assembly language.

The GNU Modula-2 compiler tries to use the C calling convention wherever possible however some parameters have no C equivalent and thus a language specific method is used. For example unbounded arrays are passed as a `struct void *address, unsigned int high' and the contents of these arrays are copied by callee functions when they are declared as non `VAR' parameters. The `VAR' equivalent unbounded array parameters need no copy, but still use the `struct' representation.

The recommended method of interfacing GNU Modula-2 to C is by telling the definition module that the implementation is in the C language. This is achieved by using the tokens `DEFINITION MODULE FOR “C”'.

     DEFINITION MODULE FOR "C" libprintf ;
     EXPORT UNQUALIFIED printf ;
     PROCEDURE printf (a: ARRAY OF CHAR; ...) ;
     END libprintf.

The `UNQUALIFIED' keyword in the definition module informs GNU Modula-2 not to prefix the module name to exported references in the object file.

The `printf' declaration states that the first parameter semantically matches `ARRAY OF CHAR' but since the module is for the C language it will be mapped onto 'char *'. The token `...' indicates a variable number of arguments (varargs) and all parameters passed here are mapped onto their C equivalents. Arrays and constant strings are passed as pointers.

The hello world program can be rewritten as:

     MODULE hello ;
     FROM libprintf IMPORT printf ;
     BEGIN
        printf("hello world0)
     END hello.

and it can be compiled by: gm2 -fmakeall -g -I. hello.mod -lc.

In reality the `-lc' is redundant as libc is always included in the linking process. It is shown here to emphasize that the C library or object file containing `printf' must be present.

Interfacing to Assembly Language

The interface for GNU Modula-2 to assembly language is almost identical to GNU C. The only alterations are that the keywords `asm' and `volatile' are in capitals, following the Modula-2 convention.

A simple, but highly non-optimal, example is given below. Here we want to add the two `CARDINAL's `foo' and `bar' together and return the result.

     PROCEDURE Example (foo, bar: CARDINAL) : CARDINAL;
     VAR
        myout: CARDINAL;
     BEGIN
        ASM VOLATILE ("movl %1,%%eax; addl %2,%%eax; movl %%eax,%0"
           : "=g" (myout)           (* outputs *)
           : "g" (foo), "g" (bar)   (* inputs  *)
           : "eax");                (* we trash *)
        RETURN( myout );
     END Example;

Special Tokens

GNU Modula-2 provides support for the special tokens __LINE__, __FILE__, __FUNCTION__, and __DATE__. Support for these tokens will occur even if the -fcpp option is not supplied. A table of these identifiers and their data type and values is given below:

  Scope       GNU Modula-2 token      Data type and example value
  anywhere    __LINE__                Constant Literal compatible
                                      with CARDINAL, INTEGER and WORD.
                                      Example 1234
  anywhere    __FILE__                Constant string compatible
                                      with parameter ARRAY OF CHAR or
                                      an ARRAY whose SIZE is >= string
                                      length. Example "hello.mod"
  procedure   __FUNCTION__            Constant string compatible
                                      with parameter ARRAY OF CHAR or
                                      an ARRAY whose SIZE is >= string
                                      length. Example
                                      "calc"
  module      __FUNCTION__            Example
                                      "module hello initialization"
  anywhere    __DATE__                Constant string compatible
                                      with parameter ARRAY OF CHAR or
                                      an ARRAY whose SIZE is >= string
                                      length. Example
                                      "Thu Apr 29 10:07:16 BST 2004"

Preprocessor

The preprocessor cpp can be invoked via the -fcpp command line option. This in turn invokes cpp with the following arguments -traditional -lang-asm. These options preserve comments and all quotations. gm2 treats a `#' character in the first column as a preprocessor directive.

For example here is a module which calls `FatalError' via the macro `ERROR'.

     MODULE cpp ;
     FROM SYSTEM IMPORT ADR, SIZE ;
     FROM libc IMPORT exit, printf, malloc ;
     PROCEDURE FatalError (a, file: ARRAY OF CHAR;
                              line: CARDINAL;
                              func: ARRAY OF CHAR) ;
     VAR
        r: INTEGER ;
     BEGIN
        r := printf("%s:%d:fatal error, %s, in %s0,
                    ADR(file), line, ADR(a), ADR(func)) ;
        exit(1)
     END FatalError ;
     #define ERROR(X)  FatalError(X, __FILE__, __LINE__, __FUNCTION__)
     VAR
        pc: POINTER TO CARDINAL;
     BEGIN
        pc := malloc(SIZE(CARDINAL)) ;
        IF pc=NIL
        THEN
           ERROR('out of memory')
        END
     END cpp.

Optional procedure parameter

GNU Modula-2 allows the last parameter to a procedure or function parameter to be optional. This is achieved by enclosing the last formal parameter within square brackets, and providing an initializer (a constant assignment).

For example in the ISO library 'COROUTINES.def' the procedure NEWCOROUTINE is defined as having an optional fifth argument (`initProtection') which, if absent, is automatically replaced by `NIL'.

     PROCEDURE NEWCOROUTINE (procBody: PROC; workspace: SYSTEM.ADDRESS;
                             size: CARDINAL; VAR cr: COROUTINE;
                             [initProtection: PROTECTION = NIL]);

The implementation module `COROUTINES.mod' implements this procedure using the following syntax:

     PROCEDURE NEWCOROUTINE (procBody: PROC; workspace: SYSTEM.ADDRESS;
                             size: CARDINAL; VAR cr: COROUTINE;
                             [initProtection: PROTECTION]);
     BEGIN
     END NEWCOROUTINE ;

Note that it is illegal for this declaration to contain an initializer value for `initProtection'. However it is necessary to surround this parameter with the brackets `[' and `]'. This serves to remind the programmer that the last parameter was declared as optional in the definition module.

Local procedures can be declared to have an optional final parameter in which case the initializer is mandatory in the implementation or program module.

Builtins

This section describes the built-in constants and functions defined in GNU Modula-2. The following compiler constants can be accessed using the `__ATTRIBUTE__', `__BUILTIN__' keywords. These are not part of the Modula-2 language and they may differ depending upon the target architecture but they provide a method whereby common libraries can interface to a different underlying architecture.

The built-in constants are: `BITS_PER_UNIT', `BITS_PER_WORD', 'BITS_PER_CHAR ' and `UNITS_PER_WORD'. They are integrated into GNU Modula-2 by an extension to the `ConstFactor' rule:

     ConstFactor := ConstQualidentOrSet | Number | ConstString |
                    "(" ConstExpression ")" | "NOT" ConstFactor |
                    ConstAttribute =:
     ConstAttribute := "__ATTRIBUTE__" "__BUILTIN__" "(" "(" Ident ")" ")" =:

Here is an example taken from the ISO library `SYSTEM.def':

     CONST
        BITSPERLOC    = __ATTRIBUTE__ __BUILTIN__ ((BITS_PER_UNIT)) ;
        LOCSPERWORD   = __ATTRIBUTE__ __BUILTIN__ ((UNITS_PER_WORD)) ;

Built-in functions are transparent to the end user. All built-in functions are declared in `DEFINITION MODULE's and are imported as and when required. Built-in functions are declared in definition modules by using the `__BUILTIN__' keyword. Here is a section of the ISO library `LongMath.def' which demonstrates this feature.

    PROCEDURE __BUILTIN__ sqrt (x: LONGREAL): LONGREAL;
       (* Returns the square root of x *)

This indicates that the function `sqrt' will be implemented using the gcc built-in math library. If gcc cannot utilize the built-in function (for example if the programmer requested the address of `sqrt') then code is generated to call the alternative function implemented in the `IMPLEMENTATION MODULE'.

Sometimes a function exported from the `DEFINITION MODULE' will have a different name from the built-in function within gcc. In such cases the mapping between the GNU Modula-2 function name and the gcc name is expressed using the keywords `__ATTRIBUTE__ __BUILTIN__ ((Ident))'. For example the function `sqrt' in `LongMath.def' maps onto the gcc built-in function `sqrtl' and this is expressed as:

     PROCEDURE __ATTRIBUTE__ __BUILTIN__ ((sqrtl)) sqrt
                                         (x: LONGREAL) : LONGREAL;
       (* Returns the positive square root of x *)

The following module `Builtins.def' enumerates the list of built-in functions which can be accessed in GNU Modula-2. It also serves to define the parameter and return value for each function:

     DEFINITION MODULE Builtins ;
     FROM SYSTEM IMPORT ADDRESS ;
     PROCEDURE __BUILTIN__ sinf (x: SHORTREAL) : SHORTREAL ;
     PROCEDURE __BUILTIN__ sin (x: REAL) : REAL ;
     PROCEDURE __BUILTIN__ sinl (x: LONGREAL) : LONGREAL ;
     PROCEDURE __BUILTIN__ cosf (x: SHORTREAL) : SHORTREAL ;
     PROCEDURE __BUILTIN__ cos (x: REAL) : REAL ;
     PROCEDURE __BUILTIN__ cosl (x: LONGREAL) : LONGREAL ;
     PROCEDURE __BUILTIN__ sqrtf (x: SHORTREAL) : SHORTREAL ;
     PROCEDURE __BUILTIN__ sqrt (x: REAL) : REAL ;
     PROCEDURE __BUILTIN__ sqrtl (x: LONGREAL) : LONGREAL ;
     PROCEDURE __BUILTIN__ fabsf (x: SHORTREAL) : SHORTREAL ;
     PROCEDURE __BUILTIN__ fabs (x: REAL) : REAL ;
     PROCEDURE __BUILTIN__ fabsl (x: LONGREAL) : LONGREAL ;
     PROCEDURE __BUILTIN__ alloca (i: CARDINAL) : ADDRESS ;
     PROCEDURE __BUILTIN__ memcpy (dest, src: ADDRESS; n: CARDINAL) : ADDRESS ;
     PROCEDURE __BUILTIN__ index (s: ADDRESS; c: INTEGER) : ADDRESS ;
     PROCEDURE __BUILTIN__ rindex (s: ADDRESS; c: INTEGER) : ADDRESS ;
     PROCEDURE __BUILTIN__ memcmp (s1, s2: ADDRESS; n: CARDINAL) : INTEGER ;
     PROCEDURE __BUILTIN__ memset (s: ADDRESS; c: INTEGER; n: CARDINAL) : ADDRESS ;
     PROCEDURE __BUILTIN__ strcat (dest, src: ADDRESS) : ADDRESS ;
     PROCEDURE __BUILTIN__ strncat (dest, src: ADDRESS; n: CARDINAL) : ADDRESS ;
     PROCEDURE __BUILTIN__ strcpy (dest, src: ADDRESS) : ADDRESS ;
     PROCEDURE __BUILTIN__ strncpy (dest, src: ADDRESS; n: CARDINAL) : ADDRESS ;
     PROCEDURE __BUILTIN__ strcmp (s1, s2: ADDRESS) : INTEGER ;
     PROCEDURE __BUILTIN__ strncmp (s1, s2: ADDRESS; n: CARDINAL) : INTEGER ;
     PROCEDURE __BUILTIN__ strlen (s: ADDRESS) : INTEGER ;
     PROCEDURE __BUILTIN__ strstr (haystack, needle: ADDRESS) : ADDRESS ;
     PROCEDURE __BUILTIN__ strpbrk (s, accept: ADDRESS) : ADDRESS ;
     PROCEDURE __BUILTIN__ strspn (s, accept: ADDRESS) : CARDINAL ;
     PROCEDURE __BUILTIN__ strcspn (s, accept: ADDRESS) : CARDINAL ;
     PROCEDURE __BUILTIN__ strchr (s: ADDRESS; c: INTEGER) : ADDRESS ;
     PROCEDURE __BUILTIN__ strrchr (s: ADDRESS; c: INTEGER) : ADDRESS ;
     PROCEDURE __BUILTIN__ huge_val (r: REAL) : REAL ;
     PROCEDURE __BUILTIN__ huge_valf (s: SHORTREAL) : SHORTREAL ;
     PROCEDURE __BUILTIN__ huge_vall (l: LONGREAL) : LONGREAL ;
     END Builtins.

Although this module exists and will result in the generation of inline code if optimization flags are passed to GNU Modula-2, users are advised to utilize the same functions from more generic libraries. The built-in mechanism will be applied to these generic libraries where appropriate. NOTE: for the mathematical routines to be inlined you need to specify the `-ffast-math -O' options.

LIBRARIES

EXAMPLES

This section describes how to compile and link a simple 'hello world' program. It provides a few examples of using the different options mentioned above.

Assume the file "hello.mod" contains the code:

     MODULE Hello;
     FROM StrIO IMPORT WriteString, WriteLn;
     BEGIN
        WriteString('hello world');
        WriteLn;
     END Hello.

You should be able to compile it by: gm2 -c hello.mod and link via: gm2 hello.mod. The result should be an `a.out' file created in your directory.

Alternatively it may be compiled by: gm2 -g -I. -fmakeall hello.mod.

FILES

ENVIRONMENT

CONFORMING TO

The GNU Modula-2 compiler is based on the language as defined in:

'Programming in Modula-2' 2nd Edition, Springer Verlag, 1982, 1983 by Niklaus Wirth (PIM2),

'Programming in Modula-2', 3rd Corrected Edition, Springer Verlag, 1985 (PIM3) and

'Programming in Modula-2', 4th Edition, Springer Verlag, 1988 (PIM4).

It also includes ISO M2 features and GNU Modula-2 extensions.

BUGS

COPYRIGHT

LICENCE

The GNU Modula-2 compiler and associated software is released under the GNU PUBLIC LICENCE (GPL) which should be available in a file named COPYING.

The runtime libraries (pim, iso, and Logitech Compatable) are released under the LESSER GNU PUBLIC LICENCE (LGPL) which allows any user to link against the runtime libraries without invoking all the clauses of the full GPL.

The Ulm library is released under the GPL.

AUTHOR

This manual page was written (using the documentation from the texinfo files) by

SEE ALSO

The many fine books about Modula-2.

The GNU Modula-2 web site at

27-Nov-2005 GM2