Oberon || Library || Module Index || Search Engine || Definition || Module

Ulm's Oberon Library:


SYSTEM - system-dependent built-ins of Ulm's Oberon Compiler


TYPE INT16 = (* 2-byte integer type *);
TYPE ADDRESS = (* LONGINT-compatible & traced by the GC *);
TYPE UNTRACEDADDRESS = (* LONGINT-compatible & ignored by the GC *);
TYPE COROUTINE = (* coroutine of Ulm's coroutine scheme *);

(* function procedures *) PROCEDURE ADR(VAR variable: AnyType) : ADDRESS; PROCEDURE BIT(address: LONGINT; n: LONGINT) : BOOLEAN; PROCEDURE LSH(value, n: LONGINT) : LONGINT; PROCEDURE ROT(value, n: LONGINT) : LONGINT; PROCEDURE SIZE(type: AnyTypeName) : LONGINT; PROCEDURE TAS(VAR flag: BOOLEAN) : BOOLEAN; PROCEDURE VAL(type: AnyTypeName; value: AnyType) : type;

(* proper procedures *) PROCEDURE GET(address: LONGINT; VAR variable: AnyBasicType); PROCEDURE PUT(address: LONGINT; value: AnyBasicType); PROCEDURE HALT(exitcode: LONGINT); PROCEDURE MOVE(VAR fromVariable, toVariable: AnyType; n: LONGINT); PROCEDURE WMOVE(from, to: LONGINT; n: LONGINT); PROCEDURE WCLEAR(address: LONGINT; n: LONGINT); PROCEDURE NEW(VAR ptr: AnyPointerType; n: LONGINT);




SYSTEM is a built-in module of the compiler which is not searched for in the compilation environment. Each Oberon implementation is free to decide about the contents of SYSTEM. Modules importing SYSTEM are therefore implementation-dependent.

Because these procedures are implemented by the compiler they do not necessarily follow the strong declaration semantics of the Oberon language. SIZE, for example, takes the name of a type, and NEW accepts any pointer variable but nothing else. Some ad-hoc type names have been used in the synopsis to describe the semantics of parameters:

Note that parameters which are named variable accept a variable but not an arbitrary designator.


Ulm's Oberon Compiler implements SHORTINT as 1-byte integer and INTEGER as 4-byte integer. To fill the rarely needed gap, a 2-byte integer is provided by INT16. SHORT of an INT16-value yields a SHORTINT, and LONG returns an INTEGER. But note that neither SHORT of an INTEGER, nor LONG of a SHORTINT return an INT16-value. This is necessary to preserve the standard semantics of SHORT and LONG. Conversions to an INT16-value may be achieved by VAL.

ADDRESS and UNTRACEDADDRESS are to be preferred over LONTINT for holding address values. Note that unlike the ETH implementations ADR does not return a LONGINT-value but ADDRESS. Ulm's Oberon Compiler produces tables which allow the garbage collection to follow pointer and address references. ADDRESS-values will be recognized by the garbage collection, i.e. the objects they point to will keep alive if the address belongs to a living structure and the addresses will be updated automatically by copying garbage collectors (see SysStorage). This works not only when addresses point to the beginning of an object (like ordinary pointers) but also if they point to an arbitrary component of an object.

Variables of type UNTRACEDADDRESS are fine to hold address values but are never looked at by the garbage collection. This is useful for addresses returned by the address space management (see Memory). Both, ADDRESS and UNTRACEDADDRESS, are compatible to LONGINT. Nevertheless, the compiler feels free to emit warnings when addresses are assigned to LONGINT because this is generally to be considered as an unsafe technique.

Note that because of portability problems none of these types should be used directly. It is recommended to use the type declarations of Types which may be easily adapted to any implementation of Oberon.

Function procedures

ADR returns the address of the given variable. BIT returns the n-th bit of the 32-bit word at address. LSH shifts value (which is always seen as 32-bit value) by n bits logically to the left. Logically means that the sign bit is not treated special. Shifts to the right side may be achieved by giving a negative value of n. ROT works like LSH but rotates value, i.e. bits which are shifted out appear on the other side again.

SIZE returns the number of bytes which are occupied by objects of the given type. Note that the size of composite types is sometimes larger than the sum of the sizes of the parts.

TAS is an atomic operation which sets flag to TRUE and returns the old value of flag. TAS allows to avoid critical regions to be entered twice:

(* enter critical region only if flag was not set *)
   (* critical region *)
   flag := FALSE;

VAL allows a large number of system-dependent type conversions. It permits any numerical type to be converted to any other numerical type. Other type conversions are supported only if both, type and the type of value, occupy the same number of bytes.

Proper procedures

GET and PUT allow to access memory at arbitrary memory addresses. HALT works like the standard procedure HALT but does not initiate any termination handling (see Process). It should be used in emergencies only.

MOVE copies n bytes of from to to. MOVE does not check n against the length of from or to. WMOVE copies n 4-byte words from from to to. Note that WMOVE takes addresses while MOVE works for variables only. WCLEAR zeroes n 4-byte words beginning at address.

NEW allocates n bytes and returns the address in ptr. This variant of NEW does not allocate a type tag (i.e. type tests and type guards are not permitted for ptr) and the allocated data is considered as pointer-free by the garbage collection.

Ulm's coroutine scheme

CRSPAWN creates and returns a new coroutine cr which takes the calling procedure as body. The new coroutine is initially suspended and the callee returns immediately. CRSWITCH allows to switch to another coroutine. Note that CRSWITCH causes some variables of Coroutines to be set automatically. Further, CRSWITCH needs usually not to be called because of Tasks.

Interface to UNIX

UNIXCALL offers an interface to all UNIX system calls with the exception of fork(2) and sigvec(2) which are covered by UNIXFORK and UNIXSIGNAL. The system call number syscall which may be imported from Sys must be a constant value. The values of d0 and d1 will be put into the equally named registers, and, after the call, the values of the registers d0 and d1 will be copied back to the variables. The return value or error code (see errno(2)) is usually found in d0. An arbitrary number of arguments may be given which must follow C-conventions, i.e. integers should be passed as 4-byte integers (INTEGER or LONGINT), and array or structure references as addresses (ADDRESS or UNTRACEDADDRESS) but not as pointers. UNIXCALL returns TRUE on success and FALSE if the carry bit has been set by the kernel. Note that all common system calls are covered by the library (e.g. SysIO, SysFile, SysIPC, SysSockets etc).

UNIXFORK performs a fork(2) operation, and returns, on success, a positive pid value to the parent process and zero to the child process. pid contains in case of failures (return of FALSE) the error number. Note that SysProcess should usually be used instead.

UNIXSIGNAL registers p as new reaction for the signal number signo. Values of 0 (default reaction) or 1 (ignore) are legal for p. On success, UNIXSIGNAL returns TRUE and returns the old reaction in old. In case of failures, the error number is returned in error.


With the exception of the UNIX system calls there is no checking performed at runtime by code generated by the compiler. So use these calls at your own risk.


collection of all supported system call numbers
conversions of Oberon records into C structures and vice versa (may be needed for system calls)
collection of types which correspond to C type definitions which are used for system calls
allocation of storage which is not covered by the garbage collection


CC is not supported by Ulm's Oberon Compiler.
Edited by: borchert, last change: 2000/05/27, revision: 1.3, converted to HTML: 2000/05/27

Oberon || Library || Module Index || Search Engine || Definition || Module