|
|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 337152 (0x52500)
Types: TextFile
Names: »mpasc0«
└─⟦00964e8f7⟧ Bits:30007478 RC8000 Dump tape fra HCØ.
└─⟦b2ec5d50f⟧
└─⟦this⟧ »mpasc0«
(*$M20 COMPILE 68000 *)
(*$L+ OPTIONS HERE *) (* %M% %I% %H% ID KEYWORDS TO SCCS *)
(* +++++++++++++++++++++++++++++++++++++++++++++++++++++++*
* *
* 10/7/73 SYNTAX ANALYSIS INCLUDING ERROR *
* HANDLING; CHECKS BASED ON DECLARA- *
* TIONS; ADDRESS AND CODE GENERATION *
* FOR A HYPOTHETICAL STACK COMPUTER *
* URS AMMANN ETH ZURICH *
* *
* 05/20/74 *
* THE COMPILER IS NOW WRITTEN IN A SUBSET OF *
* STANDARD PASCAL - AS DEFINED IN THE NEW *
* MANUAL BY K. JENSEN AND N. WIRTH - AND IT *
* PROCESSES EXACTLY THIS SUBSET. *
* KESAV NORI ETH ZURICH *
* *
* THE COMPILER IS NOW CHANGED TO: *
* *
* -PRODUCE THE INTERMEDIATE CODE IN AN *
* ASSEMBLER READABLE FORM (NAMELY THE *
* 370, ASSEMBLER_H), 15-NOV-75. *
* *
* -PRESERVE PROCEDURE NAMES AND THEIR *
* STATIC LEVELS AT THE OBJECT LEVEL, THUS *
* ALLOWING A SET OF 'DISPLAY' REGISTERS TO *
* BE USED IN ACCESSING NON_LOCAL, NON_GLOBAL *
* VARIABLES (INSTEAD OF GOING THROUGH A *
* CHAIN OF POINTERS), 10-DEC-75. *
* *
* -INCLUDE THE TYPE OF THE OPERANDS IN THE *
* P_INSTRUCTIONS AS FOLLOWS: *
* *
* A : ADDRESS (POINTER) OPERAND *
* B : BOOLEAN " *
* C : CHARACTER " *
* I : INTEGER " *
* R : REAL " *
* S : SET " *
* *
* THE P_INSTRUCTION NOW LOOKS LIKE: *
* (LAB) OPCODE (TYPE),(OPERANDS) *
* A NEW PROCEDURE 'HALT(RC: INTEGER)' IS *
* ADDED TO THE SET OF STANDARD PROCEDURES *
* TO FACILITATE TERMINATING A PROGRAM AT *
* ANY POINT AND RETURNING A 'RETURN CODE' *
* TO THE OPERATING SYSTEM, 26-JAN-76. *
* *
* -TREAT THE INPUT AS A TEXT FILE WITH *
* LINES (RECORDS) OF LINELGTH CHAR. EACH, *
* THIS ALLOWS A MORE EFFICIENT STRING *
* ORIENTED INPUT, 20-MAR-76. *
* *
* -ALLOCATE AND PROPERLY ALIGN VARIABLES ON *
* THE BASIS OF THEIR TYPES, I.E. *
* *
* TYPE SIZE ALIGNED ON *
* *
* B,C 1-BYTE 1-BYTE *
* A,I 4-BYTES 4-BYTE *
* S 8-BYTES 4-BYTE *
* R 8-BYTES 8-BYTE *
* *
* DYNAMIC STORAGE HOWEVER IS ALWAYS ALLOC- *
* CATED ON 8-BYTE BOUNDARIES TO AVOID RUN- *
* TIME CHECKING OVERHEAD, 25-APR-76. *
* *
* -'READ' OF 'STRING' VARIABLES (I.E. ARRAY *
* OF CHAR) IS NOW IMPLEMENTED AND IT IS TO *
* COMPLEMENT THE SIMILAR 'WRITE' FUNCTION. *
* ALSO THE STANDARD PROCEDURE: *
* TRAP(I: INTEGER; VAR V: (.ANY TYPE.) ); *
* IS ADDED TO THE SET OF STANDARD PROCEDURES *
* TO FACILITATE COMMUNICATION WITH THE OUT- *
* SIDE WORLD, 10-SEP-76. *
* *
* -RELEVENT INFORMATION ON/ABOUT PROCEDURES *
* ARE NOW SENT TO 'QRD' FILE. THIS INCLUDES *
* SUCH INFORMATION AS THE SIZE OF THE PROCE- *
* DURE AS WELL AS ITS DATA AREA, LIST OF THE *
* PROCEDURES CALLED AND THE # OF CALLS, THE *
* LEVEL OF THE HIGHEST_LEVEL PROCEDURE CALLED *
* ETC. THIS INFORMATION IS MAINLY INTENDED *
* FOR INTER_PROCEDURAL ANALYSIS, BUT IT IS *
* ALSO USEFUL FOR MORE EFFICIENT PROCEDURE *
* ENTRY/EXIT CODE, 22-MAR-77. *
* *
* -THE COMPILER IS NOW SET UP TO GENERATE *
* P_CODE SUITABLE FOR A MICRO_PROCESSOR *
* IMPLEMENTATION. THE LENGTH (IN # OF *
* BYTES) OF BASIC DATA TYPES AS WELL AS *
* THE FORMAT OF THE OUTPUT IS (SLIGHTLY) *
* DIFFERENT FROM THAT OF THE 370 VERSION, *
* 11-FEB-78. *
* *
* *
* THE ABOVE CHANGES (INCLUDING ADDITIONS AND/OR *
* DELETIONS) HAVE BEEN TAGGED BY A '#' TAG AT *
* THE BEGINNING OR THE END OF AFFECTED LINES. *
* S. HAZEGHI SLAC *
* *
* *
* NEW CHANGES MADE 12/78 BY EPS (MARKED BY 'EPS') *
* TO PERMIT COMPILATION BY THE BERKELEY UNIX *
* COMPILER. *
* -FIX LOOSE TYPE MATCHES (ARG TO GENLABEL) *
* (TYPE OF CSTPART) *
* -CHANGE READ(LINEBUF) TO FOR LOOP WHICH *
* READS CHAR BY CHAR *
* -FILL IN ALL UNUSED VARIANTS OF RECORD *
* CASES *
* -COMMENT ALL UNUSED VARIABLES *
* -COMMENT ALL # COMMENTS PUT IN BY HAZEGHI *
* *
* SKIP STRITTER *
* MOTOROLA *
* *
* GOTO'S ELIMINATED IN INSYMBOL, NEW1, SEARCHID, *
* SEARCHSECTION, AND CASESTATEMENT FOR COMPILATION *
* BY NBS COMPILER *
* 12/28/78 EPS MOTOROLA *
* *
* 01/04/79 CHANGES IN INSYMBOL (COLLECTING *
* INTEGERS) FOR NON-DECIMAL RADIX INTEGER CONSTANTS *
* (OF THE FORM RR#NN...N WHERE RR IS BASE 10 AND *
* 1 <= RR <= 16 AND N < RR ) EPS *
* *
* 01/05/79 CHANGE INSYMBOL AND ADD ARRAY UPPER FOR *
* TRANSLATION OF ALL INPUT IDENTIFIERS AND *
* RESERVED WORDS TO UPPER CASE - UPPER CASE *
* AND LOWER CASE ARE INDISTINGUISHABLE TO THE *
* COMPILER EXCEPT IN STRINGS EPS *
* *
* 01/23/79 UPDATE INSYMBOL TO ACCEPT MOTOROLA *
* OPTIONS EPS *
* *
* 01/23/79 CREATE WARNING FACILITY SIMILAR TO *
* EXISTING ERROR FACILITY. NEW PROC WARNING; *
▶1a◀▶1a◀ NEW C▶1a◀LOBALS WARNINGS:BOOLEAN AND WARNCOUNT: ▶1a◀▶1a◀
* INTEGER EPS *
* *
* 01/23/79 CHANGES TO SUPPORT ALPHANUMERIC *
* LABELS. CHANGES MADE IN 'LABELDECL', *
* 'GOTOST', AND 'STATEMENT'. RECORD 'LABL' *
* CHANGED TO INCLUDE A VARIANT FIELD OF INTEGER *
* OR ALPHA VALUE. LABELS ARE KEPT IN A STRING *
* OF 'LABL'S; ALPHA LABELS ARE ALSO ENTERED *
* INTO THE SYMBOL TABLE TO AVOID CONFLICTING *
* DEFINITIONS WITH VARIABLES. 'GOTOST' AND 'ST' *
* SCAN THE STRING OF DECLARED LABELS TO FIND *
* THE LABEL THEY ARE PARSING. EPS *
* *
* 01/25/79 CHANGE TO SUPPORT UNORDERED DECLARATION *
* STATEMENTS. CHANGE 'ERROR(18)' TO 'WARNING(502)' *
* IN 'BLOCK' AND MOVE CHECK FOR UNRESOLVED FORWARD *
* TYPE DECL'S FROM INSIDE 'TYPEDECLARATION' *
* AND 'VARDECLARATION' TO 'BLOCK' EPS *
* *
* 01/30/79 ALL GEN ROUTINES REPLACED BY MOTOROLA *
* VERSIONS. ALL CALLS TO GEN ROUTINES REPLACED *
* BY CALLS TO NEW ROUTINE. THE COMPILER NOW *
* COMPILES TO PM, THE MOTOROLA P LANGUAGE EPS *
* *
* 02/02/79 ADDED 'OTHERWISE' CLAUSE TO 'CASE' *
* STATEMENT. NEW SYMBOL 'OTHERWISE' AND CORRE- *
* SPONDING ENTRIES IN RW AND FRW. 'OTHERWISE' *
* IS OPTIONAL; IT FOLLOWS ALL ALTERNATIVES IN *
* THE CASE BODY; THE SYMBOL ITSELF IS NOT FOLLOWED *
* BY A SEMICOLON. EVEN WITHOUT THE OTHERWISE *
* CLAUSE THE CASE STATEMENT IS SAFE - IT MAY BE *
* EQUIV TO A NULL STATEMENT FOR SOME VALUES OF THE *
* CASE INDEX, BUT IT NEVER EXEC'S BAD CODE *
* EPS *
* *
* 02/02/79 ADDED 'EXIT' STATEMENT. NEW PROCEDURES *
* 'LOOPENTRY', 'LOOPEXIT', AND 'EXITSTATEMENT' *
* AND VARIABLES 'LOOPLISTPTR' AND TYPES 'LOOPPTR' *
* AND LOOPLABL. COMMENTS IN THE CODE. EPS *
* *
* 02/21/79 CHANGED LINELGTH TO 133 TO ALLOW LONGER *
* INPUT LINES. ADDED WARNING(503) IN INSYMBOL WHEN *
* SCANNING A LEFTHAND-CURLY-BRACKET COMMENT IF *
* ENCOUNTER ANOTHER LEFTHAND CURLY BRACKET, *
* TO HELP DETECT BADLY FORMED, E.G. NESTED COMMENTS *
* EPS *
* *
* 02/23/79 ADDED 'ORIGIN' FEATURE. CHANGES IN *
* 'VARDECLARATION', 'SELECTOR', AND ADDITION OF *
* NEW SYMBOL TYPE 'ORIGINSY' AND NEW RESERVED WORD *
* 'ORIGIN' EPS *
* *
* 02/26/79 CHANGE FORM OF CONSTANT TO HAVE PTR TO *
* 'STRCONST' INSTEAD OF CONTAINING THE LITERAL *
* STRING IN THE RECORD. SAVES SPACE AND ALLOWS *
* MAX STRING LITERAL SIZE TO BE BIGGER (NOW 64) *
* EPS *
* FIXIBM SHELL FILE FOR TRANSPORTATION TO IBM/370 *
* EPS *
* *
* 03/30/79 ADDED FACILITY FOR COUNTING EXECUTION *
* UNITS FOR PROFILING BY A DEBUG PROGRAM. UNITS *
* CALLED 'EXECUTION ENTITIES' ARE COUNTED BY *
* 'LSC N' OR 'ISC' P-CODE STATEMENTS. THESE ENTITIES*
* ARE PRIMITIVE STATEMENTS (CALL,ASSIGN,GOTO,EXIT) *
* OR LOOP HEADER COMPUTATIONS (CASE,FOR) OR THE *
* BOOLEAN EXPR COMPUTATION IN (WHILE,IF,REPEAT) *
* CHANGES: IN 'STATEMENT' TO CALL GENKOUNT *
* IN ENDOFLINE TO DELAY PRINTING LINE *
* TO PRINT 'ENTITY' # FOR LINE *
* IN MAIN TO REFLECT CHANGES IN ENDOFLINE *
* ADDITION: OF VARIABLES KOUNT,KOUNTERS,HOLDKOUNT, *
* AND FIRSTKOUNT *
* OF PROC GENKOUNT EPS *
* *
* 04/16/79 CHANGE IN THE WAY VARIABLE OFFSETS ARE *
* GENERATED: PARAMETERS ARE POSITIVE OFFSETS *
* (RELATIVE TO THE "FRAME POINTER") AND LOCAL *
* VARIABLES ARE MINUS OFFSETS. EPS *
* *
* 04/17/79 HANDLING OF STRUCTURED NON-VAR PARAMETERS*
* CHANGED: THEY ARE NOW LOADED DIRECTLY ONTO *
* THE STACK BY THE CALLER (1 INSTRUCTION IN *
* MOTOROLA P-CODE) RATHER THE OLD WAY OF CALLER *
* LOADING PARAMETER ADDRESS ON STACK AND CALLEE *
* COPYING THE STRUCTURED VALUE TO LOCAL STORAGE *
* EPS *
* *
* 04/17/79 STRUCTURED FUNCTION VALUES ALLOWED. *
* SPACE IS ALLOCATED ON THE STACK BEFORE PARAMS *
* ARE PUSHED (BY AST P-INSTRUCTION) FOR ARBITRARY *
* SIZED FUNCTION VALUE EPS *
* *
* 05/02/79 DISPOSE ADDED, 'NEW1' NOW CALLED *
* 'NEWDISPOSE' EPS *
* *
* 05/03/79 HANDLING OF FILES COMPLETELY RESTRUCTURED*
* FILES IN HEADER ARE CHAINED ON 'FEXTFILEP'. *
* FILES IN HEADER MUST BE DECLARED IN OUTERMOST *
* LEVEL. INPUT AND OUTPUT MUST NOT BE DECL'D BUT *
* MUST APPEAR IN HEADER IF THEY ARE USED. *
* FILES ARE DECL'D IN LOCAL SCOPES AND OPENED *
* (WITH 'IFD') AND CLOSED (WITH 'CLO') IN THAT *
* SCOPE. UNDECL'D FILES FROM HEADER GENERATE *
* ERROR MESSAGE. FILE COMPONENTS CAN BE ANY TYPE *
* NOT RESTRICTED TO 'CHAR' EPS *
* *
* 05/04/79 EXTERNAL PROC/FUNCS IMPLEMENTED. *
* 'FORWARD' DEFINED PROCEDURES AND FUNCTIONS ARE *
* NOW FLAGGED IF NOT LATER DEFINED IN THE SAME *
* SCOPE. 'FORWARD' DEFINED PROC/FUNCS AT GLOBAL *
* LEVEL ARE ASSUMED TO BE EXTERNAL REFERENCES, AND *
* THEY GENERATE "$N DEF 'PROCFUNCNAME' " IN THE *
* OUTPUT FILE (AS WELL AS A WARNING IN THE LISTING) *
* EPS *
* 05/09/79 SUBPROGRAM CONCEPT (FOR SEPARATE *
* COMPILATION) IMPLEMENTED. SOURCE FILES BEGINNING *
* WITH 'SUBPROGRAM' ARE COMPILED. THEY MAY NOT HAVE *
* A MAIN PROGRAM BODY. THE LAST INNER PROC/FUNC *
* BODY ENDS WITH '.' INSTEAD OF ';' EPS *
* *
* 06/13/79 MACHINE M OPTION NOW SETS ALIGNMENT SIZE.*
* SMALL OBJECTS (BOOL,CHAR) NOW ALLOCATED THE *
* MINIMUM SPACE REQ'D SUBJECT TO ALIGNMENT RULES *
* OF THE TARGET MACHINE(BELOW). *
* *
* IN THE CASE OF A BYTE ALIGNED MACHINE (6809) ALL *
* OBJECTS TAKE THE MINIMUM NUMBER OF BYTES REGARD- *
* LESS OF COMPOSITION. IN THE CASE OF WORD ALIGNED *
* MACHINE (68000) ANY OBJECT THAT IS 2 BYTES OR *
* BIGGER IS WORD ALIGNED (AND SUB-OBJECTS, SUCH *
* AS RECORDS WITHIN RECORDS, FOLLOW THE SAME RULE.) *
* *
* OBJECTS IN STATIC STORAGE TAKE THE MINIMUM SPACE *
* SUBJECT TO THE ABOVE RULES. OBJECTS IN DYNAMIC *
* STORAGE (HEAP) SHOULD BE NEW'ED ON ALIGNMENT *
* BOUNDARIES SINCE THEIR INTERNAL ALIGNMENT IS NOT *
* KNOWN AT RUNTIME. PARAMETER OBJECTS FOR 68000 ARE *
* CURRENTLY ALL ALIGNED ON WORD BOUNDARIES REGARD- *
* LESS OF SIZE, BECAUSE OF THE STACK POINTER *
* ALIGNMENT RESTRICTION ON THE 68000. SLIGHTLY *
* MORE EFFICIENT STORAGE OF PARAMETERS IS POSSIBLE *
* (WITH CONSIDERABLY MORE WORK.) EPS *
* *
* 7/29/79 STRING FACILITY IMPLEMENTED. A NEW *
* TYPE CONSTRUCTOR "STRING" IS RECOGNIZED. DECL'S *
* TAKE THE FORM "VARIABLENAME: STRING(.INTEGER.);" *
* THE INTEGER INDICATES THE MAXIMUM SIZE IN CHARS *
* THAT THE STRING WILL TAKE. SIZE+1 BYTES ARE *
* ALLOCATED FOR STRING STORAGE; THE FIRST BYTE *
* BEING USED TO HOLD THE CURRENT STRING LENGTH AT *
* RUN-TIME. STRINGS MAY BE INDEXED TO OBTAIN *
* INDIVIDUAL CHARACTERS ("STRINGVAR(.N.)" IS THE NTH *
* CHAR OF STRINGVAR). STRINGS ARE ASSIGNABLE TO *
* PACKED ARRAY OF CHAR BUT NOT VICE VERSA. STRINGS *
* ARE COMPATIBLE WITH OTHER STRINGS REGARDLESS OF *
* SIZE. MANIFEST STRING CONSTANTS ARE STRINGS. *
* EPS *
* 07/25/79 BUILTIN FUNCTIONS AND PROCEDURES CAN *
* NOW BE REDEFINED BY THE USER PROGRAM EPS *
* *
* 07/27/79 LINES MARKED '%MOTO' ARE REMOVED BY *
* FIXMOTO SHELL FILE FOR TRANSPORTATION TO PHOENIX *
* EPS *
* *
* 08/15/79 READ AND WRITE OF NON-TEXT FILES EPS *
* *
* NEXT COMMENT *
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++ *)
PROGRAM PASCALCOMPILER(OUTPUT, SOURCE, PCODE, LISTING);
CONST
VERSION = ' 1.10';
M6809 = 1;
M68000 = 2;
MACHINE = M68000;
DISPLIMIT = 20; MAXLEVEL = 8;
MINADDR =-32000; MAXADDR = 32000 ;
MAXINTEGER = 32767;
INT2SIZE = 2; REALSIZE = 4;
INT1SIZE = 1; INT4SIZE = 4;
CHARSIZE = 1; BOOLSIZE = 1;
SETSIZE = 8;
LASTRESWD = 40; NEXTRESWD = 41 ;
STRGLNGTH = 64; ORDMAXCHAR =127 (*WAS 63 EPS*);
REALLNGTH = 11;
DIGMAX = 11 ; (*=REALLNGTH*)
IDLNGTH = 8 ; (*SIZE OF TYPE ALPHA*)
SETRANGE = 63 ;
LINELGTH = 133; (*CHANGED FROM 81 EPS*)
MAXLABEL = 4000; (* MAXIMUM NUMBER OF LABELS *)
PAGEDEFAULT = 76; (* DEFAULT TOTAL LENGTH OF A PAGE *)
ENDOFPAGE = 76; (* DEFAULT END OF PAGE *)
STARTPAGE = 77; (* START PAGE POS HERE (MDOS = 66) *)
WIDTHDEFAULT = 132; (* DEFAULT PAGE WIDTH TO 132 COLUMNS *)
LMARGIN = 21; (* WIDTH OF THE LEFT MARGIN IN LISTING FILE *)
ORDMAXBASECHAR = 255; (* ORD OF MAX CHAR IN BASE CHAR TYPE *)
(* 255 FOR EBCDIC, 127 FOR ASCII *)
SYSTEM = 0;
USER = 1;
TYPE (* DESCRIBING: *)
(* +++++++++++ *)
(* BASIC SYMBOLS
*) (* +++++++++++++
*)
SYMBOL = (IDENT,INT1CONST,INT2CONST,INT4CONST,REALCONST,STRINGCONST,NOTS
Y, MULOP,ADDOP,RELOP,LPARENT,RPARENT,LBRACK,RBRACK,COMMA,SEMICOLO
N, PERIOD,ARROW,COLON,RANGE,BECOMES,LABELSY,CONSTSY,TYPESY,VARSY,
FUNCSY,PROGSY,PROCSY,SETSY,PACKEDSY,ARRAYSY,RECORDSY,FILESY,
FORWARDSY,BEGINSY,IFSY,CASESY,REPEATSY,WHILESY,FORSY,WITHSY,
GOTOSY,ENDSY,ELSESY,UNTILSY,OFSY,DOSY,TOSY,DOWNTOSY,
THENSY,OTHERSY,OTHERWZSY,EXITSY,ORIGINSY,STRINGSY,SUBPROGSY);
OPERATOR = (MUL,RDIV,ANDOP,IDIV,IMOD,PLUS,MINUS,OROP,LTOP,LEOP,GEOP,GTOP
, NEOP,EQOP,INOP,NOOP);
(* THE FOLLOWING IS AN ENUMERATED TYPE OF STANDARD NAMES, EXCLUDING *)
(* INPUT AND OUTPUT. THEY ARE ARRANGED IN THE FOLLOWING ORDER: *)
(* CONSTANTS FIRST, TYPES SECOND, FUNCTIONS THIRD, AND PROCEDURES *)
(* LAST. WITHIN EACH CLASS, THE INDIVIDUAL NAMES ARE ARRANGED IN *)
(* THE ORDER IN WHICH THEY WILL GO INTO THE TREE - TO HELP BALANCE *)
(* IT. *)
STDNAMES = (XMAXINT, XFALSE, XTRUE, XNIL,
XTEXT, XCHAR, XREAL, XINTEGER,
XBOOLEAN, XODD, XEOLN, XCONCAT,
XLENGTH, XDELETE, XPOS, XSQR,
XARCTAN, XCHR, XCOPY, XLN,
XPOSITION, XROUND, XSQRT, XABS,
XCLOCK, XCOS, XEOF, XEXP,
XINSERT, XORD, XPRED, XSIN,
XSUCC, XTRUNC, XREWRITE, XPUT,
XHALT, XUNPACK, XDISPOSE, XNEW,
XPACK, XREAD, XRELEASE, XWRITE,
XGET, XMARK, XPAGE, XREADLN,
XRESET, XWRITELN );
SETOFSYS = SET OF SYMBOL;
(*POTENTIAL PORTABILITY PROBLEM: SET OF 54 ELEMENTS*)
CHTYP = (ATOZ, NUMBER, STRQUOTE, COLONCHAR, PERIODCHAR,
LPOINTY, RPOINTY, LPARN, MISCCHAR,
CMNTBRACK,BLANKCHAR, ILLEGALCHAR);
LNGINT = PACKED ARRAY (.1..4.) OF INTEGER;
LNGRELATION = (LNGLESS,LNGEQUAL,LNGGREATER);
(* CONSTANTS *)
(* +++++++++ *)
CSTCLASS = (LINT,REEL,PSET,STRG);
SETCONST = SET OF 0..SETRANGE;
(*POTENTIAL PORTABILITY PROBLEM: SET OF 64 ELEMENTS*)
STRCONST = PACKED ARRAY (.1..STRGLNGTH.) OF CHAR;
CSP = @ CONSTANT;
CONSTANT = RECORD CASE CSTCLASS OF
LINT: (LINTVAL: LNGINT);
REEL: (RVAL: PACKED ARRAY (.0..REALLNGTH.) OF CHAR);
PSET: (PVAL: SETCONST );
STRG: (SLNGTH: 0..STRGLNGTH;
SVAL: @STRCONST)
END;
VALU = RECORD CASE (*INTVAL:*) BOOLEAN OF (*INTVAL NEVER SET NOR TESTED*
) TRUE: (IVAL: INTEGER);
FALSE: (VALP: CSP)
END;
(* DATA STRUCTURES *)
(* +++++++++++++++ *)
MNRANGE = 0..118;
ADDRRANGE = MINADDR..MAXADDR;
LEVRANGE = 0..MAXLEVEL;
LABELRNG = 0..MAXLABEL ;
STRUCTFORM = (SCALAR,SUBRANGE,POINTER,POWER,STRINGS,ARRAYS,RECORDS,
FILES,TAGFLD,VARIANT); (*ORDER OF ELEMENTS IS IMPORTANT*)
CTP = @IDENTIFIER;
STP = @STRUCTURE;
STRUCTURE = PACKED RECORD
SIZE: ADDRRANGE;
CASE FORM: STRUCTFORM OF
SCALAR: (FCONST: CTP);
SUBRANGE: (RANGETYPE: STP; MIN,MAX: VALU);
POINTER: (ELTYPE: STP);
POWER: (ELSET: STP);
(*STRINGS: ();*)
ARRAYS: (AELTYPE,INXTYPE: STP);
RECORDS: (FSTFLD: CTP; RECVAR: STP);
FILES: (FILTYPE: STP);
TAGFLD: (TAGFIELDP: CTP; FSTVAR: STP);
VARIANT: (NXTVAR,SUBVAR: STP; VARVAL: VALU)
END;
(* NAMES *)
(* +++++ *)
IDCLASS = (TYPES,LABELS,KONST,VARS,FIELD,PROC,FUNC);
SETOFIDS = SET OF IDCLASS;
IDKIND = (ACTUAL,FORMAL,ORIGINED);
ALPHA = PACKED ARRAY(.1..IDLNGTH.) OF CHAR;(*SIZE(ALPHA) MUST=IDLNGTH*)
DECLKIND = (BUILTIN,DECLARED);
IDENTIFIER = PACKED RECORD
NAME: ALPHA; LLINK, RLINK: CTP;
IDTYPE: STP; NEXT: CTP;
CASE KLASS: IDCLASS OF
(* TYPES,LABELS: ( ); NOT ALLOWED BY AMSTERDAM EPS *)
(* REQ'D BY BERKELEY EPS *)
KONST: (VALUES: VALU);
VARS: (VKIND: IDKIND; EXTRNL: BOOLEAN;
VLEV: LEVRANGE; VADDR: LNGINT);
FIELD: (FLDADDR: ADDRRANGE);
PROC,
FUNC: (CASE PFDECKIND: DECLKIND OF
BUILTIN: (KEY: STDNAMES);
DECLARED: (PFLEV: LEVRANGE; PFNAME: LABELRNG;
PFADDR: ADDRRANGE;
CASE PFKIND: IDKIND OF
(*ORIGINED, FORMAL: ( ); *)
(*ABOVE NOT ALLOWED BY AMSTERDAM EPS *)
(* BUT REQ'D BY BERKELEY EPS *)
ACTUAL: (FORWDECL(*, EXTERN*):
BOOLEAN)))
END;
DISPRANGE = 0..DISPLIMIT;
WHERE = (BLCK,CREC,VREC,REC);
(* EXPRESSIONS *)
(* +++++++++++ *)
ATTRKIND = (CST,VARBL,FILEPTR,EXPR);
VACCESS = (DRCT,INDRCT);
ATTR = RECORD TYPTR : STP;
CASE KIND: ATTRKIND OF
CST: (CVAL: VALU);
(* EXPR: ( ); NOT ALLOWED BY AMSTERDAM EPS *)
(* REQ'D BY BERKELEY EPS *)
VARBL,FILEPTR: (CASE ACCESS: VACCESS OF
DRCT: (VLEVEL: LEVRANGE; DPLMT: ADDRRANGE);
INDRCT: (IDPLMT: ADDRRANGE) )
END;
TESTP = @ TESTPOINTER;
TESTPOINTER = PACKED RECORD
ELT1,ELT2 : STP;
LASTTESTP : TESTP
END;
(* LABELS *)
(* ++++++ *)
LBP = @ LABL;
LABL = RECORD NEXTLAB: LBP;
DEFINED: BOOLEAN;
LABNO: LABELRNG;
CASE ALF:BOOLEAN OF
FALSE:(LABVAL: INTEGER);
TRUE: (LABNAME: ALPHA )
END;
LOOPPTR = @LOOPLABL;
LOOPLABL = RECORD LABNO: LABELRNG; (*ENTRY ON STACK OF LOOPEXIT LABELS*)
ASSOCLAB: LBP;
NEXTLOOP: LOOPPTR;
USED: BOOLEAN
END;
EXTFILEP = @FILEREC;
FILEREC = RECORD FILENAME:ALPHA;
NEXTFILE:EXTFILEP;
POS: INTEGER;
DEF:BOOLEAN
END;
(* -------------------------------------------------------------------------
*)
VAR
SOURCE,
PCODE,
LISTING: FILE OF CHAR;
(*NOT ALLOWED BY AMSTERDAM; REQ'D BY MOTO AND TSO*)
(* RETURNED BY SOURCE PROGRAM SCANNER
INSYMBOL:
+++++++++ *)
SY: SYMBOL; (* LAST SYMBOL *)
OP: OPERATOR; (* CLASSIFICATION OF LAST SYMBOL *)
CH: CHAR; (* LAST CHARACTER READ *)
EOL: BOOLEAN; (* END OF LINE FLAG *)
DOUBLECHAR: BOOLEAN; (*DOUBLE CHAR FOUND IN NUMBER FLAG*)
DOUBLESYM: SYMBOL; (*SYMBOL TYPE OF DOUBLE CHAR FOUND*)
(* COUNTERS: *)
(* +++++++++ *)
CHCNT: 0..LINELGTH; (* CHARACTER COUNTER *)
LINELEN:1..LINELGTH; (* LENGTH OF CURRENT LINE *)
LOCN,IC,OLDIC: ADDRRANGE ; (* DATA LOCATION AND INSTRUCTION COUNTER
*) LINECOUNT,I: INTEGER;
INTLABEL, (* LABEL NUMBER *)
PROCLAB: LABELRNG; (* PROCEDURE LABEL NUMBER *)
ERRORCOUNT:INTEGER ; (* TOTAL ERROR COUNT *)
WARNCOUNT:INTEGER ;
ERRORS, WARNINGS: BOOLEAN;
GATTR: ATTR; (* DESCRIBES THE EXPR CURRENTLY COMPILED
*) VAL: VALU; (* VALUE OF LAST CONSTANT *)
LNGTH: INTEGER; (* LENGTH OF LAST STRING CONSTANT *)
ID, BLANKID, PROGNAME: ALPHA; (* LAST IDENTIFIER (POSSIBLY TRUNCATED) *
)
(* SWITCHES: *)
(* +++++++++ *)
LONGONLY, (*LONG INTEGER ONLY ALLOWED IN INSYMBOL*)
SUBPROG,
DP, (* DECLARATION PART *)
PRTERR, (* TO ALLOW FORWARD REF IN PTR VARIABLES
*) ASSIGN, (* DECLARATION BY SUPPRESSING ERROR MSG *
) LIST, (* SOURCE PROGRAM LISTING OPTION *)
PLIST, (* INCLUDE SOURCE IN PCODE OPTION *)
PRCODE, (* PRODUCE PCODE OPTION *)
DEBUG, (* PRODUCE RANGE CHECKING *)
KOUNTERS, (* PRODUCE LINE COUNTING CODE OPTION *)
PKOUNTERS, (* PRODUCE PROCEDURE COUNTING CODE OPT *)
STANDARD: BOOLEAN; (* PRINT WARNINGS IF NON STANDARD OPTION
*)
JUMPENTRIES: INTEGER; (*# OF JUMP TABLE ENTRIES*)
JUMPBASE, (*JUMP TABLE BASE ADDRESS*)
HEAPSTART, (*HEAP START ADDRESS*)
STACKSTART: LNGINT; (*STACK START (TOP) ADDRESS*)
ADDRSIZE, ALIGNMENT:INTEGER;
(* SET BY THE OPTION 'M' TO 2 OR 4 DEPENDING ON
ADDRESS SIZE (BYTES) OF TARGET *)
PAGENUM, (* LISTING FORMAT VARIABLES *)
PAGEPOS,
LINEWIDTH,
PAGEEND,
PAGELEN,
LASTERR: INTEGER;
BLEV, MLEV: CHAR; (* BLOCK NESTING ACCOUNTING VARS *)
SBLOCK,
EBLOCK: BOOLEAN;
KOUNT,
MINKOUNT: INTEGER; (* STATEMENT COUNTING VARIBLES *)
PRINTKOUNT,
LABELEDKOUNT: BOOLEAN;
ARITHMETICSIZE: CHAR; (* SIZE OF INTEGER ARITHMETIC *)
(* POINTERS: *)
(* +++++++++ *)
INT1PTR,INT2PTR,INT4PTR,
REALPTR,CHARPTR,
BOOLPTR,NILPTR,TEXTPTR: STP; (* POINTERS TO ENTRIES OF STANDARD IDS *)
SINGLECHARSTRING: STP; (* POINTER TO RESULT OF CONVERTING CHAR TO STR *)
UTYPPTR,UCSTPTR,UVARPTR,
UFLDPTR,UPRCPTR,UFCTPTR, (* POINTERS TO ENTRIES FOR UNDECLARED IDS*)
ULABPTR,FWPTR:CTP; (* HEAD OF CHAIN OF FORW DECL TYPE IDS *)
STDINPUT,STDOUTPUT: CTP; (* POINTERS TO DEFAULT FILES FOR READ,WRITE
*)
GLOBFILELIST: CTP;
FEXTFILEP: EXTFILEP; (* HEAD OF CHAIN OF EXTERNAL FILES *)
GLOBTESTP: TESTP; (* LAST TESTPOINTER *)
CNSTVALPTR : CSP ; (* POINTERS TO CURRENT STRING/REAL CNST*)
CNSTSTRPTR : @STRCONST;
(* BOOKKEEPING OF DECLARATION LEVELS: *)
(* ++++++++++++++++++++++++++++++++++ *)
LEVEL: LEVRANGE; (* CURRENT STATIC LEVEL *)
STKSIZES: ARRAY (.LEVRANGE.) (*MAX STACK SIZE OF EACH STATIC LEVEL*)
OF INTEGER;
DISX, (* LEVEL OF LAST ID SEARCHED BY SEARCHID
*) TOP: DISPRANGE; (* TOP OF DISPLAY *)
DISPLAY: (* WHERE: MEANS: *)
ARRAY (.DISPRANGE.) OF
PACKED RECORD (* =BLCK: ID IS VARIABLE ID *)
FNAME: CTP; FLABEL: LBP; (* =CREC: ID IS FIELD ID IN RECORD WITH*)
CASE OCCUR: WHERE OF (* CONSTANT ADDRESS *)
CREC: (CLEV: LEVRANGE; (* =VREC: ID IS FIELD ID IN RECORD WITH*)
CDSPL: ADDRRANGE);(* VARIABLE ADDRESS *)
VREC: (VDSPL: ADDRRANGE)
END; (* --> PROCEDURE WITHSTATEMENT *)
(* ERROR MESSAGES: *)
(* +++++++++++++++ *)
ERRINX: 0..10; (* NR OF ERRORS IN CURRENT SOURCE LINE *)
ERRLIST:
ARRAY (.1..10.) OF
PACKED RECORD POS: 0..LINELGTH;
NMR: 1..999
END;
(* STRUCTURED CONSTANTS: *)
(* +++++++++++++++++++++ *)
LONGZERO, (*LONG ZERO VALUE*)
LINT1MIN,LINT1MAX,
LINT2MIN,LINT2MAX,
LINT4MIN,LINT4MAX,
LONGORDMAXCHAR: LNGINT; (*LONG VALUE OF ORDMAXCHR*)
LINEBUF: ARRAY(.0..LINELGTH.) OF CHAR ; (* CURRENT LINE BUFFER *)
CONSTBEGSYS,SIMPTYPEBEGSYS,TYPEBEGSYS,BLOCKBEGSYS,SELECTSYS,FACBEGSYS,
STATBEGSYS,TYPEDELS,LOOPBEGSYS: SETOFSYS;
RW: ARRAY (.0..LASTRESWD(* NR. OF RES. WORDS *).) OF ALPHA;
FRW: ARRAY (.0..14.) OF 1..NEXTRESWD(* NR. OF RES. WORDS + 1 *);
RSY: ARRAY (.0..LASTRESWD(* NR. OF RES. WORDS *).) OF SYMBOL;
SSY: ARRAY (.CHAR.) OF SYMBOL;
ROP: ARRAY (.0..LASTRESWD(* NR. OF RES. WORDS *).) OF OPERATOR;
SOP: ARRAY (.CHAR.) OF OPERATOR;
MN: ARRAY (.MNRANGE.) OF PACKED ARRAY (.1..4.) OF CHAR;
UPPER: ARRAY(.CHAR.) OF CHAR; (* INSYMBOL UPPERCASE TABLE *)
ASCII: ARRAY(.CHAR.) OF INTEGER;
CHTAB: ARRAY(.CHAR.) OF CHTYP; (* INSYMBOL DIRECTOR TABLE *)
HEADER: PACKED ARRAY (. 1..29 .) OF CHAR; (* HEADER MESSAGE & DATE *)
EOFMESSAGE: PACKED ARRAY (. 1..35 .) OF CHAR; (* EOF MESSAGE *)
STARS: PACKED ARRAY (. 1..5 .) OF CHAR; (* 4 STARS *)
ERRMES: PACKED ARRAY (. 1..9 .) OF CHAR; (* **ERROR-- MESSAGE *)
(*----------------------------------------------------------------------
FUNCTION USUCC
-----------------------------------------------------------------------*)
FUNCTION USUCC(C: CHAR): CHAR; (* UNIVERSAL SUCCSESOR FUNCTION *)
BEGIN
IF (C <> 'I') AND (C <> 'R') THEN
USUCC := SUCC(C)
ELSE IF C = 'I' THEN
USUCC := 'J'
ELSE IF C = 'R' THEN
USUCC := 'S'
END;
(*---------------------------------------------------------
FUNCTION UPRED
----------------------------------------------------------*)
FUNCTION UPRED(C: CHAR): CHAR; (* UNIVERSAL PREDISESOR FUNCTION *)
BEGIN
IF (C <> 'J') AND (C <> 'S') AND (C <> 'A') THEN
UPRED := PRED(C)
ELSE IF C = 'J' THEN
UPRED := 'I'
ELSE IF C = 'S' THEN
UPRED := 'R'
ELSE
UPRED := C
END;
(*-------------------------------------------------------------------
PROCEDURE NEWPAGE
--------------------------------------------------------------------*)
PROCEDURE NEWPAGE;
VAR
I: INTEGER;
BEGIN
PAGENUM := PAGENUM + 1;
FOR I := PAGEPOS TO PAGELEN DO
WRITELN(LISTING,' ');
WRITE(LISTING,'LINE LOC LEV BE ':20,HEADER,VERSION);
WRITELN(LISTING,'PAGE ':(LINEWIDTH - 64),PAGENUM:0);
WRITELN(LISTING,' ');
PAGEPOS := 3
END;
(*-----------------------------------------------------------------
PROCEDURE WRITELINE
------------------------------------------------------------------*)
PROCEDURE WRITELINE;
VAR
I,LINESIZE: INTEGER;
BEGIN (* WRITELINE *)
IF PAGEPOS > PAGEEND THEN
NEWPAGE
ELSE IF ERRORS OR WARNINGS THEN
IF PAGEPOS > PAGEEND - 2 THEN
NEWPAGE;
WRITE(LISTING,LINECOUNT:6);
IF DP THEN
WRITE(LISTING,'(',LOCN:6,')')
ELSE IF PRINTKOUNT THEN
WRITE(LISTING, MINKOUNT:7,' ')
ELSE
WRITE(LISTING, ' ':8);
WRITE(LISTING,LEVEL:2,')');
IF SBLOCK THEN
WRITE(LISTING, MLEV)
ELSE
WRITE(LISTING, '-');
IF EBLOCK THEN
WRITE(LISTING, BLEV,' ')
ELSE
WRITE(LISTING, '- ');
IF LINELEN <= LINEWIDTH - LMARGIN THEN
LINESIZE := LINELEN
ELSE
LINESIZE := LINEWIDTH - LMARGIN;
FOR I := 1 TO LINESIZE DO
WRITE(LISTING, LINEBUF(. I .));
WRITELN(LISTING,' ');
PAGEPOS := PAGEPOS + 1
END; (* WRITELINE *)
(*------------------------------------------------------------------
PROCEDURE PRINTERROR
-------------------------------------------------------------------*)
PROCEDURE PRINTERROR;
VAR
SECONDLINE: BOOLEAN;
F,K,
LASTPOS,
FREEPOS,
CURRPOS,
CURRNMR: INTEGER;
BEGIN (* PRINTERROR *)
IF NOT LIST THEN WRITELINE;
IF ERRORS THEN
WRITE(LISTING, ERRMES:11)
ELSE
WRITE(LISTING, '*WARNING-':11);
WRITE(LISTING, LASTERR:6,'** ':3);
LASTPOS := 0;
FREEPOS := 1;
SECONDLINE := FALSE;
FOR K := 1 TO ERRINX DO
BEGIN
WITH ERRLIST(. K .) DO
BEGIN
CURRPOS := POS;
CURRNMR := NMR
END; (* WITH *)
IF CURRNMR < 10 THEN
F := 1
ELSE IF CURRNMR < 100 THEN
F := 2
ELSE
F := 3;
IF SECONDLINE THEN
BEGIN
WRITE(LISTING,',',CURRNMR:F);
FREEPOS := FREEPOS + F + 1
END
ELSE IF ((CURRPOS = LASTPOS)
AND (FREEPOS + F + 1 > LINEWIDTH - LMARGIN))
OR (CURRPOS + F + 1 > LINEWIDTH - LMARGIN) THEN
BEGIN
IF K > 1 THEN
BEGIN
IF (CURRPOS = LASTPOS) THEN
WRITELN(LISTING,',')
ELSE
WRITELN(LISTING,' ');
PAGEPOS := PAGEPOS + 1;
WRITE(LISTING,'****CONTINUED**** ':20);
FREEPOS := 1
END;
WRITE(LISTING,CURRNMR:F);
FREEPOS := FREEPOS + F;
SECONDLINE := TRUE
END
ELSE
BEGIN
IF CURRPOS = LASTPOS THEN
WRITE(LISTING,',')
ELSE IF CURRPOS <= FREEPOS THEN
WRITE(LISTING,'@')
ELSE
BEGIN
WRITE(LISTING,'@':(CURRPOS - FREEPOS + 1));
FREEPOS := CURRPOS
END;
WRITE(LISTING, CURRNMR:F);
FREEPOS := FREEPOS + F + 1
END;
LASTPOS := CURRPOS;
END; (* FOR K ... *)
IF SECONDLINE THEN
WRITELN(LISTING,'>')
ELSE
WRITELN(LISTING,' ');
PAGEPOS := PAGEPOS + 1;
LASTERR := LINECOUNT;
ERRINX := 0;
PRCODE := NOT ERRORS AND PRCODE;
PLIST := NOT ERRORS AND PLIST;
ERRORS := FALSE;
WARNINGS := FALSE
END; (* PRINTERROR *)
(* -------------------------------------------------------------------------
PROCEDURE ERROR
------------------------------------------------------------------------- *
)
PROCEDURE ERROR(FERRNR: INTEGER);
BEGIN
ERRORS := TRUE;
IF ERRINX >= 9 THEN
BEGIN ERRLIST(.10.).NMR := 255; ERRINX := 10 END
ELSE
BEGIN ERRINX := ERRINX + 1;
ERRLIST(.ERRINX.).NMR := FERRNR
END;
ERRLIST(.ERRINX.).POS := CHCNT ;
ERRORCOUNT := ERRORCOUNT+1 ;
END (* ERROR *) ;
(* -------------------------------------------------------------------------
PROCEDURE WARNING
------------------------------------------------------------------------- *
)
PROCEDURE WARNING(FERRNR: INTEGER);
BEGIN
WARNINGS := TRUE;
IF ERRINX >= 9 THEN
BEGIN ERRLIST(.10.).NMR := 255; ERRINX := 10 END
ELSE
BEGIN ERRINX := ERRINX + 1;
ERRLIST(.ERRINX.).NMR := FERRNR
END;
ERRLIST(.ERRINX.).POS := CHCNT ;
WARNCOUNT := WARNCOUNT+1 ;
END (* ERROR *) ;
(* -------------------------------------------------------------------------
PROCEDURE READLINE
------------------------------------------------------------------------- *
)
PROCEDURE READLINE;
VAR
I: INTEGER;
BEGIN (* READLINE *)
IF EOF(SOURCE) THEN
BEGIN
WRITELN(LISTING,EOFMESSAGE:45);
WRITELN(OUTPUT, EOFMESSAGE:36);
WRITELN(PCODE,'END':4);
(*PP*) HALT (* POSSIBLE PORTABILLITY PROBLEM *)
END
ELSE
BEGIN
LINELEN := 1;
WHILE NOT EOLN(SOURCE) AND (LINELEN < LINELGTH) DO
BEGIN
READ(SOURCE, LINEBUF(. LINELEN .));
LINELEN := LINELEN + 1
END;
READLN(SOURCE);
CHCNT := 0;
LINEBUF(. LINELEN .) := ' ';
MINKOUNT := KOUNT;
PRINTKOUNT := FALSE;
MLEV := BLEV;
SBLOCK := FALSE;
EBLOCK := FALSE;
LINECOUNT := LINECOUNT + 1;
IF PLIST THEN
BEGIN
WRITE(PCODE,'.',' ':10);
FOR I := 1 TO LINELEN DO WRITE(PCODE,LINEBUF(. I .));
WRITELN(PCODE,' ')
END
END (* ELSE *)
END; (* READLINE *)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE WRITELONG (FIL,LVAL) *)
(* *)
(* THIS PROCEDURE WRITES THE VALUE OF THE LONG INTEGER IN *)
(* 'LVAL' TO THE TEXT FILE 'FIL'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE WRITELONG (VAR FIL: TEXT; LVAL: LNGINT);
VAR
I: INTEGER;
BEGIN (*WRITELONG*)
FOR I := 4 DOWNTO 1 DO
BEGIN
WRITE (FIL,LVAL(.I.):1);
IF I <> 1 THEN WRITE (FIL,', ')
END (*FOR*)
END; (*WRITELONG*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE OUTHEX (FIL,LVAL) *)
(* *)
(* THIS PROCEDURE OUTPUTS THE LONG INTEGER IN LVAL TO THE *)
(* FILE FIL IN HEX FORMAT. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE OUTHEX (VAR FIL: TEXT; LVAL: LNGINT);
VAR
I: INTEGER;
PROCEDURE OUTBYTE (BYTE: INTEGER);
PROCEDURE OUTNIBBLE (NIBBLE: INTEGER);
BEGIN (*OUTNIBBLE*)
IF NIBBLE < 10
THEN WRITE (FIL,CHR(ORD('0') + NIBBLE))
ELSE WRITE (FIL,CHR(ORD('A') + NIBBLE - 10))
END; (*OUTNIBBLE*)
BEGIN (*OUTBYTE*)
OUTNIBBLE (BYTE DIV 16);
OUTNIBBLE (BYTE MOD 16)
END; (*OUTNIBBLE*)
BEGIN (*OUTHEX*)
FOR I := 4 DOWNTO 1 DO
OUTBYTE (LVAL(.I.))
END; (*OUTHEX*)
(*$E------------------------------------------------------------------*)
(* *)
(* FUNCTION COMPLONGS (VAL1,VAL2): LNGRELATION *)
(* *)
(* THIS FUNCTION COMPARES THE SIGNED VALUE REPRESENTED BY *)
(* THE LONG INTEGER IN 'VAL1' TO THE SIGNED VALUE REPRESENTED *)
(* BY THE LONG INTEGER IN 'VAL2'. *)
(* *)
(*--------------------------------------------------------------------*)
FUNCTION COMPLONGS (VAL1,VAL2: LNGINT): LNGRELATION;
VAR
I: INTEGER;
BEGIN (*COMPLONGS*)
IF (VAL1(.4.) >= 128) AND (VAL2(.4.) < 128)
THEN COMPLONGS := LNGLESS
ELSE
IF (VAL1(.4.) < 128) AND (VAL2(.4.) >= 128)
THEN COMPLONGS := LNGGREATER
ELSE
BEGIN (*SIGNS ARE THE SAME - COMPARE THEM*)
I := 5;
REPEAT
I := I - 1
UNTIL (I = 1) OR (VAL1(.I.) <> VAL2(.I.));
IF VAL1(.I.) < VAL2(.I.)
THEN COMPLONGS := LNGLESS
ELSE
IF VAL1(.I.) = VAL2(.I.)
THEN COMPLONGS := LNGEQUAL
ELSE COMPLONGS := LNGGREATER
END (*ELSE*)
END; (*COMPLONGS*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE ADDLONG (LONGVALUE,ADDVALUE,OVERFLOW) *)
(* *)
(* THIS PROCEDURE ADDS THE INTEGER IN 'ADDVALUE' TO THE LONG *)
(* INTEGER IN 'LONGVALUE'. 'OVERFLOW' IS RETURNED TRUE IF *)
(* THE ADDITION RESULTED IN AN OVERFLOW. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE ADDLONG (VAR LONGVALUE: LNGINT; ADDVALUE: INTEGER;
VAR OVERFLOW: BOOLEAN);
VAR
I: 0..4;
C: INTEGER;
TEMP: INTEGER;
BEGIN (*ADDLONG*)
I := 0;
C := ADDVALUE;
REPEAT
I := I + 1;
TEMP := LONGVALUE(.I.) + C;
C := TEMP DIV 256;
IF C > 0 THEN TEMP := TEMP MOD 256;
LONGVALUE(.I.) := TEMP
UNTIL (I = 4) OR (C = 0);
OVERFLOW := C <> 0
END; (*ADDLONG*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE MULTLONG (LONGVALUE,RADIX,OVERFLOW) *)
(* *)
(* THIS PROCEDURE MULTIPLIES THE LONG INTEGER IN 'LONGVALUE' *)
(* BY THE INTEGER IN 'RADIX'. IF AN OVERFLOW OCCURS, *)
(* 'OVERFLOW' IS RETURNED TRUE. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE MULTLONG (VAR LONGVALUE: LNGINT; RADIX: INTEGER;
VAR OVERFLOW: BOOLEAN);
VAR
I: 1..4;
C: INTEGER;
TEMP: INTEGER;
BEGIN (*MULTLONG*)
C := 0;
FOR I := 1 TO 4 DO
BEGIN
TEMP := LONGVALUE(.I.) * RADIX + C;
C := TEMP DIV 256;
IF C > 0 THEN TEMP := TEMP MOD 256;
LONGVALUE(.I.) := TEMP
END; (*FOR*)
OVERFLOW := C <> 0
END; (*MULTLONG*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE ADD2LONGS (LVAL1,LVAL2,RVAL,OVERFLOW) *)
(* *)
(* THIS PROCEDURE ADDS THE TWO LONG INTEGERS IN 'LVAL1' AND *)
(* 'LVAL2' AND PUTS THE RESULT IN 'RVAL'. IF AN OVERFLOW *)
(* OCCURS, 'OVERFLOW' IS RETURNED TRUE. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE ADD2LONGS (LVAL1,LVAL2: LNGINT; VAR RVAL: LNGINT;
VAR OVERFLOW: BOOLEAN);
VAR
I,C,R: INTEGER;
BEGIN (*ADD2LONGS*)
C := 0; (*INIT THE CARRY*)
FOR I := 1 TO 4 DO
BEGIN (*ADD A BYTE*)
R := LVAL1(.I.) + LVAL2(.I.) + C;
C := R DIV 256;
RVAL(.I.) := R MOD 256
END; (*FOR*)
OVERFLOW := (C <> 0) (*SET UP OVERFLOW FLAG*)
END; (*ADD2LONGS*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE RSHIFTLONG (LVAL,BITS) *)
(* *)
(* THIS PROCEDURE PERFORMS A LOGICAL SHIFT RIGHT OF THE LONG *)
(* INTEGER IN 'LVAL' FOR 'BITS' BITS. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE RSHIFTLONG (VAR LVAL: LNGINT; BITS: INTEGER);
VAR
I,J,C: INTEGER;
BEGIN (*RSHIFTLONG*)
FOR I := 1 TO BITS DO
BEGIN (*SHIFT RIGHT ONE BIT*)
LVAL(.1.) := LVAL(.1.) DIV 2;
FOR J := 2 TO 4 DO
BEGIN
C := LVAL(.J.) MOD 2;
LVAL(.J.) := LVAL(.J.) DIV 2;
IF C = 1 THEN LVAL(.J - 1.) := LVAL(.J - 1.) + 128
END (*FOR*)
END (*FOR*)
END; (*RSHIFTLONG*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE NEGLONG (LVAL) *)
(* *)
(* THIS PROCEDURE NEGATES (TWO'S COMPLEMENT) THE VALUE IN *)
(* THE LONG INTEGER 'LVAL'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE NEGLONG (VAR LVAL: LNGINT);
VAR
I: INTEGER;
B: BOOLEAN;
BEGIN (*NEGLONG*)
B := FALSE; (*INIT THE BORROW FLAG*)
FOR I := 1 TO 4 DO
IF B
THEN LVAL(.I.) := 255 - LVAL(.I.)
ELSE IF LVAL(.I.) > 0 THEN (*HAVE TO BORROW*)
BEGIN
LVAL(.I.) := 256 - LVAL(.I.);
B := TRUE
END (*THEN*)
END; (*NEGLONG*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE MAKELONG (IVAL,LVAL) *)
(* *)
(* THIS PROCEDURE TURNS THE SIGNED INTEGER VALUE IN 'IVAL' *)
(* INTO A SIGNED LONG INTEGER VALUE IN 'LVAL'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE MAKELONG (IVAL: INTEGER; VAR LVAL: LNGINT);
VAR TEMP: INTEGER;
BEGIN (*MAKELONG*)
TEMP := IVAL;
IF TEMP < 0 THEN
BEGIN (*MAKE IT POSITIVE*)
TEMP := TEMP + 32767;
TEMP := TEMP + 1
END; (*THEN*)
LVAL := LONGZERO;
LVAL(.2.) := TEMP DIV 256;
LVAL(.1.) := TEMP MOD 256;
IF IVAL < 0 THEN
BEGIN (*MAKE IT NEGATIVE*)
LVAL(.2.) := LVAL(.2.) + 128;
LVAL(.3.) := 255;
LVAL(.4.) := 255
END (*THEN*)
END; (*MAKELONG*)
(*$E------------------------------------------------------------------*)
(* *)
(* FUNCTION MAKESHORT (LVAL): INTEGER *)
(* *)
(* THIS FUNCTION TURNS THE VALUE IN THE LONG INTEGER 'LVAL' *)
(* INTO A REGULAR INTEGER. *)
(* *)
(*--------------------------------------------------------------------*)
FUNCTION MAKESHORT (LVAL: LNGINT): INTEGER;
VAR
NEG: BOOLEAN;
IVAL: INTEGER;
BEGIN (*MAKESHORT*)
IF LVAL(.4.) >= 128
THEN BEGIN
NEGLONG (LVAL);
NEG := TRUE
END (*THEN*)
ELSE NEG := FALSE;
IVAL := LVAL(.2.) * 256 + LVAL(.1.);
IF NEG THEN IVAL := -IVAL;
MAKESHORT := IVAL
END; (*MAKESHORT*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE INSYMBOL *)
(* *)
(* THIS PROCEDURE GETS THE NEXT BASIC SYMBOL OF THE SOURCE *)
(* PROGRAM AND RETURNS ITS DESCRIPTION IN THE GLOBAL *)
(* VARIABLES 'SY', 'OP', 'ID', 'VAL', AND 'LNGTH'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE INSYMBOL;
VAR SYMBOLGOTTEN: BOOLEAN; (*SYMBOL GOTTEN YET?*)
(* -------------------------------------------------------------------------
PROCEDURE NEXTCH
------------------------------------------------------------------------- *
)
PROCEDURE NEXTCH;
BEGIN (* NEXTCH *)
IF EOL THEN
BEGIN
IF LIST THEN WRITELINE;
IF ERRORS OR WARNINGS THEN PRINTERROR;
READLINE
END;
CHCNT := CHCNT + 1;
EOL := (CHCNT = LINELEN);
CH := LINEBUF (. CHCNT .)
END; (* NEXTCH *)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE OPTIONS *)
(* *)
(* THIS PROCEDURE PROCESSES THE OPTIONS IN A COMMENT. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE OPTIONS;
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE COMMENTWARNING *)
(* *)
(* THIS PROCEDURE GENERATES A 511 WARNING IN AN OPTION *)
(* COMMENT. IT THEN SKIPS CHARACTERS UNTIL IT FINDS A *)
(* COMMA, ASTERISK, OR RIGHT CURLY BRACE. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE COMMENTWARNING;
BEGIN (*COMMENTWARNING*)
WARNING (511);
WHILE (CH <> ',') AND (CH <> '*') AND (CH <> 'å') DO
NEXTCH
END; (*COMMENTWARNING*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETARITHMETICSIZE *)
(* *)
(* THIS PROCEDURE GETS THE SIZE OF INTEGER ARITHMETIC. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETARITHMETICSIZE;
BEGIN (*GETARITHMETICSIZE*)
NEXTCH;
IF CH <> '='
THEN COMMENTWARNING
ELSE
BEGIN (*LOOK FOR A 1, 2, OR 4*)
NEXTCH;
IF CH = '1'
THEN BEGIN
ARITHMETICSIZE := 'H';
NEXTCH
END (*THEN*)
ELSE
IF CH = '2'
THEN BEGIN
ARITHMETICSIZE := 'I';
NEXTCH
END (*THEN*)
ELSE
IF CH = '4'
THEN BEGIN
ARITHMETICSIZE := 'J';
NEXTCH
END (*THEN*)
ELSE COMMENTWARNING
END (*ELSE*)
END; (*GETARITHMETICSIZE*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETPLUSORMINUS (PLUSFLAG,ERR) *)
(* *)
(* THIS PROCEDURE LOOKS FOR A PLUS OR MINUS SIGN IN THE NEXT *)
(* CHARACTER OF INPUT. IF A PLUS SIGN IS FOUND, PLUSFLAG IS *)
(* RETURNED TRUE. IF A MINUS SIGN IS FOUND, PLUSFLAG IS *)
(* RETURNED FALSE. IF NEITHER IS FOUND, ERR IS RETURNED TRUE. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETPLUSORMINUS (VAR PLUSFLAG,ERR: BOOLEAN);
BEGIN (*GETPLUSORMINUS*)
PLUSFLAG := FALSE;
ERR := FALSE;
NEXTCH;
IF CH = '+'
THEN BEGIN
PLUSFLAG := TRUE;
NEXTCH
END (*THEN*)
ELSE IF CH = '-'
THEN NEXTCH
ELSE BEGIN
ERR := TRUE;
COMMENTWARNING
END (*ELSE*)
END; (*GETPLUSORMINUS*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GET1PLUSORMINUS (FLAG) *)
(* *)
(* THIS PROCEDURE GETS A PLUS OR MINUS SIGN AND ASSIGNS THE *)
(* PROPER BOOLEAN VALUE TO 'FLAG'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GET1PLUSORMINUS (VAR FLAG: BOOLEAN);
VAR
PLUSFLAG,
ERR: BOOLEAN;
BEGIN (*GET1PLUSORMINUS*)
GETPLUSORMINUS (PLUSFLAG,ERR);
IF NOT ERR THEN FLAG := PLUSFLAG
END; (*GET1PLUSORMINUS*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE GET2PLUSORMINUS (FLAG1,FLAG2) *)
(* *)
(* THIS PROCEDURE GETS A PLUS OR MINUS FLAG FOR AN OPTION *)
(* AND ASSIGNS THE PROPER BOOLEAN VALUE TO THE FLAGS 'FLAG1' *)
(* AND 'FLAG2'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GET2PLUSORMINUS (VAR FLAG1,FLAG2: BOOLEAN);
VAR
PLUSFLAG,
ERR: BOOLEAN;
BEGIN (*GET2PLUSORMINUS*)
GETPLUSORMINUS (PLUSFLAG,ERR);
IF NOT ERR THEN
BEGIN
FLAG1 := PLUSFLAG;
FLAG2 := PLUSFLAG
END (*THEN*)
END; (*GET2PLUSORMINUS*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETLINT (LVAL) *)
(* *)
(* THIS PROCEDURE GETS AN '=<LONG INT>' IN AN OPTION COMMENT *)
(* AND ASSIGNS IT TO 'LVAL'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETLINT (VAR LVAL: LNGINT);
BEGIN (*GETLINT*)
NEXTCH;
IF CH <> '='
THEN COMMENTWARNING
ELSE
BEGIN (*NOW LOOK FOR THE LINT*)
NEXTCH;
IF CHTAB(.CH.) <> NUMBER
THEN COMMENTWARNING
ELSE
BEGIN (*GET THE LINT*)
LONGONLY := TRUE;
INSYMBOL;
LONGONLY := FALSE;
IF SY <> INT4CONST
THEN COMMENTWARNING
ELSE LVAL := VAL.VALP@.LINTVAL
END (*ELSE*)
END (*ELSE*)
END; (*GETLINT*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETINT (IVAL) *)
(* *)
(* THIS PROCEDURE GETS AN '=<INTEGER>' IN AN OPTION COMMENT *)
(* AND ASSIGNS IT TO 'IVAL'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETINT (VAR IVAL: INTEGER);
BEGIN (*GETINT*)
NEXTCH;
IF CH <> '='
THEN COMMENTWARNING
ELSE
BEGIN
NEXTCH;
IF CHTAB(.CH.) <> NUMBER
THEN COMMENTWARNING
ELSE
BEGIN
INSYMBOL;
IF (SY <> INT1CONST) AND (SY <> INT2CONST)
THEN COMMENTWARNING
ELSE IVAL := VAL.IVAL
END (*ELSE*)
END (*ELSE*)
END; (*GETINT*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETMACHINETYPE *)
(* *)
(* THIS PROCEDURE GETS THE MACHINE TYPE FROM AN OPTION *)
(* COMMENT. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETMACHINETYPE;
VAR
MACHINENUM: 1..2;
BEGIN (*GETMACHINETYPE*)
MACHINENUM := MACHINE;
NEXTCH;
IF CH = '2'
THEN BEGIN (*MAKE SURE 'M20'*)
NEXTCH;
IF CH <> '0'
THEN COMMENTWARNING
ELSE
BEGIN
NEXTCH;
MACHINENUM := M68000;
END;
END (*THEN*)
ELSE
IF CH <> '0' (*MAKE SURE 'M09'*)
THEN COMMENTWARNING
ELSE
BEGIN
NEXTCH;
IF CH <> '9'
THEN COMMENTWARNING
ELSE
BEGIN (*SET UP FOR THE 6809*)
NEXTCH;
MACHINENUM := M6809;
END (*ELSE*)
END (*ELSE*);
ADDRSIZE := 2 * MACHINENUM;
ALIGNMENT := MACHINENUM;
TEXTPTR@.SIZE := 2 * ADDRSIZE;
NILPTR@.SIZE := ADDRSIZE;
END; (*GETMACHINETYPE*)
(*$E------------------------------------------------------------------*)
(* *)
(* OPTIONS STARTS HERE *)
(* *)
(*--------------------------------------------------------------------*)
BEGIN (*OPTIONS*)
REPEAT (*FOR EACH OPTION*)
NEXTCH; (*GET THE... *)
CH := UPPER(.CH.); (*NEXT CHARACTER.*)
IF CH = 'A' THEN GETARITHMETICSIZE
ELSE IF CH = 'C' THEN GET1PLUSORMINUS (PRCODE)
ELSE IF CH = 'D' THEN GET2PLUSORMINUS (DEBUG,KOUNTERS)
ELSE IF CH = 'E' THEN
BEGIN
IF LIST THEN NEWPAGE;
NEXTCH
END (*THEN*)
ELSE IF CH = 'H' THEN GETLINT (HEAPSTART)
ELSE IF CH = 'J' THEN GETLINT (JUMPBASE)
ELSE IF CH = 'K' THEN GET1PLUSORMINUS (KOUNTERS)
ELSE IF CH = 'L' THEN
BEGIN
GET1PLUSORMINUS (LIST);
IF NOT LIST THEN
BEGIN
WRITELN (LISTING,' ');
PAGEPOS := PAGEPOS + 1
END (*THEN*)
END (*THEN*)
ELSE IF CH = 'M' THEN GETMACHINETYPE
ELSE IF CH = 'O' THEN GET1PLUSORMINUS (PLIST)
ELSE IF CH = 'P' THEN GET1PLUSORMINUS (PKOUNTERS)
ELSE IF CH = 'R' THEN GET1PLUSORMINUS (DEBUG)
ELSE IF CH = 'T' THEN GETLINT (STACKSTART)
ELSE IF CH = 'W' THEN GET1PLUSORMINUS (STANDARD)
ELSE IF CH = 'X' THEN GETINT (JUMPENTRIES)
UNTIL CH <> ','
END; (*OPTIONS*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETIDENTIFIER *)
(* *)
(* THIS PROCEDURE GETS AN IDENTIFIER FROM THE SOURCE INPUT. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETIDENTIFIER;
VAR
I,J: INTEGER;
FOUND: BOOLEAN;
LASTRW: INTEGER;
BEGIN
J := 1;
ID := BLANKID;
(*GET THE IDENTIFIER*)
REPEAT
IF J <= IDLNGTH THEN
BEGIN (*SAVE THE CURRENT CHARACTER*)
ID(.J.) := UPPER(.CH.);
J := J + 1
END; (*THEN*)
NEXTCH (*GET THE NEXT CHARACTER*)
UNTIL (CHTAB(.CH.) <> ATOZ) AND (CHTAB(.CH.) <> NUMBER);
(*NOW SEE IF THIS IDENTIFIER IS A RESERVED WORD*)
I := FRW(.J - 1.);
LASTRW := FRW(.J.) - 1;
FOUND := FALSE;
WHILE NOT FOUND AND (I <= LASTRW) DO
IF RW(.I.) = ID
THEN FOUND := TRUE
ELSE I := I + 1;
IF FOUND
THEN BEGIN (*IS A RESERVED WORD - SET UP SYMBOL AND OPERATOR
*) SY := RSY(.I.);
OP := ROP(.I.)
END (*THEN*)
ELSE BEGIN (*ISN'T A RESERVED WORD - SHOW IT IS AN IDENTIFIE
R*) SY := IDENT;
OP := NOOP
END (*ELSE*)
END; (*GETIDENTIFIER*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETNUMBER *)
(* *)
(* THIS PROCEDURE GETS A CONSTANT NUMBER FROM THE SOURCE *)
(* INPUT. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETNUMBER;
CONST
HEXOK = TRUE; (*HEX DIGITS OK IN NUMBER*)
HEXNOTOK = FALSE; (*HEX DIGITS ARE NOT OK IN NUMBER*)
TYPE
DIGITSTR = PACKED ARRAY (.1..35.) OF CHAR; (*DIGITS IN A NUMBER*)
VAR
REAL: BOOLEAN; (*IS THIS A REAL NUMBER?*)
I: INTEGER;
DIGITS: DIGITSTR; (*DIGITS IN THE NUMBER*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE STORECHAR (CH,INDEX,DIGITS) *)
(* *)
(* THIS PROCEDURE STORES THE CHARACTER 'CH' IN THE DIGIT *)
(* STRING 'DIGITS' AT THE POSITION AFTER 'INDEX'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE STORECHAR (CH: CHAR; VAR INDEX: INTEGER; VAR DIGITS: DIGITSTR);
BEGIN (*STORECHAR*)
INDEX := INDEX + 1;
IF INDEX <= DIGMAX THEN (*SAVE THIS CHARACTER*)
DIGITS(.INDEX.) := CH;
END; (*STORECHAR*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETDIGITS (HEXOK,INDEX,DIGITS) *)
(* *)
(* THIS PROCEDURE GETS A STRING OF DIGITS FROM THE SOURCE *)
(* INPUT. IF 'HEXOK' IS TRUE, HEX DIGITS WILL BE ALLOWED. *)
(* THE DIGITS WILL BE STORED IN THE DIGIT STRING 'DIGITS' *)
(* STARTING AT THE POSITION AFTER 'INDEX'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETDIGITS (HEXOK: BOOLEAN; VAR INDEX: INTEGER;
VAR DIGITS: DIGITSTR);
VAR CHT: CHTYP;
BEGIN (*GETDIGITS*)
REPEAT
STORECHAR (UPPER(.CH.),INDEX,DIGITS); (*STORE CURRENT CHARACTER*
) NEXTCH; (*GET THE NEXT CHARACTER*)
CHT := CHTAB(.CH.)
UNTIL (HEXOK AND (CHT <> NUMBER) AND (CHT <> ATOZ))
OR (NOT HEXOK AND (CHT <> NUMBER))
END; (*GETDIGITS*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE MAKEINT (LEN,DIGITS) *)
(* *)
(* THIS PROCEDURE MAKES AN INTEGER OUT OF THE FIRST 'LEN' *)
(* DIGITS IN THE DIGIT STRING 'DIGITS'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE MAKEINT (LEN: INTEGER; VAR DIGITS: DIGITSTR);
VAR
DIGITCH: CHAR; (*CURRENT CHARACTER CONSIDERING*)
RADIX: 0..99; (*RADIX OF NUMBER BUILDING*)
DIGIT: 0..15; (*VALUE OF CURRENT DIGIT*)
ZERO: INTEGER; (*ORD OF CHARACTER '0'*)
A: INTEGER;
LONGVAL: LNGINT; (*THE LONG VALUE OF THE INTEGER*)
I: INTEGER;
OVRFLW1,
OVRFLW2: BOOLEAN; (*OVERFLOW FLAGS*)
BEGIN (*MAKEINT*)
ZERO := ORD('0');
A := ORD('A');
LONGVAL := LONGZERO;
IF CH <> '#'
THEN RADIX := 10 (*USE DEFAULT RADIX*)
ELSE
BEGIN (*USER SUPPLIED RADIX - USE IT*)
IF STANDARD THEN WARNING(500);
IF LEN = 1
THEN RADIX := ORD(DIGITS(.1.)) - ZERO
ELSE
IF LEN = 2
THEN RADIX := (ORD(DIGITS(.1.)) - ZERO) * 10
+ (ORD(DIGITS(.2.)) - ZERO)
ELSE RADIX := 0; (*FORCE AN ERROR*)
IF (RADIX > 16) OR (RADIX < 2) THEN
BEGIN (*BAD RADIX - LET HIM KNOW*)
ERROR (400);
RADIX := 10
END; (*THEN*)
(*GET DIGITS AFTER RADIX CHARACTER '#'*)
NEXTCH;
LEN := 0;
IF (CHTAB(.CH.) <> NUMBER) AND (CHTAB(.CH.) <> ATOZ)
THEN ERROR (401)
ELSE GETDIGITS (HEXOK,LEN,DIGITS)
END; (*ELSE*)
IF LEN > DIGMAX
THEN BEGIN (*NUMBER IS TOO LONG*)
ERROR (203);
SY := INT2CONST;
VAL.IVAL := 0
END (*THEN*)
ELSE
BEGIN (*MAKE THE INTEGER*)
FOR I := 1 TO LEN DO
BEGIN (*PROCESS A DIGIT*)
DIGITCH := DIGITS(.I.);
IF (DIGITCH >= '0') AND (DIGITCH <= '9')
THEN DIGIT := ORD(DIGITCH) - ZERO
ELSE IF (DIGITCH >= 'A') AND (DIGITCH <= 'F')
THEN DIGIT := ORD(DIGITCH) - A + 10
ELSE BEGIN (*ILLEGAL DIGIT*)
ERROR (402);
DIGIT := 0
END; (*ELSE*)
IF DIGIT >= RADIX
THEN ERROR (402) (*ILLEGAL DIGIT*)
ELSE BEGIN (*ADD DIGIT TO CURRENT NUMBER*)
MULTLONG (LONGVAL,RADIX,OVRFLW1);
ADDLONG (LONGVAL,DIGIT,OVRFLW2);
IF OVRFLW1 OR OVRFLW2 THEN
BEGIN (*NUMBER TOO BIG*)
ERROR (203);
LONGVAL := LONGZERO
END (*THEN*)
END; (*ELSE*)
END; (*FOR*)
WITH CNSTVALPTR@ DO
BEGIN (*NOW SET UP THE CONSTANT*)
IF (LONGVAL(.4.) = 0) AND (LONGVAL(.3.) = 0)
AND (LONGVAL(.2.) <= 127) AND (NOT LONGONLY)
THEN BEGIN (*MAKE A REGULAR INTEGER*)
VAL.IVAL := LONGVAL(.2.) * 256 + LONGVAL(.1
.); IF VAL.IVAL <= 127
THEN SY := INT1CONST
ELSE SY := INT2CONST
END (*THEN*)
ELSE BEGIN (*SET UP A LONG INTEGER*)
SY := INT4CONST;
LINTVAL := LONGVAL;
VAL.VALP := CNSTVALPTR
END (*ELSE*)
END (*WITH*)
END (*ELSE*)
END; (*MAKEINT*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE MAKEREAL (LEN,DIGITS) *)
(* *)
(* THIS PROCEDURE CONSTRUCTS A REAL NUMBER OUT OF THE FIRST *)
(* 'LEN' DIGITS IN THE DIGIT STRINT 'DIGITS'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE MAKEREAL (LEN: INTEGER; VAR DIGITS: DIGITSTR);
VAR I: INTEGER;
BEGIN (*MAKEREAL*)
ERROR (398); (*UNTIL REALS ARE REAL*)
SY := REALCONST; (*SET UP SYMBOL TYPE*)
WITH CNSTVALPTR@ DO
BEGIN (*BUILD THE REAL NUMBER*)
FOR I := 1 TO REALLNGTH DO
RVAL(.I.) := ' ';
IF LEN > REALLNGTH
THEN BEGIN (*REAL IS TOO LONG*)
ERROR (203);
RVAL(.1.) := '0';
RVAL(.2.) := '.';
RVAL(.3.) := '0'
END (*THEN*)
ELSE FOR I := 1 TO LEN DO
RVAL(.I.) := DIGITS(.I.)
END; (*WITH*)
VAL.VALP := CNSTVALPTR
END; (*MAKEREAL*)
(*$E------------------------------------------------------------------*)
(* *)
(* GETNUMBER STARTS HERE *)
(* *)
(*--------------------------------------------------------------------*)
BEGIN (*GETNUMBER*)
OP := NOOP;
I := 0;
REAL := FALSE;
GETDIGITS (HEXNOTOK,I,DIGITS); (*GET STRING OF DIGITS*)
IF CH = '.' THEN
BEGIN (*POSSIBLY HAVE A REAL NUMBER*)
NEXTCH;
IF CH = '.'
THEN BEGIN (*NOPE - HAVE A '..'*)
DOUBLECHAR := TRUE;
DOUBLESYM := RANGE
END (*THEN*)
ELSE
IF CH = ')'
THEN BEGIN (*NOPE - HAVE A '.)'*)
DOUBLECHAR := TRUE;
DOUBLESYM := RBRACK
END (*THEN*)
ELSE
IF CHTAB(.CH.) <> NUMBER
THEN ERROR (201) (*ILLEGAL CHAR AFTER '.'*)
ELSE BEGIN (*HAVE A REAL # - GET THE RES
T*) STORECHAR ('.',I,DIGITS);
GETDIGITS (HEXNOTOK,I,DIGITS);
REAL := TRUE
END (*ELSE*)
END; (*THEN*)
IF UPPER(.CH.) = 'E' THEN
BEGIN (*HAVE AN EXPONENT - GET IT*)
REAL := TRUE;
STORECHAR ('E',I,DIGITS);
NEXTCH;
IF (CH = '+') OR (CH = '-') THEN
BEGIN (*SAVE THE SIGN*)
STORECHAR (CH,I,DIGITS);
NEXTCH
END; (*THEN*)
IF CHTAB(.CH.) <> NUMBER
THEN ERROR (201) (*HAVE TO HAVE AT LEAST ONE DIGIT*)
ELSE GETDIGITS (HEXNOTOK,I,DIGITS)
END; (*THEN*)
IF REAL
THEN MAKEREAL (I,DIGITS) (*MAKE A REAL NUMBER*)
ELSE MAKEINT (I,DIGITS) (*MAKE AN INTEGER*)
END; (*GETNUMBER*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETSTRING *)
(* *)
(* THIS PROCEDURE GETS A CONSTANT STRING FROM THE SOURCE *)
(* INPUT. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETSTRING;
BEGIN (*GETSTRING*)
LNGTH := 0;
SY := STRINGCONST;
OP := NOOP;
WITH CNSTVALPTR@ DO
BEGIN (*SET UP THE CONSTANT*)
SVAL := CNSTSTRPTR;
REPEAT
REPEAT
NEXTCH; (*GET THE NEXT CHARACTER*)
LNGTH := LNGTH + 1;
IF LNGTH <= STRGLNGTH THEN
SVAL@(.LNGTH.) := CH (*SAVE THE CHARACTER*)
UNTIL (EOL) OR (CH = '''');
IF EOL
THEN ERROR (202) (*END OF LINE IN MIDDLE OF STR*
) ELSE NEXTCH (*GET NEXT CHARACTER*)
UNTIL CH <> ''''; (*TO CHECK FOR DOUBLE QUOTES*)
LNGTH := LNGTH - 1;
IF LNGTH = 1
THEN VAL.IVAL := ORD(SVAL@(.1.)) (*HAVE A SINGLE CHARACTER
*) ELSE
BEGIN (*CHECK ON LENGTH OF STRING*)
IF LNGTH > STRGLNGTH THEN
BEGIN (*STRING IS TOO LONG*)
ERROR (398);
LNGTH := STRGLNGTH
END; (*THEN*)
VAL.VALP := CNSTVALPTR;
SLNGTH := LNGTH
END (*ELSE*)
END (*WITH*)
END; (*GETSTRING*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETCOLONORBECOMES *)
(* *)
(* THIS PROCEDURE GETS A SINGLE COLON OR A BECOMES SYMBOL. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETCOLONORBECOMES;
BEGIN (*GETCOLONORBECOMES*)
OP := NOOP;
NEXTCH; (*LOOK AT NEXT CHARACTER*)
IF CH = '='
THEN BEGIN (*HAVE A BECOMES (':=')*)
SY := BECOMES;
NEXTCH
END (*THEN*)
ELSE SY := COLON
END; (*GETCOLONORBECOMES*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETPERIODBRACKETORRANGE *)
(* *)
(* THIS PROCEDURE GETS A PERIOD, A RIGHT BRACKET, OR A *)
(* RANGE SYMBOL. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETPERIODBRACKETORRANGE;
BEGIN (*GETPERIODBRACKETORRANGE*)
OP := NOOP;
NEXTCH; (*LOOK AT NEXT CHARACTER*)
IF CH = '.'
THEN BEGIN (*HAVE A RANGE*)
SY := RANGE;
NEXTCH
END (*THEN*)
ELSE IF CH = ')'
THEN BEGIN (*HAVE A RIGHT BRACKET*)
SY := RBRACK;
NEXTCH
END (*THEN*)
ELSE SY := PERIOD (*JUST A PERIOD*)
END; (*GETPERIODBRACKETORRANGE*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETLESSLESSEQUALORNOTEQUAL *)
(* *)
(* THIS PROCEDURE GETS A LESS THAN, A LESS THAN OR EQUAL, OR *)
(* A NOT EQUAL SYMBOL. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETLESSLESSEQUALORNOTEQUAL;
BEGIN (*GETLESSLESSEQUALORNOTEQUAL*)
SY := RELOP;
NEXTCH; (*LOOK AT NEXT CHARACTER*)
IF CH = '='
THEN BEGIN (*LESS THAN OR EQUAL*)
OP := LEOP;
NEXTCH
END (*THEN*)
ELSE IF CH = '>'
THEN BEGIN (*NOT EQUAL*)
OP := NEOP;
NEXTCH
END (*THEN*)
ELSE OP := LTOP (*JUST A LESS THAN*)
END; (*GETLESSLESSEQUALORNOTEQUAL*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETGREATERORGREATEREQUAL *)
(* *)
(* THIS PROCEDURE GETS A GREATER THAN OR A GREATER THAN OR *)
(* EQUAL SYMBOL. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETGREATERORGREATEREQUAL;
BEGIN (*GETGREATERORGREATEREQUAL*)
SY := RELOP;
NEXTCH;
IF CH = '='
THEN BEGIN (*GREATER THAN OR EQUAL*)
OP := GEOP;
NEXTCH
END (*THEN*)
ELSE OP := GTOP (*JUST A GREATER THAN*)
END; (*GETGREATERORGREATEREQUAL*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETMISCCHAR *)
(* *)
(* THIS PROCEDURE HANDLES A MISCELLANEOUS CHARACTER. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETMISCCHAR;
BEGIN (*GETMISCCHAR*)
SY := SSY(.CH.);
OP := SOP(.CH.);
NEXTCH
END; (*GETMISCCHAR*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE SKIPILLEGALCHAR (SYMBOLGOTTEN) *)
(* *)
(* THIS PROCEDURE SKIPS OVER AN ILLEGAL CHARACTER, AFTER *)
(* GENERATING AN ERROR FOR THAT CHARACTER. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE SKIPILLEGALCHAR (VAR SYMBOLGOTTEN: BOOLEAN);
BEGIN (*SKIPILLEGALCHAR*)
SY := OTHERSY;
OP := NOOP;
ERROR (398);
NEXTCH;
SYMBOLGOTTEN := FALSE
END; (*SKIPILLEGALCHAR*)
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETPARNCOMMENTORBRACKET (SYMBOLGOTTEN) *)
(* *)
(* THIS PROCEDURE GETS A LEFT PAREN, A COMMENT, OR A *)
(* LEFT BRACKET. 'SYMBOLGOTTEN' IS RETURNED TRUE IF A *)
(* SYMBOL OTHER THAN A COMMENT WAS FOUND. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETPARNCOMMENTORBRACKET (VAR SYMBOLGOTTEN: BOOLEAN);
BEGIN (*GETPARNCOMMENTORBRACKET*)
NEXTCH; (*TAKE A LOOK AT THE NEXT CHAR*)
IF CH = '*'
THEN BEGIN (*THIS IS A COMMENT*)
NEXTCH;
IF CH = '$' THEN OPTIONS; (*PROCESS OPTION COMMENT*)
REPEAT (*FIND END OF COMMENT*)
WHILE CH <> '*' DO
BEGIN
IF CH = '(' THEN
BEGIN (*CHECK FOR NESTED COMMENT*)
NEXTCH;
IF CH = '*' THEN WARNING (503)
END; (*THEN*)
NEXTCH
END; (*WHILE*)
NEXTCH
UNTIL CH = ')';
NEXTCH;
SYMBOLGOTTEN := FALSE
END (*THEN*)
ELSE IF CH = '.'
THEN BEGIN (*HAVE A LEFT BRACKET*)
SY := LBRACK;
OP := NOOP;
NEXTCH
END (*THEN*)
ELSE BEGIN (*JUST A LEFT PAREN*)
SY := LPARENT;
OP := NOOP
END (*ELSE*)
END; (*GETPARNCOMMENTORBRACKET*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE GETCOMMENT *)
(* *)
(* THIS PROCEDURE GETS A COMMENT THAT WAS STARTED BY A LEFT *)
(* CURLY BRACKET. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE GETCOMMENT (VAR SYMBOLGOTTEN: BOOLEAN);
BEGIN (*GETCOMMENT*)
NEXTCH;
IF CH = '$' THEN OPTIONS; (*PROCESS AN OPTION COMMENT*)
WHILE CH <> 'å' DO (*FIND THE END OF THE COMMENT*)
BEGIN
NEXTCH;
IF CH = 'æ' THEN WARNING (503)
END; (*WHILE*)
NEXTCH;
SYMBOLGOTTEN := FALSE
END; (*GETCOMMENT*)
(*$E------------------------------------------------------------------*)
(* *)
(* INSYMBOL STARTS HERE *)
(* *)
(*--------------------------------------------------------------------*)
BEGIN (*INSYMBOL*)
REPEAT
SYMBOLGOTTEN := TRUE;
IF DOUBLECHAR
THEN BEGIN (*HAVE DOUBLE CHAR LEFT OVER FROM NUM
*) DOUBLECHAR := FALSE;
SY := DOUBLESYM;
OP := NOOP;
NEXTCH
END (*THEN*)
ELSE BEGIN (*HAVE TO GET A SYMBOL*)
(*FIRST SKIP BLANKS*)
WHILE CHTAB(.CH.) = BLANKCHAR DO NEXTCH;
(*NOW XFER CONTROL BASED ON CURRENT CHARACTER*)
CASE CHTAB(.CH.) OF
ATOZ: GETIDENTIFIER;
NUMBER: GETNUMBER;
STRQUOTE: GETSTRING;
COLONCHAR: GETCOLONORBECOMES;
PERIODCHAR: GETPERIODBRACKETORRANGE;
LPOINTY: GETLESSLESSEQUALORNOTEQUAL;
RPOINTY: GETGREATERORGREATEREQUAL;
MISCCHAR: GETMISCCHAR;
ILLEGALCHAR: SKIPILLEGALCHAR (SYMBOLGOTTEN);
LPARN: GETPARNCOMMENTORBRACKET (SYMBOLGOTTEN);
CMNTBRACK: GETCOMMENT (SYMBOLGOTTEN)
END (*CASE*)
END (*ELSE*)
UNTIL SYMBOLGOTTEN
END; (*INSYMBOL*)
(*$E------------------------------------------------------------------*)
(* *)
(* FUNCTION INTTYPE (TYPTR): BOOLEAN *)
(* *)
(* THIS FUNCTION DETERMINES IF THE TYPE POINTED TO BY 'TYPTR' *)
(* IS AN INTEGER (SHORT, MEDIUM, OR TALL). *)
(* *)
(*--------------------------------------------------------------------*)
FUNCTION INTTYPE (TYPTR: STP): BOOLEAN;
BEGIN (*INTTYPE*)
INTTYPE := (TYPTR = INT1PTR) OR (TYPTR = INT2PTR) OR (TYPTR = INT4PTR)
END; (*INTTYPE*)
(* -------------------------------------------------------------------------
PROCEDURE ENTERID
------------------------------------------------------------------------- *
)
PROCEDURE ENTERID(FCP: CTP);
(* ENTER ID POINTED AT BY FCP INTO THE NAME-TABLE,
WHICH ON EACH DECLARATION LEVEL IS ORGANISED AS
AN UNBALANCED BINARY TREE *)
VAR NAM: ALPHA; LCP, LCP1: CTP; LLEFT: BOOLEAN;
BEGIN NAM := FCP@.NAME;
LCP := DISPLAY(.TOP.).FNAME;
IF LCP = NIL THEN
DISPLAY(.TOP.).FNAME := FCP
ELSE
BEGIN
REPEAT LCP1 := LCP;
IF LCP@.NAME = NAM THEN (* NAME CONFLICT, FOLLOW RIGHT LINK *)
BEGIN ERROR(101); LCP := LCP@.RLINK; LLEFT := FALSE END
ELSE
IF LCP@.NAME < NAM THEN
BEGIN LCP := LCP@.RLINK; LLEFT := FALSE END
ELSE BEGIN LCP := LCP@.LLINK; LLEFT := TRUE END
UNTIL LCP = NIL;
IF LLEFT THEN LCP1@.LLINK := FCP ELSE LCP1@.RLINK := FCP
END;
FCP@.LLINK := NIL; FCP@.RLINK := NIL
END (* ENTERID *) ;
(* -------------------------------------------------------------------------
PROCEDURE SEARCHSECTION
------------------------------------------------------------------------- *
)
PROCEDURE SEARCHSECTION(FCP: CTP; VAR FCP1: CTP);
(* TO FIND RECORD FIELDS AND FORWARD DECLARED PROCEDURE ID'S
--> PROCEDURE PROCEDUREDECLARATION
--> PROCEDURE SELECTOR *)
VAR DONE: BOOLEAN;
BEGIN
DONE := FALSE;
WHILE (FCP <> NIL) AND NOT DONE DO
IF FCP@.NAME = ID THEN DONE := TRUE
ELSE IF FCP@.NAME < ID THEN FCP := FCP@.RLINK
ELSE FCP := FCP@.LLINK;
FCP1 := FCP
END (* SEARCHSECTION *) ;
(* -------------------------------------------------------------------------
PROCEDURE SEARCHID
------------------------------------------------------------------------- *
)
PROCEDURE SEARCHID(FIDCLS: SETOFIDS; VAR FCP: CTP);
VAR LCP: CTP;
FOUND: BOOLEAN;
BEGIN
FOUND := FALSE;
DISX := TOP + 1;
WHILE NOT FOUND AND (DISX > 0) DO
BEGIN DISX := DISX - 1;
LCP := DISPLAY(.DISX.).FNAME;
WHILE NOT FOUND AND (LCP <> NIL) DO
IF LCP@.NAME = ID THEN
IF LCP@.KLASS IN FIDCLS THEN FOUND := TRUE
ELSE
BEGIN IF PRTERR THEN ERROR(103);
LCP := LCP@.RLINK
END
ELSE
IF LCP@.NAME < ID THEN
LCP := LCP@.RLINK
ELSE LCP := LCP@.LLINK;
END;
(*IF SEARCH NOT SUCCESSFUL; SUPPRESS ERROR MESSAGE IN CASE
OF FORWARD REFERENCED TYPE ID IN POINTER TYPE DEFINITION
--> PROCEDURE SIMPLETYPE *)
IF NOT FOUND AND PRTERR THEN
BEGIN ERROR(104);
(*TO AVOID RETURNING NIL, REFERENCE AN ENTRY
FOR AN UNDECLARED ID OF APPROPRIATE CLASS
--> PROCEDURE ENTERUNDECL *)
IF TYPES IN FIDCLS THEN LCP := UTYPPTR
ELSE
IF VARS IN FIDCLS THEN LCP := UVARPTR
ELSE
IF FIELD IN FIDCLS THEN LCP := UFLDPTR
ELSE
IF KONST IN FIDCLS THEN LCP := UCSTPTR
ELSE
IF PROC IN FIDCLS THEN LCP := UPRCPTR
ELSE
IF LABELS IN FIDCLS THEN LCP := ULABPTR
ELSE LCP := UFCTPTR;
END;
FCP := LCP
END (* SEARCHID *) ;
(* -------------------------------------------------------------------------
PROCEDURE GETBOUNDS
------------------------------------------------------------------------- *
)
PROCEDURE GETBOUNDS(FSP: STP; VAR FMIN,FMAX: LNGINT);
(* GET INTERNAL BOUNDS OF SUBRANGE OR SCALAR TYPE *)
(* ASSUME (FSP <> NIL) AND (FSP@.FORM <= SUBRANGE)
AND NOT COMPTYPES(REALPTR,FSP) *)
BEGIN
WITH FSP@ DO
IF FORM = SUBRANGE THEN
BEGIN
IF RANGETYPE = CHARPTR THEN
BEGIN
MAKELONG (ASCII(.CHR(MIN.IVAL).),FMIN);
MAKELONG (ASCII(.CHR(MAX.IVAL).),FMAX)
END
ELSE
IF RANGETYPE = INT4PTR
THEN BEGIN
FMIN := MIN.VALP@.LINTVAL;
FMAX := MAX.VALP@.LINTVAL
END (*THEN*)
ELSE BEGIN
MAKELONG (MIN.IVAL,FMIN);
MAKELONG (MAX.IVAL,FMAX)
END (*ELSE*)
END
ELSE
BEGIN FMIN := LONGZERO;
IF FSP = CHARPTR THEN FMAX := LONGORDMAXCHAR
ELSE IF FSP = INT1PTR THEN
BEGIN
FMIN := LINT1MIN;
FMAX := LINT1MAX
END (*THEN*)
ELSE IF FSP = INT2PTR THEN
BEGIN
FMIN := LINT2MIN;
FMAX := LINT2MAX
END (*THEN*)
ELSE IF FSP = INT4PTR THEN
BEGIN
FMIN := LINT4MIN;
FMAX := LINT4MAX
END (*THEN*)
ELSE
IF (FORM = SCALAR) AND ((* FSP@. *)FCONST <> NIL) THEN
MAKELONG (FSP@.FCONST@.VALUES.IVAL,FMAX)
ELSE FMAX := LONGZERO
END
END (* GETBOUNDS *) ;
(* -------------------------------------------------------------------------
PROCEDURE GENLABEL
------------------------------------------------------------------------- *
)
PROCEDURE GENLABEL(VAR NXTLAB: LABELRNG);
BEGIN INTLABEL := INTLABEL + 1;
NXTLAB := INTLABEL
END (* GENLABEL *);
(* -------------------------------------------------------------------------
PROCEDURE GENLI (USED TO BE INSIDE "BODY" NEAR OTHER "GEN.."S)
------------------------------------------------------------------------- *
)
PROCEDURE GENLI (FOP:MNRANGE; LEVEL:LEVRANGE; OPERAND:INTEGER);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, LEVEL:3, ' ', OPERAND);
IC := IC + 1
END (*THEN*)
END; (*GENLI*)
PROCEDURE GENDEF1(L1: LABELRNG; LNAME:ALPHA ) ;
BEGIN
IF PRCODE THEN
WRITELN(PCODE,'$', L1:3,MN(.17(* DEF *).):5,
'''',LNAME:IDLNGTH,'''');
END (* GENDEF1 *) ;
(* -------------------------------------------------------------------------
PROCEDURE BLOCK
------------------------------------------------------------------------- *
)
PROCEDURE BLOCK(FSYS: SETOFSYS; FSY: SYMBOL; FPROCP: CTP);
TYPE FWDREC = RECORD PF:CTP; NEXTPF:@FWDREC END;
VAR LSY: SYMBOL; TEST: BOOLEAN;
LOOPLISTPTR: LOOPPTR;
FWDLIST,KFWD: @FWDREC;
LOCFILELIST: CTP;
PARMLEN: INTEGER ;
(* -------------------------------------------------------------------------
PROCEDURE SKIP
------------------------------------------------------------------------- *
)
PROCEDURE SKIP(FSYS: SETOFSYS);
(* SKIP INPUT STRING UNTIL RELEVANT SYMBOL FOUND *)
BEGIN
WHILE NOT(SY IN FSYS) DO INSYMBOL
END (* SKIP *) ;
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE NEGICONST (LSP,IVAL,LVAL) *)
(* *)
(* THIS PROCEDURE NEGATES THE INTEGER CONSTANT WHOSE STP IS *)
(* 'LSP' AND VALUE IS 'IVAL' OR 'LVAL'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE NEGICONST (VAR LSP: STP; VAR IVAL: INTEGER; VAR LVAL: LNGINT);
BEGIN (*NEGICONST*)
IF LSP = INT1PTR
THEN
BEGIN (*NEGATE A 1-BYTE VALUE*)
IVAL := -IVAL;
IF IVAL = 128 THEN LSP := INT2PTR
END (*THEN*)
ELSE
IF LSP = INT2PTR
THEN
BEGIN (*NEGATE A 2-BYTE VALUE*)
IF IVAL + 1 = -32767
THEN
BEGIN (*MAKE A LONG VALUE*)
LVAL := LONGZERO;
LVAL(.2.) := 128;
LSP := INT4PTR
END (*THEN*)
ELSE
BEGIN
IVAL := -IVAL;
IF IVAL = -128 THEN LSP := INT1PTR
END (*ELSE*)
END (*THEN*)
ELSE (*NEGATE A 4-BYTE VALUE*)
IF (LVAL(.4.) = 0) AND (LVAL(.3.) = 0)
AND (LVAL(.2.) = 128) AND (LVAL(.1.) = 0)
THEN
BEGIN (*MAKE IT A 2-BYTE VALUE*)
IVAL := -32767;
IVAL := IVAL - 1;
LSP := INT2PTR
END (*THEN*)
ELSE NEGLONG (LVAL)
END; (*NEGICONST*)
(* -------------------------------------------------------------------------
PROCEDURE CONSTANT
------------------------------------------------------------------------- *
)
PROCEDURE CONSTANT(FSYS: SETOFSYS; VAR FSP: STP; VAR FVALU: VALU);
VAR LSP: STP; LCP: CTP; SIGN: (NONE,POS,NEG);
LVP: CSP; I: 0..REALLNGTH;
INTVAL: INTEGER;
LNGVAL: LNGINT;
BEGIN LSP := NIL; FVALU.IVAL := 0;
IF NOT(SY IN CONSTBEGSYS) THEN
BEGIN ERROR(50); SKIP(FSYS+CONSTBEGSYS) END;
IF SY IN CONSTBEGSYS THEN
BEGIN
IF SY = STRINGCONST THEN
BEGIN
IF LNGTH = 1 THEN LSP := CHARPTR
ELSE
BEGIN
NEW(LSP,STRINGS);
WITH LSP@ DO
BEGIN
IF ODD(LNGTH) AND (ALIGNMENT = 2) THEN
LNGTH := LNGTH + 1;
SIZE := LNGTH+ALIGNMENT; FORM := STRINGS;
END ;
LVP := VAL.VALP ;
NEW(VAL.VALP, STRG) ;
VAL.VALP@.SLNGTH := LVP@.SLNGTH ;
VAL.VALP@.SVAL := LVP@.SVAL ;(* COPY STRING CONST TO HEAP *
) END;
FVALU(* .VALP *) := VAL(* .VALP *) ; INSYMBOL;
END
ELSE
BEGIN
SIGN := NONE;
IF (SY = ADDOP) AND (OP IN (.PLUS,MINUS.)) THEN
BEGIN IF OP = PLUS THEN SIGN := POS ELSE SIGN := NEG;
INSYMBOL
END;
IF SY = IDENT THEN
BEGIN SEARCHID((.KONST.),LCP);
WITH LCP@ DO
BEGIN LSP := IDTYPE; FVALU := VALUES END;
IF SIGN <> NONE THEN
IF INTTYPE(LSP) THEN
BEGIN
IF SIGN = NEG THEN
BEGIN (*NEGATE AN INTEGER CONST*)
INTVAL := FVALU.IVAL;
IF LSP = INT4PTR THEN
LNGVAL := FVALU.VALP@.LINTVAL;
NEGICONST (LSP,INTVAL,LNGVAL);
IF (LSP = INT1PTR) OR (LSP = INT2PTR)
THEN FVALU.IVAL := INTVAL
ELSE BEGIN (*MAKE A LONG*)
NEW (LVP,LINT);
LVP@.LINTVAL := LNGVAL;
FVALU.VALP := LVP
END (*ELSE*)
END (*THEN*)
END (*THEN*)
ELSE
IF LSP = REALPTR THEN
BEGIN
IF SIGN = NEG THEN
BEGIN NEW(LVP,REEL);
IF FVALU.VALP@.RVAL(.0.) = '-' THEN
LVP@.RVAL(.0.) := '+'
ELSE LVP@.RVAL(.0.) := '-';
FOR I := 1 TO REALLNGTH DO
LVP@.RVAL(.I.) := FVALU.VALP@.RVAL(.I.);
FVALU.VALP := LVP;
END
END
ELSE ERROR(105);
INSYMBOL;
END
ELSE
IF (SY = INT1CONST) OR (SY = INT2CONST) OR (SY = INT4CONST) T
HEN BEGIN
INTVAL := VAL.IVAL;
IF SY = INT1CONST
THEN LSP := INT1PTR
ELSE
IF SY = INT2CONST
THEN LSP := INT2PTR
ELSE
BEGIN
LSP := INT4PTR;
LNGVAL := VAL.VALP@.LINTVAL
END; (*ELSE*)
IF SIGN = NEG THEN NEGICONST (LSP,INTVAL,LNGVAL);
IF (LSP = INT1PTR) OR (LSP = INT2PTR)
THEN FVALU.IVAL := INTVAL
ELSE BEGIN
NEW (LVP,LINT);
LVP@.LINTVAL := LNGVAL;
FVALU.VALP := LVP
END; (*ELSE*)
INSYMBOL
END (*THEN*)
ELSE
IF SY = REALCONST THEN
BEGIN
WITH VAL.VALP@ DO
IF SIGN = NEG THEN RVAL(.0.) := '-'
ELSE RVAL(.0.) := '+' ;
NEW(LVP, REEL) ;
LVP@.RVAL := VAL.VALP@.RVAL ;
LSP := REALPTR; FVALU.VALP := LVP; INSYMBOL
END
ELSE
BEGIN ERROR(106); SKIP(FSYS) END
END;
IF NOT (SY IN FSYS) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END;
FSP := LSP;
END (* CONSTANT *) ;
(*$E------------------------------------------------------------------*)
(* *)
(* FUNCTION COMPTYPES *)
(* *)
(* FUNCTION COMPTYPES CHECKS TO SEE IF THE TYPES DESCRIBED BY *)
(* THE POINTERS FSP1, AND FSP2 ARE ASSIGNMENT COMPATIBLE. *)
(*--------------------------------------------------------------------*)
FUNCTION COMPTYPES(FSP1,FSP2: STP) : BOOLEAN;
(*DECIDE WHETHER STRUCTURES PTED AT BY FSP1 & FSP2 ARE COMPATIBLE *)
VAR NXT1,NXT2: CTP; COMP: BOOLEAN;
LTESTP1,LTESTP2 : TESTP;
BEGIN
IF FSP1 = FSP2 THEN COMPTYPES := TRUE
ELSE
IF (FSP1 <> NIL) AND (FSP2 <> NIL) THEN
IF FSP1@.FORM = FSP2@.FORM THEN
CASE FSP1@.FORM OF
SCALAR:
COMPTYPES := INTTYPE (FSP1) AND INTTYPE (FSP2);
(* IDENTICAL SCALARS DECLARED ON DIFFERENT LEVELS ARE
NOT RECOGNIZED TO BE COMPATIBLE UNLESS THE ARE BOTH
INTEGER TYPES (LONG REG, OR SHORT) *)
SUBRANGE:
COMPTYPES := COMPTYPES(FSP1@.RANGETYPE,FSP2@.RANGETYPE);
POINTER:
BEGIN
COMP := FALSE; LTESTP1 := GLOBTESTP;
LTESTP2 := GLOBTESTP;
WHILE LTESTP1 <> NIL DO
WITH LTESTP1@ DO
BEGIN
IF (ELT1 = FSP1@.ELTYPE) AND
(ELT2 = FSP2@.ELTYPE) THEN COMP := TRUE;
LTESTP1 := LASTTESTP
END;
IF NOT COMP THEN
BEGIN NEW(LTESTP1);
WITH LTESTP1@ DO
BEGIN ELT1 := FSP1@.ELTYPE;
ELT2 := FSP2@.ELTYPE;
LASTTESTP := GLOBTESTP
END;
GLOBTESTP := LTESTP1;
COMP := COMPTYPES(FSP1@.ELTYPE,FSP2@.ELTYPE)
END;
COMPTYPES := COMP; GLOBTESTP := LTESTP2
END;
POWER:
COMPTYPES := COMPTYPES(FSP1@.ELSET,FSP2@.ELSET);
STRINGS:
COMPTYPES := TRUE;
ARRAYS:
COMPTYPES := COMPTYPES(FSP1@.AELTYPE,FSP2@.AELTYPE)
AND (FSP1@.SIZE = FSP2@.SIZE);
(* ALTERNATIVES: -- ADD A THIRD BOOLEAN TERM: INDEXTYPE MUST
BE COMPATIBLE.
-- ADD A FOURTH BOOLEAN TERM: LOWBOUNDS MUST
BE THE SAME *)
RECORDS:
BEGIN NXT1 := FSP1@.FSTFLD; NXT2 := FSP2@.FSTFLD; COMP:=TRUE;
WHILE (NXT1 <> NIL) AND (NXT2 <> NIL) DO
BEGIN COMP:=COMP AND COMPTYPES(NXT1@.IDTYPE,NXT2@.IDTYPE)
; NXT1 := NXT1@.NEXT; NXT2 := NXT2@.NEXT
END;
COMPTYPES := COMP AND (NXT1 = NIL) AND (NXT2 = NIL)
AND(FSP1@.RECVAR = NIL)AND(FSP2@.RECVAR = NIL)
END;
(* IDENTICAL RECORDS ARE RECOGNIZED TO BE COMPATIBLE
IFF NO VARIANTS OCCUR *)
FILES:
COMPTYPES := COMPTYPES(FSP1@.FILTYPE,FSP2@.FILTYPE);
TAGFLD: ;
VARIANT:
END (* CASE *)
ELSE (* FSP1@.FORM <> FSP2@.FORM *)
IF FSP1@.FORM = SUBRANGE THEN
COMPTYPES := COMPTYPES(FSP1@.RANGETYPE,FSP2)
ELSE
IF FSP2@.FORM = SUBRANGE THEN
COMPTYPES := COMPTYPES(FSP1,FSP2@.RANGETYPE)
ELSE COMPTYPES := FALSE
ELSE COMPTYPES := TRUE
END (* COMPTYPES *) ;
FUNCTION SAMELABEL(SYM:SYMBOL; LPTR:LBP) : BOOLEAN;
(* NEW FUNCTION TO SUPPORT ALPHANUMERIC LABELS *)
(* CALLED BY LABELDECLARATION, GOTOSTATEMENT AND *)
(* STATEMENT FOR USE IN LOOKING UP A LABEL VALUE *)
BEGIN
IF LPTR <> NIL THEN
BEGIN IF (SYM = INT2CONST) AND NOT LPTR@.ALF THEN
SAMELABEL := VAL.IVAL = LPTR@.LABVAL
ELSE IF (SYM = IDENT) AND LPTR@.ALF THEN
SAMELABEL := ID = LPTR@.LABNAME
ELSE SAMELABEL := FALSE
END
ELSE SAMELABEL := FALSE;
END (* SAMELABEL *) ;
FUNCTION CHARARRAY(FSP: STP) : BOOLEAN;
BEGIN CHARARRAY := FALSE;
IF FSP <> NIL THEN
IF FSP@.FORM = ARRAYS THEN
CHARARRAY := COMPTYPES(FSP@.AELTYPE,CHARPTR)
END ; (* CHARARRAY *)
FUNCTION ALIGN(OP:INTEGER):INTEGER; (*ALIGN OP TO 'ALIGNMENT' BOUNDARY*)
VAR
ADJUSTMENT: INTEGER;
BEGIN
ADJUSTMENT := ABS(OP) MOD ALIGNMENT;
IF ADJUSTMENT = 0 THEN ALIGN := OP
ELSE
IF OP < 0 THEN
ALIGN := OP - (ALIGNMENT - ADJUSTMENT)
ELSE
ALIGN := OP + (ALIGNMENT - ADJUSTMENT)
END;
(*$E------------------------------------------------------------------------
PROCEDURE TYP
------------------------------------------------------------------------- *
)
PROCEDURE TYP(FSYS: SETOFSYS; VAR FSP: STP; VAR FSIZE: ADDRRANGE);
VAR
LSP,
LSP1,
LSP2: STP;
OLDTOP: DISPRANGE;
LCP: CTP;
KVALU: VALU;
LSIZE,
DISPL: ADDRRANGE;
LMIN,
LMAX: INTEGER;
LNGMIN,
LNGMAX: LNGINT;
(* -------------------------------------------------------------------------
PROCEDURE SIMPLETYP
------------------------------------------------------------------------- *
)
PROCEDURE SIMPLETYPE(FSYS:SETOFSYS;
VAR FSP:STP (* ; VAR FSIZE:ADDRRANGE *));
VAR LSP,LSP1,LSP2: STP; LCP,LCP1: CTP; TTOP: DISPRANGE;
LCNT: INTEGER; VAL1,VAL2: VALU;
SUBR,BADRANGE: BOOLEAN;
CVAL: CSP;
LVAL: LNGINT;
BEGIN FSIZE := 1;
IF NOT (SY IN SIMPTYPEBEGSYS) THEN
BEGIN ERROR(1); SKIP(FSYS + SIMPTYPEBEGSYS) END;
IF SY IN SIMPTYPEBEGSYS THEN
BEGIN
IF SY = LPARENT THEN
BEGIN TTOP := TOP; (* DECL. CONSTS LOCAL TO INNERMOST BLOCK *
) WHILE DISPLAY(.TOP.).OCCUR <> BLCK DO TOP := TOP - 1;
NEW(LSP,SCALAR);
WITH LSP@ DO
BEGIN SIZE := INT2SIZE; FORM := SCALAR;
END;
LCP1 := NIL; LCNT := 0;
REPEAT INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(LCP,KONST);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := LSP; NEXT := LCP1;
VALUES.IVAL := LCNT; KLASS := KONST
END;
ENTERID(LCP);
LCNT := LCNT + 1;
LCP1 := LCP; INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + (.COMMA,RPARENT.)) THEN
BEGIN ERROR(6); SKIP(FSYS + (.COMMA,RPARENT.)) END
UNTIL SY <> COMMA;
LSP@.FCONST := LCP1; TOP := TTOP;
IF LCNT <= 128 THEN LSP@.SIZE := INT1SIZE;
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END
ELSE
BEGIN
SUBR := FALSE;
LSP := NIL;
IF SY = IDENT THEN
BEGIN SEARCHID((.TYPES,KONST.),LCP);
INSYMBOL;
IF LCP@.KLASS = KONST THEN
BEGIN
WITH LCP@ DO
BEGIN
LSP1 := IDTYPE;
IF CHARARRAY(LSP1)
THEN ERROR(148)
ELSE BEGIN
SUBR := TRUE;
VAL1 := VALUES
END (*ELSE*)
END (*WITH*)
END
ELSE
BEGIN LSP := LCP@.IDTYPE;
(* IF LSP <> NIL THEN FSIZE := LSP@.SIZE *)
END
END (* SY = IDENT *)
ELSE
BEGIN
CONSTANT(FSYS + (.RANGE.),LSP1,VAL1);
IF CHARARRAY(LSP1)
THEN ERROR(148)
ELSE SUBR := TRUE
END;
IF SUBR THEN
BEGIN (*PROCESS THE REST OF THE SUBRANG
E*) IF SY = RANGE
THEN INSYMBOL
ELSE ERROR(5);
CONSTANT (FSYS,LSP2,VAL2);
IF INTTYPE(LSP1) AND INTTYPE(LSP2) THEN
IF LSP1 <> LSP2 THEN
IF ((LSP1 = INT1PTR) OR (LSP1 = INT2PTR))
AND ((LSP2 = INT1PTR) OR (LSP2 = INT2PTR))
THEN BEGIN (*MAKE EM BOTH REGULAR*)
LSP1 := INT2PTR;
LSP2 := INT2PTR
END (*THEN*)
ELSE
BEGIN
NEW(CVAL,LINT);
IF LSP1 = INT4PTR
THEN BEGIN
MAKELONG (VAL2.IVAL,LVAL);
VAL2.VALP := CVAL;
LSP2 := INT4PTR
END (*THEN*)
ELSE BEGIN
MAKELONG (VAL1.IVAL,LVAL);
VAL1.VALP := CVAL;
LSP1 := INT4PTR
END; (*ELSE*)
CVAL@.LINTVAL := LVAL
END; (*ELSE*)
IF LSP1 <> LSP2
THEN ERROR(107)
ELSE
IF LSP1 = REALPTR
THEN ERROR(398)
ELSE
BEGIN (*CHECK FOR LEGAL RANGE*)
IF LSP1 = INT4PTR
THEN BADRANGE := COMPLONGS (VAL1.VALP@.LINTVAL,
VAL2.VALP@.LINTVAL)
= LNGGREATER
ELSE BADRANGE := VAL1.IVAL > VAL2.IVAL;
IF BADRANGE
THEN ERROR(102)
ELSE
BEGIN (*MAKE THE SUBRANGE*)
NEW (LSP,SUBRANGE);
WITH LSP@ DO
BEGIN
RANGETYPE := LSP1;
FORM := SUBRANGE;
MIN := VAL1;
MAX := VAL2;
SIZE := LSP1@.SIZE
END (*WITH*)
END (*ELSE*)
END (*ELSE*)
END (*THEN*)
END;
FSP := LSP;
IF NOT (SY IN FSYS) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END
ELSE FSP := NIL
END (* SIMPLETYPE *) ;
(* -------------------------------------------------------------------------
PROCEDURE FIELDLIST
------------------------------------------------------------------------- *
)
PROCEDURE FIELDLIST(FSYS: SETOFSYS; VAR FRECVAR: STP);
VAR LCP,LCP1,NXT,NXT1: CTP; LSP,LSP1,LSP2,LSP3,LSP4: STP;
MINSIZE,MAXSIZE,LSIZE: ADDRRANGE; LVALU: VALU;
BEGIN NXT1 := NIL; LSP := NIL;
IF NOT (SY IN FSYS+(.IDENT,CASESY.)) THEN
BEGIN ERROR(19); SKIP(FSYS + (.IDENT,CASESY.)) END;
WHILE SY = IDENT DO
BEGIN NXT := NXT1;
REPEAT
IF SY = IDENT THEN
BEGIN NEW(LCP,FIELD);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := NIL; NEXT := NXT;
KLASS := FIELD
END;
NXT := LCP;
ENTERID(LCP);
INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN (.COMMA,COLON.)) THEN
BEGIN ERROR(6); SKIP(FSYS + (.COMMA,COLON,SEMICOLON,CASESY.))
END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
TYP(FSYS + (.CASESY,SEMICOLON.),LSP,LSIZE);
WHILE NXT <> NXT1 DO
WITH NXT@ DO
BEGIN IDTYPE := LSP;
IF LSIZE > 1 THEN DISPL := ALIGN(DISPL);
FLDADDR := DISPL;
DISPL := DISPL + LSIZE;
NXT := NEXT
END;
NXT1 := LCP;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN (.IDENT,CASESY,ENDSY.)) THEN (*IGNORE EXTRA ;*)
BEGIN ERROR(19); SKIP(FSYS + (.IDENT,CASESY.)) END
END
END (* WHILE *);
NXT := NIL;
WHILE NXT1 <> NIL DO
WITH NXT1@ DO
BEGIN LCP := NEXT; NEXT := NXT; NXT := NXT1; NXT1 := LCP END;
IF SY = CASESY THEN
BEGIN NEW(LSP,TAGFLD);
WITH LSP@ DO
BEGIN TAGFIELDP := NIL; FSTVAR := NIL; FORM:=TAGFLD END;
FRECVAR := LSP;
INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(LCP,FIELD);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := NIL; KLASS:=FIELD;
NEXT := NIL ; (*FLDADDR WILL BE SET WHEN TYPE IS KNOWN*)
END;
PRTERR := FALSE ; SEARCHID((.TYPES.),LCP1) ; PRTERR := TRUE ;
IF LCP1 = NIL THEN BEGIN (* EXPLICIT TAG FIELD *)
ENTERID(LCP); INSYMBOL ;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
IF SY <> IDENT THEN
BEGIN ERROR(2); SKIP(FSYS + (.OFSY,LPARENT.)) END
END (* IF LCP1 = NIL *)
ELSE (* NO EXPLICT TAG FIELD *)
LCP@.NAME := BLANKID ;
BEGIN SEARCHID((.TYPES.),LCP1);
LSP1 := LCP1@.IDTYPE;
IF LSP1 <> NIL THEN
WITH LSP1@ DO
BEGIN
IF LCP@.NAME <> BLANKID THEN BEGIN
IF SIZE > 1 THEN DISPL := ALIGN(DISPL);
LCP@.FLDADDR := DISPL ; DISPL := DISPL + SIZE;
END (* LCP@.NAME <> BLANKID *) ;
IF (FORM <= SUBRANGE) OR CHARARRAY(LSP1) THEN
BEGIN IF COMPTYPES(REALPTR,LSP1) THEN ERROR(109)
ELSE IF CHARARRAY(LSP1) THEN ERROR(398);
LCP@.IDTYPE := LSP1; LSP@.TAGFIELDP := LCP;
END
ELSE ERROR(110);
END (* WITH LSP1@ DO *) ;
INSYMBOL;
END
END
ELSE BEGIN ERROR(2); SKIP(FSYS + (.OFSY,LPARENT.)) END;
LSP@.SIZE := DISPL;
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8);
LSP1 := NIL; MINSIZE := DISPL; MAXSIZE := DISPL;
REPEAT LSP2 := NIL;
REPEAT CONSTANT(FSYS + (.COMMA,COLON,LPARENT.),LSP3,LVALU);
IF LSP@.TAGFIELDP <> NIL THEN
IF NOT COMPTYPES(LSP@.TAGFIELDP@.IDTYPE,LSP3)THEN ERROR(111)
; NEW(LSP3,VARIANT);
WITH LSP3@ DO
BEGIN NXTVAR := LSP1; SUBVAR := LSP2; VARVAL := LVALU;
FORM := VARIANT
END;
LSP1 := LSP3; LSP2 := LSP3;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
FIELDLIST(FSYS + (.RPARENT,SEMICOLON.),LSP2);
IF DISPL > MAXSIZE THEN MAXSIZE := DISPL;
WHILE LSP3 <> NIL DO
BEGIN LSP4 := LSP3@.SUBVAR; LSP3@.SUBVAR := LSP2;
LSP3@.SIZE := DISPL;
LSP3 := LSP4
END;
IF SY = RPARENT THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + (.SEMICOLON.)) THEN
BEGIN ERROR(6); SKIP(FSYS + (.SEMICOLON.)) END
END
ELSE ERROR(4);
TEST := SY <> SEMICOLON;
IF NOT TEST THEN
BEGIN DISPL := MINSIZE;
INSYMBOL ; TEST := SY = ENDSY ; (* IGNORE EXTRA ; *)
END
UNTIL TEST;
DISPL := MAXSIZE;
LSP@.FSTVAR := LSP1;
END
ELSE FRECVAR := NIL
END (* FIELDLIST *) ;
BEGIN (* **START** TYP *)
IF NOT (SY IN TYPEBEGSYS) THEN
BEGIN ERROR(10); SKIP(FSYS + TYPEBEGSYS) END;
IF SY IN TYPEBEGSYS THEN
BEGIN
IF SY IN SIMPTYPEBEGSYS THEN SIMPLETYPE(FSYS,FSP(* ,FSIZE *))
ELSE
(* @ *) IF SY = ARROW THEN
BEGIN NEW(LSP,POINTER); FSP := LSP;
WITH LSP@ DO
BEGIN ELTYPE := NIL;
SIZE := ADDRSIZE; FORM:=POINTER
END;
INSYMBOL;
IF SY = IDENT THEN
BEGIN PRTERR := FALSE; (*NO ERROR IF SRCH NOT SUCCESSFUL*)
SEARCHID((.TYPES.),LCP); PRTERR := TRUE;
IF LCP = NIL THEN (* FORWARD REFERENCED TYPE ID *)
BEGIN NEW(LCP,TYPES);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := LSP;
NEXT := FWPTR; KLASS := TYPES
END;
FWPTR := LCP
END
ELSE
BEGIN
IF LCP@.IDTYPE <> NIL THEN
IF LCP@.IDTYPE@.FORM = FILES THEN ERROR(108)
ELSE LSP@.ELTYPE := LCP@.IDTYPE
END;
INSYMBOL;
END
ELSE ERROR(2);
END
ELSE
BEGIN
IF SY = PACKEDSY THEN
BEGIN INSYMBOL;
IF NOT (SY IN TYPEDELS) THEN
BEGIN
ERROR(10); SKIP(FSYS + TYPEDELS)
END
END;
(* STRING *) IF SY = STRINGSY THEN
BEGIN
IF STANDARD THEN WARNING(510);
INSYMBOL;
IF SY = LBRACK THEN
INSYMBOL
ELSE
ERROR(11);
CONSTANT(FSYS + (. RBRACK .), LSP2, KVALU);
IF (LSP2 = INT1PTR) OR (LSP2 = INT2PTR) THEN
BEGIN
NEW(LSP,STRINGS);
WITH LSP@ DO
BEGIN
FORM := STRINGS;
SIZE := ALIGN(KVALU.IVAL+ALIGNMENT)
END
END
ELSE
BEGIN
LSP := NIL;
IF LSP2 = INT4PTR
THEN ERROR(203)
ELSE ERROR(15)
END;
IF SY = RBRACK THEN
INSYMBOL
ELSE
ERROR(12)
END
ELSE
(* ARRAY *) IF SY = ARRAYSY THEN
BEGIN INSYMBOL;
IF SY = LBRACK THEN INSYMBOL ELSE ERROR(11);
LSP1 := NIL;
REPEAT NEW(LSP,ARRAYS);
WITH LSP@ DO
BEGIN AELTYPE := LSP1; INXTYPE := NIL;
FORM:=ARRAYS END;
LSP1 := LSP;
SIMPLETYPE(FSYS + (.COMMA,RBRACK,OFSY.),LSP2);
IF LSP2 <> NIL THEN
IF LSP2@.FORM <= SUBRANGE THEN
BEGIN
IF LSP2 = REALPTR THEN
BEGIN ERROR(109); LSP2 := NIL END
ELSE
IF LSP2 = INT4PTR THEN
BEGIN ERROR(149); LSP2 := NIL END;
LSP@.INXTYPE := LSP2
END
ELSE BEGIN ERROR(113); LSP2 := NIL END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12);
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8);
TYP(FSYS,LSP,LSIZE);
REPEAT
WITH LSP1@ DO
BEGIN LSP2 := AELTYPE; AELTYPE := LSP;
IF INXTYPE <> NIL THEN
BEGIN
GETBOUNDS (INXTYPE, LNGMIN, LNGMAX);
LMIN := MAKESHORT (LNGMIN);
LMAX := MAKESHORT (LNGMAX);
LSIZE := LSIZE * (LMAX - LMIN + 1);
SIZE := LSIZE;
END
END;
LSP := LSP1; LSP1 := LSP2
UNTIL LSP1 = NIL
END
ELSE
(* RECORD *) IF SY = RECORDSY THEN
BEGIN INSYMBOL;
OLDTOP := TOP;
IF TOP < DISPLIMIT THEN
BEGIN TOP := TOP + 1;
WITH DISPLAY(.TOP.) DO
BEGIN FNAME := NIL;
FLABEL := NIL;
OCCUR := REC
END
END
ELSE ERROR(250);
DISPL := 0;
FIELDLIST(FSYS-(.SEMICOLON.)+(.ENDSY.),LSP1);
NEW(LSP,RECORDS);
WITH LSP@ DO
BEGIN FSTFLD := DISPLAY(.TOP.).FNAME;
RECVAR := LSP1; SIZE := ALIGN (DISPL);
FORM := RECORDS ;
END;
TOP := OLDTOP;
IF SY = ENDSY THEN INSYMBOL ELSE ERROR(13)
END
ELSE
(* SET *) IF SY = SETSY THEN
BEGIN INSYMBOL;
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8);
SIMPLETYPE(FSYS,LSP1(* ,LSIZE *));
IF LSP1 <> NIL THEN
IF LSP1@.FORM > SUBRANGE THEN
BEGIN ERROR(115); LSP1 := NIL END
ELSE
IF LSP1 = REALPTR THEN ERROR(114);
NEW(LSP,POWER);
WITH LSP@ DO
BEGIN ELSET:=LSP1;
SIZE:=SETSIZE; FORM:=POWER
END;
END
ELSE
(* FILE *) IF SY = FILESY THEN
BEGIN INSYMBOL ;
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8) ;
SIMPLETYPE(FSYS,LSP1(* ,LSIZE *)) ;
IF LSP1 = NIL THEN
BEGIN
ERROR(398);
LSP := NIL;
END
ELSE IF LSP1@.FORM = FILES THEN
BEGIN
ERROR (398);
LSP := NIL
END (*THEN*)
ELSE IF LSP1 = CHARPTR THEN LSP := TEXTPTR
ELSE BEGIN NEW(LSP,FILES);
WITH LSP@ DO BEGIN
FORM := FILES;
SIZE := 2*ADDRSIZE;
FILTYPE := LSP1 END
END
END ;
FSP := LSP
END;
IF NOT (SY IN FSYS) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END
ELSE FSP := NIL;
IF FSP = NIL THEN FSIZE := 1 ELSE FSIZE := FSP@.SIZE
END (* TYP *) ;
(* -------------------------------------------------------------------------
PROCEDURE LABELDECLARATION
------------------------------------------------------------------------- *
)
PROCEDURE LABELDECLARATION;
VAR LLP: LBP; REDEF: BOOLEAN; LBNAME: LABELRNG ;
LCP: CTP;
BEGIN
REPEAT
IF (SY = INT2CONST) OR (SY = IDENT) THEN
WITH DISPLAY(.TOP.) DO
BEGIN LLP := FLABEL; REDEF := FALSE;
WHILE (LLP <> NIL) AND NOT REDEF DO
IF NOT SAMELABEL(SY, LLP) THEN
LLP := LLP@.NEXTLAB
ELSE BEGIN REDEF := TRUE; ERROR(166) END;
IF NOT REDEF THEN
BEGIN NEW(LLP);
WITH LLP@ DO BEGIN
LABNO := 0;
DEFINED := FALSE; NEXTLAB := FLABEL;
IF SY = INT2CONST
THEN BEGIN ALF := FALSE; LABVAL := VAL.IVAL END
ELSE BEGIN ALF := TRUE; LABNAME := ID;
NEW(LCP,LABELS); (* ALPHA LABEL *)
WITH LCP@ DO
BEGIN NAME := ID;
KLASS := LABELS;
NEXT := NIL;
IDTYPE := NIL;
END;
ENTERID(LCP); (* PUT IN SYMBOL TABLE *
) IF STANDARD THEN WARNING(501) END
END;
FLABEL := LLP
END;
INSYMBOL
END
ELSE ERROR(404);
IF NOT ( SY IN FSYS + (.COMMA, SEMICOLON.) ) THEN
BEGIN ERROR(6); SKIP(FSYS+(.COMMA,SEMICOLON.)) END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14)
END (* LABELDECLARATION *) ;
(* -------------------------------------------------------------------------
PROCEDURE CONSTDECLARATION
------------------------------------------------------------------------- *
)
PROCEDURE CONSTDECLARATION;
VAR LCP: CTP; LSP: STP; LVALU: VALU;
BEGIN
IF SY <> IDENT THEN
BEGIN ERROR(2); SKIP(FSYS + (.IDENT.)) END;
WHILE SY = IDENT DO
BEGIN NEW(LCP,KONST);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := NIL; NEXT := NIL; KLASS:=KONST END;
INSYMBOL;
IF (SY = RELOP) AND (OP = EQOP) THEN INSYMBOL ELSE ERROR(16);
CONSTANT(FSYS + (.SEMICOLON.),LSP,LVALU);
ENTERID(LCP);
LCP@.IDTYPE := LSP; LCP@.VALUES := LVALU;
IF LSP = REALPTR THEN
BEGIN
NEW(LCP@.VALUES.VALP);
LCP@.VALUES.VALP@.RVAL := LVALU.VALP@.RVAL;
END
ELSE IF LSP = INT4PTR THEN
BEGIN
NEW (LCP@.VALUES.VALP);
LCP@.VALUES.VALP@.LINTVAL := LVALU.VALP@.LINTVAL
END (*THEN*)
ELSE IF LSP <> NIL THEN
IF LSP@.FORM = STRINGS THEN
BEGIN
NEW(LCP@.VALUES.VALP);
LCP@.VALUES.VALP@.SLNGTH := LVALU.VALP@.SLNGTH;
NEW(LCP@.VALUES.VALP@.SVAL);
LCP@.VALUES.VALP@.SVAL@ := LVALU.VALP@.SVAL@;
END;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + (.IDENT.)) THEN
BEGIN ERROR(6); SKIP(FSYS + (.IDENT.)) END
END
ELSE ERROR(14)
END
END (* CONSTDECLARATION *) ;
(* -------------------------------------------------------------------------
PROCEDURE TYPEDECLARATION
------------------------------------------------------------------------- *
)
PROCEDURE TYPEDECLARATION;
VAR LCP,LCP1,LCP2: CTP; LSP: STP; LSIZE: ADDRRANGE;
BEGIN
IF SY <> IDENT THEN
BEGIN ERROR(2); SKIP(FSYS + (.IDENT.)) END;
WHILE SY = IDENT DO
BEGIN NEW(LCP,TYPES);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := NIL; KLASS := TYPES END;
INSYMBOL;
IF (SY = RELOP) AND (OP = EQOP) THEN INSYMBOL ELSE ERROR(16);
TYP(FSYS + (.SEMICOLON.),LSP,LSIZE);
ENTERID(LCP);
LCP@.IDTYPE := LSP;
(* HAS ANY FORWARD REFERENCE BEEN SATISFIED: *)
LCP1 := FWPTR;
WHILE LCP1 <> NIL DO
BEGIN
IF LCP1@.NAME = LCP@.NAME THEN
BEGIN LCP1@.IDTYPE@.ELTYPE := LCP@.IDTYPE;
IF LCP1 <> FWPTR THEN
LCP2@.NEXT := LCP1@.NEXT
ELSE FWPTR := LCP1@.NEXT;
END;
LCP2 := LCP1; LCP1 := LCP1@.NEXT
END;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + (.IDENT.)) THEN
BEGIN ERROR(6); SKIP(FSYS + (.IDENT.)) END
END
ELSE ERROR(14)
END;
END (* TYPEDECLARATION *) ;
(* -------------------------------------------------------------------------
PROCEDURE VARDECLARATION
------------------------------------------------------------------------- *
)
PROCEDURE VARDECLARATION;
VAR LCP,NXT,TNEXT: CTP; LSP: STP; LSIZE: ADDRRANGE; COUNT: 0..100 ;
KFILE: EXTFILEP; (* TEMP PTR INTO CHAIN OF EXTERNAL FILES *)
BEGIN NXT := NIL;
REPEAT COUNT := 0 ;
REPEAT
IF SY = IDENT THEN
BEGIN NEW(LCP,VARS); COUNT := COUNT+1 ;
WITH LCP@ DO
BEGIN NAME := ID; NEXT := NXT; KLASS := VARS;
EXTRNL := FALSE;
IDTYPE := NIL; VKIND := ACTUAL; VLEV := LEVEL
END;
ENTERID(LCP);
NXT := LCP;
INSYMBOL;
END
ELSE ERROR(2);
(*CODE FOR ORIGIN*)
IF SY = LBRACK THEN BEGIN
INSYMBOL;
IF SY <> ORIGINSY THEN ERROR(415)
ELSE BEGIN LCP@.VKIND := ORIGINED;
IF STANDARD THEN
WARNING(504) END;
LONGONLY := TRUE;
INSYMBOL;
LONGONLY := FALSE;
IF SY <> INT4CONST THEN ERROR(416)
ELSE
WITH VAL.VALP@ DO
IF (MACHINE = M6809)
AND ( (LINTVAL(.4.) <> 0)
OR (LINTVAL(.3.) <> 0))
THEN ERROR (203)
ELSE LCP@.VADDR := LINTVAL;
INSYMBOL;
IF SY <> RBRACK THEN ERROR(417);
INSYMBOL
END;
(*END OF ORIGIN CODE *)
IF NOT (SY IN FSYS + (.COMMA,COLON.) + TYPEDELS) THEN
BEGIN ERROR(6); SKIP(FSYS+(.COMMA,COLON,SEMICOLON.)+TYPEDELS) END
; TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
TYP(FSYS + (.SEMICOLON.) + TYPEDELS,LSP,LSIZE);
WHILE NXT <> NIL DO
WITH NXT@ DO
BEGIN IDTYPE := LSP;
IF VKIND <> ORIGINED THEN (*NO LOCAL ALLOC FOR ORIGIN*)
BEGIN LOCN := LOCN - LSIZE;
IF LSIZE > 1 THEN LOCN := ALIGN(LOCN);
VADDR(.1.) := LOCN END ;
IF (LOCN < MINADDR) OR (LOCN > MAXADDR) THEN
BEGIN ERROR(504) ; (*LOCAL DATA AREA TOO LARGE*)
LOCN := 0 ;
END;
(*CODE TO CHECK IF FILE WAS MENTIONED IN FILE HEADER*)
(*ALSO TO CHAIN FILE DECL'S TOGETHER FOR LATER OPENS, ETC*)
IF LSP <> NIL THEN IF LSP@.FORM = FILES THEN
BEGIN (*MARK AS DEFINED ON LIST OF EXTERNAL FILES*)
IF (LEVEL = 0) AND (FEXTFILEP <> NIL) THEN
BEGIN KFILE := FEXTFILEP;
WHILE KFILE <> NIL DO BEGIN
IF KFILE@.FILENAME = NAME THEN
BEGIN EXTRNL := TRUE;
KFILE@.DEF := TRUE
END;
KFILE := KFILE@.NEXTFILE
END
END;
TNEXT:=NEXT;
NEXT := LOCFILELIST; (*ADD TO LOCAL FILE LIST*)
LOCFILELIST := NXT;
NXT := TNEXT ;
END
ELSE NXT := NEXT
ELSE NXT := NEXT
END;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + (.IDENT.)) THEN
BEGIN ERROR(6); SKIP(FSYS + (.IDENT.)) END
END
ELSE ERROR(14)
UNTIL (SY <> IDENT) AND NOT (SY IN TYPEDELS);
END (* VARDECLARATION *) ;
(* -------------------------------------------------------------------------
PROCEDURE PROCDECLARATION
------------------------------------------------------------------------- *
)
PROCEDURE PROCDECLARATION(FSY: SYMBOL);
VAR OLDLEV: LEVRANGE; LCP,LCP1: CTP; LSP: STP;
FORW, NEWDEF: BOOLEAN; OLDTOP: DISPRANGE;
LLC: ADDRRANGE;
OLDLABEL: LABELRNG;
MARKP: @INTEGER;
(* -------------------------------------------------------------------------
PROCEDURE PARAMETERLIST
------------------------------------------------------------------------- *
)
PROCEDURE PARAMETERLIST(FSY: SETOFSYS; VAR FPAR: CTP);
VAR LCP,LCP1,LCP2,LCP3: CTP; LSP: STP; LKIND: IDKIND;
LLC,LEN : ADDRRANGE; COUNT : INTEGER;
BEGIN LCP1 := NIL; PARMLEN := 0;
IF NOT (SY IN FSY + (.LPARENT.)) THEN
BEGIN ERROR(7); SKIP(FSYS + FSY + (.LPARENT.)) END;
IF SY = LPARENT THEN
BEGIN IF FORW THEN ERROR(119);
INSYMBOL;
IF NOT (SY IN (.IDENT,VARSY,PROCSY,FUNCSY.)) THEN
BEGIN ERROR(7); SKIP(FSYS + (.IDENT,RPARENT.)) END;
WHILE SY IN (.IDENT,VARSY,PROCSY,FUNCSY.) DO
BEGIN
IF SY = PROCSY THEN
BEGIN ERROR(398);
REPEAT INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(LCP,PROC,DECLARED,FORMAL);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := NIL; NEXT := LCP1;
PFLEV := LEVEL;
(* BEWARE OF PARAMETER PROCEDURES *)
KLASS:=PROC;PFDECKIND:=DECLARED;PFKIND:=FORMAL
END;
ENTERID(LCP);
LCP1 := LCP;
PARMLEN := PARMLEN + ADDRSIZE;
INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + (.COMMA,SEMICOLON,RPARENT.)) THEN
BEGIN ERROR(7);
SKIP(FSYS+(.COMMA,SEMICOLON,RPARENT.)) END
UNTIL SY <> COMMA
END
ELSE
BEGIN
IF SY = FUNCSY THEN
BEGIN ERROR(398); LCP2 := NIL;
REPEAT INSYMBOL;
IF SY = IDENT THEN
BEGIN NEW(LCP,FUNC,DECLARED,FORMAL);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := NIL; NEXT := LCP2
; PFLEV := LEVEL (* BEWARE PARAM FUNCS *);
KLASS:=FUNC;PFDECKIND:=DECLARED;
PFKIND:=FORMAL
END;
ENTERID(LCP);
LCP2 := LCP;
PARMLEN := PARMLEN + ADDRSIZE;
INSYMBOL;
END;
IF NOT (SY IN (.COMMA,COLON.) + FSYS) THEN
BEGIN ERROR(7);
SKIP(FSYS+(.COMMA,SEMICOLON,RPARENT.))
END
UNTIL SY <> COMMA;
IF SY = COLON THEN
BEGIN INSYMBOL;
IF SY = IDENT THEN
BEGIN SEARCHID((.TYPES.),LCP);
LSP := LCP@.IDTYPE;
IF LSP <> NIL THEN
IF NOT(LSP@.FORM IN
(.SCALAR,SUBRANGE,POINTER.))
THEN BEGIN ERROR(120); LSP := NIL END;
LCP3 := LCP2;
WHILE LCP2 <> NIL DO
BEGIN LCP2@.IDTYPE := LSP; LCP := LCP2;
LCP2 := LCP2@.NEXT
END;
LCP@.NEXT := LCP1; LCP1 := LCP3;
INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + (.SEMICOLON,RPARENT.)) THEN
BEGIN ERROR(7);
SKIP(FSYS+(.SEMICOLON,RPARENT.)) END
END
ELSE ERROR(5)
END
ELSE
BEGIN
IF SY = VARSY THEN
BEGIN LKIND := FORMAL; INSYMBOL END
ELSE LKIND := ACTUAL;
LCP2 := NIL;
COUNT := 0;
REPEAT
IF SY = IDENT THEN
BEGIN NEW(LCP,VARS);
WITH LCP@ DO
BEGIN NAME:=ID; IDTYPE:=NIL; KLASS:=VARS;
VKIND := LKIND; NEXT := LCP2; VLEV := LEVEL
; END;
ENTERID(LCP);
LCP2 := LCP; COUNT := COUNT+1;
INSYMBOL;
END;
IF NOT (SY IN (.COMMA,COLON.) + FSYS) THEN
BEGIN ERROR(7);
SKIP(FSYS+(.COMMA,SEMICOLON,RPARENT.))
END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN
BEGIN INSYMBOL;
IF SY = IDENT THEN
BEGIN SEARCHID((.TYPES.),LCP); LEN := ADDRSIZE
; LSP := LCP@.IDTYPE;
IF LSP <> NIL THEN
IF (LKIND=ACTUAL) THEN BEGIN
LEN := LSP@.SIZE ;
IF LSP@.FORM = FILES
THEN ERROR(121); END;
(*IF LEN > 1 THEN PARMLEN := ALIGN(PARMLEN)
;*) (*IF COUNT > 1 THEN LEN := ALIGN(LEN);*)
LEN := ALIGN(LEN);
(*THE ABOVE IS SLIGHTLY LESS EFFICIENT
THAN ABSOLUTELY NECESSARY (BYTE SIZE
OBJECTS TAKE A WHOLE WORD ON WORD-ALIGNED
MACHINES) *)
PARMLEN := PARMLEN + COUNT * LEN;
LCP3 := LCP2 ;
LLC := PARMLEN;
WHILE LCP2 <> NIL DO
BEGIN LCP := LCP2;
WITH LCP2@ DO
BEGIN IDTYPE := LSP;
VADDR(.1.) := LLC;
LLC:=LLC - LEN;
END;
LCP2 := LCP2@.NEXT
END;
LCP@.NEXT := LCP1; LCP1 := LCP3;
INSYMBOL
END
ELSE ERROR(2);
IF NOT (SY IN FSYS + (.SEMICOLON,RPARENT.)) THEN
BEGIN ERROR(7);
SKIP(FSYS+(.SEMICOLON,RPARENT.)) END
END
ELSE ERROR(5);
END;
END;
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSYS + (.IDENT,VARSY,PROCSY,FUNCSY.)) THEN
BEGIN ERROR(7); SKIP(FSYS + (.IDENT,RPARENT.)) END
END
END (* WHILE *) ;
IF SY = RPARENT THEN
BEGIN INSYMBOL;
IF NOT (SY IN FSY + FSYS) THEN
BEGIN ERROR(6); SKIP(FSY + FSYS) END
END
ELSE ERROR(4);
LCP3 := NIL;
(* REVERSE POINTERS *)
WHILE LCP1 <> NIL DO
WITH LCP1@ DO
BEGIN LCP2 := NEXT; NEXT := LCP3;
LCP3 := LCP1; LCP1 := LCP2
END;
FPAR := LCP3
END (* IF SY = LPAREN *)
ELSE FPAR := NIL ;
END (* PARAMETERLIST *) ;
BEGIN (* **START** PROCDECLARATION *)
LLC := LOCN;
LOCN := 0;
LCP := UPRCPTR ; (* TO INITIALIZE LCP IN CASE (. *)
IF SY = IDENT THEN
BEGIN SEARCHSECTION(DISPLAY(.TOP.).FNAME,LCP);
(* DECIDE WHETHER FORW. *)
FORW := FALSE;
IF LCP <> NIL THEN
IF (LCP@.KLASS <> PROC) AND (LCP@.KLASS <> FUNC) THEN
LCP := NIL
ELSE IF LCP@.PFDECKIND <> BUILTIN THEN
BEGIN
IF LCP@.KLASS = PROC THEN
FORW:=LCP@.FORWDECL AND(FSY=PROCSY)AND(LCP@.PFKIND=ACTUAL)
ELSE
IF LCP@.KLASS = FUNC THEN
FORW:=LCP@.FORWDECL AND(FSY=FUNCSY)AND(LCP@.PFKIND=ACTUAL);
IF NOT FORW THEN ERROR(160)
END;
IF NOT FORW THEN
BEGIN
NEWDEF := LCP = NIL;
(*NEWDEF = FALSE IF REDEFINING BUILTIN PROC/FUNC*)
IF NEWDEF THEN
IF FSY = PROCSY THEN NEW(LCP,PROC,DECLARED,ACTUAL)
ELSE NEW(LCP,FUNC,DECLARED,ACTUAL);
WITH LCP@ DO
BEGIN NAME := ID ; IDTYPE := NIL;
(*EXTERN := FALSE;*) PFLEV := LEVEL;
PFDECKIND := DECLARED; PFKIND := ACTUAL;
PROCLAB := PROCLAB+1; PFNAME := PROCLAB;
IF FSY = PROCSY THEN KLASS := PROC
ELSE KLASS := FUNC
END;
IF NEWDEF THEN ENTERID(LCP)
END
ELSE BEGIN (*TAKE OFF LIST OF UNDECL'D FORWARD PROC/FUNCS*)
IF FWDLIST <> NIL THEN
IF FWDLIST@.PF = LCP THEN
FWDLIST := FWDLIST@.NEXTPF
ELSE BEGIN KFWD :=FWDLIST;
WHILE KFWD@.NEXTPF <> NIL DO
IF KFWD@.NEXTPF@.PF = LCP
THEN KFWD@.NEXTPF:=
KFWD@.NEXTPF@.NEXTPF
ELSE KFWD := KFWD@.NEXTPF;
END;
END;
INSYMBOL
END
ELSE ERROR(2);
OLDLEV := LEVEL; OLDTOP := TOP;
(* OLDLABEL := INTLABEL ; INTLABEL := 0 ; UNIQUE LABELS *)
IF LEVEL < MAXLEVEL THEN LEVEL := LEVEL + 1 ELSE ERROR(251);
IF TOP < DISPLIMIT THEN
BEGIN TOP := TOP + 1;
WITH DISPLAY(.TOP.) DO
BEGIN
IF FORW THEN FNAME := LCP@.NEXT
ELSE FNAME := NIL;
FLABEL := NIL;
OCCUR := BLCK
END
END
ELSE ERROR(250);
IF FSY = PROCSY THEN
BEGIN PARAMETERLIST((.SEMICOLON.),LCP1);
IF NOT FORW THEN LCP@.NEXT := LCP1;
END
ELSE
BEGIN PARAMETERLIST((.SEMICOLON,COLON.),LCP1);
IF NOT FORW THEN LCP@.NEXT := LCP1;
IF SY = COLON THEN
BEGIN INSYMBOL;
IF SY = IDENT THEN
BEGIN IF FORW THEN ERROR(122);
SEARCHID((.TYPES.),LCP1);
LSP := LCP1@.IDTYPE;
LCP@.IDTYPE := LSP;
IF (LSP <> NIL) AND STANDARD THEN
IF NOT (LSP@.FORM IN (.SCALAR,SUBRANGE,POINTER,POWER.)
) THEN WARNING(509);
INSYMBOL
END
ELSE BEGIN ERROR(2);
LCP@.IDTYPE := NIL;
SKIP(FSYS + (.SEMICOLON.))
END
END
ELSE
IF NOT FORW THEN ERROR(123)
END;
IF FORW THEN
PARMLEN := LCP@.PFADDR
ELSE
BEGIN
LCP1 := LCP@.NEXT;
WHILE LCP1 <> NIL DO
BEGIN
WITH LCP1@ DO
IF KLASS = VARS THEN VADDR(.1.) := PARMLEN - VADDR(.1.);
LCP1 := LCP1@.NEXT
END;
LCP@.PFADDR := PARMLEN
END;
IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14);
IF SY = FORWARDSY THEN
BEGIN
IF FORW THEN ERROR(161)
ELSE BEGIN LCP@.FORWDECL := TRUE;
(*PUT ON LIST OF FORWARD PROC/FUNCS*)
KFWD := FWDLIST;
NEW(FWDLIST);
FWDLIST@.NEXTPF := KFWD;
FWDLIST@.PF := LCP END;
INSYMBOL;
IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14);
IF NOT (SY IN FSYS+(.PERIOD.)) THEN
BEGIN ERROR(6); SKIP(FSYS+(.PERIOD.)) END
END
ELSE
BEGIN LCP@.FORWDECL := FALSE; MARK (MARKP);
REPEAT BLOCK(FSYS,SEMICOLON,LCP);
GENLI(77(* RET *),LEVEL,ALIGN(PARMLEN));
IF SY = SEMICOLON THEN
BEGIN INSYMBOL;
IF NOT (SY IN (.BEGINSY,PROCSY,FUNCSY.)) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END
ELSE IF NOT(SUBPROG AND (LEVEL=1)) THEN ERROR(14)
UNTIL SY IN (.BEGINSY,PROCSY,FUNCSY,PERIOD.);
RELEASE (MARKP); (* RELEASE LOCAL ENTRIES FROM RUNTIME HEAP *)
END;
LEVEL := OLDLEV; TOP := OLDTOP; LOCN := LLC;
(*INTLABEL := OLDLABEL ; SEE ABOVE: TO MAKE LABELS UNIQ ONLY INTRA-PROC
*) END (* PROCDECLARATION *) ;
(* -------------------------------------------------------------------------
PROCEDURE BODY
------------------------------------------------------------------------- *
)
PROCEDURE BODY(FSYS: SETOFSYS);
CONST CIXMAX = 1000;
VAR
SEGSIZE: LABELRNG;
KLOCFILELIST: CTP;
KFILE: EXTFILEP; (* TEMP PTR INTO CHAIN OF EXTERNAL FILES *)
STDFILE:BOOLEAN;
LLCP:CTP;
CSTPTR: CSP;
(* ALLOWS REFERENCING OF NONINTEGER CONSTANTS BY AN INDEX
(INSTEAD OF A POINTER), WHICH CAN BE STORED IN THE P2-FIELD
OF THE INSTRUCTION RECORD UNTIL WRITEOUT.
--> PROCEDURE LOAD, PROCEDURE WRITEOUT, NOT NEEDED IN P_COMP*)
STATUS, ENTNAME, K: INTEGER;
LCMIN, LLC1: ADDRRANGE; LCP: CTP;
LLP: LBP; PROCNAME : ALPHA ;
FUNCTION GETTYPE(OPERAND: STP): CHAR;
BEGIN (* THE FOLLOWING COME IN FREQUENCY ORDER *)
IF OPERAND = NIL THEN
BEGIN
IF ERRORCOUNT = 0 THEN ERROR(500);
GETTYPE := 'I'
END (*THEN*)
ELSE IF (OPERAND = INT2PTR)
OR ((OPERAND@.FORM = SCALAR) AND (OPERAND@.SIZE = INT2SIZE
)) THEN
GETTYPE := 'I'
ELSE IF OPERAND@.FORM = POINTER THEN
GETTYPE := 'A'
ELSE IF OPERAND = CHARPTR THEN
GETTYPE := 'C'
ELSE IF OPERAND = BOOLPTR THEN
GETTYPE := 'B'
ELSE IF (OPERAND = INT1PTR)
OR ((OPERAND@.FORM = SCALAR) AND (OPERAND@.SIZE = INT1SIZE
)) THEN
GETTYPE := 'H'
ELSE IF OPERAND@.FORM = SUBRANGE THEN
GETTYPE := GETTYPE(OPERAND@.RANGETYPE)
ELSE IF OPERAND = INT4PTR THEN
GETTYPE := 'J'
ELSE IF OPERAND@.FORM = STRINGS THEN
GETTYPE := 'S'
ELSE IF OPERAND@.FORM > STRINGS THEN
GETTYPE := 'V'
ELSE IF OPERAND@.FORM = POWER THEN
GETTYPE := 'P'
ELSE IF OPERAND = REALPTR THEN
GETTYPE := 'R'
ELSE
GETTYPE := 'I' (* DEFAULT TO INTEGER TYPE *)
END (* GETTYPE *) ;
(* -------------------------------------------------------------------------
CODE GENERATION PROCEDURES
------------------------------------------------------------------------- *
)
PROCEDURE GEN (FOP:MNRANGE);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5);
IC := IC + 1
END (*THEN*)
END; (*GEN*)
PROCEDURE GENT (FOP:MNRANGE; OPTYPE:CHAR);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, OPTYPE:3);
IC := IC + 1
END (*THEN*)
END; (*GENT*)
PROCEDURE GEN2T (FOP:MNRANGE; OPTYPE1:CHAR; OPTYPE2:CHAR);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, OPTYPE1:3, OPTYPE2:3);
IC := IC + 1
END (*THEN*)
END; (*GEN2T*)
PROCEDURE GENTI (FOP:MNRANGE; OPTYPE:CHAR; OPERAND:INTEGER);
BEGIN
IF PRCODE THEN
BEGIN
IF (FOP <> 45(*LDC*)) OR (OPTYPE <> 'C') THEN
WRITELN(PCODE, MN(.FOP.):5, OPTYPE:3, ' ', OPERAND)
ELSE BEGIN
WRITE(PCODE, MN(.FOP.):5, OPTYPE:3, ' ''', CHR(OPERAND)
); IF CHR(OPERAND)='''' THEN WRITE(PCODE,'''');
WRITELN(PCODE,'''') END;
IC := IC + 1
END (*THEN*)
END; (*GENTI*)
PROCEDURE GENTJ (FOP: MNRANGE; OPTYPE: CHAR; OPERAND: LNGINT);
BEGIN (*GENTJ*)
IF PRCODE THEN
BEGIN
WRITE (PCODE,MN(.FOP.):5,OPTYPE:3,' ');
WRITELONG (PCODE,OPERAND);
WRITELN (PCODE,' ')
END (*THEN*)
END; (*GENTJ*)
PROCEDURE GENT2I(FOP:MNRANGE; OPTYPE:CHAR; OPERAND1:INTEGER;
OPERAND2:INTEGER);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, OPTYPE:3, ' ', OPERAND1, ' ',
OPERAND2);
IC := IC + 1
END (*THEN*)
END; (*GENT2I*)
PROCEDURE GENT2J (FOP: MNRANGE; OPTYPE: CHAR;
OPERAND1,OPERAND2: LNGINT);
BEGIN (*GENT2J*)
IF PRCODE THEN
BEGIN
WRITE (PCODE,MN(.FOP.):5,OPTYPE:3,' ');
WRITELONG (PCODE,OPERAND1);
WRITE (PCODE,' ');
WRITELONG (PCODE,OPERAND2);
WRITELN (PCODE);
IC := IC + 1
END (*THEN*)
END; (*GENT2J*)
PROCEDURE GEN2TI(FOP:MNRANGE; OPTYPE1:CHAR; OPTYPE2:CHAR;
OPERAND:INTEGER);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, OPTYPE1:3, OPTYPE2:3, ' ',
OPERAND);
IC := IC + 1
END (*THEN*)
END; (*GEN2TI*)
PROCEDURE GENI (FOP:MNRANGE; OPERAND:INTEGER);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, ' ', OPERAND);
IC := IC + 1
END (*THEN*)
END; (*GENI*)
PROCEDURE GENTLI(FOP:MNRANGE; OPTYPE:CHAR; LEVEL:LEVRANGE;
OPERAND:INTEGER);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, OPTYPE:3, LEVEL:3, ' ', OPERAND)
; IC := IC + 1
END (*THEN*)
END; (*GENTLI*)
PROCEDURE GENTL2I(FOP:MNRANGE; OPTYPE:CHAR; LEVEL:LEVRANGE;
OPERAND1,OPERAND2:INTEGER);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, OPTYPE:3, LEVEL:3, ' ',
OPERAND1,OPERAND2);
IC := IC + 1
END (*THEN*)
END; (*GENTL2I*)
PROCEDURE GENTL (FOP:MNRANGE; OPTYPE:CHAR; LAB:LABELRNG);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, MN(.FOP.):5, OPTYPE:3, LAB:4);
IC := IC + 1
END (*THEN*)
END; (*GENTL*)
PROCEDURE GENENT(ENTNM:INTEGER; FOP:MNRANGE; LEVEL:LEVRANGE;
LAB:LABELRNG; NAME:ALPHA);
BEGIN
IF PRCODE THEN
BEGIN
IF ENTNM = 0 THEN WRITE(PCODE,' ')
ELSE WRITE(PCODE,'$',ENTNM:3);
WRITELN(PCODE,MN(.FOP.):5,LEVEL:3,' ',
LAB:4,' ''OPTIONS'' ''',NAME,'''');
IC := IC + 1
END (*THEN*)
END; (*GENENT*)
PROCEDURE GENTV (FOP:MNRANGE; OPTYPE:CHAR; LVP:CSP);
VAR I,J,K:INTEGER;
TCHAR:CHAR;
BEGIN
IF PRCODE THEN
BEGIN
IF OPTYPE = 'R' THEN (*OUTPUT REAL VALUE*)
WRITELN(PCODE, MN(.FOP.):5, OPTYPE:3, ' ', LVP@.RVAL
) ELSE IF OPTYPE = 'S' THEN (*OUTPUT STRING VALUE*)
WITH LVP@ DO
BEGIN WRITE(PCODE, MN(.FOP.):5, OPTYPE:3,' ''');
FOR I := 1 TO SLNGTH DO BEGIN
TCHAR:=SVAL@(.I.);
WRITE(PCODE,TCHAR);
IF TCHAR='''' THEN WRITE(PCODE,TCHAR);
END;
WRITELN(PCODE,'''')
END
ELSE IF OPTYPE = 'P' THEN (*OUTPUT SET VALUE*)
BEGIN WRITE(PCODE, MN(.FOP.):5, OPTYPE:3,' ');
FOR I := 0 TO 7 DO
BEGIN J := 0 ; K := SETRANGE-I*8 ;
FOR K := K DOWNTO K-7 DO
BEGIN J := J*2 ;
IF K IN LVP@.PVAL THEN J := J+1 ;
END ;
IF I > 0 THEN WRITE(PCODE,',') ;
WRITE(PCODE, J:4) ;
END (* FOR I := 0 TO 7 *) ;
WRITELN(PCODE)
END;
IC := IC + 1
END (*THEN*)
END; (*GENTV*)
PROCEDURE GENDEF(L1: LABELRNG; L2: ADDRRANGE ) ;
BEGIN
IF PRCODE THEN
WRITELN(PCODE,'L', L1:3,MN(.17(* DEF *).):5, L2:7);
END (* GENDEF *) ;
PROCEDURE GENKOUNT(PORK:BOOLEAN);
BEGIN (* GENKOUNT *)
IF (KOUNTERS OR (PORK AND PKOUNTERS)) AND PRCODE THEN
BEGIN
IF LABELEDKOUNT THEN
BEGIN
WRITELN(PCODE, MN(. 50 (*LSC*).):5, KOUNT);
LABELEDKOUNT := FALSE;
END
ELSE
WRITELN(PCODE, MN(. 40 (*ISC*).):5);
IC := IC + 1;
END;
KOUNT := KOUNT + 1;
PRINTKOUNT := TRUE;
END (* GENKOUNT *);
(* -------------------------------------------------------------------------
PROCEDURE LOAD
------------------------------------------------------------------------- *
)
PROCEDURE LOAD;
VAR TIPE:CHAR;
BEGIN
WITH GATTR DO
IF TYPTR <> NIL THEN
BEGIN
TIPE:=GETTYPE(TYPTR);
CASE KIND OF
CST: IF (TYPTR@.FORM = SCALAR) AND (TYPTR <> REALPTR) THEN
IF TYPTR = BOOLPTR THEN GENTI(45(*LDC*),'B',CVAL.IVA
L) ELSE
IF TIPE = 'C' THEN
GENTI(45(*LDC*),'C',CVAL.IVAL)
ELSE IF TIPE = 'I' THEN
GENTI (45(*LDC*),'I',CVAL.IVAL) (* INTEGER *)
ELSE IF TIPE = 'H' THEN
GENTI (45(*LDC*),'H',CVAL.IVAL) (* SHORT INT
*) ELSE GENTJ (45(*LDC*),'J',CVAL.VALP@.LINTVAL)
ELSE
IF TYPTR = NILPTR THEN GENTJ(45(*LDC*),'A',LONGZERO)
ELSE
BEGIN
CSTPTR := CVAL.VALP;
IF TYPTR = REALPTR THEN
GENTV(45(*LDC*),'R',CSTPTR)
ELSE IF TYPTR@.FORM = STRINGS THEN
GENTV(45(*LDC*),'S',CSTPTR)
ELSE GENTV(45(*LDC*),'P',CSTPTR)
END;
VARBL: BEGIN
CASE ACCESS OF
DRCT: IF TIPE = 'V'
THEN GENTL2I(48(*LOD*),TIPE,VLEVEL,
DPLMT,TYPTR@.SIZE)
ELSE GENTLI(48(*LOD*),TIPE,VLEVEL,DPLMT)
; INDRCT: IF TIPE = 'V'
THEN GENT2I(35(*IND*),TIPE,
IDPLMT,TYPTR@.SIZE)
ELSE GENTI (35(*IND*),TIPE,IDPLMT)
END END;
FILEPTR: BEGIN
GENI(112 (* MST *), 0 (* BUILTIN *));
IF ACCESS = DRCT THEN
BEGIN ACCESS := INDRCT;
GENLI(44(*LDA*),VLEVEL,DPLMT);
END;
GENTI(116 (*ARG*), 'A', 0);
GEN(65(*PEE*));
IF TIPE = 'V'
THEN GENT2I(35(*IND*),TIPE,0,TYPTR@.SIZE
) ELSE GENTI (35(*IND*),TIPE,0)
END;
EXPR:
END;
KIND := EXPR
END
END (* LOAD *) ;
(* -------------------------------------------------------------------------
PROCEDURE STORE
------------------------------------------------------------------------- *
)
PROCEDURE STORE(VAR FATTR: ATTR);
VAR TIPE:CHAR;
BEGIN
WITH FATTR DO
IF TYPTR <> NIL THEN
BEGIN TIPE := GETTYPE(TYPTR);
CASE ACCESS OF
DRCT: IF (TIPE = 'V') OR (TIPE = 'S')
THEN GENTL2I(96(*STR*),TIPE,VLEVEL,DPLMT,TYPTR@.SIZE)
ELSE GENTLI (96(*STR*),TIPE,VLEVEL,DPLMT);
INDRCT: IF IDPLMT <> 0 THEN ERROR(400)
ELSE IF (TIPE = 'V') OR (TIPE = 'S')
THEN GENTI(94(*STO*),TIPE,TYPTR@.SIZE)
ELSE GENT (94(*STO*),TIPE)
END END
END (* STORE *) ;
(* -------------------------------------------------------------------------
PROCEDURE LOADADDRESS
------------------------------------------------------------------------- *
)
PROCEDURE LOADADDRESS;
BEGIN
WITH GATTR DO
IF TYPTR <> NIL THEN
BEGIN
CASE KIND OF
CST: IF CHARARRAY(TYPTR) THEN
BEGIN
CSTPTR := CVAL.VALP ;
GENTV(43(*LCA*),'S',CSTPTR);
END
ELSE ERROR(400);
VARBL: CASE ACCESS OF
DRCT: GENLI(44(*LDA*),VLEVEL,DPLMT);
INDRCT: IF IDPLMT <> 0 THEN
GENTI(34(*INC*),'A',IDPLMT)
END;
FILEPTR: IF ACCESS = DRCT
THEN GENTLI(48(*LOD*),'A',VLEVEL,DPLMT)
ELSE GENTI (35(*IND*),'A',0);
EXPR: ERROR(400)
END;
KIND := VARBL; ACCESS := INDRCT; IDPLMT := 0
END
END (* LOADADDRESS *) ;
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE CHKBNDS (LHSP,RHSP,ERR) *)
(* *)
(* THIS PROCEDURE FIRST CHECKS TO MAKE SURE THAT THE TYPES *)
(* POINTED TO BY 'RHSP' AND 'LHSP' ARE ASSIGNMENT *)
(* COMPATABLE (IE. THEIR RANGES INTERSECT SOMEWHERE). IF *)
(* THEY ARE NOT, THE ERROR INDICATED BY 'ERR' IS GENERATED. *)
(* IF THEY ARE, AND DEBUGGING IS ON, A CHK INSTRUCTION IS *)
(* GENERATED TO CHECK AT RUNTIME IF THE VALUE ON THE TOP OF *)
(* THE STACK IS WITHIN THE RANGE INDICATED BY 'LHSP'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE CHKBNDS (LHSP,RHSP: STP; ERR: INTEGER);
VAR
LHSMIN,LHSMAX,
RHSMIN,RHSMAX,
LMIN,LMAX: LNGINT;
IMIN,IMAX: INTEGER;
K: CHAR;
BEGIN (*CHKBNDS*)
IF (LHSP <> NIL) AND (RHSP <> NIL) THEN
IF (LHSP <> BOOLPTR) AND (LHSP <> INT4PTR)
AND (LHSP <> REALPTR) AND (LHSP@.FORM < POINTER) THEN
BEGIN
GETBOUNDS (LHSP,LHSMIN,LHSMAX);
GETBOUNDS (RHSP,RHSMIN,RHSMAX);
IF COMPLONGS(LHSMIN,RHSMIN) = LNGGREATER
THEN LMIN := LHSMIN
ELSE LMIN := RHSMIN;
IF COMPLONGS(LHSMAX,RHSMAX) = LNGLESS
THEN LMAX := LHSMAX
ELSE LMAX := RHSMAX;
IF COMPLONGS(LMIN,LMAX) = LNGGREATER
THEN ERROR(ERR)
ELSE
IF DEBUG THEN
BEGIN (* GENERATE THE CHK INSTRUCTION *)
K := GETTYPE (RHSP);
IF K = 'J'
THEN GENT2J (6 (*CHK*),K,LMIN,LMAX)
ELSE BEGIN
IMIN := MAKESHORT(LMIN);
IMAX := MAKESHORT(LMAX);
GENT2I (6 (*CHK*),K,IMIN,IMAX)
END (*ELSE*)
END (*THEN*)
END (*THEN*)
END; (*CHKBNDS*)
(* -------------------------------------------------------------------------
PROCEDURE PUTLABEL
------------------------------------------------------------------------- *
)
PROCEDURE PUTLABEL(LABNUM: LABELRNG);
BEGIN
IF PRCODE THEN
BEGIN
WRITELN(PCODE, 'L', LABNUM:3,' LAB');
LABELEDKOUNT := TRUE;
END (*THEN*)
END (* PUTLABEL *);
(* -------------------------------------------------------------------------
PROCEDURE STATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE STATEMENT(FSYS: SETOFSYS);
VAR LCP: CTP; LLP: LBP;
FOUND, INLOOP: BOOLEAN;
TTOP: DISPRANGE ;
(* -------------------------------------------------------------------------
PROCEDURE EXPRESSION
------------------------------------------------------------------------- *
)
PROCEDURE EXPRESSION(FSYS: SETOFSYS); FORWARD;
(*$E------------------------------------------------------------------*)
(* PROCEDURE CNVRTTOLHS *)
(* *)
(* CNVRTTOLHS STANDS FOR CONVERT TO LEFT HAND SIDE. *)
(* IF THE TYPE OF THE RIGHT HAND SIDE IS NOT THE SAME AS THE LEFT *)
(* HAND SIDE THE A CONVERT INSTRUCTION IS GENERATED TO CONVERT THE *)
(* RIGHT TO THE SAME SIDE AS THE LEFT. *)
(*--------------------------------------------------------------------*)
PROCEDURE CNVRTTOLHS (LEFTSIDE: STP; VAR RIGHTSIDE: STP);
VAR
LEFTKIND,
RIGHTKIND: CHAR; (* INTERNAL TYPE OF OPERANDS *)
BEGIN
IF LEFTSIDE <> NIL THEN
IF LEFTSIDE@.FORM = SUBRANGE THEN
LEFTSIDE := LEFTSIDE@.RANGETYPE;
LEFTKIND := GETTYPE (LEFTSIDE);
RIGHTKIND := GETTYPE (RIGHTSIDE);
IF LEFTKIND <> RIGHTKIND THEN
BEGIN
GEN2T (13 (*CVT*), RIGHTKIND, LEFTKIND);
RIGHTSIDE := LEFTSIDE;
END;
END (* CNVRTTOLHS *);
(*$E------------------------------------------------------------------------
PROCEDURE SELECTOR
------------------------------------------------------------------------- *
)
PROCEDURE SELECTOR(FSYS: SETOFSYS; FCP: CTP);
VAR
LATTR: ATTR;
LCP: CTP;
LMIN,
LMAX: INTEGER;
K: CHAR;
I: INTEGER;
LNGMIN,
LNGMAX: LNGINT;
BEGIN
WITH FCP@, GATTR DO
BEGIN TYPTR := IDTYPE; KIND := VARBL;
CASE KLASS OF
TYPES: ;
KONST: ;
VARS:
IF VKIND = ACTUAL THEN
BEGIN ACCESS := DRCT; VLEVEL := VLEV;
DPLMT := VADDR(.1.)
END
ELSE (*VKIND = FORMAL OR ORIGINED*)
BEGIN
IF VKIND = ORIGINED
THEN GENTJ(45 (*LDC*), 'A', VADDR)
ELSE GENTLI(48 (*LOD*), 'A', VLEV, VADDR(.1.));
ACCESS := INDRCT; IDPLMT := 0
END;
FIELD:
WITH DISPLAY(.DISX.) DO
IF OCCUR = CREC THEN
BEGIN ACCESS := DRCT; VLEVEL := CLEV;
DPLMT := CDSPL + FLDADDR
END
ELSE
BEGIN
GENTLI(48(*LOD*),'A',LEVEL,VDSPL) ;
ACCESS := INDRCT; IDPLMT := FLDADDR
END;
PROC: ;
FUNC:
IF PFDECKIND = BUILTIN THEN ERROR(150)
ELSE
IF PFKIND = FORMAL THEN ERROR(151)
ELSE
IF (FPROCP <> FCP) THEN ERROR(177)
ELSE
BEGIN ACCESS := DRCT; VLEVEL := PFLEV + 1;
DPLMT := PFADDR;
END
END (* CASE *) ;
END (* WITH *);
IF NOT (SY IN SELECTSYS + FSYS) THEN
BEGIN ERROR(59); SKIP(SELECTSYS + FSYS) END;
WHILE SY IN SELECTSYS DO
BEGIN
(* (. *) IF SY = LBRACK THEN
BEGIN
IF GATTR.TYPTR = NIL THEN
BEGIN
ERROR(138);
INSYMBOL;
SKIP((.RBRACK.)+SELECTSYS+FSYS)
END
ELSE
BEGIN
IF GATTR.TYPTR@.FORM = ARRAYS THEN
REPEAT LATTR := GATTR;
WITH LATTR DO
IF TYPTR <> NIL THEN
IF TYPTR@.FORM <> ARRAYS THEN
BEGIN ERROR(138); TYPTR := NIL END;
LOADADDRESS;
INSYMBOL; EXPRESSION(FSYS + (.COMMA,RBRACK.));
LOAD;
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM <> SCALAR THEN ERROR(113);
IF LATTR.TYPTR <> NIL THEN
WITH LATTR.TYPTR@ DO
BEGIN
IF COMPTYPES(INXTYPE,GATTR.TYPTR) THEN
BEGIN
IF INXTYPE <> NIL THEN
BEGIN
CHKBNDS (INXTYPE, GATTR.TYPTR, 139);
K := GETTYPE (GATTR.TYPTR);
IF K <> 'I' THEN
GEN2T (13 (*CVT*), K, 'I');
GETBOUNDS (INXTYPE, LNGMIN, LNGMAX);
LMIN := MAKESHORT (LNGMIN);
IF LMIN > 0 THEN
GENTI (16 (*DEC*), 'I', LMIN)
ELSE IF LMIN < 0 THEN
GENTI (34 (*INC*), 'I', ABS (LMIN
)); END
END
ELSE ERROR(139);
WITH GATTR DO
BEGIN TYPTR := AELTYPE; KIND := VARBL;
ACCESS := INDRCT; IDPLMT := 0 ;
IF GATTR.TYPTR <> NIL THEN
BEGIN LMIN := TYPTR@.SIZE ;
GENI(41(*IXA*),LMIN)
END (* TYPTR <> NIL *) ;
END (* WITH GATTR DO *) ;
END
UNTIL SY <> COMMA
ELSE IF GATTR.TYPTR@.FORM = STRINGS THEN
BEGIN
LOADADDRESS;
INSYMBOL;
EXPRESSION(FSYS + (.RBRACK.));
LOAD;
IF GATTR.TYPTR <> NIL THEN
IF COMPTYPES(GATTR.TYPTR,INT2PTR)
THEN CNVRTTOLHS (INT2PTR,GATTR.TYPTR)
ELSE ERROR (139);
WITH GATTR DO
BEGIN
TYPTR := CHARPTR;
KIND := VARBL;
ACCESS:= INDRCT;
IDPLMT:= ALIGNMENT - 1;
END;
GENI(41(*IXA*),1);
END
ELSE
BEGIN
ERROR(138);
INSYMBOL;
SKIP((. RBRACK .)+SELECTSYS+FSYS)
END
END; (* IF GATTR.TYPTR = NIL *)
IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12)
END (* IF SY = LBRACK *)
ELSE
(* . *) IF SY = PERIOD THEN
BEGIN
WITH GATTR DO
BEGIN
IF TYPTR <> NIL THEN
IF TYPTR@.FORM <> RECORDS THEN
BEGIN ERROR(140); TYPTR := NIL END;
INSYMBOL;
IF SY = IDENT THEN
BEGIN
IF TYPTR <> NIL THEN
BEGIN SEARCHSECTION(TYPTR@.FSTFLD,LCP);
IF LCP = NIL THEN
BEGIN ERROR(152); TYPTR := NIL END
ELSE
WITH LCP@ DO
BEGIN TYPTR := IDTYPE;
CASE ACCESS OF
DRCT: DPLMT := DPLMT + FLDADDR;
INDRCT: IDPLMT := IDPLMT + FLDADDR
END
END
END;
INSYMBOL
END (* SY = IDENT *)
ELSE ERROR(2)
END (* WITH GATTR *)
END (* IF SY = PERIOD *)
ELSE
(* @ *) BEGIN
IF GATTR.TYPTR <> NIL THEN
WITH GATTR,TYPTR@ DO
IF (FORM = POINTER) THEN
BEGIN
LOAD ;
IF DEBUG THEN GENT2I (6 (*CHK*), 'A', 0, 0);
TYPTR := ELTYPE;
WITH GATTR DO
BEGIN KIND := VARBL;
ACCESS := INDRCT;
IDPLMT := 0
END
END
ELSE IF FORM = FILES THEN BEGIN
TYPTR:=FILTYPE;
GATTR.KIND := FILEPTR
END
ELSE ERROR(141);
INSYMBOL
END;
IF NOT (SY IN FSYS + SELECTSYS) THEN
BEGIN ERROR(6); SKIP(FSYS + SELECTSYS) END ;
END (* WHILE *) ;
END (* SELECTOR *) ;
(* -------------------------------------------------------------------------
PROCEDURE CALL
------------------------------------------------------------------------- *
)
PROCEDURE CALL(FSYS: SETOFSYS; FCP: CTP);
VAR LKEY: STDNAMES;
(* -------------------------------------------------------------------------
PROCEDURE VARIABLE
------------------------------------------------------------------------- *
)
PROCEDURE VARIABLE(FSYS: SETOFSYS);
VAR LCP: CTP;
BEGIN
IF SY = IDENT THEN
BEGIN SEARCHID((.VARS,FIELD.),LCP); INSYMBOL END
ELSE BEGIN ERROR(2); LCP := UVARPTR END;
SELECTOR(FSYS,LCP)
END (* VARIABLE *) ;
(* -------------------------------------------------------------------------
STANDARD PROCEDURE CALL HANDLERS
------------------------------------------------------------------------- *
)
PROCEDURE IFNOTINTEGERTHENERROR (ERR: INTEGER);
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF INTTYPE(GATTR.TYPTR) THEN
BEGIN
IF GATTR.TYPTR <> INT2PTR THEN
GEN2T(13 (*CVT*), GETTYPE(GATTR.TYPTR), 'I');
GENTI(116 (*ARG*), 'I', SYSTEM);
END
ELSE
ERROR(ERR);
END (* IFNOTINTEGERTHENERROR *);
PROCEDURE RWSETUP(DEFAULTFILE: CTP; VAR ACTUAL:CTP;
RD: BOOLEAN; VAR TEXTF: BOOLEAN; DELAY:BOOLEAN);
(* TO SET UP FILE ADDRESS PARAMETER FOR READ/WRITE *)
VAR LCP: CTP; SAVED: BOOLEAN; TEMPSY: SYMBOL;
BEGIN SAVED := TRUE ;
IF SY = IDENT THEN
BEGIN SEARCHID((.VARS,FIELD,FUNC,KONST.),LCP) ;
IF LCP@.IDTYPE <> NIL THEN
IF LCP@.IDTYPE@.FORM = FILES THEN SAVED := FALSE;
END (*SY = IDENT*) ;
IF SAVED THEN BEGIN IF DEFAULTFILE <> NIL THEN LCP := DEFAULTFILE
ELSE BEGIN IF RD
THEN ERROR(175)
ELSE ERROR(176)
; LCP := UVARPTR
END;
TEMPSY := SY; SY := COMMA
END
ELSE INSYMBOL ;
TEXTF := LCP@.IDTYPE = TEXTPTR;
IF TEXTF OR NOT DELAY THEN BEGIN
GENI(112 (*MST*),0 (*BUILTIN CALL*));
SELECTOR(FSYS+(.COMMA,RPARENT.),LCP) ;
LOADADDRESS; (*GET FILE ADR*)
GENTI(116 (*ARG*), 'A', 0);
END;
ACTUAL := LCP;
IF SAVED THEN SY := TEMPSY;
END (* RWSETUP *) ;
PROCEDURE GETPUTPAGE;
VAR MKEY: MNRANGE;
TFILE: CTP;
TEXTF,PARAMS,RD: BOOLEAN;
BEGIN
IF SY = LPARENT THEN BEGIN PARAMS := TRUE; INSYMBOL END
ELSE PARAMS := FALSE;
IF LKEY = XGET THEN BEGIN TFILE := STDINPUT(*GET*);
RD := TRUE END
ELSE BEGIN TFILE := STDOUTPUT(*PUT,PAGE*);RD := FALSE E
ND; RWSETUP(TFILE,TFILE,RD,TEXTF,FALSE); (*DEFAULT IS IN 'TFILE'*)
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM <> FILES THEN ERROR(116);
IF LKEY = XGET THEN MKEY := 31(*GET *)
ELSE IF LKEY = XPUT THEN MKEY := 68(*PUT *)
ELSE MKEY :=64(*PAGE*);
GEN(MKEY(* GET,PUT *)) ;
IF PARAMS THEN IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END (* GETPUTPAGE *) ;
PROCEDURE CHECKFORCHAR;
BEGIN
IF GATTR.TYPTR = CHARPTR THEN
BEGIN
GEN2T(13 (*CVT*), 'C', 'S');
GATTR.TYPTR := SINGLECHARSTRING;
END;
END (* CHECKFORCHAR *);
PROCEDURE RESETREWRITE;
VAR MKEY: MNRANGE;
TFILE: CTP;
TEXTF,PARAMS,RD: BOOLEAN;
BEGIN
IF SY = LPARENT THEN BEGIN PARAMS := TRUE; INSYMBOL END
ELSE PARAMS := FALSE;
IF LKEY = XRESET THEN BEGIN TFILE := STDINPUT(*RST*);
RD := TRUE END
ELSE BEGIN TFILE := STDOUTPUT(*RWT*);RD := FALSE END
; RWSETUP(TFILE,TFILE,RD,TEXTF,FALSE); (*DEFAULT IS IN 'TFILE'*)
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM <> FILES THEN ERROR(116);
IF SY = COMMA THEN BEGIN
IF STANDARD THEN WARNING(508);
LOADADDRESS; (*OF FILE DESCRIPTOR FOR 'AFI'*)
INSYMBOL;
EXPRESSION(FSYS + (.RPARENT.)); LOAD;
CHECKFORCHAR;
IF GATTR.TYPTR <> NIL THEN
IF (GATTR.TYPTR@.FORM <> STRINGS) THEN
ERROR(116)
ELSE
GENT2I(116 (*ARG*), 'S', 0, GATTR.TYPTR@.SIZE);
(*IF NOT CHARARRAY(GATTR.TYPTR) THEN ERROR(116); *)
GEN(2 (* AFI *))
END;
IF LKEY = XRESET THEN MKEY := 80(*RST*)
(*AFI LEAVES DESCRIPTOR ON STK*)
ELSE MKEY := 81(*RWT*);
GEN(MKEY (* RST,RWT *)) ;
IF PARAMS THEN IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END (* RESETREWRITE *) ;
PROCEDURE READ1;
VAR PARAMS,TEXTF: BOOLEAN;
K:CHAR; FSP:STP;
ACTUALFILE: CTP;
BEGIN
IF SY = LPARENT THEN BEGIN PARAMS := TRUE; INSYMBOL END
ELSE PARAMS := FALSE;
RWSETUP(STDINPUT,ACTUALFILE,TRUE,TEXTF,TRUE); (*DEFAULT IS 'INPUT'*
) IF PARAMS THEN
BEGIN
IF ACTUALFILE@.IDTYPE <> NIL THEN
FSP := ACTUALFILE@.IDTYPE@.FILTYPE
ELSE
FSP := NIL;
K := GETTYPE(FSP);
IF (SY = RPARENT) AND (LKEY = XREAD) THEN ERROR(116);
(*'6' IS 'READ'; IT'S REQ'D TO HAVE AT LEAST
ONE PARAM; CAREFUL IF PROC #'S CHANGE *)
IF SY = COMMA THEN INSYMBOL;
IF SY = IDENT THEN
REPEAT VARIABLE(FSYS + (.COMMA,RPARENT.));
LOADADDRESS;
IF TEXTF THEN BEGIN
GENTI(116 (*ARG*), 'A', 0);
IF GATTR.TYPTR <> NIL THEN
IF CHARARRAY(GATTR.TYPTR) THEN
BEGIN
GENTI(45(*LDC*),'I',GATTR.TYPTR@.SIZE DIV CHARSIZE);
GENTI(116 (*ARG*), 'I', 0);
GEN (114 (*RDV*));
END
ELSE
IF GATTR.TYPTR@.FORM = STRINGS THEN
BEGIN
GENTI(45(*LDC*),'I',GATTR.TYPTR@.SIZE(*STRSZ*));
GENTI(116 (*ARG*), 'I', 0);
GEN(76 (*RDS*))
END
ELSE
BEGIN
K := GETTYPE (GATTR.TYPTR);
IF K = 'J' THEN
GEN(73 (*RDJ*))
ELSE
IF K = 'H' THEN
GEN(117 (*RDH*))
ELSE
IF K = 'I' THEN
GEN(72 (*RDI*))
ELSE
IF K = 'R' THEN
GEN(75 (*RDR*))
ELSE
IF K = 'C' THEN
GEN(70 (*RDC*))
ELSE
IF K = 'B' THEN
GEN(69 (*RDB*))
ELSE ERROR(116) ;
END ;
END ELSE (*NONTEXT FILE*)
IF COMPTYPES(FSP,GATTR.TYPTR) THEN
BEGIN
GENI (112(*MST*),0);
WITH ACTUALFILE@ DO IF VKIND = ACTUAL
THEN GENLI (44 (*LDA*),VLEV,VADDR(.1.))
ELSE GENTLI(48 (*LOD*),'A',VLEV,VADDR(.1.));
GENTI(116 (*ARG*), 'A', 0);
GEN (65 (*PEE*));
IF K = 'V' THEN BEGIN
GENT2I(35 (*IND*),K,0,FSP@.SIZE);
GENTI (94 (*STO*),K,FSP@.SIZE);
END
ELSE BEGIN
GENTI(35 (*IND*),K,0);
GENT (94 (*STO*),K);
END;
GENI (112(*MST*),0);
WITH ACTUALFILE@ DO IF VKIND = ACTUAL
THEN GENLI (44 (*LDA*),VLEV,VADDR(.1.))
ELSE GENTLI(48 (*LOD*),'A',VLEV,VADDR(.1.));
GENTI(116 (*ARG*), 'A', 0);
GEN(31(*GET*));
END
ELSE ERROR(127);
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST ;
IF TEXTF THEN
IF LKEY = XREADLN THEN GEN(78(*RLN*)) ELSE GEN(111(*EIO*));
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END
ELSE IF LKEY = XREADLN THEN GEN(78 (*RLN*)) ELSE ERROR(9);
END (* READ1 *) ;
PROCEDURE WRITE1;
VAR LSP: STP; DEFAULT : BOOLEAN;
PARAMS,TEXTF: BOOLEAN;
K:CHAR; FSP:STP;
ACTUALFILE: CTP;
BEGIN
IF SY = LPARENT THEN BEGIN PARAMS := TRUE; INSYMBOL END
ELSE PARAMS := FALSE;
RWSETUP(STDOUTPUT,ACTUALFILE,FALSE,TEXTF,TRUE);
(*DEFAULT IS 'OUTPUT'*)
IF PARAMS THEN
BEGIN
IF ACTUALFILE@.IDTYPE <> NIL THEN
FSP := ACTUALFILE@.IDTYPE@.FILTYPE
ELSE
FSP := NIL;
K := GETTYPE(FSP);
TEST := FALSE ;
IF (SY = RPARENT) THEN
BEGIN TEST := TRUE ;
IF LKEY = XWRITE THEN ERROR(116) ; END ;
(*'7' IS 'WRITE'; IT'S REQ'D TO HAVE AT LEAST
ONE PARAM; CAREFUL IF PROC #'S CHANGE *)
IF SY = COMMA THEN INSYMBOL ;
IF NOT TEST THEN
REPEAT IF TEXTF THEN BEGIN
EXPRESSION(FSYS+(.COMMA,COLON,RPARENT.)) ;
LSP := GATTR.TYPTR;
IF LSP <> NIL THEN
BEGIN
K := GETTYPE(LSP);
LOAD;
IF (K = 'S') OR (K = 'V') THEN
GENT2I(116 (*ARG*), K, 0, LSP@.SIZE)
ELSE
GENTI(116 (*ARG*), K, 0);
END;
IF SY = COLON THEN
BEGIN INSYMBOL; EXPRESSION(FSYS + (.COMMA,COLON,RPARENT.));
LOAD; DEFAULT := FALSE;
IFNOTINTEGERTHENERROR (116)
END
ELSE DEFAULT := TRUE;
IF SY = COLON THEN
BEGIN INSYMBOL; EXPRESSION(FSYS + (.COMMA,RPARENT.));
IF LSP <> REALPTR THEN ERROR(124);
LOAD; ERROR(398);
IFNOTINTEGERTHENERROR (116)
END
ELSE
IF LSP = INT4PTR THEN
BEGIN
IF DEFAULT THEN
BEGIN
GENTI(45 (*LDC*),'I',12);
GENTI(116(*ARG*),'I',SYSTEM)
END; (*THEN*)
GEN(105 (*WRJ*))
END (*THEN*)
ELSE IF LSP = INT1PTR THEN
BEGIN
IF DEFAULT THEN
BEGIN
GENTI(45 (*LDC*),'I',5);
GENTI(116(*ARG*),'I',SYSTEM)
END; (*THEN*)
GEN(118 (*WRH*))
END (*THEN*)
ELSE IF LSP = INT2PTR THEN
BEGIN
IF DEFAULT THEN
BEGIN
GENTI(45 (*LDC*), 'I', 7);
GENTI(116 (*ARG*), 'I', SYSTEM);
END;
GEN(104 (*WRI*))
END
ELSE
IF LSP = REALPTR THEN
BEGIN
IF DEFAULT THEN
BEGIN
GENTI(45 (*LDC*), 'I', 14);
GENTI(116 (*ARG*), 'I', 0);
END;
GEN(107 (*WRR*))
END
ELSE
IF LSP = CHARPTR THEN
BEGIN
IF DEFAULT THEN
BEGIN
GENTI(45 (*LDC*), 'I', 1);
GENTI(116 (*ARG*), 'I', 0);
END;
GEN(102 (*WRC*))
END
ELSE
IF LSP = BOOLPTR THEN
BEGIN
IF DEFAULT THEN
BEGIN
GENTI(45 (*LDC*), 'I', 5);
GENTI(116 (*ARG*), 'I', 0);
END;
GEN(101 (*WRB*))
END
ELSE
IF LSP <> NIL THEN
BEGIN
IF LSP@.FORM = SCALAR THEN ERROR(398)
ELSE
IF CHARARRAY(LSP) THEN
BEGIN
IF DEFAULT THEN
BEGIN
GENTI(45 (*LDC*), 'I', LSP@.SIZE);
GENTI(116 (*ARG*), 'I', 0);
END;
GENTI(45(*LDC*),'I',LSP@.SIZE); (*VAR SIZE
*) GENTI(116 (*ARG*), 'I', 0);
GEN (115 (*WRV*))
END
ELSE
IF LSP@.FORM = STRINGS THEN
BEGIN
IF DEFAULT THEN
BEGIN
GENTI(45 (*LDC*), 'I', 0);
GENTI(116 (*ARG*), 'I', 0);
END;
GEN(108 (*WRS*))
END
ELSE ERROR(116)
END;
END ELSE (*NONTEXT FILE*)
BEGIN WITH ACTUALFILE@ DO IF VKIND = ACTUAL
THEN GENTLI(48 (*LOD*),'A',VLEV,VADDR(.1.))
ELSE BEGIN
GENTLI(48 (*LOD*),'A',VLEV,VADDR(.1.))
; GENTI (35 (*IND*),'A',0);
END;
EXPRESSION(FSYS+(.COMMA,COLON,RPARENT.)) ;
LSP := GATTR.TYPTR;
IF LSP <> NIL THEN LOAD;
IF NOT COMPTYPES(FSP,LSP) THEN ERROR(127);
IF K = 'V'
THEN GENTI (94 (*STO*),K,FSP@.SIZE)
ELSE GENT (94 (*STO*),K);
GENI (112(*MST*),0);
WITH ACTUALFILE@ DO IF VKIND = ACTUAL
THEN GENLI (44 (*LDA*),VLEV,VADDR(.1.))
ELSE GENTLI(48 (*LOD*),'A',VLEV,VADDR(.1.));
GENTI(116 (*ARG*), 'A', 0);
GENTI(116 (*ARG*), 'A', 0);
GEN(68(*PUT*));
END;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL;
UNTIL TEST;
IF TEXTF THEN
IF LKEY = XWRITELN THEN GEN(100 (*WLN*)) ELSE GEN(111(*EIO*));
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END (*SY = LPARENT*)
ELSE IF LKEY = XWRITELN THEN GEN(100 (*WLN*)) ELSE ERROR(9);
END (* WRITE1 *) ;
(* PROCEDURE PACK1;
VAR LSP,LSP1: STP;
BEGIN IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
ERROR(398); VARIABLE(FSYS + (.COMMA,RPARENT.));
LSP := NIL; LSP1 := NIL;
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR@ DO
IF FORM = ARRAYS THEN
BEGIN LSP := INXTYPE; LSP1 := AELTYPE END
ELSE ERROR(116);
IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
EXPRESSION(FSYS + (.COMMA,RPARENT.));
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM <> SCALAR THEN ERROR(116)
ELSE
IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN ERROR(116);
IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
VARIABLE(FSYS + (.RPARENT.));
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR@ DO
IF FORM = ARRAYS THEN
BEGIN
IF NOT COMPTYPES(AELTYPE,LSP1)
OR NOT COMPTYPES(INXTYPE,LSP) THEN
ERROR(116)
END
ELSE ERROR(116);
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END;*) (* PACK *)
(* PROCEDURE UNPACK1;
VAR LSP,LSP1: STP;
BEGIN IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
ERROR(398); VARIABLE(FSYS + (.COMMA,RPARENT.));
LSP := NIL; LSP1 := NIL;
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR@ DO
IF FORM = ARRAYS THEN
BEGIN LSP := INXTYPE; LSP1 := AELTYPE END
ELSE ERROR(116);
IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
VARIABLE(FSYS + (.COMMA,RPARENT.));
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR@ DO
IF FORM = ARRAYS THEN
BEGIN
IF NOT COMPTYPES(AELTYPE,LSP1)
OR NOT COMPTYPES(INXTYPE,LSP) THEN
ERROR(116)
END
ELSE ERROR(116);
IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
EXPRESSION(FSYS + (.RPARENT.));
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM <> SCALAR THEN ERROR(116)
ELSE
IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN ERROR(116);
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END;*) (* UNPACK *)
PROCEDURE NEWDISPOSE;
VAR LSP,LSP1: STP; VARTS: INTEGER;
LSIZE: ADDRRANGE; LVAL: VALU;
FOUND: BOOLEAN;
BEGIN IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
GENI(112 (*MST*),0 (*BUILTIN CALL*));
VARIABLE(FSYS + (.COMMA,RPARENT.)); LOADADDRESS;
LSP := NIL; VARTS := 0; LSIZE := 0;
IF GATTR.TYPTR <> NIL THEN
WITH GATTR.TYPTR@ DO
IF FORM = POINTER THEN
BEGIN
IF ELTYPE <> NIL THEN
BEGIN LSIZE := ELTYPE@.SIZE;
IF ELTYPE@.FORM = RECORDS THEN LSP := ELTYPE@.RECVAR
END
END
ELSE ERROR(116);
WHILE SY = COMMA DO
BEGIN FOUND := FALSE;
INSYMBOL;CONSTANT(FSYS + (.COMMA,RPARENT.),LSP1,LVAL);
VARTS := VARTS + 1;
(* CHECK TO INSERT HERE: IS CONSTANT IN TAGFIELDTYPE RANGE *)
IF LSP = NIL THEN ERROR(158)
ELSE
IF LSP@.FORM <> TAGFLD THEN ERROR(162)
ELSE
IF LSP@.TAGFIELDP <> NIL THEN
IF CHARARRAY(LSP1) OR (LSP1 = REALPTR) THEN ERROR(159)
ELSE
IF COMPTYPES(LSP@.TAGFIELDP@.IDTYPE,LSP1) THEN
BEGIN
LSP1 := LSP@.FSTVAR;
LSIZE := LSP@.SIZE; LSP := NIL;
WHILE NOT FOUND AND (LSP1 <> NIL) DO
WITH LSP1@ DO
IF VARVAL.IVAL = LVAL.IVAL THEN
BEGIN LSIZE := SIZE; LSP := SUBVAR;
FOUND := TRUE
END
ELSE LSP1 := NXTVAR;
END
ELSE ERROR(116);
END (* WHILE *) ;
IF LKEY = XNEW THEN GENI(60(* NEW *),LSIZE)
ELSE GENI(19(* DIS *),LSIZE);
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END (* NEW *) ;
PROCEDURE MARK1;
BEGIN IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
GENI(112 (*MST*),0 (*BUILTIN CALL*));
VARIABLE(FSYS+(.RPARENT.));
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM = POINTER THEN
BEGIN
LOADADDRESS;
GENTI(116 (*ARG*), 'A', 0);
GEN(58 (*MRK*));
END
ELSE ERROR(125);
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END(* MARK1 *);
PROCEDURE RELEASE1;
BEGIN IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
GENI(112 (*MST*),0 (*BUILTIN CALL*));
VARIABLE(FSYS+(.RPARENT.));
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM = POINTER THEN
BEGIN
LOAD;
GENTI(116 (*ARG*), 'A', 0);
GEN(79 (*RLS*));
END
ELSE ERROR(125);
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END (* RELEASE1 *);
PROCEDURE HALT1 ;
(* *THIS PROCEDURE IS TO FACILITATE COMMUNICATION WITH THE OUTSIDE
* WORLD AND PROVIDE BREAK POINTS IN THE PASCAL PROGRAM.
* 'HALT(I, R)' RETURNS THE INTEGER CONSTANT I TO THE OPERATING
* SYSTEM. THIS PARAMETER IS INTENDED TO BE USED AS A
* 'FUNCTION NUMBER' *)
BEGIN IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
GENI(112 (*MST*),0 (*BUILTIN CALL*));
EXPRESSION(FSYS+(.RPARENT,COMMA.)) ;
LOAD;
IFNOTINTEGERTHENERROR (116);
GENI(26 (*EXI*), 1) ;
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END; (* HALT1 *)
PROCEDURE ABS1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF INTTYPE(GATTR.TYPTR) OR (GATTR.TYPTR = REALPTR)
THEN GENT(0 (*AB*),GETTYPE(GATTR.TYPTR))
ELSE BEGIN ERROR(125); GATTR.TYPTR := INT4PTR END
END (* ABS *) ;
PROCEDURE SQR1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF INTTYPE(GATTR.TYPTR) OR (GATTR.TYPTR = REALPTR) THEN
GENT(92 (*SQR*), GETTYPE(GATTR.TYPTR))
ELSE
BEGIN
ERROR(125);
GATTR.TYPTR := INT4PTR;
END;
END (* SQR *);
(* PROCEDURE ROUND1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> REALPTR THEN ERROR(125);
GENT(110 RND ,'R');
GATTR.TYPTR := INT4PTR
END;*)
(* PROCEDURE TRUNC1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> REALPTR THEN ERROR(125);
GENT(97 TRC ,'R');
GATTR.TYPTR := INT4PTR
END;*) (* TRUNC *)
PROCEDURE ODD1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF (NOT INTTYPE(GATTR.TYPTR))
THEN ERROR(125)
ELSE GENT(63(* ODD *),GETTYPE(GATTR.TYPTR));
GATTR.TYPTR := BOOLPTR
END (* ODD *) ;
PROCEDURE ORD1;
VAR K:CHAR;
BEGIN
WITH GATTR DO
IF TYPTR = NIL
THEN TYPTR := INT2PTR
ELSE
IF TYPTR@.FORM <> SCALAR
THEN BEGIN
ERROR(125);
TYPTR := INT2PTR
END (*THEN*)
ELSE
IF INTTYPE(TYPTR) OR (TYPTR = REALPTR)
THEN BEGIN
ERROR(125);
TYPTR := INT2PTR
END (*THEN*)
ELSE
BEGIN
K := GETTYPE(TYPTR);
IF (K = 'C') OR (K = 'B')
THEN GEN2T(13 (*CVT*),K,'H');
CASE TYPTR@.SIZE OF
1: TYPTR := INT1PTR;
2: TYPTR := INT2PTR;
4: TYPTR := INT4PTR
END (*CASE*)
END (*ELSE*)
END (* ORD1 *) ;
PROCEDURE CHR1;
VAR K: CHAR;
BEGIN
IF GATTR.TYPTR <> NIL THEN
BEGIN
IF INTTYPE(GATTR.TYPTR)
THEN K := GETTYPE(GATTR.TYPTR)
ELSE BEGIN
ERROR(125);
K := 'I'
END; (*ELSE*)
IF DEBUG THEN
IF K = 'J'
THEN GENT2J(6 (*CHK*),K,LONGZERO,LONGORDMAXCHAR)
ELSE GENT2I(6 (*CHK*),K,0,ORDMAXCHAR);
GEN2T(13 (*CVT*),K,'C');
GATTR.TYPTR := CHARPTR
END (*THEN*)
END (* CHR *) ;
PROCEDURE PREDSUCC;
BEGIN (* ERROR(398); *) (* TRANSLATES INTO 'DEC' AND 'INC' *)
IF GATTR.TYPTR <> NIL THEN
IF (GATTR.TYPTR = REALPTR) OR (GATTR.TYPTR@.FORM <> SCALAR) THE
N ERROR(125) ;
IF LKEY = XPRED THEN GENTI(16(*DEC*),GETTYPE(GATTR.TYPTR),1)
ELSE IF LKEY = XSUCC THEN
GENTI(34(*INC*),GETTYPE(GATTR.TYPTR),1)
END (* PREDSUCC *) ;
PROCEDURE EOF1;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM <> FILES THEN ERROR(125);
GENTI(116 (*ARG*), 'A', 0);
IF LKEY = XEOF THEN GEN(23(*EOF*))
ELSE GEN(24(*EOL*));
GATTR.TYPTR := BOOLPTR
END (* EOF1 *) ;
(* PROCEDURE SINCOSEXPLOG;
VAR MKEY: MNRANGE;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> REALPTR THEN ERROR(125);
CASE LKEY OF
XSIN: MKEY := 88 SIN ;
XCOS: MKEY := 8 COS ;
XEXP: MKEY := 27 EXP ;
XSQRT: MKEY := 93 SQT ;
XLN: MKEY := 49 LOG ;
XARCTAN: MKEY := 5 ATN
END ;
GEN(MKEY) ;
END;*) (* SINCOSEXPLOG *)
PROCEDURE ERRORIFNOTSTRING;
BEGIN
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM = STRINGS THEN
GENT2I(116 (*ARG*), 'S', SYSTEM, GATTR.TYPTR@.SIZE)
ELSE
ERROR(125);
END (* ERRORIFNOTSTRING *);
PROCEDURE STRCONCAT;
BEGIN
ERRORIFNOTSTRING;
IF SY <> COMMA THEN
ERROR(20)
ELSE
WHILE SY = COMMA DO
BEGIN
INSYMBOL;
EXPRESSION(FSYS + (. RPARENT, COMMA .));
LOAD;
CHECKFORCHAR;
ERRORIFNOTSTRING;
GEN(83 (*SCON*));
END;
END (* STRCONCAT *);
PROCEDURE STRDELETEORCOPY(OPKIND: STDNAMES);
VAR
STRPTR: STP;
BEGIN
ERRORIFNOTSTRING;
STRPTR := GATTR.TYPTR;
IF SY = COMMA THEN
INSYMBOL
ELSE
ERROR(20);
EXPRESSION(FSYS + (. COMMA .));
LOAD;
IFNOTINTEGERTHENERROR (125);
IF SY = COMMA THEN
INSYMBOL
ELSE
ERROR(20);
EXPRESSION(FSYS + (. RPARENT .));
LOAD;
IFNOTINTEGERTHENERROR (125);
IF OPKIND = XDELETE THEN
GEN(85 (*SDEL*))
ELSE
GEN(84 (*SCOP*));
GATTR.TYPTR := STRPTR;
END (* STRDELETEORCOPY *);
PROCEDURE STRINSERT;
VAR
STRPTR: STP;
BEGIN
CHECKFORCHAR;
ERRORIFNOTSTRING;
IF SY = COMMA THEN
INSYMBOL
ELSE
ERROR(20);
EXPRESSION (FSYS + (.RPARENT, COMMA.));
LOAD;
ERRORIFNOTSTRING;
STRPTR := GATTR.TYPTR;
IF SY = COMMA THEN
INSYMBOL
ELSE
ERROR(20);
EXPRESSION (FSYS + (. RPARENT .));
LOAD;
IFNOTINTEGERTHENERROR (125);
GEN(89 (*SINS*));
GATTR.TYPTR := STRPTR;
END (* STRINSERT *);
PROCEDURE STRPOS;
BEGIN
ERRORIFNOTSTRING;
IF SY = COMMA THEN
INSYMBOL
ELSE
ERROR(20);
EXPRESSION (FSYS + (. RPARENT .));
LOAD;
CHECKFORCHAR;
ERRORIFNOTSTRING;
GEN(91 (*SPOS*));
GATTR.TYPTR := INT2PTR;
END (* STRPOS *);
PROCEDURE STRLENGTH;
BEGIN
ERRORIFNOTSTRING;
GEN(90 (*SLEN*));
GATTR.TYPTR := INT2PTR;
END (* STRLENGTH *);
(* -------------------------------------------------------------------------
PROCEDURE CALLNONSTANDARD
------------------------------------------------------------------------- *
)
PROCEDURE CALLNONSTANDARD;
VAR NXT,LCP: CTP; LSP: STP; LKIND: IDKIND; LB: BOOLEAN;
LLC: ADDRRANGE; K: CHAR;
BEGIN
GENI(112 (*MST*),1 (*USER CALL*));
WITH FCP@ DO
BEGIN NXT := NEXT; LKIND := PFKIND;
IF (KLASS = FUNC) AND (IDTYPE <> NIL) THEN
GENTI(4 (*AST*),GETTYPE(IDTYPE),IDTYPE@.SIZ
E); (*AST ALLOCATES SPACE ON RUNTIME STK FOR FUNCTION RESULT*)
END;
IF SY = LPARENT THEN
BEGIN LLC := LOCN;
REPEAT LB := FALSE; (*DECIDE IF PROC/FUNC MUST BE PASSED*)
IF LKIND = ACTUAL THEN
BEGIN
IF NXT = NIL THEN ERROR(126)
ELSE LB := NXT@.KLASS IN (.PROC,FUNC.)
END ELSE ERROR(398);
(*FOR FORMAL PROC/FUNC LB IS FALSE AND EXPRESSION
WILL BE CALLED, WHICH WILL ALLWAYS INTERPRET A PROC/FUNC ID
AT ITS BEGINNING AS A CALL RATHER THAN A PARAMETER PASSING.
IN THIS IMPLEMENTATION, PARAMETER PROC/FUNCS ARE THEREFORE
NOT ALLOWED TO HAVE PROC/FUNC PARAMETERS *)
INSYMBOL;
IF LB THEN (* PASS FUNCTION OR PROCEDURE *)
BEGIN ERROR(398);
IF SY <> IDENT THEN
BEGIN ERROR(2); SKIP(FSYS + (.COMMA,RPARENT.)) END
ELSE
BEGIN
IF NXT@.KLASS = PROC THEN SEARCHID((.PROC.),LCP)
ELSE
BEGIN SEARCHID((.FUNC.),LCP);
IF NOT COMPTYPES(LCP@.IDTYPE,NXT@.IDTYPE) THEN
ERROR(128)
END;
INSYMBOL;
IF NOT (SY IN FSYS + (.COMMA,RPARENT.)) THEN
BEGIN ERROR(6); SKIP(FSYS + (.COMMA,RPARENT.)) EN
D END
END (* IF LB *)
ELSE
BEGIN EXPRESSION(FSYS + (.COMMA,RPARENT.));
IF GATTR.TYPTR <> NIL THEN
IF LKIND = ACTUAL THEN
BEGIN
IF NXT <> NIL THEN
BEGIN LSP := NXT@.IDTYPE;
IF LSP <> NIL THEN
BEGIN
IF (NXT@.VKIND = ACTUAL) THEN
IF LSP@.FORM <= POWER THEN
BEGIN
LOAD;
IF COMPTYPES (LSP, GATTR.TYPTR) T
HEN CHKBNDS (LSP, GATTR.TYPTR, 142
);
IF INTTYPE (GATTR.TYPTR) THEN
CNVRTTOLHS (LSP, GATTR.TYPTR);
END
ELSE
BEGIN
LOAD; (*****LOADADDRESS;*****)
IF LSP@.FORM = STRINGS THEN
GEN2TI(13(*CVT*),'S','U',LSP@.SIZE(*STRSZ
*)) (*CONVERTS NORMALIZED STRING TO
FULL SIZE STRING FOR PARAM PASS*)
ELSE IF CHARARRAY(LSP) AND
(GATTR.TYPTR@.FORM=STRINGS) THEN
BEGIN
GEN2TI(13(*CVT*),'S','V',LSP@.SIZ
E); GATTR.TYPTR := LSP
END
END
ELSE
IF (GATTR.KIND = VARBL) OR
(GATTR.KIND = FILEPTR) THEN
BEGIN LOADADDRESS;
IF GATTR.TYPTR@.SIZE <> LSP@.SIZE THE
N ERROR(142) ;
END
ELSE ERROR(154);
IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN
ERROR(142);
WITH GATTR DO
IF (KIND = VARBL) OR (KIND = FILEPTR)
THEN
K := 'A'
ELSE
K := GETTYPE(LSP);
IF (K = 'S') OR (K = 'V') THEN
GENT2I(116 (*ARG*), K, 1, LSP@.SIZE)
ELSE
GENTI(116 (*ARG*), K, 1);
END
END
END
ELSE (* LKIND = FORMAL *)
BEGIN (* PASS FORMAL PARAM *)
END
END;
IF (LKIND = ACTUAL) AND (NXT <> NIL) THEN NXT := NXT@.NEXT
UNTIL SY <> COMMA;
LOCN := LLC;
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END (* IF LPARENT *);
IF LKIND = ACTUAL THEN
BEGIN IF NXT <> NIL THEN ERROR(126);
GENTL(11(*CUP*),'$',FCP@.PFNAME);
KOUNT := KOUNT - 1;
LABELEDKOUNT := TRUE;
GENKOUNT (FALSE);
END;
IF (FCP@.KLASS = FUNC) AND (FCP@.IDTYPE <> NIL) THEN
WITH FCP@.IDTYPE@ DO
IF (FORM = STRINGS) THEN GEN2TI(13 (*CVT*),'U','S',SIZE);
(*NORMALIZE STRING FUNCTION RESULT*
) GATTR.TYPTR := FCP@.IDTYPE ;
END (* CALLNONSTANDARD *) ;
BEGIN (* **START** CALL *)
IF FCP@.PFDECKIND = BUILTIN THEN
BEGIN
LKEY := FCP@.KEY;
IF FCP@.KLASS = PROC THEN
CASE LKEY OF
XNEW,
XDISPOSE: NEWDISPOSE;
XGET,
XPUT,
XPAGE: GETPUTPAGE;
XRESET,
XREWRITE: RESETREWRITE;
XREAD,
XREADLN: READ1;
XWRITE,
XWRITELN: WRITE1;
XPACK: (*PACK1; *)
BEGIN
ERROR (398);
SKIP (FSYS + (.RPARENT.))
END;
XUNPACK: (*UNPACK1; *)
BEGIN
ERROR (398);
SKIP (FSYS + (.RPARENT.))
END;
XRELEASE: RELEASE1;
XMARK: MARK1;
XHALT: HALT1
END
ELSE
BEGIN IF LKEY IN (.XROUND,XTRUNC,XEOF,XEOLN,XSIN,XCOS,
XEXP,XSQRT,XLN,XARCTAN,XCONCAT,XCOPY,
XDELETE,XINSERT,XPOS,XLENGTH,XPOSITION.)
THEN GENI (112 (* MST *), 0);
IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
IF LKEY IN (.XCONCAT, XCOPY, XDELETE, XINSERT, XPOS .)
THEN
EXPRESSION (FSYS + (. COMMA .))
ELSE
EXPRESSION (FSYS + (.RPARENT .));
IF (LKEY = XEOF) OR (LKEY = XEOLN) THEN
LOADADDRESS ELSE LOAD;
CASE LKEY OF
XROUND: (*ROUND1; *)
BEGIN
ERROR (398);
SKIP (FSYS + (.RPARENT.))
END;
XABS: ABS1;
XSQR: SQR1;
XTRUNC: (*TRUNC1; *)
BEGIN
ERROR (398);
SKIP (FSYS + (.RPARENT.))
END;
XODD: ODD1;
XORD: ORD1;
XCHR: CHR1;
XPRED,
XSUCC: PREDSUCC;
XCLOCK: (*CLOCK; *)
BEGIN
ERROR (398);
SKIP (FSYS + (.RPARENT.))
END;
XEOF,
XEOLN: EOF1;
XSIN,
XCOS,
XEXP,
XSQRT,
XLN,
XARCTAN: (*SINCOSEXPLOG; *)
BEGIN
ERROR (398);
SKIP (FSYS + (.RPARENT.))
END;
XCONCAT: STRCONCAT;
XCOPY,
XDELETE: STRDELETEORCOPY(LKEY);
XINSERT: STRINSERT;
XPOS: STRPOS;
XLENGTH: STRLENGTH;
XPOSITION: (*STRING FUNCTIONS*)
BEGIN
ERROR (398);
SKIP (FSYS + (.RPARENT.))
END
END (* CASE LKEY OF *) ;
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END;
END (* STANDARD PROCEDURES AND FUNCTIONS *)
ELSE CALLNONSTANDARD
END (* CALL *) ;
PROCEDURE CONVERTTOLIKEINTEGERS (VAR LEFTSIDE, RIGHTSIDE: STP);
VAR
LEFTKIND,
RIGHTKIND,
RESULTKIND: CHAR;
RESULTTYPE: STP;
FUNCTION MAX (ARG1, ARG2: CHAR): CHAR;
BEGIN (*MAX*)
IF ARG1 > ARG2 THEN
MAX := ARG1
ELSE
MAX := ARG2;
END (*MAX*);
BEGIN (* CONVERTTOLIKEINTEGERS *)
LEFTKIND := GETTYPE (LEFTSIDE);
RIGHTKIND := GETTYPE (RIGHTSIDE);
RESULTKIND := MAX (ARITHMETICSIZE, MAX (LEFTKIND, RIGHTKIND
));
IF RESULTKIND = 'H' THEN
RESULTTYPE := INT1PTR
ELSE IF RESULTKIND = 'I' THEN
RESULTTYPE := INT2PTR
ELSE
RESULTTYPE := INT4PTR;
IF LEFTKIND < RESULTKIND THEN
BEGIN
GEN2T (14 (*CVB*), LEFTKIND, RESULTKIND);
LEFTSIDE := RESULTTYPE;
END;
IF RIGHTKIND < RESULTKIND THEN
BEGIN
GEN2T (13 (*CVT*), RIGHTKIND, RESULTKIND);
RIGHTSIDE := RESULTTYPE;
END;
END (* CONVERTTOLIKEINTEGERS *);
PROCEDURE ILLEGALOPERANDS;
BEGIN (* ILLEGALOPERANDS *)
ERROR (134);
GATTR.TYPTR := NIL;
END (* ILLEGALOPERANDS *);
FUNCTION COMPATABLESETS (TYP1, TYP2: STP): BOOLEAN;
BEGIN (* COMPATABLESETS *)
COMPATABLESETS := FALSE;
IF TYP1 <> NIL THEN
COMPATABLESETS := (TYP1@.FORM = POWER)
AND COMPTYPES (TYP1, TYP2);
END (* COMPATABLESETS *);
(*$E------------------------------------------------------------------*)
(* *)
(* PROCEDURE CONSTFACTOR (TYP,VAL) *)
(* *)
(* THIS PROCEDURE HANDLES A FACTOR WHICH IS A CONSTANT. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE CONSTFACTOR (TYP: STP; VAL: VALU);
BEGIN (*CONSTFACTOR*)
WITH GATTR DO
BEGIN
KIND := CST;
IF INTTYPE(TYP) AND (ARITHMETICSIZE > GETTYPE(TYP))
THEN
IF ARITHMETICSIZE = 'J'
THEN
BEGIN (*CONVERT UP TO A LONG INTEGER*)
NEW (CVAL.VALP,LINT);
MAKELONG (VAL.IVAL,CVAL.VALP@.LINTVAL);
TYPTR := INT4PTR
END (*THEN*)
ELSE
BEGIN
TYPTR := INT2PTR;
CVAL.IVAL := VAL.IVAL
END (*ELSE*)
ELSE
BEGIN
TYPTR := TYP;
CVAL := VAL
END (*ELSE*)
END (*WITH*)
END; (*CONSTFACTOR*)
PROCEDURE TERM(FSYS: SETOFSYS);
VAR
LATTR: ATTR;
LOP: OPERATOR;
INTEGERS: BOOLEAN;
PROCEDURE FACTOR(FSYS: SETOFSYS);
VAR LCP: CTP; VARPART: BOOLEAN;
C : CHAR;
CSTPART: SETCONST; LSP: STP; I: 0..64;
RNGTYPE: STP;
CSTVAL,CSTVAL2: INTEGER;
RANGED,CONSTEL: BOOLEAN;
BEGIN (* **START** FACTOR *)
IF NOT (SY IN FACBEGSYS) THEN
BEGIN ERROR(58); SKIP(FSYS + FACBEGSYS);
GATTR.TYPTR := NIL
END;
WHILE SY IN FACBEGSYS DO
BEGIN
CASE SY OF
(* ID *) IDENT:
BEGIN SEARCHID((.KONST,VARS,FIELD,FUNC.),LCP);
INSYMBOL;
IF LCP@.KLASS = FUNC THEN
BEGIN CALL(FSYS,LCP);
WITH GATTR DO
BEGIN KIND := EXPR;
IF TYPTR <> NIL THEN
IF TYPTR@.FORM=SUBRANGE THEN
TYPTR := TYPTR@.RANGETYPE
END
END
ELSE
IF LCP@.KLASS = KONST THEN
WITH LCP@ DO
CONSTFACTOR (IDTYPE,VALUES)
ELSE
BEGIN SELECTOR(FSYS,LCP);
IF GATTR.TYPTR<>NIL THEN
(* ELIM.SUBR.TYPES TO SIMPLIFY LATER TESTS *)
WITH GATTR,TYPTR@ DO
IF FORM = SUBRANGE THEN
TYPTR := RANGETYPE
END
END;
(* CST *) INT1CONST:
BEGIN
CONSTFACTOR (INT1PTR,VAL);
INSYMBOL
END; (*INT1CONST*)
INT2CONST:
BEGIN
CONSTFACTOR (INT2PTR,VAL);
INSYMBOL
END; (*INT2CONST*)
INT4CONST:
BEGIN
CONSTFACTOR (INT4PTR,VAL);
INSYMBOL
END; (*INT4CONST*)
REALCONST:
BEGIN
WITH GATTR DO
BEGIN TYPTR := REALPTR; KIND := CST;
(* CVAL := VAL ; *) CVAL.VALP := VAL.VALP ;
END;
INSYMBOL
END;
(* STRG *) STRINGCONST:
BEGIN
WITH GATTR DO
BEGIN
IF LNGTH = 1 THEN TYPTR := CHARPTR
ELSE
BEGIN NEW(LSP,STRINGS);
WITH LSP@ DO
BEGIN FORM:=STRINGS;
SIZE := LNGTH+ALIGNMENT
END;
TYPTR := LSP
END;
KIND := CST ; CVAL := VAL ;
END;
INSYMBOL
END;
(* ( *) LPARENT:
BEGIN INSYMBOL; EXPRESSION(FSYS + (.RPARENT.));
IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
END;
(* NOT *) NOTSY:
BEGIN INSYMBOL; FACTOR(FSYS);
LOAD; GEN(62(* NOT *));
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> BOOLPTR THEN
BEGIN ERROR(135); GATTR.TYPTR := NIL END;
END;
(* (. *) LBRACK:
BEGIN INSYMBOL; CSTPART := (. .); VARPART := FALSE;
CONSTEL := FALSE;
RANGED := FALSE;
NEW(LSP,POWER);
WITH LSP@ DO
BEGIN ELSET:=NIL;SIZE:=SETSIZE;FORM:=POWER END;
IF SY = RBRACK THEN
BEGIN
WITH GATTR DO
BEGIN TYPTR := LSP; KIND := CST END;
INSYMBOL
END
ELSE
BEGIN
REPEAT
(*CF <--------------------- *)
EXPRESSION(FSYS + (. COMMA, RANGE, RBRACK .));
WITH GATTR DO
BEGIN
IF TYPTR <> NIL THEN
IF TYPTR@.FORM <> SCALAR THEN
BEGIN ERROR(136); TYPTR := NIL END
ELSE
IF COMPTYPES(LSP@.ELSET,TYPTR) THEN
BEGIN
IF KIND = CST THEN
BEGIN
IF COMPTYPES(TYPTR,CHARPTR) THEN
CSTVAL := ASCII(. CHR(CVAL.IVAL) .) - 32
ELSE
CSTVAL := CVAL.IVAL;
IF ((CSTVAL < 0) OR (CSTVAL > SETRANGE)) THEN
ERROR(304)
ELSE
IF RANGED THEN
IF TYPTR <> RNGTYPE THEN
ERROR(137)
ELSE
IF NOT CONSTEL THEN
CSTPART := CSTPART + (. CSTVAL .)
ELSE
IF CSTVAL < CSTVAL2 THEN
CSTPART := CSTPART - (. CSTVAL2 .)
ELSE
FOR I := CSTVAL2 + 1 TO CSTVAL DO
CSTPART := CSTPART + (. I .)
ELSE
CSTPART := CSTPART + (. CSTVAL .);
CONSTEL := TRUE;
IF SY = RANGE THEN (* RANGE GIVEN *)
BEGIN
RNGTYPE := TYPTR;
CSTVAL2 := CSTVAL
END
END
ELSE
BEGIN
LOAD;
IF RANGED AND CONSTEL THEN ERROR(398);
IF NOT COMPTYPES(TYPTR,INT2PTR) THEN
BEGIN
C := GETTYPE(TYPTR);
IF C <> 'I' THEN
BEGIN
GEN2T(13 (*CVT*),C,'I');
IF C = 'C' THEN GENTI(16(*DEC*), 'I', 32)
END
END (*THEN*)
ELSE CNVRTTOLHS (INT2PTR,TYPTR);
IF DEBUG THEN GENT2I(6 (*CHK*),'I',0,SETRANGE);
GEN(87(*SGS*));
IF VARPART THEN GEN(99(*UNI*))
ELSE VARPART := TRUE;
CONSTEL := FALSE
END;
LSP@.ELSET := TYPTR;
TYPTR := LSP
END
ELSE
ERROR(137);
RANGED := ((SY = RANGE) AND (NOT RANGED));
IF (RANGED AND (NOT CONSTEL)) THEN ERROR(398);
TEST := ((SY <> COMMA) AND (NOT RANGED));
IF NOT TEST THEN INSYMBOL
END (* WITH GATTR DO *)
(*CF ---------------------> *)
UNTIL TEST;
IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12)
END;
CNSTVALPTR@.PVAL := CSTPART ;
IF VARPART THEN
BEGIN
IF CSTPART <> (. .) THEN
BEGIN
(* NEW(LVP,PSET); LVP@.PVAL := CSTPART;*)
CSTPTR := (* LVP *) CNSTVALPTR ;
GENTV(45(* LDC *),'P',CSTPTR);
GEN(99(* UNI *)); GATTR.KIND := EXPR
END
END
ELSE
BEGIN (* NEW(LVP,PSET); LVP@.PVAL := CSTPART; *)
(* LVP@.CCLASS := PSET; *)
GATTR.CVAL.VALP := (* LVP *) CNSTVALPTR ;
END
END
END (* CASE *) ;
IF NOT (SY IN FSYS) THEN
BEGIN ERROR(6); SKIP(FSYS + FACBEGSYS) END
END (* WHILE *)
END (* FACTOR *) ;
BEGIN (* **START** TERM *)
FACTOR(FSYS + (.MULOP.));
WHILE SY = MULOP DO
BEGIN LOAD; LATTR := GATTR; LOP := OP;
INSYMBOL; FACTOR(FSYS + (.MULOP.)); LOAD;
IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
BEGIN
INTEGERS := INTTYPE (LATTR.TYPTR)
AND INTTYPE (GATTR.TYPTR);
IF INTEGERS THEN
CONVERTTOLIKEINTEGERS (LATTR.TYPTR, GATTR.TYPTR);
CASE LOP OF
MUL:
BEGIN
IF INTEGERS THEN
GENT (57 (*MP*), GETTYPE (GATTR.TYPTR))
ELSE IF COMPATABLESETS (LATTR.TYPTR,
GATTR.TYPTR)
THEN
GEN (38 (*INT*))
ELSE
ILLEGALOPERANDS;
END (* MUL *);
RDIV:
BEGIN
ERROR (398);
GATTR.TYPTR := NIL;
END (*RDIV*);
IDIV:
BEGIN
IF INTEGERS THEN
GENT (20 (*DV*), GETTYPE (GATTR.TYPTR))
ELSE
ILLEGALOPERANDS;
END (*IDIV*);
IMOD:
BEGIN
IF INTEGERS THEN
GENT (54 (*MOD*), GETTYPE (GATTR.TYPTR))
ELSE
ILLEGALOPERANDS;
END (*IMOD*);
ANDOP:
BEGIN
IF (LATTR.TYPTR = BOOLPTR)
AND (GATTR.TYPTR = BOOLPTR)
THEN
GEN (3 (*AND*))
ELSE
ILLEGALOPERANDS;
END (*ANDOP*);
END (* CASE LOP OF *);
END (* IF (LATTR.TYPTR <> NIL) ... *)
ELSE
GATTR.TYPTR := NIL
END (* WHILE *)
END (* TERM *) ;
(* -------------------------------------------------------------------------
PROCEDURE EXPRESSION
------------------------------------------------------------------------- *
)
PROCEDURE EXPRESSION;
VAR LATTR: ATTR; KOP: MNRANGE;
C : CHAR;
LOP: OPERATOR; TYPIND: CHAR; LSIZE: ADDRRANGE;
PROCEDURE SIMPLEEXPRESSION(FSYS: SETOFSYS);
VAR
LATTR: ATTR;
LOP: OPERATOR;
SIGNED: BOOLEAN;
INTEGERS: BOOLEAN;
BEGIN (* SIMPLEEXPRESSION *)
SIGNED := FALSE;
IF (SY = ADDOP) AND ((OP = PLUS) OR (OP = MINUS)) THEN
BEGIN
SIGNED := OP = MINUS;
INSYMBOL;
END;
TERM (FSYS + (. ADDOP .));
IF SIGNED THEN
BEGIN
LOAD;
IF INTTYPE (GATTR.TYPTR) THEN
GENT (61 (*NG*), GETTYPE (GATTR.TYPTR))
ELSE
ILLEGALOPERANDS;
END;
WHILE SY = ADDOP DO
BEGIN
LOAD;
LATTR := GATTR;
LOP := OP;
INSYMBOL;
TERM (FSYS + (. ADDOP .));
LOAD;
IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
BEGIN
INTEGERS := INTTYPE (LATTR.TYPTR)
AND INTTYPE (GATTR.TYPTR);
IF INTEGERS THEN
CONVERTTOLIKEINTEGERS (LATTR.TYPTR, GATTR.TYPTR);
CASE LOP OF
PLUS:
BEGIN
IF INTEGERS THEN
GENT (1 (*AD*), GETTYPE (GATTR.TYPTR))
ELSE IF COMPATABLESETS (LATTR.TYPTR,
GATTR.TYPTR)
THEN
GEN (99 (*UNI*))
ELSE
ILLEGALOPERANDS;
END (* PLUS *);
MINUS:
BEGIN
IF INTEGERS THEN
GENT (82 (*SB*), GETTYPE (GATTR.TYPTR))
ELSE IF COMPATABLESETS (LATTR.TYPTR,
GATTR.TYPTR)
THEN
GEN (18 (*DIF*))
ELSE
ILLEGALOPERANDS;
END (* MINUS *);
OROP:
BEGIN
IF (LATTR.TYPTR = BOOLPTR)
AND (GATTR.TYPTR = BOOLPTR)
THEN
GEN (39 (*IOR*))
ELSE
ILLEGALOPERANDS;
END (*OROP*);
END (*CASE LOP OF*);
END (* IF (LATTR.TYPTR <> NIL) ... *)
ELSE
GATTR.TYPTR := NIL;
END (* WHILE SY = ADDOP *);
END (* SIMPLEEXPRESSION *) ;
BEGIN (* **START** EXPRESSION *)
SIMPLEEXPRESSION(FSYS + (.RELOP.));
IF SY = RELOP THEN
BEGIN
IF GATTR.TYPTR <> NIL THEN
LOAD; (*******)
(******IF GATTR.TYPTR@.FORM <= POWER THEN LOAD
ELSE LOADADDRESS; ******)
LATTR := GATTR; LOP := OP;
IF LOP = INOP THEN
BEGIN
IF NOT COMPTYPES(GATTR.TYPTR,INT2PTR) THEN
BEGIN C := GETTYPE(LATTR.TYPTR);
IF C <> 'I' THEN GEN2T(13 (*CVT*), C, 'I');
IF C = 'C' THEN GENTI(16(*DEC*), 'I', 32)
END (*THEN*)
ELSE CNVRTTOLHS (INT2PTR,GATTR.TYPTR);
IF DEBUG THEN GENT2I(6(* CHK *),'I',0,SETRANGE) ;
END ;
INSYMBOL; SIMPLEEXPRESSION(FSYS);
IF GATTR.TYPTR <> NIL THEN
LOAD; (*******)
(****** IF GATTR.TYPTR@.FORM <= POWER THEN LOAD
ELSE LOADADDRESS; ******)
IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
(* IN *) IF LOP = INOP THEN
IF GATTR.TYPTR@.FORM = POWER THEN
BEGIN
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR@.ELSET) THEN
GEN(36(* INN *))
ELSE BEGIN ERROR(129); GATTR.TYPTR := NIL END
END
ELSE BEGIN ERROR(130); GATTR.TYPTR := NIL END
ELSE
BEGIN
IF LATTR.TYPTR <> GATTR.TYPTR THEN
IF INTTYPE (LATTR.TYPTR) AND INTTYPE (GATTR.TYPTR) THE
N CONVERTTOLIKEINTEGERS (LATTR.TYPTR, GATTR.TYPTR)
ELSE IF CHARARRAY(LATTR.TYPTR) AND
(GATTR.TYPTR@.FORM = STRINGS) THEN
BEGIN GEN2TI(13(* CVT *),'S','V',LATTR.TYPTR@.SIZ
E); GATTR.TYPTR := LATTR.TYPTR
END
ELSE IF CHARARRAY(GATTR.TYPTR) AND
(LATTR.TYPTR@.FORM = STRINGS) THEN
BEGIN GEN2TI(14(* CVB *),'S','V',GATTR.TYPTR@.SIZ
E); LATTR.TYPTR := GATTR.TYPTR
END;
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
BEGIN LSIZE := LATTR.TYPTR@.SIZE;
CASE LATTR.TYPTR@.FORM OF
SCALAR:
TYPIND := GETTYPE (LATTR.TYPTR);
POINTER:
BEGIN
IF LOP IN (.LTOP,LEOP,GTOP,GEOP.)
THEN ERROR(131);
TYPIND := 'A'
END;
POWER:
BEGIN IF LOP IN (.LTOP,GTOP.) THEN ERROR(132);
TYPIND := 'P'
END;
STRINGS:
TYPIND := 'S';
ARRAYS:
BEGIN
IF NOT CHARARRAY(LATTR.TYPTR)
AND(LOP IN(.LTOP,LEOP,GTOP,GEOP.))
THEN ERROR(131);
TYPIND := 'V'
END;
RECORDS:
BEGIN
IF LOP IN (.LTOP,LEOP,GTOP,GEOP.)
THEN ERROR(131);
TYPIND := 'V'
END;
FILES:
BEGIN ERROR(133); TYPIND := 'F' END;
SUBRANGE: ;
TAGFLD: ;
VARIANT:
END;
CASE LOP OF
(* < *) LTOP: KOP := 47(* LES *);
(* <= *) LEOP: KOP := 46(* LEQ *);
(* > *) GTOP: KOP := 32(* GRT *);
(* >= *) GEOP: KOP := 30(* GEQ *);
(* <> *) NEOP: KOP := 59(* NEQ *);
(* = *) EQOP: KOP := 25(* EQU *)
END;
IF (TYPIND = 'V') OR (TYPIND = 'S')
THEN GENTI(KOP, TYPIND,LSIZE)
ELSE GENT (KOP, TYPIND)
END
ELSE ERROR(129)
END;
GATTR.TYPTR := BOOLPTR; GATTR.KIND := EXPR
END (* SY = RELOP *)
END (* EXPRESSION *) ;
(* -------------------------------------------------------------------------
PROCEDURE ASSIGNMENT
------------------------------------------------------------------------- *
)
PROCEDURE ASSIGNMENT(FCP: CTP);
VAR LATTR: ATTR;
BEGIN
SELECTOR(FSYS+(.BECOMES.), FCP) ;
IF SY = BECOMES THEN
BEGIN
WITH GATTR DO
IF TYPTR <> NIL THEN
IF (ACCESS<>DRCT) OR (TYPTR@.FORM>STRINGS)
OR (KIND=FILEPTR) THEN
BEGIN
LOADADDRESS ;
END ;
LATTR := GATTR;
INSYMBOL; EXPRESSION(FSYS);
IF GATTR.TYPTR <> NIL THEN
IF (GATTR.TYPTR@.FORM <= STRINGS)
OR (GATTR.KIND <> VARBL) (*******)
THEN LOAD
ELSE LOADADDRESS;
IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
BEGIN
(* IF COMPTYPES(REALPTR,LATTR.TYPTR)AND(GATTR.TYPTR=INT2PTR)TH
EN BEGIN GEN2T(13( CVT ),'I','R');
GATTR.TYPTR := REALPTR
END
ELSE *) IF (GATTR.TYPTR@.FORM=STRINGS) AND CHARARRAY(LATTR.TYP
TR) THEN BEGIN GEN2TI(13(* CVT *),'S','V',LATTR.TYPTR@.SIZE);
GATTR.TYPTR := LATTR.TYPTR
END
ELSE IF (LATTR.TYPTR@.FORM = STRINGS)
AND (GATTR.TYPTR = CHARPTR)
THEN
BEGIN
GEN2T(13 (*CVT*), 'C', 'S');
GATTR.TYPTR := LATTR.TYPTR
END;
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
BEGIN
CHKBNDS (LATTR.TYPTR, GATTR.TYPTR, 129);
IF INTTYPE (GATTR.TYPTR) THEN
CNVRTTOLHS (LATTR.TYPTR, GATTR.TYPTR);
CASE LATTR.TYPTR@.FORM OF
SCALAR,
SUBRANGE,
POINTER,
POWER,
STRINGS: STORE(LATTR);
ARRAYS,
RECORDS: BEGIN IF GATTR.KIND = VARBL (*******)
THEN GENI (55(*MOV*),LATTR.TYPTR@.SIZE)
ELSE GENTI(94(*STO*),'V',LATTR.TYPTR@.SIZE
); END ;
FILES: ERROR(146);
TAGFLD: ;
VARIANT:
END (* CASE LATTR... *)
END
ELSE ERROR(129)
END
END (* SY = BECOMES *)
ELSE ERROR(51)
END (* ASSIGNMENT *) ;
(* -------------------------------------------------------------------------
PROCEDURE GOTOSTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE GOTOSTATEMENT;
VAR LLP: LBP; FOUND: BOOLEAN; TTOP,TTOP1: DISPRANGE;
BEGIN
IF (SY = INT2CONST) OR (SY = IDENT) THEN
BEGIN (* ALPHA LABELS ALLOWED *)
FOUND := FALSE; TTOP := TOP;
WHILE DISPLAY(.TTOP.).OCCUR <> BLCK DO TTOP := TTOP - 1;
TTOP1 := TTOP;
REPEAT
LLP := DISPLAY(.TTOP.).FLABEL;
WHILE (LLP <> NIL) AND NOT FOUND DO
WITH LLP@ DO
IF SAMELABEL(SY, LLP) THEN
BEGIN FOUND := TRUE;
IF TTOP = TTOP1 THEN
BEGIN
IF LABNO = 0 THEN
GENLABEL(LABNO);
GENTL(98 (*UJP*), 'L', LABNO);
END
ELSE (* GOTO LEADS OUT OF PROCEDURE *) ERROR(398)
END
ELSE LLP := NEXTLAB;
IF TTOP > 0 THEN TTOP := TTOP - 1
UNTIL FOUND OR (TTOP <= 0);
IF NOT FOUND THEN ERROR(167);
INSYMBOL
END
ELSE ERROR(404)
END (* GOTOSTATEMENT *) ;
(* -------------------------------------------------------------------------
PROCEDURE COMPOUNDSTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE COMPOUNDSTATEMENT;
BEGIN
REPEAT
REPEAT STATEMENT(FSYS + (.SEMICOLON,ENDSY.))
UNTIL NOT (SY IN STATBEGSYS);
TEST := SY <> SEMICOLON;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = ENDSY THEN
BEGIN
BLEV := UPRED(BLEV);
EBLOCK := TRUE;
INSYMBOL
END
ELSE
ERROR(13)
END (* COMPOUNDSTATEMENET *) ;
(* -------------------------------------------------------------------------
PROCEDURE IFSTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE IFSTATEMENT;
VAR LCIX1,LCIX2: LABELRNG;
BEGIN EXPRESSION(FSYS + (.THENSY.));
GENLABEL(LCIX1);
LOAD;
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> BOOLPTR THEN ERROR(144);
GENTL(29(* FJP *),'L',LCIX1);
IF SY = THENSY THEN INSYMBOL ELSE ERROR(52);
STATEMENT(FSYS + (.ELSESY.));
IF SY = ELSESY THEN
BEGIN GENLABEL(LCIX2); GENTL(98(* UJP *),'L',LCIX2);
PUTLABEL(LCIX1);
INSYMBOL; STATEMENT(FSYS);
PUTLABEL(LCIX2)
END
ELSE PUTLABEL(LCIX1)
END (* IFSTATEMENT *) ;
(* -------------------------------------------------------------------------
PROCEDURE CASESTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE CASESTATEMENT;
(* CHANGED TO ACCEPT OTHERWISE CLAUSE *
) (* CODE GEN'D IS: *
) (* LOAD CASE INDEX VALUE *
) (* XJP LBND *
) (* UJP LOTHERWZ *
) (* LCIX1A: <CODE FOR FIRST ALT> *
) (* UJP LFINISH *
) (* LCIX1B: <CODE FOR NEXT ALT> *
) (* UJP LFINISH *
) (* . *
) (* . *
) (* . *
) (* LCIX1I: <CODE FOR LAST ALT> *
) (* UJP LFINISH *
) (* LOTHERWZ:<CODE FOR OTHERWISE> *
) (* UJP LFINISH *
) (* LBND: DEF 'LEAST ALTERNATE VAL' *
) (* UBND: DEF 'BIG ALTERNATE VAL' *
) (* LCIX: VJP LOTHERWZ *
) (* VJP LCIX1I *
) (* . *
) (* . *
) (* . *
) (* LFINISH: . . . *
) (*(WHERE VJP IS UJP WITHOUT SHORT DISP)*
)
TYPE CIP = @CASEINFO;
CASEINFO = PACKED
RECORD NEXT: CIP;
CSSTART: LABELRNG;
CSLAB: INTEGER
END;
VAR LSP,LSP1: STP; FSTPTR,LPT1,LPT2,LPT3: CIP; LVAL: VALU;
LMIN, LMAX: ADDRRANGE ;
LOTHERWZ, LFINISH, LCIX, LCIX1, UBND, LBND: LABELRNG ;
C: CHAR;
OTHERWZ, FOUND: BOOLEAN;
BEGIN EXPRESSION(FSYS + (.OFSY,COMMA,COLON.));
LOAD ;
LSP := GATTR.TYPTR;
IF LSP <> NIL THEN
IF (LSP@.FORM <> SCALAR) OR (LSP = REALPTR) THEN
BEGIN ERROR(144); LSP := NIL END
ELSE IF COMPTYPES(LSP,INT2PTR) THEN
CNVRTTOLHS (INT2PTR, LSP)
ELSE
BEGIN
C := GETTYPE (LSP);
IF C <> 'I' THEN GEN2T (13 (*CVT*), C, 'I');
END;
IF SY = OFSY THEN INSYMBOL ELSE ERROR(8);
FSTPTR := NIL ; GENLABEL(LBND) ; GENLABEL(UBND) ;
GENLABEL(LCIX) ; GENLABEL(LOTHERWZ); GENLABEL(LFINISH);
(* WE MUST HAVE: LCIX = UBND+1 = LBND+2 FOR THE 'XJP' TO WORK *)
GENTL(109(* XJP *),'L', LBND) ;
GENTL(98 (* UJP *),'L', LOTHERWZ) ;
(*'XJP' WILL FALL THRU TO 'UJP' IF EXPR NOT IN RANGE OF ALTS*)
OTHERWZ := FALSE;
REPEAT
LPT3 := NIL; GENLABEL(LCIX1);
IF NOT(SY IN (.SEMICOLON,ENDSY.)) THEN
BEGIN
IF SY <> OTHERWZSY THEN
BEGIN
REPEAT CONSTANT(FSYS + (.COMMA,COLON.),LSP1,LVAL);
IF LSP <> NIL THEN
BEGIN
IF LSP = CHARPTR THEN LVAL.IVAL := ASCII(.CHR(LVAL.IVAL).);
IF COMPTYPES(LSP,LSP1) THEN
BEGIN LPT1 := FSTPTR; LPT2 := NIL;
FOUND := FALSE;
WHILE NOT FOUND AND (LPT1 <> NIL) DO
WITH LPT1@ DO
BEGIN
IF CSLAB <= LVAL.IVAL THEN
BEGIN IF CSLAB = LVAL.IVAL THEN ERROR(156);
FOUND := TRUE
END
ELSE BEGIN LPT2 := LPT1; LPT1 := NEXT END
END;
NEW(LPT3);
WITH LPT3@ DO
BEGIN NEXT := LPT1; CSLAB := LVAL.IVAL;
CSSTART := LCIX1
END;
IF LPT2 = NIL THEN FSTPTR := LPT3
ELSE LPT2@.NEXT := LPT3
END
ELSE ERROR(147);
END (* LSP <> NIL *) ;
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = COLON THEN INSYMBOL ELSE ERROR(5);
PUTLABEL(LCIX1)
END
ELSE BEGIN OTHERWZ := TRUE;
IF STANDARD THEN WARNING(506);
INSYMBOL;
PUTLABEL(LOTHERWZ)
END;
REPEAT STATEMENT(FSYS + (.SEMICOLON.))
UNTIL NOT (SY IN STATBEGSYS);
IF (LPT3 <> NIL) OR OTHERWZ THEN
GENTL(98(* UJP *),'L',LFINISH);
END ;
TEST := SY <> SEMICOLON;
IF NOT TEST THEN INSYMBOL
UNTIL TEST OR OTHERWZ;
IF FSTPTR <> NIL THEN
BEGIN LMAX := FSTPTR@.CSLAB;
(* REVERSE POINTERS *)
LPT1 := FSTPTR; FSTPTR := NIL;
REPEAT LPT2 := LPT1@.NEXT; LPT1@.NEXT := FSTPTR;
FSTPTR := LPT1; LPT1 := LPT2
UNTIL LPT1 = NIL;
LMIN := FSTPTR@.CSLAB;
GENDEF(LBND,LMIN);
GENDEF(UBND,LMAX);
PUTLABEL(LCIX);
IF LMAX - LMIN < CIXMAX THEN
BEGIN
REPEAT
WITH FSTPTR@ DO
BEGIN
WHILE CSLAB > LMIN DO
BEGIN GENTL(113(* VJP *),'L',LOTHERWZ);
LMIN:=LMIN+1 END;
GENTL(113(* VJP *),'L',CSSTART);
FSTPTR := NEXT; LMIN := LMIN + 1
END
UNTIL FSTPTR = NIL;
IF NOT OTHERWZ THEN BEGIN PUTLABEL(LOTHERWZ);
GENI (112(*MST*),SYSTEM);
GENTI(45 (*LDC*),'I',1);
GENTI(116(*ARG*),'I',SYSTEM);
GENI (26 (*EXI*), 0) END;
PUTLABEL(LFINISH) ;
END
ELSE ERROR(157)
END;
IF SY = ENDSY THEN
BEGIN
BLEV := UPRED(BLEV);
EBLOCK := TRUE;
INSYMBOL
END
ELSE
ERROR(13)
END (* CASESTATEMENT *) ;
(* -------------------------------------------------------------------------
PROCEDURE REPEATSTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE REPEATSTATEMENT;
VAR LADDR: LABELRNG;
BEGIN GENLABEL(LADDR); PUTLABEL(LADDR);
REPEAT
REPEAT STATEMENT(FSYS + (.SEMICOLON,UNTILSY.))
UNTIL NOT (SY IN STATBEGSYS);
TEST := SY <> SEMICOLON;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = UNTILSY THEN
BEGIN
BLEV := UPRED(BLEV);
EBLOCK := TRUE;
GENKOUNT(FALSE);
INSYMBOL;
EXPRESSION(FSYS);
LOAD;
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> BOOLPTR THEN
ERROR(144);
GENTL(29 (* FJP *), 'L', LADDR)
END
ELSE ERROR(53)
END (* REPEATSTATEMENT *) ;
(* -------------------------------------------------------------------------
PROCEDURE WHILESTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE WHILESTATEMENT;
VAR LADDR, LCIX: LABELRNG;
BEGIN GENLABEL(LADDR); PUTLABEL(LADDR);
EXPRESSION(FSYS + (.DOSY.)); GENLABEL(LCIX);
LOAD;
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR <> BOOLPTR THEN ERROR(144);
GENTL(29(* FJP *),'L',LCIX);
IF SY = DOSY THEN INSYMBOL ELSE ERROR(54);
STATEMENT(FSYS); GENTL(98(* UJP *),'L',LADDR); PUTLABEL(LCIX)
END (* WHILESTATEMENT *) ;
(* -------------------------------------------------------------------------
PROCEDURE FORSTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE FORSTATEMENT;
VAR LATTR: ATTR; K: CHAR; LSY: SYMBOL;
LCIX, LADDR: LABELRNG ; LLC : ADDRRANGE ;
INDEXVARSIZE: INTEGER;
LCP: CTP;
BEGIN
INDEXVARSIZE := 0;
IF SY = IDENT
THEN SEARCHID((.VARS.),LCP)
ELSE BEGIN
ERROR (2);
LCP := UVARPTR
END; (*ELSE*)
WITH LCP@,LATTR DO
BEGIN
TYPTR := IDTYPE;
KIND := VARBL;
IF VKIND = ACTUAL
THEN BEGIN
ACCESS := DRCT;
VLEVEL := VLEV;
DPLMT := VADDR(.1.)
END (*THEN*)
ELSE BEGIN
ERROR (155);
TYPTR := NIL
END (*ELSE*)
END; (*WITH*)
IF LATTR.TYPTR <> NIL THEN
IF (LATTR.TYPTR@.FORM > SUBRANGE) OR (LATTR.TYPTR = REALPTR) THE
N BEGIN
ERROR (143);
LATTR.TYPTR := NIL
END; (*THEN*)
K := GETTYPE(LATTR.TYPTR);
IF SY = IDENT
THEN INSYMBOL
ELSE SKIP(FSYS + (.BECOMES,TOSY,DOWNTOSY,DOSY.));
IF SY = BECOMES THEN
BEGIN INSYMBOL; EXPRESSION(FSYS + (.TOSY,DOWNTOSY,DOSY.));
IF (GATTR.TYPTR <> NIL) AND (LATTR.TYPTR <> NIL) THEN
IF GATTR.TYPTR@.FORM <> SCALAR THEN ERROR(144)
ELSE
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
BEGIN
LOAD;
CHKBNDS (LATTR.TYPTR, GATTR.TYPTR, 145);
IF INTTYPE (GATTR.TYPTR) THEN
CNVRTTOLHS (LATTR.TYPTR, GATTR.TYPTR);
STORE (LATTR);
END
ELSE ERROR(145)
END
ELSE
BEGIN ERROR(51); SKIP(FSYS + (.TOSY,DOWNTOSY,DOSY.)) END;
IF SY IN (.TOSY,DOWNTOSY.) THEN
BEGIN LSY := SY; INSYMBOL; EXPRESSION(FSYS + (.DOSY.));
IF (GATTR.TYPTR <> NIL) AND (LATTR.TYPTR <> NIL) THEN
IF GATTR.TYPTR@.FORM <> SCALAR THEN ERROR(144)
ELSE
IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
BEGIN
LOAD;
CHKBNDS (LATTR.TYPTR, GATTR.TYPTR, 145);
IF INTTYPE (GATTR.TYPTR) THEN
CNVRTTOLHS (LATTR.TYPTR, GATTR.TYPTR);
INDEXVARSIZE := LATTR.TYPTR@.SIZE;
LOCN := LOCN - INDEXVARSIZE;
IF INDEXVARSIZE > 1 THEN LOCN := ALIGN(LOCN);
LLC := LOCN ;
GENTLI(96(* STR *),K,LEVEL,LLC);
GATTR := LATTR; LOAD;
GENTLI(48(* LOD *),K,LEVEL,LLC);
IF LOCN < LCMIN THEN LCMIN := LOCN;
IF LSY = TOSY THEN GENT(46(* LEQ *),K)
ELSE GENT(30(* GEQ *),K);
END
ELSE ERROR(145)
END
ELSE BEGIN ERROR(55); SKIP(FSYS + (.DOSY.)) END;
GENLABEL(LADDR) ; GENLABEL(LCIX); GENTL(29(* FJP *),'L',LCIX);
PUTLABEL(LADDR) ; (* BEGINNING OF THE FOR 'LOOP' *)
IF SY = DOSY THEN INSYMBOL ELSE ERROR(54);
STATEMENT(FSYS);
GATTR := LATTR ; LOAD ;
GENTLI(48(* LOD *),K,LEVEL,LLC) ;
GENT(59(* NEQ *),K) ; GENTL(29(* FJP *),'L',LCIX) ;
GATTR := LATTR; LOAD;
IF LSY = TOSY THEN GENTI(34(* INC *),K,1)
ELSE GENTI(16(* DEC *),K,1);
CHKBNDS (LATTR.TYPTR, GATTR.TYPTR, 145);
STORE(LATTR); GENTL(98(* UJP *),'L',LADDR); PUTLABEL(LCIX);
LOCN := LLC + INDEXVARSIZE ;
END (* FORSTATEMENT *) ;
(* -------------------------------------------------------------------------
PROCEDURE WITHSTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE WITHSTATEMENT;
VAR LCP: CTP; LCNT: DISPRANGE; LLC: ADDRRANGE;
BEGIN LCNT := TOP ; LLC := LOCN ;
REPEAT
IF SY = IDENT
THEN BEGIN SEARCHID((.VARS,FIELD.),LCP); INSYMBOL END
ELSE BEGIN ERROR(2); LCP := UVARPTR END;
SELECTOR(FSYS + (.COMMA,DOSY.),LCP);
IF GATTR.TYPTR <> NIL THEN
IF GATTR.TYPTR@.FORM = RECORDS THEN
IF TOP < DISPLIMIT THEN
BEGIN TOP := TOP + 1;
WITH DISPLAY(.TOP.) DO BEGIN
FNAME := GATTR.TYPTR@.FSTFLD;
FLABEL := NIL
END;
IF GATTR.ACCESS = DRCT THEN
WITH DISPLAY(.TOP.) DO
BEGIN OCCUR := CREC;
CLEV := GATTR.VLEVEL;
CDSPL := GATTR.DPLMT
END
ELSE
BEGIN LOADADDRESS;
LOCN := LOCN - ADDRSIZE;
LOCN := ALIGN(LOCN);
GENTLI(96(* STR *),'A',LEVEL,LOCN);
WITH DISPLAY(.TOP.) DO
BEGIN OCCUR := VREC; VDSPL := LOCN END;
IF LOCN < LCMIN THEN LCMIN := LOCN
END
END
ELSE ERROR(250)
ELSE ERROR(140);
TEST := SY <> COMMA;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = DOSY THEN INSYMBOL ELSE ERROR(54);
STATEMENT(FSYS);
TOP := LCNT ; LOCN := LLC ;
END (* WITHSTATEMENT *) ;
(* -------------------------------------------------------------------------
PROCEDURE EXITSTATEMENT
------------------------------------------------------------------------- *
)
PROCEDURE EXITSTATEMENT; (*TAKES LABEL OR NULL. IF NULL *
) VAR FOUND: BOOLEAN; (*THEN EXIT CURRENT LOOP CONSTRUCT*
) LPTR: LOOPPTR; (*(WHILE,REPEAT,OR FOR) IF LABEL *
) (*THEN EXIT LOOP WITH THAT LABEL *
) (*'LOOPENTRY' AND 'LOOPEXIT' KEEP *
) (*A STACK OF THE CURRENT EXIT LABS*
) (*EITHER USE THE TOP ITEM OR SCAN *
) (*BACK UNTIL FIND ONE POINTING TO *
) (*TO SPECIFIED ACTUAL LABEL *
) BEGIN
IF STANDARD THEN WARNING(505);
IF (SY = INT2CONST) OR (SY = IDENT) THEN
BEGIN FOUND := FALSE;
LPTR := LOOPLISTPTR;
WHILE NOT FOUND AND (LPTR <> NIL) DO
IF SAMELABEL(SY,LPTR@.ASSOCLAB) THEN
BEGIN
FOUND := TRUE;
IF LPTR@.LABNO = 0 THEN
GENLABEL(LPTR@.LABNO);
GENTL(98 (*UJP*), 'L', LPTR@.LABNO);
LPTR@.USED := TRUE;
END
ELSE LPTR := LPTR@.NEXTLOOP;
IF NOT FOUND THEN ERROR(411);
INSYMBOL
END
ELSE BEGIN
IF NOT (SY IN (.SEMICOLON,ENDSY,ELSESY,UNTILSY.)) THEN ERROR(41
0) ELSE IF LOOPLISTPTR <> NIL THEN
BEGIN
IF LOOPLISTPTR@.LABNO = 0 THEN
GENLABEL(LOOPLISTPTR@.LABNO);
GENTL(98 (*UJP*), 'L', LOOPLISTPTR@.LABNO);
LOOPLISTPTR@.USED := TRUE;
END
ELSE ERROR(412)
END
END; (*EXITSTATEMENT*)
PROCEDURE LOOPENTRY; (*DEFINE AN EXIT LABEL FOR THIS LOOP STMNT *)
VAR
LPTR: LOOPPTR;
BEGIN
NEW(LPTR); (*CREATE NEW LOOP EXIT LABEL*)
WITH LPTR@ DO BEGIN
LABNO := 0;
ASSOCLAB:= LLP; (*POINT TO ACTUAL LABEL OF LOOP IF ANY*)
(*THIS CODE ASSUMES THAT LLP IS NIL IF
THE CURRENT STATEMENT IS NOT LABELLED*)
NEXTLOOP:= LOOPLISTPTR; (*PUT ON STACK OF LOOP EXIT LABELS*)
USED := FALSE (*NOT REFERENCED YET*)
END;
LOOPLISTPTR := LPTR
END; (*LOOPENTRY*)
PROCEDURE LOOPEXIT; (*PROCESS AND REMOVE THE EXIT
LABEL FOR THIS LOOP*)
BEGIN WITH LOOPLISTPTR@ DO BEGIN
IF USED THEN PUTLABEL(LABNO); (*INSERT EXIT LABEL INTO OBJECT
IF IT WAS REFERENCED*)
LOOPLISTPTR := NEXTLOOP (*REMOVE FROM STACK*)
END
END; (*LOOPEXIT*)
BEGIN (* *START** STATEMENT *)
LLP := NIL; (*NEEDED FOR EXIT LOOPS*)
IF (SY = INT2CONST) OR (SY = IDENT) THEN (* LABEL *)
BEGIN TTOP := TOP ;
WHILE DISPLAY(.TTOP.).OCCUR <> BLCK DO TTOP := TTOP-1 ;
LLP := DISPLAY(.TTOP.).FLABEL;
FOUND := FALSE;
WHILE NOT FOUND AND (LLP <> NIL) DO
WITH LLP@ DO
IF SAMELABEL(SY, LLP) THEN
BEGIN
IF DEFINED THEN ERROR(165);
IF LABNO = 0 THEN
GENLABEL(LABNO);
PUTLABEL(LABNO);
DEFINED := TRUE;
FOUND := TRUE;
END
ELSE LLP := NEXTLAB;
IF SY = INT2CONST THEN BEGIN
IF NOT FOUND THEN ERROR(167);
INSYMBOL; IF SY = COLON THEN INSYMBOL ELSE ERROR(5)
END
ELSE IF FOUND THEN (* ALPHA LABEL *)
BEGIN INSYMBOL; IF SY = COLON THEN INSYMBOL ELSE ERROR(5) END;
END;
IF NOT (SY IN FSYS + (.IDENT.)) THEN
BEGIN ERROR(6); SKIP(FSYS) END;
IF SY IN STATBEGSYS + (.IDENT.) THEN
BEGIN
IF SY IN LOOPBEGSYS THEN BEGIN LOOPENTRY; (*SET UP EXIT LABEL*)
INLOOP := TRUE END
ELSE INLOOP := FALSE;
CASE SY OF
IDENT: BEGIN SEARCHID((.VARS,FIELD,FUNC,PROC.),LCP);
GENKOUNT(FALSE); INSYMBOL;
IF LCP@.KLASS = PROC THEN CALL(FSYS,LCP)
ELSE ASSIGNMENT(LCP)
END;
BEGINSY: BEGIN
BLEV := USUCC(BLEV);
SBLOCK := TRUE;
INSYMBOL;
COMPOUNDSTATEMENT
END;
GOTOSY: BEGIN GENKOUNT(FALSE); INSYMBOL; GOTOSTATEMENT END;
IFSY: BEGIN GENKOUNT(FALSE); INSYMBOL; IFSTATEMENT END;
CASESY: BEGIN
BLEV := USUCC(BLEV);
SBLOCK := TRUE;
GENKOUNT(FALSE);
INSYMBOL;
CASESTATEMENT
END;
WHILESY: BEGIN GENKOUNT(FALSE); INSYMBOL; WHILESTATEMENT END;
REPEATSY: BEGIN
BLEV := USUCC(BLEV);
SBLOCK := TRUE;
INSYMBOL;
REPEATSTATEMENT
END;
(* GENKOUNT(FALSE) WHEN 'UNTIL' ENCOUNTERED *)
FORSY: BEGIN GENKOUNT(FALSE); INSYMBOL; FORSTATEMENT END;
EXITSY: BEGIN GENKOUNT(FALSE); INSYMBOL; EXITSTATEMENT END;
WITHSY: BEGIN INSYMBOL; WITHSTATEMENT END
END;
IF INLOOP THEN LOOPEXIT;
IF NOT (SY IN (.SEMICOLON,ENDSY,ELSESY,UNTILSY.)) THEN
BEGIN ERROR(6); SKIP(FSYS) END
END
END (* STATEMENT *) ;
BEGIN (***START** BODY *)
IF FPROCP <> NIL THEN
BEGIN ENTNAME := FPROCP@.PFNAME; PROCNAME := FPROCP@.NAME END
ELSE
BEGIN ENTNAME := 0; PROCNAME := PROGNAME; PARMLEN := 0 END;
GENLABEL(SEGSIZE) ;
GENENT(ENTNAME,21(* ENT *),LEVEL,SEGSIZE,PROCNAME) ;
LABELEDKOUNT := TRUE;
GENKOUNT(TRUE);
PRINTKOUNT := FALSE;
MINKOUNT := KOUNT;
LCMIN := LOCN;
(*OPEN LOCAL FILES*)
KLOCFILELIST := LOCFILELIST;
WHILE KLOCFILELIST <> NIL DO BEGIN
WITH KLOCFILELIST@ DO BEGIN
GENI(112 (*MST*), 0);
GENLI(44(*LDA*),VLEV,VADDR(.1.));(*PUSH ADDR(FILE PTR
)*) GENTI(116 (*ARG*), 'A', 0);
(*GET POSITION IN PROGRAM HEADER LIST*)
K := 0;
IF (LEVEL = 0) AND (FEXTFILEP <> NIL) THEN
BEGIN KFILE := FEXTFILEP;
WHILE KFILE <> NIL DO BEGIN
IF KFILE@.FILENAME = NAME THEN
K := KFILE@.POS;
KFILE := KFILE@.NEXTFILE
END
END;
GENTI(45(*LDC*),'I',K); (*PUSH FILE POSITION*)
GENTI(116 (*ARG*), 'I', 0);
(*BUILD FILE STATUS*)
IF IDTYPE = TEXTPTR THEN STATUS := 4 ELSE STATUS := 0
; IF NOT EXTRNL THEN STATUS := STATUS + 8;
STDFILE := FALSE;
IF KLOCFILELIST = STDINPUT THEN
BEGIN STDFILE := TRUE;
STATUS := STATUS + 2 END
ELSE IF KLOCFILELIST = STDOUTPUT THEN
BEGIN STDFILE := TRUE;
STATUS := STATUS + 1 END;
GENTI(45(*LDC*),'I',STATUS); (*PUSH FILE STATUS*)
GENTI(116 (*ARG*), 'I', 0);
GENTI(45(*LDC*),'I',IDTYPE@.FILTYPE@.SIZE);
(*PUSH COMPONENT SIZE*)
GENTI(116 (*ARG*), 'I', 0);
GEN(33(*IFD*)) ;
IF STDFILE THEN BEGIN
GENI(112 (*MST*), 0);
(*PUSH ADDR(FILE PTR)*)
GENLI(44(*LDA*),VLEV,VADDR(.1.));
GENTI(116 (*ARG*), 'A', 0);
IF KLOCFILELIST = STDINPUT THEN K := 80(*RST*)
ELSE K := 81(*RWT*);
GEN(K (*RST,RWT*))
END;
KLOCFILELIST := (*KLOCFILELIST@.*)NEXT END
END;
LOOPLISTPTR := NIL;
REPEAT
REPEAT STATEMENT(FSYS + (.SEMICOLON,ENDSY.))
UNTIL NOT (SY IN STATBEGSYS);
TEST := SY <> SEMICOLON;
IF NOT TEST THEN INSYMBOL
UNTIL TEST;
IF SY = ENDSY THEN
BEGIN
EBLOCK := TRUE;
BLEV := UPRED(BLEV);
INSYMBOL
END
ELSE
ERROR(13);
(*CLOSE LOCAL FILES*)
KLOCFILELIST := LOCFILELIST;
WHILE KLOCFILELIST <> NIL DO BEGIN
WITH KLOCFILELIST@ DO BEGIN
GENI(112 (*MST*), 0);
GENLI(44(*LDA*),VLEV,VADDR(.1.));(*PUSH ADDR(FILE PTR
)*) GENTI(116 (*ARG*), 'A', 0);
GEN(7(*CLO*)) END;
KLOCFILELIST := KLOCFILELIST@.NEXT END;
LLP := DISPLAY(.TOP.).FLABEL; (* TEST FOR UNDEFINED LABELS *)
WHILE LLP <> NIL DO
WITH LLP@ DO
BEGIN
IF NOT DEFINED THEN
BEGIN
IF PAGEPOS > PAGEEND THEN NEWPAGE;
ERRORCOUNT := ERRORCOUNT + 1;
WRITE(LISTING, ERRMES:11,LASTERR:6,'** 168 ');
IF ALF THEN WRITELN(LISTING,LABNAME)
ELSE WRITELN(LISTING,LABVAL:0);
LASTERR := LINECOUNT;
PAGEPOS := PAGEPOS + 1
END;
LLP := LLP@.NEXTLAB
END;
K := ALIGN (ABS(LCMIN));
GENDEF(SEGSIZE,K) ; (* ASSURE EVEN ADDR *)
IF K > STKSIZES(.LEVEL.) THEN STKSIZES(.LEVEL.) := K;
IF FPROCP = NIL THEN GEN(95(* STP *));
OLDIC := OLDIC+ IC ; IC := 0 ; (* RESET IC FOR NEXT PROC *)
END (* BODY *) ;
BEGIN (* **START** BLOCK *)
FWDLIST := NIL;
LOCFILELIST:= GLOBFILELIST; GLOBFILELIST := NIL;
DP := TRUE;
REPEAT
IF SY = LABELSY THEN
BEGIN INSYMBOL; LABELDECLARATION END;
IF SY = CONSTSY THEN
BEGIN INSYMBOL; CONSTDECLARATION END;
IF SY = TYPESY THEN
BEGIN INSYMBOL; TYPEDECLARATION END;
IF SY = VARSY THEN
BEGIN INSYMBOL; VARDECLARATION END;
WHILE SY IN (.PROCSY,FUNCSY.) DO
BEGIN LSY := SY; INSYMBOL; PROCDECLARATION(LSY) END;
IF NOT(SY IN FSYS + (.PERIOD.)) THEN
BEGIN ERROR(18); SKIP(FSYS + (.PERIOD.)) END;
IF STANDARD AND (SY <> BEGINSY) THEN WARNING(502) (* UNORDERED DECL'S *
) UNTIL SY IN STATBEGSYS+(.PERIOD.);
(* EXPECTING DECL'S TO BE FINISHED HERE; CHECK UNRESOLVED
FWD TYPE DEFINITIONS (CODE MOVED HERE FROM 'TYPEDECL' *)
WHILE FWPTR <> NIL DO
BEGIN
IF PAGEPOS > PAGEEND THEN NEWPAGE;
ERRORCOUNT := ERRORCOUNT + 1;
WRITELN(LISTING,ERRMES:11,LASTERR:6,'** 117 TYPE-ID ',FWPTR@.NAME
); PAGEPOS := PAGEPOS + 1;
LASTERR := LINECOUNT;
FWPTR := FWPTR@.NEXT
END;
(* CHECK FOR AND FLAG UNRESOLVED FORWARD PROC/FUNCS *)
(* IF IN MAIN BODY THEY ARE ASSUMED TO BE EXTERNAL *)
WHILE FWDLIST <> NIL DO
BEGIN WITH FWDLIST@.PF@ DO
BEGIN
IF LEVEL = 0 THEN
BEGIN (* IN MAIN BODY *)
GENDEF1(PFNAME,NAME);
IF PAGEPOS > PAGEEND THEN NEWPAGE;
PAGEPOS := PAGEPOS + 1;
WRITELN(LISTING, STARS:7,NAME,' ASSUMED EXTERNAL')
END
ELSE
BEGIN
IF PAGEPOS > PAGEEND THEN NEWPAGE;
ERRORCOUNT := ERRORCOUNT + 1;
WRITE(LISTING, ERRMES:11,LASTERR:6);
WRITELN(LISTING,'** 117 PROC/FUNC ',NAME);
LASTERR := LINECOUNT;
PAGEPOS := PAGEPOS + 1;
END;
END;
FWDLIST := FWDLIST@.NEXTPF
END;
DP := FALSE;
IF NOT (SUBPROG AND (LEVEL = 0)) THEN
BEGIN
IF SY = BEGINSY THEN
BEGIN
PRINTKOUNT := TRUE;
SBLOCK := TRUE;
BLEV := 'B';
MLEV := 'A';
INSYMBOL
END
ELSE
ERROR(17);
REPEAT BODY(FSYS + (.CASESY.));
IF (SY <> FSY) AND NOT ((SY = PERIOD) AND (LEVEL = 1) AND SUBPROG)
THEN BEGIN ERROR(6); SKIP(FSYS + (.FSY.) + (.PERIOD.)) END
UNTIL (SY = FSY) OR (SY = PERIOD) OR (SY IN BLOCKBEGSYS);
END
END (* BLOCK *) ;
(* -------------------------------------------------------------------------
PROCEDURE PROGRAMME
------------------------------------------------------------------------- *
)
PROCEDURE PROGRAMME(FSYS: SETOFSYS);
VAR EXTFP:EXTFILEP;
LCP: CTP;
I, FILEPOS: INTEGER;
BEGIN
IF (SY = PROGSY) OR (SY = SUBPROGSY) THEN
BEGIN IF SY = SUBPROGSY THEN BEGIN SUBPROG:=TRUE;
IF STANDARD THEN WARNING(507)
END
ELSE SUBPROG:=FALSE;
INSYMBOL; IF SY <> IDENT THEN ERROR(2); PROGNAME:=ID; INSYMBOL;
IF NOT (SY IN (.LPARENT,SEMICOLON.)) THEN ERROR(14);
IF SY = LPARENT THEN
BEGIN
FILEPOS := 0;
REPEAT INSYMBOL;
IF SY = IDENT THEN
BEGIN
IF (ID <> 'INPUT ')
AND (ID <> 'OUTPUT ') THEN
BEGIN NEW(EXTFP);
FILEPOS := FILEPOS + 1;
WITH EXTFP@ DO
BEGIN FILENAME := ID;
NEXTFILE := FEXTFILEP ;
POS := FILEPOS;
DEF := FALSE
END;
FEXTFILEP := EXTFP;
END
ELSE
BEGIN NEW(LCP,VARS);
WITH LCP@ DO
BEGIN NAME := ID; IDTYPE := TEXTPTR;
KLASS := VARS; VKIND := ACTUAL; VLEV := 0;
EXTRNL := TRUE;
LOCN := LOCN - 2 * ADDRSIZE; VADDR(.1.) := LOCN;
NEXT := GLOBFILELIST; GLOBFILELIST := LCP;
END;
IF ID = 'INPUT ' THEN STDINPUT := LCP
ELSE STDOUTPUT := LCP;
ENTERID(LCP)
END;
INSYMBOL;
IF NOT ( SY IN (.COMMA,RPARENT.) ) THEN ERROR(20)
END
ELSE ERROR(2)
UNTIL SY <> COMMA;
IF SY <> RPARENT THEN ERROR(4);
INSYMBOL
END;
IF SY <> SEMICOLON THEN ERROR(14)
ELSE INSYMBOL;
END;
WRITE(PCODE,'HP');
IF ADDRSIZE = 4 THEN
WRITE(PCODE,'20')
ELSE
WRITE(PCODE,'09');
WRITE (PCODE,' ''',PROGNAME,'''');
IF SUBPROG THEN
WRITE(PCODE,'S ':3)
ELSE
WRITE(PCODE,'M ':3);
OUTHEX (PCODE,JUMPBASE);
WRITE (PCODE,JUMPENTRIES:6,' ');
OUTHEX (PCODE,HEAPSTART);
WRITE (PCODE,' ');
OUTHEX (PCODE,STACKSTART);
WRITELN (PCODE,' ');
(*REPEAT*) BLOCK(FSYS,PERIOD,NIL);
IF SY <> PERIOD THEN ERROR(21)
(*UNTIL SY = PERIOD*) ;
WRITELN (PCODE,' END');
IF LIST THEN WRITELINE;
IF ERRINX > 0 THEN PRINTERROR ;
WHILE FEXTFILEP <> NIL DO
BEGIN
IF NOT FEXTFILEP@.DEF THEN
BEGIN
IF PAGEPOS > PAGEEND THEN NEWPAGE;
ERRORCOUNT := ERRORCOUNT + 1;
WRITE(LISTING, ERRMES:11, LASTERR:6);
WRITELN(LISTING,'** 172 FILE ',FEXTFILEP@.FILENAME);
LASTERR := LINECOUNT;
PAGEPOS := PAGEPOS + 1;
END; (* IF NOT FEXTFILEP@.DEF ... *)
FEXTFILEP := FEXTFILEP@.NEXTFILE
END; (* WHILE FEXTFILEP <> NIL *)
END (* PROGRAMME *) ;
(* -------------------------------------------------------------------------
INITIALIZATION PROCEDURES
------------------------------------------------------------------------- *
)
PROCEDURE ENTERSTDTYPES;
BEGIN (* TYPE UNDERLYING: *)
(* +++++++++++++++++ *)
NEW (INT1PTR,SCALAR); (*SHORTINT*)
WITH INT1PTR@ DO
BEGIN
SIZE := INT1SIZE;
FORM := SCALAR
END; (*WITH*)
NEW(INT2PTR,SCALAR); (* INTEGER *)
WITH INT2PTR@ DO
BEGIN SIZE := INT2SIZE;
FORM := SCALAR; END;
NEW (INT4PTR,SCALAR); (*LONGINT*)
WITH INT4PTR@ DO
BEGIN
SIZE := INT4SIZE;
FORM := SCALAR
END; (*WITH*)
NEW(REALPTR,SCALAR); (* REAL *)
WITH REALPTR@ DO
BEGIN SIZE := REALSIZE;
FORM := SCALAR; END;
NEW(CHARPTR,SCALAR); (* CHAR *)
WITH CHARPTR@ DO
BEGIN SIZE := CHARSIZE;
FORM := SCALAR; END;
NEW(BOOLPTR,SCALAR); (* BOOLEAN *)
WITH BOOLPTR@ DO
BEGIN SIZE := BOOLSIZE;
FORM := SCALAR; END;
NEW(NILPTR,POINTER); (* NIL *)
WITH NILPTR@ DO
BEGIN ELTYPE := NIL; SIZE := ADDRSIZE;
FORM := POINTER END;
NEW(TEXTPTR,FILES); (* TEXT *)
WITH TEXTPTR@ DO
BEGIN FILTYPE := CHARPTR; SIZE := 2*ADDRSIZE;
FORM := FILES END;
NEW(SINGLECHARSTRING, STRINGS);
WITH SINGLECHARSTRING@ DO
BEGIN
FORM := STRINGS;
SIZE := 4;
END;
END (* ENTERSTDTYPES *) ;
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE ENTSTDNAMES *)
(* *)
(* THIS PROCEDURE ENTERS THE STANDARD NAMES INTO THE HEAP. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE ENTSTDNAMES;
VAR
NA: ARRAY (.STDNAMES.) OF ALPHA; (*THE NAMES*)
CP,
CPLAST: CTP; (*PTRS TO NAMES*)
N: STDNAMES;
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE ENTERPROC (PROCNAME,PROCTYPE) *)
(* *)
(* THIS PROCEDURE ENTERS THE PROCEDURE OR FUNCTION WHOSE *)
(* NAME IS 'PROCNAME' AND TYPE IS 'PROCTYPE' INTO THE HEAP. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE ENTERPROC (PROCNAME: STDNAMES; PROCTYPE: IDCLASS);
VAR
CP: CTP; (*PTR TO NAME*)
BEGIN (*ENTERPROC*)
NEW (CP,PROC); (*GET A NEW RECORD*)
WITH CP@ DO (*SET UP THE RECORD*)
BEGIN
NAME := NA(.PROCNAME.);
IDTYPE := NIL;
NEXT := NIL;
KEY := PROCNAME;
KLASS := PROCTYPE;
PFDECKIN := BUILTIN
END; (*WITH*)
ENTERID (CP) (*ENTER THE NAME*)
END; (*ENTERPROC*)
(*--------------------------------------------------------------------*)
(* *)
(* PROCEDURE ENTERTYPE (TYPENAME,TYPEPTR) *)
(* *)
(* THIS PROCEDURE ENTERS THE TYPE WHOSE NAME IS 'TYPENAME' *)
(* AND POINTER IS 'TYPEPTR'. *)
(* *)
(*--------------------------------------------------------------------*)
PROCEDURE ENTERTYPE (TYPENAME: STDNAMES; TYPEPTR: STP);
VAR
CP: CTP; (*PTR TO THE NAME*)
BEGIN (*ENTERTYPE*)
NEW (CP,TYPES); (*GET A NEW RECORD*)
WITH CP@ DO (*SET UP THE RECORD*)
BEGIN
NAME := NA(.TYPENAME.);
IDTYPE := TYPEPTR;
KLASS := TYPES
END; (*WITH*)
ENTERID (CP) (*ENTER THE NAME*)
END; (*ENTERTYPES*)
(*--------------------------------------------------------------------*)
(* *)
(* ENTSTDNAMES STARTS HERE *)
(* *)
(*--------------------------------------------------------------------*)
BEGIN (*ENTSTDNAMES*)
(*FIRST INITIALIZE THE ARRAY OF NAMES*)
(*CONSTANTS*)
NA(.XTRUE .) := 'TRUE '; NA(.XMAXINT .) := 'MAXINT ';
NA(.XNIL .) := 'NIL '; NA(.XFALSE .) := 'FALSE ';
(*TYPES*)
NA(.XCHAR .) := 'CHAR '; NA(.XBOOLEAN .) := 'BOOLEAN ';
NA(.XINTEGER .) := 'INTEGER '; NA(.XREAL .) := 'REAL ';
NA(.XTEXT .) := 'TEXT ';
(*FUNCTIONS*)
NA(.XPOSITION.) := 'POSITION'; NA(.XCOPY .) := 'COPY ';
NA(.XEOF .) := 'EOF '; NA(.XLENGTH .) := 'LENGTH ';
NA(.XORD .) := 'ORD '; NA(.XSQR .) := 'SQR ';
NA(.XTRUNC .) := 'TRUNC '; NA(.XARCTAN .) := 'ARCTAN ';
NA(.XCLOCK .) := 'CLOCK '; NA(.XDELETE .) := 'DELETE ';
NA(.XEXP .) := 'EXP '; NA(.XINSERT .) := 'INSERT ';
NA(.XSUCC .) := 'SUCC '; NA(.XABS .) := 'ABS ';
NA(.XCHR .) := 'CHR '; NA(.XCONCAT .) := 'CONCAT ';
NA(.XCOS .) := 'COS '; NA(.XEOLN .) := 'EOLN ';
NA(.XLN .) := 'LN '; NA(.XODD .) := 'ODD ';
NA(.XPOS .) := 'POS '; NA(.XPRED .) := 'PRED ';
NA(.XROUND .) := 'ROUND '; NA(.XSIN .) := 'SIN ';
NA(.XSQRT .) := 'SQRT ';
(*PROCEDURES*)
NA(.XGET .) := 'GET '; NA(.XREWRITE .) := 'REWRITE ';
NA(.XUNPACK .) := 'UNPACK '; NA(.XREADLN .) := 'READLN ';
NA(.XWRITELN .) := 'WRITELN '; NA(.XPAGE .) := 'PAGE ';
NA(.XPUT .) := 'PUT '; NA(.XRELEASE .) := 'RELEASE ';
NA(.XWRITE .) := 'WRITE '; NA(.XDISPOSE .) := 'DISPOSE ';
NA(.XHALT .) := 'HALT '; NA(.XMARK .) := 'MARK ';
NA(.XNEW .) := 'NEW '; NA(.XPACK .) := 'PACK ';
NA(.XREAD .) := 'READ '; NA(.XRESET .) := 'RESET ';
(* NOW PUT THE STUFF IN THE HEAP IN SUCH AN ORDER AS TO KEEP THE *)
(* TREE AS BALANCED AS POSSIBLE. *)
FOR N := XODD TO XDELETE DO
ENTERPROC (N,FUNC);
ENTERPROC (XREWRITE,PROC);
ENTERTYPE (XTEXT,TEXTPTR);
FOR N := XPUT TO XUNPACK DO
ENTERPROC (N,PROC);
ENTERTYPE (XCHAR,CHARPTR);
(* ENTERTYPE (XREAL,REALPTR); COMMENTED UNTIL REALS ARE REAL*)
NEW (CP,KONST); (*MAXINT*)
WITH CP@ DO
BEGIN
NAME := NA(.XMAXINT.);
IDTYPE := INT4PTR;
NEXT := NIL;
NEW (VALUES.VALP,LINT);
VALUES.VALP@.LINTVAL := LINT4MAX;
KLASS := KONST
END; (*WITH*)
ENTERID (CP);
FOR N := XPOS TO XSQRT DO
ENTERPROC (N,FUNC);
FOR N := XDISPOSE TO XWRITE DO
ENTERPROC (N,PROC);
ENTERTYPE (XINTEGER,INT4PTR);
CPLAST := NIL;
FOR N := XFALSE TO XTRUE DO
BEGIN
NEW (CP,KONST);
WITH CP@ DO
BEGIN
NAME := NA(.N.);
IDTYPE := BOOLPTR;
NEXT := CPLAST;
IF N = XFALSE
THEN VALUES.IVAL := 0
ELSE VALUES.IVAL := 1;
KLASS := KONST
END; (*WITH*)
ENTERID (CP);
CPLAST := CP
END; (*FOR*)
BOOLPTR@.FCONST := CPLAST;
NEW (CP,KONST); (*NIL*)
WITH CP@ DO
BEGIN
NAME := NA(.XNIL.);
IDTYPE := NILPTR;
NEXT := NIL;
VALUES.IVAL := 0;
KLASS := KONST
END; (*WITH*)
ENTERID (CP);
ENTERTYPE (XBOOLEAN,BOOLPTR);
FOR N := XGET TO XWRITELN DO
ENTERPROC (N,PROC);
FOR N := XABS TO XTRUNC DO
ENTERPROC (N,FUNC);
(* NOW UP THE DISPLAY TO ALLOW REDEFINITION OF STD NAMES *)
(* AT A GLOBAL LEVEL. *)
TOP := TOP + 1;
WITH DISPLAY(.TOP.) DO
BEGIN
FNAME := NIL;
FLABEL := NIL;
OCCUR := BLCK
END (*WITH*)
END; (*ENTSTDNAMES*)
PROCEDURE ENTERUNDECL;
BEGIN
NEW(UTYPPTR,TYPES);
WITH UTYPPTR@ DO
BEGIN NAME := BLANKID; IDTYPE := NIL; KLASS := TYPES END;
NEW(UCSTPTR,KONST);
WITH UCSTPTR@ DO
BEGIN NAME := BLANKID; IDTYPE := NIL; NEXT := NIL;
VALUES.IVAL := 0; KLASS := KONST
END;
NEW(ULABPTR,LABELS);
WITH ULABPTR@ DO
BEGIN NAME := BLANKID; IDTYPE := NIL;
NEXT := NIL; KLASS := LABELS
END;
NEW(UVARPTR,VARS);
WITH UVARPTR@ DO
BEGIN NAME := BLANKID; IDTYPE := NIL; VKIND := ACTUAL;
EXTRNL := FALSE;
NEXT := NIL; VLEV := 0; VADDR := LONGZERO; KLASS := VARS
END;
NEW(UFLDPTR,FIELD);
WITH UFLDPTR@ DO
BEGIN NAME := BLANKID; IDTYPE := NIL; NEXT := NIL; FLDADDR := 0;
KLASS := FIELD
END;
NEW(UPRCPTR,PROC,DECLARED,ACTUAL);
WITH UPRCPTR@ DO
BEGIN NAME := BLANKID; IDTYPE := NIL; FORWDECL := FALSE;
NEXT := NIL; (*EXTERN := FALSE;*) PFLEV := 0;
PFNAME := 1;
KLASS := PROC; PFDECKIND := DECLARED; PFKIND := ACTUAL
END;
NEW(UFCTPTR,FUNC,DECLARED,ACTUAL);
WITH UFCTPTR@ DO
BEGIN NAME := BLANKID; IDTYPE := NIL; NEXT := NIL;
FORWDECL := FALSE; (*EXTERN := FALSE;*) PFLEV := 0;
PFNAME := 1;
KLASS := FUNC; PFDECKIND := DECLARED; PFKIND := ACTUAL
END
END (* ENTERUNDECL *) ;
PROCEDURE INITSCALARS;
VAR I: INTEGER;
BEGIN FOR I := 1 TO IDLNGTH DO BLANKID(.I.) := ' ';
FWPTR := NIL;
NEW(CNSTVALPTR) ;
NEW(CNSTSTRPTR) ;
CNSTVALPTR@.SVAL:=CNSTSTRPTR;
LIST := TRUE; DEBUG := FALSE ;
PLIST := TRUE; PRCODE := TRUE;
DP := TRUE; STANDARD := FALSE;
PRTERR := TRUE;
ERRORS := FALSE; ERRORCOUNT :=0 ;
WARNINGS := FALSE; WARNCOUNT :=0 ;
ERRINX := 0;
(* DEFAULTS FOR 32 BIT ADDRESSES, AND WORD (16 BITS) ALIGNED MACHINE *)
ADDRSIZE := 2 * MACHINE;
ALIGNMENT := MACHINE;
ASSIGN := FALSE ;
FEXTFILEP := NIL;
GLOBFILELIST := NIL;
STDINPUT := NIL; STDOUTPUT := NIL;
LOCN := 0; (* ADR. OF THE FIRST VARIABLE OF 'MAIN BLOCK' *)
PKOUNTERS:=FALSE; KOUNTERS:=FALSE; PRINTKOUNT := FALSE;
LABELEDKOUNT := TRUE; KOUNT := 1;
OLDIC := 0; IC := 0;
EOL := FALSE; CH := ' '; LINEBUF(.0.) := ' ';
DOUBLECHAR := FALSE;
GLOBTESTP := NIL;
INTLABEL := 0; PROCLAB := 0;
ARITHMETICSIZE := 'J';
LONGZERO(.1.) := 0; LONGZERO(.2.) := 0;
LONGZERO(.3.) := 0; LONGZERO(.4.) := 0;
MAKELONG (-128,LINT1MIN);
MAKELONG (127,LINT1MAX);
MAKELONG (-32767 - 1,LINT2MIN);
MAKELONG (32767,LINT2MAX);
LINT4MIN := LONGZERO;
LINT4MIN(.4.) := 128;
LINT4MAX(.1.) := 255; LINT4MAX(.2.) := 255;
LINT4MAX(.3.) := 255; LINT4MAX(.4.) := 127;
MAKELONG (ORDMAXCHAR,LONGORDMAXCHAR);
(*SET UP THE DEFAULT JUMP TABLE ADDRESS, JUMP TABLE SIZE,
HEAP START ADDRESS, AND STACK START (TOP) ADDRESS *)
JUMPENTRIES := 10;
JUMPBASE := LONGZERO;
JUMPBASE(.2.) := 48;
HEAPSTART := LINT4MAX;
HEAPSTART(.4.) := 255;
STACKSTART := LONGZERO;
STACKSTART(.1.) := 254;
STACKSTART(.2.) := 127;
FOR I := 0 TO MAXLEVEL DO STKSIZES(.I.) := 0;
LONGONLY := FALSE;
TOP := 0;
LEVEL := 0;
WITH DISPLAY(. 0 .) DO
BEGIN
FNAME := NIL;
FLABEL := NIL;
OCCUR := BLCK
END;
LASTERR := 0;
LINECOUNT := 0;
PAGENUM := 0;
PAGELEN := PAGEDEFAULT;
PAGEPOS := STARTPAGE;
LINEWIDTH := WIDTHDEFAULT;
PAGEEND := ENDOFPAGE;
BLEV := 'A';
HEADER := 'MOTOROLA PASCAL JUL 25, 1980 ';
STARS := '**** ';
ERRMES := '**ERROR--';
EOFMESSAGE := '**** ERROR, END OF FILE ENCOUNTERED';
END (* INITSCALARS *) ;
PROCEDURE INITSETS;
BEGIN
CONSTBEGSYS := (.ADDOP,INT1CONST,INT2CONST,INT4CONST,REALCONST,
STRINGCONST,IDENT.);
SIMPTYPEBEGSYS := (.LPARENT.) + CONSTBEGSYS;
TYPEBEGSYS := (.ARROW,PACKEDSY,STRINGSY,ARRAYSY,RECORDSY,SETSY,FILESY
.) +SIMPTYPEBEGSYS;
TYPEDELS := (.STRINGSY,ARRAYSY,RECORDSY,SETSY,FILESY.);
BLOCKBEGSYS := (.LABELSY,CONSTSY,TYPESY,VARSY,PROCSY,FUNCSY,
BEGINSY.);
SELECTSYS := (.ARROW,PERIOD,LBRACK.);
FACBEGSYS := (.INT1CONST,INT2CONST,INT4CONST,REALCONST,STRINGCONST,
IDENT,LPARENT,LBRACK,NOTSY.);
STATBEGSYS := (.BEGINSY,GOTOSY,IFSY,WHILESY,REPEATSY,FORSY,WITHSY,
CASESY,EXITSY.);
LOOPBEGSYS := (.WHILESY,FORSY,REPEATSY.);
END (* INITSETS *) ;
PROCEDURE INITTABLES;
PROCEDURE RESWORDS;
BEGIN
RW(. 1.):= 'IF '; RW(. 2.):= 'DO '; RW(. 3.):= 'OF ';
RW(. 4.):= 'TO '; RW(. 5.):= 'IN '; RW(. 6.):= 'OR ';
RW(. 7.):= 'END '; RW(. 8.):= 'FOR '; RW(. 9.):= 'VAR ';
RW(.10.):= 'DIV '; RW(.11.):= 'MOD '; RW(.12.):= 'SET ';
RW(.13.):= 'AND '; RW(.14.):= 'NOT '; RW(.15.):= 'THEN ';
RW(.16.):= 'ELSE '; RW(.17.):= 'WITH '; RW(.18.):= 'GOTO ';
RW(.19.):= 'CASE '; RW(.20.):= 'TYPE '; RW(.21.):= 'EXIT ';
RW(.22.):= 'FILE '; RW(.23.):= 'BEGIN ';
RW(.24.):= 'UNTIL '; RW(.25.):= 'WHILE '; RW(.26.):= 'ARRAY ';
RW(.27.):= 'CONST '; RW(.28.):= 'LABEL ';
RW(.29.):= 'REPEAT '; RW(.30.):= 'RECORD '; RW(.31.):= 'DOWNTO ';
RW(.32.):= 'PACKED '; RW(.33.):= 'ORIGIN '; RW(.34.):= 'STRING ';
RW(.35.):= 'FORWARD ';
RW(.36.):= 'PROGRAM '; RW(.37.):= 'FUNCTION'; RW(.38.):= 'PROCEDUR';
RW(.39.):= 'OTHERWIS'; RW(.40.):= 'SUBPROGR';
FRW(.1.) := 1; FRW(.2.) := 1; FRW(.3.) := 7; FRW(.4.) := 15;
FRW(.5.) := 23; FRW(.6.) := 29; FRW(.7.) := 35; FRW(.8.) := 37;
FRW(.9.) := NEXTRESWD; FRW(.10.) := NEXTRESWD;
FRW(.11.) := NEXTRESWD; FRW(.12.) := NEXTRESWD; FRW(.13.):= NEXTRESWD;
END (* RESWORDS *) ;
PROCEDURE SYMBOLS;
VAR C: CHAR;
BEGIN
RSY(.1.) := IFSY; RSY(.2.) := DOSY; RSY(.3.) := OFSY;
RSY(.4.) := TOSY; RSY(.5.) := RELOP; RSY(.6.) := ADDOP;
RSY(.7.) := ENDSY; RSY(.8.) := FORSY; RSY(.9.) := VARSY;
RSY(.10.) := MULOP; RSY(.11.) := MULOP; RSY(.12.) := SETSY;
RSY(.13.) := MULOP; RSY(.14.) := NOTSY; RSY(.15.) := THENSY;
RSY(.16.) := ELSESY; RSY(.17.) := WITHSY; RSY(.18.) := GOTOSY;
RSY(.19.) := CASESY; RSY(.20.) := TYPESY; RSY(.21.) := EXITSY;
RSY(.22.) := FILESY;
RSY(.23.) := BEGINSY; RSY(.24.) := UNTILSY; RSY(.25.) := WHILESY;
RSY(.26.) := ARRAYSY; RSY(.27.) := CONSTSY; RSY(.28.) := LABELSY;
RSY(.29.) := REPEATSY; RSY(.30.) := RECORDSY; RSY(.31.) := DOWNTOSY;
RSY(.32.) := PACKEDSY; RSY(.33.) := ORIGINSY; RSY(.34.) := STRINGSY;
RSY(.35.) := FORWARDSY;
RSY(.36.) := PROGSY; RSY(.37.) := FUNCSY; RSY(.38.) := PROCSY;
RSY(.39.) := OTHERWZSY;RSY(.40.) := SUBPROGSY;
(*PP*)FOR C := CHR(0) TO CHR(ORDMAXBASECHAR) DO SSY(.C.) := OTHERSY;
(*POSSIBLE PORTABILITY PROBLEM WITH "127"*)
SSY(.'+'.) := ADDOP; SSY(.'-'.) := ADDOP; SSY(.'*'.) := MULOP;
SSY(.'/'.) := MULOP; SSY(.'('.) := LPARENT; SSY(.')'.) := RPARENT;
SSY(.'='.) := RELOP; SSY(.','.) := COMMA; SSY(.'.'.) := PERIOD;
SSY(.':'.) := COLON;
SSY(.'Æ'.) := LBRACK; SSY(.'Å'.) := RBRACK; SSY(.'!'.) := ARROW;
SSY(.'!'.) := ADDOP ; SSY(.'&'.) := MULOP ;
SSY(.'ü'.) := NOTSY; SSY(.'<'.) := RELOP; SSY(.'>'.) := RELOP;
SSY(.'@'.) := ARROW; SSY(.';'.) := SEMICOLON;
END (* SYMBOLS *) ;
PROCEDURE RATORS;
VAR I: INTEGER; C: CHAR;
BEGIN
FOR I := 1 TO LASTRESWD (* NR OF RES WORDS *) DO ROP(.I.) := NOOP;
ROP(.5.) := INOP; ROP(.10.) := IDIV; ROP(.11.) := IMOD;
ROP(.6.) := OROP; ROP(.13.) := ANDOP;
(*PP*)FOR C := CHR(0) TO CHR(ORDMAXBASECHAR) DO SOP(.C.) := NOOP;
(*POSSIBLE PORTABILITY PROBLEM WITH "127"*)
SOP(.'+'.) := PLUS; SOP(.'-'.) := MINUS; SOP(.'*'.) := MUL;
SOP(.'='.) := EQOP; SOP(.'/'.) := RDIV;
SOP(.'<'.) := LTOP; SOP(.'>'.) := GTOP;
SOP(.'ø'.) := OROP; SOP(.'&'.) := ANDOP;
(*PP*)SOP(.'Æ'.) := NOOP; SOP(.'Å'.) := NOOP;
(* INITIALIZE CHARACTER TABLE FOR INSYMBOL *)
(*PP*)FOR C := CHR(0) TO CHR(ORDMAXBASECHAR) DO CHTAB(.C.) := ILLEGALCHAR;
(*POSSIBLE PORTABILITY PROBLEM WITH "127"*)
FOR C := 'a' TO 'z' DO CHTAB(.C.) := ATOZ;
FOR C := 'A' TO 'Z' DO CHTAB(.C.) := ATOZ;
FOR C := '0' TO '9' DO CHTAB(.C.) := NUMBER;
CHTAB(.'_'.) := ATOZ; CHTAB(. '$' .) := ATOZ;
CHTAB(.'*'.) := MISCCHAR; CHTAB(.'+'.) := MISCCHAR;
CHTAB(.'-'.) := MISCCHAR; CHTAB(.'='.) := MISCCHAR;
CHTAB(.'/'.) := MISCCHAR; CHTAB(.')'.) := MISCCHAR;
CHTAB(.'&'.) := MISCCHAR; CHTAB(.'@'.) := MISCCHAR;
CHTAB(.','.) := MISCCHAR; CHTAB(.';'.) := MISCCHAR;
(*PP*)CHTAB(.'Æ'.) := MISCCHAR; CHTAB(.'Å'.) := MISCCHAR;
(*PP*)CHTAB(.'æ'.) := CMNTBRACK; CHTAB(.'!'.) := MISCCHAR;
CHTAB(.':'.) := COLONCHAR;
CHTAB(.'.'.) := PERIODCHAR; CHTAB(.''''.):= STRQUOTE;
CHTAB(.'<'.) := LPOINTY; CHTAB(.'>'.) := RPOINTY;
CHTAB(.'('.) := LPARN;
CHTAB(.' '.) := BLANKCHAR; CHTAB(.CHR(9).) := BLANKCHAR; (* TAB CHAR
*)
(* INITIALIZE ASCII TABLE FOR CASESTATEMENT, ETC. *)
(*PP*)FOR C := CHR(0) TO CHR(ORDMAXBASECHAR) DO ASCII(.C.) := 95 (*UNDERLINE*
); (*POSSIBLE PORTABILITY PROBLEM WITH "127"*)
ASCII(.'a'.):= 97; ASCII(.'b'.):= 98; ASCII(.'c'.):= 99; ASCII(.'d'.):=10
0; ASCII(.'e'.):=101; ASCII(.'f'.):=102; ASCII(.'g'.):=103; ASCII(.'h'.):=10
4; ASCII(.'i'.):=105; ASCII(.'j'.):=106; ASCII(.'k'.):=107; ASCII(.'l'.):=01
8; ASCII(.'m'.):=109; ASCII(.'n'.):=110; ASCII(.'o'.):=111; ASCII(.'p'.):=11
2; ASCII(.'q'.):=113; ASCII(.'r'.):=114; ASCII(.'s'.):=115; ASCII(.'t'.):=11
6; ASCII(.'u'.):=117; ASCII(.'v'.):=118; ASCII(.'w'.):=119; ASCII(.'x'.):=12
0; ASCII(.'y'.):=121; ASCII(.'z'.):=122; ASCII(.'A'.):= 65; ASCII(.'B'.):= 6
6; ASCII(.'C'.):= 67; ASCII(.'D'.):= 68; ASCII(.'E'.):= 69; ASCII(.'F'.):= 7
0; ASCII(.'G'.):= 71; ASCII(.'H'.):= 72; ASCII(.'I'.):= 73; ASCII(.'J'.):= 7
4; ASCII(.'K'.):= 75; ASCII(.'L'.):= 76; ASCII(.'M'.):= 77; ASCII(.'N'.):= 7
8; ASCII(.'O'.):= 79; ASCII(.'P'.):= 80; ASCII(.'Q'.):= 81; ASCII(.'R'.):= 8
2; ASCII(.'S'.):= 83; ASCII(.'T'.):= 84; ASCII(.'U'.):= 85; ASCII(.'V'.):= 8
6; ASCII(.'W'.):= 87; ASCII(.'X'.):= 88; ASCII(.'Y'.):= 89; ASCII(.'Z'.):= 9
0; ASCII(.'0'.):= 48; ASCII(.'1'.):= 49; ASCII(.'2'.):= 50; ASCII(.'3'.):= 5
1; ASCII(.'4'.):= 52; ASCII(.'5'.):= 53; ASCII(.'6'.):= 54; ASCII(.'7'.):= 5
5; ASCII(.'8'.):= 56; ASCII(.'9'.):= 57;
ASCII(.' '.) := 32; ASCII(.'*'.) := 42; ASCII(.'>'.) := 62;
ASCII(.'!'.) := 33; ASCII(.'+'.) := 43; ASCII(.'?'.) := 63;
ASCII(.'"'.) := 34; ASCII(.','.) := 44; ASCII(.'@'.) := 64;
ASCII(.'#'.) := 35; ASCII(.'-'.) := 45; ASCII(.'Æ'.) := 91;
ASCII(.'$'.) := 36; ASCII(.'.'.) := 46; ASCII(.'Ø'.) := 92;
ASCII(.'%'.) := 37; ASCII(.'/'.) := 47; ASCII(.'Å'.) := 93;
ASCII(.'&'.) := 38; ASCII(.':'.) := 58; ASCII(.'!'.) := 94;
ASCII(.''''.):= 39; ASCII(.';'.) := 59; ASCII(.'_'.) := 95;
ASCII(.'('.) := 40; ASCII(.'<'.) := 60; ASCII(.'`'.) := 96;
ASCII(.')'.) := 41; ASCII(.'='.) := 61;
(* POTENTIAL PORTABILITY PROBLEM WITH THE FOLLOWING CHARACTERS ON A
EBCDIC MACHINE *)
ASCII(.'æ'.) := 123; ASCII(.'ø'.) := 124; ASCII(.'å'.) := 125
; ASCII(.'^'.) := 126;
END (* RATORS *) ;
PROCEDURE INSTRMNEMONICS;
BEGIN
MN(. 0.) :='AB ';MN(. 1.) :='AD ';MN(. 2.) :='AFI ';MN(. 3.) :='AND ';
MN(. 4.) :='AST ';MN(. 5.) :='ATN ';MN(. 6.) :='CHK ';MN(. 7.) :='CLO ';
MN(. 8.) :='COS ';MN(. 9.) :='CSP ';MN(.10.) :='CSPF';MN(.11.) :='CUP ';
MN(.12.) :='CUPF';MN(.13.) :='CVT ';MN(.14.) :='CVB ';MN(.15.) :='DAS ';
MN(.16.) :='DEC ';MN(.17.) :='DEF ';MN(.18.) :='DIF ';MN(.19.) :='DIS ';
MN(.20.) :='DV ';MN(.21.) :='ENT ';MN(.22.) :='ENTB';MN(.23.) :='EOF ';
MN(.24.) :='EOL ';MN(.25.) :='EQU ';MN(.26.) :='EXIT';MN(.27.) :='EXP ';
MN(.28.) :='EXT ';MN(.29.) :='FJP ';MN(.30.) :='GEQ ';MN(.31.) :='GET ';
MN(.32.) :='GRT ';MN(.33.) :='IFD ';MN(.34.) :='INC ';MN(.35.) :='IND ';
MN(.36.) :='INN ';MN(.37.) :='INS ';MN(.38.) :='INT ';MN(.39.) :='IOR ';
MN(.40.) :='ISC ';MN(.41.) :='IXA ';MN(.42.) :='LAB ';MN(.43.) :='LCA ';
MN(.44.) :='LDA ';MN(.45.) :='LDC ';MN(.46.) :='LEQ ';MN(.47.) :='LES ';
MN(.48.) :='LOD ';MN(.49.) :='LOG ';MN(.50.) :='LSC ';MN(.51.) :='LSPA';
MN(.52.) :='LTA ';MN(.53.) :='LUPA';MN(.54.) :='MOD ';MN(.55.) :='MOV ';
MN(.56.) :='MOVV';MN(.57.) :='MP ';MN(.58.) :='MRK ';MN(.59.) :='NEQ ';
MN(.60.) :='NEW ';MN(.61.) :='NG ';MN(.62.) :='NOT ';MN(.63.) :='ODD ';
MN(.64.) :='PAG ';MN(.65.) :='PEE ';MN(.66.) :='POS ';MN(.67.) :='POK ';
MN(.68.) :='PUT ';MN(.69.) :='RDB ';MN(.70.) :='RDC ';MN(.71.) :='RDE ';
MN(.72.) :='RDI ';MN(.73.) :='RDJ ';MN(.74.) :='RDQ ';MN(.75.) :='RDR ';
MN(.76.) :='RDS ';MN(.77.) :='RET ';MN(.78.) :='RLN ';MN(.79.) :='RLS ';
MN(.80.) :='RST ';MN(.81.) :='RWT ';MN(.82.) :='SB ';MN(.83.) :='SCON';
MN(.84.) :='SCOP';MN(.85.) :='SDEL';MN(.86.) :='SEE ';MN(.87.) :='SGS ';
MN(.88.) :='SIN ';MN(.89.) :='SINS';MN(.90.) :='SLEN';MN(.91.) :='SPOS';
MN(.92.) :='SQR ';MN(.93.) :='SQT ';MN(.94.) :='STO ';MN(.95.) :='STP ';
MN(.96.) :='STR ';MN(.97.) :='TRC ';MN(.98.) :='UJP ';MN(.99.) :='UNI ';
MN(.100.):='WLN ';MN(.101.):='WRB ';MN(.102.):='WRC ';MN(.103.):='WRE ';
MN(.104.):='WRI ';MN(.105.):='WRJ ';MN(.106.):='WRQ ';MN(.107.):='WRR ';
MN(.108.):='WRS ';MN(.109.):='XJP ';MN(.110.):='RND ';MN(.111.):='EIO ';
MN(.112.):='MST ';MN(.113.):='VJP ';MN(.114.):='RDV ';MN(.115.):='WRV ';
MN(.116.):='ARG ';MN(.117.):='RDH ';MN(.118.):='WRH ';
(*IF MN GETS BIGGER CHANGE TYPE "MNRANGE"*)
END (* INSTRMNEMONICS *) ;
PROCEDURE UPPERCASE; (* FOR INSYMBOL TO CONVERT TO UPPERCASE
INTERNAL FORM OF IDENTIFIERS *)
VAR C: CHAR;
BEGIN
(*PP*) FOR C := CHR(0) TO CHR(ORDMAXBASECHAR) DO UPPER(.C.) := C;
(*PP*) FOR C := 'a' TO 'z' DO UPPER(.C.) := CHR(ORD(C)-ORD('a')+ORD('A'))
; END;
BEGIN (* INITTABLES *)
RESWORDS;
SYMBOLS;
RATORS;
INSTRMNEMONICS;
UPPERCASE;
END (* INITTABLES *) ;
BEGIN (* **START** PASCALCOMPILER *)
WRITELN(OUTPUT,' MOTOROLA PASCAL COMPILER VERSION ', VERSION);
WRITELN(OUTPUT,' COPYRIGHTED 1980 BY MOTOROLA, INC.');
INITSCALARS; (* INITIALIZE GLOBAL SCALARS *)
INITSETS; (* INITIALIZE GLOBAL SETS *)
INITTABLES; (* INITIALIZE GLOBAL TABLES *)
ENTERSTDTYPES; (* INITIALIZE HEAP WITH STANDARD TYPES *)
ENTSTDNAMES; (* INITIALIZE HEAP WITH STANDARD NAMES *)
ENTERUNDECL; (* INITIALIZE HEAP WITH UNDECLARED DEFAULTS *)
RESET(SOURCE);
REWRITE(PCODE);
REWRITE(LISTING);
NEWPAGE;
WRITELN(PCODE,'.',HEADER);
READLINE;
INSYMBOL; (* GET FIRST SYMBOL *)
PROGRAMME(BLOCKBEGSYS + STATBEGSYS - (. CASESY .));
(* SUMMERIZE COMPILATION *)
IF PAGEEND - PAGEPOS < 9 THEN NEWPAGE;
WRITELN(LISTING,' ');
WRITELN(LISTING,' ');
WRITE(LISTING, STARS:15);
IF ERRORCOUNT = 0 THEN
WRITE(LISTING,'NO')
ELSE
WRITE(LISTING,ERRORCOUNT:0);
WRITE(LISTING,'ERROR(S) AND ':14);
IF WARNCOUNT = 0 THEN
WRITE(LISTING,'NO')
ELSE
WRITE(LISTING,WARNCOUNT:0);
WRITELN(LISTING,'WARNING(S) DETECTED':20);
WRITELN(LISTING,' ');
IF (ERRORCOUNT <> 0) OR (WARNCOUNT <> 0) THEN
BEGIN
WRITELN(LISTING, STARS:15,'LAST ERROR LINE WAS ', LASTERR:0);
WRITELN(LISTING,' ')
END;
WRITE(LISTING, STARS:15,LINECOUNT:0,'LINES ':7);
WRITELN(LISTING, PROCLAB:0,'PROCEDURES':11);
WRITELN(LISTING,' ');
WRITELN(LISTING, STARS:15,OLDIC:0, 'PCODE INSTRUCTIONS':19);
WRITELN(OUTPUT,' ');
WRITE(OUTPUT, STARS:6);
IF ERRORCOUNT = 0 THEN
WRITE(OUTPUT,'NO')
ELSE
WRITE(OUTPUT,ERRORCOUNT:0);
WRITELN(OUTPUT,'ERROR(S) DETECTED IN COMPILATION ****':38)
END.
▶EOF◀