Modula-2 || Compiler & Tools || Library || Search Engine


Ulm's Modula-2 Library:
SYSTEM


NAME

SYSTEM - system-dependent built-ins of Ulm's Modula-2 Compiler

SYNOPSIS

TYPE BYTE = (* 1-byte generic type *);
TYPE WORD = (* 4-byte generic type *);
TYPE ADDRESS = POINTER TO WORD;


PROCEDURE ADR(VAR variable: AnyType) : ADDRESS; PROCEDURE TSIZE(type: AnyTypeName) : CARDINAL; PROCEDURE TSIZE(type: AnyTypeName; tagval1, tagval2, ...: AnyConst) : CARDINAL;

PROCEDURE NEWPROCESS(p: PROC; stack: ADDRESS; stacksize: CARDINAL; VAR cr: ADDRESS); PROCEDURE TRANSFER(VAR cr1, cr2: ADDRESS);

PROCEDURE UNIXCALL(syscall: CARDINAL; VAR r0, r1: INTEGER; ...) : BOOLEAN; PROCEDURE UNIXFORK(VAR pid: CARDINAL) : BOOLEAN; PROCEDURE UNIXSIGNAL(signo: CARDINAL; p: PROCEDURE; VAR old: PROCEDURE; VAR result: CARDINAL) : BOOLEAN;

PROCEDURE SQRT(x: REAL) : REAL;

DESCRIPTION

The module SYSTEM is provided by the compiler itself, does not have associated sources (neither a definition nor an implementation module) and therefore does not need to be located in the search path like other modules.

The Modula-2 reports state that the contents of SYSTEM is system-dependant which gives a great freedom for implementors and declares every module which imports SYSTEM as non-portable. Luckily, a large subset of SYSTEM as given by PIM3 is widely available on many implementations including Ulm's Modula-2 compiler. Following sections show which parts conform to PIM3, which parts are not implemented and which goodies of SYSTEM are specific to Ulm's Modula-2 compiler.

Commonly available parts

Ulm's Modula-2 compiler supports the types BYTE, WORD, ADDRESS, and the procedures ADR, TSIZE, NEWPROCESS, TRANSFER.

BYTE is assignment compatible to all other types which occupy one byte while WORD is compatible to all other types which have a size of four bytes. Both, ARRAY OF BYTE and ARRAY OF WORD are supported as formal parameter types which accept any actual parameter. The only exception is that ARRAY OF WORD accepts only types which occupy a multiple of 4 bytes -- this includes all arrays, records, and pointer types. Note, however, that many newer implementations do not offer WORD or ARRAY OF WORD while BYTE and ARRAY OF BYTE are to be expected on nearly all platforms.

ADDRESS is assignment compatible to all pointer types and compatible to CARDINAL. Note that some implementations define ADDRESS as POINTER TO BYTE and define ADDRESS to be compatible to LONGCARD or LONGINT instead of CARDINAL. Therefore, it is fairly portable to accept generic pointers as ADDRESS and to pass it, for example, to Storage but it is very system-dependent to assume a size, a structure, or a compatibility to one of the integer types, or to perform address arithmetics. The duplication of unstructured byte quantities is best delegated to a library module which usually contains code which is tuned for the local implementation. In Ulm's Modula-2 library this is done by the module Bytes.

ADR is a function which returns the address of a given variable as value of type ADDRESS.

TSIZE returns the number of bytes of the specified type (as value of type CARDINAL). Note that TSIZE like NEW accepts further constant arguments which select by their tag value specific variants of a record. This may be useful if some variants of a record occupy much less space than others but not all Modula-2 compilers support this feature.

Ulm's Modula-2 compiler supports coroutines and their associated procedures NEWPROCESS and TRANSFER. Regrettably, these procedures require some system-dependent knowledge about the necessary size of a coroutine stack and even TRANSFER is not without system dependencies. The SPARC-implementation of Ulm's Modula-2 compiler consumes much more stack space than other implementations and requires therefore a minimum size of 8192 bytes for stacks. Stacks which are too small may lead to compiler errors (if a constant is given) or to undefined effects at runtime (you are lucky if it is just a segmentation violation because the system is unable to redzone protect stacks as long as they are given by the programmer and not allocated by the system). Currently, there are no runtime checks for stecks but they are not necessary if a redzone protected area is provided by the programmer (this is not a problem by using the mmap(2) system call).

Note that NEWPROCESS and TRANSFER expect coroutines to be of type ADDRESS. The older revisions of Modula-2 expect PROCESS as argument type of NEWPROCESS and TRANSFER which is provided if one of the older revisions is selected (option -r0 or -r1 at the command line of m2c).

Unimplemented Parts

UNIX-systems restrict accesses of devices to the kernel. Therefore, IOTRANSFER is not implemented.

Specific Extensions

Most implementations of Modula-2 for UNIX depend on the C-library to access system calls. Ulm's Modula-2 compiler neither supports nor needs an access to system calls via foreign libraries (i.e. the standard C-library.

UNIXCALL interfaces all system calls with the exception of fork(2) and sigaction(2) which have a different calling scheme (on the machine instruction level). The parameter syscall must be a constant number (see Sys or /usr/include/sys/syscall.h for valid numbers). Some system calls expect under some UNIX-variants one or two parameters in some specific registers or, more often, return some values in these registers:

-------------------------------------------------------------
Platform                   OS Release      registers
-------------------------------------------------------------
Concurrent 3200 Series     XELOS R02       registers 0 and 1
Nixdorf Targon/31          System V.3      d0 and d1
Sun-3 Workstation          SunOS 4.1.x     d0 and d1
SPARC architecture         Solaris 2.x     o0 and o1
-------------------------------------------------------------

Any number of additional parameters may be passed as additional arguments. Note, however, that the compiler does not care about compatibility issues here. Strings and buffers, for example, must be passed by address and not as dynamic arrays. UNIXCALL returns FALSE in case of errors. All UNIX-architectures we know of (including those platforms which has been listed above) return the error code (see errno(2)) in the first register (VAR-parameter r0). In case of success, some results may be returned into the VAR-parameters r0 and r1. read(2), for example, returns the number of bytes read in r0, and pipe(2) returns (on many platforms but not all) both file descriptors in r0 and r1.

Following example is taken from the library and shows the implementation of SysWrite on the Solaris 2.x system (which runs in identical form on all other platforms mentioned above):

IMPLEMENTATION MODULE SysWrite;

   FROM Errno IMPORT errno;
   FROM Sys IMPORT write;
   FROM SYSTEM IMPORT UNIXCALL, ADDRESS;

   PROCEDURE Write(fd: CARDINAL; ptr: ADDRESS;
                   VAR bytecount: CARDINAL) : BOOLEAN;
      VAR r0, r1: CARDINAL;
   BEGIN
      IF UNIXCALL(write, r0, r1, fd, ptr, bytecount) THEN
         bytecount := r0;
         RETURN TRUE
      ELSE
         errno := r0;
         bytecount := 0;
         RETURN FALSE
      END;
   END Write;

END SysWrite.

UNIXFORK is already interfaced by SysFork and should not be used anywhere else. Note that in case of failures the error code is returned in pid. In case of success, pid will contain the process id of the son (for the father process) or 0 (in the child process).

Similarly, UNIXSIGNAL is interfaced by SysSignal and should not be called in other modules. The parameters signo and p specify which parameterless procedure is to be called on which signal number. The old signal handler is returned in old and, in case of failures, the error code is returned in result together with a return value of FALSE. Note that UNIXSIGNAL does not offer all facilities of sigaction(2) (under Solaris 2.x) in their full generality but at least UNIXSIGNAL and SysSignal work on all our implementations without changes.

Interface to Specific Machine Instructions

SQRT interfaces the equally named machine instruction on the SPARC architecture and is used by the SPARC-specific implementation of MathLib.

SEE ALSO

m2c, Storage, SysFork, SysSignal
PIM3: Niklaus Wirth, Programming in Modula-2, 3rd edition, Springer-Verlag
Installation and User Guide for Ulm's Modula-2 System
Edited by: borchert, last change: 1997/02/26, revision: 1.1, converted to HTML: 1997/04/28

Modula-2 || Compiler & Tools || Library || Search Engine