home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-07-28 | 53.2 KB | 2,234 lines |
- end
- until tq = nil;
- 555:
- writeln(';');
- if tp^.tt = nvarpar then
- if tp^.tbind^.tt = nconfarr then
- begin
- indent;
- etypedef(tp^.tbind^.tindtyp);
- write(tab1);
- tq := tp^.tbind^.tcindx^.thi;
- printid(tq^.tsym^.lid);
- writeln(';')
- end;
- tp := tp^.tnext
- end
- end; (* evar *)
-
- (* Emit code for a statment. *)
- procedure estmt(tp : treeptr);
-
- var tq : treeptr;
- locid1,
- locid2 : idptr;
- stusd : boolean;
- opc1,
- opc2 : char;
-
- (* Emit typename for with-variable. *)
- procedure ewithtype(tp : treeptr);
-
- var tq : treeptr;
-
- begin
- tq := typeof(tp);
- write('struct ');
- printid(tq^.tuid)
- end;
-
- (* Emit code for a case-choise. *)
- procedure echoise(tp : treeptr);
-
- var tq : treeptr;
- i : integer;
-
- begin
- while tp <> nil do
- begin
- tq := tp^.tchocon;
- i := 0;
- indent;
- while tq <> nil do
- begin
- write(' case ');
- conflag := true;
- eexpr(tq);
- conflag := false;
- write(':');
- i := i + 1;
- tq := tq^.tnext;
- if (tq = nil) or (i mod 4 = 0) then
- begin
- writeln;
- if tq <> nil then
- indent;
- i := 0
- end
- end;
- increment;
- if tp^.tchostmt^.tt = nbegin then
- estmt(tp^.tchostmt^.tbegin)
- else
- estmt(tp^.tchostmt);
- indent;
- writeln('break ;');
- decrement;
- tp := tp^.tnext;
- if tp <> nil then
- if tp^.tchocon = nil then
- tp := nil
- end
- end; (* echoise *)
-
- (* Rename all accessible record-fields to include *)
- (* pointer name. *)
- procedure cenv(ip : idptr; dp : declptr);
-
- var tp : treeptr;
- sp : symptr;
- np : idptr;
- h : hashtyp;
-
- begin
- with dp^ do
- for h := 0 to hashmax - 1 do
- begin
- sp := ddecl[h];
- while sp <> nil do
- begin
- if sp^.lt = lfield then
- begin
- np := sp^.lid;
- tp := sp^.lsymdecl^.tup^.tup;
- if (tp^.tup^.tt = nvariant) and
- (tp^.tuid <> nil) then
- np := mkconc('.',
- tp^.tuid, np);
- np := mkconc('>', ip, np);
- sp^.lid := np
- end;
- sp := sp^.lnext
- end
- end
- end; (* cenv *)
-
- (* Emit identifiers for push/pop of global ptrs. *)
- procedure eglobid(tp : treeptr);
-
- var j : toknidx;
- w : toknbuf;
-
- begin
- gettokn(tp^.tsym^.lid^.istr, w);
- j := 1;
- if w[1] = '*' then
- j := 2;
- while w[j] <> chr(null) do
- begin
- write(w[j]);
- j := j + 1
- end
- end;
-
- begin (* estmt *)
- while tp <> nil do
- begin
- case tp^.tt of
- nbegin:
- begin
- if tp^.tup^.tt in [nbegin, nrepeat,
- nproc, nfunc, npgm] then
- indent;
- writeln('{');
- increment;
- estmt(tp^.tbegin);
- decrement;
- indent;
- write('}');
- if tp^.tup^.tt <> nif then
- writeln
- end;
- nrepeat:
- begin
- indent;
- writeln('do {');
- increment;
- estmt(tp^.treptstmt);
- decrement;
- indent;
- write('} while (!(');
- eexpr(tp^.treptxp);
- writeln('));')
- end;
- nwhile:
- begin
- indent;
- write('while (');
- increment;
- eexpr(tp^.twhixp);
- stusd := setused;
- if tp^.twhistmt^.tt = nbegin then
- begin
- decrement;
- write(') ');
- estmt(tp^.twhistmt)
- end
- else begin
- writeln(')');
- estmt(tp^.twhistmt);
- decrement
- end;
- setused := stusd or setused
- end;
- nfor:
- begin
- indent;
- if tp^.tincr then
- begin
- opc1 := '+'; (* increment variable *)
- opc2 := '<' (* test for <= *)
- end
- else begin
- opc1 := '-'; (* decrement variable *)
- opc2 := '>'; (* test for >= *)
- end;
- if not lazyfor then
- begin
- locid1 := mkvariable('B');
- locid2 := mkvariable('B');
- writeln('{');
- increment;
- indent;
- tq := idup(tp^.tforid);
- etypedef(tq^.tbind);
- tq := typeof(tq^.tbind);
- write(tab1);
- printid(locid1);
- write(' = ');
- eexpr(tp^.tfrom);
- writeln(',');
- indent;
- write(tab1);
- printid(locid2);
- write(' = ');
- eexpr(tp^.tto);
- writeln(';');
- writeln;
- indent;
- write('if (');
- if tq^.tt = nscalar then
- begin
- write('(int)(');
- printid(locid1);
- write(')')
- end
- else
- printid(locid1);
- write(' ', opc2, '= ');
- if tq^.tt = nscalar then
- begin
- write('(int)(');
- printid(locid2);
- write(')')
- end
- else
- printid(locid2);
- writeln(')');
- increment;
- indent;
- tp^.tfrom := newid(locid1);
- tp^.tfrom^.tup := tp
- end;
- write('for (');
- increment;
- eexpr(tp^.tforid);
- tq := typeof(tp^.tforid);
- write(' = ');
- eexpr(tp^.tfrom);
- write('; ');
- if lazyfor then
- begin
- if tq^.tt = nscalar then
- begin
- write('(int)(');
- eexpr(tp^.tforid);
- write(')')
- end
- else
- eexpr(tp^.tforid);
- write(' ', opc2, '= ');
- if tq^.tt = nscalar then
- begin
- write('(int)(');
- eexpr(tp^.tto);
- write(')')
- end
- else
- eexpr(tp^.tto)
- end;
- write('; ');
- eexpr(tp^.tforid);
- if tq^.tt = nscalar then
- begin
- write(' = (');
- eexpr(tq^.tup^.tidl);
- write(')((int)(');
- eexpr(tp^.tforid);
- write(')', opc1, '1)')
- end
- else
- write(opc1, opc1);
- if not lazyfor then
- begin
- if tp^.tforstmt^.tt <> nbegin then
- begin
- (* create compund stmt *)
- tq := mknode(nbegin);
- tq^.tbegin := tp^.tforstmt;
- tq^.tbegin^.tup := tq;
- tp^.tforstmt := tq;
- tq^.tup := tp
- end;
- (* find end of loop *)
- tq := tp^.tforstmt^.tbegin;
- while tq^.tnext <> nil do
- tq := tq^.tnext;
- (* add break stmt *)
- tq^.tnext := mknode(nbreak);
- tq := tq^.tnext;
- tq^.tup := tp^.tforstmt;
- tq^.tbrkid := tp^.tforid;
- tq^.tbrkxp := newid(locid2);
- tq^.tbrkxp^.tup := tq
- end;
- if tp^.tforstmt^.tt = nbegin then
- begin
- decrement;
- write(') ');
- estmt(tp^.tforstmt)
- end
- else begin
- writeln(')');
- estmt(tp^.tforstmt);
- decrement
- end;
- if not lazyfor then
- begin
- decrement;
- decrement;
- indent;
- writeln('}')
- end
- end;
- nif:
- begin
- indent;
- write('if (');
- increment;
- eexpr(tp^.tifxp);
- stusd := setused;
- setused := false;
- if tp^.tthen^.tt = nbegin then
- begin
- decrement;
- write(') ');
- estmt(tp^.tthen);
- if tp^.telse <> nil then
- write(space)
- else
- writeln
- end
- else begin
- writeln(')');
- estmt(tp^.tthen);
- decrement;
- if tp^.telse <> nil then
- indent
- end;
- if tp^.telse <> nil then
- begin
- write('else');
- if tp^.telse^.tt = nbegin then
- begin
- write(space);
- estmt(tp^.telse);
- writeln
- end
- else begin
- increment;
- writeln;
- estmt(tp^.telse);
- decrement
- end;
- end;
- setused := stusd or setused
- end;
- ncase:
- begin
- indent;
- write('switch (');
- increment;
- eexpr(tp^.tcasxp);
- writeln(') {');
- decrement;
- echoise(tp^.tcaslst);
- indent;
- writeln(' default:');
- increment;
- if tp^.tcasother = nil then
- begin
- indent;
- writeln('Caseerror(Line);')
- end
- else
- estmt(tp^.tcasother);
- decrement;
- indent;
- writeln('}')
- end;
- nwith:
- begin
- indent;
- writeln('{');
- increment;
- tq := tp^.twithvar;
- while tq <> nil do
- begin
- indent;
- write(registr);
- ewithtype(tq^.texpw);
- write(' *');
- locid1 := mkvariable('W');
- printid(locid1);
- write(' = ');
- eaddr(tq^.texpw);
- writeln(';');
- cenv(locid1, tq^.tenv);
- tq := tq^.tnext
- end;
- writeln;
- if tp^.twithstmt^.tt = nbegin then
- estmt(tp^.twithstmt^.tbegin)
- else
- estmt(tp^.twithstmt);
- decrement;
- indent;
- writeln('}')
- end;
- ngoto:
- begin
- indent;
- if islocal(tp^.tlabel) then
- writeln('goto L',
- tp^.tlabel^.tsym^.lno:1, ';')
- else begin
- tq := idup(tp^.tlabel);
- writeln('longjmp(J[', (* LIB *)
- tq^.tstat:1, '].jb, ',
- tp^.tlabel^.tsym^.lno:1, ');')
- end
- end;
- nlabstmt:
- begin
- decrement;
- indent;
- writeln('L', tp^.tlabno^.tsym^.lno:1, ':');
- increment;
- estmt(tp^.tstmt)
- end;
- nassign:
- begin
- indent;
- eexpr(tp);
- writeln(';')
- end;
- ncall:
- begin
- indent;
- tq := idup(tp^.tcall);
- if (tq^.tt in [nfunc, nproc]) and
- (tq^.tsubstmt <> nil) then
- if tq^.tsubstmt^.tt = npredef then
- epredef(tq, tp)
- else begin
- ecall(tp);
- writeln(';')
- end
- else begin
- ecall(tp);
- writeln(';')
- end
- end;
- npush:
- begin
- indent;
- eglobid(tp^.ttmp);
- write(' = ');
- eglobid(tp^.tglob);
- writeln(';');
- indent;
- eglobid(tp^.tglob);
- write(' = ');
- if tp^.tloc^.tt = nid then
- begin
- tq := idup(tp^.tloc);
- if tq^.tt in [nparproc, nparfunc] then
- printid(tp^.tloc^.tsym^.lid)
- else
- eaddr(tp^.tloc)
- end
- else
- eaddr(tp^.tloc);
- writeln(';')
- end;
- npop:
- begin
- indent;
- eglobid(tp^.tglob);
- write(' = ');
- eglobid(tp^.ttmp);
- writeln(';')
- end;
- nbreak:
- begin
- indent;
- write('if (');
- eexpr(tp^.tbrkid);
- write(' == ');
- eexpr(tp^.tbrkxp);
- writeln(') break;')
- end;
- nempty:
- if not (tp^.tup^.tt in [npgm, nproc, nfunc,
- nchoise, nbegin, nrepeat]) then
- begin
- indent;
- writeln(';')
- end
- end;(* case *)
- if setused and
- (tp^.tup^.tt in [npgm, nproc, nfunc, nrepeat,
- nbegin, nchoise, nwith]) then
- begin
- indent;
- writeln('Claimset();');
- setused := false
- end;
- tp := tp^.tnext
- end
- end; (* estmt *)
-
- (* Emit initialization for non-local gotos. *)
- procedure elabel(tp : treeptr);
-
- var tq : treeptr;
- i : integer;
-
- begin
- i := 0;
- tq := tp^.tsublab;
- while tq <> nil do
- begin
- if tq^.tsym^.lgo then
- i := i + 1;
- tq := tq^.tnext
- end;
- if i =1 then
- begin
- tq := tp^.tsublab;
- while not tq^.tsym^.lgo do
- tq := tq^.tnext;
- indent;
- writeln('if (',
- 'setjmp(J[', tp^.tstat:1, '].jb))'); (* LIB *)
- writeln(tab1, 'goto L', tq^.tsym^.lno:1, ';')
- end
- else if i > 1 then
- begin
- indent;
- writeln('switch (',
- 'setjmp(J[', tp^.tstat:1, '].jb)) {'); (* LIB *)
- indent;
- writeln(' case 0:');
- indent;
- writeln(tab1, 'break');
- tq := tp^.tsublab;
- while tq <> nil do
- begin
- if tq^.tsym^.lgo then
- begin
- (* label used in non-local goto *)
- indent;
- writeln(' case ',
- tq^.tsym^.lno:1, ':');
- indent;
- writeln(tab1, 'goto L',
- tq^.tsym^.lno:1, ';')
- end;
- tq := tq^.tnext
- end;
- indent;
- writeln(' default:');
- indent;
- writeln(tab1, 'Caseerror(Line)');
- indent;
- writeln('}')
- end
- end; (* elabel *)
-
- (* Emit declaration for lower bound of conformant array. *)
- procedure econf(tp : treeptr);
-
- var tq : treeptr;
-
- begin
- while tp <> nil do
- begin
- if tp^.tt = nvarpar then
- if tp^.tbind^.tt = nconfarr then
- begin
- indent;
- etypedef(tp^.tbind^.tindtyp);
- write(tab1);
- tq := tp^.tbind^.tcindx^.tlo;
- printid(tq^.tsym^.lid);
- write(' = (');
- etypedef(tp^.tbind^.tindtyp);
- writeln(')0;')
- end;
- tp := tp^.tnext
- end
- end; (* econf *)
-
- (* Emit code for subroutines. *)
- procedure esubr(tp : treeptr);
-
- label 999;
-
- var tq, ti : treeptr;
-
- begin
- while tp <> nil do
- begin
- (* emit nested subroutines *)
- if tp^.tsubsub <> nil then
- begin
- (* emit forward declaration of this subroutine
- in case of recursion *)
- etypedef(tp^.tfuntyp);
- write(space);
- printid(tp^.tsubid^.tsym^.lid);
- writeln('();');
- writeln;
- esubr(tp^.tsubsub)
- end;
- (* emit this subroutine *)
- if tp^.tsubstmt = nil then
- begin
- (* forward/external decl *)
- if tp^.tsubid^.tsym^.lsymdecl^.tup = tp then
- write(xtern);
- etypedef(tp^.tfuntyp);
- write(space);
- printid(tp^.tsubid^.tsym^.lid);
- writeln('();');
- goto 999
- end;
- write(space);
- etypedef(tp^.tfuntyp);
- writeln;
- printid(tp^.tsubid^.tsym^.lid);
- write('(');
- tq := tp^.tsubpar;
- while tq <> nil do
- begin
- case tq^.tt of
- nvarpar,
- nvalpar:
- begin
- ti := tq^.tidl;
- while ti <> nil do
- begin
- printid(ti^.tsym^.lid);
- ti := ti^.tnext;
- if ti <> nil then
- write(', ');
- end;
- if tq^.tbind^.tt = nconfarr then
- begin
- (* add upper bound parameter *)
- ti := tq^.tbind^.tcindx^.thi;
- write(', ');
- printid(ti^.tsym^.lid)
- end;
- end;
- nparproc,
- nparfunc:
- begin
- ti := tq^.tparid;
- printid(ti^.tsym^.lid)
- end
- end;(* case *)
- tq := tq^.tnext;
- if tq <> nil then
- write(', ');
- end;
- writeln(')');
- increment;
- evar(tp^.tsubpar);
- writeln('{');
- econf(tp^.tsubpar);
- econst(tp^.tsubconst);
- etype(tp^.tsubtype);
- evar(tp^.tsubvar);
-
- if (tp^.tsubconst <> nil) or (tp^.tsubtype <> nil) or
- (tp^.tsubvar <> nil) then
- writeln;
- elabel(tp);
- estmt(tp^.tsubstmt);
- if tp^.tt = nfunc then
- begin
- (* return value in the FIRST variable,
- see renamf() above *)
- indent;
- write('return ');
- printid(tp^.tsubvar^.tidl^.tsym^.lid);
- writeln(';');
- end;
- decrement;
- writeln('}');
- 999:
- writeln;
- tp := tp^.tnext
- end
- end; (* esubr *)
-
- function use(d : predefs) : boolean;
-
- begin
- use := defnams[d]^.lused
- end;
-
- (* Emit code for main program. *)
- procedure eprogram(tp : treeptr);
-
- (* Symbol that sp refers to is renamed if it has *)
- (* been redefined in source program. *)
- procedure capital(sp : symptr);
-
- var tb : toknbuf;
-
- begin
- if sp^.lid^.inref > 1 then
- begin
- gettokn(sp^.lid^.istr, tb);
- tb[1] := uppercase(tb[1]);
- sp^.lid := saveid(tb)
- end
- end;
-
- procedure etextdef;
-
- var tq : treeptr;
-
- begin
- write('typedef ');
- tq := mknode(nfileof);
- tq^.tof := typnods[tchar];
- etypedef(tq);
- writeln(tab1, 'text;')
- end;
-
- begin (* eprogram *)
- if tp^.tsubid <> nil then
- begin
- (* program heading was seen *)
- writeln('/', '*');
- write('** Code derived from program ');
- printid(tp^.tsubid^.tsym^.lid);
- writeln;
- writeln('*', '/');
- writeln(xtern, voidtyp, tab1, 'exit();')
- end;
- if usecase or usesets or
- use(dinput) or use(doutput) or
- use(dwrite) or use(dwriteln) or use(dmessage) or
- use(deof) or use(deoln) or use(dflush) or use(dpage) or
- use(dread) or use(dreadln) or use(dclose) or
- use(dreset) or use(drewrite) or use(dget) or use(dput) then
- begin
- writeln('/', '*');
- writeln('** Definitions for i/o');
- writeln('*', '/');
- writeln(include, '<stdio.h>') (* LIB *)
- end;
- if use(dinput) or use(doutput) or use(dtext) then
- begin
- etextdef;
- if use(dinput) then
- begin
- if tp^.tsubid = nil then
- write(xtern);
- write('text', tab1);
- printid(defnams[dinput]^.lid);
- if tp^.tsubid <> nil then
- write(' = { stdin, 0, 0 }');
- writeln(';')
- end;
- if use(doutput) then
- begin
- if tp^.tsubid = nil then
- write(xtern);
- write('text', tab1);
- printid(defnams[doutput]^.lid);
- if tp^.tsubid <> nil then
- write(' = { stdout, 0, 0 }');
- writeln(';')
- end
- end;
- if use(dinput) or use(dget) or use(dread) or use(dreadln) or
- use(deof) or use(deoln) or use(dreset) or use(drewrite) then
- begin
- writeln(define, 'Fread(x, f) ',
- 'fread((char *)&x, sizeof(x), 1, f)'); (* LIB *)
- writeln(define, 'Get(f) Fread((f).buf, (f).fp)');
- writeln(define, 'Getx(f) (f).init = 1, ',
- '(f).eoln = (((f).buf = ',
- 'fgetc((f).fp)', (* LIB *)
- ') == ', nlchr, ') ? (((f).buf = ',
- spchr, '), 1) : 0');
- writeln(define, 'Getchr(f) (f).buf, Getx(f)')
- end;
- if use(dread) or use(dreadln) then
- begin
- writeln(static, 'FILE', tab1, '*Tmpfil;');
- writeln(static, 'long', tab1, 'Tmplng;');
- writeln(static, 'double', tab1, 'Tmpdbl;');
- writeln(define, 'Fscan(f) (f).init ? ',
- 'ungetc((f).buf, (f).fp)', (* LIB *)
- ' : 0, Tmpfil = (f).fp');
- writeln(define, 'Scan(p, a) ',
- 'Scanck(fscanf(Tmpfil, p, a))'); (* LIB *)
- writeln(voidtyp, tab1, 'Scanck();');
- if use(dreadln) then
- writeln(voidtyp, tab1, 'Getl();');
- end;
- if use(deoln) then
- writeln(define, 'Eoln(f) ((f).eoln ? true : false)');
- if use(deof) then
- writeln(define, 'Eof(f) ',
- '((((f).init == 0) ? (Get(f)) : 0, ',
- '((f).eof ? 1 : ',
- 'feof((f).fp))) ? ', (* LIB *)
- 'true : false)');
- if use(doutput) or use(dput) or
- use(dwrite) or use(dwriteln) or
- use(dreset) or use(drewrite) or use(dclose) then
- begin
- writeln(define, 'Fwrite(x, f) ',
- 'fwrite((char *)&x, sizeof(x), 1, f)');(* LIB *)
- writeln(define, 'Put(f) Fwrite((f).buf, (f).fp)');
- writeln(define, 'Putx(f) (f).eoln = ((f).buf == ',
- nlchr, '), ', voidcast,
- 'fputc((f).buf, (f).fp)'); (* LIB *)
- writeln(define, 'Putchr(c, f) (f).buf = (c), Putx(f)');
- writeln(define, 'Putl(f, v) (f).eoln = v')
- end;
- if use(dreset) or use(drewrite) or use(dclose) then
- writeln(define, 'Finish(f) ((f).out && !(f).eoln) ? ',
- '(Putchr(', nlchr, ', f), 0) : 0, ',
- 'rewind((f).fp)'); (* LIB *)
- if use(dclose) then
- begin
- writeln(define, 'Close(f) (f).init = ',
- '((f).init ? (',
- 'fclose((f).fp), ', (* LIB *)
- '0) : 0), (f).fp = NULL');
- writeln(define, 'Closex(f) (f).init = ',
- '((f).init ? ',
- '(Finish(f), ',
- 'fclose((f).fp), ', (* LIB *)
- '0) : 0), (f).fp = NULL')
- end;
- if use(dreset) then
- begin
- writeln(ifdef, 'READONLY');
- writeln(static, chartyp, tab1, 'Rmode[] = "r";');
- writeln(elsif);
- writeln(static, chartyp, tab1, 'Rmode[] = "r+";');
- writeln(endif);
- writeln(define, 'Reset(f, n) (f).init = ',
- '(f).init ? rewind((f).fp) : ', (* LIB *)
- '(((f).fp = Fopen(n, Rmode)), 1), ',
- '(f).eof = (f).out = 0, Get(f)');
- writeln(define, 'Resetx(f, n) (f).init = ',
- '(f).init ? (Finish(f)) : ',
- '(((f).fp = Fopen(n, Rmode)), 1), ',
- '(f).eof = (f).out = 0, Getx(f)');
- usefopn := true
- end;
- if use(drewrite) then
- begin
- writeln(ifdef, 'WRITEONLY');
- writeln(static, chartyp, tab1, 'Wmode[] = "w";');
- writeln(elsif);
- writeln(static, chartyp, tab1, 'Wmode[] = "w+";');
- writeln(endif);
- writeln(define, 'Rewrite(f, n) (f).init = ',
- '(f).init ? rewind((f).fp) : ', (* LIB *)
- '(((f).fp = Fopen(n, Wmode)), 1), ',
- '(f).out = (f).eof = 1');
- writeln(define, 'Rewritex(f, n) (f).init = ',
- '(f).init ? (Finish(f)) : ',
- '(((f).fp = Fopen(n, Wmode)), 1), ',
- '(f).out = (f).eof = (f).eoln = 1');
- usefopn := true
- end;
- if usefopn then
- begin
- writeln('FILE *Fopen();');
- writeln(define, 'MAXFILENAME 256')
- end;
- if usecase or usejmps then
- begin
- writeln('/', '*');
- writeln('** Definitions for case-statements');
- writeln('** and for non-local gotos');
- writeln('*', '/');
- writeln(define, 'Line __LINE__');
- writeln(voidtyp, tab1, 'Caseerror();')
- end;
- if usejmps then
- begin
- writeln(include, '<setjmp.h>'); (* LIB *)
- writeln(static, 'struct Jb { jmp_buf', tab1, 'jb; } J[',
- (maxlevel+1):1, '];')
- end;
- if use(dinteger) or use(dmaxint) or
- use(dboolean) or use(dfalse) or use(dtrue) or
- use(deof) or use(deoln) or use(dexp) or
- use(dln) or use(dsqr) or use(dsin) or
- use(dcos) or use(dtan) or use(darctan) or
- use(dsqrt) or use(dreal) then
- begin
- writeln('/', '*');
- writeln('** Definitions for standard types');
- writeln('*', '/')
- end;
- if usecomp then
- begin
- writeln(xtern, inttyp, ' strncmp();'); (* LIB *)
- writeln(define,
- 'Cmpstr(x, y) ',
- 'strncmp((x), (y), sizeof(x))') (* LIB *)
- end;
- if use(dboolean) or use(dfalse) or use(dtrue) or
- use(deof) or use(deoln) or usesets then
- begin
- capital(defnams[dboolean]);
- write(typdef, chartyp, tab1);
- printid(defnams[dboolean]^.lid);
- writeln(';');
- capital(defnams[dfalse]);
- write(define);
- printid(defnams[dfalse]^.lid);
- write(' (');
- printid(defnams[dboolean]^.lid);
- writeln(')0');
- capital(defnams[dtrue]);
- write(define);
- printid(defnams[dtrue]^.lid);
- write(' (');
- printid(defnams[dboolean]^.lid);
- writeln(')1');
- writeln(xtern, chartyp, tab1, '*Bools[];')
- end;
- capital(defnams[dinteger]);
- if use(dinteger) then
- begin
- write(typdef, inttyp, tab1);
- printid(defnams[dinteger]^.lid);
- writeln(';')
- end;
- if use(dmaxint) then
- writeln(define, 'maxint', tab1, maxint:1);
- capital(defnams[dreal]);
- if use(dreal) then
- begin
- write(typdef, realtyp, tab1);
- printid(defnams[dreal]^.lid);
- writeln(';')
- end;
- if use(dexp) then
- writeln(xtern, doubletyp, ' exp();'); (* LIB *)
- if use(dln) then
- writeln(xtern, doubletyp, ' log();'); (* LIB *)
- if use(dsqr) then
- writeln(xtern, doubletyp, ' pow();'); (* LIB *)
- if use(dsin) then
- writeln(xtern, doubletyp, ' sin();'); (* LIB *)
- if use(dcos) then
- writeln(xtern, doubletyp, ' cos();'); (* LIB *)
- if use(dtan) then
- writeln(xtern, doubletyp, ' tan();'); (* LIB *)
- if use(darctan) then
- writeln(xtern, doubletyp, ' atan();'); (* LIB *)
- if use(dsqrt) then
- writeln(xtern, doubletyp, ' sqrt();'); (* LIB *)
- if use(dabs) and use(dreal) then
- writeln(xtern, doubletyp, ' fabs();'); (* LIB *)
- if use(dhalt) then
- writeln(xtern, voidtyp, ' abort();'); (* LIB *)
- if use(dnew) or usenilp then
- begin
- writeln('/', '*');
- writeln('** Definitions for pointers');
- writeln('*', '/');
- end;
- if use(dnew) then
- begin
- writeln(ifndef, 'Unionoffs');
- writeln(define, 'Unionoffs(p, m) ',
- '(((long)(&(p)->m))-((long)(p)))'); (* CPU *)
- writeln(endif)
- end;
- if usenilp then
- writeln(define, 'NIL 0'); (* CPU *)
- if use(dnew) then
- writeln(xtern, chartyp, ' *malloc();'); (* LIB *)
- if use(ddispose) then
- writeln(xtern, voidtyp, ' free();'); (* LIB *)
- if usesets then
- begin
- writeln('/', '*');
- writeln('** Definitions for set-operations');
- writeln('*', '/');
- writeln(define, 'Claimset() ',
- voidcast, 'Currset(0, (', setptyp, ')0)');
- writeln(define, 'Newset() ',
- 'Currset(1, (', setptyp, ')0)');
- writeln(define, 'Saveset(s) Currset(2, s)');
- writeln(define, 'setbits ', setbits:1);
- writeln(typdef, wordtype, tab1, setwtyp, ';');
- writeln(typdef, setwtyp, ' *', tab1, setptyp, ';');
- printid(defnams[dboolean]^.lid);
- writeln(tab1, 'Member(), Le(), Ge(), Eq(), Ne();');
- writeln(setptyp, tab1, 'Union(), Diff();');
- writeln(setptyp, tab1, 'Insmem(), Mksubr();');
- writeln(setptyp, tab1, 'Currset(), Inter();');
- writeln(static, setptyp, tab1, 'Tmpset;');
- writeln(xtern, setptyp, tab1, 'Conset[];');
- writeln(voidtyp, tab1, 'Setncpy();')
- end;
- writeln(xtern, chartyp, ' *strncpy();'); (* LIB *)
- if use(dargc) or use(dargv) then
- begin
- writeln('/', '*');
- writeln('** Definitions for argv-operations');
- writeln('*', '/');
- writeln(inttyp, tab1, 'argc;'); (* OS *)
- writeln(chartyp, tab1, '**argv;');
- writeln(' void');
- writeln('Argvgt(n, cp, l)');
- writeln(inttyp, tab1, 'n;');
- writeln(registr, inttyp, tab1, 'l;');
- writeln(registr, chartyp, tab1, '*cp;');
- writeln('{');
- writeln(tab1, registr, chartyp, tab1, '*sp;');
- writeln;
- writeln(tab1, 'for (sp = argv[n]; l > 0 && *sp; l--)');
- writeln(tab2, '*cp++ = *sp++;');
- writeln(tab1, 'while (l-- > 0)');
- writeln(tab2, '*cp++ = ', spchr, ';');
- writeln('}');
- end;
- if (tp^.tsubconst <> nil) or (tp^.tsubtype<> nil) or
- (tp^.tsubvar <> nil) or (tp^.tsubsub <> nil) then
- begin
- writeln('/', '*');
- writeln('** Start of program definitions');
- writeln('*', '/');
- end;
- econst(tp^.tsubconst);
- etype(tp^.tsubtype);
- evar(tp^.tsubvar);
- if tp^.tsubsub <> nil then
- writeln;
- esubr(tp^.tsubsub);
- if tp^.tsubid <> nil then
- begin
- (* program heading was seen *)
- writeln('/', '*');
- writeln('** Start of program code');
- writeln('*', '/');
- if use(dargc) or use(dargv) then
- begin
- writeln('main(_ac, _av)'); (* OS *)
- writeln(inttyp, tab1, '_ac;');
- writeln(chartyp, tab1, '*_av[];');
- writeln('{');
- writeln;
- writeln(tab1, 'argc = _ac;');
- writeln(tab1, 'argv = _av;')
- end
- else begin
- writeln('main()');
- writeln('{')
- end;
- increment;
- elabel(tp);
- estmt(tp^.tsubstmt);
- indent;
- writeln('exit(0);');
- decrement;
- writeln('}');
- writeln('/', '*');
- writeln('** End of program code');
- writeln('*', '/')
- end
- end; (* eprogram *)
-
- (* Emit definitions for constant sets *)
- procedure econset(tp : treeptr; len : integer);
-
- var i : integer;
-
- function size(tp : treeptr) : integer;
-
- var r, x : integer;
-
- begin
- r := 0;
- while tp <> nil do
- begin
- if tp^.tt = nrange then
- x := cvalof(tp^.texpr)
- else if tp^.tt = nempty then
- x := 0
- else
- x := cvalof(tp);
- if x > r then
- r := x;
- tp := tp^.tnext
- end;
- size := csetwords(r+1)
- end;
-
- (* Emit bits in a constant set *)
- procedure ebits(tp : treeptr);
-
- type bitset = set of 0 .. setbits;
-
- var sets : array [ 0 .. maxsetrange ] of bitset;
- s, m, n : integer;
-
- procedure eword(s : bitset);
-
- const bitshex = 4; (* nr of bits in a hex-digit *)
-
- var n, i : integer;
- x : 0 .. setbits;
-
- begin
- n := 0;
- while n <= setbits do
- n := n + bitshex;
- n := n - bitshex;
- while n >= 0 do
- begin
- (* compute 1 hexdigit *)
- x := 0;
- for i := 0 to bitshex - 1 do
- if (n + i) in s then
- case i of
- 0: x := x + 1;
- 1: x := x + 2;
- 2: x := x + 4;
- 3: x := x + 8
- end;(* case *)
- (* print it *)
- write(hexdig[x]);
- n := n - bitshex
- end
- end;
-
- begin
- s := size(tp);
- for n := 0 to s - 1 do
- sets[n] := [];
- while tp <> nil do
- begin
- if tp^.tt = nrange then
- for m := cvalof(tp^.texpl) to
- cvalof(tp^.texpr) do
- begin
- n := m div (setbits+1);
- sets[n] := sets[n] +
- [m mod (setbits+1)]
- end
- else if tp^.tt <> nempty then
- begin
- m := cvalof(tp);
- n := m div (setbits+1);
- sets[n] := sets[n] +
- [m mod (setbits+1)]
- end;
- tp := tp^.tnext
- end;
- write(tab1, s:1);
- for n := 0 to s - 1 do
- begin
- write(',');
- if n mod 6 = 0 then
- writeln;
- write(tab1, '0x');
- eword(sets[n]);
- end;
- writeln
- end;
-
- begin
- i := 0;
- while tp <> nil do
- begin
- writeln(static, setwtyp, tab1, 'Q', i:1, '[] = {');
- ebits(tp^.texps);
- writeln('};');
- i := i + 1;
- tp := tp^.tnext
- end;
- writeln(static, setwtyp, tab1, '*Conset[] = {');
- for i := len - 1 downto 1 do
- begin
- write(tab1, 'Q', i:1, ',');
- if i mod 6 = 5 then
- writeln
- end;
- writeln(tab1, 'Q0');
- writeln('};');
- end;
-
- begin (* emit *)
- indnt := 0;
- varno := 0;
- conflag := false;
- setused := false;
- dropset := false;
- doarrow := 0;
- eprogram(top);
- if usebool then
- writeln(chartyp, tab1, '*Bools[] = { "false", "true" };');
- if usescan then
- begin
- writeln;
- writeln(static, voidtyp);
- writeln('Scanck(n)');
- writeln(inttyp, tab1, 'n;');
- writeln('{');
- writeln(tab1, 'if (n != 1) {');
- writeln(tab2, voidcast, 'fprintf(stderr, "Bad input\n");');
- writeln(tab2, 'exit(1);');
- writeln(tab1, '}');
- writeln('}')
- end;
- if usegetl then
- begin
- writeln;
- writeln(static, voidtyp);
- writeln('Getl(f)');
- writeln(' text', tab1, '*f;');
- writeln('{');
- writeln(tab1, 'while (f->eoln == 0)');
- writeln(tab2, 'Getx(*f);');
- writeln(tab1, 'Getx(*f);');
- writeln('}')
- end;
- if usefopn then
- begin
- writeln;
- writeln(static, 'FILE *');
- writeln('Fopen(n, m)');
- writeln(chartyp, tab1, '*n, *m;');
- writeln('{');
- writeln(tab1, 'FILE', tab2, '*f;');
- writeln(tab1, registr, chartyp, tab1, '*s;');
- writeln(tab1, static, chartyp, tab1, 'ch = ',
- quote, 'A', quote, ';');
- writeln(tab1, static, chartyp, tab1, 'tmp[MAXFILENAME];');
- writeln(tab1, xtern , inttyp, tab1, 'unlink();'); (* OS *)
- writeln;
- writeln(tab1, 'if (n == NULL)');
- writeln(tab2, 'sprintf(tmp, ', tmpfilename, 'ch++);');
- writeln(tab1, 'else {');
- writeln(tab2, 'strncpy(tmp, n, sizeof(tmp));');
- writeln(tab2, 'for (s = &tmp[sizeof(tmp)-1]; *s == ',
- spchr, ' || *s == ', nulchr, '; )');
- writeln(tab3, '*s-- = ', nulchr, ';');
- writeln(tab2, 'if (tmp[sizeof(tmp)-1]) {');
- writeln(tab3, voidcast, 'fprintf(stderr, "Too long filename ',
- quote, '%s', quote, '\n", n);');
- writeln(tab3, 'exit(1);');
- writeln(tab2, '}');
- writeln(tab1, '}');
- writeln(tab1, 's = tmp;');
- writeln(tab1, 'if ((f = fopen(s, m)) == NULL) {');
- writeln(tab2, voidcast,
- 'fprintf(stderr, "Cannot open: %s\n", s);');
- writeln(tab2, 'exit(1);');
- writeln(tab1, '}');
- writeln(tab1, 'if (n == NULL)');
- writeln(tab2, 'unlink(tmp);'); (* OS *)
- writeln(tab1, 'return (f);');
- writeln('}');
- writeln(xtern, inttyp, tab1, 'rewind();')
- end;
- if setcnt > 0 then
- econset(setlst, setcnt);
- if useunion then
- begin
- writeln;
- writeln(static, setptyp);
- writeln('Union(p1, p2)');
- writeln(tab1, registr, setptyp, tab1, 'p1, p2;');
- writeln('{');
- writeln(tab1, registr, inttyp, tab2, 'i, j, k;');
- writeln(tab1, registr, setptyp, tab2, 'sp = Newset(),');
- writeln(tab4, 'p3 = sp;');
- writeln;
- writeln(tab1, 'j = *p1;');
- writeln(tab1, '*p3 = j;');
- writeln(tab1, 'if (j > *p2)');
- writeln(tab2, 'j = *p2;');
- writeln(tab1, 'else');
- writeln(tab2, '*p3 = *p2;');
- writeln(tab1, 'k = *p1 - *p2;');
- writeln(tab1, 'p1++, p2++, p3++;');
- writeln(tab1, 'for (i = 0; i < j; i++)');
- writeln(tab2, '*p3++ = (*p1++ | *p2++);');
- writeln(tab1, 'while (k > 0) {');
- writeln(tab2, '*p3++ = *p1++;');
- writeln(tab2, 'k--;');
- writeln(tab1, '}');
- writeln(tab1, 'while (k < 0) {');
- writeln(tab2, '*p3++ = *p2++;');
- writeln(tab2, 'k++;');
- writeln(tab1, '}');
- writeln(tab1, 'return (Saveset(sp));');
- writeln('}')
- end;
- if usediff then
- begin
- writeln;
- writeln(static, setptyp);
- writeln('Diff(p1, p2)');
- writeln(tab1, registr, setptyp, tab1, 'p1, p2;');
- writeln('{');
- writeln(tab1, registr, inttyp, tab2, 'i, j, k;');
- writeln(tab1, registr, setptyp, tab2, 'sp = Newset(),');
- writeln(tab4, 'p3 = sp;');
- writeln;
- writeln(tab1, 'j = *p1;');
- writeln(tab1, '*p3 = j;');
- writeln(tab1, 'if (j > *p2)');
- writeln(tab2, 'j = *p2;');
- writeln(tab1, 'k = *p1 - *p2;');
- writeln(tab1, 'p1++, p2++, p3++;');
- writeln(tab1, 'for (i = 0; i < j; i++)');
- writeln(tab2, '*p3++ = (*p1++ & ~ (*p2++));');
- writeln(tab1, 'while (k > 0) {');
- writeln(tab2, '*p3++ = *p1++;');
- writeln(tab2, 'k--;');
- writeln(tab1, '}');
- writeln(tab1, 'return (Saveset(sp));');
- writeln('}')
- end;
- if useintr then
- begin
- writeln;
- writeln(static, setptyp);
- writeln('Inter(p1, p2)');
- writeln(tab1, registr, setptyp, tab1, 'p1, p2;');
- writeln('{');
- writeln(tab1, registr, inttyp, tab2, 'i, j, k;');
- writeln(tab1, registr, setptyp, tab2, 'sp = Newset(),');
- writeln(tab4, 'p3 = sp;');
- writeln;
- writeln(tab1, 'if ((j = *p1) > *p2)');
- writeln(tab2, 'j = *p2;');
- writeln(tab1, '*p3 = j;');
- writeln(tab1, 'p1++, p2++, p3++;');
- writeln(tab1, 'for (i = 0; i < j; i++)');
- writeln(tab2, '*p3++ = (*p1++ & *p2++);');
- writeln(tab1, 'return (Saveset(sp));');
- writeln('}')
- end;
- if usememb then
- begin
- writeln;
- write(static);
- printid(defnams[dboolean]^.lid);
- writeln;
- writeln('Member(m, sp)');
- writeln(tab1, registr, usigned, inttyp, tab1, 'm;');
- writeln(tab1, registr, setptyp, tab1, 'sp;');
- writeln('{');
- writeln(tab1, registr, usigned, inttyp,
- tab1, 'i = m / (setbits+1) + 1;');
- writeln;
- writeln(tab1, 'if ((i <= *sp) &&',
- ' (sp[i] & (1 << (m % (setbits+1)))))');
- write(tab2, 'return (');
- printid(defnams[dtrue]^.lid);
- writeln(');');
- write(tab1, 'return (');
- printid(defnams[dfalse]^.lid);
- writeln(');');
- writeln('}')
- end;
- if useseq or usesne then
- begin
- writeln;
- write(static);
- printid(defnams[dboolean]^.lid);
- writeln;
- writeln('Eq(p1, p2)');
- writeln(tab1, registr, setptyp, tab1, 'p1, p2;');
- writeln('{');
- writeln(tab1, registr, inttyp, tab1, 'i, j;');
- writeln;
- writeln(tab1, 'i = *p1++;');
- writeln(tab1, 'j = *p2++;');
- writeln(tab1, 'while (i != 0 && j != 0) {');
- writeln(tab2, 'if (*p1++ != *p2++)');
- write(tab3, 'return (');
- printid(defnams[dfalse]^.lid);
- writeln(');');
- writeln(tab2, 'i--, j--;');
- writeln(tab1, '}');
- writeln(tab1, 'while (i != 0) {');
- writeln(tab2, 'if (*p1++ != 0)');
- write(tab3, 'return (');
- printid(defnams[dfalse]^.lid);
- writeln(');');
- writeln(tab2, 'i--;');
- writeln(tab1, '}');
- writeln(tab1, 'while (j != 0) {');
- writeln(tab2, 'if (*p2++ != 0)');
- write(tab3, 'return (');
- printid(defnams[dfalse]^.lid);
- writeln(');');
- writeln(tab2, 'j--;');
- writeln(tab1, '}');
- write(tab1, 'return (');
- printid(defnams[dtrue]^.lid);
- writeln(');');
- writeln('}')
- end;
- if usesne then
- begin
- writeln;
- write(static);
- printid(defnams[dboolean]^.lid);
- writeln;
- writeln('Ne(p1, p2)');
- writeln(tab1, registr, setptyp, tab1, 'p1, p2;');
- writeln('{');
- write(tab1, 'return (!Eq(p1, p2));');
- writeln('}')
- end;
- if usesle then
- begin
- writeln;
- write(static);
- printid(defnams[dboolean]^.lid);
- writeln;
- writeln('Le(p1, p2)');
- writeln(tab1, registr, setptyp, tab1, 'p1, p2;');
- writeln('{');
- writeln(tab1, registr, inttyp, tab1, 'i, j;');
- writeln;
- writeln(tab1, 'i = *p1++;');
- writeln(tab1, 'j = *p2++;');
- writeln(tab1, 'while (i != 0 && j != 0) {');
- writeln(tab2, 'if ((*p1++ & ~ *p2++) != 0)');
- write(tab3, 'return (');
- printid(defnams[dfalse]^.lid);
- writeln(');');
- writeln(tab2, 'i--, j--;');
- writeln(tab1, '}');
- writeln(tab1, 'while (i != 0) {');
- writeln(tab2, 'if (*p1++ != 0)');
- write(tab3, 'return (');
- printid(defnams[dfalse]^.lid);
- writeln(');');
- writeln(tab2, 'i--;');
- writeln(tab1, '}');
- write(tab1, 'return (');
- printid(defnams[dtrue]^.lid);
- writeln(');');
- writeln('}')
- end;
- if usesge then
- begin
- writeln;
- write(static);
- printid(defnams[dboolean]^.lid);
- writeln;
- writeln('Ge(p1, p2)');
- writeln(tab1, registr, setptyp, tab1, 'p1, p2;');
- writeln('{');
- writeln(tab1, registr, inttyp, tab1, 'i, j;');
- writeln;
- writeln(tab1, 'i = *p1++;');
- writeln(tab1, 'j = *p2++;');
- writeln(tab1, 'while (i != 0 && j != 0) {');
- writeln(tab2, 'if ((*p2++ & ~ *p1++) != 0)');
- writeln(tab3, 'return (false);');
- writeln(tab2, 'i--, j--;');
- writeln(tab1, '}');
- writeln(tab1, 'while (j != 0) {');
- writeln(tab2, 'if (*p2++ != 0)');
- write(tab3, 'return (');
- printid(defnams[dfalse]^.lid);
- writeln(');');
- writeln(tab2, 'j--;');
- writeln(tab1, '}');
- write(tab1, 'return (');
- printid(defnams[dtrue]^.lid);
- writeln(');');
- writeln('}')
- end;
- if usemksub then
- begin
- writeln;
- writeln(static, setptyp);
- writeln('Mksubr(lo, hi, sp)');
- writeln(tab1, registr, usigned, inttyp, tab1, 'lo, hi;');
- writeln(tab1, registr, setptyp, tab1, 'sp;');
- writeln('{');
- writeln(tab1, registr, inttyp, tab1, 'i, k;');
- writeln;
- writeln(tab1, 'if (hi < lo)');
- writeln(tab2, 'return (sp);');
- writeln(tab1, 'i = hi / (setbits+1) + 1;');
- writeln(tab1, 'for (k = *sp + 1; k <= i; k++)');
- writeln(tab2, 'sp[k] = 0;');
- writeln(tab1, 'if (*sp < i)');
- writeln(tab2, '*sp = i;');
- writeln(tab1, 'for (k = lo; k <= hi; k++)');
- writeln(tab2, 'sp[k / (setbits+1) + 1] |= ',
- '(1 << (k % (setbits+1)));');
- writeln(tab1, 'return (sp);');
- writeln('}')
- end;
- if useins then
- begin
- writeln;
- writeln(static, setptyp);
- writeln('Insmem(m, sp)');
- writeln(tab1, registr, usigned, inttyp, tab1, 'm;');
- writeln(tab1, registr, setptyp, tab1, 'sp;');
- writeln('{');
- writeln(tab1, registr, inttyp, tab1, 'i,');
- writeln(tab3, tab1, 'j = m / (setbits+1) + 1;');
- writeln;
- writeln(tab1, 'if (*sp < j)');
- writeln(tab2, 'for (i = *sp + 1, *sp = j; i <= *sp; i++)');
- writeln(tab3, 'sp[i] = 0;');
- writeln(tab1, 'sp[j] |= (1 << (m % (setbits+1)));');
- writeln(tab1, 'return (sp);');
- writeln('}')
- end;
- if usesets then
- begin
- writeln;
- writeln(ifndef, 'SETSPACE');
- writeln(define, 'SETSPACE 256');
- writeln(endif);
- writeln(static, setptyp);
- writeln('Currset(n,sp)');
- writeln(tab1, inttyp, tab1, 'n;');
- writeln(tab1, setptyp, tab1, 'sp;');
- writeln('{');
- writeln(tab1, static, setwtyp, tab1, 'Space[SETSPACE];');
- writeln(tab1, static, setptyp, tab1, 'Top = Space;');
- writeln;
- writeln(tab1, 'switch (n) {');
- writeln(tab1, ' case 0:');
- writeln(tab2, 'Top = Space;');
- writeln(tab2, 'return (0);');
- writeln(tab1, ' case 1:');
- writeln(tab2, 'if (&Space[SETSPACE] - Top <= ',
- maxsetrange:1, ') {');
- writeln(tab3,
- voidcast, 'fprintf(stderr, "Set-space exhausted\n");');
- writeln(tab3, 'exit(1);');
- writeln(tab2, '}');
- writeln(tab2, '*Top = 0;');
- writeln(tab2, 'return (Top);');
- writeln(tab1, ' case 2:');
- writeln(tab2, 'if (Top <= &sp[*sp])');
- writeln(tab3, 'Top = &sp[*sp + 1];');
- writeln(tab2, 'return (sp);');
- writeln(tab1, '}');
- writeln(tab1, '/', '* NOTREACHED *', '/');
- writeln('}')
- end;
- if usescpy then
- begin
- writeln;
- writeln(static, voidtyp);
- writeln('Setncpy(S1, S2, N)');
- writeln(tab1, registr, setptyp, tab1, 'S1, S2;');
- writeln(tab1, registr, usigned, inttyp, tab1, 'N;');
- writeln('{');
- writeln(tab1, registr, usigned, inttyp, tab1, 'm;');
- writeln;
- writeln(tab1, 'N /= sizeof(', setwtyp, ');');
- writeln(tab1, '*S1++ = --N;');
- writeln(tab1, 'm = *S2++;');
- writeln(tab1, 'while (m != 0 && N != 0) {');
- writeln(tab2, '*S1++ = *S2++;');
- writeln(tab2, '--N;');
- writeln(tab2, '--m;');
- writeln(tab1, '}');
- writeln(tab1, 'while (N-- != 0)');
- writeln(tab2, '*S1++ = 0;');
- writeln('}')
- end;
- if usecase then
- begin
- writeln;
- writeln(static, voidtyp);
- writeln('Caseerror(n)');
- writeln(tab1, inttyp, tab1, 'n;');
- writeln('{');
- writeln(tab1, voidcast,
- 'fprintf(stderr, "Missing case limb: line %d\n", n);');
- writeln(tab1, 'exit(1);');
- writeln('}')
- end;
- if usemax then
- begin
- writeln;
- writeln(static, inttyp);
- writeln('Max(m, n)');
- writeln(tab1, inttyp, tab1, 'm, n;');
- writeln('{');
- writeln(tab1, 'if (m > n)');
- writeln(tab2, 'return (m);');
- writeln(tab1, 'return (n);');
- writeln('}')
- end;
- if use(dtrunc) then
- begin
- writeln(static, inttyp);
- writeln('Trunc(f)');
- printid(defnams[dreal]^.lid);
- writeln(tab1, 'f;');
- writeln('{');
- writeln(tab1, 'return f;');
- writeln('}')
- end;
- if use(dround) then
- begin
- writeln(static, inttyp);
- writeln('Round(f)');
- printid(defnams[dreal]^.lid);
- writeln(tab1, 'f;');
- writeln('{');
- writeln(tab1, xtern, doubletyp, ' floor();'); (* LIB *)
- writeln(tab1,
- 'return floor(', dblcast, '(0.5+f));'); (* LIB *)
- writeln('}')
- end
- end; (* emit *)
-
- (* Initialize all global structures used in translator. *)
- procedure initialize;
-
- var s : hashtyp;
- t : pretyps;
- d : predefs;
-
- (* Define names in ctable. *)
- procedure defname(cn : cnames; str : keyword);
-
- label 999;
-
- var w : toknbuf;
- i : toknidx;
-
- begin
- unpack(str, w, 1);
- for i := 1 to keywordlen do
- if w[i] = space then
- begin
- w[i] := chr(null);
- goto 999
- end;
- w[keywordlen+1] := chr(null);
- 999:
- ctable[cn] := saveid(w)
- end;
-
- (* Define predefined identifiers. *)
- procedure defid(nt : treetyp; did : predefs; str : keyword);
-
- label 999;
-
- var w : toknbuf;
- i : toknidx;
- tp, tq,
- tv : treeptr;
-
- begin
- for i := 1 to keywordlen do
- if str[i] = space then
- begin
- w[i] := chr(null);
- goto 999
- end
- else
- w[i] := str[i];
- w[keywordlen+1] := chr(null);
- 999:
- tp := newid(saveid(w));
- defnams[did] := tp^.tsym;
- if nt in [ntype, nfunc, nproc] then
- begin
- (* predefined types, procedures and functions
- are marked with a particular node *)
- tv := mknode(npredef);
- tv^.tdef := did;
- tv^.tobtyp := tnone
- end
- else
- tv := nil; (* predefined constants and variables will
- eventually be bound to something *)
- case nt of
- nscalar:
- begin
- tv := mknode(nscalar);
- tv^.tscalid := nil;
- tq := mknode(ntype);
- tq^.tbind := tv;
- tq^.tidl := tp;
- tp := tq
- end;
- nconst,
- ntype,
- nfield,
- nvar:
- begin
- tq := mknode(nt);
- tq^.tbind := tv;
- tq^.tidl := tp;
- tq^.tattr := anone;
- tp := tq
- end;
- nfunc,
- nproc:
- begin
- tq := mknode(nt);
- tq^.tsubid := tp;
- tq^.tsubstmt := tv;
- tq^.tfuntyp := nil;
- tq^.tsubpar := nil;
- tq^.tsublab := nil;
- tq^.tsubconst := nil;
- tq^.tsubtype := nil;
- tq^.tsubvar := nil;
- tq^.tsubsub := nil;
- tq^.tscope := nil;
- tq^.tstat := 0;
- tp := tq
- end;
- nid:
- end;(* case *)
- deftab[did] := tp
- end; (* defid *)
-
- (* Define keywords. *)
- procedure defkey(s : symtyp; w : keyword);
-
- var i : 1 .. keywordlen;
-
- begin
- for i := 1 to keywordlen do
- if w[i] = space then
- w[i] := chr(null);
- (* relies on symtyp being sorted *)
- with keytab[ord(s)] do
- begin
- wrd := w;
- sym := s
- end;
- end;
-
- procedure fixinit(i : strindx);
-
- var t : toknbuf;
-
- begin
- gettokn(i, t);
- t[1] := 'i';
- puttokn(i, t);
- end;
-
- (* Add a cpu word type description. *)
- (* Parameters lo and hi gives the range of a machine- *)
- (* dependant integer type. Parameter str gives the corres- *)
- (* ponding C-language type-name. *)
- procedure defmach(lo, hi : integer; str : machdefstr);
-
- label 999;
-
- var i : toknidx;
- w : toknbuf;
-
- begin
- unpack(str, w, 1);
- if w[machdeflen] <> space then
- error(ebadmach);
- for i := machdeflen - 1 downto 1 do
- if w[i] <> space then
- begin
- w[i+1] := chr(null);
- goto 999
- end;
- error(ebadmach);
- 999:
- if nmachdefs >= maxmachdefs then
- error(emanymachs);
- nmachdefs := nmachdefs + 1;
- with machdefs[nmachdefs] do
- begin
- lolim := lo;
- hilim := hi;
- typstr := savestr(w)
- end
- end;
-
- procedure initstrstore;
-
- var i : strbcnt;
-
- begin
- for i := 1 to maxblkcnt do
- strstor[i] := nil;
- new(strstor[0]);
- strstor[0]^[0] := chr(null);
- strfree := 1;
- strleft := maxstrblk
- end;
-
- begin (* initialize *)
- lineno := 1;
- colno := 0;
-
- initstrstore;
-
- setlst := nil;
- setcnt := 0;
- hexdig := '0123456789ABCDEF';
-
- symtab := nil;
- statlvl := 0;
- maxlevel := -1;
- enterscope(nil);
- varno:= 0;
-
- usenilp := false;
-
- usesets := false;
- useunion := false;
- usediff := false;
- usemksub := false;
- useintr := false;
- usesge := false;
- usesle := false;
- usesne := false;
- useseq := false;
- usememb := false;
- useins := false;
- usescpy := false;
- usefopn := false;
- usescan := false;
- usegetl := false;
-
- usecase := false;
- usejmps := false;
-
- usebool := false;
-
- usecomp := false;
- usemax := false;
-
- for s := 0 to hashmax do
- idtab[s] := nil;
- for d := dabs to dztring do
- begin
- deftab[d] := nil;
- defnams[d] := nil
- end;
-
- (* Pascal keywords *)
- defkey(sand, 'and ');
- defkey(sarray, 'array ');
- defkey(sbegin, 'begin ');
- defkey(scase, 'case ');
- defkey(sconst, 'const ');
- defkey(sdiv, 'div ');
- defkey(sdo, 'do ');
- defkey(sdownto, 'downto ');
- defkey(selse, 'else ');
- defkey(send, 'end ');
- defkey(sextern, externsym); (* non-standard *)
- defkey(sfile, 'file ');
- defkey(sfor, 'for ');
- defkey(sforward,'forward ');
- defkey(sfunc, 'function ');
- defkey(sgoto, 'goto ');
- defkey(sif, 'if ');
- defkey(sinn, 'in ');
- defkey(slabel, 'label ');
- defkey(smod, 'mod ');
- defkey(snil, 'nil ');
- defkey(snot, 'not ');
- defkey(sof, 'of ');
- defkey(sor, 'or ');
- defkey(sother, othersym); (* non-standard *)
- defkey(spacked, 'packed ');
- defkey(sproc, 'procedure ');
- defkey(spgm, 'program ');
- defkey(srecord, 'record ');
- defkey(srepeat, 'repeat ');
- defkey(sset, 'set ');
- defkey(sthen, 'then ');
- defkey(sto, 'to ');
- defkey(stype, 'type ');
- defkey(suntil, 'until ');
- defkey(svar, 'var ');
- defkey(swhile, 'while ');
- defkey(swith, 'with ');
- defkey(seof, dummysym); (* dummy entry *)
-
- (* C language operator priorities *)
- cprio[nformat] := 0;
- cprio[nrange] := 0;
- cprio[nin] := 0;
- cprio[nset] := 0;
- cprio[nassign] := 0;
- cprio[nor] := 1;
- cprio[nand] := 2;
- cprio[neq] := 3;
- cprio[nne] := 3;
- cprio[nlt] := 3;
- cprio[nle] := 3;
- cprio[ngt] := 3;
- cprio[nge] := 3;
- cprio[nplus] := 4;
- cprio[nminus] := 4;
- cprio[nmul] := 5;
- cprio[ndiv] := 5;
- cprio[nmod] := 5;
- cprio[nquot] := 5;
- cprio[nnot] := 6;
- cprio[numinus] := 6;
- cprio[nuplus] := 7;
- cprio[nindex] := 7;
- cprio[nselect] := 7;
- cprio[nderef] := 7;
- cprio[ncall] := 7;
- cprio[nid] := 7;
- cprio[nchar] := 7;
- cprio[ninteger] := 7;
- cprio[nreal] := 7;
- cprio[nstring] := 7;
- cprio[nnil] := 7;
-
- (* Pascal language operator priorities *)
- pprio[nassign] := 0;
- pprio[nformat] := 0;
- pprio[nrange] := 1;
- pprio[nin] := 1;
- pprio[neq] := 1;
- pprio[nne] := 1;
- pprio[nlt] := 1;
- pprio[nle] := 1;
- pprio[ngt] := 1;
- pprio[nge] := 1;
- pprio[nor] := 2;
- pprio[nplus] := 2;
- pprio[nminus] := 2;
- pprio[nand] := 3;
- pprio[nmul] := 3;
- pprio[ndiv] := 3;
- pprio[nmod] := 3;
- pprio[nquot] := 3;
- pprio[nnot] := 4;
- pprio[numinus] := 4;
- pprio[nuplus] := 5;
- pprio[nset] := 6;
- pprio[nindex] := 6;
- pprio[nselect] := 6;
- pprio[nderef] := 6;
- pprio[ncall] := 6;
- pprio[nid] := 6;
- pprio[nchar] := 6;
- pprio[ninteger] := 6;
- pprio[nreal] := 6;
- pprio[nstring] := 6;
- pprio[nnil] := 6;
-
- (* table of C keywords/functions (which Pascal doesn't know about) *)
- defname(cabort, 'abort '); (* OS *)
- defname(cbreak, 'break ');
- defname(ccontinue, 'continue ');
- defname(cdefine, 'define ');
- defname(cdefault, 'default ');
- defname(cdouble, 'double ');
- defname(cedata, 'edata '); (* OS *)
- defname(cenum, 'enum ');
- defname(cetext, 'etext '); (* OS *)
- defname(cextern, 'extern ');
- defname(cfclose, 'fclose '); (* LIB *)
- defname(cfflush, 'fflush '); (* LIB *)
- defname(cfgetc, 'fgetc '); (* LIB *)
- defname(cfloat, 'float ');
- defname(cfloor, 'floor '); (* OS *)
- defname(cfprintf, 'fprintf '); (* LIB *)
- defname(cfputc, 'fputc '); (* LIB *)
- defname(cfread, 'fread '); (* LIB *)
- defname(cfscanf, 'fscanf '); (* LIB *)
- defname(cfwrite, 'fwrite '); (* LIB *)
- defname(cgetc, 'getc '); (* OS *)
- defname(cgetpid, 'getpid '); (* OS *)
- defname(cint, 'int ');
- defname(cinclude, 'include ');
- defname(clong, 'long ');
- defname(clog, 'log '); (* OS *)
- defname(cmain, 'main ');
- defname(cmalloc, 'malloc '); (* LIB *)
- defname(cprintf, 'printf '); (* LIB *)
- defname(cpower, 'pow '); (* OS *)
- defname(cputc, 'putc '); (* LIB *)
- defname(cread, 'read '); (* OS *)
- defname(creturn, 'return ');
- defname(cregister, 'register ');
- defname(crewind, 'rewind '); (* LIB *)
- defname(cscanf, 'scanf '); (* LIB *)
- defname(csetbits, 'setbits ');
- defname(csetword, 'setword ');
- defname(csetptr, 'setptr ');
- defname(cshort, 'short ');
- defname(csigned, 'signed ');
- defname(csizeof, 'sizeof ');
- defname(csprintf, 'sprintf '); (* LIB *)
- defname(cstatic, 'static ');
- defname(cstdin, 'stdin '); (* LIB *)
- defname(cstdout, 'stdout '); (* LIB *)
- defname(cstderr, 'stderr '); (* LIB *)
- defname(cstrncmp, 'strncmp '); (* OS *)
- defname(cstrncpy, 'strncpy '); (* OS *)
- defname(cstruct, 'struct ');
- defname(cswitch, 'switch ');
- defname(ctypedef, 'typedef ');
- defname(cundef, 'undef ');
- defname(cungetc, 'ungetc '); (* LIB *)
- defname(cunion, 'union ');
- defname(cunlink, 'unlink '); (* OS *)
- defname(cunsigned, 'unsigned ');
- defname(cwrite, 'write '); (* OS *)
-
- (* create predefined identifiers *)
- defid(nfunc, dabs, 'abs ');
- defid(nfunc, darctan, 'arctan ');
- defid(nvar, dargc, 'argc '); (* OS *)
- defid(nproc, dargv, 'argv '); (* OS *)
- defid(nscalar, dboolean, 'boolean ');
- defid(ntype, dchar, 'char ');
- defid(nfunc, dchr, 'chr ');
- defid(nproc, dclose, 'close '); (* OS *)
- defid(nfunc, dcos, 'cos ');
- defid(nproc, ddispose, 'dispose ');
- defid(nid, dfalse, 'false ');
- defid(nfunc, deof, 'eof ');
- defid(nfunc, deoln, 'eoln ');
- defid(nproc, dexit, 'exit '); (* OS *)
- defid(nfunc, dexp, 'exp ');
- defid(nproc, dflush, 'flush '); (* OS *)
- defid(nproc, dget, 'get ');
- defid(nproc, dhalt, 'halt '); (* OS *)
- defid(nvar, dinput, 'input ');
- defid(ntype, dinteger, 'integer ');
- defid(nfunc, dln, 'ln ');
- defid(nconst, dmaxint, 'maxint ');
- defid(nproc, dmessage, 'message '); (* OS *)
- defid(nproc, dnew, 'new ');
- defid(nfunc, dodd, 'odd ');
- defid(nfunc, dord, 'ord ');
- defid(nvar, doutput, 'output ');
- defid(nproc, dpack, 'pack ');
- defid(nproc, dpage, 'page ');
- defid(nfunc, dpred, 'pred ');
- defid(nproc, dput, 'put ');
- defid(nproc, dread, 'read ');
- defid(nproc, dreadln, 'readln ');
- defid(ntype, dreal, 'real ');
- defid(nproc, dreset, 'reset ');
- defid(nproc, drewrite, 'rewrite ');
- defid(nfunc, dround, 'round ');
- defid(nfunc, dsin, 'sin ');
- defid(nfunc, dsqr, 'sqr ');
- defid(nfunc, dsqrt, 'sqrt ');
- defid(nfunc, dsucc, 'succ ');
- defid(ntype, dtext, 'text ');
- defid(nid, dtrue, 'true ');
- defid(nfunc, dtrunc, 'trunc ');
- defid(nfunc, dtan, 'tan ');
- defid(nproc, dunpack, 'unpack ');
- defid(nproc, dwrite, 'write ');
- defid(nproc, dwriteln, 'writeln ');
-
- defid(nfield, dzinit, '$nit '); (* for internal use *)
- defid(ntype, dztring, '$ztring ');
-
- (* bind constants and variables *)
- deftab[dboolean]^.tbind^.tscalid := deftab[dfalse];
- deftab[dfalse]^.tnext := deftab[dtrue];
- currsym.st := sinteger;
- currsym.vint := maxint;
- deftab[dmaxint]^.tbind := mklit;
- deftab[dargc]^.tbind := deftab[dinteger]^.tbind;
- deftab[dinput]^.tbind := deftab[dtext]^.tbind;
- deftab[doutput]^.tbind := deftab[dtext]^.tbind;
-
- for t := tnone to terror do
- begin
- (* for predefined types: set up pointers to "npredef" nodes
- describing type, fill in constant identifying type *)
- case t of
- tboolean:
- typnods[t] := deftab[dboolean]; (* scalar type *)
- tchar:
- typnods[t] := deftab[dchar]^.tbind;
- tinteger:
- typnods[t] := deftab[dinteger]^.tbind;
- treal:
- typnods[t] := deftab[dreal]^.tbind;
- ttext:
- typnods[t] := deftab[dtext]^.tbind;
- tstring:
- typnods[t] := deftab[dztring]^.tbind;
- tnil,
- tset,
- tpoly,
- tnone:
- typnods[t] := mknode(npredef);
- terror:
- (* no op *)
- end;(* case *)
- if t in [tchar, tinteger, treal, ttext, tnone, tpoly,
- tstring, tnil, tset] then
- typnods[t]^.tobtyp := t
- end;
-
- (* fix name and type of field "init" *)
- fixinit(defnams[dzinit]^.lid^.istr);
- deftab[dzinit]^.tbind := deftab[dinteger]^.tbind;
-
- for d := dabs to dztring do
- linkup(nil, deftab[d]);
-
- deftab[dchr]^.tfuntyp := typnods[tchar];
-
- deftab[deof]^.tfuntyp := typnods[tboolean];
- deftab[deoln]^.tfuntyp := typnods[tboolean];
- deftab[dodd]^.tfuntyp := typnods[tboolean];
-
- deftab[dord]^.tfuntyp := typnods[tinteger];
- deftab[dround]^.tfuntyp := typnods[tinteger];
- deftab[dtrunc]^.tfuntyp := typnods[tinteger];
-
- deftab[darctan]^.tfuntyp := typnods[treal];
- deftab[dcos]^.tfuntyp := typnods[treal];
- deftab[dsin]^.tfuntyp := typnods[treal];
- deftab[dtan]^.tfuntyp := typnods[treal];
- deftab[dsqrt]^.tfuntyp := typnods[treal];
- deftab[dexp]^.tfuntyp := typnods[treal];
- deftab[dln]^.tfuntyp := typnods[treal];
-
- deftab[dsqr]^.tfuntyp := typnods[tpoly];
- deftab[dabs]^.tfuntyp := typnods[tpoly];
- deftab[dpred]^.tfuntyp := typnods[tpoly];
- deftab[dsucc]^.tfuntyp := typnods[tpoly];
-
- deftab[dargv]^.tfuntyp := typnods[tnone];
- deftab[ddispose]^.tfuntyp := typnods[tnone];
- deftab[dexit]^.tfuntyp := typnods[tnone];
- deftab[dget]^.tfuntyp := typnods[tnone];
- deftab[dhalt]^.tfuntyp := typnods[tnone];
- deftab[dnew]^.tfuntyp := typnods[tnone];
- deftab[dpack]^.tfuntyp := typnods[tnone];
- deftab[dput]^.tfuntyp := typnods[tnone];
- deftab[dread]^.tfuntyp := typnods[tnone];
- deftab[dreadln]^.tfuntyp := typnods[tnone];
- deftab[dreset]^.tfuntyp := typnods[tnone];
- deftab[drewrite]^.tfuntyp := typnods[tnone];
- deftab[dwrite]^.tfuntyp := typnods[tnone];
- deftab[dwriteln]^.tfuntyp := typnods[tnone];
- deftab[dmessage]^.tfuntyp := typnods[tnone];
- deftab[dunpack]^.tfuntyp := typnods[tnone];
-
- (* set up definitions for integer subranges *)
- nmachdefs := 0;
- defmach(0, 255, 'unsigned char '); (* CPU *)
- defmach(-128, 127, 'char '); (* CPU *)
- defmach(0, 65535, 'unsigned short '); (* CPU *)
- defmach(-32768, 32767, 'short '); (* CPU *)
- defmach(-2147483647, 2147483647, 'long '); (* CPU *)
- { defmach(0, 4294967295, 'unsigned long ');}(* CPU *)
- end; (* initialize *)
-
- procedure exit(i : integer); external; (* OS *)
-
- (* Action to take when an error is detected. *)
- procedure error;
-
- begin
- prtmsg(m);
- exit(1); (* OS *)
- goto 9999
- end;
-
- (* Action to take when a fatal error is detected. *)
- procedure fatal;
-
- begin
- prtmsg(m);
- halt (* OS *)
- (* goto 9999 *)
- end;
-
-
- begin (* program *)
- initialize;
- if echo then
- writeln('# ifdef PASCAL');
- parse;
- if echo then
- writeln('# else');
- lineno := 0; lastline := 0;
- transform;
- emit;
- if echo then
- writeln('# endif');
- 9999:
- (* the very *)
- end.
-
-