{ > PasExpr } { Tutu 20 feb 86 - hacked array totalbytes for new array access code } { Tutu 17 feb 86 - fixed caray conformance with D1.07 } { Tutu 11 feb 86 - hacked array access stuff } { Tutu hacked for ARM 29 jan 86 } { Sam fixed for Bug 14 with buffer variables -> D1.05 } FUNCTION SIGNABLE : BOOLEAN; { This function returns true if THISSYMP points to a descriptor which describes a type that can be preceeded by a sign (+ or -). } BEGIN SIGNABLE := (THISSYMP^.IDTYP = REEL) OR (ISINT (THISSYMP^)) END; { signable } PROCEDURE KONSTANT; { This procedure gets a constant (signed or unsigned) from the source file. The constant descriptor is pointed to by THISSYMP. } BEGIN GETSIGN; IF SYM <> KONST THEN ERROR (111); {CONSTANT EXPECTED} IF SIGNED THEN IF SIGNABLE THEN BEGIN IF NEGSIGN THEN BEGIN BASESYMP^ := THISSYMP^; IF THISSYMP^.IDTYP = REEL THEN BASESYMP^.REELVAL := -(THISSYMP^.REELVAL) ELSE BASESYMP^.VAL := -(THISSYMP^.VAL); THISSYMP := BASESYMP END END ELSE ERROR (112) END; { konstant } PROCEDURE ORDCON; { This procedure gets an ordinal constant from the source file. i.e. idtyp = subr (ange). } BEGIN KONSTANT; IF THISSYMP^.IDTYP <> SUBR THEN BEGIN ERROR (136); THISSYMP^.VAL := 0 END END; { ordcon } PROCEDURE UC; { Unsigned constant } { This procedure gets an unsigned constant (including NIL) from source file. } BEGIN IF SYM = KONST THEN BEGIN IF (NOT SIGNABLE) AND (SIGNED) THEN ERROR (112) END ELSE IF SYM = NILSY THEN BEGIN IF SIGNED THEN ERROR (112); BASESYMP^.IDTYP := PNTR; BASESYMP^.VAL := 0; THISSYMP := BASESYMP END ELSE ERROR (111) END; { uc } PROCEDURE SETFUN (VAR FUNCRES : SYMREC; FUNCDESC : SYMREC); { This procedure is used to set a id descriptor to hold info on a function's return result. } BEGIN FUNCRES := FUNCDESC; FUNCRES.REF := FUNCDESC.REF^.FUNCREF; FUNCRES.LEV := SUCC (FUNCDESC.LEV); FUNCRES.ADR := FUNCDESC.REF^.FUNCVAR END; { setfun } PROCEDURE SETSUBRTYP (VAR DESCREK : SYMREC;DESC : STP); { This procedure sets an id descriptor to hold info on a subr (ange) type whose type is pointed to by DESC. } BEGIN DESCREK.IDTYP := SUBR; DESCREK.OBJ := KONST; DESCREK.REF := DESC END; { setsubrtyp } FUNCTION ISLAB : BOOLEAN; { This function returns TRUE if the symbol just read could be a LABEL. ie. integer constant represented by digits, not an identifier. } BEGIN ISLAB := (SYM = KONST) AND (BASESYMP = THISSYMP) AND (ISINT (THISSYMP^)) END; { islab } PROCEDURE DEBLINE; { If DEBUG is TRUE then this procedure outputs a here_is_short_debug_line BL-code to the temp code file if the line number is less than 256 otherwise a here_is_long_debug_line BL-code is output. If DEBUG is FALSE then this procedure does nothing. } BEGIN IF DEBUG THEN genopwtb (&4E, x.lineno) { Tutu - debug_line_long } { Tutu - was GENLORS (253-ORD (X.LINENO > 255) * 217,X.LINENO) {} END; { debline } FUNCTION CONTAINSFILE (TP : TYPES; RF : TYPREC; CHKTP : BOOLEAN) : BOOLEAN; { This function recursively searches down through a linked list structure describing a type and returns TRUE if the type contains a file type anywhere in it. If the initial type (TP) is not to be checked then CHKTP is passed in a value FALSE. Superb bit of programming. } VAR CONTAINS : BOOLEAN; LAST : SYMP; BEGIN CONTAINS := CHKTP AND (TP >= FYLE); IF NOT CONTAINS THEN BEGIN CASE TP OF FYLE,TXT : CONTAINS := CONTAINSFILE (RF.TYP,RF.FILEREF^,TRUE); ARAY,CARAY : CONTAINS := CONTAINSFILE (RF.TYP,RF.ELREF^ ,TRUE); REKORD : BEGIN LAST := RF.LASTSYM; WHILE (LAST <> NIL) AND (NOT CONTAINS) DO BEGIN { search all field identifier types } CONTAINS := CONTAINSFILE (LAST^.IDTYP,LAST^.REF^,TRUE); LAST := LAST^.LINK END END END OTHERWISE END; CONTAINSFILE := CONTAINS END; { containsfile } FUNCTION LIMITS (DESC : SYMREC) : SI; { This function returns the high bound of a subrange or the length of a string. It also sets a global variable LLIM to the low bound of the subrange or 1 if it is a string. For ordinal constants the high and low bounds are the same. } BEGIN IF DESC.OBJ = KONST THEN BEGIN IF DESC.IDTYP = SUBR THEN BEGIN LIMITS := DESC.VAL; LLIM := DESC.VAL END ELSE BEGIN LIMITS := DESC.STRLEN; LLIM := 1 END END ELSE BEGIN IF DESC.IDTYP <> SUBR THEN DESC.REF := DESC.REF^.IREF; LIMITS := DESC.REF^.HIGH; LLIM := DESC.REF^.LOW END END; { limits } FUNCTION EQTYPS (VAR LEFT : SYMREC; RIGHT:SYMREC; ASSIGNCHK:BOOLEAN) : BOOLEAN; { This function checks that the types described by LEFT and RIGHT are compatible (EQTYPS returns true if they are else false). If they are mixed integer and real then MIXED is set true and EQTYPS returns false. This function also generates range checking code if ASSIGNCHK is true and also does type conversion for integers which should be reals. } VAR NO_CONSTS : BOOLEAN; LEFTC : SYMREC; LREF, RREF : TYPREC; BEGIN MIXED := FALSE; LEFTC := LEFT; LREF := LEFTC.REF^; RREF := RIGHT.REF^; IF LEFTC.IDTYP = RIGHT.IDTYP THEN BEGIN EQTYPS := TRUE; NO_CONSTS := (LEFTC.OBJ <> KONST) AND (RIGHT.OBJ <> KONST); IF NO_CONSTS THEN EQTYPS := LEFTC.REF = RIGHT.REF; CASE LEFTC.IDTYP OF STRNG : BEGIN { Check that strings are the same size } EQTYPS := (LIMITS (LEFTC) = LIMITS (RIGHT)) END; SUBR : BEGIN { Check for subranges ie ordinals } EQTYPS := (LREF.TYP = RREF.TYP) AND (LREF.SUBRREF = RREF.SUBRREF); END; SETT : BEGIN IF NO_CONSTS THEN EQTYPS := LEFTC.PAK = RIGHT.PAK; IF (LEFTC.REF <> NIL) AND (RIGHT.REF <> NIL) THEN IF (LREF.TYP <> RREF.TYP) OR (LREF.SUBRREF <> RREF.SUBRREF) THEN BEGIN ERROR (139); EQTYPS := FALSE END END END OTHERWISE; { Generate range checking code if required } IF (RNGCHK AND ASSIGNCHK) AND ((LEFTC.IDTYP = SETT) OR (LEFTC.IDTYP = SUBR)) THEN IF ISINT (LEFTC) THEN BEGIN IF (LREF.LOW <> -MAXINT) OR (LREF.HIGH <> MAXINT) THEN { Tutu - was IF BYTES (LREF.LOW,LREF.HIGH) = 1 THEN BEGIN FLUSHNGEN (&F6{Chk_int_s{{); GENUB (LREF.LOW); GENUB (LREF.HIGH) END ELSE } BEGIN FLUSHNGEN (76{Chk_int_l}); GENSI (LREF.LOW); GENSI (LREF.HIGH) END END ELSE BEGIN FLUSHNGEN (74{Chkbce}+ (ORD (LEFTC.IDTYP = SETT)*150)); GENUB (LREF.LOW); GENUB (LREF.HIGH) END END ELSE BEGIN { Check for mixed integer and real operands } EQTYPS := FALSE; IF LEFTC.IDTYP = REEL THEN BEGIN IF ISINT (RIGHT) THEN BEGIN { Gen code to convert TOS to real} FLUSHNGEN (FLTROP); EQTYPS := ASSIGNCHK; MIXED := TRUE END END ELSE IF (RIGHT.IDTYP = REEL) AND (ISINT (LEFTC)) THEN BEGIN { Gen code to convert TOS-1 to real } IF ASSIGNCHK THEN ERROR (11) { Can't assign real to integer } ELSE BEGIN LEFT.IDTYP := REEL; LEFT.REF := NIL END; FLUSHNGEN (FLTLOP); MIXED := TRUE END END END; { eqtyps } PROCEDURE VAL_CONF_DISPOSE (THISSYMP : SYMP); { This procedure generates code to dispose of a value_conformant_array copy on the heap. Called when a GOTO out of, or the end of the procedure is found. } BEGIN WHILE THISSYMP <> NIL DO BEGIN IF (THISSYMP^.IDTYP = CARAY) AND THISSYMP^.NRM THEN BEGIN IF X.ACTIVLEV <> X.LEVEL THEN SETLEV (X.LEVEL); { Tutu - both 11's below were 15's - psh_int instead of psh_uwd } GENLORS (11,THISSYMP^.ADR); { Push array_copy adr on heap to TOS } GENLORS (11,THISSYMP^.ADR+4); { Push array_copy size to TOS } GENUB (168) { Release heap } END; THISSYMP := THISSYMP^.LINK END END; { val_conf_dispose } PROCEDURE BLKSTMT (TERMSY : SYMBOLS); { This procedure parses a Block_statement which is redefined by me as BEGIN [statement_seq] END or REPEAT [statement_seq] UNTIL boolean where statement_seq is defined as stmt [; stmt]. See 'passtmt' file for BLKSTMT procedure block. } VAR THISSEQ : UW; PROCEDURE STKUP (STKEL : UW); { This procedure increments the amount of crap on the stack by STKEL and keeps track of the largest size that the stack grows to. (Only approximate but, close enough). } BEGIN X.STKINC := STKEL + X.STKINC; IF X.STKINC > X.MAXSTK THEN X.MAXSTK := X.STKINC END; { stkup } PROCEDURE APARAMLIST (LASTPARAM : SYMP); FORWARD; { This procedure parses an actual parameter list by calling GETARG (which type checks the parameter) for each parameter in the list. Also checks that number of parameters are correct. } PROCEDURE PFCALL (PROCDESC : SYMP); { This procedure parses all user procedure or function calls and generates code to call them. If PROCDESC^.NRM is false then this procedure is a procedural parameter. } BEGIN IF NOT PROCDESC^.NRM THEN BEGIN { Procedural parameter } GENUB (67); { Push Display } STKUP (dspsize) { Tutu - was 16 } END; FLUSHNGEN (MARKS); STKUP (hkfsize); { Tutu - was 9 } APARAMLIST (PROCDESC^.REF^.LASTPARAM); IF PROCDESC^.NRM THEN BEGIN FLUSHNGEN (CALLS); { Tutu - was GENUB (PROCDESC^.ADR) {} genuw (procdesc^.adr) { Tutu } END ELSE BEGIN { Procedural parameter } IF X.ACTIVLEV <> PROCDESC^.LEV THEN SETLEV (PROCDESC^.LEV); GENOPWTB (225,PROCDESC^.ADR); { S_call_param } FLUSHNGEN (239) { Debodge_display } END; X.ACTIVLEV := X.LEVEL END; { pfcall } PROCEDURE FACTOR (VAR CODEINFO:SYMREC; VAR STKEL : UW); FORWARD; { This procedure parses a factor. } PROCEDURE TERM (VAR LFACTOR:SYMREC; VAR LSTKEL : UW); { This procedure parses a term. ie FACTOR 0orMore[ multop FACTOR]. } VAR SAVEMULTOP : SYMBOLS; RFACTOR : SYMREC; RSTKEL : UW; BEGIN FACTOR (LFACTOR,LSTKEL); WHILE SYM IN [MULT,SLASH,DIVSY,MODSY,ANDSY] DO BEGIN SAVEMULTOP := SYM; NXTSYMOK; FACTOR (RFACTOR,RSTKEL); X.STKINC := (-RSTKEL) + X.STKINC; CASE SAVEMULTOP OF ANDSY : BEGIN IF (LFACTOR.REF <> BOOLDESC) OR (RFACTOR.REF <> BOOLDESC) THEN ERROR (161); FLUSHNGEN (ANDOP) END; MODSY, DIVSY : BEGIN IF NOT (ISINT (LFACTOR) AND ISINT (RFACTOR)) THEN ERROR (163); IF SAVEMULTOP = MODSY THEN FLUSHNGEN (MODOP) ELSE FLUSHNGEN (IDIVOP) END; SLASH : BEGIN IF EQTYPS (LFACTOR,RFACTOR,FALSE) OR MIXED THEN BEGIN IF LFACTOR.IDTYP <> REEL THEN BEGIN IF NOT ISINT (LFACTOR) THEN ERROR (159); FLUSHNGEN (FLTROP); FLUSHNGEN (FLTLOP) END; FLUSHNGEN (RDIVOP) END ELSE ERROR (159); LFACTOR.IDTYP := REEL; LFACTOR.REF := NIL END; MULT : BEGIN IF EQTYPS (LFACTOR,RFACTOR,FALSE) OR MIXED THEN BEGIN IF LFACTOR.IDTYP = REEL THEN FLUSHNGEN (RMULOP) ELSE IF ISINT (LFACTOR) THEN FLUSHNGEN (IMULOP) ELSE IF LFACTOR.IDTYP = SETT THEN FLUSHNGEN (SMULOP) ELSE ERROR (159) END ELSE ERROR (159) END END { case } END END; { term } PROCEDURE GB (OP : UB; DESC : SYMREC); { This procedure is called when a subtraction, addition or relational operation BL-code is needed. Passed into the procedure in OP is the basic operation eg op_add_int = 106 (which is the first BL-code add_operation). The machine code call to TABSEARCH looks up in a table (indexing on DESC.IDTYP) a byte value, which is the offset to add to the basic operation to get to the operation of the correct type. eg if DESC.IDTYP = real then the offset returned is 14 which when added to 106 gives 120 which is the BL-code op_add_real } BEGIN IF ISINT (DESC) THEN DESC.IDTYP := INT; FLUSHNGEN (OP + CODE0 (TABSEARCH,ORD (DESC.IDTYP),OLO,OHI{OPTYPVAL}) MOD 128) END; { gb } PROCEDURE SIMPEXP (VAR LTERM:SYMREC; VAR LSTKEL : UW); { This procedure parses a simple expression. ie. [SIGN] TERM 0orMore[ ADDOP TERM] } VAR SAVEADOP : SYMBOLS; RTERM : SYMREC; ISNEGSIGN, HASSIGN : BOOLEAN; RSTKEL : UW; BEGIN GETSIGN; HASSIGN := SIGNED; ISNEGSIGN := NEGSIGN; TERM (LTERM,LSTKEL); IF HASSIGN THEN BEGIN IF (ISINT (LTERM)) OR (LTERM.IDTYP = REEL) THEN BEGIN IF ISNEGSIGN THEN BEGIN { Inverse of term required } IF LTERM.IDTYP = REEL THEN FLUSHNGEN (RNEGOP) ELSE FLUSHNGEN (INEGOP) END END ELSE ERROR (112) { Can't sign non numerics } END; WHILE SYM IN [PLUS,MINUS,ORSY] DO BEGIN SAVEADOP := SYM; NXTSYMOK; SIGNED := FALSE; TERM (RTERM,RSTKEL); X.STKINC := (-RSTKEL) + X.STKINC; IF SAVEADOP = ORSY THEN BEGIN IF (LTERM.REF <> BOOLDESC)OR (RTERM.REF <> BOOLDESC) THEN ERROR (161); FLUSHNGEN (OROP) END ELSE BEGIN IF EQTYPS (LTERM,RTERM,FALSE) OR MIXED THEN BEGIN IF (LTERM.IDTYP <> REEL) AND (LTERM.IDTYP <> SETT) AND (NOT ISINT (LTERM)) THEN ERROR (159); GB (ORD (SAVEADOP)+94,LTERM) END ELSE ERROR (159) END END END; { simpexp } PROCEDURE EXPRESSION (VAR LSIMP:SYMREC; VAR LSTKEL : UW); { This procedure parses an expression. ie. SIMPLE_EXPRESSION [RELOP SIMPLE_EXPRESSION]. } VAR SAVERELOP : SYMBOLS; RSIMP : SYMREC; RSTKEL : UW; BEGIN SIMPEXP (LSIMP,LSTKEL); IF SYM IN [EQUALS,NE,LT,GT,LE,GE,INSY] THEN BEGIN SAVERELOP := SYM; NXTSYMOK; SIMPEXP (RSIMP,RSTKEL); X.STKINC := (-(RSTKEL + LSTKEL)) + X.STKINC + reasize; { Tutu - was 5 } IF SAVERELOP = INSY THEN BEGIN IF (RSIMP.IDTYP = SETT) AND (LSIMP.IDTYP = SUBR) THEN BEGIN IF ISINT (LSIMP) THEN FLUSHNGEN (IINOP) ELSE FLUSHNGEN (BINOP); IF RSIMP.REF <> NIL THEN IF LSIMP.REF^.SUBRREF <> RSIMP.REF^.SUBRREF THEN ERROR (78) END ELSE ERROR (159) END ELSE IF EQTYPS (LSIMP,RSIMP,FALSE) OR MIXED THEN BEGIN IF (SAVERELOP >= LE) THEN BEGIN IF (LSIMP.IDTYP=PNTR) OR ((LSIMP.IDTYP=SETT) AND (SAVERELOP >= LT)) THEN ERROR (159) END; IF LSIMP.IDTYP > STRNG THEN ERROR (159); GB (ORD (SAVERELOP)+69,LSIMP); IF LSIMP.IDTYP = STRNG THEN GENUW (LIMITS (LSIMP)) END ELSE ERROR (6); SETSUBRTYP (LSIMP,BOOLDESC) END END; { expression } PROCEDURE EXPRESS (VAR DESC:SYMREC); { This procedure is used to call EXPRESSION when the returned value of STKEL is not needed. It saves on code by not having to call EXPRESSION with 2 params. } VAR STKEL : UW; BEGIN EXPRESSION (DESC,STKEL) END; { express } PROCEDURE LOCADESC (ARRAE : SYMREC; ADESCREF : STP); { This procedure generates code to push the address of the array descriptor associated with ARRAE onto the stack. } VAR LOCORPUSH : UB; BEGIN IF ARRAE.IDTYP = CARAY THEN BEGIN ARRAE.IDTYP := PNTR; LOCORPUSH := PUSH END ELSE BEGIN LOCORPUSH := LOCATE; ARRAE.IDTYP := REKORD END; ARRAE.NRM := TRUE; ARRAE.OBJ := VARID; ARRAE.LEV := ADESCREF^.ALEV MOD 128; ARRAE.ADR := ADESCREF^.ADESCOFF; GENMOV (LOCORPUSH,ARRAE) END; { locadesc } PROCEDURE ACTIVREC (RECDESC : SYMREC); { This procedure adds the record's field id list (pointed to by a field of RECDESC) to the list of activated field identifiers. Also checks that RECDESC does actually describe a record. } BEGIN NEW (NEWACTIVE); NEWACTIVE^.NEXT := ACTIVELIST; ACTIVELIST := NEWACTIVE; NEWACTIVE^.FIELDS := NIL; IF RECDESC.IDTYP <> REKORD THEN ERROR (150) ELSE NEWACTIVE^.FIELDS := RECDESC.REF { Activate this record's field ids } END; { activrec } PROCEDURE VARACCESS (VAR CODEINFO:SYMREC); { This procedure is used to parse any variable access. ie. either generates code to get the address of a variable onto the stack, or if it is a simple variable which is not a var param then it sets NOCODE to true and returns without generating any code (the caller should then generate the code). To parse the variable, repetition is used rather than recursion. } VAR ENDACCESS, { End of variable detected } LOOP : BOOLEAN; { Used in the array parser to signal that another index is present (ie comma detected) } COPYINFO, INDEXINFO : SYMREC; { Holds array's index & record's field descriptor. } ADESC1, { Holds pointer to first the array descriptor in case of multidimensional arrays (ADESCOFF must be the base of the first array, same goes for ALEV) } SAVEREF : STP; { Saves COPYINFO.REF } FOFFSET, { Record's field offset if variable is a field } DESCOFF, { Offset from start of array descriptor to find start of sub_array descriptor. } { TOTBYTES : SI; { Total number of bytes on the stack for a Removed by Tutu 21-Feb-86 BL-code array_access. } DIMS : UB; { Number of parsed dimensions of the array. } SAVECADR, { Saved code address (to say if any code has been generated by the variable access. } STKP : UW; { Used to save the stack pointer in order to restore it later. } SAVERETKONST, NOT_CARAY, this_vars_LHS : BOOLEAN; { Sam - fixes Bug 14 } PROCEDURE LOCVAR; { This procedure is used to locate a variable. ie. get its address on TOS. } BEGIN IF COPYINFO.IDTYP = CARAY THEN COPYINFO.NRM := FALSE; GENMOV (LOCATE,COPYINFO); IF (COPYINFO.OBJ = FIELD) OR (COPYINFO.OBJ = TAG) THEN GENRECOFF (FOFFSET) END; { locvar } BEGIN { varaccess } this_vars_LHS := LHS; { Sam } DESCOFF := 0; ENDACCESS := FALSE; FLUSH; COPYINFO := THISSYMP^; SIMPLE := TRUE; { Flags if variable is a simple variable } NOCODE := FALSE; SAVECADR := X.CADR; IF NOT (COPYINFO.OBJ IN [VARID,FIELD,TAG,FUNC]) THEN ERROR (1); IF COPYINFO.IDTYP >= FYLE THEN IF COPYINFO.ADR < -2 THEN { Permanent file not declared in global vars } ERROR (153) ELSE IF COPYINFO.ADR < 0 THEN ERROR (16); IF COPYINFO.OBJ = FUNC THEN BEGIN IF DISPLAY[SUCC (COPYINFO.LEV)] <> COPYINFO.REF THEN ERROR (66); { Can only assign value to current function id } SETFUN (COPYINFO,COPYINFO); THISSYMP^.FUNCASS := TRUE; { Flags that the func id has been assigned} IF NOT LHS THEN { Function designators are allowed only on the left } ERROR (67); { hand side of an assignment statement } IF NOT COPYINFO.NRM THEN ERROR (99); END; IF (COPYINFO.OBJ = FIELD) OR (COPYINFO.OBJ = TAG) THEN BEGIN FOFFSET := COPYINFO.ADR; COPYINFO.NRM := FALSE; COPYINFO.LEV := X.LEVEL; SIMPLE := FALSE; COPYINFO.ADR := THISACTIVE^.WITHADR END; NEXTSYM; ADESC1 := COPYINFO.REF; IF NOT (SYM IN [LBRAK,AT,DOT]) THEN BEGIN { Simple variable } IF (COPYINFO.OBJ = FIELD) OR (COPYINFO.OBJ = TAG) OR ((COPYINFO.IDTYP <= REKORD) AND (COPYINFO.IDTYP >= STRNG)) OR NOT (COPYINFO.NRM AND this_vars_LHS) THEN { Sam } LOCVAR ELSE BEGIN IF (COPYINFO.LEV < X.LEVEL) AND (VARP OR this_vars_LHS) THEN THISSYMP^.THREAT := TRUE; NOCODE := TRUE END END ELSE { Pointer,file,record or array variable } BEGIN SIMPLE := FALSE; LOCVAR; REPEAT CASE SYM OF AT : BEGIN copyinfo.funcass := false; { Tutu - 6.6.3.7.3 fix } DESCOFF := 0; IF COPYINFO.IDTYP = PNTR THEN BEGIN IF COPYINFO.OBJ = FUNC THEN ERROR (162); GENMOV (IPUSH+ORD (ASSCHK)*7,COPYINFO); NXTSYMOK; COPYINFO.IDTYP := COPYINFO.REF^.TYP; COPYINFO.REF := COPYINFO.REF^.PNTRREF END ELSE BEGIN COPYINFO.PERM := FALSE; IF this_vars_LHS OR VARP THEN FLUSHNGEN (240{IdentifyI_Wbuff}) ELSE FLUSHNGEN (75{IdentifyI_Rbuff}); IF COPYINFO.IDTYP = FYLE THEN BEGIN COPYINFO.IDTYP := COPYINFO.REF^.TYP; COPYINFO.PAK := COPYINFO.REF^.FILEPAC; NXTSYMOK; COPYINFO.REF := COPYINFO.REF^.FILEREF END ELSE IF COPYINFO.IDTYP = TXT THEN BEGIN COPYINFO.IDTYP := SUBR; NXTSYMOK END ELSE BEGIN ERROR (148); NEXTSYM END END; ADESC1 := COPYINFO.REF END; { OF AT } DOT : BEGIN copyinfo.funcass := copyinfo.pak; { Tutu - 6.6.3.7.3 - set to pak field of parent if not simple } DESCOFF := 0; ACTIVREC (COPYINFO); { Get the field id } NXTSYMOK; INDEXINFO := THISSYMP^; IF (SYM <> TAG) AND (SYM <> FIELD) THEN ERROR (65); IF THISACTIVE <> NEWACTIVE THEN { wrong field id } ERROR (137); { Deactivate the field id } ACTIVELIST := ACTIVELIST^.NEXT; DISPOSE (NEWACTIVE); NEXTSYM; GENRECOFF (INDEXINFO.ADR); COPYINFO.REF := INDEXINFO.REF; COPYINFO.IDTYP := INDEXINFO.IDTYP; COPYINFO.PAK := INDEXINFO.PAK; COPYINFO.OBJ := INDEXINFO.OBJ; ADESC1 := COPYINFO.REF END; LBRAK : BEGIN {SYM = [} copyinfo.funcass := copyinfo.pak; { Tutu - 6.6.3.7.3 - set to pak field of parent if not simple } DESCOFF := 0; ADESC1 := COPYINFO.REF; STKP := X.STKINC; { Push array descriptor address onto top of stack } LOCADESC (COPYINFO,ADESC1); { Tutu - removed totbytes := 0; { Tutu - was 4, then twiceptrsize } { ptr, base now pulled off extra to this in SystemA } DIMS := 0; SAVERETKONST := RETKONST; WHILE SYM = LBRAK DO BEGIN NOT_CARAY := COPYINFO.IDTYP <> CARAY; NXTSYMOK; REPEAT IF (COPYINFO.IDTYP > ARAY) OR (COPYINFO.IDTYP= STRNG) THEN DESCOFF := DESCOFF + totaldescsize; {Tutu - was 11} COPYINFO.PAK := SAVEREF^.ALEV > 127 UNTIL (NOT LOOP) OR (SYM = RBRAK); IF LOOP THEN ERROR (149); CHKNEXT (RBRAK) END; X.STKINC := STKP; RETKONST := SAVERETKONST; { Generate code to get base address of array element } IF RNGCHK AND (NOT NOT_CARAY) THEN FLUSHNGEN (81{Chk_caray}) ELSE FLUSHNGEN (AACESOP); { Tutu - was IF TOTBYTES > 255 THEN ERROR (121); GENUB (TOTBYTES); } if dims > 255 then error (121); { Tutu } GENUB (DIMS) { Tutu - only need count of indices now } END END OTHERWISE ENDACCESS := TRUE UNTIL ENDACCESS END; IF (COPYINFO.IDTYP < STRNG) AND (SAVECADR = X.CADR) AND (CBUFF.BASICOP = LOCATE) AND LHS THEN BEGIN { No code has been generated for the left hand side of an assignment statement, but a locate code has been put into the code buffer. Remove the locate from buffer so that 1 byte can be saved by using a POP value at the end of the statement instead of a POP INDIRECT. } NOCODE := TRUE; CBUFF.BASICOP := 0; COPYINFO.ADR := CBUFF.VARADR END; CODEINFO := COPYINFO; ADESC := DESCOFF; ADESCREF := ADESC1 END; { varaccess } {$S'PasExpr2'}