Trailing-Edge
-
PDP-10 Archives
-
BB-4157D-BM
-
sources/cgstmn.bli
There are 12 other files named cgstmn.bli in the archive. Click here to see a list.
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
! OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
!COPYRIGHT (C) 1972,1977 BY DIGITAL EQUIPMENT CORPORATION
!AUTHOR: S. MURPHY/HPW/DCE/SJW
MODULE CGSTMNT(SREG=#17,VREG=#15,FREG=#16,DREGS=4,RESERVE(0,1,2,3)) =
BEGIN
GLOBAL BIND CGSTV = 5^24 + 1^18 + 131; !VERSION DATE: 14-AUG-77
%(
REVISION HISTORY
105 ----- ----- ADD CODE GENERATION ROUTINES FOR E1LISTCALL AND
E2LISTCALL NODES
106 ----- ----- GENERATE ZERO INCREMENT FOR E1 OR E2 LISTCALL
NODES OUT OF LINE
107 ----- ----- GENERATE CODE FOR COMMON SUBS ON CALL STMNTS
108 ----- ----- FOR A REFERENCE TO A FORMAT STMNT, MAKE THE
PEEPHOLE BUFFER ENTRY POINT TO THE FORMAT STMNT RATHER
THAN SIMPLY CONTAINING THE RELATIVE ADDRESS OF THE STRING
109 ----- ----- FIX CAE1LIST AND CAE2LIST TO CALL IOPTR INSTEAD
OF ARGGEN
110 ----- ----- ADD CODE TO HANDLE ARBITRARY EXPRESSION AS THE VAL
OF AN ARG TO OPEN; ADD CODE TO HANDLE ARBITRARY EXPRESSION
AS A UNIT NUMBER
111 ----- ----- FIX BUG IN 110 (HAD LEFT OUT "FIND" AND "OPEN/CLOSE"
FOR EXPRESSIONS AS UNIT NOS)
112 ----- ----- COMMENT OUT THE ROUTINE "CGRELS" - WE CALL
"CGMTOP" FOR RELEASE STMNTS
113 ----- ----- FIX ERROR CALLS
114 ----- ----- FIX REFERENCES TO PROEPITYP AND PROGNAME
115 ----- ----- FIX CGDCALL TO SET INDIRECT BIT OVER FORMAL
ARRAYS UNDER DATACALL NODES
116 ----- ----- FIX CALLS TO IOPTR IN CAE1LIST AND CAE2LIST TO
CLEAR PBOPWD FIRST
117 ----- ----- CHANGE IOIMMED AS FOLLOWS:
FOROTS WILL NOW PERFORM THE INDIRECT
FOR ALL ARGUMENTS NOT IMMEDIATE MODE
CONSTANTS
DISTINGUISH IMMEDIATE MODE CONSTANTS FROM
IMMEDIATE MODE ARGUMENTS IN MEMORY
AS FOLLOWS:
CONSTANTS HAVE AN EMPTY LEFT HALF
OTHER VARIABLES HAVE TYPE FIELD SET
ONLY AN ARGUMENT PASSED IN THE FIRST
ELEMENT OF A FORMAL ARRAY
WILL HAVE THE INDIRECT BIT
SET
FOROTS WILL PERFORM AN EXTRA OPERATION
TO LOAD THE RIGHT HALF OF THE ARGUMENT
IN MEMORY
118 ----- ----- DO NOT CALL "IOENDERR" FOR FIND STMNTS,
SIMPLY PUT OUT 2 WDS OF 0 (THE STMNT NODE DOES NOT HAVE END/ERR FIELDS)
119 ----- ----- IN CGSTMN, IF THE FLAG "DBGTRAC" IS SET CALL
XCTFDDT TO GENERATE "XCT FDDT."
120 ----- ----- TAKE OUT CALLS TO FIN. FOR NAMELIST READ/WRITE
122 ----- ----- DONT CALL "XCTFDDT" FOR STMNT FNS AND ENTRIES
UNTIL AFTER THE LABELS ON THEM ARE DEFINED
123 ----- ----- FIX CODE GEN FOR "DIALOG" IN AN OPEN STMNT
124 306 16156 FIX OPEN/CLOSE TO GIVE FOROTS FORMAL ARRAYS RIGHT
125 367 18239 MAKE WRITE(3) GENERATE CORRECT CODE
126 376 18398 PREVENT CGRECNUM FROM CHANGING A1LABEL
*********** BEGIN VERSION 5A *************
127 532 20323 SET INDIRECT BIT IN ARG BLOCK FOR ARRAY
REF AS ASSOCIATE VARIABLE
130 564 ----- MAKE CGREAD AND CGWRIT SYMMETRICAL:
MAKE CGREAD CHECK FOR NAMELIST ONLY IF IONAME
PTR NEQ 0;
MAKE CGWRIT GENERATE FIN CALL IF UNFORMATTED
131 607 22685 SET GLOBAL FLAG NEDZER IN CGEND, CGSTOP & CGPAUS
TO INDICATE ZERO-ARG-BLOCK NEEDED
)%
FORWARD
CGASMNT(0),CGAGO(0),CGCGO(0), CGLOGIF(0),CGARIF(0),CGASSI(0),CGCMNSUB(0),
CGPAUSE(0),CGSTOP(0),
CGIOLST(0),CGIOCALL(1),
CGIOLARGS(0),CGDCALL(0),CGSLIST(0),
CGE1LIST(1),CGE2LIST(1),
CAE1LIST(0),CAE2LIST(0),
BLDIOIMWD(1),
CGMTOP(0),CGREAD(0),CGWRIT(0),CGDECO(0),CGENCO(0),CGRERE(0),
CGUNIT(0),CGRECNUM(0),CGFIND(0),
CGCLOS(0),CGOPEN(0),CGEND(0),
IOPTR(1);
EXTERNAL CGERR,OUTMOD, PEEPOPTIMZ, CGFNCALL, CGARREF,
OPCMGET,OPGETA,OPGETI,OPGARI,OPGARA,OPGSTA,OPGSTI,
OPGPAU,OPGSTP,OPGEXI,OPGIOL,OPGREL,OPGBOOL,OPGCGO,OPGCGI,
OPGASR,OPGVTS,OPGAIF,ZERBLK,
%[607]% NEDZER, ! FLAG TO INDICATE IF ZERO-ARG-BLOCK NEEDED
OPGENDISP;
EXTERNAL
CGETVAL,CGOPGEN,
CGARGEVAL,TREEPTR,A1NODE,A2NODE,A1LABEL,C1H,OPDSPIX,REGFORCOMP,CSTMNT;
EXTERNAL
CGCBOOL,GENLAB,DEFLAB,CGREL1;
EXTERNAL CGDOLOOP,CGDOEND,CGPROEPI,CGSFN,CGSBPRGM,CGRETURN,CGARGS;
EXTERNAL
PBOPWD,PSYMPTR,OBUFF,OBUFFA;
EXTERNAL OPGASA,OPGASI,OPASIN;
EXTERNAL OPGAI1,OPGAI2;
SWITCHES NOLIST;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
SWITCHES LIST;
MAP PEXPRNODE TREEPTR:A1NODE:A2NODE;
MAP BASE CSTMNT;
OWN BASE TOPSTMNT; !WHEN HAVE A STATEMENT EMBEDDED INSIDE ANOTHER (EG IN
! LOGICAL IFS) THIS VAR PTS TO THE TOP LEVEL STMNT NODE
GLOBAL ROUTINE CGSTMNT=
%(***************************************************************************
ROUTINE TO PERFORM CODE GENERATION FOR A STATEMENT.
CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT FOR WHICH CODE
IS TO BE GENERATED.
***************************************************************************)%
BEGIN
EXTERNAL XCTFDDT; !ROUTINE TO GENERATE "XCT FDDT."
EXTERNAL PBFPTR;
MAP PPEEPFRAME PBFPTR;
%(***IF THERE IS A LABEL ON THIS STATEMENT, ASSOCIATE THAT LABEL WITH THE
CURRENT LOCATION***)%
IF .CSTMNT[SRCLBL] NEQ 0
THEN DEFLAB(.CSTMNT[SRCLBL]);
%(***SET ISN FIELD FOR NEXT INSTR TO BE GENERATED TO ISN OF THIS STMNT***)%
PBFPTR[PBFISN]_.CSTMNT[SRCISN];
IF .FLGREG<DBGTRAC> !IF USER SPECIFIED /DEB:TRACE
THEN
( IF .CSTMNT[SRCID] NEQ ENTRID AND .CSTMNT[SRCID] NEQ SFNID
THEN XCTFDDT()); ! GENERATE "XCT FDDT."
%(***GENERATE CODE FOR THE STATEMENT************)%
CASE .CSTMNT[SRCID] OF SET
CGASMNT(); !FOR AN ASSIGNMENT
CGASSI(); ! ASSIGN
BEGIN ! CALL
IF .CSTMNT[SRCCOMNSUB] NEQ 0
THEN CGCMNSUB(); !IF HAVE ANY COMMON SUBS
! GENERATE CODE FOR THEM
CGSBPRGM(.CSTMNT[CALLIST],.CSTMNT[CALSYM]);
END;
BEGIN END; ! CONTINUE
CGDOLOOP(); ! DO
CGPROEPI(); ! ENTRY
CGASMNT(); ! COMMON SUBEXPR - SAME AS ASMNT
JRSTGEN(.CSTMNT[GOTOLBL]); !GOTO
CGAGO(); ! ASSIGNED GOTO
CGCGO(); ! COMPUTED GOTO
CGARIF(); !ARITHMETIC IF
CGLOGIF(); ! LOGICAL IF
CGRETURN(.CSTMNT[RETEXPR]); ! RETURN
CGSTOP(); ! STOP
CGREAD(); ! READ
CGWRIT(); ! WRITE
CGDECO(); ! DECODE
CGENCO(); ! ENCODE
CGRERE(); ! REREAD
CGFIND(); ! FIND
CGCLOS(); ! CLOSE
BEGIN END; ! INPUT (NOT IN RELEASE 1)
BEGIN END; ! OUTPUT (NOT IN RELEASE 1)
CGMTOP(); ! BACKSPACE
CGMTOP(); ! BACKFILE
CGMTOP(); ! REWIND
CGMTOP(); ! SKIP FILE
CGMTOP(); ! SKIP RECORD
CGMTOP(); ! UNLOAD
CGMTOP(); ! RELEASE
CGMTOP(); ! ENDFILE
CGEND(); ! END
CGPAUSE(); ! PAUSE
CGOPEN(); ! OPEN
CGSFN(); ! STATEMENT FN
BEGIN END; ! FORMAT - NO CODE GENERATED
BEGIN END; ! BLT (NOT IN RELEASE 1)
BEGIN END; ! OVERLAY ID
TES;
%(***IF THIS STMNT HAS A LABEL, CHECK FOR WHETHER IT ENDS A DO STMNT***)%
IF .CSTMNT[SRCLBL] NEQ 0
THEN CGDOEND(.CSTMNT[SRCLBL]);
END;
GLOBAL ROUTINE CGASMNT=
%(***************************************************************************
ROUTINE TO GENERATE CODE FOR ASSIGNMENT STATEMENTS.
CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT FOR
WHICH CODE IS TO BE GENERATED.
***************************************************************************)%
BEGIN
%(***COMPUTE THE VALUES OF ANY COMMON SUBEXPRS ASSOCIATED WITH THIS STATEMENT***)%
IF .CSTMNT[SRCCOMNSUB] NEQ 0 THEN CGCMNSUB();
%(***GET THE VALUE OF THE LEFT HAND SIDE OF THE STATEMENT AND THE ADDRESS
OF THE RIGHT HAND SIDE WITHIN REACH OF ONE INSTRUCTION***)%
IF .CSTMNT[A1VALFLG]
OR (.CSTMNT[MEMCMPFLG] AND .CSTMNT[RVRSFLG]) !IF RHS IS COMPUTED DIRECTLY TO
! MEMORY LOC OF LHS AND VAL OF LHS NEEDNT BE PRELOADED
THEN
BEGIN
IF NOT .CSTMNT[A2VALFLG]
THEN
BEGIN
TREEPTR_.CSTMNT[RHEXP];
CGETVAL();
END;
END
ELSE
IF .CSTMNT[A2VALFLG]
THEN
BEGIN
TREEPTR_.CSTMNT[LHEXP];
CGETVAL();
END
ELSE
IF .CSTMNT[RVRSFLG]
THEN
%(***IF RIGHT-HAND SIDE SHOULD BE EVALUATED FIRST***)%
BEGIN
TREEPTR_.CSTMNT[RHEXP];
CGETVAL();
TREEPTR_.CSTMNT[LHEXP];
CGETVAL();
END
ELSE
%(***IF LEFT-HAND SIDE SHOULD BE EVALUATED FIRST***)%
BEGIN
TREEPTR_.CSTMNT[LHEXP];
CGETVAL();
TREEPTR_.CSTMNT[RHEXP];
CGETVAL();
END;
%(***IF THE RHS WAS NOT COMPUTED DIRECTLY INTO THE MEMORY LOC FOR THE LHS, PICK UP THE
RHS AND STORE IT INTO THE LHS*******)%
IF NOT .CSTMNT[MEMCMPFLG]
THEN
BEGIN
REGFORCOMP_GETASMNREG(CSTMNT);
%(***GET VAL OF RIGHT-HAND SIDE INTO REG FOR COMPUTATION OF THE STMNT***)%
A1NODE_.CSTMNT[RHEXP];
TREEPTR_.CSTMNT;
OPDSPIX_GETA2OPIX(CSTMNT,A1NODE);
CGOPGEN();
%(***STORE THE VALUE FROM REG-FOR-COMPUTATION INTO THE ADDRESS
SPECIFIED BY THE LEFT-HAND-SIDE***)%
IF NOT .CSTMNT[A1SAMEFLG]
THEN
BEGIN
TREEPTR_.CSTMNT[LHEXP];
OPDSPIX_ASNOPIX(CSTMNT,TREEPTR);
CGOPGEN();
END;
END;
END;
GLOBAL ROUTINE CGASSI=
%(***************************************************************************
GENERATE CODE FOR AN ASSIGN STATEMENT.
NOTE THAT THE VARIABLE WILL ALWAYS BE LOADED INTO REGISTER 1
***************************************************************************)%
BEGIN
%(***IF THE ASSIGNED VAR IS AN ARRAYREF, GENERATE CODE TO COMPUTE ITS ADDR***)%
TREEPTR_.CSTMNT[ASISYM];
IF .TREEPTR[OPRCLS] EQL ARRAYREF
THEN
CGETVAL();
%(***COMPUTE THE ASSIGN*******)%
A1NODE_.CSTMNT[ASISYM];
A1LABEL_.CSTMNT[ASILBL];
OPDSPIX_OPASIN;
CGOPGEN();
END;
GLOBAL ROUTINE CGAGO=
%(***************************************************************************
ROUTINE TO GENERATE CODE FOR ASSIGNED GOTO STATEMENT.
CALLED WITH "CSTMNT" POINTING TO THE STATEMENT TO BE PROCESSED.
IF A LIST OF LABELS WAS SPECIFIED FOR THIS STMNT,
CODE GENERATED IS:
MOVE 1,VAR
CAIN 1,LAB1
JRST LAB1
CAIN 1,LAB2
JRST LAB2
.
.
IF NOT, THE CODE GENERATED IS
SKIPE 1,VAR
JRST 0(1)
***************************************************************************)%
BEGIN
%(***OPCODES NEEDED FOR CODE FOR ASSIGNED GOTO***)%
BIND
HRRZOC=#550^27,
CAINOC=#306^27,
SKIPEOC=#332^27;
%(***ALWAYS USE REGISTER 1 TO HOLD THE ASSIGNED VAR***)%
BIND AGOREG=1^23;
BIND AGORGIX=1^18;
OWN AGOLSTPTR;
OWN PEXPRNODE AGOVAR;
%(***SET UP THE GLOBALS "PBOPWD" AND "PSYMPTR" USED BY THE OUTPUT ROUTINE
TO INDICATE AN ADDRESS REFERENCE TO THE ASSIGNED VARIABLE***)%
AGOVAR_.CSTMNT[AGOTOLBL];
%(***IF ASSIGNED VAR IS AN ARRAY REFERENCE*****)%
IF .AGOVAR[OPRCLS] EQL ARRAYREF
THEN
BEGIN
TREEPTR_.AGOVAR;
CGETVAL();
PSYMPTR_.AGOVAR[ARG1PTR]; !SYMBOL TABLE ENTRY FOR THE
! ARRAY
PBOPWD_.AGOVAR[TARGET]; !ADDRESS FIELD TO REF THE ARRAY
! ELEMENT DESIRED
END
%(***IF ASSIGNED VAR IS A SCALAR***)%
ELSE
BEGIN
PSYMPTR_.AGOVAR;
PBOPWD_.AGOVAR[IDADDR];
END;
%(****IF NO LIST OF LABELS WAS SPECIFIED******)%
IF .CSTMNT[GOTOLIST] EQL 0
THEN
BEGIN
%(***GENERATE "SKIPE 1,VAR" ***)%
PBOPWD_.PBOPWD OR SKIPEOC OR AGOREG;
OBUFF();
%(***GENERATE JRST 0(1)***)%
PSYMPTR_PBFNOSYM;
PBOPWD_JRSTOC OR AGORGIX;
OBUFF();
END
%(***IF A LIST OF LABELS WAS SPECIFIED***)%
ELSE
BEGIN
%(***GENERATE HRRZ 1,VAR****)%
PBOPWD_.PBOPWD OR HRRZOC OR AGOREG;
OBUFF();
%(***FOR EACH LABEL IN THE LIST, COMPARE REG 1 WITH THE LABEL AND
IF IT IS EQUAL, TRANSFER TO THE LABEL*****)%
AGOLSTPTR_.CSTMNT[GOTOLIST];
DECR CT FROM (.CSTMNT[GOTONUM]-1) TO 0
DO
BEGIN
PBOPWD_CAINOC OR AGOREG OR @.AGOLSTPTR;
PSYMPTR_PBFLABREF;
OBUFF();
JRSTGEN(@.AGOLSTPTR);
AGOLSTPTR_.AGOLSTPTR+1;
END;
END;
END;
GLOBAL ROUTINE CGCGO=
%(***************************************************************************
ROUTINE TO GENERATE CODE FOR COMPUTED GOTO.
CODE GENERATED IS:
SKIPLE 01,VAL
CAILE 01,CT
JRST Y
JRST @.(1)
ARG L1
ARG L2
.
.
Y: 1ST INSTR OF NEXT STMNT
CALLED WITH THE GLOBAL CSTMNT POINTING TO THE COMPUTED GOTO STMNT
***************************************************************************)%
BEGIN
OWN BASE NXTSTMNT;
%(***DEFINE OPCODES USED FOR COMPUTED GOTO***)%
BIND SKIPLEOC=#333^27,
CAILEOC=#303^27,
SKIPAOC=#334^27,
ARGOC=JUMPOCD^27; !USE JUMP
%(***ALWAYS USE REGISTER 1 TO HOLD THE COMPUTED VAL***)%
BIND CGOREG=1^23,
CGORGIX=1^18;
OWN PEXPRNODE CGOEXP;
OWN CLOC;
OWN CGOLSTPTR;
%(***COMPUTE THE VALUES OF ANY COMMON SUBEXPRS ASSOCIATED WITH THIS STMNT***)%
IF .CSTMNT[SRCCOMNSUB] NEQ 0 THEN CGCMNSUB();
CGOEXP_.CSTMNT[CGOTOLBL];
%(***IF THE EXPRESSION IS NOT A SCALAR OR A COMMON SUB, EVALUATE IT***)%
IF .CGOEXP[OPRCLS] NEQ DATAOPR AND .CGOEXP[OPRCLS] NEQ CMNSUB
THEN
BEGIN
TREEPTR_.CGOEXP;
CGETVAL();
END;
%(***GENERATE THE SKIPLE, CAILE, JRST SEQUENCE***)%
%(******DETERMINE WHAT THE LABEL ON THE NEXT STMNT IS, IF THERE IS NONE, GENERATE ONE***)%
%(*******(NOTE THAT IF THIS STMNT IS EMBEDDED INSIDE AN ARITH OR LOGICAL IF, MUST
LOOK AT THE "TOP-LEVEL" STMNT NODE TO GET A PTR TO THE NEXT STMNT)***)%
NXTSTMNT_(IF .CSTMNT[CLINK] NEQ 0 THEN .CSTMNT[CLINK] ELSE .TOPSTMNT[CLINK]);
A1LABEL_(IF .NXTSTMNT[SRCLBL] NEQ 0 THEN .NXTSTMNT[SRCLBL]
ELSE (NXTSTMNT[SRCLBL]_GENLAB() ) );
A1NODE_.CGOEXP;
C1H_.CSTMNT[GOTONUM];
%(***HAVE A SPECIAL CASE WHEN THE EXPRESSION IS THE LOOP INDEX OF A LOOP IN
WHICH THE INDEX IS STORED IN THE RIGHT HALF OF AN AC
(IN THIS CASE GENERATE:
MOVEI 1,0(LOOPAC)
JUMPLE 1,Y
CAILE 1,CT
JRST Y)
*********)%
IF .CSTMNT[A1IMMEDFLG] AND .CGOEXP[OPRCLS] EQL REGCONTENTS
THEN OPDSPIX_OPGCGI
ELSE OPDSPIX_OPGCGO;
CGOPGEN();
%(***ASSOCIATE A LABEL WITH THE CURRENT LOC***)%
CLOC_GENLAB();
DEFLAB(.CLOC);
%(***GENERATE JRST @CLOC(1)***)%
PBOPWD_JRSTOC OR INDBIT OR CGORGIX OR .CLOC;
PSYMPTR_PBFLABREF;
OBUFF();
%(***FOR EACH LABEL LISTED, GENERTAE "ARG LAB"***)%
PSYMPTR_PBFLABREF;
CGOLSTPTR_.CSTMNT[GOTOLIST];
DECR CT FROM (.CSTMNT[GOTONUM]-1) TO 0
DO
BEGIN
PBOPWD_ARGOC OR @.CGOLSTPTR;
OBUFF();
CGOLSTPTR_.CGOLSTPTR+1;
END;
END;
GLOBAL ROUTINE CGLOGIF=
%(***************************************************************************
ROUTINE TO GENERATE CODE FOR LOGICAL IF STATEMENTS.
CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT FOR
WHICH CODE IS TO BE GENERATED.
A LOGICAL IF STATEMENT NODE MAY HAVE THE FLAG "A1NOTFLG" SET, WHICH
MEANS TO TAKE THE "NOT" (COMPLEMENT) OF THE CONDITION SPECIFIED.
BECAUSE "NOT" PROPAGATES OVER BOTH BOOLEANS AND RELATIONALS, IT IS ASSUMED
THAT THIS FLAG WILL NEVER BE SET WHEN THE CONDITION IS A BOOLEAN OR RELATIONAL.
***************************************************************************)%
BEGIN
OWN THENLAB,ELSELAB; !NEW LABEL TABLE ENTRIES
!WHICH WILL BE CREATED TO PROCESS
! THIS STMNT
OWN BASE SUBSTATMNT; !STATEMENT TO BE EXECUTED IF CONDITION HOLDS
OWN BASE SAVSTMNT; !SAVE PTR TO THE LOG IF STATEMENT
OWN PEXPRNODE CONDEXPR; !CONDITIONAL EXPRESSION TO BE TESTED
%(***EVALUATE ANY COMMON SUBEXPRESSIONS UNDER THIS STATEMENT***)%
IF .CSTMNT[SRCCOMNSUB] NEQ 0 THEN CGCMNSUB();
SUBSTATMNT_.CSTMNT[LIFSTATE];
CONDEXPR_.CSTMNT[LIFEXPR];
TREEPTR_.CSTMNT[LIFEXPR];
%(*****WHEN THE STATEMENT TO BE EXECUTED IF CONDITION IS TRUE IS A GOTO***)%
IF .SUBSTATMNT[SRCID] EQL GOTOID
THEN
BEGIN
%(****IF THE CONDITION TO BE TESTED IS A RELATIONAL***)%
IF .CONDEXPR[OPRCLS] EQL RELATIONAL
THEN
BEGIN
CGREL1(FALSE); !SKIP NEXT INSTR IF REL IS FALSE
%(***GENERATE A JRST TO THE GOTO-LABEL***)%
JRSTGEN(.SUBSTATMNT[GOTOLBL]);
END
%(***IF THE CONDITION TO BE TESTED IS A BOOLEAN***)%
ELSE
IF .CONDEXPR[OPRCLS] EQL BOOLEAN
THEN
BEGIN
ELSELAB_GENLAB(); !CREATE LABEL TABLE ENTRY FOR LABEL
! TO GO TO IF CONDITION IS FALSE
CGCBOOL(.SUBSTATMNT[GOTOLBL],.ELSELAB);
DEFLAB(.ELSELAB);
END
ELSE
%(***IF CONDITION IS NOT A RELATIONAL OR BOOLEAN, EVALUATE THE CONDEXPR AND
TEST WHETHER IS IS TRUE (SIGN BIT EQUAL 1) OR FALSE(SIGN=0) ***)%
BEGIN
CGETVAL();
%(***TEST VAL OF CONDEXPR,
IF "A1NOTFLG" IS SET, TRANSFER TO GOTO-LABEL IF ARG IS
FALSE, OTHERWISE TRANSFER TO GOTOLABEL IF ARG IS TRUE***)%
OPDSPIX_CNDVTRIX(CONDEXPR,(IF .CSTMNT[A1NOTFLG] THEN FALSE ELSE TRUE));
A1LABEL_.SUBSTATMNT[GOTOLBL];
TREEPTR_.CONDEXPR;
REGFORCOMP_GETTAC(TREEPTR);
CGOPGEN();
END;
END
%(****WHEN STATEMENT TO BE EXECUTED ON TRUE CONDITION IS NOT A GOTO***)%
ELSE
BEGIN
ELSELAB_GENLAB(); !CREATE LABEL TABLE ENTRY FOR LABEL
! TO GO TO WHEN CONDITION IS FALSE
%(***IF CONDITION TO BE TESTED IS A RELATIONAL***)%
IF .CONDEXPR[OPRCLS] EQL RELATIONAL
THEN
BEGIN
CGREL1(TRUE); !SKIP NEXT INSTR IF REL IS TRUE
%(***GENERTAE CODE TO GO TO THE LABEL ON THE CODE FOLLOWING THAT
FOR THE SUBSTATMNT OF THE IF STMNT***)%
JRSTGEN(.ELSELAB);
END
%(***IF THE CONDITION TO BE TESTED IS A BOOLEAN*****)%
ELSE
IF .CONDEXPR[OPRCLS] EQL BOOLEAN
THEN
BEGIN
THENLAB_GENLAB(); !CREATE LABEL TABLE ENTRY FOR LABEL TO
! GO TO WHEN CONDITION IS TRUE
CGCBOOL(.THENLAB,.ELSELAB);
DEFLAB(.THENLAB); !ASSOCIATE THIS LOC WITH THENLAB
END
%(***IF CONDITIONAL EXPRESSION IS NOT A REL OR BOOLEAN, EVALUATE IT AND
TEST WHETHER ITS VAL IS TRUE (SIGN=1) OR FALSE (SIGN=0)***)%
ELSE
BEGIN
CGETVAL();
%(***TEST VAL OF CONDEXPR,
IF "A1NOTFLG" IS SET, TRANSFER TO ELSELAB IF VAL IS TRUE
OTHERWISE TRANSFER TO ELSELAB IF VAL IS FALSE***)%
OPDSPIX_CNDVTRIX(CONDEXPR,(IF .CSTMNT[A1NOTFLG] THEN TRUE ELSE FALSE));
A1LABEL_.ELSELAB;
TREEPTR_.CONDEXPR;
REGFORCOMP_GETTAC(TREEPTR);
CGOPGEN();
END;
%(****GENERATE CODE FOR THE STATEMENT TO BE EXECUTED WHEN THE CONDITION IS TRUE***)%
TOPSTMNT_.CSTMNT; !SAVE A PTR TO THIS "TOP-LEVEL" STMNT
SAVSTMNT_.CSTMNT;
CSTMNT_.SUBSTATMNT;
CGSTMNT();
CSTMNT_.SAVSTMNT; !RESTORE THE GLOBAL CSTMNT
%(***ASSOCIATE THIS LOC WITH THE LABEL TRANSFERED TO WHEN THE CONDITION
IS FALSE****)%
DEFLAB(.ELSELAB);
END;
END;
GLOBAL ROUTINE CGEND=
%(*********************************************************
TO GENERATE CODE FOR AN END STATEMENT
**********************************************************)%
BEGIN
EXTERNAL CGEPILOGUE;
%[607]% EXTERNAL NEDZER; ! FLAG TO INDICATE IF ZERO-ARG-BLOCK NEEDED
EXTERNAL ZERBLK;
!AN END TRIGGERS A CALL TO EXIT ONLY IN A MAIN
!PROGRAM, NOT FOR A SUBPROGRAM
!IN A SUBPROGRAM THE END TRIGGERS A RETURN.
IF .FLGREG<PROGTYP> EQL MAPROG
THEN
BEGIN
%[607]% NEDZER _ 1; ! FLAG ZERO-ARG-BLOCK NEEDED
A1LABEL_.ZERBLK; !ARGLIST FOR CALL TO EXIT IS ALWAYS
! 0 FOR THE END STMNT
OPDSPIX_OPGEXI;
CGOPGEN();
END
ELSE
!ALSO CHECK FOR A BLOCK DATA SUBPROGRAM
IF .FLGREG<PROGTYP> NEQ BKPROG
THEN
BEGIN
!IF THERE ARE MULTIPLE ENTRIES OR LABELS AS ARGS
IF .FLGREG<MULTENT> OR .FLGREG<LABLDUM>
! HAS MULTIPLE ENTRIES
THEN CGRETURN(0); ! GENERATE CODE TO "RETURN"
!FOR A SINGLE ENTRY SUBPROGRAM GENERATE THE
!EPILOGUE
IF NOT .FLGREG<MULTENT>
THEN
BEGIN
REGISTER BASE TSTMNT;
TSTMNT_.SORCPTR<LEFT>; !PTR TO 1ST STMNT IN PROG
WHILE .TSTMNT[SRCID] NEQ ENTRID
DO
BEGIN
TSTMNT_.TSTMNT[CLINK]; !(SKIP DUMMY CONTINUES)
IF .TSTMNT EQL 0 THEN CGERR() !IF NEVER FIND THE ENTRY
END;
CGEPILOGUE(.TSTMNT); !GENERATE THE EPILOGUE CORRESPONDING TO THIS ENTRY
END;
END
END;
GLOBAL ROUTINE CGSTOP=
%(***************************************************************************
TO GENERATE CODE FOR A STOP STMNT
***************************************************************************)%
BEGIN
%[607]% EXTERNAL NEDZER; ! FLAG TO INDICATE IF ZERO-ARG-BLOCK NEEDED
EXTERNAL ZERBLK;
%(***USE THE ZERO-ARG-BLOCK AS THE ARG BLOCK FOR THIS CALL TO FOROTS***)%
A1LABEL_(IF .CSTMNT[STOPIDENT] EQL 0 !IF DO NOT HAVE A CNST
! TO PRINT OUT, THEN ARGLIST
! FOR EXIT WILL BE 0
%[607]% THEN (NEDZER _ 1; .ZERBLK) ! FLAG ZERO-ARG-BLOCK NEEDED
ELSE GENLAB() ); !IF HAVE AN ARG TO
! PASS TO EXIT, ASSOCIATE A LABEL
! WITH THE ARGLIST TO BE GENERATED
CSTMNT[STOPLBL]_.A1LABEL; !SAVE LABEL TO BE USED
OPDSPIX_OPGSTP;
CGOPGEN();
END;
GLOBAL ROUTINE CGPAUSE=
%(***************************************************************************
ROUTINE TO GENERATE CODE FOR PAUSE
***************************************************************************)%
BEGIN
%[607]% EXTERNAL NEDZER; ! FLAG TO INDICATE IF ZERO-ARG-BLOCK NEEDED
EXTERNAL ZERBLK;
A1LABEL_(IF .CSTMNT[PAUSIDENT] EQL 0 !IF DO NOT HAVE A CNST
! TO PRINT OUT, THEN ARGLIST
! FOR FOROTS "PAUSE" ROUTINE WILL BE 0
%[607]% THEN (NEDZER _ 1; .ZERBLK) ! FLAG ZERO-ARG-BLOCK NEEDED
ELSE GENLAB() ); !IF HAVE AN ARG TO
! PASS TO FOROTS, ASSOCIATE A LABEL
! WITH THE ARGLIST TO BE GENERATED
CSTMNT[PAUSLBL]_.A1LABEL;
OPDSPIX_OPGPAU;
CGOPGEN();
END;
GLOBAL ROUTINE CGARIF=
%(***************************************************************************
ROUTINE TO GENERATE CODE FOR AN ARITHMETIC IF STATEMENT.
CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT
FOR WHICH CODE IS TO BE GENERATED.
***************************************************************************)%
BEGIN
EXTERNAL A1LABEL,A2LABEL,A3LABEL; !GLOBALS USED BY THE CODE-GENERATION
EXTERNAL REGFORCOMP,A1NODE,A2NODE; ! TABLE DRIVER
EXTERNAL TREEPTR;
MAP PEXPRNODE A1NODE:A2NODE:TREEPTR;
OWN BASE NXTSTMNT;
OWN PEXPRNODE CONDEXPR; !THE ARITHMETIC EXPRESSION UNDER THIS STMNT
%(***COMPUTE ANY COMMON SUBEXPRESSIONS UNDER THIS NODE***)%
IF .CSTMNT[SRCCOMNSUB] NEQ 0 THEN CGCMNSUB();
%(***DETERMINE WHICH (IF ANY) OF THE 3 LABELS ASSOCIATED WITH
THIS NODE ARE EQUAL TO THE LABEL ON THE FOLLOWING STMNT***)%
NXTSTMNT_.CSTMNT[SRCLINK];
CSTMNT[AIFLBNXT]_
BEGIN
IF .CSTMNT[AIFLESS] EQL .NXTSTMNT[SRCLBL]
THEN LLBNXT
ELSE
IF .CSTMNT[AIFEQL] EQL .NXTSTMNT[SRCLBL]
THEN ELBNXT
ELSE
IF .CSTMNT[AIFGTR] EQL .NXTSTMNT[SRCLBL]
THEN GLBNXT
ELSE NOLBNXT
END;
%(***GET PTR TO THE CONDITIONAL EXPRESSION***)%
CONDEXPR_.CSTMNT[AIFEXPR];
TREEPTR_.CONDEXPR;
%(***COMPUTE THE VAL OF THE ARITH EXPR, THEN TEST IT****)%
%(***COMPUTE THE VAL OF THE ARITH EXPR***)%
IF NOT .CSTMNT[A1VALFLG]
THEN CGETVAL();
%(***IF THERE IS A NEG ON THE VALUE, EXCHANGE THE GTR AND LESS LABELS***)%
IF .CSTMNT[A1NEGFLG]
THEN
BEGIN
A1LABEL_.CSTMNT[AIFGTR];
A3LABEL_.CSTMNT[AIFLESS];
A2LABEL_.CSTMNT[AIFEQL];
%(***MODIFY THE "AIFLBNXT" FIELD WHICH INDICATED WHICH OF
THE 3 LABELS IS ON THE NEXT STMNT (CHANGE "GTR LABEL NEXT"
TO "LESS LABEL NEXT", "LESS LABEL NEXT" TO
"GTR LABEL NXT" LEAVE OTHERS UNCHANGED
MODIFY THE "AIFLBEQV" FIELD SO THAT "GTR LABEL SAME
AS EQL LABEL" BECOMES "LESS LABEL SAME AS EQL LABEL"
AND VICE-VERSA
****)%
SWPAIFFLGS(CSTMNT);
END
ELSE
BEGIN
A1LABEL_.CSTMNT[AIFLESS];
A3LABEL_.CSTMNT[AIFGTR];
A2LABEL_.CSTMNT[AIFEQL];
END;
%(***USE THE TABLE-DRIVER TO GENERATE CODE TO TEST THE VAL AND TRANSFER***)%
REGFORCOMP_GETAIFREG(CSTMNT);
OPDSPIX_AIFIX(CSTMNT,CONDEXPR);
A1NODE_.CONDEXPR;
CGOPGEN();
END;
GLOBAL ROUTINE CGCMNSUB=
%(***************************************************************************
GENERATE CODE TO EVLUATE ANY COMMON SUBEXPRESSIONS THAT OCCUR UNDER
THE STATEMENT NODE POINTED TO BY "CSTMNT"
***************************************************************************)%
BEGIN
OWN PEXPRNODE CCMNSUB;
%(***COMPUTE THE VALUES OF ANY COMMON SUBEXPRS ASSOCIATED WITH THIS STATEMENT***)%
CCMNSUB_.CSTMNT[SRCCOMNSUB];
UNTIL .CCMNSUB EQL 0
DO
BEGIN
IF NOT .CCMNSUB[A2VALFLG]
THEN
BEGIN
TREEPTR_.CCMNSUB[ARG2PTR];
CGETVAL();
END;
%(***IF THE COMMON SUBEXPR IS TO BE LEFT IN A DIFFERENT PLACE THAN
THAT INTO WHICH IT WAS COMPUTED, PUT IT THERE.
NOT THAT THIS CAN ONLY OCCUR WHEN THE PLACE IN WHICH
IT IS TO BE LEFT IS A REGISTER.
*******)%
IF NOT .CCMNSUB[A2SAMEFLG]
THEN
BEGIN
A1NODE_.CCMNSUB[ARG2PTR];
OPDSPIX_GETA2OPIX(CCMNSUB,A1NODE);
REGFORCOMP_GETTAC(CCMNSUB);
CGOPGEN();
END;
%(***IF THE VAL OF THIS COMMON SUB MUST BE STORED INTO A TMP, GENERATE
CODE TO DO SO***)%
IF .CCMNSUB[STOREFLG]
THEN
BEGIN
TREEPTR_.CCMNSUB;
REGFORCOMP_GETTAC(CCMNSUB);
OPDSPIX_STOROPIX(CCMNSUB);
CGOPGEN();
END;
CCMNSUB_.CCMNSUB[CLINK];
END;
END;
GLOBAL ROUTINE CGIOLST=
%(***************************************************************************
ROUTINE TO PERFORM CODE GENERATION FOR AN IOLIST.
CALLED WITH THE GLOBAL CSTMNT POINTING TO THE STATEMENT FOR WHICH AN
IOLIST IS TO BE PROCESSED.
FOR EACH ELEMENT IN THE IOLIST:
1. IF THE ELEMENT IS A "STATEMENT" (EITHER A DO, OR A CONTINUE
WHICH TERMINATES A DO-LOOP, OR AN ASSIGNMENT), PERFORM
USUAL CODE GENERATION FOR THAT TYPE OF STATEMENT
2. IF THE ELEMENT IS AN "IOLSCLS" NODE (IE A DATACALL, SLISTCALL,
IOLSTCALL,E1LISTCALL,OR E2LISTCALL), PERFORM CODE
GENERATION FOR ALL ELEMENTS UNDER THE NODE AND
ALSO GENERATE:
MOVEI 16,ARGBLKP
PUSHJ 17,IOLST.
WHERE ARGBLKP IS A PTR TO THE ARGBLOCK FOR THIS ELEMENT
***************************************************************************)%
BEGIN
LOCAL SAVSTMNT;
LOCAL BASE IOLELEM;
EXTERNAL GENLAB;
EXTERNAL OPDSPIX,A1LABEL,CGOPGEN,OPGFIN;
%(***GET PTR TO 1ST ELEMENT ON THE IOLIST TO BE PROCESSED***)%
IOLELEM_.CSTMNT[IOLIST];
%(***SAVE PTR TO CURRENT STATEMENT (IF THERE ARE DO-STMNTS IN THE IOLIST,
WILL CLOBBER CSTMNT) *****)%
SAVSTMNT_.CSTMNT;
%(***WALK THUR THE IOLIST, PROCESSING ALL ELEMENTS***)%
UNTIL .IOLELEM EQL 0
DO
BEGIN
IF .IOLELEM[OPRCLS] EQL STATEMENT
THEN
BEGIN
CSTMNT_.IOLELEM;
CGSTMNT();
%(***IF THE LAST ELEMENT IN AN IO-LIST FOR A GIVEN STMNT IS
NOT OF IOLSCLS (IE DOES NOT GENERATE AN ARG-LIST)
THEN MUST GENERATE A "PUSHJ 17,FIN."
********)%
IF .IOLELEM[CLINK] EQL 0
THEN
BEGIN
OPDSPIX_OPGFIN;
CGOPGEN();
END;
END
ELSE
IF .IOLELEM[OPRCLS] EQL IOLSCLS
THEN
BEGIN
%(***GENERATE CODE TO EVALUATE ALL EXPRESSIONS UNDER THIS ELEMENT***)%
CASE .IOLELEM[OPERSP] OF SET
%(***FOR A DATACALL NODE - EVAL THE EXPR UNDER THE NODE ***)%
BEGIN
TREEPTR_.IOLELEM[DCALLELEM];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN
CGETVAL();
END;
%(***FOR AN SLISTCALL NODE - EVAL THE EXPR FOR THE NUMBER OF ELEMS***)%
BEGIN
TREEPTR_.IOLELEM[SCALLCT];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN
CGETVAL();
END;
%(***FOR AN IOLSTCALL NODE - EVAL ALL EXPRS UNDER IT****)%
CGIOCALL(.IOLELEM);
%(***FOR AN E1LISTCALL NODE - OPTIMIZED CODE ONLY***)%
BEGIN
LOCAL BASE SAVCSTMNT;
SAVCSTMNT_.CSTMNT;
CSTMNT_.IOLELEM;
CGCMNSUB();
CSTMNT_.SAVCSTMNT;
CGE1LIST(.IOLELEM)
END;
%(**FOR AN E2LISTCALL NODE - OPTIMIZED CODE ONLY***)%
BEGIN
LOCAL BASE SAVCSTMNT;
SAVCSTMNT_.CSTMNT;
CSTMNT_.IOLELEM;
CGCMNSUB();
CSTMNT_.SAVCSTMNT;
CGE2LIST(.IOLELEM)
END
TES;
%(***CREATE A LABEL TABLE ENTRY FOR THE LABEL ASSOCIATED WITH
THE ARGBLOCK FOR THIS NODE***)%
A1LABEL_GENLAB();
IOLELEM[IOLSTLBL]_.A1LABEL;
%(***GENERATE CALL TO IOLST.***)%
OPDSPIX_OPGIOL;
CGOPGEN();
END
ELSE CGERR();
%(***GO ON TO NEXT ELEMENT***)%
IOLELEM_.IOLELEM[CLINK];
END;
CSTMNT_.SAVSTMNT;
END;
GLOBAL ROUTINE CGE1LIST(IOLELEM)=
%(**********************************************************************
ROUTINE TO GENERTE IN LINE CODE FOR
AN E1LISTCALL NODE
**********************************************************************)%
BEGIN
MAP BASE IOLELEM;
LOCAL BASE IOARRAY;
TREEPTR_.IOLELEM[ECNTPTR];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN CGETVAL();
TREEPTR_.IOLELEM[E1INCR];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN CGETVAL();
IOARRAY_.IOLELEM[ELSTPTR];
WHILE .IOARRAY NEQ 0 DO
BEGIN
TREEPTR_.IOARRAY[E2ARREFPTR];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN CGETVAL();
IOARRAY_.IOARRAY[CLINK]
END
END;
GLOBAL ROUTINE CGE2LIST(IOLELEM)=
%(**********************************************************************
ROUTINE TO GENERATE INLINE CODE FOR
AN E2LISTCALL NODE
**********************************************************************)%
BEGIN
MAP BASE IOLELEM;
LOCAL BASE IOARRAY;
TREEPTR_.IOLELEM[ECNTPTR];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN CGETVAL();
IOARRAY_.IOLELEM[ELSTPTR];
WHILE .IOARRAY NEQ 0 DO
BEGIN
TREEPTR_.IOARRAY[E2INCR];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN CGETVAL();
IOARRAY_.IOARRAY[CLINK]
END;
IOARRAY_.IOLELEM[ELSTPTR];
WHILE .IOARRAY NEQ 0 DO
BEGIN
TREEPTR_.IOARRAY[E2ARREFPTR];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN CGETVAL();
IOARRAY_.IOARRAY[CLINK]
END
END;
GLOBAL ROUTINE CGIOCALL(IOLSNODE)=
%(***************************************************************************
ROUTINE TO GENERATE THE CODE FOR AN IOLSTCALL NODE.
GENERATES CODE TO EVALUATE ALL EXPRESSIONS UNDER THE
IOLSTCALL.
***************************************************************************)%
BEGIN
MAP BASE IOLSNODE;
OWN BASE IOLELEM;
OWN SAVSTMNT;
%(***SAVE THE GLOBAL CSTMNT***)%
SAVSTMNT_.CSTMNT;
%(***GENERATE CODE FOR ANY COMMON SUBEXPRS UNDER THIS NODE***)%
CSTMNT_.IOLSNODE;
CGCMNSUB();
%(***WALK THRU THE ELEMS UNDER THIS IOLSTCALL***)%
IOLELEM_.IOLSNODE[IOLSTPTR];
UNTIL .IOLELEM EQL 0
DO
BEGIN
CASE .IOLELEM[OPERSP] OF SET
%(***FOR A DATACALL****)%
BEGIN
TREEPTR_.IOLELEM[DCALLELEM];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN CGETVAL();
END;
%(***FOR AN SLISTCALL (AN SLIST THAT HAS ONLY ONE ARRAYREF, AND
THAT ARRAYREF STARTS AT THE BASE OF THE ARRAY, AND THE
INCREMENT IS A CONSTANT) ***)%
BEGIN
TREEPTR_.IOLELEM[SCALLCT];
IF .TREEPTR[OPRCLS] NEQ DATAOPR
THEN CGETVAL();
END;
%(***AN IOLSTCALL NODE UNDER ANOTHER IOLSTCALL NODE IS ILLEGAL***)%
CGERR();
%(***FOR AN E1LISTCALL - OPTIMIZED CODE ONLY***)%
BEGIN
CGE1LIST(.IOLELEM)
END;
%(***FOR AN E2LISTCALL - OPTIMIZED CODE ONLY***)%
BEGIN
CGE2LIST(.IOLELEM)
END
TES;
IOLELEM_.IOLELEM[CLINK];
END;
%(***RESTORE CSTMNT***)%
CSTMNT_.SAVSTMNT;
END;
MAP PEXPRNODE TREEPTR;
%(*********DEFINE MACRO TO OUTPUT A WD OF 0 IN AN ARG-BLOCK***)%
MACRO ZIPOUT=
BEGIN
EXTERNAL PBOPWD,PSYMPTR,OBUFFA;
PBOPWD_0;
PSYMPTR_PBF2NOSYM;
OBUFFA()
END$;
GLOBAL ROUTINE CGIOLARGS=
%(***************************************************************************
ROUTINE TO GENERATE THE ARG BLOCKS FOR AN IOLIST.
CALLED WITH THE GLOBAL TREEPTR POINTING TO THE IOLIST.
***************************************************************************)%
BEGIN
MAP OBJECTCODE PBOPWD;
MAP PEXPRNODE PSYMPTR;
OWN SAVTREEPTR;
%(***WALK THRU ALL THE ELEMENTS ON THE IOLIST***)%
UNTIL .TREEPTR EQL 0
DO
BEGIN
%(**ONLY GENERATE ARG BLOCKS FOR NODES OF OPRCLS "IOLSCLS" (IGNORE
STATEMENT NODES) ***)%
IF .TREEPTR[OPRCLS] EQL IOLSCLS
THEN
BEGIN
%(***OUTPUT A WORD OF 0 IN FRONT OF THE ARG-LIST
SO THAT THE TRACE ROUTINE WONT PICK UP GARBAGE AS
AN ARG-COUNT***)%
ZIPOUT;
%(***ASSOCIATE CURRENT LOC WITH THE LABEL ON THIS ARGBLOCK***)%
DEFLAB(.TREEPTR[IOLSTLBL]);
%(********GENERATE THE ARG BLOCK************************)%
CASE .TREEPTR[OPERSP] OF SET
%(***FOR DATACALL***)%
CGDCALL();
%(***FOR SLISTCALL***)%
CGSLIST();
%(***FOR IOLSTCALL***)%
BEGIN
%(***SAVE VAL OF TREEPTR***)%
SAVTREEPTR_.TREEPTR;
%(***WALK THRU THE ELEMENTS UNDER THIS NODE, GENERATING
ARG BLOCKS FOR THEM***)%
TREEPTR_.TREEPTR[IOLSTPTR];
UNTIL .TREEPTR EQL 0
DO
BEGIN
CASE .TREEPTR[OPERSP] OF SET
CGDCALL(); !FOR A DATACALL
CGSLIST(); !FOR AN SLIST
CGERR(); !IOLSTCALL IS ILLEGAL UNDER
! ANOTHER IOLSTCALL
CAE1LIST(); !E1LISTCALL NODE
CAE2LIST() !E2LISTCALL NODE
TES;
TREEPTR_.TREEPTR[CLINK];
END;
%(***RESTORE TREEPTR***)%
TREEPTR_.SAVTREEPTR;
END;
%(***FOR AN E1LISTCALL - OPTIMIZED CODE ONLY***)%
CAE1LIST();
%(***FOR AN E2LISTCALL - OPTIMIZED CODE ONLY***)%
CAE2LIST()
TES;
%(***IF THIS IS THE LAST ARG-BLOCK FOR THIS STMNT, GENERATE A FIN-BLOCK
AFTER IT; OTHERWISE GENERATE A ZERO-BLOCK AFTER IT***)%
PBOPWD_(IF .TREEPTR[CLINK] EQL 0 THEN OTSFINWD ELSE OTSZERWD);
PSYMPTR_PBF2NOSYM;
OBUFFA();
END;
%(***GO ON TO NEXT ELEMENT***)%
TREEPTR_.TREEPTR[CLINK];
END;
END;
GLOBAL ROUTINE CGDCALL=
%(***************************************************************************
ROUTINE TO GENERATE AN ARG BLOCK FOR A DATACALL ELEMENT IN AN IOLIST
CALLED WITH THE GLOBAL TREEPTR POINTING TO THE DATACALL NODE FOR
WHICH THE BLOCK IS TO BE GENERATED.
***************************************************************************)%
BEGIN
MAP OBJECTCODE PBOPWD;
MAP PEXPRNODE PSYMPTR;
OWN PEXPRNODE ARGNODE;
EXTERNAL EVALU;
%(***GET PTR TO THE EXPRESSION-NODE WHOSE VAL IS TO BE AN ARG***)%
ARGNODE_.TREEPTR[DCALLELEM];
%(***INIT OUTPUT WD TO 0****)%
PBOPWD_0;
%(***SET ID FIELD OF OUTPUT WD TO INDICATE DATA***)%
PBOPWD[OTSIDN]_OTSDATA;
%(***SET TYPE FIELD OF ARG BLOCK TO THE EXTERNAL-TYPE CODE CORRESPONDING
TO THE VALTYPE INDICATED IN ARGNODE***)%
PBOPWD[OTSTYPE]_.EVALU[.ARGNODE[VALTYPE]];
%(***IF THE EXPRESSION IS A SCALER VARIABLE***)%
IF .ARGNODE[OPRCLS] EQL DATAOPR
THEN
BEGIN
PBOPWD[OTSADDR]_.ARGNODE[IDADDR];
IF .ARGNODE[OPERSP] EQL FORMLARRAY THEN
PBOPWD[OTSIND]_1; !SET INDIRECT OVER FORMAL ARRAY
PSYMPTR_.ARGNODE; !PTR TO SYMBOL TABLE ENTRY
END
ELSE
%(***IF THE EXPRESSION IS AN ARRAYREF****)%
IF .ARGNODE[OPRCLS] EQL ARRAYREF
THEN
BEGIN
PBOPWD[OTSMEMRF]_.ARGNODE[TARGTMEM];
PSYMPTR_.ARGNODE[ARG1PTR];
%(***FOR A FORMAL ARRAY, WILL NOT WANT TO RELOCATE THE ADDRESS
FIELD OF THE ARGUMENT - SINCE WILL HAVE COMPUTED THE ARRAY BASE
ADDRESS INTO THE SUBSCRIPT***)%
IF .PSYMPTR[FORMLFLG] THEN PSYMPTR_PBF2NOSYM;
END
ELSE
%(***IF THE VAL OF THE EXPRESSION IS IN A REG***)%
IF .ARGNODE[INREGFLG]
THEN
BEGIN
PBOPWD[OTSADDR]_.ARGNODE[TARGADDR];
PSYMPTR_PBF2NOSYM;
END
ELSE
%(***IF THE VAL OF THE EXPRESSION IS IN A TEMP***)%
BEGIN
PSYMPTR_.ARGNODE[TARGADDR];
PBOPWD[OTSADDR]_.PSYMPTR[IDADDR];
PBOPWD[OTSIND]_.ARGNODE[TARGIF];
END;
OBUFFA();
END;
GLOBAL ROUTINE CGSLIST=
%(***************************************************************************
ROUTINE TO GENERATE AN ARGUMENT BLOCK FOR AN SLIST CALL
IN AN IOLIST.
CALLED WITH THE GLOBAL POINTING TO THE SLISTCALL NODE.
THIS ROUTINE IS USED ONLY FOR THE SLISTS GENERATED BY
PHASE 1 FOR STMNTS OF THE FORM:
READ 11,A
WHERE A IS AN ARRAY.
IN A LATER RELEASE, PHASE 2 SKELETON WILL RECOGNIZE
IOLISTS THAT CAN BE TRANSFORMED INTO SLISTS AND WILL FORM
"S1LISTCALL" NODES FOR THESE SLISTS (WHICH MAY HAVE MORE THAN ONE ARRAY
AND INCREMENTS OTHER THAN 1).
***************************************************************************)%
BEGIN
MAP OBJECTCODE PBOPWD;
MAP PEXPRNODE PSYMPTR;
EXTERNAL EVALU;
%(******OUTPUT FIRST WD OF ARGBLOCK (WD CONTAINING CODE FOR SLSIST AND COUNT)*****)%
%(***INIT OUTPUT WD TO 0***)%
PBOPWD_0;
%(***SET IDN FIELD TO CODE FOR SLSIST**)%
PBOPWD[OTSIDN]_OTSSLIST;
%(***BUILD THE WD THAT CONTAINS THE CT***)%
BLDIOIMWD(.TREEPTR[SCALLCT]);
OBUFFA();
%(****OUTPUT THE 2ND WD OF ARGBLOCK (WHICH CONTAINS THE INCREMENT 1)***)%
PBOPWD_1;
PSYMPTR_PBF2NOSYM;
OBUFFA();
%(***OUTPUT THE 3RD WD (WHICH CONTAINS A PTR TO THE ARRAY TO BE USED)*******)%
%(***GET PTR TO SYMBOL TABLE ENTRY FOR THE ARRAY***)%
PSYMPTR_.TREEPTR[SCALLELEM];
%(***ADDRESS FOR ARGBLOCK IS ADDRESS INDICATED BY THE SYMBOL TABLE ENTRY***)%
PBOPWD[OTSADDR]_.PSYMPTR[IDADDR];
PBOPWD[OTSTYPE]_.EVALU[.PSYMPTR[VALTYPE]];
%(***SET INDIRECT BIT FOR A FORMAL ARRAY***)%
IF .PSYMPTR[FORMLFLG]
THEN
PBOPWD[OTSIND]_1;
OBUFFA();
END;
GLOBAL ROUTINE CAE1LIST=
%(**********************************************************************
ROUTINE TO GENERATE CODE FOR AN ARGBLK FOR AN E1LISTCALL NODE
CALLED WITH GLOBAL POINTING TO E1LISTCALL NODE
**********************************************************************)%
BEGIN
LOCAL PEXPRNODE IOARRAY;
MAP OBJECTCODE PBOPWD;
MAP PEXPRNODE PSYMPTR;
%(***OUTPUT FIRST WORD - CONTAINS "SLIST" AND COUNT***)%
PBOPWD_0; !INITIALIZE WORD TO 0
PBOPWD[OTSIDN]_OTSSLIST; !SET ID FIELD TO SLIST
BLDIOIMWD(.TREEPTR[ECNTPTR]); !FILL IN THE COUNT
OBUFFA(); !OUTPUT THE WORD
%(***OUTPUT SECOND WORD - CONTAINS INCREMENT***)%
IOARRAY_.TREEPTR[E1INCR];
IF
BEGIN
IF .IOARRAY[OPR1] NEQ CONSTFL THEN 0 ELSE
IF .IOARRAY[CONST1] EQL 0 AND .IOARRAY[CONST2] EQL 0
THEN 1 ELSE 0
END
THEN
BEGIN
PSYMPTR_.IOARRAY; !MARK SYMBOL
PBOPWD<LEFT>_#100; !SET INTEGER
PBOPWD<RIGHT>_.IOARRAY[IDADDR]
END
ELSE
BEGIN
PBOPWD_0;
BLDIOIMWD(.TREEPTR[E1INCR]) !FILL IN THE INCREMENT
END;
OBUFFA(); !OUTPUT THE WORD
%(***OUTPUT ONE WORD FOR EACH ARRAYREF UNDER ELSTPTR***)%
IOARRAY_.TREEPTR[ELSTPTR];
WHILE .IOARRAY NEQ 0 DO
BEGIN
PBOPWD_0; !CLEAR TARGET
IOPTR(.IOARRAY[E2ARREFPTR]); !GENERATE ARGUMENT
IOARRAY_.IOARRAY[CLINK]
END
END;
GLOBAL ROUTINE CAE2LIST=
%(**********************************************************************
ROUTINE TO GENERATE CODE FOR AN ARGBLK FOR AN E2LISTCALL NODE
CALLED WITH GLOBAL POINTING TO E2LISTCALL NODE
**********************************************************************)%
BEGIN
LOCAL PEXPRNODE IOARRAY;
MAP OBJECTCODE PBOPWD;
MAP PEXPRNODE PSYMPTR;
%(***OUTPUT FIRST WORD - CONTAINS "ELIST" AND COUNT***)%
PBOPWD_0; !INITIALIZE WORD TO 0
PBOPWD[OTSIDN]_OTSELIST; !SET ID FIELD TO ELIST
BLDIOIMWD(.TREEPTR[ECNTPTR]); !FILL IN THE COUNT
OBUFFA(); !OUTPUT THE WORD
%(***OUTPUT TWO WORD FOR EACH ARRAYREF UNDER ELSTPTR***)%
IOARRAY_.TREEPTR[ELSTPTR];
WHILE .IOARRAY NEQ 0 DO
BEGIN
LOCAL PEXPRNODE E2ARG;
%(***OUTPUT INCREMENT***)%
E2ARG_.IOARRAY[E2INCR];
IF
BEGIN
IF .E2ARG[OPR1] NEQ CONSTFL THEN 0 ELSE
IF .E2ARG[CONST1] EQL 0 AND .E2ARG[CONST2] EQL 0
THEN 1 ELSE 0
END
THEN
BEGIN
PSYMPTR_.E2ARG;
PBOPWD<LEFT>_#100;
PBOPWD<RIGHT>_.E2ARG[IDADDR]
END
ELSE
BEGIN
PBOPWD_0;
BLDIOIMWD(.IOARRAY[E2INCR]) !FILL IN INCREMENT
END;
OBUFFA(); !OUTPUT INCREMENT
%(***OUTPUT ARRAY ADDRESS***)%
PBOPWD_0; !CLEAR TARGET
IOPTR(.IOARRAY[E2ARREFPTR]); !GENERATE ARGUMENT
IOARRAY_.IOARRAY[CLINK]
END
END;
GLOBAL ROUTINE BLDIOIMWD(ARGNODE)=
%(***************************************************************************
ROUTINE TO BUILD A WD OF AN ARGUMENT BLOCK FOR FOROTS WHEN
THAT WORD IS TO HAVE EITHER THE FORM:
1. INDIRECT BIT=0, IMMEDIATE CONSTANT IN RIGHT HALF
OR 2. INDIRECT BIT=1, PTR TO VAL IN RIGHT HALF
CALLED WITH THE ARG:
ARGNODE - PTR TO THE EXPRESSION NODE FOR THE VAL TO
BE REPRESENTED
CALLED WITH PBOPWD INITIALIZED SUCH THAT THE FIRST 9 BITS HAVE
THE VALUE DESIRED,AND THE RIGHT 27 BITS ARE 0.
***************************************************************************)%
BEGIN
EXTERNAL EVALU;
MAP OBJECTCODE PBOPWD;
MAP PEXPRNODE PSYMPTR;
MAP PEXPRNODE ARGNODE;
%(***SET TYPE TO INDICATE IMMEDIATE ARG IN MEMORY***)%
PBOPWD[OTSTYPE]_.EVALU[.ARGNODE[VALTYPE]];
%(***IF THE ARG IS A CONSTANT, USE THE IMMEDIATE FORM***)%
IF .ARGNODE[OPR1] EQL CONSTFL
THEN
BEGIN
PBOPWD[OTSTYPE]_IMMEDTYPE;
PBOPWD[OTSADDR]_.ARGNODE[CONST2];
PSYMPTR_PBF2NOSYM; !FLAG TO OUTMOD THAT NO SYMBOLIC
! REPRESENTATION CAN BE USED
END
ELSE
%(***IF ARG IS A VARIABLE, USE INDIRECT THRU ITS ADDR***)%
IF .ARGNODE[OPRCLS] EQL DATAOPR
THEN
BEGIN
IF .ARGNODE[OPERSP] EQL FORMLARRAY THEN PBOPWD[OTSIND]_1;
PBOPWD[OTSADDR]_.ARGNODE[IDADDR];
PSYMPTR_.ARGNODE; !PTR TO SYMBOL TABLE ENTRY
END
ELSE
%(***IF ARG IS AN EXPRESSION, USE THE TEMP IN WHICH THE VAL WAS STORED***)%
BEGIN
%(***IF VAL WAS LEFT IN AREG***)%
IF .ARGNODE[INREGFLG]
THEN
BEGIN
PBOPWD[OTSADDR]_.ARGNODE[TARGADDR];
PSYMPTR_PBF2NOSYM;
END
ELSE
%(***IF VAL WAS LEFT IN A TEMP***)%
BEGIN
%(***GET PTR TO TEMPORARY TABLE ENTRY***)%
PSYMPTR_.ARGNODE[TARGADDR];
PBOPWD[OTSADDR]_.PSYMPTR[IDADDR];
END;
END;
END;
GLOBAL ROUTINE CGSTPAUARGS=
%(***************************************************************************
ROUTINE TO GENERATE THE ARG BLOCK FOR A STOP/PAUSE STMNT.
THIS BLOCK WILL HAVE THE FORM:
-------------------------------
! ARGCT ! 0 !
---------------------------------
LABEL: ! !TYPE ! ! ARGPTR !
----------------------------------
WHERE "LABEL" IS THE ARG-BLOCK LABEL, ARGCT IS NEG ARGCT AND WILL ALWAYS
BE -1 OR 0, TYPE IS THE VALUE TYPE OF THE ARG (LITERAL,OCTAL,INTEGER,REAL
DOUBLE PREC, OR COMPLEX) AND IS IN BITS 9-12, AND ARGPTR PTS TO THE ARG
THIS ROUTINE IS CALLED WITH THE GLOBAL "CSTMNT" POINTING TO THE STOP OR
PAUSE STMNT FOR WHICH AN ARG-BLOCK IS TO BE GENERATED.
***************************************************************************)%
BEGIN
EXTERNAL EVALU; !TABLE OF EXTERNAL VALUE-TYPE CODES
MAP OBJECTCODE PBOPWD; !GLOBAL IN WHICH THE WD TO
! BE OUTPUT IS PASSED TO THE ROUTINE "OBUFFA"
MAP PEXPRNODE PSYMPTR; !WILL PT TO THE SYMBOL TABLE ENTRY (OR
! CONSTANT TABLE ENTRY) FOR THE ARG OF THE STOP/PAUSE
%(***IF THE STOP/PAUSE HAD NO ARG, WILL HAVE USED "ZERBLK" FOR THE
ARG-BLOCK. SO DONT HAVE TO GENERATE ANYTHING.***)%
IF .CSTMNT[PAUSIDENT] EQL 0
THEN RETURN;
%(***IF THIS STMNT WAS ELIMINATED (BY FOLDING A LOG IF), DO NOT WANT TO
GENERATE AN ARG LIST***)%
IF .CSTMNT[PAUSLBL] EQL 0 THEN RETURN;
%(***OUTPUT THE ARG-CT WD*****)%
PSYMPTR_PBF2NOSYM;
PBOPWD_(-1)^18;
OBUFFA();
%(***ASSOCIATE THE LABEL FOR THIS ARG-LIST WITH THE 2ND WD***)%
DEFLAB(.CSTMNT[PAUSLBL]);
%(***OUTPUT THE PTR WD***)%
PSYMPTR_.CSTMNT[PAUSIDENT];
PBOPWD_0; !INIT WD TO BE OUTPUT TO 0
PBOPWD[OTSTYPE]_.EVALU[.PSYMPTR[VALTYPE]]; !SET TYPE FIELD OF WD TO BE OUTPUT
PBOPWD[OTSADDR]_.PSYMPTR[IDADDR]; !ADDRESS OF VAR/CONSTANT/LITERAL
! TO BE OUTPUT
OBUFFA();
RETURN
END;
!AUTHOR: NORMA ABEL
!THIS FILE CONTAINS THE ROUTINES NECESSARY TO GENERATE CODE
!FOR THE I/O STATEMENTS THEMSELVES. WHERE APPROPRIATE THE ROUTINE
!CGIOLST IS CALLED TO GENERATE THE CALLS TO IOLST.
GLOBAL ROUTINE CGMTOP=
BEGIN
!CALLS TO MTOP FOR ALL STATEMENTS BACKID THRU ENDFID
EXTERNAL CSTMNT,GENLAB,A1LABEL,CGOPGEN,OPDSPIX;
MAP BASE CSTMNT;
EXTERNAL OPGMTO;
CGUNIT(); !GENERATE CODE TO EVAL THE UNIT NUMBER (IF AN EXPRESSION)
!FILL IN IOARGLBL FIELD
A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
OPDSPIX_OPGMTO;
CGOPGEN();
END;
GLOBAL ROUTINE CGENCO=
BEGIN
!CODE GENERATION FOR ENCODE
EXTERNAL CSTMNT,GENLAB,A1LABEL,CGOPGEN,OPDSPIX;
MAP BASE CSTMNT;
EXTERNAL CGIOLST,OPGENC;
EXTERNAL TREEPTR,CGETVAL;
%(***IF THE COUNT FIELD IS AN EXPRESSION, EVALUATE IT***)%
TREEPTR_.CSTMNT[IOCNT];
CGETVAL();
%(***IF THE ENCODE VAR IS AN ARRAY-REF, GENERATE CODE FOR THE
SS CALCULATION***)%
TREEPTR_.CSTMNT[IOVAR];
CGETVAL();
!FILL IN IOARGLBL FIELD
A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
OPDSPIX_OPGENC;
CGOPGEN();
CGIOLST();
END;
GLOBAL ROUTINE CGDECO=
BEGIN
!CODE GENERATION FOR DECODE
EXTERNAL CSTMNT,GENLAB,A1LABEL,CGOPGEN,OPDSPIX;
MAP BASE CSTMNT;
EXTERNAL OPGDEC,CGIOLST;
%(***IF THE COUNT FIELD IS AN EXPRESSION, EVALUATE IT***)%
TREEPTR_.CSTMNT[IOCNT];
CGETVAL();
%(***IF THE DECODE ARRAY IS AN ARRAYREF - CALCULATE THE
OFFSET***)%
TREEPTR_.CSTMNT[IOVAR];
CGETVAL();
!FILL IN IOARGLBL FIELD
A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
OPDSPIX_OPGDEC;
CGOPGEN();
CGIOLST();
END;
GLOBAL ROUTINE CGRERE=
BEGIN
!CODE GENERATION FOR REREAD
EXTERNAL CSTMNT,GENLAB,A1LABEL,CGOPGEN,OPDSPIX;
EXTERNAL OPGFIN;
MAP BASE CSTMNT;
EXTERNAL CGIOLST,OPGIN;
CGUNIT(); !GENERATE CODE TO EVAL THE UNIT NUMBER (IF AN EXPRESSION)
!FILL IN IOARGLBL FIELD
A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
OPDSPIX_OPGIN;
CGOPGEN();
IF .CSTMNT[IOLIST]EQL 0
THEN
BEGIN
%(***IF HAVE NO IOLIST GENERATE A CALL TO FIN***)%
OPDSPIX_OPGFIN;
CGOPGEN();
END
ELSE
CGIOLST();
END;
GLOBAL ROUTINE CGUNIT=
%(***************************************************************************
GENERATE CODE TO EVALUATE THE UNIT NUMBER IN AN IO STMNT
CALLED WITH CSTMNT POINTING TO AN IO STMNT
***************************************************************************)%
BEGIN
TREEPTR_.CSTMNT[IOUNIT]; !PTR TO EXPRESSION NODE FOR UNIT
IF .TREEPTR[OPRCLS] NEQ DATAOPR THEN CGETVAL()
END;
GLOBAL ROUTINE CGRECNUM=
%(***************************************************************************
TO GENERATE THE CODE TO COMPUTE THE RECORD NUMBER FOR AN IO STMNT
THAT HAS AN EXPRESSION FOR A RECORD NUMBER (UGH!!!)
***************************************************************************)%
BEGIN
EXTERNAL CSTMNT;
MAP PEXPRNODE CSTMNT;
OWN PEXPRNODE RECNUM;
IF (RECNUM_.CSTMNT[IORECORD]) NEQ 0
THEN
BEGIN
IF .RECNUM[OPRCLS] NEQ DATAOPR
THEN
BEGIN
TREEPTR_.RECNUM;
CGETVAL()
END
END
END;
GLOBAL ROUTINE CGREAD=
BEGIN
!CODE GENERATION FOR ALL TYPES OF READ
EXTERNAL CSTMNT,GENLAB,A1LABEL,CGOPGEN,OPDSPIX;
MAP BASE CSTMNT;
EXTERNAL CGIOLST,OPGNLI,OPGIN,OPGRTB,OPGFIN;
LOCAL BASE T1;
CGUNIT(); !GENERATE CODE TO EVAL THE UNIT NUMBER (IF AN EXPRESSION)
%(***IF THERE AN EXPRESSION TO BE EVALUATED FOR THE RECORD NUMBER (UGH!!!)
GENERATE CODE TO EVALUATE IT***)%
CGRECNUM();
!FILL IN IOARGLBL FIELD
A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
!**[564] CGREAD @4846 SJW 29-APR-77
![564] MAKE CGREAD AND CGWRIT SYMMETRICAL: DON'T MAKE A NAMELIST
![564] CHECK WITHOUT CHECKING FOR IONAME PTR = 0
%[564]% T1 _ .CSTMNT [IOFORM]; ! IOFORM == IONAME
%[564]% IF .CSTMNT [IOLIST] EQL 0 ! NO IOLIST (BEWARE NAMELIST)
%[564]% THEN
%[564]% IF .T1 EQL 0 ! NO FORMAT
%[564]% THEN BEGIN
%[564]% OPDSPIX _ OPGRTB; ! UNFORMATTED READ
%[564]% CGOPGEN ();
%[564]% OPDSPIX _ OPGFIN; ! FIN CALL SINCE NO IOLIST
%[564]% CGOPGEN ();
%[564]% END
%[564]% ELSE
%[564]% IF .T1 [OPRCLS] NEQ STATEMENT AND ! CHECK FOR NAMELIST
%[564]% .T1 [IDATTRIBUT (NAMNAM)]
%[564]% THEN BEGIN
%[564]% OPDSPIX _ OPGNLI; ! NAMELIST READ
%[564]% CGOPGEN ();
%[564]% END
%[564]% ELSE BEGIN
%[564]% OPDSPIX _ OPGIN; ! FORMATTED READ
%[564]% CGOPGEN ();
%[564]% OPDSPIX _ OPGFIN; ! FIN CALL SINCE NO IOLIST
%[564]% CGOPGEN ();
%[564]% END
%[564]% ELSE BEGIN ! THERE IS AN IOLIST
%[564]% IF .T1 EQL 0 ! CHECK FOR FORMAT
%[564]% THEN OPDSPIX _ OPGRTB ! UNFORMATTED READ
%[564]% ELSE OPDSPIX _ OPGIN; ! FORMATTED READ
%[564]% CGOPGEN ();
%[564]% CGIOLST (); ! PROCESS IOLIST
%[564]% END;
END;
GLOBAL ROUTINE CGWRIT=
BEGIN
!CODE GENERATION FOR WRITE STATEMENTS OF ALL FORMS
EXTERNAL CGOPGEN,OPDSPIX,A1LABEL,OPGOUT,OPGNLO,OPGWTB,GENLAB,
CGIOLST,CSTMNT,OPGFIN;
MAP BASE CSTMNT;
LOCAL BASE T1;
CGUNIT(); !GENERATE CODE TO EVAL THE UNIT NUMBER (IF AN EXPRESSION)
%(***IF THERE AN EXPRESSION TO BE EVALUATED FOR THE RECORD NUMBER (UGH!!!)
GENERATE CODE TO EVALUATE IT***)%
CGRECNUM();
!**;[376], CGWRIT @4892, DCE, 28-APR-76
!**;[376], REORDER THINGS SO THAT THE CALL TO CGREGNUM DOES
!**;[376], NOT OVERWRITE A1LABEL CAUSING BAD CODE
!FILL IN IOARGLBL FIELD[376]
A1LABEL_CSTMNT[IOARGLBL]_GENLAB(); ![376]
!**[564] CGWRIT @4907 SJW 29-APR-77
![564] MAKE CGREAD AND CGWRIT SYMMETRICAL: GENERATE A FIN CALL
![564] AFTER AN UNFORMATTED WRITE; REPLACE EDIT [367]
%[564]% T1 _ .CSTMNT [IOFORM]; ! IOFORM == IONAME
%[564]% IF .CSTMNT [IOLIST] EQL 0 ! NO IOLIST (BEWARE NAMELIST)
%[564]% THEN
%[564]% IF .T1 EQL 0 ! NO FORMAT
%[564]% THEN BEGIN
%[564]% OPDSPIX _ OPGWTB; ! UNFORMATTED WRITE
%[564]% CGOPGEN ();
%[564]% OPDSPIX _ OPGFIN; ! FIN CALL SINCE NO IOLIST
%[564]% CGOPGEN ();
%[564]% END
%[564]% ELSE
%[564]% IF .T1 [OPRCLS] NEQ STATEMENT AND ! CHECK FOR NAMELIST
%[564]% .T1 [IDATTRIBUT (NAMNAM)]
%[564]% THEN BEGIN
%[564]% OPDSPIX _ OPGNLO; ! NAMELIST WRITE
%[564]% CGOPGEN ();
%[564]% END
%[564]% ELSE BEGIN
%[564]% OPDSPIX _ OPGOUT; ! FORMATTED WRITE
%[564]% CGOPGEN ();
%[564]% OPDSPIX _ OPGFIN; ! FIN CALL SINCE NO IOLIST
%[564]% CGOPGEN ();
%[564]% END
%[564]% ELSE BEGIN ! THERE IS AN IOLIST
%[564]% IF .T1 EQL 0 ! CHECK FOR FORMAT
%[564]% THEN OPDSPIX _ OPGWTB ! UNFORMATTED WRITE
%[564]% ELSE OPDSPIX _ OPGOUT; ! FORMATTED WRITE
%[564]% CGOPGEN ();
%[564]% CGIOLST (); ! PROCESS IOLIST
%[564]% END;
END;
GLOBAL ROUTINE CGOPLST=
%(***************************************************************************
ROUTINE TO GENERATE CODE TO EVALUATE ANY EXPRESSIONS THAT
OCCUR AS VALS OF ARGS UNDER AN OPEN/CLOSE STMNT
***************************************************************************)%
BEGIN
OWN OPENLIST ARVALLST; !LIST OF ARGS AND THEIR VALS UNDER THIS STMNT
CGUNIT(); !GENERATE CODE FOR UNIT NUMBER THAT IS AN EXPRESSION
ARVALLST_.CSTMNT[OPLST];
INCR I FROM 0 TO (.CSTMNT[OPSIZ]-1) !LOOK AT EACH ARG
DO
BEGIN
TREEPTR_.ARVALLST[.I,OPENLPTR]; !PTR TO THE EXPRESSION NODE FOR THE VAL OF THIS ARG
IF .TREEPTR EQL 0 !FOR "DIALOG", CAN HAVE NULL VAL
THEN BEGIN END
ELSE
IF .TREEPTR[OPRCLS] NEQ DATAOPR THEN CGETVAL()
END
END; !END OF ROUTINE "CGOPLST"
GLOBAL ROUTINE CGOPEN=
BEGIN
!CODE GENERATION FOR THE CALL TO OPEN.
EXTERNAL CGOPGEN,OPDSPIX,A1LABEL,GENLAB,OPGOPE;
EXTERNAL CSTMNT; MAP BASE CSTMNT;
CGOPLST(); !GENERATE CODE TO EVAL ANY EXPRESSIONS THAT OCCUR AS VALS OF ARGS
!FILL IN IOARGLBL FIELD
A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
OPDSPIX_OPGOPE;
CGOPGEN();
END;
!GLOBAL ROUTINE CGRELS=
!BEGIN
! !CODE GENERATION FOR RELAEASE STATEMENT
!
! EXTERNAL CSTMNT,CGOPGEN,OPDSPIX,A1LABEL,OPGREL,GENLAB;
! MAP BASE CSTMNT;
! !FILL IN IOARGLBL FIELD
!
! A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
! OPDSPIX_OPGREL;
! CGOPGEN();
!END;
!
GLOBAL ROUTINE CGFIND=
BEGIN
!CODE GENERATION FOR FIND
EXTERNAL CGOPGEN,CSTMNT,A1LABEL,GENLAB,OPDSPIX,OPGFND;
MAP BASE CSTMNT;
CGUNIT(); !GENERATE CODE FOR UNIT NUMBER
!FILL IN IOARGLBL FIELD
A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
%(***IF THERE AN EXPRESSION TO BE EVALUATED FOR THE RECORD NUMBER (UGH!!!)
GENERATE CODE TO EVALUATE IT***)%
CGRECNUM();
OPDSPIX_OPGFND;
CGOPGEN();
END;
GLOBAL ROUTINE CGCLOS=
BEGIN
!CODE GENERATION FOR CLOSE STATEMENT
EXTERNAL CSTMNT,GENLAB,A1LABEL,OPDSPIX,CGOPGEN,OPGCLO;
MAP BASE CSTMNT;
CGOPLST(); !GENERATE CODE TO EVAL ANY EXPRESSIONS THAT OCCUR AS VALS OF ARGS
!FILL IN IOARGLBL FIELD
A1LABEL_CSTMNT[IOARGLBL]_GENLAB();
OPDSPIX_OPGCLO;
CGOPGEN();
END;
MACRO
IOWHOLE=0,7,0,36$,
OPENFFIELD=0,33,3$,
OPENGFIELD=0,27,5$,
OPENCODE=0,0,18,18$,
OPENARG=0,0,0,18$,
UTILLOW=BACKID$,
UTILHI=ENDFID$;
GLOBAL ROUTINE CGDECARGS=
%(***************************************************************************
TO GENERATE THE ARG BLOCK FOR AN ENCODE OR DECODE STATEMENT
ARG BLOCK HAS THE FORM:
--------------------------------------------------
! -6 ! !
--------------------------------------------------
! !TYPE !I! X ! CHAR CT (IMMED) !
--------------------------------------------------
! !TYPE !I! X ! END= !
--------------------------------------------------
! !TYPE !I! X ! ERR= !
--------------------------------------------------
! !TYPE !I! X ! FORMAT ADDR !
--------------------------------------------------
! !TYPE !I! X ! FORMAT SIZE(IMMED) !
--------------------------------------------------
! !TYPE !I! X ! VAR ARRAY ADDR !
--------------------------------------------------
WHERE THE ARGLIST PTR POINTS TO THE WORD CONTAINING THE CHAR CT (IE
THE -6 IS IN THE WD PRECEEDING THE ARG PTR)
***************************************************************************)%
BEGIN
EXTERNAL IOIMMED,IOPTR;
EXTERNAL PBOPWD,CSTMNT,PSYMPTR,OBUFF;
EXTERNAL IOENDERR,IOFORMAT,EVALU;
MAP PEXPRNODE CSTMNT; !ENCODE OR DECODE STMNT FOR WHICH ARG BLOCK
! IS TO BE GENERATED
MAP OBJECTCODE PBOPWD;
OWN PEXPRNODE ENCARRAY; !ARRAY TO BE INPUT OR OUTPUT
OWN PEXPRNODE CHARCT; !NUMBER OF CHARS TO BE PROCESSED
ENCARRAY_.CSTMNT[IOVAR];
CHARCT_.CSTMNT[IOCNT];
%(***OUTPUT WD CONTAINING THE CT OF WDS IN THE ARGLIST***)%
PBOPWD_(-6)^18; !CT IN LEFT HALF WD
PSYMPTR_PBF2NOSYM;
OBUFFA();
%(***ASSOCIATE THE LABEL ON THE ARGLIST WITH THIS LOC***)%
DEFLAB(.CSTMNT[IOARGLBL]);
%(***SET UP THE COUNT OF CHARS TO BE PROCESSED IN THE 1ST WD OF THE ARG BLOCK***)%
IOIMMED(.CHARCT);
IOENDERR(); !OUTPUT THE END/ERROR WORDS OF THE ARG BLOCK
IOFORMAT(); !OUTPUT THE FORMAT WDS OF THE ARG BLOCK
%(***OUTPUT A PTR TO THE ARRAY***)%
IOPTR(.ENCARRAY);
END;
ROUTINE IO1ARG(NUMB)=
%(*********************
ROUTINE TO OUTPUT 2 WDS OF THE FORM:
--------------------------------------------------
! -CT ! !
-------------------------------------------------
LAB: ! ! TYPE !I! X ! UNIT !
---------------------------------------------------
WHERE "UNIT" IS IMMEDIATE
***********************)%
BEGIN
EXTERNAL IOIMMED;
EXTERNAL PBOPWD,PSYMPTR,OBUFF,CSTMNT;
MAP BASE CSTMNT;
MAP OBJECTCODE PBOPWD;
%(***OUTPUT MINUS THE CT OF WDS IN THE ARG BLOCK***)%
PBOPWD_(-.NUMB)^18; !CT IN LEFT HALF WD
PSYMPTR_PBF2NOSYM;
OBUFFA();
%(***ASSOCIATE THE LABEL ON THE ARG BLOCK WITH THIS LOC***)%
DEFLAB(.CSTMNT[IOARGLBL]);
IOIMMED(.CSTMNT[IOUNIT]); !GENERATE AN "IMMEDIATE" MODE
! ARG FOR THE UNIT NUMBER
PBOPWD_0;
END;
GLOBAL ROUTINE IOENDERR=
%(***********************
OUTPUT THE END= AND ERR-= WORDS OF AN IO ARG BLOCK.
THESE 2 WDS HAVE THE FORM:
---------------------------------------------------------
! ! TYPE !I! X ! IOEND !
---------------------------------------------------------
! ! TYPE !I! X ! IOERR !
---------------------------------------------------------
**************************)%
BEGIN
EXTERNAL PBOPWD,OBUFFA,PSYMPTR,CSTMNT;
MAP BASE CSTMNT;
MAP OBJECTCODE PBOPWD;
%(***OUTPUT THE "END" WD***)%
PBOPWD_0;
IF .CSTMNT[IOEND] EQL 0
THEN PSYMPTR_PBF2NOSYM
ELSE
BEGIN
PBOPWD[OTSTYPE]_ADDRTYPE; !TYPE IS "ADDRESS"
PBOPWD[OTSADDR]_.CSTMNT[IOEND];
PSYMPTR_PBFLABREF;
END;
OBUFFA();
%(***OUTPUT THE "ERROR" WD***)%
PBOPWD_0;
IF .CSTMNT[IOERR] EQL 0
THEN PSYMPTR_PBF2NOSYM
ELSE
BEGIN
PBOPWD[OTSTYPE]_ADDRTYPE; !TYPE IS "ADDRESS"
PBOPWD[OTSADDR]_.CSTMNT[IOERR];
PSYMPTR_PBFLABREF;
END;
OBUFFA();
PBOPWD_0;
END;
GLOBAL ROUTINE IOFORMAT=
%(********************
ROUTINE TO OUTPUT THE 2 FORMAT WDS OF AN IO ARG-BLOCK
THESE WDS HAVE THE FORM:
----------------------------------------------------------
! ! TYPE !I! X ! FORMAT ADDR !
----------------------------------------------------------
! ! TYPE !I! X! ! FORMAT SIZE !
----------------------------------------------------------
************************)%
BEGIN
EXTERNAL CSTMNT,PBOPWD,OBUFFA,PSYMPTR;
EXTERNAL ISN,FATLERR,E91;
EXTERNAL EVALU;
MAP BASE CSTMNT;
MAP OBJECTCODE PBOPWD;
MAP PEXPRNODE PSYMPTR;
OWN BASE T:FORMATP;
FORMATP_.CSTMNT[IOFORM];
!IOSTATEMENT CONTAINS POINTER TO LABEL TABLES
!OR VARIABLE
PBOPWD_0;
IF .FORMATP[OPRCLS] EQL LABOP
THEN
%(***IF FORMAT IS A STMNT- HAVE A PTR TO THE LABEL TABLE ENTRY FOR ITS LABEL***)%
BEGIN
FORMATP_.FORMATP[SNHDR];
%(***IF THE STMNT REFERENCED IS NOT A FORMAT STMNT, GIVE AN ERROR MESSAGE.***)%
IF .FORMATP[SRCID] NEQ FORMID
THEN
BEGIN
FATLERR(.FORMATP[SRCISN],E91<0,0>);
%(***PUT OUT 2 WDS OF 0 FOR THE FORMAT WDS***)%
ZIPOUT;
ZIPOUT;
RETURN;
END;
%(***OUTPUT THE FORMAT ADDRESS WD***)%
PBOPWD[OTSADDR]_.FORMATP;
PBOPWD[OTSTYPE]_ADDRTYPE; !TYPE FIELD EQL TO "ADDRESS"
! INDICATES THAT FORMAT IS NOT
! AN ARRAY
PSYMPTR_PBFFORMAT;
OBUFFA();
%(***OUTPUT THE FORMAT SIZE WD***)%
PBOPWD_.FORMATP[FORSIZ];
PBOPWD[OTSTYPE]_IMMEDTYPE; !SIZE IS REFERENCED IMMED
PSYMPTR_PBF2NOSYM;
OBUFFA();
END
ELSE
%(***IF FORMAT IS AN ARRAY, HAVE A PTR TO THE SYMBOL TABLE ENTR