Mercurial > hg > CbC > old > device
view mc-parse.c @ 33:8500dbb69dd9
bad macro processing. give up this method.
author | kono |
---|---|
date | Sun, 09 Feb 2003 23:17:23 +0900 |
parents | b35787d8a442 |
children | 0756caa79167 |
line wrap: on
line source
/* Micro-C Parser Part */ /* $Id$ */ #define EXTERN /**/ #include "mc.h" void ntable_consistency(); static void adecl(NMTBL *n); static int decl_data(int t, NMTBL *n,int offset); static int alpha(char c); static int binop(int op, int e1, int e2, int t1, int t2); static void compatible(int t1, int t2); static void decl(void); static void def(NMTBL *n); static int digit(char c); static void docase(void); static void docomp(void); static void dodefault(void); static void dodo(void); static void dofor(void); static void dogoto(void); static void doif(void); static void dolabel(void); static void doswitch(void); static void doreturn(void); static void dowhile(void); static void errmsg(void); static void macro_processing(); static void macro_define(); static void macro_define0(); static void copy(NMTBL *nptr, char *s); void error(int n); static int expr(void); static int expr0(void); static int expr1(void); static int expr2(void); static int expr3(void); static int expr4(void); static int expr5(void); static int expr6(void); static int expr7(void); static int expr8(void); static int expr9(void); static int expr10(void); static int expr11(void); static int expr12(void); static int expr13(void); static int expr14(void); static int expr15(int e1); static int expr16(int e1); static void fcheck(NMTBL *n); static void fdecl(NMTBL *n); static int getch(void); static int getfree(int n); static void getline(void); static void getstring(void); static int getsym(void); static int indop(int e); static void init(void); static int integral(int t); static void lcheck(int e); extern int glist2(int e1,int e2); extern int list2(int e1, int e2); extern int list3(int e1, int e2, int e3); extern int list4(int e1, int e2, int e3, int e4); extern int rplacad(int e, int n); extern int rplacadd(int e, int n); static void reserve(char *s, int d); static int macroeq(char *s); static int ndecl0(void); static int ndecl1(void); static int neqname(char *p,char *name); static void newfile(void); static int postequ(int s1, int s2); static void reverse(int t1); int reverse0(int t1); static int rvalue(int e); int scalar(int t); static int sdecl(int s); static int skipspc(void); static void statement(void); static int strop(int e); static int typeid(int s); static int typename(void); static int typespec(void); static int cexpr(int e); static void code_decl(NMTBL *n); static int macro_args(); static void fmacro(); static void local_define(); static void local_undef(); static int recursive_macro(char *); extern void display_ntable(NMTBL *n, char *s); extern void closing(void); extern void opening(char *filename); extern void gen_gdecl(char *n, int gpc); extern void emit_init(void); extern void enter(char *name); extern void enter1(int disp); extern void leave(int control, char *name); extern void ret(void); extern void jmp(int l); extern void gexpr(int e1); extern void g_expr(int e1); extern int get_register_var(void); extern void bexpr(int e1, char cond, int l1); extern int fwdlabel(void); extern void fwddef(int l); extern int backdef(void); extern int def_label(int cslabel, int dlabel); extern void jmp_label(int l); extern void cmpdimm(int e, int csreg); extern void jcond(int l, char cond); extern void jmp_eq_label(int l); extern void gen_comment(char *s); extern void gen_source(char *s); extern void code_init(void); extern void code_enter(char *name) ; extern void code_leave(char *name) ; extern void code_enter1(int disp0,int args); extern void emit_data_closing(NMTBL *n); extern void emit_data(int e, int t, NMTBL *n); extern void exit(int l); int main(int argc, char **argv) { NMTBL *nptr; int i; char *ccout; if(argc==1) exit(1); lsrc = chk = asmf = 0; ccout = OUTPUT_FILE_NAME; ac=argc; av=argv; for (ac2=1; (ac2 < ac) && (*av[ac2] == '-'); ++ac2) { switch (*(av[ac2]+1)) { case 'S': case 's': lsrc = 1; break; case 'O': case 'o': ccout = av[ac2]+2; break; case 'C': case 'c': chk = 1; break; case 'D': case 'd': debug = 1; break; default: error(OPTION); exit(1); } } if (!chk) if ( (freopen(ccout,"w",stdout)) == NULL ) error(FILERR); init(); while(1) { for (nptr = &ntable[GSYMS],i=LSYMS; i--;) { (nptr++)->sc = 0; } emit_init(); mode=TOP; lfree= HEAPSIZE; while(getsym()==SM); mode=GDECL; stmode=0; args=0; decl(); } /*NOTREACHED*/ } void error(int n) { if(n == EOFERR) { if(filep!=filestack) { fclose(filep->fcb); lineno=filep->ln; --filep; return; } else if(ac2!=ac) { fclose(filep->fcb); newfile(); return; } else if(mode == TOP) { /* if (!chk) fprintf(stderr, "Total internal labels : %u.\n",labelno-1); fprintf(stderr, "Total global variables : %u bytes.\n\n",gpc); */ closing(); exit(0); } } fprintf(stderr,"%s:%d:%s\n",filep->name0,lineno, (n==FILERR) ? "Can't open specified file" : (n==DCERR) ? "Declaration syntax" : (n==STERR) ? "Statement syntax" : (n==EXERR) ? "Expression syntax" : (n==CNERR) ? "Constant required" : (n==CHERR) ? "Illegal character" : (n==GSERR) ? "Too many global symbols" : (n==LSERR) ? "Too many local symbols" : (n==MSERR) ? "Too many macro symbols" : (n==STRERR) ? "Too many strings or macros" : (n==LNERR) ? "Line too long" : (n==EOFERR) ? "Unexpected end of file" : (n==MCERR) ? "Macro syntax" : (n==INCERR) ? "Include syntax" : (n==HPERR) ? "Too long expression" : (n==TYERR) ? "Type mismatch" : (n==LVERR) ? "Lvalue required" : (n==UDERR) ? "Undeclared identifier" : (n==OPTION) ? "Illegal option" : (n==REG_ERR) ? "illegal register var" : (n==CODE_ERR) ? "goto code is necessary" : "Bug of compiler"); errmsg(); exit(1); } void errmsg(void) { char *p,*lim; if(lineno==0) return; fprintf(stderr,"%s",linebuf); lim=chptr; while (chptrsave) { lim = (char *)car(chptrsave); chptrsave = cadr(chptrsave); } for (p=linebuf; p < lim;) fprintf(stderr,(*p++ == '\t') ? "\t" : " "); fprintf (stderr,"^\n"); } void checksym(int s) { char *p; if (sym != s) { p=(s==RPAR) ? "')'": (s==RBRA) ? "']'": (s==SM) ? "';'": (s==LPAR) ? "'('": (s==WHILE) ? "'while'": (s==COLON) ? "':'": "Identifier"; fprintf(stderr,"%d:%s expected.\n",lineno,p); errmsg(); } else getsym(); } void init(void) { NMTBL *nptr; int i; cheapp=cheap; for(nptr = ntable,i = GSYMS; i--;) (nptr++)->sc = 0; for(nptr = mtable,i = MSYMS; i--;) (nptr++)->sc = 0; reserve("int",INT); reserve("void",VOID); reserve("char",CHAR); reserve("const",KONST); reserve("struct",STRUCT); reserve("union",UNION); reserve("unsigned",UNSIGNED); reserve("static",STATIC); reserve("goto",GOTO); reserve("return",RETURN); reserve("break",BREAK); reserve("continue",CONTINUE); reserve("if",IF); reserve("else",ELSE); reserve("for",FOR); reserve("do",DO); reserve("while",WHILE); reserve("switch",SWITCH); reserve("case",CASE); reserve("default",DEFAULT); reserve("typedef",TYPEDEF); reserve("sizeof",SIZEOF); reserve("long",LONG); reserve("short",SHORT); reserve("extern",EXTRN); reserve("defined",DEFINED); reserve("register",REGISTER); reserve("code",CODE); reserve("environment",ENVIRONMENT); gpc=glineno=mflag=0; gfree=ilabel=1; labelno=2; lfree=HEAPSIZE; filep=filestack; code_init(); newfile(); macro_define("__micro_c__ 1\n"); getline(); getch(); } void newfile(void) { char *s; lineno=0; /* fprintf(stderr,"%s:\n",av[ac2]); */ opening(av[ac2]); if ( (filep->fcb = fopen(av[ac2++],"r")) == NULL ) error(FILERR); s = av[ac2-1]; filep->name0 = cheapp; while((*cheapp++ = *s++)); } void reserve(char *s, int d) { NMTBL *nptr; int i; hash=0; name=namebuf; i=0; while((name[i++] = *s)) { hash=((7*hash) ^ *s++); } if (cheapp+i >= cheap+CHEAPSIZE) error(STRERR); name[i++] = 0; (nptr = gsearch())->sc = RESERVE; if (d==0) { nptr->sc = MACRO; nptr->dsp = (int)""; nptr->ty=0; } else { nptr->dsp = d; } } static NMTBL null_nptr; void decl(void) { NMTBL *n; int t; if(sym==STATIC) { if(mode==LDECL) { getsym(); mode=STADECL; stmode=LDECL; } else if(mode==GDECL) { getsym(); stmode=STATIC; } else error(DCERR); } else if(sym==REGISTER) { if(mode!=LDECL) error(DCERR); stmode=REGISTER; getsym(); } else if(sym==EXTRN) { getsym(); stmode=EXTRN; } else if(sym==TYPEDEF) { if(mode==GDECL) { getsym(); mode=GTDECL; } else if(mode==LDECL) { getsym(); mode=LTDECL; } else error(DCERR); } if((t=typespec())==0) return; if(sym==SM) return; type=t; n=decl0(); reverse(t); if (n == &null_nptr) { error(DCERR); return; } if(sym==LC || ( sym!=SM && sym!=COMMA && sym!=ASS )) { if (car(type)==CODE) { code_decl(n); return; } else if (car(type)==FUNCTION) { fdecl(n); return; } } def(n); while(sym==COMMA) { getsym(); type=t; n=decl0(); reverse(t); if(n == &null_nptr) error(DCERR); /* if(args) error(DCERR); */ def(n); } if(sym!=SM) error(DCERR); if(mode==GTDECL) mode=GDECL; if(mode==STADECL||mode==LTDECL) mode=LDECL; } int typespec(void) { int t; while (sym==KONST) { getsym(); } switch(sym) { case VOID: case INT: case CHAR: case CODE: t= sym; getsym(); break; case STRUCT: case UNION: t=sdecl(sym); break; case UNSIGNED: t = UNSIGNED; if(getsym()==INT) getsym(); break; case SHORT: t=CHAR; if(getsym()==INT) getsym(); break; case LONG: t=INT; if(getsym()==INT) getsym(); break; default: if(sym==IDENT) { if(nptr->sc==TYPE) { t=nptr->ty; getsym(); break; } else if(nptr->sc==EMPTY && gnptr->sc==TYPE) { t=gnptr->ty; getsym(); break; } } while (sym==KONST) { getsym(); } if(mode==LDECL) return 0; t= INT; } while (sym==KONST) { getsym(); } return t; } struct nametable * decl0(void) { NMTBL *n; if(sym==MUL) { getsym(); n=decl0(); type=list2(POINTER,type); return n; } return decl1(); } NMTBL * decl1(void) { NMTBL *n; int i,t; if(sym==LPAR) { getsym(); n=decl0(); checksym(RPAR); } else if (sym == IDENT) { n=nptr; getsym(); } else { /* error(DCERR); */ n= &null_nptr; } while(1) { if(sym==LBRA) { if(getsym()==RBRA) { getsym(); if(mode==ADECL) { t=type; type=list2(POINTER,type); } else if (mode==GDECL) { t=type; type=list3(ARRAY,t,0); } else { error(DCERR); } } else { t=type; i=cexpr(expr()); checksym(RBRA); type=list3(ARRAY,t,i); } } else if(sym==LPAR) { if(mode==GDECL) { mode=ADECL;getsym();mode=GDECL; /* ??? */ } else getsym(); if(sym==RPAR) getsym(); else { if (type==CODE) { n->sc=CODE; n->dsp=0; stmode=REGISTER; adecl(n); stmode=0; n->sc=EMPTY; type=list3(CODE,type,cadr(n->ty)); return n; } else { n->sc=FUNCTION; n->dsp=0; adecl(n); n->sc=EMPTY; } } type=list3(FUNCTION,type,cadr(n->ty)); } else return n; } } void adecl(NMTBL *n) { NMTBL *arg,*sfnptr; int sreg_var,t; int stype,smode; stype=type; sfnptr=fnptr; fnptr=n; sreg_var=reg_var; reg_var=0; n->dsp=0; smode = mode; /* if(mode!=GDECL && mode!=ADECL) error(DCERR); */ mode=ADECL; args= 0; for(;;) { if(sym==IDENT && nptr->sc!=TYPE) { rplacad(n->ty,glist2(INT,cadr(n->ty))); if (stmode==REGISTER && reg_var < MAX_REGISTER_VAR) { nptr->ty = INT; nptr->sc = REGISTER; if ((nptr->dsp = get_register_var())<0) error(-1); reg_var++; } else { nptr->ty = INT; nptr->sc = LVAR; nptr->dsp = args ; args += size_of_int; } getsym(); if(sym==RPAR) break; } else { if(sym==DOTS) { rplacad(n->ty,glist2(INT,cadr(n->ty))); getsym(); break; } if((t=typespec())==0) { error(DCERR); break; } if(sym!=COMMA && sym!=RPAR) { if(sym==RPAR) break; type=t; arg=decl0(); reverse(t); if (arg != &null_nptr) { /* no varname typespec only */ def(arg); } } rplacad(n->ty,glist2(t,cadr(n->ty))); if(sym==RPAR) break; } if (sym!=COMMA) error(DCERR); getsym(); } checksym(RPAR); mode=smode; reg_var=sreg_var; fnptr=sfnptr; type=stype; return; } void reverse(int t1) { int t2,t3; t2=t1; while(type!=t1) { t3=cadr(type); rplacad(type,t2); t2=type; type=t3; } type = t2; } int reverse0(int t1) { int t2,t3; t2=0; while(t1) { t3=cadr(t1); rplacad(t1,t2); t2=t1; t1=t3; } return t2; } int size(int t) { if(t==CHAR) return 1; if(t==VOID) return 0; if(scalar(t)) return size_of_int; if(car(t)==STRUCT||car(t)==UNION) { if(cadr(t)==-1) error(DCERR); return(cadr(t)); } if(car(t)==ARRAY) return(size(cadr(t))*caddr(t)); else error(DCERR); return 0; } void def(NMTBL *n) { int sz,nsc,ndsp,t; nsc=ndsp=0; if(car(type)==FUNCTION) { fcheck(n); return; } if (n->sc!=EMPTY && !(n->sc==GVAR&&n->dsp==EXTRN) && !(n->sc==FUNCTION&&n->dsp==EXTRN) && (mode!=ADECL || n->sc!=LVAR || n->ty!=INT) && (mode!=ADECL || n->sc!=REGISTER || n->ty!=INT) && ((mode!=GSDECL&&mode!=LSDECL) || n->sc!=FIELD || n->dsp!=disp) && ((mode!=GUDECL&&mode!=LUDECL) || n->sc!=FIELD || n->dsp!=0) ) error(DCERR); sz = size(n->ty = type); switch(mode) { case GDECL: gen_gdecl(n->nm,gpc); case STADECL: nsc = GVAR; ndsp = gpc; if (stmode==EXTRN) n->dsp = EXTRN; else n->dsp = ndsp; /* emit_data will override this */ n->sc = nsc; if (stmode==LDECL) { copy(n,n->nm); cheapp[-1] = '.'; ndsp = ++stat_no; while(ndsp>0) { *cheapp++ = ndsp%10+'0'; ndsp /= 10; } *cheapp++ = 0; } if(sym==ASS) { decl_data(type,n,0); emit_data_closing(n); /* gpc is incremented by emit_data */ } else gpc +=sz; return; case GSDECL: nsc = FIELD; ndsp = disp; disp += sz; break; case GUDECL: nsc = FIELD; ndsp = 0; if (disp < sz) disp = sz; break; case GTDECL: nsc = TYPE; break; case ADECL: if (stmode==REGISTER && reg_var <MAX_REGISTER_VAR) { if (type!=CHAR && !scalar(type)) error(TYERR); nptr->sc = REGISTER; reg_var++; if (nptr->dsp==0) { if ((nptr->dsp = get_register_var())<0) { error(-1); } } return; } nptr->sc = LVAR; if(type==CHAR) { /* nptr->ty=INT; */ if (nptr->dsp==0) { nptr->dsp = args; if (endian) n->dsp += size_of_int-1; } args += size_of_int; } else { if (nptr->dsp==0) nptr->dsp = args; args += sz; } if(type==VOID) { } else if (!scalar(type)) { if((t=car(type))==STRUCT || t==UNION) { nptr->ty = type; } else error(TYERR); } return; case LDECL: if (stmode==REGISTER && reg_var <=MAX_REGISTER_VAR) { if(!scalar(type)) /* non integer register type ... */ error(DCERR); nsc = REGISTER; reg_var++; if ((ndsp = get_register_var())<0) error(-1); } else { nsc = LVAR; ndsp = (disp -= sz); } n->sc = nsc; n->dsp = ndsp; if(sym==ASS) { decl_data(type,n,0); } return; case LSDECL: nsc = FIELD; ndsp = disp; disp += sz; break; case LUDECL: nsc = FIELD; ndsp = 0; if (disp < sz) disp = sz; break; case LTDECL: nsc = TYPE; break; default: error(DCERR); } n->sc = nsc; if (stmode==EXTRN) n->dsp = EXTRN; else n->dsp = ndsp; } void emit_init_vars(void) { if (!init_vars) return; init_vars = reverse0(init_vars); while(init_vars) { g_expr(car(init_vars)); init_vars = cadr(init_vars); } } int assign_data(int e, int t, NMTBL *n,int offset) { int ass; if(mode==GDECL) { emit_data(e,t,n); return offset+size(t); } else if(mode==LDECL) { if(t==CHAR) { ass =list3(CASS,list2(LVAR,n->dsp+offset),rvalue(e)); } else if (scalar(t)) { ass = list3(ASS,list2(LVAR,n->dsp+offset),rvalue(e)); } else if (car(t)==STRUCT || car(t)==UNION || car(t)==STRING) { ass = list4(SASS,list2(LVAR,n->dsp+offset),rvalue(e),size(t)); } else { error(DCERR); } init_vars = list2(ass,init_vars); return offset+size(t); } else { error(DCERR); } return 0; /* not reached */ } int decl_data(int t, NMTBL *n,int offset) { int t1,e,i,mode_save; mode_save = mode; mode=STAT; getsym(); if (scalar(t)) { e=expr1(); mode = mode_save; if(car(e)!=CONST && t==CHAR) error(TYERR); offset = assign_data(e,t,n,offset); type=t; return offset; } t1 = car(t); if (t1==ARRAY) { if (sym==LC) { mode = mode_save; t1 = cadr(t); for(i=0;;i++) { if (sym!=RC) offset=decl_data(t1,n,offset); /* array of some thing */ if (sym==COMMA) { continue; } else if (sym==RC) { if (caddr(t)==0) { /* size not defined */ heap[t+2]=i+1; /* define array size */ } else if (caddr(t)!=i+1) { /* size match? */ error(TYERR); } getsym(); return offset; } else { error(TYERR); } } } else if (cadr(t)==CHAR) { e=expr1(); mode = mode_save; if(car(e)!=STRING) error(TYERR); offset=assign_data(e,list3(ARRAY,CHAR,size(type)),n,offset); if (caddr(t)==0) { /* size not defined */ heap[t+2]=size(type); /* define array size */ } else if (caddr(t)!=size(type)) { /* size match? */ error(TYERR); } } else error(DCERR); } else if (t1==STRUCT) { mode = mode_save; if(cadr(t)==-1) error(DCERR); t1 = caddr(t); /* list of fields */ while(t1) { offset = decl_data(car(t1),n,offset); /* alignment? */ t1 = cadr(t1); if ( t1 && sym==COMMA) continue; if (!t1 && sym!=RC) error(DCERR); } getsym(); return offset; } else { mode = mode_save; error(TYERR); /* should be initialization error */ } return offset; /* not reached */ } int sdecl(int s) { int smode,sdisp,type0; NMTBL *nptr0,*gnptr0; int tags; smode=mode; if (mode==GDECL || mode==GSDECL || mode==GUDECL || mode==GTDECL) mode=(s==STRUCT?GSDECL:GUDECL); else mode=(s==STRUCT?LSDECL:LUDECL); sdisp=disp; disp=0; if (getsym() == IDENT) { nptr0 = nptr; gnptr0 = gnptr; if (getsym() == LC) { if (nptr0->sc != EMPTY) error(DCERR); nptr0->sc = TAG; tags = 0; nptr0->ty = list3(s,-1,tags); while (getsym() != RC) { decl(); tags = list2(type,tags); } getsym(); tags=reverse0(tags); heap[nptr0->ty+2]=tags; rplacad(type0 = nptr0->ty,disp); } else { /* struct tag name */ if(nptr0->sc == EMPTY) nptr0=gnptr0; if(nptr0->sc == EMPTY) error(UDERR); if(nptr0->sc != TAG) error(TYERR); tags = caddr(nptr0->ty); disp = cadr(nptr0->ty); } type0 = list3(s,disp,tags); } else if(sym==LC) { tags = 0; while(getsym() != RC) { decl(); tags = list2(type,tags); } getsym(); tags=reverse0(tags); type0 = list3(s,disp,tags); } else error(DCERR); disp=sdisp; mode=smode; return type0; } void code_decl(NMTBL *n) { int odisp; if (n->sc==EMPTY) n->sc = CODE; code_enter(n->nm); fnptr=n; disp = -args; args = 0; reg_var=0; mode=ADECL; stmode=REGISTER; while (sym!=LC) { /* argument declaration !ANSI */ decl(); getsym(); } if (args) disp = -args; else args = -disp; init_vars=0; /* local variable declaration */ stmode=0; mode=STAT; init_vars=0; odisp=disp; while (typeid(getsym()) || sym==STATIC || sym==EXTRN || sym==TYPEDEF) { mode=LDECL; decl(); mode=STAT; } control=1; code_enter1(disp-odisp,args); emit_init_vars(); while(sym!=RC) statement(); if(control) error(STERR); control=0; code_leave(n->nm); } void fdecl(NMTBL *n) { enter(n->nm); fnptr=n; retlabel=fwdlabel(); retcont = 0; args=0; reg_var=0; fcheck(n); mode=ADECL; while (sym!=LC) { /* argument declaration !ANSI */ stmode=0; decl(); getsym(); } disp=0; init_vars=0; /* local variable declaration */ mode=STAT; while (typeid(getsym()) || sym==STATIC || sym==EXTRN || sym==REGISTER || sym==TYPEDEF) { mode=LDECL; stmode=0; decl(); mode=STAT; } control=1; enter1(disp); emit_init_vars(); while(sym!=RC) statement(); leave(control,n->nm); retpending = 0; control=0; } void fcheck(NMTBL *n) { if(mode!=GDECL||car(type)!=FUNCTION) error(DCERR); if(n->sc==FUNCTION) compatible(car(n->ty),cadr(type)); else { if(n->sc!=EMPTY) error(DCERR); else { n->sc=FUNCTION; n->ty=glist2(cadr(type),0); } } } void compatible(int t1, int t2) { if(integral(t1)) { if(t1!=t2) error(TYERR); } else if(car(t1)!=car(t2)) error(TYERR); else if((car(t1)==STRUCT || car(t1)==UNION) && cadr(t1)!=cadr(t2)) error(TYERR); else if(car(t1)==POINTER || car(t1)==ARRAY ||car(t1)==FUNCTION) compatible(cadr(t1),cadr(t2)); } int scalar(int t) { return(integral(t)||car(t)==POINTER); } int integral(int t) { return(t==INT||t==CHAR||t==UNSIGNED); } void checkret(void) { if (retpending) { ret(); control=0; retpending=0; } } void statement(void) { int slfree; if(sym==SM) { getsym(); return; } checkret(); switch(sym) { case IF: doif(); return; case WHILE: dowhile(); return; case DO: dodo(); return; case FOR: dofor(); return; case SWITCH: doswitch(); return; case LC: docomp(); return; case BREAK: jmp(blabel); getsym(); checksym(SM); return; case CONTINUE: jmp(clabel); getsym(); checksym(SM); return; case CASE: docase(); statement(); return; case DEFAULT: dodefault(); statement(); return; case RETURN: doreturn(); return; case GOTO: dogoto(); return; default: if(sym==IDENT&&skipspc()==':') { dolabel(); statement(); } else { slfree=lfree; gexpr(expr()); lfree=slfree; checksym(SM); } } } void doif(void) { int l1,l2,slfree; getsym(); checksym(LPAR); slfree=lfree; bexpr(expr(),0,l1=fwdlabel()); lfree=slfree; checksym(RPAR); statement(); checkret(); if(sym==ELSE) { if ((l2 = control)) jmp(l2=fwdlabel()); fwddef(l1); getsym(); statement(); checkret(); if (l2) fwddef(l2); } else fwddef(l1); } void dowhile(void) { int sbreak,scontinue,slfree,e; sbreak=blabel; scontinue=clabel; blabel=fwdlabel(); clabel=backdef(); getsym(); checksym(LPAR); slfree=lfree; e=expr(); checksym(RPAR); if(sym==SM) { bexpr(e,1,clabel); lfree=slfree; getsym(); } else { bexpr(e,0,blabel); lfree=slfree; statement(); checkret(); if(control) jmp(clabel); } fwddef(blabel); clabel=scontinue; blabel=sbreak; } void dodo(void) { int sbreak,scontinue,l,slfree; sbreak=blabel; scontinue=clabel; blabel=fwdlabel(); clabel=fwdlabel(); l=backdef(); getsym(); statement(); checkret(); fwddef(clabel); checksym(WHILE); checksym(LPAR); slfree=lfree; bexpr(expr(),1,l); lfree=slfree; checksym(RPAR); checksym(SM); fwddef(blabel); clabel=scontinue; blabel=sbreak; } void dofor(void) { int sbreak,scontinue,l,e,slfree; sbreak=blabel; scontinue=clabel; blabel=fwdlabel(); getsym(); checksym(LPAR); slfree=lfree; if(sym!=SM) { gexpr(expr()); checksym(SM); } else getsym(); lfree=slfree; l=backdef(); if(sym!=SM) { bexpr(expr(),0,blabel); checksym(SM); } else getsym(); lfree=slfree; if(sym==RPAR) { clabel=l; getsym(); statement(); checkret(); } else { clabel=fwdlabel(); e=expr(); checksym(RPAR); statement(); checkret(); fwddef(clabel); gexpr(e); lfree=slfree; } jmp(l); fwddef(blabel); clabel=scontinue; blabel=sbreak; } void doswitch(void) { int sbreak,scase,sdefault,slfree,svalue; sbreak=blabel; /* save parents break label */ blabel=fwdlabel(); sdefault=dlabel; /* save parents default label */ dlabel=0; scase=cslabel; /* save parents next case label */ getsym(); checksym(LPAR); slfree=lfree; svalue=csvalue1; /* save parents switch value */ gexpr(expr()); csvalue1=csvalue ; lfree=slfree; checksym(RPAR); cslabel = control = 0; /* should be case statement but... */ statement(); checkret(); if(dlabel) def_label(cslabel,dlabel); else fwddef(cslabel); csvalue1=svalue; cslabel=scase; dlabel=sdefault; fwddef(blabel); blabel=sbreak; } void docomp(void) { getsym(); while(sym!=RC) { statement(); checkret();} getsym(); } void docase(void) { int c,l,slfree; c=0; slfree=lfree; while(sym==CASE) { getsym(); c=list2(cexpr(expr()),c); checksym(COLON); } l=fwdlabel(); if (control) { control=0; jmp(l); } if (cslabel) fwddef(cslabel); while(cadr(c)) { cmpdimm(car(c),csvalue1); jcond(l,0); c=cadr(c); } lfree=slfree; cmpdimm(car(c),csvalue1); jcond(cslabel=fwdlabel(),1); fwddef(l); } void dodefault(void) { getsym(); checksym(COLON); if (dlabel) error(STERR); if (!cslabel) jmp(cslabel = fwdlabel()); dlabel = backdef(); } void doreturn(void) { int slfree; if(getsym()==SM) { getsym(); retpending = 1; return; } slfree=lfree; gexpr(expr()); lfree=slfree; checksym(SM); retpending = 1; } void dogoto(void) { NMTBL *nptr0; int t,e1,e2,env; getsym(); e1 = expr(); t=car(e1); if (t==FNAME) { nptr0 = (NMTBL *)cadr(e1); t = nptr0->sc; if (t==EMPTY) { nptr0->sc = FLABEL; jmp(nptr0->dsp = fwdlabel()); } else if (t==FLABEL||t==BLABEL) { jmp(nptr0->dsp); } control=0; checksym(SM); return; } if (t==COMMA) { env = caddr(e1); e1 = cadr(e1); t = car(e1); } else { env = 0; } if (t==FUNCTION) { e2 = cadr(e1); if (car(e2) == FNAME) { nptr0=(NMTBL *)cadr(e2); nptr0->sc = CODE; } gexpr(list3(CODE,e1,env)); control=0; checksym(SM); return; } error(STERR); return; } void dolabel(void) { if(nptr->sc == FLABEL) fwddef(nptr->dsp); else if(nptr->sc != EMPTY) error(TYERR); nptr->sc = BLABEL; nptr->dsp = backdef(); getsym(); checksym(COLON); } int expr(void) { return(rvalue(expr0())); } int expr0(void) { int e; e=expr1(); while(sym==COMMA) { getsym();e=list3(COMMA,e,rvalue(expr1())); } return e; } int expr1(void) { int e1,e2,t,op; e1=expr2(); switch (sym) { case ASS: lcheck(e1); t=type; getsym(); e2=rvalue(expr1()); if(t==VOID) error(TYERR); if(t==CHAR) { type= INT;return(list3(CASS,e1,e2)); } else if(!scalar(t)&&(car(t)==STRUCT||car(t)==UNION)) { type= t;return(list4(SASS,e1,e2,size(t))); } type=t; return(list3(ASS,e1,e2)); case ADD+AS: case SUB+AS: case MUL+AS: case DIV+AS: case MOD+AS: case RSHIFT+AS: case LSHIFT+AS: case BAND+AS: case EOR+AS: case BOR+AS: op = sym-AS; lcheck(e1); t=type; getsym(); e2=rvalue(expr1()); if(!integral(type)) error(TYERR); if((t==UNSIGNED||type==UNSIGNED)&& (op==MUL||op==DIV||op==MOD||op==RSHIFT||op==LSHIFT)) op=op+US; if(t==CHAR) { type= INT; return(list4(CASSOP,e1,e2,op)); } type=t; if(integral(t)) return(list4(ASSOP,e1,e2,op)); if((op!=ADD&&op!=SUB)||car(t)!=POINTER) error(TYERR); e2=binop(MUL,e2,list2(CONST,size(cadr(t))),INT,UNSIGNED); type=t; return list4(ASSOP,e1,e2,op); default: return(e1); } } int expr2(void) { int e1,e2,e3,t; e1=expr3(); if(sym==COND) { e1=rvalue(e1); getsym(); e2=rvalue(expr2()); t=type; checksym(COLON); e3=rvalue(expr2()); if(car(e1)==CONST) { if(cadr(e1)) { type=t;return e2; } else return e3; } if(type==INT||(t!=INT&&type==UNSIGNED)) type=t; return(list4(COND,e1,e2,e3)); } return(e1); } int expr3(void) { int e; e=expr4(); while(sym==LOR) { e=rvalue(e); getsym(); e=list3(LOR,e,rvalue(expr4())); type= INT; } return(e); } int expr4(void) { int e; e=expr5(); while(sym==LAND) { e=rvalue(e); getsym(); e=list3(LAND,e,rvalue(expr5())); type= INT; } return(e); } int expr5(void) { int e1,e2,t; e1=expr6(); while(sym==BOR) { e1=rvalue(e1); t=type; getsym(); e2=rvalue(expr6()); e1=binop(BOR,e1,e2,t,type); } return(e1); } int expr6(void) { int e1,e2,t; e1=expr7(); while(sym==EOR) { e1=rvalue(e1); t=type; getsym(); e2=rvalue(expr7()); e1=binop(EOR,e1,e2,t,type); } return(e1); } int expr7(void) { int e1,e2,t; e1=expr8(); while(sym==BAND) { e1=rvalue(e1); t=type; getsym(); e2=rvalue(expr8()); e1=binop(BAND,e1,e2,t,type); } return(e1); } int expr8(void) { int e,op; e=expr9(); while((op=sym)==EQ||op==NEQ) { e=rvalue(e); getsym(); e=list3(op,e,rvalue(expr9())); type= INT; } return e; } int expr9(void) { int e1,e2,t,op; e1=expr10(); while((op=sym)==GT||op==GE||op==LT||op==LE) { e1=rvalue(e1); t=type; getsym(); e2=rvalue(expr10()); if(t==INT&&type==INT) e1=list3(op,e1,e2); else e1=list3(op+US,e1,e2); type= INT; } return e1; } int expr10(void) { int e1,e2,t,op; e1=expr11(); while((op=sym)==RSHIFT||op==LSHIFT) { e1=rvalue(e1); t=type; getsym(); e2=rvalue(expr11()); e1=binop(op,e1,e2,t,type); } return e1; } int expr11(void) { int e1,e2,t,op; e1=expr12(); while((op=sym)==ADD||op==SUB) { e1=rvalue(e1); t=type; getsym(); e2=rvalue(expr12()); e1=binop(op,e1,e2,t,type); } return e1; } int expr12(void) { int e1,e2,t,op; e1=expr13(); while((op=sym)==MUL||op==DIV||op==MOD) { e1=rvalue(e1); t=type; getsym(); e2=rvalue(expr13()); e1=binop(op,e1,e2,t,type); } return e1; } int expr13(void) { int e,op; switch (op = sym) { case INC: case DEC: getsym(); lcheck(e=expr13()); if(type==CHAR) { type= INT; return(list2(op==INC?CPREINC:CPREDEC,e)); } if(integral(type)) return(list3(PREINC,e,op==INC?1:-1)); if(car(type)!=POINTER) error(TYERR); return(list3(PREINC,e, op==INC?size(cadr(type)):-size(cadr(type)) )); case MUL: getsym(); e=rvalue(expr13()); return(indop(e)); case BAND: getsym(); switch(car(e=expr13())) { case INDIRECT: e=cadr(e); break; case GVAR: case LVAR: e=list2(ADDRESS,e); break; case FNAME: return e; default:error(LVERR); } type=list2(POINTER,type); return e; case SUB: getsym(); e=rvalue(expr13()); if(!integral(type)) error(TYERR); return(car(e)==CONST?list2(CONST,-cadr(e)):list2(MINUS,e)); case BNOT: getsym(); e=rvalue(expr13()); if(!integral(type)) error(TYERR); return(car(e)==CONST?list2(CONST,~cadr(e)):list2(BNOT,e)); case LNOT: getsym(); e=rvalue(expr13()); if(!scalar(type)) error(TYERR); return(car(e)==CONST?list2(CONST,!cadr(e)):list2(LNOT,e)); case SIZEOF: if(getsym()==LPAR) { if(typeid(getsym())) { e=list2(CONST,size(typename())); type=INT; checksym(RPAR); return e; } else { e=expr0(); checksym(RPAR); expr16(e); if(sym==INC||sym==DEC) { getsym(); if(type==CHAR) type=INT; else if(!scalar(type)) error(TYERR); } } } else expr13(); e=list2(CONST,size(type)); type=INT; return e; } e=expr14(); if((op=sym)==INC||op==DEC) { lcheck(e); getsym(); if(type==CHAR) { type= INT; return(list2(op==INC?CPOSTINC:CPOSTDEC,e)); } if(integral(type)) return(list3(POSTINC,e,op==INC?1:-1)); if(car(type)!=POINTER) error(TYERR); return (list3(POSTINC,e, op == INC ? size(cadr(type)): -size(cadr(type)) )); } return e; } int expr14(void) { int e1,t; switch(sym) { case IDENT: switch(nptr->sc) { case GVAR: e1=list3(GVAR,nptr->dsp,(int)nptr->nm); type=nptr->ty; getsym(); break; case LVAR: e1=list2(LVAR,nptr->dsp); type=nptr->ty; getsym(); break; case REGISTER: e1=list2(REGISTER,nptr->dsp); type=nptr->ty; getsym(); break; case FMACRO: fmacro(); getsym(); return expr(); case FLABEL: case BLABEL: case FUNCTION: case CODE: e1=list2(FNAME,(int)nptr); type=list3(nptr->sc,car(nptr->ty),cadr(nptr->ty)); getsym(); break; case EMPTY: if(getsym()==LPAR) { nptr->sc = FUNCTION; nptr->ty= glist2(INT,0); type= list3(FUNCTION,INT,0); e1=expr15(list2(FNAME,(int)nptr)); break; } else { e1=list2(FNAME,(int)nptr); type=list3(nptr->sc,nptr->ty,0); break; } default:error(UDERR); } break; case STRING: e1=list3(STRING,(int)sptr,symval); type=list3(ARRAY,CHAR,symval); getsym(); break; case CONST: type= INT; e1=list2(CONST,symval); getsym(); break; case RETURN: if (fnptr->sc != FUNCTION) { error(STERR); } type=list2(POINTER,CODE); e1=list2(RETURN,(int)fnptr); getsym(); break; case DEFINED: getsym(); t = mode; mode = IFDEF; checksym(LPAR); mode = t; type= INT; e1=list2(CONST,symval); getsym(); checksym(RPAR); break; case ENVIRONMENT: type=list2(POINTER,VOID); e1=list2(ENVIRONMENT,0); getsym(); break; case LPAR: if(typeid(getsym())) { t=typename(); checksym(RPAR); e1=expr13(); type=t; return e1; } e1=expr0(); checksym(RPAR); break; default:error(EXERR); } return expr16(e1); } int expr16(int e1) { int e2,t; while(1) { if(sym==LBRA) { e1=rvalue(e1); t=type; getsym(); e2=rvalue(expr0()); checksym(RBRA); e1=binop(ADD,e1,e2,t,type); e1=indop(e1); } else if(sym==LPAR) e1=expr15(e1); else if(sym==PERIOD) e1=strop(e1); else if(sym==ARROW) e1=strop(indop(rvalue(e1))); else break; } if(car(e1)==FNAME) type=list2(POINTER,type); return e1; } int rvalue(int e) { int t; if(type==CHAR) { type= INT; switch(car(e)) { case GVAR: return(list3(CRGVAR,cadr(e),caddr(e))); case LVAR: return(list2(CRLVAR,cadr(e))); case INDIRECT: return(list2(CRINDIRECT,cadr(e))); default:return(e); } } if(!integral(type)&&type!=VOID) { if(type==CODE) { return(e); } else if((t=car(type))==ARRAY) { type=list2(POINTER,cadr(type)); if(car(e)==INDIRECT) return cadr(e); return list2(ADDRESS,e); } else if(t==STRUCT || t==UNION) { return e; } else if(t!=POINTER) error(TYERR); } switch(car(e)) { case GVAR: return(list3(RGVAR,cadr(e),caddr(e))); case LVAR: return(list2(RLVAR,cadr(e))); case INDIRECT: return(list2(RINDIRECT,cadr(e))); default:return(e); } } void lcheck(int e) { int t; if(!scalar(type)|| (car(e)!=GVAR&&car(e)!=LVAR&&car(e)!=INDIRECT&&car(e)!=REGISTER)) if ((t=car(type))<0 && t!=STRUCT && t!=UNION) error(LVERR); } int indop(int e) { if(type!=INT&&type!=UNSIGNED) { if(car(type)==POINTER) type=cadr(type); else error(TYERR); } else type= CHAR; if(car(e)==ADDRESS) return(cadr(e)); return(list2(INDIRECT,e)); } int strop(int e) { getsym(); if (sym!=IDENT||nptr->sc!=FIELD) error(TYERR); if (integral(type)||(car(type)!=STRUCT && car(type)!=UNION)) e=rvalue(e); type = nptr->ty; switch(car(e)) { case GVAR: e=list2(INDIRECT,list3(ADD,e,list2(CONST,nptr->dsp))); break; case LVAR: e=list2(car(e),cadr(e) + nptr->dsp); break; case INDIRECT: if(!nptr->dsp) break; e=list2(INDIRECT,list3(ADD,cadr(e),list2(CONST,nptr->dsp))); break; default: e=list2(INDIRECT,list3(ADD,e,list2(CONST,nptr->dsp))); } getsym(); return e; } int binop(int op, int e1, int e2, int t1, int t2) { int e; if(car(e1)==CONST&&car(e2)==CONST) { e1=cadr(e1); e2=cadr(e2); type= INT; switch(op) { case BOR: e=e1|e2;break; case EOR: e=e1^e2;break; case BAND: e=e1&e2;break; case ADD: if(integral(t1)) { if(integral(t2)) { e=e1+e2; } else { if(car(t2)!=POINTER) error(TYERR); e=size(cadr(t2))*e1+e2; type=t2; } } else { if(car(t1)!=POINTER) error(TYERR); e=e1+size(cadr(t1))*e2; type=t1; } break; case SUB: if(integral(t1)) { e=e1-e2; } else { if(car(t1)!=POINTER) error(TYERR); e=e1-size(cadr(t1))*e2; type=t1; } break; case MUL: e=e1*e2;break; case DIV: if(!e2) error(EXERR);e=e1/e2;break; case MOD: if(!e2) error(EXERR);e=e1%e2;break; case RSHIFT: e=e1>>e2;break; case LSHIFT: e=e1<<e2; } return list2(CONST,e); } if((op==ADD||op==MUL||op==BOR||op==EOR||op==BAND)&& (car(e1)==CONST||(car(e2)!=CONST&& (car(e1)==RGVAR||car(e1)==RLVAR)))) { e=e1;e1=e2;e2=e;e=t1;t1=t2;t2=e; } if(op==ADD) { if(integral(t1)) { if(integral(t2)) { if(t1==INT) type=t2;else type=t1; return(list3(ADD,e1,e2)); } if(car(t2)!=POINTER) error(TYERR); e=binop(MUL,e1,list2(CONST,size(cadr(t2))),t1,INT); type=t2; return(list3(ADD,e,e2)); } if(car(t1)!=POINTER||!integral(t2)) error(TYERR); e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT); type=t1; if(car(e1)==ADDRESS&&car(e)==CONST&&car(cadr(e1))!=GVAR) return(list2(ADDRESS,list2(car(cadr(e1)), cadr(cadr(e1))+cadr(e)))); return(list3(ADD,e1,e)); } if(op==SUB) { if(integral(t1)) { if(!integral(t2)) error(TYERR); if(t1==INT) type=t2;else type=t1; return(list3(SUB,e1,e2)); } if(car(t1)!=POINTER) error(TYERR); if(integral(t2)) { e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT); type=t1; return(list3(SUB,e1,e)); } if(car(t2)!=POINTER) error(TYERR); compatible(t1,t2); e=list3(SUB,e1,e2); e=binop(DIV,e,list2(CONST,size(cadr(t1))),UNSIGNED,INT); type= INT; return e; } if(!integral(t1)||!integral(t2)) error(TYERR); if(t1==INT) type=t2;else type=t1; if((op==MUL||op==DIV)&&car(e2)==CONST&&cadr(e2)==1) return e1; if(op==BOR||op==EOR||op==BAND) return(list3(op,e1,e2)); return(list3(type==UNSIGNED?op+US:op,e1,e2)); } int expr15(int e1) { int t,arglist,e; t=type; if(integral(t)|| (car(t)!=FUNCTION && car(t)!=CODE)) error(TYERR); getsym(); arglist=0; while(sym!=RPAR) { e=rvalue(expr1()); arglist=list3(e,arglist,type); if(sym!=COMMA) break; getsym(); } checksym(RPAR); if(car(t)!=CODE) { t=cadr(t); if(t==CHAR) type= INT;else type=t; } return list3(FUNCTION,e1,arglist); } int typeid(int s) { return (integral(s) || s==CODE || s==SHORT || s==LONG || s==STRUCT || s==UNION || (s==IDENT && nptr->sc==TYPE)); } int typename(void) { int t; type=t=typespec(); ndecl0(); reverse(t); return type; } int ndecl0(void) { if(sym==MUL) { getsym(); return type=list2(POINTER,ndecl0()); } return ndecl1(); } int ndecl1(void) { int i,t,arglist; if(sym==LPAR) { if(getsym()==RPAR) { type=list3(FUNCTION,type,0); getsym(); } else { ndecl0(); checksym(RPAR); } } while(1) { if(sym==LBRA) { getsym(); t=type; i=cexpr(expr()); checksym(RBRA); type=list3(ARRAY,t,i); } else if(sym==LPAR) { t = type; getsym(); arglist=0; while(sym!=RPAR) { ndecl0(); arglist=list2(type,arglist); if(sym!=COMMA) break; getsym(); } checksym(RPAR); type=list3(FUNCTION,t,arglist); } else return type; } } int cexpr(int e) { if (car(e) != CONST) error(CNERR); return (cadr(e)); } int in_comment = 0; int getsym(void) { NMTBL *nptr0,*nptr1,*nptrm; int i,macro_type; char c,*macro; if (alpha(skipspc())) { i = hash = 0; name = namebuf; while (alpha(ch) || digit(ch)) { if (i < LBUFSIZE-1) hash=(7*hash ^ (name[i++]=ch)); getch(); } name[i++] = '\0'; nptrm=msearch(name); if (mode==MDECL) { nptr = nptrm; return (sym==MACRO); } if (mode==IFDEF) { if (nptrm->sc == MACRO||nptrm->sc==FMACRO) { return (symval=1); } else { return (symval=0); } } if (nptrm->sc!=EMPTY && !recursive_macro((char *)car((nptrm->dsp)))) { if (nptrm->sc == FMACRO) { nptr = nptrm; sym = IDENT; return sym; } if ((macro_type = nptrm->ty)!=0) { macro = (char *)(car(nptrm->dsp)); while (!(macro_type<=0||cadddr(macro_type)==mflag)) { macro = (char *)car(caddr(macro_type)); macro_type = cadr(macro_type); } if (macro_type) { /* fprintf(stderr,"%d: macro %s save: ch=%c chptr=%s\n",lineno,name,ch,chptr); */ chptrsave = list4((int)chptr,chptrsave,ch, list2((int)nptrm,(int)macro)); if (macro_type!=-1) { mflag--; } chptr = macro; getch(); sym = getsym(); if (macro_type!=-1) { mflag++; } return sym; } } /* else diffrent depth level localmacro leave it alone */ } nptr0 = gsearch(); if (nptr0->sc == RESERVE) return sym = nptr0->dsp; sym = IDENT; gnptr=nptr=nptr0; if (mode==ADECL && nptr0->sc ==TYPE) return sym; if (mode==GDECL || mode==GSDECL || mode==GUDECL || mode==GTDECL || mode==TOP) { return sym; } nptr1=lsearch(nptr0->nm); if (mode==STAT) { if (nptr1->sc == EMPTY) return sym; } nptr=nptr1; return sym; } else if (digit(ch)) { symval=0; if (ch == '0') { if (getch() == 'x' || ch == 'X') { while(1) { if(digit(getch())) symval=symval*16+ch-'0'; else if('a'<=ch&&ch<='f') symval=symval*16+ch-'a'+10; else if('A'<=ch&&ch<='F') symval=symval*16+ch-'A'+10; else break; } } else { while (digit(ch)) { symval=symval*8+ch-'0';getch(); } } } else { while(digit(ch)) { symval=symval*10+ch-'0';getch(); } } return sym=CONST; } else if(ch=='\'') { getch(); symval=escape(); if(ch!='\'') error(CHERR); getch(); return sym=CONST; } else if(ch=='"') { getstring(); return sym= STRING; } c=ch; getch(); switch(c) { case '*': return postequ(MUL,MUL+AS); case '&': if(ch=='&') {getch();return sym=LAND;} return postequ(BAND,BAND+AS); case '-': if(ch=='>') {getch();return sym=ARROW;} if(ch=='-') {getch();return sym=DEC;} return postequ(SUB,SUB+AS); case '!': return postequ(LNOT,NEQ); case '~': return sym=BNOT; case '+': if(ch=='+') {getch();return sym=INC;} return postequ(ADD,ADD+AS); case '%': return postequ(MOD,MOD+AS); case '^': return postequ(EOR,EOR+AS); case '|': if(ch=='|') {getch();return sym=LOR;} return postequ(BOR,BOR+AS); case '=': return postequ(ASS,EQ); case '>': if(ch=='>') {getch();return postequ(RSHIFT,RSHIFT+AS);} return postequ(GT,GE); case '<': if(ch=='<') {getch();return postequ(LSHIFT,LSHIFT+AS);} return postequ(LT,LE); case '(': return sym=LPAR; case ')': return sym=RPAR; case '[': return sym=LBRA; case ']': return sym=RBRA; case '{': return sym=LC; case '}': return sym=RC; case ',': return sym=COMMA; case ';': return sym=SM; case ':': return sym=COLON; case '?': return sym=COND; case '.': if(ch=='.') { getch(); if (ch=='.') { getch(); return sym=DOTS; } error(CHERR); return getsym(); } else return sym=PERIOD; case '/': if(ch!='*') return postequ(DIV,DIV+AS); in_comment = 1; getch(); while(ch=='*'?getch()!='/':getch()); in_comment = 0; getch(); return getsym(); default: error(CHERR); return getsym(); } } int postequ(int s1, int s2) { if(ch=='=') {getch();return sym=s2;} return sym=s1; } int alpha(char c) { return(('a'<=c&&c<='z')||('A'<=c&&c<='Z')||c=='_'); } int digit(char c) { return('0'<=c&&c<='9'); } NMTBL * gsearch(void) { NMTBL *nptr,*iptr; iptr=nptr= &ntable[hash % GSYMS]; while(nptr->sc!=0 && neqname(nptr->nm,name)) { if (++nptr== &ntable[GSYMS]) nptr=ntable; if (nptr==iptr) error(GSERR); } if (nptr->sc == 0) { copy(nptr,name); nptr->sc=EMPTY; } return nptr; } NMTBL * lsearch(char *name) { NMTBL *nptr,*iptr; iptr=nptr= &ntable[hash%LSYMS+GSYMS]; while(nptr->sc!=0 && neqname(nptr->nm,name)) { if (++nptr== &ntable[LSYMS+GSYMS]) nptr= &ntable[GSYMS]; if (nptr==iptr) error(LSERR); } if (nptr->sc == 0) { nptr->nm=name; /* already saved in gsearch */ nptr->sc=EMPTY; nptr->dsp=0; } return nptr; } NMTBL * msearch(char *name) { NMTBL *nptr,*iptr; iptr=nptr= &mtable[hash%MSYMS]; while(nptr->sc!=0 && neqname(nptr->nm,name)) { if (++nptr== &mtable[MSYMS]) nptr= &mtable[0]; if (nptr==iptr) error(MSERR); } if (nptr->sc == 0) { copy(nptr,name); nptr->sc=EMPTY; nptr->dsp=0; nptr->ty=0; } return nptr; } NMTBL * msearch0(char *name) { NMTBL *nptr,*iptr; int hash,i; i = 0; hash = 0; while((name[i])) { hash=((7*hash) ^ name[i++]); } iptr=nptr= &mtable[hash%MSYMS]; while(nptr->sc!=0 && neqname(nptr->nm,name)) { if (++nptr== &mtable[MSYMS]) nptr= &mtable[0]; if (nptr==iptr) error(MSERR); } if (nptr->sc == 0) { copy(nptr,name); nptr->sc=EMPTY; nptr->dsp=0; nptr->ty=0; } return nptr; } void copy(NMTBL *nptr, char *s) { nptr->nm = cheapp; while((*cheapp++ = *s++)); } int neqname(char *p,char *q) { if (!p) return 0; while(*p && *p!='.') if(*p++ != *q++) return 1; return (*q!=0); } void getstring(void) { getch(); symval = 0; sptr = cheapp; while (ch != '"') { *cheapp++ = escape(); symval++; if (cheapp >= cheap+CHEAPSIZE) error(STRERR); } getch(); *cheapp++ = '\0'; symval++; } int skipspc(void) { while(ch=='\t'||ch=='\n'||ch==' '||ch=='\r') getch(); return ch; } int getch(void) { NMTBL *nptr0; int sargs; if(*chptr) return ch = *chptr++; while (chptrsave) { nptr0=(NMTBL *)car(cadddr(chptrsave)); if (nptr0->sc==FMACRO) { sargs = cadr(nptr0->dsp); while(sargs) { local_undef(car(sargs)); sargs = cadr(sargs); } mflag--; } chptr=(char *)car(chptrsave); ch=caddr(chptrsave); chptrsave=cadr(chptrsave); /* fprintf(stderr,"macro end: ch=%c chptr=%s\n",ch,chptr); */ if (ch) return ch; } getline(); return getch(); } char escape(void) { char c; if ((c=ch) == '\\') { if (digit(c=getch())) { c = ch-'0'; if (digit(getch())) { c = c*8+ch-'0'; if (digit(getch())) { c=c*8+ch-'0';getch(); } } return c; } getch(); switch(c) { case 'n': return '\n'; case 't': return '\t'; case 'b': return '\b'; case 'r': return '\r'; case 'f': return '\f'; case '\n': return escape(); default: return c; } } if (c == '\n') error(EXERR); getch(); return c; } FILE * getfname(void) { int i; char *s,name[LBUFSIZE]; FILE *fp; getch(); if(skipspc()!='"') error(INCERR); for(i=0;(getch()!='"' && ch!='\n');) { if(i<LBUFSIZE-1) name[i++]=ch; } if(ch=='\n') error(INCERR); name[i]=0; fp = fopen(name,"r") ; s = name; (filep+1)->name0 = cheapp; while((*cheapp++ = *s++)); return ( (filep+1)->fcb = fp ); } static int macro_if_depth ; static int macro_if_current ; static int macro_if_skip ; void getline(void) { int i; int c; do { lineno++; glineno++; chptr=linebuf; i=0; while ((*chptr++ = c = getc(filep->fcb)) != '\n') { if (++i > LBUFSIZE-2) error(LNERR); if (c==EOF) { error(EOFERR); --chptr; } } *chptr = '\0'; if (lsrc && !asmf && !macro_if_skip) gen_comment(linebuf); if (*(chptr = linebuf) == '#' && !in_comment) { macro_processing(); } } while(macro_if_skip || linebuf[0] == '#'); } void macro_processing() { int i; int c; int mode_save; ++chptr; if (macroeq("ifdef") || macroeq("ifndef")) { c = (chptr[-4]=='n'); macro_if_current++; if (!macro_if_skip) { mode_save = mode; mode = IFDEF; ch= *chptr; i = getsym(); mode = mode_save; macro_if_depth = macro_if_current; macro_if_skip = (!i)^c; } return; } else if (macroeq("if")) { macro_if_current++; if (!macro_if_skip) { for(c=0;chptr[c];c++); chptr[c] = ';'; /* this can't happen in macro expression */ ch= *chptr; getsym(); i=cexpr(expr()); macro_if_depth = macro_if_current; macro_if_skip = !i; } return; } else if (macroeq("else")) { if (macro_if_current==0) { error(MCERR); /* extra #else */ return; } if (macro_if_current == macro_if_depth) macro_if_skip = !macro_if_skip; return; } else if (macroeq("endif")) { if (macro_if_current == macro_if_depth) { macro_if_skip = 0; macro_if_depth = --macro_if_current; } else { if (macro_if_current<=0) { error(MCERR); /* extra #if */ return; } macro_if_current--; } return; } if (macro_if_skip) return; if (macroeq("define")) { macro_define0(); *(chptr = linebuf) = '\0'; } else if (macroeq("undef")) { i=mode; mode=LDECL; ch= *chptr; if (getsym() == IDENT) { if (nptr->sc == MACRO) { nptr->sc = EMPTY; } else if (nptr->sc == FMACRO) { nptr->sc = EMPTY; /* we cannot reclaim it's arg */ } else error(MCERR); } mode=i; } else if (macroeq("include")) { if(filep+1 >= filestack + FILES) error(FILERR); if ( ((filep+1)->fcb=getfname()) == NULL) error(FILERR); (filep+1)->ln=lineno; lineno=0; ++filep; *(chptr = linebuf) = '\0'; } else if (macroeq("asm")) { if (asmf) error(MCERR); asmf = 1; getline(); while (asmf) { gen_source(linebuf); getline(); } } else if (macroeq("endasm")) { if (!asmf) error(MCERR); asmf = 0; } else if (macroeq(" ")) getline(); else error(MCERR); } int macroeq(char *s) { char *p; for (p = chptr; *s;) if (*s++ != *p++) return 0; chptr = p; return 1; } void macro_define(char *macro) { char *chptr_save; int chsave; chptr_save = chptr; chsave = ch; chptr = macro; ch= *chptr++; macro_define0(); chptr = chptr_save; ch = chsave; } void macro_define0() { int i,args,c; i=mode; mode=MDECL; ch= *chptr; getsym(); /* fprintf(stderr,"macro def: %s\n",name); */ if (nptr->sc != EMPTY) { /* override exisiting macro */ } args = 0; if (ch=='(') { nptr->sc = FMACRO; args = macro_args(); } else { nptr->sc = MACRO; /* -1 means gloabl macro, 0 means no macro, >0 means local macro */ nptr->ty = -1; } nptr->dsp = glist2((int)cheapp,args); while ((*cheapp++ = c = *chptr++) && c != '\n'); *cheapp++ = '\0'; if (cheapp >= cheap+CHEAPSIZE) /* too late? */ error(STRERR); mode=i; } int macro_args() { int c; int in_quote = 0; int in_wquote = 0; int plevel = 0; int args = glist2((int)cheapp,0); for(;;) { *cheapp++ = c = *chptr++; if (!c) { chptr--; error(MCERR); return reverse0(args); } if (in_quote) { if (c=='\\') { if (*chptr != '\n') { *cheapp++ = *chptr++; } else { getline(); } } else if (c=='\'') { in_quote = 0; } } else if (in_wquote) { if (c=='\\') { if (*chptr !='\n') { *cheapp++ = *chptr++; } else { *cheapp = '\n'; getline(); } } else if (c=='"') { in_wquote = 0; } } else if (c=='"') { in_wquote = 1; } else if (c=='\'') { in_quote = 1; } if (plevel==0) { if (c==',') { cheapp[-1] = 0; args = glist2((int)cheapp,args); } else if (c==')') { cheapp[-1] = 0; break; } else if (c=='(') { plevel++; } else if (c=='\\') { if (*chptr=='\n') { cheapp--; getline(); } } else if (c==' '||c=='\t') { cheapp--; } else if (c=='\n') { cheapp--; getline(); } } else if (c==')') { plevel--; } else if (c=='\n') { cheapp--; getline(); } } ch = *chptr; if (ch) chptr++; return reverse0(args); } void fmacro() { int args,values; args = cadr(nptr->dsp); values = macro_args(); mflag++; while(args) { local_define(car(args),car(values)); args = cadr(args); values = cadr(values); } /* fprintf(stderr,"%d: fmacro %s save: ch=%c chptr=%s\n",lineno,nptr->nm,ch,chptr); */ chptrsave = list4((int)chptr,chptrsave,ch,list2((int)nptr,car(nptr->dsp))); chptr = (char *)car(nptr->dsp); getch(); } int recursive_macro(char *macro) { int save = chptrsave; while(save) { if (cadr(cadddr(save))==(int)macro) return 1; save = cadr(save); } return 0; } void local_define(char *macro,char *value) { NMTBL *nptr0; nptr0 = msearch0(macro); nptr0->ty=list4(nptr0->sc,nptr0->ty,nptr0->dsp,mflag); nptr0->sc=MACRO; nptr0->dsp=list2((int)value,0); } void local_undef(char *macro) { NMTBL *nptr0; int save; nptr0 = msearch0(macro); save = nptr0->ty; nptr0->sc=car(save); nptr0->dsp=caddr(save); nptr0->ty=cadr(save); } int list2(int e1, int e2) { int e; e=getfree(2); heap[e]=e1; heap[e+1]=e2; return e; } int list3(int e1, int e2, int e3) { int e; e=getfree(3); heap[e]=e1; heap[e+1]=e2; heap[e+2]=e3; return e; } int list4(int e1, int e2, int e3, int e4) { int e; e=getfree(4); heap[e]=e1; heap[e+1]=e2; heap[e+2]=e3; heap[e+3]=e4; return e; } int getfree(int n) { int e; switch (mode) { case GDECL: case GSDECL: case GUDECL: case GTDECL: e=gfree; gfree+=n; break; default: lfree-=n; e=lfree; } if(lfree<gfree) error(HPERR); return e; } int glist2(int e1,int e2) { int smode,ret; smode = mode; mode = GDECL; ret = list2(e1,e2); mode = smode; return ret; } int rplacad(int e, int n) { heap[e+1]=n; return e; } int rplacadd(int e, int n) { heap[e+2]=n; return e; } void display_ntable(NMTBL *n, char *s) { fprintf(stderr,"\n%s %0x %0x ",s,(int)n,(int)ntable); fprintf(stderr,"nptr->sc %d ",n->sc); fprintf(stderr,"nptr->dsp %d ",n->dsp); fprintf(stderr,"nptr->ty %d ",n->ty); fprintf(stderr,"nptr->nm %s\n",n->nm); } /* end */