int parse() { token=getlex(); do { if (token <= 0) return 1; if (istoken('#')) { if (istoken(T_DEFINE)) dodefine(); else if (istoken(T_INCLUDE)) doinclude(); else error1("define oder include erwartet"); } else{ typeName(); if (token=='(') dofunc(); else doglob(); } } while(1); }
int doreg(char *dr) { expect('='); prs("\n mov "); prs(dr); prs(", "); if (istoken(T_CONST)) prunsign(lexval); else if (istoken(T_NAME )) { if (eqstr(symbol,"_DX")) prs("dx"); else if (eqstr(symbol,"_CX")) prs("cx"); else prs(symbol); } else error1("Nur Zahl oder Var erlaubt"); }
// examples might be ".OUT('GN1')" or ".OUT(.LABEL *1)"? // I think I have a typo or three: // OUTPUT = ('.OUT' '(' // \$ OUT1 ')' / '.LABEL' .OUT('LB') OUT1) .OUT('OUT') ., void output() { istoken(TOKEN_OUT); istoken(TOKEN_OPEN_PAREN); is_token(TOKEN_LABEL); emit(OP_LB); out1(); emit(OP_OUT); }
int rterm(char *op) {int mode; int opint; int ixarr; int id1; if (istoken(T_CONST)) { prnl(); prs(op); if (wi) prs(" ax, "); else prs(" al, "); prnum(lexval); return;} mode=typeName(); id1=searchname(); ixarr=0; if (istoken('[')) { ixarr=searchname(); expect(T_NAME); expect(']'); gettypes(ixarr); if (widthi==0) error1("Arrayindex muss int sein"); } if (eqstr(symbol,"_AX")) return; opint=op; dovar1(mode, opint, ixarr, id1); }
// This is the part of the syntax that occurs // inside the .OUT args, alone or after // void out1() { if (istoken(TOKEN_LABEL1)) { emit(OP_GN1); } else if (istoken(TOKEN_LABEL2)) { emit(OP_GN2); } else if (istoken(TOKEN_STAR)) { emit(OP_C1); } else if (istoken(TOKEN_STRING)) { emit_op(OP_CL, lexval); } else { assert(false); } }
//If input is not a token, throw exception int expect(int t) { if (!istoken(t)) { error("syntax error"); } }
//pff int type() { expect(T_INT); while(istoken(T_MUL)) ; }
int stmt() { int c; if(istoken('{')) {while(istoken('}')==0) stmt();} else if(istoken(T_IF)) doif(); else if(istoken(T_DO)) dodo(); else if(istoken(T_WHILE)) dowhile(); else if(istoken(T_GOTO)) {prs("\n jmp @@");name1();prs(symbol);expect(';');} else if(token==T_ASM) {prs("\n"); c=next(); while(c != '\n') { prc(c); c=next(); }; token=getlex(); } else if(istoken(T_ASMBLOCK)) {prs("\n"); expect('{'); c=next(); while(c!= '}') { prc(c); c=next(); }; token=getlex(); } else if(istoken(T_EMIT)) doemit(); else if(istoken(';')) { } else if(istoken(T_RETURN)){if (token!=';') expr(); prs("\n jmp @@retn"); nreturn++; expect(';'); } else if(thechar==':') {prs("\n@@"); /*Label*/ prs(symbol); prc(':'); expect(T_NAME); expect(':'); } else {expr(); expect(';'); } }
static int lex_next(void) { int c; // skip other tokens do { if ((c = fgetc(stdin)) == EOF) return 0; } while (!istoken(c)); return c; }
bool havetoken (SCAN * content, const char *literal) { if (istoken (content, literal)) { nexttoken (content); return (true); } return (false); }
int typeName() { int m; /*0=V,1=*,2=&*/ issign='S'; if(istoken(T_SIGNED)) issign='S'; if(istoken(T_UNSIGNED)) issign='U'; if(istoken(T_VOID)) error1("Void ist unbekannt"); iswidth='W'; if(istoken(T_CHAR)) iswidth='B'; if(istoken(T_INT)) iswidth='W'; istype='V'; m=0; if(istoken('*')) { istype='*'; m=1; } if(istoken('&')) { istype='&'; m=2; } name1(); return m; }
int dofunc() { cloc=&co; strcpy1(fname, symbol); prs("\n\n"); prs(symbol); prs(" PROC"); expect('('); narg=0; LTop=LStart; if (istoken(')')==0) { prs("\narg "); do { typeName(); addlocal(); if (narg) prc(','); prs(symbol); if (istype!='*') {if (iswidth=='B') prs(":byte ");} narg++; } while (istoken(',')); expect(')'); } expect('{'); /*body*/ nlocal=0; nreturn=0; nconst=0; if (isvariable()) prs("\nlocal "); while(isvariable()) { do { typeName(); addlocal(); if (nlocal) prc(','); prs(symbol); if (istype!='*') {if (iswidth=='B') prs(":byte ");} nlocal++; if (istoken('[')){istype='&';GType[LTop]='&';expect(T_CONST);expect(']'); prs(":BYTE:"); prnum(lexval); } } while (istoken(',')); expect(';'); } while(istoken('}')==0) stmt(); if (nreturn) prs("\n@@retn:"); prs("\n ret\nENDP"); listproc(); }
/*PLA V.88*/ #include ".\INCLUDE\CONST1.C" #include ".\INCLUDE\VAR1.C" #include ".\INCLUDE\DOS1.C" int BCC=1; /*is Borland C, dann kein BSS */ unsigned char testa[]={148,153,129,154,0}; /*"öÖüÜ";*/ int test3( int i, unsigned int u){ _AX=0xB800; } char Nametemp[16]; int doglob() { int symlen; int j; int isstringarray; isstringarray=0; if (GTop >= GMAX) error1("Globale Tabelle voll"); symlen = strlen1(symbol); if (symlen > 15 ) error1("Variable ist laenger als 15 Zeichen"); if (istoken('[')) { istype='&'; if (istoken(T_CONST)) { if (BCC == FALSE) {prs("\nAData = $\norg "); prnum(orgData);} prs("\n"); prs(symbol); if (iswidth=='B') prs(" db "); else prs(" dw "); prnum(lexval); prs(" dup (?)"); if (BCC == FALSE) prs("\norg AData"); orgData=orgData+lexval; if (iswidth=='W') orgData=orgData+lexval; GData[GTop]=lexval; expect(']'); }else { expect(']'); if (iswidth=='W') error1("Nur ByteArray erlaubt"); prs("\n"); prs(symbol); prs(" db "); isstringarray=1; strcpy1(Nametemp, symbol); expect('='); if (istoken(T_STRING)) { prc(34); prscomment(symbol); prc(34); prs(",0"); symlen=strlen1(symbol); GData[GTop]=symlen; } else if (istoken('{' )) { narg=0; do { if(narg) prc(','); expect(T_CONST); prnum(lexval); narg++; } while (istoken(',')); expect('}'); } else error1("String oder Zahlenarray erwartet"); }; }else { expect('='); prs("\n"); prs(symbol); if (istype=='*') prs(" dw "); else { if(iswidth=='B') prs(" db "); else prs(" dw "); } if(istoken('-')) prc('-'); expect(T_CONST); prnum(lexval); } GSign [GTop]=issign; GWidth[GTop]=iswidth; GType [GTop]=istype; j=GTop*16; pt=&GNameField + j; if (isstringarray) strcpy1(pt, Nametemp); else strcpy1(pt, symbol); GTop++; expect(';'); } int addlocal() { int j; if(LTop >= LMAX) error1("Lokale Tabelle voll"); GSign [LTop]=issign; GWidth[LTop]=iswidth; GType [LTop]=istype; j=LTop*16; pt=&GNameField + j; strcpy1(pt, symbol); LTop++; } int gettypes(int i) {int j; char c; c=GSign [i]; if (c=='S') signi =1; else signi =0; c=GWidth[i]; if (c=='W') widthi=wi=1; else widthi=wi=0; c=GType [i]; typei=0; if (c=='*') typei=wi=1; if (c=='&') typei=2; return i; } int adrofname(int i) {int j; int k; j=i*16; k=&GNameField + j; return k; } int printName(int i) { i=adrofname(i); prs(i); } int searchname() { int i; int j; i=LStart;while(i<LTop) {j=adrofname(i);if(eqstr(symbol,j))return i; i++;} i=0; while(i<GTop) {j=adrofname(i);if(eqstr(symbol,j))return i; i++;} error1("Variable unbekannt"); } int typeName() { int m; /*0=V,1=*,2=&*/ issign='S'; if(istoken(T_SIGNED)) issign='S'; if(istoken(T_UNSIGNED)) issign='U'; if(istoken(T_VOID)) error1("Void ist unbekannt"); iswidth='W'; if(istoken(T_CHAR)) iswidth='B'; if(istoken(T_INT)) iswidth='W'; istype='V'; m=0; if(istoken('*')) { istype='*'; m=1; } if(istoken('&')) { istype='&'; m=2; } name1(); return m; } int name1() {if (token!=T_NAME) error1("Name erwartet"); token=getlex(); } int dofunc() { cloc=&co; strcpy1(fname, symbol); prs("\n\n"); prs(symbol); prs(" PROC"); expect('('); narg=0; LTop=LStart; if (istoken(')')==0) { prs("\narg "); do { typeName(); addlocal(); if (narg) prc(','); prs(symbol); if (istype!='*') {if (iswidth=='B') prs(":byte ");} narg++; } while (istoken(',')); expect(')'); } expect('{'); /*body*/ nlocal=0; nreturn=0; nconst=0; if (isvariable()) prs("\nlocal "); while(isvariable()) { do { typeName(); addlocal(); if (nlocal) prc(','); prs(symbol); if (istype!='*') {if (iswidth=='B') prs(":byte ");} nlocal++; if (istoken('[')){istype='&';GType[LTop]='&';expect(T_CONST);expect(']'); prs(":BYTE:"); prnum(lexval); } } while (istoken(',')); expect(';'); } while(istoken('}')==0) stmt(); if (nreturn) prs("\n@@retn:"); prs("\n ret\nENDP"); listproc(); } int pexpr() {expect('('); iscmp=0; if (token==T_NAME) {if (eqstr(symbol, "_")) {constantexpr(); return;}} expr(); if (iscmp==0) prs("\n or al, al\n je @@"); expect(')'); } int constantexpr() { int mode; int id1;int ids; token=getlex(); mode=typeName(); id1=searchname(); gettypes(id1); ids=signi; if (isrelational() ==0) error1("Vergleich erwartet"); expect(T_CONST); prs("; constant expression"); prs("\ncmp "); printName(id1); prs(", "); prnum(lexval); cmpneg(ids); expect(')'); } int expr() { int mode; int id1; int ixarr; int ids; if (istoken(T_CONST)) {doconst(); return 1; } mode=typeName(); /*0=V,1=*,2=&*/ if (token=='(') {docall1(); goto e1; } if (isreg()) goto e1; id1=searchname(); gettypes(id1); ids=signi; ixarr=0; if (istoken('[')) { ixarr=searchname(); expect(T_NAME); expect(']'); gettypes(ixarr); if (widthi==0) error1("Arrayindex muss int sein"); } if (istoken(T_PLUSPLUS )) {if(mode)error1("Nur var erlaubt");doinc();goto e1;} if (istoken(T_MINUSMINUS)) {if(mode)error1("Nur var erlaubt");dodec();goto e1;} if (istoken(T_PLUSASS )) {compoundass("add", mode); goto e1;} if (istoken(T_MINUSASS )) {compoundass("sub", mode); goto e1;} if (istoken(T_ANDASS )) {compoundass("and", mode); goto e1;} if (istoken(T_ORASS )) {compoundass("or" , mode); goto e1;} if (istoken(T_MULASS )) {error1("nicht implementiert");} if (istoken(T_DIVASS )) {error1("nicht implementiert");} if (istoken('=')) { isconst=expr(); if (isconst) { if(mode==0) {prs("\n;++++ mov "); printName(id1); prs(", "); prnum(lexval); } } doassign(mode, id1, ixarr); goto e1;} dovar1(mode, "mov", ixarr, id1); e1: if (istoken('+')) rterm("add"); else if (istoken('-')) rterm("sub" ); else if (istoken('&')) rterm("and" ); else if (istoken('|')) rterm("or" ); else if (istoken(T_LESSLESS)) rterm("shl"); else if (istoken(T_GREATGREAT)) rterm("shr"); else if (istoken('*')) domul (ids); else if (istoken('/')) doidiv(ids); else if (istoken('%')) domod (ids); if (isrelational()) { rterm("cmp"); cmpneg(ids);} return 0; } int compoundass(char *op, int mode) { if(mode) error1("Nur scalar Var erlaubt"); prnl(); prs(op); prs(" "); prs(symbol); prs(", "); expect(T_CONST); prnum(lexval); } int dovar1(int mode, int op, int ixarr, int id1) { gettypes(id1); if (mode==1) {prs("\n mov bx, "); printName(id1); prnl(); prs(op); if(widthi) prs(" ax, [bx]"); else prs(" al, [bx]\n mov ah, 0"); return; } if (mode==2){prnl();prs(op);prs(" ax, offset ");printName(id1); return; } if (ixarr) { prs("\n mov bx, "); printName(ixarr); if (wi) prs("\n shl bx, 1"); prs("\n "); prs(op); if (wi) prs(" ax, "); else prs(" al, "); printName(id1); prs(" [bx]"); return; } prnl();prs(op); if(wi) prs(" ax, "); else prs(" al, "); printName(id1); } int rterm(char *op) {int mode; int opint; int ixarr; int id1; if (istoken(T_CONST)) { prnl(); prs(op); if (wi) prs(" ax, "); else prs(" al, "); prnum(lexval); return;} mode=typeName(); id1=searchname(); ixarr=0; if (istoken('[')) { ixarr=searchname(); expect(T_NAME); expect(']'); gettypes(ixarr); if (widthi==0) error1("Arrayindex muss int sein"); } if (eqstr(symbol,"_AX")) return; opint=op; dovar1(mode, opint, ixarr, id1); } int isreg() { if (eqstr(symbol,"_AH")) {doreg("ah"); goto r1;} if (eqstr(symbol,"_AL")) {doreg("al"); goto r1;} if (eqstr(symbol,"_AX")) {doreg("ax"); goto r1;} if (eqstr(symbol,"_BH")) {doreg("bh"); goto r1;} if (eqstr(symbol,"_BL")) {doreg("bl"); goto r1;} if (eqstr(symbol,"_BX")) {doreg("bx"); goto r1;} if (eqstr(symbol,"_CH")) {doreg("ch"); goto r1;} if (eqstr(symbol,"_CL")) {doreg("cl"); goto r1;} if (eqstr(symbol,"_CX")) {doreg("cx"); goto r1;} if (eqstr(symbol,"_DH")) {doreg("dh"); goto r1;} if (eqstr(symbol,"_DL")) {doreg("dl"); goto r1;} if (eqstr(symbol,"_DX")) {doreg("dx"); goto r1;} if (eqstr(symbol,"_FLAGS")) {doreg("flags"); goto r1;} return 0; r1: return 1; } int doreg(char *dr) { expect('='); prs("\n mov "); prs(dr); prs(", "); if (istoken(T_CONST)) prunsign(lexval); else if (istoken(T_NAME )) { if (eqstr(symbol,"_DX")) prs("dx"); else if (eqstr(symbol,"_CX")) prs("cx"); else prs(symbol); } else error1("Nur Zahl oder Var erlaubt"); } int doinc() { prs("\n inc "); prs(symbol); } int dodec() { prs("\n dec "); prs(symbol); } int doassign(int mode, int i, int ixarr) { gettypes(i); if (mode==1) {prs("\n mov bx, ");printName(i); if (widthi) prs("\n mov [bx], ax"); else prs("\n mov [bx], al"); return;} if (mode==2) {prs("\n mov offset ");printName(i); prs(", ax"); return;} if (ixarr) { prs("\n mov bx, "); printName(ixarr); if (wi) prs("\n shl bx, 1"); prs("\n mov "); printName(i); if (wi) prs(" [bx], ax"); else prs(" [bx], al"); return; } prs("\n mov "); printName(i); if (wi) prs(", ax"); else prs(", al"); } int domul(int ids) { if (ids) rterm("imul"); else { if (istoken(T_CONST)) {prs("\n mov bx, "); prnum(lexval); prs("\n mul bx"); } else error1("Bei MUL nur Zahl als Multiplikator erlaubt"); } } int doidiv(int ids) { if (istoken(T_CONST)) { prs("\n mov bx, "); prnum(lexval); if (ids) prs("\n cwd\n idiv bx"); else prs("\n mov dx, 0\n div bx"); } else error1("Nur Zahl als Divisor erlaubt"); } int domod(int ids) { doidiv(ids); prs("\n mov ax, dx"); } int doconst() { prs("\n mov ax, "); prnum(lexval); } int part1=0;int part2=0;int part3=0;int part4=0;int part5=0;int part6=0; int parn1=0;int parn2=0;int parn3=0;int parn4=0;int parn5=0;int parn6=0; char procname[20]; /*1=CONST,2=String,3=&,4=Name*/ int docall1() {int i; int nargs; int t0; int n0; nargs=0; strcpy1(&procname, symbol);expect('('); if (istoken(')') ==0 ) { do { nargs++; if (nargs >6 ) error1("Max. 6 Parameter"); t0=0; if(istoken(T_CONST)) {t0=1; n0=lexval; } if(istoken(T_STRING)){t0=2; n0=nconst; eprs("\n"); eprs(fname); eprc(95);eprnum(nconst);eprs(" db "); eprc(34);eprs(symbol);eprc(34);eprs(",0"); nconst++; } if(istoken('&')) {t0=3; name1(); n0=searchname();} if(istoken(T_NAME)) {t0=4; n0=searchname(); p1=>ype; p1=p1+n0; if (*p1=='&') t0=3; } if (t0==0) error1("Parameter nicht erkannt (kein * erlaubt)"); if (nargs==1) {part1=t0; parn1=n0; } if (nargs==2) {part2=t0; parn2=n0; } if (nargs==3) {part3=t0; parn3=n0; } if (nargs==4) {part4=t0; parn4=n0; } if (nargs==5) {part5=t0; parn5=n0; } if (nargs==6) {part6=t0; parn6=n0; } } while (istoken(',')); expect(')'); i=nargs; do { if (i==1) {t0=part1; n0=parn1; } if (i==2) {t0=part2; n0=parn2; } if (i==3) {t0=part3; n0=parn3; } if (i==4) {t0=part4; n0=parn4; } if (i==5) {t0=part5; n0=parn5; } if (i==6) {t0=part6; n0=parn6; } if(t0==1){ prs("\n push "); prnum(n0);} if(t0==2){ prs("\n push offset "); prs(fname);prc(95);prnum(n0);} if(t0==3){ prs("\n lea ax, "); printName(n0); prs("\n push ax");} if(t0==4){ gettypes(n0); if(wi) { prs("\n push "); printName(n0);} else { prs("\n mov al, byte ptr "); printName(n0); prs("\n mov ah, 0\n push ax"); } } i--; } while (i > 0); } prs("\n call "); prs(&procname); if (nargs>0) {prs("\n add sp, "); nargs=nargs+nargs; prnum(nargs); } }
//havent a dammed clue, constants everywhere int stmt() { int jdest; int tst; if (istoken('{')) { while(!istoken('}')) stmt(); } else if (istoken(T_IF)) { pexpr(); jdest = emitj(C_JFALSE, 0); stmt(); if (istoken(T_ELSE)) { tst = emitj(C_JUMP, 0); emitat(jdest, curloc); stmt(); emitat(tst, curloc); } else { emitat(jdest, curloc); } } else if (istoken(T_WHILE)) { tst = curloc; pexpr(); jdest = emitj(C_JFALSE, 0); stmt(); emitj(C_JUMP, tst); emitat(jdest, curloc); } else if (istoken(T_DO)) { jdest = curloc; stmt(); expect(T_WHILE); pexpr(); emit(C_NOT); emitj(C_JFALSE, jdest); } else if (istoken(T_RETURN)) { expr(1, P_NONE); expect(';'); emit(C_RETURN); } else if (istoken(';')) { /* empty */ } else { /* just an expression */ expr(1, P_NONE); emit(C_POP); expect(';'); } }
int parse() { int objid; token = getlex(); while(1) { if (token < 0) return 1; type(); /* T_INT or CHAR */ objid = name(); /* T_NAME */ if (istoken('(')) { /* function */ funids[nfun] = objid; funoffs[nfun++] = curloc; narg = 0; if (!istoken(')')) { do { type(); argids[narg++] = name(); } while(istoken(',')); expect(')'); } expect('{'); /* body */ /* decls */ nlocal = 0; while(token == T_INT) { type(); do { localids[nlocal++] = name(); } while (istoken(',')); expect(';'); } if (DEFSTK < nlocal) emitop(C_ALLOC, nlocal); /* stmts */ while(!istoken('}')) stmt(); emit(C_RETURN); } else { globoffs[nglob] = curgloboffs; if (istoken('[')) { /* array */ expect(T_CONST); curgloboffs = curgloboffs + lexval; expect(']'); globscalar[nglob] = 0; } else { curgloboffs++; globscalar[nglob] = 1; } globids[nglob++] = objid; expect(';'); } } }
int doglob() { int symlen; int j; int isstringarray; isstringarray=0; if (GTop >= GMAX) error1("Globale Tabelle voll"); symlen = strlen1(symbol); if (symlen > 15 ) error1("Variable ist laenger als 15 Zeichen"); if (istoken('[')) { istype='&'; if (istoken(T_CONST)) { if (BCC == FALSE) {prs("\nAData = $\norg "); prnum(orgData);} prs("\n"); prs(symbol); if (iswidth=='B') prs(" db "); else prs(" dw "); prnum(lexval); prs(" dup (?)"); if (BCC == FALSE) prs("\norg AData"); orgData=orgData+lexval; if (iswidth=='W') orgData=orgData+lexval; GData[GTop]=lexval; expect(']'); }else { expect(']'); if (iswidth=='W') error1("Nur ByteArray erlaubt"); prs("\n"); prs(symbol); prs(" db "); isstringarray=1; strcpy1(Nametemp, symbol); expect('='); if (istoken(T_STRING)) { prc(34); prscomment(symbol); prc(34); prs(",0"); symlen=strlen1(symbol); GData[GTop]=symlen; } else if (istoken('{' )) { narg=0; do { if(narg) prc(','); expect(T_CONST); prnum(lexval); narg++; } while (istoken(',')); expect('}'); } else error1("String oder Zahlenarray erwartet"); }; }else { expect('='); prs("\n"); prs(symbol); if (istype=='*') prs(" dw "); else { if(iswidth=='B') prs(" db "); else prs(" dw "); } if(istoken('-')) prc('-'); expect(T_CONST); prnum(lexval); } GSign [GTop]=issign; GWidth[GTop]=iswidth; GType [GTop]=istype; j=GTop*16; pt=&GNameField + j; if (isstringarray) strcpy1(pt, Nametemp); else strcpy1(pt, symbol); GTop++; expect(';'); }
/* returns true if lvalue, else false */ int expr(int needval, int prec) { int na; int islval; int jdst; int op; int any; int opprec; islval = 0; /* parse one expr */ if (istoken(T_CONST)) { emitop(C_PUSHC, lexval); } else if (istoken(T_STRING)) { /* If the syntax is ok the string must still be in the symbol buffer. Stuff it into global space. */ emitop(C_PUSHS, strsize); any = 0; while(any < strsize) emit(symbol[any++]); } else if (istoken(T_NAME)) { islval = pushval(); } else if (istoken('(')) { islval = expr(0, P_NONE); expect(')'); } else if (istoken(T_NOT)) { expr(1, P_PRE); emit(C_NOT); } else if (istoken(T_SUB)) { expr(1, P_PRE); emit(C_NEG); } else if (istoken(T_MUL)) { expr(1, P_PRE); islval = 1; } else if (istoken(T_AND)) { if (expr(0, P_PRE) == 0) error("lvalue required"); } else error("syntax error in expr"); /* one expression parsed, try for hi prec ops */ any = 1; while(any) { op = token % OPMOD; if (istoken('(')) { /* function call */ pderef(islval); na = 0; if (!istoken(')')) { do { expr(1, P_NONE); na++; } while(istoken(',')); expect(')'); } emitop(C_CALL, na*2); islval = 0; } else if (istoken('[')) { /* array ref */ pderef(islval); expr(1, P_NONE); emit(C_ADD); expect(']'); islval = 1; } else if (istoken(T_POSTINC) || istoken(T_POSTDEC)) { if (!islval) error("no lval for ++"); emit(op); islval = 0; } else any = 0; } opprec = token / OPMOD; while (prec < opprec) { if ( (op = token % OPMOD) != C_ASSIGN) { pderef(islval); } else { if (!islval) error("no lval for ="); } if (istoken(T_ANDAND) || istoken(T_OROR)) { emit(C_DUP); if (op == C_OROR) emit(C_NOT); jdst = emitj(C_JFALSE, 0); emit(C_POP); expr(1, opprec); emitat(jdst, curloc); } else { /* emit binop code */ token = getlex(); expr(1, opprec); emit(op); } islval = 0; opprec = token / OPMOD; } if (needval) { pderef(islval); islval = 0; } return islval; }
/*- *----------------------------------------------------------------------- * Cond_Eval -- * Evaluate the conditional in the passed line. The line * looks like this: * .<cond-type> <expr> * where <cond-type> is any of if, ifmake, ifnmake, ifdef, * ifndef, elif, elifmake, elifnmake, elifdef, elifndef * and <expr> consists of &&, ||, !, make(target), defined(variable) * and parenthetical groupings thereof. * * Input: * line Line to parse * * Results: * COND_PARSE if should parse lines after the conditional * COND_SKIP if should skip lines after the conditional * COND_INVALID if not a valid conditional. * * Side Effects: * None. * * Note that the states IF_ACTIVE and ELSE_ACTIVE are only different in order * to detect splurious .else lines (as are SKIP_TO_ELSE and SKIP_TO_ENDIF) * otherwise .else could be treated as '.elif 1'. * *----------------------------------------------------------------------- */ int Cond_Eval(char *line) { #define MAXIF 64 /* maximum depth of .if'ing */ enum if_states { IF_ACTIVE, /* .if or .elif part active */ ELSE_ACTIVE, /* .else part active */ SEARCH_FOR_ELIF, /* searching for .elif/else to execute */ SKIP_TO_ELSE, /* has been true, but not seen '.else' */ SKIP_TO_ENDIF /* nothing else to execute */ }; static enum if_states cond_state[MAXIF + 1] = { IF_ACTIVE }; const struct If *ifp; Boolean isElif; Boolean value; int level; /* Level at which to report errors. */ enum if_states state; level = PARSE_FATAL; /* skip leading character (the '.') and any whitespace */ for (line++; *line == ' ' || *line == '\t'; line++) continue; /* Find what type of if we're dealing with. */ if (line[0] == 'e') { if (line[1] != 'l') { if (!istoken(line + 1, "ndif", 4)) return COND_INVALID; /* End of conditional section */ if (cond_depth == cond_min_depth) { Parse_Error(level, "if-less endif"); return COND_PARSE; } /* Return state for previous conditional */ cond_depth--; if (cond_depth > MAXIF) return COND_SKIP; return cond_state[cond_depth] <= ELSE_ACTIVE ? COND_PARSE : COND_SKIP; } /* Quite likely this is 'else' or 'elif' */ line += 2; if (istoken(line, "se", 2)) { /* It is else... */ if (cond_depth == cond_min_depth) { Parse_Error(level, "if-less else"); return COND_PARSE; } if (cond_depth > MAXIF) return COND_SKIP; state = cond_state[cond_depth]; switch (state) { case SEARCH_FOR_ELIF: state = ELSE_ACTIVE; break; case ELSE_ACTIVE: case SKIP_TO_ENDIF: Parse_Error(PARSE_WARNING, "extra else"); /* FALLTHROUGH */ default: case IF_ACTIVE: case SKIP_TO_ELSE: state = SKIP_TO_ENDIF; break; } cond_state[cond_depth] = state; return state <= ELSE_ACTIVE ? COND_PARSE : COND_SKIP; } /* Assume for now it is an elif */ isElif = TRUE; } else isElif = FALSE; if (line[0] != 'i' || line[1] != 'f') /* Not an ifxxx or elifxxx line */ return COND_INVALID; /* * Figure out what sort of conditional it is -- what its default * function is, etc. -- by looking in the table of valid "ifs" */ line += 2; for (ifp = ifs; ; ifp++) { if (ifp->form == NULL) return COND_INVALID; if (istoken(ifp->form, line, ifp->formlen)) { line += ifp->formlen; break; } } /* Now we know what sort of 'if' it is... */ if (isElif) { if (cond_depth == cond_min_depth) { Parse_Error(level, "if-less elif"); return COND_PARSE; } if (cond_depth > MAXIF) /* Error reported when we saw the .if ... */ return COND_SKIP; state = cond_state[cond_depth]; if (state == SKIP_TO_ENDIF || state == ELSE_ACTIVE) { Parse_Error(PARSE_WARNING, "extra elif"); cond_state[cond_depth] = SKIP_TO_ENDIF; return COND_SKIP; } if (state != SEARCH_FOR_ELIF) { /* Either just finished the 'true' block, or already SKIP_TO_ELSE */ cond_state[cond_depth] = SKIP_TO_ELSE; return COND_SKIP; } } else { /* Normal .if */ if (cond_depth >= MAXIF) { cond_depth++; Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.", MAXIF); return COND_SKIP; } state = cond_state[cond_depth]; cond_depth++; if (state > ELSE_ACTIVE) { /* If we aren't parsing the data, treat as always false */ cond_state[cond_depth] = SKIP_TO_ELSE; return COND_SKIP; } } /* And evaluate the conditional expresssion */ if (Cond_EvalExpression(ifp, line, &value, 1) == COND_INVALID) { /* Syntax error in conditional, error message already output. */ /* Skip everything to matching .endif */ cond_state[cond_depth] = SKIP_TO_ELSE; return COND_SKIP; } if (!value) { cond_state[cond_depth] = SEARCH_FOR_ELIF; return COND_SKIP; } cond_state[cond_depth] = IF_ACTIVE; return COND_PARSE; }
static Token compare_function(Boolean doEval) { static const struct fn_def { const char *fn_name; int fn_name_len; int (*fn_getarg)(char **, char **, const char *); Boolean (*fn_proc)(int, const char *); } fn_defs[] = { { "defined", 7, CondGetArg, CondDoDefined }, { "make", 4, CondGetArg, CondDoMake }, { "exists", 6, CondGetArg, CondDoExists }, { "empty", 5, get_mpt_arg, CondDoEmpty }, { "target", 6, CondGetArg, CondDoTarget }, { "commands", 8, CondGetArg, CondDoCommands }, { NULL, 0, NULL, NULL }, }; const struct fn_def *fn_def; Token t; char *arg = NULL; int arglen; char *cp = condExpr; char *cp1; for (fn_def = fn_defs; fn_def->fn_name != NULL; fn_def++) { if (!istoken(cp, fn_def->fn_name, fn_def->fn_name_len)) continue; cp += fn_def->fn_name_len; /* There can only be whitespace before the '(' */ while (isspace(*(unsigned char *)cp)) cp++; if (*cp != '(') break; arglen = fn_def->fn_getarg(&cp, &arg, fn_def->fn_name); if (arglen <= 0) { condExpr = cp; return arglen < 0 ? TOK_ERROR : TOK_FALSE; } /* Evaluate the argument using the required function. */ t = !doEval || fn_def->fn_proc(arglen, arg); if (arg) free(arg); condExpr = cp; return t; } /* Push anything numeric through the compare expression */ cp = condExpr; if (isdigit((unsigned char)cp[0]) || strchr("+-", cp[0])) return compare_expression(doEval); /* * Most likely we have a naked token to apply the default function to. * However ".if a == b" gets here when the "a" is unquoted and doesn't * start with a '$'. This surprises people. * If what follows the function argument is a '=' or '!' then the syntax * would be invalid if we did "defined(a)" - so instead treat as an * expression. */ arglen = CondGetArg(&cp, &arg, NULL); for (cp1 = cp; isspace(*(unsigned char *)cp1); cp1++) continue; if (*cp1 == '=' || *cp1 == '!') return compare_expression(doEval); condExpr = cp; /* * Evaluate the argument using the default function. * This path always treats .if as .ifdef. To get here the character * after .if must have been taken literally, so the argument cannot * be empty - even if it contained a variable expansion. */ t = !doEval || if_info->defProc(arglen, arg) != if_info->doNot; if (arg) free(arg); return t; }
int expr() { int mode; int id1; int ixarr; int ids; if (istoken(T_CONST)) {doconst(); return 1; } mode=typeName(); /*0=V,1=*,2=&*/ if (token=='(') {docall1(); goto e1; } if (isreg()) goto e1; id1=searchname(); gettypes(id1); ids=signi; ixarr=0; if (istoken('[')) { ixarr=searchname(); expect(T_NAME); expect(']'); gettypes(ixarr); if (widthi==0) error1("Arrayindex muss int sein"); } if (istoken(T_PLUSPLUS )) {if(mode)error1("Nur var erlaubt");doinc();goto e1;} if (istoken(T_MINUSMINUS)) {if(mode)error1("Nur var erlaubt");dodec();goto e1;} if (istoken(T_PLUSASS )) {compoundass("add", mode); goto e1;} if (istoken(T_MINUSASS )) {compoundass("sub", mode); goto e1;} if (istoken(T_ANDASS )) {compoundass("and", mode); goto e1;} if (istoken(T_ORASS )) {compoundass("or" , mode); goto e1;} if (istoken(T_MULASS )) {error1("nicht implementiert");} if (istoken(T_DIVASS )) {error1("nicht implementiert");} if (istoken('=')) { isconst=expr(); if (isconst) { if(mode==0) {prs("\n;++++ mov "); printName(id1); prs(", "); prnum(lexval); } } doassign(mode, id1, ixarr); goto e1;} dovar1(mode, "mov", ixarr, id1); e1: if (istoken('+')) rterm("add"); else if (istoken('-')) rterm("sub" ); else if (istoken('&')) rterm("and" ); else if (istoken('|')) rterm("or" ); else if (istoken(T_LESSLESS)) rterm("shl"); else if (istoken(T_GREATGREAT)) rterm("shr"); else if (istoken('*')) domul (ids); else if (istoken('/')) doidiv(ids); else if (istoken('%')) domod (ids); if (isrelational()) { rterm("cmp"); cmpneg(ids);} return 0; }
int domul(int ids) { if (ids) rterm("imul"); else { if (istoken(T_CONST)) {prs("\n mov bx, "); prnum(lexval); prs("\n mul bx"); } else error1("Bei MUL nur Zahl als Multiplikator erlaubt"); } }
int doidiv(int ids) { if (istoken(T_CONST)) { prs("\n mov bx, "); prnum(lexval); if (ids) prs("\n cwd\n idiv bx"); else prs("\n mov dx, 0\n div bx"); } else error1("Nur Zahl als Divisor erlaubt"); }
bool validtoken(char *s) { if (!istokenfirst(*s++)) return FALSE; while (*s != 0) if (!istoken(*s++)) return FALSE; return TRUE; }
int expect(int t) {if (istoken(t)==0) { listproc(); prs("\nErwartet ASCII(dez): "); prnum(t); error1(" nicht gefunden"); } }
int doif() {int jdest; int tst; pexpr(); nlabel++; jdest=nlabel; prnum(jdest); stmt(); if (istoken(T_ELSE)) { nlabel++; tst=nlabel; prjump(tst); prlabel(jdest); stmt(); prlabel(tst); } else prlabel(jdest); }
node gettoken(){ char *p = cur.text; if (*p == '\'') { char c; node token; advance(); if (cur.text == cur.eot) { fatal("file ends in character constant"); } if (*cur.text == '\\') { advance(); if (cur.text == cur.eot) { fatal("file ends in character constant"); } c = escaped(*cur.text); } else c = *cur.text; advance(); if (cur.text == cur.eot) fatal("file ends in character constant"); if (*cur.text != '\'') { fatal("character constant not terminated"); } advance(); token = newnode (CHAR_CONST,char_const_tag); token->body.char_const.contents = c; return token; } if (*p == '"') { char *s; node token; advance(); s = cur.text; while (TRUE) { if (cur.text == cur.eot) fatal("file ends before string"); if (cur.text[0]=='"') break; if (*cur.text == '\\') { advance(); if (cur.text == cur.eot) fatal("file ends before string"); } advance(); } token = newnode(STRING_CONST,string_const_tag); token->body.unique_string.characters = strnperm(s,cur.text-s); /* observe that escaped character sequences such as \n are not simplified here */ advance(); return token; } if (*p == ',' || *p == '.') { advance(); } else { bool digitssofar = TRUE; while (TRUE) { if (!isdigit((int)*cur.text)) digitssofar = FALSE; advance(); if (cur.text == cur.eot) break; if (*cur.text == '.' && digitssofar) continue; if (istoken(*cur.text)) continue; break; } if (integerq(p,cur.text-p)) { return IntegerN(p,cur.text-p); } if (doubleq(p,cur.text-p)) { return DoubleN(p,cur.text-p); } } return UniqueStringN(p,cur.text-p); }