BASSYN: DO; /* SYMBOL TABLE AND CODE SYNTHESIS MODULE */ $INCLUDE (:F1:BASCOM.LIT) /* EXTERNAL PROCEDURES (DEFINED IN BASIC.PLM) */ MON3: PROCEDURE EXTERNAL; END MON3; MOVE: PROCEDURE(S,D,C) EXTERNAL; DECLARE (S,D) ADDRESS, C BYTE; END MOVE; FILL: PROCEDURE(D,CH,CNT) EXTERNAL; DECLARE D ADDRESS, (CH, CNT) BYTE; END FILL; EMIT: PROCEDURE(C) EXTERNAL; DECLARE C BYTE; END EMIT; SETFLAGS: PROCEDURE EXTERNAL; END SETFLAGS; SETUP$INT$FILE: PROCEDURE EXTERNAL; END SETUP$INT$FILE; ERROR: PROCEDURE(ERR) EXTERNAL; DECLARE ERR ADDRESS; END ERROR; SCANNER: PROCEDURE EXTERNAL; END SCANNER; PRINT: PROCEDURE(A) EXTERNAL; DECLARE A ADDRESS; END PRINT; PRINT$DEC: PROCEDURE(VAL) EXTERNAL; DECLARE VAL ADDRESS; END PRINT$DEC; CRLF: PROCEDURE EXTERNAL; END CRLF; REWIND$SOURCE$FILE: PROCEDURE EXTERNAL; END REWIND$SOURCE$FILE; GETCHAR: PROCEDURE BYTE EXTERNAL; END GETCHAR; WRITE$INT$FILE: PROCEDURE EXTERNAL; END WRITE$INT$FILE; CLOSE$INT$FILE: PROCEDURE EXTERNAL; END CLOSE$INT$FILE; /* ********************************************************* * * * SYMBOL TABLE PROCEDURES * * * * THE SYMBOL TABLE IS BUILT FROM .MEMORY TOWARD * * THE LARGEST USABLE ADDRESS WHICH IS STORED IN MAX. * * INFORMATION REQUIRED DURING FOR STATEMENT CODE * * GENERATION IS MAINTAINED STARTING AT MAX AND * * WORKING DOWN TOWARD THE TOP OF THE SYMBOL TABLE * * THE FOLLOWING ARE MAJOR GLOBAL VARIABLES USED * * BY THE SYMBOL TABLE AND THEIR MEANING: * * SBTBLTOP - CURRENT POSITION OF FOR/NEXT * * STACK. * * SBTBL - CURRENT "TOP" OF SYMBOL TABLE * * BASE - ADDRESS OF BEGINNING OF ENTRY. THIS * * MUST BE SET BEFORE AN ENTRY MAY BE * * ACCESSED. * * PRINTNAME - ADDRESS OF PRINTNAME OF AN ENTRY * * TO BE USED IN REFERENCE TO THE * * SYMBOL TABLE. * * SYMHASH - HASH OF TOKEN REFERENCE BY * * PRINTNAME * * * * THE FOLLOWING IS THE STRUCTURE OF A SYMBOL * * TABLE ENTRY: * * LENGTH OF PRINTNAME - 1 BYTE * * COLLISION FIELD - 2 BYTES * * PRINTNAME - VARIABLE LENGTH * * TYPE - 1 BYTE * * LEFTMOST BIT OF THIS BYTE IS A FLAG * * TO INDICATE IF THE ADDRESS HAS BEEN * * SET. * * LOCATION - 2 BYTES * * SUBTYPE - 1 BYTES * * * * THE FOLLOWING GLOBAL ROUTINES ARE PROVIDED * * FOR SYMBOL TABLE MANIPULATION: * * LOOKUP ENTER GETLEN GETYPE * * SETYPE GETRES GETADDR SETADDR * * SETSUBTYPE GETSUBTYPE UNLINK RELINK * * * ********************************************************* */ /* GLOBAL VARIABLES (DEFINED IN BASIC.PLM) */ DECLARE BEXT LITERALLY 'BYTE EXTERNAL', AEXT LITERALLY 'ADDRESS EXTERNAL', /* LITERAL DECLARATIONS FOR PARSE TABLE ENTRIES */ FLOATPT LITERALLY '49', STRING LITERALLY '50', PASS1 BEXT, PASS2 BEXT, LISTPROD BEXT, ERRORCOUNT AEXT, DEBUGLN BEXT, COMPILING BEXT, DATACT AEXT, /* COUNTS SIZE OF DATA AREA */ FORSTMT BEXT, RANDOMFILE BEXT, FILEIO BEXT, INPUTSTMT BEXT, GOSUBSTMT BEXT, NEXTCHAR BEXT, FUNCOP BEXT, ACCLEN BEXT, ACCUM(IDENTSIZE) BEXT, CONT BEXT, LINENO BEXT, SEPARATOR BEXT; DECLARE /* LOCAL VARIABLES */ MAX ADDRESS AT (6H), /* DOS ADDRESS */ ULERRORFLAG BYTE INITIAL(FALSE), CODESIZE ADDRESS, /* COUNTS SIZE OF CODE AREA */ PRTCT ADDRESS, /* COUNTS PRT ENTRIES */ FDACT ADDRESS, /* COUNTS FDA ENTRIES */ NEXTSTMTPTR ADDRESS, NEXTADDRESS BASED NEXTSTMTPTR (4) ADDRESS, NEXTBYTEV BASED NEXTSTMTPTR(2) BYTE, NEXTBYTE BASED NEXTSTMTPTR BYTE, /* SIMPLE VERSION OF 'V' */ FORCOUNT BYTE INITIAL(0), BASE ADDRESS, /* BASE OF CURRENT ENTRY IN SYMBOL */ HASHTABLE(HASHTBLSIZE) ADDRESS, SBTBLTOP ADDRESS, /* CURRENT TOP OF SYMBOL TABLE */ FORADDRESS BASED SBTBLTOP (4) ADDRESS, /* FOR STMT INFO */ SBTBL ADDRESS, PTRV BASED BASE (2) BYTE, /* FIRST BYTE OF ENTRY */ PTR BASED BASE BYTE, /* SIMPLE PTRV */ APTRADDR ADDRESS, /* UTILITY VARIABLE TO ACCESS TABLE */ BYTEPTRV BASED APTRADDR (2) BYTE, BYTEPTR BASED APTRADDR BYTE, /* SIMPLE BYTEPTRV */ ADDRPTR BASED APTRADDR ADDRESS, PRINTNAME ADDRESS, /* SET PRIOR TO LOOKUP OR ENTER */ SYMHASH BYTE; /* ALSO SET PRIOR TO LOOKUP OR ENTER */ IN$SYMTBL: PROCEDURE PUBLIC; /* FILL HASHTABLE WITH 0'S */ IF PASS1 THEN DO; CALL FILL(.HASHTABLE,0,SHL(HASHTBLSIZE,1)); SBTBL = .MEMORY; END; /* INITIALIZE POINTER TO TOP OF SYMBOL TABLE */ SBTBLTOP, NEXTSTMTPTR = MAX - 2; NEXTBYTEV(1) =0; RETURN; END IN$SYMTBL; SETADDRPTR: PROCEDURE(OFFSET); /* SET PTR FOR ADDR REFERENCE */ DECLARE OFFSET BYTE; APTRADDR = BASE + PTR + OFFSET; /* POSITION FOR ADDR REFERENCE */ RETURN; END SETADDRPTR; GETHASH: PROCEDURE BYTE; DECLARE HASH BYTE, I BYTE; HASH = 0; APTRADDR = BASE + 2; DO I = 1 TO PTR; HASH = (HASH + BYTEPTRV(I)) AND HASHMASK; END; RETURN HASH; END GETHASH; NEXTENTRY: PROCEDURE; BASE = BASE + PTR + 7; RETURN; END NEXTENTRY; SETLINK: PROCEDURE; APTRADDR = BASE + 1; RETURN; END SETLINK; HASHTBL$OF$SYMHASH: PROCEDURE ADDRESS; RETURN HASHTABLE(SYMHASH); END HASHTBL$OF$SYMHASH; LIMITS: PROCEDURE(COUNT); /* CHECK TO SEE IF ADDITIONAL SBTBL WILL OVERFLOW LIMITS OF MEMORY. IF SO THEN PUNT ELSE RETURN */ DECLARE COUNT BYTE; /*SIZE BEING ADDED IS COUNT */ IF SBTBLTOP <= (SBTBL + COUNT) THEN DO; PASS2 = TRUE; /* TO PRINT ERROR MSG */ CALL ERROR('TO'); CALL MON3; END; RETURN; END LIMITS; SETADDR: PROCEDURE(LOC); /*SET THE ADDRESS FIELD AND RESOLVED BIT*/ DECLARE LOC ADDRESS; CALL SETADDRPTR (4); ADDRPTR=LOC; APTRADDR = APTRADDR - 1; BYTEPTR=BYTEPTR OR 80H; RETURN; END SETADDR; LOOKUP: PROCEDURE BYTE; /* CHECK TO SEE IF P/N LOCATED AT ADDR IN PRINTNAME IS IN SBTBL RETURN TRUE IF IN SBTBL RETURN FALSE IF NOT IN SBTBL. BASE=ADDRESS IF IN SBTBL */ DECLARE LEN BYTE, N BASED PRINTNAME (2) BYTE; /* N IS LENGTH OF P/N */ BASE = HASHTBL$OF$SYMHASH; DO WHILE BASE <> 0; IF(LEN := PTR) = N(0) THEN DO WHILE (PTRV(LEN + 2) = N(LEN)); IF (LEN := LEN - 1) = 0 THEN RETURN TRUE; END; CALL SETLINK; BASE = ADDRPTR; END; RETURN FALSE; END LOOKUP; ENTER: PROCEDURE; /* ENTER TOKEN REFERENCE BY PRINTNAME AND SYMHASH INTO NEXT AVAILABLE LOCATION IN THE SYMBOL TABLE. SET BASE TO BEGINNING OF THIS ENTRY AND INCREMENT SBTBL. ALSO CHECK FOR SYMBOL TABLE FULL. */ DECLARE I BYTE, N BASED PRINTNAME BYTE; CALL LIMITS(I:=N+7); BASE = SBTBL; /* BASE FOR NEW ENTRY */ CALL MOVE(PRINTNAME + 1,SBTBL + 3,(PTR := N)); CALL SETADDRPTR(3);/* SET RESOLVE BIT TO 0 */ BYTEPTR = 0; CALL SETLINK; ADDRPTR = HASHTBL$OF$SYMHASH; HASHTABLE(SYMHASH) = BASE; SBTBL = SBTBL + I; RETURN; END ENTER; GETLEN: PROCEDURE BYTE; /*RETURN LENGTH OF THE P/N */ RETURN PTR; END GETLEN; GETYPE: PROCEDURE BYTE; /*RETURNS TYPE OF VARIABLE */ CALL SETADDRPTR (3); RETURN (BYTEPTR AND 7FH); END GETYPE; SETYPE: PROCEDURE (TYPE); /*SET TYPEFIELD = TYPE */ DECLARE TYPE BYTE; CALL SETADDRPTR (3); BYTEPTR = BYTEPTR OR TYPE; /*THIS SETS THE TYPE AND PRESERVES RESOLVED BIT */ RETURN; END SETYPE; GETRES: PROCEDURE BYTE; /* RETURN TRUE IF RESOLVED BIT = 1, RETURN FALSE IF RESOLVED BIT = 0 */ CALL SETADDRPTR(3); RETURN ROL(BYTEPTR,1); END GETRES; GETADDR: PROCEDURE ADDRESS; /*RETURN THE ADDRESS OF THE P/N LOCATION */ CALL SETADDRPTR(4); RETURN ADDRPTR; END GETADDR; SETSUBTYPE: PROCEDURE(STYPE); /*INSERT THE SUBTYPE IN SBTBL */ DECLARE STYPE BYTE; CALL SETADDRPTR (6); BYTEPTR=STYPE; RETURN; END SETSUBTYPE; GETSUBTYPE: PROCEDURE BYTE; /*RETURN THE SUB TYPE */ CALL SETADDRPTR (6); RETURN BYTEPTR; END GETSUBTYPE; UNLINK: PROCEDURE; DECLARE NEXTA ADDRESS, NUMPARM BYTE, I BYTE, ENTRYPT BASED NEXTA ADDRESS; NUMPARM = GETYPE; DO I = 1 TO NUMPARM; CALL NEXTENTRY; NEXTA = SHL(GETHASH,1) + .HASHTABLE; /* ITS ON THIS CHAIN */ DO WHILE ENTRYPT <> BASE; NEXTA = ENTRYPT + 1; END; CALL SETLINK; ENTRYPT = ADDRPTR; END; RETURN; END UNLINK; RELINK: PROCEDURE; DECLARE TEMPA ADDRESS, I BYTE, NUMPARM BYTE, LOC BASED TEMPA ADDRESS; NUMPARM = GETYPE; DO I = 1 TO NUMPARM; CALL NEXTENTRY; TEMPA = BASE + 1; LOC = HASHTABLE(GETHASH); HASHTABLE(GETHASH) = BASE; END; RETURN; END RELINK; /* ********************************************************* * * * **** PARSER AND CODE GENERATION SECTION **** * * * ********************************************************* */ /* MNEMMONICS FOR BASIC-E MACHINE */ DECLARE FAD LIT '0', DUP LIT '18', WST LIT '36', FMI LIT '1', XCH LIT '19', RDF LIT '37', FMU LIT '2', STD LIT '20', RDB LIT '38', FDI LIT '3', SLT LIT '21', ECR LIT '39', EXP LIT '4', SGT LIT '22', WRB LIT '40', LSS LIT '5', SEQ LIT '23', RDN LIT '41', GTR LIT '6', SNE LIT '24', RDS LIT '42', EQU LIT '7', SGE LIT '25', WRN LIT '43', NEQ LIT '8', SLE LIT '26', WRS LIT '44', GEQ LIT '9', STS LIT '27', OPN LIT '45', LEQ LIT '10', ILS LIT '28', CON LIT '46', NOTO LIT '11', CAT LIT '29', RST LIT '47', ANDO LIT '12', PRO LIT '30', NEG LIT '48', BOR LIT '13', RTN LIT '31', RES LIT '49', LOD LIT '14', ROW LIT '32', NOP LIT '50', STO LIT '15', SUBO LIT '33', DAT LIT '51', XIT LIT '16', RDV LIT '34', DBF LIT '52', DEL LIT '17', WRV LIT '35', NSP LIT '53', BRS LIT '54', BRC LIT '55', BFC LIT '56', BFN LIT '57', CVB LIT '58', RCN LIT '59', DRS LIT '60', DRF LIT '61', EDR LIT '62', EDW LIT '63', CLS LIT '64', RON LIT '91', CKO LIT '92', EXR LIT '93', DEF LIT '94', BOL LIT '95', ADJ LIT '96', POT LIT '40', IRN LIT '77'; DECLARE STATE STATESIZE PUBLIC, /* THE FOLLOWING VECTORS ARE USED AS PARSE STACKS SYNTHESIZE AND THE PARSER ACCESS THESE ARRAYS */ STATESTACK(PSTACKSIZE) STATESIZE PUBLIC, HASH(PSTACKSIZE) BYTE PUBLIC, SYMLOC(PSTACKSIZE) ADDRESS PUBLIC, SRLOC(PSTACKSIZE) ADDRESS PUBLIC, VAR(PSTACKSIZE) BYTE PUBLIC, TYPE(PSTACKSIZE) BYTE PUBLIC, STYPE(PSTACKSIZE) BYTE PUBLIC, VARC(VARCSIZE) BYTE PUBLIC, ONSTACK(MAXONCOUNT) BYTE, ONSP BYTE AT (.ONSTACK(0)), VARINDEX BYTE PUBLIC, /* INDEX INTO VAR */ SP BYTE PUBLIC, MP BYTE PUBLIC, MPP1 BYTE PUBLIC, NOLOOK BYTE PUBLIC, IFLABLNG BYTE INITIAL(2), /* THE FOLLOWING VARABLES ARE USED TO GENERATE COMPILER LABELS. */ IFLAB2 BYTE INITIAL(23), IFLABLE BYTE; EMITCON: PROCEDURE(CHAR); /* WRITES NUMERIC CONSTANTS DURING PASS1 */ DECLARE CHAR BYTE; IF PASS1 THEN CALL EMIT(CHAR); RETURN; END EMITCON; IN$SYN: PROCEDURE PUBLIC; DECLARE CONZERO(*) BYTE DATA(01H,30H); DECLARE CONONE(*) BYTE DATA(01H,31H); CODESIZE,DATACT,ONSP,IFLABLE = 0; FDACT = 1; PRTCT = 0FFFFH; CALL SET$FLAGS; IF PASS1 THEN DO; CALL SETUP$INT$FILE; PRINTNAME = .CONONE(0); SYMHASH = 31H; CALL ENTER; CALL EMITCON(31H); CALL EMITCON('$'); CALL SETADDR(0); /* CONSTANT 1 IS AT FDA POS 0 */ CALL SETYPE(4); /* TYPE CONST */ PRINTNAME = .CONZERO(0); SYMHASH = 30H; CALL ENTER; CALL EMITCON(30H); CALL EMITCON('$'); CALL SETADDR(1); CALL SETYPE(4); END; RETURN; END IN$SYN; SYNTHESIZE: PROCEDURE(PRODUCTION) PUBLIC; DECLARE PRODUCTION BYTE; DECLARE /* THESE LITERALS DEFINE DIFFERENT "TYPES" WHICH MAY BE PLACED IN THE TYPE FIELD OF THE SYMBOL TABLE BY ROUTINES IN SYNTHESIZE */ SIMVAR LIT '00H', SUBVAR LIT '02', CONST LIT '04', LABLE LIT '08', UNFUNC LIT '0AH'; DECLARE /* THE FOLLOWING VARIABLES ARE USED TO HOLD THE CONTENTS OF THE PARSE STACKS DURING EXECUTION OF SYNTHESIZE. THE PROCEDURE COPY IS CALLED TO UPDATE EACH OF THESE VARIABLES ON EACH CALL TO SYNTHESIZE. THIS REDUCES THE NUMBER OF SUBSCRIPT REFERENCES REQUIRED */ (TYPESP,TYPEMP,TYPEMP1) BYTE, (STYPESP,STYPEMP,STYPEMP1) BYTE, (HASHSP,HASHMP,HASHMP1) BYTE, (SYMLOCSP,SYMLOCMP, SYMLOCMP1) ADDRESS, (SRLOCSP,SRLOCMP) ADDRESS; /* ********************************************************* * * * THE FOLLOWING PROCEDURES ARE USED BY SYTHESIZE * * TO GENERATE CODE REQUIRED BY THE PRODUCTIONS * * * * THE FIRST GROUP OF PROCEDURES CONSISTING OF * * COPY AND THE SET-------- PROCEDURES ARE USED * * TO PREVENT THE LARGE AMOUNT OF SUBSCRIPTING * * THAT WOULD BE REQUIRED TO ACCESS THE PARSE * * STACKS DURING CODE GENERATION. * * * * THE REMAINING PROCEDURES DIRECTLY SUPPORT CODE * * GENERATION AND ARE ARRANGED IN LOGICAL GROUPS * * SUCH AS THOSE WHICH ASSIST IN ACCESSING THE * * SYMBOL TABLE OR THOSE USED TO GENERATE INTERNAL * * COMPILER LABLES. * * * ********************************************************* */ COPY: PROCEDURE; TYPESP = TYPE(SP); TYPEMP1 = TYPE(MPP1); TYPEMP = TYPE(MP); STYPESP = STYPE(SP); STYPEMP1 = STYPE(MPP1); STYPEMP = STYPE(MP); SYMLOCSP = SYMLOC(SP); SYMLOCMP1 = SYMLOC(MPP1); SYMLOCMP = SYMLOC(MP); HASHMP = HASH(MP); HASHMP1 = HASH(MPP1); HASHSP = HASH(SP); SRLOCSP = SRLOC(SP); SRLOCMP = SRLOC(MP); RETURN; END COPY; SETSYMLOCSP: PROCEDURE(A); DECLARE A ADDRESS; SYMLOC(SP) = A; RETURN; END SETSYMLOCSP; SETSYMLOCMP: PROCEDURE(A); DECLARE A ADDRESS; SYMLOC(MP) = A; RETURN; END SETSYMLOCMP; SETTYPESP: PROCEDURE(B); DECLARE B BYTE; TYPE(SP) = B; RETURN; END SETTYPESP; SETSTYPESP: PROCEDURE(B); DECLARE B BYTE; STYPE(SP) = B; RETURN; END SETSTYPESP; SETSTYPEMP: PROCEDURE(B); DECLARE B BYTE; STYPE(MP) = B; RETURN; END SETSTYPEMP; SETTYPEMP: PROCEDURE(B); DECLARE B BYTE; TYPE(MP) = B; RETURN; END SETTYPEMP; SETHASHMP: PROCEDURE(B); DECLARE B BYTE; HASH(MP) = B; RETURN; END SETHASHMP; SETHASHSP: PROCEDURE(B); DECLARE B BYTE; HASH(SP) = B; RETURN; END SETHASHSP; SETSRLOCSP: PROCEDURE(A); DECLARE A ADDRESS; SRLOC(SP) = A; RETURN; END SETSRLOCSP; GENERATE: PROCEDURE(OBJCODE); /* WRITES GENERATED CODE AND COUNTS SIZE OF CODE AREA. */ DECLARE OBJCODE BYTE; CODESIZE = CODESIZE + 1; IF NOT PASS1 THEN CALL EMIT(OBJCODE); RETURN; END GENERATE; CALC$VARC: PROCEDURE(B) ADDRESS; DECLARE B BYTE; RETURN VAR(B) + .VARC; END CALC$VARC; SETLOOKUP: PROCEDURE(A); DECLARE A BYTE; PRINTNAME = CALC$VARC(A); SYMHASH = HASH(A); RETURN; END SETLOOKUP; LOOKUP$ONLY: PROCEDURE(A) BYTE; DECLARE A BYTE; CALL SETLOOKUP(A); IF LOOKUP THEN RETURN TRUE; RETURN FALSE; END LOOKUP$ONLY; NORMAL$LOOKUP: PROCEDURE(A) BYTE; DECLARE A BYTE; IF LOOKUP$ONLY(A) THEN RETURN TRUE; CALL ENTER; RETURN FALSE; END NORMAL$LOOKUP; COUNTPRT: PROCEDURE ADDRESS; /* COUNTS THE SIZE OF THE PRT */ RETURN (PRTCT := PRTCT + 1); END COUNTPRT; GENTWO: PROCEDURE(A); /* WRITES TWO BYTES OF OBJECT CODE ON DISK FOR LITERALS */ DECLARE A ADDRESS; CALL GENERATE(HIGH(A)); CALL GENERATE(LOW(A)); RETURN; END GENTWO; LITERAL: PROCEDURE(A); DECLARE A ADDRESS; CALL GENTWO(A OR 8000H); RETURN; END LITERAL; LITLOAD: PROCEDURE(A); DECLARE A ADDRESS; CALL GENTWO(A OR 0C000H); RETURN; END LITLOAD; LINE$NUMBER: PROCEDURE; IF DEBUGLN THEN DO; CALL LITERAL(LINENO); CALL GENERATE(BOL); END; RETURN; END LINE$NUMBER; SETIFNAME: PROCEDURE; PRINTNAME = .IFLABLNG; SYMHASH = IFLABLE AND HASHMASK; RETURN; END SETIFNAME; ENTER$COMPILER$LABEL: PROCEDURE(B); DECLARE B BYTE; IF PASS1 THEN DO; CALL SETIFNAME; CALL ENTER; CALL SETADDR(CODESIZE + B); END; RETURN; END ENTER$COMPILER$LABEL; SET$COMPILER$LABEL: PROCEDURE; DECLARE X BYTE; IFLABLE = IFLABLE + 1; CALL SETIFNAME; X = LOOKUP; RETURN; END SET$COMPILER$LABEL; COMPILER$LABEL: PROCEDURE; CALL SET$COMPILER$LABEL; CALL GEN$TWO(GETADDR); RETURN; END COMPILER$LABEL; CHKTYP1: PROCEDURE BYTE; /* CHECK MP,SP BOTH FLOATING PT */ IF((STYPEMP <> FLOATPT) OR (STYPESP <> FLOATPT)) THEN DO; CALL ERROR('MF'); RETURN FALSE; END; RETURN TRUE; END CHKTYP1; CHKTYP2: PROCEDURE BYTE; /* CHECK MP,SP BOTH SAME TYPE */ IF STYPESP <> STYPEMP THEN DO; CALL ERROR('MM'); RETURN FALSE; END; RETURN TRUE; END CHKTYP2; CHKTYP3: PROCEDURE BYTE; CALL SETSTYPEMP(STYPESP); IF STYPESP = FLOATPT THEN RETURN TRUE; CALL ERROR('MF'); RETURN FALSE; END CHKTYP3; CHKTYP4: PROCEDURE; IF STYPEMP1 = STRING THEN CALL ERROR('MF'); CALL GENERATE(RON); END CHKTYP4; CHKTYP5: PROCEDURE; CALL CHKTYP4; CALL SETTYPEMP(TYPEMP := TYPEMP + 1); END CHKTYP5; SUBCALC: PROCEDURE; CALL SETSUBTYPE(TYPESP); CALL GENERATE(ROW); CALL GENERATE(TYPESP); CALL GENERATE(STD); RETURN; END SUBCALC; GEN$STORE: PROCEDURE; IF STYPEMP1 = FLOATPT THEN CALL GENERATE(STD); ELSE CALL GENERATE(STS); RETURN; END GEN$STORE; SETUP$INPUT: PROCEDURE; CALL GENERATE(DBF); INPUTSTMT = TRUE; CALL GENERATE(RCN); END SETUP$INPUT; GET$FIELD: PROCEDURE; GEN$READ: PROCEDURE(I,J); DECLARE (I,J) BYTE; IF STYPESP = STRING THEN DO; CALL GENERATE(I); CALL GENERATE(STS); END; ELSE DO; CALL GENERATE(J); CALL GENERATE(STD); END; RETURN; END GEN$READ; IF(TYPESP = SIMVAR) THEN CALL LITERAL(SYMLOCSP); IF INPUTSTMT THEN CALL GEN$READ(RES,RDV); ELSE IF FILEIO THEN CALL GEN$READ(RDS,RDN); ELSE CALL GEN$READ(DRS,DRF); RETURN; END GET$FIELD; GEN$ON: PROCEDURE; CALL GENERATE(RON); CALL LITERAL(ONSTACK(ONSP := ONSP + 1)); CALL GENERATE(CKO); CALL GENERATE(BFN); RETURN; END GEN$ON; GEN$ON$2: PROCEDURE; ONSTACK(ONSP) = TYPESP; RETURN; END GEN$ON$2; GENNEXT: PROCEDURE; IF(FORCOUNT := FORCOUNT - 1) = 255 THEN DO; FORCOUNT = 0; CALL ERROR('NU'); END; ELSE DO; CALL GENERATE(BRS); CALL GEN$TWO(NEXTADDRESS(2)); NEXTADDRESS(0) = CODESIZE OR 8000H; DO WHILE NEXTBYTEV(1) > 127; NEXTSTMTPTR = NEXTSTMTPTR + 8; END; END; RETURN; END GENNEXT; GEN$NEXT$WITH$IDENT: PROCEDURE; IF LOOKUP$ONLY(MPP1) AND (BASE = NEXTADDRESS(3)) THEN CALL GENNEXT; ELSE CALL ERROR('NI'); RETURN; END GEN$NEXT$WITH$IDENT; CHECK$UL$ERROR: PROCEDURE; IF ULERRORFLAG THEN CALL ERROR('UL'); ULERRORFLAG = FALSE; END CHECK$UL$ERROR; FINDLABEL: PROCEDURE; IF NORMAL$LOOKUP(SP) THEN DO; IF PASS2 AND (NOT GETRES) THEN ULERRORFLAG = TRUE; END; RETURN; END FINDLABEL; RESOLVE$LABEL: PROCEDURE; CALL FINDLABEL; IF GOSUBSTMT THEN CALL GENERATE(PRO); ELSE CALL GENERATE(BRS); CALL GEN$TWO(GETADDR); RETURN; END RESOLVE$LABEL; PROCESS$SIMPLE$VARIABLE: PROCEDURE(LOC); DECLARE LOC BYTE; IF NORMALLOOKUP(LOC) THEN DO; IF GETYPE <> SIMVAR THEN CALL ERROR('IU'); END; ELSE DO; CALL SETADDR(COUNTPRT); CALL SETYPE(SIMVAR); END; CALL SETSYMLOCSP(SYMLOCSP:=GETADDR); CALL SETTYPESP(SIMVAR); IF FORSTMT THEN DO; FORSTMT = FALSE; FORADDRESS(3) = BASE; END; END PROCESS$SIMPLE$VARIABLE; GEN$ILS: PROCEDURE(WHERE); DECLARE STRPTR BYTE, WHERE ADDRESS, STRINGTOSPOOL BASED WHERE (2) BYTE; CALL SETSTYPESP(STRING); CALL GENERATE(ILS); DO FOREVER; DO STRPTR = 1 TO STRINGTOSPOOL(0); CALL GENERATE(STRINGTOSPOOL(STRPTR)); END; IF CONT THEN CALL SCANNER; ELSE DO; CALL GENERATE(0); RETURN; END; END; /* OF DO FOREVER */ END GEN$ILS; GENCON: PROCEDURE; DECLARE I BYTE; CALL GENERATE(CON); CALL SETTYPESP(CONST); CALL SETSTYPESP(FLOATPT); IF LOOKUP$ONLY(SP) AND (GETYPE = CONST) THEN CALL GEN$TWO(GETADDR); ELSE DO; DO I = 1 TO ACCLEN; CALL EMITCON(ACCUM(I)); END; CALL EMITCON('$'); CALL GEN$TWO(FDACT := FDACT + 1); END; RETURN; END GENCON; PUT$FIELD: PROCEDURE; IF FILEIO THEN DO; IF STYPESP = FLOATPT THEN CALL GENERATE(WRN); ELSE CALL GENERATE(WRS); END; ELSE IF STYPESP = FLOATPT THEN DO; IF TYPESP <> 74 THEN /* IS IT A TAB */ CALL GENERATE(WRV); END; ELSE CALL GENERATE(WST); RETURN; END PUT$FIELD; GEN$PARM: PROCEDURE; IF TYPEMP = UNFUNC THEN DO; BASE = SYMLOCMP; CALL NEXTENTRY; CALL SETSYMLOCMP(BASE); CALL SETHASHMP(HASHMP := HASHMP - 1); CALL LITERAL(GETADDR); END; RETURN; END GEN$PARM; CHECKPARM: PROCEDURE; IF TYPEMP = UNFUNC THEN DO; BASE = SYMLOCMP; IF(GETSUBTYPE <> STYPEMP1) THEN CALL ERROR('FP'); CALL GEN$STORE; RETURN; END; IF(HASHMP XOR (STYPEMP1 <> FLOATPT)) THEN CALL ERROR('FP'); CALL SETHASHMP(SHR(HASHMP,1)); CALL SETSTYPEMP(STYPEMP := STYPEMP -1); RETURN; END CHECKPARM; FUNCGEN: PROCEDURE; IF TYPEMP = UNFUNC THEN DO; IF HASHMP <> 0 THEN CALL ERROR('FN'); CALL GENERATE(PRO); BASE = SRLOCSP; CALL GEN$TWO(GETADDR); RETURN; END; IF((STYPEMP AND 03H) <>0) THEN CALL ERROR('FN'); CALL GENERATE(TYPEMP); IF ROL(STYPEMP,2) THEN CALL SETSTYPEMP(STRING); ELSE CALL SETSTYPEMP(FLOATPT); RETURN; END FUNCGEN; ENTER$PARM: PROCEDURE; IF PASS1 THEN DO; CALL SETLOOKUP(MPP1); CALL ENTER; CALL SETADDR(COUNTPRT); CALL SETSUBTYPE(STYPEMP1); CALL SETYPE(SIMVAR); CALL SETTYPEMP(TYPEMP + 1); END; RETURN; END ENTER$PARM; /* ********************************************************** * * * EXECUTION OF SYNTHESIS BEGINS HERE..... * * * ********************************************************** */ IF LISTPROD AND PASS2 THEN DO; /* IF LISTPROD SET PRINT OUT PRODUCTIONS */ CALL PRINT(.('PROD $')); CALL PRINTDEC(PRODUCTION); CALL CRLF; END; CALL COPY; /* SETUP FOR ACCESSING PARSE TABLES */ DO CASE PRODUCTION; /* CALL TO SYNTHESIS HANDLES ONE PROD */ /* CASE 0 NOT USED */ ; /* 1 ::= _|_ */ ; /* 2 ::= */ DO; IF LOOKUP$ONLY(SP) THEN DO; IF GETRES THEN DO; IF CODESIZE <> GETADDR THEN CALL ERROR('DL'); END; ELSE DO; CALL SETADDR(CODESIZE); CALL SETYPE(LABLE); END; END; ELSE SEPARATOR = ASTRICK; CALL LINE$NUMBER; END; /* 3 | */ CALL LINE$NUMBER; /* 4 ::= */ CALL CHECK$UL$ERROR; /* 5 | */ ; /* 6 | */ ; /* 7 | */ ; /* 8 | */ ; /* 9 ::= */ ; /* 10 | : */ /* 10 */ ; /* 11 ::= */ ; /* 12 | */ ; /* 13 | */ ; /* 14 | */ ; /* 15 | */ ; /* 16 | */ ; /* 18 | */ /* 17 | */ ; ; /* 19 | */ ; /* 20 | */ ; /* 21 | */ ; /* 22 | */ ; /* 23 | */ ; /* 24 | */ ; /* 25 | */ ; /* 26 | */ ; /* 27 | */ ; /* 28 | */ ; /* 29 ::= LET */ ; /* 30 ::= */ IF CHKTYP2 THEN CALL GEN$STORE; /* 31 ::= = */ IF TYPEMP = SIMVAR THEN CALL LITERAL(SYMLOCMP); /* 32 ::= */ ; /* 33 | */ IF CHKTYP1 THEN CALL GENERATE(TYPEMP1); /* 34 ::= OR */ CALL SETTYPESP(BOR); /* 35 | XOR */ CALL SETTYPESP(EXR); /* 36 ::= */ ; /* 37 | AND */ /* 37 */ IF CHKTYP1 THEN CALL GENERATE(ANDO); /* 38 ::= */ ; /* 39 | NOT */ IF CHKTYP3 THEN CALL GENERATE(NOTO); /* 40 ::= */ ; /* 41 | */ /* 41 */ /* 41 */ IF CHKTYP2 THEN DO; IF STYPESP = FLOATPT THEN CALL GENERATE(TYPEMP1); ELSE DO; CALL GENERATE(TYPEMP1 + 16); CALL SETSTYPEMP(FLOATPT); END; END; /* 42 ::= */ ; /* 43 | + */ /* 43 */ IF CHKTYP2 THEN DO; IF STYPESP = FLOATPT THEN CALL GENERATE(FAD); ELSE CALL GENERATE(CAT); END; /* 44 | - */ /* 44 */ IF CHKTYP1 THEN CALL GENERATE(FMI); /* 45 | + */ IF CHKTYP3 THEN ; /* NO ACTION REQUIRED */ /* 46 | - */ IF CHKTYP3 THEN CALL GENERATE(NEG); /* 47 ::= */ ; /* 48 | * */ IF CHKTYP1 THEN CALL GENERATE(FMU); /* 49 | / */ IF CHKTYP1 THEN CALL GENERATE(FDI); /* 50 ::= */ ; /* 51 | ** */ IF CHKTYP1 THEN CALL GENERATE(EXP); /* 52 ::= */ IF TYPESP = SIMVAR THEN CALL LITLOAD(SYMLOCSP); ELSE CALL GENERATE(LOD); /* 53 | */ ; /* 54 | */ ; /* 55 | ( ) */ CALL SETSTYPEMP(STYPEMP1); /* 56 ::= */ CALL PROCESS$SIMPLE$VARIABLE(SP); /* 57 | ) */ DO; IF FORSTMT THEN CALL ERROR('FI'); CALL CHKTYP5; BASE = SYMLOCMP; IF GETSUBTYPE <> TYPEMP THEN CALL ERROR('SN'); CALL LITLOAD(GETADDR); CALL GENERATE(SUBO); CALL SETTYPEMP(SUBVAR); END; /* 58 ::= ( */ DO; IF((NOT LOOKUP$ONLY(MP)) OR (GETYPE <> SUBVAR)) THEN CALL ERROR('IS'); CALL SETTYPEMP(0); CALL SETSYMLOCMP(BASE); END; /* 59 | , */ CALL CHKTYP5; /* 60 ::= ) */ DO; CALL CHECKPARM; SRLOCSP = SRLOCMP; CALL FUNCGEN; END; /* 61 | */ CALL FUNCGEN; /* 62 ::= ( */ CALL GEN$PARM; /* 63 | */ /* 63 , */ DO; CALL CHECK$PARM; CALL GEN$PARM; END; /* 64 ::= */ IF LOOKUP$ONLY(SP) THEN DO; CALL SETSRLOCSP(BASE); CALL SETSYMLOCSP(BASE); CALL SETTYPESP(UNFUNC); CALL SETHASHSP(GETYPE); END; ELSE CALL ERROR('FU'); /* 65 | */ DO; CALL SETTYPESP(FUNCOP); CALL SETHASHSP(SHR(STYPESP,2) AND 07H); END; /* 66 ::= */ CALL GENCON; /* 67 | */ CALL GEN$ILS(.ACCUM); /* 68 ::= = */ CALL SETTYPESP(7); /* 69 | > = */ CALL SETTYPEMP(9); /* 70 | GE */ CALL SETTYPEMP(9); /* 71 | < = */ CALL SETTYPEMP(10); /* 72 | LE */ CALL SETTYPEMP(10); /* 73 | > */ CALL SETTYPESP(6); /* 74 | < */ CALL SETTYPESP(5); /* 75 | < > */ CALL SETTYPEMP(8); /* 76 | NE */ CALL SETTYPEMP(8); /* 77 ::= TO */ /* 77 */ DO; BASE = FORADDRESS(3); IF TYPESP THEN CALL GENERATE(DUP); CALL LITLOAD(GETADDR); CALL GENERATE(FAD); IF TYPESP THEN DO; CALL LITERAL(GETADDR); CALL GENERATE(XCH); END; CALL GENERATE(STO); IF TYPESP THEN DO; CALL GENERATE(XCH); CALL LITERAL(0); CALL GENERATE(LSS); CALL LITERAL(5); CALL GENERATE(BFC); CALL GENERATE(LEQ); CALL LITERAL(2); CALL GENERATE(BFN); END; CALL GENERATE(GEQ); CALL GENERATE(BRC); CALL GEN$TWO(FORADDRESS(0)); FORADDRESS(1) = CODESIZE; END; /* 78 ::= */ DO; CALL GENERATE(BRS); CALL GEN$TWO(FORADDRESS(1)); FORADDRESS(2) = CODESIZE; END; /* 79 ::= FOR */ DO; FORSTMT = TRUE; SBTBLTOP,NEXTSTMTPTR = SBTBLTOP - 8; NEXTBYTEV(1) = NEXTBYTEV(1) AND 7FH; CALL LIMITS(0); FORCOUNT = FORCOUNT + 1; END; /* 80 ::= STEP */ CALL SETTYPEMP(TRUE); /* 81 | */ DO; BASE = FORADDRESS(3); CALL LITERAL(GETADDR); CALL SETTYPESP(FALSE); CALL GENERATE(CON); CALL GEN$TWO(0); END; /* 82 ::= */ CALL ENTER$COMPILER$LABEL(0); /* 83 | */ CALL ENTER$COMPILER$LABEL(0); /* 84 | IF END # THEN */ DO; CALL GENERATE(RON); CALL GENERATE(DEF); CALL FINDLABEL; CALL GEN$TWO(GETADDR); END; /* 85 ::= */ ; /* 86 | */ CALL RESOLVE$LABEL; /* 87 ::= ELSE */ DO; CALL ENTER$COMPILER$LABEL(3); CALL GENERATE(BRS); CALL COMPILER$LABEL; END; /* 88 ::= IF THEN */ DO; IF STYPEMP1 = STRING THEN CALL ERROR('IE'); CALL GENERATE(BRC); CALL COMPILER$LABEL; END; /* 89 ::= */ /* 89 = */ IF CHKTYP2 THEN DO; BASE = SYMLOCMP; CALL SETYPE(TYPEMP1); CALL UNLINK; CALL GENERATE(XCH); CALL GENERATE(RTN); CALL ENTER$COMPILER$LABEL(0); END; /* 90 ::= DEF */ DO; DECLARE FLAG BYTE; CALL GENERATE(BRS); CALL COMPILER$LABEL; FLAG = NORMAL$LOOKUP(SP); CALL SETSTYPEMP(STYPESP); CALL SETSYMLOCMP(BASE); IF PASS1 THEN DO; IF FLAG THEN CALL ERROR('FD'); CALL SETADDR(CODESIZE); END; ELSE CALL RELINK; END; /* 91 ::= ) */ CALL ENTER$PARM; /* 92 | */ CALL SETTYPEMP(0); /* 93 ::= ( */ CALL SETTYPEMP(0); /* 94 | , */ CALL ENTER$PARM; /* 95 ::= */ ; /* 96 ::= FILE */ ; /* 97 | , */ ; /* 98 ::= */ DO; CALL PROCESS$SIMPLE$VARIABLE(MP); IF STYPEMP = FLOATPT THEN CALL ERROR('IF'); CALL LITLOAD(SYMLOCSP); CALL GENERATE(OPN); END; /* 99 ::= ( ) */ CALL CHKTYP4; /* 100 | */ CALL LITERAL(0); /* 101 ::= DIM */ /* 101 */ ; /* 102 ::= */ CALL SUBCALC; /* 103 | */ /* 103 */ /* 103 , */ CALL SUBCALC; /* 104 ::= ) */ DO; CALL CHKTYP5; BASE = SYMLOCMP; END; /* 105 ::= ( */ DO; IF NORMAL$LOOKUP(MP) AND PASS1 THEN CALL ERROR('DP'); CALL SETYPE(SUBVAR); IF PASS1 THEN CALL SETADDR(COUNTPRT); CALL LITERAL(GETADDR); CALL SETTYPEMP(0); CALL SETSYMLOCMP(BASE); END; /* 106 | , */ CALL CHKTYP5; /* 107 ::= CLOSE */ ; /* 108 ::= */ DO; IF STYPESP = STRING THEN CALL ERROR('MF'); CALL GENERATE(RON); CALL GENERATE(CLS); END; /* 109 | , */ DO; IF STYPESP = STRING THEN CALL ERROR('MF'); CALL GENERATE(RON); CALL GENERATE(CLS); END; /* 110 ::= READ */ IF FILEIO THEN DO; CALL GENERATE(EDR); FILEIO = FALSE; END; /* 111 | READ */ ; /* 112 ::= INPUT */ /* 112 */ DO; CALL GENERATE(ECR); INPUTSTMT = FALSE; END; /* 113 ::= ; */ DO; CALL PUT$FIELD; CALL SETUP$INPUT; END; /* 114 | */ CALL SETUP$INPUT; /* 115 ::= */ CALL GET$FIELD; /* 116 | , */ CALL GET$FIELD; /* 117 | */ FILEIO = FALSE; /* 118 ::= PRINT */ ; /* 119 | PRINT */ DO; CALL GENERATE(EDW); FILEIO = FALSE; END; /* 120 ::= */ CALL PUT$FIELD; /* 121 | */ /* 121 */ CALL PUT$FIELD; /* 122 | */ ; /* 123 ::= */ CALL PUT$FIELD; /* 124 | , */ CALL PUT$FIELD; /* 125 ::= */ ; /* 126 | */ CALL GENERATE(DBF); /* 127 ::= # ; */ DO; FILEIO = TRUE; CALL GENERATE(RON); CALL GENERATE(RDB); END; /* 128 | # , ; */ DO; FILEIO = TRUE; CALL GENERATE(RON); CALL GENERATE(XCH); CALL GENERATE(RON); CALL GENERATE(RDF); END; /* 129 ::= ; */ ; /* 130 | , */ IF NOT FILEIO THEN CALL GENERATE(NSP); /* 131 ::= */ CALL RESOLVE$LABEL; /* 132 ::=