(* COPYRIGHT (C) 1978, REGENTS OF THE *) (* UNIVERSITY OF CALIFORNIA, SAN DIEGO *) PROCEDURE PROCDECLARATION(FSY: SYMBOL; SEGDEC: BOOLEAN); VAR LSY: SYMBOL; LCP,LCP1: CTP; LSP: STP; EXTONLY,FORW: BOOLEAN; LCM: ADDRRANGE; LLEXSTK: LEXSTKREC; PROCEDURE PARAMETERLIST(FSY: SETOFSYS; VAR FPAR: CTP; FCP: CTP); VAR LCP,LCP1,LCP2,LCP3: CTP; LSP: STP; LKIND: IDKIND; LLC,LEN : ADDRRANGE; COUNT : INTEGER; BEGIN LCP1 := NIL; LLC := LC; IF NOT (SY IN FSY + [LPARENT]) THEN BEGIN ERROR(7); SKIP(FSYS + FSY + [LPARENT]) END; IF SY = LPARENT THEN BEGIN IF FORW THEN ERROR(119); INSYMBOL; IF NOT (SY IN [IDENT,VARSY]) THEN BEGIN ERROR(7); SKIP(FSYS + [IDENT,RPARENT]) END; WHILE SY IN [IDENT,VARSY] DO BEGIN IF SY = VARSY THEN BEGIN LKIND := FORMAL; INSYMBOL END ELSE LKIND := ACTUAL; LCP2 := NIL; COUNT := 0; REPEAT IF SY <> IDENT THEN ERROR(2) ELSE BEGIN NEW(LCP,FORMALVARS,FALSE); (*MAY BE ACTUAL(SAME SIZE)*) WITH LCP^ DO BEGIN NAME := ID; IDTYPE := NIL; NEXT := LCP2; IF LKIND = FORMAL THEN KLASS := FORMALVARS ELSE KLASS := ACTUALVARS; VLEV := LEVEL END; ENTERID(LCP); LCP2 := LCP; COUNT := COUNT + 1; INSYMBOL END; IF NOT (SY IN FSYS + [COMMA,SEMICOLON,COLON]) THEN BEGIN ERROR(7); SKIP(FSYS + [COMMA,SEMICOLON,RPARENT,COLON]) END; TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; LSP := NIL; IF SY = COLON THEN BEGIN INSYMBOL; IF SY = IDENT THEN BEGIN SEARCHID([TYPES],LCP); INSYMBOL; LSP := LCP^.IDTYPE; LEN := PTRSIZE; IF LSP <> NIL THEN IF LKIND = ACTUAL THEN IF LSP^.FORM = FILES THEN ERROR(121) ELSE IF LSP^.FORM <= POWER THEN LEN := LSP^.SIZE; LC := LC + COUNT * LEN END ELSE ERROR(2) END ELSE IF LKIND = FORMAL THEN EXTONLY := TRUE ELSE ERROR(5); IF NOT (SY IN FSYS + [SEMICOLON,RPARENT]) THEN BEGIN ERROR(7); SKIP(FSYS + [SEMICOLON,RPARENT]) END; LCP3 := LCP2; LCP := NIL; WHILE LCP2 <> NIL DO BEGIN LCP := LCP2; WITH LCP2^ DO BEGIN IDTYPE := LSP; LCP2 := NEXT END END; IF LCP <> NIL THEN BEGIN LCP^.NEXT := LCP1; LCP1 := LCP3 END; IF SY = SEMICOLON THEN BEGIN INSYMBOL; IF NOT (SY IN FSYS + [IDENT,VARSY]) THEN BEGIN ERROR(7); SKIP(FSYS + [IDENT,RPARENT]) END END END (*WHILE*) ; IF SY = RPARENT THEN BEGIN INSYMBOL; IF NOT (SY IN FSY + FSYS) THEN BEGIN ERROR(6); SKIP(FSY + FSYS) END END ELSE ERROR(4); FCP^.LOCALLC := LC; LCP3 := NIL; WHILE LCP1 <> NIL DO WITH LCP1^ DO BEGIN LCP2 := NEXT; NEXT := LCP3; IF (IDTYPE <> NIL) THEN IF KLASS = FORMALVARS THEN BEGIN VADDR := LLC; LLC := LLC + PTRSIZE END ELSE IF KLASS = ACTUALVARS THEN IF (IDTYPE^.FORM <= POWER) THEN BEGIN VADDR := LLC; LLC := LLC + IDTYPE^.SIZE END ELSE BEGIN VADDR := LC; LC := LC + IDTYPE^.SIZE; LLC := LLC + PTRSIZE END; LCP3 := LCP1; LCP1 := LCP2 END; FPAR := LCP3 END ELSE FPAR := NIL END (*PARAMETERLIST*) ; BEGIN (*PROCDECLARATION*) IF SEGDEC THEN (* SEGMENT DECLARATION *) BEGIN IF CODEINSEG THEN BEGIN ERROR(399); SEGINX:=0; CURBYTE:=0; END; WITH LLEXSTK DO BEGIN DOLDSEG:=SEG; SEG:=NEXTSEG; SOLDPROC:=NEXTPROC; END; NEXTPROC:=1; LSY:=SY; IF SY IN [PROCSY,FUNCSY] THEN INSYMBOL ELSE BEGIN ERROR(399); LSY:=PROCSY END; FSY:=LSY; END; LLEXSTK.DLLC := LC; LC := LCAFTERMARKSTACK; IF FSY = FUNCSY THEN LC := LC + REALSIZE; LINEINFO := LC; DP := TRUE; EXTONLY := FALSE; IF SY = IDENT THEN BEGIN IF USING OR INMODULE AND ININTERFACE THEN FORW := FALSE ELSE BEGIN SEARCHSECTION(DISPLAY[TOP].FNAME,LCP); IF LCP <> NIL THEN BEGIN IF LCP^.KLASS = PROC THEN FORW := LCP^.FORWDECL AND (FSY = PROCSY) AND (LCP^.PFKIND = ACTUAL) ELSE IF LCP^.KLASS = FUNC THEN FORW := LCP^.FORWDECL AND (FSY = FUNCSY) AND (LCP^.PFKIND = ACTUAL) ELSE FORW := FALSE; IF NOT FORW THEN ERROR(160) END ELSE FORW := FALSE END; IF NOT FORW THEN BEGIN IF FSY = PROCSY THEN IF INMODULE THEN NEW(LCP,PROC,DECLARED,ACTUAL,TRUE) ELSE NEW(LCP,PROC,DECLARED,ACTUAL,FALSE) ELSE IF INMODULE THEN NEW(LCP,FUNC,DECLARED,ACTUAL,TRUE) ELSE NEW(LCP,FUNC,DECLARED,ACTUAL,FALSE); WITH LCP^ DO BEGIN NAME := ID; IDTYPE := NIL; LOCALLC := LC; PFDECKIND := DECLARED; PFKIND := ACTUAL; INSCOPE := FALSE; PFLEV := LEVEL; PFNAME := NEXTPROC; PFSEG := SEG; IF USING THEN PROCTABLE[NEXTPROC] := 0; IF INMODULE THEN IF USING THEN IMPORTED := TRUE ELSE IMPORTED := FALSE; IF SEGDEC THEN BEGIN IF NEXTSEG > MAXSEG THEN ERROR(250); NEXTSEG := NEXTSEG+1; SEGTABLE[SEG].SEGNAME := ID END; IF NEXTPROC = MAXPROCNUM THEN ERROR(251) ELSE NEXTPROC := NEXTPROC + 1; IF FSY = PROCSY THEN KLASS := PROC ELSE KLASS := FUNC END; ENTERID(LCP) END ELSE BEGIN LCP1 := LCP^.NEXT; WHILE LCP1 <> NIL DO BEGIN WITH LCP1^ DO IF IDTYPE = NIL THEN EXTONLY := TRUE ELSE IF KLASS = FORMALVARS THEN BEGIN LCM := VADDR + PTRSIZE; IF LCM > LC THEN LC := LCM END ELSE IF KLASS = ACTUALVARS THEN BEGIN LCM := VADDR + IDTYPE^.SIZE; IF LCM > LC THEN LC := LCM END; LCP1 := LCP1^.NEXT END; IF SEG <> LCP^.PFSEG THEN BEGIN SEG := LCP^.PFSEG; NEXTPROC := 2; IF NOT SEGDEC THEN ERROR(399) END END; INSYMBOL END ELSE BEGIN ERROR(2); LCP := UPRCPTR END; WITH LLEXSTK DO BEGIN DOLDLEV:=LEVEL; DOLDTOP:=TOP; POLDPROC:=CURPROC; DFPROCP:=LCP; END; CURPROC := LCP^.PFNAME; IF LEVEL < MAXLEVEL THEN LEVEL := LEVEL + 1 ELSE ERROR(251); IF TOP < DISPLIMIT THEN BEGIN TOP := TOP + 1; WITH DISPLAY[TOP] DO BEGIN IF FORW THEN FNAME := LCP^.NEXT ELSE FNAME := NIL; FLABEL := NIL; FFILE := NIL; OCCUR := BLCK END END ELSE ERROR(250); IF FSY = PROCSY THEN BEGIN PARAMETERLIST([SEMICOLON],LCP1,LCP); IF NOT FORW THEN LCP^.NEXT := LCP1 END ELSE BEGIN PARAMETERLIST([SEMICOLON,COLON],LCP1,LCP); IF NOT FORW THEN LCP^.NEXT := LCP1; IF SY = COLON THEN BEGIN INSYMBOL; IF SY = IDENT THEN BEGIN IF FORW THEN ERROR(122); SEARCHID([TYPES],LCP1); LSP := LCP1^.IDTYPE; LCP^.IDTYPE := LSP; IF LSP <> NIL THEN IF NOT (LSP^.FORM IN [SCALAR,SUBRANGE,POINTER]) THEN BEGIN ERROR(120); LCP^.IDTYPE := NIL END; INSYMBOL END ELSE BEGIN ERROR(2); SKIP(FSYS + [SEMICOLON]) END END ELSE IF NOT FORW THEN ERROR(123) END; IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14); LCP^.EXTURNAL := FALSE; IF (SY = EXTERNLSY) OR ((USING) AND (LSEPPROC)) THEN BEGIN IF LEVEL <> 2 THEN ERROR(183) (*EXTERNAL PROCS MUST BE IN OUTERMOST BLOCK*); IF INMODULE THEN IF ININTERFACE AND NOT USING THEN ERROR(184); (*NO EXTERNAL DECL IN INTERFACE*) IF SEGDEC THEN ERROR(399); WITH LCP^ DO BEGIN EXTURNAL := TRUE; FORWDECL := FALSE; WRITELN(OUTPUT); WRITELN(OUTPUT,NAME,' [',MEMAVAIL:5,' words]'); WRITE(OUTPUT,'<',SCREENDOTS:4,'>') END; PROCTABLE[CURPROC] := 0; DLINKERINFO := TRUE; IF SY = EXTERNLSY THEN BEGIN INSYMBOL; IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14); IF NOT (SY IN FSYS) THEN BEGIN ERROR(6); SKIP(FSYS) END END END ELSE IF USING THEN BEGIN LCP^.FORWDECL := FALSE; END ELSE IF (SY = FORWARDSY) OR INMODULE AND ININTERFACE THEN BEGIN IF FORW THEN ERROR(161) ELSE LCP^.FORWDECL := TRUE; IF SY = FORWARDSY THEN BEGIN INSYMBOL; IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14) END; IF NOT (SY IN FSYS) THEN BEGIN ERROR(6); SKIP(FSYS) END END ELSE BEGIN IF EXTONLY THEN ERROR(7); NEWBLOCK:=TRUE; NOTDONE:=TRUE; WITH LLEXSTK DO BEGIN MARK(DMARKP); WITH LCP^ DO BEGIN FORWDECL := FALSE; INSCOPE := TRUE; EXTURNAL := FALSE END; BFSY:=SEMICOLON; ISSEGMENT:=SEGDEC; PREVLEXSTACKP:=TOS; END; NEW(TOS); TOS^:=LLEXSTK; EXIT(PROCDECLARATION); END; WITH LLEXSTK DO (* FORWARD OR EXTERNAL DECLARATION, SO RESTORE STATE *) BEGIN LEVEL:=DOLDLEV; TOP:=DOLDTOP; LC:=DLLC; CURPROC:=POLDPROC; IF SEGDEC THEN BEGIN NEXTPROC:=SOLDPROC; SEG:=DOLDSEG; END; END; END; (* PROCDECLARATION *) BEGIN (*DECLARATIONPART*) IF (NOSWAP) AND (STARTINGUP) THEN BEGIN STARTINGUP:=FALSE; (* ALL SEGMENTS ARE IN BY THIS TIME *) BLOCK(FSYS); EXIT(DECLARATIONPART); END; IF NOISY THEN UNITWRITE(3,DUMMYVAR[-1600],35); (*ADJUST DISPLAY OF STACK AND HEAP*) REPEAT NOTDONE:=FALSE; IF USERINFO.STUPID THEN IF NOT CODEINSEG THEN IF (LEVEL = 1) AND (NEXTSEG = 10) THEN IF NOT(INMODULE OR USING) THEN USESDECLARATION(TRUE); (*To get turtle graphics*) IF SY = USESSY THEN BEGIN INSYMBOL; USESDECLARATION(FALSE) END; IF SY = LABELSY THEN BEGIN IF INMODULE AND ININTERFACE THEN BEGIN ERROR(186); SKIP(FSYS - [LABELSY]) END ELSE INSYMBOL; LABELDECLARATION END; IF SY = CONSTSY THEN BEGIN INSYMBOL; CONSTDECLARATION END; IF SY = TYPESY THEN BEGIN INSYMBOL; TYPEDECLARATION END; IF SY = VARSY THEN BEGIN INSYMBOL; VARDECLARATION END; IF LEVEL = 1 THEN GLEV := TOP; IF SY IN [PROCSY,FUNCSY,PROGSY] THEN BEGIN IF INMODULE THEN IF ININTERFACE AND NOT USING THEN PUBLICPROCS := TRUE; REPEAT LSY := SY; INSYMBOL; IF LSY = PROGSY THEN IF INMODULE THEN BEGIN ERROR(185 (*SEG DEC NOT ALLOWED IN UNIT*)); PROCDECLARATION(PROCSY,FALSE) END ELSE PROCDECLARATION(LSY,TRUE) ELSE PROCDECLARATION(LSY,FALSE); UNTIL NOT (SY IN [PROCSY,FUNCSY,PROGSY]) END; IF (SY <> BEGINSY) THEN IF NOT ((USING OR INMODULE) AND (SY IN [IMPLESY,ENDSY])) AND NOT( SY IN [SEPARATSY,UNITSY]) THEN IF (NOT (INCLUDING OR NOTDONE)) OR NOT(SY IN BLOCKBEGSYS) THEN BEGIN ERROR(18); SKIP(FSYS - [UNITSY,INTERSY]); END; UNTIL (SY IN (STATBEGSYS + [SEPARATSY,UNITSY,IMPLESY,ENDSY])); NEWBLOCK:=FALSE; END (*DECLARATIONPART*) ;