Trailing-Edge
-
PDP-10 Archives
-
BB-4157F-BM_1983
-
fortran/compiler/sta2.bli
There are 26 other files named sta2.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) DIGITAL EQUIPMENT CORPORATION 1972, 1983
!AUTHOR: F.J. INFANTE, D. B. TOLMAN/DCE/SJW/EGM/CKS/AHM/TFV
MODULE STA2(RESERVE(0,1,2,3),SREG=#17,FREG=#16,VREG=#15,DREGS=4,GLOROUTINES)=
BEGIN
GLOBAL BIND STA2V = 7^24 + 0^18 + #1704; ! Version Date: 21-Dec-82
%(
***** Begin Revision History *****
36 ----- ----- ADD THE INCLUDE STATEMENT SEMANTICS ROUTINE
37 ----- ----- ALLOW LITSTRINGS IN THE PARAMETER STATEMENT
38 ----- ----- FIX REAL*8 X*4 SO IT WORKS
ALLOW SIGNED CONSTANTS IN THE PARAMETER STATEMENT
39 ----- ----- THE "CLEVER" WAY OF DEALING WITH THE LOOKUP
SKIP RETURN WAS OPTIMIZED AWAY BY 5(122)
SO WE MUST NOT BE SO CLEVER THIS TIME
40 ----- ----- FIX UP INCLUDE A LITTLE
41 320 16787 CATCH COMMON STATEMENTS LIKE /X/A(5)B(5) AS ERRORS, (JNT)
42 402 18917 RESTORE FLAGS CORRECTLY AFTER INCLUDE FILE, (DCE)
43 467 VER5 REQUIRE FTTENX.REQ ,(SJW)
44 533 21796 FIX OUTPUT BUFFER PTR FOR INCLUDE FILE TO BE 0., (DCE)
45 540 22096 ICE CAUSED BY BAD COMMON DECLARATION, (DCE)
***** Begin Version 5B *****
46 722 28072 ADD /NOCREF TO INCLUDE FILE PROCESSING, (DCE)
47 755 13884 Allow lower case for INCLUDE/NOLIST/NOCREF under TENEX,
(EGM)
***** Begin version 6 *****
48 1000 EGM 27-Jun-80 10-29620
Flag error if no name is given on PROGRAM statement
***** Begin Version 7 *****
49 1213 TFV 6-May-81 ------
Modify ASTER to handle CHARACTER*(*), CHARACTER*n, and CHARACTER*(n).
The length for character data gets put on the stack. Fix TYPDECLARE
to handle CHARACTER decl's. Add CHARSTA the CHARACTER decl semantic
routine. Move ACTLDATYPE and CHDLEN to GLOBAL.BLI. Add a second
argument to FUNCGEN to distinguish 'datatype FUNCTION ...' from
'FUNCTION ...'. The first case puts CHLEN on the stack.
50 1214 CKS 1-Jun-81
Prohibit ENTRY statement in range of block IF as well as DO
51 1224 CKS 12-Jun-81
Use "LTLSIZ-1" instead of "2" to free up literal node
52 1232 TFV 24-Jun-81 ------
CHARSTA sets CHDECL flag if a character declaration is seen. Used
in MRP3R and MRP3G to test if we have to scan the symbol table to
generate high seg character descriptors.
53 1256 CKS 8-Sep-81
Modify COMMSTA to read the modified output of SYNTAX for the modified
common statement. The difference is that COMMON // X is returned with
a concatenation lexeme instead of two slashes.
54 1267 AHM 6-Oct-81 ------
Define a stub routine SAVESTA for the SAVE statement so we don't
get undefined symbols when linking.
55 1434 TFV 14-Dec-81 ------
Modify ENTRSTA to handle multi-entry function subprograms.
Character and numeric entry points cannot occur in the same
subprogram. All character entry points must be the same length;
they share the descriptor for the function result. All numeric entry
points are equivalenced using the EQUIVALENCE statement semantic
routine.
56 1466 CDM 1-Feb-82
Added warning for using SAVE statement. Not yet implemented.
1511 CDM 18-March-82
Added code for SAVE statement in SAVESTA.
Added routine LKSVCOMMON for linking common blocks together for
SAVE statement processing.
1527 CKS 9-Apr-82
Rewrite ASTER to allow expressions as length specifiers. Modify
PARASTA to allow expressions in parameter statements.
1531 CDM 4-May-82
Changes for code review of SAVE.
1566 CDM 24-Jun-82
Remove warning for SAVE processing with overlays.
1575 TFV 7-Jul-82
Modify TYPEDECLARE and ASTER to accept 'var * len (subs) * len'.
1646 TFV 18-Oct-82
Fix ASTER to give an error for character lengths less than or
equal to 0.
1656 CKS 25-Oct-82
Modify parameter statement semantic routine PARASTA to do nothing.
It's all handled in action routine PARMASSIGN.
1667 TFV 9-Nov-82
Fix ASTER to give a better found when expecting error for type
declarations.
1704 TFV 21-Dec-82
Fix type declarations to allow optional comma after the optional
*size specifier. The comma is only allowed if the *size is
specified.
***** End Revision History *****
)%
REQUIRE FTTENX.REQ;
SWITCHES NOLIST;
REQUIRE LEXNAM.BLI;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
REQUIRE META72.BLI;
REQUIRE ASHELP.BLI;
SWITCHES LIST;
!THE NUMBER IN COMMENT'S IS THE STATEMENTS LOCATION
!IN THE HASH TABLE .
FORWARD
% 16% SUBRSTA, !SUBROUTINE
% 19% INTESTA, !INTEGER
% 29% LOGISTA, !LOGICAL - P.30
% 51% DIMESTA, !DIMENSION
% 56% DOUBSTA, !DOUBLEPRECISION - P.31
% 64% ENTRSTA, !ENTRY
% 75% BLOCSTA, !BLOCKDATA - P.38
% 81% FUNCSTA, !FUNCTION
% 86% REALSTA, !REAL - P.29
% 93% COMMSTA, !COMMON
% 96% COMPSTA, !COMPLEX - P.32
%121% PROGSTA, !PROGRAM
PARASTA, !PARAMETER STATEMENT
% 13% SAVESTA, ![1267] SAVE STATEMENT
%1511% LKSVCOMMON; ! Links together Common blocks for SAVE processing
EXTERNAL
%1232% CHDECL, ! Flag for character declaration seen
%1527% CNVCONST, ! Convert constant to desired type
CORMAN, ! Routine to get space from free memory
DOIFSTK,
E178, ! Error - character and numeric entry points cannot
! be mixed.
E179, ! Error - character entry points must have the same
! length.
%1531% E192, ! "Illegal in SAVE statement"
ENTRY, ! Parameter for TBLSEARCH
EQUISTA, ! Routine to do semantic processing for EQUIVALENCE
%1511% FATLERR, ! Error routine
FUNCGEN, ! Routine to processes the argument list for an
! ENTRY, FUNCTION or SUBROUTINE statement
NAMDEF,
NAME, ! Parameter for TBLSEARCH
%1511% NUMSAVCOMMON, ! Number of commons to SAVE.
%1531% PTRSAVCOMMON, ! Linked list of commons to SAVE.
SAVSPACE, ! Routine to return space to free memory
%1511% SAVALL, ! SAVE with no arguments specified
%1511% SAVBLC, ! SAVE blank common
%1511% SAVLOC, ! SAVE local variables
%1511% SAVNED, ! SAVE rel block is needed
STK,
TBLSEARCH, ! Routine to lookup a symbol table entry
TYPE,
WARNLEX;
GLOBAL ROUTINE INCLSTA=
BEGIN % INCLUDE STATEMENT%
GLOBAL SVFLG2;
EXTERNAL EOPSVPOOL,POOL,EOPRESTORE;
EXTERNAL LEXICAL,GSTCSCAN,GSTSSCAN,LOOK4CHAR,LEXEMEGEN,GSTEOP;
BIND EOF = #200;
MACHOP LOOKUP = #076, OPEN = #050, JFCL = #255;
OWN TMP;
MACRO DEFAULT = TMP<LEFT>$,
%[722]% NOLST = TMP<0,1>$,
%[722]% NOCRF = TMP<1,1>$;
EXTERNAL SAVFLG;
MACRO PROJNUM = DIRECTORY(ICL)<LEFT>$,
PROGNUM = DIRECTORY(ICL)<RIGHT>$,
ERRORR(X) = RETURN FATLEX(X<0,0>)$;
FORWARD
PPN,PPNUM,SCANFIL,FILSP,SWITCH;
ROUTINE FILSP =
BEGIN IF NOT FTTENEX THEN BEGIN
REGISTER R;
%GET DEVICE OR FILE NAME%
WHILE 1 DO
BEGIN
EXTERNAL E122;
IF (R_SCANFIL()) EQL 0 THEN RETURN 0;
LOOK4CHAR _ ":";
IF LEXICAL(.GSTCSCAN) EQL 0
THEN
BEGIN %FILE NAME%
EXITLOOP
END
ELSE
BEGIN %DEVICE NAME%
IF .DEVICE(ICL) NEQ 0
THEN RETURN FATLEX( SIXBIT'DEVICE', E122<0,0>);
DEVICE(ICL) _ .R
END
END %LOOP% ;
%STORE FILE NAME%
IF .FILENAME(ICL) NEQ 0
THEN RETURN FATLEX( SIXBIT'FILE', E122<0,0>);
FILENAME(ICL) _ .R;
LOOK4CHAR _ ".";
IF LEXICAL(.GSTCSCAN) EQL 0
THEN
BEGIN
%DEFAULT%
DEFAULT _ 1;
(FILENAME(ICL)+1) _ SIXBIT'FOR';
END
ELSE
BEGIN
DEFAULT _ 0;
(FILENAME(ICL)+1) _ SCANFIL()
END;
RETURN 1
END END;
ROUTINE PPN =
BEGIN IF NOT FTTENEX THEN BEGIN %PICK UP THE PPN%
LOOK4CHAR _ "[";
IF LEXICAL (.GSTCSCAN) EQL 0
THEN ( DIRECTORY(ICL) _ 0;
RETURN 0 !NONE
);
IF (PROJNUM _ PPNUM() ) EQL 0
THEN RETURN -1; !ERROR
LOOK4CHAR _ ",";
IF LEXICAL(.GSTCSCAN) EQL 0
THEN RETURN -1; !ERROR
IF ( PROGNUM _ PPNUM() ) EQL 0
THEN RETURN -1; !ERROR
LOOK4CHAR _ "]";
IF LEXICAL(.GSTCSCAN) EQL 0
THEN RETURN -1; !ERROR
RETURN 1 !GOT ONE
END END;
ROUTINE PPNUM =
BEGIN IF NOT FTTENEX THEN BEGIN %GET PPN%
REGISTER NUM,C;
NUM _ 0;
LOOK4CHAR _ "?D";
UNTIL ( C _ LEXICAL(.GSTCSCAN) ) EQL 0
DO NUM _ .NUM*8 + .C -"0";
RETURN .NUM
END END;
ROUTINE SCANFIL =
BEGIN IF NOT FTTENEX THEN BEGIN
%GET FILE NAME%
REGISTER SIX,C;
DECR SHIFT FROM 30 TO 0 BY 6
DO
BEGIN
MACHOP ADDI=#271;
SIX _ .SIX^6;
LOOK4CHAR _ "?L";
IF ( C _ LEXICAL(.GSTCSCAN) ) EQL 0
THEN
BEGIN
LOOK4CHAR _ "?D";
IF ( C_ LEXICAL(.GSTCSCAN)) EQL 0
THEN RETURN SIX_.SIX^.SHIFT;
END;
ADDI(SIX,-" ",C)
END;
WHILE 1 DO
BEGIN %SKIP ANY MORE CHARACTERS%
LOOK4CHAR _ "?L";
IF LEXICAL(.GSTCSCAN) EQL 0
THEN
BEGIN
LOOK4CHAR _ "?D";
IF LEXICAL(.GSTCSCAN) EQL 0
THEN RETURN .SIX
END
END
END END;
ROUTINE SWITCH =
BEGIN IF NOT FTTENEX THEN BEGIN
![722] REWRITE SWITCH PROCESSING TO ALLOW /NOCREF ON INCLUDE STATEMENT
%[722]% % GET /NOLIST OR /NOCREF OR BOTH %
%[722]% LOOK4CHAR_"/";
%[722]%
%[722]% IF LEXICAL(.GSTCSCAN) EQL 0 THEN RETURN 0;
%[722]% DO
%[722]% BEGIN
%[722]%
%[722]% LOOK4CHAR_PLIT'NOLIST'<36,7>;
%[722]% IF LEXICAL(.GSTSSCAN) NEQ 0
%[722]% THEN NOLST_1 !FOUND /NOLIST
%[722]% ELSE !TRY NOCREF
%[722]% BEGIN
%[722]% LOOK4CHAR_PLIT'NOCREF'<36,7>;
%[722]% IF LEXICAL(.GSTSSCAN) NEQ 0
%[722]% THEN NOCRF_1 !FOUND /NOCREF
%[722]% ELSE RETURN -1 !ERROR
%[722]% END;
%[722]% LOOK4CHAR_"/"
%[722]% END UNTIL LEXICAL(.GSTCSCAN) EQL 0;
%[722]%
%[722]% RETURN 1;
END END;
%LETS DO IT%
IF .FLGREG<ININCLUD> THEN RETURN FATLEX(E120<0,0>);
IF NOT FTTENEX THEN
BEGIN
FILENAME(ICL) _ 0;
TMP _ 0;
DIRECTORY(ICL) _ 0;
DEVICE(ICL) _ 0;
%GET THE INITIAL ' %
LOOK4CHAR _ "'";
IF LEXICAL(.GSTCSCAN) EQL 0
THEN
BEGIN
EXTERNAL LEXNAME;
LEXEMEGEN();
RETURN FATLEX(PLIT'''',.LEXNAME[.VREG<LEFT>],E0<0,0>);
END;
BEGIN
LABEL SPEC,LOOP,LOK,CHK;
SPEC:BEGIN
WHILE 1 DO
BEGIN %GET THE SPEC%
LOOP:BEGIN
IF .FILENAME(ICL) EQL 0 OR .DEVICE(ICL) EQL 0
THEN IF FILSP() EQL 1
THEN LEAVE LOOP !FOUND ONE
ELSE IF .VREG LSS 0
THEN RETURN .VREG;
IF .DIRECTORY(ICL) EQL 0
THEN IF PPN() EQL 1
THEN LEAVE LOOP
ELSE IF .VREG LSS 0
THEN ERRORR(E117);
IF SWITCH() LSS 0
THEN ERRORR(E116)
ELSE IF .VREG EQL 1
THEN LEAVE LOOP;
LEAVE SPEC !NOTHING ELSE RECOGNIZABLE
END %LOOP%
END %WHILE 1%
END ; %SPEC%
%GET THE FINAL ' %
LOOK4CHAR _ "'";
IF LEXICAL(.GSTCSCAN) EQL 0
THEN
BEGIN
EXTERNAL LEXNAME;
LEXEMEGEN();
RETURN FATLEX(PLIT'''',.LEXNAME[.VREG<LEFT>],E0<0,0>);
END;
IF LEXEMEGEN() NEQ EOSLEX^18
THEN RETURN NOEOSERRV;
%NOW LETS TRY AND OPEN THE FILE%
IF .DEVICE(ICL) EQL 0
THEN DEVICE(ICL) _ SIXBIT'DSK';
BEGIN %MAKE SURE THAT THE DEVICE IS A DISK%
MACHOP DEVCHR = #047;
EXTERNAL E124;
VREG _ .DEVICE(ICL);
DEVCHR ( VREG,4);
IF NOT .VREG<34,1> %DISK DEVICE%
THEN RETURN FATLERR(.ISN,E124<0,0>)
END;
IF .FILENAME(ICL) EQL 0
THEN ERRORR(E118); !NO FILE NAME
STATUS(ICL) _ 0; !ASCII
BUFFERS(ICL) _ BUFHDR(ICL)<0,0>;
OPEN (ICL, STATUS(ICL));
JFCL(0,0);
LOK:BEGIN
WHILE 1 DO
BEGIN
VREG _ -1;
LOOKUP(ICL,FILENAME(ICL));
VREG _ 0; !FILE NOT FOUND
IF .VREG NEQ 0 THEN LEAVE LOK; !OK FOUND THE FILE
%TRY WITHOUT .FOR %
IF .DEFAULT NEQ 0
THEN
BEGIN
EXTENSION(ICL) _ 0;
DEFAULT _ 0
END
ELSE ERRORR(E119)
END %WHILE 1%
END %LOK%
END;
END
ELSE
BEGIN %FTTENEX%
EXTERNAL OPNICL,E138;
GLOBAL ICLPTR; !FILESPEC POINTER
LOCAL BASE LIT;
EXTERNAL LITPOINTER;
LOCAL LITPNTSAV,VAL;
LITPNTSAV _ .LITPOINTER; !SAVE SO LITERAL CAN BE DELETED
%PICK UP THE LITSTRING SPEC%
LIT _ LEXICAL(.GSTLEXEME);
IF .LIT<LEFT> NEQ LITSTRING
THEN FATLEX(.LEXNAM[LITSTRING],.LEXNAM[.LIT<LEFT>],E0<0,0>);
%CHECK FOR EOS%
IF LEXICAL(.GSTLEXEME ) NEQ EOSLEX^18
THEN RETURN NOEOSERRV;
ICLPTR _ ( LIT[LIT1] )<36,7>; !SPEC POINTER
VAL _ OPNICL(); !OPEN THE FILE
IF .VAL NEQ 0 !WAS THERE AN ERROR
THEN RETURN FATLERR(.VAL,.ISN,E138<0,0>);
%MESSAGE POINTER GIVEN IN VREG%
![722] REWRITE SO THAT /NOCREF ALLOWED ON INCLUDE STATEMENT
%[722]% % OK, GOT IT, NOW LOOK FOR /NOLIST OR /NOCREF %
%[722]%
%[722]% NOLST_0;
%[722]% NOCRF_0;
%[722]%
%[722]% WHILE ..ICLPTR EQL "/"
%[722]% DO
%[722]% BEGIN
%[722]% % SEE WHAT THE SWITCH IS %
%[722]%
%[722]% LABEL CHKLST;
%[722]% LOCAL PNT,SAVICL;
%[755]% REGISTER CHAR;
%[755]% MACRO UPLOW(L) = %( CONVERT LOWER CASE TO UPPER )%
%[755]% BEGIN
%[755]% VREG=L;
%[755]% IF .VREG GEQ #141 %( LOWER CASE A )% AND
%[755]% .VREG LEQ #172 %( LOWER CASE Z )%
%[755]% THEN VREG=.VREG-#40; %( UPPER CASE )%
%[755]% .VREG
%[755]% END$;
%[722]%
%[722]% %TRY /NOLIST %
%[722]% VAL_0; !NOLST NOT FOUND YET ON THIS PASS
%[722]% PNT_(PLIT'NOLIST')<36,7>;
%[722]% SAVICL_.ICLPTR;
%[722]% CHKLST: BEGIN
%[755]% UNTIL (CHAR_SCANI(PNT)) EQL 0
%[755]% DO IF .CHAR NEQ UPLOW(SCANI(ICLPTR))
%[722]% THEN LEAVE CHKLST;
%[722]% NOLST_1; VAL_1; !WE FOUND /NOLIST
%[722]% SCANI(ICLPTR); !BUMP POINTER
%[722]% END;
%[722]%
%[722]% IF .VAL EQL 0 THEN !TRY FOR /NOCREF
%[722]% BEGIN
%[722]% ICLPTR_.SAVICL; !BACK UP THE POINTER
%[722]% PNT_(PLIT'NOCREF')<36,7>;
%[722]%
%[755]% UNTIL (CHAR_SCANI(PNT)) EQL 0
%[722]% DO
%[722]% BEGIN
%[755]% IF .CHAR NEQ UPLOW(SCANI(ICLPTR))
%[722]% THEN ( EXTERNAL CLOICL;
%[722]% FATLEX(E116<0,0>);!BAD SWITCH
%[722]% CLOICL();
%[722]% RETURN )
%[722]% END;
%[722]% NOCRF_1; !WE FOUND /NOCREF
%[722]% SCANI(ICLPTR)
%[722]% END;
%[722]% END;
%FREE UP THE LITERAL%
%[1224]% SAVSPACE( .LIT[LITSIZ]+LTLSIZ-1 , @LIT );
LITPOINTER _ .LITPNTSAV;
IF .LITPOINTER<RIGHT> NEQ 0 THEN (@LITPOINTER)<RIGHT> _ 0;
END; %FTTENEX%
%OK WE GOT THE FILE%
%SAVE THE CURRENT BUFFERS%
LEXICAL (.GSTEOP); !TERMINATE CURRENT STATEMENT
EOPSVPOOL();
%SAVE THE INFO%
BEGIN
GLOBAL SVINCL[8];
EXTERNAL LINENO;
EXTERNAL EOPSAVE,CURPOOLEND,CURPTR,STLPTR,STPTR,LINEPTR,SEQLAST,LINELINE,CHARPOS;
SVINCL[0] _ .EOPSAVE;
SVINCL[1] _ .CURPOOLEND;
SVINCL[2] _ .CURPTR;
SVINCL[3] _ .STLPTR;
SVINCL[4] _ .STPTR;
SVINCL[5] _ .LINEPTR;
IF .SEQLAST NEQ 0
THEN SVINCL[6] _ .LINELINE !LINESEQUENCE NUMBER
ELSE SVINCL[6] _ 0;
SVINCL[7] _ .CHARPOS;
IF .CHARPOS NEQ 72
THEN LINELINE _ .LINELINE+1; !MULTIPLE STATEMENTS ON LINE
SAVFLG _ .FLGREG<0,36>;
FLGREG<ININCLUD> _ 1;
FLGREG<EOCS> _ 1;
![722] HANDLE NO CREFFING TOO
%[722]% IF .NOCRF THEN FLGREG<CROSSREF> _ 0;
IF .NOLST THEN FLGREG<LISTING> _ 0;
SVFLG2 _ .FLAGS2;
FLAGS2<TTYINPUT> _ 0;
%SET LINENO[1] SO THAT AN * WILL APPEAR NEXT TO THE
INCLUDED CODES LINE NUMBER %
LINENO[1] _ '* ';
CURPOOLEND _ POOL<0,0>;
IF EOPRESTORE() EQL EOF
THEN
BEGIN
EXTERNAL POSTINCL;
POSTINCL(); !RESTORE
END
END
END; ! of INCLSTA
GLOBAL ROUTINE POSTINCL=
BEGIN
%RESTORE THE WORLD AFTER AN INCLUDED FILE %
EXTERNAL SVINCL[8];
EXTERNAL EOPSAVE,CURPOOLEND,CURPTR,STLPTR,STPTR,LINEPTR,SEQLAST,LINELINE;
EXTERNAL EOPRESTORE,SVFLG2;
EXTERNAL LINENO;
EXTERNAL SAVFLG,GSTEOP,LEXICAL,CHARPOS;
MACHOP CLOSE = #070;
% CLEAN UP LAST LINE%
LEXICAL(.GSTEOP);
IF NOT FTTENEX
THEN
CLOSE (ICL,0) !CLOSE THE FILE
ELSE
( EXTERNAL CLOICL;
CLOICL();
);
EOPSAVE _ .SVINCL[0];
CURPOOLEND _ .SVINCL[1];
CURPTR _ .SVINCL[2];
STLPTR _ .SVINCL[3];
STPTR _ .SVINCL[4];
LINEPTR _ .SVINCL[5];
IF .SVINCL[6] NEQ 0
THEN LINELINE _ .SVINCL[6]; !LINESEQUENCE NUMBER
CHARPOS _ .SVINCL[7];
SEQLAST _ 1; !SO NO ONE WILL MESS WITH THE LINELINE
LINENO[1] _ ' '; !RESET LINENO TO TAB
!KEEP VALUES OF SOME FLAGS WHICH MAY HAVE CHANGED
! DURING PROCESSING OF THE INCLUDE FILE, AND WHOSE NEW
! VALUES WE REALLY WANT TO KEEP!
SAVFLG<BTTMSTFL> _ .FLGREG<BTTMSTFL>; !IF 16 CLOBBERED
SAVFLG<WARNGERR> _ .FLGREG<WARNGERR>; !WARNINGS GIVEN
SAVFLG<FATALERR> _ .FLGREG<FATALERR>; !FATAL ERRORS GIVEN
SAVFLG<LABLDUM> _ .FLGREG<LABLDUM>; !LABELS PASSED AS ARGS
FLGREG<0,36> _ .SAVFLG;
FLAGS2 _ .SVFLG2;
EOPRESTORE(); !RESTORE THE BUFFERS
END; ! of POSTINCL
GLOBAL ROUTINE ASTER(TYPE) = ! [1527] Rewritten
BEGIN
!***************************************************************
! This routine will scan for the *length construct following the
! data type name in type or IMPLICIT or FUNCTION statements, and
%1575% ! for the forms 'var * len (subs) * len' in type declarations.
! The parameter TYPE is based upon the data type name. This
! routine will return as its value:
! 1. The amended TYPE if a valid * construct was found
! 2. TYPE if no * construct was found
! 3. -1 if there was some error in the * construct
!
%1575% ! Two words are deposited on STK:
%1575% ! length for character data or 0
%1575% ! flag = 1 if *size was specified
!***************************************************************
MACRO ERR50(X) = FATLEX( .CHLEN, X<0,0>, E50<0,0>)$,
ERR24(X) = WARNLEX( X<0,0>, .CHLEN, E24<0,0>)$;
REGISTER
BASE T1,
D;
EXTERNAL
CONSTEXPR,
CHLEN,
CHDLEN,
ACTLDATYPE;
%1575% ! Put the default character length on STK and also a zero word
%1575% ! for the flag word for *size was specified
%1575% STK[SP = .SP + 1] = CHLEN = .CHDLEN;
%1575% STK[SP = .SP + 1] = 0;
! Look at upcoming character. If '*', continue below, otherwise return
IF .LSAVE EQL 0
THEN
BEGIN
LOOK4CHAR = "*";
IF LEXICAL( .GSTCSCAN ) EQL 0 THEN RETURN .TYPE;
END
ELSE
BEGIN
IF .LEXL<LEFT> NEQ ASTERISK THEN RETURN .TYPE;
LSAVE = 0;
END;
! Got an *, set the flag for *size specified and check for '(*)'
%1575% STK[.SP] = 1;
LOOK4CHAR = (UPLIT ASCIZ '(*)')<36,7>;
IF LEXICAL(.GSTSSCAN) NEQ 0
THEN
BEGIN
IF .TYPE NEQ CHARACTER
THEN RETURN FATLEX (UPLIT'constant',UPLIT'(*)',E0<0,0>);
CHLEN = LENSTAR;
END
ELSE
BEGIN ! digits for length
LOOK4CHAR = "?D"; ! any digit
IF (D = LEXICAL(.GSTCSCAN)) NEQ 0
THEN
BEGIN ! *digits
CHLEN = .D - "0";
WHILE (D = LEXICAL(.GSTCSCAN)) NEQ 0
DO CHLEN = .CHLEN*10 + .D - "0";
END ! *digits
ELSE
BEGIN ! *(expression)
LOOK4CHAR = "(";
IF LEXICAL(.GSTCSCAN) NEQ 0
THEN
BEGIN
IF CONSTEXPR() LSS 0 THEN RETURN .VREG;
IF .LSAVE NEQ 0 THEN LSAVE = 0
ELSE LEXL = LEXEMEGEN();
IF .LEXL<LEFT> NEQ RPAREN
THEN RETURN ERR0L(RPARPLIT);
T1 = .STK[.SP];
SP = .SP - 1;
CHLEN = .T1[CONST2];
END
ELSE
%1667% BEGIN ! error - give found when expecting error
%1667% IF .LSAVE EQL 0
%1667% THEN
%1667% BEGIN
%1667% LEXL = LEXEMEGEN();
%1667% LSAVE = -1;
%1667% END;
%1667% RETURN ERR0L(UPLIT ASCIZ'integer constant or "("');
END; ! error - give found when expecting error
END; ! *(expression)
%1646% ! Give Illegal CHARACTER size modifier is less than 1
%1646% IF .CHLEN LEQ 0 THEN RETURN ERR50(CHARPLIT);
END;
STK[.SP - 1] = .CHLEN; ! Set size specifier on STK
! Check the specified size to see if it is legal. Do the check
! on the basis of ACTLDATYPE of the statement in order to allow
! REAL*8 X*4 and to exclude doubleprecision X*4. Return the
! datatype.
SELECT .ACTLDATYPE OF NSET
INTEGER:(
IF .CHLEN EQL 2
THEN
BEGIN
ERR24(INTGPLIT);
RETURN .ACTLDATYPE
END;
IF .CHLEN EQL 4 THEN RETURN .ACTLDATYPE;
RETURN ERR50(INTGPLIT);
);
REAL:(
IF .CHLEN EQL 4 THEN RETURN .ACTLDATYPE;
IF .CHLEN EQL 8 THEN RETURN DOUBLPREC;
IF .CHLEN EQL 16
THEN
BEGIN
ERR24(REALPLIT);
RETURN .ACTLDATYPE
END;
RETURN ERR50(REALPLIT)
);
COMPLEX:(
IF .CHLEN EQL 8 THEN RETURN .ACTLDATYPE;
IF .CHLEN EQL 16
THEN
BEGIN
ERR24(COMPLIT);
RETURN .ACTLDATYPE
END;
IF .CHLEN EQL 32
THEN
BEGIN
ERR24(COMPLIT);
RETURN .ACTLDATYPE
END;
RETURN ERR50(COMPLIT)
);
LOGICAL:(
IF .CHLEN EQL 4 THEN RETURN .ACTLDATYPE;
IF .CHLEN EQL 1
THEN
BEGIN
ERR24(LOGIPLIT);
RETURN .ACTLDATYPE
END;
RETURN ERR50(LOGIPLIT)
);
DOUBLPREC:(RETURN ERR50(DOUBPLIT));
CHARACTER:(RETURN .ACTLDATYPE);
TESN
END; ! of ASTER
GLOBAL ROUTINE TYPDECLARE(DTYPE)=
BEGIN
!***************************************************************
! Called by INTESTA, REALSTA, LOGIST, DOUBST, COMPST, and
! CHARSTA statement routines. It handles the *size modifier,
! then uses the syntax of DECLARESPEC to parse a function
! declaration or an explicit type declaration. It then calls
! either FUNCGEN or TYPEGEN to handle the semantics.
!***************************************************************
EXTERNAL LSAVE;
EXTERNAL FUNCGEN,TYPEGEN,SAVSPACE,TYPE,STK;
EXTERNAL PST1ST,PSTATE,PSTIMPL,PSTSPF,ENDSTA;
%1213% EXTERNAL CHDLEN,ACTLDATYPE;
REGISTER BASE T1;
ACTLDATYPE _ .DTYPE; !SAVE ACTUAL TYPE IDENTIFIER CODE
%1213% ! Default length for character data is 1.
%1213% CHDLEN _ 1;
! PICK UP THE *N CONSTRUCT IF ANY
LSAVE _ 0;
IF ( IDTYPE _ ASTER ( .DTYPE )) LSS 0 THEN RETURN .IDTYPE;
%1575% ! ASTER leaves two words on STK:
%1575% ! length for character data
%1575% ! flag = 1 if *size was specified
%1704% ! Scan for optional comma after optional *n construct
%1704% IF .STK[.SP] EQL 1
%1704% THEN
%1704% BEGIN ! *size was specified, look for optional comma
%1704% IF .LSAVE EQL 0
%1704% THEN
%1704% BEGIN
%1704% LOOK4CHAR = ",";
%1704% LEXICAL( .GSTCSCAN ); ! Skip comma
%1704% END
%1704% ELSE
%1704% BEGIN
%1704% IF .LEXL<LEFT> EQL COMMA
%1704% THEN LSAVE = 0;
%1704% END;
%1704% END; ! *size was specified, look for optional comma
%1575% ! Fetch default length for character data left on stack by ASTER
%1575% IF .IDTYPE EQL CHARACTER
%1575% THEN CHDLEN _ .STK[.SP - 1]
%1575% ELSE CHDLEN _ 0;
%1575% SP = .SP - 2; ! Discard the two words ASTER put on STK
IF SYNTAX( DECLARESPEC) LSS 0 THEN RETURN .VREG;
TYPE _ 4;
T1_ .STK[0];
IF .T1[ELMNT] EQL 1
THEN
BEGIN % FUNCTION %
% CHECK THE STATEMENT ORDERING %
IF .PSTATE EQL PST1ST<0,0>
THEN
BEGIN % FINE ITS THE 1ST STATEMENT %
PSTATE _ PSTIMPL<0,0>; ! ADJUST PSTATE TO IMPLICIT
FLGREG<PROGTYP> _ FNPROG;
%1213% ! Add second parameter to FUNCGEN; this is the
%1213% ! 'datatype FUNCTION ....' case
%1213% FUNCGEN(@.T1[ELMNT1], 1)
END
ELSE
BEGIN % MISSING END STATEMENT %
RETURN ENDSTA()
END
END
ELSE
BEGIN % TYPE DECLARATION %
IF .PSTATE EQL PST1ST<0,0>
THEN PSTATE _ PSTSPF<0,0>; ! SPECIFICATION STATE
TYPEGEN(.T1[ELMNT1])
END;
SAVSPACE(.STK[0]<LEFT>,.STK[0])
END; ! of TYPDECLARE
! TYPE STATEMENTS *************
MACRO DATATYPE ( DTYPE ) =
BEGIN
RETURN TYPDECLARE( DTYPE )
END
$;
GLOBAL ROUTINE INTESTA = DATATYPE ( INTEGER );
GLOBAL ROUTINE REALSTA = DATATYPE ( REAL ) ;
GLOBAL ROUTINE LOGISTA = DATATYPE ( LOGICAL ) ;
GLOBAL ROUTINE DOUBSTA = DATATYPE ( DOUBLPREC ) ;
GLOBAL ROUTINE COMPSTA = DATATYPE ( COMPLEX ) ;
GLOBAL ROUTINE CHARSTA =
BEGIN
%1213% ! Add CHARSTA for character declaration
! Set flag for character declaration seen used
! in MRP3R and MRP3G to test if we have to scan
! the symbol table to generate high seg
! character descriptors.
CHDECL _ -1;
DATATYPE ( CHARACTER ) ; ! Now process the character statement
END; ! of CHARSTA
GLOBAL ROUTINE FUNCSTA=
BEGIN
EXTERNAL STK,
FUNCGEN %()%,
SAVSPACE %(SIZE,LOC)%,
TYPE;
REGISTER BASE T1;
!SEMANTIC ANALYSIS BEGINS
T1_.STK[0];
IDTYPE_-1;
TYPE_4;
FLGREG<PROGTYP> _ FNPROG;
%[1213]% ! Add second parameter to FUNCGEN; this is 'FUNCTION ...' case
%[1213]% FUNCGEN(.T1[ELMNT], 0);
SAVSPACE(0,@STK[0]);
.VREG
END; ! of FUNCSTA
GLOBAL ROUTINE SUBRSTA=
BEGIN
EXTERNAL STK,FUNCGEN %()%,SAVSPACE %(SIZE,LOC)%,TYPE;
REGISTER BASE T1;
!SEMANTIC ANALYSIS BEGINS
T1_.STK[0];IDTYPE_-1;TYPE_0;
FLGREG<PROGTYP> _ SUPROG;
%[1213]% ! Add second parameter to FUNCGEN; this is 'SUBROUTINE ...' case
%[1213]% FUNCGEN(.T1[ELMNT], 0);
SAVSPACE(0,@STK[0]);
.VREG
END; ! of SUBRSTA
GLOBAL ROUTINE ENTRSTA=
BEGIN
! Process an ENTRY statement
%1434% ! Rewritten by TFV on 14-Dec-81
REGISTER
BASE FUNCID, ! Name of this function subprogram
BASE IDSYM, ! Name of the entry point
BASE PTR, ! Pointer to the syntactic output
BASE TREE; ! Pointer to the block to pass to the
! EQUIVALENCE statement semantic routine
LOCAL
VAL; ! Used to avoid VREG usage
! Check for error - entry illegal inside a do or block if
IF .DOIFSTK NEQ 0 THEN FATLEX(E75<0,0>);
! Check for error - entry illegal in main program
IF .FLGREG<PROGTYP> EQL MAPROG THEN RETURN FATLEX(E114<0,0>);
IDTYPE = -1; ! Flag for FUNCGEN
FLGREG<MULTENT> = 1; ! Set entries in subroutine flag
PTR = .STK[0]; ! Pointer to syntactic output
IDSYM = @.PTR[ELMNT]; ! Symbol table entry for this
! entry point
%1531% ! An ENTRY point can not be in a SAVE statement.
%1531% IF .IDSYM[IDSAVVARIABLE]
%1531% THEN FATLERR(.IDSYM[IDSYMBOL],UPLIT(ASCIZ'ENTRY name'),
%1531% .ISN,E192<0,0>);
! Equivalence a numeric function and its entry names, character
! functions and their entry points just share the descriptor for the
! result.
IF .FLGREG<PROGTYP> EQL FNPROG
THEN
BEGIN ! Function subprogram
ENTRY = .PROGNAME; ! Name of this subprogram
NAME = IDTAB;
FUNCID = TBLSEARCH(); ! Lookup symbol table entry for
! the subprogram name
IF .FUNCID[VALTYPE] NEQ CHARACTER
THEN
BEGIN ! Numeric function subprogram
! Give an error if this is a character entry point.
! If it is numeric, pretend that we are the syntax
! analyzer and generate an EQUIVALENCE statement
! syntax tree and then give it to EQUISTA for
! semantic processing.
! Check for error - character and numeric entry
! points cannot be mixed.
IF .IDSYM[VALTYPE] EQL CHARACTER
THEN RETURN FATLEX(E178<0,0>);
NAME<LEFT> = 9; ! Size of syntax tree
STK[0] = TREE = CORMAN(); ! Get some space
(.TREE)[0] = .TREE + 1; ! List pointer
(.TREE)[1] = 1^18 + .TREE + 2; ! All pointer
(.TREE)[2] = 1^18 + .TREE + 4; ! All pointer
(.TREE)[3] = .TREE + 6; ! List pointer
(.TREE)[4] = .FUNCID; ! Function name
(.TREE)[4]<LEFT> = IDENTIFIER;
(.TREE)[5] = 0; ! Option
(.TREE)[6] = 1^18 + .TREE + 7; ! All pointer
(.TREE)[7] = .IDSYM; ! Entry name
(.TREE)[8] = 0; ! Option
! Now process the syntax tree using the EQUIVALENCE
! statement semantic routine.
IF (VAL = EQUISTA()) LSS 0 THEN RETURN .VAL;
END ! Numeric function subprogram
ELSE
BEGIN ! Character function subprogram
! Check for error - character and numeric entry
! points cannot be mixed.
IF .IDSYM[VALTYPE] NEQ CHARACTER
THEN RETURN FATLEX(E178<0,0>);
! Check for error - Character entry points must have
! the same length.
IF .IDSYM[IDCHLEN] NEQ .FUNCID[IDCHLEN]
THEN RETURN FATLEX(E179<0,0>);
IDTYPE = CHARACTER; ! used by funcgen
END; ! Character function subprogram
END; ! Function subprogram
TYPE = 1;
%1213% ! Add second parameter to FUNCGEN; this is 'ENTRY ...' case
%1213% FUNCGEN(.PTR[ELMNT],0);
SAVSPACE(0,@PTR)
END; ! of ENTRSTA
GLOBAL ROUTINE PROGSTA=
BEGIN
EXTERNAL NAMDEF;
EXTERNAL PROGNAME;
LEXL_LEXEMEGEN();
IF .LEXL<LEFT> EQL IDENTIFIER
%[1000]% THEN
%[1000]% BEGIN
%[1000]% LOCAL BASE PR1;
PR1_ .LEXL<RIGHT>;
PROGNAME_.PR1[IDSYMBOL];
NAMDEF( ENTRYDEF, .PR1 ); ! DEFINITION OF PROGNAME
PR1[IDATTRIBUT(FENTRYNAME)] _ 1; ! SET ENTRY POINT FLAG
LEXL_LEXEMEGEN();
%[1000]% END
%[1000]% ELSE RETURN ERR0L(PLIT 'PROGRAM name'); ! Flag missing name
IF .LEXL<LEFT> NEQ LINEND
THEN
BEGIN %SKIP ANYTHING LEFT FOR CDC COMPATIBILITY%
EXTERNAL FATLEX,E134;
DO LEXEMEGEN() UNTIL .VREG<LEFT> EQL LINEND;
FATLEX(E134<0,0>)
END;
.VREG
END; ! of PROGSTA
GLOBAL ROUTINE PARASTA=
! Parameter statement.
! [1656] All semantics are done in action routines; just return.
RETURN 0; ! RETURN SUCCESS
GLOBAL ROUTINE BLOCSTA=
BEGIN
EXTERNAL PROGNAME,STK,NAMDEF;
LEXL_LEXEMEGEN();
IF .LEXL<LEFT> EQL IDENTIFIER
THEN(LOCAL BASE PR1;
PR1_ .LEXL<RIGHT>;
PROGNAME_.PR1[IDSYMBOL];
NAMDEF( ENTRYDEF, .PR1 ); ! DEFINITION OF NAME
PR1[IDATTRIBUT(FENTRYNAME)] _ 1; !ENTRY POINT FLAG
LEXL_LEXEMEGEN();
)
ELSE PROGNAME _ SIXBIT'.BLOCK';
FLGREG<PROGTYP> _ BKPROG; !BLOCK DATA SUBPROGRAM FLAG
IF .LEXL<LEFT> NEQ LINEND THEN RETURN NOEOSERRL;
.VREG
END; ! of BLOCSTA
GLOBAL ROUTINE DIMESTA=
BEGIN
EXTERNAL STK,BLDARRAY %(LIST OF ONEARRAY'S)%,SAVSPACE %(SIZE,LOC)%,TYPE;
REGISTER BASE T1;
!SEMANTIC ANALYSIS BEGINS
IDTYPE_-1;TYPE_0;T1_@STK[0];BLDARRAY(.T1[ELMNT]);
SAVSPACE(0,@STK[0]);
.VREG
END; ! of DIMESTA
GLOBAL ROUTINE COMMSTA=
BEGIN
EXTERNAL NAMDEF;
EXTERNAL STK,
BLDARRAY %(ONEARRAY LIST)%,
SAVSPACE %(SIZE,LOC)%,
TYPE,
IDTYPE,
BLKSRCH %(NAME)%;
EXTERNAL FATLEX,
E0;
REGISTER BASE T1;
LOCAL BASE T2;
REGISTER BASE R1:R2;
!SEMANTIC ANALYSIS BEGINS
!-----------------------------------------------------------------------------------
!THE FIRST LOCATION OF THE LEXEME STACK (STK[0])
!POINTS TO THE LIST OF COMMON GROUPS TO BE SCANNED.
!-----------------------------------------------------------------------------------
R1_.STK[0];
STK[1]_.R1[ELMNT];
SAVSPACE(0,@R1);
INCR CLST FROM @STK[1] TO @STK[1]+.STK[1]<LEFT> DO
BEGIN
MAP BASE CLST;
R1_.CLST[ELMNT];
IF .R1[ELMNT] EQL 0 THEN ! BLANK COMMON
BEGIN
IF .CLST EQL @STK[1] !IF WE ARE STILL AT THE BEGINNING OF THE LIST
THEN
%1511% BEGIN !IT'S OK
R2_BLKSRCH(SIXBIT '.COMM.');
%1511% ! We need a SAVE rel block
%1511% SAVBLC _ TRUE;
%1511% SAVNED _ TRUE;
%1511% END
ELSE !SOMEONE FORGOT A COMMA
FATLEX(PLIT ', OR /',PLIT 'IDENTIFIER',E0<0,0>)
END
ELSE !SLASHS SEEN GET BLOCK NAME IF THERE
BEGIN
%1256% IF .R1[ELMNT] EQL 2
! OPTION 2, // SEEN. MEANS BLANK COMMON
%1256% THEN
%1511% BEGIN
R2_BLKSRCH(SIXBIT '.COMM.');
%1511% ! Need to rel block to SAVE this
%1511% SAVBLC _ TRUE;
%1511% SAVNED _ TRUE;
%1511% END
ELSE ! OPTION 1, /IDENTIFIER/ SEEN.
BEGIN
T1_.R1[ELMNT1];
T2_.T1[ELMNT1];SAVSPACE(.T1<LEFT>,@T1);
%CHECK AND DEFINE THE NAME %
IF NAMDEF( CMNBLK, .T2 ) LSS 0 THEN RETURN .VREG;
T2[IDATTRIBUT(COMBL)] _ 1; !SET COMMONBLOCK NAME BIT
R2_BLKSRCH(.T2[IDSYMBOL]);
R1_.R1+1; !INCR PTR IF SLASHES FOR CALL TO BLDARRAY COMING UP
END;
END;
IDTYPE_-1;
TYPE_5;
STK[2]<LEFT>_.R2[COMFIRST];
!MUST BE VERY CAREFUL IF BLDARRAY FAILS, FOR UNDER SOME
! CIRCUMSTANCES, STK[2] WILL CONTAIN -1 WHICH KILLS US
STK[2]<RIGHT>_.R2[COMLAST];
IF BLDARRAY(.R1[ELMNT1]) GEQ 0
THEN
BEGIN
!---------------------------------------------------------------------------
!STK[2] CONTAINS THE INFORMATION REQUIRED BY
!BLDARRAY TO LINK ELEMENTS OF THE COMMON BLOCK. IT
!IS UPDATED BY BLDARRAY TO CONTAIN LINKS TO THE
!FIRST AND LAST ELEMENT IN THE BLOCK.
!--------------------------------------------------------------------------
R2[COMFIRST]_.STK[2]<LEFT>;
R2[COMLAST]_.STK[2]<RIGHT>;
R1 _ .R2[COMFIRST]; !FIRST ITEM IN BLOCK
DO
R1[IDCOMMON] _ .R2 !PUTTING PTR TO BLOCK IN EACH ITEM
WHILE (R1 _ .R1[IDCOLINK]) NEQ 0;
END %OF FIXING UP COMMON POINTERS%
END;
T1_.STK[1];SAVSPACE(.T1<LEFT>,@T1);
.VREG
END; ! of COMMSTA
GLOBAL ROUTINE SAVESTA= ![1511] New [1531] Rewrite
! Processes SAVE statements
BEGIN
REGISTER BASE PTR1; ! Pointer to something
REGISTER BASE PTR2; ! Pointer to something
REGISTER BASE SYMTAB; ! Symbol table entry
SAVNED = TRUE; ! We need a save statement
! STK[0]
! | len-1,,ptr | ---> | 0=no args |
! +--------------------+
! | len-1,,ptr to args |
PTR1 = .STK<RIGHT>;
IF .PTR1[ELMNT] EQL 0
THEN ! No arguments given, set global flag.
BEGIN
SAVALL = TRUE; ! Save everything possible
SAVLOC = TRUE; ! Save locals (non-commons)
END
ELSE
BEGIN ! Arguments are given, process them.
PTR1 = .PTR1[ELMNT1]; ! Get the pointer
INCR ARG FROM .PTR1<RIGHT> TO .PTR1<RIGHT> + .PTR1<LEFT>
BY 2 DO
BEGIN ! For each argument to SAVE
MAP BASE ARG;
! | len-1,,ptr to args | ---> | 1=var, 2=common |
! +-----------------+
! | len-1,,ptr |
IF .ARG[ELMNT] EQL 1
THEN
BEGIN ! Variable or array
SYMTAB = .ARG[ELMNT1]; ! Symbol table
SYMTAB[IDSAVVARIABLE] = 1; ! Found in SAVE
SAVLOC = TRUE; ! Save locals
! If this variable is declared in a common,
! then give an error.
IF .SYMTAB[IDATTRIBUT(INCOM)]
THEN FATLERR(.SYMTAB[IDSYMBOL],
UPLIT(ASCIZ'COMMON variable'),
.ISN,E192<0,0>);
! Dummy's are illegal.
IF .SYMTAB[IDATTRIBUT(DUMMY)]
THEN FATLERR(.SYMTAB[IDSYMBOL],
UPLIT(ASCIZ'Dummy argument'),
.ISN,E192<0,0>);
! External function name is illegal
IF .SYMTAB[IDATTRIBUT(INEXTERN)] OR
.SYMTAB[IDATTRIBUT(USERFUNCTION)]
THEN FATLERR(.SYMTAB[IDSYMBOL],
UPLIT(ASCIZ'External name'),
.ISN,E192<0,0>);
END ! Variable or array
ELSE
BEGIN ! Named common block name
! | len-1,,ptr | ---> | 23 octal (/) |
! +-------------------+
! | ptr to symbol tbl |
! +-------------------+
! | 23 octal (/) |
PTR2 = .ARG[ELMNT1];
SYMTAB = .PTR2[ELMNT1]; ! Symbol table
! Don't link this name if it was already
! specified in a SAVE.
IF NOT .SYMTAB[IDSAVCOMMON]
THEN LKSVCOMMON(.SYMTAB); ! Link it in
END; ! Named common block name
END; ! For each argument to SAVE
END; ! Arguments are given, process them.
END; ! of SAVESTA
GLOBAL ROUTINE LKSVCOMMON(SYMTAB)= ![1531] Rewrite
BEGIN
! Put passed common symbol table pointer into linked list of
! commons for SAVE statement processing.
REGISTER BASE NEWLINK; ! New link to be added to PTRSAVCOMMON
MAP BASE SYMTAB; ! Passed argument - symbol table entry to
! be added.
! Get one word for the link
NAME<LEFT> = 1;
NEWLINK = CORMAN();
! Place in ptr to symbol table
NEWLINK[CW0L] = .SYMTAB;
! Place in ptr to previous common symbol or 0
NEWLINK[CLINK] = .PTRSAVCOMMON;
PTRSAVCOMMON = .NEWLINK;
! Bump count of commons by one
NUMSAVCOMMON = .NUMSAVCOMMON + 1;
! Mark that this common is to be SAVE-d
SYMTAB[IDSAVCOMMON] = 1;
END; ! of LKSVCOMMNON
END
ELUDOM