Google
 

Trailing-Edge - PDP-10 Archives - BB-D480C-SB_1981 - act1.bli
There are 26 other files named act1.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,1981 BY DIGITAL EQUIPMENT CORPORATION
!AUTHOR: T.E. OSTEN/FJI/MD/SJW/JNG/DCE/TFV/AHM

MODULE ACT1(RESERVE(0,1,2,3),SREG=#17,FREG=#16,VREG=#15,DREGS=4)=
BEGIN

!		REQUIRES LEXNAM, FIRST, TABLES, ASHELP

SWITCHES NOLIST;
REQUIRE LEXNAM.BLI;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
SWITCHES LIST;
SWITCHES NOSPEC;

REQUIRE ASHELP.BLI;

GLOBAL BIND ACT1V = 6^24 + 0^18 + 128;		! Version Date:	19-Oct-81

%(

***** Begin Revision History *****

69	-----	-----	MAKE USE COUNT FOR IMPLIESD DO LOOP LABELS
			2 INSTEAD OF 1
70	-----	-----	GENERATE LABELS FOR DIMENSION BLOCKS FOR ARRAYS
			THAT ARE PROTECTED (ALSO - COMMENT OUT CODE IN
			"BLDARRAY" THAT APPEARS TO PROCESS MULTIPLE
			ARRAYS SPECIFIED BY THE SAME DIMENSION SPECIFICATION)
71	-----	-----	FIX OPERSP FIELD OF SLIST CALLS

72	-----	-----	MODIFY "BLDARRAY" TO GENERATE DIMENSION LABELS
			FOR ALL ARRAYS IF THE "BOUNDS" SWITCH WAS SPECIFIED.
			(WE HAVE DONE AWAY WITH THE "ISPROT" FLAG ON INDIVIDUAL
			ARRAYS)
76	-----	-----	DETECT UNDETECTED SUBSCRIPTED IMPLICIT DO INDICES

77	-----	-----	PUT PARAMETER STUFF IN NAMCHK AND NAMDEF.
			PUT *N OVERRIDE IN BLDARRAY.
			CHANGE NO PARAMETERS IN FUNCTION TO WARNING

78	-----	-----	IN FUNCGEN - NO LONGER SET FNNAME ON FUNCTIONS.
				  - PROGNAME IS NOW SET IN ACTION PNAMSET

79	-----	-----	MAKE A LINKED LIST OF ENTRY POINT NAMES IN FUNCGEN

80	-----	-----	ALLOW DIMENSION A(1:3)

81	-----	-----	DUMMIES CAN BE IN EXTERNAL STATEMENTS

82	-----	-----	CLEAR THE NOALOC BIT IN THE OTHER PLACE
			WHERE THE SPECIAL FORMAL ARRAY PSEUDOSYMBOL TABLE
			ENTRY IS GENERATED - FUNCGEN

83	-----	-----	CHANGE NAMDEF AND NAMCHK TO INTERPRET THE &/* EXTERNAL
			STATEMENT PROPERLY

84	-----	-----	FIX BLDARRAY SO THAT IT ACCEPTS THE TYPE INFORMATION
			FOR TYPE STATEMENTS BEFORE THE DIMENSION INFORMATION
			RATHER THAN AFTER

85	-----	-----	CHECK FOR DUPLICATE DUMMY ARGS IN FUNCTIONS,
			SUBROUTINES AND ENTRYS

86	----	-----	HAVE BLDDIM USE  DVARFLGS TO CLEAR THE FLAGS IN
			THE DIMENSION TABLE ENTRY.

87	-----	-----	DETECT THE CASE OF AN IMPLIED DO SPEC WITHOUT
			PRECEEDING VARIABLE LIST OF SOME SORT - DATALIST

88	-----	-----	ISSUE A WARNING MESSAGE WHEN LABEL INDICATORS 
			APPEAR IN THE FORMAL ARGUMENT LIST OF A FUNCTION
			FUNCGEN

89	-----	-----	FIX BLDARRAY SO THAT IT WILL REVERSE
			THE CALCULATED DIMENSIONS OF AN ARRAY WHICH
			HAS GONE TO DOUBLE PRECISION DUE TO
			AN IMPLICIT STATEMENT AND IS THEN EXPLICITLY TYPED
			TO SINGLE PRECISION

90	-----	-----	CHECK IN BLDDIM TO BE SURE THAT DIMENSIONS
			ARE WITHIN A RESPECTABLE RANGE

91	-----	-----	IN BLDDIM, CHANGE REFERENCE TO "DEBUG" FLAG
			TO "DBGDIMN" FLAG 

92	-----	-----	FUNCGEN - FIX DUPLICATE DUMMY PARAMETER CHECK SO
			IT REALLY WORKS

93	-----	-----	MAKE A CHECK FOR DO INDEX MODIFICATION IN NAMSET
			SO THAT ALL CASES ARE CHECKED

94	-----	-----	NAMSET WAS NOT CALLED FOR IMPLICIT DO INDICES

95	-----	-----	BLDDIM - CHECK FOR ZERO SINGLE DIMENSION

96	-----	-----	WITH THE ADVENT OF SIGNED PARAMETERS  - BULDDIM
			MUST BE PREPARED TO CHECK THE SIGN OF THE NUMBER
			NOT JUST WHETHER OR NOT A - WAS
			PRESENT

97	-----	-----	EXTEND NAMDEF TO DETECT REFERENCE TO DUMMY PARAMETERS
			BEFORE THEY HAVE BEEN DEFINED

***** Begin Version 4A *****

99	 230	-----	RESTORE NOALLOC BIT WHEN ADJUSTABLE DIMENSION
			IS NOT YET DEFINED, (MD)

100	232	-----	FIX BLDUNIT - IT NEEDED ONE MORE LEVEL OF
			INDIRECTION IN THE RECORD NUMBER PROCESSING., (MD)

101	235	-----	FIX NAMELIST PROBLEMS
			USING NEW PARAMETER NMLSTITM, (DT/MD)
102	265	15946	ADD CHECK FOR VARIABLE IN DATA STATEMENT TWICE, (JNT)
103	272	-----	CHANGE 102 TO ONLY CHECK SIMPLE VARIABLES, NOT ARRAYS,
			(JNT)

***** Begin Version 5 *****

104	VER5	-----	SHARE .I OFFSET IN DIMENTRY FOR ARRAYS
			WITH VARIABLE UPPER BOUND (LINK DIM ENTRIES), (SJW)
105	410	-----	MAKE DTABPTR GLOBAL SO WILL BE INITIALIZED TO 0, (SJW)
106	414	QA625	FIX SHARING .I OFFSET SO ONLY SHARES DIM2 .I
			  IF DIM1 SAME, (SJW)
107	415	18964	DON'T DESTROY SYMBOL TABLE ENTRY FOR A FORMAL
			  FUNCTION IF A LATER ENTRY STATEMENT SEEN WITH
			  THE FUNCTION AS A PARAMETER.
108	423	QA709	FIX PATCH 414: DIMNUM=1 => ARRAY HAS 1 DIM NOT 2, (SJW)
109	460	19477	TEST FOR OVERSIZED DIMENSIONING CORRECTLY, (DCE)

***** Begin Version 5A *****

110	567	22284	MAKE EXTERNAL STMNT APPLY TO ALL ENTRY POINT PARAMS
111	571	22378	FIX V5 OPTIMIZATION THAT SHARES 2ND OFFSET OF
			  FORMAL ARRAYS IF 1ST DIMENSIONS = SO ALL WILL
			  WORK IF ARRAY SUBSEQUENTLY TYPED DIFFERENTLY
			  (DIFFERENT # WORDS) THAN WHEN SHARING 1ST DONE, (SJW)
112	572	21825	CHECK IMPLIED DO INDEX FOR ALREADY ACTIVE (FROM
			  AN ENCLOSING IMPLIED OR REAL DO), (SJW)
113	601	Q20-26	FIX EDIT 572 TO CHECK IMPLIED DO INDEX IN DATA
			  STATEMENT FOR ALREADY ACTIVE FROM AN ENCLOSING
			  IMPLIED DO, (SJW)

***** Begin Version 5B *****

114	627	23755	FIX EDIT 571 TO CORRECTLY ADJUST ALL DIMENSION
			TABLE MULTIPLICATIVE FACTORS BY THE RIGHT
			CONSTANT IF AN ARRAY IS LATER DISCOVERED TO
			REQUIRE A DIFFERENT NUMBER OF WORDS PER ENTRY
			THAN ORIGINALLY THOUGHT. EDIT 571 ONLY FIXED
			THE FIRST SUBSCRIPT., (JNG)
115	635	24868	FIX DATALIST TO RETURN -1 IF IT GETS E66
			(CANNOT INIT DUMMY PARAMETER IN DATA), (JNG)
116	663	25643	FIX TYPING OF FORMAL FUNCTIONS (EXTERNAL STMNTS), (DCE)
117	717	26560	GIVE REASONABLE ERROR MESSAGE FOR
			REPEATED PARAMETER STATEMENT, (DCE)
118	741	-----	ADD SLASHWARN ROUTINE, (DCE)

***** Begin Version 6 *****

119	760	TFV	1-Jan-80	-----
	Add routines to handle keywords in I/O control lists

127	1132	AHM	22-Sep-81	Q10-06347
	Fix casing of some error message fragments.

128	1136	AHM	19-Oct-81	Q20-01652,Q20-01656
	Delete code that unjustifiably decremented SNREF for labels
	in BLDKEY, since it screwed up optimizations.

***** End Revision History *****

)%

	FORWARD
		FUNCGEN,	!
		TYPEGEN,	!
		TMPGEN,		!
		BLDDIM,		!
		BLDARRAY,	!
		BLKSRCH,	!
		BLDVAR,		!
		DATALIST,	!
		BLDFORMAT,	!
		BLDUNIT,	!
%[760]%		BLDKEY,
%[760]%		BLDKLIST,
%[760]%		KORFBLD,
		NAMSET,
		NAMREF,
		NAMDEF,
		NAMCHK;

	
	% THE FOLLOWING TABLE IS USED TO PRODUCE THE ERROR MESSAGES 
	  IT IS BASED UPON THE BIT POSITION OF THE CONFLICTING IDATTRIBUT
	  FIELD BIT %
	BIND DUMDUM  =  PLIT  (

%1132%	R18 NAMES R23 NAMES  'in EXTERNAL statement?0',
%1132%	R22 NAMES  'as dummy parameter?0',
%1132%	R19 NAMES 'in type statement?0',
%1132%	R24 NAMES 'in DATA statement?0',
%1132%	R26 NAMES 'in COMMON?0',
%1132%	R27 NAMES 'in EQUIVALENCE?0',
%1132%	R28 NAMES 'as an entry point name?0',
%1132%	R33 NAMES 'as statement function?0',
%1132%	R34 NAMES 'as COMMON block?0',
%1132%	R35 NAMES 'as NAMELIST?0',

%1132%	AYORFN NAMES ' as an array or FUNCTION?0',
%1132%	AY NAMES 'as an array?0',
%1132%	FNN NAMES 'as a FUNCTION?0'
);


	GLOBAL ROUTINE
NAMDEF (  TYPE, ID )   =
BEGIN

	EXTERNAL E136;
	MAP BASE ID;

	% ID - POINTER TO SYMBOL TABLE ENTRY %
	% TYPE - CODE FOR WHAT YOU THINK YOU HAVE  %

	% THE FOLLOWING BINDS ARE USED TO MAKE THE SYMBOL TABLE ATTRIBUTE
	  FIELD MASKS  %
	
	BIND
		NAMLST = 1^35,
		CMNBLK = 1^34,
		STFN = 1^33,
		ENTPNT = 1^28,
		EXTERN = 1^23,
		EXTRSGN = 1^18,
		TYPED = 1^19,
		EXTBTH = 1^18 + 1^23,
		EQVIN = 1^27,
		COMIN = 1^26,
		DATAIN = 1^24,
		DUMIEE = 1^22;
	
	% THE FOLLOWING ARE MASKS ( INDEXED BY .TYPE ) OF THE SYMBOLTABLE
	  IDATRIBU FIELD.  IF THE AND IS NON-ZERO THEN THERE IS A CONFLICT %
	
	BIND	DEFMASK = PLIT (
	
		%ARRYDEF%	NAMLST + STFN + ENTPNT + EXTBTH,
		%ARRYDEFT%	NAMLST + STFN + ENTPNT + EXTBTH + TYPED,
		%STFNDEF%	NAMLST + STFN + ENTPNT + EXTBTH + EQVIN + COMIN + DATAIN + DUMIEE,
		%EXTDEF%	NAMLST + STFN + ENTPNT + EXTBTH  + DATAIN + COMIN + EQVIN,
		%NMLSTDEF%	NAMLST + STFN + ENTPNT + EXTBTH + DUMIEE + DATAIN + COMIN + EQVIN,
		%VARARY%	NAMLST + STFN + EXTBTH + COMIN + DUMIEE,
		%IDDEFT%	NAMLST + TYPED,
		%IDDEFINE%	NAMLST + STFN + ENTPNT + EQVIN + COMIN + DATAIN,	%DUMMY PARAMETERS%
		%ENTRYDEF%	NAMLST + STFN + ENTPNT + EXTBTH + CMNBLK + DUMIEE,
		%EXTDEFS%	NAMLST + STFN + ENTPNT + EXTBTH + CMNBLK  + DATAIN + COMIN + EQVIN,
		%CMNBLK%	ENTPNT + EXTRSGN,
		%PARADEF%	NAMLST + CMNBLK + STFN + ENTPNT + EXTBTH + TYPED + EQVIN + COMIN + DATAIN + DUMIEE,
		%NMLSTITM%	NAMLST + STFN + EXTBTH + DUMIEE
	);
	
	
	% NAMDEF IS REFERENCED FROM THE FOLLOWING ROUTINES WITH THE  FOLLOWING TYPES:
	
		SEMANTIC ROUTINE     -   TYPES
	
		TYPE STATEMENTS 		ARRYDEFT, IDDEFT
		FUNCTION			ENTRYDEF, IDDEF
		SUBROUTINE			ENTRYDEF, IDDEF
		ENTRY				ENTRYDEF, IDDEF
		PROGRAM				ENTRYDEF
		BLOCKDATA			ENTRYDEF
		DIMENSION			ARRYDEF
		COMMON				VARARY, CMNBLK, ARYDEF
		EXTERNAL			EXTDEF, EXTDEFS(LIB FUNCTION)
		NAMELIST			NMLSTDEF, VARARY
		STMNT FUNCTION			STFNDEF
		PARAMETER			PARADEF
	
		NOTE THAT EQUIVALENCE AND DATA STATEMENTS REFERENCE NAMSET RATHER
	 THAN NAMDEF.  THIS IS DONE MAINLY FOR CONVIENCE.  IF THEY COULD BE
	CHANGED TO REFERENCE NAMREF IT MIGHT BE POSSIBLE, WITH A LITTLE THOUGHT, TO DETECT
	INSTANCES OF DEFINITION AFTER REFERENCE.
	
	%


	%THIS MASK DEFINES WHICH TYPES CAN BE THE SAME AS AN ENTRY POINT
	  NAME AS LONG AS ITS NOT IN A FUNCTION %

	BIND	OKSAMEASENTRY  = 1^ARRYDEF + 1^ARRYDEFT + 1^STFNDEF +
				1^EXTDEF + 1^NMLSTDEF + 1^IDDEFINE  ;


	BIND  PDEFAS  =  PLIT  (
	R18,R19,0,0,R22,R23,R24,0,R26,R27,R28,0,0,0,0,R33,R34,R35  );

	REGISTER R;
	EXTERNAL CREFIT;

	IF .FLGREG<CROSSREF>   THEN  CREFIT(  .ID, SETT );

	% CHECK THE ATTRIBUTES  %
	IF  ( R _ .DEFMASK[.TYPE]<LEFT> AND .ID[IDATTRIBUT(ALLOFTHEM)] )  NEQ  0
	THEN
		%ALLOW STATEMENT FUNCTIONS , ARRAYS , NAMELISTS , AND POSSIBLE LIBRARY
		  FUNCTIONS TO BE THE SAME AS ENTRY POINT NAMES PROVIDING
		  THAT THIS IS NOT A FUNCTION  %

		IF (1^(.TYPE) AND OKSAMEASENTRY )  EQL  0
			OR  .FLGREG < PROGTYP>  EQL  FNPROG
			OR    .R NEQ   ENTPNT^(-18)
		THEN
			% ALLOW ENTRY POINT DEFINITIONS TO BE THE
			  SAME AS NAMELIST, STATEMENT FUNCTIONS, AND 
			  POSSIBLE LIBRARY FUNCTIONS AS LONG AS ITS NOT A FUNCTION%

			IF .TYPE NEQ  ENTRYDEF
			  OR  .FLGREG<PROGTYP>  EQL  FNPROG
			  OR ( .R NEQ  NAMLST^(-18)
				AND  .R  NEQ  STFN^(-18)
				AND  .R  NEQ  EXTERN^(-18)  )
			THEN
				% ITS A CONFLICTING DEFINITION %
				RETURN  FATLEX  (  .PDEFAS[35-FIRSTONE(.R)], ID[IDSYMBOL], E34 );

	% WE MUST DO JUST A BIT MORE CHECKING %

	VREG _ 0;
	VREG _  CASE  .TYPE  OF   SET

	%ARRYDEF%	BEGIN
				IF .ID[OPRSP1]  NEQ  VARIABL1 THEN  AYORFN
			END;
	%ARRYDEFT%	BEGIN
				IF .ID[OPRSP1]  NEQ  VARIABL1  THEN  AYORFN
			END;
	%STFNDEF%	BEGIN
				IF .ID[OPRSP1]  NEQ  VARIABL1  THEN  AYORFN
			END;
	%EXTDEFS%	BEGIN
				IF  .ID[OPRSP1]  EQL  ARRAYNM1  THEN  AY
			END;
	%NMLSTDEF%	BEGIN
				IF .ID[OPRSP1]  NEQ  VARIABL1  THEN  AYORFN
			END;
	%VARARY%	BEGIN
				IF .ID[OPRSP1]  EQL  FNNAME1 THEN  FNN
			END;
	%IDDEFT%		BEGIN END;
	%IDDEF%	BEGIN
				%CHECK HERE TO SEE THAT DUMMY PARAMETERS
				 HAVE NEVER BEEN REFERENCED %
				IF NOT .ID[IDATTRIBUT(NOALLOC)]
				  AND NOT  .ID[IDATTRIBUT(DUMMY)]
				THEN	RETURN FATLEX(.ID[IDSYMBOL],E136<0,0>)
			 END;
	%ENTRYDEF%	BEGIN
				IF .ID[OPRSP1]  EQL FNNAME1 AND NOT .ID[IDATTRIBUT(NOALLOC)]  THEN  FNN
			END;
	%EXTDEF%	BEGIN
				IF .ID[OPRSP1]  EQL  ARRAYNM1  THEN  AY
			END;
	%CMNBLK%	BEGIN
				IF .ID[OPRSP1]  EQL  FNNAME1 AND NOT .ID[IDATTRIBUT(NOALLOC)]  THEN FNN
			END;
	%PARADEF%	BEGIN
				IF NOT .ID[IDATTRIBUT(NOALLOC)]  THEN  IDENPLIT
![717] IF ALREADY DEFINED AS PARAMETER (IF THIS IS A REDUNDENT
![717] PARAMETER DEFINITION OR REDEFINITION) GIVE FATAL ERROR
%[717]%			ELSE IF .ID[IDATTRIBUT(PARAMT)] THEN .LEXNAM[CONSTLEX]
			END;
	%NMLSTITM%	BEGIN
				IF .ID[OPRSP1] EQL FNNAME1 THEN FNN
			END
	
	TES;

	IF .VREG  NEQ  0
	THEN  RETURN  FATLEX ( .VREG, ID[IDSYMBOL], E34 );

END;	%NAMDEF%



	GLOBAL ROUTINE
NAMSET ( TYPE , ID  )   =
	
BEGIN	% THE SYMBOL POINTED TO BY ID AND DEFINED BY TYPE IS 
	  BEING SET  %

	EXTERNAL CREFIT;
	MAP BASE  ID;
	EXTERNAL CKDOINDEX,STMNDESC;

	%CHECK FOR DO INDEX MODIFICATION%
	IF CKDOINDEX ( .ID )
	THEN	IF .LABOK(@STMNDESC)  EQL  0	!FORGET DATA AND EQUIV
		THEN	FATLEX(E77<0,0>);	!MODIFICATION WARNING

	ID[IDATTRIBUT(STORD)] _ 1;
	IF  .FLGREG<CROSSREF>  THEN  CREFIT( .ID, SETT );
	RETURN  NAMCHK  ( .TYPE , .ID )

END;	%NAMSET%


	GLOBAL ROUTINE
NAMREF ( TYPE , ID )   =

BEGIN	% THE SYMBOL POINTED TO BY ID AND DEFINED BY TYPE IS BEING 
	  REFERENCED  %
	EXTERNAL CREFIT;

	IF  .FLGREG<CROSSREF>  THEN CREFIT( .ID, USE );
	RETURN  NAMCHK ( .TYPE, .ID )

END;	%NAMREF%




	GLOBAL ROUTINE
NAMCHK  (  TYPE, ID  )  =

BEGIN	% CHECK TO SEE IF WE HAVE WHAT WE THINK WE HAVE AND IF NOT
	  OUTPUT AN ERROR MESSAGE  %

	% THE FOLLOWING BINDS ARE USED TO MAKE THE SYMBOL TABLE ATTRIBUTE
	  FIELD MASKS  %
	
	BIND
		NAMLST = 1^35,
		CMNBLK = 1^34,
		STFN = 1^33,
		ENTPNT = 1^28,
		EXTERN = 1^23,
		EXTRSGN = 1^18,
		TYPED = 1^19,
		EXTBTH = 1^18 + 1^23,
		EQVIN = 1^27,
		COMIN = 1^26,
		DATAIN = 1^24,
		DUMIEE = 1^22;

	BIND DUMO  =  PLIT (

	VAORAY NAMES 'A VARIABLE OR ARRAY?0',
	VARIB NAMES  'A SCALAR VARIABLE?0',
	AAY   NAMES  'AN ARRAY?0',
	AFN   NAMES  'A SUBPROGRAM NAME?0'	);
	MAP BASE ID;


	VREG _ 0;
	VREG _ CASE .TYPE OF SET

	%VARYREF%	BEGIN
		IF .ID[OPRSP1]  EQL FNNAME1
		  OR  .ID[IDATTRIBUT(NAMNAM)]
		THEN	VAORAY
		END;

	%VARIABL1%	BEGIN
		IF .ID[OPRSP1]  NEQ  VARIABL1
		  OR  .ID[IDATTRIBUT(NAMNAM)]
		THEN  VARIB
		END;

	%ARRAYNM1%	BEGIN
		IF  .ID[OPRSP1]  NEQ  ARRAYNM1
		THEN     AAY
		END;

	%FNNAME1%	BEGIN
		IF  .ID[OPRSP1]  EQL  FNNAME1
		THEN   
		BEGIN
			%CHECK TO SEE THAT POSSIBLE LIBRARY FUNCTIONS
			WHICH TURNED OUT NOT TO BE LIBRARY FUNCTIONS
			ARE NOT CONFLICTING WITH ANY GLOBAL NAMES %

			IF ( VREG _ .ID[IDATTRIBUT(ALLOFTHEM)] AND
				( CMNBLK^(-18) + ENTPNT^(-18)) ) NEQ  0
			THEN	IF	.ID[IDATTRIBUT(COMBL)]
				THEN	FATLEX( R34, ID[IDSYMBOL], E34<0,0> )
				ELSE	FATLEX(R28,ID[IDSYMBOL],E34<0,0>);
			0
		END
		ELSE
		BEGIN
			IF .ID[OPRSP1]  EQL ARRAYNM1 OR NOT .ID[IDATTRIBUT(NOALLOC)] OR  ISDEFIND(ID)
				OR .ID[IDATTRIBUT(COMBL)]
			THEN	AFN	!ITS A VARIABLE OR ARRAY
			ELSE
			BEGIN
			 ID[OPERSP] _ IF .ID[IDATTRIBUT(DUMMY)] 
						THEN FORMLFN ELSE FNNAME;
			0
			END
		END
		END;

	%NMLSTREF%	BEGIN
		%NO CONFLICTS HERE%
		0
		END;
	%PARAREF%	BEGIN
		RETURN  .ID[IDPARAVAL]
		END


	TES;

	IF  .VREG  NEQ   0
	THEN	RETURN  FATLEX (.VREG, ID[IDSYMBOL],E15<0,0> );

	%  INDICATE THAT WE ARE USING THIS NAME %
	ID[IDATTRIBUT(NOALLOC)] _ 0;

END;	%ROUTINE  NAMCHK  %




GLOBAL ROUTINE FUNCGEN (FPNT)=
BEGIN
	LOCAL BASE R1;
	REGISTER BASE T2; MAP BASE FPNT;REGISTER BASE T1:R2;
	EXTERNAL MULENTRY;	!POINTER TO FIRST ENTRY POINT NAME
	EXTERNAL SAVSPACE %(SIZE,LOC)%,TYPE,IDTYPE,PROGNAME,CORMAN %()%,
		NEWENTRY %()%,STK,NAME;
	MACRO
	FCTN = 4$, ENT=1$,
	ERR40=RETURN FATLEX(R1[IDSYMBOL], E40<0,0>)$;

	!------------------------------------------------------------------------
	!THIS ROUTINE IS CALLED WITH THE PARAMETER FPNT POINTING TO
	!THE LIST:
	!
	!IDENTIFIER (20^18+LOC) - SUBPROGRAM NAME
	!OPTION 0 - NO ARGUMENTS, ILLEGAL IF THIS IS A FUNCTION
	! OR
	!OPTION 1 - ARGUMENT LIST POINTER FOLLOWS
	!	COUNT^18+LOC - POINTS TO LIST POINTER
	!		1^18+LOC - POINTS TO LIST OF
	!		CHOICE 1 - DUMMY ARGUMENT
	!			IDENTIFIER (20^18+LOC)
	!		CHOICE 2 - DUMMY LABEL
	!
	!THE LOCATION TYPE IS NON-ZERO (4) FOR A FUNCTION STATEMENT
	!AND ZERO FOR A SUBROUTINE OR ENTRY STATEMENT.  AN ARGUMENT
	!LIST MUST BE PRESENT IF TYPE IS NON-ZERO.  IF THE FUNCTION
	!WAS TYPED, IDTYPE WILL CONTAIN THE TYPE OTHERWISE IT CONTAINS -1
	!------------------------------------------------------------------------
	R1_.FPNT[ELMNT];!R1_LOC (SUBPROGRAM NAME)
	IF NAMDEF( ENTRYDEF, .R1) LSS 0 THEN RETURN .VREG;
	IF .FPNT[ELMNT1]EQL 0 THEN ! NO ARGUMENTS
	BEGIN
		IF .FLGREG<PROGTYP> EQL  FNPROG  THEN WARNLEX ( E28<0,0> ); !FUNCTION SUBPROGRAM
		R2_0
	END
	ELSE
	BEGIN
		!--------------------------------------------------------------------
		!CREATE AN ARGUMENT LIST ON THE UNUSED PORTION OF THE
		!LEXEME STACK (STK[2] THRU STK[100]).  THIS IS NECESSARY
		!BECAUSE THE EXACT NUMBER OF ARGUMENTS IS NOT KNOWN.
		!THE ARGUMENT LIST PRODUCED BY SYNTAX CONTAINS 2 WORDS
		!(CHOICE 1) FOR EACH DUMMY ARGUMENT BUT ONLY 1 WORD
		!FOR ACH DUMMY LABEL (CHOICE 2).  THE PROPORTION OF
		!EACH ARGUMENT TYPE IS NOT KNOWN UNTIL THE LIST IS SCANNED.
		!--------------------------------------------------------------------
		T2_.FPNT[ELMNT2];T1_.T2[ELMNT];SAVSPACE(0,@T2);
		T2_STK[3]<0,0>;!T1_LOC(GENERATED ARG LIST),SET COUNT T2 TO LOC OF ARGLIST
		INCR ALST FROM @T1 TO @T1+.T1<LEFT>DO
		BEGIN
			MAP BASE ALST;
			T2_.T2+1;
			IF .ALST[ELMNT] EQL 1 THEN !DUMMY ARGUMENT
			BEGIN
				T2[ELMNT]_R2<RIGHT>_.ALST[ELMNT1];
				IF NAMDEF(IDDEFINE, .R2 ) LSS 0 THEN RETURN .VREG;
				IF .R2[OPRCLS] EQL DATAOPR THEN T2[P1AVALFLG] _ 1;
![663] WE ARE TRYING TO ASSIGN TYPE INFORMATION TO PARAMETERS OF
![663] SUBROUTINE AND ENTRY STATEMENTS.  THERE MAY BE INFORMATION
![663] ALREADY PRESENT REGARDING THESE VARIABLES, SO WE NEED TO BE
![663] VERY CAREFUL.  IF THE VARIABLE HAS ALREADY BEEN DIMENSIONED,
![663] THEN WE KNOW THAT IT IS A FORMLARRAY.  OTHERWISE, WE MIGHT
![663] HAVE SEEN IT PREVIOUSLY IN AN EARLIER SUBROUTINE OR ENTRY
![663] STATEMENT IN WHICH CASE WE NEED TO RETAIN THE SAME TYPE.
![663] SO IF IT IS EITHER A FORMLFN OR A FORMLVAR, RETAIN THAT TYPE
![663] INFORMATION.  FINALLY, IT MIGHT HAVE OCCURRED AS A FUNCTION
![663] NAME (AS IN AN EXTERNAL DECLARATION) - IN THIS CASE CHANGE
![663] THE TYPE TO FORMLFN SO THAT SPACE WILL BE ALLOCATED FOR THE
![663] VARIABLE NAME.  IF NONE OF THE ABOVE, THEN THE VARIABLE
![663] IS A SIMPLE ONE - FORMLVAR.
%[663]%				IF .R2[IDDIM] EQL 0 THEN
%[663]%				  (IF .R2[OPERSP] NEQ FORMLFN THEN
%[663]%					IF .R2[OPERSP] EQL FNNAME 
%[663]%					THEN R2[OPERSP]_FORMLFN
%[663]%					ELSE R2[OPERSP]_FORMLVAR)
%[663]%				ELSE
				   BEGIN
				     LOCAL BASE DIMPTR;
				     R2[OPERSP] _ FORMLARRAY;
				      DIMPTR _ .R2[IDDIM];
				     IF .DIMPTR[ARADDRVAR] EQL 0
					THEN IF NOT  .DIMPTR[ADJDIMFLG]
					  THEN BEGIN
						LOCAL BASE PTRVAR;
						ENTRY[0] _ .R2[IDSYMBOL];
						NAME _ IDTAB;
						PTRVAR _ NEWENTRY();
						PTRVAR[VALTYPE] _ INTEGER;
						PTRVAR[OPERSP] _ FORMLVAR;
						PTRVAR[IDATTRIBUT(NOALLOC)] _ 0;	!LET THIS BE ALLOCATED
						DIMPTR[ARADDRVAR] _ .PTRVAR;
						END;
				   END;
				R2[IDATTRIBUT(DUMMY)]_-1;  !DUMMY ARGUMENT
				IF .FLGREG<PROGTYP> EQL FNPROG  THEN IF .R2<RIGHT> EQL .R1<RIGHT>
				THEN ! ARGUMENT IS SAME AS FUNCTION
				  FATLEX( R2[IDSYMBOL], E71<0,0>);
			END
			ELSE( EXTERNAL  E129;
				  FLGREG<LABLDUM> _ 1;	!SET DUMMY LABLES FLAG
				 IF .FLGREG<PROGTYP>  EQL  FNPROG
				 THEN	WARNLEX (E129<0,0>);
					!ISSUE WARNING BECAUSE FUNCTIONS WITH
					! MULTIPLE RETURNS CANNOT BE REFERENCED
					! AS FUNCTIONS
				 T2[ELMNT]_0 !DUMMY LABEL
				);
			IF .ALST[ELMNT] LEQ 2 THEN ALST_.ALST+1; !IF ARG IS NOT A $ THE SKIP BY 1
		END;SAVSPACE(.T1<LEFT>,@T1);
		!------------------------------------------------------------------------
		!THE FOLLOWING CODE SETS UP T1 AS THE BLT POINTER
		!(SOURCE ADDRESS ^18+ DESTINATION ADDRESS AND T2 AS THE FINAL
		!ADDRESS.  R2 POINTS TO THE BEGINNING OF THE ARG BLOCK CREATED.
		!ITS FIRST WORD CONTAINS THE ARG COUNT.
		!------------------------------------------------------------------------
		STK[2]_0;	!LINK WORD
		T2_.T2-STK[3]<0,0>; !NUMBER OF ARGUMENTS

		% CHECK FOR DUPLICATE ARGUMENTS %
		INCR PRM FROM STK[4]<0,0> TO STK[4]<0,0>+.T2-2
		DO
		BEGIN
			MAP BASE PRM;
			LOCAL BASE PLST:ID1:ID2;
			IF ( ID1 _ @@PRM )  NEQ  0	!IE AN IDENTIFIER
			THEN
			BEGIN
				PLST _ .PRM+1;
				DO
				BEGIN
					IF ( ID2 _ @@PLST ) NEQ 0	!IDENTIFIER
					THEN
					BEGIN
						IF .ID1[IDSYMBOL] EQL  .ID2[IDSYMBOL]
						THEN	RETURN FATLEX(.ID1[IDSYMBOL],E87<0,0>)
					END
				END
				UNTIL	(PLST _ .PLST+1) EQL  STK[3]<0,0>+.T2+1;
			END;
		END;

		STK[3] _ .T2;
		NAME<LEFT> _ T2_ .T2+2; !ARG BLOCK CONTAINS 2+ NUM OF ARGS
		T2_.T2-1+(T1<RIGHT>_R2_CORMAN());
		T1<LEFT>_STK[2]<0,0>; BLT(T1,0,T2);!COPY ARG LIST FROM STACK
	END;
	NAME_IDOFSTATEMENT_ENTRDATA;NAME<RIGHT>_SORTAB;T1_NEWENTRY();
	IF @IDTYPE GEQ 0 THEN( R1[IDATTRIBUT(INTYPE)] _ -1;  R1[VALTYPE]_@IDTYPE);
	IF .TYPE EQL ENT THEN
	BEGIN
		T1[ENTNUM] _ -1;
		%LINK UP THE ENTRY POINTS FOR REL OUTPUT%
		R1[IDENTLNK] _ .MULENTRY;
		MULENTRY _ .R1;
	END;
	R1[IDATTRIBUT(FENTRYNAME)] _ 1; !SET ENTRY NAME BIT

	T1[ENTSYM]_@R1;T1[ENTLIST]_@R2;
	SAVSPACE(.FPNT<LEFT>,@FPNT);
END;
GLOBAL ROUTINE TYPEGEN(TLST) =
BEGIN
	LOCAL BASE T1;
	REGISTER BASE T2; REGISTER BASE R1:R2;
	EXTERNAL SAVSPACE %(SIZE,LOC)%,STK,BLDARRAY %(ONEARRAY LIST POINTER)%;
!-----------------------------------------------------------------------
!	THIS ROUTINE IS CALLED WITH THE PARAMETER TLST
!	POINTING TO A LIST OF ELEMTNTS. EACH
!	ELEMENT POINTS TO A LIST OF SCALAR OR ARRAY DEFINITIONS
!	(ONEARRAY) FOLLOWED BY AN OPTIONAL LIST OF VALUES. UNTIL
!	THE ROUTINES TO HANDLE DATA SPECIFICATIONS HAVE BEEN
!	WRITTEN THESE VALUE LISTS WILL BE IGNORED.
!-----------------------------------------------------------------------
	INCR DLST FROM @TLST TO @TLST+.TLST<LEFT> DO
	BEGIN
		MAP BASE DLST;
		R1_.DLST[ELMNT];
		!IF A VALUELIST IS PRESENT THEN BLDARRAY
		!MUST SAVE ALL THE SCALAR AND ARRAY NAMES IT FINDS, PROBABLY ON THE STACK
		IF BLDARRAY(.R1[ELMNT]) LSS 0 THEN RETURN .VREG;
		IF.R1[ELMNT1] NEQ 0 THEN				!OPTIONAL VALUELIST IS PRESENT
		BEGIN
			FATLEX(E84<0,0>);	!OPTIONAL VALUE LIST NOT SUPPORTED
			T1_.R1[ELMNT2];					!T1_LOC(VALUELIST)
!			T2_.T1[ELMNT1];					!T2_LOC(LIST OF CONSTANTS)
!			INCR CLST FROM @T2 TO @T2+.T2<LEFT> BY 2 DO
!			BEGIN
!				MAP BASE CLST;
!				IF .CLST[ELMNT] EQL 1 THEN		!CONSTANT POSSIBLY A REPEAT COUNT
!				BEGIN
!					R1_.CLST[ELMNT1];
!					IF .R1[ELMNT1] NEQ 0 THEN
!					BEGIN				!SAVE REPEATED CONSTANT SPACE
!						R2_.R1[ELMNT2];SAVSPACE(.R2<LEFT>,@R2)
!					END;
!					SAVSPACE(.R1<LEFT>,@R1);	!SAVE CONSTANT SPACE
!				END;
!			END; SAVSPACE(.T2<LEFT>,@T2);			!SAVE CONSTANT LIST SPACE
			SAVSPACE(.T1<LEFT>,.T1);			!SAVE VALUE LIST SPACE
		END
	END;
END;
GLOBAL ROUTINE TMPGEN (TYPE) =
BEGIN
	EXTERNAL TMPCNT[4],TBLSEARCH %()%;
	BIND TMPNAM=PLIT(
	%0%	SIXBIT 'TM.000',
	%1%	SIXBIT 'MF.000',
	%2%	SIXBIT 'OF.000',
	%3%	SIXBIT 'SZ.000');
	REGISTER BASE R3,R2,R1;MACHOP IDIVI=#231,LSHC=#246;
	R1_.TMPCNT[.TYPE]_.TMPCNT[.TYPE]+1;
	DECR I FROM 2 TO 0 DO (IDIVI(R1,10);LSHC(R2,-6));
	ENTRY[0]_.TMPNAM[.TYPE]+.R3<LEFT>;
	NAME_IDTAB;R3_TBLSEARCH();
	IF .TYPE EQL 0 THEN R3[OPR1]_VARFL;
	RETURN .R3
END;
GLOBAL ROUTINE BLDDIM (SSLST) =
BEGIN
	REGISTER BASE R1:R2:T1;
	LOCAL HISIGN,LOSIGN;
	EXTERNAL NEWENTRY %()%,SAVSPACE %(SIZE,LOC)%,IDTYPE,STK,CORMAN %()%,TBLSEARCH %()%,ONEPLIT,FARRY;
	EXTERNAL GENLAB;	!ROUTINE TO ADD A LABEL TABLE ENTRY FOR A COMPILER GENERATED LABEL
	REGISTER T2=2;  MAP BASE T2;
	MAP BASE FARRY;
	EXTERNAL E125,E126;

	EXTERNAL  DTABPTR;		! HEAD OF DIM ENTRY LIST

	LABEL  LDECR, CHECKTHIS;

	MACRO ERR46 = FATLEX(.FARRY[IDSYMBOL], E125<0,0>)$;
	MACHOP BLT=#251;
	!----------------------------------------------------------------------------------------------------------
	!SSLST POINTS TO A LIST OF SUBSCRIPTS OF THE FORM:
	!
	!CHOICE 1 - SUBSCRIPT IS A CONSTANT
	!	CONSTANT (21^18+LOC)
	!CHOICE 2 - SUBSCRIPT IS AN IDENTIFIER
	!	IDENTIFIER (20^18+LOC)
	!OPTION 0 - SUBSCRIPT IS UPPER BOUND, LOWER BOUND IS ONE
	!OPTION 1 - SUBSCRIPT IS LOWER BOUND
	!	COUNT^18+LOC - POINTER TO UPPER BOUND
	!		DIVIDE
	!		CHOICE 1 - SUBSCRIPT IS A CONSTANT
	!			CONSTANT (21^18+LOC)
	!		CHOICE 2 - SUBSCRIPT IS AN IDENTIFIER
	!			IDENTIFIER (20^18+LOC)
	!
	!SINCE THE KNOWLEDGE OF WETHER OR NOT THE DIMENSIONS ARE ADJUSTABLE OR IN ERROR IS NOT KNOWN UNTIL THE
	!LIST HAS BEEN SCANNED, A PSEUDO DIMENSION NODE IS CREATED ON THE UNUSED PORTION OF THE STACK
	! (STK[2] - STK[100]).
	!----------------------------------------------------------------------------------------------------------
	BIND ADJUSTABLE=STK[2],DNUM=STK[3]<LEFT>,ASIZE=STK[3]<RIGHT>,AOFF=STK[4],MF=1,OS=2,SZ=3;

	BIND  DLBL   =  STK [5] <LEFT>,		! TEMP ARADLBL
	      ALINK  =  STK [5] <RIGHT>,	! TEMP ARALINK
	      A0F    =  STK [7] <RIGHT>;	! TEMP DFACTOR (0)


	!----------------------------------------------------------------------------------------------------------
	!OMITTING THE EXTRA CODE TO FETCH CONSTANTS AND STORE VALUES, THE ARRAY SIZE, ARRAY OFFSET, AND
	!SUBSCRIPT MULTIPLICATION FACTOR ARE CALCULATED IN THE FOLLOWING MANNER:
	!
	!IF .IDTYPE GEQ DOUBLPREC THEN WORDSIZE_2 ELSE WORDSIZE_1;
	!ARRAYSIZE_.WORDSIZE;ARRAYOFFSET_0;
	!INCR I FROM 1 TO NUMBEROF DIMENSIONS DO
	!BEGIN
	!	FACTOR(.I)_.ARRAYSIZE;
	!	ARRAYOFFSET_.ARRAYOFFSET+.FACTOR(.I)*.LOWERLIMIT(.I);
	!	SUBSCRIPTSIZE_.UPPERLIMIT(.I)-.LOWERLIMIT(.I)+1;
	!	ARRAYSIZE_.ARRAYSIZE*.SUBSCRIPTSIZE;
	!END;
	!
	!FOR EXAMPLE:
	!
	!DOUBLE PRECISION A(2/5,3/5,4/5)
	!
	!WOULD PRODUCE
	!
	!FACTOR=		2	8	24
	!ARRAYOFFSET=		4	28	124
	!SUBSCRIPTSIZE=		4	3	2
	!ARRAYSIZE=		8	24	48
	!
	!THUS USING BLISS NOTATION, THE SECOND ELEMENT OF A, A(3,3,4) IS
	!.(A+2*3+8*3+24*4-124) WHICH EQUALS .(A+2) . THE ARRAY SIZE SPECIFIES THE
	!NUMBER OF WORDS OCCUPIED BY THE ARRAY, THUS IN THE ABOVE EXAMPLE ARRAY A OCCUPIES LOCATIONS A THRU A+47.
	!----------------------------------------------------------------------------------------------------------

	EXTERNAL INITLTEMP;
	ROUTINE ERRA =
	BEGIN
		RETURN FATLEX(FARRY[IDSYMBOL], E31<0,0>)
	END;
	ROUTINE ERRB (X)=
	BEGIN
		MAP BASE X;
		RETURN FATLEX(.X[IDSYMBOL],E126<0,0>)
	END;

![741] ROUTINE TO GIVE WARNING WHEN / ENCOUNTERED IN
![741] ANY BOUNDS FOR AN ARRAY DECLARATOR

%[741]%	GLOBAL ROUTINE SLASHWARN=
%[741]%	BEGIN
%[741]%		EXTERNAL E145;
%[741]%		WARNERR(.ISN,E145<0,0>); ! USE :, NOT /
%[741]%		RETURN 0
%[741]%	END;

	ROUTINE AJDIMSTK( PTR ) =
	BEGIN
		%SAVE THIS VARIABLE NAME ON A STACK BECAUSE IT IS
		 CURRENTLY NOT IN COMMON OR A DUMMY  BUT IT
		  MIGHT BE AFTER SOME ENTRY
		 STATEMENTS  %
		EXTERNAL	DIMSTK,NAME,CORMAN,LEXLINE;
		REGISTER R1;
	
		NAME<LEFT> _ 2;	!2 WORD ENTRIES
		R1 _ CORMAN();

		IF .DIMSTK  EQL  0
		THEN
		BEGIN
			DIMSTK<LEFT> _ .R1
		END;
		(.R1)<RIGHT> _ .DIMSTK<RIGHT>;
		DIMSTK<RIGHT> _ .R1;
		(.R1+1)<RIGHT> _ .PTR;
		(.R1+1)<LEFT>_ .LEXLINE
	END;

	T2_STK[3]<0,0>;
	IF .IDTYPE GEQ DOUBLPREC THEN ASIZE_2 ELSE ASIZE_1;
	ADJUSTABLE_AOFF_DNUM_0;
	INCR SS FROM @SSLST TO @SSLST+.SSLST<LEFT> DO
	BEGIN
		MAP BASE SS;
		HISIGN_LOSIGN_0;
		T2[DVARFLGS(0)]_0;T1_.SS[ELMNT];
		IF .T1[ELMNT] NEQ 0
		  THEN(IF .T1[ELMNT] EQL 2 THEN HISIGN_-1;
			T1_.T1+2;
		      )
		  ELSE T1_.T1+1;
		R1_.T1[ELMNT1];
		IF .R1[VALTYPE] NEQ INTEGER THEN RETURN ERRA();
		CASE .T1[ELMNT2] OF SET
		BEGIN	!OPTION 0 - LOWER LIMIT IS 1 BY DEFAULT
			T2[DIMENL(0)]_.ONEPLIT;
			IF .T1[ELMNT] EQL 1 THEN
			BEGIN	!CHOICE 1 - R1 = CONSTANT POINTER
				%DO THIS BUSINESS IN CASE OF NEGITIVE PARAMETER VALUES%
				IF .HISIGN NEQ 0
				   THEN R1 _ MAKECNST(INTEGER,0,-.R1[CONST2]); !MAKE NEG CONST NODE
				IF .R1[CONST2] LSS 0 THEN ERR46;!NO NEGATIVE DIMENSION
				!THE FOLLOWING CODE CURES A WHOLE
				! HOST OF PROBLEMS CONCERNING ERROR DETECTION
				! AND RECOVERY DURING DIMENSION PROCESSING, ESPECIALLY
				! REGARDING ARRAYS WHICH ARE TOO LARGE TO HANDLE.
				IF .R1[CONST2] EQL 0
				THEN FATLEX(FARRY[IDSYMBOL],E74<0,0>);
				!DO NOT TEST FOR TOO LARGE A SUBSCRIPT HERE -
				! WILL CATCH THIS LATER ON
				T2[DIMENU(0)]_.R1;
			END
			ELSE
			BEGIN	!CHOICE 2 - R1 = IDENTIFIER POINTER
				LOCAL SAV;
				IF .HISIGN NEQ 0 THEN ERR46;
				SAV _ .R1[IDATTRIBUT(NOALLOC)];	!SAVE IN CASE ITS NOT DUMMY YET
				IF NAMREF(VARIABL1,.R1) LSS 0 THEN RETURN .VREG;
				IF .R1[OPERSP] NEQ FORMLVAR AND NOT .R1[IDATTRIBUT(INCOM)] THEN
				(
				AJDIMSTK(.R1);	! CREATE AN ENTRY
				R1[IDATTRIBUT(NOALLOC)] _ .SAV; !RESTORE
				);
				T2[DVARUBFLG(0)]_1;T2[DIMENU(0)]_@R1;ADJUSTABLE_-1;
			END;
			IF .ADJUSTABLE EQL 0 THEN
			BEGIN
				LOCAL SAV; ! NEED FULL WORD TO TEST OVERFLOW
				EXTERNAL E141; ! NEW ERROR MESSAGE
				NAME_CONTAB;ENTRY[0]_0;ENTRY[1]_.ASIZE;SYMTYPE_INTEGER;
				T2[DFACTOR(0)]_TBLSEARCH();
				!AS THE COMPLETE ARRAY SIZE IS COMPUTED, DO NOT LET
				! IT GET TOO LARGE WITHOUT REPORTING THE ERROR
				AOFF_.AOFF-.ASIZE;
				SAV_.ASIZE*.R1[CONST2]; !FULL WORD SIZE
				IF .SAV GEQ 1^18 THEN FATLEX(.FARRY[IDSYMBOL],E141<0,0>);
				!NOW IT IS SAFE TO PUT THIS INTO A HALF WORD WHETHER
				! OR NOT THERE IS A TRUNCATION!
				ASIZE_.SAV;
			END
			ELSE
			BEGIN
				T2[DVARFACTFLG(0)]_1;T2[DFACTOR(0)]_0;
			END;
		END;
		BEGIN	!OPTION 1 - BOTH LOWER AND UPPER LIMITS ARE SPECIFIED
			LOCAL SAVPTR;	!FOR SAVING PTR FOR CALL TO SAVSPACE
			IF .T1[ELMNT] EQL 2 THEN
			BEGIN	!CHOICE 2 - R1=IDENTIFIER POINTER
				LOCAL SAV;
				IF .HISIGN NEQ 0 THEN ERR46;
				SAV _ .R1[IDATTRIBUT(NOALLOC)];	!SAVE IN CASE ITS NOT DUMMY YET
				IF NAMREF(VARIABL1,.R1) LSS 0 THEN RETURN .VREG;
				IF .R1[OPERSP] NEQ FORMLVAR AND NOT .R1[IDATTRIBUT(INCOM)] THEN
				(
				AJDIMSTK(.R1);	! CREATE AN ENTRY
				R1[IDATTRIBUT(NOALLOC)] _ .SAV; !RESTORE
				);
				T2[DVARLBFLG(0)]_1;ADJUSTABLE_-1;
			END;
			T1_.T1[ELMNT3]; !GET PTR TO UPPER BOUND BLOCK
			SAVPTR _ .T1;	!SAVING PTR FOR SAVSPACE CALL LATER
			IF .R1[OPERSP] EQL  CONSTANT
			THEN
				!DO NOT NEED TO CHECK HERE FOR ARRAY BOUND SIZE
				IF .HISIGN NEQ 0
				   THEN R1 _ MAKECNST(INTEGER,0,-.R1[CONST2]); !MAKE NEG CONST NODE
			T2[DIMENL(0)] _ .R1; !LOWER BOUND
			!T1 NOW POINTS TO UPPER BOUND PART
			!SEE IF IT IS SIGNED 
			!
			IF .T1[ELMNT2] NEQ 0 !ELMNT0-1 IS THE SLASH OR COLON
			  THEN(IF .T1[ELMNT2] EQL 2 THEN HISIGN _ -1 ELSE HISIGN _ 0;
				T1 _ .T1+3;
			      )
			  ELSE (HISIGN_0; T1 _ .T1+2;);
			R2_.T1[ELMNT2];
			IF .R2[VALTYPE] NEQ INTEGER THEN RETURN ERRA();
			IF .T1[ELMNT1] EQL 2 THEN
			BEGIN	!CHOICE 2 - R2 = IDENTIFIER POINTER
				LOCAL SAV;
				IF .HISIGN NEQ 0 THEN ERR46;
				SAV _ .R2[IDATTRIBUT(NOALLOC)];	!SAVE IN CASE ITS NOT DUMMY YET
				IF NAMREF(VARIABL1,.R2) THEN RETURN .VREG;
				IF .R2[OPERSP] NEQ FORMLVAR AND NOT .R2[IDATTRIBUT(INCOM)] THEN
				(
				AJDIMSTK(.R2);	! CREATE AN ENTRY
				R2[IDATTRIBUT(NOALLOC)] _ .SAV; !RESTORE
				);
				T2[DVARUBFLG(0)]_1;ADJUSTABLE_-1;
			END;
			IF .R2[OPERSP] EQL CONSTANT
			THEN
				!DO NOT TEST ON INDIVIDUAL ELEMENTS HERE!
				IF .HISIGN NEQ 0
				  THEN R2 _ MAKECNST(INTEGER,0,-.R2[CONST2]);
			T2[DIMENU(0)]_.R2;
			IF .ADJUSTABLE EQL 0 THEN
			BEGIN
				!ALSO NEED TO CHECK THE CASE WITH UPPER AND
				! LOWER BOUNDS.
				LOCAL SAV;
				EXTERNAL E141; ! ARRAY TOO LARGE
				IF .R1[CONST2] %LOWER BOUND%
					GTR .R2[CONST2] %UPPER BOUND%
					  THEN FATLEX( FARRY[IDSYMBOL],E74<0,0>);

					!ERROR IF LOWER GTR UPPER BOUND
				NAME_CONTAB;ENTRY[0]_0;ENTRY[1]_.ASIZE;SYMTYPE_INTEGER;
				T2[DFACTOR(0)]_TBLSEARCH();
				AOFF_.AOFF-.ASIZE*.R1[CONST2];
				!CHECK FOR TOTAL SPACE NEEDED FOR THIS ARRAY
				SAV_.ASIZE*(.R2[CONST2]-.R1[CONST2]+1);
				IF .SAV GEQ 1^18 THEN FATLEX(.FARRY[IDSYMBOL],E141<0,0>);
				ASIZE_.SAV; !SAFE NOW TO SET UP ASIZE
			END
			ELSE
			BEGIN
				T2[DVARFACTFLG(0)]_1;T2[DFACTOR(0)]_0;
			END;
			SAVSPACE(.SAVPTR<LEFT>,.SAVPTR);
		END
		TES;
		T1_.SS[ELMNT]; !FOR SAVSPACE CALL
		SAVSPACE(.T1<LEFT>,.T1);DNUM_.DNUM+1;T2_.T2+2;
	END;
	!----------------------------------------------------------------------------------------------------------
	!STK[2] THRU STK[(.DNUM+1)*2] NOW CONTAINS A DIMENSION NODE. USE THE CORMAN ROUTINE TO CREATE
	!A REAL DIMENSION NODE AND COPY THE NODE FROM THE STACK.
	!----------------------------------------------------------------------------------------------------------
	IF .ADJUSTABLE NEQ 0 THEN
	   BEGIN
		!--------------------------------------------------------------------------------------------------
		!IF THE DIMENSIONS ARE ADJUSTABLE CREATE A SPECIAL SET OF TEMPS TO BE USED BY ADJ. TO
		!CALCULATE THE MULTIPLICATIVE FACTORS. ALSO SET ADJDIMFLG
		!--------------------------------------------------------------------------------------------------
		!FOR ADJ. THEY MUST BE IN A SPECIAL ORDER
		!ASIZE
		!OFFSET
		!FACTOR N-1
		! .
		! .
		! .
		!FACTOR 1
		EXTERNAL  FATLEX,E137;

	  LOCAL BASE  PTR;
	  LOCAL DIMENTRY  E;

		%CHECK TO SEE IF ADJUSTABLES ARE LEGAL %
		IF .FLGREG<PROGTYP>  NEQ  SUPROG
		  AND  .FLGREG<PROGTYP>  NEQ  FNPROG
		THEN	RETURN FATLEX(E137<0,0>);

		!CHECK FOR ADJUSTABLE ARRAY NOT A DUMMY
		IF NOT .FARRY[IDATTRIBUT(DUMMY)] THEN AJDIMSTK(.FARRY);
		ASIZE_INITLTEMP(INTEGER);
		AOFF<LEFT>_INITLTEMP(INTEGER);

		A0F_ IF .FARRY [DBLFLG]	! SET ELEMENT SIZE
		       THEN MAKECNST (INTEGER, 0, 2)
		       ELSE .ONEPLIT;
		DECR  I  FROM .DNUM - 1  TO 1  DO
LDECR:		  BEGIN
		    T2 _ .T2 - 2;	! DIMSUBENTRY (I)
		    IF .T2 [DFACTOR (0)] NEQ 0
		      THEN LEAVE LDECR;
		    IF NOT .T2 [DVARUBFLG (0)] OR
		       .T2 [DIMENL (0)] NEQ .ONEPLIT  OR
		       .I NEQ 1
		      THEN BEGIN
			T2 [DFACTOR (0)] _ INITLTEMP (INTEGER);
			LEAVE LDECR;
		      END;
		!I == 1 => T2 [...(0)] IS FOR 2ND DIM
		    PTR _ .DTABPTR <RIGHT>;
		    WHILE  .PTR NEQ 0
		      DO BEGIN
			E _ .PTR;
CHECKTHIS:		BEGIN
			  IF .E [DIMNUM] LSS 2
			    THEN LEAVE CHECKTHIS;
			  IF NOT .E [ADJDIMFLG]
			    THEN LEAVE CHECKTHIS;
			  IF .E [DFACTOR (0)] NEQ .A0F	! SAME ELEMENT SIZE
			    THEN LEAVE CHECKTHIS;
			!IF DIM1 SAME THEN SHARE FACTOR FOR DIM2
			  IF .E [DIMENU (0)] EQL .T2 [DIMENU (-1)]  AND
			     .E [DIMENL (0)] EQL .ONEPLIT
			    THEN BEGIN
			      PTR _ .E [DFACTOR (1)];
			      T2 [DFACTOR (0)] _ .PTR;
			      PTR [IDUSECNT] _ .PTR [IDUSECNT] + 1;	! UPDATE SHARING COUNT
			      LEAVE LDECR;
			    END;
			END;	! OF CHECKTHIS
		        PTR _ .E [ARALINK];	! NEXT ENTRY
		      END;	! OF WHILE .PTR NEQ 0
		    PTR _ INITLTEMP (INTEGER);		! NO MATCH FOUND
		    T2 [DFACTOR (0)] _ .PTR;
		    PTR [IDUSECNT] _ 1;			! 1ST USAGE: NO SHARING
		  END;	! OF LDECR
		T2 _ .T2 - 2;		! SUBENTRY (0)
		T2 [DVARFACTFLG (0)] _ 0;
		T2 [ADJDIMFLG] _ 1;

	   END
	   ELSE AOFF<LEFT> _ MAKECNST(INTEGER,0,.AOFF); !MAKE CONST NODE FOR OFFSET VALUE
		SAVSPACE(.SSLST<LEFT>,@SSLST);
!
!NOW MAKE A REAL DIMENSION NODE TRANSFERING THE INFORMATION ON THE
!TEMPORARY STACK (STK) TO THE DIMENSION NODE OF SIZE (.DNUM+1)*2
!
	NAME<LEFT>_T2_DIMSIZ+.DNUM*DIMSUBSIZE;
	T2 _ .T2-1; !ONE LESS FOR UPCOMING BLT
	T2_.T2+(T1_(NAME<RIGHT>_DIMTAB; NEWENTRY()));
	 !ADD THE PTR TO THE NEW DIMENSION NODE TO T2 (THE NUMBER OF WORDS IN THE BLOCK MINUS 1)

	DLBL _ 0;			! FOR SAFETY
	ALINK _ .DTABPTR <RIGHT>;	! LINK THIS ENTRY INTO LIST
	DTABPTR <RIGHT> _ .T1;			! NEW LIST HEAD

	BEGIN LOCAL SAVT1;
		T1<LEFT>_STK[3]<0,0>;
		SAVT1 _.T1; !SAVING T1 INCASE OF BLT INTERRUPT
		BLT(T1,0,T2); !MOVE THE BLOCK TO NEW LOCATION
		T1 _ .SAVT1;
	END;
	IF .FARRY[OPERSP] EQL FORMLARRAY
	THEN
	(  IF .ADJUSTABLE EQL 0
	   THEN BEGIN
		!MAKE A POINTER VARIABLE TO BE A COPY OF ARRAY'S SYMBOL TABLE NODE
		!AND PUT IT IN THE DIMENSON NODE
		LOCAL BASE PTRVAR;
		ENTRY[0] _ .FARRY[IDSYMBOL]; NAME _ IDTAB;
		PTRVAR _ NEWENTRY();
		PTRVAR[IDATTRIBUT(NOALLOC)] _ 0;	!LET THIS BE ALLOCATED
		PTRVAR[VALTYPE] _ INTEGER;
		PTRVAR[OPERSP]  _ FORMLVAR;	!MAKE IT A FORMAL DUMMY
		T1[ARADDRVAR] _ .PTRVAR; !PTR VARIABLE TO DIMENSION NODE
	       END;
	) ELSE T1[ARADDRVAR] _ 0;

	RETURN .T1	!PTR TO DIMENSION NODE
END;
GLOBAL ROUTINE BLDARRAY (LPNT) =
BEGIN
	REGISTER T2=2;  MAP BASE  T2;
	REGISTER BASE T1;REGISTER BASE R2;  LOCAL BASE R1;
	EXTERNAL GENLAB;	!ROUTINE TO ADD A COMPILER GEBERATED LABEL
	EXTERNAL SAVSPACE %(SIZE,LOC)%,IDTYPE,FARRY,TYPE,STK,NAMDEF;
	MACRO ERR4=
	BEGIN
		RETURN  FATLEX( T1[IDSYMBOL],PLIT'VARIABLE',E4<0,0> )
	END$;
	MACRO ERR41=
	BEGIN
		RETURN FATLEX (T1[IDSYMBOL],FARRY[IDSYMBOL],E41<0,0>)
	END$;
	MACRO
	ERR42=RETURN FATLEX(T1[IDSYMBOL], E42<0,0>)$,
	ERR34(X)= RETURN FATLEX ( PLIT'X?0', T1[IDSYMBOL], E34<0,0>)$;
	BIND BASE CBLOCK=STK[2];
	LOCAL POINTER;

	LABEL  OUT, CHECKTHIS;
	EXTERNAL  DTABPTR, ONEPLIT, INITLTEMP;
	LOCAL BASE  PTR;		! TO MARCH DOWN DIM ENTRY LIST
	LOCAL DIMENTRY  E;		! ONE ELEMENT ON THAT LIST

ROUTINE CHKCOMMON ( T1 ) =	!CHECKS COMMON DECLARATIONS
BEGIN
		MAP BASE T1;
			BEGIN	!COMMON STATEMENT
				IF .T1[IDATTRIBUT(INCOM)] THEN ERR42
					ELSE IF .T1[IDATTRIBUT(DUMMY)] THEN ERR34(DUMMY);
				T1[IDATTRIBUT(INCOM)]_1;
				IF .CBLOCK<LEFT> EQL 0 THEN
				BEGIN
					CBLOCK<LEFT>_CBLOCK<RIGHT>_@T1;
				END
				ELSE
				BEGIN
					CBLOCK[IDCOLINK]_@T1;CBLOCK<RIGHT>_@T1;
				END;
			END
END;	!OF CHKCOMMON
	!----------------------------------------------------------------------------------------------------------
	!THE PARAMETER LPNT POINTS TO A LIST OF ONEARRAY'S, THAT IS TO SAY EACH ELEMENT OF THE LIST POINTED TO
	!BY LPNT IS A POINTER TO A LIST OF THE FORM:
	!
	!IDENTIFIER (20^18+LOC) - FIRST ARRAY NAME
	!OPTION 0 OR OPTION 1 - ADDITIONAL ARRAY NAMES AND SUBSCRIPTS FOLLOW
	!	COUNT^18+LOC - LIST POINTER
	!VARIABLE TYPE - ONLY IF THIS IS A TYPE STATEMENT
	!
	!THE LOCATION IDTYPE CONTAINS THE VARIABLE TYPE TO BE SET IN EACH ARRAY NAME. IF IDTYPE IS LESS THAN ZERO,
	!NO TYPE IS SPECIFIED AND AN OPTION 0 (NO SUBSCRIPTS) IS ILLEGAL. IDTYPE IS SET LESS THAN ZERO FOR
	!DIMENSION, AND GLOBAL STATEMENTS.
	!IDTYPE FOR TYPE STATEMENTS IS NOW IN THE TREE IN ORDER TO IMPLIMENT THE *N TYPE OVERRIDE FEATURE
	!----------------------------------------------------------------------------------------------------------
	INCR OA FROM .LPNT TO .LPNT+.LPNT<LEFT> DO
	BEGIN
		MAP BASE OA;	!OA STANDS FOR ONEARRAY
		R1_.OA[ELMNT];
		FARRY_T1_.R1[ELMNT];
		IF .TYPE EQL  4 %TYPE STATEMENT%
		THEN
		BEGIN
			IDTYPE _ .R1[ELMNT1];	!GET TYPE FROM TREE - POSSIBLE *N CONSTRUCT
			R1 _ .R1 + 1;	!SKIP TYPE
		END
		ELSE
			IDTYPE_.T1[VALTYPE];
		IF .R1[ELMNT1] EQL 0 THEN
		BEGIN	!OPTION 0 - NO SUBSCRIPTS
			CASE .TYPE OF SET
			ERR4;	!DIMENSION
			BEGIN	!GLOBAL
				!IF .T1[IDATTRIBUT(INCOM)]THEN ERR34(COMMON)
				!	ELSE IF .T1[IDATTRIBUT(INEXTERN)]THEN ERR34(EXTERNAL);
				!T1[IDATTRIBUT(INGLOB)]_1
			END;
			BEGIN	!EXTERNAL
				!GONE
			END;
			BEGIN	!PROTECT
				!GONE
			END;
			BEGIN	!TYPE STATEMENT
				LOCAL DUB;	!SET TO 4 FOR CONVERSION TO
						! DOUBLE PRECISION AND
						!TO 1 FOR CONVERSION TO
						!SINGLE PECISION
				LABEL ADJ;
				IF .T1[IDDIM] NEQ 0
				THEN
				ADJ:BEGIN
					IF .IDTYPE GEQ DOUBLPREC
					THEN 
					BEGIN
						IF .T1[VALTYPE] LSS DOUBLPREC
						THEN 	DUB _ 4
						ELSE	LEAVE ADJ
					END
					ELSE
					BEGIN
						IF .T1[VALTYPE] GEQ DOUBLPREC
						THEN	DUB _ 1	!CONVERT TO SINGLE PRECISION
						ELSE	LEAVE ADJ
					END;
					R2 _ .T1[IDDIM];
					IF NOT .R2[ADJDIMFLG]
					THEN
					BEGIN
					       R2[ARASIZ] _ (.R2[ARASIZ]*.DUB ) / 2;
						T2 _ .R2[ARAOFFSET];
						R2[ARAOFFSET] _ MAKECNST(INTEGER,0,( .T2[CONST2] * .DUB ) / 2 );
						DECR I FROM .R2[DIMNUM]-1 TO 0 DO
						BEGIN
						   T2 _ .R2[DFACTOR(.I)];
						   R2[DFACTOR(.I)] _ MAKECNST(INTEGER,0, ( .T2[CONST2] * .DUB ) / 2 );
						END
					END
					ELSE
					BEGIN !DO ONLY FOR FIRST FACTOR IF ADJUSTABLE
%[627]%						DECR I FROM .R2[DIMNUM]-1 TO 0 DO
%[627]%							IF NOT .R2[DVARFACTFLG(.I)] THEN
%[627]%							BEGIN
%[627]%								T2 _ .R2[DFACTOR(.I)];
%[627]%								R2[DFACTOR(.I)] _ MAKECNST(INTEGER,0, ( .T2[CONST2] * .DUB ) / 2 );
%[627]%							END;
	OUT:					BEGIN
						  IF .R2 [DIMNUM] LSS 2	
						    THEN LEAVE OUT;
						  IF NOT .R2 [DVARUBFLG (1)]
						    THEN LEAVE OUT;
						  IF .R2 [DIMENL (1)] NEQ .ONEPLIT
						    THEN LEAVE OUT;
						  T2 _ .R2 [DFACTOR (1)];
						  T2 [IDUSECNT] _ .T2 [IDUSECNT] - 1;
						  IF .T2 [IDUSECNT] EQL 0
						    THEN T2 [IDATTRIBUT (NOALLOC)] _ 1;	! NOT SHARED NOW: DON'T ALLOC
						  PTR _ .DTABPTR<RIGHT>;
						  WHILE .PTR NEQ 0
						    DO BEGIN
						      E _ .PTR;
	CHECKTHIS:				      BEGIN
							IF .E EQL .R2		! DON'T SHARE WITH YOURSELF
							  THEN LEAVE CHECKTHIS;
							IF .E [DIMNUM] LSS 2
							  THEN LEAVE CHECKTHIS;
							IF NOT .E [ADJDIMFLG]
							  THEN LEAVE CHECKTHIS;
							IF .E [DFACTOR (0)] NEQ .R2 [DFACTOR (0)]	! SAME ELEMENT SIZE ?
							  THEN LEAVE CHECKTHIS;
							IF .E [DIMENU (0)] NEQ .R2 [DIMENU (0)]
							  THEN LEAVE CHECKTHIS;
							IF .E [DIMENL (0)] NEQ .ONEPLIT
							  THEN LEAVE CHECKTHIS;
	!		DIM 1 SAME: SHARE FACTOR FOR DIM2
							PTR _ .E [DFACTOR (1)];
							R2 [DFACTOR (1)] _ .PTR;
							PTR [IDUSECNT] _ .PTR [IDUSECNT] + 1;	! UPDATE SHARING COUNT
							LEAVE OUT;
						      END;	! OF CHECKTHIS
						      PTR _ .E [ARALINK];	! NEXT ENTRY
						    END;	! OF WHILE .PTR NEQ 0
						  IF .T2 [IDUSECNT] EQL 0	! NO MATCH FOUND
						    THEN T2 [IDATTRIBUT (NOALLOC)] _ 0	! USE OLD .I WHICH WAS DEALLOCED
						    ELSE T2 _ INITLTEMP (INTEGER);	! GET NEW .I TEMP
						  R2 [DFACTOR (1)] _ .T2;
						  T2 [IDUSECNT] _ 1;		! 1ST USAGE: NO SHARING
						END;	! OF OUT
					END
				END;	!ADJ BLOCK
				IF NAMDEF(IDDEFT, .T1) LSS 0 THEN RETURN .VREG;
				T1[IDATTRIBUT(INTYPE)] _ 1;
				T1[VALTYPE]_.IDTYPE;
				R1 _ .R1 -1	!RESTORE FOR SAVSPACE
			END;
			BEGIN	%COMMON%
				IF NAMDEF( VARARY, .T1) LSS 0 THEN RETURN .VREG;
				CHKCOMMON(.T1);	!ROUTINE TO CHECK COMMON DECLARATION
			END
			TES;
		END
		ELSE

		BEGIN	!OPTION 1 - ARRAY NAMES AND SUBSCRIPTS
			MAP BASE FARRY;
			LOCAL SAVSTK;
			MACRO IDCHECK =
			BEGIN
				CASE @TYPE OF SET
				BEGIN	%DIMENSION%
					IF NAMDEF(ARRYDEF,.T1) LSS 0 THEN RETURN .VREG
				END;
				BEGIN	!GLOBAL
					!IF .T1[IDATTRIBUT(INCOM)] THEN ERR34(COMMON)
					!	ELSE IF .T1[IDATTRIBUT(INEXTERN)] THEN ERR34(EXTERNAL);
					!T1[IDATTRIBUT(INGLOB)]_1
				END;
				BEGIN	!EXTERNAL
				END;
				BEGIN	!PROTECT
				END;
				BEGIN	!TYPE STATEMENT
					IF NAMDEF(ARRYDEFT,.T1) LSS 0 THEN RETURN .VREG;
					T1[IDATTRIBUT(INTYPE)] _ 1;
					T1[VALTYPE]_.IDTYPE;
					R1 _ .R1-1	!RESTORE FOR SAVSPACE
				END;
				BEGIN	%COMMON%
					IF NAMDEF (ARRYDEF,.T1) LSS 0 THEN RETURN .VREG;
					IF CHKCOMMON(.T1) LSS 0 THEN RETURN .VREG;	!CHECK COMMON DECLARATIONS
				END
				TES;
				IF .T1[OPERSP] EQL VARIABLE THEN T1[OPERSP]_ARRAYNAME
					ELSE T1[OPERSP]_FORMLARRAY;
			END$;
			R2 _ .R1[ELMNT2];
			IDCHECK;
			SAVSTK_.STK[2]; !SAVING COMMON LIST POINTERS IF PROCESSING COMMON LISTS

			IF (T2_BLDDIM(.R2[ELMNT])) LSS 0 THEN RETURN .VREG
				ELSE
				BEGIN
					 FARRY[IDDIM]_.T2;
					IF .FLGREG<BOUNDS>	!IF SS BOUNDS CHECKING IS TO BE PERFORMED
								! ON ALL ARRAYS (USER "BOUNDS" SWITCH)
						OR .FLGREG<DBGDIMN>	!OR THE "DEBUG" SWITCH WAS SPECIFIED
					THEN T2[ARADLBL]_GENLAB();	!GENERATE A LABEL TO GO ON THE BLOCK
							! THAT WILL BE OUTPUT DESCRIBING THE DIMENSION
							! INFORMATION FOR THIS ARRAY
				END;
			STK[2]_.SAVSTK;


		END;SAVSPACE(.R1<LEFT>,@R1);
	END;SAVSPACE(.LPNT<LEFT>,@LPNT);
END;
GLOBAL ROUTINE BLKSRCH	(BLKNAME)=
BEGIN
	REGISTER BASE R1:R2;
	EXTERNAL NEWENTRY %()%,COMBLKPTR;
	!---------------------------------------------------------------------------------
	!THIS ROUTINE FINDS OR CREATES THE COMMON BLOCK "NAME" AND
	!RETURNS A POINTER TO IT.
	!---------------------------------------------------------------------------------
	R1_.COMBLKPTR<LEFT>;
	UNTIL .R1 EQL 0 DO
	BEGIN
		IF .R1[COMNAME] EQL .BLKNAME THEN RETURN .R1;
		R1_.R1[NEXCOMBLK];
	END;
	ENTRY[0]_.BLKNAME;
	NAME_COMTAB;R2_NEWENTRY();
	RETURN .R2
END;
GLOBAL ROUTINE BLDVAR (VPNT)=
BEGIN
	LOCAL  BASE T2;
	GLOBAL SETUSE;	! SET TO SET/USE BY CALLER
	REGISTER  BASE	T1;REGISTER BASE R1:R2;
	EXTERNAL SAVSPACE %(SIZE,LOC)%,NEWENTRY %()%,ARRXPND %(NAME,SUBSCRIPTS)%;
	!--------------------------------------------------------------------------
	!THE PARAMETER VPNT POINTS TO THE LIST:
	!
	!IDENTIFIER (20^18+LOC) - THE SCALAR OR ARRAY VARIABLE
	!OPTION 0 OR OPTION 1 - SUBSCRIPTS FOLLOW
	!		1^18+LOC - POINTER TO SUBSCRIPT LIST POINTER
	!			COUNT^18+LOC - POINTER TO A LIST OF SUBSCRIPT EXPRESSIONS
	!--------------------------------------------------------------------------
	T1_.VPNT;T2_.T1[ELMNT];!T2_LOC(IDENTIFIER)
	IF .T1[ELMNT1] EQL 0 THEN
	BEGIN	%SCALAR%
		IF .SETUSE EQL  SETT
		THEN	NAMSET(VARYREF, .T2)
		ELSE	NAMREF(VARYREF,.T2);
		IF .VREG LSS 0 THEN T2 _ -1
		ELSE T2<LEFT>_IDENTIFIER	! USED BY ASSISTA AND GOTO - EVERYONE ELSE WILL
						! ACCEPT AN UNSUBSCRIPTE ARRRAY REF HERE
	END
	ELSE
	BEGIN
		IF .SETUSE EQL  SETT
		THEN	NAMSET(ARRAYNM1, .T2)
		ELSE	NAMREF(ARRAYNM1, .T2);
		IF .VREG LSS 0 THEN RETURN .VREG;
		R1_.T1[ELMNT2];R2_.R1[ELMNT];SAVSPACE(0,@R1); !CHANGED 1 TO 0
		INCR SCR FROM @R2 TO @R2+.R2<LEFT> DO
		BEGIN
			MAP BASE SCR;MACRO SCRFLGS=0,0,LEFT$,SCRPTR=0,0,RIGHT$;
			R1_.SCR[ELMNT];			SCR[SCRPTR]_@R1;SCR[SCRFLGS]_0;
		END;
		IF (T2_ARRXPND(@T2,@R2)) GTR 0
		THEN	T2<LEFT>_ARRAYREF;
	END;
	SAVSPACE(.VPNT<LEFT>,@VPNT);
	RETURN .T2!RETURN POINTER TO SCALAR OR ARRAY EXPRESSION
END;
GLOBAL ROUTINE DATALIST (LPNT)=
BEGIN
	LOCAL  BASE T2;
	REGISTER BASE T1;REGISTER BASE R1:R2;
	EXTERNAL TBLSEARCH,SP,DOXPN;
	EXTERNAL BLDVAR%(VPNT)%,SAVSPACE %(SIZE,LOC)%,TYPE,ONEPLIT,STK,CORMAN %()%;
	EXTERNAL SETUSE;
	EXTERNAL GENLAB,NEWENTRY,DATASUBCHK;

	EXTERNAL  CKDOINDEX;		! CHECK DO INDEX ALREADY ACTIVE
	EXTERNAL  DOCHECK;		! REMOVE DO LABEL FROM ACTIVE DO LIST
	EXTERNAL  E21;			! DO INDEX ALREADY ACTIVE MESSAGE

	MACRO  ADDOLAB (X,Y) =		! PUT INDEX ON ACTIVE DO LIST
		BEGIN
		EXTERNAL  LASDOLABEL;	! PTR TO END LABEL,,INDEX OF MOST RECENT DO
		EXTERNAL  CURDOINDEX;	! PTR TO CURRENT DO INDEX VARIABLE
		LOCAL BASE  TEMP;
			NAME<LEFT> _ 2;			! LINK IN NEW LABEL
			TEMP _ CORMAN ();
			TEMP [ELMNT] _ .LASDOLABEL;	! SAVE LAST
			TEMP [ELMNT1] _ .CURDOINDEX;	! SAVE INDEX
			LASDOLABEL<LEFT> _ .TEMP;
			LASDOLABEL<RIGHT> _ X;
			CURDOINDEX _ Y;			! INDEX PTR
		END$;

	LOCAL SAVEBOUNDSFLG;	! TO SAVE THE VALUE OF THE "BOUNDS"
				! SWITCH WHILE PROCESSING THE DATA
				! LIST FOR A DATA STMNT
	MACRO
	ERR38=(RETURN FATLEX(E38<0,0>))$, !INDEX VARIABLE NOT VARIABLE
	ERR44=RETURN FATLEX(TDOSYM[IDSYMBOL],E44<0,0>)$;
	!
	!MACROS FOR DATALIST NODE GENERATION FOR IOLISTS,DATA LISTS
	!
	MACRO SIZOFARRAY=
	BEGIN
	  IF NOT .SYMBL[DBLFLG]
		THEN(IF NOT .T2[ADJDIMFLG]
			THEN MAKECNST(INTEGER,0,.T2[ARASIZ])
			ELSE .T2[ARASIZ]	!PTR TO TEMP FOR ADJ DIMENSION
		    )
		ELSE(IF NOT .T2[ADJDIMFLG]
			THEN MAKECNST(INTEGER,0,.T2[ARASIZ]/2)
			ELSE(	NAME _ EXPTAB;
				T1 _ NEWENTRY();
				!MAKE A DIVIDE NODE .T2[ARASIZ]/2
				T1[ARG1PTR] _ .T2[ARASIZ];
				T1[ARG2PTR] _ MAKECNST(INTEGER,0,2);
				T1[A1VALFLG] _ T1[A2VALFLG] _ 1; !SETTING FLAGS
				T1[OPERATOR] _ INTDIVIDE;
				T1[PARENT] _ .R1;	!POINTS BACK TO DATA LIST NODE
				.T1	!PTR TO ASSIGN TO SCALLCT
			    )
		     )
	END$;
	MACRO IODATANODE(X)=
%[635]%	BEGIN
		NAME _ IOLTAB;	!IOLIST TABLE
		R1_X;
		T2 _ .R1[ELMNT];
		IF .TYPE EQL READD THEN
		SETUSE _ SETT	!BLDVAR FLAG
		ELSE
		IF .TYPE EQL DATALST THEN
		  BEGIN
			SETUSE _ SETT;
			IF .T2[IDATTRIBUT(INDATA)] EQL 1	!SEE IF IT'S
			AND .T2[IDDIM] EQL 0	!NOT AN ARRAY BUT
			THEN		!ALREADY IN A DATA STATEMENT
			FATLEX(T2[IDSYMBOL],E139<0,0>);	!WARN HIM
			T2[IDATTRIBUT(INDATA)] _ 1;
%[635]%			IF .T2[IDATTRIBUT(DUMMY)] THEN RETURN FATLEX( T2[IDSYMBOL],E66<0,0>);
		   END
		   ELSE	SETUSE _ USE;

		IDOFSTATEMENT _  IF .R1[ELMNT1] NEQ 0 THEN DATACALL
					ELSE (R1_.R1[ELMNT]; !PTR TO SYMBOL
						IF .R1[IDDIM] NEQ 0 THEN (NAME<LEFT>_ 3;SLISTCALL) ELSE DATACALL
					    );
		R1_NEWENTRY();
		R1[OPERSP] _ .IDOFSTATEMENT;  !DATACALL OR SLISTCALL
		IF .LISTLINK EQL 0
		  THEN (LISTLINK<LEFT>_LISTLINK<RIGHT>_.R1)
		  ELSE (LISTLINK[CLINK] _ .R1; LISTLINK<RIGHT>_.R1);
		R1[OPRCLS] _ IOLSCLS;	!IOLIST CLASS
		R1[DCALLELEM] _ BLDVAR(X);
		IF .VREG LSS 0 THEN (R1[DCALLELEM] _ 0; RETURN -1); !VREG IS -1 IF BLDVAR FOUND AN ERROR
		IF .R1[OPERSP] EQL SLISTCALL
		THEN BEGIN
			LOCAL BASE SYMBL;
			!FIX UP OPERSP BECAUSE NEWENTRY
			!HAS SET SRCID
			R1[SRCID]_0;
			R1[OPERSP]_SLISTCALL;
			SYMBL _ .R1[DCALLELEM];
			T2 _ .SYMBL[IDDIM]; !PTR TO DIMENSION NODE
			R1[SCALLCT] _ SIZOFARRAY;	!PTR TO NODE CONTAINING NUM OF ELEMENTS IN ARRAY
		    END;
	END$;
	MACRO IODONODE(X)=
	BEGIN
		IDOFSTATEMENT_NAME_DODATA;
		NAME<RIGHT> _ IOLTAB;
		T1_NEWENTRY();
		T1[CLINK]_ .X<LEFT>; X<LEFT>_ .T1;
		T1[OPRCLS]_STATEMENT;
		T1[DOLBL] _ .IOLBL;	!PSEUDO LABEL MADE BY IOCONTNODE
		T2_.IOLBL[SNDOLNK]; 
		IOLBL[SNDOLVL] _ .IOLBL[SNDOLVL]+1;
		NAME<LEFT> _ 1; IOLBL[SNDOLNK] _ CORMAN();
		(.VREG)<LEFT>_.T1; (.VREG)<RIGHT>_.T2; !LINKING IN ENDING LBL TO DO NODE AND LABEL TABLE
	END$;
	MACRO IOCONTNODE =
	BEGIN
		IDOFSTATEMENT_NAME_CONTDATA;	!NODE IDENTIFICATION AND SIZE
		NAME<RIGHT> _ IOLTAB;
		T1_NEWENTRY();
		T1[OPRCLS]_STATEMENT;
		IOLBL _ T1[SRCLBL]_ GENLAB();
		IOLBL[SNREFNO]_2;	!REFERENCE COUNT OF 2
		IOLBL[SNHDR] _ .T1	!PTR TO CONTINUE IN LABEL TABLE NODE
	END$;

	MACRO ADDCONTNODE (X) =
 BEGIN
		T1 _ .IOLBL [SNHDR];	! GET NODE FROM IOCONTNODE
		X [CLINK] _ .T1;	! LINK IN CONT NODE AT END OF LOOP
		X<RIGHT> _ .T1;		! POINT TO NEW END OF DATALIST
	END$;

	LOCAL BASE LISTLINK;	!PTR TO FIRST<LEFT> AND LAST<RIGHT> NODES IN DATALIST CHAIN
	!---------------------------------------------------------------------
	!THIS ROUTINE IS CALLED WITH LPNT POINTING TO A LIST OF
	!DATAITEMS.  EACH DATAITEM CONSISTS OF:
	!
	!CHOICE-1
	!	DATAITEM-(LOC)
	!CHOICE-2
	!	LIST-(COUNT^18+LOC)
	!		DATAITEM
	!	OPTION-0 OR
	!	OPTION-1
	!		LOOPPART
	!---------------------------------------------------------------------
	SAVEBOUNDSFLG_.FLGREG<BOUNDS>;	!PRESERVE THE VALUE OF THE "BOUNDS"
			! SWITCH (USED BY THE USER TO REQUEST ARRAY BOUNDS CHECKING)
	IF .TYPE EQL DATALST	!IF WE ARE PROCESSING THE DATA LIST FOR A DATA STATEMENT
				! (NOT AN IO STMNT)
	THEN
	FLGREG<BOUNDS>_0;	!TURN OFF THE BOUNDS FLAG UNTIL ARE THROUGH WITH THIS STMNT
				! (ELSE THE ARRAY SS CALC WILL BE TURNED INTO A CALL TO
				! A RUN-TIME FUNCTION)
	LISTLINK_0;	!INITIALIZING FOR LIST INPARENS
	INCR DATLST FROM @LPNT TO @ LPNT+.LPNT<LEFT> BY 2 DO
	BEGIN
		MAP BASE DATLST;
		IF .DATLST[ELMNT] EQL 1 THEN	!A DATAITEM
		BEGIN
			IODATANODE(.DATLST[ELMNT1]);
		END
		ELSE	!AN IMPLIED DO LOOP OR LIST ENCLOSED IN PARENS
		BEGIN
			LOCAL BASE LNKLST; !TEMPORARY HOLDER OF LINKLIST
			LOCAL BASE TDOSYM; !TEMPORARY HOLDER OF DO INDEX SYMBOL PTR
			EXTERNAL  E128;
			LOCAL  BASE DONOD:IOLBL;	!LABEL OF CONTINUE ENDING IMPLIED DO LOOP
			LNKLST _ 0;  !INIT LOCAL
			R1_.DATLST[ELMNT1];R2_.R1[ELMNT];  !R2_LOC(DATAITEM LIST)
			IF .R1[ELMNT1] NEQ 0
			 THEN (!IMPLIED DO LOOP COMING UP ; R2 HAS PTR  TO IMPLIED  DO LIST
				%FIRST CHECK TO SEE THAT THERE HAVE BEEN
				 SOME VARIABLES FOR THIS DO SPEC %
				IF .R2<LEFT>  EQL  1  
				THEN	RETURN FATLEX (E128<0,0>);
				T1_@R2+.R2<LEFT>;
				T2 _ .T1[ELMNT];
				IOCONTNODE ;		! GEN A CONTINUE NODE
				%DON'T LET SUBSCRIPTED IMPLICIT DO INDECES GO UNDETECTED%
				IF .T2[ELMNT1]  NEQ  0  THEN RETURN FATLEX(E115<0,0>);
				T2 _ TDOSYM _ .T2[ELMNT];
				IF .T2[OPRCLS] NEQ DATAOPR THEN ERR38
				  ELSE IF .T2[OPRSP1] NEQ VARIABL1 THEN ERR38;
				IF .T2[VALTYPE] NEQ INTEGER THEN RETURN FATLEX(E104<0,0>);
				IF .TYPE EQL DATALST
				THEN
				  BEGIN
					STK[SP_.SP+1] _.T2; !SAV PTR TO INDEX SYMBOL ON STACK
				  END
				ELSE BEGIN
				  IF NAMSET (VARIABL1,.T2) LSS 0
				    THEN RETURN .VREG;
				END;

				IF CKDOINDEX (.T2)
				  THEN RETURN FATLEX (T2 [IDSYMBOL], E21<0,0>);	! DO INDEX ALREADY ACTIVE
				ADDOLAB (.IOLBL, .T2);	! THIS INDEX IS CURRENTLY MOST ACTIVE

				R2<LEFT>_.R2<LEFT>-2; !RESET LIST PTR SO THAT LAST ITEM (INDEX PTR)
							!DOESN'T GET PROCESSED AS AN IODATANODE
				);
			IF (LNKLST _ DATALIST (.R2)) LSS 0
			  THEN BEGIN
			    T2 _ .VREG;
			    IF .R1 [ELMNT1] NEQ 0	! IMPLIED DO LOOP
			      THEN DOCHECK (.IOLBL);	! REMOVE LABEL FROM ACTIVE DO LIST
			    RETURN .T2;
			  END;
			IF .R1[ELMNT1] NEQ 0 THEN	!IMPLIED DO LOOP
			BEGIN
				DOCHECK (.IOLBL);	! REMOVE LABEL FROM ACTIVE DO LIST
				ADDCONTNODE (LNKLST);	! LINK IN CONT NODE
				IODONODE(LNKLST);	!GEN A DO LOOP NODE
				DONOD_.LNKLST<LEFT>; !SET UP BY IODONODE
				DONOD[DOSYM]_.TDOSYM;	!STK[2]_LOC(INDEX VARIABLE)
				R2_.R1[ELMNT2]; SAVSPACE(.R1<LEFT>,.R1); !R2_LOC(LOOPPART)
				R1_.R2[ELMNT];
				!R1 POINTS TO INITIAL VALUE
				IF .TYPE EQL DATALST THEN
					 IF .R1[OPR1] NEQ CONSTFL THEN ERR44;
				IF .R1[VALTYPE] NEQ INTEGER THEN ERR44;
				DONOD[DOM1]_@R1;R1_.R2[ELMNT1];	!_LOC(INITIAL VALUE)
				!R1 POINTS TO FINAL VALUE
				IF .TYPE EQL DATALST THEN
					 IF .R1[OPR1] NEQ CONSTFL THEN ERR44;
				IF .R1[VALTYPE] NEQ INTEGER THEN ERR44;
				DONOD[DOM2]_@R1;	!_LOC(FINAL VALUE)
				IF .R2[ELMNT2] EQL 0 THEN	!INPLIED INCREMENT OF 1
				BEGIN
					DONOD[DOM3]_.ONEPLIT;
				END
				ELSE	!INCREMENT SPECIFIED
				BEGIN
					T1_.R2[ELMNT3];R1_.T1[ELMNT];SAVSPACE(0,.T1);
					IF .TYPE EQL DATALST THEN
						IF .R1[OPR1] NEQ CONSTFL THEN ERR44;
					IF .R1[VALTYPE] NEQ INTEGER THEN ERR44;
					DONOD[DOM3]_.R1<RIGHT>;
				END;
				IF .TYPE EQL DATALST
				THEN IF .SP GTR 0
					THEN (	DATASUBCHK(.DONOD[CLINK],.SP,STK[1]<0,0>);
						SP _ .SP-1;
					     );
				SAVSPACE(.R2<LEFT>,.R2);
			END;
			IF .LISTLINK EQL 0
			THEN LISTLINK_.LNKLST
			ELSE (LISTLINK[CLINK]_.LNKLST<LEFT>;
				LISTLINK<RIGHT> _ .LNKLST<RIGHT>
			     );
		END;
	END;
	FLGREG<BOUNDS>_.SAVEBOUNDSFLG;	!RESTORE THE "BOUNDS" FLAG TO ITS ORIGINAL VAL
	RETURN .LISTLINK	!POINTS TO FIRST ELEMENT IN LIST
END;
GLOBAL ROUTINE BLDFORMAT (FPNT)=
BEGIN
	REGISTER BASE T1:T2; MAP BASE FPNT;REGISTER BASE R1:R2;
	GLOBAL NAMLSTOK;	!SET TO 1 BY CALLER IF NAMELIST IS A VIABLE ARGUMENT
	EXTERNAL SAVSPACE %(SIZE,LOC)%,STK,BLDVAR %(VPNT)%,TBLSEARCH %()%,
		 TYPE;
	MACRO
	ERR25=(RETURN FATLEX(E25<0,0>))$,
	ERR19=(RETURN FATLEX(E19<0,0>))$,
	ERR15(X)=BEGIN
			RETURN FATLEX( X,R2[IDSYMBOL],E15<0,0>)
		END$,
	ERR34=RETURN FATLEX(PLIT'PARAMETER',R2[IDSYMBOL],E34<0,0>)$;
	ROUTINE EOE=
	BEGIN
		!--------------------------------------------------------------------------------------------------
		!R2=LOC (END OR ERR IDENTIFIER)
		!T1=LOC (LABEL CHOICE)
		!T2=LOC (LABEL )
		!--------------------------------------------------------------------------------------------------
			EXTERNAL NONIOINIO,LABREF;
			% THESE LABELS ARE PICKED UP AS CONSTANTS AND THEN
			  CONVERTED TO LABELS BECAUSE THEY ARE EXECUTABLE
			  LABEL REFERENCES IN AN IO STATEMENT  %
			IF .T2[VALTYPE] NEQ INTEGER
			THEN RETURN FATLERR(.LEXNAM[LABELEX],.LEXNAM[CONSTLEX],.ISN,E0<0,0>);
			NONIOINIO _ 1;
			ENTRY[1] _ .T2[CONST2];
			T2 _ LABREF();
			T2[SNREF] _ .T2[SNREF]-1;	!DON'T COUNT REFERENES
							!TO FORMAT LABELS IN I/O STATEMENTS
		SAVSPACE(.T1<LEFT>,@T1);
		IF .R2[IDSYMBOL] EQL SIXBIT 'END' THEN
			(IF .STK[6] EQL 0 THEN STK[6]_@T2 ELSE ERR34)
			ELSE IF .R2[IDSYMBOL] EQL SIXBIT 'ERR' THEN
				(IF .STK[5] EQL 0 THEN STK[5]_@T2 ELSE ERR34)
					ELSE ERR15 (PLIT'END OR ERR ');
	END;
	!----------------------------------------------------------------------------------------------------------
	!THIS ROUTINE IS CALLED WITH THE PARAMETER FPNT POINTING TO
	!A FORMAT SPECIFICATION.  SEE EXPANSION OF METASYMBOL IOSPEC FOR
	!DETAILS.  THE FORMAT POINTER IS RETURNED IN STK[4].  IT MAY BE
	!A LABEL (LOC), ASTERISK - STANDARD FORMAT CONVERSIONS (-1)
	!AN ARRAY NAME OR NAMELIST NAME (LOC[IDENTIFIER]) OR NOT SPECIFIED (0).
	!THE END AND ERR BRANCH LOCATIONS ARE RETURNED IN STK[6] AND STK[5]
	!RESPECITVELY.  THEY MAY BE LABELS (LOC), VARIABLES (LOC) OR NOT
	!SPECIFIED (0).
	!----------------------------------------------------------------------------------------------------------
	CASE .FPNT[ELMNT] OF SET
	0;!NEVER OCCURS,INSERTED FOR SPEED ONLY
	BEGIN!LABEL
		IF .STK[4]  NEQ  0  THEN  RETURN FATLEX(E39<0,0>);	! ALREADY FOUND ONE
		STK[4]_.FPNT[ELMNT1];
	END;
	BEGIN!ARRAY NAME NAMELIST NAME OR END/ERR
		R1_.FPNT[ELMNT1];
		%FLAG BEING SET INDICATES THAT BLDFORMAT WAS CALLED FROM
		  READ OR WRITE AND THUS HAS A SLIGHTLY DIFFERENT
		  SYNTAX TREE, POSSIBLY INCLUDING END/ERR=  %

		R2 _ IF .FLAG EQL  0 THEN .R1[ELMNT] %READ OR WRITE% ELSE .R1;
		IF (.R1[ELMNT1] EQL 0) OR (.FLAG NEQ 0)  THEN !ARRAY NAME OR NAMELIST NAME
								!OR NO END= OR ERR= EXPECTED
		BEGIN
			IF .STK[4] NEQ 0 THEN RETURN FATLEX(E39<0,0>);
			IF .R2[OPRSP1] EQL ARRAYNM1
			THEN
			BEGIN
				STK[4]_.R2;
				IF .TYPE EQL READD
				THEN	NAMSET(ARRAYNM1, .R2)
				ELSE	NAMREF(ARRAYNM1, .R2);
				IF .VREG LSS 0 THEN RETURN .VREG;
			END
			ELSE IF .NAMLSTOK NEQ 0 THEN
				IF .R2[IDATTRIBUT(NAMNAM)]
				THEN
				BEGIN
					LOCAL NAMROUT; !TO PUT ROUTINE TO CALL
					LOCAL BASE NMLST:NAMCOM;
					STK[4]_@R2;
					IF NAMREF( NMLSTREF,.R2) LSS 0 THEN RETURN .VREG;
					%NOTE REFERENCE OR SETTING OF EACH ITEM IN LIST %
					NAMROUT _ IF .TYPE EQL READD THEN NAMSET ELSE NAMREF; !DETERMINE ROUTINE TO CALL
					NAMCOM_.R2[IDCOLINK]; !GET POINTER TO NAMELIST NODE
					NMLST_.NAMCOM[NAMLIST]; !GET POINTER TO LIST OF ITEMS
					WHILE .NMLST LSS (.NAMCOM[NAMLIST] + .NAMCOM[NAMCNT]) DO
					BEGIN
					R1 _ .NMLST[ELMNT];
					(.NAMROUT)(.R1[OPRSP1],.R1); !CALL THE ROUTINE
					NMLST _ .NMLST+1; !NEXT ITEM
					END;	!OF WHILE ... DO
					R1 _ .FPNT[ELMNT1]; !RESTORE R1
				END
					ELSE ERR15(PLIT'ARRAY OR NAMELIST NAME')
				ELSE ERR15(PLIT'ARRAY NAME');
		END
		ELSE !END=/ERR=
		BEGIN
			T1_.R1[ELMNT2];T2_.T1[ELMNT]; !T1 HAS PTR TO OPTIONAL (= CONST )
			  !T2 HAS PTR TO SYMBOL NODE THAT SHOULDCONTAIN
			 !'END' OR 'ERR' 
			IF EOE() LSS 0 THEN RETURN .VREG;
		END;
		IF .FLAG  EQL  0 %READ/WRITE% THEN SAVSPACE( .R1<LEFT>,@R1);
	END;
	BEGIN!ASTERISK
		IF .STK[4]  NEQ  0  THEN  RETURN FATLEX(E39<0,0>);	! ALREADY FOUND ONE
		STK[4]_-1
	END
	TES;
END;

GLOBAL ROUTINE BLDUNIT (UPNT)=
BEGIN
	MAP BASE UPNT; LOCAL BASE T2;REGISTER BASE R1:T1:R2;
	EXTERNAL SAVSPACE %(SIZE,LOC)%,STK,BLDFORMAT %(FPNT)%,BLDVAR %(UPNT)%;
	EXTERNAL SETUSE,NAMLSTOK;
	EXTERNAL CNVNODE;
	MACRO
	ERR15(X)=RETURN FATLEX( INTGPLIT<0,0>, X, E15<0,0> )  $;
	!----------------------------------------------------------------------------------------------------------
	!THIS ROUTINE IS CALLED WITH THE PARAMETER UPNT POINTING
	!TO A UNITSPEC OPTIONALLY FOLLOWED BY A FORMATID.  SEE
	!EXPANSIONS OF THE METASYMBOLS IOSPEC, UNITSPEC AND FORMATID FOR
	!DETAILS.  A UNIT NUMBER MAY BE AN INTEGER CONSTANT OR AN INTEGER
	!VARIABLE.  IF A FORMAT IS PRESENT THE ROUTINE BLDFORMAT IS CALLED
	!TO SCAN THE FORMAT.  UPON EXIT FROM THIS ROUTINE THE FOLLOWING
	!LOCATIONS WILL BE DEFINED:
	!
	!	STK[2]=UNIT
	!	STK[3]=RECORD
	!	STK[4]=FORMAT
	!	STK[5]=ERR
	!	STK[6]=END
	!----------------------------------------------------------------------------------------------------------
	R1_.UPNT[ELMNT];R2_.R1[ELMNT1];  !R2_LOC(CONSTANT OR VARIABLE)
	IF .R1[ELMNT] EQL 1 THEN !INTEGER CONSTNAT
	BEGIN
		IF .R2[VALTYPE] NEQ INTEGER THEN ERR15 (PLIT SIXBIT 'UNIT');
		STK[2]_.R2
	END
	ELSE !VARIABLE
	BEGIN
		T2 _ .R2[ELMNT];	!PTR TO IDENTIFIER OR CONSTANT NODE
		IF .T2[VALTYPE] NEQ INTEGER THEN ERR15 (T2[IDSYMBOL]);
		SETUSE _ USE;
		IF (STK[2]_BLDVAR(.R2)) LSS 0 THEN RETURN .VREG;
		%DON'T LET UNSUBSCRIPTED ARRAYS THROUGH%
		IF .VREG<LEFT>  EQL  IDENTIFIER
		THEN	( MAP BASE VREG;
			  IF .VREG[OPRSP1]  EQL  ARRAYNM1
			  THEN	RETURN FATLEX( VREG[IDSYMBOL],ARPLIT<0,0>,E4<0,0>);
			);
	END;
	IF .R1[ELMNT2] NEQ 0 THEN !RECORD NUMBER
	BEGIN
		STK[3] _ .R1[ELMNT3];
		T1 _ @@STK[3];
		IF .T1[VALTP1] NEQ INTEG1
		  THEN  (.STK[3])<FULL> _ CNVNODE(.T1,INTEGER,0);
	END ELSE ( NAMLSTOK _ 1; STK[3]_0 ) ;
	SAVSPACE(.R1<LEFT>,@R1);
	STK[4]_STK[5]_STK[6]_0;
	IF .UPNT[ELMNT1] NEQ 0 THEN !FORMAT, END/ERR
	BEGIN
		R2_.UPNT[ELMNT2];
		T1 _ .R2[ELMNT];
		INCR FMT FROM .T1 TO .T1+.T1<LEFT> DO
		BEGIN
			MAP BASE FMT;
			FLAG _ 0; !SIGNAL BLDFORMAT FOR POSSIBLE END= OR ERR=
			IF BLDFORMAT(.FMT[ELMNT]) LSS 0 THEN ( NAMLSTOK _ 0;  RETURN .VREG);
			SAVSPACE(.FMT[ELMNT]<LEFT>,.FMT[ELMNT]);
		END;
		T1 _ .R2[ELMNT]; SAVSPACE(.T1<LEFT>,.T1);
	END;
	NAMLSTOK _ 0;
	SAVSPACE(.UPNT<LEFT>,@UPNT);
END;

%[760]%	GLOBAL ROUTINE BLDKLIST(KLPNT)=
%[760]%	BEGIN
%[760]%		MAP BASE KLPNT;
%[760]%		REGISTER BASE R1:R2:R3;
%[760]%		EXTERNAL BLDKEY,SAVSPACE;
%[760]%	
%[760]%		!--------------------------------------------------------
%[760]%		! This routine is called with KLPNT pointing to a list
%[760]%		! of keyspecs
%[760]%		!--------------------------------------------------------
%[760]%		R1_.KLPNT[ELMNT];
%[760]%		SAVSPACE(.KLPNT<LEFT>,@KLPNT);
%[760]%		R2_.R1[ELMNT];
%[760]%		SAVSPACE(.R1<LEFT>,@R1);
%[760]%	
%[760]%		INCR LIST FROM @R2 TO @R2 + .R2<LEFT> DO
%[760]%		BEGIN
%[760]%			MAP BASE LIST;
%[760]%			R3_.LIST[ELMNT];
%[760]%			IF BLDKEY(.R3[ELMNT],R3[ELMNT1]) LSS 0 THEN RETURN .VREG;
%[760]%			SAVSPACE(.R3<LEFT>,@R3);
%[760]%		END;
%[760]%		SAVSPACE(.R2<LEFT>,@R2);
%[760]%		.VREG
%[760]%	END;
%[760]%	
%[760]%	GLOBAL ROUTINE BLDKEY(KPNT,VALPNT)=
%[760]%	BEGIN
%[760]%	
%[760]%		MAP BASE KPNT;
%[760]%		MAP BASE VALPNT;
%[760]%		LOCAL SPOS,TYPE,CHOICE,VAR;
%[760]%		LABEL FINDK;
%[760]%		REGISTER BASE R1:R2:R3;
%[760]%		EXTERNAL NAMLSTOK, CGERR;
%[760]%		EXTERNAL STK, LABREF, NONIOINIO, SETUSE, BLDVAR;
%[760]%		!------------------------------------------------------------
%[760]%		! This routine is called with KPNT pointing to an identifier
%[760]%		! and VALPNT pointing to the list:
%[760]%		!	CHOICE - 1 (constant), 2 (variable), 3 (asterisk)
%[760]%		!	VALUE - pointer to symbol table entry for the choice
%[760]%		!------------------------------------------------------------
%[760]%	
%[760]%		BIND	CONOK = 1^0,	! CONSTANT OK
%[760]%			VAROK = 1^1,	! VARIABLE OR ARRAY REF OK
%[760]%			ARROK = 1^2,	! ARRAY NAME OR NAMELIST NAME OK
%[760]%			LBLOK = 1^3,	! LABEL OK
%[760]%			ASTOK = 1^4;	! ASTERISK OK
%[760]%	
%[760]%		BIND	NUMKEYS = 6;
%[760]%	
%[760]%		BIND	KEYWORDS = PLIT (
%[760]%				SIXBIT 'END'	,6^18	+LBLOK,
%[760]%				SIXBIT 'ERR'	,5^18	+LBLOK,
%[760]%				SIXBIT 'FMT'	,4^18	+LBLOK +ARROK +ASTOK,
%[760]%				SIXBIT 'IOSTAT'	,7^18	+VAROK,
%[760]%				SIXBIT 'REC'	,3^18	+VAROK +CONOK,
%[760]%				SIXBIT 'UNIT'	,2^18	+VAROK +CONOK +ASTOK);
%[760]%	
%[760]%		MACRO	STKPOS(I)=	(KEYWORDS[I]+1)<LEFT>$,
%[760]%			KTYPE(I)=	(KEYWORDS[I]+1)<RIGHT>$;
%[760]%	
%[760]%		MACRO	ERR15(X) = (RETURN FATLEX(X,KPNT[IDSYMBOL],E15<0,0>))$,
%[760]%			ERR15I(X) = (RETURN FATLEX(INTGPLIT<0,0>, X, E15<0,0>))$,
%[760]%			ERR34 = (RETURN FATLEX(PLIT' ',KPNT[IDSYMBOL],E34<0,0>))$;
%[760]%			! Try to match a keyword
%[760]%		FINDK: BEGIN
%[760]%			INCR I FROM 0 TO (NUMKEYS - 1) * 2 BY 2 DO
%[760]%			BEGIN
%[760]%				IF .KPNT[IDSYMBOL] EQL @KEYWORDS[.I]
%[760]%				THEN
%[760]%				BEGIN
%[760]%					SPOS_.STKPOS(.I);
%[760]%					TYPE_.KTYPE(.I);
%[760]%					LEAVE FINDK;
%[760]%				END
%[760]%			END;
%[760]%			! no match - invalid keyword
%[760]%			ERR15( PLIT 'A KEYWORD')
%[760]%		END;
%[760]%	
%[760]%			! check for redundant keyword
%[760]%		IF .STK[.SPOS] NEQ 0 THEN ERR34;
%[760]%		CHOICE_.VALPNT[ELMNT];
%[760]%		R1_.VALPNT[ELMNT1];
%[760]%	
%[760]%		CASE .CHOICE OF SET
%[760]%			CGERR();	! FOR SPEED
%[760]%			BEGIN	! CONSTANT
%[760]%				IF (.TYPE AND CONOK) NEQ 0
%[760]%				THEN
%[760]%				BEGIN
%[760]%					IF .R1[VALTYPE] NEQ INTEGER THEN ERR15I(R1[IDSYMBOL]);
%[760]%					STK[.SPOS]_.R1;
%[760]%				END
%[760]%				ELSE IF (.TYPE AND LBLOK) NEQ 0
%[760]%				THEN
%[760]%				BEGIN
%[760]%					IF .R1[VALTYPE] NEQ INTEGER THEN ERR15I(R1[IDSYMBOL]);
%[760]%					IF .SPOS EQL 4 THEN NONIOINIO_0 ELSE NONIOINIO_1;
%[760]%					ENTRY[1]_.R1[CONST2];
%[760]%					R2_LABREF();
%[760]%					STK[.SPOS]_@R2;
%[760]%				END
%[760]%				ELSE	ERR15(PLIT 'INTEGER OR LABEL');
%[760]%			END;
%[760]%			BEGIN	! VARIABLE
%[760]%				IF (.TYPE AND VAROK) NEQ 0
%[760]%				THEN
%[760]%				BEGIN	! VARIABLE OR ARRAY REF
%[760]%					IF .SPOS EQL 7 THEN SETUSE_SETT ELSE SETUSE_USE;
%[760]%					R2_.R1[ELMNT];
%[760]%					IF .R2[VALTYPE] NEQ INTEGER THEN ERR15I(R2[IDSYMBOL]);
%[760]%					IF (VAR_BLDVAR(.R1)) LSS 0 THEN RETURN .VREG;
%[760]%					! BLDVAR allows unsubscripted arrays
%[760]%					IF .VREG<LEFT> EQL IDENTIFIER
%[760]%					THEN
%[760]%					BEGIN
%[760]%						MAP BASE VREG;
%[760]%						IF .VREG[OPRSP1] EQL ARRAYNM1
%[760]%						THEN ERR15(PLIT'A SCALAR');
%[760]%					END;
%[760]%					STK[.SPOS]_.VAR;
%[760]%				END
%[760]%				ELSE IF (.TYPE AND ARROK) NEQ 0
%[760]%				THEN
%[760]%				BEGIN	! ARRAY OR NAMELIST NAME
%[760]%					R2_.R1[ELMNT];
%[760]%					IF .R2[OPRSP1] EQL ARRAYNM1
%[760]%					THEN
%[760]%					BEGIN
%[760]%						STK[.SPOS]_.R2;
%[760]%						IF .TYPE EQL READD
%[760]%						THEN	NAMSET(ARRAYNM1, .R2)
%[760]%						ELSE	NAMREF(ARRAYNM1, .R2);
%[760]%						IF .VREG LSS 0 THEN RETURN .VREG;
%[760]%					END
%[760]%					ELSE IF .NAMLSTOK NEQ 0 THEN
%[760]%						IF .R2[IDATTRIBUT(NAMNAM)]
%[760]%						THEN
%[760]%						BEGIN
%[760]%							LOCAL NAMROUT; !TO PUT ROUTINE TO CALL
%[760]%							LOCAL BASE NMLST:NAMCOM;
%[760]%							STK[.SPOS]_@R2;
%[760]%							IF NAMREF( NMLSTREF,.R2) LSS 0 THEN RETURN .VREG;
%[760]%							NAMROUT _ IF .TYPE EQL READD THEN NAMSET ELSE NAMREF; !DETERMINE ROUTINE TO CALL
%[760]%							NAMCOM_.R2[IDCOLINK]; !GET POINTER TO NAMELIST NODE
%[760]%							NMLST_.NAMCOM[NAMLIST]; !GET POINTER TO LIST OF ITEMS
%[760]%							WHILE .NMLST LSS (.NAMCOM[NAMLIST] + .NAMCOM[NAMCNT]) DO
%[760]%							BEGIN
%[760]%							R3 _ .NMLST[ELMNT];
%[760]%							(.NAMROUT)(.R3[OPRSP1],.R3); !CALL THE ROUTINE
%[760]%							NMLST _ .NMLST+1; !NEXT ITEM
%[760]%							END;	!OF WHILE ... DO
%[760]%						END
%[760]%							ELSE ERR15(PLIT'ARRAY OR NAMELIST NAME')
%[760]%						ELSE ERR15(PLIT'ARRAY NAME');
%[760]%				END
%[760]%				ELSE ERR15(PLIT'ALLOWED');
%[760]%			END;	! VARIABLE
%[760]%			BEGIN	! ASTERISK
%[760]%				IF (.TYPE AND ASTOK) NEQ 0
%[760]%				THEN STK[.SPOS]_-1
%[760]%				ELSE ERR15(PLIT'ALLOWED');
%[760]%			END;
%[760]%		TES;
%[760]%	
%[760]%		.VREG
%[760]%	
%[760]%	END;	! BLDKEY
%[760]%	
%[760]%	GLOBAL ROUTINE KORFBLD(FPNT)=
%[760]%	BEGIN
%[760]%		MACRO ERR15(X) = (RETURN FATLEX(X,R2[IDSYMBOL],E15<0,0>))$;
%[760]%	
%[760]%		EXTERNAL BLDKEY,SAVSPACE,SETUSE,NAMLSTOK, CGERR;
%[760]%		REGISTER BASE T1:R1:R2:R3;
%[760]%		MAP BASE FPNT;
%[760]%		!---------------------------------------------------------
%[760]%		! This routine is called with FPNT pointing to the list:
%[760]%		!	choice 1 - label
%[760]%		!	pointer to label
%[760]%		! or
%[760]%		!	choice 2 - variablespec or keyword
%[760]%		!	pointer to list:
%[760]%		!		variablespec
%[760]%		!		option if keyword
%[760]%		!		pointer to choice of constant, variable,
%[760]%		!			or asterisk
%[760]%		! or
%[760]%		!	choice 3 - asterisk
%[760]%		!----------------------------------------------------------
%[760]%	
%[760]%		SETUSE _ USE;
%[760]%		CASE .FPNT[ELMNT] OF SET
%[760]%			CGERR();	! FOR SPEED
%[760]%			BEGIN	! LABEL
%[760]%				STK[4] _ .FPNT[ELMNT1];
%[760]%			END;
%[760]%			BEGIN	! VARIABLESPEC OR KEYWORD
%[760]%				R1 _ .FPNT[ELMNT1];
%[760]%				IF .R1[ELMNT1] EQL 0
%[760]%				THEN
%[760]%				BEGIN	! ARRAY OR NAMELIST NAME
%[760]%					R3_.R1[ELMNT];
%[760]%					R2_.R3[ELMNT];
%[760]%					IF .R2[OPRSP1] EQL ARRAYNM1
%[760]%					THEN
%[760]%					BEGIN
%[760]%						STK[4]_.R2;
%[760]%						IF .TYPE EQL READD
%[760]%						THEN	NAMSET(ARRAYNM1, .R2)
%[760]%						ELSE	NAMREF(ARRAYNM1, .R2);
%[760]%						IF .VREG LSS 0 THEN RETURN .VREG;
%[760]%					END
%[760]%					ELSE IF .NAMLSTOK NEQ 0 THEN
%[760]%						IF .R2[IDATTRIBUT(NAMNAM)]
%[760]%						THEN
%[760]%						BEGIN
%[760]%							LOCAL NAMROUT; !TO PUT ROUTINE TO CALL
%[760]%							LOCAL BASE NMLST:NAMCOM;
%[760]%							STK[4]_@R2;
%[760]%							IF NAMREF( NMLSTREF,.R2) LSS 0 THEN RETURN .VREG;
%[760]%							NAMROUT _ IF .TYPE EQL READD THEN NAMSET ELSE NAMREF; !DETERMINE ROUTINE TO CALL
%[760]%							NAMCOM_.R2[IDCOLINK]; !GET POINTER TO NAMELIST NODE
%[760]%							NMLST_.NAMCOM[NAMLIST]; !GET POINTER TO LIST OF ITEMS
%[760]%							WHILE .NMLST LSS (.NAMCOM[NAMLIST] + .NAMCOM[NAMCNT]) DO
%[760]%							BEGIN
%[760]%							R3 _ .NMLST[ELMNT];
%[760]%							(.NAMROUT)(.R3[OPRSP1],.R3); !CALL THE ROUTINE
%[760]%							NMLST _ .NMLST+1; !NEXT ITEM
%[760]%							END;	!OF WHILE ... DO
%[760]%						END
%[760]%							ELSE ERR15(PLIT'ARRAY OR NAMELIST NAME')
%[760]%						ELSE ERR15(PLIT'ARRAY NAME');
%[760]%				END
%[760]%				ELSE
%[760]%				BEGIN	! KEYWORD
%[760]%					R2 _ .R1[ELMNT];
%[760]%					IF BLDKEY(.R2[ELMNT],.R1[ELMNT2]) LSS 0 THEN RETURN .VREG;
%[760]%					R3 _ .R1[ELMNT2];
%[760]%					SAVSPACE(.R3<LEFT>,@R3);
%[760]%				END;
%[760]%			END;
%[760]%			BEGIN	! ASTERISK
%[760]%				STK[4] _ -1;
%[760]%			END;
%[760]%		TES;
%[760]%		.VREG
%[760]%	END;	! KORFBLD
	
	END
ELUDOM