Trailing-Edge
-
PDP-10 Archives
-
FORTRAN-10_V7wLink_Feb83
-
sta1.bli
There are 12 other files named sta1.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/SJW/DCE/TFV/EDS/CKS/AHM
MODULE STA1(RESERVE(0,1,2,3),SREG=#17,FREG=#16,VREG=#15,DREGS=4)=
BEGIN
GLOBAL BIND STA1V = 7^24 + 0^18 + #1716; ! Version Date: 17-Jan-83
! LEXNAM, FIRST, TABLES, META72, ASHELP
SWITCHES NOLIST;
REQUIRE LEXNAM.BLI;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
REQUIRE META72.BLI;
REQUIRE ASHELP.BLI;
SWITCHES LIST;
%(
***** Begin Revision History *****
57 ----- ----- FIX COMPLEX CONSTANTS IN DATA STATEMENTS SO THAT
THE ENTIRE CONSTANT CAN BE SIGNED
58 ----- ----- OPENCLOSE - FIX BUG THAT UNIT = WOULD DESTROY
THE CODE OF THE LAST PARAMETER .
AND WHILE WE ARE THERE FIX UP A FEW PARAMETER
VALUE LEGALITY CHECKS
59 ----- ----- CHECK FOR ILLEGAL LIST DIRECTED REREAD
60 ----- ----- IN DATAGEN - MUST CHECK THE SIGN OF THE
REPEAT COUNT ITSELF NOT JUST SIGNFLG
BECAUSE OF POSSIBLE NEGATIVE PARMETERS
61 ----- ----- FIX ERROR MESSAGE CALL FOR NON-ARRAY OPEN
STATEMENT PARAMETER VALUES
62 313 16666 FIX DIALOG WITH NO =
63 VER5 ----- HANDLE ERR= IN OPENCLOSE, (SJW)
64 424 QA690 ERROR IF DIRECTORY= NOT LITERAL OR ARRAY
NAME IN OPENCLOSE, (SJW)
***** Begin Version 5A ***** 7-Nov-76
65 521 QA900 FIX E15 PARAMS TO FATLEX IN OPENCLOSE, (SJW)
66 531 20323 GIVE WARNING FOR PARAMETER USED AS ASSOC VAR ,(DCE)
***** Begin Version 6 *****
67 760 TFV 1-Jan-80 -----
Add new OPEN arguments and keyword based I/O (for FORTRAN 77)
68 761 TFV 1-Mar-80 -----
Add indices for folding /GFLOATING constants
69 1005 TFV 1-Jul-80 ------
Fix OPENCLOSE to handle unit specifiers without the unit=
70 1014 TFV 27-Oct-80 Q10-04556
Allow list directed rereads, making reread just like ACCEPT, TYPE, etc.
71 1015 TFV 27-Oct-80 Q10-04743
FMT= is not optional for type, accept ,reread, etc.
72 1016 TFV 27-Oct-80 Q10-04759
Report names for misspelled OPEN/CLOSE parameters
73 1017 TFV 27-Oct-80 Q10-04733
Fix IOSTAT processing in OPEN/CLOSE. Param table had wrong
dispatch value. Also fix test for formal argument used as
an associate variable.
74 1020 TFV 27-Oct-80 Q10-04575
Add synonms for PDP-11 FORTRAN compatibility to OPEN/CLOSE.
INITIALSIZE= - FILESIZE=
NAME= - DIALOG=
TYPE= - STATUS=
Also fix ERR= processing. Only allow ERR=label.
75 1030 TFV 25-Nov-80 ------
Fix ERR=label in OPENCLOSE to check for labelex not constlex.
76 1032 EDS 1-Dec-80 10-30251
Fix DATAGEN processing of DATA statements. SAVSPACE was
not called to free space used by constant options or
repeat list.
77 1042 TFV 15-Jan-81 -------
Prohibit list directed encode/decode.
78 1045 TFV 20-Jan-81 -------
Fix edit 1030. NONIOINIO and LOOK4LABEL have to be reset.
79 1071 CKS 22-May-81
Remove TAPEMODE from OPEN keyword plit
81 1076 TFV 8-Jun-81 ------
Allow list-directed I/O without an iolist
84 1124 AHM 21-Sep-81 Q20-01651
Set STORD for IOSTAT variables and ASSOCIATEVARIABLES so they get
put back in subprogram epilogues.
***** Begin Version 7 *****
80 1202 DCE 1-Jul-80 -----
Change calls to DATALIST to be calls to LISTIO for expressions
on output lists.
82 1233 CKS 28-Jun-81
Alter some .s and @s in BLDIO1 and BLDEDCODE to conform to new STK
%! produced by using %OPTCOMMA% instead of [ COMMA ] in the BNF.
% See comments in STA0.
83 1245 TFV 3-Aug-81 ------
Fix OPENCLOSE to convert character constant args to HOLLERITH
until FOROTS knows how to cope with character data.
85 1267 AHM 6-Oct-81 ------
Define a stub routine INQUSTA for the INQUIRE statement so we don't
get undefined symbols when linking.
86 1410 CKS 28-Oct-81
Modify DATASTA to read the modified tree shape caused by the optional
comma in DATA A/1/,B/1/.
1527 CKS 27-Apr-82
Rewrite OPENCLOSE to allow expressions as open specifiers
1546 CKS 31-May-82
Move PRINSTA, RERESTA, TYPESTA to STA0 for uniformity.
1571 CKS 27-Jun-82
Don't set parent pointer under OPEN if expression is omitted.
(DIALOG, READONLY.)
1622 CKS 25-Aug-82
Correctly handle ASSOCIATEVARIABLE=arrayref and IOSTAT=arrayref.
Don't blindly call NAMSET on the "variable" if it's an array ref.
1662 TFV 2-Nov-82
Fix INQUSTA to give the error Exxx (NYI) 'INQUIRE statement is
not yet implemented.'
1676 CKS 18-Nov-82
Allow hollerith constants as open specifiers.
1677 CKS 20-Nov-82
Use action routine KEYSCAN to parse FIND, ENCODE, REWIND.
1716 TFV 17-Jan-83 Q20-06103
Fix OPENCLOSE. FLGREG is trashed if UNIT is not specified.
***** End Revision History *****
)%
!THE NUMBER IN COMMENT'S IS THE STATEMENTS LOCATION
!IN THE HASH TABLE .
FORWARD
% 3% DATASTA, !DATA
% 18% OPENSTA, !OPEN
% 34% FINDSTA, !FIND
% 39% REWISTA, !REWIND
% 63% BKSPST, !BACKSPACE OR BACKFILE
% 83% CLOSSTA, !CLOSE
% 84% ENDFSTA, !ENDFILE
%???% INQUSTA; ![1267] INQUIRE
EXTERNAL
BLDVAR,
BLDUTILITY,
CNVNODE,
CORMAN,
EXPRESS,
GSTKSCAN,
GSTSSCAN,
LABELS,
LEXEMEGEN,
LEXICA,
LEXL,
LOOK4CHAR,
NAMREF,
NAMSET,
NOLABELS,
NONIOINIO;
EXTERNAL E15,E164,E182,E183,E184,E196;
GLOBAL ROUTINE BKSPST=
BEGIN
EXTERNAL BLDREPT,BLDUTILITY;
REGISTER R;
BIND DUM = PLIT( SP NAMES 'SPACE?0', FIL NAMES 'FILE?0' );
R _ BACKDATA;
LOOK4CHAR _ SP<36,7>;
DECR I FROM 1 TO 0
DO
BEGIN
IF LEXICAL(.GSTSSCAN) NEQ 0
THEN
BEGIN % GOT ONE %
IF SYNTAX(UTILSPEC) LSS 0 THEN RETURN .VREG;
RETURN BLDUTILITY(.R)
END;
R _ BKFILDATA; ! TRY FILE
LOOK4CHAR _ FIL<36,7>
END;
RETURN FATLEX(E12<0,0>); !MISSPELLED
END;
GLOBAL ROUTINE REWISTA=
%1677% BLDUTILITY(REWIDATA);
GLOBAL ROUTINE ENDFSTA=
%1677% BLDUTILITY(ENDFDATA);
GLOBAL ROUTINE FINDSTA=
%1677% BLDUTILITY(FINDDATA);
ROUTINE CMPLXCONGEN(PTR , SIGNN )= !BUILDS A COMPLEX ONSTANT NODE FROM DATA LIST
!SEMANTIC OUTPUT
BEGIN
REGISTER SIGNFLG;
LOCAL BASE REALPT :IMAGPT;
![761] Add KGFRL and KTYPCG for folding /GFLOATING constants
%[761]% EXTERNAL CNSTCM,C1H,C1L,C2H,C2L,COPRIX,KDPRL,KGFRL,KDNEGB,KTYPCB,KTYPCG;
REGISTER BASE T1:T2;
ROUTINE SIGNEDREAL(CONST)=
%(****************************
GIVEN A PTR TO A CONSTANT TABLE ENTRY FOR THE REAL OR
IMAGINARY PART OF A COMPLEX CONST, (WHERE THAT PART MAY
ITSELF BE ANY TYPE) RETURN THE SINGLE-WD REAL
VALUE TO BE USED FOR THAT PART OF THE CONSTANT.
THE REGISTER-VARIABLE "SIGNFLG" IS ASSUMED TO BE "TRUE"
IF THE CONSTANT INDICATED BY "CONST" SHOULD BE NEGATED.
SIGNN - IS THE SIGN OF THE TOTAL CONSTANT
*******************************)%
BEGIN
MAP PEXPRNODE CONST;
C1H_.CONST[CONST1]; !HI ORDER PART
C1L_.CONST[CONST2]; !LOW ORDER PART
%(***IF CONST IS NOT REAL, CONVERT IT TO REAL. THE CONSTANT FOLDING
ROUTINE TAKES ITS ARG IN THE GLOBALS C1H,C1L***)%
IF .CONST[VALTYPE] NEQ REAL
THEN
BEGIN
COPRIX_KKTPCNVIX(REAL2,.CONST[VALTP2]); !INDEX INTO CONSTNT FOLDER
! FOR THE TYPE-CONV DESIRED
CNSTCM(); !CONVERT THE CONST IN C1H,C1L
! LEAVING RESULT IN C2H,C2L;
C1H_.C2H;
C1L_.C2L
END;
%(***ROUND THE 2 WD REAL TO A SINGLE-WD REAL***)%
IF .CONST[VALTYPE] NEQ DOUBLOCT
THEN
BEGIN !DONT ROUND DOUBLE-OCTAL
![761] Convert DP to Sp based on /GFLOATING
%[761]% IF .GFLOAT !INDEX INTO THE CONST FOLDER FOR ROUNDING
%[761]% THEN COPRIX_KGFRL ! DOUBLE-WD REAL TO SINGLE-WD REAL
%[761]% ELSE COPRIX_KDPRL;
CNSTCM(); !ROUND THE DOUBLE-WD REAL IN C1H-C1L, LEAVING
! RESULT IN C2H
C1H_ .C2H
END;
%(***IF THE VALUE SHOULD BE NEGATED, DO SO***)%
IF .SIGNFLG
THEN RETURN -.C1H
ELSE RETURN .C1H
END;
%(***PROCESS REAL PART**)%
T1 _ .PTR;
SIGNFLG _ .SIGNN;
IF .T1[ELMNT] NEQ 0 !IS IT SIGNED?
THEN
(IF .T1[ELMNT] EQL 2 THEN SIGNFLG _ -1 -.SIGNN;
T1_.T1+1;
);
REALPT_SIGNEDREAL(.T1[ELMNT1]);
%(***PROCESS IMAGINARY PART**)%
SIGNFLG _ .SIGNN;
T1_.T1+2; !SKIP TO IMAG PART
IF .T1[ELMNT] NEQ 0
THEN (IF .T1[ELMNT] EQL 2 THEN SIGNFLG_ -1 -.SIGNN;
T1_.T1+1;
);
IMAGPT _ SIGNEDREAL(.T1[ELMNT1]);
!NOW MAKE ACOMPLEX CONSTANT NODE
RETURN MAKECNST(COMPLEX,.REALPT,.IMAGPT);
END; !OF ROUTINE CPLXCONGEN
GLOBAL ROUTINE DATAGEN(CONLIST)=
BEGIN
EXTERNAL CORMAN,NAME,SAVSPACE;
LOCAL REPEAT,COUNT,DATCSIZ,SIGNFLG;
LOCAL BASE CONNODE :CONPTR;
LABEL DAT1;
MACRO ERR54 = ( FATLEX(E54<0,0>))$;
![761] Add KGFRL to convert DP to SP under /GFLOATING
%[761]% EXTERNAL CNSTCM,C1H,C1L,C2H,C2L,COPRIX,KDPRL,KGFRL,KDNEGB;
MACRO DNEG(X,Y)=
BEGIN
C1H _ X[CONST1]; !HIGH ORDER
C1L _ X[CONST2]; !LOW ORDER
COPRIX _ KDNEGB;
CNSTCM(); !CONVERT TO NEG
MAKECNST(Y,.C2H,.C2L)
END$;
MACRO DDATCONNODE =
BEGIN
NAME<LEFT> _ 2; CONNODE _ CORMAN();
IF .CONPTR EQL 0
THEN (CONPTR<LEFT> _ CONPTR<RIGHT> _ .CONNODE)
ELSE (CONPTR[CLINK] _ .CONNODE;
CONPTR<RIGHT> _.CONNODE;
);
END$;
REGISTER BASE T1:T2; MAP BASE CONLIST;
%
ROUTINE BUILDS A LIST OF DATA CONSTANTS AND KEEPS COUNT FOR LATER USE
BY THE DATA LIST PROCESSING ROUTINES
%
CONPTR _ 0; COUNT _ 0;
INCR CONITEM FROM .CONLIST TO .CONLIST+.CONLIST<LEFT> BY 2 DO
BEGIN
MAP BASE CONITEM;
REPEAT _ 1; !INITIALIZE
SIGNFLG _ 0;
!SEE IF CONSTANT IS LITERAL OR NUMBER
DAT1: IF .CONITEM[ELMNT] EQL 1
THEN !NUMBER
BEGIN
T1 _ .CONITEM[ELMNT1]; !PTR TO 2 OR 3 WORD SET CONST [* CONST]
IF .T1[ELMNT] NEQ 0
THEN( !SIGHNED CONSTANT
IF .T1[ELMNT] EQL 2 !MINUS
THEN SIGNFLG_-1 ELSE SIGNFLG_0;
T1 _ .T1+1;! TO GET PAST THE SIGN
)
ELSE SIGNFLG _ 0;
%NOW DECIDE WHETHER WE HAVE A CONSTANT OR COMPLEX CONSTANT%
IF .T1[ELMNT1] EQL 2
THEN
BEGIN %COMPLEX CONSTANT%
T2 _ CMPLXCONGEN( .T1[ELMNT2] , .SIGNFLG );
COUNT _ .COUNT + 2;
SIGNFLG _ 0; !COMPLEX SIGNS ARE DONE
END
ELSE
BEGIN %ITS AN INTEGER OR REAL%
T1 _ .T1[ELMNT2]; !POINTER TO CONSTANT-OPTION
T2 _ .T1[ELMNT]; !PTR TO FIRST CONSTANT OR REPEAT COUNT
IF .T1[ELMNT1] NEQ 0
THEN (!REPEAT FACTOR T2 POINTS TO REPEAT CONST
IF .T2[VALTYPE] NEQ INTEGER
THEN (ERR54; REPEAT _ 0; LEAVE DAT1);
%DO THIS IN CASE OF NEGATIVE PARAMETER VALUES%
IF .SIGNFLG NEQ 0
THEN T2 _ MAKECNST(INTEGER,0,-.T2[CONST2]);
IF .T2[CONST2] LSS 0 THEN (ERR54; REPEAT _ 0; LEAVE DAT1);
REPEAT _ .T2[CONST2]; !REPEAT VALUE
%[1032]% T2 _ .T1; !SAVE PTR
T1 _ .T1[ELMNT2]; !PTR TO REPEATED CONST OR LITERAL
%[1032]% SAVSPACE(.T2<LEFT>,.T2);
T2 _ .T1[ELMNT2]; !PTR TO ACTUAL CONSTANT OR LITSTRING NODE
IF .T1[ELMNT1] EQL 1
THEN !NUMBER
(
IF .T2[ELMNT] NEQ 0
THEN (!SIGNED NUMBER
IF .T2[ELMNT] EQL 2
THEN SIGNFLG_-1 ELSE SIGNFLG_0;
T2 _ .T2+1
)
ELSE SIGNFLG _ 0;
%NOW WHAT KIND OF CONSTANT DO WE HAVE%
IF .T2[ELMNT1] EQL 2
THEN
BEGIN %COMPLEX%
T2_ CMPLXCONGEN( .T2[ELMNT2] , .SIGNFLG );
COUNT _ .COUNT+2;
SIGNFLG _ 0
END
ELSE
BEGIN %REAL OR INTEGER OR DOUBLE%
T2 _ .T2[ELMNT2]; !CONSTANT LEXEME
DATCSIZ _ IF .T2[DBLFLG] THEN 2 ELSE 1
END
)
ELSE !LITERAL
DATCSIZ _ .T2[LITSIZ]
)
ELSE ( %NO REPEAT%
DATCSIZ _ IF .T2[DBLFLG] THEN 2 ELSE 1;
%[1032]% SAVSPACE(.T1<LEFT>,.T1);
);
COUNT _ .COUNT + .DATCSIZ * .REPEAT;
IF .SIGNFLG NEQ 0
THEN IF .T2[VALTP1] EQL INTEG1
THEN T2 _ MAKECNST(INTEGER,0,-.T2[CONST2])
ELSE T2 _ DNEG(.T2,.T2[VALTYPE]); !NEGATE THE NUMBER
%[1032]% END; % CONSTANT OR COMPLEX %
%[1032]% T1 _ .CONITEM[ELMNT1];
%[1032]% SAVSPACE(.T1<LEFT>,.T1);
END
ELSE !LITERAL
BEGIN
T2 _ .CONITEM[ELMNT1]; !PTR TO LITERAL STRING NODE
COUNT _ .COUNT + .T2[LITSIZ];
END;
DDATCONNODE; !BUILD AND LINK A DATA CONSTANT NODE
CONPTR[DATARPT] _ .REPEAT;
CONPTR[DCONST] _ .T2;
END; !OF INCR LOOP
RETURN .COUNT^18+ .CONPTR<LEFT>;
END;
GLOBAL ROUTINE DATASTA=
BEGIN
REGISTER BASE T1;
REGISTER BASE R1:R2;
LOCAL ITEMLIST,CONLIST;
EXTERNAL DATAGEN %(LOC,SIZE)%,SAVSPACE %(SIZE,LOC)%,STK,SP,DATALIST,TYPE,NEWENTRY;
EXTERNAL DATASUBCHK;
!SEMANTIC ANALYSIS BEGINS
[email protected][0]; !T1_LOC(DATASPEC OR LIST A,LINEND)
%1410% ! The optional comma preceding the first DATALIST is not allowed. It
%1410% ! is too hard to prevent it in the BNF syntax, so check here.
%1410% R1 _ .T1[ELMNT]; ! point to first DATALIST
%1410% IF .R1[ELMNT] NEQ 0 ! check for comma preceding it
%1410% THEN FATLEX(.LEXNAM[IDENTIFIER],.LEXNAM[COMMA],E0<0,0>);
%1410% ! "Found comma when expecting identifier"
INCR DAT FROM .T1 TO .T1+.T1<LEFT> DO
BEGIN !PROCESS LIST OF DATA SPECIFICATIONS
MAP BASE DAT;
R1 _ .DAT[ELMNT]; !PTR TO 3 ITEM LIST - 1.OPTIONAL COMMA [1410]
! 2.DATALIST PTR
! 3.CONLIST PTR
%1410% T1 _ .R1[ELMNT2]; !PROCESS CONLIST PTR FIRST FO COUNT NUMBER OF CONSTANTS
!T1 POINTS TO 3 WORD LIST (SLASH,CONLISTPTR,SLASH)
R2 _ .T1[ELMNT1]; !GET PTR TO LIST OF CONSTANT SPECS
SAVSPACE (.T1<LEFT>,.T1); !GET BACK SPACE
CONLIST _ DATAGEN(.R2);
SAVSPACE(.R2<LEFT>,.R2);
!
!NOW PROCESS LIST OF DATA ITEM SPECIFICATIONS
!USE THE SAME ROUTINE AS USED BY IO LISTS AND RETURN PTR
!TO SAME KIND OF LIST STRUCTURE AS IO LISTS
!
TYPE _ DATALST; !SIGNAL DATA STATEMENT TO DATALIST ROUTINE
SP _ 0; !RESET FOR USE IN DATALIST
%1410% ITEMLIST _ DATALIST(.R1[ELMNT1]); !USEING FIRST ITEM POINTED TO BY R1
DATASUBCHK(.ITEMLIST<LEFT>,0,0); !CHECK SUBSCRIPTS ON LIST ITEMS FOR VALIDITY
SAVSPACE(.R1<LEFT>,.R1); !RETRIEVE SOME SPACE
!
!NOW BUILD A DATA STATEMENT NODE AND LINK TO ANY PREVIOUS ONES
!
NAME _ DATATAB; !ID OF DATA TABLE FOR NEWENTRY
R2 _ NEWENTRY();
!FILL IN PTRS TO LISTS IN DATA NODE
!
R2[DATITEMS] _ .ITEMLIST<LEFT>; R2[DATCONS] _ .CONLIST;
R2[DATCOUNT] _ .CONLIST<LEFT>; !NUMBER OF CONSTANTS SPECIFIED
R2[DATISN]_.ISN; !STMNT NUMBER (NEEDED FOR ERROR MESSAGES
! IN ALLOCATION ROUTINE)
END; !OF INCR LOOP
T1 _ @.STK[0]; SAVSPACE(.T1<LEFT>,.T1); SAVSPACE(0,.STK[0]);
.VREG
END; !OF DATASTA
GLOBAL ROUTINE STRNGSCAN= !STRING SCAN
!PUTS A STRING OF UP TO 6 SIXBIT CHARACTERS
!IN SIX LEFT JUSTIFIED AND RETURNS IT
BEGIN
EXTERNAL LEXICAL,GSTCSCAN,LOOK4CHAR;
REGISTER SIX,C;
LOOK4CHAR _ "?L"; ! ANY LETTER
DECR SHIFT FROM 30 TO 0 BY 6 DO !PACK THE FIRST 6 CHARACTERS
BEGIN
MACHOP ADDI=#271;
SIX_.SIX^6;
IF ( C _ LEXICAL(.GSTCSCAN ) ) EQL 0
THEN RETURN ( SIX _ .SIX^.SHIFT ) ! NO MORE LETTERS
ELSE ADDI ( SIX, -" ", C ) ! CONVERT TO SIXBIT AND PUT IN SIX
END;
DO
IF LEXICAL(.GSTCSCAN) EQL 0 THEN RETURN .SIX ! SKIP ALL CHARS PAST 6
WHILE 1;
END; !OF STRNGSCAN
GLOBAL ROUTINE OPENCLOSE (OPENCLOSDATA) = ! [1527] Rewritten
! Routine to parse the open keyword list (olist) in OPEN and CLOSE statements.
! The list can have the following forms:
!
! (u,keywords)
! (keywords)
!
! where u is an integer expression specifying the unit number
! keywords is a list of either KEYWORD=EXPRESSION or just KEYWORD
!
! The keywords DIALOG and READONLY cause problems if they are specified first
! in the keyword list because they are not followed by =. Therefore it is
! ambiguous whether they are a keyword or a variable name specifying the unit
! number. READONLY is not a valid variable name so it is parsed as a keyword.
! DIALOG is parsed as a unit expression.
BEGIN
REGISTER BASE K:N:V;
LOCAL FIRSTP;
LABEL DLP;
BIND VECTOR OPNKWD = UPLIT (
SIXBIT 'ACCESS', ! 0
SIXBIT 'ASSOCI', ! 1
SIXBIT 'BLANK', ! 2
SIXBIT 'BLOCKS', ! 3
SIXBIT 'BUFFER', ! 4
SIXBIT 'CARRIA', ! 5
SIXBIT 'DENSIT', ! 6
SIXBIT 'DEVICE', ! 7
SIXBIT 'DIALOG', ! 8
NDIALOG INDEXES SIXBIT '#DIALO', ! 9
SIXBIT 'DIRECT', ! 10
SIXBIT 'DISPOS', ! 11
NERR INDEXES SIXBIT 'ERR', ! 12
SIXBIT 'FILE', ! 13
SIXBIT 'FILESI', ! 14
SIXBIT 'FORM', ! 15
SIXBIT 'INITIA', ! 16
NIOSTAT INDEXES SIXBIT 'IOSTAT', ! 17
SIXBIT 'MODE', ! 18
SIXBIT 'NAME', ! 19
SIXBIT 'PADCHA', ! 20
SIXBIT 'PARITY', ! 21
SIXBIT 'PROTEC', ! 22
NREADONLY INDEXES SIXBIT '#READO', ! 23
SIXBIT 'RECL', ! 24
SIXBIT 'RECORD', ! 25
SIXBIT 'RECTYP', ! 26
SIXBIT 'STATUS', ! 27
SIXBIT 'TYPE', ! 28
NUNIT INDEXES SIXBIT 'UNIT', ! 29
KWDN INDEXES SIXBIT 'VERSIO'); ! 30
STRUCTURE LHVECTOR [I] = (.LHVECTOR+.I)<18,18>,
RHVECTOR [I] = (.RHVECTOR+.I)<0,18>;
BIND CE = 0, ! character expression
IE = 1, ! integer expression
IV = 4, ! integer variable
AR = 3, ! array name or char expression
LB = 2; ! label
MACRO X (A,B) = A^18 + #B$;
! Syntax of keyword's value and FOROTS keyword number
BIND VECTOR OPNDUM = UPLIT (
X (CE,2), ! ACCESS
X (IV,22), ! ASSOCIATEVARIABLE
X (CE,25), ! BLANK
X (IE,5), ! BLOCKSIZE
X (IE,4), ! BUFFERCOUNT
X (CE,26), ! CARRIAGECONTROL
X (CE,24), ! DENSITY
X (CE,3), ! DEVICE
X (AR,1), ! DIALOG
X ( 0,1), ! DIALOG (without =)
X (AR,10), ! DIRECT
X (CE,15), ! DISPOS
X (LB,37), ! ERR
X (CE,6), ! FILE
X (IE,13), ! FILESIZE
X (CE,27), ! FORM
X (IE,13), ! INITIALSIZE
X (IV,21), ! IOSTAT
X (CE,12), ! MODE
X (AR,1), ! NAME
X (CE,31), ! PADCHAR
X (CE,23), ! PARITY
X (IE,7), ! PROTECTION
X ( 0,35), ! READONLY (without =)
X (IE,14), ! RECL
X (IE,14), ! RECORDSIZE
X (CE,32), ! RECTYPE
X (CE,33), ! STATUS
X (CE,33), ! TYPE
X (IE,36), ! UNIT
X (IE,16)), ! VERSION
LHVECTOR OPNDISP = OPNDUM,
RHVECTOR OPNCODE = OPNDUM;
! Values of keywords, pointers to expression nodes
OWN OPNVAL [KWDN+1];
FIRSTP = -1; ! FIRSTP is true iff we are at first
! item in list
DECR I FROM KWDN TO 0 DO OPNVAL[.I] = 0; ! clear keyword value table
IF LEXEMEGEN() NEQ LPAREN^18 THEN RETURN ERR0V(LPARPLIT);
! read left paren to start list
DO ! loop until right paren
BEGIN ! not keyword
K = LEXICAL(.GSTKSCAN); ! look for "KEYWORD="
IF .K EQL 0 ! keyword not found
THEN ! check for DIALOG and READONLY
BEGIN ! not keyword
LOOK4CHAR = (UPLIT ASCIZ 'READONLY')<36,7>;
IF LEXICAL(.GSTSSCAN) NEQ 0
THEN
BEGIN ! READONLY
N = NREADONLY; ! set keyword number
V = -1; ! set keyword value (none)
END ! READONLY
ELSE IF .FIRSTP ! if first thing in list
THEN ! must be unit expression
BEGIN ! unit expression
N = NUNIT; ! set keyword number
IF EXPRESS() LSS 0 THEN RETURN .VREG; ! read expression
V = .STK[.SP]; ! pop expression off stack
SP = .SP - 1;
IF .V[VALTYPE] NEQ INTEGER ! convert to integer
THEN V = CNVNODE(.V,INTEGER,0); ! if necessary
END ! unit expression
ELSE
BEGIN
LOOK4CHAR = (UPLIT ASCIZ 'DIALOG')<36,7>;
IF LEXICAL(.GSTSSCAN) NEQ 0
THEN
BEGIN ! DIALOG
N = NDIALOG; ! set keyword number
V = -1; ! set keyword value (none)
END ! DIALOG
ELSE
BEGIN ! error
LEXL = LEXEMEGEN();
RETURN ERR0L (UPLIT ASCIZ 'keyword');
END; ! error
END;
END ! not keyword
ELSE
BEGIN ! keyword
N = -1; ! set flag for keyword not found yet
DLP: DECR I FROM KWDN TO 0 DO ! look up keyword in table
IF .K EQL .OPNKWD[.I] THEN (N = .I; LEAVE DLP);
IF .N LSS 0 ! if keyword not found
THEN RETURN FATLEX(.K,E183<0,0>) ! say so and abort statement
ELSE
CASE .OPNDISP[.N] OF SET
% character expression %
BEGIN
IF EXPRESS() LSS 0 THEN RETURN .VREG;
V = .STK[.SP]; ! pop expression off stack
SP = .SP - 1;
! Any character expression is OK. Numeric expression
! must be scalar or arrayref. More complex expressions
! are hereby decreed meaningless, unVAXish and illegal.
IF .V[VALTYPE] NEQ CHARACTER
THEN IF .V[OPRCLS] EQL DATAOPR THEN %OK%
ELSE IF .V[OPRCLS] EQL ARRAYREF THEN %OK%
ELSE FATLEX(.K,E184<0,0>);
! "Illegal <keyword> specifier"
END;
% integer expression %
BEGIN
IF EXPRESS() LSS 0 THEN RETURN .VREG;
V = .STK[.SP]; ! pop expression off stack
SP = .SP - 1;
! Convert numeric expressions to integer if necessary.
! Character expressions are an error, except convert
! character constants to hollerith.
IF .V[VALTYPE] EQL CHARACTER
THEN IF .V[OPERATOR] EQL CHARCONST
THEN V[OPERATOR] = HOLLCONST
ELSE FATLEX(E164<0,0>)
! "Char expression used where
! numeric expression required"
ELSE IF .V[VALTYPE] NEQ INTEGER
THEN V = CNVNODE(.V,INTEGER,0);
END;
% label %
BEGIN
LABELS();
NONIOINIO = 1;
V = LEXL = LEXEMEGEN(); ! read label
NOLABELS();
NONIOINIO = 0;
IF .V<LEFT> NEQ LABELEX ! check that it is
THEN RETURN ERR0L(.LEXNAM[LABELEX]); ! a label
END;
% char expr or numeric array name %
BEGIN
FLGREG<FELFLG> = 1; ! allow bare array names
IF EXPRESS() LSS 0 THEN RETURN .VREG;
V = .STK[.SP]; ! pop expression off stack
SP = .SP - 1;
! If expression is numeric, it must be an array name.
! Use NAMREF to check this. If expression is character,
! it can be anything but an array or function name.
IF .V[VALTYPE] NEQ CHARACTER
%1676% AND .V[VALTYPE] NEQ HOLLERITH
THEN IF .V[OPRCLS] EQL DATAOPR
THEN NAMREF(ARRAYNM1,.V)
ELSE FATLEX(UPLIT'array or character expression',.K,E196<0,0>)
ELSE IF .V[OPRSP1] GEQ ARRAYNM1
THEN FATLEX(UPLIT'array or character expression',.K,E196<0,0>)
END;
% int variable %
BEGIN
IF SYNTAX(VARIABLESPEC) LSS 0 THEN RETURN .VREG;
V = BLDVAR(.STK[.SP]); ! pop variable off stack
SP = .SP - 1;
%1622% IF .V[OPRCLS] EQL ARRAYREF ! call NAMSET; this stmt
%1622% THEN NAMSET(ARRAYNM1,.V[ARG1PTR]) ! modifies the
ELSE NAMSET(VARIABL1,.V); ! variable
IF .V[VALTYPE] NEQ INTEGER ! must be type integer
THEN FATLEX (UPLIT'integer', .V[IDSYMBOL], E196<0,0>);
END;
TES;
END; ! keyword
IF .OPNVAL[.N] NEQ 0 ! if keyword already specified, error
THEN FATLEX (.OPNKWD[.N], E182<0,0>);
! "KEYWRD may only be specified once"
OPNVAL[.N] = .V; ! set value of keyword
FIRSTP = 0; ! not first in list any more
IF .LSAVE NEQ 0 THEN LSAVE = 0 ELSE LEXL = LEXEMEGEN(); ! read lexeme
END
WHILE .LEXL<LEFT> EQL COMMA; ! while comma-separated list
IF .LEXL<LEFT> NEQ RPAREN THEN RETURN ERR0L(RPARPLIT); ! read terminating )
IF LEXEMEGEN() NEQ LINEND^18 THEN RETURN ERR0V(EOSPLIT); ! followed by EOS
![1716] Check that UNIT got specified else return fatal error now
%1716% IF .OPNVAL[NUNIT] EQL 0
%1716% THEN RETURN FATLEX (UPLIT'specified',OPNKWD+NUNIT,E15<0,0>);
! Make a statement node and fill it in
NAME = IDOFSTATEMENT = .OPENCLOSDATA;
NAME<RIGHT> = SORTAB;
N = NEWENTRY(); ! N points to empty statement node
N[IOUNIT] = .OPNVAL[NUNIT]; ! set UNIT=
N[IOERR] = .OPNVAL[NERR]; ! set ERR=
N[IOIOSTAT] = .OPNVAL[NIOSTAT]; ! set IOSTAT=
OPNVAL[NUNIT] = OPNVAL[NERR] = OPNVAL[NIOSTAT] = 0; ! clear values out of table
K = .N[IOUNIT]; ! set UNIT expression parent pointer
IF .K[OPRCLS] NEQ DATAOPR
THEN K[PARENT] = .N;
! Count keywords and copy into their block
V = 0; ! V gets keyword count
DECR I FROM KWDN TO 0 DO
IF .OPNVAL[.I] NEQ 0 THEN V = .V + 1;
IF .V GTR 0
THEN
BEGIN ! copy keywords into block
NAME<LEFT> = N[OPSIZ] = .V; ! set keyword count
N[OPLST] = V = CORMAN(); ! get block, store its address
DECR I FROM KWDN TO 0 DO ! copy from OPNVAL into block
IF .OPNVAL[.I] NEQ 0
THEN
BEGIN
K = .OPNVAL[.I]; ! copy expression ptr
(.V)<RIGHT> = (IF .K LSS 0 THEN 0 ELSE .K);
(.V)<LEFT> = .OPNCODE[.I]; ! set Forots code
%1571% IF .K GEQ 0 ! unless DIALOG or READONLY
THEN IF .K[OPRCLS] NEQ DATAOPR ! set parent pointer if subnode
THEN K[PARENT] = .N; ! is an expression
V = .V + 1; ! next keyword
END;
END; ! copy keywords into block
END; ! OPENCLOSE
GLOBAL ROUTINE OPENSTA=
BEGIN
EXTERNAL OPENCLOSE;
OPENCLOSE(OPENDATA);
.VREG
END;
GLOBAL ROUTINE CLOSSTA=
BEGIN
EXTERNAL OPENCLOSE;
OPENCLOSE(CLOSDATA);
.VREG
END;
GLOBAL ROUTINE INQUSTA=
BEGIN
%1662% EXTERNAL
%1662% FATLEX, ! Error message routine
%1662% E210;
%1662% ! Give the NYI error - INQUIRE statement is not yet implemented
%1662% RETURN FATLEX(E210<0,0>);
END; ! of INQUSTA
END
ELUDOM