|
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: 316416 (0x4d400) Types: TextFile Names: »tm68000pasc«
└─⟦00964e8f7⟧ Bits:30007478 RC8000 Dump tape fra HCØ. └─⟦b2ec5d50f⟧ └─⟦this⟧ »tm68000pasc«
(* 20 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; * * NEW GLOBALS WARNINGS:BOOLEAN AND WARNCOUNT: * * 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 * * * * TO PERMIT COMPILATION ON THE RC8000 THE FOLLOWING * * CHANGES ARE MADE: * * 10/08/81 @ REPLACED BY ^ * * (. REPLACED BY Æ * * .) REPLACED BY Å * * THE PAGE SHIFT OPTION "E" IS REPLACED * * BY THE CHAR-VALUE "12". * * THE TYPE "FILE OF CHAR" USED IN THE * * VARIABLE DECLARATION REPLACED BY "TEXT".* * THE STANDARD PROCEDURE "HALT", WHICH IS * * NOT IMPLEMENTED ON THE RC8000, USED IN * * PROCEDURE "READLINE", IS REPLACED BY A * * GOTO STATEMENT. * * THE STANDARD PROCEDURES "MARK" AND * * "RELEASE" USED AT THE BOTTOM OF * * PROCEDURE "PARAMETERLIST" ARE NOT * * AVIABLE ON THE RC8000 AND CANNOT BE * * USED. THEIR EFFECT WAS MERELY TO * * RELEASE UNUSED STRUCTURES IN THE * * DYNAMIC STORAGE. * * 01/11/82 COMMENT PARANTESIS "(*...*')" AROUND * * EMPTY TAGFIELDS IN VARIANT RECORDS ARE * * REMOVED.(REQ'D BY AMSTERDAM BUT NOT * * ALLOWED BY BERKELY) * * HENRIK JACOBSEN HCØ * * * * NEXTCOMMENT * *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*) PROGRAM PASCALCOMPILER(OUTPUT, SOURCE, PCODE, LISTING); LABEL 99; 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,NOTSY, MULOP,ADDOP,RELOP,LPARENT,RPARENT,LBRACK,RBRACK,COMMA,SEMICOLON, 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: (); (*REQ'D BY AMSTERDAM NOT ALLOWED BY BERKELY*) 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: ( ); (*REQ'D BY AMSTERDAM EPS *) (*NOT ALLOWED 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 REQ'D BY AMSTERDAM EPS *) (*BUT NOT ALLOWED 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: ( ); (* REQ'D BY AMSTERDAM EPS *) (* NOT ALLOWED 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: TEXT; (*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*) GOTO 99 (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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 *) \f (*-------------------------------------------------------------------*) (* *) (* PROCEDURE OPTIONS *) (* *) (* THIS PROCEDURE PROCESSES THE OPTIONS IN A COMMENT. *) (* *) (*--------------------------------------------------------------------*) PROCEDURE OPTIONS; \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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 IDENTIFIER*) 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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 REST*) 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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*) \f (*-------------------------------------------------------------------*) (* *) (* 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) THEN 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 *) ; \f (*-------------------------------------------------------------------*) (* *) (* 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; \f (*------------------------------------------------------------------------- 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 SUBRANGE*) 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);NOTICE COMMENT 10/08/81 *) 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; HJALFA:ALFA; BEGIN IF PRCODE THEN BEGIN IF OPTYPE = 'R' THEN (*OUTPUT REAL VALUE*) BEGIN FOR I:=0 TO REALLNGTH DO HJALFA ÆI+1Å:=LVP^.RVAL ÆIÅ; WRITELN(PCODE, MNÆFOPÅ:5, OPTYPE:3, ' ', HJALFA) END 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.IVAL) 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 *) ; \f (*-------------------------------------------------------------------*) (* *) (* 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; \f (*-------------------------------------------------------------------*) (* 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 *); \f (*------------------------------------------------------------------------- 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 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 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) THEN 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^.SIZE); (*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Å) END 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) THEN 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^.SIZE); GATTR.TYPTR := LSP END END ELSE IF (GATTR.KIND = VARBL) OR (GATTR.KIND = FILEPTR) THEN BEGIN LOADADDRESS; IF GATTR.TYPTR^.SIZE <> LSP^.SIZE THEN 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 *); \f (*-------------------------------------------------------------------*) (* *) (* 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) THEN CONVERTTOLIKEINTEGERS (LATTR.TYPTR, GATTR.TYPTR) ELSE IF CHARARRAY(LATTR.TYPTR) AND (GATTR.TYPTR^.FORM = STRINGS) THEN BEGIN GEN2TI(13(* CVT *),'S','V',LATTR.TYPTR^.SIZE); GATTR.TYPTR := LATTR.TYPTR END ELSE IF CHARARRAY(GATTR.TYPTR) AND (LATTR.TYPTR^.FORM = STRINGS) THEN BEGIN GEN2TI(14(* CVB *),'S','V',GATTR.TYPTR^.SIZE); 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)THEN BEGIN GEN2T(13( CVT ),'I','R'); GATTR.TYPTR := REALPTR END ELSE *) IF (GATTR.TYPTR^.FORM=STRINGS) AND CHARARRAY(LATTR.TYPTR) 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) THEN 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(410) 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; PFDECKIND := 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'Å:=100; ASCIIÆ'e'Å:=101; ASCIIÆ'f'Å:=102; ASCIIÆ'g'Å:=103; ASCIIÆ'h'Å:=104; ASCIIÆ'i'Å:=105; ASCIIÆ'j'Å:=106; ASCIIÆ'k'Å:=107; ASCIIÆ'l'Å:=018; ASCIIÆ'm'Å:=109; ASCIIÆ'n'Å:=110; ASCIIÆ'o'Å:=111; ASCIIÆ'p'Å:=112; ASCIIÆ'q'Å:=113; ASCIIÆ'r'Å:=114; ASCIIÆ's'Å:=115; ASCIIÆ't'Å:=116; ASCIIÆ'u'Å:=117; ASCIIÆ'v'Å:=118; ASCIIÆ'w'Å:=119; ASCIIÆ'x'Å:=120; ASCIIÆ'y'Å:=121; ASCIIÆ'z'Å:=122; ASCIIÆ'A'Å:= 65; ASCIIÆ'B'Å:= 66; ASCIIÆ'C'Å:= 67; ASCIIÆ'D'Å:= 68; ASCIIÆ'E'Å:= 69; ASCIIÆ'F'Å:= 70; ASCIIÆ'G'Å:= 71; ASCIIÆ'H'Å:= 72; ASCIIÆ'I'Å:= 73; ASCIIÆ'J'Å:= 74; ASCIIÆ'K'Å:= 75; ASCIIÆ'L'Å:= 76; ASCIIÆ'M'Å:= 77; ASCIIÆ'N'Å:= 78; ASCIIÆ'O'Å:= 79; ASCIIÆ'P'Å:= 80; ASCIIÆ'Q'Å:= 81; ASCIIÆ'R'Å:= 82; ASCIIÆ'S'Å:= 83; ASCIIÆ'T'Å:= 84; ASCIIÆ'U'Å:= 85; ASCIIÆ'V'Å:= 86; ASCIIÆ'W'Å:= 87; ASCIIÆ'X'Å:= 88; ASCIIÆ'Y'Å:= 89; ASCIIÆ'Z'Å:= 90; ASCIIÆ'0'Å:= 48; ASCIIÆ'1'Å:= 49; ASCIIÆ'2'Å:= 50; ASCIIÆ'3'Å:= 51; ASCIIÆ'4'Å:= 52; ASCIIÆ'5'Å:= 53; ASCIIÆ'6'Å:= 54; ASCIIÆ'7'Å:= 55; 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); 99: (* THE GOTO STATEMENT IS IN PROCEDURE "READLINE" *) END. ▶EOF◀