NAME
ACK - Additional information on the Amsterdam Compiler Kit
compilers
DESCRIPTION
These are the details on the Amsterdam Compiler Kit com-
pilers for the languages C, Modula-2, and Pascal. The
design decisions that were made where the respective stan-
dards allowed or mandated this, and the extensions that were
implemented.
ANSI C REPORT
This section specifies the implementation-defined behavior
of the ANSI-C compiler as required by ANS X3.159-1989.
ANS A.6.3.1
o Diagnostics are placed on the standard error output.
They have the following specification:
"<file>", line <nr>: [(<class>)] <diagnostic>
There are three classes of diagnostics: 'error',
'strict' and 'warning'. When the class is 'error', the
class specification is absent. The class 'strict' is
used for violations of the standard which are not
severe enough to stop compilation, for example the
occurrence of non white-space after an '#endif' prepro-
cessing directive. The class 'warning' is used for
legal but dubious constructions, for example the
declaration of a structure-tag in a parameter type
list.
ANS A.6.3.2
o The function 'main' can have zero or two parameters.
When it has two parameters, the first parameter is an
integer specifying the number of arguments on the com-
mand line (including the command). The second parame-
ter is a pointer to an array of pointers to the argu-
ments (as strings).
o Interactive devices are terminals.
ANS A.6.3.3
o The number of significant characters is 64.
Corresponding upper-case and lower-case letters are
different.
ANS A.6.3.4
o The compiler assumes ASCII-characters in both the
source and execution character set.
o There are no multibyte characters.
o There are 8 bits in a character.
o Character constants that cannot be represented in 8
bits are truncated.
o Character constants that are more than 1 character wide
will have the first character specified in the least
significant byte.
o The only supported locale is 'C'.
o A plain 'char' has the same range of values as 'signed
char'.
ANS A.6.3.5
o The i80x86 and 68000 both have a two's complement
binary-number system. Shorts are 2 bytes; ints are 2
bytes under 16-bits Minix-PC and 68000 MINIX 3, 4 bytes
under 32-bits Minix-PC; longs occupy 4 bytes.
o Converting an integer to a shorter signed integer is
implemented by ignoring the high-order byte(s) of the
former. Converting a unsigned integer to a signed
integer of the same type is only done in administra-
tion. This means that the bit-pattern remains
unchanged.
o The result of bitwise operations on signed integers are
what can be expected on a two's complement machine.
o When either operand is negative, the result of the /
operator is the largest integer less than or equal to
the algebraic quotient. The sign of the remainder on
integer division is the sign of the enumerator.
o The right-shift of a negative value is negative.
ANS A.6.3.6
o The compiler uses IEEE format for floating-point
numbers. High-precision floating-point is used for
constant folding.
o Truncation is done to the nearest floating-point number
that can be represented.
ANS A.6.3.7
o The type of the sizeof-operator (also known as size_t)
is 'unsigned int'.
o Casting an integer to a pointer or vice versa has no
effect in bit-pattern when the sizes are equal. Other-
wise the value will be truncated or zero-extended
(depending on the direction of the conversion and the
relative sizes).
o The type of a 'ptrdiff_t' is 'int' on Minix-PC, and
'long' on the 68000 MINIX 3 versions.
ANS A.6.3.8
o Since the front end has only limited control over the
registers, it can only make it more likely that vari-
ables that are declared as registers also end up in
registers. The only things that can possibly be put
into registers are plain ints and pointers.
ANS A.6.3.9
o When a member of a union object is accessed using a
member of a different type, the resulting value will
usually be garbage. The compiler makes no effort to
catch these errors.
o The alignment of types under 16-bit Minix-PC is 1 byte
for characters and 2 bytes for all other types. Under
other MINIX 3 versions 'int' and smaller types are
aligned to a multiple of their size, bigger scalar
types are aligned like 'int'. Arrays have the same
alignment as their elements; structs and unions are
aligned like their field with the worst alignment.
o A plain 'int' bit-field is taken as a 'signed int'.
This means that a field with a size 1 bit-field can
only store the values 0 and -1.
o In bit-fields, high-order bits are allocated first.
o An enum has the same size as a plain 'int'.
ANS A.6.3.10
o An access to a volatile object is either a load or a
store. Just mentioning a volatile variable is not
enough. E.g. the statement 'x;' where x is declared
volatile, does not constitute an access. When a vola-
tile object should be read, but its value ignored, 'if
(x);' should do the trick.
ANS A.6.3.11
o There is no fixed limit on the number of declarators
that may modify an arithmetic, structure or union type,
although specifying too many may cause the compiler to
run out of memory.
ANS A.6.3.12
o The maximum number of cases in a switch-statement is in
the order of 1e9, although the compiler may run out of
memory somewhat earlier.
ANS A.6.3.13
o Since both the preprocessor and the compiler assume
ASCII-characters, a single character constant in a
conditional-inclusion directive matches the same value
in the execution character set.
o The preprocessor recognizes I... command-line options.
The directories thus specified are searched first.
After that, /usr/include is visited.
o Quoted names are first looked for in the directory in
which the file which does the include resides.
o The characters in a h- or q- char-sequence are taken to
be UNIX paths.
o Neither the front-end nor the preprocessor know any
pragmas.
o Since the compiler runs on MINIX 3 __DATE__ and
__TIME__ will always be defined.
ANS A.6.3.14
o NULL is defined as ((void *)0). This in order to
detect dubious constructions like 'int x = NULL;'.
o The diagnostic printed by 'assert' is as follows:
Assertion "<expr>" failed, file "<file>", line <line>
where <expr> is the argument to the assert macro,
printed as string. (the <file> and <line> should be
clear)
o The sets for character test macros for the C locale are
as follows:
Name Set
isalnum 0-9A-Za-z
isalpha A-Za-z
iscntrl \000-\037\177
islower a-z
isupper A-Z
isprint \040-\176
As an addition, there is an isascii macro, which tests
whether a character is an ASCII character. Characters
in the range from \000 to \177 are ASCII characters.
o The behavior of ACK mathematical functions on domain
error is as follows:
Name Returns
asin 0.0
acos 0.0
atan2 0.0
fmod 0.0
log -HUGE_VAL
log10 -HUGE_VAL
pow 0.0
sqrt 0.0
Minix-vmd uses the BSD4.4 C library and the Sun FDLIBM
C math library instead of the ACK library. See math(3)
for details about the math functions. The Minix-vmd
libraries offer at least the same functionality as the
ACK library.
o Underflow range errors do not cause errno to be set.
o The function fmod returns 0.0 and sets errno to EDOM
when the second argument is 0.0.
o The set of signals for the signal function is as
described by sigaction(2).
o A text-stream need not end in a new-line character.
o White space characters before a new-line appear when
read in.
o There may be any number of null characters appended to
a binary stream.
o The file position indicator of an append mode stream is
initially positioned at the beginning of the file.
o A write on a text stream does not cause the associated
file to be truncated beyond that point.
o The buffering intended by the standard is fully sup-
ported.
o A zero-length file actually exists.
o A file name can consist of any character, except for
the '\0' and the '/'.
o A file can be open multiple times.
o When a remove is done on an open file, reading and
writing behave just as can be expected from a non-
removed file. When the associated stream is closed,
however, all written data will be lost.
o When a file exists prior to a call to rename, it is
removed.
o The %p conversion in fprintf has the same effect as %#x
on Minix-PC and %#lx on the 68000 versions of MINIX 3.
o The %p conversion in fscanf has the same effect as %x
on Minix-PC and %lx on the 68000 versions of MINIX 3.
o A - character that is neither the first nor the last
character in the scanlist for %[ conversion is taken to
be a range indicator. When the first character has a
higher ASCII-value than the second, the - will just be
put into the scanlist.
o The value of errno when fgetpos or ftell failed is that
of lseek. This means:
EBADF - when the stream is not valid
ESPIPE - when fildes is associated with a pipe
EINVAL - the resulting file pointer would be negative
o The messages generated by perror depend on the value of
errno. The mapping of errors to strings is done by
strerror.
o When the requested size is zero, malloc, calloc and
realloc return a null-pointer under MINIX 3. Under
Minix-vmd a unique non-null pointer is returned.
o When abort is called, output buffers will be flushed.
Temporary files (made with the tmpfile function) will
have disappeared when SIGABRT is not caught or ignored.
o The exit function returns the low-order eight bits of
its argument to the environment.
o The predefined environment names are controlled by the
user. Setting environment variables is done through
the putenv function. This function accepts a pointer
to char as its argument. To set, for example, the
environment variable TERM to a230 one writes
static char terminal[] = "TERM=a230";
putenv(terminal);
The argument to putenv is stored in an internal table,
so malloc'ed strings cannot be freed until another call
to putenv (which sets the same environment variable) is
made. The argument to putenv must be writable, which
means that officially, the argument cannot be a string
constant. The function returns 1 if it fails, 0 other-
wise.
o The argument to system is passed as argument to /bin/sh
c.
o The strings returned by strerror depend on errno. They
are listed in intro(2). Everything else causes strer-
ror to return "unknown error" under MINIX 3, or the
result of sprintf("Error %d", errno) under Minix-vmd.
o The local time zone is per default GMT. This can be
changed through the TZ environment variable, e.g.
TZ=EST6. See TZ(5).
o The clock function returns the number of ticks since
process startup.
References
[1] ANS X3.159-1989 American National Standard for Informa-
tion Systems - Programming Language C
THE MINIX MODULA-2 COMPILER
This section describes the implementation-specific features
of the MINIX 3 Modula-2 compiler. It is not intended to
teach Modula-2 programming. For a description of the
Modula-2 language, the reader is referred to [1].
The language implemented
This paragraph discusses the deviations from the Modula-2
language as described in the 'Report on The Programming
Language Modula-2', as it appeared in [1], from now on
referred to as 'the Report'. Also, the Report sometimes
leaves room for interpretation. The section numbers men-
tioned are the section numbers of the Report.
Syntax (section 2)
The syntax recognized is that of the Report, with some
extensions to also recognize the syntax of an earlier defin-
ition, given in [2]. Only one compilation unit per file is
accepted.
Vocabulary and Representation (section 3)
The input '10..' is parsed as two tokens: '10' and '..'.
The empty string "" has type
ARRAY [0 .. 0] OF CHAR
and contains one character: 0C.
When the text of a comment starts with a '$', it may be a
pragma. Currently, the following pragmas exist:
(*$F (F stands for Foreign) *)
(*$R[+|-] (Runtime checks, on or off, default on) *)
(*$A[+|-] (Array bound checks, on or off, default off) *)
(*$U (Allow for underscores within identifiers) *)
The Foreign pragma is only meaningful in a DEFINITION
MODULE, and indicates that this DEFINITION MODULE describes
an interface to a module written in another language (for
instance C or Pascal). Runtime checks that can be disabled
are: range checks, CARDINAL overflow checks, checks when
assigning a CARDINAL to an INTEGER and vice versa, and
checks that FOR-loop control-variables are not changed in
the body of the loop. Array bound checks can be enabled,
because many EM implementations do not implement the array
bound checking of the EM array instructions. When enabled,
the compiler generates a check before generating an EM array
instruction. Even when underscores are enabled, they still
may not start an identifier.
Constants of type LONGINT are integers with a suffix letter
D (for instance 1987D). Constants of type LONGREAL have
suffix D if a scale factor is missing, or have D in place of
E in the scale factor (f.i. 1.0D, 0.314D1). This addition
was made, because there was no way to indicate long con-
stants, and also because the addition was made in Wirth's
newest Modula-2 compiler.
Declarations and scope rules (section 4)
Standard identifiers are predeclared, and valid in all parts
of a program. They are called pervasive. Unfortunately,
the Report does not state how this pervasiveness is accom-
plished. However, page 87 of [1] states: 'Standard identif-
iers are automatically imported into all modules'. Our
implementation therefore allows redeclarations of standard
identifiers within procedures, but not within modules.
Constant expressions (section 5)
Each operand of a constant expression must be a constant: a
string, a number, a set, an enumeration literal, a qualifier
denoting a constant expression, a type transfer with a con-
stant argument, or one of the standard procedures ABS, CAP,
CHR, LONG, MAX, MIN, ODD, ORD, SIZE, SHORT, TSIZE, or VAL,
with constant argument(s); TSIZE and SIZE may also have a
variable as argument.
Type declarations (section 6)
1. Basic types (section 6.1)
The type CHAR includes the ASCII character set as a subset.
Values range from 0C to 377C, not from 0C to 177C.
2. Enumerations (section 6.2)
The maximum number of enumeration literals in any one
enumeration type is MAX(INTEGER).
3. Record types (section 6.5)
The syntax of variant sections in [1] is different from the
one in [2]. Our implementation recognizes both, giving a
warning for the older one.
4. Set types (section 6.6)
The only limitation imposed by the compiler is that the base
type of the set must be a subrange type, an enumeration
type, CHAR, or BOOLEAN. So, the lower bound may be nega-
tive. However, if a negative lower bound is used, the com-
piler gives a warning of the restricted class.
The standard type BITSET is defined as
TYPE BITSET = SET OF [0 .. 8*SIZE(INTEGER)-1];
Expressions (section 8)
1. Operators (section 8.2)
1.1. Arithmetic operators (section 8.2.1)
The Report does not specify the priority of the unary opera-
tors + or -: It does not specify whether
- 1 + 1
means
- (1 + 1)
or
(-1) + 1
The MINIX 3 Modula-2 compiler implements the second alterna-
tive.
Statements (section 9)
1. Assignments (section 9.1)
The Report does not define the evaluation order in an
assignment. Our compiler certainly chooses an evaluation
order, but it is explicitly left undefined. Therefore, pro-
grams that depend on it may cease to work later.
The types INTEGER and CARDINAL are assignment-compatible
with LONGINT, and REAL is assignment-compatible with LONG-
REAL.
2. Case statements (section 9.5)
The size of the type of the case-expression must be less
than or equal to the word-size.
The Report does not specify what happens if the value of the
case-expression does not occur as a label of any case, and
there is no ELSE-part. In our implementation, this results
in a runtime error.
3. For statements (section 9.8)
The Report does not specify the legal types for a control
variable. Our implementation allows the basic types (except
REAL), enumeration types, and subranges. A runtime warning
is generated when the value of the control variable is
changed by the statement sequence that forms the body of the
loop, unless runtime checking is disabled.
4. Return and exit statements (section 9.11)
The Report does not specify which result-types are legal.
Our implementation allows any result type.
Procedure declarations (section 10)
Function procedures must exit through a RETURN statement, or
a runtime error occurs.
1. Standard procedures (section 10.2)
Our implementation supports NEW and DISPOSE for backwards
compatibility, but issues warnings for their use.
Also, some new standard procedures were added, similar to
the new standard procedures in Wirth's newest compiler:
- LONG converts an argument of type INTEGER or REAL to
the types LONGINT or LONGREAL.
- SHORT performs the inverse transformation, without
range checks.
- FLOATD is analogous to FLOAT, but yields a result of
type LONGREAL.
- TRUNCD is analogous to TRUNC, but yields a result of
type LONGINT.
System-dependent facilities (section 12)
The type BYTE is added to the SYSTEM module. It occupies a
storage unit of 8 bits. ARRAY OF BYTE has a similar effect
to ARRAY OF WORD, but is safer. In some obscure cases the
ARRAY OF WORD mechanism does not quite work properly.
The procedure IOTRANSFER is not implemented.
Backwards compatibility
Besides recognizing the language as described in [1], the
compiler recognizes most of the language described in [2],
for backwards compatibility. It warns the user for old-
fashioned constructions (constructions that [1] does not
allow). If the 3 option is passed to m2, this backwards
compatibility feature is disabled.
Compile time errors
The compile time error messages are intended to be self-
explanatory, and not listed here. The compiler also some-
times issues warnings, recognizable by a warning-
classification between parentheses. There are 3 classifica-
tions:
(old-fashioned use)
These warnings are given on constructions that are not
allowed by [1], but are allowed by [2].
(strict)
These warnings are given on constructions that are sup-
ported by the MINIX 3 Modula-2 compiler, but might not
be supported by others. Examples: functions returning
structured types, SET types of subranges with negative
lower bound.
(warning)
The other warnings, such as warnings about variables
that are never assigned, never used, etc.
Runtime errors
The Traps module enables the user to install his own runtime
error handler. The default one just displays what happened
and exits. Basically, a trap handler is just a procedure
that takes an INTEGER as parameter. The INTEGER is the trap
number. This INTEGER can be one of the EM trap numbers,
listed in [3], or one of the numbers listed in the Traps
definition module.
The following runtime errors may occur:
array bound error
This error is detected if the A option is given to m2.
range bound error
Range bound errors are always detected, unless runtime
checks are disabled.
set bound error
cardinal overflow
This error is detected, unless runtime checks are dis-
abled.
cardinal underflow
This error is detected, unless runtime checks are dis-
abled.
divide by 0
divide by 0.0
conversion error
This error occurs when assigning a negative value of
type INTEGER to a variable of type CARDINAL, or when
assigning a value of CARDINAL that is > MAX(INTEGER),
to a variable of type INTEGER. It is detected, unless
runtime checking is disabled.
heap overflow
This might happen when ALLOCATE fails.
case error
This error occurs when non of the cases in a CASE
statement are selected, and the CASE statement has no
ELSE part.
stack size of process too large
This is most likely to happen if the reserved space for
a coroutine stack is too small. In this case, increase
the size of the area given to NEWPROCESS. It can also
happen if the stack needed for the main process is too
large and there are coroutines. In this case, the only
fix is to reduce the stack size needed by the main pro-
cess, f.i. by avoiding local arrays.
too many nested traps + handlers
This error can only occur when the user has installed
his own trap handler. It means that during execution
of the trap handler another trap has occurred, and that
several times. In some cases, this is an error because
of overflow of some internal tables.
no RETURN from function procedure
This error occurs when a function procedure does not
return properly ('falls' through).
illegal instruction
This error might occur when you use floating point
operations on an implementation that does not have
floating point.
In addition, some of the library modules may give error mes-
sages. The Traps-module has a suitable mechanism for this.
The procedure call interface
Parameters are pushed on the stack in reversed order. For
VAR parameters, its address is passed, for value parameters
its value. The only exception to this rule is with confor-
mant arrays. For conformant arrays, the address is passed,
and an array descriptor is passed. The descriptor is an EM
array descriptor. It consists of three fields: the lower
bound (always 0), upper bound - lower bound, and the size of
the elements. The descriptor is pushed first. If the
parameter is a value parameter, the called routine must make
sure that its value is never changed, for instance by making
its own copy of the array.
When the size of the return value of a function procedure is
larger than the maximum of SIZE(LONGREAL) and twice the
pointer-size, the caller reserves this space on the stack,
above the parameters. Callee then stores its result there,
and returns no other value.
The Modula-2 runtime library
The definition modules of the modules available in the MINIX
3 Modula-2 runtime library reside in the directory
/usr/lib/ack/m2.
References
[1] Niklaus Wirth, Programming in Modula-2, third,
corrected edition, Springer-Verlag, Berlin (1985)
[2] Niklaus Wirth, Programming in Modula-2, Stringer-
Verlag, Berlin (1983)
[3] A.S.Tanenbaum, J.W.Stevenson, Hans van Staveren,
E.G.Keizer, Description of a machine architecture for
use with block structured languages, Informatica rap-
port IR-81, Vrije Universiteit, Amsterdam
THE MINIX PASCAL COMPILER
This section refers to the (1982) BSI standard for Pascal
[1]. MINIX 3 Pascal complies with the requirements of level
1 of BS 6192: 1982, with the exceptions as listed in this
section.
The standard requires an accompanying document describing
the implementation-defined and implementation-dependent
features, the reaction on errors and the extensions to stan-
dard Pascal. These four items will be treated in the rest
of this section.
Implementation-defined features
For each implementation-defined feature mentioned in the BSI
standard we give the section number, the quotation from that
section and the definition. First we quote the definition
of implementation-defined:
Possibly differing between processors, but defined for
any particular processor.
BS 6.1.7: Each string-character shall denote an
implementation-defined value of the required char-type.
All 7-bit ASCII characters except linefeed LF (10) are
allowed.
BS 6.4.2.2: The values of type real shall be an
implementation-defined subset of the real numbers denoted as
specified by 6.1.5 by the signed-real values.
The set of real values range from a low of
-1.7976931348623157e+308 to a high of
1.7976931348623157e+308.
BS 6.4.2.2: The type char shall be the enumeration of a set
of implementation-defined characters, some possibly without
graphic representations.
The 7-bit ASCII character set is used, where LF (10)
denotes the end-of-line marker on text-files.
BS 6.4.2.2: The ordinal numbers of the character values
shall be values of integer-type, that are implementation-
defined, and that are determined by mapping the character
values on to consecutive non-negative integer values start-
ing at zero.
The normal ASCII ordering is used: ord('0')=48,
ord('A')=65, ord('a')=97, etc.
BS 6.6.5.2: The post-assertions imply corresponding activi-
ties on the external entities, if any, to which the file-
variables are bound. These activities, and the point at
which they are actually performed, shall be implementation-
defined.
The reading and writing writing of objects on files is
buffered. This means that when a program terminates
abnormally, I/O may be unfinished. Terminal I/O is
unbuffered. Files are closed whenever they are rewrit-
ten or reset, or on program termination.
BS 6.7.2.2: The predefined constant maxint shall be of
integer-type and shall denote an implementation-defined
value, that satisfies the following conditions:
(a) All integral values in the closed interval from -maxint
to +maxint shall be values of the integer-type.
(b) Any monadic operation performed on an integer value in
this interval shall be correctly performed according to
the mathematical rules for integer arithmetic.
(c) Any dyadic integer operation on two integer values in
this same interval shall be correctly performed accord-
ing to the mathematical rules for integer arithmetic,
provided that the result is also in this interval.
(d) Any relational operation on two integer values in this
same interval shall be correctly performed according to
the mathematical rules for integer arithmetic.
The representation of integers under 16-bit Minix-PC or
under 68000 MINIX 3 is a 16-bit word using two's com-
plement arithmetic. The integers range from -32768 to
+32767. Under 32-bit Minix-PC a 32-bit integer is used
ranging from -2147483648 to +2147483647.
BS 6.7.2.2: The result of the real arithmetic operators and
functions shall be approximations to the corresponding
mathematical results. The accuracy of this approximation
shall be implementation-defined
The default size of reals is 8 bytes, the accuracy is
11 bits for the exponent, and 53 bits for the mantissa.
This gives an accuracy of about 16 digits. and
exponents ranging from -307 to +307.
BS 6.9.3.1: The default TotalWidth values for integer,
Boolean and real types shall be implementation-defined.
The defaults are:
integer 6 (16-bit)
integer 11 (32-bit)
Boolean 5
real 14
BS 6.9.3.4.1: ExpDigits, the number of digits written in an
exponent part of a real, shall be implementation-defined.
ExpDigits is defined as 3.
BS 6.9.3.4.1: The character written as part of the represen-
tation of a real to indicate the beginning of the exponent
part shall be implementation-defined, either 'E' or 'e'.
The exponent part starts with 'e'.
BS 6.9.3.5: The case of the characters written as represen-
tation of the Boolean values shall be implementation-
defined.
The representations of true and false are 'true' and
'false'.
BS 6.9.5: The effect caused by the standard procedure page
on a text file shall be implementation-defined.
The ASCII character form feed FF (12) is written.
BS 6.10: The binding of the variables denoted by the
program-parameters to entities external to the program shall
be implementation-defined if the variable is of a file-type.
The program parameters must be files and all, except
input and output, must be declared as such in the pro-
gram block.
The program parameters input and output, if specified, will
correspond with the UNIX streams 'standard input' and
'standard output'.
The other program parameters will be mapped to the argument
strings provided by the caller of this program. The argu-
ment strings are supposed to be path names of the files to
be opened or created. The order of the program parameters
determines the mapping: the first parameter is mapped onto
the first argument string, etc. Note that input and output
are ignored in this mapping.
The mapping is recalculated each time a program parameter is
opened for reading or writing by a call to the standard pro-
cedures reset or rewrite. This gives the programmer the
opportunity to manipulate the list of string arguments using
the external procedures argc, argv and argshift available in
the Pascal library.
BS 6.10: The effect of an explicit use of reset or rewrite
on the standard text files input or output shall be
implementation-defined.
The procedures reset and rewrite are no-ops if applied
to input or output.
Implementation-dependent features
For each implementation-dependent feature mentioned in the
BSI standard, we give the section number, the quotation from
that section and the way this feature is treated by the
MINIX 3 Pascal system. First we quote the definition of
'implementation-dependent':
Possibly differing between processors and not neces-
sarily defined for any particular processor.
BS 6.7.2.1: The order of evaluation of the operands of a
dyadic operator shall be implementation-dependent.
Operands are always evaluated, so the program part
if (p<>nil) and (p^.value<>0) then
is probably incorrect.
The left-hand operand of a dyadic operator is almost always
evaluated before the right-hand side. Some peculiar evalua-
tions exist for the following cases:
1. The modulo operation is performed by a library routine
to check for negative values of the right operand.
2. The expression
set1 <= set2
where set1 and set2 are compatible set types is
evaluated in the following steps:
- evaluate set2;
- evaluate set1;
- compute set2+set1;
- test set2 and set2+set1 for equality.
3. The expression
set1 >= set2
where set1 and set2 are compatible set types is
evaluated in the following steps:
- evaluate set1;
- evaluate set2;
- compute set1+set2;
- test set1 and set1+set2 for equality.
BS 6.7.3: The order of evaluation, accessing and binding of
the actual-parameters for functions shall be
implementation-dependent.
The order of evaluation is from right to left.
BS 6.8.2.2: The decision as to the order of accessing the
variable and evaluating the expression in an assignment-
statement, shall be implementation-dependent.
The expression is evaluated first.
BS 6.8.2.3: The order of evaluation and binding of the
actual-parameters for procedures shall be implementation-
dependent.
The same as for functions.
BS 6.9.5: The effect of inspecting a text file to which the
page procedure was applied during generation is
implementation-dependent.
The formfeed character written by page is treated like
a normal character, with ordinal value 12.
BS 6.10: The binding of the variables denoted by the
program-parameters to entities external to the program shall
be implementation-dependent unless the variable is of a
file-type.
Only variables of a file-type are allowed as program
parameters.
Error handling
There are three classes of errors to be distinguished. In
the first class are the error messages generated by the com-
piler. The second class consists of the occasional errors
generated by the other programs involved in the compilation
process. Errors of the third class are the errors as
defined in the standard by:
An error is a violation by a program of the require-
ments of this standard that a processor is permitted to
leave undetected.
Compiler errors
Error are written on the standard error output. Each line
has the form:
<file>, line <number>: <description>
Every time the compiler detects an error that does not have
influence on the code produced by the compiler or on the
syntax decisions, a warning messages is given. If only
warnings are generated, compilation proceeds and probably
results in a correctly compiled program.
Sometimes the compiler produces several errors for the same
line. They are only shown up to a maximum of 5 errors per
line. Warning are also shown up to a maximum of 5 per line.
Extensive treatment of these errors is outside the scope of
this manual.
Runtime errors
Errors detected at run time cause an error message to be
generated on the diagnostic output stream (UNIX file
descriptor 2). The message consists of the name of the pro-
gram followed by a message describing the error, possibly
followed by the source line number. Unless the n option is
turned on, the compiler generates code to keep track of
which source line causes which instructions to be generated.
For each error mentioned in the standard we give the section
number, the quotation from that section and the way it is
processed by the Pascal-compiler or runtime system.
For detected errors the corresponding message and trap
number are given. Trap numbers are useful for exception-
handling routines. Normally, each error causes the program
to terminate. By using exception-handling routines one can
ignore errors or perform alternate actions. Only some of
the errors can be ignored by restarting the failing instruc-
tion. These errors are marked as non-fatal, all others as
fatal. A list of errors with trap number between 0 and 63
(EM errors) can be found in [2]. Errors with trap number
between 64 and 127 (Pascal errors) are listed below.
BS 6.4.6: It shall be an error if a value of type T2 must be
assignment-compatible with type T1, while T1 and T2 are com-
patible ordinal-types and the value of type T2 is not in the
closed interval specified by T1.
The compiler distinguishes between array-index expres-
sions and the other places where assignment-
compatibility is required.
Array subscripting errors are only detected when the 'A'
option is used. In the other cases, a range bound error
occurs when the value of type T2 is not in the closed inter-
val specified by T1, unless range checks are disabled.
BS 6.4.6: It shall be an error if a value of type T2 must be
assignment-compatible with type T1, while T1 and T2 are com-
patible set-types and any member of the value of type T2 is
not in the closed interval specified by the base-type of the
type T1.
This error is not detected.
BS 6.5.3.3: It shall be an error if a component of a
variant-part of a variant, where the selector of the
variant-part is not a field, is accessed unless the variant
is active for the entirety of each reference and access to
each component of the variant.
This error is not detected.
BS 6.5.4: It shall be an error if the pointer-variable of an
identified-variable either denotes a nil-value or is unde-
fined.
This error is not detected.
BS 6.5.4: It shall be an error to remove the identifying-
value of an identified variable from its pointer-type when a
reference to the variable exists.
When the identified variable is an element of the
record-variable-list of a with-statement, a warning is
given at compile-time. Otherwise, this error is not
detected.
BS 6.5.5: It shall be an error to alter the value of a
file-variable f when a reference to the buffer-variable f^
exists.
When f is altered when it is an element of the record-
variable-list of a with-statement, a warning is given.
When a buffer-variable is used as a variable-parameter,
an error is given. This is done at compile-time.
BS 6.6.5.2: It shall be an error if the stated pre-assertion
does not hold immediately prior to any use of the file han-
dling procedures rewrite, put, reset and get.
For each of these four operations the pre-assertions
can be reformulated as:
rewrite(f): no pre-assertion.
put(f): f is opened for writing and f^ is not undefined.
reset(f): f exists.
get(f): f is opened for reading and eof(f) is false.
The following errors are detected for these operations:
rewrite(f):
more args expected, trap 64, fatal:
f is a program-parameter and the corresponding
file name is not supplied by the caller of the
program.
rewrite error, trap 101, fatal:
the caller of the program lacks the necessary
access rights to create the file in the file sys-
tem or operating system problems like table over-
flow prevent creation of the file.
put(f):
file not yet open, trap 72, fatal:
reset or rewrite are never applied to the file.
The checks performed by the run time system are
not foolproof.
not writable, trap 96, fatal:
f is opened for reading.
write error, trap 104, fatal:
probably caused by file system problems. For
instance, the file storage is exhausted. Because
I/O is buffered to improve performance, it might
happen that this error occurs if the file is
closed. Files are closed whenever they are
rewritten or reset, or on program termination.
reset(f):
more args expected, trap 64, fatal:
same as for rewrite(f).
reset error, trap 100, fatal:
f does not exist, or the caller has insufficient
access rights, or operating system tables are
exhausted.
get(f):
file not yet open, trap 72, fatal:
as for put(f).
not readable, trap 97, fatal:
f is opened for writing.
end of file, trap 98, fatal:
eof(f) is true just before the call to get(f).
read error, trap 103, fatal:
unlikely to happen. Probably caused by hardware
problems or by errors elsewhere in your program
that destroyed the file information maintained by
the run time system.
truncated, trap 99, fatal:
the file is not properly formed by an integer
number of file elements. For instance, the size
of a file of integer is odd.
non-ASCII char read, trap 106, non-fatal:
the character value of the next character-type
file element is out of range (0..127). Only for
text files.
BS 6.6.5.3: It shall be an error if a variant of a variant-
part within the new variable becomes active and a different
variant of the variant-part is one of the specified vari-
ants.
This error is not detected.
BS 6.6.5.3: It shall be an error to use dispose(q) if the
identifying variable has been allocated using the form
new(p,c1,...,cn).
This error is not detected. However, this error can
cause more memory to be freed then was allocated.
Dispose causes a fatal trap 73 when memory already on
the free list is freed again.
BS 6.6.5.3: It shall be an error to use dispose(q,k1,...,km)
if the identifying variable has been allocated using the
form new(p,c1,...,cn) and m is not equal to n.
This error is not detected. However, this error can
cause more memory to be freed then was allocated.
Dispose causes a fatal trap 73 when memory already on
the free list is freed again.
BS 6.6.5.3: It shall be an error if the variants of a vari-
able to be disposed are different from those specified by
the case-constants to dispose.
This error is not detected.
BS 6.6.5.3: It shall be an error if the value of the pointer
parameter of dispose has nil-value or is undefined.
This error is detected for nil-value (dispose error,
trap 73, fatal).
BS 6.6.5.3: It shall be an error if a variable created using
the second form of new is accessed by the identified vari-
able of the variable-access of a factor, of an assignment-
statement, or of an actual-parameter.
This error is not detected.
BS 6.6.6.2: It shall be an error if the value of sqr(x) does
not exist.
This error is detected for real-type arguments (real
overflow, trap 4, non-fatal).
BS 6.6.6.2: It shall be an error if x in ln(x) is smaller
than or equal to 0.
This error is detected (error in ln, trap 66, non-
fatal)
BS 6.6.6.2: It shall be an error if x in sqrt(x) is smaller
than 0.
This error is detected (error in sqrt, trap 67, non-
fatal)
In addition to these errors, overflow in the expression
exp(x) is detected (error in exp, trap 65, non-fatal;
real overflow, trap 4, non-fatal)
BS 6.6.6.3: It shall be an error if the integer value of
trunc(x) does not exist.
This error is detected (conversion error, trap 10,
non-fatal).
BS 6.6.6.3: It shall be an error if the integer value of
round(x) does not exist.
This error is detected (conversion error, trap 10,
non-fatal).
BS 6.6.6.4: It shall be an error if the integer value of
ord(x) does not exist.
This error can not occur, because the compiler will not
allow such ordinal types.
BS 6.6.6.4: It shall be an error if the character value of
chr(x) does not exist.
This error is detected (range bound error, trap 1,
non-fatal).
BS 6.6.6.4: It shall be an error if the value of succ(x)
does not exist.
Same comments as for chr(x).
BS 6.6.6.4: It shall be an error if the value of pred(x)
does not exist.
Same comments as for chr(x).
BS 6.6.6.5: It shall be an error if f in eof(f) is unde-
fined.
This error is detected (file not yet open, trap 72,
fatal).
BS 6.6.6.5: It shall be an error if f in eoln(f) is unde-
fined, or if eof(f) is true at that time.
The following errors may occur:
file not yet open, trap 72, fatal;
not readable, trap 97, fatal;
end of file, trap 98, fatal.
BS 6.7.1: It shall be an error if a variable-access used as
an operand in an expression is undefined at the time of its
use.
The compiler performs some limited checks to see if
identifiers are used before they are set. Since it can
not always be sure (one could, for instance, jump out
of a loop), only a warning is generated. When an
expression contains a function-call, an error occurs if
the function is not assigned at run-time.
BS 6.7.2.2: A term of the form x/y shall be an error if y is
zero.
This error is detected (divide by 0.0, trap 7, non-
fatal).
BS 6.7.2.2: It shall be an error if j is zero in 'i div j'.
This error is detected (divide by 0, trap 6, non-
fatal).
BS 6.7.2.2: It shall be an error if j is zero or negative in
i MOD j.
This error is detected (only positive j in 'i mod j',
trap 71, non-fatal).
BS 6.7.2.2: It shall be an error if the result of any opera-
tion on integer operands is not performed according to the
mathematical rules for integer arithmetic.
This implementation does not detect integer overflow.
BS 6.8.3.5: It shall be an error if none of the case-
constants is equal to the value of the case-index upon entry
to the case-statement.
This error is detected (case error, trap 20, fatal).
BS 6.9.1: It shall be an error if the sequence of characters
read looking for an integer does not form a signed-integer
as specified in 6.1.5.
This error is detected (digit expected, trap 105, non-
fatal).
BS 6.9.1: It shall be an error if the sequence of characters
read looking for a real does not form a signed-number as
specified in 6.1.5.
This error is detected (digit expected, trap 105, non-
fatal).
BS 6.9.1: When read is applied to f, it shall be an error if
the buffer-variable f^ is undefined or the pre-assertions
for get do not hold.
This error is detected (see get(f)).
BS 6.9.3: When write is applied to a text file f, it shall
be an error if f is undefined or f is opened for reading.
This error is detected (see put(f)). Furthermore, this
error is also detected when f is not a text file.
BS 6.9.3.1: The values of TotalWidth or FracDigits shall be
greater than or equal to one; it shall be an error if either
value is less then one.
When either value is less than zero, an error (illegal
field width, trap 75, non-fatal) occurs. Zero values
are allowed, in order to maintain some compatibility
with the old MINIX 3 Pascal compiler.
BS 6.9.5: It shall be an error if the pre-assertion required
for writeln(f) doe not hold prior to the invocation of
page(f);
This error is detected (see put(f)).
Extensions to the standard
1. External routines
Except for the required directive 'forward' the MINIX 3 Pas-
cal compiler recognizes the directive 'extern'. This direc-
tive tells the compiler that the procedure block of this
procedure will not be present in the current program. The
code for the body of this procedure must be included at a
later stage of the compilation process.
This feature allows one to build libraries containing often
used routines. These routines do not have to be included in
all the programs using them. Maintenance is much simpler if
there is only one library module to be changed instead of
many Pascal programs.
Another advantage is that these library modules may be writ-
ten in a different language, for instance C.
The use of external routines, however, is dangerous. The
compiler normally checks for the correct number and type of
parameters when a procedure is called and for the result
type of functions. If an external routine is called these
checks are not sufficient, because the compiler can not
check whether the procedure heading of the external routine
as given in the Pascal program matches the actual routine
implementation. It should be the loader's task to check
this. However, the current loaders are not that smart.
For those who wish the use the interface between C and Pas-
cal we give an incomplete list of corresponding formal
parameters in C and Pascal.
Pascal C
a:integer int a
a:char int a
a:boolean int a
a:real double a
a:^type type *a
var a:type type *a
procedure a(pars) struct {
void (*a)() ;
char *static_link ;
}
function a(pars):type struct {
type (*a)() ;
char *static_link ;
}
The Pascal runtime system uses the following algorithm when
calling function/procedures passed as parameters.
if (static_link) {
(*a)(static_link, pars);
} else {
(*a)(pars);
}
2. Separate compilation.
The compiler is able to (separately) compile a collection of
declarations, procedures and functions to form a library.
The library may be linked with the main program, compiled
later. The syntax of these modules is
module = [constant-definition-part]
[type-definition-part]
[var-declaration-part]
[procedure-and-function-declaration-part]
The compiler accepts a program or a module:
unit = program | module
All variables declared outside a module must be imported by
parameters, even the files input and output. Access to a
variable declared in a module is only possible using the
procedures and functions declared in that same module. By
giving the correct procedure/function heading followed by
the directive 'extern' you may use procedures and functions
declared in other units.
3. Assertions.
When the s-option is off, MINIX 3 Pascal compiler recognizes
an additional statement, the assertion. Assertions can be
used as an aid in debugging and documentation. The syntax
is:
assertion = 'assert' Boolean-expression
An assertion is a simple-statement, so
simple-statement = [assignment-statement |
procedure-statement |
goto-statement |
assertion
]
An assertion causes an error if the Boolean-expression is
false. That is its only purpose. It does not change any of
the variables, at least it should not. Therefore, do not
use functions with side-effects in the Boolean-expression.
If the a-option is turned on, then assertions are skipped by
the compiler. 'assert' is not a word-symbol (keyword) and
may be used as identifier. However, assignment to a vari-
able and calling of a procedure with that name will be
impossible. If the s-option is turned on, the compiler will
not know a thing about assertions, so using assertions will
then give a parse error.
4. Additional procedures.
Three additional standard procedures are available:
halt:
a call of this procedure is equivalent to jumping to
the end of your program. It is always the last state-
ment executed. The exit status of the program may be
supplied as optional argument. If not, it will be
zero.
release:
mark:
for most applications it is sufficient to use the heap
as second stack. Mark and release are suited for this
type of use, more suited than dispose. mark(p), with p
of type pointer, stores the current value of the heap
pointer in p. release(p), with p initialized by a call
of mark(p), restores the heap pointer to its old value.
All the heap objects, created by calls of new between
the call of mark and the call of release, are removed
and the space they used can be reallocated. Never use
mark and release together with dispose!
5. UNIX interfacing.
If the c-option is turned on, then some special features are
available to simplify an interface with the UNIX environ-
ment. First of all, the compiler allows you to use a dif-
ferent type of string constants. These string constants are
delimited by double quotes ('"'). To put a double quote
into these strings, you must repeat the double quote, like
the single quote in normal string constants. These special
string constants are terminated by a zero byte (chr(0)).
The type of these constants is a pointer to a packed array
of characters, with lower bound 1 and unknown upper bound.
Secondly, the compiler predefines a new type identifier
'string' denoting this just described string type.
The only thing you can do with these features is declaration
of constants and variables of type 'string'. String objects
may not be allocated on the heap and string pointers may not
be de-referenced. Still these strings are very useful in
combination with external routines. The procedure write is
extended to print these zero-terminated strings correctly.
6. Double length (32 bit) integers.
If the d-option is turned on, then the additional type
'long' is known to the compiler. Long variables have
integer values in the range -2147483648 .. +2147483647.
Long constants can not be declared. Longs can not be used
as control-variables. It is not allowed to form subranges
of type long. All operations allowed on integers are also
allowed on longs and are indicated by the same operators:
'+', '-', '*', '/', 'div', 'mod'. The procedures read and
write have been extended to handle long arguments correctly.
It is possible to read longs from a file of integers and
vice-versa, but only if longs and integers have the same
size. The default width for longs is 11. The standard pro-
cedures 'abs' and 'sqr' have been extended to work on long
arguments. Conversion from integer to long, long to real,
real to long and long to integer are automatic, like the
conversion from integer to real. These conversions may
cause a
conversion error, trap 10, non-fatal
7. Underscore as letter.
The character '_' may be used in forming identifiers, if the
u- or U-option is turned on. It is forbidden to start iden-
tifiers with underscores, since this may cause name-clashes
with run-time routines.
8. Zero field width in write.
Zero TotalWidth arguments are allowed. In this case, no
characters are written for character, string or Boolean type
arguments. A zero FracDigits argument for fixed-point
representation of reals causes the fraction and the charac-
ter '.' to be suppressed.
9. Pre-processing.
If the very first character of a file containing a Pascal
program is the sharp ('#', ASCII 23(hex)) the file is
preprocessed in the same way as C programs. Lines beginning
with a '#' are taken as preprocessor command lines and not
fed to the Pascal compiler proper. C style comments,
/*......*/, are removed by the C preprocessor, thus C com-
ments inside Pascal programs are also removed when they are
fed through the preprocessor.
Deviations from the standard
MINIX 3 Pascal deviates from the standard in the following
ways:
1. Standard procedures and functions are not allowed as
parameters in MINIX 3 Pascal. You can obtain the same
result with negligible loss of performance by declaring
some user routines like:
function sine(x:real):real;
begin
sine:=sin(x)
end;
2. The standard procedures read, readln, write and writeln
are implemented as word-symbols, and can therefore not
be redeclared.
Compiler options
Some options of the compiler may be controlled by using
'{$....}'. Each option consists of a lower case letter fol-
lowed by +, - or an unsigned number. Options are separated
by commas. The following options exist:
a+/- This option switches assertions on and off. If this
option is on, then code is included to test these
assertions at run time. Default +.
c+/- This option, if on, allows you to use C-type string
constants surrounded by double quotes. Moreover, a new
type identifier 'string' is predefined. Default -.
d+/- This option, if on, allows you to use variables of type
'long'. Default -.
i<num>
With this flag the setsize for a set of integers can be
manipulated. The number must be the number of bits per
set. The default value is 16.
l+/- If + then code is inserted to keep track of the source
line number. When this flag is switched on and off, an
incorrect line number may appear if the error occurs in
a part of your program for which this flag is off.
Default +.
r+/- If + then code is inserted to check subrange variables
against lower and upper subrange limits. Default +.
s+/- If + then the compiler will hunt for places in your
program where non-standard features are used, and for
each place found it will generate a warning. Default
-.
t+/- If + then each time a procedure is entered, the routine
'procentry' is called, and each time a procedure exits,
the procedure 'procexit' is called. Both 'procentry'
and 'procexit' have a 'string' as parameter. This
means that when a user specifies his or her own pro-
cedures, the c-option must be used. Default procedures
are present in the run time library. Default -.
u+/- If + then the character '_' is treated like a letter,
so that it may be used in identifiers. Procedure and
function identifiers are not allowed to start with an
underscore because they may collide with library rou-
tine names. Default -.
Some of these flags (c, d, i, s, u, C and U) are only effec-
tive when they appear before the 'program' symbol. The oth-
ers may be switched on and off.
A very powerful debugging tool is the knowledge that inac-
cessible statements and useless tests are removed by the
optimizer. For instance, a statement like:
if debug then
writeln('initialization done');
is completely removed by the optimizer if debug is a con-
stant with value false. The first line is removed if debug
is a constant with value true. Of course, if debug is a
variable nothing can be removed.
Library routines
The following library of external routines for Pascal pro-
grams is available:
const bufsize = ?;
type br1 = 1..bufsize;
br2 = 0..bufsize;
br3 = -1..bufsize;
ok = -1..0;
buf = packed array[br1] of char;
alfa = packed array[1..8] of char;
string = ^packed array[1..?] of char;
filetype = file of ?;
long = ?;
{all routines must be declared extern}
function argc:integer;
function argv(i:integer):string;
function environ(i:integer):string;
procedure argshift;
procedure buff(var f:filetype);
procedure nobuff(var f:filetype);
procedure notext(var f:text);
procedure diag(var f:text);
procedure pcreat(var f:text; s:string);
procedure popen(var f:text; s:string);
procedure pclose(var f:filetype);
procedure trap(err:integer);
procedure encaps(procedure p; procedure q(n:integer));
function perrno:integer;
function uread(fd:integer; var b:buf; len:br1):br3;
function uwrite(fd:integer; var b:buf; len:br1):br3;
function strbuf(var b:buf):string;
function strtobuf(s:string; var b:buf; len:br1):br2;
function strlen(s:string):integer;
function strfetch(s:string; i:integer):char;
procedure strstore(s:string; i:integer; c:char);
function clock:integer;
This library contains some often used external routines for
Pascal programs. The routines can be divided into several
categories:
Argument control:
argc Gives the number of arguments provided when
the program is called.
argv Selects the specified argument from the argu-
ment list and returns a pointer to it. This
pointer is nil if the index is out of bounds
(<0 or >=argc).
environ Returns a pointer to the i-th environment
string (i>=0). Returns nil if i is beyond
the end of the environment list (UNIX version
7).
argshift Effectively deletes the first argument from
the argument list. Its function is
equivalent to shift in the UNIX shell:
argv[2] becomes argv[1], argv[3] becomes
argv[2], etc. It is a useful procedure to
skip optional flag arguments. Note that the
matching of arguments and files is done at
the time a file is opened by a call to reset
or rewrite.
Additional file handling routines:
buff Turn on buffering of a file. Not very useful,
because all files are buffered except standard
output to a terminal and diagnostic output. Input
files are always buffered.
nobuff
Turn off buffering of an output file. It causes
the current contents of the buffer to be flushed.
notext
Only useful for input files. End of line charac-
ters are not replaced by a space and character
codes out of the ASCII range (0..127) do not cause
an error message.
diag Initialize a file for output on the diagnostic
output stream (fd=2). Output is not buffered.
pcreat
The same as rewrite(f), except that you must pro-
vide the file name yourself. The name must be
zero terminated. Only text files are allowed.
popen
The same as reset(f), except that you must provide
the file name yourself. The name must be zero
terminated. Only text files are allowed.
pclose
Gives you the opportunity to close files hidden in
records or arrays. All other files are closed
automatically.
String handling:
strbuf
Type conversion from character array to string.
It is your own responsibility that the string is
zero terminated.
strtobuf
Copy string into buffer until the string terminat-
ing zero byte is found or until the buffer if
full, whatever comes first. The zero byte is also
copied. The number of copied characters, exclud-
ing the zero byte, is returned. So if the result
is equal to the buffer length, then the end of
buffer is reached before the end of string.
strlen
Returns the string length excluding the terminat-
ing zero byte.
strfetch
Fetches the i-th character from a string. There
is no check against the string length.
strstore
Stores a character in a string. There is no check
against string length, so this is a dangerous pro-
cedure.
Trap handling:
These routines allow you to handle almost all the pos-
sible error situations yourself. You may define your
own trap handler, replacing the default handler that
produces an error message and quits. You may also gen-
erate traps yourself.
trap Trap generates the trap passed as argument
(0..252). The trap numbers 128..252 may be used
freely. The others are reserved.
encaps
Encapsulate the execution of p with the trap
handler q. Encaps replaces the previous trap
handler by q, calls p and restores the previous
handler when p returns. If, during the execution
of p, a trap occurs, then q is called with the
trap number as parameter. For the duration of q
the previous trap handler is restored, so that you
may handle only some of the errors in q. All the
other errors must then be raised again by a call
to trap.
Encapsulations may be nested: you may encapsulate
a procedure while executing an encapsulated rou-
tine.
Jumping out of an encapsulated procedure (non-
local goto) is dangerous, because the previous
trap handler must be restored. Therefore, you may
only jump out of procedure p from inside q and you
may only jump out of one level of encapsulation.
If you want to exit several levels of encapsula-
tion, use traps. See pc_prlib(7) for lists of
trap numbers for EM machine errors and Pascal run
time system errors. Note that p may not have
parameters.
UNIX system calls:
uread
Equal to the read system call. Its normal name is
blocked by the standard Pascal routine read.
uwrite
As above but for write(2).
perrno
Because external data references are not possible
in Pascal, this routine returns the global vari-
able errno, indicating the result of the last sys-
tem call.
Miscellaneous:
clock
Return the number of ticks of user and system time
consumed by the program.
The following program presents an example of how these
routines can be used. This program is equivalent to
the UNIX command cat(1).
{$c+}
program cat(input,inp,output);
var inp:text;
s:string;
function argc:integer; extern;
function argv(i:integer):string; extern;
procedure argshift; extern;
function strlen(s:string):integer; extern;
function strfetch(s:string; i:integer):char; extern;
procedure copy(var fi:text);
var c:char;
begin reset(fi);
while not eof(fi) do
begin
while not eoln(fi) do
begin
read(fi,c);
write(c)
end;
readln(fi);
writeln
end
end;
begin {main}
if argc = 1 then
copy(input)
else
repeat
s := argv(1);
if (strlen(s) = 1) and (strfetch(s,1) = '-')
then copy(input)
else copy(inp);
argshift;
until argc <= 1;
end.
Another example gives some idea of the way to manage
trap handling:
program bigreal(output);
const EFOVFL=4;
var trapped:boolean;
procedure encaps(procedure p; procedure q(n:integer)); extern;
procedure trap(n:integer); extern;
procedure traphandler(n:integer);
begin if n=EFOVFL then trapped:=true else trap(n) end;
procedure work;
var i,j:real;
begin trapped:=false; i:=1;
while not trapped do
begin j:=i; i:=i*2 end;
writeln('bigreal = ',j);
end;
begin
encaps(work,traphandler);
end.
Two routines may cause fatal error messages to be gen-
erated. These are:
pcreat
Rewrite error (trap 77) if the file cannot be
created.
popen
Reset error (trap 76) if the file cannot be opened
for reading
References
[1] BSI standard BS 6192: 1982 (ISO 7185).
[2] A.S.Tanenbaum, J.W.Stevenson, Hans van Staveren,
E.G.Keizer, "Description of a machine architecture for
use with block structured languages", Informatica rap-
port IR-81.