PROCEDURE docommand(thecommand: cmdtyp); VAR signvalue : sign; numbervalue : integer; tabcounter : llen; (* 3---------------3 *) PROCEDURE getoption; BEGIN (* getoption *) getsym; IF syl.lin[1] IN ['0'..'9', varchr, '('] THEN BEGIN getnum(signvalue, numbervalue); IF (signvalue = invalid) OR (numbervalue <= 0) THEN BEGIN error(11) (* expecting positive number *); signvalue := invalid; END; END ELSE BEGIN backupsyl; signvalue := invalid; END; END (* getoption *); (* 3---------------3 *) PROCEDURE getnumberandsign; BEGIN (* getnumberandsign *) getsym; getnum(signvalue, numbervalue); END (* getnumberandsign *); (* 3---------------3 *) PROCEDURE cmdclmar; VAR i : integer; BEGIN (* cmdclmar *) getnumberandsign; IF otl.len = val[vlm] THEN otl.len := 0; CASE signvalue OF minus: IF testok(((val[vlm] - numbervalue) >= 0), 12) THEN (* error - lm < 0 *) val[vlm] := val[vlm] - numbervalue; plus: IF testok((val[vlm] + numbervalue <= 136), 13) THEN (* error - lm > 136 *) val[vlm] := val[vlm] + numbervalue; unsigned: IF testok(((numbervalue >= 1) AND (numbervalue <= 136)), 14) THEN (* error - lm out OF range *) val[vlm] := numbervalue; invalid: error(15); (* error - lm followed by *) END; (* case *) WITH otl DO IF len = 0 THEN BEGIN len := val[vlm]; FOR i := 1 TO len DO lin[i] := ' '; END; END (* cmdclmar *); (* 3---------------3 *) PROCEDURE cmdcrmar; BEGIN (* cmdcrmar *) getnumberandsign; CASE signvalue OF plus: IF testok(((val[vrm] + numbervalue) <= 136), 16) THEN (* error - rm > 136 *) val[vrm] := val[vrm] + numbervalue; minus: IF testok(((val[vrm] - numbervalue) >= 1), 17) THEN (* error - rm < 1 *) val[vrm] := val[vrm] - numbervalue; unsigned: IF testok(((numbervalue >= 1) AND (numbervalue <= 136)), 18) THEN (* error - rm out OF range *) val[vrm] := numbervalue; invalid: error(19) (* error - rm followed by *) END; (* case *) END (* cmdcrmar *); (* 3---------------3 *) PROCEDURE cmdcps; BEGIN (* cmdcps *) getnumberandsign; IF (signvalue = unsigned) AND (numbervalue > 10) THEN BEGIN oetxt := numbervalue; ovetxt := pred(numbervalue); getnumberandsign; IF (signvalue = unsigned) AND (numbervalue > 10) THEN BEGIN val[vrm] := numbervalue; pagenv.rm := numbervalue; END ELSE error(20) (* error - invalid ps column *); END ELSE error(21) (* error - invalid ps lines *); END (* cmdcps *); (* 3---------------3 *) PROCEDURE cmdcp; BEGIN (* cmdcp *) getnumberandsign; IF (signvalue <> invalid) THEN BEGIN pmar := numbervalue; prel := true; (* defaults *) CASE signvalue OF unsigned: prel := false; minus: pmar := -numbervalue; plus: ; END; (* case *) getnumberandsign; IF (signvalue = unsigned) AND (numbervalue >= 0) AND (numbervalue <= 5) THEN BEGIN parspace := numbervalue; getnumberandsign; IF (signvalue = unsigned) THEN partest := numbervalue ELSE error(22) (* error - paragraph tp *); END ELSE error(23) (* error - paragraph space *); END ELSE error(24) (* error - paragraph indent. *); END (* cmdcp *); (* 3---------------3 *) PROCEDURE cmdci; VAR i : integer; BEGIN (* cmdci *) getnumberandsign; IF signvalue <> invalid THEN BEGIN CASE signvalue OF unsigned: ; plus: numbervalue := val[vlm] + numbervalue; minus: numbervalue := val[vlm] - numbervalue; END; (* case *) IF numbervalue > 0 THEN BEGIN WITH otl DO BEGIN len := numbervalue; FOR i := 1 TO numbervalue DO lin[i] := ' '; END; END ELSE error(25) (* error - indent less than 0 *); END ELSE error(26) (* error - i followed by *); END (* cmdci *); (* 3---------------3 *) PROCEDURE cmdchl; VAR hlcounter : integer; BEGIN (* cmdchl *) IF succ(ovetxt - val[volno]) > 8 THEN BEGIN enp := 0; val[vlist] := 0; (* clearing lists *) getnumberandsign; IF (signvalue = unsigned) AND (numbervalue > 0) AND (numbervalue <= vhlmax) AND (numbervalue <= succ(val[vhl])) THEN BEGIN IF firstch THEN BEGIN savenv(pagenv); firstch := false; END; resenv(pagenv); enp := 0; clear; putblank(3); IF numbervalue > val[vhl] THEN val[vhl + numbervalue] := 0; val[vhl] := numbervalue; numbervalue := vhl + numbervalue; val[numbervalue] := succ(val[numbervalue]); IF val[vch] > 0 THEN BEGIN hlcounter := succ(vhl); addnum(val[vch], otl); END ELSE BEGIN hlcounter := vhl + 2; addnum(val[succ(vhl)], otl); END; FOR hlcounter := hlcounter TO numbervalue DO BEGIN addchr('.'); addnum(val[hlcounter], otl) END; addchr(' '); addchr(' '); defrb := 1; force := true; END ELSE error(27) (* error -- bad header level *); END ELSE BEGIN backupsyl; pushtext(defrfrcpgmacp); END; END (* cmdchl *); (* 3---------------3 *) PROCEDURE cmdcsp; BEGIN (* cmdcsp *) getnumberandsign; IF (signvalue <> invalid) AND (numbervalue >= 1) AND (numbervalue <= 5) THEN val[vsp] := numbervalue ELSE error(28) (* error - sp followed by *); END (* cmdcsp *); (* 3---------------3 *) PROCEDURE cmdcs; BEGIN (* cmdcs *) (* return plus numbervalue extra carriage returns *) getoption; IF signvalue <> invalid THEN putblank(numbervalue * val[vsp]) ELSE putblank(val[vsp]); END (* cmdcs *); (* 3---------------3 *) PROCEDURE stuffmac(p: pmac); BEGIN (* stuffmac *) WITH p^, stgstack[topofstack] DO IF yes THEN BEGIN (* all predefined macros have linlen characters avail. *) macroend := pred(macrobegin + linlen); stacktomacro(stgposition, macrobegin, macroend); stgposition := stgend; END ELSE BEGIN macroend := pred(macrobegin); stgtable[macrobegin] := ' '; END; END (* stuffmac *); (* 3---------------3 *) PROCEDURE cmdcch; VAR saveloc : integer; BEGIN (* cmdcch *) yes := true; saveloc := stgstack[topofstack].stgposition; stuffmac(chtmacp); IF atitle THEN BEGIN stgstack[topofstack].stgposition := saveloc; (* same as above *) stuffmac(ttlmacp); stuffmac(stlmacp); END; pushtext(chaptermacp); END (* cmdcch *); (* 3---------------3 *) PROCEDURE cmdcpno; BEGIN (* cmdcpno *) getnumberandsign; IF (signvalue = unsigned) AND (numbervalue < 1000) THEN val[vpage] := pred(numbervalue) ELSE error(29); (* error - page number was *) END (* cmdcpno *); (* 3---------------3 *) PROCEDURE cmdclist; BEGIN (* cmdclist *) getnumberandsign; IF (signvalue = unsigned) AND (numbervalue > 0) AND (numbervalue < 6) THEN BEGIN pshenv; IF val[vlist] = 0 THEN val[vlm] := val[vlm] + 9 ELSE val[vlm] := val[vlm] + 4; val[vlist] := succ(val[vlist]); val[vlist + val[vlist]] := 0; val[vsp] := numbervalue; parspace := succ(numbervalue); pmar := 0; prel := true; pshenv; END ELSE error(30); END; (* cmdclist *) (* 3---------------3 *) PROCEDURE cmdcle; BEGIN (* cmdcle *) IF val[vlist] > 0 THEN BEGIN putblank(val[vsp]); resenv(enstk[pred(enp)]); clear; val[vlist + val[vlist]] := succ(val[vlist + val[vlist]]); otl.len := val[vlm] - 4; addnum(val[vlist + val[vlist]], otl); addchr('.'); otl.len := val[vlm]; END ELSE error(31); (* error - no active list *) END (* cmdcle *); (* 3---------------3 *) PROCEDURE cmdcelist; BEGIN (* cmdcelist *) IF val[vlist] > 0 THEN BEGIN val[vlist] := pred(val[vlist]); popenv; popenv; END ELSE error(32); (* error - no active list *) END (* cmdcelist *); (* 3---------------3 *) PROCEDURE cmdcfig; BEGIN (* cmdcfig *) getnumberandsign; IF (signvalue = unsigned) THEN BEGIN IF numbervalue <= succ(ovetxt - val[volno]) THEN BEGIN ovbtxt := 0; (* so putblank works *) putblank(numbervalue); END ELSE BEGIN IF figp < figmax THEN BEGIN figp := succ(figp); fign[figp] := numbervalue; END ELSE error(33); (* error - too many pending figs *) END; END ELSE error(34); (* error - fig followed by *) END (* cmdcfig *); (* 3---------------3 *) PROCEDURE cmdcmacro; VAR n8 : 0..maxparms; tmacp, macp : pmac; tl : line; (* 4---------------4 *) PROCEDURE syltomac; BEGIN (* syltomac *) WITH tmacp^ DO BEGIN getalfafromsyl(1, nm); np := 0; on := false; macrobegin := 0; macroend := 0; END; END (* syltomac *); (* 4---------------4 *) PROCEDURE makparm; BEGIN (* makparm *) syl := tl; addnum(succ(numbervalue - n8), syl); new(tmacp); syltomac; WITH tmacp^ DO BEGIN ma := macp^.ma; macp^.ma := tmacp; mt := parm; macp := tmacp; END; END (* makparm *); (* 4---------------4 *) BEGIN (* cmdcmacro *) IF topofstack = 0 THEN BEGIN gettoken; IF syl.len <> 0 THEN BEGIN new(tmacp); syltomac; tmacp^.ma := maclstp; tmacp^.mt := header; tl := syl (* save macro name *); tl.len := succ(tl.len) (* for addnum *); IF tl.len > alfalen THEN tl.len := alfalen; gettoken; IF NOT (syl.lin[1] IN ['*', '=']) THEN getnum(signvalue, numbervalue) ELSE signvalue := invalid; IF signvalue = unsigned THEN gettoken ELSE IF (syl.lin[1] = '*') AND (syl.len = 1) THEN BEGIN numbervalue := maxparms; gettoken END ELSE numbervalue := 0; IF (syl.lin[1] = '=') AND (syl.len = 1) THEN BEGIN maclstp := tmacp; WITH stgstack[topofstack], tmacp^ DO BEGIN stacktomacro(stgposition, macrobegin, macroend); IF numbervalue < maxparms THEN BEGIN np := numbervalue; macp := maclstp; FOR n8 := numbervalue DOWNTO 1 DO makparm; END ELSE BEGIN np := maxparms; n8 := numbervalue; macp := maclstp; makparm; END; stgposition := stgend; END; END ELSE error(35); (* error - missing = IN macro def *) END ELSE error(36); (* error - no macro name *) END ELSE error(37); (* error - nested macro definitions *) END (* cmdcmacro *); (* 3---------------3 *) PROCEDURE cmdcvar; BEGIN (* cmdcvar *) getsym; IF symtype = vars THEN BEGIN lookupvar; IF varndx < varmax THEN BEGIN IF varndx = tv THEN BEGIN tv := succ(tv); vty[varndx] := vitem; END; getmacsym; IF (syl.len = 1) AND (syl.lin[1] = '=') THEN BEGIN getnumberandsign; IF signvalue <> invalid THEN BEGIN IF signvalue = minus THEN numbervalue := - numbervalue; val[varndx] := numbervalue; END; END ELSE pushsyl(syl); END ELSE error(38); (* error - too many variables *) END ELSE error(39); (* error - needed variable name; got *) END; (* cmdcvar *) (* 3---------------3 *) PROCEDURE cmdcinc; BEGIN (* cmdcinc *) getsym; IF symtype = vars THEN IF varndx < tv THEN val[varndx] := succ(val[varndx]) ELSE error(40) (* error - undeclared variable *) ELSE error(41); (* error - inc followed by *) END; (* cmdcinc *) (* 3---------------3 *) PROCEDURE cmdcdec; BEGIN (* cmdcdec *) getsym; IF symtype = vars THEN IF varndx < tv THEN val[varndx] := pred(val[varndx]) ELSE error(42) (* error - undeclared variable *) ELSE error(43); (* error - dec followed by *) END; (* cmdcinc *) (* 3---------------3 *) PROCEDURE cmdcarray; BEGIN (* cmdcarray *) getsym; IF symtype = vars THEN BEGIN lookupvar; IF varndx = tv THEN BEGIN numbervalue := getexp; IF (numbervalue > 0) AND (NOT exprerr) THEN IF numbervalue + tv < varmax THEN BEGIN tv := succ(tv + numbervalue); vup[varndx] := numbervalue; vty[varndx] := varray; END ELSE BEGIN varname := vid[varndx]; error(44); (* error - no room FOR ARRAY *) END ELSE error(45); (* error - bad ARRAY size *) END ELSE error(46); (* error - already declared *) END ELSE error(47); (* error - NOT a variable symbol *) END (* cmdcarray *); (* 3---------------3 *) PROCEDURE cmdinclude; VAR i : integer; testname : string; fp : inclfptr; BEGIN (* cmdinclude *) gettoken; testname := blankstring; FOR i := 1 TO syl.len DO testname[i] := syl.lin[i]; (* get a file control block *) IF freefptr = NIL THEN BEGIN new(fp); fileinit(fp^.f); END ELSE BEGIN fp := freefptr; freefptr := freefptr^.next; END; fp^.next := inclf; (* for backing out *) (*$s-*) IF exists(fp^.f, testname) THEN BEGIN (*$s+*) inclf := fp; fp^.lno := 0; END ELSE BEGIN (* not found *) fp^.next := freefptr; freefptr := fp; (* to retain space *) error(49); (* error - include FILE NOT present *) END; doinclfl := inclf <> NIL; END (* cmdinclude *); (* 3---------------3 *) PROCEDURE upcasesyl; VAR i : integer; BEGIN (* upcasesyl *) FOR i := 1 TO syl.len DO syl.lin[i] := forceuppercase(syl.lin[i]); END (* upcasesyl *); (* 3---------------3 *) PROCEDURE cmdcaseflag(convert: boolean); (* defeat OR enable CASE conversion *) VAR achar, lcchar : char; BEGIN (* cmdcaseflag *) lcchar := 'a'; FOR achar := 'A' TO 'Z' DO BEGIN IF convert THEN BEGIN makeupper[lcchar] := achar; makelower[achar] := lcchar; END ELSE BEGIN makeupper[lcchar] := lcchar; makelower[achar] := achar; END; lcchar := succ(lcchar); END; END; (* cmdcaseflag *) (* 3---------------3 *) BEGIN (* docommand *) CASE thecommand OF cbreak: (* handled IN processline *); ccr: (* handled IN processline *); cfrcpage: (* done WITH a macro *); cinclude: cmdinclude; cblank: (* break followed by numbervalue extra blank lines *) BEGIN getoption; IF signvalue <> invalid THEN putblank(numbervalue) ELSE putblank(1); END; cflag: flag := yes; cflagcaps: flagcaps := yes; clower: lower := yes; cupper: lower := NOT yes; cescchr: escchr := yes; cperiod: period := yes; ccenter: otl.center := true; cjust: justit := yes; cul: ul := yes; clmar: cmdclmar; crmar: cmdcrmar; cfill: fill := yes; csig: sigbl := yes; cpage: pushtext(defrfrcpgmacp); ctop: dotop; cmid: domid; cbot: dobot; csup: sup := yes; cstd: setstd; cps: cmdcps; csav: pshenv; cp: cmdcp; cres: BEGIN popenv; clear; END; cpp: paragraph; cap: ap := yes; ci: cmdci; csp: cmdcsp; cs: cmdcs; ctp: BEGIN getnumberandsign; IF signvalue = unsigned THEN testpage(numbervalue, false) ELSE error(50); (* error - tp followed by *) END; cch: cmdcch; chl: cmdchl; cnmp: val[vnmp] := ord(yes); {boolord for UCSD bug} cpno: cmdcpno; ctitle: stuffmac(ttlmacp); cst: stuffmac(stlmacp); catitle: atitle := yes; clist: cmdclist; cle: cmdcle; celist: cmdcelist; cfig: cmdcfig; cbar: bar := yes; cbb: BEGIN bb := true; otl.bbar := true; END; ceb: BEGIN IF empty THEN otl.bbar := false; bb := false; END; cu: undl := yes; cbold: bold := yes; ct: t := true; ctab, ctabs: BEGIN clrtab; tabcounter := 1; getoption; WHILE (signvalue <> invalid) AND (tabcounter <= tabmax) DO BEGIN tabs[tabcounter] := numbervalue; tabcounter := succ(tabcounter); getoption; END; backupsyl; END; crt: rt := true; cdot: dot := yes; cright: BEGIN getnumberandsign; IF (signvalue = unsigned) AND (numbervalue <= 136) THEN rightspace := numbervalue ELSE error(51) (* right space *) END; clines: BEGIN getnumberandsign; IF (signvalue = unsigned) THEN oepag := numbervalue ELSE error(52) (* error - lines followed by *) END; cmacro: cmdcmacro; cx: xtend := yes; cvar: cmdcvar; cinc: cmdcinc; cdec: cmdcdec; csavpag: BEGIN savenv(pagenv); firstch := false; END; crespag: resenv(pagenv); carray: cmdcarray; cfmt: BEGIN numbervalue := getexp; dofmt(numbervalue, getexp); END; cif: IF getexp = 0 THEN stgstack[topofstack].stgposition := stgstack[topofstack].stgend; casis : BEGIN topofstack := 0 (* !!! should free *); asis := true END; cflagover: flagover := yes; cflagsig: flagsig := yes; crem: stgstack[topofstack].stgposition := stgstack[topofstack].stgend (* makes rest OF a line a comment. *); cupp: BEGIN (* force next symbol upper *) getsym; upcasesyl; addword; END; cusb: usb := yes; notcmd: BEGIN END; ccaseflag: cmdcaseflag(yes); END; (* case *) END (* docommand *); (* 2---------------2 *)