1 .\" $Id: pc_prlib.7,v 2.11 1994/06/24 14:02:12 ceriel Exp $
2 .TH PC_PRLIB 7 "$Revision: 2.11 $"
5 pc_prlib \- library of Pascal runtime routines
7 .ta 11n 22n 33n 44n 55n
9 type alpha=packed array[1..8] of char;
10 pstring= ^packed array[] of char;
12 function _abi(i:integer):integer;
13 function _abl(i:long):long;
14 function _mdi(j,i:integer):integer;
15 function _mdl(j,i:long):long;
16 function _dvi(j,i:integer):integer;
17 function _dvl(j,i:long):long;
18 function _abr(r:real):real;
19 function _sin(r:real):real;
20 function _cos(r:real):real;
21 function _atn(r:real):real;
22 function _exp(r:real):real;
23 function _log(r:real):real;
24 function _sqt(r:real):real;
25 function _rnd(r:real):real;
29 pcoffset:^procedure; { procedure id. without static link }
39 arr2=packed array[] of ?;
41 function _bcp(sz:integer; s2,s1:pstring):compared;
42 function _bts(size,high,low:integer; base:^set 0..(8*size-1))
43 :set of 0..(8*size-1);
44 procedure _gto(lb:^integer; p:^gotoinfo);
45 procedure _rcka(a: arrdescr; index : integer);
46 procedure _nfa(bool:integer);
48 procedure _new(size:integer; var p:^integer);
49 procedure _dis(size:integer; var p:^integer);
50 procedure _sav(var p:^integer);
51 procedure _rst(var p:^integer);
53 procedure _pac(var ad,zd:arrdescr; var zp:arr2; i:integer;
55 procedure _unp(var ad,zd:arrdescr; i:integer; var ap:arr1;
56 var zp:arr2;nosgnext:boolean);
57 function _asz(var dp:arrdescr):integer;
59 procedure _ass(line:integer; b:boolean);
60 procedure procentry(name:pstring);
61 procedure procexit(name:pstring);
73 flags: set of [0..15];
78 buflen: max(PC_BUFLEN,size) div size * size;
79 bufadr: packed array[1..max(PC_BUFLEN,size)]
84 _extfl:^array[] of filep;
86 procedure _ini(args:pstring; var c:integer;
87 var p:array[] of filep; mainlb:pstring);
88 procedure _hlt(status:0..255);
90 procedure _opn(size:integer; f:filep);
91 procedure _cre(size:integer; f:filep);
92 procedure _cls(f:filep);
94 procedure _get(f:filep);
95 procedure _put(f:filep);
96 function _wdw(f:filep):^char;
97 function _efl(f:filep):boolean;
99 function _eln(f:filep):boolean;
100 function _rdc(f:filep):char;
101 function _rdi(f:filep):integer;
102 function _rdl(f:filep):long;
103 function _rdr(f:filep):real;
104 procedure _rln(f:filep);
105 procedure _wrc(c:char; f:filep);
106 procedure _wsc(w:integer; c:char; f:filep);
107 procedure _wri(i:integer; f:filep);
108 procedure _wsi(w:integer; i:integer; f:filep);
109 procedure _wrl(l:long; f:filep);
110 procedure _wsl(w:integer; l:long; f:filep);
111 procedure _wrr(r:real; f:filep);
112 procedure _wsr(w:integer; r:real; f:filep);
113 procedure _wrf(ndigit:integer; w:integer; r:real; f:filep);
114 procedure _wrs(l:integer; s:pstring; f:filep);
115 procedure _wss(w:integer; l:integer; s:pstring; f:filep);
116 procedure _wrb(b:boolean; f:filep);
117 procedure _wsb(w:integer; b:boolean; f:filep);
118 procedure _wrz(s:string; f:filep);
119 procedure _wsz(w:integer; s:string; f:filep);
120 procedure _wln(f:filep);
121 procedure _pag(f:filep);
124 This library is used by the Pascal to EM compiler and
125 contains all the runtime routines for standard Pascal programs.
126 Most routines are written in C, a few in EM assembly language.
127 These routines can be divided into several categories.
128 A description of each category with its routines follows.
133 Compute the absolute value of an integer.
136 Compute the absolute value of a long.
138 Perform the Pascal modulo operation on integers.
140 Perform the Pascal modulo operation on longs.
142 Perform the Pascal divide operation on integers.
144 Perform the Pascal divide operation on longs.
146 Compute the absolute value of a real.
148 Compute the sine of a real.
150 Compute the cosine of a real.
152 Compute the arc tangent of a real.
154 Compute the e-power of a real.
156 Compute the natural logarithm of a real.
158 Compute the square root of a real.
160 Return a real that when truncated will
161 result in the nearest integer (-3.5->-4).
165 Miscellaneous routines:
168 Compare two strings. Use dictionary ordering with the ASCII
169 character set. The EM instruction CMU can not be used, because it needs
170 an even number of bytes.
173 Include a range of elements from low to high in a set of size bytes
174 at address base.(size can be divided by the wordsize)
176 Execute a non-local goto. Lb points to the
177 local base of the target procedure.
178 A lb of zero indicates a jump to the program body, the lb of the main
179 program is found in _m_lb, which is set by _ini.
180 The new EM stack pointer is calculated by adding the number of locals
181 to the new local base
182 (jumping into statements is not allowed; there are no local generators
185 Check if an array reference isn't out of bounds. This is should be done by
186 the backends, but some don't.
188 Check whether a function is assigned or not. This could have
189 been done by the compiler, but that would make the interface between the
190 compiler and the run-time library messier.
197 There is one way to allocate new heap space (_new), but two different
198 incompatible ways to deallocate it.
200 The most general one is by using dispose (_dis).
201 A circular list of free blocks, ordered from low to high addresses, is maintained.
202 Merging free blocks is done when a new block enters the free list.
203 When a new block is requested (_new), the free list is searched using a
205 Two global variables are needed:
207 Points to the free block with the highest address.
210 Points to the most recently entered free block or to a block
211 in the neighborhood of the most recently allocated block.
213 The free list is empty, when one of these pointers (but then at the same
216 The second way to deallocate heap space is by using
217 mark (_sav) and release (_rst). Mark saves the current value of the
218 heap pointer HP in the program variable passed as a parameter.
219 By calling release with this old HP value as its argument, the old HP value
220 is restored, effectively deallocating all blocks requested between
221 the calls to mark and release.
222 The heap is used as second stack in this case.
224 It will be clear that these two ways of deallocating heap space
225 can not be used together.
226 To be able to maintain the free list, all blocks must be a multiple
227 of n bytes long, with a minimum of n bytes,
228 where n is the sum of the size of a word and a pointer in the
229 EM implementation used.
236 Deallocate heap space.
238 Save the current value of HP.
240 Restore an old value of HP.
247 The only useful form of packing implemented, is packing bytes into words.
248 All other forms of packing and unpacking result in a plain copy.
250 Pack an unpacked array \fIa\fP into a packed array \fIz\fP.
251 \fIap\fP and \fIzp\fP
252 are pointers to \fIa\fP and \fIz\fP. \fIad\fP and \fIzd\fP
253 are pointers to the descriptors of \fIa\fP and \fIz\fP. \fIi\fP is
254 the index in \fIa\fP of the first element to be packed.
255 Pack until \fIz\fP is full.
258 Unpack \fIz\fP into \fIa\fP.
259 \fIap\fP, \fIzp\fP, \fIad\fP and \fIzd\fP are as for _pac. \fIi\fP is
260 the index in \fIa\fP where the first element of \fIz\fP is copied into.
261 Unpack all elements of \fIz\fP. The boolean flag \fInosgnext\fP indicates
262 whether the values should or should not be sign-extended.
264 Compute array size. Used for copying conformant arrays.
268 Debugging facilities:
270 The compiler allows for the verification of assertions.
271 It generates a call to the routine _ass to check the assertion at runtime.
272 Another feature of the compiler is that it enables the user to trace the
273 procedure calling sequence. If the correct option is turned on, then
274 a call to the procedure \fIprocentry\fP is generated at the start of each
275 compiled procedure or function. Likewise, the routine \fIprocexit\fP is called
276 just before a procedure or function exits.
277 Default procedure \fIprocentry\fP
278 and \fIprocexit\fP are available in this library.
280 If \fIb\fP is zero, then change eb[0] to \fIline\fP
281 (to give an error message with source line number) and call the error routine.
284 Print the name of the called procedure on standard output. Output must
285 be declared in the program heading.
287 Print the name of the procedure that is about to exit. Output must
288 be declared in the program heading.
295 Most of the runtime routines are needed for file handling.
296 For each file in the Pascal program a record of type file, as described
297 above, is allocated, static if this file is declared in the outermost block,
298 dynamic if it is declared in inner blocks.
299 The fields in the file record are used for:
301 IO is buffered except for standard input and output if
302 terminals are involved. The size of the buffer is the maximum of PC_BUFLEN
303 and the file element size.
306 The effective buffer length is the maximum number of file elements
307 fitting in the buffer, multiplied by the element size.
309 The file element size (1 or even).
311 Some flag bits are stored in the high byte and a magic pattern
312 in the low byte provides detection of destroyed file
315 Points to the file window inside the buffer.
317 The number of bytes (the window inclusive) left in the buffer
318 to be read or the number of free bytes (the window inclusive) for output files.
320 The UNIX file descriptor for the file.
322 Points to the name of the file (INPUT for standard input,
323 OUTPUT for standard output and LOCAL for local files).
324 This field is used for generating error messages.
327 The constants used by the file handling routines are:
329 Bit in flags set if the window of an input file is initialized.
330 Used to resolve the famous interactive input problem.
333 Bit in flags set if end of file seen
335 Bit in flags set if linefeed seen
337 Bit in flags set for text files. Process linefeeds.
339 Bit in flags set for output files
341 Pattern for the low byte of flags
343 The maximum number of open files in UNIX
347 Prelude and postlude:
350 These routines are called once for each Pascal program:
352 When a file mentioned in the program heading is opened by reset or
353 rewrite, its file pointer must be mapped onto one of the program
355 The compiler knows how to map and therefore builds a table with
356 a pointer to the file structure for each program argument.
357 One of the first actions of the Pascal program is to call this procedure
358 with this table as an argument.
359 The global variable _extfl is used to save the address of this table.
360 Another task of _ini is to initialize the standard input and output files.
361 For standard output it must decide whether to buffer or not.
362 If standard output is a terminal, then buffering is off by setting
364 Two other task of _ini are the copying of two variables from
365 the argument list to global memory, mainlb to _m_lb and c to _extflc.
366 The first contains the local base of the program body, the second
367 contains the number of paremeters the program is called with.
368 A last task of _ini is to set the global variables _pargc, _pargv and
369 _penvp from args for possible reference later on.
370 Args points to the argument count placed on the stack by the EM runtime system,
371 see chapter 8 in [1].
374 If the program is about to finish, the buffered files must be flushed.
375 That is done by this procedure.
382 Files in Pascal are opened for reading by reset and opened for writing by
384 Files to be rewritten may or may not exist already.
385 Files not mentioned in the program heading are considered local files.
386 The next steps must be done for reset and rewrite:
388 If size is zero, then a text file must be opened with elements of
392 Find out if this file is mentioned in the program heading
393 (scan table pointed to by _extfl).
394 If not, then it is a local file and goto 7.
396 If the file is standard input or output then return.
398 If there are not enough arguments supplied, generate an error.
400 If the file was already open, flush the buffer if necessary and close it.
401 Note that reset may be used to force the buffer to be flushed.
402 This is sometimes helpful against program or system crashes.
404 If it is a reset, open the file, otherwise create it.
405 In both cases goto 9.
407 If the local file is to be written, then close it if it was open and
408 create a new nameless file. First try to create it in /usr/tmp, then in /tmp
409 and if both fail then try the current directory.
410 See to it that the file is open for both reading and writing.
412 If the local file is to be read
413 and the file is opened already, then
414 flush the buffer and seek to the beginning.
415 Otherwise open a temporary file as described in 7.
417 Initialize all the file record fields.
420 The necessary procedures are:
427 Close a file. Closing of files is done for local files when the procedure
428 in which they are declared exits.
429 The compiler only closes local files if they are not part of a structured type.
430 Files allocated in the heap are not closed when they are deallocated.
431 There is an external routine \fIpclose\fP in libpc(7), that may be called
432 explicitly to do the closing in these cases.
433 Closing may be necessary to flush buffers or to keep the number of
434 simultaneously opened files below NFILES.
435 Files declared in the outermost block are automatically closed when the
443 These routines are provided for general file IO:
445 Append the file element in the window to the file and advance the
448 Advance the file window so that it points to the next element
450 For text files (TXTBIT on) the ELNBIT in flags is set if the new character
451 in the window is a line feed (ASCII 10) and the character is then changed
453 Otherwise the ELNBIT is cleared.
455 Return the current pointer to the file window.
457 Test if end of file is reached.
458 Is always true for output files.
465 The rest of the routines all handle text files.
467 Return true if the next character on an input file is an end-of-line marker.
468 An error occurs if eof(f) is true.
471 Return the character currently in the window and advance the window.
473 Build an integer from the next couple of characters on the file,
474 starting with the character in the window.
475 The integer may be preceded by spaces (and line feeds), tabs and a sign.
476 There must be at least one digit.
477 The first non-digit signals the end of the integer.
479 Like _rdi, but for longs.
481 Like _rdi, but for reals. Syntax is as required for Pascal.
483 Skips the current line and clears the WINDOW flag, so that the
484 next routine requiring an initialized window knows that it has to
485 fetch the next character first.
487 Write a character, not preceeded by spaces.
489 Write a character, left padded with spaces up to a field width
492 Write an integer, left padded with spaces up to a field width
493 of 6 on 2-byte machines and a field width of 11 on 4-byte machines.
495 Write an integer, left padded with spaces up to a field width
498 Write a long, left padded with spaces up to a field width
501 Write a long, left padded with spaces up to a field width
504 Write a real in scientific format,
505 left padded with spaces up to a field width of 13.
507 Write a real in scientific format,
508 left padded with spaces up to a field width of \fIw\fP.
510 Write a real in fixed point format, with exactly \fIndigit\fP digits
511 behind the decimal point, the last one rounded; it is left padded up to
512 a field width of \fIw\fP.
514 Write a string of length \fIl\fP, without additional spaces.
516 Write a string of length \fIl\fP, left padded up to a field
519 Write a boolean, represented by "true" or "false", left padded
520 up to a field width of 5.
522 Write a boolean, represented by "true" or "false", left padded
523 up to a field width of \fIw\fP.
525 Write a C-type string up to the zero-byte.
527 Write a C-type string, left padded up to a field width of w.
529 Write a line feed (ASCII 10).
531 Write a form feed (ASCII 12).
535 All the routines to which calls are generated by the compiler are described above.
536 They use the following global defined routines to do some of the work:
538 Check input files for MAGIC and WRBIT.
539 Initialize the window if WINDOW is cleared.
542 Check output files for MAGIC and WRBIT.
544 Advance the file window and read a new buffer if necessary.
546 Write out the current buffer if necessary and advance the window.
548 Flush the buffer if it is an output file.
549 Append an extra line marker if EOLBIT is off.
551 All output routines make up a string in a local buffer.
552 They call _wstrin to output this buffer and to do the left padding.
554 Skip spaces (and line feeds) on input files.
556 Read '+' or '-' if present.
558 See to it that the next character is a digit. Otherwise error.
560 Check if the next character is a digit.
562 Do the work for _rdi.
564 Convert real into string of digits for printout in scientific notation.
566 Convert real into string of digits for fixed point printout
568 Split real into integer and fraction part
570 Split real into exponent and fraction part
573 The following global variables are used:
575 For heap management (see above).
578 For heap management (see above).
580 Used to save the argument p of _ini for later reference.
582 Used to save the argument c of _ini for later reference.
584 Used to store the local base of the main program.
586 Save the current file pointer, so that the
587 error message can access the file name.
588 .IP "_pargc, _pargv, _penvp"
589 Used to access the arguments of the main program.
592 .IP ~em/lib/*/tail_pc 20
593 The library used by ack[5] to link programs.
597 A.S. Tanenbaum, Ed Keizer, Hans van Staveren & J.W. Stevenson
598 "Description of a machine architecture for use of
599 block structured languages" Informatica rapport IR-81.
603 "PASCAL, User Manual and Report" Springer-Verlag.
605 Specification fo Computer programming language Pascal, BS6192: 1982
608 J.W. Stevenson, H. van Eck, "Amsterdam Compiler Kit-Pascal reference manual".
610 (try \fItbl ~em/doc/pcref.doc | nroff\fP).
615 All errors discovered by this runtime system cause an EM TRP instruction
616 to be executed. This TRP instruction expects the error number on top
617 of the stack. See [1] for a more extensive treatment of the subject.
619 EM allows the user to specify a trap handling routine, called whenever
620 an EM machine trap or a language or user defined trap occurs.
621 One of the first actions in _ini is to specify that the routine _fatal,
622 available in this library, will handle traps.
623 This routine is called with an error code (0..252) as argument.
624 The following information is printed
625 on file descriptor 2:
627 The name of the Pascal program
630 The name of the file pointed to by _curfil, if the error number
631 is between 96 and 127 inclusive.
633 The error message (or the error number if not found).
635 The source line number if not equal to 0.
638 The routine _fatal stops the program as soon as the message is printed.
640 The following error codes are used by the Pascal runtime system:
653 array bound error in pack
655 array bound error in unpack
657 only positive j in \fIi mod j\fP
663 function not assigned
668 file xxx: not writable
670 file xxx: not readable
672 file xxx: end of file
676 file xxx: reset error
678 file xxx: rewrite error
680 file xxx: close error
684 file xxx: write error
686 file xxx: digit expected
688 file xxx: non-ASCII char read
692 Johan Stevenson and Ard Verhoog, Vrije Universiteit.