PROCEDURE getnum(VAR signvalue : sign; VAR numbervalue : integer); CONST smnestmax = 5; VAR endofsyl : boolean; sylcharindex : integer; curchar, lookaheadchar : char; submacstackindx : integer; smstack : ARRAY[1..smnestmax] OF RECORD textptr : integer; smmac : pmac; END; (* smstack record *) (* 3----------------3 *) PROCEDURE nextchar; BEGIN (* nextchar *) curchar := ' '; IF submacstackindx = 0 THEN BEGIN exprerr := exprerr OR endofsyl; IF sylcharindex <= syl.len THEN BEGIN curchar := syl.lin[sylcharindex]; sylcharindex := succ(sylcharindex); END ELSE endofsyl := true; END ELSE BEGIN WITH smstack[submacstackindx] DO WITH smmac^ DO BEGIN IF textptr <= macroend THEN BEGIN curchar := stgtable[textptr]; textptr := succ(textptr); END; END; END; END (* nextchar *); (* 3----------------3 *) FUNCTION expression : integer; VAR expr1, expr2 : integer; expr3 : boolean; exprop : relopr; (* 4----------------4 *) FUNCTION number : integer; VAR ival : integer; (* 5----------------5 *) PROCEDURE usedigit; BEGIN (* usedigit *) ival := ival * 10 + (ord(curchar) - ord('0')); nextchar; END; (* usedigit *) (* 5----------------5 *) BEGIN (* number *) ival := 0; WHILE (curchar IN ['0' .. '9']) AND (ival < dangerpoint) DO usedigit; IF curchar IN ['0' .. '9'] THEN IF (ord(curchar) - ord('0')) > maxint MOD 10 THEN error(58) (* number too big *) ELSE BEGIN usedigit; IF curchar IN ['0' .. '9'] THEN error(58) (* number too big *); END; WHILE curchar IN ['0' .. '9'] DO nextchar; number := ival; END; (* number *) (* 4----------------4 *) FUNCTION character : integer; VAR cval : char; BEGIN (* character *) nextchar (* skip quote *); cval := curchar; exprerr := false; IF curchar = '''' THEN BEGIN (* handle quotes as characters *) nextchar; exprerr := curchar <> ''''; END; nextchar; exprerr := exprerr OR (curchar <> ''''); nextchar; IF exprerr THEN BEGIN error(59) (* bad character constant *); cval := '?'; exprerr := false; END; character := ord(cval); END; (* character *) (* 4----------------4 *) FUNCTION term : integer; VAR term1, term2 : integer; tch : char; (* 5----------------5 *) FUNCTION item : integer; VAR itemsign : (none, negative, positive, logicalnot); item1 : integer; (* 6----------------6 *) FUNCTION variable : integer; VAR v : alfa; i : integer; vndx1, vndx2 : 0..varmax; var1 : integer; BEGIN (* variable *) nextchar; v := alfablanks; i := 0; WHILE forceuppercase(curchar) IN ['A'..'Z', '$', '0'..'9'] DO BEGIN i := succ(i); IF i <= alfalen THEN v[i] := forceuppercase(curchar); nextchar; END; var1 := 0; IF i = 0 THEN exprerr := true ELSE BEGIN vid[tv] := v; vndx1 := 1; vndx2 := 0; WHILE vid[vndx1] <> v DO vndx1 := vndx1 + 1; IF vndx1 <> tv THEN BEGIN IF (vty[vndx1] = varray) AND (curchar = '[') THEN BEGIN nextchar; vndx2 := term; IF curchar <> ']' THEN exprerr := true ELSE nextchar; IF (vndx2 < 0) OR (vndx2 > vup[vndx1]) THEN BEGIN (* error - ARRAY index out OF bounds *) error(4); vndx2 := 0; END; END; IF curchar = '=' THEN BEGIN nextchar; val[vndx1 + vndx2] := term; END; var1 := val[vndx1 + vndx2]; END ELSE BEGIN (* undefined variable: $v *) varname := v; error(55); END; END; variable := var1; END (* variable *); (* 6----------------6 *) FUNCTION submacro : integer; VAR savecurchar : char; submac : pmac; macname : alfa; namindx : integer; exitflag : boolean; BEGIN (* submacro *) macname := alfablanks; nextchar; namindx := 0; WHILE curchar = macchr DO BEGIN (* pick up leading macchrs *) namindx := succ(namindx); IF namindx <= alfalen THEN macname[namindx] := curchar; nextchar; END; WHILE curchar IN ['A'..'Z', 'a'..'z', '0'..'9'] DO BEGIN namindx := succ(namindx); IF namindx <= alfalen THEN macname[namindx] := forceuppercase(curchar); nextchar; END; submac := maclstp; exitflag := false; REPEAT IF submac = NIL THEN exitflag := true ELSE IF submac ^.nm = macname THEN exitflag := true ELSE submac := submac^.ma; UNTIL exitflag; IF testok((submac <> NIL), 1) THEN (* error - unrecognized sub-macro name *) IF testok(NOT submac^.on, 2) THEN (* error - recursive sub-macro *) IF submacstackindx < smnestmax THEN BEGIN savecurchar := curchar; submacstackindx := succ(submacstackindx); WITH smstack[submacstackindx], submac^ DO BEGIN (* stack sub-macro value *) on := true; smmac := submac; textptr := macrobegin; nextchar; lookaheadchar := stgtable[textptr]; submacro := expression; on := false; END; submacstackindx := pred(submacstackindx); curchar := savecurchar; END; END (* submacro *); (* 6----------------6 *) BEGIN (* item *) itemsign := none; IF curchar = '-' THEN itemsign := negative ELSE IF curchar = '#' THEN itemsign := logicalnot ELSE IF curchar = '+' THEN itemsign := positive; IF itemsign <> none THEN nextchar; item1 := 0; IF curchar = varchr THEN item1 := variable ELSE IF curchar = macchr THEN item1 := submacro ELSE IF curchar IN ['0'..'9'] THEN item1 := number ELSE IF curchar = '''' THEN item1 := character ELSE exprerr := true; CASE itemsign OF none, positive: ; negative: item1 := - item1; logicalnot: item1 := ord(item1 = 0); END; (* case *) item := item1; END (* item *); (* 5----------------5 *) BEGIN (* term *) term1 := 0; IF curchar = '(' THEN BEGIN nextchar; term1 := term; IF curchar <> ')' THEN exprerr := true ELSE nextchar; END ELSE IF curchar IN itemset THEN BEGIN term1 := item; WHILE curchar IN ['+', '-'] DO BEGIN tch := curchar; nextchar; term2 := 0; IF curchar IN itemset THEN term2 := item ELSE IF curchar = '(' THEN term2 := term; IF tch = '+' THEN term1 := term1 + term2 ELSE term1 := term1 - term2; END; END; term := term1; END (* term *); (* 4----------------4 *) FUNCTION relop : relopr; VAR op : alfa; rop : relopr; BEGIN (* relop *) op := alfablanks; nextchar; op[1] := forceuppercase(curchar); nextchar; op[2] := forceuppercase(curchar); nextchar; IF curchar = '.' THEN nextchar; arelopr[badrelop] := op; rop := eq; WHILE (arelopr[rop] <> op) DO rop := succ(rop); IF (rop = badrelop) THEN error(5) (* unrecognized relational operator *); relop := rop; END (* relop *); (* 4----------------4 *) BEGIN (* expression *) expr1 := 0; IF (curchar = varchr) AND (lookaheadchar = '(') THEN nextchar; IF curchar IN termset THEN BEGIN expr1 := term; IF curchar = '.' THEN BEGIN exprop := relop; expr2 := 0; IF curchar IN termset THEN expr2 := term; CASE exprop OF eq: expr3 := expr1 = expr2; gt: expr3 := expr1 > expr2; lt: expr3 := expr1 < expr2; ne: expr3 := expr1 <> expr2; ge: expr3 := expr1 >= expr2; le: expr3 := expr1 <= expr2; badrelop: expr3 := false; END; (* case *) expr1 := ord(expr3); END; END; expression := expr1; END (* expression *); (* 3----------------3 *) BEGIN (* getnum *) submacstackindx := 0; endofsyl := false; sylcharindex := 1; nextchar; IF curchar = '+' THEN signvalue := plus ELSE IF curchar = '-' THEN signvalue := minus ELSE signvalue := unsigned; IF signvalue <> unsigned THEN nextchar; lookaheadchar := syl.lin[sylcharindex]; exprerr := false; numbervalue := expression; IF curchar = ';' THEN BEGIN showexpr := false; nextchar; END ELSE showexpr := true; WHILE (curchar = ' ') AND NOT endofsyl DO nextchar; IF exprerr OR NOT endofsyl THEN BEGIN (* error in expression *) signvalue := invalid; error(6); END; END (* getnum *); (* 2----------------2 *)