-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+ X X Xbuild`20:`09`09`09`09`09executables X`09write`20sys$output`20"Build`20complete" X Xexecutables`20:`09`09`09`09exe$:sdcl.$(exe),- X`09`09`09`09`09exe$:sdcl-debug.$(exe) X`09write`20sys$output`20"Executables`20complete" X Xexe$:sdcl.$(exe)`20:`09`09`09obj$:sdcl.$(obj),- X`09`09`09`09`09obj$:lex.$(obj),- X`09`09`09`09`09obj$:output.$(obj),- X`09`09`09`09`09obj$:stack.$(obj),- X`09`09`09`09`09obj$:stmt.$(obj),- X`09`09`09`09`09src$:sdcl.$(opt) X`09link/exec=$(mms$target)/notrace`20- X`09`09$(mms$source),- X`09`09obj$:lex.$(obj),- X`09`09obj$:output.$(obj),- X`09`09obj$:stack.$(obj),- X`09`09obj$:stmt.$(obj),- X`09`09src$:sdcl.$(opt)/options X Xexe$:sdcl-debug.$(exe)`20:`09`09`09obj$:sdcl.$(obj),- X`09`09`09`09`09obj$:lex.$(obj),- X`09`09`09`09`09obj$:output.$(obj),- X`09`09`09`09`09obj$:stack.$(obj),- X`09`09`09`09`09obj$:stmt.$(obj),- X`09`09`09`09`09src$:sdcl.$(opt) X`09link/exec=$(mms$target)/debug`20- X`09`09$(mms$source),- X`09`09obj$:lex.$(obj),- X`09`09obj$:output.$(obj),- X`09`09obj$:stack.$(obj),- X`09`09obj$:stmt.$(obj),- X`09`09src$:sdcl.$(opt)/options X X Xobj$:lex.$(obj)`20:`09`09`09`09src$:lex.c,- X`09`09`09`09`09inc$:tcodes.h,- X`09`09`09`09`09inc$:defs.h X`09$(CC)`20$(CFLAGS)`20$(MMS$SOURCE) X Xobj$:output.$(obj)`20:`09`09`09src$:output.c,- X`09`09`09`09`09inc$:defs.h X`09$(CC)`20$(CFLAGS)`20$(MMS$SOURCE) X Xobj$:sdcl.$(obj)`20:`09`09`09`09src$:sdcl.c,- X`09`09`09`09`09inc$:defs.h X`09$(CC)`20$(CFLAGS)`20$(MMS$SOURCE) X Xobj$:stack.$(obj)`20:`09`09`09src$:stack.c,- X`09`09`09`09`09inc$:defs.h X`09$(CC)`20$(CFLAGS)`20$(MMS$SOURCE) X Xobj$:stmt.$(obj)`20:`09`09`09`09src$:stmt.c,- X`09`09`09`09`09inc$:tcodes.h,- X`09`09`09`09`09inc$:defs.h X`09$(CC)`20$(CFLAGS)`20$(MMS$SOURCE) $ call unpack [.REF-LIB]SDCL.MMS;4 103261330 "" 4 9 13 $! $ create 'f' X.flags`20bold X.ps`2060,72 X.lm`200 X.sp`201 X.b`202 X.c`2072 XSDCL`20--`20A`20Preprocessor`20for`20Structured`20DCL`20 X.b`204 X.c`2072 XSohail`20Aslam X.b`202 X.c`2072 XUniversity`20of`20Colorado`20at`20Colorado`20Springs X.c`2072 XColorado`20Springs,`20CO`2080933 X.b`202 X.c`2072 XDick`20Munroe X.b`202 X.c`2072 XAcorn`20Software X.c`2072 X267`20Cox`20St. X.c`2072 XHudson,`20Ma.`2001749 X.c`2072 Xmunroe@acornsw.com X.b`202 X X.p`205,1,4 XThe`20command`20language`20under`20the`20VAX/VMS`20operating`20system`20is`20c Valled XDigital`20Command`20Language,`20or`20DCL.`20 XDCL`20provides`20a`20whole`20host`20of`20capabilities`20that`20allow`20the`20u Vser`20not`20only Xexecute`20simple`20commands`20but`20develop`20command`20procedures`20that`20ca Vn`20accomplish Xa`20complex`20task.`20DCL`20provides`20variables,`20conditional`20operators, V`20 Xan`20IF-THEN-command`20construct`20and`20a`20number`20of`20built-in`20function Vs.`20It`20is Xthus`20a`20small`20programming`20language.`20Unfortunately,`20the`20only`20con Vtrol`20structure Xprovided`20is`20the`20 X.b`201 X#####IF_`20condition_`20THEN_`20a_`20command X.b`201 XBy`20building`20a`20simple`20preprocessor,`20I`20have`20extended`20the`20contr Vol`20structure`20to Xinclude`20C`20like`20control`20structures,`20e.g,`20if-else,`20while,`20for, V`20do-while, Xon`20condition`20blocks,`20`20etc. XThese`20structures`20can`20operate`20on`20a`20single`20command`20or`20a`20grou Vp`20of`20commands. X.p`205,1,4 XI`20taught`20a`20class`20here`20at`20UCCS`20in`20the`20spring`20semester`20of V`201985`20titled`20"The XUNIX`20Programming`20Environment";`20I`20chose`20developing`20the`20preprocess Vor`20for`20 Xstructured`20DCL`20as`20the`20semester`20project.`20For`20the`20benefit`20of V`20other`20teachers Xwho`20may`20wish`20to`20assign`20such`20a`20project`20to`20their`20class,`20I V`20have`20included`20the XUNIX`20nroff/troff`20source`20and`20formatted`20version`20of`20the`20project V`20handout.`20The`20 Xhandout`20provides`20a`20very`20detailed,`20step`20by`20step`20description`20o Vf`20the`20design`20and Ximplementation`20of`20sdcl.`20Thus`20it`20serves`20as`20a`20document`20for`20a Vnyone`20who`20wants Xto`20understand`20the`20workings`20of`20the`20preprocessor.`20The`20file`20"sd Vcl.nr"`20contains Xthe`20nroff/troff`20source`20and`20"sdcl.doc"`20is`20the`20formatted`20version V`20of`20"sdcl.nr" Xdesigned`20to`20be`20printed`20on`20ordinary`20line`20printers. X.p`205,1,4 XThe`20real`20motivation`20for`20wanting`20to`20have`20structured`20DCL`20came V`20from`20the`20tradition Xset`20by`20RATFOR`20(RATional`20FORtran).`20For`20those`20of`20you`20not`20fam Viliar`20with`20RATFOR,`20 XRATFOR`20allows`20one`20to`20write`20code`20in`20FORTRAN`20in`20a`20C`20like V`20manner.`20DCL`20has`20similar Xdeficiencies`20when`20it`20comes`20to`20writing`20command`20procedures.`20I`20 Vjust`20wanted`20to Xillustrate`20that`20one`20does`20not`20have`20to`20live`20with`20GOTO's`20and V`20COMEFROM's`20in`20one's Xprogramming`20practices.`20It`20is`20rather`20trivial`20to`20develop`20a`20lay Ver`20of`20structured Xenvironment`20on`20top`20of`20something`20that`20does`20not`20support`20it. X.pg X.p`205,1,4 XThe`20language`20recognized,`20and`20thus`20parsed,`20by`20sdcl`20is`20very`20 Vsimple.`20Here`20it`20is XBNF`20form: X.lm`20+5 X.nj X.nf X.b`201 Xprogram`20`20`20:`20statement X`20`20`20`20`20`20`20`20`20`20`7C`20program`20statement X Xstatement`20:`20`5E*if`20(`5C*`20condition`20`5E*)`5C*`20statement X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*if`20(`5C*`20condition`20`5E*)`5C*`20s Vtatement`20`5E*else`5C*`20statement X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*while`20(`5C*`20condition`20`5E*)`5C* V`20statement X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*for`20(`5C*`20intialize`20`5E*;`5C*`20 Vcondition`20`5E*;`5C*`20reinitialze`20`5E*)`5C* X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20statement X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*do`5C*`20statement`20`5E*while`20(`20 V`5C*`20condition`20`5E*)`5C* X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*on`5C*`20statusCondition`20statement X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*on`5C*`20statusCondition`20`5E*then`5C V*`20statement X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*break`5C* X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*next`5C* X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*`7B`5C*`20program`20`5E*`7D`5C* X`20`20`20`20`20`20`20`20`20`20`7C`20`5E*other`5C* X.lm`20-5 X.f X.ju X.b`201 XHere`20is`20a`20summary`20of`20sdcl`20usage.`20Please`20refer`20to`20 Xthe`20file`20"sdcl.doc."`20for`20a`20detailed`20description. X.list`20"o" X.le XThe`20input`20file`20to`20sdcl`20is`20an`20ordinary`20text`20file`20containing V`20sdcl`20statements. XUnlike`20DCL,`20statements`20must`20not`20begin`20with`20a`20"_$"`20sign.`20 X.le XStatements`20can`20be`20enclosed`20within`20_`7B_`7D`20to`20form`20the`20so-ca Vlled`20compound Xstatement. X.le XThe`20preprocessor`20looks`20at`20the`20first`20token`20of`20each`20statement V`20to`20determine Xthe`20type`20of`20statement`20so`20you`20should`20not`20preceed`20keywords`20w Vith`20DCL`20labels Xe.g.`20"usage:`20if(`20p1`20.eqs.`20..".`20Statements`20that`20donot`20match V`20one`20of`20the Xstructured`20statements`20are`20classified`20as`20"other"`20and`20simply`20emi Vtted. X.le XAny`20`20sdcl`20source`20statement`20can`20be`20continued`20across`20more`20th Vat`20one`20line`20by Xplacing`20a`20"_`5C"`20(backslash)`20just`20before`20the`20end`20of`20line. X.le XIn`20structured`20constructs,`20the`20"_`5C"`20need`20not`20be`20used`20howeve Vr,`20because`20sdcl Xcan`20infer`20whether`20the`20constructs`20is`20complete`20or`20not`20by`20sim Vply`20going Xacross`20line`20boundaries`20until`20satisfied.`20So`20if`20the`20condition`20 Vpart`20is`20too Xlong`20to`20fit`20on`20one`20line`20in`20an`20"if"`20statement,`20it`20can`20s Vimply`20be`20continued`20on Xthe`20next`20line. X.le XDonot`20use`20the`20"-"`20(minus)`20as`20the`20continuation`20character`20in V`20sdcl`20statements. X.le XIf`20a`20source`20line`20begins`20with`20a`20"_#"`20or`20"_$"`20sign,`20the`20 Vpound`20sign`20(then`20dollar`20sign Xis`20NOT`20removed)`20is`20removed`20and`20 Xrest`20of`20the`20line`20is`20emitted`20AS`20IS.`20This`20can`20be`20used`20to V`20pass`20lines`20through Xsdcl`20untouched`20to`20DCL. X.le XQuoted`20strings`20are`20not`20broken. X.le XVariable`20substitution`20is`20not`20broken. X.end`20list X.pg X.b`202 XThe`20sdcl`20can`20be`20invoked`20as`20follows: X.b`201 X.nj X.nf X####$`20sdcl`20`5Binfile.ext`5D`20`5Boutfile.ext`5D`20`5B-x`5D X.b`201 Xwhere X.b`201 X.lm`20+5 X"infile.ext"`20`20is`20the`20input`20source`20file.`20If`20not`20specified,`20 V`20input X`20`20`20`20`20`20`20`20`20`20`20`20`20`20is`20taken`20from`20"sys_$input". X.b`201 X"outfile.ext"`20is`20the`20output`20file`20that`20will`20receive`20the`20gener Vated X`20`20`20`20`20`20`20`20`20`20`20`20`20`20DCL`20code.`20If`20outfile`20is`20no Vt`20specified,`20then`20the`20ge- X`20`20`20`20`20`20`20`20`20`20`20`20`20`20code`20will`20be`20placed`20in`20"in Vfile.COM".`20If`20no`20`20infile X`20`20`20`20`20`20`20`20`20`20`20`20`20`20was`20specified,`20output`20goes`20t Vo`20"sys_$output". X.b`201 X-x`20`20`20`20`20`20`20`20`20`20`20`20If`20-x`20is`20specifed,`20then`20the`20 Vcode`20in`20outfile`20is`20pas- X`20`20`20`20`20`20`20`20`20`20`20`20`20`20to`20DCL`20for`20execution`20via`20l Vib_$do__command. X.lm`20-5 X.ju X.f X.b`201 XMake`20sure`20that`20the`20symbol`20"sdcl"`20is`20defined`20as`20a`20foreign V`20command`20either Xin`20your`20login.com`20or`20in`20the`20system`20wide`20login.com.`20For`20exa Vmple,`20if`20the Ximage`20"sdcl.exe"`20resides`20in`20"sys_$sysexe"`20then`20here`20is`20how`20y Vou`20may Xdefine`20"sdcl"`20as`20a`20foreign`20command`20in`20your`20login.com: X.b`201 X#####$#sdcl#:==#_$sys_$sysexe:sdcl X.b`201 XNote`20that`20parameters`20cannot`20be`20passed`20to`20the`20command`20procedu Vre`20in Xoutfile`20when`20it`20is`20executed`20through`20the`20"-x"`20option. X.pg XHere`20is`20a`20command`20procedure`20to`20give`20you`20a`20flavor`20of`20sdcl V,`20 X.b`201 X.literal X/*`20`20Bun`20--`20VMS`20DCL`20command`20procedure`20to`20bundle`20files`20int Vo`20`20`20`20`20*/ X/*`20`20`20`20`20`20`20`20`20distribution`20package`20which`20can`20then`20be V`20unbundled`20`20`20*/ X/*`20`20`20`20`20`20`20`20`20using`20UNIX`20shell.`20The`20output`20will`20be V`20placed`20on`20the`20*/ X/*`20`20`20`20`20`20`20`20`20on`20the`20file`20given`20as`20the`20arg`20to`20t Vhis`20procedure`20`20`20`20`20*/ Xif(`20p1`20.eqs.`20""`20)`7B X`20`20`20`20write`20sys$output`5C X`20`20`20`20`09"Usage:`20bundle`20outfile`20(outfile`20will`20receive`20bundle V)" X`20`20`20`20exit`20`20`20`20/*`20DCL`20exit`20*/ X`7D X/*`20if`20the`20file`20exists,`20open`20it,`20otherwise`20create`20it`20*/ Xopen/write/err=out_err`20fout`20'p1' Xexist`20:=`20"TRUE" Xout_err: Xif(`20exist`20.nes.`20"TRUE"`20)`7B X`20`20`20`20create`20'p1' X`20`20`20`20open/write/err=give_up`20fout`20'p1' X`7D Xq`20:=`20"'" Xfor(`20rc`20=`200;`20;`20)`7B`20`20`20`20/*`20no`20condition,`20no`20reinit`20 V*/ X`20`20`20`20inquire`20infile`20"File?`20" X`20`20`20`20if(`20infile`20.eqs.`20""`20) X`09break`20`20`20`20`20`20`20`20/*`20time`20to`20wrapup`20*/ X`20`20`20`20open/read/err=infile_err`20inf`20'infile' X`20`20`20`20write`20fout`20"echo`20''infile'`201>`262" X`20`20`20`20write`20fout`20"cat`20>''infile'`20<<''q'END`20OF`20''infile'''q'" V X`20`20`20`20rc`20=`20rc`20+`202`20`20 X`20`20`20`20done`20=`200 X`20`20`20`20while(`20done`20.eq.`200`20)`7B X`09read/end=eof`20inf`20line X`09write`20`20`20`20`20`20`20fout`20line X`09rc`20=`20rc`20+`201 X`20`20`20`20`7D X`20`20`20`20eof:`20close`20inf X`20`20`20`20write`20fout`20"END`20OF`20''infile'" X`20`20`20`20rc`20=`20rc`20+`201 X`20`20`20`20next X`20`20`20`20/* X`20`20`20`20`20come`20here`20if`20trouble`20opening`20'infile' X`20`20`20`20*/ X`20`20`20`20infile_err:`20write`20sys$output`20`5C X`09`09`20`20`20"error`20opening`20''infile'" X`7D Xif(`20rc`20.gt.`200`20)`7B X`20`20`20`20write`20sys$output`20"''rc'`20records`20written`20to`20''p1'" X`20`20`20`20close`20fout X`7D Xelse X`20`20`20`20write`20sys$output`20"0`20records`20written`20out" Xexit X.end`20literal X.pg XAnd`20here`20is`20the`20generated`20code. X.literal X$`20if`20(.not.(p1`20.eqs.`20""`20))`20then`20goto`2023000 X$`20write`20sys$output`20"Usage:`20bundle`20outfile`20(outfile`20will`20receiv Ve`20bundle)" X$`20exit`20`20`20`20 X$`2023000:`20 X$`20open/write/err=out_err`20fout`20'p1' X$`20exist`20:=`20"TRUE" X$`20out_err: X$`20if`20(.not.(exist`20.nes.`20"TRUE"`20))`20then`20goto`2023002 X$`20create`20'p1' X$`20open/write/err=give_up`20fout`20'p1' X$`2023002:`20 X$`20q`20:=`20"'" X$`20rc`20=`200 X$`2023004:`20 X$`20inquire`20infile`20"File?`20" X$`20if`20(.not.(infile`20.eqs.`20""`20))`20then`20goto`2023007 X$`20goto`2023006 X$`2023007:`20 X$`20open/read/err=infile_err`20inf`20'infile' X$`20write`20fout`20"echo`20''infile'`201>`262" X$`20write`20fout`20"cat`20>''infile'`20<<''q'END`20OF`20''infile'''q'" X$`20rc`20=`20rc`20+`202`20`20 X$`20done`20=`200 X$`2023009:`20if`20(.not.(done`20.eq.`200`20))`20then`20goto`2023010 X$`20read/end=eof`20inf`20line X$`20write`20`20`20`20`20`20`20fout`20line X$`20rc`20=`20rc`20+`201 X$`20goto`2023009 X$`2023010:`20 X$`20eof:`20close`20inf X$`20write`20fout`20"END`20OF`20''infile'" X$`20rc`20=`20rc`20+`201 X$`20goto`2023005 X$`20infile_err:`20write`20sys$output`20`20"error`20opening`20''infile'" X$`2023005:`20 X$`20goto`2023004 X$`2023006:`20 X$`20if`20(.not.(rc`20.gt.`200`20))`20then`20goto`2023011 X$`20write`20sys$output`20"''rc'`20records`20written`20to`20''p1'" X$`20close`20fout X$`20goto`2023012 X$`2023011:`20 X$`20write`20sys$output`20"0`20records`20written`20out" X$`2023012:`20 X$`20exit X.end`20literal $ call unpack [.REF-LIB]SDCL.RNO;2 1027619007 "" 17 10 13 $! $ create 'f' X/* X`20*`09The`20functions`20within`20this`20file`20are`20used`20to`20maintain X`20*`09a`20stack`20structure.`20`20Include`20here`20all`20typedefs,`20pointers V X`20*`09and`20stack`20maintenance`20functions.`20`20These`20functions`20include V X`20*`09push(),`20pop(),`20and`20peek().`20`20A`20hidden`20variable,`20top,`20i Vs X`20*`09declared`20within`20this`20file`20and`20is`20used`20to`20indicate`20the V X`20*`09top`20of`20this`20stack.`20`20 X`20* X`20*/ X X#include`20 X#include`20"defs.h" X X/* X`20*`09The`20following`20struct`20definition`20will`20be`20used`20to`20maintai Vn X`20*`09the`20stack`20of`20information`20that`20will`20be`20used`20by`20the`20b Vreak X`20*`09and`20next`20code`20generating`20functions.`20`20The`20information`20 X`20*`09contained`20in`20each`20node`20of`20the`20stack`20is`20the`20type`20of V`20loop X`20*`09being`20parsed`20and`20the`20number`20of`20the`20last`20label`20that`20 Vhas X`20*`09been`20used`20in`20the`20code`20generation`20process. X`20* X`20*`09The`20variable`20declared`20after`20the`20typedef`20will`20always`20poi Vnt X`20*`09to`20the`20top`20of`20the`20stack.`20`20By`20declaring`20it`20as`20a`20 Vstatic X`20*`09variable`20it`20becomes`20hidden`20by`20all`20procedures`20that`20resid Ve X`20*`09outside`20of`20this`20file.`20`20Initialize`20this`20pointer`20to`20NUL VL`20(0). X`20*`09This`20value`20indicates`20that`20the`20stack`20is`20empty. X`20* X`20*/ X Xtypedef`20struct`20nodetype`20NODETYPE; X Xstruct`20nodetype X`7B X`09int`20looptype;`20`20/*`20While`20loop`20=`202,`20corresponding`20to`20WHIL VE`20=`202.`20*/ X`09int`20label;`20`20`20`20`20/*`20Last`20label`20used`20before`20this`20loop. V`20*/ X`09struct`20nodetype`20*next;`20/*`20Makes`20this`20a`20self-referential`20str Vuct.`20*/ X`7D; X Xstatic`20NODETYPE`20*top`20=`20NULL; X X/*`20Define`20a`20macro`20that`20will`20return`20the`20size`20of`20a`20stack V`20node.`20*/ X X#define`20NODESIZE`20sizeof(NODETYPE) X X/*`20Define`20the`20push(),`20pop(),`20and`20peek()`20functions.`20*/ X Xextern`20int`20errmsg(); X Xvoid`20push(ltype,`20labl) X`20`20`20`20int`20ltype; X`20`20`20`20int`20labl; X`20`20`20`20`7B X`09NODETYPE`20*ptr; X`09extern`20char`20*malloc(); X X`09/*`20First`20create`20a`20new`20node.`20`20Coerce`20it`20to`20point`20to`20 Va`20nodetype.`20*/ X`09ptr`20=`20(NODETYPE`20*)`20malloc(NODESIZE); X`09/*`20 X`09`20*`09Check`20to`20see`20if`20there`20was`20enough`20stack`20memory`20left V X`09`20*`09to`20allocate.`20`20If`20there`20wasn't,`20ptr`20will`20be`20NULL. X`09`20*`09Time`20for`20an`20error`20message. X`09`20* X`09`20*/ X`09if`20(ptr`20==`20NULL)`7B X`09`09errmsg("Fatal`20error`20--`20loops`20nested`20to`20deep`5Cn"`20); X`09`09exit(1); X`09`7D X X`09ptr->looptype`20=`20ltype; X`09ptr->label`20=`20labl; X`09ptr->next`20=`20top; X`09top`20=`20ptr; X`20`20`20`20`7D X Xint`20pop(pltype,`20plabl) X`20`20`20`20int`20*pltype; X`20`20`20`20int`20*plabl; X`20`20`20`20`7B X`09NODETYPE`20*ptr; X`09extern`20char`20*free(); X X`09if`20(top)`7B X`09`20`20`20`20*pltype`20=`20top->looptype; X`09`20`20`20`20*plabl`20=`20top->label; X`09`20`20`20`20ptr`20=`20top; X`09`20`20`20`20top`20=`20top->next; X`09`20`20`20`20free((char`20*)`20ptr); X`09`20`20`20`20return(`201`20); X`09`7D X`09else`20`7B X`09`09errmsg("Internal`20Error`20--`20Attempt`20to`20pop`20an`20empty`20stack- V-"); X`09`09errmsg("continuing`5Cn`5Cn"); X`09`09return(0); X`09`7D X`20`20`20`20`7D X Xpeek(pltype,`20plab) X`20`20`20`20int`20*pltype; X`20`20`20`20int`20*plab; X/* X`20*`09Return`20the`20contents`20of`20the`20top`20of`20the`20stack`20without V`20actually X`20*`09popping`20the`20stack.`20`20This`20function`20is`20the`20same`20as`20po Vp(),`20but`20 X`20*`09only`20up`20to`20the`20point`20where`20top`20is`20changed.`20`20 X`20*/ X`20`20`20`20`7B X`09if`20(top)`20`7B X`09`20`20`20`20*pltype`20=`20top->looptype; X`09`20`20`20`20*plab`20=`20top->label; X`09`20`20`20`20return`20(`201`20); X`09`7D X`09else`20`7B X`09`09return(0); X`09`7D X`20`20`20`20`7D $ call unpack [.REF-LIB]STACK.C;3 1962954923 "" 6 11 13 $! $ create 'f' X/* X`20*`09this`20file`20contains`20all`20the`20semantic`20analysis`20functions`20 Vto`20be X`20*`09used`20in`20generating`20sdcl`20output.`20`20All`20of`20these`20functio Vns`20are X`20*`09ultimately`20called`20by`20statement(),`20depending`20on`20what`20the V`20 X`20*`09current`20input`20token`20is.`20`20All`20of`20these`20functions`20then V`20process X`20*`09a`20line`20of`20input`20by`20calling`20the`20lexical`20analysis`20funct Vion`20and, X`20*`09depending`20on`20what`20token`20is`20returned,`20generating`20correct V`20DCL X`20*`09output`20lines. X`20* X**`20`200.001`20Dick`20Munroe`2007-Aug-90 X**`09There`20is`20a`20bug`20in`20condition`20that`20winds`20up`20incorrectly V`20parsing X**`09conditional`20statements`20of`20the`20form: X** X**`09if`20(`20(cond)`20.op.`20(cond)`20...`20)`20... X** X**`20`200.002`20Dick`20Munroe`2008-Aug-90 X**`09There`20is`20a`20bug`20in`20for`20statement`20processing`20that,`20incorr Vectly, X**`09stops`20when`20the`20first`20closing`20parenthesis`20in`20the`20input`20s Vtream X**`09occurs`20rather`20than`20the`20first`20UNBALANCED`20closing`20parenthesis V. X** X**`20`200.003`20Dick`20Munroe`2003-Sep-90 X**`09Make`20$`20equivalent`20to`20#. X** X**`20`200.004`20Dick`20Munroe`2015-Sep-90 X**`09Get`20quoted`20string`20as`20first`20token`20on`20line`20output`20correct Vly. X** X**`20`200.005`20Dick`20Munroe`2030-May-95 X**`09Preserve`20quoted`20strings`20in`20conditionals. X** X**`20`200.006`20Dick`20Munroe`2030-May-95 X**`09Preserve`20variable`20substitution X** X**`20`200.007`20Dick`20Munroe`2001-Jun-95 X**`09Add`20on`20blocks. X** X**`20`200.008`20Dick`20Munroe`2001-Jun-95 X**`09Add`20definition`20of`20$BREAK`20and`20$NEXT`20symbols`20to`20allow`20int Vegration`20ofg X**`09SDCL`20end`20of`20loop`20statements`20with`20things`20like`20read. X*/ X X#include`20 X#include`20"tcodes.h" X#include`20"defs.h" X Xint`20`20tokencode; Xchar`20token`5BMAXTOKENLEN`5D; X X/*`20 X`20*`09The`20following`20serve`20as`20forward`20declarations`20of`20internal V`20and`20 X`20*`09external`20to`20this`20file. X`20* X`20*/ X Xextern`20void`20condition(),`20statement(int); Xextern`20int`20lex(); Xextern`20void`20push()`20; Xextern`20int`20pop(),`20genlab(),`20errmsg(); Xextern`20void`20emitlabel(),`20emitqstring(),`20emittarget(); X Xvoid`20breakstmt(int); Xvoid`20compstmt(int); Xvoid`20condition(); Xvoid`20dowhilestmt(int); Xvoid`20forstmt(int); Xvoid`20ifstatement(int)`20; Xvoid`20initialize(int); Xvoid`20nextstmt(int); Xvoid`20onstmt(int)`20; Xvoid`20other(int); Xvoid`20reinitialize(); Xvoid`20statement(int); Xvoid`20whilestmt(int); Xvoid`20popBreakNext()`20; X Xscan() X/* X`20*`09Repeatedly`20call`20lex`20until`20a`20token`20that`20is`20not`20a`20COM VMENT, X`20*`09WSPACE,`20NEWLINE`20can`20be`20returned.`20 X`20*/ X`20`20`20`20`7B X`09do`20 X`09`7B X`09`09tokencode`20=`20lex(token); X`09`7D`20while`09`20(tokencode`20==`20COMMENT`20`7C`7C`20tokencode`20==`20WSPA VCE`20`7C`7C X`09`09`20`20tokencode`20==`20NEWLINE`20); X`09return(tokencode); X`20`20`20`20`7D X Xvoid`20statement(int`20beginning) X/* X`20*`09Based`20on`20current`20token,`20invoke`20the`20appropriate X`20*`09routine`20to`20process`20a`20statement`20beginning`20with`20that`20toke Vn. X`20*/ X`20`20`20`20`7B X`09switch`20(tokencode)`20`7B X`09`09case`20IF:`20ifstatement(beginning);`20`20 X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20bre Vak; X X`09`09case`20WHILE:`20whilestmt(beginning); X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20 V`20`20break; X X`09`09case`20FOR:`20forstmt(beginning); X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20 Vbreak; X X`09`09case`20DO:`20dowhilestmt(beginning); X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20 Vbreak; X X`09`09case`20BREAK:`20breakstmt(beginning);`20`20 X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20 V`20`20break; X X`09`09case`20NEXT:`20nextstmt(beginning); X`09`09`09`20`20`20break; X X`09`09case`20ON:`20onstmt(beginning)`20; X`09`09`09`20break; X`09`09`09`20 X`09`09case`20OBRACE:`20compstmt(beginning);`20`20 X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20 V`20`20`20break; X X`09`09default:`20other(beginning); X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20bre Vak; X`09`7D X`7D X Xvoid`20ifstatement(beginning) X/* X`20*`09Process`20an`20if`20stmt.`20In`20the`20process`20generate`20any`20code V`20associated X`20*`09with`20the`20if/else`20control`20structure.`20`20When`20this`20function V`20is`20called X`20*`09the`20current`20value`20of`20tokencode`20should`20be`20IF. X`20* X`20*/ X`20`20`20`20`7B X`09int`20looptype,`20lab1,`20lab2; X X`09scan();`20`20`20 X`09if(`20tokencode`20==`20OPAREN`20) X`09`09/*`20skip`20over`20OPAREN`20so`20conditon()`20gets`20the`20next`20token. V`20*/ X`09`09scan(); X`09else X`09`09errmsg("Error--missing`20a`20'('`20in`20if`20condition`5Cn"); X X`09lab1`20=`20genlab(); X`09lab2`20=`20genlab();`20`20/*`20reserve`20this`20in`20case`20there`20is`20an V`20else`20*/ X`09if`20(beginning)`20emitstring("$`20"); X`09emitstring("if`20(.not.("); X X`09/*`20Parse`20the`20condition`20from`20the`20input`20stream.`20*/ X`09condition(); X`09 X`09if(`20tokencode`20==`20CPAREN) X`09`09scan(); X`09else X`09`09errmsg("Error--missing`20a`20')'`20in`20if`20condition`5Cn"); X`09/*`20 X`09`20*`09Build`20the`20remainder`20of`20the`20if-()-then-goto`20line`20and`20 V X`09`20*`09output`20it.`20`20Function`20emittarget()`20is`20almost`20exactly`20 Vlike X`09`20*`09emitlabel()`20except`20that`20no`20colon`20is`20appended`20to`20the V X`09`20*`09label. X`09`20*/ X`09emitstring("))`20then`20goto`20"); X`09emittarget(lab1); X`09emitstring("`5Cn"); X`09/*`20 X`09`20*`09Process`20the`20action`20part`20if`20the`20if-statement`20with`20a X`09`20*`09recursive`20call`20to`20statement(). X`09`20*/ X`09statement(1); X X`09/*`20Check`20for`20an`20else`20part.`20*/ X`09if`20(tokencode`20==`20ELSE`20)`7B X`09`09scan();`20`20`20`20`20`20`20 X`09`09emitstring("$`20goto`20"); X`09`09emittarget(lab2); X`09`09emitstring("`5Cn"); X`09`09emitstring("$`20"); X`09`09emitlabel(lab1); X`09`09emitstring("`5Cn"); X X`09`09statement(1); X`09`09/*`20 X`09`09`20*`09Finally,`20build`20the`20target`20for`20the`20transfer`20from X`09`09`20*`09the`20if`20portion`20of`20the`20statement`20if`20the`20statement V X`09`09`20*`09is`20an`20if-then-else. X`09`09`20*/ X`09`09emitstring("$`20"); X`09`09emitlabel(lab2); X`09`09emitstring("`5Cn"); X`09`7D X`09else`7B X`09`09/* X`09`09`20*`09Build`20the`20target`20for`20a`20transfer`20from`20the X`09`09`20*`09if`20condition`20when`20there`20is`20no`20else`20clause. X`09`09`20*/ X`09`09emitstring("$`20"); X`09`09emitlabel(lab1); X`09`09emitstring("`5Cn"); X`09`7D X`20`20`20`20`7D X Xvoid`20compstmt(int`20beginning) X/* X`20*`09Called`20in`20response`20to`20encountering`20a`20OBRACE`20token,`20 X`20*`09signalling`20a`20compound`20statement.`20`20What`20can X`20*`09legally`20follow`20is`20one`20or`20several`20statements.`20`20These`20 V X`20*`09statements`20can`20in`20turn`20be`20compound`20statements`20as`20well V`20as`20any X`20*`09other`20statement`20type.`20`20All`20this`20function`20need`20do`20is V`20call`20 X`20*`09function`20statement`20recursively`20until`20a`20CBRACE`20is`20encounte Vred X`20*`09(or`20the`20end`20of`20file). X`20*/ X`20`20`20`20`7B X`09int`20flag`20=`201`20; X X`09scan(); X`09while`20(tokencode`20!=`20CBRACE`20`26`26`20tokencode`20!=`20FILEEND) X`09`09if`20(flag) X`09`09`7B X`09`09`20`20`20`20flag`20=`200`20; X`09`09`20`20`20`20statement(beginning)`20; X`09`09`7D X`09`09else X`09`09`20`20`20`20statement(1); X X`09/*`20Get`20the`20next`20token`20following`20the`20CBRACE`20for`20statement( V)`20to`20use.`20*/ X`09scan(); X`20`20`20`20`7D X Xvoid`20onstmt(int`20beginning) X/* X`20*`09Process`20an`20on`20stmt.`20In`20the`20process`20generate`20any`20code V`20associated X`20*`09with`20the`20on`20control`20structure.`20`20When`20this`20function`20is V`20called X`20*`09the`20current`20value`20of`20tokencode`20should`20be`20ON. X`20* X`20*/ X`20`20`20`20`7B X`09char`20onCondition`5BMAXTOKENLEN`5D`20; X`09int`20looptype, X`09`20`20`20`20lab1,`20`20`20/*`20Name`20of`20the`20on`20block.`20*/ X`09`20`20`20`20lab2,`20`20`20/*`20Exit`20label`20of`20the`20on`20block.`20*/ X`09`20`20`20`20lab3;`20`20`20/*`20Branch`20around`20the`20on`20block.`20*/ X X`09lab1`20=`20genlab(); X`09lab2`20=`20genlab(); X`09lab3`20=`20genlab(); X`09push(ON,`20lab1); X X`09scan();`20`20`20 X`09switch`20(tokencode) X`09`7B X`09`20`20`20`20case`20ON_WARNING: X`09`20`20`20`20case`20ON_ERROR: X`09`20`20`20`20case`20ON_SEVERE_ERROR: X`09`20`20`20`20case`20ON_CONTROL_Y: X`09`09strcpy`20(onCondition,`20token)`20; X`09`09break`20; X X`09`20`20`20`20default: X`09`09errmsg("Error--Invalid`20on`20condition`5Cn")`20; X`09`09break`20; X`09`7D X X`09scan()`20; X`09switch`20(tokencode) X`09`7B X`09`20`20`20`20case`20THEN: X`09`09if`20(beginning)`20emitstring("$`20")`20; X`09`09emitstring("on`20")`20; X`09`09emitstring(onCondition)`20; X`09`09emitstring("`20then`20")`20; X`09`09scan()`20; X`09`09pop(`26looptype,`20`26lab1); X`09`09statement(0)`20; X`09`09return`20; X`09`09 X`09`20`20`20`20case`20OBRACE: X`09`09if`20(beginning)`20emitstring("$`20")`20; X`09`09emitstring("on`20")`20; X`09`09emitstring(onCondition)`20; X`09`09emitstring("`20then`20gosub`20")`20; X`09`09emittarget(lab1)`20; X`09`09emitstring("`5Cn")`20; X`09`09emitstring("$`20goto`20")`20; X`09`09emittarget(lab3)`20; X`09`09emitstring("`5Cn")`20; X`09`09emitstring("$")`20; X`09`09emitlabel(lab1)`20; X`09`09emitstring("`5Cn")`20; X`09`09compstmt(1)`20; X`09`09break`20; X X`09`20`20`20`20default: X`09`09errmsg("Error--Invalid`20argument`20for`20ON`20condition`5Cn")`20; X`09`09break`20; X`09`7D X X`09emitstring("$")`20; X`09emitlabel(lab2)`20; X`09emitstring("`5Cn")`20; X X`09emitstring("$`20on`20")`20; X`09emitstring(onCondition)`20; X`09emitstring("`20then`20gosub`20")`20; X`09emittarget(lab1)`20; X`09emitstring("`5Cn")`20; X`09 X`09emitstring("$`20return`5Cn")`20; X`09 X`09emitstring("$")`20; X`09emitlabel(lab3)`20; X`09emitstring("`5Cn")`20; X X`09/* X`09`20*`09It`20is`20necessary`20to`20pop`20the`20stack`20although`20the`20valu Ves`20 X`09`20*`09returned`20by`20the`20operation`20will`20not`20be`20used. X`09`20*/ X`09pop(`26looptype,`20`26lab1); X`09popBreakNext()`20; X`20`20`20`20`7D X Xvoid`20other(int`20beginning) X X/*`09This`20function`20is`20called`20when`20an`20input`20line`20doesn't`20begi Vn`20with X**`09a`20keyword`20token`20or`20an`20OBRACE.`20`20Assume`20the`20line`20ends V`20when`20a`20 X**`09newline`20or`20EOF`20is`20encountered.`20 X** X**`09If`20the`20current`20token`20begins`20with`20a`20POUND`20it`20is`20a`20sp Vecial X**`09sdcl`20preprocessor`20directive`20to`20strip`20off`20the`20POUND`20and X**`09pass`20whatever`20follows`20it`20to`20the`20output.`20`20 X** X**`09If`20the`20current`20token`20begins`20with`20a`20DOLLAR`20it`20is`20a`20s Vpecial X**`09sdcl`20preprocessor`20directive`20to`20pass`20the`20whatever`20follows X**`09it`20to`20the`20output. X** X**`09If`20there`20is`20no`20beginning`20POUND`20the`20output`20line`20has`20a V`20 X**`09DOLLAR`20prepended`20to`20it`20then`20the`20first,`20and`20all`20subseque Vnt`20tokens`20are X**`09passed`20to`20the`20output`20stream. X** X**`09Certain`20tokens`20cause`20special`20actions`20to`20be`20taken.`20`20A`20 VBACKSLASH X**`09tokencode`20is`20an`20sdcl`20line-continuation`20signal.`20`20What`20it V`20means`20is X**`09that`20the`20next`20input`20line`20is`20to`20be`20considered`20to`20be`20 Va`20continuation X**`09of`20the`20current`20line.`20`20When`20a`20backslash`20is`20encountered V`20parse X**`09until`20the`20following`20newline`20character`20is`20encountered`20and X**`09discard`20the`20newline.`20`20Continue`20the`20parse`20appending`20the X**`09tokens`20from`20the`20next`20line`20until`20another`20newline,`20semicolo Vn, X**`09of`20EOF`20token`20is`20found. X** X**`09A`20STRING`20token`20causes`20a`20call`20to`20emitqstring()`20instead`20o Vf X**`09emitstring().`20`20Emitqstring()`20merely`20checks`20to`20see`20if`20the V X**`09STRING`20token`20will`20fit`20on`20the`20current`20output`20line.`20`20If V`20it X**`09won't`20a`20dash`20(DCL`20continuation`20character)`20and`20a`20newline V`20are X**`09appended`20to`20the`20current`20output`20line.`20`20This`20will`20then`20 Vflush X**`09the`20current`20output`20line.`20`20Then`20the`20STRING`20token`20is`20ou Vtput X**`09without`20a`20prepended`20dollar`20sign. X*/ X`20`20`20`20`7B X`09/*`20If`20no`20directive`20to`20pass`20the`20input`20line`20directly...`20* V/ X X`09switch`20(tokencode) X`09`7B X`09`09default`09:`09if`20(beginning)`20emitstring("$`20")`20; X`09`09`09`09emitstring(token)`20; X`09`09`09`09break`20; X X`09`09case`20GRAVE`20: X`09`09case`20STRING`20:`09if`20(beginning)`20emitstring("$`20")`20; X`09`09`09`09emitqstring(token)`20; X`09`09`09`09break`20; X X`09`09case`20POUND`20:`20`09tokencode`20=`20lex(token)`20; X`09`09case`20DOLLAR`20:`09while`20((tokencode`20!=`20NEWLINE)`20`26`26 X`09`09`09`09`20`20`20`20`20`20`20(tokencode`20!=`20FILEEND)) X`09`09`09`09`7B X`09`09`09`09`09emitlstring(token)`20; X`09`09`09`09`09tokencode`20=`20lex(token)`20; X`09`09`09`09`7D`20; X`09`09`09`09emitstring("`5Cn")`20; X`09`09`09`09scan()`20; X`09`09`09`09return`20; X`09`7D`20; X X`09tokencode`20=`20lex(token); X X`09while`20(tokencode`20!=`20NEWLINE`20`26`26`20tokencode`20!=`20FILEEND)`7B X`09`09/*`20 X`09`09`20*`09If`20a`20backslash`20include`20the`20next`20line`20of`20input`20 V X`09`09`20*`09with`20the`20current`20one. X`09`09`20*/ X`09`09if`20(tokencode`20==`20BACKSLASH)`7B X`09`09`09while`20(tokencode`20!=`20NEWLINE) X`09`09`09`09tokencode`20=`20lex(token); X`09`09`09scan(); X`09`09`09/*`20Add`20a`20space`20for`20readability.`20*/ X`09`09`09emitstring("`20"); X`09`09`7D X`09`09/* X`09`09`20*`09Insure`20that`20the`20current`20STRING`20token`20will`20not X`09`09`20*`09be`20broken`20by`20a`20newline`20by`20outputting`20the`20 X`09`09`20*`09string`20via`20calling`20emitqstring()`20instead`20of X`09`09`20*`09emitstring(). X`09`09`20*/ X`09`09else`20if`20((tokencode`20==`20STRING)`20`7C`7C`20(tokencode`20==`20GRAV VE))`7B X`09`09`09emitqstring(token); X`09`09`09tokencode`20=`20lex(token); X`09`09`7D X`09`09else`20if`20(`20tokencode`20!=`20COMMENT`20)`20`7B X`09`09`09emitstring(token); X`09`09`09tokencode`20=`20lex(token); X`09`09`7D X`09`09else`20`20/*`20don't`20emit`20sdcl`20comment,`20just`20get`20next`20toke Vn`20*/ X`09`09`09tokencode`20=`20lex(token); X`09`7D X`09emitstring("`5Cn");`20`20`20`20`20`20/*`20cause`20a`20output`20line`20flush V`20*/ X`09scan(); X`20`20`20`20`7D X Xvoid`20whilestmt(int`20beginning) X/* X`20*`20`09This`20function`20processes`20a`20while`20statement`20in`20a`20manne Vr`20 X`20*`20`09similar`20to`20how`20if`20statements`20are`20handled.`20`20This`20fu Vnction`20 X`20*`09will`20be`20invoked`20in`20response`20to`20finding`20the`20keyword`20"w Vhile" X`20*`09in`20the`20input`20stream. X`20* X`20*`09While`20the`20semantic`20parse`20is`20being`20performed`20the`20interme Vdiate X`20*`09code`20for`20this`20statement`20is`20also`20being`20generated. X`20*/`09 X`20`20`20`20`7B X`09int`20looptype,`20lab1,`20lab2; X X`09/*`20Skip`20the`20keyword`20and`20get`20two`20labels.`20*/ X`09scan(); X`09lab1`20=`20genlab(); X`09lab2`20=`20genlab(); X`09/*`20 X`09`20*`09Begin`20building`20the`20output`20string.`20`20This`20will`20be X`09`20*`09the`20destination`20label`20for`20any`20next`20statements. X`09`20*/ X`09if`20(beginning)`20emitstring`20("$`20"); X`09emitlabel(lab1); X`09emitstring("if`20(.not.("); X X`09if`20(tokencode`20==`20OPAREN) X`09`09scan(); X`09else X`09`09errmsg("Error--missing`20a`20'('`20in`20while`20condition`5Cn"); X`09/* X`09`20*`09Call`20condition.`20`20When`20it`20returns`20the`20current`20token X`09`20*`09should`20be`20a`20CPAREN. X`09`20*/ X`09condition(); X`09if`20(tokencode`20==`20CPAREN) X`09`09scan(); X`09else X`09`09errmsg("Error--missing`20a`20')'`20in`20while`20condition`5Cn"); X X`09`20emitstring("))`20then`20goto`20"); X`09`20emittarget(lab2); X`09`20emitstring("`5Cn"); X X`09emitstring("$`20$BREAK`20=`20`5C"")`20; X`09emittarget(lab2)`20; X`09emitstring("`5C"`5Cn")`20; X X`09emitstring("$`20$NEXT`20=`20`5C"")`20; X`09emittarget(lab1)`20; X`09emitstring("`5C"`5Cn")`20; X X`09/* X`09`20*`09Do`20the`20necessary`20stack`20operations`20to`20preserve`20the X`09`20*`09labels`20used`20with`20this`20while`20stmt.`20These`20will`20be`20us Ved X`09`20*`09to`20target`20any`20next`20or`20break`20stmts. X`09`20*/ X`09push(WHILE,`20lab1); X`09statement(1); X X`09/* X`09`20*`09After`20the`20statement`20code`20has`20been`20generated`20the`20tran Vsfer X`09`20*`09statement`20to`20the`20beginning`20of`20the`20condition`20must`20be V`20 X`09`20*`09generated($`20goto`20lab1).`20`20Then`20the`20destination`20for`20 X`09`20*`09condition`20failure`20must`20be`20inserted.`20`20This`20value`20will V`20 X`09`20*`09be`20lab`20+`201`20(lab2).`20`20Lab2`20will`20*`09be`20the`20destina Vtion`20 X`09`20*`09address`20for`20any`20break`20statements. X`09`20*/ X`09emitstring("$`20goto`20"); X`09emittarget(lab1); X`09emitstring("`5Cn"); X`09emitstring("$`20"); X`09emitlabel(lab2); X`09emitstring("`5Cn"); X`09/* X`09`20*`09It`20is`20necessary`20to`20pop`20the`20stack`20although`20the`20valu Ves`20 X`09`20*`09returned`20by`20the`20operation`20will`20not`20be`20used. X`09`20*/ X`09pop(`26looptype,`20`26lab1); X`09popBreakNext()`20; X`20`20`20`20`7D X Xvoid`20dowhilestmt(int`20beginning) X/* X`20*`09Parse`20and`20generate`20the`20contruct X`20*`09`20`20do X`20*`09`20`20`20`20`20`20statement X`20*`09`20`20while`20(`20condition`20) X`20*/ X`20`20`20`20`7B X`20`20`20`20`20`20`20`20int`20lab1,`20lab2,`20lab3,`20looptype; X X`09scan(); X`09/* X`09`20*`20reserve`20all`20the`20labels`20needed`20for`20do-while`20and`20recor Vd`20loop X`09`20*`20on`20stack. X`09`20*/ X`09lab1`20=`20genlab(); X`09lab2`20=`20genlab(); X`09lab3`20=`20genlab(); X`09push(`20DO,`20lab1`20); X X`09/* X`09`20*`20emit`20the`20label`20where`20the`20true`20exit`20from`20the`20condit Vion X`09`20*`20will`20come`20to.`20 X`09*/ X`09if`20(beginning)`20emitstring(`20"$`20"`20); X`09emitlabel(`20lab1`20); X`09emitstring(`20"`5Cn"`20); X`09 X`09emitstring("$`20$BREAK`20=`20`5C"")`20; X`09emittarget(lab3)`20; X`09emitstring("`5C"`5Cn")`20; X X`09emitstring("$`20$NEXT`20=`20`5C"")`20; X`09emittarget(lab2)`20; X`09emitstring("`5C"`5Cn")`20; X X`09statement(1); X`09if`20(`20tokencode`20==`20WHILE`20) X`09`20`20`20`20scan(); X`09else X`09`20`20`20`20errmsg("Error`20--`20missing`20keyword`20'while'`20in`20do-whil Ve`5Cn"`20); X`09if`20(`20tokencode`20==`20OPAREN`20) X`09`20`20`20`20scan(); X`09else X`09`20`20`20`20errmsg("Error`20--`20missing`20(`20in`20do-while`20condition`5C Vn"`20); X X`09/* X`09`20*`20emit`20code`20for`20condition`20test`20and`20branch`20 X`09`20*/ X`09emitstring(`20"$`20"`20); X`09emitlabel(`20lab2`20); X`09emitstring("if(`20"`20); X X`09condition(); X`09if`20(`20tokencode`20==`20CPAREN`20) X`09`20`20`20`20scan(); X`09else X`09`20`20`20`20errmsg("Error`20--`20missing`20)`20in`20do-while`20condition`5C Vn"`20); X X`09/* X`09`20*`20branch`20to`20start`20of`20loop,`20and`20label`20for`20any`20break V`20statements. X`09`20*/ X`09emitstring("`20)`20then`20goto`20"); X`09emittarget(`20lab1`20); X`09emitstring(`20"`5Cn"`20); X`09emitstring(`20"$`20"); X`09emitlabel(`20lab3`20); X`09emitstring(`20"`5Cn"`20); X`09/* X`09`20*`20pop`20stack`20now`20that`20we`20are`20done. X`09`20*/ X`09pop(`20`26looptype,`20`26lab1`20); X`09popBreakNext()`20; X`20`20`20`20`7D X Xvoid`20breakstmt(int`20beginning) X/* X`20*`09As`20its`20name`20implies`20this`20small`20function`20handles`20a`20bre Vak X`20*`09statement.`20`20It`20is`20called`20by`20function`20statement()`20whenev Ver X`20*`09the`20token`20BREAK`20is`20encountered.`20`20All`20this`20function`20ne Ved X`20*`09do`20is`20call`20scan`20until`20a`20NEWLINE,`20or`20FILEEND X`20*`09is`20encountered.`20`20When`20it`20is`20found`20the`20appropriate`20got Vo X`20*`09string`20must`20be`20generated.`20`20Then`20one`20more`20call`20to`20sc Van`20will`20be`20 X`20*`09performed`20to`20prepare`20for`20the`20next`20call`20to`20function`20st Vatement(). X`20*/ X`20`20`20`20`7B`20 X`09int`20looptype,`20label; X X`09while`20(tokencode`20!=`20NEWLINE`20`26`26`20tokencode`20!=FILEEND`20) X`09`09tokencode`20=`20lex(token);`09 X`09/* X`09`20*`09Examine`20the`20top`20of`20the`20stack`20to`20see`20what`20action`20 Vshould X`09`20*`09be`20taken.`20`20If`20currently`20within`20a`20for`20loop,`20generat Ve X`09`20*`09a`20"$`20goto`20(label`20+`202)."`20`20If`20in`20a`20while,`20genera Vte`20a X`09`20*`09"$`20goto`20(label`20+`201)." X`09`20*/ X`09if(`20peek(`26looptype,`20`26label)`20)`7B X`09`20`20`20`20if`20(beginning)`20emitstring("$`20"); X`09`20`20`20`20emitstring("goto`20"); X`09`20`20`20`20if`20(looptype`20==`20FOR`20`7C`7C`20looptype`20==`20DO) X`09`09emittarget(label`20+`202); X`09`20`20`20`20else X`09`09emittarget(label`20+`201); X`09`20`20`20`20emitstring("`5Cn"); X`09`7D X`09else X`09`20`20`20`20errmsg("Error`20--`20break`20statement`20is`20not`20within`20an Vy`20loop`5Cn"); X X`09scan(); X`20`20`20`20`7D X Xvoid`20nextstmt(int`20beginning) X/*`20 X`20*`09Called`20by`20statement()`20whenever`20the`20NEXT`20keyword`20is`20foun Vd.`20`20 X`20*`09This`20function`20repeatedly`20calls`20scan()`20until`20it`20finds`20a V`20 X`20*`09NEWLINE,`20or`20the`20end`20of`20the`20input`20file`20is`20encountered. V`20`20 X`20*`09After`20any`20of`20these`20tokens`20are`20found`20the`20appropriate`20g Voto`20 X`20*`09string`20is`20generated`20to`20continue`20loop`20execution.`20`20 X`20*`09Then`20one`20final`20call`20to`20scan`20is`20performed`20to`20prepare V`20for`20 X`20*`09any`20further`20calls`20to`20statement(). X`20*/ X`20`20`20`20`7B X`09int`20looptype,`20label; X X`09while`20(tokencode`20!=`20NEWLINE`20`26`26`20tokencode`20!=`20FILEEND`20) X`09`09tokencode`20=`20lex(token); X`09/* X`09`20*`09Examine`20the`20top`20of`20the`20stack`20to`20see`20what`20action`20 Vshould X`09`20*`09be`20taken.`20`20If`20currently`20within`20a`20for`20loop,`20generat Ve X`09`20*`09a`20"$`20goto`20(label`20+`201)."`20`20If`20in`20a`20while,`20genera Vte`20a X`09`20*`09"$`20goto`20label." X`09`20*/ X`09if(`20peek(`26looptype,`20`26label)`20)`20`7B X`09`20`20`20`20if`20(beginning)`20emitstring("$`20"); X`09`20`20`20`20emitstring("goto`20"); X`09`20`20`20`20if`20(looptype`20==`20FOR`20`7C`7C`20looptype`20==`20DO) X`09`09emittarget(label`20+`201); X`09`20`20`20`20else`20if`20(looptype`20==`20WHILE) X`09`09emittarget(label); X`09`20`20`20`20else X`09`09errmsg("Error`20--`20next`20statement`20is`20not`20within`20any`20loop V`5Cn")`20; X`09`20`20`20`20emitstring("`5Cn"); X`09`7D X`09else X`09`20`20`20`20errmsg("Error`20--`20next`20statement`20is`20not`20within`20any V`20loop`5Cn"); X X`09scan(); X`20`20`20`20`7D X Xvoid`20condition() X/* X`20*`09This`20function`20will`20be`20called`20whenever`20a`20DCL`20condition V`20needs X`20*`09to`20be`20evaluated.`20`20The`20current`20token`20should`20be`20an`20OP VAREN,`20but X`20*`09it`20may`20not`20be.`20`20DCL`20conditions`20may`20have`20nested`20sets V`20of`20 X`20*`09parentheses`20and`20these`20must`20be`20handled`20by`20this`20function. V X`20*`09Initialize`20a`20variable,`20paren_count,`20to`20one. X`20*`09Whenever`20another`20OPAREN`20is`20encountered`20increment`20paren_coun Vt. X`20*`09Decrement`20paren_count`20when`20a`20CPAREN`20is`20found.`20`20Repeat V`20until X`20*`09paren_count`20goes`20to`20zero`20and`20a`20CPAREN`20has`20been`20found. V`20`20 X`20*`09Be`20sure`20to`20return`20with`20CPAREN`20as`20the`20current`20token. X`20* X`20*`09Since`20this`20condition`20can`20also`20appear`20in`20a`20for`20stateme Vnt`20of X`20*`09sdcl`20condition`20can`20also`20be`20terminated`20by`20a`20SEMICOLON. X`20* X`20*`09For`20the`20code`20generation`20portion`20part`20of`20this`20function V`20merely X`20*`09pass`20anything`20encountered`20to`20emistring(),`20except`20for`20the V X`20*`09closing,`20CPAREN. X`20* X`20*/ X`20`20`20`20`7B X`09short`20paren_count`20=`201; X X`09/*`20 X`09**`20Output`20the`20current`20token`20and`20update`20the`20state`20of`20par Ven_count X`09**`20appropriately.`20`20This`20is`20necessary`20to`20catch`20parenthesized V`20conditional X`09**`20forms: X`09** X`09**`20`09if`20(`20(cond1)`20.op.`20(cond2)`20...)`20... X`09*/ X X`09switch`20(tokencode) X`09`7B X`09`09case`20NEWLINE`09:`20break`20;`20/*`20eatup`20newlines`20*/ X X`09`09case`20CPAREN`09:`09/*`20A`20condition`20of`20the`20form: X`09`09`09`09`09**`20().`20`20This`20should`20probably`20be`20a X`09`09`09`09`09**`20syntax`20error.`20*/ X`09`09case`20SEMICOLON`20`20:`20return`20;`20`20/*`20in`20a`20for`20loop`20*/ V X X`09`09case`20GRAVE`20: X`09`09case`20STRING`20:`09emitqstring(token)`20; X`09`09`09`09break`20;`09/*`20Quoted`20strings`20in`20conditionals`20`20`20*/ X`09`09`09`09`09/*`20should`20be`20preserved.`09`09`20`20`20`20*/ X X`09`09case`20OPAREN`09:`20paren_count++; X`09`09default`09`09:`20emitstring(token); X`09`09`09`09`20`20break; X`09`7D X X`09/* X`09`20*`09Output`20all`20tokens`20returned`20by`20lex()`20except`20for X`09`20*`09the`20last`20CPAREN.`20`20Maintain`20level`20of`20parentheses X`09`20*`09nesting`20via`20increments`20and`20decrements`20to`20paren_count. X`09`20*`09The`20loop`20will`20terminate`20whenever`20either`20a`20SEMICOLON X`09`20*`09is`20found`20or`20a`20CPAREN`20is`20found`20when`20paren_count`20is V X`09`20*`09zero. X`09`20*/ X`09do`7B X`09`09tokencode`20=`20lex(token); X`09`09switch`20(tokencode) X`09`09`7B X`09`09`09case`20OPAREN`09:`20paren_count++; X`09`09`09`09`09`20`20emitstring(token); X`09`09`09`09`09`20`20break; X X`09`09`09case`20CPAREN`09:`20paren_count--; X`09`09`09`09`09`20`20if`20(paren_count) X`09`09`09`09`09`20`20`09emitstring(token); X`09`09`09`09`09`20`20break; X X`09`09`09case`20NEWLINE`09:`20`20/*`20eatup`20newlines`20*/ X`09`09`09case`20SEMICOLON`20`20:`20break;`20`20/*`20in`20a`20for`20loop`20*/ X X`09`09`09case`20GRAVE`20: X`09`09`20`20`20`20`20`20`20`20case`20STRING`20:`09emitqstring(token)`20; X`09`09`09`09`20`20`20`20`20`20`20`20break`20;`09 X`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20`20 V`20`20`20`20`20`20`20`20`20`20`20`20`20`20/*`20Quoted`20strings`20in`20conditi Vonals`20`20`20*/ X`09`09`09`09`09/*`20should`20be`20preserved.`09`09`20`20`20`20*/ X X`09`09`09default`09`09:`20emitstring(token); X`09`09`09`09`09`20`20break; X`09`09`7D X`09`7D`20while`20(paren_count`20`26`26`20tokencode`20!=`20SEMICOLON`20`26`26 X`09`09`20tokencode`20!=`20FILEEND`20); X X`09/*`20 X`09`20*`09At`20the`20end`20of`20this`20function`20the`20current`20token`20will V`20be X`09`20*`09either`20a`20CPAREN`20or`20a`20SEMICOLON. X`09`20*/ X`7D X Xvoid`20forstmt(int`20beginning) X/* X`20*`09The`20code`20generation`20porion`20of`20this`20function`20is`20somewhat V`20involved. X`20*`09The`20reinitialization`20portion`20of`20the`20code`20is`20saved`20in`20 Va`20temporary X`20*`09buffer`20called`20rstring`5B`5D.`20`20It`20is`20put`20into`20rsring`20b Vy`20a`20call`20to X`20*`09reinitialize().`20`20Then`20the`20statement`20portion`20of`20the`20inpu Vt`20stream X`20*`09is`20read`20and`20processed.`20`20Then`20the`20reinitialization`20code V`20is X`20*`09output`20after`20the`20proper`20transfer`20label`20is`20output. X`20*/ X`20`20`20`20`7B X`09int`20lab1,`20lab2,`20lab3,`20looptype; X`09char`20rstring`5BMAXCONDLEN`5D; X X`09scan(); X`09if`20(tokencode`20==`20OPAREN) X`09`09scan(); X`09else X`09`09errmsg("Error--missing`20a`20'('`20in`20for`20statement`5Cn"); X`09/*`20`20Get`20the`20three`20labels`20necessary`20for`20a`20for-statement. V`20*/ X`09lab1`20=`20genlab(); X`09lab2`20=`20genlab(); X`09lab3`20=`20genlab(); X X`09/*`20`20 X`09`20*`09If`20the`20next`20token`20is`20not`20a`20SEMICOLON`20then`20an`20ini Vtialization X`09`20*`09statement`20exists`20for`20this`20for`20statement.`20`20Process`20it V`20via X`09`20*`09a`20call`20to`20initialize(). X`09`20*/ X`09if`20(tokencode`20!=`20SEMICOLON) X`09`7B X`09`09initialize(beginning); X`09`09beginning`20=`201`20; X`09`7D X X`09if`20(beginning)`20emitstring("$`20"); X`09emitlabel(lab1); X`09emitstring("$BREAK`20=`20`5C"")`20; X`09emittarget(lab3)`20; X`09emitstring("`5C"`5Cn")`20; X X`09emitstring("$`20$NEXT`20=`20`5C"")`20; X`09emittarget(lab2)`20; X`09emitstring("`5C"")`20; X X`09scan(); X X`09/* X`09`20*`09If`20the`20next`20token`20isn't`20a`20SEMICOLON`20assume`20that`20a V X`09`20*`09condition`20statement`20exists.`20`20Begin`20building`20the X`09`20*`09string`20to`20test`20this`20condition.`20`20Call`20condition() X`09`20*`09to`20parse`20and`20output`20the`20relational`20expression,`20then X`09`20*`09finish`20building`20the`20statement`20by`20adding`20the`20"goto" X`09`20*`09clause`20with`20the`20appropriate`20transfer`20address`20for X`09`20*`09when`20the`20condition`20fails. X`09`20*/ X`09if`20(tokencode`20!=`20SEMICOLON)`7B X`09`09emitstring("`5Cn")`20; X`09`09emitstring("$`20if`20(.not.("); X`09`09condition(); X`09`09emitstring("))`20then`20goto`20"); X`09`09emittarget(lab3); X`09`7D X`09emitstring("`5Cn"); X`09scan(); X`09/* X`09`20*`09If`20the`20next`20token`20is`20not`20a`20CPAREN`20then`20we`20know V`20that X`09`20*`09we`20don't`20have`20a`20null`20reinitialization`20statement.`20`20 X`09`20*`09Call`20reinitialize()`20to`20parse`20and`20save`20this`20statement. V X`09`20*`09The`20statement`20will`20be`20saved`20in`20rstring`5B`5D`20for`20lat Ver X`09`20*`09use`20after`20the`20statement`20portion`20of`20the`20for-loop X`09`20*`09has`20been`20processed. X`09`20*/ X`09rstring`5B0`5D`20=`20'`5C0'; X`09if`20(tokencode`20!=`20CPAREN)`20 X`09`09reinitialize(rstring); X X`09if`20(tokencode`20==`20CPAREN) X`09`09scan(); X`09else X`09`09errmsg("Error--missing`20a`20')'`20in`20for`20statement`5Cn"); X`09/* X`09`20*`09Push`20lab1`20onto`20the`20stack`20to`20enable`20processing`20of`20b Vreak X`09`20*`09and`20next`20statements.`20`20Process`20the`20action`20portion`20of V`20 X`09`20*`09this`20while-loop.`20 X`09`20*/ X`09push(FOR,`20lab1); X`09statement(1); X`09/* X`09`20*`09Build`20the`20label`20that`20preceedes`20the`20reinitialization`20st Vuff, X`09`20*`09and,`20if`20this`20stuff`20isn't`20NULL,`20output`20it`20after`20the V`20label. +-+-+-+-+-+-+-+- END OF PART 2 +-+-+-+-+-+-+-+- -- Dick Munroe Internet: munroe@acornsw.com Acorn Software, Inc. 267 Cox St. Office: (508) 568-1618 x16 Hudson, Ma. 01749 USA FAX: (508) 562-1133 -- Dick Munroe Internet: munroe@acornsw.com Acorn Software, Inc. 267 Cox St. Office: (508) 568-1618 x16 Hudson, Ma. 01749 USA FAX: (508) 562-1133