The purpose of Chapter 7 is to define the language features of Pascal/MT+ which are common to each implementation of the compiler. Those features of Pascal/MT+ which are not part of the Pascal language as it is defined in Jensen and Wirth are discussed in more detail than the features which are identical to the Jensen and Wirth definition. Therefore, if you do not know Pascal it is recommended that a copy of Jensen and Wirth's 'User Manual and Report' be studied as you read this chapter. The chapter headings are the same as those used in the 'Report'. In each section BNF (Backus Normal Form) syntax is provided for reference. The complete BNF description of the language is present in an appendix.
Features of the ISO Pascal include the data types REAL, INTEGER, CHAR, BOOLEAN, multidimensional ARRAYS, user-defined RECORDS, POINTER types, File variables, user defined TYPES and CONSTANTS, and SETS (implemented in this version with a base type of 256 one byte elements), ENUMERATED types, and SUBRANGE types.
Also included in ISO Pascal are PROCEDURES, FUNCTIONS, and PROGRAMS. Passing procedures and functions as parameters to a Pascal routine is part of the ISO standard, as well as conformant arrays in which arrays of the same index type and element type but different sizes may be passed to the same procedure. Supported at the syntax level are external parameters with the PROGRAM statement.
TYPED and TEXT files are supported as defined in the standard using the Pascal routines RESET, REWRITE, GET, PUT, READ, WRITE, READLN, and WRITELN. The default I/O files INPUT and OUTPUT are defined.
All ISO statements are supported including WITH, REPEAT...UNTIL, CASE, WHILE loops, FOR loops, IF..THEN..ELSE, and GOTO.
PACK and UNPACK are supported but do not affect the outcome of the program (data structures are always packed at the byte level). NEW and DISPOSE are implemented and allocate and deallocate HEAP space.
Modular compilation is an extension of MT+ compilers. Variables and routines may be made public and/or private and may be called from any other module or main program. This feature allows easy inclusion of relocatable assembly language as separate modules in a final program.
The extended data types STRING, BYTE, and WORD are implemented in all versions of the Pascal compiler. The STRING type includes a length byte followed by the maximum number of bytes possible. Routines are supplied to INSERT a character or a string, DELETE from a string, find the POSition of a character in a string, COPY a portion of one string to another, and CONCATenate two or more strings and/or characters together. BYTE is a one byte data item for representing numbers from 0 to 255. WORD is CPU dependent but is two bytes for 8-bit CPU's and four bytes for 16-bit CPU's.
Additional procedures to manage files on disk are implemented. A file on disk is associated with an internal file, may be closed or deleted. RANDOM files are supported in all versions except those running under CP/M 1.4 and CP/M 1.4 compatible operating systems.
Manipulating BITS and BYTES is done using routines to TEST, SET, CLEAR, SHIFT RIGHT and LEFT, return HI or LOW of a variable, and SWAP the high and low bytes of a varible.
Miscelaneous routines to access items in a program are to return the address of a variable or routine, return the size of a variable or type, move a given number of bytes from one memory location to another, fill a data item with a certain character. Also, the amount of HEAPspace available at any given time is accessable. Garbage collection on the HEAP is supported.
Logical operators for non-booleans is implemented.
HEX literal numbers may be used with a dollar sign ($).
Include files are supported.
An ELSE clause on the CASE statement is provided.
Program CHAINING and OVERLAYS are supported. Chaining is such that the code for one program is totally replaced by code for the next program, but heap space may be maintained across a CHAIN. Overlays are desribed in Chapter 3.
<letter> ::= A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | a | b | c | d | e | f | g | h | i | j | k | l | m | n | n | o | p | q | r | s | t | u | v | w | x | y | z | @ <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F {only allowed in HEX numbers} <special symbol> ::= {reserved words are listed in the appendix} + | - | * | / | = | <> | < | > | <= | >= | ( | ) | [ | ] | { | } | := | . | , | ; | : | ' | ^ | {the following are additional or substitutions:} (. | .) | ~ | \ | ? | ! | | | $ | & | # ~, \, and ? are synonyms (see Section 7.8.1.1) !, and | are synonyms (see Section 7.8.1.2) & (see Section 7.8.1.3)
Extensions:
The symbol '@' is a legal letter in addition to those listed in the 'Report.' This has been added because the run-time library routines are written using this special character as the first letter of their name. By adding '@' conflict. with user names is avoided. Users are allowed to call the run-time library routines. See Section 7.4 for further information.
A comment beginning with '(*' must end with '*)'. A comment beginning with '{' must end with '}'.
<comment>::= { < any characters > } | (* < any characters > *)
To allow nested comments the begin comment delimiter must be the same as the end comment delimiter. Thus, in Pascal/MT+ the following is legal:
(* outer comment ...{ inner comment....}...outer comment *)
<identifier> ::= <letter> {<letter or digit or underscore>} <letter or digit or underscore> ::= <letter> | <digit> | _ <digit sequence> ::= <digit> {<digit>} <unsigned integer> ::= $ <digit sequence> | # <digit sequence> | <digit sequence> <unsigned real> ::= <unsigned integer> . <digit sequence> | <unsigned integer> . <digit sequence> E <scale factor> | <unsigned integer> E <scale factor> <unsigned number> ::= <unsigned integer> | <unsigned real> <scale factor> ::= <unsigned integer> | <sign><unsigned integer> <sign> ::= + | - <string> ::= ' <character> {<character>}' | ''
All identifiers are significant to eight characters. External identifiers may be significant to only six or seven characters depending upon the host systems. The underscore character (_) is legal between letters and digits in an identifier and is ignored by the compiler, i.e. A_B is equivalent to AB. Whether the identifier is upper or lower case does not matter, i.e ab is equivalent to AB, aB, and Ab. Identifiers may begin with an '@' character. This is to allow declaration of external run-time routines within a Pascal program. Users are, in general, advised to avoid the '@' character to eliminate the chance of conflict with run-time routine names. Because the ISO standard defines '@' to be equivalent to '^', a compiler switch, '@', causes the '@' character to be removed from the <letter> production and become the pointer symbol. This means that '@' is no longer available for identifiers.
Numbers may be hex as well as decimal. Placing a '$' in front of an integer number causes it to be interpreted as a hex number by the compiler. The symbol <digit> now includes: 'A', 'B', 'C', 'D', 'E' and 'F'. These may be upper or lower case.
<constant identifier> ::= <identifier> <constant> ::= <unsigned number> | <sign><unsigned number> | <constant identifier> | <sign><constant identifier> | <string> <constant definition> ::= <identifier> = <constant>
In addition to all constant declarations available in standard Pascal, Pascal/MT+ supports declaration of a null string constant:
EXAMPLE: nullstr = '';
<type> ::= <simple type> | <structured type> | <pointer type> <type definition> ::= <identifier> = <type>
<simple type> ::= <scalar type> | <subrange type> | <type identifier> <type identifier> ::= <identifier>
<scalar type> ::= ( <identifier> { , <identifier>} )
The following types are standard in Pascal/MT+
INTEGER REAL BOOLEAN CHAR BYTE WORD STRING
The following additional standard types exist in Pascal/MT+. See Section 5.1 for information on representation and usage of all standard and structured types.
STRING : Packed array [ 0..n ] of char; byte 0 is dynamic-length byte bytes 1..n are characters. BYTE : Subrange 0..255 with special attribute that it is compatible also with CHAR type WORD : Unsigned integer.
<subrange type> ::= <constant> .. <constant>
<structured type> ::= <unpacked structured type> | PACKED <unpacked structured type> <unpacked structured type> ::= <array type> | <record type> | <set type> | <file type>
The reserved word PACKED is detected but because all structures are packed at the BYTE level even if the PACKED reserved word is not found, it has no effect. The same is true for UNPACK.
<array type> ::= <normal array> | <string array> <string array> ::= STRING <max length> <max length> ::= [ <intconst> ] | <empty> <intconst> ::= <unsigned integer> | <int const id> <int const id> ::= <identifier> <normal array> ::= ARRAY [ <index type> {,<index type>}] OF <component type> <index type> ::= <simple type> <component type> ::= <type>
Variables of type STRING have a default length of 81 bytes (80 data characters). A different length can be specified in square brackets following the word STRING. The length must be either a literal or declared constant and represents the length of the DATA portion (i.e. one more byte is actually allocated for the length). For example, STRING[5] or STRING[XYZ], where XYZ is a constant (XYZ = 5), would cause allocation of six bytes of data storage for a variable of this type.
<record type> ::= RECORD <field list> END <field list> ::= <fixed part> | <fixed part> ; <variant part> | <variant part> <fixed part> ::= <record section> {;<record section>} <record section> ::= <field identifier> {,<field identifier>} : <type> | <empty> <variant part> ::= CASE <tag field> <type identifier> OF <variant> {;<variant>} <variant> ::= <case label list> : (<field list>) | <empty> <case label list> ::= <case label> {,<case label>} <case label> ::= <constant> <tag field> ::= <identifier> : | <empty>
<set type> ::= SET OF <base type> <base type> ::= <simple type>
The maximum range of a base type is 0..255. For example, the set of [0..10000] or the set of 0..256 are not legal, but the set of CHAR or set of 0..255 are legal.
<file type> ::= file {of <type>}
Both typed and untyped files are allowed. Untyped files are used for CHAINING (see the Section 3.5) and are also used with the BLOCKREAD and BLOCKWRITE procedures (see Section 3.4.). The user should be extremely careful when using untyped files.
When wishing to read a file of ASCII characters and using implied conversions for integers and reals the user should use the predefined type TEXT. TEXT is NOT exactly the same as FILE OF CHAR but has conversion implied in READ and WRITE procedure calls and also may be used with READLN and WRITELN. A file that is of type TEXT is declared in the following manner. ' VAR F : TEXT'. The INCORRECT syntax for declaring a TEXT file is 'VAR F : FILE OF TEXT'. See the appendix on Pascal file handling.
<pointer type> ::= ^ <type identifier>
Pointer types are identical to the standard except that weak type checking exists when the RELAXED type checking feature of the compiler is enabled (the default). In this case pointers and WORDs used as pointers are compatible in all cases. Also, pointer arithmetic is allowed. Note that with compiler switch @, the character may be replaced with '@' (the two may be mixed within a program).
The most common "standard Pascal" question concerns type conflict errors messages from the compiler. Types must be identical if the variable is passed to a VAR parameter. Types must be compatible for expressions and assignment statments. To understand the difference between compatible and identical types the user should think of types as pointers to compile-time records. If you declare a type (such as T=ARRAY [1..10] OF INTEGER) then any thing which is declared as type T really points to the record describing type T. If, on the other hand, you declare two variables to be as below,
VAR A1 : ARRAY [1..10] OF INTEGER; A2 : ARRAY [1..10] OF INTEGER;
they are not identical since the compiler created a new record for each type and therefore Al and A2 do not point to the same record in memory at compile-time. The general rule is that if you cannot find your way back to a type definition then the types are not identical.
Below is a section from the ISO draft standard (DPS-7185) which is
available from the American National Standards Institute. The ISO
standard definition of compatible types is:
Types T1 and T2 shall be designated compatible if any of the four
statements that follow is true. ...Assignment compatibility. A value of type T2 shall be designated
assignment-compatible with a type T1 if any of the five statements
that follow is true. At any place where the rule of assignment-compatibility is used:
(a) T1 and T2 are the same type.
(b) T1 is a subrange of T2 or T2 is a subrange of T1, or both T1 and
T2 are subranges of the same host type.
(c) T1 and T2 are designated packed or neither T1 nor T2 is designated
packed.
(d) T1 and T2 are string-types * with the same number of
components.
(a) T1 and T2 are the same type, that is neither a file-type nor a
structured-type with a file component (this rule is to be interpreted
recursively).
(b) T1 is the real-type and T2 is the integer-type.
(c) T1 and T2 are compatible ordinal-types ** and the value of type T2
is in the closed interval specified by the type T1.
(d) T1 and T2 are compatible set-types and all the members of the
value of type T2 are in the closed interval specified by the base-type
of T1.
(e) T1 and T2 are compatible string-types * .
(a) It shall be an error if T1 and T2 are compatible ordinal-types **
and the value of type T2 is not in the closed interval specified by
the type T1.
(b) It shall be an error is 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.
* string-types in ISO Pascals are arrays of characters.
** ordinal types are named subranges of numbers or enumerations.
CHR, ORD, ODD, and WRD are type conversion operators which generate no code but tell the compiler that the following 8 or 16 bit data item is to be considered to be of type CHAR, INTEGER, BOOLEAN, or WORD respectively. These may be used in expressions and with value parameters but not VAR parameters.
<variable declaration> ::= <variable> : <type> | <empty> <variable> ::= <var> | <external var> | <absolute var> <external var> ::= EXTERNAL <var> <absolute var> ::= ABSOLUTE [ <constant> ] <var> <var> ::= <entire variable> | <component variable> | <referenced variable>
More information on ABSOLUTE variables may be found in Section 3.7 on Non-standard data access methods.
<entire variable> ::= <variable identifier> <variable identifier> ::= <identifier>
<component variable> ::= <indexed variable> | <field designator> | <file buffer>
<indexed variable> ::= <array variable> [<expression> {,<expression>}] <array variable> ::= <variable>
STRING variables are to be treated as a PACKED array of CHAR for subscripting purposes. The valid range is 0..max-length where max-length is 80 for a default length.
<field designator> ::= <record variable> . <field identifier> <record variable> ::= <variable> <field identifier> ::= <identifier>
<file buffer> ::= <file variable> ^ <file variable> ::= <variable>
<referenced variable> ::= <pointer variable> ^ <pointer variable> ::= <variable>
<unsigned constant> ::= <unsigned number> | <string> | NIL | <constant identifier> <factor> ::= <variable> | <unsigned constant> | <function designator> | ( <expression> ) | <logical not operator> <factor> | <set> <set> ::= [ <element list> ] <element list> ::= <element> {,<element>} | <empty> <element> ::= <expression> | <expression> .. <expression> <term> ::= <factor> <multiplying operator> <factor> <simple expression> ::= <term> | <simple expression> <adding operator> <term> | <adding operator> <term> <expression> ::= <simple expression> | <simple expression> <relational operator> | <simple expression>
An additional category of operators on 16-bit variables is &, ! (also |), and ~ (also \ and ?) denoting AND, OR and ONE's complement NOT, respectively. These have the same precedence as their equivalent boolean operators and accept any type of operand with a size <= 2 bytes.
<logical not operator> ::= NOT | ~ | \ | ?
~ (synonyms \ and ?) is a NOT operator for non-booleans.
<multiplying operator> ::= * | / | DIV | MOD | AND | &
& is an AND operator on non-booleans.
<adding operator> ::= + | - | OR | | | !
! (synonym |) is an OR operator on non-booleans.
<relational operators> ::= = | <> | < | <= | > | >= | IN
<function designator> ::= <function identifier> | <function identifier> ( <parm> {,<parm>} ) <function identifier> ::= <identifier>
<statement> ::= <label> : <unlabelled statement> | <unlabelled statement> <unlabelled statement> ::= <simple statement> | <structured statement> <label> ::= <unsigned integer>
<simple statement> ::= <assignment statement> | <procedure statement> | <goto statement> | <empty statement> <empty statement> ::= <empty>
<assignment statement> ::= <variable> := <expression> | <function identifier> := <expression>
To the list of exceptions to assignment compatibility in Jensen and Wirth add:
<procedure statement> ::= <procedure identifier> ( <parm> {,<parm>} ) | <procedure identifier> <procedure identifier>::= <identifier> <parm> ::= <procedure identifier> | <function identifier> | <expression> <variable>
<goto statement> ::= goto <label>
Goto out of a recursive procedure or out of a sequence of recursive calls is not supported.
<structured statement> ::= <repetitive statment> | <conditional statement> | <compound statement> | <with statement>
<compound statement> ::= BEGIN <statement> {,<statement>} END
<conditional statement> ::= <case statement> | <if statement>
<if statement> ::= IF <expression> THEN <statement> ELSE <statement> | IF <expression> THEN <statement>
<case statement> ::= CASE <expression> OF <case list> {;<case list>} {ELSE <statement>} END <case list> ::= <label list> : <statement> | <empty> <label list> ::= <case label> {,<case label>} <case label> ::= <non-real short scalar constant>
Pascal/MT+ implements an ELSE clause on the case statement. In addition, if the selecting expression does not match any of the case selectors, the program flow will "drop through" the case statement. This is different than the standard which says this condition is an error.
Example:
CASE CH OF 'A' : WRITELN('A'); 'Q' : WRITELN('Q'); (* optional semicolon *) ELSE WRITELN('NOT A OR Q') END
<repetitive statement> ::= <repeat statement> | <while statement> | <for statement>
<while statement> ::= WHILE <expression> DO <statement>
<repeat statement> ::= REPEAT <statement> {;<statement>} UNTIL <expression>
<for statement> ::= FOR <ctrlvar> := <for list> DO <statement> <for list> ::= <expression> DOWNTO <expression> | <expression> TO <expression> <ctrlvar> ::= <variable>
<with statement> ::= WITH <record variable list> DO <statment> <record variable list> ::= <record variable> {,<record variable>}
The user should note that the ISO standard differs from Jensen and Wirth in that only LOCAL variables are allowed as FOR loop control variables. This prevents such programming errors as the inadvertant use of a GLOBAL variable as a FOR control variable when buried five levels deep in nesting.
<procedure declaration> ::= EXTERNAL <procedure heading> | <procedure heading> <block> <block> ::= <label declaration part> <constant definition part> <type definition part> <variable declaration part> <procfunc declaration part> <statement part> <procedure heading> ::= PROCEDURE <identifier> <parmlist> | PROCEDURE <identifier> ; | PROCEDURE INTERRUPT [ <constant> ] ; <parmlist> ::= ( <fparm> {,<fparm>} ) <fparm> ::= <procedure heading> | <function heading> | VAR <parm group> | <parm group> <parm group> ::= <identifier> {,<identifier>} : <type identifier> | <identifier> {,<identifier>} : <conformant array> <conformant array> ::= VAR ARRAY [ <indxtyp> {;<indxtyp>} ] OF <conarray2> <conarray2> ::= <type identifier> | <conformant array> <indxtyp> ::= <identifier> .. <identifier> : <ordtypid> <ordtypid> ::= <scalar type identifier> | <subrange type identifier> <scalar type identifier> ::= <identifier> <subrange type identifier> ::= <identifier> <label declaration part> ::= <empty> | LABEL <label> {,<label>} ; <constant definition part> ::= <empty> | CONST <constant definition> {;<constant definition>} ; <type definition part> ::= <empty> | TYPE <type definition> {;<type definition>} ; <variable declaration part> ::= <empty> | VAR <variable declaration> {;<variable declaration>} ; <procfunc declaration part> ::= {<proc or func> ; } <proc or func> ::= <procedure declaration> | <function declaration> <statement part> ::= <compound statement>
A special procedure type is implemented in Pascal/MT+, the interrupt procedure. The user selects the vector to be associated with each interrupt. The procedure is declared as follows:
PROCEDURE INTERRUPT[vector number] procname;
The user may refer to Section 3.6 for more information on using INTERRUPT procedures.
The following is a list of Pascal/MT+ built-in procedures (except I/O which are listed in Section 7.10.1.1). See Section 3.4 for parameters and usage. These procedures are predeclared in a scope surrounding the program. Therefore, any user routines of the same name will take precedence.
NEW DISPOSE EXIT INSERT DELETE COPY CONCAT FILLCHAR MOVELEFT MOVERIGHT CLRBIT HI LO SETBIT SHL SHR SWAP TSTBIT LENGTH POS ADDR EXIT MAXAVAIL MEMAVAIL SIZEOF WAIT LEAVE
All standard file handling procedures are included. In addition the procedure ASSIGN(f,string) is added where f is a file and string is a literal or variable string. ASSIGN assigns the external file name contained in string to the file f. It is used preceeding a RESET or REWRITE. See Section 3.4.15 for details.
Listed below are the names of the file handling procedures:
GET PUT RESET REWRITE ASSIGN CLOSE CLOSEDEL PURGE OPEN BLOCKREAD BLOCKWRITE SEEKWRITE CHAIN PAGE SEEKREAD READ GNB WNB IORESULT WRITE READLN WRITELN
"Local" (sometimes called temporary) files in Pascal do not require the use of the ASSIGN procedure but are implemented in a different way in each Pascal system. In Pascal/MT+ a file is assigned a system-defined file name of PASTMP??.$$$. The REWRITE routine and the linker interact to allow this to be done. The linker fills the data areas with bytes of 00 so that the REWRITE routine can see if the file name is of length 0. In a recursive environment the data area in which files are allocated is not initialized at the beginning of procedure execution. Therefore if the user wishes to use a "temporary" file accessed by a local variable in a recursive environment the user must execute ASSIGN(<file>,'') before executing REWRITE.
NEW DISPOSE
In addition to NEW and DISPOSE, MEMAVAIL and MAXAVAIL are also included.
PACK(A,I,Z) UNPACK(Z,A,I)
Forward procedure declarations are implemented in Pascal/MT+. It is recommended that this feature not be used unless strict Pascal conformance is required. Due to the nature of the three pass compiler, forward declarations are not necessary.
The user should note that the ISO standard has added the CONFORMANT ARRAY SCHEMA for passing arrays of similar structure, i.e., same number of dimensions, compatible index type, and same element type, but different upper and lower bounds. The user may now pass, for example, an array dimensioned as 1..10 and an array 2..50 to a procedure which is expecting an array as a parameter. The user defines the array as a VAR parameter (failure to do this generates error 154: 'actual parameter must be a variable'), and in the process of declaring the array, the user also defines variables to hold the upper and lower bound of the array. These upper- and lower-bound items are filled in at RUN-TIME by the generated code. The user should note that in order to pass arrays in this manner, the index type must be compatible with the type of the conformant array bounds.
Below is an example of passing two arrays to a procedure which displays the contents of the arrays on the file OUTPUT:
PROGRAM DEMOCON; TYPE NATURAL = 0..MAXINT; (* FOR USE IN CONFORMANT ARRAY DECLARATION *) VAR A1 : ARRAY [1..10] OF INTEGER; A2 : ARRAY [2..20] OF INTEGER; PROCEDURE DISPLAYIT( VAR AR1 : ARRAY [LOWBOUND..HIBOUND:NATURAL] OF INTEGER ); (* THIS DECLARATION DEFINES THREE VARIABLES: AR1 : THE PASSED ARRAY LOWBOUND: THE LOWER BOUND OF AR1 (PASSED AT RUN-TIME) HIBOUND : THE UPPER BOUND OF AR1 (PASSED AT RUN-TIME) *) VAR I : NATURAL; (* COMPATIBLE WITH THE INDEX TYPE OF THE CONFORMANT ARRAY *) BEGIN FOR I := LOWBOUND TO HIBOUND DO WRITELN('INPUT ARRAY[',I,']=',AR1[I]) END; BEGIN (* MAIN PROGRAM *) DISPLAYIT(A1); (* CALL DISPLAYIT AND PASS A1 EXPLICITLY AND 1 AND 10 IMPLICITLY *) DISPLAYIT(A2) (* CALL DISPLAYIT AND PASS A2 EXPLICITLY AND 2 AND 20 IMPLICITLY *) END.
<function decl> ::= EXTERNAL <function heading> | <function heading> <block> <functon heading> ::= FUNCTION <identifier><parmlist>:<result type> | FUNCTION <identifier> : <result type> ; <result type> ::= <type identifier>
Listed below are the names of the standard functions supported:
ABS SQR SIN COS SHORT EXP LN SQRT ARCTAN * ODD TRUNC ROUND ORD WRD CHR SUCC PRED EOLN EOF IORESULT MEMAVAIL MAXAVAIL ADDR SIZEOF POS LENGTH LENGTH LONG ULONG
* for input which is less than 0, ARCTAN returns values in the 4th quadrant.
WRD(x) : The value x (a variable or expression) is treated as the WORD (unsigned integer) value of x.
Other transfer functions are as defined in standard Pascal.
File handling: ( F is a file variable. See files in appendix.)
PUT(F) GET(F) RESET(F) REWRITE(F) PAGE(F) EOF(F) EOLN(F)
Because the CP/M file structure does not store the number of valid bytes which are present in the last sector, EOF does not return true on NON-TEXT files until all of the last sector is read. The user must check a dummy final record or save in a separate file the number of records contained in the file.
Dynamic Allocation: (Tn is a variant record selector, P is a pointer)
NEW(P) NEW(P,T1,T2,...,Tn) DISPOSE(P) DISPOSE(P,T1,T2,...,Tn)
Data Transfer Procedures: (see page 106 of Jensen and Wirth for a more complete description)
PACK(A,I,Z) UNPACK(Z,A,I)
Arithmetic functions:
ABS(X) OR ABS(I) - special returns the type of its argument SQR(X) OR SQR(I) - if passed integer returns integer, etc.
THE FOLLOWING ARE AVAILABLE ONLY IN FLOATING POINT IN PASCAL/MT+ AND NOT BCD:
SIN(X) COS(X) ARCTAN(X) EXP(X) LN(X) SQRT(X)
Transfer functions: (SC is a non-real short scalar)
Implemented at compile-time and generate no code:
ODD(SC) : BOOLEAN ORD(SC) : INTEGER CHR(SC) : CHAR WRD(SC) : WORD
Implemented at run-time and do generate code:
SUCC(<any scalar type except real>) PRED(<any scalar type except real>)
Pascal/MT+ supports all standard Pascal I/O facilities. In addition to the standard I/O facilities, Pascal/MT+ provides a mechanism by which Pascal/MT+ programmers can write their own character level I/O drivers in Pascal/MT+. This facility allows the ROM-based program to be system independent and allows the user to use the input and output format conversion routines with strings, I/O ports, etc. See Section 3.7 for more information on using redirected I/O.
Reading into subranges is implemented but no range checking is performed, even with range checking turned on.
<readcall> ::= <read or readln> {( {<filevar> ,} {<varlist>} )} <read or readln> ::= READ | READLN <filevar> ::= <variable> <varlist> ::= <variable> {,<variable>}
With variables of type string, only READLN may be used, Reading after EOF is undefined. This usually results in causing the program to stop executing in unpredictable ways.
<writecall> ::=<write or writeln>{({<filevar>,}{exprlist})} <write or writeln> ::= WRITE | WRITELN <exprlist> ::= <wexpr> {,<wexpr>} <wexpr> ::= <expression> {:<width expr> {:<dec expr>}} <width expr> ::= <expression> <dec expr> ::= <expression>
You may not use functions which perform input or output as a parameter to a WRITE or WRITELN statement. These include access routines such as GNB. The file pointers become modified by the reading routines causing the output to be done to the input file.
The Pascal/MT+ system does not support writing a single line feed character CON: due to the manner in which CP/M handles end-of- line on console and disk files. If you desire to write a line feed use the TRM: device.
Data written using WRITE or WRITELN may be formatted. The format, presented above, allows a field width (<width expr>) and a decimal place (<dec expr>) specification in the write-statement. The field width is the number of spaces this item is to occupy including decimal points, signs, and exponential notations. The decimal place number (used only with real numbers.) tells the output routine how many places to the right of the decimal place are to be used. All data items are right justified in the field.
The real numbers default output format is to write in exponential notation with five digits to the right of the decimal place and 12 spaces in the field width. If the number cannot be expressed within the field width specified the output is always in exponential notation.
See Section 7.10.1.1
WORD input and output is not performed via the standard READ and WRITE procedures. Two new procedures are READHEX and WRITEHEX. These allow Hex I/O on variables of any one- or two-byte type such as integer, char, byte subrange, enumerated, or word. See the section in Chapter 3.4 on Pascal/MT+ extensions.
<program> ::= <program heading> <block> . | <module heading> <label declaration part> <constant definition part> <type definition part> <variable declaration part> <procfunc declaration part> MODEND . <program heading> ::= PROGRAM <identifier> (( <prog parms> )}; <module heading> ::= MODULE <identifier> ; <prog parms> ::= <identifier> {,<identifier>}
Identical to the standard with the addition of modules. See Chapter 3.