Trailing-Edge
-
PDP-10 Archives
-
decuslib10-04
-
43,50325/declar.bli
There are no other files named declar.bli in the archive.
! File: DECLAR.BLI
!
! This work was supported by the Advanced Research
! Projects Agency of the Office of the Secretary of
! Defense (F44620-73-C-0074) and is monitored by the
! Air Force Office of Scientific Research.
MODULE DECLAR(TIMER=EXTERNAL(SIX12))=
BEGIN
! DECLAR MODULE
! -------------
!
! D. WILE
! MODIFIED BY:
! R. JOHNSSON
! P. KNUEVEN
!
!
! THIS MODULE PROCESSES DECLARATIONS.
!
!
REQUIRE COMMON.BEG;
REQUIRE GTST.BEG;
REQUIRE ST.BEG;
REQUIRE GTX.BEG;
REQUIRE LDSFT.BEG;
REQUIRE LDSF.BEG;
REQUIRE ERROR.BEG;
REQUIRE STRUCT.BEG;
REQUIRE TN.BEG;
REQUIRE IO.BEG;
BEGIN
!NEXT FIELD DEFINITIONS FOR THE FIELDS OF THE 2 WORD
!LIST WE MAKE UP FOR SIZE PROCESSING IN THE DECLARATIONS.
MACRO
STELNEXTF=0,0,18$,
STELSTEF=0,18,18$,
STELCPF=1,0,36$;
!-------------------------------------------------------
! THE FOLLOWING ARE MISC. EXTERNALS FOR DECLAR ONLY
EXTERNAL
CSCNAME,
CSDNAME,
CSGNAME,
CSONAME,
CSPNAME,
DECLSIZE, ! 1 DURING "BYTE" DECLARATION, OTHERWISE 2
IDENTFLG,
IDENTLEX,
INAPLIT, ! SIGNAL FROM PLIT PARSER TO DETBRACKET (VIA HRUND)
% THE FOLLOWING FOUR VARIABLES ARE SET BY GROMLIST %
OEQL, ! POINTS TO ROUTINE TO PROCESS "="
OFUN, ! POINTS TO ROUTINE TO DO RANDOM BITS OF
! PROCESSING ON EACH VARIABLE (E.G. PLABEL, PLOCAL)
OPAR, ! NOT USED AS FAR AS I KNOW.
OTYPE, ! VARIABLE TYPE BEING DECLARED
PLHEAD, ! CHARACTER STRING - NAME OF CURRENT PLIT
PLLBRAC, ! LOCATION OF LAST PLIT LEFT PAREN
STELAST, ! LAST ENTRY IN LIST OF SYMBOLS BEING DECLARED
STELIST, ! LIST OF SYMBOLS BEING DECLARED
UNAMNO;
EXTERNAL
GETTN, ! FROM LOW SEGMENT
STRMAPPEND, ! FROM LEXAN
STRMQUIT,
STRUSC,
BINDBIND, ! FROM SYNTAX
PDETACH,
DYNBIND,
EXPRESSION,
GETNCSE,
RNAMEFOLLOWS,
SENABLE,
STRUPICKOFF;
! MACROS AND BINDS FOR SWITCHES:
!
BIND SWSWL=19; !HIGHEST SWITCH INDEX VALID IN SWITCHES DECL.
MACRO ALLSW=.SWTBL[-1]$; ! " " " " " MODULE HEAD
! THESE MACROS HELP IN SPECIFYING THE VALID SWITCHES.
MACRO
BS(NUM,STR)=('STR' OR ((-1)^(-7*NUM))) AND (-2)$,
BL(STR)='STR' AND (-2)$;
! THE FOLLOWING IS A LIST OF SWITCHES FOR THE BLISS COMPILER.
! IT IS A PLIT WHICH IS SEARCHED AS A VECTOR.
!
! THIS DECLARATION IS SET UP AS FOLLOWS:
!
! FOR EACH ALLOWABLE SWITCH NAME, ONE OF THE ABOVE
! MACROS IS INVOKED WITH THE FIRST FIVE (5) CHARACTERS
! OF THAT SWITCH NAME AS ITS ARGUMENT. THE REMAINING
! CHARACTERS OF THE SWITCH NAME, IF ANY, FOLLOW AS A COMMENT.
BIND SWTBL=PLIT (
BL(EXPAN) %D%,
BL(NOEXP) %AND%,
BS(4,LIST),
BL(NOLIS) %T%,
BS(4,ERRS),
BL(NOERR) %S%,
BL(MLIST),
BL(NOMLI) %ST%,
BL(OPTIM) %IZE%,
BL(NOOPT) %IMIZE%,
BL(UNAME) %S%,
BL(NOUNA) %MES%,
BL(FINAL),
BL(NOFIN) %AL%,
BS(4,SAFE),
BL(UNSAF) %E%,
BS(3,ZIP),
BL(UNZIP),
BL(DEBUG),
BL(NODEB) %UG%,
BS(3,PIC),
BL(NOPIC),
% END OF SWITCHES VALID IN BOTH MODULE HEAD AND SWITCHES DECLARATION.
MODIFY SWSWL IF THE NUMBER OF SWITCHES ABOVE THIS CHANGES.
THE FOLLOWING SWITCHES ARE VALID ONLY IN THE MODULE HEAD. %
BL(SEGME) %NT%,
BL(NOSEG) %MENT%,
BL(START),
BL(STACK),
BS(4,MAIN),
BL(RESER) %VE%,
BL(IDENT),
BL(SYNTA) %X%);
! KEYWORD TABLE FOR CSECT/PSECT PROCESSING
BIND KWTBL=PLIT(
BS(4,CODE),
BL(DEBUG),
BL(GLOBA) %L%,
BS(3,OWN),
BS(4,PLIT));
FORWARD
ERRDECL,
DCLARE,
DECLARESYM,
DEFOG,
DEFGLO,
DEFASYM,
DEFMAP,
INITEQ,
OWNEQ,
GLOBALEQ,
MAPPURGE,
SYMPURGE,
GETLNKG,
SFORWARD,
SUNDECLARE,
STARTLNKG,
STARTNAME,
MAYBEDECLARE,
STARTCOL,
CONTIDLIST,
MAPONE,
ENDIDBATCH,
WHICHBIND,
BINDEQ,
GLBINDEQ,
REGEQ,
DOEQL,
DOSIZE,
GROMLIST,
PGLOBAL,
POWN,
PSTACKLOCAL,
PLOCAL,
PEXTERNAL,
PLABEL,
PREGISTER,
PBIND,
PGLOBBIND,
PROCPARMS,
GLOBROUT,
SLOCAL,
SSTACKLOCAL,
SOWN,
SGLOBAL,
SEXTERNAL,
SDCLLABEL,
SREGISTER,
SBIND,
SGLOBBIND,
SROUTINE,
SMAP,
SSETSIZE,
SBYTE,
SWORD,
INCRDECRREG,
SSWITCHES,
DOMODULE,
GETCONS,
GETSTRING,
SWITCHER,
SIDENT,
SSTACK,
SMAIN,
SSTART,
SRESERVE,
SRESERVE,
PPARAM,
SSTRUCTURE,
SMACRO,
GETSTRING2,
SCSECT,
SLNKGDECL,
SPLIT,
SPLITB,
PLITARG,
TUPLEITEM,
LSORLE,
LEXTOP,
SREQUIRE,
REQUINIT;
BIND DECLARATORS=PLIT(
0, !0
SBYTE, !1
SOWN, !2
SGLOBAL, !3
SEXTERNAL, !4
SROUTINE, !5
SSTRUCTURE, !6
SMAP, !7
SFORWARD, !8
SBIND, !9
SMACRO, !10
SUNDECLARE, !11
SDCLLABEL, !12
SWORD, !13
SSWITCHES, !14
SLOCAL, !15
SREGISTER, !16
SENABLE, !17
SREQUIRE, !18
SCSECT, !19
SSTACKLOCAL, !20
SLNKGDECL, !21
SCSECT !22 - PSECTS HANDLED BY CSECT ROUTINE
);
MACRO
ALLIGN(TABLE,NBYTE)=IF @TABLE AND NOT NBYTE
THEN TABLE_@TABLE+1$,
NEXTINTAB(TABLE,STE)=(STE[OFFSETF]_@TABLE;
TABLE_@TABLE+.STE[NCONTIGLOC])$,
BYTES(STE)=(.STE[SIZEF]/8)$;
MACRO ERROR(A,B,C,D)=ERRORR(D,C,B,A)$,
DELERR(COND,ERM)=IF .DEL COND THEN
RETURN ERROR(.LOBRAC,.NDEL,.LASTEND,ERM)$,
SXCTDECL=(LOBRAC_.NDEL;(@DECLARATORS[.DEL[HSYNTYP]])())$,
XCTDECL=(IF .SYM NEQ HEMPTY
THEN (SYM_HEMPTY;
ERROR(.LOBRAC,.NSYM,.LASTEND,DECLSYMERR))
ELSE (SXCTDECL;
IF .DEL NEQ HSEMICOLON
THEN ERROR(.LOBRAC,.NDEL,.LASTEND,DCLDELERR)
ELSE RUND(QLLEXEME)))$,
DECF(TP)=(IF NOT DECLARESYM(SENTRY,TP,1)
THEN RETURN
ELSE (SENTRY[POSF]_0; SENTRY[SIZEF]_16))$,
CKFORWD(RTYPE)=(IF (SENTRY_.NT[.SYM[ADDRF],SYMLINK]) NEQ 0
THEN IF .SENTRY[BLF] EQL .BLOCKLEVEL
AND .SENTRY[TYPEF] EQL FORWT
THEN (SENTRY[TYPEF]_RTYPE; SENTRY[DEBUGF]_.DEBFLG)
ELSE DECF(RTYPE)
ELSE DECF(RTYPE))$,
FBIT(BITNUM)=BITNUM,1$,
MUSTDECLARE =FBIT(0)$, !DECLARATION OTHER THAN MAP.
MUSTMAP =FBIT(1)$, !MUST BE MAPPED.
ISSBSLEX =FBIT(2)$, !HAS A SIZE LEXEME STREAM.
TEMPF =FBIT(3)$, !TEMPORARY BOOLEAN.
WASANEQUAL =FBIT(4)$, !EQUAL FOUND FOLLOWING THE
!INCARNATION ACTUALS.
LITRESULT=(.SYM[LTYPF] EQL LITTYP)$,
RULITEXP(LOCALSAV,LOCINFO)=(RUND(QLLEXEME);
LITEXP(LOCALSAV,LOCINFO))$,
LITEXP(LOCALSAV,LOCINFO)=(LOCALSAV_LOCINFO;
EXPRESSION();
SYM_BINDBIND(.SYM);
IF NOT LITRESULT
THEN (WARNEM(.LOCALSAV,ERMBADEXP); SYM_ONE))$;
EXTERNAL STVEC LNKGLX:INCACTS:STRSTE;
EXTERNAL INITSYMLSTS;
EXTERNAL LOBRAC;
GLOBAL ROUTINE ERRDECL=SXCTDECL; ! FOR ERROR HANDLING--SEE RUNC IN SYNTAX
GLOBAL ROUTINE DCLARE=
BEGIN
LOCAL SAVEL;
INDCL;
DECLSIZE_2;
NEWLASTEND(PSSEM);
BLOCKLEVEL_.BLOCKLEVEL+1;
WHILE .DEL[HCLASS] EQL DCLRTR DO
XCTDECL;
IF .NEXTLOCAL THEN NEXTLOCAL_.NEXTLOCAL+1;
RESINDECL;
RESLASTEND;
LCBRAC_.NDEL
END;
ROUTINE DECLARESYM(WHERE,TYPE,ERRHURTS)=
!I. GENERAL:
!
! 1. THIS ROUTINE DECLARES A SYMBOL IN "SYM".
!
! 2. PARAMETERS:
!
! A. WHERE - A POINTER TO A LOCATION WHERE THE
! SYMBOL TABLE INDEX OF THE SYMBOL
! DECLARED IN "SYM" SHOULD BE PUT.
!
! B. TYPE - THE TYPE OF THE SYMBOL TO BE DECLARED
!
! C. ERRHURTS - A BOOLEAN THAT DETERMINES THE TYPE
! OF ERROR RECOVERY TO BE ATTEMPTED.
!
!II. SPECIFIC:
!
! 1. *
!
! A. FIRST EXAMINE THE LEXEME IN SYM.
! 1. IF IT IS NOT A NAME TABLE ENTRY, GIVE
! EITHER AN ERROR OR A WARNING MESSAGE,
! DEPENDING ON THE SETTING OF "ERRHURTS".
!
! 2. PICK UP THE SYMBOL TABLE ENTRY MOST
! RECENTLY ATTACHED TO THIS NAME TABLE
! ENTRY.
!
! B. IF THE ENTRY IS UNDECLARED, OR FROM AN OUTER
! BLOCK, THEN:
! 1. DECLARE THE SYMBOL, AND ENTER ITS NEW
! TYPE IN A NEW SYMBOL TABLE ENTRY FOR
! THIS BLOCK.
!
!
! 2. PUT IT WHERE THE CALLER WANTS IT,
! AND CORRECT THE FUTURE SYMBOL LEXEME.
!
! C. OTHERWISE, WE HAVE ALREADY DECLARED IT IN
! THIS BLOCK, AND THAT IS AN ERROR.
BEGIN
BIND STVEC STSYM=SYM;
LOCAL STVEC STENTRY,MSGTYPE,ERRLOC;
MSGTYPE_ERNOSYM; ERRLOC_.NSYM;
IF .SYM EQL HEMPTY
THEN (ERRLOC_.NDEL;
IF .RESWD
THEN (RUNDE();
MSGTYPE_ERDCLRESWD));
IF .SYM[LTYPF] EQL BNDVAR
THEN (WARNEM(.LOBRAC,.NSYM,ERNOSYM);
SYM_.STSYM[NAMEPTR])
ELSE IF .SYM[LTYPF] NEQ UNBNDVAR
THEN (IF .ERRHURTS
THEN ERROR(.LOBRAC,.ERRLOC,.LASTEND,.MSGTYPE)
ELSE WARNEM(.LOBRAC,.ERRLOC,.MSGTYPE);
RETURN 0);
IF .STRUEXPAND
THEN STINSERT(.SYM[ADDRF],UNDECTYPE,0);
STENTRY_.STSYM[SYMLINK];
IF .STENTRY[TYPEF] NEQ UNDECTYPE
AND .STENTRY[BLF] GEQ .BLOCKLEVEL
THEN (ERRINFO[0]_.STENTRY; WARNEM(.NSYM,WASMPREV));
.WHERE_STINSERT(.SYM[ADDRF],.TYPE,0);
RETURN 1;
END;
MACRO BDEF=BEGIN MAP STVEC STE;$, EDEF=END$;
ROUTINE DEFOG(TABLE,STE,REQIN,RELIN,INIT)=
BDEF
ALLIGN(.TABLE,BYTES(STE));
IF .REQIN THEN
(STE[REQINIT]_TRUE;
STE[RELEASEINIT]_.RELIN;
STE[INITP]_.INIT);
STE[REGF]_PC;
IF .STE[ITSAPLIT] THEN
IF .STE[COUNTED] THEN (.TABLE)<0,36>[email protected]+2;
NEXTINTAB(.TABLE,STE);
INITSYMLSTS(.STE);
0
EDEF;
ROUTINE DEFGLO(STE,REQIN,RELIN,INIT)=
BDEF DEFOG(NEXTGLOBAL,.STE,.REQIN,.RELIN,.INIT);
STE[MODE]_ABSOLUTE; EDEF;
GLOBAL ROUTINE DEFASYM(STE,NOBYTES,POS,SIZ)=
BDEF
STE[NCONTIGLOC]_.NOBYTES;
STE[POSF]_.POS;
STE[SIZEF]_.SIZ;
STE[LNKGNMF]_.LNKGLX;
EDEF;
GLOBAL ROUTINE DEFMAP(STE)=
BDEF STE[HAVNOACTS]_TRUE;
STE[STRUORIACT]_.STRUDEFV; EDEF;
ROUTINE INITEQ=
BEGIN LOCAL PLITP,ERR, SIZ;
ERR_.NDEL;
OLDDELI_#126; ! "PLIT" SIGNAL TO DETBRACKET
IF (SIZ_2*SPLITB(PLITP %, T%)) GTR .SIZE
THEN (IF NOT .NOTREE THEN WARNEM(.ERR,ERISEDS); SIZE_.SIZ);
SYM_.PLITP;
0
END;
ROUTINE OWNEQ=INITEQ();
ROUTINE GLOBALEQ=INITEQ();
ROUTINE MAPPURGE(STE)=
% PRESUMES MAPPABLE SYMBOL %
BDEF
LOCAL STVEC STREAM;
IF (.STE[STRUORIACT] EQL 0) OR
.STE[HAVNOACTS] OR
NOT .STE[RELEASEACTS]
THEN RETURN;
STREAM_.STE[STRUORIACT];
STREAM[STRUCF]_0;
STRMRELEASE(.STREAM);
TRUE
EDEF;
GLOBAL ROUTINE SYMPURGE(STE)=
! SYMPURGE RETURNS TRUE IF THE SYMBOL MAY BE PURGED. IN
! ADDITION IT RELEASES ALL FIELDS (STREAMS AND
! TREES ASSOCIATED WITH THE FIELDS WITHIN THE SYMBOL.
BDEF
EXTERNAL FERASEDET;
MACRO
INIPURGE(STE)=
(IF .STE[REQINIT] AND .STE[RELEASEINIT]
THEN FERASEDET(.STE[INITP]); 2)$,
MACPURGE(STE)=
(STRMRELEASE(.STE[STREAMF]); 1)$,
STRPURGE(STE)=
(STRMRELEASE(.STE[BODYSTRM]);
IF .STE[SIZESTRM] NEQ 0 THEN STRMRELEASE(.STE[SIZESTRM]);
1)$;
SELECT .STE[TYPEF] OF
NSET
UNDECTYPE: RETURN 1;
MACROT: RETURN MACPURGE(STE);
STRUCTURET: RETURN STRPURGE(STE);
FORWT: (ERRINFO[0]_.STE; WARNEM(0,ERMRD); RETURN 1);
% MAPPABLE TYPES ONLY PAST HERE %
ALWAYS: IF NOT ISSTVAR(STE) THEN RETURN 1 ELSE MAPPURGE(.STE);
GLOBALT: RETURN INIPURGE(STE);
OWNT: RETURN INIPURGE(STE);
ALWAYS: RETURN 2;
TESN;
0
EDEF;
ROUTINE GETLNKG(LOC)=
!
! CALLED BY SFORWARD, GLOBROUT, AND SROUTINE
! PARSES THE LINKAGE NAME OF THE ROUTINE
!
BEGIN
BIND NTVEC NTSYM=SYM;
LOCAL STVEC LNKGNM;
LNKGNM _ .DFLTLNKGLX;
IF .DEL EQL ERRLEX THEN
BEGIN
LNKGNM _ .NTSYM[SYMLINK];
IF .LNKGNM[TYPEF] NEQ LNKGNMT THEN
(WARNEM(.NSYM,WAMSPLNKG);
LNKGNM _ .DFLTLNKGLX);
RUND(QLQNAME);
END;
.LOC _ .LNKGNM;
NOVALUE
END;
ROUTINE SFORWARD=
!
!SYNTAX: FORWARD <NAMESPEC1>,<NAMESPEC2>,...,<NAMESPECN>
!
! <NAMESPEC>::=<NAME>/<NAME>(<#PARAMETERS>)
!
!I. GENERAL:
!
! 1. THIS ROUTINE DECLARES AS FORWARD WITHIN THE BLOCK
! OPEN AT THE TIME OF DECLARATION.
!
! 2. THIS MEANS THAT THE ROUTINE WILL BE FOUND, AND
! DECLARED LATER WITHIN THIS SAME BLOCK;
!
!II. SPECIFIC:
!
! 1. *
!
! A. IT DOES EACH OF THE FOLLOWING THINGS TO
! DECLARE A FORWARD NAME UNTIL IT COMES TO
! A ";".
!
! 1. DECLARE THE NAME IN "SYM" AS OF
! TYPE FORWARD.
!
! 2. NEXT, IF WE SEE AN OPEN PARENTHESIS,
! ("("),THEN:
!
! A. PROCESS THE EXPRESSION WITHIN
! THE PARENTHESIS PAIR, AND
! MAKE SURE IT IS A LITERAL.
!
! B. IF WE DON'T NOW SEE A
! CLOSE PARENTHESIS
! AND AND EMPTY FUTURE SYMBOL,
! IE, THE WINDOW SHOULD BE:
!
! (XXX,")",<EMPTY>,",")
!
! THEN THERE IS AN ERROR.
!
! C. SAVE THE RESULTING LITERAL,
! AND MOVE THE WINDOW.
!
! 3. FINALLY, ADD THE NUMBER OF PARAMETERS
! FOR THE ROUTINE TO ITS SYMBOL TABLE
! ENTRY.
!
! 4. GENERATE INFORMATION FOR THE ROUTINE.
!
! 5. WE SHOULD HAVE A COMMA NEXT, OR A ";"
BEGIN
LOCAL SFSYMCHK,SAVSYM,STVEC SFSTE:LNKGNM;
DO
BEGIN
RUND(QLQNAME);
GETLNKG(LNKGNM);
IF DECLARESYM(SFSTE,FORWT,0)
THEN IF .DEL EQL HPARAOPEN
THEN BEGIN
RULITEXP(SFSYMCHK,.NSYM);
IF .DEL NEQ HPARACLOSE
THEN RETURN ERROR(.LOBRAC,.NDEL,.LASTEND,ERSYMNPRD);
SAVSYM_.SYM;
RUND(QLLEXEME);
IF .SYM NEQ HEMPTY THEN RETURN
ERROR(.LOBRAC,.NDEL,.LASTEND,ERSYMNPRD);
END
ELSE SAVSYM_0
ELSE EXITCOMPOUND;
DEFMAP(.SFSTE);
SFSTE[LNKGNMF]_.LNKGNM;
SFSTE[POSF]_0;
SFSTE[SIZEF]_16;
SFSTE[REGF]_PC;
SFSTE[MODE]_IF .PICSW THEN RELATIVE ELSE ABSOLUTE;
END
WHILE .DEL EQL HCOMMA;
END;
ROUTINE SUNDECLARE=
DO
BEGIN
MAP STVEC SYM;
RUND(QLQNAME);
STINSERT(.SYM,UNDECTYPE,0)
END
WHILE .DEL EQL HCOMMA;
ROUTINE STARTLNKG=
BEGIN
LOCAL STVEC STE;
LNKGLX_.DFLTLNKGLX;
IF .DEL EQL ERRLEX
THEN BEGIN
MACRO FORGET(WARNTYPE) =
(WARNEM(.NSYM,WARNTYPE);
EXITBLOCK RUND(QLQNAME)) $;
IF .SYM[LTYPF] EQL UNBNDVAR
THEN SYM_FASTLEXOUT(BNDVAR,.NT[.SYM,SYMLINK])
ELSE IF .SYM[LTYPF] NEQ BNDVAR
THEN FORGET(WAINVSTRUC);
IF (STE_.SYM[ADDRF]) EQL .TRAPLNKGLX[ADDRF]
THEN FORGET(WATRAPLNKG);
IF .STE[TYPEF] NEQ LNKGNMT
THEN RETURN 0;
LNKGLX_.STE;
RUND(QLQNAME)
END;
RETURN 0;
END;
ROUTINE STARTNAME=
!I. GENERAL:
!
! 1.THIS ROUTINE SETS UP A STRUCTURE SYMBOL TABLE ENTRY
! FOR THE SYMBOLS FOLLOWING IT, IF THE STRUCTURE IS
! SPECIFIED.
!
! 2. WE THEN SET FIELDS RELEVANT TO THE STRUCTURE, ONLY
! IF THE SYMBOLS FOLLOWING IN THIS DECLARATION ARE
! TO BE MAPPED.
!
!II. SPECIFIC:
!
! 1. *
!
! A. IF ".DEL" IS AN ERROR LEXEME THEN WE
! HAVE: <NAME1> <NAME2>
! WITH NO INTERVENING DELIMITER, AND THUS
! SPECIFIES A STRUCTURE MAPPING.
!
! B. WE HAVE ERRORS NOW, IF:
!
! 1. THE SYMBOL TABLE ENTRY FOR THE
! STRUCTURE IS OF AN UNDECLARED TYPE.
!
! 2. THE SYMBOL IS NOT OF TYPE STRUCTURE.
!
! C. IF EVERYTHING ELSE IS OK, THEN WE HAVE A
! STRUCTURE, SO WE SET THE "MUSTMAP" FIELD
! OF THE FLAGS "OFLAGS", SINCE WE MUST THEN
! MAP THIS STRUCTURE ONTO ALL FOLLOWING
! IDENTIFIERS IN THIS FIELD.
!
! D. OTHERWISE,, IF WE DON'T EXPLICITLY HAVE A STRUCTURE,
! THEN THE STRUCTURE SYMBOL TABLE INDEX IS SET
! TO THE VECTOR DEFAULT INDEX, AND WE NEED NOT
! MAP AT THIS POINT. THE REASON THAT WE DO
! SET THE INDEX THOUGH IS THAT WE MAY FIND
! LATER THAT WE INDEED DO NEED TO MAP, AND WE
! WILL THEN HAVE EVERYTHING SET UP.
! E. NEXT WE SEE IF THE FOLLOWING ID'S NEED TO BE
! MAPPED WHETHER OR NOT WE SAW A STRUCTURE.
! THEY NEED TO BE MAPPED IN THE FOLLOWING
! CASES:
!
! 1. A STRUCTURE WAS SPECIFIED.
!
! 2. WE SEE "<NAME>[".
!
! 3. WE SEE "<NAME>:".
!
! 4. THE IDENTIFIERS FOLLOWING ARE
! NOT TO BE DECLARED.
!
! 2. *
!
! A. THEN, IF WE DO NEED TO MAP, THEN WE DO THE
! FOLLOWING:
!
! 1. SET THE FLAG FOR THE LEXEME STREAM
! TYPE.
!
! 2. SET THE LEXEME STREAM STRUCTURE INDEX.
! 3. SET THE INCARNATION ACTUALS CELL BLOCK
! SIZE, AND THE NUMBER OF EXPECTED
! INCARNATION ACTUALS. NOTE THAT THE
! NUMBER OF EXPECTED INCARNATION
! ACTUALS IS OBTAINED FROM THE
! STRUCTURE SYMBOL TABLE ENTRY.
BEGIN
INCACTS_0; STRSTE_.STRUDEFV;
IF .DEL EQL ERRLEX
THEN BEGIN
LOCAL STVEC STE;
MACRO FORGET(WARNTYPE) =
(WARNEM(.NSYM,WARNTYPE);
EXITBLOCK RUND(QLQNAME)) $;
IF .SYM[LTYPF] EQL UNBNDVAR
THEN SYM_.NT[.SYM,SYMLINK]
ELSE IF .SYM[LTYPF] NEQ BNDVAR
THEN FORGET(WAINVSTRUC);
STE_.SYM[ADDRF];
IF .STE[TYPEF] NEQ STRUCTURET
THEN FORGET(WASMNOTSTR)
ELSE RUND(QLQNAME);
STRSTE_.STE
END;
RETURN 0;
END;
ROUTINE MAYBEDECLARE(ERRHURTS)=
!I. GENERAL:
!
! 1. THIS ROUTINE DECLARES THE SYMBOL IN "SYM" IF IT
! SHOULD BE, (IE IF OFLAGS[MUSTDECLARE] IS ON).
!
! 2. RETURNS:
!
! A. THIS ROUTINE RETURNS A 1 IF THERE WERE
! ANY ERRORS FOUND DURING DECLARATION.
(IF .OFLAGS[MUSTDECLARE]
THEN NOT DECLARESYM(STE,.OTYPE,.ERRHURTS)
ELSE (STE_.NT[.SYM[ADDRF],SYMLINK];0));
ROUTINE STARTCOL=
!I. GENERAL:
!
! 1. THIS ROUTINE TAKES THE SYMBOL IN "SYM", DECLARES
! IT IF NECESSARY, AND PUTS IT AS THE FIRST ELEMENT
! ON THE SYMBOL TABLE LIST.
!
! 2. THIS SYMBOL TABLE LIST IS MADE SINCE WE CAN HAVE
! THINGS OF THE FORM:
!
! <NAME1>:...:<NAMEN>[<VAL1>,...,<VALM>]:...
BEGIN
IF MAYBEDECLARE(1)
THEN RETURN 1;
ST[STELAST_STELIST_GETSPACE(ST,2),STELSTEF]_.STE;
ST[.STELIST,STELCPF]_.NSYM;
RETURN 0;
END;
ROUTINE CONTIDLIST=
!I. GENERAL:
!
! 1. THIS ROUTINE SIMPLY CONTINUES DECLARING SYMBOLS
! IN "SYM".
!
! 2. WINDOW IN:
!
! A. (<NAME1> , ":" )
!
! 3. WINDOW OUT:
!
! A. (<NAME2> , ":"/"["/","/";" )
BEGIN
REGISTER SAVSTE;
RUND(QLQNAME);
IF MAYBEDECLARE(0)
THEN RETURN 1;
SAVSTE_.STELAST;
ST[.SAVSTE,STELNEXTF]_STELAST_GETSPACE(ST,2);
ST[.STELAST,STELSTEF]_.STE;
ST[.STELAST,STELCPF]_.NSYM;
RETURN 0;
END;
ROUTINE MAPONE(POS,FIRST)=
BEGIN
MAP STVEC STE;
LOCAL STEE;
IF .OTYPE EQL 0 THEN
BEGIN
IF NOT ISEXP(STE)
THEN (WARNEM(.POS,WACANTMAP);
RETURN 0);
IF .STE[BLF] EQL .BLOCKLEVEL
THEN MAPPURGE(.STE)
ELSE (SYM_LEXOUT(UNBNDVAR,.ST[STEE_.STE,NAMEPTR]);
DECLARESYM(STE,MBINDT,0);
DEFASYM(.STE,0,0,8*.DECLSIZE);
STE[BINDLEXF]_BINDBIND(LEXOUT(BNDVAR,.STEE)));
END;
STE[STRUORIACT]_
IF .INCACTS NEQ 0
THEN (IF STE[RELEASEACTS]_.FIRST
THEN INCACTS[STRUCF]_.STRSTE; .INCACTS)
ELSE (STE[HAVNOACTS]_TRUE; .STRSTE);
0
END;
ROUTINE ENDIDBATCH=
BEGIN
REGISTER TEMP;
MAP STVEC STELIST:TEMP:STE;
LOCAL FIRSTACT;
FIRSTACT_TRUE;
DO
BEGIN
STE_.STELIST[STELSTEF];
IF MAPONE(.ST[.STELIST,STELCPF],.FIRSTACT) THEN RETURN 1;
IF .OFLAGS[MUSTDECLARE]
THEN BEGIN
DEFASYM(.STE,.SIZE,0,8*.DECLSIZE);
IF (.OFUN)(.FIRSTACT,.SIZE,.STE)
THEN RETURN 1;
END;
FIRSTACT_FALSE;
END
WHILE
BEGIN
TEMP_.STELIST;
STELIST_.TEMP[STELNEXTF];
RELEASESPACE(ST,.TEMP,2);
.TEMP NEQ .STELAST
END;
RETURN 0;
END;
ROUTINE WHICHBIND=
!I. GENERAL:
!
! 1. THIS ROUTINE DETERMINES WHAT TYPE OF BIND WE MUST
! DO, AND PASSES ITS FINDINGS TO ITS CALLER AS A
! RETURN VALUE.
!
! 2. RETURNS:
!
! A. 0 - CODE MUST BE GENERATED FOR THIS
! BIND.
!
! B. 1 - THE BIND IS TO A LITERAL.
!
! C. 2 - GENERAL ADDRESS BIND, BUT NO CODE.
BEGIN
MAP LEXEME SYM;
EXPRESSION();
SYM_BINDBIND(.SYM);
IF .SYM[LTYPF] EQL GTTYP
THEN IF NOT
BEGIN ! GET RID OF <0,0> AND <0,8> BEFORE CHECKONELOCAL DOES SO
BIND STVEC STSYM=SYM;
IF .STSYM[NODEX] EQL SYNPOI
THEN IF .STSYM[OPR2] EQL ZERO
THEN IF LITVALUE(.STSYM[OPR3]) MOD 8 EQL 0
THEN BEGIN
BIND TEMP=.SYM[ADDRF];
STSYM_.STSYM[OPR1];
PDETACH(TEMP);
RELEASESPACE(GT,TEMP,BASEGTNODESIZE+3);
.SYM[LTYPF] NEQ GTTYP
END
END
THEN (DYNBIND(); RETURN 0);
IF LITRESULT THEN 1 ELSE 2
END;
ROUTINE BINDEQ=(RUND(QLLEXEME); WHICHBIND(); 0);
ROUTINE GLBINDEQ=
BEGIN
RUND(QLLEXEME);
CASE WHICHBIND() OF
SET
%0% (WARNEM(.NSYM,ERSMPLNLO); SYM_ZERO);
%1% ;
%2% (IF .SYM[LTYPF] EQL BNDVAR
THEN IF LOADCONST(SYM)
THEN EXITCASE;
WARNEM(.NSYM,ERSMPLNLO); SYM_ZERO)
TES;
0
END;
ROUTINE REGEQ=
!I. GENERAL:
!
! 1. THIS ROUTINE PROCESSES AN "=" IN A REGISTER
! DECLARATION.
!
!II. SPECIFIC:
!
! 1. *
!
! A. EVALUATE AN EXPRESSION WHOSE RESULT SHOULD
! BE A LITERAL.
!
! B. IF THE RESULT IS A LITERAL, THEN CHECK THAT
! IT IS WITHIN LIMITS FOR A REGISTER
! DECLARATION.
!
! C. IF EVERYTHING ELSE SO FAR IS OK, THEN SEE IF
! THE REGISTER IS IN USE FOR ANYTHING ELSE AT
! THIS TIME, AND IF IT IS, THEN GIVE A WARNING.
BEGIN
LOCAL SAVSYMPOS; REGISTER LTRES;
BIND LOWREG=0,
HIGHREG=5;
RUND(QLLEXEME);
LITEXP(SAVSYMPOS,.NSYM);
LTRES_LITVALUE(.SYM[ADDRF]);
IF (.LTRES GTR HIGHREG) OR (.LTRES LSS LOWREG)
THEN (WARNEM(.SAVSYMPOS,ERSMNDEC); SYM_ONE);
RETURN 0;
END;
ROUTINE DOEQL=
!I. GENERAL:
!
! 1. THIS ROUTINE HANDLES THE GENERAL CASE OF AN EQUAL
! SIGN ("=") AFTER AN IDENTIFIER IN A DECLARATION.
!
! 2. RETURNS:
!
! A. 1 - IF ANY ERRORS WERE FOUND. AN ERROR OCCURS
! IF:
!
! 1. NO EQUAL SIGN IS FOUND, AND WE
! REQUIRE ONE.
!
! 2. THE SPECIFIC ROUTINE WHICH PROCESSES
! EQUAL SIGNS FOR THE TYPE OF
! DECLARATION WE ARE NOW PROCESSING
! FINDS ANY ERRORS.
!
!II. SPECIFIC:
!
! 1. *
!
! A. IF A PROCESSING ROUTINE WAS SPECIFIED, AND
! AN EQUAL SIGN WAS FOUND (IN "SYM"), THEN
! MOVE THE WINDOW SO IT IS AT THE
! BEGILNING OF THE EXPRESSION FOLLOWING THE
! EQUAL SIGN.
!
! B. THERE ARE FOUR (4) RETURN CASES.
!
! 1. NO EQUAL SEEN, NONE REQUIRED, ALL OK.
! 2. NO EQUAL, BUT ONE IS REQUIRED,
! ERROR.
!
! 3. EQUAL SEEN, AND NOT REQUIRED. PROCESS
! IT, AND RETURN IN THE SAME STATE AS
! THE PROCESSING ROUTINE EXITED.
!
! 4. EQUAL SEEN, AND IT WAS REQUIRED.
! AGAIN PROCESS IT AND RETURN IN THE
! SAME STATE AS THE PROCESSING ROUTINE
! EXITED.
BEGIN
IF .DEL EQL HEQUAL
THEN BEGIN
OFLAGS[WASANEQUAL]_TRUE;
IF .OEQL EQL 0
THEN (WARNEM(.NDEL,WANOEQL);
RETURN INITEQ())
END
ELSE OFLAGS[WASANEQUAL]_FALSE;
RETURN CASE .OFLAGS[WASANEQUAL]*2+(.OEQL LSS 0) OF
SET
0;
BEGIN
ERROR(.LOBRAC,.NDEL,.LASTEND,ERSYMEQ);
1
END;
(.OEQL)(.SIZE);
(-.OEQL)(.SIZE)
TES;
END;
ROUTINE DOSIZE=
BEGIN
LOCAL NOBRAC, NSTART;
SIZE_.DECLSIZE;
IF .DEL EQL HCOLON THEN RETURN 0;
NSTART_.NDEL;
INCACTS_GETSPACE(ST,.STRSTE[NUMPARM]+3);
INCACTS[STKLEN]_.STRSTE[NUMPARM]+2;
IF .DEL EQL HSQBOPEN
THEN (LOCAL SAVMNACTS;
IF .OTYPE EQL LABELT
THEN WARNEM(.NDEL,LSIZERR);
SAVMNACTS_.MANYACTS; MANYACTS_0;
STRUPICKOFF(HSQBCLOSE,.INCACTS+2,.INCACTS[STKLEN]-1,ONE,TRUE);
MANYACTS_.SAVMNACTS;
NOBRAC_FALSE)
ELSE (SETCORE(INCACTS[2],.INCACTS[STKLEN]-1,ONE);
NOBRAC_TRUE);
INCACTS[1,0,36]_LITLEXEME(.DECLSIZE);
IF .STRSTE[SIZESTRM] NEQ 0
THEN BEGIN
LOCAL SAVDEL;
IF .NOBRAC THEN SAVDEL_.DEL;
ESTRU(.STRSTE[SIZESTRM],.INCACTS-1,.STRSTE,.NOBRAC);
IF .NOBRAC THEN DEL_.SAVDEL;
SYM_BINDBIND(.SYM);
IF NOT LITRESULT
THEN (WARNEM(.NSTART,ERMBADEXP); SYM_ONE);
SIZE_LITVALUE(.SYM)
END
ELSE IF NOT .NOBRAC THEN RUNDE();
RETURN 0;
END;
ROUTINE GROMLIST(GRLTYPE,GRLPARAM,GRLFUN,GRLEQL,GRLASS)=
!
!SYNTAX: <DELTYPE> <NAMESPEC1>,...,<NAMESPECN>
!
! <NAMESPEC> ::=<STRUCSPEC> <NAMSZ1>...:<NAMSZK>
! <STRUCSPEC>::=/<STRUCTURE NAME>
! <NAMSZ> ::=<NAME1>:...:<NAMEM><SIZE><EQSPEC>
! <SIZE> ::=/[<SIZE1>,...,<SIZEL>]
! <EQSPEC> ::=/ = <EXPRESSION>
!
!I. GENERAL:
!
! 1. THIS ROUTINE HANDLES THE GENERAL PROCESSING OF
! DECLARATIONS.
!
! 2. MACROS:
!
! A. CHECK(ROUTNAME) - "ROUTNAME" MUST BE THE
! NAME OF A ROUTINE WHICH RETURNS A 1
! IF ANY ERRORS WERE FOUND. THIS MACRO
! SIMPLY SERVES TO CALL THIS ROUTINE, AND
! RETURN IF ANY ERRORS WERE FOUND.
!
! B. OTHERCHECKS - THIS MACRO STARTS THE PROCESSING
! OF A FIELD FOLLOWING THE
! OPTIONAL STRUCTURE, UP TO THE
! FIRST COMMA. IT WORKS AS
! FOLLOWS. IT FIRST PROCESSES
! THE FIRST NAME IN A POSSIBLE
! STRING OF AN ARBITRARY
! NUMBER, LIKE - X:Y:Z:...
! THEN IT PROCESSES ALL OTHERS
! WHILE THE DELIMITER FOLLOWING
! EACH IS A COLON (":"), IE
! UNTIL IT COMES TO "[" OR "="
! AS IN X:Y:Z[10] OR X:Y:Z=20
! IT THEN TRIES TO PROCESS AN
! OPTIONAL SIZE FIELD, AND THEN
! AN "=" (BIND). FINALLY, IT
! CALLS "ENDIDBATCH" TO ANY
! LAST NECESSARY THINGS IN THE
! DECLARATION OF IDENTIFIERS SO
! FAR FOUND.
!
!II. SPECIFIC:
!
! 1. *
!
! A. FIRST PUT ALL PARAMETERS INTO GLOBALS FOR
! OTHER PROCESSING ROUTINES TO USE.
!
! B. TO PROCESS A FIELD OF DECLARATIONS,(IE
! BETWEEN COMMAS), WE MUST DO THE FOLLOWING
! THINGS:
!
! 1. FIRST CHECK IF THERE IS A STRUCTURE
! NAME, AND IF THERE IS, THEN DO THE
! APPROPRIATE THINGS TO SET IT UP.
!
! 2. THEN WE MUST SEE IF THERE ARE BINDS,
! ETC FOR A LIST OF IDENTIFIERS WHICH
! WE PROCESS NOW.SINCE THE FOLLOWING
! IS LEGAL, WE MUST DO THESE
! INSIDE STEPS AN ARBITRARY NUMBER OF
! TIMES:
!
! X:Z:T[100]:P:R[29,4]:D:C
!
! HERE WE SEE THAT THERE ARE 3
! DECOMPOSABLE UNITS WHICH SHOULD
! BE TREATED THE SAME, THEY ARE:
!
! X:Z:T[100]
! P:R[29,4]
! D:C
!
! C. KEEP DOING PART [1.B] UNTIL
! THERE ARE NO MORE COMMAS.
!
! D. THE LAST DELIMITER SHOULD BE ";", AND THERE
! IS AN ERROR IF IT IS NOT.
BEGIN
MACRO CHECK(ROUTNAME)=(IF ROUTNAME() THEN RETURN)$,
OTHERCHECKS=(CHECK(STARTCOL);
WHILE .DEL EQL HCOLON
DO CHECK(CONTIDLIST);
CHECK(DOSIZE);
CHECK(DOEQL);
CHECK(ENDIDBATCH))$,
NAMEPROC=(CHECK(STARTLNKG);CHECK(STARTNAME);
DO OTHERCHECKS
WHILE IF .DEL EQL HCOLON THEN (RUND(QLQNAME);1))$;
LOCAL SAVTYPE,SAVPARM,SAVFUN,SAVEQL,SAVFLAGS;
LOBRAC_.NDEL;
SAVTYPE_.OTYPE;
SAVPARM_.OPAR;
SAVFUN_.OFUN;
SAVEQL_.OEQL;
SAVFLAGS_.OFLAGS;
OTYPE_.GRLTYPE;
OPAR_.GRLPARAM;
OFUN_.GRLFUN;
OEQL_.GRLEQL;
OFLAGS[MUSTDECLARE]_.GRLTYPE NEQ 0;
DO (RUND(QLQNAME); NAMEPROC) WHILE .DEL EQL HCOMMA;
OTYPE_.SAVTYPE;
OPAR_.SAVPARM;
OFUN_.SAVFUN;
OEQL_.SAVEQL;
OFLAGS_.SAVFLAGS;
END;
ROUTINE PGLOBAL(FIRST,SIZE,STE)=DEFGLO(.STE,.OFLAGS[WASANEQUAL],.FIRST,.SYM);
ROUTINE POWN(FIRST,SIZE,STE)=
BEGIN MAP STVEC STE;
DEFOG(NEXTOWN,.STE,.OFLAGS[WASANEQUAL],.FIRST,.SYM);
STE[MODE]_ABSOLUTE;
END;
ROUTINE PSTACKLOCAL(IGP,PGSIZE,PGSTE)=
BEGIN MAP STVEC PGSTE;
ALLIGN(NEXTLOCAL,BYTES(PGSTE));
NEXTLOCAL_.NEXTLOCAL+.STE[NCONTIGLOC];
STE[OFFSETF]_-.NEXTLOCAL;
PGSTE[REGF]_SP;
PGSTE[MODE]_INDEXED;
PGSTE[NOUPLEVEL]_TRUE;
INITSYMLSTS(.PGSTE);
0
END;
ROUTINE PLOCAL(IGP,PGSIZE,PGSTE)=
BEGIN MAP STVEC PGSTE;
IF .PGSIZE EQL 2
THEN BEGIN
LOCAL GTVEC TN;
TN_PGSTE[REGF]_GETTN();
TNDECREQD(.TN);
TN[LDF]_.LOOPDEPTH;
PGSTE[MODE]_GENREG;
PGSTE[NOUPLEVEL]_TRUE;
INITSYMLSTS(.PGSTE);
END
ELSE PSTACKLOCAL(.IGP,.PGSIZE,.PGSTE);
0
END;
GLOBAL ROUTINE PEXTERNAL(IGPARAM,IGSIZE,PESTE)=
!I. GENERAL:
!
! 1. THIS ROUTINE HANDLES THE SPECIFIC PROCESSING FOR
! THE EXTERNAL DECLARATION.
!
!II. SPECIFIC:
!
! 1. *
!
! A. SIMPLY SET THE ADDITIONAL INFORMATION WORD
! TO A UNIQUE NUMBER REPRESENTING THE EXTERNAL
! TYPE FOR LATER PROCESSING BY THE LOADER
! INTERFACE.
BEGIN
MAP STVEC PESTE;
% BIND EXTERNALADDR=#777777; %
PESTE[REGF]_PC;
PESTE[OFFSETF]_0;
PESTE[MODE]_ABSOLUTE;
% PESTE[ADDRESSF]_EXTERNALADDR; %
INITSYMLSTS(.PESTE);
RETURN 0;
END;
ROUTINE PLABEL(PARAM,PLSIZE,PLSTE)= NOVALUE;
ROUTINE PREGISTER(IGPARAM,PRSIZE,PRSTE)=
!I. GENERAL:
!
! 1. THIS ROUTINE PERFORMS THE FUNCTIONS UNIQUE TO
! REGISTER DECLARATIONS.
!
!II. SPECIFIC:
!
! 1. *
!
! A. IF THERE WAS AN EQUAL SIGN, THEN THE
! REGISTER IS DECLARED AS AN ABSOLUTE
! TYPE.
!
! B. OTHERWISE, WE ACQUIRE THE REGISTER, INSERT
! IT INTO THE LITERAL TABLE, AND SET THE
! ADDITIONAL INFORMATION FIELD TO THIS
! LITERAL TABLE INDEX.
BEGIN
MAP STVEC PRSTE;
LOCAL GTVEC TN;
TN_PRSTE[REGF]_GETTN();
PRSTE[MODE]_GENREG;
PRSTE[NOUPLEVEL]_TRUE;
IF .OFLAGS[WASANEQUAL]
THEN (BIND NUM=LITVALUE(.SYM);
TNSRREQD(.TN,NUM);
IF .RESERVED[NUM,1]
THEN PRSTE[NOUPLEVEL]_FALSE)
ELSE TNARREQD(.TN);
TN[LDF]_.LOOPDEPTH;
INITSYMLSTS(.PRSTE);
RETURN 0;
END;
ROUTINE PBIND(PARM,SIZE,STENTRY)=
BEGIN
MAP STVEC STENTRY;
STENTRY[BINDLEXF]_.SYM;
STENTRY[NOUPLEVEL]_
CASE .SYM[LTYPF] OF
SET
% 0 % ;
% LITTYP % FALSE;
% BNDVAR % .ST[.SYM,NOUPLEVEL];
% GTTYP % TRUE
TES;
END;
ROUTINE PGLOBBIND(PARM,SIZE,STENTRY)=
BEGIN
MAP STVEC STENTRY;
STENTRY[BINDLEXF]_.SYM;
STENTRY[GLBIND]_TRUE;
END;
GLOBAL ROUTINE PROCPARMS(RNAME)=
BEGIN
MAP STVEC RNAME;
MACRO ISTRAPTYPE=
ONEOF(.LNKT,BIT4(EMTLNKGT,INTRRPTLNKGT,TRAPLNKGT,IOTLNKGT))$;
MACRO OLDPCPS=
IF ISTRAPTYPE THEN
BEGIN
BIND PCPS=PLIT ('OLDPC','OLDPS');
LOCAL SACC[2],SSYM;
SACC_.ACCUM;
SACC[1]_.ACCUM[1];
SSYM_.SYM;
DECR I FROM 1 TO 0 DO
BEGIN
ACCUM_.PCPS[.I]; ACCUM[1]_-2;
SYM_FASTLEXOUT(UNBNDVAR,SEARCH(UNDECTYPE));
DECLARESYM(FORMAL,FORMALT,0);
NP_.NP+1;
DEFASYM(.FORMAL,2,0,16);
FORMAL[STRUORIACT]_.STRUDEFV;
FORMAL[HAVNOACTS]_1;
FORMAL[OFFSETF]_.LSF;
LSF_.FORMAL;
FORMAL[REGF]_SP;
FORMAL[MODE]_INDEXED;
END;
SYM_.SSYM;
ACCUM[1]_.SACC[1]; ACCUM_.SACC;
-2
END ELSE 0$;
MACRO NEXTFORMDESC=
IF (FNO_.FNO+1) GTR .LNKG[LNKGSIZEF]
THEN FT_STACKPARM
ELSE (FT_.LNKG[PARMTYPE(.FNO)];
FL_.LNKG[PARMLOC(.FNO)])$;
REGISTER STVEC T:LNKG:FORMAL,LNKT;
LOCAL FT,FL,FNO,LSF,NP;
EXTERNAL LIFOENTER; ! FROM LSTPKG
NP_LSF_FNO_0;
LNKG_.RNAME[LNKGNMF];
LNKT_.LNKG[LNKGTF];
LNKG_.LNKG[LNKGDESCF];
RNAME[REGFORMLST]_MAKHDR(0,LIFOENTER);
IF .DEL EQL HPARAOPEN
THEN BEGIN
WHILE .DEL NEQ HPARACLOSE DO
BEGIN
RUND(QLQNAME);
IF NOT DECLARESYM(FORMAL,FORMALT,0)
THEN EXITCOMPOUND;
NP_.NP+1;
DEFASYM(.FORMAL,2,0,16);
FORMAL[STRUORIACT]_.STRUDEFV;
FORMAL[HAVNOACTS]_1;
NEXTFORMDESC;
CASE .FT OF
SET
! 0: STACK
BEGIN
FORMAL[OFFSETF]_.LSF;
LSF_.FORMAL;
FORMAL[REGF]_SP;
FORMAL[MODE]_INDEXED
END;
! 1: REGISTER
BEGIN
FORMAL[MODE]_GENREG;
FORMAL[SREGF]_.FL;
T_FORMAL[REGF]_GETTN();
T[LDF]_.LOOPDEPTH;
T[LONFU]_T[LONLU]_T[FONFU]_T[FONLU]_1; ! SPAN MUST START AT 1
ENLST(.RNAME[REGFORMLST],MAKITEM(.FL^18+.FORMAL<ADDRF>,1))
END;
! 2: (LITERAL) MEMORY
BEGIN
FORMAL[TYPEF]_MBINDT;
FORMAL[BINDLEXF]_LITLEXEME(.FL)
END;
! 3: (NAMED) MEMORY
BEGIN
FORMAL[TYPEF]_MBINDT;
FORMAL[BINDLEXF]_LEXOUT(BNDVAR,.FL)
END
TES;
FORMAL[NOUPLEVEL]_TRUE;
IF .DEL NEQ HPARACLOSE AND .DEL NEQ HCOMMA
THEN (ERROR(.LOBRAC,.NDEL,.LASTEND,DCLDELERR); RETURN 0);
INITSYMLSTS(.FORMAL);
END;
END;
FNO_OLDPCPS;
WHILE .LSF NEQ 0 DO
BEGIN
FORMAL_.LSF;
LSF_.FORMAL[OFFSETF];
FORMAL[OFFSETF]_FNO_.FNO+2;
IF ONEOF(.LNKT,BIT2(HBLISLNKGT,IHBLISLNKGT))
THEN FORMAL[OFFSETF]_.FORMAL[OFFSETF]+8;
END;
RNAME[RNPARMSF]_.NP;
IF .DEL EQL HPARACLOSE THEN RUNDE();
RETURN 1
END;
ROUTINE GLOBROUT=
DO
BEGIN
LOCAL STVEC SENTRY:LNKGNM;
RUND(QLQNAME);
GETLNKG(LNKGNM);
CKFORWD(GROUTINET);
DEFMAP(.SENTRY);
SENTRY[LNKGNMF]_.LNKGNM;
SENTRY[REGF]_PC;
SENTRY[MODE]_ABSOLUTE;
RNAMEFOLLOWS(.SENTRY);
END
WHILE .DEL EQL HCOMMA;
! GENERAL DECLARATION ROUTINES
! ----------------------------
!
!SYNTAX: <DELTYPE> <NAMESPEC1>,...,<NAMESPECN>
!
! <NAMESPEC> ::=<STRUCSPEC> <NAMSZ1>...:<NAMSZK>
! <STRUCSPEC>::=/<STRUCTURE NAME>
! <NAMSZ> ::=<NAME1>:...:<NAMEM><SIZE><EQSPEC>
! <SIZE> ::=/[<SIZE1>,...,<SIZEL>]
! <EQSPEC> ::=/ = <EXPRESSION>
!
!I. GENERAL:
!
! 1. THE FOLLOWING SEVEN(7) ROUTINES, (SLOCAL,
! SOWN,SGLOBAL,SEXTERNAL,SREGISTER,SBIND,SMAP), ARE ALL
! ROUTINES WHICH DECLARE THE LIST OF IDENTIFIERS
! AS THE TYPE WHICH THEIR NAME IMPLIES.
!
! 2. THEY ARE ALL OF THE SAME FORM, IE THEY ALL CALL
! "GROMLIST" WITH THE FOLLOWING PARAMETERS:
!
! A. #1 - TYPE WHICH SYMBOLS SHOULD BE DECLARED
! AS. NOTE THAT "MAP" HAS NO TYPE
! ASSOCIATED WITH IT.
!
! B. #2 - A POINTER TO A VARIABLE WHICH CONTAINS
! THE TOTAL NUMBER OF VARIABLES OF THAT
! TYPE DECLARED SO FAR. FOR LOCALS, ONLY
! THE DIFFERENCE BETWEEN THAT NUMBER ON
! ENTRANCE AND EXIT OF A BLOCK IS OF
! INTEREST, BU FOR OWNS AND GLOBALS,
! THE TOTAL NUMBER IS NECESSARY, SINCE
! THATS HOW MUCH SPACE SHOULD BE ALLOCATED.
!
! C. #3 - NAME OF A ROUTINE TO HANDLE THE
! PECULIARITIES DUE TO A SPECIFIC
! TYPE OF DECLARATION.
!
! D. #4 - ROUTINE TO HANDLE AN EQUAL SIGN ("=")
! FOLLOWING A NAME (TO BE BOUND).
!
! E. #5 - ROUTINE TO HANDLE "_" AFTER A NAME.
ROUTINE SLOCAL=GROMLIST(LOCALT,0,PLOCAL,0,0);
ROUTINE SSTACKLOCAL=GROMLIST(LOCALT,0,PSTACKLOCAL,0,0);
ROUTINE SOWN=GROMLIST(OWNT,0,POWN,OWNEQ,0);
ROUTINE SGLOBAL=(RUND(QLQNAME);
IF .SYM EQL HEMPTY
THEN SELECT .DEL[HSYNTYP] OF
NSET
DCLROU: RETURN GLOBROUT();
DCLBIN: RETURN SGLOBBIND();
TESN;
PEEKBIT_TRUE;
GROMLIST(GLOBALT,0,PGLOBAL,GLOBALEQ,0));
ROUTINE SEXTERNAL=GROMLIST(EXTERNALT,0,PEXTERNAL,0,0);
ROUTINE SDCLLABEL=GROMLIST(LABELT,0,PLABEL,0,0);
ROUTINE SREGISTER= GROMLIST(REGT,0,PREGISTER,REGEQ,0) ;
ROUTINE SGLOBBIND=GROMLIST(MBINDT,0,PGLOBBIND,-GLBINDEQ<0,0>,0);
ROUTINE SBIND=GROMLIST(MBINDT,0,PBIND,-BINDEQ<0,0>,0);
ROUTINE SROUTINE=
DO
BEGIN
LOCAL STVEC SENTRY:LNKGNM;
RUND(QLQNAME);
GETLNKG(LNKGNM);
CKFORWD(ROUTINET);
DEFMAP(.SENTRY);
SENTRY[LNKGNMF] _ .LNKGNM;
SENTRY[REGF]_PC;
SENTRY[MODE]_IF .PICSW THEN RELATIVE ELSE ABSOLUTE;
RNAMEFOLLOWS(.SENTRY);
END
WHILE .DEL EQL HCOMMA;
ROUTINE SMAP=GROMLIST(0,0,0,0,0);
ROUTINE SSETSIZE(N)=
BEGIN
DECLSIZE_.N; RUND(QLLEXEME);
IF .SYM NEQ HEMPTY THEN RETURN ERROR(.LOBRAC,.NSYM,.LASTEND,DECLSYMERR);
IF .DEL[HCLASS] NEQ DCLRTR
THEN RETURN ERROR(.LOBRAC,.NDEL,.LASTEND,ERRBYTEFOL);
SXCTDECL;
DECLSIZE_2;
END;
ROUTINE SBYTE=SSETSIZE(1);
ROUTINE SWORD=SSETSIZE(2);
GLOBAL ROUTINE INCRDECRREG=
!I. GENERAL:
!
! 1. THIS ROUTINE IS USED TO DECLARE A REGISTER FOR THE
! INDEX OF AN "INCR" OR "DECR" LOOP EXPRESSION.
!
!II. SPECIFIC:
!
! 1. *
!
! A. OPEN A NEW BLOCK.
!
! B. SET DECLARATION FLAGS.
!
! C. DECLARE THE REGISTER, AND RETURN IF
! THERE ARE ANY ERRORS.
!
! D. DO THINGS UNIQUE TO REGISTER DECLARATION.
BEGIN
LOCAL STVEC REGSTE;
BLOCKLEVEL_.BLOCKLEVEL+1;
OFLAGS_0;
OFLAGS[MUSTDECLARE]_1;
RUND(QLQNAME);
IF NOT DECLARESYM(REGSTE,LOCALT,1)
THEN RETURN 0;
PLOCAL(0,2,.REGSTE);
REGSTE[POSF]_0;
REGSTE[SIZEF]_16;
RETURN 1;
END;
ROUTINE SSWITCHES=
BEGIN
LOCAL LOBRAC;
LOBRAC_.NDEL;
SWITCHER(SWSWL);
DELERR(NEQ HSEMICOLON,DCLDELERR);
END;
GLOBAL ROUTINE DOMODULE=
BEGIN
MAP NTVEC SYM;
EXTERNAL FLOWINIT;
ROUTINE DCLMODNAME =
!
! DECLARE MODULE NAME AS A GLOBAL ROUTINE.
! A CALL ON THIS MUST BE PAIRED, OF COURSE, WITH
! A LATER CALL ON BLOCKPURGE.
!
BEGIN
LOCAL NTVEC NAME;
BLOCKLEVEL_.BLOCKLEVEL+1;
ACCUM[0]_.MODNAME[0]; ACCUM[1]_.MODNAME[1];
NAME_SEARCH(UNDECTYPE);
STE_STINSERT(.NAME,GROUTINET,0);
LNKGLX_.DFLTLNKGLX;
DEFASYM(.STE,2,0,16);
DEFGLO(.STE,FALSE,0,0);
NOVALUE
END;
FLOWINIT();
IF .DEL EQL HMODULE
THEN
BEGIN
IF .SYM NEQ HEMPTY THEN %%%%%%;
RUND(QLQNAME);
IF .SYM NEQ HEMPTY THEN (MODNAME[0]_.SYM[ACCUM1];
MODNAME[1]_.SYM[ACCUM2];
CSNAME_.MODNAME; CSFLAG_-1;
SYM_HEMPTY);
IF .DEL EQL HPARAOPEN THEN
BEGIN
SWITCHER(ALLSW);
IF .DEL NEQ HPARACLOSE THEN EXITCOMPOUND;
RUND(QLLEXEME);
END;
IF .DEL NEQ HEQUAL OR .SYM NEQ HEMPTY
THEN BEGIN
UNTIL .DEL EQL HBEGIN DO RUND(QLLEXEME);
WARNEM(.NDEL,WABADMOD);
END
ELSE RUND(QLLEXEME);
DCLMODNAME();
EXPRESSION();
IF .DEL NEQ HELUDOM THEN WARNEM(0,WAMODDOM);
BLOCKPURGE();
END
ELSE
(EXPRESSION();
IF .DEL EQL HELUDOM THEN WARNEM(.NDEL,WAMODDOM));
GETNCSE();
NOVALUE
END;
ROUTINE GETCONS=
BEGIN
IF .DEL EQL HPARACLOSE
THEN SYM_ZERO
ELSE (RUND(QLLEXEME);
IF .SYM EQL HEMPTY THEN SYM_ZERO);
.SYM[LTYPF] EQL LITTYP
AND (.DEL EQL HCOMMA OR .DEL EQL HPARACLOSE)
END;
ROUTINE GETSTRING=
BEGIN
RUND(QLLSLEX);
IF .SYM EQL HEMPTY THEN SYM_ZERO;
(.SYM[LTYPF] EQL LSLEXTYP OR .SYM[LTYPF] EQL LITTYP)
AND (.DEL EQL HCOMMA OR .DEL EQL HPARACLOSE)
END;
ROUTINE SWITCHER(HIGH)=
!I. GENERAL
!
! 1. THIS ROUTINE IS USED TO PROCESS A LIST OF SWITCHES
! SEPARATED BY COMMAS.
!
! 2. THE PARAMETER IS THE INDEX INTO THE PLIT SWTBL
! OF THE LAST SWITCH WHICH IS CONSIDERED VALID IN
! THE CURRENT CONTEXT.
BEGIN
MACRO SYCHK(X)=IF X THEN WARNEM(.LOBRAC,WASWSYN)$;
MAP NTVEC SYM;
LOCAL LOBRAC;
REGISTER X;
LOBRAC_.NDEL;
DO
BEGIN
RUND(QLQNAME); !SWITCH NAME NOW IN SYM
X_.SYM[ACCUM1];
X_INCR I FROM 0 TO .HIGH DO IF .X EQL .SWTBL[.I] THEN EXITLOOP .I;
CASE 1+.X OF
SET
WARNEM(.LOBRAC,WASWNONX); !WARNING, NOT FOUND
EMFLG_1; ! EXPAND MACRO
EMFLG_0; ! DON'T EXPAND MACRO
LSTFLG_0; ! LIST
LSTFLG_1; ! NO LIST
ERRBIT_0; ! ERR MSGS TO TTY
ERRBIT_1; ! NO ERR MSGS TO TTY
MLFLG_1; ! MACH LIST
MLFLG_0; ! NO MACH LIST
NPTFLG_0; ! OPTIMIZE
NPTFLG_1; ! NO-OPTIMIZE
UNAMESW_1; ! GENERATE UNIQUE NAMES
UNAMESW_0; ! DO NOT GENERATE UNIQUE NAMES
FINALSW_1; ! DO FINAL PEEPHOLE OPTIMIZATION
FINALSW_0; ! DO NOT DO FINAL PEEPHOLE OPTIMIZATION
MRKFLG_0; ! TURN ON UNCERTAIN OPTIMIZATIONS
MRKFLG_1; ! TURN OFF " "
ZIPSW_1; ! CHOOSE SPEED OVER TIME
ZIPSW_0; ! CHOOSE TIME OVER SPEED
DEBFLG_1; ! GENERATE SIX12 SYMBOL & NAME TABLES
DEBFLG_0; ! DO NOT DO ABOVE
PICSW_1; ! POSITION INDEPENDENT CODE
PICSW_0; ! NO POSITION INDEPENDENT CODE
SEGSW_1; ! NO DATA ALLOWED IN CODE CSECT
SEGSW_0; ! DATA (CASE STMT. TABLES, OFFSET
! FOR $ENABL) ALLOWED IN CODE CSECT
SYCHK(SSTART()); ! STARTING ADDRESS DECLARATION
SSTACK(DEFAULTSSTK); ! STACK DECLARATION
SYCHK(SMAIN()); ! MAIN DECLARATION
SYCHK(SRESERVE()); ! RESERVE SPECIFIC REGS.
SYCHK(SIDENT()); ! IDENT
NOTREE_-1 ! SYNTAX CHECK ONLY
TES;
END
UNTIL .DEL NEQ HCOMMA;
0 END;
ROUTINE SIDENT=
BEGIN
IF .DEL NEQ HEQUAL THEN RETURN 1;
IF GETSTRING() THEN (IDENTLEX_.SYM;IDENTFLG_1;RETURN 0);
RETURN 1
END;
ROUTINE SSTACK(X)=
BEGIN
MODMAIN[0]_.MODNAME[0];
MODMAIN[1]_.MODNAME[1];
SSTKLEN_.X;
MAINDECL_TRUE;
END;
ROUTINE SMAIN=
BEGIN
SSTACK(0);
IF .DEL EQL HCOMMA OR .DEL EQL HPARACLOSE THEN RETURN 0;
IF .DEL NEQ HPARAOPEN THEN RETURN 1;
IF NOT GETCONS() THEN RETURN 1;
SSTKLEN_LITVALUE(.SYM[ADDRF]);
IF .DEL NEQ HPARACLOSE THEN RETURN 1;
RUND(QLLEXEME);
IF .SYM NEQ HEMPTY THEN RETURN 1;
RETURN 0;
END;
ROUTINE SSTART=
BEGIN
BIND STVEC STSYM=SYM;
IF .DEL NEQ HEQUAL THEN RETURN 1;
RUND(QLQNAME);
IF .SYM[LTYPF] NEQ UNBNDVAR
OR (.DEL NEQ HCOMMA AND .DEL NEQ HPARACLOSE)
THEN RETURN 1;
MODMAIN[0]_.STSYM[ACCUM1];
MODMAIN[1]_.STSYM[ACCUM2];
RETURN 0;
END;
ROUTINE SRESERVE=
BEGIN
LABEL NEXT;
IF .DEL NEQ HPARAOPEN THEN RETURN 1;
DO NEXT:BEGIN
IF NOT GETCONS() THEN RETURN 1;
SYM_EXTEND(LITVALUE(.SYM));
IF .SYM LSS 1 OR .SYM GTR 5
THEN (WARNEM(.NSYM,WACANTRES); LEAVE NEXT);
RESERVED[.SYM,1]_TRUE
END
UNTIL .DEL NEQ HCOMMA;
RUND(QLLEXEME);
IF .SYM NEQ HEMPTY THEN RETURN 1;
RETURN 0
END;
ROUTINE PPARAM(TYP,INITOFF,RBRACK)=
BEGIN
LOCAL STVEC PARAM, OFFST;
OFFST_.INITOFF;
RUND(QLQNAME);
IF .SYM EQL HEMPTY AND .DEL EQL .RBRACK THEN (RUNDE(); RETURN 0);
DO (IF DECLARESYM(PARAM,.TYP,0)
THEN (PARAM[WHICHF]_.OFFST; OFFST_.OFFST+1))
WHILE (IF .DEL EQL HCOMMA THEN (RUND(QLQNAME); 1));
DELERR(NEQ .RBRACK,ERSMSQBCLOSE);
RUNDE();
.OFFST-.INITOFF
END;
ROUTINE SSTRUCTURE=
DO
BEGIN
LOCAL SAVENME;
RUND(QLQNAME);
SAVENME_.SYM[ADDRF];
IF NOT DECLARESYM(STRUDEF,STRUCTURET,1) THEN RETURN;
IF .SAVENME EQL .STRUDVNME THEN STRUDEFV_.STRUDEF;
BLOCKLEVEL_.BLOCKLEVEL+1;
IF NOT .STRUCP THEN STRUCLEVEL_.BLOCKLEVEL;
NINP_STRUDEF[NUMPARM]_IF .DEL EQL HSQBOPEN THEN
PPARAM(STRUFT,3,HSQBCLOSE);
DELERR(NEQ HEQUAL, ERMEQ);
RUND(QLLEXEME);
STRUDEF[SIZESTRM]_
IF .SYM EQL HEMPTY AND .DEL EQL HSQBOPEN
THEN
BEGIN
LOCAL STREAM;
RUND(QLLEXEME);
STREAM_STRUSC(1);
DELERR(NEQ HSQBCLOSE, ERSMSQBCLOSE);
DEL_HEQUAL; !HIDE THE SPECIAL USE OF [] FROM LEXAN
RUND(QLLEXEME);
.STREAM
END;
STRUDEF[BODYSTRM]_STRUSC(0);
IF NOT .STRUCP THEN STRUCLEVEL_#777777;
IF .DEL EQL HCOMMA THEN FSYMPROTECT();
BLOCKPURGE()
END
WHILE .DEL EQL HCOMMA;
ROUTINE SMACRO=
DO
BEGIN
LOCAL SUBTYP, QUIT, SAVCOPY;
MACRO CHKPL(LB,RB,DEF,INITOFF,ZER,NONZER)=
IF .DEL EQL LB THEN SUBTYP_.SUBTYP+
(IF (DEF_PPARAM(MACRFT,INITOFF,RB)) EQL 0 THEN ZER ELSE NONZER)$;
RUND(QLQNAME);
IF NOT DECLARESYM(MACRDEF,MACROT,1) THEN RETURN;
BLOCKLEVEL_.BLOCKLEVEL+1;
MACRDEF[NUMFIXED]_MACRDEF[NUMITED]_SUBTYP_0;
CHKPL(HPARAOPEN,HPARACLOSE,MACRDEF[NUMFIXED],1,0,MACRFIND);
CHKPL(HSQBOPEN,HSQBCLOSE,MACRDEF[NUMITED],.MACRDEF[NUMFIXED]+1,MACRRIND,MACRIIND);
BLOCKLEVEL_.BLOCKLEVEL-1;
MACRDEF[SUBTYPEM]_.SUBTYP;
DELERR(NEQ HEQUAL, ERMEQ);
% SEE ALSO STRUSC AND STRUCOPY %
SAVCOPY_.MACRCP;
MACRCP_TRUE;
SCANTYPE_"M";
SCANCHANGE_.NDEL;
QUIT_FALSE;
UNTIL .QUIT DO
BEGIN
RUND(QLMACR);
UNLESSQUOTED(SYM)
IF .SYM[LTYPF] EQL UNBNDVAR
THEN IF .ST[.NT[.SYM[ADDRF],SYMLINK],TYPEF] EQL MACRFT
THEN (SYM[LTYPF]_CLMACRF;
SYM[ADDRF]_.ST[.NT[.SYM[ADDRF],SYMLINK],WHICHF]);
UNLESSQUOTED(DEL)
IF .DEL EQL "$" THEN
IF .SYM EQL HEMPTY THEN EXITLOOP ELSE (DEL_0; QUIT_TRUE);
STRMAPPEND(WSTBUF,WSTMAX-1)_FORMWINDOW(.SYM,.DEL)
END;
MACRDEF[STREAMF]_STRMQUIT(WSTBUF);
BLOCKLEVEL_.BLOCKLEVEL+1;
BLOCKPURGE();
SCANTYPE_" ";
MACRCP_.SAVCOPY;
IF RUNDE() THEN RETURN;
END
WHILE .DEL EQL HCOMMA;
MACRO RUNSC=UNTIL .DEL EQL HSEMICOLON DO RUND(QLLEXEME)$,
KWCHK=IF NOT GETSTRING2() THEN(WARNEM(.LOBRAC,WBADCSECT);RUNSC;RETURN)$;
ROUTINE GETSTRING2=
BEGIN
RUND(QLLSLEX);
IF .SYM EQL HEMPTY THEN SYM_ZERO;
(.SYM[LTYPF] EQL LSLEXTYP OR .SYM[LTYPF] EQL LITTYP) AND
(.DEL EQL HCOMMA OR .DEL EQL HSEMICOLON)
END;
ROUTINE SCSECT=
BEGIN
MAP STVEC SYM;
LOCAL X,Y,Z,FLG,LOBRAC;
LOBRAC_.NDEL;
Y_0;
IF .DEL EQL HCSECT THEN FLG_1 ELSE FLG_2;
DO
BEGIN
RUND(QLQNAME);
Y_.Y+1;
IF .SYM EQL HEMPTY
THEN (Z_SELECT .DEL OF
NSET
HOWN : BS(3,OWN);
HGLOBAL : BL(GLOBA);
HPLIT : BS(4,PLIT);
OTHERWISE : 0
TESN;
RUND(QLLEXEME);
IF .DEL NEQ HEQUAL THEN (WARNEM(.LOBRAC,WBADCSECT);RUNSC;RETURN))
ELSE Z_.SYM[ACCUM1];
X_INCR I FROM 0 TO .KWTBL[-1]-1 DO
IF .Z EQL .KWTBL[.I] THEN EXITLOOP .I;
IF .X LSS 0 THEN
BEGIN
IF (.DEL EQL HSEMICOLON) AND (.Y EQL 1)
THEN (CSNAME_.Z;
CSFLG_.FLG;
CSFLAG_-1)
ELSE (WARNEM(.LOBRAC,WBADCSECT);
RUNSC; RETURN)
END
ELSE
BEGIN
BIND FLGPLIT=PLIT(CSCFLG,CSDFLG,CSGFLG,CSOFLG,CSPFLG),
NAMEPLIT=PLIT(CSCNAME,CSDNAME,CSGNAME,CSONAME,CSPNAME);
KWCHK;
.FLGPLIT[.X]_.FLG;
.NAMEPLIT[.X]_.SYM
END;
END
UNTIL .DEL NEQ HCOMMA;
0
END;
ROUTINE SLNKGDECL=
BEGIN
BIND NP=30;
STRUCTURE V1[I]=(.V1+.I-1)<0,36>;
LOCAL STVEC S:LP, V1 P[NP], N,LT;
MACRO RERR(EN)=RETURN ERROR(.LOBRAC,.NSYM,.LASTEND,(EN))$;
MACRO RERRD(EN)=EXITLOOP ERROR(.LOBRAC,.NSYM,PSPAR,(EN))$;
BIND STVEC SYMST=SYM;
DO BEGIN
LOCAL SAVENME;
N_0; RUND(QLQNAME);
SAVENME_.SYM[ADDRF];
IF NOT DECLARESYM(S,LNKGNMT,1) THEN RETURN;
IF .DEL NEQ HEQUAL THEN RERR(LNKGNOEQUAL);
RUND(QLLEXEME);
IF .SYM[LTYPF] NEQ BNDVAR THEN RERR(LNKGNOTYP) ELSE
IF .SYMST[TYPEF] NEQ LNKGNMT THEN RERR(LNKGNOTYP) ELSE
LT_.SYMST[LNKGTF];
IF .SAVENME EQL .ST[.DFLTLNKGLX,NAMEPTR]
THEN DFLTLNKGLX_LEXOUT(BNDVAR,.S);
IF .DEL EQL HPARAOPEN THEN
WHILE 1 DO
BEGIN
IF (N_.N+1) GTR NP THEN RERRD(LNKGTOOMANYP);
RUND(QLQNAME);
IF .SYM EQL HEMPTY THEN
BEGIN
IF .DEL NEQ HREGISTER THEN RERRD(LNKGINVPARM) ELSE
BEGIN
RUND(QLLEXEME);
IF .DEL NEQ HEQUAL THEN RERRD(LNKGNOEQUAL) ELSE
BEGIN
RUND(QLLEXEME); SYM_BINDBIND(.SYM);
IF (IF .SYM[LTYPF] NEQ LITTYP THEN 1 ELSE
IF (P[.N]_LITVALUE(.SYM)) LSS 0 THEN 1 ELSE
IF .P[.N] GTR 6 THEN 1 ELSE 0)
THEN (WARNEM(.NSYM,LNKGNOTREG); P[.N]_1);
END;
END
END ELSE
IF .SYMST[ACCUM1] EQL 'STACK' THEN P[.N]_-1 ELSE
IF .SYMST[ACCUM1] EQL 'MEMOR' %Y% THEN
BEGIN
LABEL LAB;
IF .DEL NEQ HEQUAL THEN RERRD(LNKGNOEQUAL);
RUND(QLLEXEME); EXPRESSION(); SYM_BINDBIND(.SYM);
LAB: SELECT .SYM[LTYPF] OF
NSET
LITTYP: (P[.N]_.SYM; LEAVE LAB);
BNDVAR: IF LOADCONST(SYM)
THEN (P[.N]_.SYM; LEAVE LAB);
ALWAYS: (WARNEM(.NSYM,LNKGINVPARM); P[.N]_-1)
TESN
END ELSE
RERRD(LNKGINVPARM);
IF .DEL EQL HPARACLOSE THEN EXITLOOP RUND(QLLEXEME) ELSE
IF .DEL NEQ HCOMMA THEN RERRD(LNKGINVSYNTAX);
END;
LP_GETSPACE(ST,.N+1);
LP[LNKGSIZEF]_.N;
WHILE .N GTR 0 DO
BEGIN
LP[PARMTYPE(.N)]_.P[.N]<LEFTPART>+1;
! THE ABOVE RELIES ON LITTYP BEING 1,BNDVAR BEING 2.
LP[PARMLOC(.N)]_.P[.N];
N_.N-1;
END;
S[LNKGTF]_.LT; S[LNKGDESCF]_.LP;
END
UNTIL .DEL NEQ HCOMMA;
END;
%%
% PLIT SYNTAX PROCESSING ROUTINES. THE SYNTAX FOR PLITS IS AS
FOLLOWS:
<PLIT> ::= PLIT <PLITARG>
<PLITARG> ::= <LOAD TIME EXPRESSION> !
<LONG STRING> !
<TUPLE>
<TUPLE> ::= (<TUPLE ITEM LIST>)
<TUPLE ITEM LIST> ::= <TUPLE ITEM> !
<TUPLE ITEM>,<TUPLE ITEM LIST>
<TUPLE ITEM> ::= <LOAD TIME EXPRESSION> !
<LONG STRING> !
<DUPLICATION FACTOR>:<PLITARG>
<DUPLICATION FACTOR> ::= <COMPILE TIME EXPRESSION>
[NOTE: <LOAD TIME EXPRESSION> ::= <PLIT> ! ...]
%
%%
BIND PLNEXT=NEXTGLOBAL;
GLOBAL ROUTINE SPLIT=
BEGIN
MACRO MAKENEWNAME=
(PLHEAD_.PLHEAD+2;
IF .PLHEAD<1,7> EQL "[" THEN (PLHEAD<1,7>_"A";
IF (PLHEAD<8,7>_.PLHEAD<8,7>+1) EQL "[" THEN
(PLHEAD<8,7>_"A"; PLHEAD<15,7>_.PLHEAD<15,7>+1));
ACCUM[0]_.PLHEAD; ACCUM[1]_-2)$;
LOCAL PLITLEN, STVEC STE, PLITP, ISCOUNTED;
ISCOUNTED_(.DEL EQL HPLIT);
MAKENEWNAME;
STE_.NT[SEARCH(GLOBALT),SYMLINK];
PLITLEN_SPLITB(PLITP);
DEFASYM(.STE,2*.PLITLEN,0,16);
DEFMAP(.STE);
STE[ITSAPLIT]_TRUE;
STE[COUNTED]_.ISCOUNTED;
DEFGLO(.STE,TRUE,TRUE,.PLITP);
SYM_LEXOUT(BNDVAR,.STE)
END;
GLOBAL ROUTINE SPLITB(GLOSTE) =
BEGIN
MAP STVEC GLOSTE;
LOCAL STVEC TEMPHEAD:NEXTCELL:FIRSTCELL, OFFST, SLBRAC;
SLBRAC_.PLLBRAC; PLLBRAC_.NDEL;
TEMPHEAD_GETCELL(CHTPLIT,1);
INAPLIT_TRUE;
OFFST_PLITARG(.TEMPHEAD);
INAPLIT_FALSE;
TEMPHEAD[LSLENGTH]_.OFFST;
.GLOSTE_.TEMPHEAD;
PLLBRAC_.SLBRAC;
.OFFST
END;
ROUTINE PLITARG(HEAD) =
BEGIN
RUND(QLLSLEX);
IF .SYM NEQ HEMPTY OR
(.DEL NEQ HPARAOPEN AND .DEL NEQ HCOMPOPEN)
THEN RETURN LSORLE(.HEAD);
BEGIN
LOCAL LENTH, SLBRAC, SAVEL;
NEWLASTEND(PSPARCOM);
SLBRAC_.PLLBRAC; PLLBRAC_.NDEL;
LENTH_0;
DO (RUND(QLLSLEX); LENTH_.LENTH+TUPLEITEM(.HEAD))
WHILE .DEL EQL HCOMMA;
RESLASTEND;
IF .DEL NEQ HPARACLOSE
THEN RETURN ERROR(.PLLBRAC,.NDEL,.LASTEND,ERSYPLMRP);
RUNDE();
PLLBRAC_.SLBRAC;
.LENTH
END
END;
ROUTINE TUPLEITEM(HEAD) =
BEGIN
EXPRESSION();
IF .DEL EQL HCOLON
THEN
BEGIN
LOCAL LEN, STVEC NEWHEAD;
SYM_BINDBIND(.SYM);
IF NOT LITRESULT THEN (ERROR(.PLLBRAC,.NSYM,0,ERSMPLNLI);
SYM_LITLEXEME(1));
NEWHEAD_GETCELL(CHTDUP,1);
NEWHEAD[DUPLENGTH]_LEN_LITVALUE(.SYM[ADDRF]);
PUSHBOT(.HEAD,.NEWHEAD);
.LEN*PLITARG(.NEWHEAD)
END
ELSE LSORLE(.HEAD)
END;
ROUTINE LSORLE(HEAD)=
BEGIN
IF .SYM[LTYPF] EQL LSLEXTYP
THEN
BEGIN
MAP STVEC SYM;
LEXTOP(.HEAD,.SYM);
RETURN .SYM[LSLENGTH]
END
ELSE
BEGIN
CASE WHICHBIND() OF
SET
(WARNEM(.NSYM,ERSMPLNLO); SYM_ZERO);
;
(IF .SYM[LTYPF] EQL BNDVAR
THEN IF LOADCONST(SYM)
THEN EXITCASE;
WARNEM(.NSYM,ERSMPLNLO);
SYM_ZERO)
TES;
RETURN LEXTOP(.HEAD,.SYM)
END
END;
ROUTINE LEXTOP(HEAD,LEX) =
BEGIN
LOCAL STVEC CELL;
CELL_GETCELL(CHTLEX,1);
CELL[LEXEMEF]_.SYM;
PUSHBOT(.HEAD,.CELL);
1
END;
! THESE ROUTINES HANDLE THE "REQUIRE" DECLARATION
! VERY MACHINE DEPENDENT.
ROUTINE SREQUIRE=
BEGIN
LOCAL DEVICE;
REGISTER N;
EXTERNAL SCANFOR,FILESELECT,RLS;
MACRO
FILE=BUFDATA[.CURCHN+1,FILENAMEF]$,
EXT=BUFDATA[.CURCHN+1,EXTF]$,
PPN=BUFDATA[.CURCHN+1,PPNF]$,
THISPPN=BUFDATA[.CURCHN,PPNF]$;
BIND CMUDEC=-2;
MACRO
FUTSYM=SYMPART(.FUTWINDOW)<0,36>$,
FUTDEL=DT[.FUTWINDOW[DELIND]]$,
SCANSYM=SCANFOR(1,QLQNAME)$,
SCANDEL=(SCANFOR(0,QLQNAME); DEL_.DT[.DEL])$,
LITP(X)=X[LTYPF] EQL LITTYP$,
LITV(X)=LITVALUE(X)$,
ABORT(NUM)=RETURN (RLS(.CURCHN+1); ERROR(.LOBRAC,.NDEL,PSSEM,NUM))$;
ROUTINE JRUND=(SCANDEL; SCANSYM);
ROUTINE CVSIX=
BEGIN LOCAL SYMPTR,SIXPTR,SIXSYM; REGISTER R; MACHOP ILDB=#134,IDPB=#136;
SIXSYM_0;
SYMPTR_NT[.SYM,0,36,7];
SIXPTR_SIXSYM<36,6>;
DECR I FROM 5 TO 0 DO
(ILDB(R,SYMPTR);
IF .R EQL #177 THEN EXITLOOP;
IF .R LEQ #132 THEN R_.R-#40;
IDPB(R,SIXPTR) );
.SIXSYM
END;
EXTERNAL SKAN1;
FILE_EXT_PPN_0;
SCANSYM;
DEVICE_IF .FUTDEL EQL HCOLON THEN (N_CVSIX(); JRUND(); .N) ELSE SIXBIT 'DSK ';
IF NOT (N_REQUINIT(.DEVICE)) THEN RETURN
ERROR(.LOBRAC,.NDEL,PSSEM,(IF .N EQL 0
THEN ERREQDEV
ELSE ERREQNEST));
FILE_CVSIX();
IF .FUTDEL EQL HDOT THEN (JRUND(); EXT_(CVSIX())^(-18));
IF .FUTDEL EQL HSQBOPEN
THEN
BEGIN
JRUND();
IF .FUTDEL EQL HSQBCLOSE
THEN (IF .SYM EQL HEMPTY THEN (PPN_.THISPPN; SYM_ZERO))
ELSE
IF .FUTDEL EQL HCOMMA THEN
(IF NOT LITP(.SYM) THEN ABORT(ERREQDPPN);
PPN<18,18>_LITV(.SYM);
JRUND());
IF .FUTDEL NEQ HSQBCLOSE THEN ABORT(ERREQDPPN);
IF LITP(.SYM) THEN (IF (PPN_.PPN OR LITV(.SYM)) EQL 0 THEN PPN_.THISPPN)
ELSE
BEGIN
N<RIGHTPART>_NT[.SYM,0,0,0];
N<LEFTPART>_PPN<0,0>;
IF NOT SKIP(CALLI(N,CMUDEC)) THEN ABORT(ERREQCPPN);
END;
JRUND()
END;
IF NOT LKUP(.CURCHN+1) THEN ABORT(ERREQFIND);
CURCHN_.CURCHN+1;
SKAN1(); !FORCE EOL AND GET NEW LINE FROM REQUIRED FILE
SEQNUM_' '; ! BLANK OUT SEQNUM FIELD FOR NEW FILE
SCANDEL
END; !OF SREQUIRE
ROUTINE REQUINIT(DEVICE)=
BEGIN
REGISTER N;
EXTERNAL OPN;
MACRO
DEVCHR=4$,
INPUTF=19,1$,
ASCIIMF=0,1$,
STATUS=OPENBLOCK[0]$,
ODEV=OPENBLOCK[1]$,
BUFW=OPENBLOCK[2]$;
N_.DEVICE;
CALLI(N,DEVCHR);
IF .N EQL 0 THEN RETURN 0;
IF NOT .N<INPUTF> THEN RETURN 0;
IF NOT .N<ASCIIMF> THEN RETURN 0;
IF (.CURCHN+1) GTR #17 THEN RETURN 2;
OPN(.CURCHN+1,.DEVICE,1,2)
END; !OF REQUINIT
END;
END ELUDOM