NBS Pascal User's Guide RSX / RSTS / RT-11 Version 1.6i 20 October 1981 Brian G. Lucas and Justin C. Walker Interactive Systems Corp 1050 17th Street, N.W. Suite 580 Washington, D.C. 20036 Bill Heidebrecht TRW DSSG One Space Park Redondo Beach, CA 90278 John R. Barr Department of Computer Science University of Montana Missoula, Montana 59812 NBS Pascal User's Guide Page 2 Preface ------- The NBS Pascal compiler for the PDP-11 implements most of Standard Pascal, as defined in "Pascal User Manual and Report" by Kathleen Jensen and Niklaus Wirth (Second Edition, Springer Verlag, 1975). For the remainder of this guide, the term "Standard Pascal" will refer to the language defined in that Report. This User's Guide describes the use of the NBS compiler as well as the exceptions and extensions to Standard Pascal. This version of the Guide is primarily directed to RSX, IAS, RT-11 and RSTS users, although much of the information presented pertains to other systems as well. The reader is assumed to be familiar with the Jensen and Wirth Report. The current compiler consists of two passes, written entirely in Pascal except for the runtime library. It is capable of compiling itself on a PDP-11/45 in less than five minutes. Pass 1 performs lexical, syntax, and semantic analysis, and pass 2 performs code generation. The compiler is currently available under RSX-11M, -11D, IAS, RT-11, RSTS and UNIX on LSI-11 and PDP-11 machines. The present version assumes the existence of the EIS and FP11 or FIS hardware options. DECUS and the UNIX User's Group distribute the compiler free of charge (except for possible nominal processing charges) with the understanding that no warantees are made as to its correctness. Neither NBS, DEC, DECUS, the UNIX User's Group, nor any other organization assume any responsibility for supporting this compiler. However, the authors would appreciate hearing of problems experienced with it, and an attempt will be made to publish bug fixes in the DECUS Structured Languages SIG Newsletter. This software was developed at the National Bureau of Standards and the University of Montana. As a product of the U.S. government, it is in the public domain, and should not be sold or otherwise used for profit. Historical Note --------------- The NBS Pascal compiler was written by Brian G. Lucas and Justin C. Walker. An early bootstrap version was implemented by Lucas and Walker using their BSM (Block Structured Macros) under PDP-11 DOS. It had its roots in the P-compiler of Urs Ammann, et al., but was different in that it produced machine code for the PDP-11. The BSM compiler was later replaced by a version written in C under UNIX by Lucas and Walker, and was then hand translated to Pascal. The Pascal version was subsequently moved to RSX-11D, -11M and RT-11 by John R. Barr. Bill Heidebrecht has assisted with documentation and maintenance. NBS Pascal User's Guide Page 3 Contents -------- 1 Compiling and Task Building a Pascal Program 1.1 Compilation 1.2 Compiler Options 1.3 Task Building 1.4 Running a Pascal Program 1.5 RT-11 Compilation and Linking 2 Extensions 2.1 Character Set and Special Symbols 2.2 Significant Length of Identifiers 2.3 The PROGRAM Statement 2.4 Ordering of Declaration Statements 2.5 Real Types 2.6 Octal Constants 2.7 Structured Constants 2.8 The LOOP Statement 2.9 NEW, MARK and RELEASE 2.10 Standard Files 2.11 RESET, REWRITE and UPDATE 2.12 WRITE 2.13 BREAK 2.14 Directives 2.15 External Procedures and Separate Compilation 2.16 MCR Command Line Arguments 2.17 RT-11 Random Files 2.18 RT-11 Command Line Arguments 3 Restrictions 3.1 Standard Procedures and Functions 3.2 Real Constants 3.3 Sets 3.4 Maximum Number of Procedures 3.5 Maximum Number of Nesting Levels 3.6 Maximum Number of Case Constants 3.7 LABEL and GOTO 3.8 PACKED ARRAYs 3.9 Procedural and Functional Parameters 4 Building the Compiler 5 Code Optimization Appendix A. Error Number Summary A.1 Compile Time Errors (Pass 1) A.2 Compile Time Errors (Pass 2) A.3 Run Time Errors A.4 RT-11 Run Time Errors Appendix B. Runtime Environment B.1 Procedure Interface B.2 Runtime Library B.3 External Names NBS Pascal User's Guide Page 4 1 Compiling and Task Building a Pascal Program ----------------------------------------------- 1.1 Compilation ---------------- Both passes of the NBS Pascal compiler must be installed before compiling a Pascal program. If the tasks are not already installed, type the following MCR commands: MCR>INS [uic]P1FP MCR>INS [uic]P2FP where [uic] indicates the uic used when the compiler was built (implementation dependent). The compiler task names are ...PF1 and ...PF2. Having created a Pascal program (say on file MYPROG.PAS), the next step is to invoke the compiler: MCR>PF1 - MYPROG.PAS MYPROG.INT MYPROG.DAT MYPROG.LST MCR>PF2 - MYPROG.INT MYPROG.DAT MYPROG.OBJ MYPROG.OLS (The minus signs must be included on the command lines.) The files MYPROG.INT and MYPROG.DAT are intermediate files used by the compiler, and you should generally delete them after pass 2 finishes execution. The source listing file (possibly containing error messages) is MYPROG.LST in the example above. It is not spooled to the printer. The object file used to build the task is MYPROG.OBJ. The file MYPROG.OLS need only be specified if the O or P options are used (see Compiler Options, below). If the file type extension is omitted from the command lines, .TMP is assumed. Thus, the command lines MCR>PF1 - MYPROG.PAS INT DAT MYPROG.LST MCR>PF2 - INT DAT MYPROG.OBJ MYPROG.OLS create files INT.TMP, DAT.TMP, MYPROG.LST, MYPROG.OBJ, and possibly MYPROG.OLS. An alternate method of invoking both passes with a single command is available under RSX-11 and VAX/VMS. An indirect command file which calls both passes is executed as follows: MCR>@PAS or MCR>@PAST The command file processor prompts for the source file name. With this method, .PAS is assumed as the source file type, .LST as the list file type, and .OBJ as the object file type. All three files are given the same file name as the source file. The command file PAS.CMD performs a compile, while PAST.CMD performs a compile and a simple task build. NBS Pascal User's Guide Page 5 Compiling and Task Building 1.2 Compiler Options --------------------- Compiler options are selected in the standard Pascal way, by enclosing an option statement in a comment in the source file. Example: {$T+,W-} The above example turns on option T and turns off option W. Options are separated by a comma, with no other intervening characters. At present, the following options are recognized: E separate compilation option. If E+ is selected, the main program statement-part is not compiled. Used in conjunction with option X. default = E- L controls listing of source program text. default = L+ O generate object code list file (*.OLS). default = O- P generate procedure name/number index list file (*.OLS). default = P- S print stack dump list on standard output (user terminal) for debugging. default = S- T controls printing of the tables at the end of each procedure. default = T- W Warning message option. If W+ is selected, warning messages (see section A.1) are given for use of nonstandard Pascal extensions. default = W+ X generate psect and entry point names based on the first six characters of procedure names. Used for separate compilation of procedures, in conjunction with option E. See sections 2.15 and B.3 for more details. default = X- Y Array type compatibility option. If Y+ is selected, array sizes are checked as part of the compatibility test. If Y- is selected, the sizes are not checked. This is useful for example in passing variable length character strings to a procedure. default = Y+ NBS Pascal User's Guide Page 6 Compiling and Task Building Pass 2 options can alternatively be indicated on the MCR command line when pass 2 is invoked. Pass 2 options consist of the subset (O, P, S and X). Options specified in this way are placed immediately following the minus sign, which signals the beginning of an option string. The "$" and "+" characters are not used for options specified in this way. Example: MCR>PF2 -OPS T.INT T.DAT T.OBJ T.OLS (turns on options O, P and S) 1.3 Task Building ------------------ After correcting the compile time errors, you can create a runable task by typing commands directly to the task builder (TKB), or by creating an indirect command file. In either case, the information supplied to TKB is typically as follows: MYPROG/CP/FP,MYPROG/-SP=MYPROG,[uic]NBSLIB/LB / EXTSCT=$$$$$$:heapsize STACK=stacksize // where: CP = checkpoint switch (optional); FP = floating point switch (optional - use if the task uses floating point arithmetic); -SP = no spooling of map file; [uic] = uic assigned for Pascal run time library; heapsize = size of heap in octal bytes (default = 200 octal bytes); stacksize = size of stack in decimal words (default = 256 decimal words); For small programs, it may not be necessary to enter the EXTSCT and STACK options. However, you should increase the heapsize for programs which make extensive use of the Pascal NEW procedure, and increase the stacksize for programs which contain large local variable declarations (i.e., variables in procedures or functions). Global variables are allocated in a separate psect, and not on the stack. 1.4 Running a Pascal Program ----------------------------- Having built a task image of the Pascal program, you are now ready to run it. Under RSX-11, Pascal programs can be run either as installed or uninstalled tasks. NBS Pascal User's Guide Page 7 Compiling and Task Building Example of uninstalled task: MCR>RUN MYPROG Example of installed task: MCR>INS MYPROG/TASK=...MPG MCR>MPG It is possible to pass arguments (such as character strings or file names) to an installed program. Example: MCR>MPG string1 string2 string3 ... All fields are separated by spaces, and the first character string begins with the task name itself. The strings are not enclosed in quotes. The positions and use of the string arguments are determined by the program. This is described in more detail in section 2.16. 1.5 RT-11 Compilation and Linking ---------------------------------- Under RT-11, each pass of the compiler is invoked by the RUN command and prompts for a list of files to process: .RUN PASS1 *- PROG.PAS INT DAT PROG.LST .RUN PASS2 *-[XOSP] INT DAT PROG.OBJ [PROG.OLS] Any output file name may also include a device name and/or file size indicator (e.g. DX1:PROG.LST[200]). Input files may also include a device name. In the above commands, INT is the intermediate code file and DAT is the intermediate data file. The dash after the * prompt is the options string and must be included. Save files are created with the LINK command of the form: .LINK PROG,NPASL or .LINK PROG,CPASL,NPASL The first command generates a program which does not prompt for a list of strings when the program is invoked. The second command uses the initialization module (as does the compiler) which prompts with an asterisk and allows the user to type in one or more strings to be used by the program through the predefined parameters argc and argv. The command .LINK/BOTTOM:n PROG,NPASL can be used to increase the stack size of the program. NBS Pascal User's Guide Page 8 Compiling and Task Building 2 Extensions ------------- The extensions to Standard Pascal described in this section provide useful and sometimes necessary features not available in the standard language. However, use of these extensions will make programs less portable. Also, there is no guarantee that future versions of the compiler will support all the present extensions in exactly the same way. 2.1 Character Set and Special Symbols -------------------------------------- NBS Pascal assumes the full ASCII character set. Identifiers and Pascal reserved words can be typed in upper or lower case. Upper and lower case letters are mapped to the same internal representation in identifiers and reserved words, but not in literal character strings. Thus, identifiers abc and ABC are equivalent, but strings 'hello' and 'HELLO' are not. NOTE: In the course of this guide, certain reserved words or built-in procedure / function names may be indicated in upper case. This is for emphasis ONLY. The underscore character (_) is considered an alpha, and can be used in identifier names. The special symbols are: { } comment (* *) comment [ ] array index or set constructor symbols @ or ^ pointer symbol ' ' string delimiters " " string delimiters (compiler inserts a zero byte at the end of the string) <> not equal The Pascal reserved words are as follows: and array begin case const div do downto else end exit file for function goto if in label loop mod nil not of or packed procedure program record repeat set then to type until var while with 2.2 Significant Length of Identifiers -------------------------------------- Pascal identifiers may be of any length less than or equal to one line length. However, only the first 15 characters are NBS Pascal User's Guide Page 9 Extensions retained for comparison; therefore, two different identifiers must be unique in the first 15 characters. 2.3 The PROGRAM Statement -------------------------- The program statement may optionally have parameters enclosed in parentheses after the program name. Examples: program xyz; program xyz (a, b, c); The parameters are presently ignored. Files to be used by the program must be declared in var statements (except for "input" and "output"). If no program statement is used, the main program name defaults to '.main.'. 2.4 Ordering of Declaration Statements --------------------------------------- The rules regarding the ordering of declaration statements (const, type, var, procedure and function) are relaxed so that these statements can be entered in any order, as long as identifiers are defined before they are used (except as permitted by the language to allow mutually "recursive" declarations). The recommended order is const, type, var and procedure / function, which is consistent with standard Pascal usage. This relaxation is required for "structured constants", described below. 2.5 Real Types --------------- In addition to the standard type "real", the type "longreal" is defined. Real variables occupy 32 bits, and longreals occupy 64 bits. At present, the FPP version evaluates all real expressions as longreal, with conversion to real being done when values are stored in real variables. The FIS version of the compiler supports only 32 bit real variables. 2.6 Octal Constants -------------------- Octal constants can be used in place of decimal integer constants. Octal constants are terminated with the letter b or B. Example: 077777B NBS Pascal User's Guide Page 10 Extensions 2.7 Structured Constants ------------------------- NBS Pascal extends the standard language by permitting the declaration of structured constants. These are constants of any, possibly structured, type. Using the relaxed declaration order mentioned above, a constant of a given structured type is defined by using the type name as if it were a function name: type_name ( ... ) A structured constant can be used anywhere a constant is legal (i.e., in a constant declaration or in an expression). Since structured values are normally only used in assignments, this will account for the majority of such uses. Thus, a structured constant uses the type as a template, and supplies the constant components as "arguments" to define the value. A simple example illustrates this: function abcd (i: integer): char; type chartab = array [1..4] of char; const chars = chartab ('A','B','C','D'); begin if (i>=1) and (i<=4) then abcd := chars[i] else abcd := ' ' end {abcd}; Function abcd above returns a character 'A' through 'D' or a space depending on the value of the parameter i. Initialization of the structured constant chars is done at compile time. It is also possible to build much more complicated structured constants. In general, to build a constant of type T, whose components have types t1, ..., tn, one writes T (c1, ..., cn) where ci are the components of type ti. If the ti are themselves structured, the form of the component ci is (ci1,...,cim), where the cij are constants of type tij, these being, in turn, the component types of ti. For example: type item = record a: char; b: integer end; tabtype = array [1..5] of item; const tab = tabtype(('A',1),('B',2),('C',3),('D',4),('E',0)); NBS Pascal User's Guide Page 11 Extensions Alternate forms of constants allow the definition of character constants, real constants and expressions that can be evaluated at compile time. Examples: const NL = chr(10); Real_Ten = float(10); Max = 23; Max_Sqrd_Plus1 = sqr(Max) + 1; 2.8 The LOOP Statement ----------------------- The loop statement is a repetitive statement similar to the while and repeat statements, except that the exit is in the middle of the loop rather than at the beginning or end. Syntax: ::= loop end ::= { ; } ::= | ::= | ; ::= exit if | exit if then Note that there can be more than one exit in the loop, and that the exit statement has two forms. In the second form, the following the "then" is executed just before the exit is taken. This extended loop provides some measure of relief for the lack of GOTOs (see 3.7); it is useful for example in table searches where an exit is needed both for success and failure. 2.9 NEW, MARK and RELEASE -------------------------- The standard procedure NEW can be invoked in three different forms: 1. new (p) NBS Pascal User's Guide Page 12 Extensions 2. new (p, t1, ..., tn) 3. new (p, n) The first two forms are the standard ones described in Jensen and Wirth. If the type of the allocated variable contains variants, the maximum record size is allocated when form 1 is used. Form 2 is used with variant records to economize storage. The constant tag field values t1...tn must be listed in the order of their declaration. Form 3 is an extension to standard Pascal. It is used to economize storage of a record containing an array of which only the first n elements are needed. The actual parameter n represents an integer constant, variable or expression. Example: type id = record length: integer; str: array [1..80] of char end; var p: @id; i, n: integer; begin n := 15; new(p, n); with p@ do begin length := n; for i := 1 to n do str[i] := ' ' end; ... The predefined procedures MARK and RELEASE are used to control heap storage. MARK saves the current heap status, and RELEASE restores the heap to the state as of the last MARK. Neither procedure has an argument. Note that MARK and RELEASE thus permit a stack-oriented use of the heap, and provide a simple-minded garbage collection capability. For example, the Pascal compiler uses these to allocate and deallocate space in the heap for the symbol table. When beginning the compilation of a new procedure, the heap is MARKed. At procedure exit, when the symbol table for that procedure is no longer valid, the heap is RELEASEd, thus returning the used space for later reallocation. It is up to the user to make proper use of this facility, as extensive runtime checks are NOT made. NBS Pascal User's Guide Page 13 Extensions The standard procedure DISPOSE is not currently implemented. 2.10 Standard Files -------------------- The standard files "input" and "output" are predeclared as text files as in the standard language. They are used to perform i/o to the user's terminal (TI:). Reset and rewrite are automatically implied for input and output respectively, and need not be specified in the user's program. 2.11 RESET, REWRITE and UPDATE ------------------------------- The standard procedures RESET and REWRITE are extended to have two or optionally three parameters: RESET (f, filename { , fileattribute } ) REWRITE (f, filename { , fileattribute } ) where: f = file variable; filename = ASCII string or array containing the file name and extension, or a pointer to such a string. The string must end with a zero byte. If a literal string is used, enclosing it in double quotes insures that it will end with a zero byte. fileattribute = integer constant, variable, or expression defining the RSX file attribute. At present, the following values are recognized for RSX systems: 0 - file of char; file is not line oriented in the RSX sense. The character (chr(10)) may be used to represent line delimiters in the file. 2 - text file; file is an RSX FILES-11 line oriented file with the FD.CR attribute. The Pascal runtime library simulates the character on reads and writes. If the fileattribute parameter is not specified, the default 0 is assumed. The fileattribute parameter is presently NBS Pascal User's Guide Page 14 Extensions ignored for RESET under RSX systems. For RSTS, other values may be defined for both RESET and REWRITE. Examples: reset (infile, argv[2]@) rewrite (listfile, "OUTPUT.LST", 2) Another file access procedure, UPDATE, is also implemented for RT-11. UPDATE opens a file for both input and output. It should only be used with the RT-11 random file capabilities described in section 2.17. Only two parameters are allowed: update (f, filename) Example: update (randomfile, "PERSON.DAT") 2.12 WRITE ----------- The standard procedure WRITE is extended to allow pointer variables to be specified as arguments, which can be useful in debugging programs. The value of the pointer itself (not the value of the structure pointed to) is output in octal form. Default field width is 6. Example: program printpointer; var p: @char; begin new(p); p@ := 'A'; writeln(output, p@, p:8) end. Printed output: A 032376 2.13 BREAK ----------- The procedure BREAK(file) causes the current buffer contents to be written immediately to the indicated file. A file variable must be specified as the parameter. For example, "break(output)" forces the current buffer contents for "output" to the standard output. This procedure is primarily for use with the terminal, to force out prompts, but it also has use in debugging, permitting the current state of a program to be dumped prior to a catastrophic failure. NBS Pascal User's Guide Page 15 Extensions 2.14 Directives ---------------- Directives take the place of a procedure-block or function-block in a procedure or function declaration. Four directives are defined: directive ::= "forward" | "cext" | "external" | "fortran" The compiler flags unknown directives with warning message number 420. The forward directive allows procedure and function headings to be defined and used before the algorithm part is given. The other directives are explained in the following section. 2.15 External Procedures and Separate Compilation -------------------------------------------------- Externally compiled or assembled procedures can be called by declaring the procedure as external in the Pascal program. The syntax of the external procedure declaration is similar to the forward procedure declaration. Example: procedure ABC (p1: t1; p2: t2; ... ); external; The directive following the procedure heading defines the language in which the external procedure is written. "cext" is used to indicate the C language, "external" indicates Pascal, and "fortran" indicates FORTRAN. You can call macro assembly language procedures by declaring them as "external", if they obey the Pascal calling sequence conventions. (See Appendix B.1 for the definition of the Pascal calling sequence.) Since FORTRAN always passes arguments by reference, the user must declare all parameters passed to a FORTRAN procedure as variable parameters. The compiler reports error number 182 for the attempted use of a value parameter in a FORTRAN procedure or function declaration. NBS Pascal does not guarantee word alignment of byte sized variables or arrays of bytes (e.g., array of char). If a variable which is allocated on an odd byte address is passed to an external procedure which expects word alignment, an odd address trap can occur. To prevent this, use the T+ option to see where variables are allocated, and adjust the variable declarations as necessary. To create an object file or object library of separately compiled Pascal procedures or functions, use both the E and X options. Only one psect is created for constants for each NBS Pascal User's Guide Page 16 Extensions compilation, so this may affect how you choose to parcel up separately compiled procedures. The name of the constant psect is based on the program name, which should be unique in the first 5 characters. When the E and X options are used, they should be specified before the program declaration. The main program statement part (begin ... end.) can be omitted when the E option is used. Example: {$E+,X+} program Mod01; const ... type ... procedure Ext1 ( ... ); begin ... end {Ext1}; procedure Ext2 ( ... ); begin ... end {Ext2}; Separately compiled procedures should in general not refer to global variables, as such references are a potential source of programming errors. However, they can read from "input" and write to "output". For RSX11 / RSTS / RT11, external procedure names should be unique in the first 6 characters. External procedure names must not conflict with those generated by the compiler, which are of the form IIInnn, where nnn is a three digit number. (See Appendix B.3 for further details.) External procedures must leave the FP11 in integer and double precision modes when they return. This may restrict the user to calling only those external procedures which use integer and double precision arithmetic. 2.16 MCR Command Line Arguments -------------------------------- Arguments in the form of character strings can be passed to installed Pascal tasks (see also Section 1.4). Two predeclared global parameters are used to access the arguments. The parameter names are argc and argv, and have the following declarations: NBS Pascal User's Guide Page 17 Extensions argc is an integer count of the number of strings (arguments) on the MCR command line, including the command name (argc: integer); argv is an array of pointers used to access the strings (argv: array [0..255] of @array [0..255] of char). For example, character number i of argument n can be obtained from argv[n]@[i]. Note that the task name itself can be accessed with n = 0. Each argument is a null-terminated string. Accessing argv[m] for m>argc will give undefined results, including possible memory protection violations. At present, the RSX and RSTS versions of the Pascal runtime library restrict the number of strings passed to a program to at most 16. 2.17 RT-11 Random Files ----------------------- Random files are implemented for RT-11 with the addition of the UPDATE and SEEK procedures. Records in a file are numbered virtually from 1 to 32767 where each record is assummed to be one element of the declared file type. (e.g. file of char has one byte records, file of real has 4 byte records, and file of "record" has n byte records) Each block (512 bytes) of a file will contain an integer number of records and the largest record allowed is 512 bytes. The SEEK procedure is used to position the file variable the the Nth record of a file. After positioning the file variable the contents of the record may be accessed by dereferencing the file variable as shown below: var random: file of integer; item: integer; begin update (random, "NUMBER.DAT" ); seek (random, 100); item := random@; random@ := item+2; put (random) end; Once the file variable has been positioned to a record, GET and/or PUT can be used to access the next sequential record and/or cause the record to be updated in the file. GET merely scans the file, while PUT sets a flag indicating that the block containing the record should be rewritten before the next block is read. Note that records changed without a following PUT may or may not be updated depending on what is done to other records in the same block. NBS Pascal User's Guide Page 18 Extensions 2.18 RT-11 Command Line Arguments --------------------------------- RT-11 command line arguments are identical to the RSX-11 arguments except that argv indexes start at one instead of zero. The zero index is used for the task name in RSX-11, which does not exist in RT-11. The count of arguments (argc) will be one more than what was actually entered. NBS Pascal User's Guide Page 19 Extensions 3 Restrictions --------------- 3.1 Standard Procedures and Functions -------------------------------------- Only a subset of the Standard Pascal library procedures and functions is presently available. Future versions will implement the remaining ones. The ones presently implemented are: abs arctan break cos eof eoln exp float get ln mark new page put read readln release reset rewrite round sin sqr sqrt trunc write writeln The arguments to arctan, cos, exp, ln, sin and sqrt can be either integer, real or longreal, and the result can be stored in either a real or a longreal variable. The calculations are carried out using double precision (longreal) arithmetic. 3.2 Real Constants ------------------- Real constants cannot be used within structured constants at present. 3.3 Sets --------- Sets are currently limited to base types of at most 16 elements. Set constructors of the form [x, y] are not yet implemented for the case where x and y are variables or expressions involving variables. Instead, use [x] + [y]. However, set constructors of the form [a, b] are implemented for the case where a and b are constants of the set's base type. Set constructors of the form [x..y] are not yet implemented. The relational operators which test for set inclusion (<= and >=) are not yet implemented. 3.4 Maximum Number of Procedures --------------------------------- The number of procedures in a Pascal program is temporarily limited to 150. This limit will be changed to 255 in a future version. NBS Pascal User's Guide Page 20 Restrictions 3.5 Maximum Number of Nesting Levels ------------------------------------- The maximum nesting depth for procedures and functions is 15. 3.6 Maximum Number of Case Constants ------------------------------------- The maximum number of case-constants within a case statement is 253. The ordinal values of the case-constants must be in the range -255 .. 255. The difference between the maximum and minimum case-constant values must be less than or equal to 255. 3.7 LABEL and GOTO ------------------- "label" and "goto" are recognized as Pascal reserved words, but the compiler does not currently generate code for them. An error message (no. 398) is given for label declarations, gotos and labeled statements. A later version of the compiler may implement local gotos (within a procedure), but non-local gotos will probably never be implemented. 3.8 PACKED ARRAYs ------------------ Packed is recognized as a reserved word, but it has no effect. However, byte arrays are implicitly packed. The standard procedures pack and unpack are not implemented at present. 3.9 Procedural and Functional Parameters ----------------------------------------- Procedural and functional parameters are currently not implemented. Therefore, procedure and function identifiers may not be passed as actual parameters to another procedure or function. NBS Pascal User's Guide Page 21 Restrictions 4 Building the Compiler ------------------------ The compiler distribution tape for RSX, IAS and RSTS includes source, object and command files for building the compiler. To build the compiler on your system, the pass 1 and pass 2 tasks must be rebuilt from the object files. This should take only a few minutes. First, copy all the required files from the distribution tape to a single uic (directory) on your disk. Next, the Pascal runtime library (NBSLIB.OLB) must be built from the object files. To build the library, type: MCR>LBR @NBSLIB It may be necessary to edit the task build command files before doing the task builds. To build the tasks, type the following MCR commands: MCR>TKB @P1FP MCR>TKB @P2FP MCR>INS P1FP MCR>INS P2FP The task build command files P1FP.CMD and P2FP.CMD are shown below for an RSX-11M system: P1FP.CMD: --------- P1FP/CP/FP,P1FP/-SP=P1FP,NBSLIB/LB / EXTSCT=$$$$$$:30000 STACK=1000 ASG=SY:1:2:3:4:6 ASG=TI:5 TASK=...PF1 // P2FP.CMD: --------- P2FP/CP/FP,P2FP/-SP=P2FP,NBSLIB/LB / EXTSCT=$$$$$$:20000 STACK=1000 ASG=SY:1:2:3:4:6 ASG=TI:5 TASK=...PF2 // NBS Pascal User's Guide Page 22 Building the Compiler For an RSX-11D system, they are as follows: P1FP.CMD: --------- P1FP/MU,P1FP/SH/-SP=P1FP,NBSLIB/LB / LIBR=SYSRES:RO EXTSCT=$$$$$$:30000 STACK=1000 ASG=SY:1:2:3:4:6 ASG=TI:5 TASK=...PF1 // P2FP.CMD: --------- P2FP/MU,P2FP/SH/-SP=P2FP,NBSLIB/LB / LIBR=SYSRES:RO EXTSCT=$$$$$$:20000 STACK=1000 ASG=SY:1:2:3:4:6 ASG=TI:5 TASK=...PF2 // Normally it should not be necessary to recompile either pass of the compiler. Approximate sizes for the compiler tasks are given below. RSX-11M RSX-11D ----------------- pass 1 28000 25000 words pass 2 31000 28000 words Neither pass of the compiler need be overlayed for RSX-11M. However, both passes can be overlayed if desired. The overlayed version task images are about 4 Kwords smaller than the non-overlayed versions. The extra space can be used to compile larger programs by increasing the compiler heap space. To build the overlayed versions, type the following: MCR>LBR P1FP/CR:140.=P1FP MCR>TKB @P1FPOV MCR>INS P1FP MCR>LBR P2FP/CR:125.=P2FP MCR>TKB @P2FPOV MCR>INS P2FP Indirect command files (BLDNBS.CMD, BLDNBS.COM) are also provided as an aid in building the compiler on RSX11 and VAX/VMS systems. NBS Pascal User's Guide Page 23 Building the Compiler The RT-11 version of the compiler can be built with the following commands: .RUN LINK *PASS1=PASS1,CPASL,NPASL/B:3000 *PASS2=PASS2,CPASL,NPASL/B:2000 PASS1 requires 21810 words of memory plus 4000 words of heap space (dynamically allocated) to compile the compiler. PASS2 requires 18870 words of memory plus 7000 words of heap space. This means that the SJ monitor with only the resident disk handler and TT handler may be used when compiling large programs. Smaller programs may be compiled under the FB monitor. NBS Pascal User's Guide Page 24 Building the Compiler 5 Code Optimization -------------------- Although NBS Pascal does not do extensive global optimization, it does perform a number of local optimizations which result in very good object code in most situations. Examples are given below for some of these optimizations. * Constant folding: The compiler folds (evaluates at compile time) many expressions whose operands are constants. The following are examples of expressions which are folded (assuming M is a constant): 3 * M - 1 sqr(M) + 2 ord('A') < ord('a') * Branch optimization: NBS Pascal performs extensive branch optimization. For example, if the target of a branch is an unconditional branch, the target of the first branch is changed to the final target address. * Common subexpression elimination: In some cases, a repeated expression only needs to be evaluated once. Examples of this optimization are: i := i + 1; a[j+3] := a[j+3] - 1; In both cases, the address of the variable being updated is only evaluated once. * Dead code elimination: If-statements are optimized if the Boolean-expression is a constant. Similarly, case-statements are optimized if the case-index is a constant. In such cases, the compiler generates code only for the if-part or the else-part (if there is one) for the if-statement. For the case-statement, code is generated only for the selected statement. (If there is no selected statement in a case-statement, pass2 reports an error message.) This facility can be used to effect a limited form of conditional compilation. NBS Pascal User's Guide Page 25 Code Optimization Examples: type OS = (RSX11, RSTS, RT11, UNIX); const Debug = false; System = UNIX; begin ... if Debug then writeln(output, 'Some text'); case System of RSX11, RSTS: stmt1; RT11: stmt2; UNIX: stmt3 end; ... NBS Pascal User's Guide Page 26 Code Optimization Appendix A. Error Number Summary --------------------------------- A.1 Compile Time Errors (Pass 1) --------------------------------- The following error numbers are reported by pass 1. They are essentially the same as those found in the Jensen and Wirth Report. If errors are detected in the source code, pass 1 prints a message on the user's terminal: "Pass 1 errors: " where is a count of the number of errors. The user should then examine the source list file, which contains pointers flagging each error. The errors should be corrected and pass 1 should be rerun before running pass 2. In the source list file, fatal errors are preceded by the string '?F*+*+*', and warnings are preceded by the string '%W*+*+*'. Warning messages can be turned off by using the W- option. 1: error in simple type 2: identifier expected 3: error in value part 4: ')' expected 5: ':' expected 6: illegal symbol 7: error in parameter list 8: 'of' expected 9: '(' expected 10: error in type 11: '[' expected 12: ']' expected 13: 'end' expected 14: ';' expected 15: integer expected 16: '=' expected 17: 'begin' expected 18: error in declaration part 19: error in field list 20: ',' expected 21: '.' expected 50: error in constant 51: ':=' expected 52: 'then' expected 53: 'until' expected 54: 'do' expected 55: 'to' or 'downto' expected 56: 'if' expected 57: 'exit' expected 58: error in factor NBS Pascal User's Guide Page 27 Error Number Summary 59: error in variable 101: identifier previously declared 102: low bound exceeds high bound 103: identifier is not of appropriate class 104: identifier not declared 105: sign not allowed 106: constant expected 107: incompatible subrange types 108: file type not allowed 109: real type not allowed 110: tagfield type must be scalar or subrange 111: type incompatible with tagfield 112: real index type not allowed 113: illegal index type 114: real base type not allowed 115: illegal base type 116: error in type of standard procedure parameter 117: unsatisfied forward reference 118: forward referenced type identifier in variable declaration 119: already forward declared; parameter list not allowed 120: illegal function result type 121: file value parameter not allowed 122: already forward declared; result type not allowed 123: missing result type in function declaration 124: F-format for real type only 125: error in type of standard function parameter 126: number of parameters does not agree with declaration 127: illegal parameter substitution 128: result type of parameter function does not agree with declaration 129: type conflict of operands 130: expression is not of set type 131: tests on equality allowed only 132: strict inclusion not allowed 133: file comparison not allowed 134: illegal type of operand(s) 135: type of operand must be Boolean 136: set element type must be scalar or subrange 137: set element types not compatible 138: type of variable is not array 139: index type not compatible with declaration 140: type of variable is not record 141: type of variable must be file or pointer 142: illegal parameter substitution 143: illegal for-statement control variable 144: illegal type of expression 145: type conflict 146: assignment of files not allowed 147: label type incompatible with selecting expression 148: subrange bounds must be scalar 149: index type must not be integer 150: assignment to standard function not allowed 151: assignment to formal function not allowed 152: no such field in this record NBS Pascal User's Guide Page 28 Error Number Summary 153: illegal type in READ 154: actual parameter must be a variable 155: control variable must not be formal 156: multidefined case label 157: too many cases in case statement 158: missing corresponding variant declaration 159: illegal tagfield type 160: previous declaration was not forward 161: already declared forward 162: slice variant separator is a colon 163: missing variant in declaration 164: missing slice variant in declaration 165: multidefined label 166: undeclared exit label 167: undeclared label 168: must be file type 169: must be text file type 173: illegal case selector type 174: illegal use of type identifier 182: parameters to FORTRAN procedures and functions must be declared as var parameters 201: error in real constant: digit expected 202: string constant contains line feed 203: integer constant exceeds range 204: illegal digit in octal number 205: string too long 250: too many nested scopes of identifiers 251: too many nested procedures and/or functions 252: too many forward references of procedures 253: procedure too long 254: too many constants in this procedure 255: too many errors in this source line 396: illegal character 398: not yet implemented in NBS Pascal 399: not yet implemented 400: compiler error 401: illegal call on main program warning messages: 411: loop statement is a nonstandard extension 412: exit statement is a nonstandard extension 413: nonstandard ordering of label, const, type, var, or procedure/function declarations 414: structured constant is a nonstandard extension 415: dynamic NEW is an extension 420: unknown directive NBS Pascal User's Guide Page 29 Error Number Summary A.2 Compile Time Errors (Pass 2) --------------------------------- Pass 2 errors are generally caused by exceeding an implementation limit or possibly by an error in the compiler itself. In general, these errors mean that some sort of catastrophic failure within the compiler has occurred. One common cause of such a failure is running the second pass on intermediate code which is in error. This may happen if there are errors reported by the first pass. Error 18 may be caused by using an array (e.g., a string) as a non-var parameter to a procedure. Pass 2 errors are reported on the user's terminal by a message of the form: "Pass 2 error in " where is the name of the procedure being compiled, and is as follows: 1: stack-arg mismatch. 2: stack overflow. 3: code buffer overflow (procedure too large). 4: relocation table overflow (too many references to global variables or consts). 6: operand stack overflow. 9: non-immediate litd processed. 10: can't find temporary. 18: double load not implemented. 19: multiple store not yet implemented. 20: round not yet implemented. 30: symbol table overflow (too many procedures). 31: sadel not yet implemented (set constructor contains more than one variable). 32: set inclusion operators (<=, >=) not yet implemented. 44: no registers available in getregister. 45: insufficient registers available for data move. 70: no such case-label; no code generated. 99: incorrect data in intermediate code file. NBS Pascal User's Guide Page 30 Error Number Summary A.3 Run Time Errors -------------------- Run time errors are reported on the user's terminal by a message of the form: "PASCAL RUN-TIME ERROR NUMBER: " where is as follows: 1: RESET/REWRITE - no FDB space 2: RESET - file not found 3: GET - eof on input 4: PUT - no eof on output 8: NEW - heap overflow 9: MARK - heap overflow 10: RELEASE - no previous heap 101: SQRT - square root of a negative number 102: EXP - floating overflow 103: EXP - floating underflow 104: LN - log of a negative number 105: FICS - FIS stack overflow (fis version) 106: FICS - FIS stack underflow (fis version) A.4 RT-11 Run Time Errors ------------------------- In the RT-11 run time system errors are printed in a more descriptive form and should be self explanatory. They are of the form: ?HEAP REQUEST OR OVERFLOW ERROR NBS Pascal User's Guide Page 31 Error Number Summary Appendix B. Pascal Runtime Environment --------------------------------------- B.1 Procedure Interface ------------------------ In this section we describe the procedure interface (stack frame and call method) for Pascal on the PDP 11. Several different methods are commonly used to implement the runtime environment for block structured languages such as Algol and Pascal. One such method is to maintain a "display" of pointers to the most recently invoked stack frame at each lex level. The stack frame for lex level d is found by accessing display[d]. This method is very effective if the display can be kept in high speed registers. Since the PDP 11 does not have sufficient high speed registers to implement a display, the method used by NBS Pascal is to maintain two chains of pointers, called the "static link" and the "dynamic link". The dynamic link chains every stack frame to its immediate predecessor, while the static link chains only those frames which are currently accessible according to Pascal's scope rules. Local variables within a procedure or function are accessed by means of a local pointer (LP) to the current stack frame. Global variables are accessed as offsets to a psect. Variables declared at intermediate levels which are currently accessible are found by following the static link out to the proper level. Since most variable accesses are probably at the local level (including parameters) or global level, the additional overhead of the static chain should not affect performance significantly for most programs. Table 1 shows the PDP 11 register usage for Pascal, and Figure 1 shows the PDP 11 stack frame. NBS Pascal User's Guide Page 32 Pascal Runtime Environment General Registers Floating Point Registers ----------------- ------------------------ R0-R3: top of stack F0-F3: floating point temporaries. temporaries. R4: roving pointer (RP) F4, F5: not used. to outer lex level stack frames. R5: local pointer (LP) to current stack frame. SP: stack pointer. PC: program counter. Table 1. PDP 11 Register Usage ------------------------------ NBS Pascal User's Guide Page 33 Pascal Runtime Environment ^ ^ | | | | low addresses stack growth | | | | . . . . . . . . |===============| | |<--- sp |---------------| temporaries | (saved r2) | |---------------| | (saved r3) | . . . . . . . . |===============| | | local |---------------| variables | | lp-4 |---------------| | | lp-2 . . . . . . . . |===============| | static link |<--- lp (R5) |---------------| | dynamic link | lp+2 |---------------| | return addr | lp+4 . . . . . . . . |===============| | param n | lp+6 |---------------| | ... | lp+8 parameters |---------------| | param 2 | |---------------| | param 1 | . . . . . . . . |===============| returned value | | (functions only)| | . . . . . . . . |===============| | | | | high addresses | | v Figure 1. PDP 11 Stack Frame ---------------------------- NBS Pascal User's Guide Page 34 Pascal Runtime Environment Typical PDP 11 code sequences for procedure calls, entry, and exit are given below. procedure call: --------------- (establish environment of called procedure in r4.) mov param1, -(sp) ; push arg 1 mov param2, -(sp) ; push arg 2 ... mov paramn, -(sp) ; push arg n jsr pc, calledproc (for functions only:) mov (sp)+, destin ; pop function result. (next instruction) procedure entry: ---------------- mov r5, -(sp) ; push previous local pointer - ; dynamic link. mov r4, -(sp) ; push roving pointer - ; static link. mov sp, r5 ; establish local pointer to ; current stack frame. sub #k, sp ; make room for k bytes of ; local variables. mov r3, -(sp) ; save r3 (if used). mov r2, -(sp) ; save r2 (if used). (r0-r1 are scratch - they are not saved/restored.) (next instruction) procedure exit: --------------- (for functions only:) mov result, #p(r5) ; save function result. ... mov (sp)+, r2 ; restore r2 (if used) mov (sp)+, r3 ; restore r3 (if used) mov r5, sp ; restore sp (discard local ; variables and temporaries). mov (sp)+, r4 ; restore r4 mov (sp)+, r5 ; restore r5 mov (sp)+, #q(sp) ; move up return address add #t, sp ; discard parameters rts pc ; return NBS Pascal User's Guide Page 35 Pascal Runtime Environment B.2 Runtime Library -------------------- Standard runtime procedures are identified in the compiler and runtime library by procedure number. Entry points are of the form $$$nnn for RSX and RSTS, and ___nnn for UNIX, where nnn is the procedure number. Procedures 201 - 218 are only used in the FIS version. The procedure numbers are assigned as follows: Entry Number Point Function ------------------------ 0 $$$000 initialize program 1 $$$001 exit program 4 $$$004 new 6 $$$006 mark heap 7 $$$007 release heap 16 $$$016 initialize file block 17 $$$017 open file (reset/rewrite) 20 $$$020 close file 21 $$$021 get 22 $$$022 put 23 $$$023 break 24 $$$024 read character 25 $$$025 write character 27 $$$027 write string 29 $$$029 write boolean 30 $$$030 read integer 31 $$$031 write integer 34 $$$034 read real 35 $$$035 write real (f format) 36 $$$036 read double real 37 $$$037 write double real (f format) 39 $$$039 write octal 41 $$$041 write real (e format) 43 $$$043 write double real (e format) 44 $$$044 read end of line 45 $$$045 write end of line 47 $$$047 page 98 $$$098 trunc (FIS) 99 $$$099 round (FIS) 101 $$$101 sqrt 102 $$$102 ln 103 $$$103 exp 104 $$$104 sin 105 $$$105 cos 106 $$$106 arctan 201 $$$201 float integer value 202 $$$202 floating square 210 $$$210 pop FIS stack NBS Pascal User's Guide Page 36 Pascal Runtime Environment 211 $$$211 push to FIS stack 212 $$$212 push down FIS stack pointer 213 $$$213 push to FIS stack from SP stack 214 $$$214 pop from FIS stack to SP stack 215 $$$215 floating add 216 $$$216 floating subtract 217 $$$217 floating multiply 218 $$$218 floating divide NBS Pascal User's Guide Page 37 Pascal Runtime Environment B.3 External Names ------------------- Procedure names in the compiled object code (psect names, etc.) depend on the setting of the pass2 X option. Normally (pass2 X option off) the compiler guarantees that no name conflicts will occur regardless of whether or not the user's Pascal procedure names are unique in the first 6 characters. This guarantee cannot be made when the pass2 X option is on, as external names are then based on the first 6 characters of the actual procedure name. The following example illustrates the effect of the X option on external names: program Example; const ... procedure First; begin end {First}; procedure Second; begin end {Second}; begin end {Example}. Pass2 X option X- X+ -------------- Code for Example III000 EXAMPL Code for First III001 FIRST Code for Second III002 SECOND Constants DDD000 EXAMP. Global variables $GLOBS $GLOBS Heap $$$$$$ $$$$$$ If the underscore character ('_') is used in the first 6 characters of an external procedure name or a procedure compiled with the X option on, it will be mapped to '$' in the external name. Since this can cause conflicts with system routine names, it is best to avoid '_' in external procedure names. *********************************** ***********************************