ACK(7)
NAME
ACK - Additional information on the Amsterdam Compiler Kit compilers
DESCRIPTION
These are the details on the Amsterdam Compiler Kit compilers for the
languages C, Modula-2, and Pascal. The design decisions that were made
where the respective standards 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' preprocessing
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 command line (including the command).
The second parameter is a pointer to an array of pointers to the
arguments (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, 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 administration. 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. Otherwise 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 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 variables 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
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 volatile 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 __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 supported.
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.
o The %p conversion in fscanf has the same effect as %x on Minix-PC
and %lx on the 68000 versions of Minix.
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. 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 otherwise.
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 strerror to return "unknown
error" under Minix, 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 Information Systems -
Programming Language C
THE MINIX MODULA-2 COMPILER
This section describes the implementation-specific features of the Minix
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
mentioned 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 definition, 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 constants, 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 accomplished. However, page 87 of [1]
states: 'Standard identifiers 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 constant 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 negative. However, if a negative lower bound is
used, the compiler 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 operators + or -:
It does not specify whether
- 1 + 1
means
- (1 + 1)
or
(-1) + 1
The Minix Modula-2 compiler implements the second alternative.
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, programs 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 LONGREAL.
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 sometimes issues warnings,
recognizable by a warning-classification between parentheses. There are
3 classifications:
(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 supported by the
Minix 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 disabled.
cardinal underflow
This error is detected, unless runtime checks are disabled.
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 process,
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 messages. 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 conformant 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 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 rapport IR-81, Vrije Universiteit, Amsterdam
THE MINIX PASCAL COMPILER
This section refers to the (1982) BSI standard for Pascal [1]. Minix
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 standard 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 starting 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 activities 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 rewritten 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 according 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 is a 16-bit word using two's complement 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 representation 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 representation 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 program 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 argument 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 procedures 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 Pascal system. First we quote the
definition of 'implementation-dependent':
Possibly differing between processors and not necessarily 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 evaluations 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 compiler. 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 requirements 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 program 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 instruction.
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 compatible ordinal-types and
the value of type T2 is not in the closed interval specified by T1.
The compiler distinguishes between array-index expressions 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 interval 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 compatible 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 undefined.
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 handling 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 system or operating system
problems like table overflow 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 variants.
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 variable 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 variable 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 undefined.
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 undefined, 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 operation 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 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 Pascal compiler
recognizes the directive 'extern'. This directive 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 written 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 Pascal 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 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 variable 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 statement 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 environment. First of all, the
compiler allows you to use a different 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 procedures
'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 identifiers 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 character '.' 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 comments inside
Pascal programs are also removed when they are fed through the
preprocessor.
Deviations from the standard
Minix Pascal deviates from the standard in the following ways:
1. Standard procedures and functions are not allowed as parameters in
Minix 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 followed 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
procedures, 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 routine names. Default -.
Some of these flags (c, d, i, s, u, C and U) are only effective when they
appear before the 'program' symbol. The others may be switched on and
off.
A very powerful debugging tool is the knowledge that inaccessible
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 constant 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 programs 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 argument 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 characters 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 provide 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 terminating zero byte
is found or until the buffer if full, whatever comes first.
The zero byte is also copied. The number of copied characters,
excluding 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 terminating 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 procedure.
Trap handling:
These routines allow you to handle almost all the possible error
situations yourself. You may define your own trap handler, replacing the
default handler that produces an error message and quits. You may also
generate 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 routine.
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 encapsulation, 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 variable errno, indicating the
result of the last system 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 generated. 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 rapport IR-81.