/avr 20000000775 forsyth sys 1154021146 0 /avr/mkfile 664 forsyth sys 1074096086 279 #include #define Windows (1<<2) /* hack - can't include cc.h because of clashes */ #define Chunk (1*1024*1024) void* mysbrk(ulong size) { void *v; static int chunk; static uchar *brk; if(chunk < size) { chunk = Chunk; if(chunk < size) chunk = Chunk + size; brk = VirtualAlloc(NULL, chunk, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(brk == 0) return (void*)-1; } v = brk; chunk -= size; brk += size; return v; } int mycreat(char *n, int p) { return create(n, 1, p); } int mywait(int *s) { fprint(2, "mywait called\n"); abort(); return 0; } int mydup(int f1, int f2) { fprint(2, "mydup called\n"); abort(); return 0; } int mypipe(int *fd) { fprint(2, "mypipe called\n"); abort(); return 0; } int systemtype(int sys) { return sys&Windows; } int pathchar(void) { return '/'; } char* mygetwd(char *path, int len) { return getcwd(path, len); } int myexec(char *path, char *argv[]) { fprint(2, "myexec called\n"); abort(); return 0; } int myfork(void) { fprint(2, "myfork called\n"); abort(); return 0; } /* * fake mallocs */ void* malloc(uint n) { return mysbrk(n); } void* calloc(uint m, uint n) { return mysbrk(m*n); } void* realloc(void *p, uint n) { void *new; new = malloc(n); if(new && p) memmove(new, p, n); return new; } void free(void *p) { } int myaccess(char *f) { int fd; fd = open(f, OREAD); if(fd < 0) return -1; close(fd); return 0; } /avr/cc/Plan9.c 664 forsyth sys 1070357162 931 #include "cc.h" void* mysbrk(ulong size) { return sbrk(size); } int mycreat(char *n, int p) { return create(n, 1, p); } int mywait(int *s) { int p; Waitmsg *w; if((w = wait()) == nil) return -1; else{ p = w->pid; *s = 0; if(w->msg[0]) *s = 1; free(w); return p; } } int mydup(int f1, int f2) { return dup(f1,f2); } int mypipe(int *fd) { return pipe(fd); } int systemtype(int sys) { return sys&Plan9; } int pathchar(void) { return '/'; } char* mygetwd(char *path, int len) { return getwd(path, len); } int myexec(char *path, char *argv[]) { return exec(path, argv); } int myfork(void) { return fork(); } /* * fake mallocs */ void* malloc(ulong n) { return alloc(n); } void* calloc(ulong m, ulong n) { return alloc(m*n); } void* realloc(void*, ulong) { fprint(2, "realloc called\n"); abort(); return 0; } void free(void*) { } int myaccess(char *f) { return access(f, AEXIST); } /avr/cc/Posix.c 664 forsyth sys 1070357162 818 #include "cc.h" void* mysbrk(ulong size) { return (void*)sbrk(size); } int mycreat(char *n, int p) { return create(n, 1, p); } int mywait(int *s) { return wait(s); } int mydup(int f1, int f2) { return dup2(f1,f2); } int mypipe(int *fd) { return pipe(fd); } int systemtype(int sys) { return sys&Unix; } int pathchar(void) { return '/'; } char* mygetwd(char *path, int len) { return (char*)getcwd(path, len); } int myexec(char *path, char *argv[]) { return execvp(path, argv); } /* * fake mallocs */ void* malloc(uint n) { return alloc(n); } void* calloc(uint m, uint n) { return alloc(m*n); } void* realloc(void *p, uint n) { fprint(2, "realloc called\n"); abort(); return 0; } void free(void *p) { } int myfork(void) { return fork(); } int myaccess(char *f) { return access(f, 0); } /avr/cc/acid.c 664 forsyth sys 1070357260 5314 #include "cc.h" static char *kwd[] = { "$adt", "$aggr", "$append", "$complex", "$defn", "$delete", "$do", "$else", "$eval", "$head", "$if", "$local", "$loop", "$return", "$tail", "$then", "$union", "$whatis", "$while", }; char* amap(char *s) { int i, bot, top, new; bot = 0; top = bot + nelem(kwd) - 1; while(bot <= top){ new = bot + (top - bot)/2; i = strcmp(kwd[new]+1, s); if(i == 0) return kwd[new]; if(i < 0) bot = new + 1; else top = new - 1; } return s; } Sym* acidsue(Type *t) { int h; Sym *s; if(t != T) for(h=0; hlink) if(s->suetag && s->suetag->link == t) return s; return 0; } Sym* acidfun(Type *t) { int h; Sym *s; for(h=0; hlink) if(s->type == t) return s; return 0; } char acidchar[NTYPE]; Init acidcinit[] = { TCHAR, 'C', 0, TUCHAR, 'b', 0, TSHORT, 'd', 0, TUSHORT, 'u', 0, TLONG, 'D', 0, TULONG, 'U', 0, TVLONG, 'V', 0, TUVLONG, 'W', 0, TFLOAT, 'f', 0, TDOUBLE, 'F', 0, TARRAY, 'a', 0, TIND, 'X', 0, -1, 0, 0, }; static void acidinit(void) { Init *p; for(p=acidcinit; p->code >= 0; p++) acidchar[p->code] = p->value; acidchar[TINT] = acidchar[TLONG]; acidchar[TUINT] = acidchar[TULONG]; if(types[TINT]->width != types[TLONG]->width) { acidchar[TINT] = acidchar[TSHORT]; acidchar[TUINT] = acidchar[TUSHORT]; if(types[TINT]->width != types[TSHORT]->width) warn(Z, "acidmember int not long or short"); } } void acidmember(Type *t, long off, int flag) { Sym *s, *s1; Type *l; static int acidcharinit = 0; if(acidcharinit == 0) { acidinit(); acidcharinit = 1; } s = t->sym; switch(t->etype) { default: Bprint(&outbuf, " T%d\n", t->etype); break; case TIND: if(s == S) break; if(flag) { for(l=t; l->etype==TIND; l=l->link) ; if(typesu[l->etype]) { s1 = acidsue(l->link); if(s1 != S) { Bprint(&outbuf, " 'A' %s %ld %s;\n", amap(s1->name), t->offset+off, amap(s->name)); break; } } } else { Bprint(&outbuf, "\tprint(\"\t%s\t\", addr.%s\\X, \"\\n\");\n", amap(s->name), amap(s->name)); break; } case TINT: case TUINT: case TCHAR: case TUCHAR: case TSHORT: case TUSHORT: case TLONG: case TULONG: case TVLONG: case TUVLONG: case TFLOAT: case TDOUBLE: case TARRAY: if(s == S) break; if(flag) { Bprint(&outbuf, " '%c' %ld %s;\n", acidchar[t->etype], t->offset+off, amap(s->name)); } else { Bprint(&outbuf, "\tprint(\"\t%s\t\", addr.%s, \"\\n\");\n", amap(s->name), amap(s->name)); } break; case TSTRUCT: case TUNION: s1 = acidsue(t->link); if(s1 == S) break; if(flag) { if(s == S) { Bprint(&outbuf, " {\n"); for(l = t->link; l != T; l = l->down) acidmember(l, t->offset+off, flag); Bprint(&outbuf, " };\n"); } else { Bprint(&outbuf, " %s %ld %s;\n", amap(s1->name), t->offset+off, amap(s->name)); } } else { if(s != S) { Bprint(&outbuf, "\tprint(\"%s %s {\\n\");\n", amap(s1->name), amap(s->name)); Bprint(&outbuf, "\t%s(addr.%s);\n", amap(s1->name), amap(s->name)); Bprint(&outbuf, "\tprint(\"}\\n\");\n"); } else { Bprint(&outbuf, "\tprint(\"%s {\\n\");\n", amap(s1->name)); Bprint(&outbuf, "\t\t%s(addr+%ld);\n", amap(s1->name), t->offset+off); Bprint(&outbuf, "\tprint(\"}\\n\");\n"); } } break; } } void acidtype(Type *t) { Sym *s; Type *l; Io *i; int n; char *an; if(!debug['a']) return; if(debug['a'] > 1) { n = 0; for(i=iostack; i; i=i->link) n++; if(n > 1) return; } s = acidsue(t->link); if(s == S) return; switch(t->etype) { default: Bprint(&outbuf, "T%d\n", t->etype); return; case TUNION: case TSTRUCT: if(debug['s']) goto asmstr; an = amap(s->name); Bprint(&outbuf, "sizeof%s = %ld;\n", an, t->width); Bprint(&outbuf, "aggr %s\n{\n", an); for(l = t->link; l != T; l = l->down) acidmember(l, 0, 1); Bprint(&outbuf, "};\n\n"); Bprint(&outbuf, "defn\n%s(addr) {\n\tcomplex %s addr;\n", an, an); for(l = t->link; l != T; l = l->down) acidmember(l, 0, 0); Bprint(&outbuf, "};\n\n"); break; asmstr: if(s == S) break; for(l = t->link; l != T; l = l->down) if(l->sym != S) Bprint(&outbuf, "#define\t%s.%s\t%ld\n", s->name, l->sym->name, l->offset); break; } } void acidvar(Sym *s) { int n; Io *i; Type *t; Sym *s1, *s2; if(!debug['a'] || debug['s']) return; if(debug['a'] > 1) { n = 0; for(i=iostack; i; i=i->link) n++; if(n > 1) return; } t = s->type; while(t && t->etype == TIND) t = t->link; if(t == T) return; if(t->etype == TENUM) { Bprint(&outbuf, "%s = ", amap(s->name)); if(!typefd[t->etype]) Bprint(&outbuf, "%lld;\n", s->vconst); else Bprint(&outbuf, "%f\n;", s->fconst); return; } if(!typesu[t->etype]) return; s1 = acidsue(t->link); if(s1 == S) return; switch(s->class) { case CAUTO: case CPARAM: s2 = acidfun(thisfn); if(s2) Bprint(&outbuf, "complex %s %s:%s;\n", amap(s1->name), amap(s2->name), amap(s->name)); break; case CSTATIC: case CEXTERN: case CGLOBL: case CLOCAL: Bprint(&outbuf, "complex %s %s;\n", amap(s1->name), amap(s->name)); break; } } /avr/cc/bits.c 664 forsyth sys 1070357260 850 #include "cc.h" Bits bor(Bits a, Bits b) { Bits c; int i; for(i=0; ib[i]) return 1; return 0; } int beq(Bits a, Bits b) { int i; for(i=0; i #include #include #include #pragma lib "../cc/cc.a$O" #ifndef EXTERN #define EXTERN extern #endif typedef struct Node Node; typedef struct Sym Sym; typedef struct Type Type; typedef struct Funct Funct; typedef struct Decl Decl; typedef struct Io Io; typedef struct Hist Hist; typedef struct Term Term; typedef struct Init Init; typedef struct Bits Bits; #define NHUNK 50000L #define BUFSIZ 8192 #define NSYMB 500 #define NHASH 1024 #define STRINGSZ 200 #define HISTSZ 20 #define YYMAXDEPTH 500 #define NTERM 10 #define MAXALIGN 7 #define SIGN(n) ((vlong)1<<(n-1)) #define MASK(n) (SIGN(n)|(SIGN(n)-1)) #define BITS 5 #define NVAR (BITS*sizeof(ulong)*8) struct Bits { ulong b[BITS]; }; struct Node { Node* left; Node* right; void* label; long pc; int reg; long xoffset; double fconst; /* fp constant */ vlong vconst; /* non fp const */ char* cstring; /* character string */ ushort* rstring; /* rune string */ Sym* sym; Type* type; long lineno; char op; char class; char etype; char complex; char addable; char scale; char garb; }; #define Z ((Node*)0) struct Sym { Sym* link; Type* type; Type* suetag; Type* tenum; char* macro; long varlineno; long offset; vlong vconst; double fconst; Node* label; ushort lexical; char *name; ushort block; ushort sueblock; char class; char sym; char aused; }; #define S ((Sym*)0) struct Decl { Decl* link; Sym* sym; Type* type; long varlineno; long offset; short val; ushort block; char class; char aused; }; #define D ((Decl*)0) struct Type { Sym* sym; Sym* tag; Funct* funct; Type* link; Type* down; long width; long offset; long lineno; char shift; char nbits; char etype; char garb; }; #define T ((Type*)0) #define NODECL ((void(*)(int, Type*, Sym*))0) struct Init /* general purpose initialization */ { int code; ulong value; char* s; }; EXTERN struct { char* p; int c; } fi; struct Io { Io* link; char* p; char b[BUFSIZ]; short c; short f; }; #define I ((Io*)0) struct Hist { Hist* link; char* name; long line; long offset; }; #define H ((Hist*)0) EXTERN Hist* hist; struct Term { vlong mult; Node *node; }; enum { Axxx, Ael1, Ael2, Asu2, Aarg0, Aarg1, Aarg2, Aaut3, NALIGN, }; enum /* also in ../{8a,0a}.h */ { Plan9 = 1<<0, Unix = 1<<1, Windows = 1<<2, }; enum { DMARK, DAUTO, DSUE, DLABEL, }; enum { OXXX, OADD, OADDR, OAND, OANDAND, OARRAY, OAS, OASI, OASADD, OASAND, OASASHL, OASASHR, OASDIV, OASHL, OASHR, OASLDIV, OASLMOD, OASLMUL, OASLSHR, OASMOD, OASMUL, OASOR, OASSUB, OASXOR, OBIT, OBREAK, OCASE, OCAST, OCOMMA, OCOND, OCONST, OCONTINUE, ODIV, ODOT, ODOTDOT, ODWHILE, OENUM, OEQ, OFOR, OFUNC, OGE, OGOTO, OGT, OHI, OHS, OIF, OIND, OINDREG, OINIT, OLABEL, OLDIV, OLE, OLIST, OLMOD, OLMUL, OLO, OLS, OLSHR, OLT, OMOD, OMUL, ONAME, ONE, ONOT, OOR, OOROR, OPOSTDEC, OPOSTINC, OPREDEC, OPREINC, OPROTO, OREGISTER, ORETURN, OSET, OSIGN, OSIZE, OSTRING, OLSTRING, OSTRUCT, OSUB, OSWITCH, OUNION, OUSED, OWHILE, OXOR, ONEG, OCOM, OPOS, OELEM, OTST, /* used in some compilers */ OINDEX, OFAS, OEND }; enum { TXXX, TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, TFUNC, TARRAY, TVOID, TSTRUCT, TUNION, TENUM, NTYPE, TAUTO = NTYPE, TEXTERN, TSTATIC, TTYPEDEF, TTYPESTR, TREGISTER, TCONSTNT, TVOLATILE, TUNSIGNED, TSIGNED, TDOT, TFILE, TOLD, NALLTYPES, }; enum { CXXX, CAUTO, CEXTERN, CGLOBL, CSTATIC, CLOCAL, CTYPEDEF, CTYPESTR, CPARAM, CSELEM, CLABEL, CEXREG, NCTYPES, }; enum { GXXX = 0, GCONSTNT = 1<<0, GVOLATILE = 1<<1, NGTYPES = 1<<2, }; enum { BCHAR = 1L< ltag %type gctname gcname cname gname tname %type gctnlist gcnlist zgnlist %type tlist sbody complex %type types %type zarglist arglist zcexpr %type name block stmnt cexpr expr xuexpr pexpr %type zelist elist adecl slist uexpr string lstring %type xdecor xdecor2 labels label ulstmnt %type adlist edecor tag qual qlist %type abdecor abdecor1 abdecor2 abdecor3 %type zexpr lexpr init ilist %left ';' %left ',' %right '=' LPE LME LMLE LDVE LMDE LRSHE LLSHE LANDE LXORE LORE %right '?' ':' %left LOROR %left LANDAND %left '|' %left '^' %left '&' %left LEQ LNE %left '<' '>' LLE LGE %left LLSH LRSH %left '+' '-' %left '*' '/' '%' %right LMM LPP LMG '.' '[' '(' %token LNAME LTYPE %token LFCONST LDCONST %token LCONST LLCONST LUCONST LULCONST LVLCONST LUVLCONST %token LSTRING LLSTRING %token LAUTO LBREAK LCASE LCHAR LCONTINUE LDEFAULT LDO %token LDOUBLE LELSE LEXTERN LFLOAT LFOR LGOTO %token LIF LINT LLONG LREGISTER LRETURN LSHORT LSIZEOF LUSED %token LSTATIC LSTRUCT LSWITCH LTYPEDEF LTYPESTR LUNION LUNSIGNED %token LWHILE LVOID LENUM LSIGNED LCONSTNT LVOLATILE LSET LSIGNOF %% prog: | prog xdecl /* * external declarator */ xdecl: zctlist ';' { dodecl(xdecl, lastclass, lasttype, Z); } | zctlist xdlist ';' | zctlist xdecor { lastdcl = T; firstarg = S; dodecl(xdecl, lastclass, lasttype, $2); if(lastdcl == T || lastdcl->etype != TFUNC) { diag($2, "not a function"); lastdcl = types[TFUNC]; } thisfn = lastdcl; markdcl(); firstdcl = dclstack; argmark($2, 0); } pdecl { argmark($2, 1); } block { Node *n; n = revertdcl(); if(n) $6 = new(OLIST, n, $6); if(!debug['a'] && !debug['P']) codgen($6, $2); } xdlist: xdecor { dodecl(xdecl, lastclass, lasttype, $1); } | xdecor { $1 = dodecl(xdecl, lastclass, lasttype, $1); } '=' init { doinit($1->sym, $1->type, 0L, $4); } | xdlist ',' xdlist xdecor: xdecor2 | '*' zgnlist xdecor { $$ = new(OIND, $3, Z); $$->garb = simpleg($2); } xdecor2: tag | '(' xdecor ')' { $$ = $2; } | xdecor2 '(' zarglist ')' { $$ = new(OFUNC, $1, $3); } | xdecor2 '[' zexpr ']' { $$ = new(OARRAY, $1, $3); } /* * automatic declarator */ adecl: { $$ = Z; } | adecl ctlist ';' { $$ = dodecl(adecl, lastclass, lasttype, Z); if($1 != Z) if($$ != Z) $$ = new(OLIST, $1, $$); else $$ = $1; } | adecl ctlist adlist ';' { $$ = $1; if($3 != Z) { $$ = $3; if($1 != Z) $$ = new(OLIST, $1, $3); } } adlist: xdecor { dodecl(adecl, lastclass, lasttype, $1); $$ = Z; } | xdecor { $1 = dodecl(adecl, lastclass, lasttype, $1); } '=' init { long w; w = $1->sym->type->width; $$ = doinit($1->sym, $1->type, 0L, $4); $$ = contig($1->sym, $$, w); } | adlist ',' adlist { $$ = $1; if($3 != Z) { $$ = $3; if($1 != Z) $$ = new(OLIST, $1, $3); } } /* * parameter declarator */ pdecl: | pdecl ctlist pdlist ';' pdlist: xdecor { dodecl(pdecl, lastclass, lasttype, $1); } | pdlist ',' pdlist /* * structure element declarator */ edecl: tlist { lasttype = $1; } zedlist ';' | edecl tlist { lasttype = $2; } zedlist ';' zedlist: /* extension */ { lastfield = 0; edecl(CXXX, lasttype, S); } | edlist edlist: edecor { dodecl(edecl, CXXX, lasttype, $1); } | edlist ',' edlist edecor: xdecor { lastbit = 0; firstbit = 1; } | tag ':' lexpr { $$ = new(OBIT, $1, $3); } | ':' lexpr { $$ = new(OBIT, Z, $2); } /* * abstract declarator */ abdecor: { $$ = (Z); } | abdecor1 abdecor1: '*' zgnlist { $$ = new(OIND, (Z), Z); $$->garb = simpleg($2); } | '*' zgnlist abdecor1 { $$ = new(OIND, $3, Z); $$->garb = simpleg($2); } | abdecor2 abdecor2: abdecor3 | abdecor2 '(' zarglist ')' { $$ = new(OFUNC, $1, $3); } | abdecor2 '[' zexpr ']' { $$ = new(OARRAY, $1, $3); } abdecor3: '(' ')' { $$ = new(OFUNC, (Z), Z); } | '[' zexpr ']' { $$ = new(OARRAY, (Z), $2); } | '(' abdecor1 ')' { $$ = $2; } init: expr | '{' ilist '}' { $$ = new(OINIT, invert($2), Z); } qual: '[' lexpr ']' { $$ = new(OARRAY, $2, Z); } | '.' ltag { $$ = new(OELEM, Z, Z); $$->sym = $2; } | qual '=' qlist: init ',' | qlist init ',' { $$ = new(OLIST, $1, $2); } | qual | qlist qual { $$ = new(OLIST, $1, $2); } ilist: qlist | init | qlist init { $$ = new(OLIST, $1, $2); } zarglist: { $$ = Z; } | arglist { $$ = invert($1); } arglist: name | tlist abdecor { $$ = new(OPROTO, $2, Z); $$->type = $1; } | tlist xdecor { $$ = new(OPROTO, $2, Z); $$->type = $1; } | '.' '.' '.' { $$ = new(ODOTDOT, Z, Z); } | arglist ',' arglist { $$ = new(OLIST, $1, $3); } block: '{' adecl slist '}' { $$ = invert($3); if($2 != Z) $$ = new(OLIST, $2, $$); if($$ == Z) $$ = new(OLIST, Z, Z); } slist: { $$ = Z; } | slist stmnt { $$ = new(OLIST, $1, $2); } labels: label | labels label { $$ = new(OLIST, $1, $2); } label: LCASE expr ':' { $$ = new(OCASE, $2, Z); } | LDEFAULT ':' { $$ = new(OCASE, Z, Z); } | LNAME ':' { $$ = new(OLABEL, dcllabel($1, 1), Z); } stmnt: error ';' { $$ = Z; } | ulstmnt | labels ulstmnt { $$ = new(OLIST, $1, $2); } ulstmnt: zcexpr ';' | { markdcl(); } block { $$ = revertdcl(); if($$) $$ = new(OLIST, $$, $2); else $$ = $2; } | LIF '(' cexpr ')' stmnt { $$ = new(OIF, $3, new(OLIST, $5, Z)); if($5 == Z) warn($3, "empty if body"); } | LIF '(' cexpr ')' stmnt LELSE stmnt { $$ = new(OIF, $3, new(OLIST, $5, $7)); if($5 == Z) warn($3, "empty if body"); if($7 == Z) warn($3, "empty else body"); } | LFOR '(' zcexpr ';' zcexpr ';' zcexpr ')' stmnt { $$ = new(OFOR, new(OLIST, $5, new(OLIST, $3, $7)), $9); } | LWHILE '(' cexpr ')' stmnt { $$ = new(OWHILE, $3, $5); } | LDO stmnt LWHILE '(' cexpr ')' ';' { $$ = new(ODWHILE, $5, $2); } | LRETURN zcexpr ';' { $$ = new(ORETURN, $2, Z); $$->type = thisfn->link; } | LSWITCH '(' cexpr ')' stmnt { $$ = new(OCONST, Z, Z); $$->vconst = 0; $$->type = types[TINT]; $3 = new(OSUB, $$, $3); $$ = new(OCONST, Z, Z); $$->vconst = 0; $$->type = types[TINT]; $3 = new(OSUB, $$, $3); $$ = new(OSWITCH, $3, $5); } | LBREAK ';' { $$ = new(OBREAK, Z, Z); } | LCONTINUE ';' { $$ = new(OCONTINUE, Z, Z); } | LGOTO ltag ';' { $$ = new(OGOTO, dcllabel($2, 0), Z); } | LUSED '(' zelist ')' ';' { $$ = new(OUSED, $3, Z); } | LSET '(' zelist ')' ';' { $$ = new(OSET, $3, Z); } zcexpr: { $$ = Z; } | cexpr zexpr: { $$ = Z; } | lexpr lexpr: expr { $$ = new(OCAST, $1, Z); $$->type = types[TLONG]; } cexpr: expr | cexpr ',' cexpr { $$ = new(OCOMMA, $1, $3); } expr: xuexpr | expr '*' expr { $$ = new(OMUL, $1, $3); } | expr '/' expr { $$ = new(ODIV, $1, $3); } | expr '%' expr { $$ = new(OMOD, $1, $3); } | expr '+' expr { $$ = new(OADD, $1, $3); } | expr '-' expr { $$ = new(OSUB, $1, $3); } | expr LRSH expr { $$ = new(OASHR, $1, $3); } | expr LLSH expr { $$ = new(OASHL, $1, $3); } | expr '<' expr { $$ = new(OLT, $1, $3); } | expr '>' expr { $$ = new(OGT, $1, $3); } | expr LLE expr { $$ = new(OLE, $1, $3); } | expr LGE expr { $$ = new(OGE, $1, $3); } | expr LEQ expr { $$ = new(OEQ, $1, $3); } | expr LNE expr { $$ = new(ONE, $1, $3); } | expr '&' expr { $$ = new(OAND, $1, $3); } | expr '^' expr { $$ = new(OXOR, $1, $3); } | expr '|' expr { $$ = new(OOR, $1, $3); } | expr LANDAND expr { $$ = new(OANDAND, $1, $3); } | expr LOROR expr { $$ = new(OOROR, $1, $3); } | expr '?' cexpr ':' expr { $$ = new(OCOND, $1, new(OLIST, $3, $5)); } | expr '=' expr { $$ = new(OAS, $1, $3); } | expr LPE expr { $$ = new(OASADD, $1, $3); } | expr LME expr { $$ = new(OASSUB, $1, $3); } | expr LMLE expr { $$ = new(OASMUL, $1, $3); } | expr LDVE expr { $$ = new(OASDIV, $1, $3); } | expr LMDE expr { $$ = new(OASMOD, $1, $3); } | expr LLSHE expr { $$ = new(OASASHL, $1, $3); } | expr LRSHE expr { $$ = new(OASASHR, $1, $3); } | expr LANDE expr { $$ = new(OASAND, $1, $3); } | expr LXORE expr { $$ = new(OASXOR, $1, $3); } | expr LORE expr { $$ = new(OASOR, $1, $3); } xuexpr: uexpr | '(' tlist abdecor ')' xuexpr { $$ = new(OCAST, $5, Z); dodecl(NODECL, CXXX, $2, $3); $$->type = lastdcl; } | '(' tlist abdecor ')' '{' ilist '}' /* extension */ { $$ = new(OSTRUCT, $6, Z); dodecl(NODECL, CXXX, $2, $3); $$->type = lastdcl; } uexpr: pexpr | '*' xuexpr { $$ = new(OIND, $2, Z); } | '&' xuexpr { $$ = new(OADDR, $2, Z); } | '+' xuexpr { $$ = new(OPOS, $2, Z); } | '-' xuexpr { $$ = new(ONEG, $2, Z); } | '!' xuexpr { $$ = new(ONOT, $2, Z); } | '~' xuexpr { $$ = new(OCOM, $2, Z); } | LPP xuexpr { $$ = new(OPREINC, $2, Z); } | LMM xuexpr { $$ = new(OPREDEC, $2, Z); } | LSIZEOF uexpr { $$ = new(OSIZE, $2, Z); } | LSIGNOF uexpr { $$ = new(OSIGN, $2, Z); } pexpr: '(' cexpr ')' { $$ = $2; } | LSIZEOF '(' tlist abdecor ')' { $$ = new(OSIZE, Z, Z); dodecl(NODECL, CXXX, $3, $4); $$->type = lastdcl; } | LSIGNOF '(' tlist abdecor ')' { $$ = new(OSIGN, Z, Z); dodecl(NODECL, CXXX, $3, $4); $$->type = lastdcl; } | pexpr '(' zelist ')' { $$ = new(OFUNC, $1, Z); if($1->op == ONAME) if($1->type == T) dodecl(xdecl, CXXX, types[TINT], $$); $$->right = invert($3); } | pexpr '[' cexpr ']' { $$ = new(OIND, new(OADD, $1, $3), Z); } | pexpr LMG ltag { $$ = new(ODOT, new(OIND, $1, Z), Z); $$->sym = $3; } | pexpr '.' ltag { $$ = new(ODOT, $1, Z); $$->sym = $3; } | pexpr LPP { $$ = new(OPOSTINC, $1, Z); } | pexpr LMM { $$ = new(OPOSTDEC, $1, Z); } | name | LCONST { $$ = new(OCONST, Z, Z); $$->type = types[TINT]; $$->vconst = $1; } | LLCONST { $$ = new(OCONST, Z, Z); $$->type = types[TLONG]; $$->vconst = $1; } | LUCONST { $$ = new(OCONST, Z, Z); $$->type = types[TUINT]; $$->vconst = $1; } | LULCONST { $$ = new(OCONST, Z, Z); $$->type = types[TULONG]; $$->vconst = $1; } | LDCONST { $$ = new(OCONST, Z, Z); $$->type = types[TDOUBLE]; $$->fconst = $1; } | LFCONST { $$ = new(OCONST, Z, Z); $$->type = types[TFLOAT]; $$->fconst = $1; } | LVLCONST { $$ = new(OCONST, Z, Z); $$->type = types[TVLONG]; $$->vconst = $1; } | LUVLCONST { $$ = new(OCONST, Z, Z); $$->type = types[TUVLONG]; $$->vconst = $1; } | string | lstring string: LSTRING { $$ = new(OSTRING, Z, Z); $$->type = typ(TARRAY, types[TCHAR]); $$->type->width = $1.l + 1; $$->cstring = $1.s; $$->sym = symstring; $$->etype = TARRAY; $$->class = CSTATIC; } | string LSTRING { char *s; int n; n = $1->type->width - 1; s = alloc(n+$2.l+MAXALIGN); memcpy(s, $1->cstring, n); memcpy(s+n, $2.s, $2.l); s[n+$2.l] = 0; $$ = $1; $$->type->width += $2.l; $$->cstring = s; } lstring: LLSTRING { $$ = new(OLSTRING, Z, Z); $$->type = typ(TARRAY, types[TUSHORT]); $$->type->width = $1.l + sizeof(ushort); $$->rstring = (ushort*)$1.s; $$->sym = symstring; $$->etype = TARRAY; $$->class = CSTATIC; } | lstring LLSTRING { char *s; int n; n = $1->type->width - sizeof(ushort); s = alloc(n+$2.l+MAXALIGN); memcpy(s, $1->rstring, n); memcpy(s+n, $2.s, $2.l); *(ushort*)(s+n+$2.l) = 0; $$ = $1; $$->type->width += $2.l; $$->rstring = (ushort*)s; } zelist: { $$ = Z; } | elist elist: expr | elist ',' elist { $$ = new(OLIST, $1, $3); } sbody: '{' { $$.t1 = strf; $$.t2 = strl; strf = T; strl = T; lastbit = 0; firstbit = 1; } edecl '}' { $$ = strf; strf = $2.t1; strl = $2.t2; } zctlist: { lastclass = CXXX; lasttype = types[TINT]; } | ctlist types: complex { $$.t = $1; $$.c = CXXX; } | tname { $$.t = simplet($1); $$.c = CXXX; } | gcnlist { $$.t = simplet($1); $$.c = simplec($1); $$.t = garbt($$.t, $1); } | complex gctnlist { $$.t = $1; $$.c = simplec($2); $$.t = garbt($$.t, $2); if($2 & ~BCLASS & ~BGARB) diag(Z, "duplicate types given: %T and %Q", $1, $2); } | tname gctnlist { $$.t = simplet(typebitor($1, $2)); $$.c = simplec($2); $$.t = garbt($$.t, $2); } | gcnlist complex zgnlist { $$.t = $2; $$.c = simplec($1); $$.t = garbt($$.t, $1|$3); } | gcnlist tname { $$.t = simplet($2); $$.c = simplec($1); $$.t = garbt($$.t, $1); } | gcnlist tname gctnlist { $$.t = simplet(typebitor($2, $3)); $$.c = simplec($1|$3); $$.t = garbt($$.t, $1|$3); } tlist: types { $$ = $1.t; if($1.c != CXXX) diag(Z, "illegal combination of class 4: %s", cnames[$1.c]); } ctlist: types { lasttype = $1.t; lastclass = $1.c; } complex: LSTRUCT ltag { dotag($2, TSTRUCT, 0); $$ = $2->suetag; } | LSTRUCT ltag { dotag($2, TSTRUCT, autobn); } sbody { $$ = $2->suetag; if($$->link != T) diag(Z, "redeclare tag: %s", $2->name); $$->link = $4; suallign($$); } | LSTRUCT sbody { taggen++; sprint(symb, "_%d_", taggen); $$ = dotag(lookup(), TSTRUCT, autobn); $$->link = $2; suallign($$); } | LUNION ltag { dotag($2, TUNION, 0); $$ = $2->suetag; } | LUNION ltag { dotag($2, TUNION, autobn); } sbody { $$ = $2->suetag; if($$->link != T) diag(Z, "redeclare tag: %s", $2->name); $$->link = $4; suallign($$); } | LUNION sbody { taggen++; sprint(symb, "_%d_", taggen); $$ = dotag(lookup(), TUNION, autobn); $$->link = $2; suallign($$); } | LENUM ltag { dotag($2, TENUM, 0); $$ = $2->suetag; if($$->link == T) $$->link = types[TINT]; $$ = $$->link; } | LENUM ltag { dotag($2, TENUM, autobn); } '{' { en.tenum = T; en.cenum = T; } enum '}' { $$ = $2->suetag; if($$->link != T) diag(Z, "redeclare tag: %s", $2->name); if(en.tenum == T) { diag(Z, "enum type ambiguous: %s", $2->name); en.tenum = types[TINT]; } $$->link = en.tenum; $$ = en.tenum; } | LENUM '{' { en.tenum = T; en.cenum = T; } enum '}' { $$ = en.tenum; } | LTYPE { $$ = tcopy($1->type); } gctnlist: gctname | gctnlist gctname { $$ = typebitor($1, $2); } zgnlist: { $$ = 0; } | zgnlist gname { $$ = typebitor($1, $2); } gctname: tname | gname | cname gcnlist: gcname | gcnlist gcname { $$ = typebitor($1, $2); } gcname: gname | cname enum: LNAME { doenum($1, Z); } | LNAME '=' expr { doenum($1, $3); } | enum ',' | enum ',' enum tname: /* type words */ LCHAR { $$ = BCHAR; } | LSHORT { $$ = BSHORT; } | LINT { $$ = BINT; } | LLONG { $$ = BLONG; } | LSIGNED { $$ = BSIGNED; } | LUNSIGNED { $$ = BUNSIGNED; } | LFLOAT { $$ = BFLOAT; } | LDOUBLE { $$ = BDOUBLE; } | LVOID { $$ = BVOID; } cname: /* class words */ LAUTO { $$ = BAUTO; } | LSTATIC { $$ = BSTATIC; } | LEXTERN { $$ = BEXTERN; } | LTYPEDEF { $$ = BTYPEDEF; } | LTYPESTR { $$ = BTYPESTR; } | LREGISTER { $$ = BREGISTER; } gname: /* garbage words */ LCONSTNT { $$ = BCONSTNT; } | LVOLATILE { $$ = BVOLATILE; } name: LNAME { $$ = new(ONAME, Z, Z); if($1->class == CLOCAL) $1 = mkstatic($1); $$->sym = $1; $$->type = $1->type; $$->etype = TVOID; if($$->type != T) $$->etype = $$->type->etype; $$->xoffset = $1->offset; $$->class = $1->class; $1->aused = 1; } tag: ltag { $$ = new(ONAME, Z, Z); $$->sym = $1; $$->type = $1->type; $$->etype = TVOID; if($$->type != T) $$->etype = $$->type->etype; $$->xoffset = $1->offset; $$->class = $1->class; } ltag: LNAME | LTYPE %% /avr/cc/com.c 664 forsyth sys 1070357260 18765 #include "cc.h" void complex(Node *n) { if(n == Z) return; nearln = n->lineno; if(debug['t']) if(n->op != OCONST) prtree(n, "pre complex"); if(tcom(n)) return; if(debug['t']) if(n->op != OCONST) prtree(n, "t complex"); ccom(n); if(debug['t']) if(n->op != OCONST) prtree(n, "c complex"); acom(n); if(debug['t']) if(n->op != OCONST) prtree(n, "a complex"); xcom(n); if(debug['t']) if(n->op != OCONST) prtree(n, "x complex"); } /* * evaluate types * evaluate lvalues (addable == 1) */ enum { ADDROF = 1<<0, CASTOF = 1<<1, ADDROP = 1<<2, }; int tcom(Node *n) { return tcomo(n, ADDROF); } int tcomo(Node *n, int f) { Node *l, *r; Type *t; int o; if(n == Z) { diag(Z, "Z in tcom"); errorexit(); } n->addable = 0; l = n->left; r = n->right; switch(n->op) { default: diag(n, "unknown op in type complex: %O", n->op); goto bad; case ODOTDOT: /* * tcom has already been called on this subtree */ *n = *n->left; if(n->type == T) goto bad; break; case OCAST: if(n->type == T) break; if(n->type->width == types[TLONG]->width) { if(tcomo(l, ADDROF|CASTOF)) goto bad; } else if(tcom(l)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, n->type, tcast)) goto bad; break; case ORETURN: if(l == Z) { if(n->type->etype != TVOID) warn(n, "null return of a typed function"); break; } if(tcom(l)) goto bad; typeext(n->type, l); if(tcompat(n, n->type, l->type, tasign)) break; constas(n, n->type, l->type); if(!sametype(n->type, l->type)) { l = new1(OCAST, l, Z); l->type = n->type; n->left = l; } break; case OASI: /* same as as, but no test for const */ n->op = OAS; o = tcom(l); if(o | tcom(r)) goto bad; typeext(l->type, r); if(tlvalue(l) || tcompat(n, l->type, r->type, tasign)) goto bad; if(!sametype(l->type, r->type)) { r = new1(OCAST, r, Z); r->type = l->type; n->right = r; } n->type = l->type; break; case OAS: o = tcom(l); if(o | tcom(r)) goto bad; if(tlvalue(l)) goto bad; if(isfunct(n)) break; typeext(l->type, r); if(tcompat(n, l->type, r->type, tasign)) goto bad; constas(n, l->type, r->type); if(!sametype(l->type, r->type)) { r = new1(OCAST, r, Z); r->type = l->type; n->right = r; } n->type = l->type; break; case OASADD: case OASSUB: o = tcom(l); if(o | tcom(r)) goto bad; if(tlvalue(l)) goto bad; if(isfunct(n)) break; typeext1(l->type, r); if(tcompat(n, l->type, r->type, tasadd)) goto bad; constas(n, l->type, r->type); t = l->type; arith(n, 0); while(n->left->op == OCAST) n->left = n->left->left; if(!sametype(t, n->type)) { r = new1(OCAST, n->right, Z); r->type = t; n->right = r; n->type = t; } break; case OASMUL: case OASLMUL: case OASDIV: case OASLDIV: o = tcom(l); if(o | tcom(r)) goto bad; if(tlvalue(l)) goto bad; if(isfunct(n)) break; typeext1(l->type, r); if(tcompat(n, l->type, r->type, tmul)) goto bad; constas(n, l->type, r->type); t = l->type; arith(n, 0); while(n->left->op == OCAST) n->left = n->left->left; if(!sametype(t, n->type)) { r = new1(OCAST, n->right, Z); r->type = t; n->right = r; n->type = t; } if(typeu[n->type->etype]) { if(n->op == OASDIV) n->op = OASLDIV; if(n->op == OASMUL) n->op = OASLMUL; } break; case OASLSHR: case OASASHR: case OASASHL: o = tcom(l); if(o | tcom(r)) goto bad; if(tlvalue(l)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, r->type, tand)) goto bad; n->type = l->type; if(typeu[n->type->etype]) { if(n->op == OASASHR) n->op = OASLSHR; } break; case OASMOD: case OASLMOD: case OASOR: case OASAND: case OASXOR: o = tcom(l); if(o | tcom(r)) goto bad; if(tlvalue(l)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, r->type, tand)) goto bad; t = l->type; arith(n, 0); while(n->left->op == OCAST) n->left = n->left->left; if(!sametype(t, n->type)) { r = new1(OCAST, n->right, Z); r->type = t; n->right = r; n->type = t; } if(typeu[n->type->etype]) { if(n->op == OASMOD) n->op = OASLMOD; } break; case OPREINC: case OPREDEC: case OPOSTINC: case OPOSTDEC: if(tcom(l)) goto bad; if(tlvalue(l)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, types[TINT], tadd)) goto bad; n->type = l->type; if(n->type->etype == TIND) if(n->type->link->width < 1) diag(n, "inc/dec of a void pointer"); break; case OEQ: case ONE: o = tcom(l); if(o | tcom(r)) goto bad; if(isfunct(n)) break; typeext(l->type, r); typeext(r->type, l); if(tcompat(n, l->type, r->type, trel)) goto bad; arith(n, 0); n->type = types[TINT]; break; case OLT: case OGE: case OGT: case OLE: o = tcom(l); if(o | tcom(r)) goto bad; if(isfunct(n)) break; typeext1(l->type, r); typeext1(r->type, l); if(tcompat(n, l->type, r->type, trel)) goto bad; arith(n, 0); if(typeu[n->type->etype]) n->op = logrel[relindex(n->op)]; n->type = types[TINT]; break; case OCOND: o = tcom(l); o |= tcom(r->left); if(o | tcom(r->right)) goto bad; if(r->right->type->etype == TIND && vconst(r->left) == 0) { r->left->type = r->right->type; r->left->vconst = 0; } if(r->left->type->etype == TIND && vconst(r->right) == 0) { r->right->type = r->left->type; r->right->vconst = 0; } if(sametype(r->right->type, r->left->type)) { r->type = r->right->type; n->type = r->type; break; } if(tcompat(r, r->left->type, r->right->type, trel)) goto bad; arith(r, 0); n->type = r->type; break; case OADD: o = tcom(l); if(o | tcom(r)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, r->type, tadd)) goto bad; arith(n, 1); break; case OSUB: o = tcom(l); if(o | tcom(r)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, r->type, tsub)) goto bad; arith(n, 1); break; case OMUL: case OLMUL: case ODIV: case OLDIV: o = tcom(l); if(o | tcom(r)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, r->type, tmul)) goto bad; arith(n, 1); if(typeu[n->type->etype]) { if(n->op == ODIV) n->op = OLDIV; if(n->op == OMUL) n->op = OLMUL; } break; case OLSHR: case OASHL: case OASHR: o = tcom(l); if(o | tcom(r)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, r->type, tand)) goto bad; n->right = Z; arith(n, 1); n->right = new1(OCAST, r, Z); n->right->type = types[TINT]; if(typeu[n->type->etype]) if(n->op == OASHR) n->op = OLSHR; break; case OAND: case OOR: case OXOR: o = tcom(l); if(o | tcom(r)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, r->type, tand)) goto bad; arith(n, 1); break; case OMOD: case OLMOD: o = tcom(l); if(o | tcom(r)) goto bad; if(isfunct(n)) break; if(tcompat(n, l->type, r->type, tand)) goto bad; arith(n, 1); if(typeu[n->type->etype]) n->op = OLMOD; break; case OPOS: if(tcom(l)) goto bad; if(isfunct(n)) break; r = l; l = new(OCONST, Z, Z); l->vconst = 0; l->type = types[TINT]; n->op = OADD; n->right = r; n->left = l; if(tcom(l)) goto bad; if(tcompat(n, l->type, r->type, tsub)) goto bad; arith(n, 1); break; case ONEG: if(tcom(l)) goto bad; if(isfunct(n)) break; r = l; l = new(OCONST, Z, Z); l->vconst = 0; l->type = types[TINT]; n->op = OSUB; n->right = r; n->left = l; if(tcom(l)) goto bad; if(tcompat(n, l->type, r->type, tsub)) goto bad; arith(n, 1); break; case OCOM: if(tcom(l)) goto bad; if(isfunct(n)) break; r = l; l = new(OCONST, Z, Z); l->vconst = -1; l->type = types[TINT]; n->op = OXOR; n->right = r; n->left = l; if(tcom(l)) goto bad; if(tcompat(n, l->type, r->type, tand)) goto bad; arith(n, 1); break; case ONOT: if(tcom(l)) goto bad; if(isfunct(n)) break; if(tcompat(n, T, l->type, tnot)) goto bad; n->type = types[TINT]; break; case OANDAND: case OOROR: o = tcom(l); if(o | tcom(r)) goto bad; if(tcompat(n, T, l->type, tnot) | tcompat(n, T, r->type, tnot)) goto bad; n->type = types[TINT]; break; case OCOMMA: o = tcom(l); if(o | tcom(r)) goto bad; n->type = r->type; break; case OSIGN: /* extension signof(type) returns a hash */ if(l != Z) { if(l->op != OSTRING && l->op != OLSTRING) if(tcomo(l, 0)) goto bad; if(l->op == OBIT) { diag(n, "signof bitfield"); goto bad; } n->type = l->type; } if(n->type == T) goto bad; if(n->type->width < 0) { diag(n, "signof undefined type"); goto bad; } n->op = OCONST; n->left = Z; n->right = Z; n->vconst = convvtox(signature(n->type, 10), TULONG); n->type = types[TULONG]; break; case OSIZE: if(l != Z) { if(l->op != OSTRING && l->op != OLSTRING) if(tcomo(l, 0)) goto bad; if(l->op == OBIT) { diag(n, "sizeof bitfield"); goto bad; } n->type = l->type; } if(n->type == T) goto bad; if(n->type->width <= 0) { diag(n, "sizeof undefined type"); goto bad; } if(n->type->etype == TFUNC) { diag(n, "sizeof function"); goto bad; } n->op = OCONST; n->left = Z; n->right = Z; n->vconst = convvtox(n->type->width, TINT); n->type = types[TINT]; break; case OFUNC: o = tcomo(l, 0); if(o) goto bad; if(l->type->etype == TIND && l->type->link->etype == TFUNC) { l = new1(OIND, l, Z); l->type = l->left->type->link; n->left = l; } if(tcompat(n, T, l->type, tfunct)) goto bad; if(o | tcoma(l, r, l->type->down, 1)) goto bad; n->type = l->type->link; if(!debug['B']) if(l->type->down == T || l->type->down->etype == TOLD) { nerrors--; diag(n, "function args not checked: %F", l); } dpcheck(n); break; case ONAME: if(n->type == T) { diag(n, "name not declared: %F", n); goto bad; } if(n->type->etype == TENUM) { n->op = OCONST; n->type = n->sym->tenum; if(!typefd[n->type->etype]) n->vconst = n->sym->vconst; else n->fconst = n->sym->fconst; break; } n->addable = 1; if(n->class == CEXREG) { n->op = OREGISTER; n->reg = n->sym->offset; n->xoffset = 0; break; } break; case OLSTRING: if(n->type->link != types[TUSHORT]) { o = outstring(0, 0); while(o & 3) { outlstring(L"", sizeof(ushort)); o = outlstring(0, 0); } } n->op = ONAME; n->xoffset = outlstring(n->rstring, n->type->width); n->addable = 1; break; case OSTRING: if(n->type->link != types[TCHAR]) { o = outstring(0, 0); while(o & 3) { outstring("", 1); o = outstring(0, 0); } } n->op = ONAME; n->xoffset = outstring(n->cstring, n->type->width); n->addable = 1; break; case OCONST: break; case ODOT: if(tcom(l)) goto bad; if(tcompat(n, T, l->type, tdot)) goto bad; if(tcomd(n)) goto bad; break; case OADDR: if(tcomo(l, ADDROP)) goto bad; if(tlvalue(l)) goto bad; if(l->type->nbits) { diag(n, "address of a bit field"); goto bad; } if(l->op == OREGISTER) { diag(n, "address of a register"); goto bad; } n->type = typ(TIND, l->type); n->type->width = types[TIND]->width; break; case OIND: if(tcom(l)) goto bad; if(tcompat(n, T, l->type, tindir)) goto bad; n->type = l->type->link; n->addable = 1; break; case OSTRUCT: if(tcomx(n)) goto bad; break; } t = n->type; if(t == T) goto bad; if(t->width < 0) { snap(t); if(t->width < 0) { if(typesu[t->etype] && t->tag) diag(n, "structure not fully declared %s", t->tag->name); else diag(n, "structure not fully declared"); goto bad; } } if(typeaf[t->etype]) { if(f & ADDROF) goto addaddr; if(f & ADDROP) warn(n, "address of array/func ignored"); } return 0; addaddr: if(tlvalue(n)) goto bad; l = new1(OXXX, Z, Z); *l = *n; n->op = OADDR; if(l->type->etype == TARRAY) l->type = l->type->link; n->left = l; n->right = Z; n->addable = 0; n->type = typ(TIND, l->type); n->type->width = types[TIND]->width; return 0; bad: n->type = T; return 1; } int tcoma(Node *l, Node *n, Type *t, int f) { Node *n1; int o; if(t != T) if(t->etype == TOLD || t->etype == TDOT) /* .../old in prototype */ t = T; if(n == Z) { if(t != T && !sametype(t, types[TVOID])) { diag(n, "not enough function arguments: %F", l); return 1; } return 0; } if(n->op == OLIST) { o = tcoma(l, n->left, t, 0); if(t != T) { t = t->down; if(t == T) t = types[TVOID]; } return o | tcoma(l, n->right, t, 1); } if(f && t != T) tcoma(l, Z, t->down, 0); if(tcom(n) || tcompat(n, T, n->type, targ)) return 1; if(sametype(t, types[TVOID])) { diag(n, "too many function arguments: %F", l); return 1; } if(t != T) { typeext(t, n); if(stcompat(nodproto, t, n->type, tasign)) { diag(l, "argument prototype mismatch \"%T\" for \"%T\": %F", n->type, t, l); return 1; } switch(t->etype) { case TCHAR: case TSHORT: t = types[TINT]; break; case TUCHAR: case TUSHORT: t = types[TUINT]; break; } } else switch(n->type->etype) { case TCHAR: case TSHORT: t = types[TINT]; break; case TUCHAR: case TUSHORT: t = types[TUINT]; break; case TFLOAT: t = types[TDOUBLE]; } if(t != T && !sametype(t, n->type)) { n1 = new1(OXXX, Z, Z); *n1 = *n; n->op = OCAST; n->left = n1; n->right = Z; n->type = t; n->addable = 0; } return 0; } int tcomd(Node *n) { Type *t; long o; o = 0; t = dotsearch(n->sym, n->left->type->link, n, &o); if(t == T) { diag(n, "not a member of struct/union: %F", n); return 1; } makedot(n, t, o); return 0; } int tcomx(Node *n) { Type *t; Node *l, *r, **ar, **al; int e; e = 0; if(n->type->etype != TSTRUCT) { diag(n, "constructor must be a structure"); return 1; } l = invert(n->left); n->left = l; al = &n->left; for(t = n->type->link; t != T; t = t->down) { if(l == Z) { diag(n, "constructor list too short"); return 1; } if(l->op == OLIST) { r = l->left; ar = &l->left; al = &l->right; l = l->right; } else { r = l; ar = al; l = Z; } if(tcom(r)) e++; typeext(t, r); if(tcompat(n, t, r->type, tasign)) e++; constas(n, t, r->type); if(!e && !sametype(t, r->type)) { r = new1(OCAST, r, Z); r->type = t; *ar = r; } } if(l != Z) { diag(n, "constructor list too long"); return 1; } return e; } int tlvalue(Node *n) { if(!n->addable) { diag(n, "not an l-value"); return 1; } return 0; } /* * general rewrite * (IND(ADDR x)) ==> x * (ADDR(IND x)) ==> x * remove some zero operands * remove no op casts * evaluate constants */ void ccom(Node *n) { Node *l, *r; int t; loop: if(n == Z) return; l = n->left; r = n->right; switch(n->op) { case OAS: case OASXOR: case OASAND: case OASOR: case OASMOD: case OASLMOD: case OASLSHR: case OASASHR: case OASASHL: case OASDIV: case OASLDIV: case OASMUL: case OASLMUL: case OASSUB: case OASADD: ccom(l); ccom(r); if(n->op == OASLSHR || n->op == OASASHR || n->op == OASASHL) if(r->op == OCONST) { t = n->type->width * 8; /* bits per byte */ if(r->vconst >= t || r->vconst < 0) warn(n, "stupid shift: %lld", r->vconst); } break; case OCAST: ccom(l); if(l->op == OCONST) { evconst(n); if(n->op == OCONST) break; } if(nocast(l->type, n->type)) { l->type = n->type; *n = *l; } break; case OCOND: ccom(l); ccom(r); if(l->op == OCONST) if(vconst(l) == 0) *n = *r->right; else *n = *r->left; break; case OREGISTER: case OINDREG: case OCONST: case ONAME: break; case OADDR: ccom(l); l->etype = TVOID; if(l->op == OIND) { l->left->type = n->type; *n = *l->left; break; } goto common; case OIND: ccom(l); if(l->op == OADDR) { l->left->type = n->type; *n = *l->left; break; } goto common; case OEQ: case ONE: case OLE: case OGE: case OLT: case OGT: case OLS: case OHS: case OLO: case OHI: ccom(l); ccom(r); relcon(l, r); relcon(r, l); goto common; case OASHR: case OASHL: case OLSHR: ccom(l); if(vconst(l) == 0 && !side(r)) { *n = *l; break; } ccom(r); if(vconst(r) == 0) { *n = *l; break; } if(r->op == OCONST) { t = n->type->width * 8; /* bits per byte */ if(r->vconst >= t || r->vconst <= -t) warn(n, "stupid shift: %lld", r->vconst); } goto common; case OMUL: case OLMUL: ccom(l); t = vconst(l); if(t == 0 && !side(r)) { *n = *l; break; } if(t == 1) { *n = *r; goto loop; } ccom(r); t = vconst(r); if(t == 0 && !side(l)) { *n = *r; break; } if(t == 1) { *n = *l; break; } goto common; case ODIV: case OLDIV: ccom(l); if(vconst(l) == 0 && !side(r)) { *n = *l; break; } ccom(r); t = vconst(r); if(t == 0) { diag(n, "divide check"); *n = *r; break; } if(t == 1) { *n = *l; break; } goto common; case OSUB: ccom(r); if(r->op == OCONST) { if(typefd[r->type->etype]) { n->op = OADD; r->fconst = -r->fconst; goto loop; } else { n->op = OADD; r->vconst = -r->vconst; goto loop; } } ccom(l); goto common; case OXOR: case OOR: case OADD: ccom(l); if(vconst(l) == 0) { *n = *r; goto loop; } ccom(r); if(vconst(r) == 0) { *n = *l; break; } goto commun; case OAND: ccom(l); ccom(r); if(vconst(l) == 0 && !side(r)) { *n = *l; break; } if(vconst(r) == 0 && !side(l)) { *n = *r; break; } commun: /* look for commutative constant */ if(r->op == OCONST) { if(l->op == n->op) { if(l->left->op == OCONST) { n->right = l->right; l->right = r; goto loop; } if(l->right->op == OCONST) { n->right = l->left; l->left = r; goto loop; } } } if(l->op == OCONST) { if(r->op == n->op) { if(r->left->op == OCONST) { n->left = r->right; r->right = l; goto loop; } if(r->right->op == OCONST) { n->left = r->left; r->left = l; goto loop; } } } goto common; case OANDAND: ccom(l); if(vconst(l) == 0) { *n = *l; break; } ccom(r); goto common; case OOROR: ccom(l); if(l->op == OCONST && l->vconst != 0) { *n = *l; n->vconst = 1; break; } ccom(r); goto common; default: if(l != Z) ccom(l); if(r != Z) ccom(r); common: if(l != Z) if(l->op != OCONST) break; if(r != Z) if(r->op != OCONST) break; evconst(n); } } /avr/cc/com64.c 664 forsyth sys 1070357260 9763 #include "cc.h" /* * this is machine depend, but it is totally * common on all of the 64-bit symulating machines. */ #define FNX 100 /* botch -- redefinition */ Node* nodaddv; Node* nodsubv; Node* nodmulv; Node* noddivv; Node* noddivvu; Node* nodmodv; Node* nodmodvu; Node* nodlshv; Node* nodrshav; Node* nodrshlv; Node* nodandv; Node* nodorv; Node* nodxorv; Node* nodnegv; Node* nodcomv; Node* nodtestv; Node* nodeqv; Node* nodnev; Node* nodlev; Node* nodltv; Node* nodgev; Node* nodgtv; Node* nodhiv; Node* nodhsv; Node* nodlov; Node* nodlsv; Node* nodf2v; Node* nodd2v; Node* nodp2v; Node* nodsi2v; Node* nodui2v; Node* nodsl2v; Node* nodul2v; Node* nodsh2v; Node* noduh2v; Node* nodsc2v; Node* noduc2v; Node* nodv2f; Node* nodv2d; Node* nodv2ui; Node* nodv2si; Node* nodv2ul; Node* nodv2sl; Node* nodv2uh; Node* nodv2sh; Node* nodv2uc; Node* nodv2sc; Node* nodvpp; Node* nodppv; Node* nodvmm; Node* nodmmv; Node* nodvasop; char etconv[NTYPE]; /* for _vasop */ Init initetconv[] = { TCHAR, 1, 0, TUCHAR, 2, 0, TSHORT, 3, 0, TUSHORT, 4, 0, TLONG, 5, 0, TULONG, 6, 0, TVLONG, 7, 0, TUVLONG, 8, 0, TINT, 9, 0, TUINT, 10, 0, -1, 0, 0, }; Node* fvn(char *name, int type) { Node *n; n = new(ONAME, Z, Z); n->sym = slookup(name); if(fntypes[type] == 0) fntypes[type] = typ(TFUNC, types[type]); n->type = fntypes[type]; n->etype = type; n->class = CGLOBL; n->addable = 10; n->complex = 0; return n; } void com64init(void) { Init *p; nodaddv = fvn("_addv", TVLONG); nodsubv = fvn("_subv", TVLONG); nodmulv = fvn("_mulv", TVLONG); noddivv = fvn("_divv", TVLONG); noddivvu = fvn("_divvu", TVLONG); nodmodv = fvn("_modv", TVLONG); nodmodvu = fvn("_modvu", TVLONG); nodlshv = fvn("_lshv", TVLONG); nodrshav = fvn("_rshav", TVLONG); nodrshlv = fvn("_rshlv", TVLONG); nodandv = fvn("_andv", TVLONG); nodorv = fvn("_orv", TVLONG); nodxorv = fvn("_xorv", TVLONG); nodnegv = fvn("_negv", TVLONG); nodcomv = fvn("_comv", TVLONG); nodtestv = fvn("_testv", TLONG); nodeqv = fvn("_eqv", TLONG); nodnev = fvn("_nev", TLONG); nodlev = fvn("_lev", TLONG); nodltv = fvn("_ltv", TLONG); nodgev = fvn("_gev", TLONG); nodgtv = fvn("_gtv", TLONG); nodhiv = fvn("_hiv", TLONG); nodhsv = fvn("_hsv", TLONG); nodlov = fvn("_lov", TLONG); nodlsv = fvn("_lsv", TLONG); nodf2v = fvn("_f2v", TVLONG); nodd2v = fvn("_d2v", TVLONG); nodp2v = fvn("_p2v", TVLONG); nodsi2v = fvn("_si2v", TVLONG); nodui2v = fvn("_ui2v", TVLONG); nodsl2v = fvn("_sl2v", TVLONG); nodul2v = fvn("_ul2v", TVLONG); nodsh2v = fvn("_sh2v", TVLONG); noduh2v = fvn("_uh2v", TVLONG); nodsc2v = fvn("_sc2v", TVLONG); noduc2v = fvn("_uc2v", TVLONG); nodv2f = fvn("_v2f", TFLOAT); nodv2d = fvn("_v2d", TDOUBLE); nodv2sl = fvn("_v2sl", TLONG); nodv2ul = fvn("_v2ul", TULONG); nodv2si = fvn("_v2si", TINT); nodv2ui = fvn("_v2ui", TUINT); nodv2sh = fvn("_v2sh", TSHORT); nodv2uh = fvn("_v2ul", TUSHORT); nodv2sc = fvn("_v2sc", TCHAR); nodv2uc = fvn("_v2uc", TUCHAR); nodvpp = fvn("_vpp", TVLONG); nodppv = fvn("_ppv", TVLONG); nodvmm = fvn("_vmm", TVLONG); nodmmv = fvn("_mmv", TVLONG); nodvasop = fvn("_vasop", TVLONG); for(p = initetconv; p->code >= 0; p++) etconv[p->code] = p->value; } int com64(Node *n) { Node *l, *r, *a, *t; int lv, rv; if(n->type == 0) return 0; l = n->left; r = n->right; lv = 0; if(l && l->type && typev[l->type->etype]) lv = 1; rv = 0; if(r && r->type && typev[r->type->etype]) rv = 1; if(lv) { switch(n->op) { case OEQ: a = nodeqv; goto setbool; case ONE: a = nodnev; goto setbool; case OLE: a = nodlev; goto setbool; case OLT: a = nodltv; goto setbool; case OGE: a = nodgev; goto setbool; case OGT: a = nodgtv; goto setbool; case OHI: a = nodhiv; goto setbool; case OHS: a = nodhsv; goto setbool; case OLO: a = nodlov; goto setbool; case OLS: a = nodlsv; goto setbool; case OANDAND: case OOROR: if(rv) { r = new(OFUNC, nodtestv, r); n->right = r; r->complex = FNX; r->op = OFUNC; r->type = types[TLONG]; } case OCOND: case ONOT: l = new(OFUNC, nodtestv, l); n->left = l; l->complex = FNX; l->op = OFUNC; l->type = types[TLONG]; n->complex = FNX; return 1; } } if(rv) { switch(n->op) { case OANDAND: case OOROR: r = new(OFUNC, nodtestv, r); n->right = r; r->complex = FNX; r->op = OFUNC; r->type = types[TLONG]; return 1; } } if(typev[n->type->etype]) { switch(n->op) { default: diag(n, "unknown vlong %O", n->op); case OFUNC: n->complex = FNX; case ORETURN: case OAS: case OIND: return 1; case OADD: a = nodaddv; goto setbop; case OSUB: a = nodsubv; goto setbop; case OMUL: case OLMUL: a = nodmulv; goto setbop; case ODIV: a = noddivv; goto setbop; case OLDIV: a = noddivvu; goto setbop; case OMOD: a = nodmodv; goto setbop; case OLMOD: a = nodmodvu; goto setbop; case OASHL: a = nodlshv; goto setbop; case OASHR: a = nodrshav; goto setbop; case OLSHR: a = nodrshlv; goto setbop; case OAND: a = nodandv; goto setbop; case OOR: a = nodorv; goto setbop; case OXOR: a = nodxorv; goto setbop; case OPOSTINC: a = nodvpp; goto setvinc; case OPOSTDEC: a = nodvmm; goto setvinc; case OPREINC: a = nodppv; goto setvinc; case OPREDEC: a = nodmmv; goto setvinc; case ONEG: a = nodnegv; goto setfnx; case OCOM: a = nodcomv; goto setfnx; case OCAST: switch(l->type->etype) { case TCHAR: a = nodsc2v; goto setfnxl; case TUCHAR: a = noduc2v; goto setfnxl; case TSHORT: a = nodsh2v; goto setfnxl; case TUSHORT: a = noduh2v; goto setfnxl; case TINT: a = nodsi2v; goto setfnx; case TUINT: a = nodui2v; goto setfnx; case TLONG: a = nodsl2v; goto setfnx; case TULONG: a = nodul2v; goto setfnx; case TFLOAT: a = nodf2v; goto setfnx; case TDOUBLE: a = nodd2v; goto setfnx; case TIND: a = nodp2v; goto setfnx; } diag(n, "unknown %T->vlong cast", l->type); return 1; case OASADD: a = nodaddv; goto setasop; case OASSUB: a = nodsubv; goto setasop; case OASMUL: case OASLMUL: a = nodmulv; goto setasop; case OASDIV: a = noddivv; goto setasop; case OASLDIV: a = noddivvu; goto setasop; case OASMOD: a = nodmodv; goto setasop; case OASLMOD: a = nodmodvu; goto setasop; case OASASHL: a = nodlshv; goto setasop; case OASASHR: a = nodrshav; goto setasop; case OASLSHR: a = nodrshlv; goto setasop; case OASAND: a = nodandv; goto setasop; case OASOR: a = nodorv; goto setasop; case OASXOR: a = nodxorv; goto setasop; } } if(typefd[n->type->etype] && l && l->op == OFUNC) { switch(n->op) { case OASADD: case OASSUB: case OASMUL: case OASLMUL: case OASDIV: case OASLDIV: case OASMOD: case OASLMOD: case OASASHL: case OASASHR: case OASLSHR: case OASAND: case OASOR: case OASXOR: if(l->right && typev[l->right->etype]) { diag(n, "sorry float vlong not implemented\n"); } } } if(n->op == OCAST) { if(l->type && typev[l->type->etype]) { switch(n->type->etype) { case TDOUBLE: a = nodv2d; goto setfnx; case TFLOAT: a = nodv2f; goto setfnx; case TLONG: a = nodv2sl; goto setfnx; case TULONG: a = nodv2ul; goto setfnx; case TINT: a = nodv2si; goto setfnx; case TUINT: a = nodv2ui; goto setfnx; case TSHORT: a = nodv2sh; goto setfnx; case TUSHORT: a = nodv2uh; goto setfnx; case TCHAR: a = nodv2sc; goto setfnx; case TUCHAR: a = nodv2uc; goto setfnx; case TIND: // small pun here a = nodv2ul; goto setfnx; } diag(n, "unknown vlong->%T cast", n->type); return 1; } } return 0; setbop: n->left = a; n->right = new(OLIST, l, r); n->complex = FNX; n->op = OFUNC; return 1; setfnxl: l = new(OCAST, l, 0); l->type = types[TLONG]; l->complex = l->left->complex; setfnx: n->left = a; n->right = l; n->complex = FNX; n->op = OFUNC; return 1; setvinc: n->left = a; l = new(OADDR, l, Z); l->type = typ(TIND, l->left->type); n->right = new(OLIST, l, r); n->complex = FNX; n->op = OFUNC; return 1; setbool: n->left = a; n->right = new(OLIST, l, r); n->complex = FNX; n->op = OFUNC; n->type = types[TLONG]; return 1; setasop: if(l->op == OFUNC) { l = l->right; goto setasop; } t = new(OCONST, 0, 0); t->vconst = etconv[l->type->etype]; t->type = types[TLONG]; t->addable = 20; r = new(OLIST, t, r); t = new(OADDR, a, 0); t->type = typ(TIND, a->type); r = new(OLIST, t, r); t = new(OADDR, l, 0); t->type = typ(TIND, l->type); r = new(OLIST, t, r); n->left = nodvasop; n->right = r; n->complex = FNX; n->op = OFUNC; return 1; } void bool64(Node *n) { Node *n1; if(typev[n->type->etype]) { n1 = new(OXXX, 0, 0); *n1 = *n; n->right = n1; n->left = nodtestv; n->complex = FNX; n->addable = 0; n->op = OFUNC; n->type = types[TLONG]; } } /* * more machine depend stuff. * this is common for 8,16,32,64 bit machines. * this is common for ieee machines. */ double convvtof(vlong v) { double d; d = v; /* BOTCH */ return d; } vlong convftov(double d) { vlong v; v = d; /* BOTCH */ return v; } double convftox(double d, int et) { if(!typefd[et]) diag(Z, "bad type in castftox %s", tnames[et]); return d; } vlong convvtox(vlong c, int et) { int n; n = 8 * ewidth[et]; c &= MASK(n); if(!typeu[et]) if(c & SIGN(n)) c |= ~MASK(n); return c; } /avr/cc/compat 644 forsyth sys 1070357260 684 int myaccess(char *f) { return access(f, AEXIST); } void* mysbrk(ulong size) { return sbrk(size); } int mycreat(char *n, int p) { return create(n, 1, p); } int mywait(int *s) { int p; Waitmsg *w; if((w = wait()) == nil) return -1; else{ p = w->pid; *s = 0; if(w->msg[0]) *s = 1; free(w); return p; } } int mydup(int f1, int f2) { return dup(f1,f2); } int mypipe(int *fd) { return pipe(fd); } int systemtype(int sys) { return sys & Plan9; } int pathchar(void) { return '/'; } char* mygetwd(char *path, int len) { return getwd(path, len); } int myexec(char *path, char *argv[]) { return exec(path, argv); } int myfork(void) { return fork(); } /avr/cc/compat.c 664 forsyth sys 1070357260 266 #include "cc.h" #include "compat" /* * fake mallocs */ void* malloc(ulong n) { return alloc(n); } void* calloc(ulong m, ulong n) { return alloc(m*n); } void* realloc(void*, ulong) { fprint(2, "realloc called\n"); abort(); return 0; } void free(void*) { } /avr/cc/con.c 664 forsyth sys 1070357260 8349 #include "cc.h" void evconst(Node *n) { Node *l, *r; int et, isf; vlong v; double d; if(n == Z || n->type == T) return; et = n->type->etype; isf = typefd[et]; l = n->left; r = n->right; d = 0; v = 0; switch(n->op) { default: return; case OCAST: if(et == TVOID) return; et = l->type->etype; if(isf) { if(typefd[et]) d = l->fconst; else d = l->vconst; } else { if(typefd[et]) v = l->fconst; else v = convvtox(l->vconst, n->type->etype); } break; case OCONST: break; case OADD: if(isf) d = l->fconst + r->fconst; else { v = l->vconst + r->vconst; } break; case OSUB: if(isf) d = l->fconst - r->fconst; else v = l->vconst - r->vconst; break; case OMUL: if(isf) d = l->fconst * r->fconst; else { v = l->vconst * r->vconst; } break; case OLMUL: v = (uvlong)l->vconst * (uvlong)r->vconst; break; case ODIV: if(vconst(r) == 0) { warn(n, "divide by zero"); return; } if(isf) d = l->fconst / r->fconst; else v = l->vconst / r->vconst; break; case OLDIV: if(vconst(r) == 0) { warn(n, "divide by zero"); return; } v = (uvlong)l->vconst / (uvlong)r->vconst; break; case OMOD: if(vconst(r) == 0) { warn(n, "modulo by zero"); return; } v = l->vconst % r->vconst; break; case OLMOD: if(vconst(r) == 0) { warn(n, "modulo by zero"); return; } v = (uvlong)l->vconst % (uvlong)r->vconst; break; case OAND: v = l->vconst & r->vconst; break; case OOR: v = l->vconst | r->vconst; break; case OXOR: v = l->vconst ^ r->vconst; break; case OLSHR: v = (uvlong)l->vconst >> r->vconst; break; case OASHR: v = l->vconst >> r->vconst; break; case OASHL: v = l->vconst << r->vconst; break; case OLO: v = (uvlong)l->vconst < (uvlong)r->vconst; break; case OLT: if(typefd[l->type->etype]) v = l->fconst < r->fconst; else v = l->vconst < r->vconst; break; case OHI: v = (uvlong)l->vconst > (uvlong)r->vconst; break; case OGT: if(typefd[l->type->etype]) v = l->fconst > r->fconst; else v = l->vconst > r->vconst; break; case OLS: v = (uvlong)l->vconst <= (uvlong)r->vconst; break; case OLE: if(typefd[l->type->etype]) v = l->fconst <= r->fconst; else v = l->vconst <= r->vconst; break; case OHS: v = (uvlong)l->vconst >= (uvlong)r->vconst; break; case OGE: if(typefd[l->type->etype]) v = l->fconst >= r->fconst; else v = l->vconst >= r->vconst; break; case OEQ: if(typefd[l->type->etype]) v = l->fconst == r->fconst; else v = l->vconst == r->vconst; break; case ONE: if(typefd[l->type->etype]) v = l->fconst != r->fconst; else v = l->vconst != r->vconst; break; case ONOT: if(typefd[l->type->etype]) v = !l->fconst; else v = !l->vconst; break; case OANDAND: if(typefd[l->type->etype]) v = l->fconst && r->fconst; else v = l->vconst && r->vconst; break; case OOROR: if(typefd[l->type->etype]) v = l->fconst || r->fconst; else v = l->vconst || r->vconst; break; } if(isf) { n->fconst = d; } else { n->vconst = convvtox(v, n->type->etype); } n->op = OCONST; } void acom(Node *n) { Type *t; Node *l, *r; int i; switch(n->op) { case ONAME: case OCONST: case OSTRING: case OINDREG: case OREGISTER: return; case OADD: case OSUB: case OMUL: l = n->left; r = n->right; if(addo(n)) { if(addo(r)) break; if(addo(l)) break; } acom(l); acom(r); return; default: l = n->left; r = n->right; if(l != Z) acom(l); if(r != Z) acom(r); return; } /* bust terms out */ t = n->type; term[0].mult = 0; term[0].node = Z; nterm = 1; acom1(1, n); if(debug['m']) for(i=0; itype = t; } int acomcmp1(const void *a1, const void *a2) { vlong c1, c2; Term *t1, *t2; t1 = (Term*)a1; t2 = (Term*)a2; c1 = t1->mult; if(c1 < 0) c1 = -c1; c2 = t2->mult; if(c2 < 0) c2 = -c2; if(c1 > c2) return 1; if(c1 < c2) return -1; c1 = 1; if(t1->mult < 0) c1 = 0; c2 = 1; if(t2->mult < 0) c2 = 0; if(c2 -= c1) return c2; if(t2 > t1) return 1; return -1; } int acomcmp2(const void *a1, const void *a2) { vlong c1, c2; Term *t1, *t2; t1 = (Term*)a1; t2 = (Term*)a2; c1 = t1->mult; c2 = t2->mult; if(c1 > c2) return 1; if(c1 < c2) return -1; if(t2 > t1) return 1; return -1; } void acom2(Node *n, Type *t) { Node *l, *r; Term trm[NTERM]; int et, nt, i, j; vlong c1, c2; /* * copy into automatic */ c2 = 0; nt = nterm; for(i=0; iop = OCONST; n->vconst = c1; return; } et = t->etype; /* * prepare constant term, * combine it with an addressing term */ if(c1 != 0) { l = new1(OCONST, Z, Z); l->type = t; l->vconst = c1; trm[0].mult = 1; for(i=1; iop != OADDR) continue; r->type = t; l = new1(OADD, r, l); l->type = t; trm[i].mult = 0; break; } trm[0].node = l; } /* * look for factorable terms * c1*i + c1*c2*j -> c1*(i + c2*j) */ qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1); for(i=nt-1; i>=0; i--) { c1 = trm[i].mult; if(c1 < 0) c1 = -c1; if(c1 <= 1) continue; for(j=i+1; jtype->etype != et) { r = new1(OCAST, r, Z); r->type = t; } c2 = trm[j].mult/trm[i].mult; if(c2 != 1 && c2 != -1) { r = new1(OMUL, r, new(OCONST, Z, Z)); r->type = t; r->right->type = t; r->right->vconst = c2; } l = trm[i].node; if(l->type->etype != et) { l = new1(OCAST, l, Z); l->type = t; } r = new1(OADD, l, r); r->type = t; if(c2 == -1) r->op = OSUB; trm[i].node = r; trm[j].mult = 0; } } if(debug['m']) { print("\n"); for(i=0; i=0; i--) { c1 = trm[i].mult; if(c1 == 0) continue; r = trm[i].node; if(r->type->etype != et || r->op == OBIT) { r = new1(OCAST, r, Z); r->type = t; } if(c1 != 1 && c1 != -1) { r = new1(OMUL, r, new(OCONST, Z, Z)); r->type = t; r->right->type = t; if(c1 < 0) { r->right->vconst = -c1; c1 = -1; } else { r->right->vconst = c1; c1 = 1; } } if(l == Z) { l = r; c2 = c1; continue; } if(c1 < 0) if(c2 < 0) l = new1(OADD, l, r); else l = new1(OSUB, l, r); else if(c2 < 0) { l = new1(OSUB, r, l); c2 = 1; } else l = new1(OADD, l, r); l->type = t; } if(c2 < 0) { r = new1(OCONST, 0, 0); r->vconst = 0; r->type = t; l = new1(OSUB, r, l); l->type = t; } *n = *l; } void acom1(vlong v, Node *n) { Node *l, *r; if(v == 0 || nterm >= NTERM) return; if(!addo(n)) { if(n->op == OCONST) if(!typefd[n->type->etype]) { term[0].mult += v*n->vconst; return; } term[nterm].mult = v; term[nterm].node = n; nterm++; return; } switch(n->op) { case OCAST: acom1(v, n->left); break; case OADD: acom1(v, n->left); acom1(v, n->right); break; case OSUB: acom1(v, n->left); acom1(-v, n->right); break; case OMUL: l = n->left; r = n->right; if(l->op == OCONST) if(!typefd[n->type->etype]) { acom1(v*l->vconst, r); break; } if(r->op == OCONST) if(!typefd[n->type->etype]) { acom1(v*r->vconst, l); break; } break; default: diag(n, "not addo"); } } int addo(Node *n) { if(n != Z) if(!typefd[n->type->etype]) if(!typev[n->type->etype]) switch(n->op) { case OCAST: if(nilcast(n->left->type, n->type)) return 1; break; case OADD: case OSUB: return 1; case OMUL: if(n->left->op == OCONST) return 1; if(n->right->op == OCONST) return 1; } return 0; } /avr/cc/dcl.c 664 forsyth sys 1070357261 25755 #include "cc.h" Node* dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n) { Sym *s; Node *n1; long v; nearln = lineno; lastfield = 0; loop: if(n != Z) switch(n->op) { default: diag(n, "unknown declarator: %O", n->op); break; case OARRAY: t = typ(TARRAY, t); t->width = 0; n1 = n->right; n = n->left; if(n1 != Z) { complex(n1); v = -1; if(n1->op == OCONST) v = n1->vconst; if(v <= 0) { diag(n, "array size must be a positive constant"); v = 1; } t->width = v * t->link->width; } goto loop; case OIND: t = typ(TIND, t); t->garb = n->garb; n = n->left; goto loop; case OFUNC: t = typ(TFUNC, t); t->down = fnproto(n); n = n->left; goto loop; case OBIT: n1 = n->right; complex(n1); lastfield = -1; if(n1->op == OCONST) lastfield = n1->vconst; if(lastfield < 0) { diag(n, "field width must be non-negative constant"); lastfield = 1; } if(lastfield == 0) { lastbit = 0; firstbit = 1; if(n->left != Z) { diag(n, "zero width named field"); lastfield = 1; } } if(!typei[t->etype]) { diag(n, "field type must be int-like"); t = types[TINT]; lastfield = 1; } if(lastfield > tfield->width*8) { diag(n, "field width larger than field unit"); lastfield = 1; } lastbit += lastfield; if(lastbit > tfield->width*8) { lastbit = lastfield; firstbit = 1; } n = n->left; goto loop; case ONAME: if(f == NODECL) break; s = n->sym; (*f)(c, t, s); if(s->class == CLOCAL) s = mkstatic(s); firstbit = 0; n->sym = s; n->type = s->type; n->xoffset = s->offset; n->class = s->class; n->etype = TVOID; if(n->type != T) n->etype = n->type->etype; if(debug['d']) dbgdecl(s); acidvar(s); s->varlineno = lineno; break; } lastdcl = t; return n; } Sym* mkstatic(Sym *s) { Sym *s1; if(s->class != CLOCAL) return s; snprint(symb, NSYMB, "%s$%d", s->name, s->block); s1 = lookup(); if(s1->class != CSTATIC) { s1->type = s->type; s1->offset = s->offset; s1->block = s->block; s1->class = CSTATIC; } return s1; } /* * make a copy of a typedef * the problem is to split out incomplete * arrays so that it is in the variable * rather than the typedef. */ Type* tcopy(Type *t) { Type *tl, *tx; int et; if(t == T) return t; et = t->etype; if(typesu[et]) return t; tl = tcopy(t->link); if(tl != t->link || (et == TARRAY && t->width == 0)) { tx = copytyp(t); tx->link = tl; return tx; } return t; } Node* doinit(Sym *s, Type *t, long o, Node *a) { Node *n; if(t == T) return Z; if(s->class == CEXTERN) { s->class = CGLOBL; if(debug['d']) dbgdecl(s); } if(debug['i']) { print("t = %T; o = %ld; n = %s\n", t, o, s->name); prtree(a, "doinit value"); } n = initlist; if(a->op == OINIT) a = a->left; initlist = a; a = init1(s, t, o, 0); if(initlist != Z) diag(initlist, "more initializers than structure: %s", s->name); initlist = n; return a; } /* * get next major operator, * dont advance initlist. */ Node* peekinit(void) { Node *a; a = initlist; loop: if(a == Z) return a; if(a->op == OLIST) { a = a->left; goto loop; } return a; } /* * consume and return next element on * initlist. expand strings. */ Node* nextinit(void) { Node *a, *b, *n; a = initlist; n = Z; if(a == Z) return a; if(a->op == OLIST) { n = a->right; a = a->left; } if(a->op == OUSED) { a = a->left; b = new(OCONST, Z, Z); b->type = a->type->link; if(a->op == OSTRING) { b->vconst = convvtox(*a->cstring, TCHAR); a->cstring++; } if(a->op == OLSTRING) { b->vconst = convvtox(*a->rstring, TUSHORT); a->rstring++; } a->type->width -= b->type->width; if(a->type->width <= 0) initlist = n; return b; } initlist = n; return a; } int isstruct(Node *a, Type *t) { Node *n; switch(a->op) { case ODOTDOT: n = a->left; if(n && n->type && sametype(n->type, t)) return 1; case OSTRING: case OLSTRING: case OCONST: case OINIT: case OELEM: return 0; } n = new(ODOTDOT, Z, Z); *n = *a; /* * ODOTDOT is a flag for tcom * a second tcom will not be performed */ a->op = ODOTDOT; a->left = n; a->right = Z; if(tcom(n)) return 0; if(sametype(n->type, t)) return 1; return 0; } Node* init1(Sym *s, Type *t, long o, int exflag) { Node *a, *l, *r, nod; Type *t1; long e, w, so, mw; a = peekinit(); if(a == Z) return Z; if(debug['i']) { print("t = %T; o = %ld; n = %s\n", t, o, s->name); prtree(a, "init1 value"); } if(exflag && a->op == OINIT) return doinit(s, t, o, nextinit()); switch(t->etype) { default: diag(Z, "unknown type in initialization: %T to: %s", t, s->name); return Z; case TCHAR: case TUCHAR: case TINT: case TUINT: case TSHORT: case TUSHORT: case TLONG: case TULONG: case TVLONG: case TUVLONG: case TFLOAT: case TDOUBLE: case TIND: single: if(a->op == OARRAY || a->op == OELEM) return Z; a = nextinit(); if(a == Z) return Z; if(t->nbits) diag(Z, "cannot initialize bitfields"); if(s->class == CAUTO) { l = new(ONAME, Z, Z); l->sym = s; l->type = t; l->etype = TVOID; if(s->type) l->etype = s->type->etype; l->xoffset = s->offset + o; l->class = s->class; l = new(OASI, l, a); return l; } complex(a); if(a->type == T) return Z; if(a->op == OCONST) { if(!sametype(a->type, t)) { /* hoop jumping to save malloc */ if(nodcast == Z) nodcast = new(OCAST, Z, Z); nod = *nodcast; nod.left = a; nod.type = t; nod.lineno = a->lineno; complex(&nod); if(nod.type) *a = nod; } if(a->op != OCONST) { diag(a, "initializer is not a constant: %s", s->name); return Z; } if(vconst(a) == 0) return Z; goto gext; } if(t->etype == TIND) { while(a->op == OCAST) { warn(a, "CAST in initialization ignored"); a = a->left; } if(!sametype(t, a->type)) { diag(a, "initialization of incompatible pointers: %s", s->name); print("%T and %T\n", t, a->type); } if(a->op == OADDR) a = a->left; goto gext; } while(a->op == OCAST) a = a->left; if(a->op == OADDR) { warn(a, "initialize pointer to an integer: %s", s->name); a = a->left; goto gext; } diag(a, "initializer is not a constant: %s", s->name); return Z; gext: gextern(s, a, o, t->width); return Z; case TARRAY: w = t->link->width; if(a->op == OSTRING || a->op == OLSTRING) if(typei[t->link->etype]) { /* * get rid of null if sizes match exactly */ a = nextinit(); mw = t->width/w; so = a->type->width/a->type->link->width; if(mw && so > mw) { if(so != mw+1) diag(a, "string initialization larger than array"); a->type->width -= a->type->link->width; } /* * arrange strings to be expanded * inside OINIT braces. */ a = new(OUSED, a, Z); return doinit(s, t, o, a); } mw = -w; l = Z; for(e=0;;) { /* * peek ahead for element initializer */ a = peekinit(); if(a == Z) break; if(a->op == OELEM && t->link->etype != TSTRUCT) break; if(a->op == OARRAY) { if(e && exflag) break; a = nextinit(); r = a->left; complex(r); if(r->op != OCONST) { diag(r, "initializer subscript must be constant"); return Z; } e = r->vconst; if(t->width != 0) if(e < 0 || e*w >= t->width) { diag(a, "initialization index out of range: %ld", e); continue; } } so = e*w; if(so > mw) mw = so; if(t->width != 0) if(mw >= t->width) break; r = init1(s, t->link, o+so, 1); l = newlist(l, r); e++; } if(t->width == 0) t->width = mw+w; return l; case TUNION: case TSTRUCT: /* * peek ahead to find type of rhs. * if its a structure, then treat * this element as a variable * rather than an aggregate. */ if(isstruct(a, t)) goto single; if(t->width <= 0) { diag(Z, "incomplete structure: %s", s->name); return Z; } l = Z; again: for(t1 = t->link; t1 != T; t1 = t1->down) { if(a->op == OARRAY && t1->etype != TARRAY) break; if(a->op == OELEM) { if(t1->sym != a->sym) continue; nextinit(); } r = init1(s, t1, o+t1->offset, 1); l = newlist(l, r); a = peekinit(); if(a == Z) break; if(a->op == OELEM) goto again; } if(a && a->op == OELEM) diag(a, "structure element not found %F", a); return l; } } Node* newlist(Node *l, Node *r) { if(r == Z) return l; if(l == Z) return r; return new(OLIST, l, r); } void suallign(Type *t) { Type *l; long o, w; o = 0; switch(t->etype) { case TSTRUCT: t->offset = 0; w = 0; for(l = t->link; l != T; l = l->down) { if(l->nbits) { if(l->shift <= 0) { l->shift = -l->shift; w = round(w, tfield->width); o = w; w += tfield->width; } l->offset = o; } else { if(l->width <= 0) if(l->sym) diag(Z, "incomplete structure element: %s", l->sym->name); else diag(Z, "incomplete structure element"); w = align(w, l, Ael1); l->offset = w; w = align(w, l, Ael2); } } w = align(w, t, Asu2); t->width = w; acidtype(t); pickletype(t); return; case TUNION: t->offset = 0; w = 0; for(l = t->link; l != T; l = l->down) { if(l->width <= 0) if(l->sym) diag(Z, "incomplete union element: %s", l->sym->name); else diag(Z, "incomplete union element"); l->offset = 0; l->shift = 0; o = align(align(0, l, Ael1), l, Ael2); if(o > w) w = o; } w = align(w, t, Asu2); t->width = w; acidtype(t); pickletype(t); return; default: diag(Z, "unknown type in suallign: %T", t); break; } } long round(long v, int w) { int r; if(w <= 0 || w > 8) { diag(Z, "rounding by %d", w); w = 1; } r = v%w; if(r) v += w-r; return v; } Type* ofnproto(Node *n) { Type *tl, *tr, *t; if(n == Z) return T; switch(n->op) { case OLIST: tl = ofnproto(n->left); tr = ofnproto(n->right); if(tl == T) return tr; tl->down = tr; return tl; case ONAME: t = copytyp(n->sym->type); t->down = T; return t; } return T; } #define ANSIPROTO 1 #define OLDPROTO 2 void argmark(Node *n, int pass) { Type *t; autoffset = align(0, thisfn->link, Aarg0); stkoff = 0; for(; n->left != Z; n = n->left) { if(n->op != OFUNC || n->left->op != ONAME) continue; walkparam(n->right, pass); if(pass != 0 && anyproto(n->right) == OLDPROTO) { t = typ(TFUNC, n->left->sym->type->link); t->down = typ(TOLD, T); t->down->down = ofnproto(n->right); tmerge(t, n->left->sym); n->left->sym->type = t; } break; } autoffset = 0; stkoff = 0; } void walkparam(Node *n, int pass) { Sym *s; Node *n1; if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID]) return; loop: if(n == Z) return; switch(n->op) { default: diag(n, "argument not a name/prototype: %O", n->op); break; case OLIST: walkparam(n->left, pass); n = n->right; goto loop; case OPROTO: for(n1 = n; n1 != Z; n1=n1->left) if(n1->op == ONAME) { if(pass == 0) { s = n1->sym; push1(s); s->offset = -1; break; } dodecl(pdecl, CPARAM, n->type, n->left); break; } if(n1) break; if(pass == 0) { /* * extension: * allow no name in argument declaration diag(Z, "no name in argument declaration"); */ break; } dodecl(NODECL, CPARAM, n->type, n->left); pdecl(CPARAM, lastdcl, S); break; case ODOTDOT: break; case ONAME: s = n->sym; if(pass == 0) { push1(s); s->offset = -1; break; } if(s->offset != -1) { if(autoffset == 0) { firstarg = s; firstargtype = s->type; } autoffset = align(autoffset, s->type, Aarg1); s->offset = autoffset; autoffset = align(autoffset, s->type, Aarg2); } else dodecl(pdecl, CXXX, types[TINT], n); break; } } void markdcl(void) { Decl *d; blockno++; d = push(); d->val = DMARK; d->offset = autoffset; d->block = autobn; autobn = blockno; } Node* revertdcl(void) { Decl *d; Sym *s; Node *n, *n1; n = Z; for(;;) { d = dclstack; if(d == D) { diag(Z, "pop off dcl stack"); break; } dclstack = d->link; s = d->sym; switch(d->val) { case DMARK: autoffset = d->offset; autobn = d->block; return n; case DAUTO: if(debug['d']) print("revert1 \"%s\"\n", s->name); if(s->aused == 0) { nearln = s->varlineno; if(s->class == CAUTO) warn(Z, "auto declared and not used: %s", s->name); if(s->class == CPARAM) warn(Z, "param declared and not used: %s", s->name); } if(s->type && (s->type->garb & GVOLATILE)) { n1 = new(ONAME, Z, Z); n1->sym = s; n1->type = s->type; n1->etype = TVOID; if(n1->type != T) n1->etype = n1->type->etype; n1->xoffset = s->offset; n1->class = s->class; n1 = new(OADDR, n1, Z); n1 = new(OUSED, n1, Z); if(n == Z) n = n1; else n = new(OLIST, n1, n); } s->type = d->type; s->class = d->class; s->offset = d->offset; s->block = d->block; s->varlineno = d->varlineno; s->aused = d->aused; break; case DSUE: if(debug['d']) print("revert2 \"%s\"\n", s->name); s->suetag = d->type; s->sueblock = d->block; break; case DLABEL: if(debug['d']) print("revert3 \"%s\"\n", s->name); if(s->label && s->label->addable == 0) warn(s->label, "label declared and not used \"%s\"", s->name); s->label = Z; break; } } return n; } Type* fnproto(Node *n) { int r; r = anyproto(n->right); if(r == 0 || (r & OLDPROTO)) { if(r & ANSIPROTO) diag(n, "mixed ansi/old function declaration: %F", n->left); return T; } return fnproto1(n->right); } int anyproto(Node *n) { int r; r = 0; loop: if(n == Z) return r; switch(n->op) { case OLIST: r |= anyproto(n->left); n = n->right; goto loop; case ODOTDOT: case OPROTO: return r | ANSIPROTO; } return r | OLDPROTO; } Type* fnproto1(Node *n) { Type *t; if(n == Z) return T; switch(n->op) { case OLIST: t = fnproto1(n->left); if(t != T) t->down = fnproto1(n->right); return t; case OPROTO: lastdcl = T; dodecl(NODECL, CXXX, n->type, n->left); t = typ(TXXX, T); if(lastdcl != T) *t = *paramconv(lastdcl, 1); return t; case ONAME: diag(n, "incomplete argument prototype"); return typ(TINT, T); case ODOTDOT: return typ(TDOT, T); } diag(n, "unknown op in fnproto"); return T; } void dbgdecl(Sym *s) { print("decl \"%s\": C=%s [B=%d:O=%ld] T=%T\n", s->name, cnames[s->class], s->block, s->offset, s->type); } Decl* push(void) { Decl *d; d = alloc(sizeof(*d)); d->link = dclstack; dclstack = d; return d; } Decl* push1(Sym *s) { Decl *d; d = push(); d->sym = s; d->val = DAUTO; d->type = s->type; d->class = s->class; d->offset = s->offset; d->block = s->block; d->varlineno = s->varlineno; d->aused = s->aused; return d; } int sametype(Type *t1, Type *t2) { if(t1 == t2) return 1; return rsametype(t1, t2, 5, 1); } int rsametype(Type *t1, Type *t2, int n, int f) { int et; n--; for(;;) { if(t1 == t2) return 1; if(t1 == T || t2 == T) return 0; if(n <= 0) return 1; et = t1->etype; if(et != t2->etype) return 0; if(et == TFUNC) { if(!rsametype(t1->link, t2->link, n, 0)) return 0; t1 = t1->down; t2 = t2->down; while(t1 != T && t2 != T) { if(t1->etype == TOLD) { t1 = t1->down; continue; } if(t2->etype == TOLD) { t2 = t2->down; continue; } while(t1 != T || t2 != T) { if(!rsametype(t1, t2, n, 0)) return 0; t1 = t1->down; t2 = t2->down; } break; } return 1; } if(et == TARRAY) if(t1->width != t2->width && t1->width != 0 && t2->width != 0) return 0; if(typesu[et]) { if(t1->link == T) snap(t1); if(t2->link == T) snap(t2); t1 = t1->link; t2 = t2->link; for(;;) { if(t1 == t2) return 1; if(!rsametype(t1, t2, n, 0)) return 0; t1 = t1->down; t2 = t2->down; } } t1 = t1->link; t2 = t2->link; if((f || !debug['V']) && et == TIND) { if(t1 != T && t1->etype == TVOID) return 1; if(t2 != T && t2->etype == TVOID) return 1; } } return 0; } ulong signature(Type *t, int n) { Type *t1; long s; s = 0; if(n > 0) for(; t; t=t->link) { s = s*thash1 + thash[t->etype]; switch(t->etype) { default: return s; case TARRAY: s = s*thash2 + t->width; break; case TFUNC: case TSTRUCT: case TUNION: for(t1=t; t1; t1=t1->down) s = s*thash3 + signature(t1, n-1); case TIND: break; } } return s; } void snap(Type *t) { if(typesu[t->etype]) if(t->link == T && t->tag && t->tag->suetag) { t->link = t->tag->suetag->link; t->width = t->tag->suetag->width; } } Type* dotag(Sym *s, int et, int bn) { Decl *d; if(bn != 0 && bn != s->sueblock) { d = push(); d->sym = s; d->val = DSUE; d->type = s->suetag; d->block = s->sueblock; s->suetag = T; } if(s->suetag == T) { s->suetag = typ(et, T); s->sueblock = autobn; } if(s->suetag->etype != et) diag(Z, "tag used for more than one type: %s", s->name); if(s->suetag->tag == S) s->suetag->tag = s; return s->suetag; } Node* dcllabel(Sym *s, int f) { Decl *d, d1; Node *n; n = s->label; if(n != Z) { if(f) { if(n->complex) diag(Z, "label reused: %s", s->name); n->complex = 1; // declared } else n->addable = 1; // used return n; } d = push(); d->sym = s; d->val = DLABEL; dclstack = d->link; d1 = *firstdcl; *firstdcl = *d; *d = d1; firstdcl->link = d; firstdcl = d; n = new(OXXX, Z, Z); n->sym = s; n->complex = f; n->addable = !f; s->label = n; if(debug['d']) dbgdecl(s); return n; } Type* paramconv(Type *t, int f) { switch(t->etype) { case TUNION: case TSTRUCT: if(t->width <= 0) diag(Z, "incomplete structure: %s", t->tag->name); break; case TARRAY: t = typ(TIND, t->link); t->width = types[TIND]->width; break; case TFUNC: t = typ(TIND, t); t->width = types[TIND]->width; break; case TFLOAT: if(!f) t = types[TDOUBLE]; break; case TCHAR: case TSHORT: if(!f) t = types[TINT]; break; case TUCHAR: case TUSHORT: if(!f) t = types[TUINT]; break; } return t; } void adecl(int c, Type *t, Sym *s) { if(c == CSTATIC) c = CLOCAL; if(t->etype == TFUNC) { if(c == CXXX) c = CEXTERN; if(c == CLOCAL) c = CSTATIC; if(c == CAUTO || c == CEXREG) diag(Z, "function cannot be %s %s", cnames[c], s->name); } if(c == CXXX) c = CAUTO; if(s) { if(s->class == CSTATIC) if(c == CEXTERN || c == CGLOBL) { warn(Z, "just say static: %s", s->name); c = CSTATIC; } if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL) if(s->block == autobn) diag(Z, "auto redeclaration of: %s", s->name); if(c != CPARAM) push1(s); s->block = autobn; s->offset = 0; s->type = t; s->class = c; s->aused = 0; } switch(c) { case CAUTO: autoffset = align(autoffset, t, Aaut3); stkoff = maxround(stkoff, autoffset); s->offset = -autoffset; break; case CPARAM: if(autoffset == 0) { firstarg = s; firstargtype = t; } autoffset = align(autoffset, t, Aarg1); if(s) s->offset = autoffset; autoffset = align(autoffset, t, Aarg2); break; } } void pdecl(int c, Type *t, Sym *s) { if(s && s->offset != -1) { diag(Z, "not a parameter: %s", s->name); return; } t = paramconv(t, c==CPARAM); if(c == CXXX) c = CPARAM; if(c != CPARAM) { diag(Z, "parameter cannot have class: %s", s->name); c = CPARAM; } adecl(c, t, s); } void xdecl(int c, Type *t, Sym *s) { long o; o = 0; switch(c) { case CEXREG: o = exreg(t); if(o == 0) c = CEXTERN; if(s->class == CGLOBL) c = CGLOBL; break; case CEXTERN: if(s->class == CGLOBL) c = CGLOBL; break; case CXXX: c = CGLOBL; if(s->class == CEXTERN) s->class = CGLOBL; break; case CAUTO: diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]); c = CEXTERN; break; case CTYPESTR: if(!typesuv[t->etype]) { diag(Z, "typestr must be struct/union: %s", s->name); break; } dclfunct(t, s); break; } if(s->class == CSTATIC) if(c == CEXTERN || c == CGLOBL) { warn(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]); c = CSTATIC; } if(s->type != T) if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) { diag(Z, "external redeclaration of: %s", s->name); print(" %s %T %L\n", cnames[c], t, nearln); print(" %s %T %L\n", cnames[s->class], s->type, s->varlineno); } tmerge(t, s); s->type = t; s->class = c; s->block = 0; s->offset = o; } void tmerge(Type *t1, Sym *s) { Type *ta, *tb, *t2; t2 = s->type; /*print("merge %T; %T\n", t1, t2);/**/ for(;;) { if(t1 == T || t2 == T || t1 == t2) break; if(t1->etype != t2->etype) break; switch(t1->etype) { case TFUNC: ta = t1->down; tb = t2->down; if(ta == T) { t1->down = tb; break; } if(tb == T) break; while(ta != T && tb != T) { if(ta == tb) break; /* ignore old-style flag */ if(ta->etype == TOLD) { ta = ta->down; continue; } if(tb->etype == TOLD) { tb = tb->down; continue; } /* checking terminated by ... */ if(ta->etype == TDOT && tb->etype == TDOT) { ta = T; tb = T; break; } if(!sametype(ta, tb)) break; ta = ta->down; tb = tb->down; } if(ta != tb) diag(Z, "function inconsistently declared: %s", s->name); /* take new-style over old-style */ ta = t1->down; tb = t2->down; if(ta != T && ta->etype == TOLD) if(tb != T && tb->etype != TOLD) t1->down = tb; break; case TARRAY: /* should we check array size change? */ if(t2->width > t1->width) t1->width = t2->width; break; case TUNION: case TSTRUCT: return; } t1 = t1->link; t2 = t2->link; } } void edecl(int c, Type *t, Sym *s) { Type *t1; if(s == S) { if(!typesu[t->etype]) diag(Z, "unnamed structure element must be struct/union"); if(c != CXXX) diag(Z, "unnamed structure element cannot have class"); } else if(c != CXXX) diag(Z, "structure element cannot have class: %s", s->name); t1 = t; t = copytyp(t1); t->sym = s; t->down = T; if(lastfield) { t->shift = lastbit - lastfield; t->nbits = lastfield; if(firstbit) t->shift = -t->shift; if(typeu[t->etype]) t->etype = tufield->etype; else t->etype = tfield->etype; } if(strf == T) strf = t; else strl->down = t; strl = t; } /* * this routine is very suspect. * ansi requires the enum type to * be represented as an 'int' * this means that 0x81234567 * would be illegal. this routine * makes signed and unsigned go * to unsigned. */ Type* maxtype(Type *t1, Type *t2) { if(t1 == T) return t2; if(t2 == T) return t1; if(t1->etype > t2->etype) return t1; return t2; } void doenum(Sym *s, Node *n) { if(n) { complex(n); if(n->op != OCONST) { diag(n, "enum not a constant: %s", s->name); return; } en.cenum = n->type; en.tenum = maxtype(en.cenum, en.tenum); if(!typefd[en.cenum->etype]) en.lastenum = n->vconst; else en.floatenum = n->fconst; } if(dclstack) push1(s); xdecl(CXXX, types[TENUM], s); if(en.cenum == T) { en.tenum = types[TINT]; en.cenum = types[TINT]; en.lastenum = 0; } s->tenum = en.cenum; if(!typefd[s->tenum->etype]) { s->vconst = convvtox(en.lastenum, s->tenum->etype); en.lastenum++; } else { s->fconst = en.floatenum; en.floatenum++; } if(debug['d']) dbgdecl(s); acidvar(s); } void symadjust(Sym *s, Node *n, long del) { switch(n->op) { default: if(n->left) symadjust(s, n->left, del); if(n->right) symadjust(s, n->right, del); return; case ONAME: if(n->sym == s) n->xoffset -= del; return; case OCONST: case OSTRING: case OLSTRING: case OINDREG: case OREGISTER: return; } } Node* contig(Sym *s, Node *n, long v) { Node *p, *r, *q, *m; long w; if(debug['i']) { print("contig v = %ld; s = %s\n", v, s->name); prtree(n, "doinit value"); } if(n == Z) goto no; w = s->type->width; /* * nightmare: an automatic array whose size * increases when it is initialized */ if(v != w) { if(v != 0) diag(n, "automatic adjustable array: %s", s->name); v = s->offset; autoffset = align(autoffset, s->type, Aaut3); s->offset = -autoffset; stkoff = maxround(stkoff, autoffset); symadjust(s, n, v - s->offset); } if(w <= 4) goto no; if(n->op == OAS) diag(Z, "oops in contig"); /*ZZZ this appears incorrect need to check if the list completely covers the data. if not, bail */ if(n->op == OLIST) goto no; if(n->op == OASI) if(n->left->type) if(n->left->type->width == w) goto no; while(w & 3) w++; /* is this a bug?? */ /* * insert the following code * *(long**)&X = (long*)((char*)X + sizeof(X)); do { *(long**)&X -= 1; **(long**)&X = 0; } while(*(long**)&X); */ for(q=n; q->op != ONAME; q=q->left) ; p = new(ONAME, Z, Z); *p = *q; p->type = typ(TIND, types[TLONG]); p->xoffset = s->offset; r = new(ONAME, Z, Z); *r = *p; r = new(OPOSTDEC, r, Z); q = new(ONAME, Z, Z); *q = *p; q = new(OIND, q, Z); m = new(OCONST, Z, Z); m->vconst = 0; m->type = types[TLONG]; q = new(OAS, q, m); r = new(OLIST, r, q); q = new(ONAME, Z, Z); *q = *p; r = new(ODWHILE, q, r); q = new(ONAME, Z, Z); *q = *p; q->type = q->type->link; q->xoffset += w; q = new(OADDR, q, 0); q = new(OASI, p, q); r = new(OLIST, q, r); n = new(OLIST, r, n); no: return n; } /avr/cc/dpchk.c 664 forsyth sys 1070357261 6738 #include "cc.h" #include "y.tab.h" enum { Fnone = 0, Fl, Fvl, Fignor, Fstar, Fadj, Fverb = 10, }; typedef struct Tprot Tprot; struct Tprot { Type* type; Bits flag; Tprot* link; }; typedef struct Tname Tname; struct Tname { char* name; int param; Tname* link; }; static Type* indchar; static uchar flagbits[512]; static char fmtbuf[100]; static int lastadj; static int lastverb; static int nstar; static Tprot* tprot; static Tname* tname; void argflag(int c, int v) { switch(v) { case Fignor: case Fstar: case Fl: case Fvl: flagbits[c] = v; break; case Fverb: flagbits[c] = lastverb; //print("flag-v %c %d\n", c, lastadj); lastverb++; break; case Fadj: flagbits[c] = lastadj; //print("flag-l %c %d\n", c, lastadj); lastadj++; break; } } Bits getflag(char *s) { Bits flag; int f; char *fmt; Rune c; fmt = fmtbuf; flag = zbits; nstar = 0; for(;;) { s += chartorune(&c, s); if(c == 0 || c >= nelem(flagbits)) break; fmt += runetochar(fmt, &c); f = flagbits[c]; switch(f) { case Fnone: argflag(c, Fverb); f = flagbits[c]; break; case Fstar: nstar++; case Fignor: continue; case Fl: if(bset(flag, Fl)) flag = bor(flag, blsh(Fvl)); } flag = bor(flag, blsh(f)); if(f >= Fverb) break; } *fmt = 0; return flag; } void newprot(Sym *m, Type *t, char *s) { Bits flag; Tprot *l; if(t == T) { warn(Z, "%s: newprot: type not defined", m->name); return; } flag = getflag(s); for(l=tprot; l; l=l->link) if(beq(flag, l->flag) && sametype(t, l->type)) return; l = alloc(sizeof(*l)); l->type = t; l->flag = flag; l->link = tprot; tprot = l; } void newname(char *s, int p) { Tname *l; for(l=tname; l; l=l->link) if(strcmp(l->name, s) == 0) { if(l->param != p) yyerror("vargck %s already defined\n", s); return; } l = alloc(sizeof(*l)); l->name = s; l->param = p; l->link = tname; tname = l; } void arginit(void) { int i; // debug['F'] = 1; // debug['w'] = 1; lastadj = Fadj; lastverb = Fverb; indchar = typ(TIND, types[TCHAR]); memset(flagbits, Fnone, sizeof(flagbits)); for(i='0'; i<='9'; i++) argflag(i, Fignor); argflag('.', Fignor); argflag('#', Fignor); argflag('u', Fignor); argflag('+', Fignor); argflag('-', Fignor); argflag('*', Fstar); argflag('l', Fl); argflag('o', Fverb); flagbits['x'] = flagbits['o']; flagbits['X'] = flagbits['o']; } void pragvararg(void) { Sym *s; int n, c; char *t; Rune r; Type *ty; if(!debug['F']) goto out; s = getsym(); if(s && strcmp(s->name, "argpos") == 0) goto ckpos; if(s && strcmp(s->name, "type") == 0) goto cktype; if(s && strcmp(s->name, "flag") == 0) goto ckflag; yyerror("syntax in #pragma varargck"); goto out; ckpos: //#pragma varargck argpos warn 2 s = getsym(); if(s == S) goto bad; n = getnsn(); if(n < 0) goto bad; newname(s->name, n); goto out; ckflag: //#pragma varargck flag 'c' c = getnsc(); if(c != '\'') goto bad; c = getr(); if(c == '\\') c = getr(); else if(c == '\'') goto bad; if(c == '\n') goto bad; if(getc() != '\'') goto bad; argflag(c, Fignor); goto out; cktype: //#pragma varargck type O int c = getnsc(); if(c != '"') goto bad; t = fmtbuf; for(;;) { r = getr(); if(r == ' ' || r == '\n') goto bad; if(r == '"') break; t += runetochar(t, &r); } *t = 0; t = strdup(fmtbuf); s = getsym(); if(s == S) goto bad; ty = s->type; while((c = getnsc()) == '*') ty = typ(TIND, ty); unget(c); newprot(s, ty, t); goto out; bad: yyerror("syntax in #pragma varargck"); out: while(getnsc() != '\n') ; } Node* nextarg(Node *n, Node **a) { if(n == Z) { *a = Z; return Z; } if(n->op == OLIST) { *a = n->left; return n->right; } *a = n; return Z; } void checkargs(Node *nn, char *s) { Node *a, *n; Bits flag; Tprot *l; if(!debug['F']) return; n = nn; for(;;) { s = strchr(s, '%'); if(s == 0) { nextarg(n, &a); if(a != Z) warn(nn, "more arguments than format %T", a->type); return; } s++; flag = getflag(s); while(nstar > 0) { n = nextarg(n, &a); nstar--; if(a == Z) { warn(nn, "more format than arguments %s", fmtbuf); return; } if(a->type == T) continue; if(!sametype(types[TINT], a->type) && !sametype(types[TUINT], a->type)) warn(nn, "format mismatch '*' in %s %T", fmtbuf, a->type); } for(l=tprot; l; l=l->link) if(sametype(types[TVOID], l->type)) { if(beq(flag, l->flag)) { s++; goto loop; } } n = nextarg(n, &a); if(a == Z) { warn(nn, "more format than arguments %s", fmtbuf); return; } if(a->type == 0) continue; for(l=tprot; l; l=l->link) if(sametype(a->type, l->type)) { //print("checking %T/%ulx %T/%ulx\n", a->type, flag.b[0], l->type, l->flag.b[0]); if(beq(flag, l->flag)) goto loop; } warn(nn, "format mismatch %s %T", fmtbuf, a->type); loop:; } } void dpcheck(Node *n) { char *s; Node *a, *b; Tname *l; int i; if(n == Z) return; b = n->left; if(b == Z || b->op != ONAME) return; s = b->sym->name; for(l=tname; l; l=l->link) if(strcmp(s, l->name) == 0) break; if(l == 0) return; i = l->param; b = n->right; while(i > 0) { b = nextarg(b, &a); i--; } if(a == Z) { warn(n, "cant find format arg"); return; } if(!sametype(indchar, a->type)) { warn(n, "format arg type %T", a->type); return; } if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) { // warn(n, "format arg not constant string"); return; } s = a->left->cstring; checkargs(b, s); } void praghjdicks(void) { Sym *s; hjdickflg = 0; s = getsym(); if(s) { hjdickflg = atoi(s->name+1); if(strcmp(s->name, "on") == 0 || strcmp(s->name, "yes") == 0 || strcmp(s->name, "dick") == 0) hjdickflg = 1; } while(getnsc() != '\n') ; if(debug['f']) if(hjdickflg) print("%4ld: hjdicks %d\n", lineno, hjdickflg); else print("%4ld: hjdicks off\n", lineno); } void pragfpround(void) { Sym *s; fproundflg = 0; s = getsym(); if(s) { fproundflg = atoi(s->name+1); if(strcmp(s->name, "on") == 0 || strcmp(s->name, "yes") == 0) fproundflg = 1; } while(getnsc() != '\n') ; if(debug['f']) if(fproundflg) print("%4ld: fproundflg %d\n", lineno, fproundflg); else print("%4ld: fproundflg off\n", lineno); } void pragprofile(void) { Sym *s; profileflg = 0; s = getsym(); if(s) { profileflg = atoi(s->name+1); if(strcmp(s->name, "on") == 0 || strcmp(s->name, "yes") == 0) fproundflg = 1; } while(getnsc() != '\n') ; if(debug['f']) if(profileflg) print("%4ld: profileflg %d\n", lineno, profileflg); else print("%4ld: profileflg off\n", lineno); } /avr/cc/funct.c 664 forsyth sys 1070357261 6167 #include "cc.h" typedef struct Ftab Ftab; struct Ftab { char op; char* name; char typ; }; typedef struct Gtab Gtab; struct Gtab { char etype; char* name; }; Ftab ftabinit[OEND]; Gtab gtabinit[NTYPE]; int isfunct(Node *n) { Type *t, *t1; Funct *f; Node *l; Sym *s; int o; o = n->op; if(n->left == Z) goto no; t = n->left->type; if(t == T) goto no; f = t->funct; switch(o) { case OAS: // put cast on rhs case OASI: case OASADD: case OASAND: case OASASHL: case OASASHR: case OASDIV: case OASLDIV: case OASLMOD: case OASLMUL: case OASLSHR: case OASMOD: case OASMUL: case OASOR: case OASSUB: case OASXOR: if(n->right == Z) goto no; t1 = n->right->type; if(t1 == T) goto no; if(t1->funct == f) break; l = new(OXXX, Z, Z); *l = *n->right; n->right->left = l; n->right->right = Z; n->right->type = t; n->right->op = OCAST; if(!isfunct(n->right)) prtree(n, "isfunc !"); break; case OCAST: // t f(T) or T f(t) t1 = n->type; if(t1 == T) goto no; if(f != nil) { s = f->castfr[t1->etype]; if(s == S) goto no; n->right = n->left; goto build; } f = t1->funct; if(f != nil) { s = f->castto[t->etype]; if(s == S) goto no; n->right = n->left; goto build; } goto no; } if(f == nil) goto no; s = f->sym[o]; if(s == S) goto no; /* * the answer is yes, * now we rewrite the node * and give diagnostics */ switch(o) { default: diag(n, "isfunct op missing %O\n", o); goto bad; case OADD: // T f(T, T) case OAND: case OASHL: case OASHR: case ODIV: case OLDIV: case OLMOD: case OLMUL: case OLSHR: case OMOD: case OMUL: case OOR: case OSUB: case OXOR: case OEQ: // int f(T, T) case OGE: case OGT: case OHI: case OHS: case OLE: case OLO: case OLS: case OLT: case ONE: if(n->right == Z) goto bad; t1 = n->right->type; if(t1 == T) goto bad; if(t1->funct != f) goto bad; n->right = new(OLIST, n->left, n->right); break; case OAS: // structure copies done by the compiler case OASI: goto no; case OASADD: // T f(T*, T) case OASAND: case OASASHL: case OASASHR: case OASDIV: case OASLDIV: case OASLMOD: case OASLMUL: case OASLSHR: case OASMOD: case OASMUL: case OASOR: case OASSUB: case OASXOR: if(n->right == Z) goto bad; t1 = n->right->type; if(t1 == T) goto bad; if(t1->funct != f) goto bad; n->right = new(OLIST, new(OADDR, n->left, Z), n->right); break; case OPOS: // T f(T) case ONEG: case ONOT: case OCOM: n->right = n->left; break; } build: l = new(ONAME, Z, Z); l->sym = s; l->type = s->type; l->etype = s->type->etype; l->xoffset = s->offset; l->class = s->class; tcomo(l, 0); n->op = OFUNC; n->left = l; n->type = l->type->link; if(tcompat(n, T, l->type, tfunct)) goto bad; if(tcoma(n->left, n->right, l->type->down, 1)) goto bad; return 1; no: return 0; bad: diag(n, "cant rewrite typestr for op %O\n", o); prtree(n, "isfunct"); n->type = T; return 1; } void dclfunct(Type *t, Sym *s) { Funct *f; Node *n; Type *f1, *f2, *f3, *f4; int o, i, c; char str[100]; if(t->funct) return; // recognize generated tag of dorm _%d_ if(t->tag == S) goto bad; for(i=0; c = t->tag->name[i]; i++) { if(c == '_') { if(i == 0 || t->tag->name[i+1] == 0) continue; break; } if(c < '0' || c > '9') break; } if(c == 0) goto bad; f = alloc(sizeof(*f)); for(o=0; osym); o++) f->sym[o] = S; t->funct = f; f1 = typ(TFUNC, t); f1->down = copytyp(t); f1->down->down = t; f2 = typ(TFUNC, types[TINT]); f2->down = copytyp(t); f2->down->down = t; f3 = typ(TFUNC, t); f3->down = typ(TIND, t); f3->down->down = t; f4 = typ(TFUNC, t); f4->down = t; for(i=0;; i++) { o = ftabinit[i].op; if(o == OXXX) break; sprint(str, "%s_%s_", t->tag->name, ftabinit[i].name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->sym[o] = n->sym; switch(ftabinit[i].typ) { default: diag(Z, "dclfunct op missing %d\n", ftabinit[i].typ); break; case 1: // T f(T,T) + dodecl(xdecl, CEXTERN, f1, n); break; case 2: // int f(T,T) == dodecl(xdecl, CEXTERN, f2, n); break; case 3: // void f(T*,T) += dodecl(xdecl, CEXTERN, f3, n); break; case 4: // T f(T) ~ dodecl(xdecl, CEXTERN, f4, n); break; } } for(i=0;; i++) { o = gtabinit[i].etype; if(o == TXXX) break; /* * OCAST types T1 _T2_T1_(T2) */ sprint(str, "_%s%s_", gtabinit[i].name, t->tag->name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->castto[o] = n->sym; f1 = typ(TFUNC, t); f1->down = types[o]; dodecl(xdecl, CEXTERN, f1, n); sprint(str, "%s_%s_", t->tag->name, gtabinit[i].name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->castfr[o] = n->sym; f1 = typ(TFUNC, types[o]); f1->down = t; dodecl(xdecl, CEXTERN, f1, n); } return; bad: diag(Z, "dclfunct bad %T %s\n", t, s->name); } Gtab gtabinit[NTYPE] = { TCHAR, "c", TUCHAR, "uc", TSHORT, "h", TUSHORT, "uh", TINT, "i", TUINT, "ui", TLONG, "l", TULONG, "ul", TVLONG, "v", TUVLONG, "uv", TFLOAT, "f", TDOUBLE, "d", TXXX }; Ftab ftabinit[OEND] = { OADD, "add", 1, OAND, "and", 1, OASHL, "ashl", 1, OASHR, "ashr", 1, ODIV, "div", 1, OLDIV, "ldiv", 1, OLMOD, "lmod", 1, OLMUL, "lmul", 1, OLSHR, "lshr", 1, OMOD, "mod", 1, OMUL, "mul", 1, OOR, "or", 1, OSUB, "sub", 1, OXOR, "xor", 1, OEQ, "eq", 2, OGE, "ge", 2, OGT, "gt", 2, OHI, "hi", 2, OHS, "hs", 2, OLE, "le", 2, OLO, "lo", 2, OLS, "ls", 2, OLT, "lt", 2, ONE, "ne", 2, OASADD, "asadd", 3, OASAND, "asand", 3, OASASHL, "asashl", 3, OASASHR, "asashr", 3, OASDIV, "asdiv", 3, OASLDIV, "asldiv", 3, OASLMOD, "aslmod", 3, OASLMUL, "aslmul", 3, OASLSHR, "aslshr", 3, OASMOD, "asmod", 3, OASMUL, "asmul", 3, OASOR, "asor", 3, OASSUB, "assub", 3, OASXOR, "asxor", 3, OPOS, "pos", 4, ONEG, "neg", 4, OCOM, "com", 4, ONOT, "not", 4, // OPOSTDEC, // OPOSTINC, // OPREDEC, // OPREINC, OXXX, }; // Node* nodtestv; // Node* nodvpp; // Node* nodppv; // Node* nodvmm; // Node* nodmmv; /avr/cc/lex.c 664 forsyth sys 1076922940 23769 #include "cc.h" #include "y.tab.h" #ifndef CPP #define CPP "/bin/cpp" #endif /* * known debug flags * -o file output file * -D name define * -I path include * -a acid declaration output * -M constant multiplication * -B non ANSI * -A !B * -d print declarations * -t print type trees * -L print every NAME symbol * -i print initialization * -F format specification check * -r print registerization * -v verbose printing * -X abort on error * -w print warnings * -m print add/sub/mul trees * -s print structure offsets (with -a or -aa) * -n print acid to file (%.c=%.acid) (with -a or -aa) * -p use standard cpp ANSI preprocessor (not on windows) * -V enable void* conversion warnings */ void main(int argc, char *argv[]) { char *defs[50], *p; int nproc, nout, status, i, c, ndef; memset(debug, 0, sizeof(debug)); tinit(); cinit(); ginit(); arginit(); profileflg = 1; /* #pragma can turn it off */ tufield = simplet((1L<etype) | BUNSIGNED); ndef = 0; outfile = 0; include[ninclude++] = "."; ARGBEGIN { default: c = ARGC(); if(c >= 0 && c < sizeof(debug)) debug[c]++; break; case 'o': outfile = ARGF(); break; case 'D': p = ARGF(); if(p) { defs[ndef++] = p; dodefine(p); } break; case 'I': p = ARGF(); setinclude(p); break; } ARGEND if(argc < 1 && outfile == 0) { print("usage: %cc [-options] files\n", thechar); errorexit(); } if(argc > 1 && systemtype(Windows)){ print("can't compile multiple files on windows\n"); errorexit(); } if(argc > 1 && !systemtype(Windows)) { nproc = 1; if(p = getenv("NPROC")) nproc = atol(p); /* */ c = 0; nout = 0; for(;;) { while(nout < nproc && argc > 0) { i = myfork(); if(i < 0) { i = mywait(&status); if(i < 0) { print("cannot create a process\n"); errorexit(); } if(status) c++; nout--; continue; } if(i == 0) { fprint(2, "%s:\n", *argv); if (compile(*argv, defs, ndef)) errorexit(); exits(0); } nout++; argc--; argv++; } i = mywait(&status); if(i < 0) { if(c) errorexit(); exits(0); } if(status) c++; nout--; } } if(argc == 0) c = compile("stdin", defs, ndef); else c = compile(argv[0], defs, ndef); if(c) errorexit(); exits(0); } int compile(char *file, char **defs, int ndef) { char ofile[100], incfile[20]; char *p, *av[100], opt[256]; int i, c, fd[2]; strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(outfile) { if(p = utfrrune(outfile, '.')) if(p[1] == 'c' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); if(debug['a'] && debug['n']) strcat(p, ".acid"); else if(debug['P'] && debug['n']) strcat(p, "_pickle.c"); else { p[0] = '.'; p[1] = thechar; p[2] = 0; } } else outfile = "/dev/null"; } if(p = getenv("INCLUDE")) { setinclude(p); } else { if(systemtype(Plan9)) { sprint(incfile, "/%s/include", thestring); setinclude(strdup(incfile)); setinclude("/sys/include"); } } if((debug['a'] || debug['P']) && !debug['n']) { outfile = 0; Binit(&outbuf, 1, OWRITE); } else { c = mycreat(outfile, 0664); if(c < 0) { diag(Z, "cannot open %s", outfile); outfile = 0; errorexit(); } Binit(&outbuf, c, OWRITE); } newio(); /* Use an ANSI preprocessor */ if(debug['p']) { if(systemtype(Windows)) { diag(Z, "-p option not supported on windows"); errorexit(); } if(myaccess(file) < 0) { diag(Z, "%s does not exist", file); errorexit(); } if(mypipe(fd) < 0) { diag(Z, "pipe failed"); errorexit(); } switch(myfork()) { case -1: diag(Z, "fork failed"); errorexit(); case 0: close(fd[0]); mydup(fd[1], 1); close(fd[1]); av[0] = CPP; i = 1; if(debug['+']) { sprint(opt, "-+"); av[i++] = strdup(opt); } for(c = 0; c < ndef; c++) { sprint(opt, "-D%s", defs[c]); av[i++] = strdup(opt); } for(c = 0; c < ninclude; c++) { sprint(opt, "-I%s", include[c]); av[i++] = strdup(opt); } if(strcmp(file, "stdin") != 0) av[i++] = file; av[i] = 0; if(debug['p'] > 1) { for(c = 0; c < i; c++) fprint(2, "%s ", av[c]); print("\n"); } myexec(av[0], av); fprint(2, "can't exec C preprocessor %s: %r\n", CPP); errorexit(); default: close(fd[1]); newfile(file, fd[0]); break; } } else { if(strcmp(file, "stdin") == 0) newfile(file, 0); else newfile(file, -1); } yyparse(); if(!debug['a'] && !debug['P']) gclean(); return nerrors; } void errorexit(void) { if(outfile) remove(outfile); exits("error"); } void pushio(void) { Io *i; i = iostack; if(i == I) { yyerror("botch in pushio"); errorexit(); } i->p = fi.p; i->c = fi.c; } void newio(void) { Io *i; static pushdepth = 0; i = iofree; if(i == I) { pushdepth++; if(pushdepth > 1000) { yyerror("macro/io expansion too deep"); errorexit(); } i = alloc(sizeof(*i)); } else iofree = i->link; i->c = 0; i->f = -1; ionext = i; } void newfile(char *s, int f) { Io *i; if(debug['e']) print("%L: %s\n", lineno, s); i = ionext; i->link = iostack; iostack = i; i->f = f; if(f < 0) i->f = open(s, 0); if(i->f < 0) { yyerror("%cc: %r: %s", thechar, s); errorexit(); } fi.c = 0; linehist(s, 0); } Sym* slookup(char *s) { strcpy(symb, s); return lookup(); } Sym* lookup(void) { Sym *s; ulong h; char *p; int c, n; h = 0; for(p=symb; *p;) { h = h * 3; h += *p++; } n = (p - symb) + 1; if((long)h < 0) h = ~h; h %= NHASH; c = symb[0]; for(s = hash[h]; s != S; s = s->link) { if(s->name[0] != c) continue; if(strcmp(s->name, symb) == 0) return s; } s = alloc(sizeof(*s)); s->name = alloc(n); memmove(s->name, symb, n); strcpy(s->name, symb); s->link = hash[h]; hash[h] = s; syminit(s); return s; } void syminit(Sym *s) { s->lexical = LNAME; s->block = 0; s->offset = 0; s->type = T; s->suetag = T; s->class = CXXX; s->aused = 0; } #define EOF (-1) #define IGN (-2) #define ESC (1<<20) #define GETC() ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff)) enum { Numdec = 1<<0, Numlong = 1<<1, Numuns = 1<<2, Numvlong = 1<<3, Numflt = 1<<4, }; long yylex(void) { vlong vv; long c, c1; char *cp; Rune rune; Sym *s; if(peekc != IGN) { c = peekc; peekc = IGN; goto l1; } l0: c = GETC(); l1: if(c >= Runeself) { /* * extension -- * all multibyte runes are alpha */ cp = symb; goto talph; } if(isspace(c)) { if(c == '\n') lineno++; goto l0; } if(isalpha(c)) { cp = symb; if(c != 'L') goto talph; *cp++ = c; c = GETC(); if(c == '\'') { /* L'x' */ c = escchar('\'', 1, 0); if(c == EOF) c = '\''; c1 = escchar('\'', 1, 0); if(c1 != EOF) { yyerror("missing '"); peekc = c1; } yylval.vval = convvtox(c, TUSHORT); return LUCONST; } if(c == '"') { goto caselq; } goto talph; } if(isdigit(c)) goto tnum; switch(c) { case EOF: peekc = EOF; return -1; case '_': cp = symb; goto talph; case '#': domacro(); goto l0; case '.': c1 = GETC(); if(isdigit(c1)) { cp = symb; *cp++ = c; c = c1; c1 = 0; goto casedot; } break; case '"': strcpy(symb, "\"\""); cp = alloc(0); c1 = 0; /* "..." */ for(;;) { c = escchar('"', 0, 1); if(c == EOF) break; if(c & ESC) { cp = allocn(cp, c1, 1); cp[c1++] = c; } else { rune = c; c = runelen(rune); cp = allocn(cp, c1, c); runetochar(cp+c1, &rune); c1 += c; } } yylval.sval.l = c1; do { cp = allocn(cp, c1, 1); cp[c1++] = 0; } while(c1 & MAXALIGN); yylval.sval.s = cp; return LSTRING; caselq: /* L"..." */ strcpy(symb, "\"L\""); cp = alloc(0); c1 = 0; for(;;) { c = escchar('"', 1, 0); if(c == EOF) break; cp = allocn(cp, c1, sizeof(ushort)); *(ushort*)(cp + c1) = c; c1 += sizeof(ushort); } yylval.sval.l = c1; do { cp = allocn(cp, c1, sizeof(ushort)); *(ushort*)(cp + c1) = 0; c1 += sizeof(ushort); } while(c1 & MAXALIGN); yylval.sval.s = cp; return LLSTRING; case '\'': /* '.' */ c = escchar('\'', 0, 0); if(c == EOF) c = '\''; c1 = escchar('\'', 0, 0); if(c1 != EOF) { yyerror("missing '"); peekc = c1; } vv = c; yylval.vval = convvtox(vv, TUCHAR); if(yylval.vval != vv) yyerror("overflow in character constant: 0x%lx", c); else if(c & 0x80) warn(Z, "sign-extended character constant"); yylval.vval = convvtox(vv, TCHAR); return LCONST; case '/': c1 = GETC(); if(c1 == '*') { for(;;) { c = getr(); while(c == '*') { c = getr(); if(c == '/') goto l0; } if(c == EOF) { yyerror("eof in comment"); errorexit(); } } } if(c1 == '/') { for(;;) { c = getr(); if(c == '\n') goto l0; if(c == EOF) { yyerror("eof in comment"); errorexit(); } } } if(c1 == '=') return LDVE; break; case '*': c1 = GETC(); if(c1 == '=') return LMLE; break; case '%': c1 = GETC(); if(c1 == '=') return LMDE; break; case '+': c1 = GETC(); if(c1 == '+') return LPP; if(c1 == '=') return LPE; break; case '-': c1 = GETC(); if(c1 == '-') return LMM; if(c1 == '=') return LME; if(c1 == '>') return LMG; break; case '>': c1 = GETC(); if(c1 == '>') { c = LRSH; c1 = GETC(); if(c1 == '=') return LRSHE; break; } if(c1 == '=') return LGE; break; case '<': c1 = GETC(); if(c1 == '<') { c = LLSH; c1 = GETC(); if(c1 == '=') return LLSHE; break; } if(c1 == '=') return LLE; break; case '=': c1 = GETC(); if(c1 == '=') return LEQ; break; case '!': c1 = GETC(); if(c1 == '=') return LNE; break; case '&': c1 = GETC(); if(c1 == '&') return LANDAND; if(c1 == '=') return LANDE; break; case '|': c1 = GETC(); if(c1 == '|') return LOROR; if(c1 == '=') return LORE; break; case '^': c1 = GETC(); if(c1 == '=') return LXORE; break; default: return c; } peekc = c1; return c; talph: /* * cp is set to symb and some * prefix has been stored */ for(;;) { if(c >= Runeself) { for(c1=0;;) { cp[c1++] = c; if(fullrune(cp, c1)) break; c = GETC(); } cp += c1; c = GETC(); continue; } if(!isalnum(c) && c != '_') break; *cp++ = c; c = GETC(); } *cp = 0; if(debug['L']) print("%L: %s\n", lineno, symb); peekc = c; s = lookup(); if(s->macro) { newio(); cp = ionext->b; macexpand(s, cp); pushio(); ionext->link = iostack; iostack = ionext; fi.p = cp; fi.c = strlen(cp); if(peekc != IGN) { cp[fi.c++] = peekc; cp[fi.c] = 0; peekc = IGN; } goto l0; } yylval.sym = s; if(s->class == CTYPEDEF || s->class == CTYPESTR) return LTYPE; return s->lexical; tnum: c1 = 0; cp = symb; if(c != '0') { c1 |= Numdec; for(;;) { *cp++ = c; c = GETC(); if(isdigit(c)) continue; goto dc; } } *cp++ = c; c = GETC(); if(c == 'x' || c == 'X') for(;;) { *cp++ = c; c = GETC(); if(isdigit(c)) continue; if(c >= 'a' && c <= 'f') continue; if(c >= 'A' && c <= 'F') continue; if(cp == symb+2) yyerror("malformed hex constant"); goto ncu; } if(c < '0' || c > '7') goto dc; for(;;) { if(c >= '0' && c <= '7') { *cp++ = c; c = GETC(); continue; } goto ncu; } dc: if(c == '.') goto casedot; if(c == 'e' || c == 'E') goto casee; ncu: if((c == 'U' || c == 'u') && !(c1 & Numuns)) { c = GETC(); c1 |= Numuns; goto ncu; } if((c == 'L' || c == 'l') && !(c1 & Numvlong)) { c = GETC(); if(c1 & Numlong) c1 |= Numvlong; c1 |= Numlong; goto ncu; } *cp = 0; peekc = c; if(mpatov(symb, &yylval.vval)) yyerror("overflow in constant"); vv = yylval.vval; if(c1 & Numvlong) { if(c1 & Numuns) { c = LUVLCONST; goto nret; } yylval.vval = convvtox(yylval.vval, TVLONG); if(yylval.vval < 0) { c = LUVLCONST; goto nret; } c = LVLCONST; goto nret; } if(c1 & Numlong) { if(c1 & Numuns) { c = LULCONST; goto nret; } yylval.vval = convvtox(yylval.vval, TLONG); if(yylval.vval < 0) { c = LULCONST; goto nret; } c = LLCONST; goto nret; } if(c1 & Numuns) { c = LUCONST; goto nret; } yylval.vval = convvtox(yylval.vval, TINT); if(yylval.vval < 0) { c = LUCONST; goto nret; } c = LCONST; goto nret; nret: return c; casedot: for(;;) { *cp++ = c; c = GETC(); if(!isdigit(c)) break; } if(c != 'e' && c != 'E') goto caseout; casee: *cp++ = 'e'; c = GETC(); if(c == '+' || c == '-') { *cp++ = c; c = GETC(); } if(!isdigit(c)) yyerror("malformed fp constant exponent"); while(isdigit(c)) { *cp++ = c; c = GETC(); } caseout: if(c == 'L' || c == 'l') { c = GETC(); c1 |= Numlong; } else if(c == 'F' || c == 'f') { c = GETC(); c1 |= Numflt; } *cp = 0; peekc = c; yylval.dval = strtod(symb, nil); if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) { yyerror("overflow in float constant"); yylval.dval = 0; } if(c1 & Numflt) return LFCONST; return LDCONST; } /* * convert a string, s, to vlong in *v * return conversion overflow. * required syntax is [0[x]]d* */ int mpatov(char *s, vlong *v) { vlong n, nn; int c; n = 0; c = *s; if(c == '0') goto oct; while(c = *s++) { if(c >= '0' && c <= '9') nn = n*10 + c-'0'; else goto bad; if(n < 0 && nn >= 0) goto bad; n = nn; } goto out; oct: s++; c = *s; if(c == 'x' || c == 'X') goto hex; while(c = *s++) { if(c >= '0' || c <= '7') nn = n*8 + c-'0'; else goto bad; if(n < 0 && nn >= 0) goto bad; n = nn; } goto out; hex: s++; while(c = *s++) { if(c >= '0' && c <= '9') c += 0-'0'; else if(c >= 'a' && c <= 'f') c += 10-'a'; else if(c >= 'A' && c <= 'F') c += 10-'A'; else goto bad; nn = n*16 + c; if(n < 0 && nn >= 0) goto bad; n = nn; } out: *v = n; return 0; bad: *v = ~0; return 1; } int getc(void) { int c; if(peekc != IGN) { c = peekc; peekc = IGN; } else c = GETC(); if(c == '\n') lineno++; if(c == EOF) { yyerror("End of file"); errorexit(); } return c; } long getr(void) { int c, i; char str[UTFmax+1]; Rune rune; c = getc(); if(c < Runeself) return c; i = 0; str[i++] = c; loop: c = getc(); str[i++] = c; if(!fullrune(str, i)) goto loop; c = chartorune(&rune, str); if(rune == Runeerror && c == 1) { nearln = lineno; diag(Z, "illegal rune in string"); for(c=0; c0; i--) { c = getc(); if(c >= '0' && c <= '9') { l = l*16 + c-'0'; continue; } if(c >= 'a' && c <= 'f') { l = l*16 + c-'a' + 10; continue; } if(c >= 'A' && c <= 'F') { l = l*16 + c-'A' + 10; continue; } unget(c); break; } if(escflg) l |= ESC; return l; } if(c >= '0' && c <= '7') { /* * note this is not ansi, * supposed to only accept 3 oct */ i = 2; if(longflg) i = 5; l = c - '0'; for(; i>0; i--) { c = getc(); if(c >= '0' && c <= '7') { l = l*8 + c-'0'; continue; } unget(c); } if(escflg) l |= ESC; return l; } switch(c) { case '\n': goto loop; case 'n': r