12330 (*+81()
12340 (**)
12350 (*+04()
12360 FUNCTION FLOAT(N: A68INT): REAL;
12370     BEGIN FLOAT := SHRINK(N) (*THIS IS SLOPPY*) END;
12380 ()+04*)
12390 (*+25()   (*+31()   (*$P+  +)   ()+31+)    ()+25*)
12400 (**)
12410 (**)
12420                (*LISTING*)
12430                (*********)
12440 (**)
12450 (*+05()
12460 PROCEDURE OPENLOADFILE(VAR F: LOADFILE; PARAM: INTEGER; WRITING: BOOLEAN);
12470   VAR S: ARGSTRING;
12480   PROCEDURE NAMEFILE(S: ARGSTRING; SU, SL: INTEGER; VAR F: ANYFILE); EXTERN;
12490   FUNCTION GETARG(VAR S: ARGSTRING; SU, SL: INTEGER; I: INTEGER): BOOLEAN; EXTERN;
12500     BEGIN
12510     IF GETARG(S, 50 ,1, PARAM) THEN
12520       NAMEFILE(S, 50, 1, F);
12530     IF WRITING THEN REWRITE(F) ELSE RESET(F);
12540     END;
12550 PROCEDURE OPENTEXT(VAR F: TEXT; PARAM: INTEGER; WRITING: BOOLEAN);
12560   VAR S: ARGSTRING;
12570   PROCEDURE NAMEFILE(S: ARGSTRING; SU, SL: INTEGER; VAR F: ANYFILE); EXTERN;
12580   FUNCTION GETARG(VAR S: ARGSTRING; SU, SL: INTEGER; I: INTEGER): BOOLEAN; EXTERN;
12590     BEGIN
12600     IF GETARG(S, 50, 1, PARAM) THEN
12610       NAMEFILE(S, 50, 1, F);
12620     IF WRITING THEN REWRITE(F) ELSE RESET(F);
12630     END;
12632 FUNCTION TIME: INTEGER; EXTERN;
12634 PROCEDURE CTIME(VAR RESULT: TIMSTRING; SU, SL: INTEGER; CLOCK: INTEGER); EXTERN;
12640 ()+05*)
12650 (**)
12660 (**)
12670 PROCEDURE CHECKPAGE;
12680   (*STARTS NEW PAGE IF LISTING IN PROGRESS AND OLD PAGE
12690     EXHAUSTED*)
12700     BEGIN
12710     IF LSTCNT>LINESPERPAGE THEN
12720       BEGIN
12730       LSTCNT := 0;
12740       IF PRGLIST IN PRAGFLGS THEN
12750         BEGIN
12760         LSTPAGE := LSTPAGE+1;
12770         IF ONLINE THEN
12780         BEGIN
12782 (*-01() IF LSTPAGE<>1 THEN PAGE(LSTFILE); ()-01*)
12790         WRITELN(LSTFILE, (*+01()'1',()+01*)
12800                 'ALGOL68S COMPILER ',VERSIONNUM,
12810         (*-04() (*-02() (*-05()DAT, ' ',()-05*) TIM, ()-02*) ()-04*) '             PAGE ', LSTPAGE:3);
12820         WRITELN(LSTFILE (*+01(),' '()+01*));
12830         END
12840 (*-02() (*-04() (*-05()
12850         ELSE  (*BATCH*)
12860         BEGIN
12862 (*-01() IF LSTPAGE<>1 THEN PAGE(LSTFILE); ()-01*)
12870         WRITELN(OUTPUT, (*+01()'1',()+01*)
12880                 'ALGOL68S COMPILER ',VERSIONNUM,
12890         DAT, ' ', TIM, '             PAGE ', LSTPAGE:3);
12900         WRITELN(OUTPUT, ' ');
12910         END
12920 ()-05*) ()-04*) ()-02*)
12930         END
12940       END;
12950     END;
12960 (**)
12970 (**)
12980 PROCEDURE INITIO;
12990 (*+01()   VAR AW66: PW66; ()+01*)
13000 (*+05()   TYPE STRING = PACKED ARRAY [1..12] OF CHAR;
13010           VAR S: STRING;
13020 ()+05*)
13030     BEGIN
13040     ERRDEV := FALSE;
13050 (*+23()   NUMPARAMS:=0;  (* TO COUNT NO OF P-OP PARAMETERS OUTPUT TO LSTFILE *)  ()+23*)
13060     LSTLINE := -1;  (*FOR FIRST TIME OF OUTSRC*)
13070     LSTCNT := 100;         (*TO FORCE NEWPAGE*)
13080     LSTPAGE := 0;
13090 (*-03() (*-04() (*-05()
13100     RESET(SOURCDECS);
13110     REWRITE(LSTFILE);
13120 ()-05*) ()-04*) ()-03*)
13130 (*+03()
13140 WRITE('SOURCE-FILE: ');
13150 OPEN(SOURCDECS,'','SYMB',SEQRD);
13160 WRITE('LIST-FILE: ');
13170 OPEN(LSTFILE,'','DATA',SEQWR);
13180 OPEN(OUTPUT,'TERMINAL','SYMB',SEQWR);
13190 ()+03*)
13200 (*+04()
13210     RESET(SOURCDECS, 'SOURCDECS');
13220     REWRITE(OUTPUT, 'CONSOLE');
13230     REWRITE(LSTFILE, 'LSTFILE');
13240 ()+04*)
13250 (*+05()
13260     OPENTEXT(SOURCDECS, 1, FALSE);
13270     OPENTEXT(LSTFILE, 3, TRUE);
13280 ()+05*)
13290     SRCBUF[0]  := ' '; (*IT WILL NEVER BE WRITTEN TO AGAIN*)
13300 (*+01()
13310     LINELIMIT(OUTPUT, 100000);
13320     AW66 := ASPTR(66B);
13330     ONLINE := AW66^.JOPR=3;
13340  ()+01*)
13350 (*+02() ONLINE := TRUE; ()+02*)
13360 (*+03() ONLINE := FILENR(LSTFILE)<>1; ()+03*)
13370 (*+04() ONLINE := TRUE; ()+04*)
13380 (*+05() ONLINE := TRUE; ()+05*)
13390 (*+01() DATE(DAT); TIME(TIM); ()+01*)
13392 (*+03() DATE(DAT); TIME(TIM); ()+03*)
13394 (*+05() CTIME(TIM, 26, 1, TIME); TIM[25] := CHR(0); ()+05*)
13400     END;
13410 (**)
13420 (**)
13430 PROCEDURE OUTLST(LINE: INTEGER; VAR BUF: BUFFER; PTR: INTEGER);
13440 (*FUNCTION: SEND A SINGLE RECORD TO THE LISTING DEVICE (AND
13450     POSSIBLY THE ERROR DEVICE AS WELL). THE PRAGMAT NOLIST MAY BE
13460     USED TO SUPPRESS THE PRINTING OF THE LISTING. IN THIS CASE,
13470     NO ACTION IS TAKEN UNLESS THE LINE IS BEING SENT TO THE ERROR
13480     DEVICE. ERROR LINES ARE ALWAYS TRANSMITTED.
13490   INPUTS:
13500     LINE  - THE LINE NUMBER; -VE IF NO NUMBER TO BE PRINTED
13510     BUF   - BUFFER CONTAINING THE LINE TO BE PRINTED; USUALLY
13520             SRCBUF OR ERRBUF
13530     PTR   - NUMBER OF CHARACTERS IN BUF; USUALLY SRCPTR OR ERRPTR
13540   GLOBALS:
13550     PRAGFLGS
13560     LSTCNT- THE NUMBER OF LINES ALREADY PRINTED ON THE CURRENT
13570             PAGE
13580     ERRDEV- TRUE IFF RECORD IS TO BE SENT TO ERROR DEVICE
13590     SRCSTAT-THE VALUE OF SRCSTCH AT THE BEGINNING OF THE LINE
13600 *)
13610   VAR I: INTEGER;
13620     BEGIN
13630     IF ONLINE THEN
13640     BEGIN
13650     IF PRGLIST IN PRAGFLGS THEN
13660       BEGIN
13662 (*+01() WRITE(LSTFILE, ' '); ()+01*)
13670       IF LINE>=0 THEN
13680         WRITE(LSTFILE, SRCSTAT, ' ', LINE:5, ' ')
13690       ELSE WRITE(LSTFILE, '        ');
13700       FOR I := 0 TO PTR DO
13710         WRITE(LSTFILE, BUF[I]);
13720       WRITELN(LSTFILE);
13730       LSTCNT := LSTCNT+1;
13740       END;
13750     IF ERRDEV THEN
13760       BEGIN
13770       IF LINE>=0 THEN
13780         WRITE(OUTPUT, SRCSTAT, ' ', LINE:5, ' ')
13790       ELSE WRITE(OUTPUT, '        ');
13800       FOR I := 0 TO PTR DO
13810         WRITE(OUTPUT, BUF[I]);
13820       WRITELN(OUTPUT);
13830       END
13840     END
13850 (*-02() (*-04() (*-05()
13860     ELSE  (*BATCH*)
13870     IF ERRDEV OR (PRGLIST IN PRAGFLGS) THEN
13880       BEGIN
13882 (*+01() WRITE(LSTFILE, ' '); ()+01*)
13890       IF LINE >=0 THEN
13900         WRITE(OUTPUT, SRCSTAT, ' ', LINE:5, ' ')
13910       ELSE WRITE(OUTPUT, '        ');
13920       FOR I := 1 TO PTR DO
13930         WRITE(OUTPUT, BUF[I]);
13940       WRITELN(OUTPUT);
13950       LSTCNT := LSTCNT+1
13960       END;
13970 ()-05*) ()-04*) ()-02*)
13980     END;
13990 (**)
14000 (**)
14010                 (*ERROR HANDLING*)
14020                 (****************)
14030 (**)
14040 PROCEDURE OUTERR(N: INTEGER; LEV: ERRLEV; LEX: PLEX);
14050 (*FUNCTION: OUTPUT ERROR MESSAGE AND WRITE CHARACTER TO
14060     APPROPRIATE POSITION IN ERRBUF.
14070   INPUTS:
14080     N - IDENTIFIES MESSAGE TO BE PRINTED
14090     LEV - INDICATES WARNING OR ERROR
14100   GLOBALS:
14110     ERRLXPTR - POINTS TO ERRBUF POSITION JUST BEFORE START OF
14120         OFFENDING LEXEME
14130     ERRDEV, ERRNONBLANK, ERRBUF, ERRS, LSTCNT, PRAGFLGS
14140 *)
14150   VAR I: INTEGER;
14160   PROCEDURE PRINTLEX(VAR F: TEXT);
14170     VAR I: INTEGER;
14180       BEGIN WITH LEX^ DO
14190         BEGIN
14200         WRITE(F, ' - ');
14210         CASE LXTOKEN OF
14220           TKTAG: (*NOTHING*);
14230           TKBOLD: WRITE(F, '.');
14240           TKSYMBOL: WRITE(F, '''');
14250           END;
14260         FOR I := 1 TO LXCOUNT*CHARPERWORD DO
14270           IF STRNG[I]<>' ' THEN WRITE(F, STRNG[I]);
14280         IF LXTOKEN=TKSYMBOL THEN WRITE(F, '''');
14290         END
14300       END;
14310 (**)
14320    PROCEDURE ERRMSG(VAR F: TEXT);
14330       BEGIN
14340       WRITE(F, '      ');
14350       CASE LEV OF
14360         ERRORR:  WRITE(F, 'ERROR   ');
14370         WARNING: WRITE(F, 'WARNING ')
14380         END;
14390 (*+55() WRITE(F,N:3); ()+55*)
14400 (*-55()
14410       CASE N OF
14420         (*ELX*)
14430         3: WRITE(F, 'MISSING CLOSE QUOTE IN STRING-DENOTATION');
14440         4: WRITE(F, 'MISSING CLOSE-PRAGMENT-SYMBOL');
14450         5: WRITE(F, 'ILLEGAL SYMBOL');
14460         6: WRITE(F, 'ILL-FORMED DENOTATION');
14470         7: WRITE(F, 'STRAY STROP MARK');
14480         8: WRITE(F, 'ILLEGAL CHARACTER');
14490         9: WRITE(F, 'IDENTIFIER OR STRING-DENOTATION TOO ',
14500                          'LONG, COMPLAIN TO CHL');
14510        10: WRITE(F, 'DENOTATION OUT OF RANGE');
14520       (*ESY*)
14530        11: WRITE(F, 'MISSING UNIT (OR EXTRA ;)');
14540        12: WRITE(F, 'DECLARER NOT FOUND WHERE EXPECTED');
14550        13: WRITE(F, 'ILLEGAL FORM OF TRIMMER OR MISPLACED COLON');
14560        14: WRITE(F, '.DO NOT FOUND WHERE EXPECTED');
14570        15: WRITE(F, 'FIELD NOT SPECIFIED PROPERLY');
14575        16: WRITE(F, 'MISMATCH AFTER ''[''');
14580        17: WRITE(F, 'MISMATCH AFTER ''(''');
14590        18: WRITE(F, 'END OF PROGRAM TEXT');
14600        19: WRITE(F, 'MISSING LABEL-DECLARATION FOLLOWING .EXIT');
14610        20: WRITE(F, 'MISSING = IN IDENTITY-DECLARATION');
14620        21: WRITE(F, 'INCORRECT VARIABLE-DECLARATION');
14630        22: WRITE(F, 'INCORRECT MODE-DECLARATION');
14640        23: WRITE(F, '.GOTO NOT FOLLOWED BY LABEL');
14650        24: WRITE(F, '.STRUCT NOT FOLLOWED BY ''(''');
14660        25: WRITE(F, 'MISPLACED PROCEDURE-PLAN');
14670        26: WRITE(F, 'MISSING DECLARER OR DENOTATION AFTER .LONG OR .SHORT');
14680        27: WRITE(F, 'ILLEGAL BOUNDS IN FORMAL-DECLARER');
14690        28: WRITE(F, 'FORMAL-PARAMETER NOT SPECIFIED PROPERLY');
14700        29: WRITE(F, 'PARAMETER MODE NOT SPECIFIED PROPERLY');
14710        30: WRITE(F, 'ACTUAL-BOUNDS NOT TERMINATED BY '','' OR '']''');
14720        31: WRITE(F, 'ADDITIONAL TEXT FOLLOWS A COMPLETE PROGRAM');
14730        32: WRITE(F, 'ILLEGAL ACTUAL-PARAMETER-LIST');
14740        33: WRITE(F, 'MISSING COLON IN ROUTINE-TEXT');
14750        34: WRITE(F, 'MISSING ;');
14760        35: WRITE(F, 'MISPLACED COMMA OR MISSING COMMA');
14770        36: WRITE(F, 'MISMATCH IN LOOP-CLAUSE');
14780        37: WRITE(F, 'MISMATCH AFTER .BEGIN');
14790        38: WRITE(F, 'MISMATCH IN CASE-CLAUSE');
14800        39: WRITE(F, 'MISMATCH IN IF-CLAUSE');
14810        40: WRITE(F, 'MISSING SEMICOLON AFTER DECLARATION');
14820        41: WRITE(F, 'MISPLACED ACTUAL-DECLARER');
14830        42: WRITE(F, 'LOOKS LIKE AN ILLEGAL DECLARATION');
14840        43: WRITE(F, 'ILLEGAL UNIT IN THIS CONTEXT');
14850        44: WRITE(F, 'ILLEGAL CONTEXT FOR DISPLAY IN ALGOL 68S');
14860        45: WRITE(F, 'MODE IS ILLEGAL IN ALGOL 68S');
14870        46: WRITE(F, 'MISSING IDENTIFIER AFTER .FOR');
14880        47: WRITE(F, 'ILL-FORMED DISPLAY OR DATA-LIST');
14890        48: WRITE(F, 'MISSING = IN OPERATION-DECLARATION');
14900        49: WRITE(F, 'MISSING BOUNDS IN ACTUAL-DECLARER');
14910        50: WRITE(F, 'INCORRECT PRIORITY-DECLARATION');
14920        51: WRITE(F, 'MISSING = OR := IN ROUTINE-DECLARATION');
14930        52: WRITE(F, 'ILLEGAL CASE-CLAUSE');
14940        53: WRITE(F, 'PRIORITY MUST BE A DIGIT');
14950 ()-55*)
14960 (*+53()
14970         END;
14980        IF LEX<>NIL THEN PRINTLEX(F);
14990        WRITELN(F);
15000        END;
15010   PROCEDURE ERRMSG2(VAR F: TEXT);
15020       BEGIN
15030       WRITE(F, '      ');
15040       CASE LEV OF
15050         ERRORR:  WRITE(F, 'ERROR   ');
15060         WARNING: WRITE(F, 'WARNING ');
15070         END;
15080 (*+55() WRITE(F,N:3); ()+55*)
15090 (*-55() CASE N OF ()-55*)
15100 ()+53*)
15110       (*ESE*)
15120 (*-55()
15130        61: WRITE(F, 'DUPLICATED FIELD-SELECTOR IN .STRUCT DECLARER');
15140        62: WRITE(F, 'LABEL-DECLARATION IN ENQUIRY-CLAUSE');
15150        63: WRITE(F, 'ILL-FORMED MODE IN MODE-DECLARATION');
15160        64: WRITE(F, 'LABEL PRECEDES A DECLARATION IN CURRENT RANGE');
15170        65: WRITE(F, 'LOCAL-GENERATOR MAY NOT PRECEDE FIRST DECLARATION OF RANGE IN ALGOL 68S');
15180        66: WRITE(F, 'TOO MANY .SHORTS');
15190        67: WRITE(F, 'LABEL ALREADY USED AS IDENTIFIER');
15200        68: WRITE(F, 'IDENTIFIER ALREADY USED IN THIS REACH');
15210        69: WRITE(F, 'IDENTIFIER ALREADY DECLARED');
15220        70: WRITE(F, 'VALUE DISCARDED WITHOUT BEING USED');
15230        71: WRITE(F, 'MODE-INDICATION ALREADY DECLARED');
15240        72: WRITE(F, 'MODE-INDICATION ALREADY USED IN THIS REACH');
15250        73: WRITE(F, 'LABEL ALREADY DECLARED');
15260        74: WRITE(F, 'SCOPE VIOLATION');
15270        75: WRITE(F, 'IDENTIFIER ALREADY USED AS LABEL');
15280        76: WRITE(F, 'IDENTIFIER NOT DECLARED');
15290        78: WRITE(F, 'DISPLAYS MUST BE IN STRONG NON-VOID POSITIONS');
15300        79: WRITE(F, 'TOO MANY .LONGS');
15310        80: WRITE(F, 'LEFT SIDE OF ASSIGNMENT IS NOT A VARIABLE');
15320        81: WRITE(F, '.NIL OCCURS IN NON-REF CONTEXT');
15330        82: WRITE(F, 'MONADIC-OPERATOR USED AS DYADIC-OPERATOR');
15340        83: WRITE(F, 'UNSUITABLE OPERAND FOR MONADIC-OPERATOR');
15350        84: WRITE(F, 'UNSUITABLE OPERANDS FOR DYADIC-OPERATOR');
15360        85: WRITE(F, 'THE OBJECT CALLED IS NOT A .PROC');
15370        86: WRITE(F, 'BALANCE CANNOT BE MADE IN A SOFT POSITION');
15380        87: WRITE(F, 'BALANCE CANNOT BE MADE IN A WEAK POSITION');
15390        88: WRITE(F, 'BALANCE CANNOT BE MADE IN A MEEK POSITION');
15400        89: WRITE(F, 'BALANCE CANNOT BE MADE IN A FIRM POSITION');
15410        90: WRITE(F, 'TOO MANY ACTUAL-PARAMETERS IN CALL');
15420        91: WRITE(F, 'ILLEGAL MODE FOR TRANSPUT');
15430        92: WRITE(F, 'STRING-SLICE MAY NOT CONTAIN .AT IN ALGOL 68S');
15440        93: WRITE(F, 'ILLEGAL MODE FOR THIS POSITION');
15450        94: WRITE(F, 'ENQUIRY IN IF-CLAUSE MUST BE .BOOL');
15460        95: WRITE(F, 'ENQUIRY IN CASE-CLAUSE MUST BE .INT');
15470        96: WRITE(F, 'ENQUIRY IN WHILE-PART OF LOOP-CLAUSE MUST BE .BOOL');
15480        97: WRITE(F, 'ENQUIRY IN BRIEF CHOICE-CLAUSE MUST BE .BOOL OR .INT');
15490        98: WRITE(F, '.GOTO UNDEFINED LABEL');
15500        99: WRITE(F, 'UNIT AFTER .TO, .BY OR .FROM MUST BE .INT');
15510       100: WRITE(F, 'JUMP MAY NOT OCCUR IN .PROC MODE CONTEXT IN ALGOL 68S');
15520       101: WRITE(F, 'PRIORITY MUST BE FROM 1 TO 9');
15530       102: WRITE(F, 'PRIORITY ALREADY GIVEN FOR THIS OPERATOR');
15540       103: WRITE(F, 'THE OBJECT AFTER .OF IS NOT A .STRUCT');
15550       104: WRITE(F, 'FIELD-SELECTOR NOT RECOGNIZED IN THIS .STRUCT');
15560       105: WRITE(F, 'ROWED NAME USED IN IDENTITY-RELATION');
15570       106: WRITE(F, 'MODE-INDICATION NOT DECLARED');
15580       107: WRITE(F, 'THE OBJECT SLICED IS NOT AN ARRAY');
15590       108: WRITE(F, 'TOO MANY TRIMSCRIPTS IN SLICE');
15600       109: WRITE(F, 'TOO FEW TRIMSCRIPTS IN SLICE');
15610       110: WRITE(F, 'UNIT AFTER .AT MUST BE .INT');
15620       111: WRITE(F, 'UNIT IN SUBSCRIPT MUST BE .INT');
15630       112: WRITE(F, 'UNIT IN LOWER-BOUND MUST BE .INT');
15640       113: WRITE(F, 'UNIT IN UPPER-BOUND MUST BE .INT');
15650       114: WRITE(F, 'TOO FEW/MANY PARAMETERS FOR OPERATOR');
15660       115: WRITE(F, 'PRIORITY-DECLARATION MUST PRECEDE OPERATOR-DECLARATION IN ALGOL 68S');
15670       116: WRITE(F, 'A MEEKLY-RELATED OPERATOR ALREADY EXISTS');
15680       117: WRITE(F, 'OPERAND OF IDENTITY-RELATION IS NOT A NAME');
15690       118: WRITE(F, 'TOO FEW UNITS IN STRUCTURE-DISPLAY');
15700       119: WRITE(F, 'TOO MANY UNITS IN STRUCTURE-DISPLAY');
15710       120: WRITE(F, 'DISPLAY DOES NOT HAVE REQUIRED MODE');
15720       121: WRITE(F, 'A JUMP TO THIS LABEL BYPASSES A DECLARATION');
15730       122: WRITE(F, 'TOO MANY INTERMEDIATE VALUES (POSSIBLE RUNTIME ERROR)');
15740       123: WRITE(F, 'IDENTIFIER USED BEFORE DECLARATION COMPLETE');
15750       132: WRITE(F, 'TOO FEW ACTUAL-PARAMETERS IN CALL');
15760       133: WRITE(F, '.LOC OMITTED IN VARIABLE-DECLARATION');
15770         END;
15780 ()-55*)
15790       IF LEX<>NIL THEN PRINTLEX(F);
15800       WRITELN(F);
15810       END;
15820   (*START OF OUTERR*)
15830     BEGIN
15840     IF (LEV=ERRORR) OR (PRGWARN IN PRAGFLGS) THEN
15850       BEGIN
15860       ERRDEV := TRUE;
15870       IF ERRPTR<ERRLXPTR THEN
15880         BEGIN
15890         FOR I := ERRPTR+1 TO ERRLXPTR-1 DO ERRBUF[I] := ERRCHAR;
15900         ERRPTR := ERRLXPTR;
15910         ERRBUF[ERRLXPTR] := '1'
15920         END
15930       ELSE
15940       ERRBUF[ERRLXPTR] :=
15950         CHR((ORD(ERRBUF[ERRLXPTR])-ORD('0')+1) MOD 10 + ORD('0'));
15960       ERRNONBLANK := TRUE;
15970       IF ONLINE THEN
15980       BEGIN
15990 (*+53()     IF N<=ESE THEN ERRMSG(OUTPUT) ELSE ERRMSG2(OUTPUT);   ()+53*)
16000 (*-53()     ERRMSG(OUTPUT);   ()-53*)
16010       IF PRGLIST IN PRAGFLGS THEN
16020         BEGIN
16030         IF LSTCNT>4+LINESPERPAGE THEN CHECKPAGE;
16040 (*+01() WRITE(LSTFILE, ' '); ()+01*)
16050 (*+53() IF N<=ESE THEN ERRMSG(LSTFILE) ELSE ERRMSG2(LSTFILE); ()+53*)
16060 (*-53() ERRMSG(LSTFILE); ()-53*)
16070         LSTCNT := LSTCNT+1;
16080         END;
16090       END
16100 (*-02() (*-04() (*-05()
16110       ELSE  (*BATCH*)
16120       BEGIN
16130       IF LSTCNT>4+LINESPERPAGE THEN CHECKPAGE;
16140 (*+01()WRITE(OUTPUT, ' '); ()+01*)
16150 (*+53()     IF N<=ESE THEN ERRMSG(OUTPUT) ELSE ERRMSG2(OUTPUT);   ()+53*)
16160 (*-53()     ERRMSG(OUTPUT);   ()-53*)
16170       LSTCNT := LSTCNT+1;
16180       END
16190 ()-05*) ()-04*) ()-02*)
16200 ;     IF LEV=ERRORR THEN
16210         ERRS := ERRS+1
16220       ELSE WARNS := WARNS+1
16230       END
16240     END;
16250 (**)
16260 (**)
16270 PROCEDURE SEMERR(N: INTEGER);
16280 (*FUNCTION: PRINT ERROR MESSAGE PRODUCED BY SEMANTIC ROUTINES.
16290     A FUTURE VERSION OF THIS PROCEDURE MIGHT INCREMENT A SPECIAL COUNTER
16300     (AS DISTINCT FROM ERRS) FOR SEMANTIC ERRORS.
16310 *)
16320     BEGIN OUTERR(N, ERRORR, NIL); SEMERRS := SEMERRS+1 END;
16330 (**)
16340 (**)
16350 PROCEDURE SEMERRP(N: INTEGER; LEX: PLEX);
16360 (*FUNCTION: PRINTS ERROR MESSAGE FOLLOWED BY THE OFFENDING LEXEME*)
16370     BEGIN OUTERR(N, ERRORR, LEX); SEMERRS := SEMERRS+1 END;
16380 (**)
16390 (**)
16400 PROCEDURE MODERR(M: MODE; N: INTEGER);
16410 (*FUNCTION: PRINTS ERROR MESSAGE UNLESS M=MDERROR*)
16420     BEGIN
16430     IF (M<>MDERROR) AND (M<>PRCERROR) THEN
16440       BEGIN OUTERR(N, ERRORR, NIL); SEMERRS := SEMERRS+1 END
16450     END;
16460 (**)
16470 ()+81*)
16480 (*+82()
16490 (**)
16500                 (*LEXICAL ANALYSIS*)
16510                 (******************)
16520 (**)
16530 PROCEDURE OUTSRC;
16540 (*FUNCTION: OUTPUT A LINE OF SOURCE ON THE LISTING DEVICE.
16550     IF AN ERROR OCCURRED IN THE LINE OR THE LINE WAS IGNORED DUE
16560     TO A PREVIOUS ERROR, THEN A LINE OF ERROR INDICATION IS ALSO
16570     OUTPUT.IF AN ERROR OCCURRED IN THE LINE, THEN ERRORDEV WILL
16580     BE TRUE AND THUS ALL OUTPUT WILL GO TO THE ERROR DEVICE ALSO.
16590   GLOBALS:
16600     SRCBUF, SRCPTR - SOURCE BUFFER
16610     ERRBUF, ERRPTR - BUFFER CONTAINING ERROR INDICATIONS
16620     ERRNONBLANK - FALSE IF NO ERROR INDICATIONS
16630     ERRLXPTR
16640     PRAGFLGS
16650     INDEX - INDEX TYPE OF CURRENT CHARACTER
16660     LSTLINE - LINE NUMBER
16670     SRCSTAT, SRCSTCH
16680 *)
16690   VAR I: INTEGER;
16700     BEGIN
16710     IF LSTCNT>4+LINESPERPAGE THEN CHECKPAGE;  (*MAINLY FOR FIRST TIME*)
16720     OUTLST(LSTLINE, SRCBUF, SRCPTR);
16730     IF ERRNONBLANK THEN
16740       BEGIN
16750       FOR I := ERRPTR+1 TO SRCPTR DO ERRBUF[I] := ERRCHAR;
16760       OUTLST(-1, ERRBUF, SRCPTR);
16770       IF ERRCHAR=' ' THEN
16780         ERRNONBLANK := FALSE;
16790       ERRDEV := FALSE
16800       END;
16810     IF INDEX=EOL THEN
16820       IF EOF(SOURCDECS) THEN INDEX := EOFF
16830       ELSE IF (LINENUMBERS IN PRAGFLGS) THEN
16840         BEGIN READ(SOURCDECS, LSTLINE); IF SOURCDECS^=' ' THEN GET(SOURCDECS); END
16850       ELSE LSTLINE := LSTLINE+1;
16860     SRCPTR := 0; ERRPTR := -1; ERRLXPTR := 0;
16870     IF LSTCNT>LINESPERPAGE THEN CHECKPAGE;
16880     SRCSTAT := SRCSTCH
16890     END;
16900 (**)
16910 (**)
16920 PROCEDURE NEXTCH(LEVEL: INDEXTYPE);
16930 (*FUNCTION: GET THE NEXT ACCEPTABLE CHARACTER FROM THE SOURCE
16940     INPUT. LEVEL IS USED TO INDICATE WHICH CHARACTERS ARE
16950     ACCEPTABLE.
16960   INPUTS
16970     LEVEL - THE LOWEST INDEX TYPE WHICH IS ACCEPTABLE
16980   OUTPUTS (GLOBAL)
16990     CHA   - THE CURRENT INPUT CHARACTER
17000     TYPE  - THE TYPE TYPE OF CHA
17010     INDEX - THE INDEX TYPE OF CHA
17020 *)
17030   LABEL 99;
17040     BEGIN
17050     REPEAT
17060       IF (INDEX=EOL) OR (SRCPTR>=CBUFSIZE) THEN
17070         OUTSRC;
17080         IF INDEX=EOFF THEN GOTO 99
17090         ELSE CHA := SOURCDECS^;
17100         SRCPTR := SRCPTR+1; SRCBUF[SRCPTR] := CHA;
17110         CHAC:=UPC;
17120 (*-50()
17130         IF (ORD(CHA)>96) AND (ORD(CHA)<127) THEN
17140           BEGIN
17150           CHA:=CHR(ORD(CHA)-32);
17160           CHAC:=LOWC
17170           END;
17180 ()-50*)
17190 (*+02() (*-25() IF EOF(SOURCDECS) THEN BEGIN INDEX := EOFF; GOTO 99 END ELSE ()-25*) ()+02*)
17192 (*-50() IF (ORD(CHA)<32) OR (ORD(CHA)>=127) THEN
17194           BEGIN INDEX := ERRCH; TYP := [] END
17196         ELSE ()-50*)
17200         CASE CHA OF
17210           ' ':
17220                 BEGIN
17230                 TYP := [];
17240                 IF EOF(SOURCDECS) THEN BEGIN INDEX:=EOFF; GOTO 99 END
17250                 ELSE IF EOLN(SOURCDECS) THEN INDEX:=EOL
17260                 ELSE INDEX := SPACE
17270                 END;
17280 (*-51()
17290           '$', '&', '''', '?', '\', '_':
17300 ()-51*)
17310 (*+51()
17320           '$', '_', '"', '\', '?', '^':
17330 ()+51*)
17340 (*+50()         BEGIN INDEX := ERRCH; TYP := [] END; ()+50*)
17342 (*-50()         BEGIN IF CHAC=UPC THEN INDEX := ERRCH ELSE INDEX := PUNCT; TYP := [] END; ()-50*)
17350           '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
17360                 BEGIN
17370                 INDEX := DIGIT;
17380                 TYP := [HEX, DIG]
17390                 END;
17400           '.':
17410                 BEGIN
17420                 GET(SOURCDECS);
17430                 IF SOURCDECS^ IN ['0'..'9'] THEN INDEX := POINT
17440                 ELSE INDEX := STROP;
17450                 TYP := [];
17460                 GOTO 99
17470                 END;
17480 (*-51()
17490           '"':  BEGIN INDEX := QUOTE; TYP := [] END;
17500           ':', '!', '%', '(', ')', '*', '/', ',', ';', '<', '>',
17510             '^', '=', '@', '[', ']':
17520 ()-51*)
17530 (*+51()
17540           '!': BEGIN INDEX := QUOTE; TYP := [] END;
17550           ':', '&', '%', '(', ')', '*', '/', ',', ';', '<', '>',
17560             '''', '=', '@', '[', ']':
17570 ()+51*)
17580 (*+50()         BEGIN INDEX := PUNCT; TYP :=[] END; ()+50*)
17582 (*-50()         BEGIN IF CHAC=UPC THEN INDEX := PUNCT ELSE INDEX := ERRCH; TYP := [] END; ()-50*)
17590           '+', '-':
17600                 BEGIN INDEX := PLSMIN; TYP := [] END;
17610           'A', 'B', 'C', 'D', 'E', 'F':
17620                 BEGIN
17630                 INDEX := LETTER;
17640                 TYP := [HEX, CHAC]
17650                 END;
17660           'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
17670             'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z':
17680                 BEGIN
17690                 INDEX := LETTER;
17700                 TYP := [CHAC]
17710                 END;
17720           '#':
17730                 BEGIN INDEX := PRAG; TYP := [] END;
17740           END;
17750         GET(SOURCDECS);
17760   99:
17770     UNTIL INDEX>LEVEL
17780     END;
17790 (**)
17800 (**)
17810 PROCEDURE LXERR(N: INTEGER);
17820 (*FUNCTION: PRINT ERROR MESSAGE UNLESS CURRENTLY PROCESSING
17830     INSIDE A PRAGMENT.
17840   INPUT:
17850     N - IDENTIFIES MESSAGE TO BE PRINTED
17860   GLOBALS:
17870     INPRAGMENT
17880 *)
17890     BEGIN
17900     IF NOT INPRAGMENT THEN
17910       OUTERR(N, ERRORR, NIL)
17920     END;
17930 (**)
17940 (**)
17950 PROCEDURE INITLX;
17960 (*FUNCTION: PERFORM PER-COMPILATION INITIALIZATION REQUIRED BY
17970     THE LEXICAL ANALYZER.
17980 *)
17990 (*VAR I: 0..HTSIZE; *)
18000     BEGIN
18010     (*WORDS := 0;*)
18020 (*+50()
18030 (*-52() PRAGFLGS := [PRGPOINT, PRGWARN, PRGMACH, PRGLIST, PRGGO]; ()-52*)
18040 (*+52() PRAGFLGS := [PRGPOINT, PRGWARN, PRGMACH, PRGLIST]; ()+52*)
18050 ()+50*)
18060 (*-50() PRAGFLGS := [PRGUPPER, PRGWARN, PRGMACH, PRGLIST, PRGGO]; ()-50*)
18070     INDEX := CONTROL;
18080     INPRAGMENT := FALSE;
18090     LONGSCNT := 0;
18100     ERRLXPTR := 0; ERRPTR := -1;
18110     ERRCHAR := ' '; ERRNONBLANK := FALSE;
18120     SRCPTR := 0;
18130     (*KRONOS HAS A CONVENTION FOR LINE NUMBERING OF FILES.
18140       THE FIRST CHARACTER OF THE FILE WILL NOW BE READ, AND IF
18150       IT IS A DIGIT, IT WILL BE ASSUMED THAT THE SOURCE TEXT
18160       IS NUMBERED ACCORDING TO THIS CONVENTION.*)
18170     LSTLINE := 1;
18180     IF NOT EOF(SOURCDECS) THEN
18190       BEGIN
18200     WHILE EOLN(SOURCDECS) DO GET(SOURCDECS);
18210       IF SOURCDECS^ IN ['0'..'9'] THEN
18220         BEGIN
18230       READ(SOURCDECS,LSTLINE);
18240         IF SOURCDECS^=' ' THEN GET(SOURCDECS);
18250         PRAGFLGS := PRAGFLGS+[LINENUMBERS];
18260         END
18270       END;
18280     LEXLINE := LSTLINE;
18290     SRCSTAT := ' ';
18340     END;
18350 (**)
18360 (**)
18370 (*+04()
18380 FUNCTION LABS(X: A68INT): A68INT;
18390     BEGIN IF X>0 THEN LABS := X ELSE LABS := -X END;
18400 ()+04*)
18410 ()+82*)
18420 (*+81()
18430 FUNCTION HASHIN: PLEX;
18440 (*FUNCTION: SEARCH HASH TABLE FOR LEXEME SITTING IN CURRENTLEX.
18450     IF LEXEME IS ALREADY IN TABLE, THEN RETURN POINTER TO THIS OLD
18460     LEXEME.  IF IT IS NOT IN THE TABLE AND NOENTER IS FALSE AND WE
18470     ARE NOT INSIDE A PRAGMENT, THEN ENTER THE LEXEME IN THE TABLE
18480     AND RETURN A POINTER TO THE NEW LEXEME.  IF LEXEME IS NOT
18490     FOUND AND A NEW ENTRY IS NOT MADE, THEN RETURN NIL.
18500 *)
18510   LABEL 8, 9;
18520   VAR TOTAL: A68INT; HASHVAL, HASHSTART:  INTEGER; I:  1..TAXLENWD; THIS:  PLEX;
18530     BEGIN
18540     WITH CURRENTLEX DO
18550       BEGIN
18560       TOTAL := 0;
18570       HASHSTART := 1+ORD(LXTOKEN=TKDENOT);
18580       FOR I := HASHSTART TO LXCOUNT DO
18590 (*+11() TOTAL := TOTAL+FUDGE[2*I-1]+FUDGE[2*I];
18592       HASHVAL := ABS(TOTAL MOD HTSIZE);   (*HASH VALUE*) ()+11*)
18600 (*-11()
18601 (*-05() TOTAL := (TOTAL+INTEGERS[I]) MOD HTSIZE; ()-05*)
18602 (*+05() TOTAL := TOTAL+INTEGERS[I]; ()+05*)
18604 (*-04()(*-05() HASHVAL := TOTAL;   (*HASH VALUE*) ()-05*)()-04*)
18610 (*+05() HASHVAL := ABS(TOTAL MOD HTSIZE);   (*HASH VALUE*) ()+05*)
18620 (*+04() HASHVAL := SHRINK(LABS(TOTAL)); ()+04*)
18624 ()-11*)
18630       THIS := HT[HASHVAL];
18640       WHILE THIS<>NIL DO
18650         BEGIN
18660           IF LXCOUNT<>THIS^.LXCOUNT THEN GOTO 8;
18670           FOR I := 1 TO LXCOUNT DO
18680             IF INTEGERS[I]<>THIS^.INTEGERS[I] THEN GOTO 8;
18690           IF LXTOKEN=THIS^.LXTOKEN THEN
18700             IF LXTOKEN<>TKDENOT THEN GOTO 9
18710             ELSE IF LXDENMD=THIS^.LXDENMD THEN GOTO 9 ELSE GOTO 8;
18720     8:  THIS := THIS^.LINK
18730         END;
18740    9: IF (THIS=NIL) AND (NOT INPRAGMENT) THEN
18750         BEGIN
18760         (*NEW LEXEME MUST BE CREATED*)
18770         (*CREATE LEXEME JUST BIG ENOUGH*)
18780         ENEW(THIS, LXCOUNT*SZWORD+LEX1SIZE);
18790         FOR I := 1 TO LXCOUNT + LEX1SIZE DIV SZWORD DO
18800           THIS^.LEXWORDS[I] := LEXWORDS[I];
18810         THIS^.LINK := HT[HASHVAL];
18820         HT[HASHVAL] := THIS;
18830         END;
18840       HASHIN := THIS
18850       END (*OF WITH CURRENTLEX*)
18860     END;
18870 (**)
18880 ()+81*)
18890 (*+82()
18900 (**)
18910 FUNCTION LX: PLEX;
18920 (*FUNCTION: SCAN A SYMBOL FROM THE INPUT.
18930   VALUE: PLEX FOR THE SYMBOL.
18940 *)
18950   LABEL 1, 6, 7, 8, 77, 88, 99;
18960   CONST SKIPNONE=CONTROL; SKIPEOL=EOL; SKIPSPACES=SPACE;
18970         SKIPDENS=PLSMIN; SKIPTAGS=LETTER;
18980 (*+11()      MAX10=3146314631463146313B;
18990     MAX2=37777777777777777777B;
19000 ()+11*)
19002 (*+12()
19004     MAX10=3277;
19006     MAX2=16383;
19008 ()+12*)
19010 (*+13() MAX10=214748364;
19020       MAX2=1073741824;
19030 ()+13*)
19040   VAR LEX: PLEX; SYMCNT, I: INTEGER;
19050     S: 0..127;
19060     STATE: (PT, INTPT, R, PM, FRACPT, E, EXP, BITS);
19070               (*FOR GETPRIMDEN*)
19080     EXPONENT, SIGN, SCALE, DIGT: INTEGER;
19090     NS: BOOLEAN;
19100     RR, FAC: REAL;
19110     LEVEL: INDEXTYPE;
19120   PROCEDURE FINISHOFF(C: CHAR);
19130   (*FUNCTION: FILLS REST OF STRING WITH SPACES UP TO NEXT FULL
19140     WORD AND SETS LXCOUNT.
19150   *)
19160     VAR I: 0..TAXLEN;
19170       BEGIN
19180       WITH CURRENTLEX DO
19190         BEGIN
19200         IF SYMCNT<TAXLEN THEN
19210           BEGIN
19220         LXCOUNT := (SYMCNT+CHARPERWORD-1) DIV CHARPERWORD;
19230           FOR I := (SYMCNT-1) MOD CHARPERWORD TO CHARPERWORD-2 DO
19240             BEGIN SYMCNT := SYMCNT+1; STRNG[SYMCNT] := C END
19250         END
19260         ELSE BEGIN LXCOUNT := TAXLENWD; LXERR(ELX+9) END
19270         END
19280       END;
19290   (*START OF LX*)
19300     BEGIN
19310     WITH CURRENTLEX DO
19320       BEGIN
19330       REPEAT
19340      1: ERRLXPTR := SRCPTR;
19350         LEXLINE := LSTLINE;
19360         CASE INDEX OF
19370   (*SKIPSPACES*)
19380           CONTROL, EOL, SPACE:
19390             BEGIN NEXTCH(SKIPSPACES); GOTO 1 END;
19400   (*ERRORCHAR*)
19410           ERRCH: (*ERRORCHAR*)
19420             BEGIN
19430             LXERR(ELX+8);
19440             NEXTCH(SKIPNONE);
19450             LEX := LEXERROR;
19460             GOTO 99
19470             END;
19480   (*GETPRIMDEN*)
19490           DIGIT, POINT: (*GETPRIMDEN*)
19500             BEGIN
19510             LXDENRPREAL := 0.0; EXPONENT := 0; SIGN := +1; SCALE := 0;
19514 (*+02()     SYMCNT := ((SZADDR+SZREAL) DIV SZINT) * CHARPERWORD; ()+02*)
19520             STATE := INTPT;
19530             WHILE TRUE DO
19540               BEGIN
19550           6: (*LABEL TO REPEAT CASE WITH DIFFERENT STATE*)
19560               CASE STATE OF
19570                 INTPT: (*SCAN DIGITS*)
19580 (*+43()           IF INDEX=POINT THEN STATE := PT
19590                   ELSE IF (CHA='R')(*-50() AND ((PRGPOINT IN PRAGFLGS) OR (LOWC IN TYP))()-50*) THEN
19600                     STATE := R
19610                   ELSE IF (CHA='E')(*-50() AND ((PRGPOINT IN PRAGFLGS) OR (LOWC IN TYP))()-50*) THEN
19620                     BEGIN STATE := PM;
19630                     IF LXDENRP<=MAXINT THEN
19640                       LXDENRPREAL := (*-04() LXDENRP ()-04*)(*+04() FLOAT(LXDENRP) ()+04*)
19650                     ELSE BEGIN OUTERR(ELX+10, ERRORR, NIL); LXDENRPREAL := 0.0 END
19660                     END
19670                   ELSE IF DIG IN TYP THEN
19680                     IF LXDENRP<MAX10 THEN
19690                       LXDENRP := LXDENRP*10+(ORD(CHA)-ORD('0'))
19700                     ELSE BEGIN OUTERR(ELX+10, ERRORR, NIL); LXDENRP := 0 END
19710 (*+61()                 (*WORRY ABOUT LONG CONVERSIONS*) ()+61*)
19720                   ELSE
19730                     BEGIN (*+61() IF LONGSCNT=1 THEN LXDENMD := MDLINT ELSE ()+61*) LXDENMD := MDINT;
19740                       GOTO 7 END;
19750 ()+43*)
19760 (*-43()           IF INDEX=POINT THEN STATE := PT
19770                   ELSE IF (CHA='R')(*-50() AND ((PRGPOINT IN PRAGFLGS) OR (LOWC IN TYP))()-50*) THEN
19780                        STATE:=R
19790                   ELSE IF (CHA='E')(*-50() AND ((PRGPOINT IN PRAGFLGS) OR (LOWC IN TYP))()-50*) THEN
19800                        STATE:=PM
19810                   ELSE IF DIG IN TYP THEN
19820                     LXDENRPREAL := LXDENRPREAL*10+(ORD(CHA)-ORD('0'))
19830                   ELSE IF LXDENRPREAL<=MAXINT
19840                        THEN BEGIN (*+61() IF LONGSCNT=1 THEN LXDENMD := MDLINT ELSE ()+61*) LXDENMD:=MDINT;
19850                        LXDENRP:=TRUNC(LXDENRPREAL);GOTO 7 END
19860                      ELSE BEGIN  OUTERR(ELX+10,ERRORR,NIL);
19870 (*+61()                  (*WORRY ABOUT LONG CONVERSIONS*) ()+61*)
19880                        LXDENMD := MDINT;
19890                        LXDENRP:=0 END;
19900 ()-43*)
19910                 PT: (*FIXED-POINT-NUMERAL MUST FOLLOW IN
19920                       FRACTIONAL-PART*)
19930                   BEGIN STATE := FRACPT;
19940 (*-02() (*+43()   IF LXDENRP<=MAXINT THEN
19950                     LXDENRPREAL := LXDENRP
19960                   ELSE BEGIN OUTERR(ELX+10, ERRORR, NIL); LXDENRPREAL := 0.0 END;
19970 (*+61()               (*WORRY ABOUT LONG CONVERSIONS*) ()+61*)
19980 ()+43*) ()-02*)
19990                   GOTO 6
20000                   END;
20010                 FRACPT: (*SCAN DIGITS OF FRACTIONAL-PART*)
20020                   IF (CHA='E') AND ((PRGPOINT IN PRAGFLGS) OR (LOWC IN TYP))
20030                        THEN STATE:=PM
20040                   ELSE IF DIG IN TYP THEN
20050 (*-02()             BEGIN LXDENRPREAL := LXDENRPREAL*10+(ORD(CHA)-ORD('0')); SCALE := SCALE-1 END ()-02*)
20060                   ELSE BEGIN STATE := EXP; GOTO 6 END;
20070                 PM: (*CHECK FOR PLUSMINUS IN EXPONENT-PART*)
20080                   IF INDEX=PLSMIN THEN
20090                     BEGIN IF CHA='-' THEN SIGN := -1; STATE := E END
20100                   ELSE IF DIG IN TYP THEN
20110                     BEGIN STATE := EXP; GOTO 6 END
20120                   ELSE BEGIN LXERR(ELX+6); LEX := LEXERROR; GOTO 99 END;
20130                 E: (*FIXED-POINT-NUMERAL MUST FOLLOW PLUSMINUS*)
20140                   IF DIG IN TYP THEN
20150                     BEGIN STATE := EXP; GOTO 6 END
20160                   ELSE BEGIN LXERR(ELX+6); LEX := LEXERROR; GOTO 99 END;
20170                 EXP: (*SCAN FIXED-POINT-NUMERAL IN EXPONENT-PART*)
20180                   IF DIG IN TYP THEN
20190 (*-02()             EXPONENT := EXPONENT*10+(ORD(CHA)-ORD('0'))*SIGN ()-02*)
20200                   ELSE
20202                     BEGIN
20210 (*-02()             SCALE := SCALE+EXPONENT;
20220                     RR := 1.0; NS := SCALE<0; SCALE := ABS(SCALE); FAC := 10.0;
20230                     WHILE SCALE<>0 DO
20240                       BEGIN IF ODD(SCALE) THEN RR := RR*FAC;
20250                       SCALE := SCALE DIV 2;
20252                       IF SCALE<>0 THEN FAC := SQR(FAC);
20260                       END;  (*RR = 10^SCALE*)
20270                     IF NS THEN LXDENRPREAL := LXDENRPREAL/RR
20280                     ELSE LXDENRPREAL := LXDENRPREAL*RR;
20284 ()-02*)
20290             (*+61() IF LONGSCNT=1 THEN LXDENMD := MDLREAL ELSE ()+61*) LXDENMD := MDREAL;
20300                     GOTO 7;
20310                     END;
20320                 R: (*DIGITS MUST FOLLOW LETTER-R IN
20330                      BITS-DENOTATION*)
20340 (*+43()           IF (HEX IN TYP)(*-50() AND ((PRGPOINT IN PRAGFLGS) OR NOT(UPC IN TYP)) ()-50*)
20350 (*-04()               AND (LXDENRP IN [2,4,8,16]) THEN ()-04*)
20360 (*+04()               AND (SHRINK(LXDENRP) IN [2,4,8,16]) THE ()+04*)
20370                     BEGIN STATE := BITS;
20380                       EXPONENT := (*-04() LXDENRP; ()-04*)(*+04() SHRINK(LXDENRP); ()+04*)
20390                       LXDENRP := 0; GOTO 6;
20400                     END
20410                   ELSE BEGIN LXERR(ELX+6); LEX := LEXERROR; GOTO 99 END;
20420 ()+43*)
20430 (*-43()          IF (HEX IN TYP)(*-50() AND ((PRGPOINT IN PRAGFLGS) OR NOT(UPC IN TYP))()-50*)
20440                  AND (TRUNC(LXDENRPREAL)-1 IN [1,3,7,15]) THEN
20450                     BEGIN STATE := BITS; EXPONENT := TRUNC(LXDENRPREAL); LXDENRPREAL := 0; GOTO 6 END
20460                  ELSE BEGIN LXERR(ELX+6); LEX := LEXERROR; GOTO 99 END;
20470 ()-43*)
20480                 BITS: (*SCAN DIGITS IN BITS-DENOTATION*)
20490 (*+43()           IF (HEX IN TYP)(*-50() AND ((PRGPOINT IN PRAGFLGS) OR NOT(UPC IN TYP))()-50*) THEN
20500                     BEGIN IF DIG IN TYP THEN DIGT := ORD(CHA)-ORD('0')
20510                           ELSE DIGT := ORD(CHA)-ORD('A')+10;
20520                     IF DIGT<EXPONENT THEN
20530                       BEGIN SCALE := EXPONENT;
20540                       WHILE SCALE<>1 DO
20550                         IF LXDENRP<=MAX2 THEN
20560                           BEGIN LXDENRP := LXDENRP*2; SCALE := SCALE DIV 2 END
20570                                         (*RELIES ON THE FACT THAT *2 IS A SHIFT*)
20580                         ELSE BEGIN OUTERR(ELX+10, ERRORR, NIL); LXDENRP := 0 END;
20590                       LXDENRP := LXDENRP+DIGT
20600                       END
20610                     ELSE BEGIN LXERR(ELX+6); LEX := LEXERROR; GOTO 99 END
20620                     END
20630                   ELSE BEGIN LXDENMD := MDBITS; GOTO 7 END
20640 ()+43*)
20650 (*-43()           IF (HEX IN TYP) AND ((PRGPOINT IN PRAGFLGS) OR (NOT(UPC IN TYP))) THEN
20660                     BEGIN IF DIG IN TYP THEN DIGT := ORD(CHA)-ORD('0')
20670                           ELSE DIGT := ORD(CHA)-ORD('A')+10;
20680                     IF DIGT<EXPONENT THEN
20690                       BEGIN SCALE := EXPONENT;
20700                       WHILE SCALE<>1 DO
20710                         BEGIN LXDENRPREAL := LXDENRPREAL*2; SCALE := SCALE DIV 2 END;
20720                       LXDENRPREAL := LXDENRPREAL+DIGT
20730                       END
20740                     ELSE BEGIN LXERR(ELX+6); LEX := LEXERROR; GOTO 99 END
20750                     END
20760                   ELSE BEGIN
20770                       IF LXDENRPREAL-MAXINT-1<=MAXINT THEN
20780                         IF LXDENRPREAL<=MAXINT THEN
20790                            LXDENRP := TRUNC(LXDENRPREAL)
20800                         ELSE LXDENRP := TRUNC(LXDENRPREAL-MAXINT-MAXINT-2)
20810                       ELSE BEGIN OUTERR(ELX+10, ERRORR, NIL); LXDENRP:=0 END ;
20820                         LXDENMD := MDBITS; GOTO 7 END
20830 ()-43*)
20840                 END; (*OF CASE STATE*)
20844 (*+02()       SYMCNT := SYMCNT+1; STRNG[SYMCNT] := CHA; ()+02*)
20850               NEXTCH(SKIPSPACES)  (*SKIPNONE IN RES*)
20860               END (*OF LOOP*);
20870           7: (*EXIT LABEL FOR LOOP*)
20880 (*+61()     IF LONGSCNT<0 THEN SEMERR(ESE+6) ELSE IF LONGSCNT>1 THEN SEMERR(ESE+19); ()+61*)
20884             IF LXDENMD=MDREAL THEN
20886               BEGIN
20890 (*-02()       LXCOUNT := WORDSPERREAL + SZADDR DIV SZWORD ()-02*)
20892 (*+02()       LXDENRP := SYMCNT - ((SZADDR+SZREAL) DIV SZINT)*CHARPERWORD;
20894               FINISHOFF(CHR(0));
20896 ()+02*)
20900 (*+61()       (*WORRY ABOUT LONG MODES*) ()+61*)
20904               END
20910             ELSE LXCOUNT := (SZADDR+SZINT) DIV SZWORD;
20920             LXV := LXVPRDEN;
20930             LXTOKEN := TKDENOT;
20940             GOTO 88
20950             END (*OF GETPRIMDEN*);
20960   (*GETSTRGDEN*)
20970           QUOTE: (*GETSTRGDEN*)
20980             BEGIN
20990             SRCSTCH := 'S';
21000             SYMCNT := ((SZADDR+SZINT) DIV SZINT)*CHARPERWORD; (*ALLOWS ROOM FOR LXDENMD AND LXDENRP*)
21010             WHILE TRUE DO
21020               BEGIN
21030               NEXTCH(SKIPEOL);
21040               IF INDEX=EOFF THEN
21050                 BEGIN LXERR(ELX+3); LEX := LEXERROR; GOTO 99 END
21060               ELSE IF INDEX<>QUOTE THEN
21070                 BEGIN
21080 (*-50()         IF CHAC=LOWC THEN CHA := CHR(ORD(CHA)+32); ()-50*)
21090                 IF SYMCNT<TAXLEN THEN
21100                   BEGIN SYMCNT := SYMCNT+1; STRNG[SYMCNT] := CHA END
21110                 ELSE (*NO ACTION*)
21120                 END
21130               ELSE
21140                 BEGIN
21150                 NEXTCH(SKIPNONE);
21160                 IF INDEX=QUOTE THEN
21170                   IF SYMCNT<TAXLEN THEN
21180                     BEGIN SYMCNT := SYMCNT+1; STRNG[SYMCNT] := CHA END
21190                   ELSE (*NO ACTION*)
21200                 ELSE
21210                   BEGIN
21220                   SRCSTCH := ' ';
21230                   IF INDEX<=SKIPSPACES THEN NEXTCH(SKIPSPACES);
21240                   IF INDEX<>QUOTE THEN GOTO 8;
21250                   SRCSTCH := 'S'
21260                   END
21270                 END
21280               END (*OF LOOP*);
21290            8: (*UPON RECOGNITION OF END OF STRING-DENOTATION*)
21300             LXDENRP := SYMCNT-((SZADDR+SZINT)DIV SZINT)*CHARPERWORD;  (*LENGTH OF STRING*)
21310             IF SYMCNT=((SZADDR+SZINT) DIV SZINT)*CHARPERWORD+1 THEN
21320               BEGIN LXDENMD := MDCHAR;
21330               LXDENRP := ORD(STRNG[((SZADDR+SZINT) DIV SZINT)*CHARPERWORD+1]);
21340               LXV := LXVPRDEN; LXCOUNT := (SZADDR+SZINT) DIV SZWORD;
21350               END
21360             ELSE
21370               BEGIN LXDENMD := MDSTRNG; FINISHOFF(CHR(0)); LXV := LXVSTRGDEN END;
21380             LXTOKEN := TKDENOT;
21390             GOTO 88
21400             END (*OF GETSTRGDEN*);
21410   (*GETOPR*)
21420           PUNCT, PLSMIN, PRAG: (*GETOPR*)
21430             BEGIN
21440 (*+01()     IF CHA=':' THEN S := ORD('$')-ORD('+') ELSE S := ORD(CHA)-ORD('+');  ()+01*)
21450 (*+25()     IF CHA=':' THEN S := ORD('$')-ORD('+') ELSE S := ORD(CHA)-ORD('+');  ()+25*)
21460 (*-01() (*-25()     S := ORD(CHA)-ORD('!'); (*ASCII VERSION*)
21462             IF CHA='%' THEN S := 23
21465             IF CHA = '%' THEN S:=23 ELSE
21470             IF CHA IN ['[',']','^','\'] THEN S:=S-55; ()-25*)  ()-01*)
21480             NEXTCH(SKIPNONE);
21490             WITH OPCHTABLE[S] DO
21500               BEGIN
21510               LEX := OTLEX;
21520               S := OTNEXT
21530               END;
21540             WHILE S<>0 DO
21550               WITH OPCHTABLE[S] DO
21560                 IF CHA=OTCHAR THEN
21570                   BEGIN
21580                   NEXTCH(SKIPNONE);
21590                   LEX := OTLEX;
21600                   S := OTNEXT
21610                   END
21620                 ELSE S := OTALT;
21630             IF LEX=LEXERROR THEN
21640               BEGIN
21650               NEXTCH(SKIPNONE);
21660               LXERR(ELX+5);
21670               END;
21680             GOTO 99
21690             END;
21700   (*GETTAX*)
21710           LETTER: (*GETTAX*)
21720             BEGIN
21730             (*IN RES STROPPING, NOENTER IS SET.
21740               IF UPPER/LOWER STROP AND UPPER/LOWER OR IF RES
21750               THEN USE HASHBOLD
21760               ELSE*)
21770             IF PRGPOINT IN PRAGFLGS THEN TTYPE:=[UPC, LOWC, DIG]
21780                                      ELSE TTYPE:=[CHAC, DIG];
21790             IF (PRGUPPER IN PRAGFLGS) AND (CHAC=UPC) THEN
21800               BEGIN
21810               LXV:=LXVTAB;
21820               LXTOKEN:=TKBOLD;
21830               LEVEL:=SKIPNONE
21840               END
21850             ELSE
21860               BEGIN
21870               LXV:=LXVTAG;
21880               LXTOKEN:=TKTAG;
21890               LEVEL:=SKIPSPACES
21900               END
21910             END (*OF GETTAX*);
21920   (*GETBOLD*)
21930           STROP: (*GETBOLD*)
21940             BEGIN
21950             NEXTCH(SKIPNONE);
21960             IF INDEX=LETTER THEN
21970               BEGIN
21980               (*HASHBOLD*)
21990             TTYPE:=[CHAC,DIG];
22000               LXV := LXVTAB;
22010               LXTOKEN := TKBOLD;
22020               LEVEL := SKIPNONE
22030               END
22040             ELSE BEGIN LXERR(ELX+7); LEX := LEXERROR; GOTO 99 END
22050             END (*OF GETBOLD*);
22060   (*ENDOFFILE*)
22070           EOFF: (*ENDOFFILE*)
22080             BEGIN
22090             LEX := LEXSTOP;
22100             GOTO 99
22110             END;
22120           END (*OF CASE INDEX*);
22130       77: (*SCANTAX*)
22140       SYMCNT := 0;
22150       REPEAT
22160         IF SYMCNT<TAXLEN THEN
22170           BEGIN SYMCNT := SYMCNT+1; STRNG[SYMCNT] := CHA END;
22180         NEXTCH(LEVEL)
22190       UNTIL TYP*TTYPE=[];
22200 (*+11()
22210       IF SYMCNT<11 THEN
22220         BEGIN
22230         LXCOUNT := 1;
22240         WHILE SYMCNT<10 DO
22250           BEGIN SYMCNT := SYMCNT+1; STRNG[SYMCNT] := ' ' END;
22260         LEX := HT[(FUDGE1+FUDGE2) MOD HTSIZE];
22270         WHILE LEX<>NIL DO
22280           BEGIN
22290           IF S10=LEX^.S10 THEN
22300             IF LXTOKEN=LEX^.LXTOKEN THEN GOTO 99;
22310           LEX := LEX^.LINK
22320           END
22330         END
22340       ELSE     ()+11*)
22350            FINISHOFF(' ');
22360       88: (*HASHIN*)
22370       LEX := HASHIN;
22380       99: (*LABEL REACHED FROM EXITLX*)
22390       UNTIL (LEX<>LEXERROR) OR INPRAGMENT;
22400       LX := LEX;
22410       END (*OF WITH CURRENTLEX*)
22420     END;
22430 (**)
22440 (**)
22450 PROCEDURE LEXALF(LEX: PLEX; VAR ALF: ALFA);
22460 (*OBTAINS 1ST 10 CHARS OF IDENTIFIER IN LEX*)
22470   VAR I: INTEGER;
22480     BEGIN
22490     IF LEX=NIL THEN ALF := '-UNNAMED- '
22500     ELSE WITH LEX^ DO
22510       IF LXCOUNT=0 THEN ALF := '-UNNAMED- '
22520       ELSE
22530 (*-11() IF LXCOUNT*CHARPERWORD<10 THEN
22540           BEGIN ALF := '          ';
22550           FOR I := 1 TO LXCOUNT*CHARPERWORD DO ALF[I] := S10[I];
22560           END
22570         ELSE
22580  ()-11*)
22590           ALF := S10;
22600     END;
22610 (**)
22620 (**)
22630 (*+01()
22640 PROCEDURE SETPARAM(S: ALFA; COUNT: INTEGER);
22650 (*SETS S AS THE COUNTTH PARAMETER IN THE COMMUNICATION AREA*)
22660   VAR PARAMS: PACKED RECORD CASE SEVERAL OF
22670           1: (INT: INTEGER);
22680           2: (REC: PACKED ARRAY [1..7] OF CHAR;
22690               CODE: 0..777777B);
22700           3,4,5,6,7,8,9,10: ()
22710           END;
22720       P: PINTEGER;
22730       I: INTEGER;
22740     BEGIN WITH PARAMS DO
22750       BEGIN
22760       IF COUNT=0 THEN P := ASPTR(64B)
22770       ELSE P := ASPTR(1+COUNT);
22780       FOR I := 1 TO 7 DO
22790         IF S[I]=' ' THEN REC[I] := CHR(0)
22800         ELSE REC[I] := S[I];
22810       CODE := 1; (*FOR COMMA*)
22820       P^ := INT;
22830       P := ASPTR(64B);
22840       INT := P^;
22850       CODE := COUNT;
22860       P^ := INT
22870       END
22880     END;
22890 (**)
22900 (**)
22910  ()+01*)
22920 FUNCTION PARSIN: PLEX;
22930 (*FUNCTION: SCAN A TOKEN FROM THE INPUT AND RETURN ITS LEXEME.
22940     A TOKEN CONSISTS OF AN OPTIONAL PRAGMENT (PRAGMAT OR COMMENT)
22950     FOLLOWED BY A SYMBOL.
22960 *)
22970   LABEL 9;
22980   CONST SKIPDENS=PLSMIN;
22990   VAR LEX, LEX2: PLEX;
23000       PTR: PLEXQ;
23010       GOCOUNT, I:  INTEGER;
23020     BEGIN
23030     (*PARSCLKS := PARSCLKS+1; LXCLOCK := LXCLOCK-CLOCK;*)
23040     IF PLINPQ=NIL THEN
23050     BEGIN
23060     REPEAT
23070       SRCSTCH := ' ';
23080       LEX := LX;
23090       WITH LEX^.LXV DO
23100         BEGIN
23110         IF (LXIO=LXIOCMMENT) OR (LXIO=LXIOPRAGMAT) THEN
23120           BEGIN
23130           IF LXIO=LXIOCMMENT THEN SRCSTCH := 'C'
23140           ELSE SRCSTCH := 'P';
23150           INPRAGMENT := TRUE; LEX2 := NIL;
23160           REPEAT
23170             IF INDEX=EOFF THEN
23180               BEGIN OUTERR(ELX+4, ERRORR, LEX); GOTO 9 END
23190             ELSE IF INDEX>=LETTER THEN
23200               BEGIN
23210               LEX2 := LX;
23220               IF SRCSTCH='P' THEN
23230   (*DOPRAG*)    WITH CURRENTLEX DO
23232                 BEGIN
23240 (*-11()         FOR I:=LXCOUNT*CHARPERWORD+1 TO 10 DO S10[I]:=' ';   ()-11*)
23250                 IF S10='WARN      ' THEN PRAGFLGS := PRAGFLGS+[PRGWARN]
23260                   ELSE IF S10='NOWARN    ' THEN PRAGFLGS := PRAGFLGS-[PRGWARN]
23270                   ELSE IF S10='POINT     ' THEN PRAGFLGS := PRAGFLGS+[PRGPOINT]
23280                                                                     -[PRGUPPER]
23290                   ELSE IF S10='UPPER     ' THEN PRAGFLGS := PRAGFLGS+[PRGUPPER]
23300                                                                     -[PRGPOINT]
23310                   ELSE IF S10='LIST      ' THEN PRAGFLGS := PRAGFLGS+[PRGLIST]
23320                   ELSE IF S10='NOLIST    ' THEN
23330                     BEGIN
23340                     PRAGFLGS := PRAGFLGS-[PRGLIST];
23350                     LSTCNT := 100  (*TO FORCE NEW PAGE ON RESTARTING*)
23360                     END
23370                   ELSE IF (S10='PAGE      ') AND (PRGLIST IN PRAGFLGS) THEN
23380                       LSTCNT := 55
23390                   ELSE IF S10='GO        ' THEN
23400                     BEGIN
23410                     PRAGFLGS := PRAGFLGS+[PRGGO]; GOCOUNT := 0;
23420 (*+01()
23430                     REPEAT
23440                       SETPARAM(S10, GOCOUNT); GOCOUNT := GOCOUNT+1;
23450                       IF INDEX<=SKIPDENS THEN NEXTCH(SKIPDENS); LEX2 := LX
23460                     UNTIL LEX2=LEX
23470 ()+01*)
23480                     END
23490                   ELSE IF S10='NOGO      ' THEN PRAGFLGS := PRAGFLGS-[PRGGO]
23500                (* ELSE IF S10='SPACE     ' THEN
23510                     BEGIN
23520                     REPEAT LEX2 := LEX
23530                     UNTIL (LXTOKEN=TKDENOT) OR (LEX2=LEX);
23540                     IF LXTOKEN=TKDENOT THEN WORDS := LXDENRP
23550                     END
23560                *)
23570                 END
23580             END
23590             ELSE NEXTCH(SKIPDENS)  (*MAYBE DIFFERENT IN RES*)
23600           UNTIL LEX2=LEX;  (*MATCHING PRAGMENT-SYMBOL*)
23610           INPRAGMENT := FALSE;
23620       9: (*LABEL REACHED AFTER ELX+4*)
23630           END
23640         END
23650     UNTIL SRCSTCH=' ';
23660     IF LEX^.LXV.LXIO=LXIOLONG THEN
23670       LONGSCNT := LONGSCNT+1
23680     ELSE IF LEX^.LXV.LXIO=LXIOSHORT THEN
23690       LONGSCNT := LONGSCNT-1
23700     ELSE LONGSCNT := 0;
23710     PARSIN := LEX
23720     END
23730     ELSE WITH PLINPQ^ DO
23740       BEGIN
23750       PARSIN := DATA1;
23760       PTR := PLINPQ; PLINPQ := LINK; DISPOSE(PTR)
23770       END;
23780     (*LXCLOCK := LXCLOCK+CLOCK; LXCLOCKS := LXCLOCKS+1*)
23790     END;
23800 (**)
23810 ()+82*)
23820 (*+81()
23830 (**)
23840                 (*STACK HANDLING*)
23850                 (****************)
23860 (**)
23870 PROCEDURE SUBSAVE;
23880     BEGIN SRSEMP := SRSEMP+1; SRSTK[SRSEMP].SUBP := SRSUBP; SRSUBP := SRSEMP END;
23890 (**)
23900 (**)
23910 PROCEDURE SUBREST;
23920     BEGIN SRSEMP := SRSUBP-1; SRSUBP := SRSTK[SRSEMP+1].SUBP END;
23930 (**)
23940 (**)
23950 FUNCTION SRPOPMD: MODE;
23960     BEGIN SRPOPMD := SRSTK[SRSEMP].MD; SRSEMP := SRSEMP-1 END;
23970 (**)
23980 (**)
23990 PROCEDURE SCPUSH(M: MODE);
24000   VAR SC: PMODECHAIN;
24010     BEGIN NEW(SC); WITH SC^ DO
24020       BEGIN LINK := SCL; SCMODE := M END;
24030    SCL := SC
24040     END;
24050 (**)
24060 (**)
24070 FUNCTION SCPOP: MODE;
24080   VAR SC: PMODECHAIN;
24090     BEGIN SCPOP := SCL^.SCMODE; SC := SCL; SCL := SCL^.LINK; DISPOSE(SC) END;
24100 (**)
24110 (**)
24120 ()+81*)
24130 (*+84()
24140                 (*MODE CREATION*)
24150                 (***************)
24160 (**)
24170 PROCEDURE FIND(VAR SEARCHLIST: MODE; RECURSIVE: BOOLEAN; LENGTH: CNTR);
24180 (*REPLACES THE FIRST MODE OF SEARCHLIST BY ANY DUPLICATES OF ITSELF*)
24190   VAR PREV, THIS, NEXT: MODE;
24200   FUNCTION COMPARE(M1, M2: MODE; ASSUMPTION: PMODECHAIN; SEARCHDEEP: BOOLEAN): BOOLEAN;
24210   (*IF SEARCHDEEP THEN
24220         RETURNS TRUE IFF M1 AND M2 ARE EQUIVALENT UNDER THE ASSUMPTION THAT
24230         NIL AND ALL MODES IN ASSUMPTION ARE EQUIVALENT TO SEARCHLIST
24240     ELSE
24250         RETURNS TRUE IFF M1=M2
24260   *)
24270     VAR FOUND: BOOLEAN;
24280         I: INTEGER;
24290         APTR: PMODECHAIN;
24300       BEGIN
24310       IF M1=M2 THEN COMPARE := TRUE
24320       ELSE IF SEARCHDEEP THEN
24330         IF M1=NIL THEN
24340           IF RECURSIVE THEN
24350             BEGIN
24360             APTR := ASSUMPTION; FOUND := FALSE;
24370             WHILE (APTR<>NIL) AND NOT FOUND DO WITH APTR^ DO (*SCAN ASSUMPTIONS*)
24380               BEGIN FOUND := SCMODE=M2; APTR := LINK END;
24390             COMPARE := FOUND;
24400             IF NOT FOUND THEN (*MAKE NEW ASSUMPTION*)
24410               BEGIN
24420               NEW(APTR);
24430               APTR^.LINK := ASSUMPTION; APTR^.SCMODE := M2;
24440               COMPARE := COMPARE(SEARCHLIST, M2, APTR, TRUE);
24450               DISPOSE(APTR)
24460               END
24470             END
24480           ELSE COMPARE := FALSE
24490         ELSE IF M2=NIL THEN COMPARE := COMPARE(NIL, M1, ASSUMPTION, SEARCHDEEP)
24500         ELSE WITH M1^ DO IF (MDV.MDCNT=M2^.MDV.MDCNT) AND (MDV.MDID=M2^.MDV.MDID) THEN
24510           BEGIN
24520           IF MDV.MDID IN [MDIDPROC, MDIDPASC, MDIDREF, MDIDROW] THEN
24530             FOUND := COMPARE(MDPRRMD, M2^.MDPRRMD, ASSUMPTION, RECURSIVE)
24540           ELSE FOUND := TRUE;
24550           IF MDV.MDID IN [MDIDPROC, MDIDPASC] THEN
24560             FOR I := 0 TO MDV.MDCNT-1 DO
24570               FOUND := FOUND AND COMPARE(MDPRCPRMS[I], M2^.MDPRCPRMS[I], ASSUMPTION, RECURSIVE)
24580           ELSE IF MDV.MDID=MDIDSTRUCT THEN
24590             FOR I := 0 TO MDV.MDCNT-1 DO WITH MDSTRFLDS[I] DO
24600               FOUND := FOUND
24610                 AND (MDSTRFLEX=M2^.MDSTRFLDS[I].MDSTRFLEX)
24620                 AND COMPARE(MDSTRFMD, M2^.MDSTRFLDS[I].MDSTRFMD, ASSUMPTION, RECURSIVE);
24630           COMPARE := FOUND
24640           END
24650         ELSE COMPARE := FALSE
24660       ELSE COMPARE := FALSE
24670       END; (*COMPARE*)
24680     BEGIN (*FIND*)
24690     PREV := SEARCHLIST;
24700     THIS := SEARCHLIST^.MDLINK; (*FIRST MODE TO BE TESTED*)
24710     WHILE THIS<>NIL DO WITH THIS^ DO
24720       BEGIN
24730       NEXT := MDLINK;
24740       IF COMPARE(SEARCHLIST, THIS, NIL, TRUE) THEN (*MOVE THIS TO START OF SEARCHLIST*)
24750         BEGIN
24760         PREV^.MDLINK := NEXT;
24770         MDLINK := SEARCHLIST^.MDLINK;
24780         IF PREV=SEARCHLIST THEN PREV := THIS;
24790         EDISPOSE(SEARCHLIST, LENGTH+MODE1SIZE);
24800         SEARCHLIST := THIS;
24810         THIS := NEXT;
24820         END
24830       ELSE
24840         BEGIN PREV := THIS; THIS := NEXT  END;
24850       END;
24860     END;
24870 (**)
24880 (**)
24890 FUNCTION FINDREF(M: MODE): MODE;
24900 (*FIND, OR CREATE, A MODE TABLE ENTRY FOR .REF M*)
24910   VAR CURRENTMD: MODE;
24920     BEGIN
24930     ENEW(CURRENTMD, MODE1SIZE);
24940     WITH CURRENTMD^ DO
24950       BEGIN
24960       MDV := MDVREF; MDPRRMD := M;
24970       MDLINK := REFL; REFL := CURRENTMD
24980       END;
24990     FIND(REFL, FALSE, 0);
25000     FINDREF := REFL
25010     END;
25020 (**)
25030 (**)
25040 FUNCTION FINDROW(M: MODE; CNT: CNTR): MODE;
25050 (*FIND, OR CREATE, A MODE TABLE ENTRY FOR ROWS OF M*)
25060   VAR CURRENTMD: MODE;
25070     BEGIN
25080     IF CNT<=0 THEN FINDROW := M
25090     ELSE BEGIN
25100       ENEW(CURRENTMD, MODE1SIZE);
25110       WITH CURRENTMD^ DO
25120         BEGIN
25130         MDV := MDVROW; MDPRRMD := M; MDV.MDCNT := CNT;
25140         IF M<>NIL THEN
25150           BEGIN MDV.MDIO := M^.MDV.MDIO; MDV.MDSCOPE := M^.MDV.MDSCOPE END;
25152         IF M^.MDV.MDID IN [MDIDOUT..MDIDINB] THEN MDV.MDPILE := FALSE;
25160         MDLINK := ROWL; ROWL := CURRENTMD
25170         END;
25180       FIND(ROWL, FALSE, 0);
25190       FINDROW := ROWL
25200       END
25210     END;
25220 (**)
25230 (**)
25240 PROCEDURE FINDPRC(RESMD: MODE; CNT: CNTR; CP: CODEPROC);
25250 (*FIND, OR CREATE, A MODE TABLE ENTRY FOR A .PROC MODE.
25260   RESMD IS THE RESULT MODE. THE PARAMETER MODES, IF ANY, ARE ON THE SUBSTACK
25270 *)
25280   VAR CURRENTMD: MODE;
25290       LENGTH, I: INTEGER;
25300     BEGIN
25310     LENGTH := CNT*SZADDR;
25320     ENEW(CURRENTMD, LENGTH+MODE1SIZE);
25330     WITH CURRENTMD^ DO
25340       BEGIN
25350       CASE CP OF
25360         PROC: BEGIN MDV := MDVPROC; MDLINK := PROCL; PROCL := CURRENTMD END;
25370         PASC: BEGIN MDV := MDVPASC; MDLINK := PASCL; PASCL := CURRENTMD END;
25390         END;
25400       MDPRRMD := RESMD; MDV.MDCNT := CNT; MDV.MDDEPROC := CNT=0;
25410       FOR I := 0 TO CNT-1 DO (*COPY PARAMETERS*)
25420         MDPRCPRMS[I] := SRSTK[SRSUBP+1+I].MD;
25430       SUBREST
25440       END;
25450     SRSEMP := SRSEMP+1; WITH SRSTK[SRSEMP] DO
25460       CASE CP OF
25470         PROC: BEGIN FIND(PROCL, FALSE, LENGTH); MD := PROCL END;
25480         PASC: BEGIN FIND(PASCL, FALSE, LENGTH); MD := PASCL END;
25500         END
25510     END;
25520 (**)
25530 (**)
25540 PROCEDURE FINSTRLEN(M: MODE);
25550 (*FUNCTION: FILLS IN MDLEN, MDSCOPE AND MDIO FIELDS OF MODE,
25560     IF ENOUGH INFORMATION IS AVAILABLE.
25570 *)
25580   LABEL 7;
25590   VAR TOTAL: INTEGER; IO, SCOPE: BOOLEAN;
25600     I: INTEGER;
25610     BEGIN
25620     WITH M^ DO
25630       IF MDV.MDLEN=0 THEN
25640         BEGIN (*LENGTH HAS NOT BEEN CALCULATED BEFORE*)
25650         TOTAL := 0; IO := TRUE; SCOPE := FALSE;
25660         FOR I := MDV.MDCNT-1 DOWNTO 0 DO
25670           WITH MDSTRFLDS[I] DO
25680             IF MDSTRFMD=NIL THEN GOTO 7
25690             ELSE BEGIN
25700               IF MDSTRFMD^.MDV.MDLEN=0 THEN GOTO 7;
25710               IO := IO AND MDSTRFMD^.MDV.MDIO;
25720               SCOPE := SCOPE OR MDSTRFMD^.MDV.MDSCOPE;
25730               TOTAL := TOTAL+MDSTRFMD^.MDV.MDLEN
25740               END;
25750         MDV.MDIO := IO; MDV.MDLEN := TOTAL; MDV.MDSCOPE := SCOPE
25760         END;
25770  7: END;
25780 (**)
25790 (**)
25800 PROCEDURE FINSTRUCT(CNT: CNTR);
25810 (*FIND, OR CREATE, A MODE TABLE ENTRY FOR A .STRUCT MODE.
25820   THE FIELDS ARE ALREADY ON THE SUBSTACK.
25830 *)
25840   VAR CURRENTMD: MODE;
25850       LENGTH, I: INTEGER;
25860     BEGIN
25870 (*+01() LENGTH := SZADDR*CNT;   ()+01*)
25880 (*-01() LENGTH := 2*SZADDR*CNT; ()-01*)
25890     ENEW(CURRENTMD, LENGTH+MODE1SIZE);
25900     WITH CURRENTMD^ DO
25910       BEGIN
25920       MDV := MDVSTRUCT; MDSTRSDB := 0; MDV.MDCNT := CNT;
25930       FOR I := 0 TO CNT-1 DO WITH MDSTRFLDS[I] DO
25940         BEGIN MDSTRFMD := SRSTK[SRSUBP+1+2*I].MD; MDSTRFLEX := SRSTK[SRSUBP+2+2*I].LEX END;
25950       SUBREST;
25960       MDLINK := STRUCTL; STRUCTL := CURRENTMD
25970       END;
25980     FIND(STRUCTL, FALSE, LENGTH);
25990     SRSEMP := SRSEMP+1; WITH SRSTK[SRSEMP] DO
26000       BEGIN MD := STRUCTL; FINSTRLEN(MD) END
26010     END;
26020 (**)
26030 (**)
26040 PROCEDURE NEWFIELD(LEX: PLEX);
26050 (*FUNCTION: CALLED FROM SR07A AND SR07B TO PROCESS ANOTHER FIELD-SELECTOR IN A DECLARER*)
26060   VAR ISLEX: BOOLEAN;
26070       SEMP: -1..SRSTKSIZE;
26080     BEGIN
26090     ISLEX := FALSE;
26100     SEMP := SRSUBP+1;
26110     WHILE SEMP<=SRSEMP DO
26120       BEGIN
26130       IF ISLEX THEN
26140         IF SRSTK[SEMP].LEX=LEX THEN SEMERRP(ESE+01, LEX);
26150       ISLEX := NOT ISLEX;
26160       SEMP := SEMP+1
26170       END;
26180     SRSEMP := SRSEMP+1; SRSTK[SRSEMP].LEX := LEX
26190     END;
26200 (**)
26210 (**)
26220 PROCEDURE RECURFIX(VAR BASEM: MODE);
26230 (*BASEM IS THE MODE TO BE DEFINED IN A RECURSIVE MODE-DEFINITION.
26240   IT IS AT THE START OF ITS APPROPRIATE MODE LIST.
26250   IT IS REPLACED AT THE START OF THAT LIST BY ANY OTHER MODE EQUIVALENT
26260   TO ITSELF, AND THEN ALL APPLIED OCCURRENCES OF THE MODE INDICATION WITHIN
26270   IT ARE REPLACED BY THE NEW BASEM.
26280 *)
26290   FUNCTION FIXM(M: MODE): MODE;
26300     VAR I: INTEGER;
26310       BEGIN
26320       IF M=NIL THEN FIXM := BASEM
26330       ELSE WITH M^ DO
26340         BEGIN
26350         IF NOT MDV.MDRECUR THEN
26360           BEGIN
26370           IF MDV.MDID IN [MDIDPROC, MDIDPASC, MDIDREF, MDIDROW] THEN
26380             MDPRRMD := FIXM(MDPRRMD);
26390           IF MDV.MDID IN [MDIDPROC, MDIDPASC] THEN
26400             FOR I := 0 TO MDV.MDCNT-1 DO
26410               MDPRCPRMS[I] := FIXM(MDPRCPRMS[I])
26420           ELSE IF MDV.MDID=MDIDSTRUCT THEN
26430             BEGIN
26440             FOR I := 0 TO MDV.MDCNT-1 DO WITH MDSTRFLDS[I] DO
26450               MDSTRFMD := FIXM(MDSTRFMD);
26460             FINSTRLEN(M)
26470             END;
26480           MDV.MDRECUR := TRUE
26490           END;
26500         FIXM := M
26510         END
26520       END; (*OF FIXM*)
26530     BEGIN (*RECURFIX*)
26540     WITH BASEM^ DO CASE MDV.MDID OF
26550       MDIDREF: BEGIN FIND(REFL, TRUE, 0); BASEM := REFL END;
26560       MDIDROW: BEGIN FIND(ROWL, TRUE, 0); BASEM := ROWL END;
26570       MDIDPROC: BEGIN FIND(PROCL, TRUE, MDV.MDCNT); BASEM := PROCL END;
26580       (*DON'T BOTHER WITH MDIDPASC FOR NOW*)
26590       MDIDSTRUCT: BEGIN FIND(STRUCTL, TRUE,
26600                                     (*+11() SZADDR*MDV.MDCNT ()+11*)
26610                                     (*+12() 2*SZADDR*MDV.MDCNT ()+12*)
26620                                     (*+13() 2*SZADDR*MDV.MDCNT ()+13*) );
26630                   BASEM := STRUCTL END;
26640       END;
26650     BASEM := FIXM(BASEM)
26660     END;
26670 (**)
26680 ()+84*)
26690 (**)
26700 (*+04()
26710 BEGIN SIN; S1
26720 END.
26730 ()+04*)