diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /utils/c2l | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'utils/c2l')
| -rw-r--r-- | utils/c2l/Nt.c | 131 | ||||
| -rw-r--r-- | utils/c2l/Plan9.c | 108 | ||||
| -rw-r--r-- | utils/c2l/Posix.c | 91 | ||||
| -rw-r--r-- | utils/c2l/acid.c | 13 | ||||
| -rw-r--r-- | utils/c2l/bits.c | 89 | ||||
| -rw-r--r-- | utils/c2l/c2l.c | 5118 | ||||
| -rw-r--r-- | utils/c2l/cc.h | 849 | ||||
| -rw-r--r-- | utils/c2l/cc.y | 1239 | ||||
| -rw-r--r-- | utils/c2l/com.c | 918 | ||||
| -rw-r--r-- | utils/c2l/com64.c | 52 | ||||
| -rw-r--r-- | utils/c2l/dcl.c | 1387 | ||||
| -rw-r--r-- | utils/c2l/dpchk.c | 392 | ||||
| -rw-r--r-- | utils/c2l/lex.c | 1675 | ||||
| -rw-r--r-- | utils/c2l/lexbody | 650 | ||||
| -rw-r--r-- | utils/c2l/mac.c | 3 | ||||
| -rw-r--r-- | utils/c2l/macbody | 773 | ||||
| -rw-r--r-- | utils/c2l/mkfile | 38 | ||||
| -rw-r--r-- | utils/c2l/mpatof.c | 337 | ||||
| -rw-r--r-- | utils/c2l/out.c | 825 | ||||
| -rw-r--r-- | utils/c2l/scon.c | 250 | ||||
| -rw-r--r-- | utils/c2l/sub.c | 1694 |
21 files changed, 16632 insertions, 0 deletions
diff --git a/utils/c2l/Nt.c b/utils/c2l/Nt.c new file mode 100644 index 00000000..bf36e0dd --- /dev/null +++ b/utils/c2l/Nt.c @@ -0,0 +1,131 @@ +#include <windows.h> +#include <lib9.h> + +#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) +{ + int ok; + + ok = _dup2(f1, f2); + if(ok < 0) + return -1; + return 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) +{ +} diff --git a/utils/c2l/Plan9.c b/utils/c2l/Plan9.c new file mode 100644 index 00000000..853df40b --- /dev/null +++ b/utils/c2l/Plan9.c @@ -0,0 +1,108 @@ +#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); +} + +/* + * 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 +myfork(void) +{ + return fork(); +} + +void +setmalloctag(void*, ulong) +{ +} diff --git a/utils/c2l/Posix.c b/utils/c2l/Posix.c new file mode 100644 index 00000000..065f1e20 --- /dev/null +++ b/utils/c2l/Posix.c @@ -0,0 +1,91 @@ +#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(size_t n) +{ + return alloc(n); +} + +void* +calloc(size_t m, size_t n) +{ + return alloc(m*n); +} + +void* +realloc(void *p, size_t n) +{ + fprint(2, "realloc called\n"); + abort(); + return 0; +} + +void +free(void *p) +{ +} + +int +myfork(void) +{ + return fork(); +} diff --git a/utils/c2l/acid.c b/utils/c2l/acid.c new file mode 100644 index 00000000..c31e600f --- /dev/null +++ b/utils/c2l/acid.c @@ -0,0 +1,13 @@ +#include "cc.h" + +void +acidtype(Type *t) +{ + USED(t); +} + +void +acidvar(Sym *s) +{ + USED(s); +} diff --git a/utils/c2l/bits.c b/utils/c2l/bits.c new file mode 100644 index 00000000..a22ba512 --- /dev/null +++ b/utils/c2l/bits.c @@ -0,0 +1,89 @@ +#include "cc.h" + +Bits +bor(Bits a, Bits b) +{ + Bits c; + int i; + + for(i=0; i<BITS; i++) + c.b[i] = a.b[i] | b.b[i]; + return c; +} + +Bits +band(Bits a, Bits b) +{ + Bits c; + int i; + + for(i=0; i<BITS; i++) + c.b[i] = a.b[i] & b.b[i]; + return c; +} + +/* +Bits +bnot(Bits a) +{ + Bits c; + int i; + + for(i=0; i<BITS; i++) + c.b[i] = ~a.b[i]; + return c; +} +*/ + +int +bany(Bits *a) +{ + int i; + + for(i=0; i<BITS; i++) + if(a->b[i]) + return 1; + return 0; +} + +int +beq(Bits a, Bits b) +{ + int i; + + for(i=0; i<BITS; i++) + if(a.b[i] != b.b[i]) + return 0; + return 1; +} + +int +bnum(Bits a) +{ + int i; + long b; + + for(i=0; i<BITS; i++) + if(b = a.b[i]) + return 32*i + bitno(b); + diag(Z, "bad in bnum"); + return 0; +} + +Bits +blsh(uint n) +{ + Bits c; + + c = zbits; + c.b[n/32] = 1L << (n%32); + return c; +} + +int +bset(Bits a, uint n) +{ + if(a.b[n/32] & (1L << (n%32))) + return 1; + return 0; +} diff --git a/utils/c2l/c2l.c b/utils/c2l/c2l.c new file mode 100644 index 00000000..f870d640 --- /dev/null +++ b/utils/c2l/c2l.c @@ -0,0 +1,5118 @@ +#define EXTERN + +#include "cc.h" + +/* + * locals, parameters, globals etc of the same name should work ok without having + * to duplicate Syms because the details are on the containing Nodes + */ + +#define SZ_CHAR 1 +#define SZ_SHORT 2 +#define SZ_INT 4 +#define SZ_LONG 4 +#define SZ_FLOAT 4 +#define SZ_IND 4 +#define SZ_VLONG 8 +#define SZ_DOUBLE 8 + +char buf[128], mbuf[128]; +static Sym *sysop, *bioop, *libcop; +static int again; + +#define INFINITY 0x7fffffff +#define STAR 0x80 +#define RET 0x80 + +#define LARR (-1729) + +static void swalk(void); +static int isdec(Node*); +static int isconst(Node*, vlong); +static int cktype(Node*, Node*, int, int); +static void addnode(int, Node*); +static int argpos(Node*, Node*); +static void setdec(Sym*, Type*); +static Type* tcp(Type*); +static int isadt(Type*); +static void aargs(Node*); +static int iteq(Type*, Type*); +static Node* arg(Node*, int); +static void etgen2(Sym*); +static Node* ckneg(Node*); +static Sym* suename(Type*); +static int isnil(Node*); +static void sliceasgn(Node*); +static Node* lastn(Node*); +static char* hasm(void); +static void prn(Node*, int); +static int isfn(Type*); + +schar ewidth[NTYPE] = +{ + -1, /* [TXXX] */ + SZ_CHAR, /* [TCHAR] */ + SZ_CHAR, /* [TUCHAR] */ + SZ_SHORT, /* [TSHORT] */ + SZ_SHORT, /* [TUSHORT] */ + SZ_INT, /* [TINT] */ + SZ_INT, /* [TUINT] */ + SZ_LONG, /* [TLONG] */ + SZ_LONG, /* [TULONG] */ + SZ_VLONG, /* [TVLONG] */ + SZ_VLONG, /* [TUVLONG] */ + SZ_FLOAT, /* [TFLOAT] */ + SZ_DOUBLE, /* [TDOUBLE] */ + SZ_IND, /* [TIND] */ + 0, /* [TFUNC] */ + -1, /* [TARRAY] */ + 0, /* [TVOID] */ + -1, /* [TSTRUCT] */ + -1, /* [TUNION] */ + SZ_INT, /* [TENUM] */ +}; + +long ncast[NTYPE] = +{ + 0, /* [TXXX] */ + BCHAR|BUCHAR, /* [TCHAR] */ + BCHAR|BUCHAR, /* [TUCHAR] */ + BSHORT|BUSHORT, /* [TSHORT] */ + BSHORT|BUSHORT, /* [TUSHORT] */ + BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */ + BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */ + BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */ + BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */ + BVLONG|BUVLONG, /* [TVLONG] */ + BVLONG|BUVLONG, /* [TUVLONG] */ + BFLOAT, /* [TFLOAT] */ + BDOUBLE, /* [TDOUBLE] */ + BLONG|BULONG|BIND, /* [TIND] */ + 0, /* [TFUNC] */ + 0, /* [TARRAY] */ + 0, /* [TVOID] */ + BSTRUCT, /* [TSTRUCT] */ + BUNION, /* [TUNION] */ + 0, /* [TENUM] */ +}; + +enum{ + TCFD = 1, + TCFC = 2, + TCPC = 4, + TCAR = 8, + TCIN = 16, + TCGEN = TCFD|TCFC|TCPC|TCAR, + TCALL = TCFD|TCFC|TCPC|TCAR|TCIN, +}; + +enum{ + SGLOB, + SPARM, + SAUTO, +}; + +typedef struct Scope Scope; + +struct Scope{ + Node *n; + int k; + Scope *nxt; +}; + +static void +prtyp(Type *t, char *s, int nl) +{ + print("%s: ", s); + if(t == T){ + print("nil"); + if(nl) + print("\n"); + return; + } + while(t != T){ + print("%d(%d)[%x] ", t->etype, t->mark, (int)t); + if(isadt(t)) + break; + t = t->link; + } + if(nl) + print("\n"); +} + +static Node* +func(Node *n) +{ + while(n != Z && n->op != OFUNC) + n = n->left; + return n; +} + +static void +setmain(Node *n) +{ + inmain |= n->left->op == ONAME && strcmp(n->left->sym->name, "main") == 0; +} + +static Node* +protoname(Node *n) +{ + do + n = n->left; + while(n != Z && n->op != ONAME && n->op != ODOTDOT); + return n; +} + +static Type* +prototype(Node *n, Type *t) +{ + for( ; n != Z ; n = n->left){ + switch(n->op){ + case OARRAY: + t = typ(TARRAY, t); + t->width = 0; + break; + case OIND: + t = typ(TIND, t); + break; + case OFUNC: + t = typ(TFUNC, t); + t->down = fnproto(n); + break; + } + } + return t; +} + +static Scope *scopes, *freescopes; + +static void +pushdcl(Node *n, int c) +{ + Sym *s; + + if(passes){ + s = n->sym; + push1(s); + if(c != CAUTO || s->class != CSTATIC) + s->class = c; + s->type = n->type; + } +} + +static void +pushparams(Node *n) +{ + if(n == Z) + return; + if(passes){ + if(n->op == OLIST){ + pushparams(n->left); + pushparams(n->right); + } + else if(n->op == OPROTO){ + n = protoname(n); + if(n != Z && n->op == ONAME) + pushdcl(n, CPARAM); + } + else if(n->op == ONAME){ + addnode(OPROTO, n); + pushdcl(n, CPARAM); + } + else if(n->op != ODOTDOT) + diag(Z, "bad op in pushparams"); + } +} + +static void +pushscope(Node *n, int k) +{ + Scope *s; + + if(freescopes != nil){ + s = freescopes; + freescopes = freescopes->nxt; + } + else + s = (Scope*)malloc(sizeof(Scope)); + s->n = n; + s->k = k; + s->nxt = scopes; + scopes = s; + if(passes && (k == SPARM || k == SAUTO)) + markdcl(); + if(k == SPARM) + pushparams(n->right); +} + +static void +popscope(void) +{ + int k; + Scope *s; + + s = scopes; + k = s->k; + scopes = scopes->nxt; + s->nxt = freescopes; + freescopes = s; + if(passes && (k == SPARM || k == SAUTO)) + revertdcl(); +} + +static Node* +curfn(void) +{ + Scope *s; + + for(s = scopes; s != nil; s = s->nxt) + if(s->k == SPARM) + return s->n; + return Z; +} + +static void +marktype(Type *t, int tc) +{ + t->mark = tc; +} + +static int +marked(Type *t) +{ + return t == T ? 0 : t->mark; +} + +static Sym* +decsym(Node *n) +{ + if(n == Z) + return S; + if(n->op == OFUNC){ + if(n->left->op == ONAME) + return n->left->sym; + return S; + } + if(n->op == ODAS) + return n->left->sym; + return n->sym; +} + +static void +trep(Type *t1, Type *t) +{ + int l; + Sym *s; + Type *t2; + + if(t1 != T){ + l = t1->lineno; + s = t1->sym; + t2 = t1->down; + *t1 = *t; + t1->down = t2; + t1->sym = s; + t1->lineno = l; + } +} + +static void +tind(Node *n) +{ + if(n == Z) + return; + n = protoname(n); + if(n != Z && n->type != T){ + n->type = tcp(n->type->link); + marktype(n->type, TCIN); + } +} + +static void +tcon(Node *n, Type *t) +{ + Type *tt; + + if(n->garb) + return; + n->garb = 1; + again = 1; + switch(n->op){ + case OCONST: + if(t->mark == TCFD && !isnil(n)) + addnode(OFILDES, n); + n->type = t; + break; + case OCAST: + tcon(n->left, t); + *n = *n->left; + n->type = t; + break; + case ONAME: + n->sym->type = t; + n->type = t; + setdec(n->sym, t); + break; + case ODOT: + case ODOTIND: + trep(n->type, t); + n->type = t; + break; + case OARRIND: + tt = n->left->type; + if(tt != T) + tt->link = t; + n->type = t; + break; + case OFUNC: + n->left->type->link = t; + if(n->left->op == ONAME) + n->left->sym->type->link = t; + n->type = t; + break; + } +} + +static Node* +retval(Node *n) +{ + int i; + Type *t; + Node *a, *l, *cf; + + cf = curfn(); + t = cf->left->type->link; + if(t->mark&(TCPC|TCFC) && (n == Z || !(n->type->mark&(TCPC|TCFC)))){ + if(n == Z) + n = new1(ORETURN, Z, Z); + l = n->left; + for(i = 0; ; i++){ + a = arg(cf->right, i); + if(a == Z) + break; + a = protoname(a); + if(a == Z || a->op != ONAME) + break; + if(a->type->mark == TCIN){ + if(l == Z) + l = ncopy(a); + else + l = new1(OTUPLE, l, ncopy(a)); + } + } + n->left = l; + n->type = l->type = t; + } + return n; +} + +static void +sube(Node *n) +{ + Node *l, *r, *nn; + Type *tt; + static Node *gn; + int p; + + if(n == Z) + return; + l = n->left; + r = n->right; + switch(n->op){ + default: + sube(l); + sube(r); + break; + case OIND: + if(l == Z) + return; + tt = l->type; + sube(l); + if(cktype(l, n, TCIN, 0) && iteq(tt, l->type)) + *n = *n->left; + break; + case OARRIND: + tt = l->type; + sube(l); + sube(r); + if(!isconst(r, 0)) + break; + if(cktype(l, n, TCIN, 0) && iteq(tt, l->type)) + *n = *n->left; + break; + case ONAME: + if(cktype(n, n, TCALL, 0)) + setdec(n->sym, n->type); + break; + case OCAST: + sube(l); + if(cktype(l, n, TCALL, 0)) + n->type = l->type; + break; + case OPROTO: + sube(l); + sube(r); + nn = protoname(n); + if(nn != Z && cktype(nn, n, TCALL, 0)){ + n->type = nn->type; + p = argpos(n, gn->right); + for(tt = gn->left->type->down; tt != T && p >= 0; tt = tt->down){ + if(p == 0){ + trep(tt, nn->type); + break; + } + --p; + } + } + break; + case OFUNC: + if(n->kind == KEXP) + aargs(n); + if(n->left->op == ONAME) + gn = n; + sube(l); + sube(r); + if(l != Z && cktype(n, n, TCGEN, 0)) + l->type->link = n->type; + break; + case OAS: + sube(l); + sube(r); + if(r->op == ORETV){ + n->left = new1(OTUPLE, l, r->right); + n->right = r->left; + n->left->type = n->type; + break; + } + if(cktype(r, n, TCGEN, 0)){ + tcon(l, r->type); + n->type = r->type; + } + if(cktype(l, n, TCGEN, 1)){ + tcon(r, l->type); + n->type = l->type; + } + break; + case OLT: + case OGE: + sube(l); + sube(r); + if(cktype(l, n, TCFD, 0) && isconst(r, 0)){ + n->op = n->op == OLT ? OEQ : ONE; + r->op = ONIL; + r->type = l->type; + } + break; + case OGT: + case OLE: + sube(l); + sube(r); + if(cktype(r, n, TCFD, 0) && isconst(l, 0)){ + n->op = n->op == OGT ? OEQ : ONE; + l->op = ONIL; + l->type = r->type; + } + break; + } +} + +static void +subs(Node *n, int blk, int aut) +{ + Node *l, *r; + + if(n == Z) + return; + if(blk) + pushscope(n, SAUTO); + nearln = n->lineno; + l = n->left; + r = n->right; + switch(n->op){ + default: + sube(n); + break; + case ONAME: + if(aut && n->kind != KEXP) + pushdcl(n, CAUTO); + if(cktype(n, n, TCALL, 0)) + setdec(n->sym, n->type); + break; + case ODAS: + if(aut) + pushdcl(l, CAUTO); + subs(l, 0, aut); + if(cktype(l, n, TCALL, 0)) + tcon(r, l->type); + break; + case OSBREAK: + case ONUL: + case OLABEL: + case OGOTO: + case OCONTINUE: + case OBREAK: + case OSET: + case OUSED: + break; + case OBLK: + subs(l, 1, aut); + break; + case OCASE: + subs(r, 1, aut); + break; + case OLIST: + subs(l, 0, aut); + subs(r, 0, aut); + break; + case ORETURN: + sube(l); + if(l != Z && cktype(l, n, TCGEN, 0)){ + n->type = l->type; + tcon(curfn(), l->type); + } + retval(n); + break; + case OSWITCH: + case OWHILE: + case ODWHILE: + sube(l); + subs(r, 1, aut); + break; + case OIF: + sube(l); + subs(r->left, 1, aut); + subs(r->right, 1, aut); + break; + case OFOR: + sube(l->left); + sube(l->right->left); + sube(l->right->right); + subs(r, 1, aut); + break; + } + if(blk) + popscope(); +} + +static Node* +finddec0(Sym *s, Node *n) +{ + Node *nn; + + if(n == Z) + return ZZ; + switch(n->op){ + case OLIST: + nn = finddec0(s, n->left); + if(nn != Z) + return nn; + return finddec0(s, n->right); + case OFUNC: + if(n->op != KEXP){ + if(s == decsym(n)) + return n; + return finddec0(s, n->right); + } + else + return ZZ; + case OPROTO: + case OIND: + case OARRAY: + return finddec0(s, n->left); + case ODOTDOT: + return ZZ; + case ONOOP: + case OPUSH: + case OPOP: + case OCODE: + case ODECE: + case ODECT: + return finddec0(s, n->right); + case ODECV: + case ODECF: + if(s == decsym(n->left) && !isfn(n->left->type)) + return n->left; + return finddec0(s, n->right); + } + if(isdec(n)){ + if(s == decsym(n) && !isfn(n->type)) + return n; + return Z; + } + return ZZ; +} + +static Node* +finddec(Sym *s, int g) +{ + Node *n; + Scope *sc; + + for(sc = scopes; sc != nil; sc = sc->nxt){ + if(!g || sc->k == SGLOB){ + n = finddec0(s, sc->n); + if(n != Z && n != ZZ) + return n; + } + } + return Z; +} + +static void +setdec(Sym *s, Type *t) +{ + Node *n; + + if((n = finddec(s, 0)) != Z){ + n->type = t; + if(n->op == ODAS){ + n = n->left; + n->type = t; + } + n->sym->type = t; + } +} + +typedef struct Syml Syml; + +struct Syml{ + Sym *sym; + Syml *nxt; +}; + +typedef struct Symq Symq; + +struct Symq{ + Syml *f; + Syml *r; +}; + +typedef struct Modl Modl; + +struct Modl{ + char *mod; + int ld; + Modl *nxt; +}; + +static void +prn(Node *n, int i) +{ + int j; + + for(j = 0; j < i; j++) + print("\t"); + if(n == Z){ + print("Z\n"); + return; + } + print("%s", onames[n->op]); + if(n->blk) + print(" block"); + if(n->type == T) + print(" T"); + else + print(" %s", tnames[n->type->etype]); + if(n->op == OCONST) + print(" %d", (int)n->vconst); + else if(n->op == OSTRING) + print(" %s", n->cstring); + else if(n->op == ONAME) + print(" %s", n->sym->name); + print("\n"); + if(n->op != OLIST) + i++; + prn(n->left, i); + prn(n->right, i); +} + +static int +isbigv(vlong v) +{ + return v > 0xffffffff; +} + +static int +islbigv(vlong v) +{ + return v > 0x7fffffff || v < -0x7fffffff; +} + +static int +isuintv(vlong v) +{ + return !isbigv(v) && (v&0x80000000) != 0; +} + +static int +isadt(Type *t) +{ + return t != T && (t->etype == TSTRUCT || t->etype == TUNION); +} + +static int +isreal(Type *t) +{ + return t != T && (t->etype == TDOUBLE || t->etype == TFLOAT); +} + +static int +isbyte(Type *t) +{ + return t != T && (t->etype == TCHAR || t->etype == TUCHAR); +} + +static int +isshort(Type *t) +{ + return t != T && (t->etype == TSHORT || t->etype == TUSHORT); +} + +static int +isint(Type *t) +{ + return t != T && (t->etype == TINT || t->etype == TUINT); +} + +static int +islong(Type *t) +{ + return t != T && (t->etype == TLONG || t->etype == TULONG); +} + +static int +isbig(Type *t) +{ + return t != T && (t->etype == TVLONG || t->etype == TUVLONG); +} + +static int +isinteger(Type *t) +{ + return isbyte(t) || isshort(t) || isint(t) || islong(t) || isbig(t); +} + +static int +isptr(Type *t) +{ + return t != T && (t->etype == TIND || t->etype == TARRAY || t->etype == TFUNC); +} + +static int +isscalar(Type *t) +{ + return t != T && !isadt(t) && t->etype != TTUPLE; +} + +static int +isvoid(Type *t) +{ + return t == T || t->etype == TVOID; +} + +static int +isnum(Type *t) +{ + return t != T && isscalar(t) && !isptr(t) && !isvoid(t); +} + +static int +isarray(Type *t) +{ + return t != T && (t->etype == TARRAY || (t->etype == TIND && !isadt(t->link))); +} + +static int +isstr(Type *t) +{ + return t != T && (t->etype == TSTRING || isarray(t) && isbyte(t->link)); +} + +static int +isfn(Type *t) +{ + return t != T && t->etype == TFUNC; +} + +static int +iscastable(Type *t, Type *tt) +{ + return t != T && (!isptr(t) || isarray(t) && isbyte(t->link) && isstr(tt)); +} + +static int +isname(Node *n) +{ + return n->op == ONAME; +} + +static int +isstring(Node *n) +{ + return n->op == OSTRING || n->op == OLSTRING || n->op == ONAME && n->sym->tenum != T && n->sym->tenum->etype == TIND; +} + +static int +isnil(Node *n) +{ + if(!isptr(n->type)) + return 0; + while(n->op == OCAST) + n = n->left; + return n->op == OCONST && n->vconst == 0 || n->op == ONIL; +} + +static int +isconst(Node *n, vlong v) +{ + while(n->op == OCAST) + n = n->left; + return n->op == OCONST && n->vconst == v; +} + +static Node* +cknil(Node *n) +{ + if(isconst(n, 0)) + n->op = ONIL; + return n; +} + +static int +cktype(Node *n, Node *t, int mask, int lev) +{ + int g, m, m0; + + g = t->garb > lev; + m = marked(n->type) & mask; + if(n->op == ONAME){ + m0 = marked(n->sym->type) & mask; + if(m && !m0){ + n->sym->type = n->type; + if(!g) + again = 1; + } + if(!m && m0){ + n->type = n->sym->type; + if(!g) + again = 1; + } + m |= m0; + } + if(m && t->garb < 2) + t->garb++; + return m && !g ? m : 0; +} + +int +isconsym(Sym *s) +{ + switch(s->class){ + case CXXX: + case CTYPEDEF: + return 1; + case CEXTERN: + case CGLOBL: + case CSTATIC: + case CLOCAL: + return s->type != T && s->type->etype == TENUM; + } + return -1; +} + +static void genstart(void); + +static char* +mprolog[] = +{ + "%%: module", + "{", + "\tPATH: con \"%%%.dis\";", + "", + nil +}; + +static char* +mepilog[] = +{ + "};", + nil +}; + +static char* +bprolog[] = +{ + "implement %%;", + "", + "include \"draw.m\";", + "", + "%%: module", + "{", + " init: fn(nil: ref Draw->Context, argl: list of string);", + "};", + "", + nil +}; + +static char* +bmprolog[] = +{ + "implement %%;", + "", + "include \"draw.m\";", + "", + nil +}; + +static char* +bepilog[] = +{ + nil +}; + +static void +pgen0(char **txt) +{ + int sub; + char *b, *s, *t, **p; + + p = txt; + for(;;){ + s = *p++; + if(s == nil) + break; + sub = 0; + for(t = s; *t != 0; t++){ + if(*t == '%' && *(t+1) == '%'){ + sub = 1; + break; + } + } + if(sub){ + strcpy(buf, s); + b = buf; + for(t = s; *t != 0; t++){ + if(*t == '%' && *(t+1) == '%'){ + if(*(t+2) == '%'){ + outmod(mbuf, 0); + t++; + } + else + outmod(mbuf, 1); + strcpy(b, mbuf); + b += strlen(mbuf); + t++; + } + else + *b++ = *t; + } + *b = 0; + prline(buf); + } + else + prline(s); + } +} + +static char* +hasm() +{ + outmod(mbuf, 0); + strcat(mbuf, ".m"); + if(exists(mbuf)) + return mbuf; + else if(domod){ + outmod(buf, 0); + strcat(buf, ".h"); + if(exists(buf)) + return mbuf; + } + return nil; +} + +void +pgen(int b) +{ + char **p; + + if(!dolog()) + return; + if(b) + p = hasm() ? bmprolog : bprolog; + else + p = mprolog; + pgen0(p); + if(b && passes) + genstart(); + if(!b) + incind(); +} + +void +epgen(int b) +{ + char **p; + + /* output(INFINITY, 1); */ + if(!dolog()) + return; + if(b){ + if(!passes) + genstart(); + p = bepilog; + } + else + p = mepilog; + if(!b) + decind(); + pgen0(p); +} + +static int lastsec = 0; + +#define ASSOC 1 +#define RASSOC 2 +#define POSTOP 4 + +#define LEFT 1 +#define RIGHT 2 +#define PRE 4 +#define POST 8 + +static int space[] = { 0, 0, 2, 0, 4, 5, 0, 0, 0, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0 }; + +static struct{ + char *name; + int prec; + int kind; +} ops[] = { + "", 0, 0, /* ONOOP */ + "", 16, 0, /* OXXX, */ + "+", 12, ASSOC, /* OADD, */ + "&", 14, RASSOC, /* OADDR, */ + "&", 8, ASSOC, /* OAND, */ + "&&", 5, ASSOC, /* OANDAND, */ + "", 16, 0, /* OARRAY, */ + "=", 2, RASSOC, /* OAS, */ + "=", 2, RASSOC, /* OASI, */ + "+=", 2, RASSOC, /* OASADD, */ + "&=", 2, RASSOC, /* OASAND, */ + "<<=", 2, RASSOC, /* OASASHL, */ + ">>=", 2, RASSOC, /* OASASHR, */ + "/=", 2, RASSOC, /* OASDIV, */ + "<<", 11, 0, /* OASHL, */ + ">>", 11, 0, /* OASHR, */ + "/=", 2, RASSOC, /* OASLDIV, */ + "%=", 2, RASSOC, /* OASLMOD, */ + "*=", 2, RASSOC, /* OASLMUL, */ + ">>=", 2, RASSOC, /* OASLSHR, */ + "%=", 2, RASSOC, /* OASMOD, */ + "*=", 2, RASSOC, /* OASMUL, */ + "|=", 2, RASSOC, /* OASOR, */ + "-=", 2, RASSOC, /* OASSUB, */ + "^=", 2, RASSOC, /* OASXOR, */ + "", -1, 0, /* OBIT, */ + "", -1, 0, /* OBREAK, */ + "", -1, 0, /* OCASE, */ + "", 14, RASSOC, /* OCAST, */ + "", 1, ASSOC, /* OCOMMA, */ + "", 3, RASSOC, /* OCOND, */ + "", 16, 0, /* OCONST, */ + "", -1, 0, /* OCONTINUE, */ + "/", 13, 0, /* ODIV, */ + ".", 15, 0, /* ODOT, */ + "...", 16, 0, /* ODOTDOT, */ + "", -1, 0, /* ODWHILE, */ + "", -1, 0, /* OENUM, */ + "==", 9, 0, /* OEQ, */ + "", -1, 0, /* OFOR, */ + "", 15, 0, /* OFUNC, */ + ">=", 10, 0, /* OGE, */ + "", -1, 0, /* OGOTO, */ + ">", 10, 0, /* OGT, */ + ">", 10, 0, /* OHI, */ + ">=", 10, 0, /* OHS, */ + "", -1, 0, /* OIF, */ + "*", 14, RASSOC, /* OIND, */ + "", -1, 0, /* OINDREG, */ + "", 16, 0, /* OINIT, */ + "", -1, 0, /* OLABEL, */ + "/", 13, 0, /* OLDIV, */ + "<=", 10, 0, /* OLE, */ + "", 16, 0, /* OLIST, */ + "%", 13, 0, /* OLMOD, */ + "*", 13, ASSOC, /* OLMUL, */ + "<", 10, 0, /* OLO, */ + "<=", 10, 0, /* OLS, */ + ">>", 11, 0, /* OLSHR, */ + "<", 10, 0, /* OLT, */ + "%", 13, 0, /* OMOD, */ + "*", 13, ASSOC, /* OMUL, */ + "", 16, 0, /* ONAME, */ + "!=", 9, 0, /* ONE, */ + "!", 14, RASSOC, /* ONOT, */ + "|", 6, ASSOC, /* OOR, */ + "||", 4, ASSOC, /* OOROR, */ + "--", 14, RASSOC|POSTOP, /* OPOSTDEC, */ + "++", 14, RASSOC|POSTOP, /* OPOSTINC, */ + "--", 14, RASSOC, /* OPREDEC, */ + "++", 14, RASSOC, /* OPREINC, */ + "", 16, 0, /* OPROTO, */ + "", -1, 0, /* OREGISTER, */ + "", 0, 0, /* ORETURN, */ + "SET", -1, 0, /* OSET, */ + "signof", 14, RASSOC, /* OSIGN, */ + "sizeof", 14, RASSOC, /* OSIZE, */ + "", 16, 0, /* OSTRING, */ + "", 16, 0, /* OLSTRING, */ + "", 16, 0, /* OSTRUCT, */ + "-", 12, 0, /* OSUB, */ + "", -1, 0, /* OSWITCH, */ + "", 16, 0, /* OUNION, */ + "USED", -1, 0, /* OUSED, */ + "", -1, 0, /* OWHILE, */ + "^", 7, ASSOC, /* OXOR, */ + "-", 14, RASSOC, /* ONEG, */ + "~", 14, RASSOC, /* OCOM, */ + "", 16, 0, /* OELEM, */ + "", -1, 0, /* OTST, */ + "", -1, 0, /* OINDEX, */ + "", -1, 0, /* OFAS, */ + "", -1, 0, /* OBLK */ + "+", 14, RASSOC, /* OPOS */ + "", -1, 0, /* ONUL */ + ".", 15, 0, /* ODOTIND */ + "", 15, 0, /* OARRIND */ + "", -1, 0, /* ODAS */ + ":=", 2, RASSOC, /* OASD */ + "", 16, 0, /* OIOTA */ + "", 14, RASSOC, /* OLEN */ + "", 17, 0, /* OBRACKET */ + "", 14, RASSOC, /* OREF */ + "", 14, RASSOC, /* OARRAYOF */ + "", 15, 0, /* OSLICE */ + "&", 14, RASSOC, /* OSADDR, */ + "", 16, 0, /* ONIL */ + "", 16, 0, /* OS2AB */ + "", 16, 0, /* OAB2S */ + "", 16, 0, /* OFILDES */ + ".", 15, 0, /* OFD */ + "", 16, 0, /* OTUPLE */ + ".", 15, 0, /* OT0 */ + "", 15, 0, /* ORETV */ + "+", 12, ASSOC, /* OCAT */ + "", -1, 0, /* OSBREAK, */ + ".", 15, 0, /* OLDOT */ + "->", 15, 0, /* OMDOT */ + nil, -1, 0, /* OCODE */ + nil, -1, 0, /* ODECE */ + nil, -1, 0, /* ODECT */ + nil, -1, 0, /* ODECV */ + nil, -1, 0, /* ODECF */ + nil, -1, 0, /* OPUSH */ + nil, -1, 0, /* OPOP */ + "", -1, 0, /* OEND */ +}; + +#define COMPLEX 32 + +#define NOBR 2 +#define NOIN 4 +#define YESBR 8 +#define NONL 16 +#define NOENL 32 + +enum{ + LNONE, + LSTRLEN, + LSTRCMP, + LSTRCPY, + LSTRCAT, + LSTRNCMP, + LSTRNCPY, + LSTRNCAT, + LSTRDUP, + LMEMMOVE, + LMALLOC, + LFREE, + LEXIT, + LCLOSE, + LATOI, + LATOL, + LATOF, + LPRINT, + LFPRINT, + LSPRINT, + LSELF, +}; + +static int tmp; + +static void egen(Node*, int, int); +static Node* buildcases(Node*); +static void tdgen(Node *, int); +static Node* cfind(Node*); +static Node* cgen(Node*, Node*); +static void cgen0(Node*, Node*); +static int lteq(Type*, Type*); +static Type* ntype(Node*); +static int rewe(Node*, Type*, int); +static void rewlc(Node*, int, Type*); +static Node* con(vlong); +static void clrbrk(Node*); +static int hasbrk(Node*); +static int isgen(char*); +static int simple(Node*); +static void pfmt(char*); +static void lpfmt(ushort*); +static int lline(Node*); +static void args(Node*); +static void addmodn(Sym*); +static void scomplex(Node*); +static void mset(Node*); + +static Node *lastd; + +static int +rev(int op) +{ + switch(op){ + case OLT: return OGT; + case OLE: return OGE; + case OGT: return OLT; + case OGE: return OLE; + } + return op; +} + +void +newsec(int l) +{ + if(l != 1 && lastd != Z){ + tdgen(lastd, 1); + lastd = Z; + } + if(l != 2) + etgen2(nil); + if(lastsec && l != lastsec) + newline(); + lastsec = l; +} + +static Node* +defval(Type *t) +{ + Node *n; + + if(t == T) + t = types[TINT]; + n = con(0); + n->type = types[TINT]; + n->kind = KDEC; + switch(t->etype){ + case TFLOAT: + case TDOUBLE: + n->type = types[TDOUBLE]; + n->fconst = 0.0; + n->cstring = "0.0"; + return n; + default: + break; + case TIND: + case TFUNC: + case TARRAY: + n->type = typ1(TIND, types[TVOID]); + return n; + case TVOID: + case TSTRUCT: + case TUNION: + free(n); + return Z; + } + if(!lteq(n->type, t)){ + n = new1(OCAST, n, Z); + n->type = t; + } + return n; +} + +static int +teq(Type *t1, Type *t2) +{ + if(t1 == t2) + return 1; + return sametype(t1, t2); +/* + if(t1->etype != t2->etype) + return 0; + switch(t1->etype){ + case TARRAY: + if(t1->width != t2->width) + return 0; + break; + case TFUNC: + if(!teq(t1->down, t2->down)) + return 0; + break; + case TSTRUCT: + case TUNION: + return t1->link == t2->link; + case TENUM: + return 1; + } + return teq(t1->link, t2->link); +*/ +} + +static int +tequiv(Type *t1, Type *t2) +{ + if(!teq(t1, t2)) + return 0; + if(t1->etype == TSTRUCT || t1->etype == TUNION) + return suename(t1) == suename(t2); + return 1; +} + +static int +iteq(Type *t1, Type *t2) +{ + if(t1 == T || t2 == T) + return 0; + return t1->etype == TIND && (teq(t1->link, t2) || (t1->link->etype == TVOID && isnum(t2))); +} + +static Type * +ltype(Type *t) +{ + switch(t->etype){ + case TUCHAR: + return types[TCHAR]; + case TSHORT: + case TUSHORT: + case TUINT: + case TLONG: + case TULONG: + case TENUM: + return types[TINT]; + case TUVLONG: + return types[TVLONG]; + case TFLOAT: + return types[TDOUBLE]; + default: + return t; + } + return t; +} + +static int +lteq(Type *t1, Type *t2) +{ + if(t1 == T || t2 == T) + return 0; + if(t1 == t2) + return 1; + if(t1->etype == TIND && t2->etype == TIND) + return lteq(t1->link, t2->link); + return sametype(ltype(t1), ltype(t2)); +} + +static Type* +tcp(Type *t) +{ + Type *nt; + + if(t == T) + return T; + nt = typ1(TXXX, T); + *nt = *t; + return nt; +} + +static Type* +tuple(Type *t1, Type *t2) +{ + Type *t, **at, *l; + + if(t1 == T || t1->etype == TVOID) + return tcp(t2); + if(t2 == T || t2->etype == TVOID) + return tcp(t1); + if(t2->etype == TTUPLE) + diag(Z, "bad tuple type"); + t = typ1(TTUPLE, T); + at = &t->link; + if(t1->etype == TTUPLE){ + for(l = t1->link; l != T; l = l->down){ + *at = tcp(l); + at = &(*at)->down; + } + } + else{ + *at = tcp(t1); + at = &(*at)->down; + } + *at = tcp(t2); + return t; +} + +static Sym* +sue(Type *t) +{ + int h; + Sym *s; + + if(t != T) + for(h=0; h<nelem(hash); h++) + for(s = hash[h]; s != S; s = s->link) + if(s->suetag && s->suetag->link == t) + return s; + return S; +} + +static void +pranon(int i) +{ + prid("anon_"); + prnum(i+1, KDEC, T); +} + +static int +dotpath(Sym *s, Type *t, int pr) +{ + int i; + Type *t1; + + if(t == T) + return 0; + for(t1 = t->link; t1 != T; t1 = t1->down){ + if(t1->sym == s){ + if(pr){ + prdelim("."); + prsym(s, 0); + } + return 1; + } + } + i = 0; + for(t1 = t->link; t1 != T; t1 = t1->down){ + if(t1->sym == S){ + i++; + if(typesu[t1->etype] && sametype(s->type, t1)){ + if(pr){ + prdelim("."); + pranon(i-1); + } + return 1; + } + } + } + i = 0; + for(t1 = t->link; t1 != T; t1 = t1->down){ + if(t1->sym == S){ + i++; + if(typesu[t1->etype] && dotpath(s, t1, 0)){ + if(pr){ + prdelim("."); + pranon(i-1); + dotpath(s, t1, 1); + } + return 1; + } + } + } + return 0; +} + +static Sym* +suename(Type *t) +{ + Sym *s; + + s = sue(t->link); + if(s != S) + return s; + else if(t->tag != S) + return t->tag; + else if(t->sym != S) + return t->sym; + return S; +} + +static int +cycle(Type *t, Type *base) +{ + int r; + Type *l; + + if(t->vis){ + /* sametype() does structural comparison so have to check names */ + if(t == base || tequiv(t, base)) + return 1; + return 0; + } + r = 0; + t->vis = 1; + switch(t->etype){ + case TIND: + case TARRAY: + r = cycle(t->link, base); + break; + case TSTRUCT: + case TUNION: + case TTUPLE: + for(l = t->link; l != T; l = l->down) + r |= cycle(l, base); + break; + } + t->vis = 0; + return r; +} + +static void +addnode(int op, Node *n) +{ + Node *nn; + + nn = new1(OXXX, Z, Z); + *nn = *n; + n->op = op; + n->left = nn; + n->right = Z; + n->type = nn->type; +} + +static void +cast(Node *n, Type *t) +{ + addnode(OCAST, n); + n->type = t; +} + +static void +intcast(Node *n) +{ + if(isptr(n->type)){ + addnode(ONE, n); + n->right = con(0); + n->right->type = n->left->type; + n->type = types[TINT]; + } + else + cast(n, types[TINT]); +} + +static void +strcast(Node *n) +{ + cast(n, stringtype); +} + +static void +bptr(Node *n) +{ + if(n == Z) + return; + switch(n->op){ + default: + if(!lteq(n->type, types[TINT])) + intcast(n); + break; + case ONOT: + if(!lteq(n->left->type, types[TINT])){ + intcast(n->left); + if(n->left->op == ONE){ + n->left->op = OEQ; + *n = *n->left; + } + } + break; + case OANDAND: + case OOROR: + bptr(n->left); + bptr(n->right); + break; + case OCOND: + bptr(n->right->left); + bptr(n->right->right); + break; + } +} + +static void +bcomplex(Node *n) +{ + if(n == Z) + return; + if(!passes) + complex(n); + bptr(n); +} + +static void +ecomplex(Node *n) +{ + if(!passes) + complex(n); + rewe(n, T, 0); +} + +static void +becomplex(Node *n) +{ + bcomplex(n); + rewe(n, T, 0); +} + +static void +tgen(Type *t, int dec, int arinit) +{ + Type *l; + + if(t == T) + return; + switch(t->etype){ + case TXXX: + prid("int"); + break; + case TCHAR: + case TUCHAR: + prid("byte"); + break; + case TSHORT: + case TUSHORT: + case TINT: + case TUINT: + case TLONG: + case TULONG: + case TENUM: + prid("int"); + break; + case TVLONG: + case TUVLONG: + prid("big"); + break; + case TFLOAT: + case TDOUBLE: + prid("real"); + break; + case TIND: + if(strings == 2 && t->link && t->link->etype == TCHAR){ + prid("string"); + break; + } + if(isadt(t->link) || t->link->etype == TFUNC) + prid("ref "); + else + prid("array of "); + if(t->link && t->link->etype == TVOID){ + prid("byte"); + prcom("was void*", Z); + } + else + tgen(t->link, 1, 0); + break; + case TFUNC: + if(0){ + prid("int"); + prcom("was function", Z); + break; + } + prid("fn"); + prdelim("("); + for(l = t->down; l != T; l = l->down){ + if(l->etype == TVOID && l->down == T) + break; + if(l->etype == TDOT){ + prcom("was ...", Z); + break; + } + if(l->sym != S) + prsym(l->sym, 0); + else + prid("nil"); + prdelim(": "); + tgen(l, 1, 0); + if(l->down != T && l->down->etype != TDOT) + prdelim(", "); + } + /* tgen(t->down, dec, 0, 0); */ + prdelim(")"); + if(!isvoid(t->link)){ + prdelim(": "); + tgen(t->link, dec, 0); + } + break; + case TARRAY: + prid("array"); + if(t->width == LARR) + t->width = LARR; + else if(dec){ + if(t->nwidth != Z) + prcom("array index was ", t->nwidth); + else if(t->width != 0){ + sprint(buf, "array index was %ld", t->width/t->link->width); + prcom(buf, Z); + } + } + else{ + prdelim("["); + if(t->nwidth != Z) + egen(t->nwidth, ONOOP, PRE); + else if(t->width != 0) + prnum(t->width/t->link->width, KDEC, T); + prdelim("]"); + } + prdelim(" of "); + if(!arinit) + tgen(t->link, 1, 0); + break; + case TVOID: + /* prid("void"); */ + prid("byte"); + prcom("was void", Z); + break; + case TSTRUCT: + case TUNION: + if(t->link != T && t->link->etype == TFD){ + prid("Sys->FD"); + usemod(sysop, 0); + } + else + prsym(suename(t), 1); + break; + case TTUPLE: + prdelim("("); + for(l = t->link; l != T; l = l->down){ + tgen(l, dec, 0); + if(l->down != T) + prdelim(", "); + } + prdelim(")"); + break; + case TDOT: + prdelim("..."); + break; + case TSTRING: + prid("string"); + break; + case TFD: + prid("fd"); + break; + default: + diag(Z, "unknown type"); + break; + } +} + +static Type* +typn(Type *t, int i) +{ + Type *l; + + for(l = t->down; l != T && --i >= 0; l = l->down) + ; + return l; +} + +void +ttgen2(Type *t) +{ + Type *l; + Sym *s; + int anon = 0; + + switch(t->etype){ + case TSTRUCT: + case TUNION: + newsec(0); + output(t->lineno, 1); + s = suename(t); + if(isgen(s->name)) + addmodn(s); + setmod(s); + prsym(s, 0); + prdelim(": "); + prid("adt"); + prdelim("{"); + if(t->etype == TUNION) + prcom("was union", Z); + newline(); + incind(); + t->vis = 1; + for(l = t->link; l != T; l = l->down){ + output(l->lineno, 1); + if(l->nbits) + prcom("was bit field", Z); + if(l->sym != S) + prsym(l->sym, 0); + else + pranon(anon++); + prdelim(": "); + if(cycle(l, t)) + prid("cyclic "); + tgen(l, 1, 0); + prdelim(";"); + newline(); + } + t->vis = 0; + decind(); + prdelim("};"); + newline(); + newline(); + break; + default: + break; + } +} + +static int +canjoin(Node *n, Node *nn) +{ + return teq(n->type, nn->type) && isname(n) && isname(nn) && n->type->etype != TARRAY; +} + +void +vtgen2(Node *n) +{ + int t, c, comma = 0; + Node *nn; + Sym *s; + + nn = n; + if(n->op == ODAS) + nn = n->left; + if(nn->type == T || nn->sym == S) + return; + t = nn->type->etype; + c = nn->sym->class; + if(0 && c == CTYPEDEF){ + /* egen(nn, ONOOP, PRE); */ + /* tdgen(n, 1, 0); */ + if(isadt(n->type)){ + s = suename(n->type); + if(isgen(s->name)){ + s->lname = nn->sym->name; + ttgen2(n->type); + } + } + } + if(c != CGLOBL && c != CSTATIC && c != CLOCAL && c != CEXREG) + return; + newsec(1); + if(lastd != Z){ + if(t != TFUNC && canjoin(lastd, n)) + comma = 1; + else + tdgen(lastd, 1); + } + output(nn->lineno, 1); + if(t == TFUNC){ + if(ism()){ + setmod(nn->sym); + egen(nn, ONOOP, PRE); + tdgen(n, 1); + } + lastd = Z; + return; + } + if(comma) + prdelim(", "); + if(nn->op != ONAME) + diag(nn, "internal: not name in vtgen"); + setmod(nn->sym); + prsym(nn->sym, 0); + /* egen(nn, ONOOP, PRE); */ + /* tdgen(n, 1, 0); */ + lastd = n; + if(n->op == ODAS) + rewe(n->right, T, 1); +} + +static void minseq(Syml*); + +static Node* +con(vlong v) +{ + int neg = 0; + Node *n; + + if(v < 0){ + neg = 1; + v = -v; + } + n = new1(OCONST, Z, Z); + n->vconst = v; + n->kind = KDEC; + n->type = types[TINT]; + if(neg) + n = new1(ONEG, n, Z); + return n; +} + +/* +static Node* +fcon(double v) +{ + int neg = 0; + Node *n; + + if(v < 0){ + neg = 1; + v = -v; + } + n = new1(OCONST, Z, Z); + n->fconst = v; + n->kind = KDEC; + n->type = types[TDOUBLE]; + if(neg) + n = new1(ONEG, n, Z); + return n; +} +*/ + +static Node* +add(vlong v, Node *n) +{ + if(v == 0) + return n; + return new1(OADD, con(v), n); +} + +static Node* +addn(Node *n1, Node *n2) +{ + if(n1 == Z || n2 == Z) + return Z; + if(isconst(n1, 0)) + return n2; + if(isconst(n2, 0)) + return n1; + return new1(OADD, n1, n2); +} + +static Node* +mul(vlong v, Node *n) +{ + if(v == 0) + return con(0); + else if(v == 1) + return n; + else if(v == -1) + return new1(ONEG, n, Z); + return new1(OMUL, con(v), n); +} + +static Node* +mydiv(Node *n, vlong w) +{ + Node *nn; + + if(w == 0) + return Z; + if(w == 1) + return n; + else if(w == -1) + return new1(ONEG, n, Z); + switch(n->op){ + case OCONST: + if(n->vconst % w == 0){ + n->vconst /= w; + if(n->left != Z && mydiv(n->left, w) == Z){ + n->vconst *= w; + break; + } + return n; + } + break; + case OCAST: + return mydiv(n->left, w); + case OMUL: + nn = mydiv(n->right, w); + if(nn != Z){ + if(isconst(nn, 1)) + *n = *n->left; + return n; + } + nn = mydiv(n->left, w); + if(nn != Z){ + if(isconst(nn, 1)) + *n = *n->right; + return n; + } + break; + default: + break; + } + return Z; +} + +static Node* +iota(void) +{ + return new1(OIOTA, Z, Z); +} + +static Node* +symcon(Sym *s) +{ + Node *n; + + if(s->nconst != Z) + return s->nconst; + n = con(s->vconst); + n->kind = s->kind; + return n; +} + +#define ARITH 1 +#define GEOM 2 + +static Syml* +newsyml(Sym *s, Syml **frees) +{ + Syml *sl, *f; + + if((f = *frees) != nil){ + sl = f; + *frees = f->nxt; + } + else + sl = (Syml*)malloc(sizeof(Syml)); + sl->sym = s; + sl->nxt = nil; + return sl; +} + +static Syml* +etseq(Syml *syml) +{ + int e, pio, io, comma; + vlong d, dd, v0, v1, v, t, tt; + Node *expr; + Sym *s; + Syml *sl, *lsl; + + lsl = nil; + pio = io = ARITH|GEOM; + e = 0; + dd = 0; + for(sl = syml; sl != nil; sl = sl->nxt){ + s = sl->sym; + if(isreal(s->tenum) || s->tenum->etype == TIND) + break; + if(e == 0) + v0 = s->vconst; + if(e == 1){ + v1 = s->vconst; + d = v1-v0; + } + if(e > 0 && (v <= 0 || s->vconst != 2*v)) + io &= ~GEOM; + if(0 && e > 1 && s->vconst-v != d) + io &= ~ARITH; + if(e > 1){ + t = s->vconst-v; + tt = t-d; + if(e > 2 && tt != dd) + io &= ~ARITH; + else{ + d = t; + dd = tt; + } + } + if(io == 0) + break; + v = s->vconst; + lsl = sl; + pio = io; + e++; + } + if(e < 2) + pio = 0; + if(pio&GEOM){ + if(e < 3) + pio = 0; + } + else if(pio&ARITH){ + int n; + + if(d == 0 && dd == 0) + n = 2; + else if(dd == 0) + n = 3; + else + n = 4; + if(e < n || (dd&1) != 0) + pio = 0; + } + if(lsl == nil || pio == 0) + lsl = syml; + comma = 0; + for(sl = syml; sl != nil; sl = sl->nxt){ + s = sl->sym; + nearln = s->lineno; + output(s->lineno, 1); + if(pio){ + if(comma) + prdelim(", "); + setmod(s); + prsym(s, 0); + comma = 1; + } + else{ + setmod(s); + prsym(s, 0); + prdelim(": "); + prid("con "); + if(isbyte(s->tenum) || isbig(s->tenum) && !islbigv(s->vconst) || !isbig(s->tenum) && isuintv(s->vconst)){ + tgen(s->tenum, 1, 0); + prdelim(" "); + } + if(s->nconst != Z) + egen(s->nconst, ONOOP, PRE); + else if(s->kind == KCHR) + prchar(s->vconst); + else if(isreal(s->tenum)) + prreal(s->fconst, s->cstring, s->kind); + else + prnum(s->vconst, s->kind, s->tenum); + prdelim(";"); + newline(); + } + if(sl == lsl) + break; + } + if(pio){ + s = syml->sym; + prdelim(": "); + prid("con "); + if(isbyte(s->tenum) || isbig(s->tenum)){ + tgen(s->tenum, 1, 0); + prdelim(" "); + } + if(pio&GEOM){ + if(v0 == 0 || v0 == 1 || v0 == -1) + expr = mul(v0, new1(OASHL, con(1), iota())); + else + expr = new1(OMUL, symcon(s), new1(OASHL, con(1), iota())); + } + else if(d == 0 && dd == 0) + expr = symcon(s); + else if(dd == 0) + expr = add(v0, mul(d, iota())); + else + expr = add(v0, new1(OADD, mul(v1-dd/2-v0, iota()), mul(dd/2, new1(OMUL, iota(), iota())))); + complex(expr); + expr = ckneg(expr); + egen(expr, ONOOP, PRE); + prdelim(";"); + newline(); + } + return lsl->nxt; +} + +static void +adde(Syml *sl, Symq *q) +{ + if(q->f == nil) + q->f = sl; + else + q->r->nxt = sl; + q->r = sl; +} + +static void +freeq(Symq *q, Syml **frees) +{ + if(q->f){ + q->r->nxt = *frees; + *frees = q->f; + q->f = q->r = nil; + } +} + +static void +etgen2(Sym *s) +{ + Syml *sl; + static Syml *frees; + static Symq symq, symq1; + + if(s != nil){ + newsec(2); + sl = newsyml(s, &frees); + adde(sl, &symq); + if(isinteger(s->tenum) && isbigv(s->vconst) && !isbig(s->tenum)) + s->tenum = types[TVLONG]; + return; + } + /* end of enums */ + if(symq.f && symq.f == symq.r){ /* try to merge with other singletons */ + adde(symq.f, &symq1); + symq.f = symq.r = nil; + return; + } + if(symq1.f){ + for(sl = symq1.f; sl != nil; sl = etseq(sl)) + ; + freeq(&symq1, &frees); + } + if(symq.f){ + for(sl = symq.f; sl != nil; sl = etseq(sl)) + ; + freeq(&symq, &frees); + } +} + +static void +lgen(Node *n, int br, int first) +{ + if(br) + prdelim("("); + if(n == Z){ + if(br) + prdelim(")"); + return; + } + if(n->op == OLIST || n->op == OTUPLE){ + lgen(n->left, 0, first); + lgen(n->right, 0, 0); + } + else if(n->op != ODOTDOT){ + if(!first) + prdelim(", "); + egen(n, ONOOP, PRE); + } + else + prcom("was ...", Z); + if(br) + prdelim(")"); +} + +static void +preced(int op1, int op2, int s, int c) +{ + int p1, p2, k1, k2, br; + char buf[2]; + + br = 0; + p1 = ops[op1].prec; + p2 = ops[op2].prec; + if(p1 < 0 || p2 < 0) + diag(Z, "-ve precedence"); + if(p1 > p2) + br = 1; + else if(p1 == p2){ + k1 = ops[op1].kind; + k2 = ops[op2].kind; + if(op1 == op2){ + if(k1&RASSOC) + br = s == LEFT; + else + br = s == RIGHT && !(k1&ASSOC); + } + else{ + if(k1&RASSOC) + br = s == LEFT; + else + br = s == RIGHT && op1 != OADD; + + if(k1&POSTOP && !(k2&POSTOP)) + br = 1; + + /* funny case */ + if(op2 == OMDOT && s == LEFT && (op1 == ODOT || op1 == ODOTIND)) + br = 1; + } + } + if(br){ + buf[0] = c; + buf[1] = '\0'; + prdelim(buf); + } +} + +static void +egen(Node *n, int op0, int side) +{ + int op, p; + Type *t; + Node *nn; + + if(n == Z){ + if(op0 == OBRACKET) + prdelim("()"); + return; + } + if(n->op == OCONST && n->left != Z){ /* actual node in source */ + n->left->type = n->type; + n = n->left; + } + if((n->op == OSTRING || n->op == OLSTRING) && n->left != Z) /* actual node in source */ + n = n->left; + if(n->op == OCAST && (lteq(n->type, n->left->type) || isnil(n) || !iscastable(n->type, n->left->type))){ + if(isnil(n)) + prid("nil"); + else + egen(n->left, op0, side); + return; + } + if(n->op == ONAME && arrow(n->sym)) + n->op = OMDOT; + if(n->op != OLIST) + output(n->lineno, 0); + op = n->op; + preced(op0, op, side, '('); + switch(op){ + case OLIST: + case OTUPLE: + lgen(n, 1, 1); + break; + case OIOTA: + prid("iota"); + break; + case OMDOT: + case ONAME: + case OXXX: + prsym(n->sym, 1); + break; + case OCONST: + if(n->kind == KCHR) + prchar(n->vconst); + else if(isreal(n->type)) + prreal(n->fconst, n->cstring, n->kind); + else if(isnil(n)) + prid("nil"); + else + prnum(n->vconst, n->kind, n->type); + if(n->right != Z) + prcom("was ", n->right); + break; + case OSTRING: + prstr(n->cstring); + break; + case OLSTRING: + prlstr(n->rstring); + break; + case OCOND: + egen(n->left, op, POST); + prdelim(" ? "); + egen(n->right->left, op, PRE|POST); + prdelim(" : "); + egen(n->right->right, op, PRE); + prcom("?", Z); + break; + case OCOMMA: + if(op0 != OCOMMA) + prdelim("("); + egen(n->left, op, LEFT); + prdelim(", "); + egen(n->right, op, RIGHT); + if(op0 != OCOMMA) + prdelim(")"); + break; + case OLDOT: + egen(n->left, OMOD, LEFT); /* any precedence 13 operator */ + prdelim("."); + egen(n->right, op, RIGHT); + break; + default: + p = ops[op].prec; + egen(n->left, op, LEFT); + if(space[p]) + prdelim(" "); + prdelim(ops[op].name); + if(space[p]) + prdelim(" "); + egen(n->right, op, RIGHT); + break; + case OIND: case OADDR: case OSADDR: + case OPOS: case ONEG: + case ONOT: case OCOM: + case OPREINC: case OPREDEC: + if(op == OADDR){ + n->op = OSADDR; + if(!isfn(n->left->type)) + prcom("was ", n); + } + else + prdelim(ops[op].name); + egen(n->left, op, PRE); + break; + case OPOSTINC: case OPOSTDEC: + egen(n->left, op, POST); + prdelim(ops[op].name); + break; + case ODOT: + egen(n->left, op, LEFT); + dotpath(n->sym, n->left->type, 1); + /* prdelim(ops[op].name); */ + /* prsym(n->sym, 0); */ + break; + case ODOTIND: + egen(n->left, op, LEFT); + if(isadt(n->left->type)) + dotpath(n->sym, n->left->type, 1); /* type may be demoted arg */ + else + dotpath(n->sym, n->left->type->link, 1); + /* prdelim(ops[op].name); */ + /* prsym(n->sym, 0); */ + break; + case OARRIND: + egen(n->left, op, LEFT); + prdelim("["); + egen(n->right, ONOOP, RIGHT); + prdelim("]"); + if(n->right->op == OCONST && n->right->vconst < 0) + prcom("negative array index", Z); + break; + case OLEN: + prid("len "); + egen(n->right, op, PRE); + break; + case OREF: + prid("ref "); + tgen(n->type->link, 0, 0); + break; + case OARRAYOF: + prid("array"); + prdelim("["); + egen(n->left, ONOOP, LEFT); + prdelim("]"); + prid(" of "); + tgen(n->type->link, 0, 0); + break; + case OSLICE: + egen(n->left, op, LEFT); + prdelim("["); + egen(n->right->left, ONOOP, RIGHT); + prdelim(": "); + egen(n->right->right, ONOOP, RIGHT); + prdelim("]"); + break; + case OFUNC: + if(n->kind == KEXP) + egen(n->left, op, LEFT); + else + prsym(n->left->sym, 0); + lgen(n->right, 1, 1); + if(n->kind != KEXP && !isvoid(n->left->type->link)){ + prdelim(": "); + tgen(n->left->type->link, 0, 0); + } + break; + case ONIL: + prid("nil"); + break; + case OCAST: + if(isnil(n)) + prid("nil"); + else if(iscastable(n->type, n->left->type)){ + tgen(n->type, 0, 0); + prdelim(" "); + egen(n->left, op, RIGHT); + } + else + egen(n->left, op0, RIGHT); + break; + case OARRAY: + tgen(n->type, 0, 0); + egen(n->left, op, LEFT); + prdelim("["); + egen(n->right, ONOOP, RIGHT); + prdelim("]"); + break; + case OSTRUCT: + case OUNION: + tgen(n->type, 0, 0); + lgen(n->left, 1, 1); + break; + case OELEM: + prdelim("."); + /* tgen(n->type, 0, 0, 0); */ + prsym(n->sym, 0); + break; + case OSIZE: + case OSIGN: + prid(ops[op].name); + if(n->left != Z) + egen(n->left, OBRACKET, RIGHT); + else{ + prdelim(" "); + prid(tnames[n->type->etype]); + if(typesu[n->type->etype] && n->type->tag){ + prdelim(" "); + prid(n->type->tag->name); + } + } + break; + case OPROTO: + nn = n; + t = n->type; + n = protoname(n); + if(n != Z) + t = n->type; + else + t = prototype(nn->left, t); + if(!isvoid(t) || n != Z){ + if(n == Z) + prid("nil"); + else if(n->op == ODOTDOT){ + prcom("was ...", Z); + break; + } + else + prsym(n->sym, 0); + /* egen(n, ONOOP, PRE); */ + prdelim(": "); + tgen(t, 1, 0); + } + break; + case ODOTDOT: + prid("..."); + break; + case OINIT: + egen(n->left, ONOOP, PRE); + break; + case OS2AB: + prid("libc0->s2ab"); + prdelim("("); + egen(n->left, ONOOP, PRE); + prdelim(")"); + usemod(libcop, 1); + break; + case OAB2S: + prid("libc0->ab2s"); + prdelim("("); + egen(n->left, ONOOP, PRE); + prdelim(")"); + usemod(libcop, 1); + break; + case OFILDES: + prid("sys->fildes"); + prdelim("("); + egen(n->left, ONOOP, PRE); + prdelim(")"); + usemod(sysop, 1); + break; + case OFD: + egen(n->left, op, LEFT); + prdelim(ops[op].name); + prid("fd"); + break; + case OT0: + egen(n->left, op, LEFT); + prdelim(ops[op].name); + prid("t0"); + break; + case ORETV: + n->op = OAS; + nn = n->left; + p = isvoid(n->type) || n->type->etype != TTUPLE || n->type->mark == TCPC; + if(p) + n->left = n->right; + else + n->left = new1(OTUPLE, new1(ONIL, Z, Z), n->right); + n->right = nn; + n->left->type = n->type; + if(!p && op0 != ONOOP) + addnode(OT0, n); + egen(n, op0, side); + break; + case OCAT: + egen(n->left, op, LEFT); + prdelim(" + "); + egen(n->right, op, RIGHT); + break; + } + preced(op0, op, side, ')'); +} + +static int +isexpr(Node *n, Type *t) +{ + if(n == Z) + return 0; + if(n->op == OLIST || n->op == OINIT || n->op == OSTRUCT) + return 0; + if(teq(t, n->type)) + return 1; + return 0; +} + +static Node * +nxtval(Node *n, Node **nn) +{ + if(n == Z){ + *nn = Z; + return Z; + } + if(n->op == OLIST){ + *nn = n->right; + return n->left; + } + *nn = Z; + return n; +} + +static Node* +eagen(Node *n, Type *t, int ar, int *nz, int depth) +{ + int i, w, nw, down; + Type *t1; + Node *nn, *tn; + + if(n != Z){ + if(n->type == T && t == T){ + egen(n, ONOOP, PRE); + if(ar){ + prdelim(","); + newline(); + } + return Z; + } + if(ar && n->op == OLIST && n->left->op == OARRAY){ + egen(n->left->left, ONOOP, PRE); + prdelim(" => "); + n = n->right; + } + if(n->op == OLIST && n->left->op == OELEM){ + prcom("cannot do ", n->left); + n = n->right; + } + if(n->op == OUSED || n->op == ODOTDOT) + n = n->left; + if(t == T) + t = n->type; + } + switch(t->etype){ + case TSTRUCT: + case TUNION: + if(isexpr(n, t)) + goto Default; + down = 0; + tn = nxtval(n, &nn); + if(tn != Z && (tn->op == OINIT || tn->op == OSTRUCT)){ + down = 1; + n = tn->left; + } + if(depth > 0){ + tgen(t, 0, 0); + prdelim(" "); + } + prdelim("("); + for(t1 = t->link; t1 != T; t1 = t1->down){ + if(n == Z) + n = defval(t1); + n = eagen(n, t1, 0, nil, depth+1); + if(t1->down != T){ + prdelim(","); + if(ar) + prdelim("\t"); + else + prdelim(" "); + } + } + prdelim(")"); + if(down) + n = nn; + break; + case TARRAY: + if(isexpr(n, t)) + goto Default; + if(depth > 0){ + tgen(t, 0, 1); + prdelim(" "); + } + prdelim("{"); + newline(); + incind(); + w = t->width/t->link->width; + nw = 0; + for(i = 0; i < w; i++){ + down = 0; + tn = nxtval(n, &nn); + if(tn != Z && (tn->op == OINIT || tn->op == OSTRUCT)){ + down = 1; + n = tn->left; + } + n = eagen(n, t->link, 1, &nw, depth+1); + if(down) + n = nn; + } + if(nw > 0){ + if(nw > 1) + prdelim("* => "); + egen(defval(t->link), ONOOP, PRE); + newline(); + } + decind(); + prdelim("}"); + break; + default: +Default: + if(n == Z){ + if(ar) + (*nz)++; + else + egen(defval(t), ONOOP, PRE); + return Z; + } + n = nxtval(n, &nn); + if(ar && isnil(n) && iscastable(t, types[TINT])){ + tgen(t, 0, 0); + prdelim(" "); + } + egen(n, ONOOP, PRE); + n = nn; + break; + } + if(ar){ + prdelim(","); + newline(); + } + return n; +} + +/* better is + * array of byte "abcde\0" + * but limbo compiler does not accept this as a constant expression + */ +static void +stob(Node *n) +{ + int m; + char *s = nil, buf[UTFmax]; + ushort *u = nil; + + while(n->op == ONAME) + n = n->sym->nconst; + if(n->op == OSTRING) + s = n->cstring; + else + u = n->rstring; + prdelim("{ "); + if(s){ + while(*s){ + prid("byte "); + prchar(*s++); + prdelim(", "); + } + } + else{ + while(*u){ + m = runetochar(buf, u++); + s = buf; + while(--m >= 0){ + prid("byte "); + prchar(*s++); + prdelim(", "); + } + } + } + prid("byte "); + prchar('\0'); + prdelim(" }"); +} + +static Type *arrayofchar; + +static void +sdgen(Node *n, int glob) +{ + int sop = 0; + + prdelim(" := "); + if(glob && n->right->op == OS2AB && isstring(n->right->left)){ + if(arrayofchar == T){ + arrayofchar = typ1(TARRAY, types[TCHAR]); + arrayofchar->width = 0; + } + n->type = n->right->type = arrayofchar; + sop = 1; + } + else + n->type = n->right->type = T; + tgen(n->type, 0, 1); + if(sop) + stob(n->right->left); + else + eagen(n->right, n->type, 0, nil, 0); + prdelim(";"); + newline(); +} + +static void +tdgen(Node *n, int glob) +{ + int ar, arinit; + + if(ism()){ + prdelim(": "); + tgen(n->type, 1, 0); + if(n->op == ODAS) + prcom("initial value was ", n->right); + prdelim(";"); + newline(); + return; + } + if(n->op == ODAS && (isstring(n->right) || n->right->op == OS2AB)){ + sdgen(n, glob); + return; + } + ar = n->type->etype == TARRAY && n->type->width != LARR; + arinit = ar && n->op == ODAS; + if(ar) + prdelim(" := "); + else + prdelim(": "); + tgen(n->type, 0, arinit); + if(n->op == ODAS){ + if(!arinit) + prdelim(" = "); + eagen(n->right, n->type, 0, nil, 0); + } + prdelim(";"); + newline(); +} + +static int +isdec(Node *n) +{ + return isname(n) && n->kind != KEXP || n->op == ODAS; +} + +static void +sgen(Node *n, int blk, Node **ln) +{ + int comma = 0; + Node *nn; + + if(n == Z) + return; + if(blk){ + pushscope(n, SAUTO); + if(n->op == OLIST && !(blk&NOBR) || (blk&YESBR)){ + prdelim("{"); + newline(); + } + else if(!(blk&NONL)) + newline(); + if(!(blk&NOIN)) + incind(); + } + if((nn = *ln) != Z && isdec(nn)){ + if(isdec(n)){ + if(canjoin(nn, n)) + comma = 1; + else + tdgen(nn, 0); + } + else if(n->op != OLIST){ + tdgen(nn, 0); + newline(); + } + } + if(n->op != OLIST){ + *ln = n; + output(n->lineno, 1); + } + switch(n->op){ + default: + egen(n, ONOOP, PRE); + prdelim(";"); + newline(); + break; + case ODAS: + pushdcl(n->left, CAUTO); + egen(n->left, ONOOP, PRE); + break; + case ONAME: + if(n->kind == KEXP){ + egen(n, ONOOP, PRE); + prdelim(";"); + newline(); + } + else{ + pushdcl(n, CAUTO); + if(comma) + prdelim(", "); + if(n->op != ONAME) + diag(n, "internal: not name in sgen"); + prsym(n->sym, 0); + /* egen(n, ONOOP, PRE); */ +/* + prdelim(": "); + tgen(n->type, 0, 0, 0); + prdelim(";"); + newline(); +*/ + } + break; + case OSBREAK: + break; + case ONUL: + prdelim(";"); + newline(); + break; + case OBLK: + sgen(n->left, 1|YESBR, ln); + break; + case OLIST: + sgen(n->left, 0, ln); + sgen(n->right, 0, ln); + break; + case ORETURN: + prkeywd("return"); + if(n->left != Z) + prdelim(" "); + egen(n->left, ONOOP, PRE); + prdelim(";"); + newline(); + break; + case OLABEL: + prcom("was label ", n->left); + /* i = zeroind(); */ + /* egen(n->left, ONOOP, PRE); */ + /* prdelim(":"); */ + newline(); + /* restoreind(i); */ + break; + case OGOTO: + prcom("was goto ", n->left); + /* prkeywd("goto "); */ + /* egen(n->left, ONOOP, PRE); */ + prdelim(";"); + newline(); + break; + case OCASE: + for(nn = n->left; nn != Z; nn = nn->right){ + if(nn != n->left) + prkeywd(" or "); + if(nn->left != Z) + egen(nn->left, ONOOP, PRE); + else + prkeywd("*"); + } + prdelim(" =>"); + clrbrk(n->right); + sgen(n->right, 1|NOBR, ln); + if(n->kind != KLAST && !hasbrk(n->right)){ + prcom("fall through", Z); + newline(); + } + break; + case OSWITCH: + prkeywd("case"); + egen(n->left, OBRACKET, PRE); + sgen(n->right, 1|NOIN|YESBR, ln); + break; + case OWHILE: + prkeywd("while"); + egen(n->left, OBRACKET, PRE); + sgen(n->right, 1, ln); + break; + case ODWHILE: + prkeywd("do"); + sgen(n->right, 1|NOENL, ln); + prkeywd("while"); + egen(n->left, OBRACKET, PRE); + prdelim(";"); + newline(); + break; + case OFOR: + prkeywd("for"); + prdelim("("); + egen(n->left->right->left, ONOOP, PRE); + prdelim(";"); + if(n->left->left != Z) + prdelim(" "); + egen(n->left->left, ONOOP, PRE); + prdelim(";"); + if(n->left->right->right != Z) + prdelim(" "); + egen(n->left->right->right, ONOOP, PRE); + prdelim(")"); + sgen(n->right, 1, ln); + break; + case OCONTINUE: + prkeywd("continue"); + prdelim(";"); + newline(); + break; + case OBREAK: + prkeywd("break"); + prdelim(";"); + newline(); + break; + case OIF: + prkeywd("if"); + egen(n->left, OBRACKET, PRE); + if(n->right->left->op == OIF && n->right->left->right->right == Z && n->right->right != Z) /* avoid dangling else */ + sgen(n->right->left, 1|YESBR, ln); + else + sgen(n->right->left, 1, ln); + if(n->right->right != Z){ + prdelim("else"); + if(n->right->right->op == OIF){ /* merge else and if */ + prdelim(" "); + sgen(n->right->right, 1|NONL|NOIN, ln); + } + else + sgen(n->right->right, 1, ln); + } + break; + case OSET: + case OUSED: + prkeywd(ops[n->op].name); + lgen(n->left, 1, 1); + prdelim(";"); + newline(); + break; + } + if(blk){ + if(!(blk&NOIN)) + decind(); + if(n->op == OLIST&& !(blk&NOBR) || (blk&YESBR)){ + prdelim("}"); + if(!(blk&NOENL)) + newline(); + } + popscope(); + } +} + +static void rew(Node*, int); + +static void +rewc0(Node *n, Node *r) +{ + Node *nn; + + if((nn = cfind(n)) != Z){ + cgen0(nn, n); + if(r->op == ORETURN){ + n->right->left = new1(ORETURN, n->right->left, Z); + n->right->right = new1(ORETURN, n->right->right, Z); + n->right->left->type = n->right->left->left->type; + n->right->right->type = n->right->right->left->type; + *r = *n; + } + } +} + +static void +rewc1(Node *n) +{ + Node *c, *nc; + + if(n == Z || n->op != OCOND || side(n) || !simple(n)) + return; + c = n->left; + nc = new1(ONOT, ncopy(c), Z); + n->op = OOROR; + n->left = new1(OANDAND, c, n->right->left); + n->right = new1(OANDAND, nc, n->right->right); +} + +static void +rewc(Node *n, Node *r) +{ + Node *nn, *rr, *i; + + if((nn = cfind(n)) != Z){ + i = cgen(nn, n); + rr = new1(OXXX, Z, Z); + if(n == r && nn == n) + *rr = *nn; + else + *rr = *r; + r->op = OLIST; + r->left = i; + r->right = rr; + } +} + +static int +rewe(Node *n, Type *t, int lev) +{ + int op, k, k1, k2; + int v; + Node *nn; + + if(n == Z) + return -1; + switch(n->op){ + case OCONST: + break; + case ONAME: + if(strings || !isstring(n)) + break; + case OSTRING: + case OLSTRING: + if(!strings) + addnode(OS2AB, n); + break; + case OCOND: + bptr(n->left); + rewe(n->left, T, 1); + rewe(n->right, T, 1); + break; + case OIND: + if(isfn(n->type)){ + *n = *n->left; + rewe(n, T, 1); + break; + } + if(!isadt(n->type)){ + n->op = OARRIND; + n->right = con(0); + rewe(n, T, 1); + break; + } + rewe(n->left, T, 1); + break; + case OADDR: + if(n->left->op == OARRIND){ + n->right = n->left; + n->left = n->right->left; + n->right->left = n->right->right; + n->right->right = Z; + n->right->op = OLIST; + n->op = OSLICE; + rewe(n, T, 1); + break; + } + rewe(n->left, T, 1); + break; + case OSLICE: + rewe(n->left, T, 1); + rewe(n->right, T, 1); + if(n->left->op == OSLICE){ + n->right->left = addn(n->left->right->left, n->right->left); + n->right->right = addn(n->left->right->left, n->right->right); + n->left = n->left->left; + rewe(n, T, 1); + break; + } + break; + case OCOMMA: + rewe(n->left, T, 1); + rewe(n->right, T, 1); + if(n->left->op == OAS && n->right->op == OAS){ + n->op = OAS; + n->left->op = n->right->op = OLIST; + nn = n->left->right; + n->left->right = n->right->left; + n->right->left = nn; + rewe(n, T, 1); + break; + } + break; + case OFUNC: + if(n->left->op == ONAME){ + if((k = n->left->sym->kind) != LNONE){ + rewlc(n, k, t); + rewe(n->left, T, 1); + rewe(n->right, T, 1); + args(n); + return k; + } + } + else + rewe(n->left, T, 1); + rewe(n->right, T, 1); + args(n); + break; + case OCAST: + rewe(n->left, n->type, 1); + break; + case OAS: + case OASI: + case OASD: + rewe(n->left, T, 1); + rewe(n->right, n->type, 1); + break; + case ONOT: + case OANDAND: + case OOROR: + bptr(n); + rewe(n->left, T, 1); + rewe(n->right, T, 1); + break; + case OPREINC: + case OPOSTINC: + case OASADD: + if(n->op != OPOSTINC || lev == 0){ + sliceasgn(n); + if(n->op == OAS){ + rewe(n, T, 1); + break; + } + } + rewe(n->left, T, 1); + rewe(n->right, T, 1); + break; + case OEQ: + case ONE: + case OLT: + case OLE: + case OGT: + case OGE: + k1 = rewe(n->left, T, 1); + k2 = rewe(n->right, T, 1); + if(k1 == LSTRCMP && n->right->op == OCONST){ + op = -1; + v = n->right->vconst; + switch(v){ + case -1: + if(n->op == OEQ) + op = OLT; + else if(n->op == ONE) + op = OGE; + break; + case 0: + op = n->op; + break; + case 1: + if(n->op == OEQ) + op = OGT; + else if(n->op == ONE) + op = OLE; + break; + } + if(op != -1){ + *n = *n->left; + n->op = op; + } + } + if(k2 == LSTRCMP && n->left->op == OCONST){ + op = -1; + v = n->left->vconst; + switch(v){ + case -1: + if(n->op == OEQ) + op = OLT; + else if(n->op == ONE) + op = OGE; + break; + case 0: + op = rev(n->op); + break; + case 1: + if(n->op == OEQ) + op = OGT; + else if(n->op == ONE) + op = OLE; + break; + } + if(op != -1){ + *n = *n->right; + n->op = op; + } + } + break; + default: + rewe(n->left, T, 1); + rewe(n->right, T, 1); + break; + } + return -1; +} + +/* +static void +rewf(Node *n) +{ + if(n == Z) + return; + switch(n->op){ + case OFUNC: + if(n->left->op == ONAME) + fdargs(n); + break; + default: + rewf(n->left); + rewf(n->right); + break; + } +} +*/ + +static void +rew(Node *n, int blk) +{ + int i; + Node *a, *nn; + + if(n == Z) + return; + if(blk) + pushscope(n, SAUTO); + nearln = n->lineno; + if(n->blk){ + n->blk = 0; + addnode(OBLK, n); + } + switch(n->op){ + default: + if(simple(n)) + rewc0(n, n); + else + rewc(n, n); + if(n->op == OLIST || n->op == OIF){ + rew(n, 0); + break; + } + ecomplex(n); + break; + case ODAS: + pushdcl(n->left, CAUTO); + rewe(n->right, T, 1); + break; + case OSBREAK: + case ONUL: + break; + case ONAME: + if(n->kind == KEXP) + ecomplex(n); + else + pushdcl(n, CAUTO); + break; + case OBLK: + rew(n->left, 1); + break; + case OLIST: + rew(n->left, 0); + rew(n->right, 0); + break; + case ORETURN: + if(simple(n->left)) + rewc0(n->left, n); + else + rewc(n->left, n); + if(n->op != ORETURN){ + rew(n, 0); + break; + } + ecomplex(n); + break; + case OLABEL: + case OGOTO: + break; + case OCASE: + for(nn = n->left; nn != Z; nn = nn->right) + if(nn->left != Z) + ecomplex(nn->left); + rew(n->right, 1); + break; + case OSWITCH: + rewc(n->left, n); + if(n->op == OLIST){ + rew(n, 0); + break; + } + ecomplex(n->left); + if(!lteq(n->left->type, types[TINT])) + intcast(n->left); + n->right = buildcases(n->right); + rew(n->right, 1); + break; + case OWHILE: + case ODWHILE: + rewc1(n->left); + becomplex(n->left); + rew(n->right, 1); + break; + case OFOR: + rewc1(n->left->left); + rewc(n->left->right->left, n); + if(n->op == OLIST){ + rew(n, 0); + break; + } + becomplex(n->left->left); + ecomplex(n->left->right->left); + ecomplex(n->left->right->right); + rew(n->right, 1); + break; + case OCONTINUE: + break; + case OBREAK: + break; + case OIF: + rewc1(n->left); + rewc(n->left, n); + if(n->op == OLIST){ + rew(n, 0); + break; + } + becomplex(n->left); + rew(n->right->left, 1); + rew(n->right->right, 1); + break; + case OSET: + if(n->left == Z){ + n->op = ONUL; + n->left = n->right = Z; + break; + } + if(n->left->op != OLIST){ + n->op = OAS; + n->right = defval(n->left->type); + rew(n, 0); + break; + } + i = 0; + nn = Z; + for(;;){ + a = arg(n->left, i); + if(a == Z) + break; + a = new1(OAS, a, defval(a->type)); + if(i == 0) + nn = a; + else + nn = new1(OLIST, nn, a); + i++; + } + *n = *nn; + rew(n, 0); + break; + case OUSED: + if(n->left == Z){ + n->op = ONUL; + n->left = n->right = Z; + break; + } + i = 0; + nn = Z; + for(;;){ + a = arg(n->left, i); + if(a == Z) + break; + if(i == 0) + nn = a; + else + nn = new1(OOROR, nn, a); + i++; + } + n->op = OIF; + n->left = nn; + n->right = new1(OLIST, Z, Z); + n->right->left = new1(ONUL, Z, Z); + rew(n, 0); + break; + } + if(blk) + popscope(); +} + +void +codgen2(Node *n, Node *nn, int lastlno, int rw) +{ + Node *ln = Z; + + newsec(0); + output(nn->lineno, 1); + tmp = 0; + /* t = types[TVOID]; */ + nn = func(nn); + pushscope(nn, SPARM); + if(rw) + rew(n, 1); + egen(nn, ONOOP, PRE); + newline(); + prdelim("{"); + newline(); + incind(); + /* rewf(n); */ + pushscope(n, SAUTO); + sgen(n, 0, &ln); + if(ln != Z && isdec(ln)) + tdgen(ln, 0); + popscope(); + popscope(); + if(n != Z) + output(lline(n), 1); + output(lastlno, 1); + decind(); + prdelim("}"); + newline(); + newline(); + setmain(nn); +} + +void +rewall(Node *n, Node *nn, int lastlno) +{ + USED(lastlno); + tmp = 0; + nn = func(nn); + pushscope(nn, SPARM); + rew(n, 1); + popscope(); + setmain(nn); +} + +void +suball(Node *n, Node *nn) +{ + Node *rn; + + nn = func(nn); + pushscope(nn, SPARM); + subs(nn, 0, 0); + subs(n, 1, 1); + nn = lastn(n); + if(nn != Z && nn->op != ORETURN){ + rn = retval(Z); + if(rn != Z){ + addnode(OLIST, nn); + nn->right = rn; + } + } + popscope(); +} + +void +ginit(void) +{ + thechar = 'o'; + thestring = "386"; + tfield = types[TLONG]; +} + +long +align(long i, Type *t, int op) +{ + long o; + Type *v; + int w; + + o = i; + w = 1; + switch(op) { + default: + diag(Z, "unknown align opcode %d", op); + break; + + case Asu2: /* padding at end of a struct */ + w = SZ_LONG; + break; + + case Ael1: /* initial allign of struct element */ + for(v=t; v->etype==TARRAY; v=v->link) + ; + w = ewidth[v->etype]; + if(w <= 0 || w >= SZ_LONG) + w = SZ_LONG; + break; + + case Ael2: /* width of a struct element */ + o += t->width; + break; + + case Aarg0: /* initial passbyptr argument in arg list */ + if(typesuv[t->etype]) { + o = align(o, types[TIND], Aarg1); + o = align(o, types[TIND], Aarg2); + } + break; + + case Aarg1: /* initial allign of parameter */ + w = ewidth[t->etype]; + if(w <= 0 || w >= SZ_LONG) { + w = SZ_LONG; + break; + } + w = 1; /* little endian no adjustment */ + break; + + case Aarg2: /* width of a parameter */ + o += t->width; + w = SZ_LONG; + break; + + case Aaut3: /* total allign of automatic */ + o = align(o, t, Ael2); + o = align(o, t, Ael1); + w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */ + break; + } + o = round(o, w); + if(0) + print("align %s %ld %T = %ld\n", bnames[op], i, t, o); + return o; +} + +long +maxround(long max, long v) +{ + v = round(v, SZ_LONG); + if(v > max) + return v; + return max; +} + +static int +nlen(Node *n) +{ + if(n == Z) + return 0; + if(n->op == OLIST) + return nlen(n->left)+nlen(n->right); + return 1; +} + +static void +flatten(Node *n, Node **a, int *i) +{ + if(n == Z) + return; + if(n->op == OLIST){ + flatten(n->left, a, i); + flatten(n->right, a, i); + free(n); + return; + } + a[(*i)++] = n; +} + +static Node* +addcase(Node *n, Node **e, Node **s, int k) +{ + Node *nn; + + if(*e != Z){ + nn = new1(OCASE, *e, *s); + nn->right->blk = 0; + nn->kind = k; + } + else + nn = *s; + *e = *s = Z; + if(n == Z) + return nn; + return new1(OLIST, n, nn); +} + +/* collect case code together */ +static Node* +buildcases(Node *n) +{ + int i, m, m0, c; + Node *e, *s, *nn, **a, **ep; + + m = nlen(n); + a = (Node **)malloc(m*sizeof(Node*)); + m0 = 0; + flatten(n, a, &m0); + if(m != m0) + diag(Z, "internal: bad buildcases()"); + c = 1; + e = s = nn = Z; + ep = &e; + for(i = 0; i < m; i++){ + n = a[i]; + if(n->op == OCASE){ + if(!c){ + nn = addcase(nn, &e, &s, KNIL); + ep = &e; + } + *ep = new1(OLIST, n->left, Z); + if(n->left == Z) + (*ep)->lineno = n->lineno; + ep = &(*ep)->right; + c = 1; + } + else{ + if(s == Z) + s = n; + else + s = new1(OLIST, s, n); + c = 0; + } + } + nn = addcase(nn, &e, &s, KLAST); + free(a); + return nn; +} + +static Sym * +tmpgen(Type *t) +{ + Sym *s; + + sprint(buf, "tmp_%d", ++tmp); + s = slookup(buf); + s->type = t; + s->class = CAUTO; + if(t->etype == TENUM) + s->type = types[TINT]; + return s; +} + +static Node* +cfind(Node *n) +{ + Node *nn; + + if(n == Z) + return Z; + if(n->op == OCOND) + return n; + nn = cfind(n->left); + if(nn != Z) + return nn; + return cfind(n->right); +} + +Node* +ncopy(Node *n) +{ + Node *nn; + + if(n == Z) + return Z; + nn = new1(n->op, Z, Z); + *nn = *n; + nn->left = ncopy(n->left); + nn->right = ncopy(n->right); + return nn; +} + +static int +complexity(Node *n, int *cond) +{ + int c; + + if(n == Z) + return 0; + c = complexity(n->left, cond)+1+complexity(n->right, cond); + if(n->op == OCOND) + (*cond)++; + return c; +} + +static int +simple(Node *n) +{ + int c; + + c = 0; + return complexity(n, &c) < COMPLEX && c <= 1; +} + +static Type* +intype(Node *n) +{ + Type *t; + + t = ntype(n); + if(t == T) + return T; + return t->link; +} + +static Type* +ntype(Node *n) +{ + Type *t; + + if(n == Z) + return T; + t = n->type; + if(t != T){ + if(t->etype == TENUM) + return n->sym->tenum; + return t; + } + switch(n->op){ + case OEQ: + case ONE: + case OLT: + case OGE: + case OGT: + case OLE: + case ONOT: + case OANDAND: + case OOROR: + case OIOTA: + return types[TINT]; + case OCOMMA: + return ntype(n->right); + case OCOND: + return maxtype(ntype(n->right->left), ntype(n->right->right)); + case OFUNC: + return intype(n->left); + case ODOT: + tcomd(n, ntype(n->left)); + t = n->type; + n->type = T; + return t; + case ODOTIND: + tcomd(n, intype(n->left)); + t = n->type; + n->type = T; + return t; + case OARRIND: + return intype(n->left); + case OADDR: + return typ1(TIND, ntype(n->left)); + case OIND: + return intype(n->left); + case OSTRUCT: + return T; + } + return maxtype(ntype(n->left), ntype(n->right)); +} + +static Type* +gettype(Node *n1, Node *n2) +{ + Type *t; + + t = maxtype(n1->type, n2->type); + if(t != T) + return t; + return maxtype(ntype(n1), ntype(n2)); +} + +static void +cgen0(Node *n, Node *e) +{ + Node *c, *nn, *ed, *ee; + + if(n == e){ + n->op = OIF; + return; + } + c = n->left; + ed = new1(OXXX, Z, Z); + *ed = *e; + ee = ncopy(e); + nn = cfind(ee); + *n = *n->right->left; + *nn = *nn->right->right; + e->op = OIF; + e->left = c; + e->right = new1(OLIST, ed, ee); +} + +static Node* +cgen(Node *n, Node *e) +{ + Type *t; + Node *tn, *i; + + USED(e); + tn = new1(ONAME, Z, Z); + t = gettype(n->right->left, n->right->right); + tn->sym = tmpgen(t); + tn->type = tn->sym->type; +/* + if(n == e){ + n->op = OIF; + n->right->left = new1(OASD, tn, n->right->left); + n->right->right = new1(OAS, tn, n->right->right); + return n; + } +*/ + i = new1(OIF, n->left, new1(OLIST, new1(OASD, tn, n->right->left), new1(OAS, tn, n->right->right))); + *n = *tn; + return i; +} + +static struct{ + char *name; + int args; + int fd; + char *lname; +} sysops[] = { + "create", 1, RET, nil, + "dirstat", 1, 0, "stat", + "dirfstat", 0, 1, "fstat", + "dirwstat", 1, 0, "wstat", + "dirfwstat", 0, 1, "fwstat", + "dirread", 0, 1, nil, + "dup", 0, 0, nil, + "fprint", 2|STAR, 1, nil, + "fprintf", 2|STAR, 1, "fprint", + "open", 1, RET, nil, + "print", 1|STAR, 0, nil, + "printf", 1|STAR, 0, "print", + "read", 0, 1, nil, + "remove", 1, 0, nil, + "seek", 0, 1, nil, + "sleep", 0, 0, nil, + "sprint", 1|STAR, 0, nil, + "sprintf", 1|STAR, 0, "sprint", + "write", 0, 1, nil, + 0 +}; + +/* dummy entry for module */ +#define BIOTMP "__bio__" + +static struct{ + char *name; + char *lname; +} bioops[] = { + "Bflush", "flush", + "Bgetc", "getc", + "Bprint", "puts", + "Bputc", "putc", + "Bread", "read", + "Bseek", "seek", + "Bungetc", "ungetc", + "Bwrite", "write", + BIOTMP, nil, + 0 +}; + +char *libcops[] = { + "isalnum", + "isalpha", + "isascii", + "iscntrl", + "isdigit", + "isgraph", + "islower", + "isprint", + "ispunct", + "isspace", + "isupper", + "isxdigit", + "strchr", + "strrchr", + "toascii", + "tolower", + "toupper", + "abs", + "min", + "max", + 0, +}; + +static struct{ + char *name; + int type; + int string; +} xops[] = { + "strlen", LSTRLEN, 1, + "strcmp", LSTRCMP, 1, + "strcpy", LSTRCPY, 1, + "strcat", LSTRCAT, 1, + "strncmp", LSTRNCMP, 1, + "strncpy", LSTRNCPY, 1, + "strncat", LSTRNCAT, 1, + "strdup", LSTRDUP, 1, + "memcpy", LMEMMOVE, 0, + "memmove", LMEMMOVE, 0, + "malloc", LMALLOC, 0, + "free", LFREE, 0, + "exit", LEXIT, 0, + "exits", LEXIT, 0, + "close", LCLOSE, 0, + "atoi", LATOI, 0, + "atol", LATOI, 0, + "atoll", LATOL, 0, + "atof", LATOF, 0, + "atod", LATOF, 0, + "print", LPRINT, 0, + "printf", LPRINT, 0, + "fprint", LFPRINT, 0, + "fprintf", LFPRINT, 0, + "sprint", LSPRINT, 0, + "sprintf", LSPRINT, 0, + 0 +}; + +char *mathsops[] = { + "sin", + "cos", + "tan", + "sinh", + "cosh", + "tanh", + "asin", + "acos", + "atan", + "asinh", + "acosh", + "atanh", + "atan2", + "sqrt", + "cbrt", + "pow", + "pow10", + "exp", + "log", + "log10", + 0 +}; + +Node *glob, *globe; + +void +sysinit(void) +{ + int i; + Sym *s; + + glob = globe = new1(ONOOP, Z, Z); + for(i = 0; sysops[i].name; i++){ + s = slookup(sysops[i].name); + s->class = CEXTERN; + s->args = sysops[i].args; + s->fd = sysops[i].fd; + s->mod = "sys"; + s->lname = sysops[i].lname; + s->limbo = 1; + sysop = s; + } + for(i = 0; bioops[i].name; i++){ + s = slookup(bioops[i].name); + s->class = CEXTERN; + if(strcmp(bioops[i].name, BIOTMP) == 0){ + s->mod = "bufio"; + bioop = s; + } + s->lname = bioops[i].lname; + s->kind = LSELF; + s->limbo = 1; + } + for(i = 0; mathsops[i]; i++){ + s = slookup(mathsops[i]); + s->class = CEXTERN; + s->mod = "math"; + s->limbo = 1; + } + for(i = 0; libcops[i]; i++){ + s = slookup(libcops[i]); + s->class = CEXTERN; + s->mod = strings ? "libc" : "libc0"; + s->limbo = 1; + libcop = s; + } + for(i = 0; xops[i].name; i++){ + s = slookup(xops[i].name); + s->class = CEXTERN; + if(strings || !xops[i].string) + s->kind = xops[i].type; + else + s->mod = "libc0"; + if(s->kind == LEXIT) + s->lname = "exit"; + s->limbo = 1; + } + usemod(sysop, 1); + if(!strings) + usemod(libcop, 1); +} + +void +clbegin(void) +{ + pushscope(glob, SGLOB); +} + +void +clend(void) +{ + if(passes) + swalk(); + popscope(); +} + +static Modl *mods; + +void +usemod(Sym *s, int ld) +{ + Modl *ml; + + for(ml = mods; ml != nil; ml = ml->nxt) + if(strcmp(ml->mod, s->mod) == 0){ + ml->ld |= ld; + return; + } + ml = (Modl *)malloc(sizeof(Modl)); + ml->mod = s->mod; + ml->ld = ld; + ml->nxt = mods; + mods = ml; +} + +static void +ginc(Modl *ml) +{ + int c; + char *s; + + if(ml == nil) + return; + if(ml->nxt != nil) + ginc(ml->nxt); + s = ml->mod; + c = toupper(s[0]); + sprint(buf, "include \"%s.m\";", s); + prline(buf); + if(ml->ld){ + sprint(buf, " %s: %c%s;", s, c, s+1); + prline(buf); + } +} + +static void +gload(Modl *ml) +{ + int c; + char *s; + + if(ml == nil) + return; + if(ml->nxt != nil) + gload(ml->nxt); + if(ml->ld){ + s = ml->mod; + c = toupper(s[0]); + sprint(buf, " %s = load %c%s %c%s->PATH;", s, c, s+1, c, s+1); + prline(buf); + } +} + +static void +callmain(void) +{ + if(inmain){ + if(strings) + prline(" main(len argl, argl);"); + else + prline(" main(len argl, libc0->ls2aab(argl));"); + } +} + +static void +genstart(void) +{ + char *s; + + if(!strings && inmain) + usemod(libcop, 1); + ginc(mods); + s = hasm(); + if(s){ + sprint(buf, "include \"%s\";", s); + prline(buf); + } + prline(""); + prline("init(nil: ref Draw->Context, argl: list of string)"); + prline("{"); + gload(mods); + callmain(); + prline("}"); + prline(""); +} + +static int +argpos0(Node *nn, Node *n, int *p) +{ + int pp; + + if(n == Z) + return -1; + if(n->op == OLIST){ + pp = argpos0(nn, n->left, p); + if(pp >= 0) + return pp; + return argpos0(nn, n->right, p); + } + if(n == nn) + return *p; + (*p)++; + return -1; +} + +static int +argpos(Node *nn, Node *n) +{ + int p = 0; + + p = argpos0(nn, n, &p); + if(p < 0) + diag(Z, "-ve argpos"); + return p; +} + +static Node* +arg0(Node *n, int a, int *i) +{ + Node *nn; + + if(n == Z) + return Z; + if(n->op == OLIST){ + nn = arg0(n->left, a, i); + if(nn != Z) + return nn; + return arg0(n->right, a, i); + } + if(a == (*i)++) + return n; + return Z; +} + +static Node* +arg(Node *n, int a) +{ + int i = 0; + + return arg0(n, a, &i); +} + +static Node* +list(Node *l, Node *r) +{ + if(r == Z) + return l; + if(l == Z) + return r; + return new1(OLIST, l, r); +} + +static Node* +droparg(Node *n, int a, int *i) +{ + if(n == Z) + return Z; + if(n->op == OLIST) + return list(droparg(n->left, a, i), droparg(n->right, a, i)); + if(a == (*i)++) + return Z; + return n; +} + +static void +sargs(Node *n) +{ + int s, f, i, j; + Node *a; + + if(strings || (f = n->left->sym->args) == 0) + return; + s = 0; + for(i = 1, j = 0; i < STAR || s; i *= 2, j++){ + if(f&i || s){ + a = arg(n->right, j); + if(a == Z) + break; + if(s && !isstr(a->type)) + continue; + if(f&STAR) + s++; + if(a->op == OS2AB){ + *a = *a->left; + continue; + } + addnode(OAB2S, a); + } + } +} + +static void +fdargs(Node *n) +{ + int f, i, j; + Node *a; + + if((f = n->left->sym->fd) == 0) + return; + marktype(pfdtype, TCFD); + if(f&RET) + tcon(n, pfdtype); + for(i = 1, j = 0; i < RET; i *= 2, j++){ + if(f&i){ + a = arg(n->right, j); + if(a == Z) + break; + tcon(a, pfdtype); + } + } +} + +static void +aargs(Node *n) +{ + int i; + Node *a, *nn, *fn; + Type *t, *t0, *ft, *at, *st; + + if(!doaddr) + return; + if(n->op != OFUNC || n->left->op != ONAME) + return; + /* ft = n->left->type; */ + ft = n->left->sym->type; + t = t0 = ft->link; + nn = Z; + for(i = 0; ; i++){ + a = arg(n->right, i); + if(a == Z) + break; + at = typn(ft, i); + if(at != T && at->etype != TDOT && (a->op == OADDR || iteq(a->type, at) || iteq(at, a->type))){ + if(iteq(at, a->type)) + st = at->link; + else + st = a->type->link; + if(doalladdr || isscalar(st)){ + if(a->op == OADDR) + *a = *a->left; + else if(iteq(a->type, at)) + a->type = at; + if(t->mark == 0){ + t = tuple(t, a->type); + trep(at, at->link); + fn = finddec(n->left->sym, 1); + if(fn != Z && fn->op == OFUNC) + tind(arg(fn->right, i)); + } + if(nn == Z) + nn = cknil(ncopy(a)); + else{ + nn = new1(OTUPLE, nn, cknil(ncopy(a))); + nn->type = t; + } + } + } + } + if(nn != Z){ + if(isvoid(t0) || t->mark == TCPC) + marktype(t, TCPC); + else + marktype(t, TCFC); + tcon(n, t); + addnode(ORETV, n); + n->right = nn; + } +} + +static void +args(Node *n) +{ + if(n->op != OFUNC || n->left->op != ONAME) + return; + sargs(n); + if(passes){ + fdargs(n); + aargs(n); + } +} + +static Node* +indir(Node *n) +{ + if(n->op == OADDR) + return n->left; + return new1(OIND, n, Z); +} + +static void +rewlc(Node *n, int k, Type *t) +{ + int i; + Type *tt; + Node *a0, *a1, *a2, *nn; + + if(t == T) + t = n->type; + a0 = arg(n->right, 0); + a1 = arg(n->right, 1); + switch(k){ + case LSTRLEN: + n->op = OLEN; + break; + case LSTRCMP: + n->op = ONE; + n->left = a0; + n->right = a1; + break; + case LSTRCPY: + n->op = OAS; + n->left = a0; + n->right = a1; + n->type = n->left->type; + break; + case LSTRCAT: + n->op = OASADD; + n->left = a0; + n->right = a1; + n->type = n->left->type; + break; + case LSTRDUP: + *n = *a0; + break; + case LMEMMOVE: + if(!teq(a0->type, a1->type)) + break; + if(a0->type->etype == TIND){ + tt = a0->type->link; + a2 = arg(n->right, 2); + if(isadt(tt) && isconst(a2, tt->width)){ + n->op = OAS; + n->left = indir(a0); + n->right = indir(a1); + n->type = n->left->type = n->right->type = tt; + break; + } + if(mydiv(a2, tt->width) != Z){ + n->op = OAS; + n->left = new1(OSLICE, a0, new1(OLIST, con(0), Z)); + n->right = new1(OSLICE, a1, new1(OLIST, con(0), a2)); + n->type = n->left->type = n->right->type = a0->type; + } + } + break; + case LMALLOC: + if(t->etype == TIND){ + tt = t->link; + if(isadt(tt) && isconst(a0, tt->width)){ + n->op = OREF; + n->left = Z; + n->right = Z; + n->type = t; + break; + } + if(mydiv(a0, tt->width) != Z){ + n->op = OARRAYOF; + n->left = a0; + n->right = Z; + n->type = t; + if(isadt(tt)){ + n->type = typ1(TARRAY, tt); + n->type->width = LARR; /* limbo array without bounds */ + marktype(n->type, TCAR); + } + } + } + break; + case LFREE: + n->op = OAS; + n->left = a0; + n->right = con(0); + n->type = n->left->type; + n->right->type = n->type; + break; + case LEXIT: + i = n->kind; + *n = *n->left; + n->kind = i; + break; + case LCLOSE: + n->op = OAS; + n->left = a0; + n->right = con(0); + n->left->type = typ1(TIND, n->left->type); + n->type = n->left->type; + n->right->type = n->type; + break; + case LATOI: + if(!strings) + strcast(a0); + n->op = OCAST; + n->left = a0; + n->right = Z; + n->type = types[TINT]; + break; + case LATOL: + if(!strings) + strcast(a0); + n->op = OCAST; + n->left = a0; + n->right = Z; + n->type = types[TVLONG]; + break; + case LATOF: + if(!strings) + strcast(a0); + n->op = OCAST; + n->left = a0; + n->right = Z; + n->type = types[TDOUBLE]; + break; + case LPRINT: + if(a0->op == OSTRING) + pfmt(a0->cstring); + else if(a0->op == OLSTRING) + lpfmt(a0->rstring); + break; + case LFPRINT: + if(a1->op == OSTRING) + pfmt(a1->cstring); + else if(a1->op == OLSTRING) + lpfmt(a1->rstring); + break; + case LSPRINT: + if(n->right->kind != KDROP){ + if(a1->op == OSTRING) + pfmt(a1->cstring); + else if(a1->op == OLSTRING) + lpfmt(a1->rstring); + nn = new1(OXXX, Z, Z); + *nn = *n; + i = 0; + nn->right = droparg(nn->right, 0, &i); + nn->right->kind = KDROP; + n->op = OAS; + n->left = a0; + n->right = nn; + n->type = nn->type; + } + break; + case LSELF: + if(n->right != Z && n->right->kind != KDROP){ + i = 0; + n->right = droparg(n->right, 0, &i); + if(n->right != Z) + n->right->kind = KDROP; + addnode(OLDOT, n->left); + n->left->right = n->left->left; + n->left->left = a0; + usemod(bioop, 1); + } + break; + } +} + +void +expgen(Node *n) +{ + egen(n, ONOOP, PRE); +} + +static void +clrbrk(Node *n) +{ + if(n == Z) + return; + switch(n->op){ + case OLIST: + clrbrk(n->right); + break; + case OBREAK: + n->op = OSBREAK; + n->left = n->right = Z; + break; + } +} + +static int +hasbrk(Node *n) +{ + if(n == Z) + return 0; + switch(n->op){ + case OLIST: + case OWHILE: + case ODWHILE: + case OFOR: + return hasbrk(n->right); + case OIF: + if(n->right->right == Z) + return 0; + return hasbrk(n->right->left) && hasbrk(n->right->right); + case ORETURN: + case OGOTO: + case OCONTINUE: + case OBREAK: + case OSBREAK: + return 1; + default: + return 0; + } + return 0; +} + +static int +isgen(char *s) +{ + char *s1, *s2; + + s1 = strchr(s, '_'); + s2 = strrchr(s, '_'); + if(s1 == nil || s2-s1 != 4) + return 0; + return s1[1] == 'a' && s1[2] == 'd' && s1[3] == 't'; +} + +static void +addmodn(Sym *s) +{ + char buf[128], *ns; + + if(s->name[0] == '_'){ + outmod(buf, -1); + ns = malloc(strlen(buf)+strlen(s->name)+1); + strcpy(ns, buf); + strcat(ns, s->name); + s->name = ns; + } +} + +static void +pfmt(char *s) +{ + char *t = s; + + while(*s != '\0'){ + if(*s == '%'){ + *t++ = *s++; + if(*s == 'l'){ + s++; + if(*s == 'l') + *t++ = 'b'; + else + *t++ = *s; + s++; + } + else if(*s == 'p'){ + *t++ = 'x'; + s++; + } + else + *t++ = *s++; + } + else + *t++ = *s++; + } + *t = '\0'; +} + +static void +lpfmt(ushort *s) +{ + ushort*t = s; + + while(*s != '\0'){ + if(*s == '%'){ + *t++ = *s++; + if(*s == 'l'){ + s++; + if(*s == 'l') + *t++ = 'b'; + else + *t++ = *s; + s++; + } + else if(*s == 'p'){ + *t++ = 'x'; + s++; + } + else + *t++ = *s++; + } + else + *t++ = *s++; + } + *t = '\0'; +} + +int +line(Node *n) +{ + if(n == Z) + return 0; + if(n->op == OLIST) + return line(n->left); + return n->lineno; +} + +static int +lline(Node *n) +{ + if(n == Z) + return 0; + if(n->op == OLIST) + return lline(n->right); + return n->lineno+1; +} + +static Node* +lastn(Node *n) +{ + while(n != Z && n->op == OLIST) + n = n->right; + return n; +} + +static Node* +newnode(int op, Node *l) +{ + Node *n; + + n = new1(op, l, Z); + globe->right = n; + globe = n; + return n; +} + +void +codgen1(Node *n, Node *nn, int lastlno) +{ + Node *nnn; + + scomplex(n); + nnn = newnode(OCODE, new1(OLIST, n, nn)); + nnn->lineno = lastlno; + mset(n); + mset(nn); + nn = func(nn); + newnode(ODECF, nn); + setmain(nn); +} + +void +vtgen1(Node *n) +{ + int c; + Node *nn = n; + + if(n->op == ODAS) + nn = n->left; + if(nn->type == T || nn->sym == S) + return; + c = nn->sym->class; + if(c == CGLOBL || c == CSTATIC || c == CLOCAL || c == CEXREG){ + newnode(ODECV, n); + if(nn->type->etype != TFUNC || ism()) + setmod(nn->sym); + } + mset(n); +} + +void +etgen1(Sym *s) +{ + Node *n; + + n = newnode(ODECE, Z); + n->sym = s; + if(s != S) + setmod(s); +} + +void +ttgen1(Type *t) +{ + Node *n; + + n = newnode(ODECT, Z); + n->type = t; + if(isadt(t)) + setmod(suename(t)); +} + +void +outpush1(char *s) +{ + Node *n; + char *t; + + n = newnode(OPUSH, Z); + if(s == nil) + t = nil; + else{ + t = malloc(strlen(s)+1); + strcpy(t, s); + } + n->cstring = t; + outpush0(s, n); +} + +void +outpop1(int lno) +{ + Node *n; + + n = newnode(OPOP, Z); + n->lineno = lno; + outpop0(lno); +} + +void +codgen(Node *n, Node *nn, int lastlno) +{ + if(passes) + codgen1(n, nn, lastlno); + else + codgen2(n, nn, lastlno, 1); +} + +void +vtgen(Node *n) +{ + if(passes) + vtgen1(n); + else + vtgen2(n); +} + +void +etgen(Sym *s) +{ + if(passes) + etgen1(s); + else + etgen2(s); +} + +void +ttgen(Type *t) +{ + if(passes) + ttgen1(t); + else + ttgen2(t); +} + +void +outpush(char *s) +{ + if(passes) + outpush1(s); + else + outpush2(s, Z); +} + +void +outpop(int lno) +{ + if(passes) + outpop1(lno); + else + outpop2(lno); +} + +static void +swalk(void) +{ + Node *n, *l; + + for(n = glob; n != Z; n = n->right){ + l = n->left; + switch(n->op){ + case OCODE: + rewall(l->left, l->right, n->lineno); + break; + default: + break; + } + } + while(again){ + again = 0; + for(n = glob; n != Z; n = n->right){ + l = n->left; + switch(n->op){ + case OCODE: + suball(l->left, l->right); + break; + case ODECV: + subs(l, 0, 0); + break; + case ODECE: + case ODECT: + case ODECF: + break; + default: + break; + } + } + } + for(n = glob; n != Z; n = n->right){ + l = n->left; + switch(n->op){ + case ONOOP: + break; + case OPUSH: + outpush2(n->cstring, n); + break; + case OPOP: + outpop2(n->lineno); + break; + case OCODE: + codgen2(l->left, l->right, n->lineno, 0); + break; + case ODECV: + vtgen2(l); + break; + case ODECE: + etgen2(n->sym); + break; + case ODECT: + ttgen2(n->type); + break; + case ODECF: + break; + } + } +} + +static void +scomplex(Node *n) +{ + if(n == Z) + return; + switch(n->op){ + default: + complex(n); + break; + case ODAS: + case OSBREAK: + case ONUL: + case OLABEL: + case OGOTO: + case OCONTINUE: + case OBREAK: + break; + case ONAME: + if(n->kind == KEXP) + complex(n); + break; + case OBLK: + case OSET: + case OUSED: + scomplex(n->left); + break; + case OLIST: + scomplex(n->left); + scomplex(n->right); + break; + case ORETURN: + complex(n); + break; + case OCASE: + complex(n->left); + break; + case OSWITCH: + case OWHILE: + case ODWHILE: + complex(n->left); + scomplex(n->right); + break; + case OFOR: + complex(n->left->left); + complex(n->left->right->left); + complex(n->left->right->right); + scomplex(n->right); + break; + case OIF: + complex(n->left); + scomplex(n->right->left); + scomplex(n->right->right); + break; + } +} + +static void +mtset(Type *t) +{ + if(t == T) + return; + switch(t->etype){ + case TIND: + case TARRAY: + mtset(t->link); + break; + case TSTRUCT: + case TUNION: + prsym0(suename(t)); + /* + for(l = t->link; l != T; l = l->down) + mtset(l); + */ + break; + } +} + +static void +mset(Node *n) +{ + if(n == Z) + return; + n->garb = 0; + if(n->op == ONAME) + prsym0(n->sym); + mtset(n->type); + mset(n->left); + mset(n->right); +} + +static int +sign(Node *n) +{ + int s; + + if(n == Z) + return 1; + switch(n->op){ + case OCONST: + sign(n->left); + if(n->vconst < 0){ + n->vconst = -n->vconst; + return -1; + } + break; + case OPOS: + s = sign(n->left); + *n = *n->left; + return s; + case ONEG: + s = sign(n->left); + *n = *n->left; + return -s; + case OADD: + if(sign(n->right) < 0) + n->op = OSUB; + break; + case OSUB: + if(sign(n->right) < 0) + n->op = OADD; + break; + case OMUL: + case ODIV: + return sign(n->left)*sign(n->right); + default: + break; + } + return 1; +} + +static Node* +ckneg(Node *n) +{ + if(sign(n) < 0) + return new1(ONEG, n, Z); + return n; +} + +static void +sliceasgn(Node *n) +{ + Type *t; + Node *nn; + + if(side(n->left) || (n->right != Z && side(n->right))) + return; + t = n->type; + if(isarray(t) && (!strings || t->link->etype != TCHAR)){ + if(n->op == OASADD) + nn = n->right; + else + nn = con(1); + n->op = OAS; + n->right = new1(OSLICE, ncopy(n->left), new1(OLIST, nn, Z)); + } +} diff --git a/utils/c2l/cc.h b/utils/c2l/cc.h new file mode 100644 index 00000000..3900506d --- /dev/null +++ b/utils/c2l/cc.h @@ -0,0 +1,849 @@ +#include <lib9.h> +#include <bio.h> +#include <ctype.h> + +#ifndef EXTERN +#define EXTERN extern +#endif + +typedef struct Node Node; +typedef struct Sym Sym; +typedef struct Type Type; +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]; +}; + +EXTERN int lastnumbase; + +#define KNIL 0 +#define KCHR 1 +#define KOCT 2 +#define KDEC 3 +#define KHEX 4 +#define KEXP 5 +#define KDROP 6 +#define KLAST 7 + +struct Node +{ + Node* left; + Node* right; + 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 garb; + char kind; + char blk; +}; +#define Z ((Node*)0) +#define ZZ ((Node*)-1) + +struct Sym +{ + Sym* link; + Type* type; + Type* suetag; + Type* tenum; + char* macro; + long lineno; + long offset; + vlong vconst; + double fconst; + Node* nconst; + char* cstring; + Node* label; + char *name; + char *lname; + char *mod; + ushort lexical; + ushort block; + ushort sueblock; + char class; + char kind; + char lkw; + char args; + char fd; + char limbo; +}; +#define S ((Sym*)0) + +struct Decl +{ + Decl* link; + Sym* sym; + Type* type; + long offset; + long lineno; + short val; + ushort block; + char class; +}; +#define D ((Decl*)0) + +struct Type +{ + Sym* sym; + Sym* tag; + Type* link; + Type* down; + Node* nwidth; + long width; + long offset; + long lineno; + char shift; + char nbits; + char etype; + char garb; + char vis; + char mark; +}; +#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 +{ + ONOOP, + 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, + OELEM, + + OTST, /* used in some compilers */ + OINDEX, + OFAS, + + OBLK, + OPOS, + ONUL, + ODOTIND, + OARRIND, + ODAS, + OASD, + OIOTA, + OLEN, + OBRACKET, + OREF, + OARRAYOF, + OSLICE, + OSADDR, + ONIL, + OS2AB, + OAB2S, + OFILDES, + OFD, + OTUPLE, + OT0, + ORETV, + OCAT, + OSBREAK, + OLDOT, + OMDOT, + + OCODE, + ODECE, + ODECT, + ODECV, + ODECF, + OPUSH, + OPOP, + + 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, + TREGISTER, + TCONSTNT, + TVOLATILE, + TUNSIGNED, + TSIGNED, + TDOT, + TFILE, + TOLD, + + TSTRING, + TFD, + TTUPLE, + + NALLTYPES, +}; +enum +{ + CXXX, + CAUTO, + CEXTERN, + CGLOBL, + CSTATIC, + CLOCAL, + CTYPEDEF, + CPARAM, + CSELEM, + CLABEL, + CEXREG, + NCTYPES, +}; +enum +{ + GXXX = 0, + GCONSTNT = 1<<0, + GVOLATILE = 1<<1, + NGTYPES = 1<<2, +}; +enum +{ + BCHAR = 1L<<TCHAR, + BUCHAR = 1L<<TUCHAR, + BSHORT = 1L<<TSHORT, + BUSHORT = 1L<<TUSHORT, + BINT = 1L<<TINT, + BUINT = 1L<<TUINT, + BLONG = 1L<<TLONG, + BULONG = 1L<<TULONG, + BVLONG = 1L<<TVLONG, + BUVLONG = 1L<<TUVLONG, + BFLOAT = 1L<<TFLOAT, + BDOUBLE = 1L<<TDOUBLE, + BIND = 1L<<TIND, + BFUNC = 1L<<TFUNC, + BARRAY = 1L<<TARRAY, + BVOID = 1L<<TVOID, + BSTRUCT = 1L<<TSTRUCT, + BUNION = 1L<<TUNION, + BENUM = 1L<<TENUM, + BFILE = 1L<<TFILE, + BOLD = 1L<<TOLD, + BDOT = 1L<<TDOT, + BCONSTNT = 1L<<TCONSTNT, + BVOLATILE = 1L<<TVOLATILE, + BUNSIGNED = 1L<<TUNSIGNED, + BSIGNED = 1L<<TSIGNED, + BAUTO = 1L<<TAUTO, + BEXTERN = 1L<<TEXTERN, + BSTATIC = 1L<<TSTATIC, + BTYPEDEF = 1L<<TTYPEDEF, + BREGISTER = 1L<<TREGISTER, + + BINTEGER = BCHAR|BUCHAR|BSHORT|BUSHORT|BINT|BUINT| + BLONG|BULONG|BVLONG|BUVLONG, + BNUMBER = BINTEGER|BFLOAT|BDOUBLE, + +/* these can be overloaded with complex types */ + + BCLASS = BAUTO|BEXTERN|BSTATIC|BTYPEDEF|BREGISTER, + + BGARB = BCONSTNT|BVOLATILE, +}; + +EXTERN struct +{ + Type* tenum; /* type of entire enum */ + Type* cenum; /* type of current enum run */ + vlong lastenum; /* value of current enum */ + double floatenum; /* value of current enum */ +} en; + +EXTERN int autobn; +EXTERN long autoffset; +EXTERN int blockno; +EXTERN int comm; +EXTERN Decl* dclstack; +EXTERN int doaddr; +EXTERN int doalladdr; +EXTERN int doinc; +EXTERN int doloc; +EXTERN int domod; +EXTERN Hist* ehist; +EXTERN long firstbit; +EXTERN Decl* firstdcl; +EXTERN int fperror; +EXTERN Sym* hash[NHASH]; +EXTERN char* hunk; +EXTERN char* include[20]; +EXTERN Type* fdtype; +EXTERN int inmain; +EXTERN Io* iofree; +EXTERN Io* ionext; +EXTERN Io* iostack; +EXTERN int justcode; +EXTERN long lastbit; +EXTERN char lastclass; +EXTERN Type* lastdcl; +EXTERN long lastfield; +EXTERN Type* lasttype; +EXTERN long lineno; +EXTERN long nearln; +EXTERN int nerrors; +EXTERN int newflag; +EXTERN long nhunk; +EXTERN int ninclude; +EXTERN Node* nodproto; +EXTERN Node* nodcast; +EXTERN int passes; +EXTERN char* pathname; +EXTERN int peekc; +EXTERN Type* pfdtype; +EXTERN long pline; +EXTERN long saveline; +EXTERN Type* strf; +EXTERN int strings; +EXTERN Type* stringtype; +EXTERN Type* strl; +EXTERN char symb[NSYMB]; +EXTERN Sym* symstring; +EXTERN int taggen; +EXTERN Type* tfield; +EXTERN Type* tufield; +EXTERN int thechar; +EXTERN char* thestring; +EXTERN Type* thisfn; +EXTERN long thunk; +EXTERN Type* types[NTYPE]; +EXTERN Node* initlist; +EXTERN int nterm; +EXTERN int hjdickflg; +EXTERN int fproundflg; +EXTERN Bits zbits; + +extern char *onames[], *tnames[], *gnames[]; +extern char *cnames[], *qnames[], *bnames[]; +extern char tab[NTYPE][NTYPE]; +extern char comrel[], invrel[], logrel[]; +extern long ncast[], tadd[], tand[]; +extern long targ[], tasadd[], tasign[], tcast[]; +extern long tdot[], tfunct[], tindir[], tmul[]; +extern long tnot[], trel[], tsub[]; + +extern char typeaf[]; +extern char typefd[]; +extern char typei[]; +extern char typesu[]; +extern char typesuv[]; +extern char typeu[]; +extern char typev[]; +extern char typec[]; +extern char typeh[]; +extern char typeil[]; +extern char typeilp[]; +extern char typechl[]; +extern char typechlp[]; +extern char typechlpfd[]; + +extern ulong thash1; +extern ulong thash2; +extern ulong thash3; +extern ulong thash[]; + +/* + * Inferno.c/Posix.c/Nt.c + */ +int mywait(int*); +int mycreat(char*, int); +int systemtype(int); +int pathchar(void); +char* mygetwd(char*, int); +int myexec(char*, char*[]); +int mydup(int, int); +int myfork(void); +int mypipe(int*); +void* mysbrk(ulong); + +/* + * parser + */ +int yyparse(void); +int mpatof(char*, double*); +int mpatov(char*, vlong*); + +/* + * lex.c + */ +void* allocn(void*, long, long); +void* alloc(long); +void cinit(void); +int compile(char*, char**, int); +void errorexit(void); +int filbuf(void); +int getc(void); +long getr(void); +int getnsc(void); +Sym* lookup(void); +void main(int, char*[]); +void newfile(char*, int); +void newio(void); +void outbegin(char *); +void outend(void); +void outfun(Node*); +void pushio(void); +long escchar(long, int, int); +Sym* slookup(char*); +void syminit(Sym*); +void unget(int); +long yylex(void); +int Lconv(Fmt*); +int Tconv(Fmt*); +int FNconv(Fmt*); +int Oconv(Fmt*); +int Qconv(Fmt*); +int VBconv(Fmt*); +void setinclude(char*); + +/* + * mac.c + */ +void dodefine(char*); +void domacro(void); +Sym* getsym(void); +long getnsn(void); +void linehist(char*, int); +void macdef(void); +void macprag(void); +void macend(void); +void macexpand(Sym*, char*); +void macif(int); +void macinc(void); +void maclin(void); +void macund(void); + +/* + * dcl.c + */ +Node* doinit(Sym*, Type*, long, Node*); +Type* tcopy(Type*); +void init1(Sym*, Type*, long, int); +Node* newlist(Node*, Node*); +void adecl(int, Type*, Sym*); +int anyproto(Node*); +void argmark(Node*, int); +void dbgdecl(Sym*); +Node* dcllabel(Sym*, int); +Node* dodecl(void(*)(int, Type*, Sym*), int, Type*, Node*, int); +Sym* mkstatic(Sym*); +void doenum(Sym*, Node*); +void snap(Type*); +Type* dotag(Sym*, int, int); +void edecl(int, Type*, Sym*); +Type* fnproto(Node*); +Type* fnproto1(Node*); +void markdcl(void); +Type* paramconv(Type*, int); +void pdecl(int, Type*, Sym*); +Decl* push(void); +Decl* push1(Sym*); +Node* revertdcl(void); +#define round ccround +long round(long, int); +int rsametype(Type*, Type*, int, int); +int sametype(Type*, Type*); +ulong signature(Type*, int); +void suallign(Type*); +void tmerge(Type*, Sym*); +void walkparam(Node*, int); +void xdecl(int, Type*, Sym*); +Node* contig(Sym*, Node*, long); + +/* + * com.c + */ +void ccom(Node*); +void complex(Node*); +int tcom(Node*); +int tcoma(Node*, Node*, Type*, int); +int tcomd(Node*, Type*); +int tcomo(Node*, int); +int tcomx(Node*); +int tlvalue(Node*); +void constas(Node*, Type*, Type*); + +/* + * con.c + */ +void acom(Node*); +void acom1(vlong, Node*); +void acom2(Node*, Type*); +int acomcmp1(const void*, const void*); +int acomcmp2(const void*, const void*); +int addo(Node*); +void evconst(Node*); + +/* + * sub.c + */ +void arith(Node*, int); +Type* dotsearch(Sym*, Type*, Node*); +long dotoffset(Type*, Type*, Node*); +void gethunk(void); +Node* invert(Node*); +int bitno(long); +void makedot(Node*, Type*, long); +Node* new(int, Node*, Node*); +Node* new1(int, Node*, Node*); +int nilcast(Type*, Type*); +int nocast(Type*, Type*); +void prtree(Node*, char*); +void prtree1(Node*, int, int); +void relcon(Node*, Node*); +int relindex(int); +int simpleg(long); +Type* garbt(Type*, long); +int simplec(long); +Type* simplet(long); +int stcompat(Node*, Type*, Type*, long[]); +int tcompat(Node*, Type*, Type*, long[]); +void tinit(void); +Type* typ(int, Type*); +Type* typ1(int, Type*); +void typeext(Type*, Node*); +void typeext1(Type*, Node*); +int side(Node*); +int vconst(Node*); +int vlog(Node*); +int topbit(ulong); +long typebitor(long, long); +void diag(Node*, char*, ...); +void warn(Node*, char*, ...); +void yyerror(char*, ...); +void fatal(Node*, char*, ...); + +/* + * acid.c + */ +void acidtype(Type*); +void acidvar(Sym*); + +/* + * bits.c + */ +Bits bor(Bits, Bits); +Bits band(Bits, Bits); +Bits bnot(Bits); +int bany(Bits*); +int bnum(Bits); +Bits blsh(uint); +int beq(Bits, Bits); +int bset(Bits, uint); + +/* + * dpchk.c + */ +void dpcheck(Node*); +void arginit(void); +void pragvararg(void); +void praghjdicks(void); +void pragfpround(void); + +/* + * calls to machine depend part + */ +void codgen(Node*, Node*, int); +void gclean(void); +void gextern(Sym*, Node*, long, long); +void ginit(void); +long outstring(char*, long); +long outlstring(ushort*, long); +void sextern(Sym*, Node*, long, long); +void xcom(Node*); +long exreg(Type*); +long align(long, Type*, int); +long maxround(long, long); + +extern schar ewidth[]; + +/* + * com64 + */ +int com64(Node*); +void com64init(void); +void bool64(Node*); +double convvtof(vlong); +vlong convftov(double); +double convftox(double, int); +vlong convvtox(vlong, int); + +#pragma varargck argpos warn 2 +#pragma varargck argpos diag 2 +#pragma varargck argpos yyerror 1 + +#pragma varargck type "F" Node* +#pragma varargck type "L" long +#pragma varargck type "Q" long +#pragma varargck type "O" int +#pragma varargck type "T" Type* +#pragma varargck type "|" int + +/* output routines */ + +void prline(char*); +void prstr(char *); +void prlstr(ushort *); +void prkeywd(char *); +void prid(char *); +void prsym(Sym*, int); +void prsym0(Sym*); +void prdelim(char *); +void prchar(vlong); +void prreal(double, char*, int); +void prnum(vlong, int, Type*); +void prcom(char *, Node*); +void newline(void); +void incind(void); +void decind(void); +int zeroind(void); +void restoreind(int); +void startcom(int); +void addcom(int); +void endcom(void); +int outcom(int); +int arrow(Sym*); + +/* limbo generating routines */ + +void pgen(int); +void epgen(int); +void ttgen(Type*); +void vtgen(Node*); +void etgen(Sym*); +void expgen(Node*); + +/* -m routines */ + +void newsec(int); + +void outpush(char*); +void outpop(int); +void outpush0(char*, Node*); +void outpop0(int); +void outpush2(char*, Node*); +void outpop2(int); +char* outmod(char*, int); + +/* miscellaneous */ + +int iscon(char*); +Node* ncopy(Node*); +void doasenum(Sym*); +Type *maxtype(Type*, Type*); + +void linit(void); +void sysinit(void); + +int ism(void); +int isb(void); +int dolog(void); + +int line(Node*); + +void output(long, int); +void usemod(Sym*, int); +void setmod(Sym*); + +int exists(char*); +int isconsym(Sym *); + +void clbegin(void); +void clend(void); + +int gfltconv(Fmt*); diff --git a/utils/c2l/cc.y b/utils/c2l/cc.y new file mode 100644 index 00000000..22dc6c0c --- /dev/null +++ b/utils/c2l/cc.y @@ -0,0 +1,1239 @@ +%{ +#include "cc.h" +%} +%union { + Node* node; + Sym* sym; + Type* type; + struct + { + Type* t; + char c; + } tycl; + struct + { + Type* t1; + Type* t2; + } tyty; + struct + { + char* s; + long l; + } sval; + long lval; + double dval; + vlong vval; +} +%type <sym> ltag +%type <lval> gctname cname gname tname +%type <lval> gctnlist zgnlist tnlist +%type <type> tlist etlist sbody complex +%type <tycl> types etypes +%type <node> zarglist arglist zcexpr +%type <node> name block stmnt cexpr expr xuexpr pexpr +%type <node> zelist elist adecl slist uexpr string lstring sstring slstring +%type <node> xdecor xdecor2 labels label ulstmnt +%type <node> adlist edecor tag qual qlist +%type <node> abdecor abdecor1 abdecor2 abdecor3 +%type <node> 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 <sym> LNAME LCTYPE LSTYPE +%token <dval> LFCONST LDCONST +%token <vval> LCHARACTER LCONST LLCONST LUCONST LULCONST LVLCONST LUVLCONST +%token <sval> 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 LUNION LUNSIGNED LWHILE +%token LVOID LENUM LSIGNED LCONSTNT LVOLATILE LSET LSIGNOF LVLONG +%% +prog: +| prog xdecl + +/* + * external declarator + */ +xdecl: + zctlist ';' + { + dodecl(xdecl, lastclass, lasttype, Z, 1); + } +| zctlist xdlist ';' +| zctlist xdecor + { + lastdcl = T; + dodecl(xdecl, lastclass, lasttype, $2, 0); + 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 + { + $6->blk = 0; + codgen($6, $2, lineno); + revertdcl(); + } + +xdlist: + xdecor + { + dodecl(xdecl, lastclass, lasttype, $1, 1); + } +| xdecor + { + $1 = dodecl(xdecl, lastclass, lasttype, $1, 0); + } + '=' init + { + $4 = doinit($1->sym, $1->type, 0L, $4); + $4 = new(ODAS, $1, $4); + $4->type = $1->type; + $4->lineno = $1->lineno; + vtgen($4); + } +| xdlist ',' xdlist + +xdecor: + xdecor2 +| '*' zgnlist xdecor + { + $$ = new(OIND, $3, Z); + $$->garb = simpleg($2); + } + +xdecor2: + tag +| '(' xdecor ')' + { + $$ = $2; + } +| xdecor2 '(' zarglist ')' + { + $$ = new(OFUNC, $1, $3); + /* outfun($$); */ + } +| xdecor2 '[' zexpr ']' + { + $$ = new(OARRAY, $1, $3); + } + +/* + * automatic declarator + */ +adecl: + { + $$ = Z; + } +| adecl ctlist ';' + { + $$ = dodecl(adecl, lastclass, lasttype, Z, 1); + 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, 1); + if($$->sym->class == CSTATIC) + $$ = Z; + } +| xdecor + { + $1 = dodecl(adecl, lastclass, lasttype, $1, 0); + } + '=' init + { + /* long w; */ + + /* w = $1->sym->type->width; */ + $$ = doinit($1->sym, $1->type, 0L, $4); + /* $$ = contig($1->sym, $$, w); */ + $$ = new(ODAS, $1, $$); + $$->type = $1->type; + $$->lineno = $1->lineno; + vtgen($$); + if($1->sym->class == CSTATIC) + $$ = Z; + } +| 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, 1); + } +| pdlist ',' pdlist + +/* + * structure element declarator + */ +edecl: + etlist + { + lasttype = $1; + } + zedlist ';' +| edecl etlist + { + lasttype = $2; + } + zedlist ';' + +zedlist: /* extension */ + { + lastfield = 0; + edecl(CXXX, lasttype, S); + } +| edlist + +edlist: + edecor + { + dodecl(edecl, CXXX, lasttype, $1, 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(ONUL, Z, Z); + $$->blk = 1; + } + +slist: + { + $$ = Z; + } +| slist stmnt + { + if($1 == Z) + $$ = $2; + else + $$ = new(OLIST, $1, $2); + } + +labels: + label +| labels label + { + $$ = new(OLIST, $1, $2); + } + +label: + LCASE expr ':' + { + $$ = new(OCASE, $2, Z); + $$->lineno = $2->lineno; + } +| LDEFAULT ':' + { + $$ = new(OCASE, Z, Z); + } +| LNAME ':' + { + $$ = new(OLABEL, dcllabel($1, 1), Z); + $1->lineno = lineno; + } + +stmnt: + error ';' + { + $$ = Z; + } +| ulstmnt +| labels ulstmnt + { + $$ = new(OLIST, $1, $2); + } + +ulstmnt: + zcexpr ';' + { + if($$ == Z) + $$ = new(ONUL, Z, Z); + $$->kind = KEXP; + } +| { + markdcl(); + } + block + { + revertdcl(); + $$ = $2; + } +| LIF '(' cexpr ')' stmnt + { + $$ = new(OIF, $3, new(OLIST, $5, Z)); + $$->lineno = $3->lineno; + $5->blk = 0; + } +| LIF '(' cexpr ')' stmnt LELSE stmnt + { + $$ = new(OIF, $3, new(OLIST, $5, $7)); + $$->lineno = $3->lineno; + $5->blk = $7->blk = 0; + } +| LFOR '(' zcexpr ';' zcexpr ';' zcexpr ')' stmnt + { + $$ = new(OFOR, new(OLIST, $5, new(OLIST, $3, $7)), $9); + if($3 != Z) + $$->lineno = $3->lineno; + else if($5 != Z) + $$->lineno = $5->lineno; + else if($7 != Z) + $$->lineno = $7->lineno; + else + $$->lineno = line($9); + $9->blk = 0; + } +| LWHILE '(' cexpr ')' stmnt + { + $$ = new(OWHILE, $3, $5); + $$->lineno = $3->lineno; + $5->blk = 0; + } +| LDO stmnt LWHILE '(' cexpr ')' ';' + { + $$ = new(ODWHILE, $5, $2); + $$->lineno = line($2); + $2->blk = 0; + } +| LRETURN zcexpr ';' + { + $$ = new(ORETURN, $2, Z); + $$->type = thisfn->link; + if($2 != Z) + $$->lineno = $2->lineno; + } +| LSWITCH '(' cexpr ')' stmnt + { + $$ = new(OSWITCH, $3, $5); + $$->lineno = $3->lineno; + $5->blk = 0; + } +| LBREAK ';' + { + $$ = new(OBREAK, Z, Z); + } +| LCONTINUE ';' + { + $$ = new(OCONTINUE, Z, Z); + } +| LGOTO LNAME ';' + { + $$ = new(OGOTO, dcllabel($2, 0), Z); + $2->lineno = lineno; + } +| LUSED '(' zelist ')' ';' + { + $$ = new(OUSED, $3, Z); + $$->lineno = line($3); + } +| LSET '(' zelist ')' ';' + { + $$ = new(OSET, $3, Z); + $$->lineno = line($3); + } + +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, 1); + $$->type = lastdcl; + } +| '(' tlist abdecor ')' '{' ilist '}' /* extension */ + { + $$ = new(OSTRUCT, $6, Z); + dodecl(NODECL, CXXX, $2, $3, 1); + $$->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, 1); + $$->type = lastdcl; + } +| LSIGNOF '(' tlist abdecor ')' + { + $$ = new(OSIGN, Z, Z); + dodecl(NODECL, CXXX, $3, $4, 1); + $$->type = lastdcl; + } +| pexpr '(' zelist ')' + { + $$ = new(OFUNC, $1, Z); + if($1->op == ONAME) + if($1->type == T) + dodecl(xdecl, CXXX, types[TINT], $$, 1); + $$->right = invert($3); + $$->kind = KEXP; + } +| pexpr '[' cexpr ']' + { + $$ = new(OARRIND, $1, $3); + } +| pexpr LMG ltag + { + $$ = new(ODOTIND, $1, Z); + $$->sym = $3; + } +| pexpr '.' ltag + { + $$ = new(ODOT, $1, Z); + $$->sym = $3; + } +| pexpr LPP + { + $$ = new(OPOSTINC, $1, Z); + } +| pexpr LMM + { + $$ = new(OPOSTDEC, $1, Z); + } +| name +| LCHARACTER + { + $$ = new(OCONST, Z, Z); + $$->type = types[TINT]; + $$->vconst = $1; + $$->kind = KCHR; + } +| LCONST + { + $$ = new(OCONST, Z, Z); + $$->type = types[TINT]; + $$->vconst = $1; + $$->kind = lastnumbase; + } +| LLCONST + { + $$ = new(OCONST, Z, Z); + $$->type = types[TLONG]; + $$->vconst = $1; + $$->kind = lastnumbase; + } +| LUCONST + { + $$ = new(OCONST, Z, Z); + $$->type = types[TUINT]; + $$->vconst = $1; + $$->kind = lastnumbase; + } +| LULCONST + { + $$ = new(OCONST, Z, Z); + $$->type = types[TULONG]; + $$->vconst = $1; + $$->kind = lastnumbase; + } +| LDCONST + { + $$ = new(OCONST, Z, Z); + $$->type = types[TDOUBLE]; + $$->fconst = $1; + $$->cstring = strdup(symb); + $$->kind = lastnumbase; + } +| LFCONST + { + $$ = new(OCONST, Z, Z); + $$->type = types[TFLOAT]; + $$->fconst = $1; + $$->cstring = strdup(symb); + $$->kind = lastnumbase; + } +| LVLCONST + { + $$ = new(OCONST, Z, Z); + $$->type = types[TVLONG]; + $$->vconst = $1; + $$->kind = lastnumbase; + } +| LUVLCONST + { + $$ = new(OCONST, Z, Z); + $$->type = types[TUVLONG]; + $$->vconst = $1; + $$->kind = lastnumbase; + } +| string +| lstring + +sstring: + LSTRING + { + $$ = new(OSTRING, Z, Z); + $$->type = typ(TARRAY, types[TCHAR]); + $$->type->width = $1.l + 1; + $$->cstring = $1.s; + $$->sym = symstring; + } + +string: + sstring + { + $$ = $1; + } +| string sstring + { + char *s; + int n1, n2; + + n1 = $1->type->width - 1; + n2 = $2->type->width - 1; + s = alloc(n1+n2+MAXALIGN); + + memcpy(s, $1->cstring, n1); + memcpy(s+n1, $2->cstring, n2); + s[n1+n2] = 0; + + $1->left = new(OCAT, ncopy($1), $2); + + $$ = $1; + $$->type->width += n2; + $$->cstring = s; + } + +slstring: + LLSTRING + { + $$ = new(OLSTRING, Z, Z); + $$->type = typ(TARRAY, types[TUSHORT]); + $$->type->width = $1.l + sizeof(ushort); + $$->rstring = (ushort*)$1.s; + $$->sym = symstring; + } + +lstring: + slstring + { + $$ = $1; + } +| lstring slstring + { + char *s; + int n1, n2; + + n1 = $1->type->width - sizeof(ushort); + n2 = $2->type->width - sizeof(ushort); + s = alloc(n1+n2+MAXALIGN); + + memcpy(s, $1->rstring, n1); + memcpy(s+n1, $2->rstring, n2); + *(ushort*)(s+n1+n2) = 0; + + $1->left = new(OCAT, ncopy($1), $2); + + $$ = $1; + $$->type->width += n2; + $$->rstring = (ushort*)s; + } + +zelist: + { + $$ = Z; + } +| elist + +elist: + expr +| elist ',' elist + { + $$ = new(OLIST, $1, $3); + } + +sbody: + '{' + { + $<tyty>$.t1 = strf; + $<tyty>$.t2 = strl; + strf = T; + strl = T; + lastbit = 0; + firstbit = 1; + } + edecl '}' + { + $$ = strf; + strf = $<tyty>2.t1; + strl = $<tyty>2.t2; + } + +zctlist: + { + lastclass = CXXX; + lasttype = types[TINT]; + } +| ctlist + +etypes: + complex + { + $$.t = $1; + $$.c = CXXX; + } +| tnlist + { + $$.t = simplet($1); + $$.c = simplec($1); + } + +types: + complex + { + $$.t = $1; + $$.c = CXXX; + } +| complex gctnlist + { + $$.t = $1; + $$.c = simplec($2); + if($2 & ~BCLASS & ~BGARB) + diag(Z, "illegal combination of types 1: %Q/%T", $2, $1); + } +| gctnlist + { + $$.t = simplet($1); + $$.c = simplec($1); + $$.t = garbt($$.t, $1); + } +| gctnlist complex + { + $$.t = $2; + $$.c = simplec($1); + $$.t = garbt($$.t, $1); + if($1 & ~BCLASS & ~BGARB) + diag(Z, "illegal combination of types 2: %Q/%T", $1, $2); + } +| gctnlist complex gctnlist + { + $$.t = $2; + $$.c = simplec($1|$3); + $$.t = garbt($$.t, $1|$3); + if(($1|$3) & ~BCLASS & ~BGARB || $3 & BCLASS) + diag(Z, "illegal combination of types 3: %Q/%T/%Q", $1, $2, $3); + } + +etlist: + zgnlist etypes + { + $$ = $2.t; + if($2.c != CXXX) + diag(Z, "illegal combination of class 4: %s", cnames[$2.c]); + $$ = garbt($$, $1); + } + +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; + $2->lineno = lineno; + } +| LSTRUCT ltag + { + dotag($2, TSTRUCT, autobn); + saveline = $2->lineno = lineno; + } + sbody + { + $$ = $2->suetag; + if($$->link != T) + diag(Z, "redeclare tag: %s", $2->name); + $$->link = $4; + $$->lineno = saveline; + suallign($$); + } +| LSTRUCT + { + saveline = lineno; + } + sbody + { + char buf[128]; + + taggen++; + sprint(symb, "%s_adt_%d", outmod(buf, -1), taggen); + $$ = dotag(lookup(), TSTRUCT, autobn); + $$->link = $3; + $$->lineno = saveline; + lookup()->lineno = saveline; + suallign($$); + } +| LUNION ltag + { + dotag($2, TUNION, 0); + $$ = $2->suetag; + $2->lineno = lineno; + } +| LUNION ltag + { + dotag($2, TUNION, autobn); + saveline = $2->lineno = lineno; + } + sbody + { + $$ = $2->suetag; + if($$->link != T) + diag(Z, "redeclare tag: %s", $2->name); + $$->link = $4; + $$->lineno = saveline; + suallign($$); + } +| LUNION + { + saveline = lineno; + } + sbody + { + char buf[128]; + + taggen++; + sprint(symb, "%s_adt_%d", outmod(buf, -1), taggen); + $$ = dotag(lookup(), TUNION, autobn); + $$->link = $3; + $$->lineno = saveline; + lookup()->lineno = saveline; + suallign($$); + } +| LENUM ltag + { + dotag($2, TENUM, 0); + $$ = $2->suetag; + if($$->link == T) + $$->link = types[TINT]; + $$ = $$->link; + $2->lineno = lineno; + } +| LENUM ltag + { + dotag($2, TENUM, autobn); + $2->lineno = lineno; + } + '{' + { + 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; + etgen(nil); + } +| LENUM '{' + { + en.tenum = T; + en.cenum = T; + } + enum '}' + { + $$ = en.tenum; + etgen(nil); + } +| LCTYPE + { + $$ = tcopy($1->type); + } +| LSTYPE + { + $$ = tcopy($1->type); + } + +tnlist: + tname +| tnlist tname + { + $$ = typebitor($1, $2); + } + +gctnlist: + gctname +| gctnlist gctname + { + $$ = typebitor($1, $2); + } + +zgnlist: + { + $$ = 0; + } +| zgnlist gname + { + $$ = typebitor($1, $2); + } + +gctname: + tname +| gname +| cname + +enum: + LNAME + { + doenum($1, Z); + $1->lineno = lineno; + } +| LNAME '=' expr + { + doenum($1, $3); + $1->lineno = lineno; + } +| enum ',' +| enum ',' enum + +tname: /* type words */ + LCHAR { $$ = BCHAR; } +| LSHORT { $$ = BSHORT; } +| LINT { $$ = BINT; } +| LLONG { $$ = BLONG; } +| LSIGNED { $$ = BSIGNED; } +| LUNSIGNED { $$ = BUNSIGNED; } +| LFLOAT { $$ = BFLOAT; } +| LDOUBLE { $$ = BDOUBLE; } +| LVOID { $$ = BVOID; } +| LVLONG { $$ = BVLONG|BLONG; } + +cname: /* class words */ + LAUTO { $$ = BAUTO; } +| LSTATIC { $$ = BSTATIC; } +| LEXTERN { $$ = BEXTERN; } +| LTYPEDEF { $$ = BTYPEDEF; } +| LREGISTER { $$ = BREGISTER; } + +gname: + LCONSTNT { $$ = BCONSTNT; } +| LVOLATILE { $$ = BVOLATILE; } + +name: + LNAME + { + $$ = new(ONAME, Z, Z); + if($1->class == CLOCAL) + $1 = mkstatic($1); + $$->sym = $1; + $$->type = $1->type; + } +tag: + ltag + { + $$ = new(ONAME, Z, Z); + $$->sym = $1; + $$->type = $1->type; + } +ltag: + LNAME +| LCTYPE +| LSTYPE + +%% diff --git a/utils/c2l/com.c b/utils/c2l/com.c new file mode 100644 index 00000000..283c2ae9 --- /dev/null +++ b/utils/c2l/com.c @@ -0,0 +1,918 @@ +#include "cc.h" + +void +complex(Node *n) +{ + + if(n == Z) + return; + + nearln = n->lineno; + if(tcom(n)) + return; + ccom(n); + acom(n); +} + +/* + * 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(); + } + 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(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: + case OASD: + 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; + 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; + typeext1(l->type, r); + if(tlvalue(l) || 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; + typeext1(l->type, r); + if(tlvalue(l) || 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) || 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) || 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) || 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; + 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; + 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(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(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(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(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(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(tcompat(n, l->type, r->type, tand)) + goto bad; + arith(n, 1); + if(typeu[n->type->etype]) + n->op = OLMOD; + break; + + case ONOT: + if(tcom(l)) + goto bad; + if(tcompat(n, T, l->type, tnot)) + goto bad; + n->type = types[TINT]; + break; + + case OPOS: + case ONEG: + case OCOM: + if(tcom(l)) + goto bad; + n->type = l->type; + break; + + case ONUL: + break; + + case OIOTA: + n->type = types[TINT]; + break; + + case ODAS: + n->type = n->left->type; + 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->right = ncopy(n); + 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->right = ncopy(n); + 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(1) + 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) { + if(n->sym->tenum->etype == TIND){ + /* n->op = OSTRING; */ + n->type = n->sym->tenum; + /* n->cstring = n->sym->sconst; */ + break; + } + n->left = ncopy(n); + n->op = OCONST; + n->type = n->sym->tenum; + if(!typefd[n->type->etype]) + n->vconst = n->sym->vconst; + else{ + n->fconst = n->sym->fconst; + n->cstring = n->sym->cstring; + } + break; + } + break; + + case OLSTRING: + case OSTRING: + case OCONST: + break; + + case ODOT: + if(tcom(l)) + goto bad; + if(tcompat(n, T, l->type, tdot)) + goto bad; + if(tcomd(n, l->type)) + goto bad; + break; + + case ODOTIND: + if(tcom(l)) + goto bad; + if(tcompat(n, T, l->type, tindir)) + goto bad; + if(tcompat(n, T, l->type->link, tdot)) + goto bad; + if(tcomd(n, l->type->link)) + goto bad; + break; + + case OARRIND: + if(tcom(l)) + goto bad; + if(tcompat(n, T, l->type, tindir)) + goto bad; + n->type = l->type->link; + if(tcom(r)) + 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 = typ1(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; + 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(n->type->etype == TARRAY) + n->type = typ1(TIND, n->type->link); + return 0; + 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->type = typ1(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]; */ + t = n->type; + break; + + case TUCHAR: + case TUSHORT: + /* t = types[TUINT]; */ + t = n->type; + break; + + case TFLOAT: + /* t = types[TDOUBLE]; */ + t = n->type; + } + } + 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; + } + return 0; +} + +int +tcomd(Node *n, Type *t) +{ + long o; + + o = 0; + /* t = n->left->type; */ + for(;;) { + t = dotsearch(n->sym, t->link, n); + if(t == T) { + diag(n, "not a member of struct/union: %F", n); + return 1; + } + o += t->offset; + if(t->sym == n->sym) + break; + if(sametype(t, n->sym->type)) + break; + } + n->type = t; + 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(0) { + 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; + + if(n == Z) + return; + l = n->left; + r = n->right; + switch(n->op) { + + case OAS: + case OASD: + 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); + 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); + ccom(r); + 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; + + 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); + } +} diff --git a/utils/c2l/com64.c b/utils/c2l/com64.c new file mode 100644 index 00000000..9a193ef3 --- /dev/null +++ b/utils/c2l/com64.c @@ -0,0 +1,52 @@ +#include "cc.h" + +/* + * this is machine depend, but it is totally + * common on all of the 64-bit symulating machines. + */ + +/* + * 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; +} diff --git a/utils/c2l/dcl.c b/utils/c2l/dcl.c new file mode 100644 index 00000000..6fb6977a --- /dev/null +++ b/utils/c2l/dcl.c @@ -0,0 +1,1387 @@ +#include "cc.h" + +Node* +dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n, int gen) +{ + 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; + t->nwidth = n1->left; + } + 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; + acidvar(s); + if(gen) + vtgen(n); + 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 = typ(TXXX, 0); + *tx = *t; + tx->link = tl; + return tx; + } + return t; +} + +Node* +doinit(Sym *s, Type *t, long o, Node *a) +{ + Node *n, *reta; + + if(t == T) + return Z; + if(s->class == CEXTERN) + s->class = CGLOBL; + if(0) { + 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; + + reta = a; + init1(s, t, o, 0); + if(initlist != Z) + diag(initlist, "more initializers than structure: %s", + s->name); + initlist = n; + + return reta; +} + +/* + * 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, *n; + + a = initlist; + n = Z; + + if(a == Z) + return a; + if(a->op == OLIST) { + n = a->right; + a = a->left; + } + 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; +} + +void +init1(Sym *s, Type *t, long o, int exflag) +{ + Node *a, *r, nod; + Type *t1; + long e, w, so, mw; + + a = peekinit(); + if(a == Z) + return; + + if(0) { + print("t = %T; o = %ld; n = %s\n", t, o, s->name); + prtree(a, "init1 value"); + } + + if(exflag && a->op == OINIT){ + doinit(s, t, o, nextinit()); + return; + } + + switch(t->etype) { + default: + diag(Z, "unknown type in initialization: %T to: %s", t, s->name); + return; + + 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; + + a = nextinit(); + if(a == Z) + return; + + if(t->nbits) + diag(Z, "cannot initialize bitfields"); + if(0 && s->class == CAUTO) + return; + + complex(a); + if(a->type == T) + return; + + 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; + } + if(vconst(a) == 0) + return; + return; + } + if(t->etype == TIND) { + while(a->op == OCAST) { + warn(a, "CAST in initialization ignored"); + a = a->left; + } + if(0 && !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; +*/ + return; + } + + while(a->op == OCAST) + a = a->left; + if(a->op == OADDR) { + warn(a, "initialize pointer to an integer: %s", s->name); + /* a = a->left; */ + return; + } + /* diag(a, "initializer is not a constant: %s", s->name); */ + return; + + 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(t->width <= 0) + t->width = w*(so-1); + USED(a); + return; + } + + mw = -w; + 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; + } + 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; + init1(s, t->link, o+so, 1); + e++; + } + if(t->width == 0) + t->width = mw+w; + return; + + 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; + } + + 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(); + } + init1(s, t1, o+t1->offset, 1); + 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; + } +} + +/* +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); + ttgen(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); + ttgen(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: + if(n->type == T) + n->type = n->sym->type; + t = typ(TXXX, T); + *t = *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); + 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; +} + +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, 1); + 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, 1); + 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) { + autoffset = align(autoffset, s->type, Aarg1); + s->offset = autoffset; + autoffset = align(autoffset, s->type, Aarg2); + } else + dodecl(pdecl, CXXX, types[TINT], n, 1); + 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; + + 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; + free(d); + return Z; + + case DAUTO: + if(0) { + 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); + } + s->type = d->type; + s->class = d->class; + s->offset = d->offset; + s->block = d->block; + s->lineno = d->lineno; + break; + + case DSUE: + s->suetag = d->type; + s->sueblock = d->block; + s->lineno = d->lineno; + break; + + case DLABEL: + if(0 && s->label) + warn(s->label, "label declared and not used \"%s\"", s->name); + s->label = Z; + s->lineno = d->lineno; + break; + } + free(d); + } + return Z; +} + +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; + n = dodecl(NODECL, CXXX, n->type, n->left, 1); + t = typ(TXXX, T); + if(lastdcl != T) + *t = *paramconv(lastdcl, 1); + if(n != Z && n->op == ONAME) + t->sym = n->sym; + 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) +{ + static Decl zdecl; + Decl *d; + + d = alloc(sizeof(*d)); + *d = zdecl; + 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->lineno = s->lineno; + 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] || et == TTUPLE) { + 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 || 1) && 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; + d->lineno = s->lineno; + 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(0) + diag(Z, "label reused: %s", s->name); + } + return n; + } + + d = push(); + d->sym = s; + d->val = DLABEL; + d->lineno = s->lineno; + dclstack = d->link; + + d1 = *firstdcl; + *firstdcl = *d; + *d = d1; + + firstdcl->link = d; + firstdcl = d; + + n = new(OXXX, Z, Z); + n->sym = s; + s->label = n; + return n; +} + +Type* +paramconv(Type *t, int f) +{ + f = 1; + 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; + } + switch(c) { + case CAUTO: + autoffset = align(autoffset, t, Aaut3); + s->offset = -autoffset; + break; + + case CPARAM: + autoffset = align(autoffset, t, Aarg1); + if(s) + s->offset = autoffset; + autoffset = align(autoffset, t, Aarg2); + break; + } + if(s) + s->lineno = lineno; +} + +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); + if(s) + s->lineno = lineno; +} + +void +xdecl(int c, Type *t, Sym *s) +{ + long o; + + o = 0; + if(c == CEXREG) + c = CEXTERN; + if(c == CXXX) { + c = CGLOBL; + if(s->class == CEXTERN) + s->class = c; + } + if(c == CEXTERN) + if(s->class == CGLOBL) + c = CGLOBL; + if(c == CAUTO) { + diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]); + c = CEXTERN; + } + 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; %s %T\n", cnames[c], t, cnames[s->class], s->type); + } + 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) +{ + long l; + 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 = typ(TXXX, T); + l = t->lineno; + *t = *t1; + t->lineno = l; + 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) +{ + int k = KDEC; + Node *nc; + + nc = Z; + if(n) { + k = n->kind; + complex(n); + if(n->op != OCONST && n->op != OSTRING && n->op != OLSTRING) { + diag(n, "enum not a constant: %s", s->name); + return; + } + nc = n->left; + 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(s->tenum->etype == TIND){ /* string */ + nc = n; + s->tenum = n->type; + } + else if(!typefd[s->tenum->etype]) { + s->vconst = convvtox(en.lastenum, s->tenum->etype); + en.lastenum++; + s->tenum = types[TINT]; + } else { + s->fconst = en.floatenum; + if(n) + s->cstring = n->cstring; + else + s->cstring = nil; + en.floatenum++; + s->tenum = types[TDOUBLE]; + } + s->nconst = nc; + + acidvar(s); + s->kind = k; + etgen(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: + return; + + case OCONST: + case OSTRING: + case OLSTRING: + case OINDREG: + case OREGISTER: + return; + } +} diff --git a/utils/c2l/dpchk.c b/utils/c2l/dpchk.c new file mode 100644 index 00000000..78865cb8 --- /dev/null +++ b/utils/c2l/dpchk.c @@ -0,0 +1,392 @@ +#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[256]; +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 c, f; + char *fmt; + + fmt = fmtbuf; + flag = zbits; + nstar = 0; + while(c = *s++) { + *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; + + 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; + + if(1) + goto out; + s = getsym(); + if(s && strcmp(s->name, "argpos") == 0) + goto ckpos; + if(s && strcmp(s->name, "type") == 0) + goto cktype; + 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; + +cktype: +/*#pragma varargck type O int*/ + c = getnsc(); + if(c != '"') + goto bad; + t = fmtbuf; + for(;;) { + c = getc(); + if(c == ' ' || c == '\n') + goto bad; + if(c == '"') + break; + *t++ = c; + } + *t = 0; + t = strdup(fmtbuf); + s = getsym(); + if(s == S) + goto bad; + c = getnsc(); + unget(c); + if(c == '*') + newprot(s, typ(TIND, s->type), t); + else + newprot(s, s->type, 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, int pos) +{ + Node *a, *n; + Bits flag; + Tprot *l; + + if(1) + 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); + pos++; + 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, arg %d", + fmtbuf, a->type, pos); + } + 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); + pos++; + 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)) + if(beq(flag, l->flag)) + goto loop; + warn(nn, "format mismatch %s %T, arg %d", fmtbuf, a->type, pos); + 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, l->param); +} + +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(0) + 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) { + hjdickflg = atoi(s->name+1); + if(strcmp(s->name, "on") == 0 || + strcmp(s->name, "yes") == 0 || + strcmp(s->name, "dick") == 0) + fproundflg = 1; + } + while(getnsc() != '\n') + ; + if(0) + if(fproundflg) + print("%4ld: fproundflg %d\n", lineno, fproundflg); + else + print("%4ld: fproundflg off\n", lineno); +} diff --git a/utils/c2l/lex.c b/utils/c2l/lex.c new file mode 100644 index 00000000..5701dd99 --- /dev/null +++ b/utils/c2l/lex.c @@ -0,0 +1,1675 @@ +#include "cc.h" +#include "y.tab.h" + +#ifndef CPP +#define CPP "/bin/cpp" +#endif + +static int ansip; + +void +main(int argc, char *argv[]) +{ + char *defs[50], *p; + int nproc, nout, status, i, c, ndef; + + tinit(); + cinit(); + ginit(); + arginit(); + + tufield = simplet((1L<<tfield->etype) | BUNSIGNED); + ndef = 0; + include[ninclude++] = "."; + strings = 1; + passes = 1; + + ARGBEGIN { + default: + break; + + case 'p': + ansip = 1; + break; + + case 'D': + p = ARGF(); + if(p) { + defs[ndef++] = p; + dodefine(p); + } + break; + + case 'I': + p = ARGF(); + setinclude(p); + break; + + case 'm': + domod = 1; + break; + + case 'i': + doinc = 1; + break; + + case 'l': + doloc = 1; + break; + + case 'c': + justcode = 1; + break; + + case 'v': + comm = 1; + break; + + case 's': + strings = 0; + break; + + case 'S': + strings = 2; + break; + + case 'M': + inmain = 1; + break; + + case 'q': + passes = 0; + break; + + case 'a': + doaddr = 1; + break; + + case 'A': + doaddr = 1; + doalladdr = 1; + break; + + } ARGEND + + if(doinc) + domod = doloc = 0; + + linit(); + + if(argc != 1) { + print("usage: c2l [-options] file\n"); + 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[200], incfile[20]; + char *p, *av[100], opt[256]; + int i, c, fd[2]; + + strcpy(ofile, file); + p = utfrrune(ofile, pathchar()); + if(p) { + *p++ = 0; + include[0] = strdup(ofile); + } else + p = ofile; + + USED(p); + if(p = getenv("INCLUDE")) { + setinclude(p); + } else { + if(systemtype(Plan9)) { + sprint(incfile, "/%s/include", thestring); + setinclude(strdup(incfile)); + setinclude("/sys/include"); + } + } + newio(); + + /* Use an ANSI preprocessor */ + if(ansip) { + if(systemtype(Windows)) { + diag(Z, "-p option not supported on windows"); + 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; + 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(0) { + 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); + } + + clbegin(); + yyparse(); + clend(); + newsec(0); + return nerrors; +} + +void +errorexit(void) +{ + 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(0) + 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("c2l: %r: %s", s); + errorexit(); + } + fi.c = 0; + linehist(s, 0); + outpush(s); +} + +Sym* +slookup(char *s) +{ + + strcpy(symb, s); + return lookup(); +} + +Sym* +lookup(void) +{ + static Sym zsym; + 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 = zsym; + 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->type = T; + s->suetag = T; + s->class = CXXX; + s->lname = s->mod = nil; + s->lineno = lineno; + s->tenum = T; +} + +#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, +}; + +static int ypeek = 0; + +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, "\"<string>\""); + 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<string>\""); + 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 LCHARACTER; + + case '/': + c1 = GETC(); + if(c1 == '*') { + startcom(lineno); + for(;;) { + c = getr(); + if(c == '*'){ + while(c == '*') { + c = getr(); + if(c == '/'){ + endcom(); + goto l0; + } + addcom('*'); + } + addcom(c); + } + else + addcom(c); + if(c == EOF) { + yyerror("eof in comment"); + errorexit(); + } + } + } + if(c1 == '/') { + startcom(lineno); + for(;;) { + c = getr(); + if(c == '\n'){ + endcom(); + goto l0; + } + addcom(c); + 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(0) + print("%L: %s\n", lineno, symb); + peekc = c; + s = lookup(); + if(s->macro && !ypeek) { + 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; + } + /* outpush(nil); */ + goto l0; + } + yylval.sym = s; + if(s->class == CTYPEDEF) { + if(s->type && typesu[s->type->etype]) + return LCTYPE; + return LSTYPE; + } + return s->lexical; + +tnum: + lastnumbase = KDEC; + 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'){ + lastnumbase = KHEX; + 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; + } + } + else + lastnumbase = KOCT; + if(c < '0' || c > '7'){ + lastnumbase = KDEC; + 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; + if(mpatof(symb, &yylval.dval)) { + yyerror("overflow in float constant"); + yylval.dval = 0; + } + if(c1 & Numflt) + return LFCONST; + return LDCONST; +} + +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; c<i; c++) + print(" %.2x", *(uchar*)(str+c)); + print("\n"); + } + return rune; +} + +int +getnsc(void) +{ + int c; + + if(peekc != IGN) { + c = peekc; + peekc = IGN; + } else + c = GETC(); + for(;;) { + if(!isspace(c)) + return c; + if(c == '\n') { + lineno++; + return c; + } + c = GETC(); + } + return 0; +} + +void +unget(int c) +{ + + peekc = c; + if(c == '\n') + lineno--; +} + +long +escchar(long e, int longflg, int escflg) +{ + long c, l; + int i; + +loop: + c = getr(); + if(c == '\n') { + yyerror("newline in string"); + return EOF; + } + if(c != '\\') { + if(c == e) + c = EOF; + return c; + } + c = getr(); + if(c == 'x') { + /* + * note this is not ansi, + * supposed to only accept 2 hex + */ + i = 2; + if(longflg) + i = 4; + l = 0; + for(; i>0; 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': return '\n'; + case 't': return '\t'; + case 'b': return '\b'; + case 'r': return '\r'; + case 'f': return '\f'; + case 'a': return '\a'; + case 'v': return '\v'; + } + return c; +} + +struct +{ + char *name; + ushort lexical; + ushort type; +} itab[] = +{ + "auto", LAUTO, 0, + "break", LBREAK, 0, + "case", LCASE, 0, + "char", LCHAR, TCHAR, + "const", LCONSTNT, 0, + "continue", LCONTINUE, 0, + "default", LDEFAULT, 0, + "do", LDO, 0, + "double", LDOUBLE, TDOUBLE, + "else", LELSE, 0, + "enum", LENUM, 0, + "extern", LEXTERN, 0, + "float", LFLOAT, TFLOAT, + "for", LFOR, 0, + "goto", LGOTO, 0, + "if", LIF, 0, + "int", LINT, TINT, + "long", LLONG, TLONG, + "register", LREGISTER, 0, + "return", LRETURN, 0, + "SET", LSET, 0, + "short", LSHORT, TSHORT, + "signed", LSIGNED, 0, + "signof", LSIGNOF, 0, + "sizeof", LSIZEOF, 0, + "static", LSTATIC, 0, + "struct", LSTRUCT, 0, + "switch", LSWITCH, 0, + "typedef", LTYPEDEF, 0, + "union", LUNION, 0, + "unsigned", LUNSIGNED, 0, + "USED", LUSED, 0, + "void", LVOID, TVOID, + "volatile", LVOLATILE, 0, + "while", LWHILE, 0, + "__int64", LVLONG, TVLONG, /* for windows */ + 0 +}; + +static char *litab[] = +{ + "adt", + "alt", + "array", + "big", + "break", + "byte", + "case", + "chan", + "con", + "continue", + "cyclic", + "do", + "else", + "exit", + "fn", + "for", + "hd", + "if", + "implement", + "import", + "include", + "int", + "len", + "list", + "load", + "module", + "nil", + "of", + "or", + "pick", + "real", + "ref", + "return", + "self", + "spawn", + "string", + "tagof", + "tl", + "to", + "type", + "while", + 0, +}; + +void +cinit(void) +{ + Sym *s; + int i; + Type *t; + + nerrors = 0; + lineno = 1; + iostack = I; + iofree = I; + peekc = IGN; + nhunk = 0; + + types[TXXX] = T; + types[TCHAR] = typ(TCHAR, T); + types[TUCHAR] = typ(TUCHAR, T); + types[TSHORT] = typ(TSHORT, T); + types[TUSHORT] = typ(TUSHORT, T); + types[TINT] = typ(TINT, T); + types[TUINT] = typ(TUINT, T); + types[TLONG] = typ(TLONG, T); + types[TULONG] = typ(TULONG, T); + types[TVLONG] = typ(TVLONG, T); + types[TUVLONG] = typ(TUVLONG, T); + types[TFLOAT] = typ(TFLOAT, T); + types[TDOUBLE] = typ(TDOUBLE, T); + types[TVOID] = typ(TVOID, T); + types[TENUM] = typ(TENUM, T); + types[TFUNC] = typ(TFUNC, types[TINT]); + types[TIND] = typ(TIND, types[TVOID]); + stringtype = typ(TSTRING, T); + fdtype = typ(TSTRUCT, typ(TFD, T)); + fdtype->width = 4; + pfdtype = typ(TIND, fdtype); + + for(i=0; i<NHASH; i++) + hash[i] = S; + for(i=0; itab[i].name; i++) { + s = slookup(itab[i].name); + s->lexical = itab[i].lexical; + if(itab[i].type != 0) + s->type = types[itab[i].type]; + } + for(i=0; litab[i]; i++){ + s = slookup(litab[i]); + s->lkw = 1; + } + blockno = 0; + autobn = 0; + autoffset = 0; + + t = typ(TARRAY, types[TCHAR]); + t->width = 0; + symstring = slookup(".string"); + symstring->class = CSTATIC; + symstring->type = t; + + t = typ(TARRAY, types[TCHAR]); + t->width = 0; + + nodproto = new(OPROTO, Z, Z); + dclstack = D; + + pathname = allocn(pathname, 0, 100); + if(mygetwd(pathname, 99) == 0) { + pathname = allocn(pathname, 100, 900); + if(mygetwd(pathname, 999) == 0) + strcpy(pathname, "/???"); + } + + fmtinstall('f', gfltconv); + fmtinstall('F', gfltconv); + fmtinstall('g', gfltconv); + fmtinstall('G', gfltconv); + fmtinstall('e', gfltconv); + fmtinstall('E', gfltconv); + + fmtinstall('O', Oconv); + fmtinstall('T', Tconv); + fmtinstall('F', FNconv); + fmtinstall('L', Lconv); + fmtinstall('Q', Qconv); + fmtinstall('|', VBconv); +} + +int +filbuf(void) +{ + Io *i; + +loop: + i = iostack; + if(i == I) + return EOF; + if(i->f < 0) + goto pop; + fi.c = read(i->f, i->b, BUFSIZ) - 1; + if(fi.c < 0) { + close(i->f); + linehist(0, 0); + goto pop; + } + fi.p = i->b + 1; + return i->b[0] & 0xff; + +pop: + if(i->f >= 0) + outpop(lineno); + iostack = i->link; + i->link = iofree; + iofree = i; + i = iostack; + if(i == I) + return EOF; + fi.p = i->p; + fi.c = i->c; + if(--fi.c < 0) + goto loop; + return *fi.p++ & 0xff; +} + +int +Oconv(Fmt *fp) +{ + int a; + char s[STRINGSZ]; + + a = va_arg(fp->args, int); + if(a < OXXX || a > OEND) { + sprint(s, "***badO %d***", a); + fmtstrcpy(fp, s); + } else + fmtstrcpy(fp, onames[a]); + return 0; +} + +int +Lconv(Fmt *fp) +{ + char str[STRINGSZ], s[STRINGSZ]; + Hist *h; + struct + { + Hist* incl; /* start of this include file */ + long idel; /* delta line number to apply to include */ + Hist* line; /* start of this #line directive */ + long ldel; /* delta line number to apply to #line */ + } a[HISTSZ]; + long l, d; + int i, n; + + l = va_arg(fp->args, long); + n = 0; + for(h = hist; h != H; h = h->link) { + if(l < h->line) + break; + if(h->name) { + if(h->offset != 0) { /* #line directive, not #pragma */ + if(n > 0 && n < HISTSZ && h->offset >= 0) { + a[n-1].line = h; + a[n-1].ldel = h->line - h->offset + 1; + } + } else { + if(n < HISTSZ) { /* beginning of file */ + a[n].incl = h; + a[n].idel = h->line; + a[n].line = 0; + } + n++; + } + continue; + } + n--; + if(n > 0 && n < HISTSZ) { + d = h->line - a[n].incl->line; + a[n-1].ldel += d; + a[n-1].idel += d; + } + } + if(n > HISTSZ) + n = HISTSZ; + str[0] = 0; + for(i=n-1; i>=0; i--) { + if(i != n-1) { + if(fp->flags & ~(FmtWidth|FmtPrec)) /* BUG ROB - was f3 */ + break; + strcat(str, " "); + } + if(a[i].line) + snprint(s, STRINGSZ, "%s:%ld[%s:%ld]", + a[i].line->name, l-a[i].ldel+1, + a[i].incl->name, l-a[i].idel+1); + else + snprint(s, STRINGSZ, "%s:%ld", + a[i].incl->name, l-a[i].idel+1); + if(strlen(s)+strlen(str) >= STRINGSZ-10) + break; + strcat(str, s); + l = a[i].incl->line - 1; /* now print out start of this file */ + } + if(n == 0) + strcat(str, "<eof>"); + fmtstrcpy(fp, str); + return 0; +} + +int +Tconv(Fmt *fp) +{ + char str[STRINGSZ+20], s[STRINGSZ+20]; + Type *t, *t1; + int et; + long n; + + str[0] = 0; + for(t = va_arg(fp->args, Type*); t != T; t = t->link) { + et = t->etype; + if(str[0]) + strcat(str, " "); + if(t->garb) { + sprint(s, "%s ", gnames[t->garb]); + if(strlen(str) + strlen(s) < STRINGSZ) + strcat(str, s); + } + sprint(s, "%s", tnames[et]); + if(strlen(str) + strlen(s) < STRINGSZ) + strcat(str, s); + if(et == TFUNC && (t1 = t->down)) { + sprint(s, "(%T", t1); + if(strlen(str) + strlen(s) < STRINGSZ) + strcat(str, s); + while(t1 = t1->down) { + sprint(s, ", %T", t1); + if(strlen(str) + strlen(s) < STRINGSZ) + strcat(str, s); + } + if(strlen(str) + strlen(s) < STRINGSZ) + strcat(str, ")"); + } + if(et == TARRAY) { + n = t->width; + if(t->link && t->link->width) + n /= t->link->width; + sprint(s, "[%ld]", n); + if(strlen(str) + strlen(s) < STRINGSZ) + strcat(str, s); + } + if(t->nbits) { + sprint(s, " %d:%d", t->shift, t->nbits); + if(strlen(str) + strlen(s) < STRINGSZ) + strcat(str, s); + } + if(typesu[et]) { + if(t->tag) { + strcat(str, " "); + if(strlen(str) + strlen(t->tag->name) < STRINGSZ) + strcat(str, t->tag->name); + } else + strcat(str, " {}"); + break; + } + } + fmtstrcpy(fp, str); + return 0; +} + +int +FNconv(Fmt *fp) +{ + char *str; + Node *n; + + n = va_arg(fp->args, Node*); + str = "<indirect>"; + if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM)) + str = n->sym->name; + fmtstrcpy(fp, str); + return 0; +} + +int +Qconv(Fmt *fp) +{ + char str[STRINGSZ+20], *s; + long b; + int i; + + str[0] = 0; + for(b = va_arg(fp->args, long); b;) { + i = bitno(b); + if(str[0]) + strcat(str, " "); + s = qnames[i]; + if(strlen(str) + strlen(s) >= STRINGSZ) + break; + strcat(str, s); + b &= ~(1L << i); + } + fmtstrcpy(fp, str); + return 0; +} + +int +VBconv(Fmt *fp) +{ + char str[STRINGSZ]; + int i, n, t, pc; + + n = va_arg(fp->args, int); + pc = 0; /*was printcol */ + i = 0; + while(pc < n) { + t = (pc+8) & ~7; + if(t <= n) { + str[i++] = '\t'; + pc = t; + continue; + } + str[i++] = ' '; + pc++; + } + str[i] = 0; + fmtstrcpy(fp, str); + return 0; +} + +/* + * real allocs + */ +void* +alloc(long n) +{ + void *p; + + while((ulong)hunk & MAXALIGN) { + hunk++; + nhunk--; + } + while(nhunk < n) + gethunk(); + p = hunk; + nhunk -= n; + hunk += n; + return p; +} + +void* +allocn(void *p, long on, long n) +{ + void *q; + + q = (uchar*)p + on; + if(q != hunk || nhunk < n) { + while(nhunk < on+n) + gethunk(); + memmove(hunk, p, on); + p = hunk; + hunk += on; + nhunk -= on; + } + hunk += n; + nhunk -= n; + return p; +} + +void +setinclude(char *p) +{ + int i; + char *e; + + while(*p != 0) { + e = strchr(p, ' '); + if(e != 0) + *e = '\0'; + + for(i=1; i < ninclude; i++) + if(strcmp(p, include[i]) == 0) + break; + + if(i >= ninclude) + include[ninclude++] = p; + + if(ninclude > nelem(include)) { + diag(Z, "ninclude too small %d", nelem(include)); + exits("ninclude"); + } + + if(e == 0) + break; + p = e+1; + } +} + +static void +doio(char *s) +{ + char *cp; + + newio(); + cp = ionext->b; + strcpy(cp, s); + 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; + } +} + +static void +undoio(void) +{ + Io *i; + + i = iostack; + iostack = i->link; + i->link = iofree; + iofree = i; + i = iostack; + fi.p = i->p; + fi.c = i->c; +} + +/* rm // comment from a string */ +static void +slashslash(char *s) +{ + for( ; *s != '\0'; s++) + if(*s == '/' && s[1] == '/'){ + *s = '\0'; + return; + } +} + +int +iscon(char *str) +{ + int olineno, opeekc, con, tok, t; + Sym *s; + char buf[1024]; + + if(str == nil || *str == 0 || strlen(str)+16 > 1024) + return 0; + ypeek = 1; + olineno = lineno; + opeekc = peekc; + peekc = IGN; + strcpy(buf, str); + slashslash(buf); + strcat(buf, " break break"); + doio(buf); + tok = 0; + con = 1; + while(con){ + t = yylex(); + if(t == LBREAK) + break; + switch(t){ + case LSTRING: + case LLSTRING: + tok = 1; + free(yylval.sval.s); + break; + case LNAME: + tok = 1; + s = yylval.sym; + if(s->macro || s->type == T || s->type->etype != TENUM) + con = 0; + break; + case LCHARACTER: + case LCONST: + case LLCONST: + case LUCONST: + case LULCONST: + case LVLCONST: + case LUVLCONST: + case LFCONST: + case LDCONST: + tok = 1; + break; + case '+': + case '-': + case '*': + case '/': + case '%': + case LPP: + case LMM: + case '<': + case '>': + case LGE: + case LLE: + case LEQ: + case LNE: + case LLSH: + case LRSH: + case '!': + case '~': + case '&': + case '|': + case '^': + case '(': + case ')': + break; + default: + con = 0; + break; + } + } + undoio(); + peekc = opeekc; + lineno = olineno; + ypeek = 0; + return con && tok; +} + +void +doasenum(Sym *s) +{ + char *b, buf[1024]; + + b = s->macro; + s->macro = nil; + lineno--; + slashslash(b+1); + sprint(buf, "enum{ %s = %s };\n", s->name, b+1); + doio(buf); + /* outpush(nil); */ + free(b); +} diff --git a/utils/c2l/lexbody b/utils/c2l/lexbody new file mode 100644 index 00000000..ab7e2439 --- /dev/null +++ b/utils/c2l/lexbody @@ -0,0 +1,650 @@ +/* + * common code for all the assemblers + */ + +/* + * real allocs + */ +void* +alloc(long n) +{ + void *p; + + while((ulong)hunk & MAXALIGN) { + hunk++; + nhunk--; + } + while(nhunk < n) + gethunk(); + p = hunk; + nhunk -= n; + hunk += n; + return p; +} + +void* +allocn(void *p, long on, long n) +{ + void *q; + + q = (uchar*)p + on; + if(q != hunk || nhunk < n) { + while(nhunk < on+n) + gethunk(); + memmove(hunk, p, on); + p = hunk; + hunk += on; + nhunk -= on; + } + hunk += n; + nhunk -= n; + return p; +} + +void +setinclude(char *p) +{ + int i; + + if(p == 0) + return; + for(i=1; i < ninclude; i++) + if(strcmp(p, include[i]) == 0) + return; + + if(ninclude >= nelem(include)) { + yyerror("ninclude too small %d", nelem(include)); + exits("ninclude"); + } + include[ninclude++] = p; +} + +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; + + i = ionext; + i->link = iostack; + iostack = i; + i->f = f; + if(f < 0) + i->f = open(s, 0); + if(i->f < 0) { + yyerror("%ca: %r: %s", thechar, s); + errorexit(); + } + fi.c = 0; + linehist(s, 0); +} + +Sym* +slookup(char *s) +{ + + strcpy(symb, s); + return lookup(); +} + +Sym* +lookup(void) +{ + static Sym zsym; + Sym *s; + long h; + char *p; + int c, l; + + h = 0; + for(p=symb; c = *p; p++) + h = h+h+h + c; + l = (p - symb) + 1; + if(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(memcmp(s->name, symb, l) == 0) + return s; + } + s = alloc(sizeof(*s)); + *s = zsym; + s->name = alloc(l); + memmove(s->name, symb, l); + + s->link = hash[h]; + hash[h] = s; + syminit(s); + return s; +} + +long +yylex(void) +{ + int c, c1; + char *cp; + Sym *s; + + c = peekc; + if(c != IGN) { + peekc = IGN; + goto l1; + } +l0: + c = GETC(); + +l1: + if(c == EOF) { + peekc = EOF; + return -1; + } + if(isspace(c)) { + if(c == '\n') { + lineno++; + return ';'; + } + goto l0; + } + if(isalpha(c)) + goto talph; + if(isdigit(c)) + goto tnum; + switch(c) + { + case '\n': + lineno++; + return ';'; + + case '#': + domacro(); + goto l0; + + case '.': + c = GETC(); + if(isalpha(c)) { + cp = symb; + *cp++ = '.'; + goto aloop; + } + if(isdigit(c)) { + cp = symb; + *cp++ = '.'; + goto casedot; + } + peekc = c; + return '.'; + + talph: + case '_': + case '@': + cp = symb; + + aloop: + *cp++ = c; + c = GETC(); + if(isalpha(c) || isdigit(c) || c == '_' || c == '$') + goto aloop; + *cp = 0; + 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; + } + if(s->type == 0) + s->type = LNAME; + if(s->type == LNAME || + s->type == LVAR || + s->type == LLAB) { + yylval.sym = s; + return s->type; + } + yylval.lval = s->value; + return s->type; + + tnum: + cp = symb; + if(c != '0') + goto dc; + *cp++ = c; + c = GETC(); + c1 = 3; + if(c == 'x' || c == 'X') { + c1 = 4; + c = GETC(); + } else + if(c < '0' || c > '7') + goto dc; + yylval.lval = 0; + for(;;) { + if(c >= '0' && c <= '9') { + if(c > '7' && c1 == 3) + break; + yylval.lval <<= c1; + yylval.lval += c - '0'; + c = GETC(); + continue; + } + if(c1 == 3) + break; + if(c >= 'A' && c <= 'F') + c += 'a' - 'A'; + if(c >= 'a' && c <= 'f') { + yylval.lval <<= c1; + yylval.lval += c - 'a' + 10; + c = GETC(); + continue; + } + break; + } + goto ncu; + + dc: + for(;;) { + if(!isdigit(c)) + break; + *cp++ = c; + c = GETC(); + } + if(c == '.') + goto casedot; + if(c == 'e' || c == 'E') + goto casee; + *cp = 0; + yylval.lval = atol(symb); + + ncu: + peekc = c; + return LCONST; + + casedot: + for(;;) { + *cp++ = c; + c = GETC(); + if(!isdigit(c)) + break; + } + if(c == 'e' || c == 'E') + goto casee; + goto caseout; + + casee: + *cp++ = 'e'; + c = GETC(); + if(c == '+' || c == '-') { + *cp++ = c; + c = GETC(); + } + while(isdigit(c)) { + *cp++ = c; + c = GETC(); + } + + caseout: + *cp = 0; + peekc = c; + if(FPCHIP) { + yylval.dval = atof(symb); + return LFCONST; + } + yyerror("assembler cannot interpret fp constants"); + yylval.lval = 1L; + return LCONST; + + case '"': + memcpy(yylval.sval, nullgen.sval, sizeof(yylval.sval)); + cp = yylval.sval; + c1 = 0; + for(;;) { + c = escchar('"'); + if(c == EOF) + break; + if(c1 < sizeof(yylval.sval)) + *cp++ = c; + c1++; + } + if(c1 > sizeof(yylval.sval)) + yyerror("string constant too long"); + return LSCONST; + + case '\'': + c = escchar('\''); + if(c == EOF) + c = '\''; + if(escchar('\'') != EOF) + yyerror("missing '"); + yylval.lval = c; + return LCONST; + + case '/': + c1 = GETC(); + if(c1 == '/') { + for(;;) { + c = GETC(); + if(c == '\n') { + lineno++; + goto l0; + } + if(c == EOF) { + yyerror("eof in comment"); + errorexit(); + } + } + } + if(c1 == '*') { + for(;;) { + c = GETC(); + while(c == '*') { + c = GETC(); + if(c == '/') + goto l0; + } + if(c == EOF) { + yyerror("eof in comment"); + errorexit(); + } + if(c == '\n') + lineno++; + } + } + break; + + default: + return c; + } + peekc = c1; + return c; +} + +int +getc(void) +{ + int c; + + c = peekc; + if(c != IGN) { + peekc = IGN; + return c; + } + c = GETC(); + if(c == '\n') + lineno++; + if(c == EOF) { + yyerror("End of file"); + errorexit(); + } + return c; +} + +int +getnsc(void) +{ + int c; + + for(;;) { + c = getc(); + if(!isspace(c) || c == '\n') + return c; + } +} + +void +unget(int c) +{ + + peekc = c; + if(c == '\n') + lineno--; +} + +int +escchar(int e) +{ + int c, l; + +loop: + c = getc(); + if(c == '\n') { + yyerror("newline in string"); + return EOF; + } + if(c != '\\') { + if(c == e) + return EOF; + return c; + } + c = getc(); + if(c >= '0' && c <= '7') { + l = c - '0'; + c = getc(); + if(c >= '0' && c <= '7') { + l = l*8 + c-'0'; + c = getc(); + if(c >= '0' && c <= '7') { + l = l*8 + c-'0'; + return l; + } + } + peekc = c; + return l; + } + switch(c) + { + case '\n': goto loop; + case 'n': return '\n'; + case 't': return '\t'; + case 'b': return '\b'; + case 'r': return '\r'; + case 'f': return '\f'; + case 'a': return 0x07; + case 'v': return 0x0b; + case 'z': return 0x00; + } + return c; +} + +void +pinit(char *f) +{ + int i; + Sym *s; + + lineno = 1; + newio(); + newfile(f, -1); + pc = 0; + peekc = IGN; + sym = 1; + for(i=0; i<NSYM; i++) { + h[i].type = 0; + h[i].sym = S; + } + for(i=0; i<NHASH; i++) + for(s = hash[i]; s != S; s = s->link) + s->macro = 0; +} + +int +filbuf(void) +{ + Io *i; + +loop: + i = iostack; + if(i == I) + return EOF; + if(i->f < 0) + goto pop; + fi.c = read(i->f, i->b, BUFSIZ) - 1; + if(fi.c < 0) { + close(i->f); + linehist(0, 0); + goto pop; + } + fi.p = i->b + 1; + return i->b[0]; + +pop: + iostack = i->link; + i->link = iofree; + iofree = i; + i = iostack; + if(i == I) + return EOF; + fi.p = i->p; + fi.c = i->c; + if(--fi.c < 0) + goto loop; + return *fi.p++; +} + +void +yyerror(char *a, ...) +{ + char buf[200]; + va_list arg; + + /* + * hack to intercept message from yaccpar + */ + if(strcmp(a, "syntax error") == 0) { + yyerror("syntax error, last name: %s", symb); + return; + } + prfile(lineno); + va_start(arg, a); + doprint(buf, buf+sizeof(buf), a, arg); + va_end(arg); + print("%s\n", buf); + nerrors++; + if(nerrors > 10) { + print("too many errors\n"); + errorexit(); + } +} + +void +prfile(long l) +{ + int i, n; + Hist a[HISTSZ], *h; + long d; + + n = 0; + for(h = hist; h != H; h = h->link) { + if(l < h->line) + break; + if(h->name) { + if(h->offset == 0) { + if(n >= 0 && n < HISTSZ) + a[n] = *h; + n++; + continue; + } + if(n > 0 && n < HISTSZ) + if(a[n-1].offset == 0) { + a[n] = *h; + n++; + } else + a[n-1] = *h; + continue; + } + n--; + if(n >= 0 && n < HISTSZ) { + d = h->line - a[n].line; + for(i=0; i<n; i++) + a[i].line += d; + } + } + if(n > HISTSZ) + n = HISTSZ; + for(i=0; i<n; i++) + print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1)); +} + +void +ieeedtod(Ieee *ieee, double native) +{ + double fr, ho, f; + int exp; + + if(native < 0) { + ieeedtod(ieee, -native); + ieee->h |= 0x80000000L; + return; + } + if(native == 0) { + ieee->l = 0; + ieee->h = 0; + return; + } + fr = frexp(native, &exp); + f = 2097152L; /* shouldnt use fp constants here */ + fr = modf(fr*f, &ho); + ieee->h = ho; + ieee->h &= 0xfffffL; + ieee->h |= (exp+1022L) << 20; + f = 65536L; + fr = modf(fr*f, &ho); + ieee->l = ho; + ieee->l <<= 16; + ieee->l |= (long)(fr*f); +} diff --git a/utils/c2l/mac.c b/utils/c2l/mac.c new file mode 100644 index 00000000..7ec6e393 --- /dev/null +++ b/utils/c2l/mac.c @@ -0,0 +1,3 @@ +#include "cc.h" + +#include "macbody" diff --git a/utils/c2l/macbody b/utils/c2l/macbody new file mode 100644 index 00000000..aacb1e6f --- /dev/null +++ b/utils/c2l/macbody @@ -0,0 +1,773 @@ + +long +getnsn(void) +{ + long n; + int c; + + c = getnsc(); + if(c < '0' || c > '9') + return -1; + n = 0; + while(c >= '0' && c <= '9') { + n = n*10 + c-'0'; + c = getc(); + } + unget(c); + return n; +} + +Sym* +getsym(void) +{ + int c; + char *cp; + + c = getnsc(); + if(!isalpha(c) && c != '_') { + unget(c); + return S; + } + for(cp = symb;;) { + if(cp <= symb+NSYMB-4) + *cp++ = c; + c = getc(); + if(isalnum(c) || c == '_') + continue; + unget(c); + break; + } + *cp = 0; + if(cp > symb+NSYMB-4) + yyerror("symbol too large: %s", symb); + return lookup(); +} + +int +getcom(void) +{ + int c; + + for(;;) { + c = getnsc(); + if(c != '/') + break; + c = getc(); + if(c == '/') { + while(c != '\n') + c = getc(); + break; + } + if(c != '*') + break; + c = getc(); + for(;;) { + if(c == '*') { + c = getc(); + if(c != '/') + continue; + c = getc(); + break; + } + if(c == '\n') { + yyerror("comment across newline"); + break; + } + c = getc(); + } + if(c == '\n') + break; + } + return c; +} + +void +dodefine(char *cp) +{ + Sym *s; + char *p; + long l; + + strcpy(symb, cp); + p = strchr(symb, '='); + if(p) { + *p++ = 0; + s = lookup(); + l = strlen(p) + 2; /* +1 null, +1 nargs */ + while(l & 3) + l++; + while(nhunk < l) + gethunk(); + *hunk = 0; + strcpy(hunk+1, p); + s->macro = hunk; + hunk += l; + nhunk -= l; + } else { + s = lookup(); + s->macro = "\0001"; /* \000 is nargs */ + } + if(0) + print("#define (-D) %s %s\n", s->name, s->macro+1); +} + +struct +{ + char *macname; + void (*macf)(void); +} mactab[] = +{ + "ifdef", 0, /* macif(0) */ + "ifndef", 0, /* macif(1) */ + "else", 0, /* macif(2) */ + + "line", maclin, + "define", macdef, + "include", macinc, + "undef", macund, + + "pragma", macprag, + "endif", macend, + 0 +}; + +void +domacro(void) +{ + int i; + Sym *s; + + s = getsym(); + if(s == S) + s = slookup("endif"); + for(i=0; mactab[i].macname; i++) + if(strcmp(s->name, mactab[i].macname) == 0) { + if(mactab[i].macf) + (*mactab[i].macf)(); + else + macif(i); + return; + } + yyerror("unknown #: %s", s->name); + macend(); +} + +void +macund(void) +{ + Sym *s; + + s = getsym(); + macend(); + if(s == S) { + yyerror("syntax in #undef"); + return; + } + s->macro = 0; +} + +#define NARG 25 +void +macdef(void) +{ + Sym *s, *a; + char *args[NARG], *np, *base; + int n, i, c, len; + + s = getsym(); + if(s == S) + goto bad; + if(s->macro) + yyerror("macro redefined: %s", s->name); + c = getc(); + n = -1; + if(c == '(') { + n++; + c = getnsc(); + if(c != ')') { + unget(c); + for(;;) { + a = getsym(); + if(a == S) + goto bad; + if(n >= NARG) { + yyerror("too many arguments in #define: %s", s->name); + goto bad; + } + args[n++] = a->name; + c = getnsc(); + if(c == ')') + break; + if(c != ',') + goto bad; + } + } + c = getc(); + } + if(isspace(c)) + if(c != '\n') + c = getnsc(); + base = hunk; + len = 1; + for(;;) { + if(isalpha(c) || c == '_') { + np = symb; + *np++ = c; + c = getc(); + while(isalnum(c) || c == '_') { + *np++ = c; + c = getc(); + } + *np = 0; + for(i=0; i<n; i++) + if(strcmp(symb, args[i]) == 0) + break; + if(i >= n) { + i = strlen(symb); + base = allocn(base, len, i); + memcpy(base+len, symb, i); + len += i; + continue; + } + base = allocn(base, len, 2); + base[len++] = '#'; + base[len++] = 'a' + i; + continue; + } + if(c == '/') { + c = getc(); + if(c != '*') { + base = allocn(base, len, 1); + base[len++] = '/'; + continue; + } + c = getc(); + for(;;) { + if(c == '*') { + c = getc(); + if(c != '/') + continue; + c = getc(); + break; + } + if(c == '\n') { + yyerror("comment and newline in define: %s", s->name); + break; + } + c = getc(); + } + continue; + } + if(c == '\\') { + c = getc(); + if(c == '\n') { + c = getc(); + continue; + } + else if(c == '\r') { + c = getc(); + if(c == '\n') { + c = getc(); + continue; + } + } + base = allocn(base, len, 1); + base[len++] = '\\'; + continue; + } + if(c == '\n') + break; + if(c == '#') + if(n > 0) { + base = allocn(base, len, 1); + base[len++] = c; + } + base = allocn(base, len, 1); + base[len++] = c; + c = ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff)); + if(c == '\n') + lineno++; + if(c == -1) { + yyerror("eof in a macro: %s", s->name); + break; + } + } + do { + base = allocn(base, len, 1); + base[len++] = 0; + } while(len & 3); + + *base = n+1; + s->macro = base; + if(0) + print("#define %s %s\n", s->name, s->macro+1); + if(n == -1 && iscon(base+1)) + doasenum(s); + return; + +bad: + if(s == S) + yyerror("syntax in #define"); + else + yyerror("syntax in #define: %s", s->name); + macend(); +} + +void +macexpand(Sym *s, char *b) +{ + char buf[2000]; + int n, l, c, nargs; + char *arg[NARG], *cp, *ob, *ecp; + + ob = b; + USED(ob); + nargs = *s->macro - 1; + if(nargs < 0) { + strcpy(b, s->macro+1); + if(0) + print("#expand %s %s\n", s->name, ob); + return; + } + c = getnsc(); + if(c != '(') + goto bad; + n = 0; + c = getc(); + if(c != ')') { + unget(c); + l = 0; + cp = buf; + ecp = cp + sizeof(buf)-4; + arg[n++] = cp; + for(;;) { + if(cp >= ecp) + goto toobig; + c = getc(); + if(c == '"') + for(;;) { + if(cp >= ecp) + goto toobig; + *cp++ = c; + c = getc(); + if(c == '\\') { + *cp++ = c; + c = getc(); + continue; + } + if(c == '\n') + goto bad; + if(c == '"') + break; + } + if(c == '\'') + for(;;) { + if(cp >= ecp) + goto toobig; + *cp++ = c; + c = getc(); + if(c == '\\') { + *cp++ = c; + c = getc(); + continue; + } + if(c == '\n') + goto bad; + if(c == '\'') + break; + } + if(l == 0) { + if(c == ',') { + *cp++ = 0; + arg[n++] = cp; + if(n > nargs) + break; + continue; + } + if(c == ')') + break; + } + if(c == '\n') + c = ' '; + *cp++ = c; + if(c == '(') + l++; + if(c == ')') + l--; + } + *cp = 0; + } + if(n != nargs) { + yyerror("argument mismatch expanding: %s", s->name); + *b = 0; + return; + } + cp = s->macro+1; + for(;;) { + c = *cp++; + if(c != '#') { + *b++ = c; + if(c == 0) + break; + continue; + } + c = *cp++; + if(c == 0) + goto bad; + if(c == '#') { + *b++ = c; + continue; + } + c -= 'a'; + if(c < 0 || c >= n) + continue; + strcpy(b, arg[c]); + b += strlen(arg[c]); + } + *b = 0; + if(0) + print("#expand %s %s\n", s->name, ob); + return; + +bad: + yyerror("syntax in macro expansion: %s", s->name); + *b = 0; + return; + +toobig: + yyerror("too much text in macro expansion: %s", s->name); + *b = 0; +} + +void +macinc(void) +{ + int c0, c, i, f; + char str[STRINGSZ], *hp; + + c0 = getnsc(); + if(c0 != '"') { + c = c0; + if(c0 != '<') + goto bad; + c0 = '>'; + } + for(hp = str;;) { + c = getc(); + if(c == c0) + break; + if(c == '\n') + goto bad; + *hp++ = c; + } + *hp = 0; + + c = getcom(); + if(c != '\n') + goto bad; + + f = -1; + for(i=0; i<ninclude; i++) { + if(i == 0 && c0 == '>') + continue; + strcpy(symb, include[i]); + strcat(symb, "/"); + if(strcmp(symb, "./") == 0) + symb[0] = 0; + strcat(symb, str); + f = open(symb, 0); + if(f >= 0) + break; + } + if(f < 0) + strcpy(symb, str); + c = strlen(symb) + 1; + while(c & 3) + c++; + while(nhunk < c) + gethunk(); + hp = hunk; + memcpy(hunk, symb, c); + nhunk -= c; + hunk += c; + newio(); + pushio(); + newfile(hp, f); + return; + +bad: + unget(c); + yyerror("syntax in #include"); + macend(); +} + +void +maclin(void) +{ + char *cp; + int c; + long n; + + n = getnsn(); + c = getc(); + if(n < 0) + goto bad; + + for(;;) { + if(c == ' ' || c == '\t') { + c = getc(); + continue; + } + if(c == '"') + break; + if(c == '\n') { + strcpy(symb, "<noname>"); + goto nn; + } + goto bad; + } + cp = symb; + for(;;) { + c = getc(); + if(c == '"') + break; + *cp++ = c; + } + *cp = 0; + c = getcom(); + if(c != '\n') + goto bad; + +nn: + c = strlen(symb) + 1; + while(c & 3) + c++; + while(nhunk < c) + gethunk(); + cp = hunk; + memcpy(hunk, symb, c); + nhunk -= c; + hunk += c; + + linehist(cp, n); + return; + +bad: + unget(c); + yyerror("syntax in #line"); + macend(); +} + +void +macif(int f) +{ + int c, l, bol; + Sym *s; + + if(f == 2) + goto skip; + s = getsym(); + if(s == S) + goto bad; + if(getcom() != '\n') + goto bad; + if(s->macro == 0 && s->type != T && s->type->etype == TENUM){ + if(!f) + return; + } + else if((s->macro != 0) ^ f) + return; + +skip: + bol = 1; + l = 0; + for(;;) { + c = getc(); + if(c != '#') { + if(!isspace(c)) + bol = 0; + if(c == '\n') + bol = 1; + continue; + } + if(!bol) + continue; + s = getsym(); + if(s == S) + continue; + if(strcmp(s->name, "endif") == 0) { + if(l) { + l--; + continue; + } + macend(); + return; + } + if(strcmp(s->name, "ifdef") == 0 || strcmp(s->name, "ifndef") == 0) { + l++; + continue; + } + if(l == 0 && f != 2 && strcmp(s->name, "else") == 0) { + macend(); + return; + } + } + +bad: + yyerror("syntax in #if(n)def"); + macend(); +} + +void +macprag(void) +{ + Sym *s; + int c0, c; + char *hp; + Hist *h; + + s = getsym(); + + if(s && strcmp(s->name, "lib") == 0) + goto praglib; + if(s && strcmp(s->name, "hjdicks") == 0) { + praghjdicks(); + return; + } + if(s && strcmp(s->name, "fpround") == 0) { + pragfpround(); + return; + } + if(s && strcmp(s->name, "varargck") == 0) { + pragvararg(); + return; + } + + while(getnsc() != '\n') + ; + return; + +praglib: + c0 = getnsc(); + if(c0 != '"') { + c = c0; + if(c0 != '<') + goto bad; + c0 = '>'; + } + for(hp = symb;;) { + c = getc(); + if(c == c0) + break; + if(c == '\n') + goto bad; + *hp++ = c; + } + *hp = 0; + c = getcom(); + if(c != '\n') + goto bad; + + /* + * put pragma-line in as a funny history + */ + c = strlen(symb) + 1; + while(c & 3) + c++; + while(nhunk < c) + gethunk(); + hp = hunk; + memcpy(hunk, symb, c); + nhunk -= c; + hunk += c; + + h = alloc(sizeof(Hist)); + h->name = hp; + h->line = lineno; + h->offset = -1; + h->link = H; + if(ehist == H) { + hist = h; + ehist = h; + return; + } + ehist->link = h; + ehist = h; + return; + +bad: + unget(c); + yyerror("syntax in #pragma lib"); + macend(); +} + +void +macend(void) +{ + int c; + + for(;;) { + c = getnsc(); + if(c < 0 || c == '\n') + return; + } +} + +void +linehist(char *f, int offset) +{ + Hist *h; + + /* + * overwrite the last #line directive if + * no alloc has happened since the last one + */ + if(newflag == 0 && ehist != H && offset != 0 && ehist->offset != 0) + if(f && ehist->name && strcmp(f, ehist->name) == 0) { + ehist->line = lineno; + ehist->offset = offset; + return; + } + + if(0) + if(f) { + if(offset) + print("%4ld: %s (#line %d)\n", lineno, f, offset); + else + print("%4ld: %s\n", lineno, f); + } else + print("%4ld: <pop>\n", lineno); + newflag = 0; + + h = alloc(sizeof(Hist)); + h->name = f; + h->line = lineno; + h->offset = offset; + h->link = H; + if(ehist == H) { + hist = h; + ehist = h; + return; + } + ehist->link = h; + ehist = h; +} + +void +gethunk(void) +{ + char *h; + long nh; + + nh = NHUNK; + if(thunk >= 10L*NHUNK) + nh = 10L*NHUNK; + h = (char*)mysbrk(nh); + if(h == (char*)-1) { + yyerror("out of memory"); + errorexit(); + } + hunk = h; + nhunk = nh; + thunk += nh; +} diff --git a/utils/c2l/mkfile b/utils/c2l/mkfile new file mode 100644 index 00000000..219d36e1 --- /dev/null +++ b/utils/c2l/mkfile @@ -0,0 +1,38 @@ +<../../mkconfig + +TARG=c2l + +OFILES=\ + acid.$O\ + bits.$O\ + com.$O\ + com64.$O\ + $TARGMODEL.$O\ + dcl.$O\ + dpchk.$O\ + lex.$O\ + mac.$O\ + mpatof.$O\ + out.$O\ + scon.$O\ + sub.$O\ + y.tab.$O\ + c2l.$O\ + +HFILES= cc.h\ + y.tab.h\ + +YFILES= cc.y\ + +LIBS=math bio 9 + +BIN=$ROOT/$OBJDIR/bin + +<$ROOT/mkfiles/mkone-$SHELLTYPE + +CFLAGS= $CFLAGS -I../include + +mac.$O: macbody + +lex.$O: lex.c + $CC $CFLAGS '-DCPP="/bin/cpp"' lex.c diff --git a/utils/c2l/mpatof.c b/utils/c2l/mpatof.c new file mode 100644 index 00000000..d55ddab4 --- /dev/null +++ b/utils/c2l/mpatof.c @@ -0,0 +1,337 @@ +#include "cc.h" + +enum +{ + Mpscale = 29, /* safely smaller than bits in a long */ + Mpprec = 36, /* Mpscale*Mpprec sb > largest fp exp */ + Mpbase = 1L<<Mpscale, +}; + +typedef +struct +{ + long a[Mpprec]; + char ovf; +} Mp; + +int mpatof(char*, double*); +int mpatov(char *s, vlong *v); +void mpint(Mp*, int); +void mppow(Mp*, int, int); +void mpmul(Mp*, int); +void mpadd(Mp*, Mp*); +int mptof(Mp*, double*); + +/* + * convert a string, s, to floating in *d + * return conversion overflow. + * required syntax is [+-]d*[.]d*[e[+-]d*] + */ +int +mpatof(char *s, double *d) +{ + Mp a, b; + int dp, c, f, ef, ex, zer; + double d1, d2; + + dp = 0; /* digits after decimal point */ + f = 0; /* sign */ + ex = 0; /* exponent */ + zer = 1; /* zero */ + memset(&a, 0, sizeof(a)); + for(;;) { + switch(c = *s++) { + default: + goto bad; + case '-': + f = 1; + case ' ': + case '\t': + case '+': + continue; + case '.': + dp = 1; + continue; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + zer = 0; + case '0': + mpint(&b, c-'0'); + mpmul(&a, 10); + mpadd(&a, &b); + if(dp) + dp++; + continue; + case 'E': + case 'e': + ex = 0; + ef = 0; + for(;;) { + c = *s++; + if(c == '+' || c == ' ' || c == '\t') + continue; + if(c == '-') { + ef = 1; + continue; + } + if(c >= '0' && c <= '9') { + ex = ex*10 + (c-'0'); + continue; + } + break; + } + if(ef) + ex = -ex; + case 0: + break; + } + break; + } + if(a.ovf) + goto bad; + if(zer) { + *d = 0; + return 0; + } + if(dp) + dp--; + dp -= ex; + if(dp > 0) { + /* + * must divide by 10**dp + */ + if(mptof(&a, &d1)) + goto bad; + + /* + * trial exponent of 8**dp + * 8 (being between 5 and 10) + * should pick up all underflows + * in the division of 5**dp. + */ + d2 = frexp(d1, &ex); + d2 = ldexp(d2, ex-3*dp); + if(d2 == 0) + goto bad; + + /* + * decompose each 10 into 5*2. + * create 5**dp in fixed point + * and then play with the exponent + * for the remaining 2**dp. + * note that 5**dp will overflow + * with as few as 134 input digits. + */ + mpint(&a, 1); + mppow(&a, 5, dp); + if(mptof(&a, &d2)) + goto bad; + d1 = frexp(d1/d2, &ex); + d1 = ldexp(d1, ex-dp); + if(d1 == 0) + goto bad; + } else { + /* + * must multiply by 10**|dp| -- + * just do it in fixed point. + */ + mppow(&a, 10, -dp); + if(mptof(&a, &d1)) + goto bad; + } + if(f) + d1 = -d1; + *d = d1; + return 0; + +bad: + return 1; +} + +/* + * convert a to floating in *d + * return conversion overflow + */ +int +mptof(Mp *a, double *d) +{ + double f, g; + long x, *a1; + int i; + + if(a->ovf) + return 1; + a1 = a->a; + f = ldexp(*a1++, 0); + for(i=Mpscale; i<Mpprec*Mpscale; i+=Mpscale) + if(x = *a1++) { + g = ldexp(x, i); + /* + * NOTE: the test (g==0) is plan9 + * specific. ansi compliant overflow + * is signaled by HUGE and errno==ERANGE. + * change this for your particular ldexp. + */ + if(g == 0) + return 1; + f += g; /* this could bomb! */ + } + *d = f; + return 0; +} + +/* + * return a += b + */ +void +mpadd(Mp *a, Mp *b) +{ + int i, c; + long x, *a1, *b1; + + if(b->ovf) + a->ovf = 1; + if(a->ovf) + return; + c = 0; + a1 = a->a; + b1 = b->a; + for(i=0; i<Mpprec; i++) { + x = *a1 + *b1++ + c; + c = 0; + if(x >= Mpbase) { + x -= Mpbase; + c = 1; + } + *a1++ = x; + } + a->ovf = c; +} + +/* + * return a = c + */ +void +mpint(Mp *a, int c) +{ + + memset(a, 0, sizeof(*a)); + a->a[0] = c; +} + +/* + * return a *= c + */ +void +mpmul(Mp *a, int c) +{ + Mp p; + int b; + + memmove(&p, a, sizeof(p)); + if(!(c & 1)) + memset(a, 0, sizeof(*a)); + c &= ~1; + for(b=2; c; b<<=1) { + mpadd(&p, &p); + if(c & b) { + mpadd(a, &p); + c &= ~b; + } + } +} + +/* + * return a *= b**e + */ +void +mppow(Mp *a, int b, int e) +{ + int b1; + + b1 = b*b; + b1 = b1*b1; + while(e >= 4) { + mpmul(a, b1); + e -= 4; + if(a->ovf) + return; + } + while(e > 0) { + mpmul(a, b); + e--; + } +} + +/* + * 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; +} diff --git a/utils/c2l/out.c b/utils/c2l/out.c new file mode 100644 index 00000000..ab81a995 --- /dev/null +++ b/utils/c2l/out.c @@ -0,0 +1,825 @@ +#include "cc.h" + +#define INCREMENT 8 +#define DEVNULL "/dev/null" + +static int indent = 0; +static int fd = -1; +static int nf = 0; +static int mylineno = 1; + +typedef struct Com{ + int lno; + char *s; + Node *n; + int tba; + struct Com *nxt; +} Com; + +Com *hdc, *curc; + +typedef struct File{ + char *s; + char *f; + char *m; + int b; + int loc; + int in; + int tg; + Node *n; + Com *c; + struct File *nxt; +} File; + +typedef struct Create{ + char *s; + struct Create *nxt; +} Create; + +File *fs; +Create *cs; + +static void genmsg(void); +static int isloc(void); + +static void +addcreate(char *s) +{ + Create *c; + + if(strcmp(s, DEVNULL) == 0) + return; + c = (Create*)malloc(sizeof(Create)); + c->s = malloc(strlen(s)+1); + strcpy(c->s, s); + c->nxt = cs; + cs = c; +} + +static int +created(char *s) +{ + Create *c; + + for(c = cs; c != nil; c = c->nxt) + if(strcmp(s, c->s) == 0) + return 1; + return 0; +} + +int +dolog(void) +{ + if(justcode) + return 0; + return domod || !doinc || inmain; +} + +static char* +curf(void) +{ + File *f; + + for(f = fs; f != nil; f = f->nxt) + if(f->f != nil) + return f->s; + return nil; +} + +static char* +curm(void) +{ + File *f; + + for(f = fs; f != nil; f = f->nxt) + if(f->f != nil) + return f->m; + return nil; +} + +void +setmod(Sym *s) +{ + if(domod && s->mod == nil && ism() && !(doloc && !isloc())) + s->mod = curm(); +} + +char * +outmod(char *buf, int up) +{ + char *s, *t; + + s = curf(); + if(s == nil) + return ""; + t = strchr(s, '.'); + if(t != nil) + *t = '\0'; + strcpy(buf, s); + if(t != nil) + *t = '.'; + if(up == 1 || (up < 0 && ism())) + buf[0] = toupper(buf[0]); + return buf; +} + +int +ism(void) +{ + return !isb(); +} + +int +isb(void) +{ + File *f; + + for(f = fs; f != nil; f = f->nxt) + if(f->f != nil) + return f->b; + return 0; +} + +static int +isloc(void) +{ + File *f; + + for(f = fs; f != nil; f = f->nxt) + if(f->f != nil) + return f->loc; + return 0; +} + +static File* +pushf(void) +{ + static File zfile; + File *f; + + f = (File*)malloc(sizeof(File)); + *f = zfile; + f->s = nil; + f->f = nil; + f->m = nil; + f->nxt = fs; + fs = f; + return f; +} + +static void +popf(void) +{ + File *f; + + f = fs; + fs = fs->nxt; + if(f->s != nil) + free(f->s); + free(f); +} + +static void +setf(File *f, char *s) +{ + int n; + char *t; + + if(s != nil){ + t = strrchr(s, '/'); + f->loc = t == nil; + if(t != nil) + s = t+1; + n = strlen(s); + f->s = malloc(n+1); + strcpy(f->s, s); + s = f->s; + if(n > 2 && s[n-2] == '.'){ + f->m = malloc(n-1); + strncpy(f->m, s, n-2); + if(s[n-1] == 'h') + s[n-1] = 'm'; + else if(s[n-1] == 'c'){ + s[n-1] = 'b'; + f->b = 1; + } + else + s = nil; + } + else + s = nil; + if(s == nil){ + free(f->s); + if(f->m != nil) + free(f->m); + f->s = nil; + f->m = nil; + } + } + f->f = f->s; + if(f->s != nil && nf > 0){ + if(doinc || doloc && !f->loc) + f->f = DEVNULL; + else if(!domod) + f->f = nil; + } +} + +void +outpush0(char *s, Node *n) +{ + File *f; + + f = pushf(); + setf(f, s); + if(f->f != nil){ + nf++; + f->tg = taggen; + taggen = 0; + f->n = n; + f->c = hdc; + hdc = nil; + } +} + +void +outpop0(int lno) +{ + File *f; + + USED(lno); + f = fs; + if(f->f != nil){ + nf--; + taggen = f->tg; + f->n->left = (void*)hdc; + hdc = f->c; + } + popf(); +} + +void +outpush2(char *s, Node *n) +{ + File *f; + + f = pushf(); + setf(f, s); + if(f->f != nil){ + if(fd >= 0){ + newsec(0); + close(fd); + close(1); + fd = -1; + } + if(created(f->f)) + f->f = DEVNULL; /* don't overwrite original if included again */ + fd = create(f->f, OWRITE, 0664); + if(fd >= 0) + addcreate(f->f); + mydup(fd, 1); + nf++; + f->tg = taggen; + taggen = 0; + f->c = hdc; + if(n != Z) + hdc = (void*)n->left; + else + hdc = nil; + f->in = indent; + indent = 0; + genmsg(); + pgen(f->b); + } +} + +void +outpop2(int lno) +{ + File *f, *g; + + f = fs; + if(f->f != nil){ + if(fd >= 0){ + newsec(0); + output(lno, 1); + epgen(f->b); + close(fd); + close(1); + fd = -1; + } + for(g = fs->nxt; g != nil; g = g->nxt){ + if(g->f != nil){ + fd = open(g->f, OWRITE); + seek(fd, 0, 2); + mydup(fd, 1); + break; + } + } + nf--; + taggen = f->tg; + hdc = f->c; + indent = f->in; + } + popf(); +} + +static void +xprint(char *s) +{ + if(nerrors == 0) + print(s); +} + +static int tot = 0; + +static void +doindent(int d) +{ + int i; + + for(i = 0; i < d/8; i++) + xprint("\t"); + for(i = 0; i < d%8; i++) + xprint(" "); +} + +void +incind(void) +{ + indent += INCREMENT; +} + +void +decind(void) +{ + indent -= INCREMENT; +} + +int +zeroind(void) +{ + int i = indent; + + indent = 0; + return i; +} + +void +restoreind(int i) +{ + indent = i; +} + +void +newline0(void) +{ + xprint("\n"); + tot = 0; + mylineno++; +} + +void +newline(void) +{ + if(!outcom(1)){ + xprint("\n"); + mylineno++; + } + tot = 0; +} + +static void +lprint(char *s) +{ + if(tot == 0) { + doindent(indent); + tot += indent; + } + xprint(s); + tot += strlen(s); +} + +void +prline(char *s) +{ + xprint(s); + xprint("\n"); + mylineno++; +} + +void +prdelim(char *s) +{ + if(*s == '%'){ + if(*++s == '=') + lprint("%%="); + else + lprint("%%"); + return; + } + lprint(s); +} + +void +prkeywd(char *kw) +{ + lprint(kw); +} + +void +prid(char *s) +{ + lprint(s); +} + +static void +priddol(char *s, int dol) +{ + char *t; + char buf[128]; + + if(dol){ + t = strchr(s, '$'); + if(t != nil) + *t = '_'; + lprint(s); + if(t != nil){ + strcpy(buf, s); + while(slookup(buf)->type != T){ + strcat(buf, "x"); + lprint("x"); + } + *t = '$'; + } + } + else + lprint(s); +} + +void +prsym(Sym *s, int mod) +{ + char buf[128]; + int c; + + if(mod && s->mod && strcmp(s->mod, curm()) != 0 && (!s->limbo || s->class == CEXTERN)){ + c = isconsym(s); + if(c >= 0){ + if(c){ + s->mod[0] = toupper(s->mod[0]); + lprint(s->mod); + s->mod[0] = tolower(s->mod[0]); + } + else + lprint(s->mod); + lprint("->"); + usemod(s, !c); + } + } + if(s->lname) + prid(s->lname); + else{ + priddol(s->name, s->class == CSTATIC); + if(s->lkw){ + strcpy(buf, s->name); + for(;;){ + strcat(buf, "x"); + lprint("x"); + s = slookup(buf); + if(s->type == T) + break; + } + } + } +} + +int +arrow(Sym *s) +{ + if(s->mod && strcmp(s->mod, curm()) != 0) + return isconsym(s) >= 0; + return 0; +} + +void +prsym0(Sym *s) +{ + int c; + + if(s->mod && strcmp(s->mod, curm()) != 0){ + c = isconsym(s); + if(c >= 0) + usemod(s, !c); + } +} + +static int +isprintable(int c) +{ + if(c >= 0x20 && c <= 0x7e) + return 1; + return c == '\0' || c == '\n' || c == '\t' || c == '\b' || c == '\r' || c == '\f' || c == '\a' || c == '\v'; +} + +static int +hex(int c) +{ + if(c < 10) + return c+'0'; + return c+'a'-10; +} + +void +prchar0(vlong x, int quote) +{ + int c, e, i = 0; + static char buf[16]; + + if(quote) + buf[i++] = '\''; + c = x; + if(c < 0 || c > 255 || !isprintable(c)){ + if(c&0xffff0000) + diag(Z, "character too big"); + buf[i++] = '\\'; + buf[i++] = 'u'; + buf[i++] = hex((c>>12)&0xf); + buf[i++] = hex((c>>8)&0xf); + buf[i++] = hex((c>>4)&0xf); + buf[i++] = hex((c>>0)&0xf); + } + else{ + e = 0; + switch(c){ + case '\n': e = 'n'; break; + case '\t': e = 't'; break; + case '\b': e = 'b'; break; + case '\r': e = 'r'; break; + case '\f': e = 'f'; break; + case '\a': e = 'a'; break; + case '\v': e = 'v'; break; + case '"': if(!quote) e = '"'; break; + case '\'': if(quote) e = '\''; break; + case '\\': e = '\\'; break; + case '%': buf[i++] = c; break; + case 0: e = '0'; if(strings) prcom("nul byte in string ?", Z); break; + } + if(e != 0){ + buf[i++] = '\\'; + c = e; + } + buf[i++] = c; + } + if(quote) + buf[i++] = '\''; + buf[i] = '\0'; + lprint(buf); +} + +void +prchar(vlong x) +{ + prchar0(x, 1); +} + +void +prstr(char *s) +{ + uchar *t; + Rune r; + + t = (uchar*)s; + lprint("\""); + while(*t != 0){ + if(*t & 0x80){ + t += chartorune(&r, (char*)t); + prchar0(r, 0); + } + else + prchar0(*t++, 0); + } + lprint("\""); +} + +void +prlstr(ushort *s) +{ + lprint("\""); + while(*s != 0) + prchar0(*s++, 0); + lprint("\""); +} + +void +prreal(double x, char *s, int b) +{ + static char buf[128]; + + if(b != KDEC) + diag(Z, "not base 10 in prreal"); + if(s != nil) + lprint(s); + else{ + sprint(buf, "%f", x); + lprint(buf); + } +} + +void +prnum(vlong x, int b, Type *t) +{ + static char buf[128]; + int w; + vlong m; + + w = 4; + if(t != T) + w = ewidth[t->etype]; + m = MASK(8*w); + if(b == KHEX) + sprint(buf, "16r%llux", x&m); + else if(b == KOCT) + sprint(buf, "8r%lluo", x&m); + else + sprint(buf, "%lld", x); + lprint(buf); +} + +char *cb; +int cn, csz; + +static void +outcom0(Com *c) +{ + Node *n; + char *s, *t, *u; + + s = c->s; + n = c->n; + if(comm && c->tba){ + t = strchr(s, '\n'); + *t = '\0'; + fprint(2, "%s:%d: %s", curf(), mylineno, s); + *t = '\n'; + if(n != Z){ + mydup(2, 1); + expgen(n); + mydup(fd, 1); + } + fprint(2, "\n"); + } + while(*s != '\0'){ + t = strchr(s, '\n'); + *t = '\0'; + if(tot != 0) + prdelim("\t"); + prdelim("# "); + while((u = strchr(s, '%')) != nil){ + /* do not let print interpret % ! */ + *u = 0; + lprint(s); + *u = '%'; + lprint("%%"); + s = u+1; + } + lprint(s); + if(n == Z) + newline0(); + *t = '\n'; + s = t+1; + } + if(n != Z){ + expgen(n); + newline0(); + } +} + +int +outcom(int f) +{ + int lno, nl; + Com *c; + + nl = 0; + lno = pline+f; + c = hdc; + while(c != nil && c->lno < lno){ +/* print("outcom: %d < %d (f=%d)\n", c->lno, lno, f); */ + nl = 1; + outcom0(c); + hdc = hdc->nxt; + free(c->s); + free(c); + c = hdc; + } + return nl; +} + +void +startcom(int lno) +{ + Com *c, **ac; + + c = (Com *)malloc(sizeof(Com)); + c->lno = lno; + c->s = nil; + c->n = Z; + c->tba = 0; + c->nxt = nil; + for(ac = &hdc; *ac != nil && (*ac)->lno <= lno; ac = &(*ac)->nxt) + ; + c->nxt = *ac; + curc = *ac = c; +} + +void +addcom(int rr) +{ + int i, nb; + char *ncb; + char s[UTFmax]; + Rune r[1]; + + if(rr >= Runeself){ + r[0] = rr; + nb = runetochar(s, r); + } + else{ + nb = 1; + s[0] = rr; + } + if(cn+nb-1 >= csz){ + csz += 32; + ncb = malloc(csz); + memcpy(ncb, cb, cn); + free(cb); + cb = ncb; + } + for(i = 0; i < nb; i++) + cb[cn++] = s[i]; +} + +void +endcom(void) +{ + char *s; + + addcom('\n'); + addcom('\0'); + s = malloc(strlen(cb)+1); + strcpy(s, cb); + curc->s = s; +/* print("com %d %s\n", curc->lno, s); */ + cn = 0; +} + +void +linit() +{ + csz = 32; + cb = malloc(csz); + sysinit(); +} + +static void +genmsg(void) +{ + prline("#"); + prline("# initially generated by c2l"); + prline("#"); + prline(""); +} + +void +prcom(char *s, Node *n) +{ + Com *c; + + startcom(pline); + c = curc; + sprint(cb, "TBA %s", s); + cn = strlen(cb); + c->n = n; + c->tba = 1; + endcom(); +} + +void +output(long lno, int com) +{ +/* print("output(%ld)\n", lno); */ + pline = lno; + if(com) + outcom(0); +} + +int +exists(char *f) +{ + int fd; + + fd = open(f, OREAD); + close(fd); + return fd >= 0; +} diff --git a/utils/c2l/scon.c b/utils/c2l/scon.c new file mode 100644 index 00000000..89f87332 --- /dev/null +++ b/utils/c2l/scon.c @@ -0,0 +1,250 @@ +#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; + + case OPOS: + if(isf) + d = l->fconst; + else + v = l->vconst; + break; + + case ONEG: + if(isf) + d = -l->fconst; + else + v = -l->vconst; + break; + + case OCOM: + if(typefd[l->type->etype]) + v = 0; /* ~l->fconst */ + else + v = ~l->vconst; + break; + } + + n->left = ncopy(n); + n->op = OCONST; + /* n->left = Z; */ + n->right = Z; + if(isf) { + n->fconst = d; + } else { + n->vconst = convvtox(v, n->type->etype); + } +} + +void +acom(Node *n) +{ + USED(n); +} diff --git a/utils/c2l/sub.c b/utils/c2l/sub.c new file mode 100644 index 00000000..a696cb0f --- /dev/null +++ b/utils/c2l/sub.c @@ -0,0 +1,1694 @@ +#include "cc.h" + +Node* +new(int t, Node *l, Node *r) +{ + static Node znode; + Node *n; + + n = alloc(sizeof(*n)); + *n = znode; + n->op = t; + n->left = l; + n->right = r; + n->lineno = lineno; + n->kind = KNIL; + newflag = 1; + return n; +} + +Node* +new1(int o, Node *l, Node *r) +{ + Node *n; + + n = new(o, l, r); + if(l != Z) + n->lineno = l->lineno; + else if(r != Z) + n->lineno = r->lineno; + else + n->lineno = nearln; + return n; +} + +void +prtree(Node *n, char *s) +{ + + print(" == %s ==\n", s); + prtree1(n, 0, 0); + print("\n"); +} + +void +prtree1(Node *n, int d, int f) +{ + int i; + + if(f) + for(i=0; i<d; i++) + print(" "); + if(n == Z) { + print("Z\n"); + return; + } + if(n->op == OLIST) { + prtree1(n->left, d, 0); + prtree1(n->right, d, 1); + return; + } + d++; + print("%O", n->op); + i = 3; + switch(n->op) + { + case ONAME: + print(" \"%F\"", n); + i = 0; + break; + + case OINDREG: + i = 0; + break; + + case OREGISTER: + i = 0; + break; + + case OSTRING: + print(" \"%s\"", n->cstring); + i = 0; + break; + + case OLSTRING: + print(" \"%S\"", n->rstring); + i = 0; + break; + + case ODOT: + case OELEM: + print(" \"%F\"", n); + break; + + case OCONST: + if(typefd[n->type->etype]) + print(" \"%.8e\"", n->fconst); + else + print(" \"%lld\"", n->vconst); + i = 0; + break; + } + if(n->type != T) + print(" %T", n->type); + print("\n"); + if(i & 2) + prtree1(n->left, d, 1); + if(i & 1) + prtree1(n->right, d, 1); +} + +Type* +typ(int et, Type *d) +{ + static Type ztype; + Type *t; + + t = alloc(sizeof(*t)); + *t = ztype; + t->etype = et; + t->link = d; + t->down = T; + t->sym = S; + t->width = ewidth[et]; + t->nwidth = Z; + t->lineno = lineno; + return t; +} + +Type* +typ1(int et, Type *d) +{ + Type *t; + + t = typ(et, d); + t->lineno = nearln; + return t; +} + +Type* +garbt(Type *t, long b) +{ + Type *t1; + + if(b & BGARB) { + t1 = typ(TXXX, T); + *t1 = *t; + t1->garb = simpleg(b); + return t1; + } + return t; +} + +int +simpleg(long b) +{ + + b &= BGARB; + switch(b) { + case BCONSTNT: + return GCONSTNT; + case BVOLATILE: + return GVOLATILE; + case BVOLATILE|BCONSTNT: + return GCONSTNT|GVOLATILE; + } + return GXXX; +} + +int +simplec(long b) +{ + + b &= BCLASS; + switch(b) { + case 0: + case BREGISTER: + return CXXX; + case BAUTO: + case BAUTO|BREGISTER: + return CAUTO; + case BEXTERN: + return CEXTERN; + case BEXTERN|BREGISTER: + return CEXREG; + case BSTATIC: + return CSTATIC; + case BTYPEDEF: + return CTYPEDEF; + } + diag(Z, "illegal combination of classes %Q", b); + return CXXX; +} + +Type* +simplet(long b) +{ + + b &= ~BCLASS & ~BGARB; + switch(b) { + case BCHAR: + case BCHAR|BSIGNED: + return types[TCHAR]; + + case BCHAR|BUNSIGNED: + return types[TUCHAR]; + + case BSHORT: + case BSHORT|BINT: + case BSHORT|BSIGNED: + case BSHORT|BINT|BSIGNED: + return types[TSHORT]; + + case BUNSIGNED|BSHORT: + case BUNSIGNED|BSHORT|BINT: + return types[TUSHORT]; + + case 0: + case BINT: + case BINT|BSIGNED: + case BSIGNED: + return types[TINT]; + + case BUNSIGNED: + case BUNSIGNED|BINT: + return types[TUINT]; + + case BLONG: + case BLONG|BINT: + case BLONG|BSIGNED: + case BLONG|BINT|BSIGNED: + return types[TLONG]; + + case BUNSIGNED|BLONG: + case BUNSIGNED|BLONG|BINT: + return types[TULONG]; + + case BVLONG|BLONG: + case BVLONG|BLONG|BINT: + case BVLONG|BLONG|BSIGNED: + case BVLONG|BLONG|BINT|BSIGNED: + return types[TVLONG]; + + case BVLONG|BLONG|BUNSIGNED: + case BVLONG|BLONG|BINT|BUNSIGNED: + return types[TUVLONG]; + + case BFLOAT: + return types[TFLOAT]; + + case BDOUBLE: + case BDOUBLE|BLONG: + case BFLOAT|BLONG: + return types[TDOUBLE]; + + case BVOID: + return types[TVOID]; + } + + diag(Z, "illegal combination of types %Q", b); + return types[TINT]; +} + +int +stcompat(Node *n, Type *t1, Type *t2, long ttab[]) +{ + int i; + ulong b; + + return 0; + i = 0; + if(t2 != T) + i = t2->etype; + b = 1L << i; + i = 0; + if(t1 != T) + i = t1->etype; + if(b & ttab[i]) { + if(ttab == tasign) + if(b == BSTRUCT || b == BUNION) + if(!sametype(t1, t2)) + return 1; + if(n->op != OCAST) + if(b == BIND && i == TIND) + if(!sametype(t1, t2)) + return 1; + return 0; + } + return 1; +} + +int +tcompat(Node *n, Type *t1, Type *t2, long ttab[]) +{ + + if(0 && stcompat(n, t1, t2, ttab)) { + if(t1 == T) + diag(n, "incompatible type: \"%T\" for op \"%O\"", + t2, n->op); + else + diag(n, "incompatible types: \"%T\" and \"%T\" for op \"%O\"", + t1, t2, n->op); + return 1; + } + return 0; +} + +void +makedot(Node *n, Type *t, long o) +{ + USED(n); + USED(o); + USED(t); + return; +} + +Type* +dotsearch(Sym *s, Type *t, Node *n) +{ + Type *t1, *xt; + + xt = T; + + /* + * look it up by name + */ + for(t1 = t; t1 != T; t1 = t1->down) + if(t1->sym == s) { + if(xt != T) + goto ambig; + xt = t1; + } + if(xt != T) + return xt; + + /* + * look it up by type + */ + for(t1 = t; t1 != T; t1 = t1->down) + if(t1->sym == S && typesu[t1->etype]) + if(sametype(s->type, t1)) { + if(xt != T) + goto ambig; + xt = t1; + } + if(xt != T) + return xt; + + /* + * look it up in unnamed substructures + */ + for(t1 = t; t1 != T; t1 = t1->down) + if(t1->sym == S && typesu[t1->etype]) + if(dotsearch(s, t1->link, n) != T) { + if(xt != T) + goto ambig; + xt = t1; + } + return xt; + +ambig: + diag(n, "ambiguous structure element: %s", s->name); + return xt; +} + +long +dotoffset(Type *st, Type *lt, Node *n) +{ + Type *t; + Sym *g; + long o, o1; + + o = -1; + /* + * first try matching at the top level + * for matching tag names + */ + g = st->tag; + if(g != S) + for(t=lt->link; t!=T; t=t->down) + if(t->sym == S) + if(g == t->tag) { + if(o >= 0) + goto ambig; + o = t->offset; + } + if(o >= 0) + return o; + + /* + * second try matching at the top level + * for similar types + */ + for(t=lt->link; t!=T; t=t->down) + if(t->sym == S) + if(sametype(st, t)) { + if(o >= 0) + goto ambig; + o = t->offset; + } + if(o >= 0) + return o; + + /* + * last try matching sub-levels + */ + for(t=lt->link; t!=T; t=t->down) + if(t->sym == S) + if(typesu[t->etype]) { + o1 = dotoffset(st, t, n); + if(o1 >= 0) { + if(o >= 0) + goto ambig; + o = o1 + t->offset; + } + } + return o; + +ambig: + diag(n, "ambiguous unnamed structure element"); + return o; +} + +/* + * look into tree for floating point constant expressions + */ +int +allfloat(Node *n, int flag) +{ + + if(n != Z) { + if(n->type->etype != TDOUBLE) + return 1; + switch(n->op) { + case OCONST: + if(flag) + n->type = types[TFLOAT]; + return 1; + case OADD: /* no need to get more exotic than this */ + case OSUB: + case OMUL: + case ODIV: + if(!allfloat(n->right, flag)) + break; + case OCAST: + if(!allfloat(n->left, flag)) + break; + if(flag) + n->type = types[TFLOAT]; + return 1; + } + } + return 0; +} + +void +constas(Node *n, Type *il, Type *ir) +{ + Type *l, *r; + + l = il; + r = ir; + + if(l == T) + return; + if(l->garb & GCONSTNT) { + warn(n, "assignment to a constant type (%T)", il); + return; + } + if(r == T) + return; + for(;;) { + if(l->etype != TIND || r->etype != TIND) + break; + l = l->link; + r = r->link; + if(l == T || r == T) + break; + if(r->garb & GCONSTNT) + if(!(l->garb & GCONSTNT)) { + warn(n, "assignment of a constant pointer type (%T)", ir); + break; + } + } +} + +void +typeext1(Type *st, Node *l) +{ + if(st->etype == TFLOAT && allfloat(l, 0)) + allfloat(l, 1); +} + +void +typeext(Type *st, Node *l) +{ + Type *lt; + + lt = l->type; + if(lt == T) + return; + if(st->etype == TIND && vconst(l) == 0) { + l->type = st; + l->vconst = 0; + return; + } + typeext1(st, l); +} + +/* + * a cast that generates no code + * (same size move) + */ +int +nocast(Type *t1, Type *t2) +{ + int i, b; + + if(t1->nbits) + return 0; + i = 0; + if(t2 != T) + i = t2->etype; + b = 1<<i; + i = 0; + if(t1 != T) + i = t1->etype; + if(b & ncast[i]) + return 1; + return 0; +} + +/* + * a cast that has a noop semantic + * (small to large, convert) + */ +int +nilcast(Type *t1, Type *t2) +{ + int et1, et2; + + if(t1 == T) + return 0; + if(t1->nbits) + return 0; + if(t2 == T) + return 0; + et1 = t1->etype; + et2 = t2->etype; + if(et1 == et2) + return 1; + if(typefd[et1] && typefd[et2]) { + if(ewidth[et1] < ewidth[et2]) + return 1; + return 0; + } + if(typechlp[et1] && typechlp[et2]) { + if(ewidth[et1] < ewidth[et2]) + return 1; + return 0; + } + return 0; +} + +/* + * "the usual arithmetic conversions are performed" + */ +void +arith(Node *n, int f) +{ + Type *t1, *t2; + int i, j, k; + long w; + + t1 = n->left->type; + if(n->right == Z) + t2 = t1; + else + t2 = n->right->type; + i = TXXX; + if(t1 != T) + i = t1->etype; + j = TXXX; + if(t2 != T) + j = t2->etype; + k = tab[i][j]; + if(k == TIND) { + if(i == TIND) + n->type = t1; + else + if(j == TIND) + n->type = t2; + } else { + /* convert up to at least int */ + if(f == 1) + while(k < TINT) + k += 2; + n->type = types[k]; + } + if(n->op == OSUB) + if(i == TIND && j == TIND) { + w = n->right->type->link->width; + if(w < 1) + goto bad; + n->type = types[TLONG]; + return; + } + if(!sametype(n->type, n->left->type)) { + n->left = new1(OCAST, n->left, Z); + n->left->type = n->type; + } + if(n->right != Z) + if(!sametype(n->type, n->right->type)) { + n->right = new1(OCAST, n->right, Z); + n->right->type = n->type; + } + return; +bad: + diag(n, "pointer addition not fully declared: %T", n->type->link); +} + +int +side(Node *n) +{ + +loop: + if(n != Z) + switch(n->op) { + case OCAST: + case ONOT: + case OADDR: + case OIND: + n = n->left; + goto loop; + + case OCOND: + if(side(n->left)) + break; + n = n->right; + + case OEQ: + case ONE: + case OLT: + case OGE: + case OGT: + case OLE: + case OADD: + case OSUB: + case OMUL: + case OLMUL: + case ODIV: + case OLDIV: + case OLSHR: + case OASHL: + case OASHR: + case OAND: + case OOR: + case OXOR: + case OMOD: + case OLMOD: + case OANDAND: + case OOROR: + case OCOMMA: + case ODOT: + if(side(n->left)) + break; + n = n->right; + goto loop; + + case OSIGN: + case OSIZE: + case OCONST: + case OSTRING: + case OLSTRING: + case ONAME: + return 0; + } + return 1; +} + +int +vconst(Node *n) +{ + int i; + + if(n == Z) + goto no; + if(n->op != OCONST) + goto no; + if(n->type == T) + goto no; + switch(n->type->etype) + { + case TFLOAT: + case TDOUBLE: + i = 100; + if(n->fconst > i || n->fconst < -i) + goto no; + i = n->fconst; + if(i != n->fconst) + goto no; + return i; + + case TVLONG: + case TUVLONG: + i = n->vconst; + if(i != n->vconst) + goto no; + return i; + + case TCHAR: + case TUCHAR: + case TSHORT: + case TUSHORT: + case TINT: + case TUINT: + case TLONG: + case TULONG: + case TIND: + i = n->vconst; + if(i != n->vconst) + goto no; + return i; + } +no: + return -159; /* first uninteresting constant */ +} + +/* + * return log(n) if n is a power of 2 constant + */ +int +vlog(Node *n) +{ + int s, i; + uvlong m, v; + + if(n->op != OCONST) + goto bad; + if(typefd[n->type->etype]) + goto bad; + + v = n->vconst; + + s = 0; + m = MASK(8*sizeof(uvlong)); + for(i=32; i; i>>=1) { + m >>= i; + if(!(v & m)) { + v >>= i; + s += i; + } + } + if(v == 1) + return s; + +bad: + return -1; +} + +int +topbit(ulong v) +{ + int i; + + for(i = -1; v; i++) + v >>= 1; + return i; +} + +/* + * try to cast a constant down + * rather than cast a variable up + * example: + * if(c == 'a') + */ +void +relcon(Node *l, Node *r) +{ + vlong v; + Node *t; + + if(l->op != OCONST) + return; + if(r->op != OCAST) + return; + if(!nilcast(r->left->type, r->type)) + return; + switch(r->type->etype) { + default: + return; + case TCHAR: + case TUCHAR: + case TSHORT: + case TUSHORT: + case TINT: + case TUINT: + case TLONG: + case TULONG: + case TVLONG: + case TUVLONG: + v = convvtox(l->vconst, r->type->etype); + if(v != l->vconst) + return; + break; + } + t = new1(OXXX, Z, Z); + *t = *l; + l->op = OCAST; + l->left = t; + l->right = Z; + l->type = r->left->type; + *r = *r->left; +} + +int +relindex(int o) +{ + + switch(o) { + default: + diag(Z, "bad in relindex: %O", o); + case OEQ: return 0; + case ONE: return 1; + case OLE: return 2; + case OLS: return 3; + case OLT: return 4; + case OLO: return 5; + case OGE: return 6; + case OHS: return 7; + case OGT: return 8; + case OHI: return 9; + } +} + +Node* +invert(Node *n) +{ + Node *i; + + if(n == Z || n->op != OLIST || n->blk) + return n; + i = n; + for(n = n->left; n != Z; n = n->left) { + if(n->op != OLIST || n->blk) + break; + i->left = n->right; + n->right = i; + i = n; + } + i->left = n; + return i; +} + +int +bitno(long b) +{ + int i; + + for(i=0; i<32; i++) + if(b & (1L<<i)) + return i; + diag(Z, "bad in bitno"); + return 0; +} + +long +typebitor(long a, long b) +{ + long c; + + c = a | b; + if(a & b) + if((a & b) == BLONG) + c |= BVLONG; /* long long => vlong */ + else + warn(Z, "once is enough: %Q", a & b); + return c; +} + +void +diag(Node *n, char *fmt, ...) +{ + char buf[STRINGSZ]; + va_list arg; + + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + fprint(2, "%L %s\n", (n==Z)? nearln: n->lineno, buf); + + if(0) + abort(); + if(n != Z) + if(0) + prtree(n, "diagnostic"); + + nerrors++; + if(nerrors > 10) { + fprint(2, "too many errors\n"); + errorexit(); + } +} + +void +warn(Node *n, char *fmt, ...) +{ + char buf[STRINGSZ]; + va_list arg; + + if(0) { + fprint(2, "warning: "); + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + fprint(2, "%L %s\n", (n==Z)? nearln: n->lineno, buf); + + if(n != Z) + if(0) + prtree(n, "warning"); + } +} + +void +yyerror(char *fmt, ...) +{ + char buf[STRINGSZ]; + va_list arg; + + /* + * hack to intercept message from yaccpar + */ + if(strcmp(fmt, "syntax error") == 0) { + yyerror("syntax error, last name: %s", symb); + return; + } + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + fprint(2, "%L %s\n", lineno, buf); + nerrors++; + if(nerrors > 10) { + fprint(2, "too many errors\n"); + errorexit(); + } +} + +void +fatal(Node *n, char *fmt, ...) +{ + char buf[STRINGSZ]; + va_list arg; + + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + fprint(2, "%L %s\n", (n==Z)? nearln: n->lineno, buf); + + if(0) + abort(); + if(n != Z) + if(0) + prtree(n, "diagnostic"); + + nerrors++; + errorexit(); +} + +ulong thash1 = 0x2edab8c9; +ulong thash2 = 0x1dc74fb8; +ulong thash3 = 0x1f241331; +ulong thash[NALLTYPES]; +Init thashinit[] = +{ + TXXX, 0x17527bbd, 0, + TCHAR, 0x5cedd32b, 0, + TUCHAR, 0x552c4454, 0, + TSHORT, 0x63040b4b, 0, + TUSHORT, 0x32a45878, 0, + TINT, 0x4151d5bd, 0, + TUINT, 0x5ae707d6, 0, + TLONG, 0x5ef20f47, 0, + TULONG, 0x36d8eb8f, 0, + TVLONG, 0x6e5e9590, 0, + TUVLONG, 0x75910105, 0, + TFLOAT, 0x25fd7af1, 0, + TDOUBLE, 0x7c40a1b2, 0, + TIND, 0x1b832357, 0, + TFUNC, 0x6babc9cb, 0, + TARRAY, 0x7c50986d, 0, + TVOID, 0x44112eff, 0, + TSTRUCT, 0x7c2da3bf, 0, + TUNION, 0x3eb25e98, 0, + TENUM, 0x44b54f61, 0, + TFILE, 0x19242ac3, 0, + TOLD, 0x22b15988, 0, + TDOT, 0x0204f6b3, 0, + -1, 0, 0, +}; + +char* bnames[NALIGN]; +Init bnamesinit[] = +{ + Axxx, 0, "Axxx", + Ael1, 0, "el1", + Ael2, 0, "el2", + Asu2, 0, "su2", + Aarg0, 0, "arg0", + Aarg1, 0, "arg1", + Aarg2, 0, "arg2", + Aaut3, 0, "aut3", + -1, 0, 0, +}; + +char* tnames[NALLTYPES]; +Init tnamesinit[] = +{ + TXXX, 0, "xxx", + TCHAR, 0, "char", + TUCHAR, 0, "uchar", + TSHORT, 0, "short", + TUSHORT, 0, "ushort", + TINT, 0, "int", + TUINT, 0, "uint", + TLONG, 0, "long", + TULONG, 0, "ulong", + TVLONG, 0, "vlong", + TUVLONG, 0, "uvlong", + TFLOAT, 0, "float", + TDOUBLE, 0, "double", + TIND, 0, "pointer", + TFUNC, 0, "function", + TARRAY, 0, "array", + TVOID, 0, "void", + TSTRUCT, 0, "struct", + TUNION, 0, "union", + TENUM, 0, "enum", + TFILE, 0, "file", + TOLD, 0, "old", + TDOT, 0, "dot", + TSTRING, 0, "string", + TFD, 0, "fd", + TTUPLE, 0, "tuple", + -1, 0, 0, +}; + +char* gnames[NGTYPES]; +Init gnamesinit[] = +{ + GXXX, 0, "GXXX", + GCONSTNT, 0, "CONST", + GVOLATILE, 0, "VOLATILE", + GVOLATILE|GCONSTNT, 0, "CONST-VOLATILE", + -1, 0, 0, +}; + +char* qnames[NALLTYPES]; +Init qnamesinit[] = +{ + TXXX, 0, "TXXX", + TCHAR, 0, "CHAR", + TUCHAR, 0, "UCHAR", + TSHORT, 0, "SHORT", + TUSHORT, 0, "USHORT", + TINT, 0, "INT", + TUINT, 0, "UINT", + TLONG, 0, "LONG", + TULONG, 0, "ULONG", + TVLONG, 0, "VLONG", + TUVLONG, 0, "UVLONG", + TFLOAT, 0, "FLOAT", + TDOUBLE, 0, "DOUBLE", + TIND, 0, "IND", + TFUNC, 0, "FUNC", + TARRAY, 0, "ARRAY", + TVOID, 0, "VOID", + TSTRUCT, 0, "STRUCT", + TUNION, 0, "UNION", + TENUM, 0, "ENUM", + + TAUTO, 0, "AUTO", + TEXTERN, 0, "EXTERN", + TSTATIC, 0, "STATIC", + TTYPEDEF, 0, "TYPEDEF", + TREGISTER, 0, "REGISTER", + TCONSTNT, 0, "CONSTNT", + TVOLATILE, 0, "VOLATILE", + TUNSIGNED, 0, "UNSIGNED", + TSIGNED, 0, "SIGNED", + TDOT, 0, "DOT", + TFILE, 0, "FILE", + TOLD, 0, "OLD", + -1, 0, 0, +}; +char* cnames[NCTYPES]; +Init cnamesinit[] = +{ + CXXX, 0, "CXXX", + CAUTO, 0, "AUTO", + CEXTERN, 0, "EXTERN", + CGLOBL, 0, "GLOBL", + CSTATIC, 0, "STATIC", + CLOCAL, 0, "LOCAL", + CTYPEDEF, 0, "TYPEDEF", + CPARAM, 0, "PARAM", + CSELEM, 0, "SELEM", + CLABEL, 0, "LABEL", + CEXREG, 0, "EXREG", + -1, 0, 0, +}; + +char* onames[OEND+1]; +Init onamesinit[] = +{ + ONOOP, 0, "NOOP", + OXXX, 0, "OXXX", + OADD, 0, "ADD", + OADDR, 0, "ADDR", + OAND, 0, "AND", + OANDAND, 0, "ANDAND", + OARRAY, 0, "ARRAY", + OAS, 0, "AS", + OASI, 0, "ASI", + OASADD, 0, "ASADD", + OASAND, 0, "ASAND", + OASASHL, 0, "ASASHL", + OASASHR, 0, "ASASHR", + OASDIV, 0, "ASDIV", + OASHL, 0, "ASHL", + OASHR, 0, "ASHR", + OASLDIV, 0, "ASLDIV", + OASLMOD, 0, "ASLMOD", + OASLMUL, 0, "ASLMUL", + OASLSHR, 0, "ASLSHR", + OASMOD, 0, "ASMOD", + OASMUL, 0, "ASMUL", + OASOR, 0, "ASOR", + OASSUB, 0, "ASSUB", + OASXOR, 0, "ASXOR", + OBIT, 0, "BIT", + OBREAK, 0, "BREAK", + OCASE, 0, "CASE", + OCAST, 0, "CAST", + OCOMMA, 0, "COMMA", + OCOND, 0, "COND", + OCONST, 0, "CONST", + OCONTINUE, 0, "CONTINUE", + ODIV, 0, "DIV", + ODOT, 0, "DOT", + ODOTDOT, 0, "DOTDOT", + ODWHILE, 0, "DWHILE", + OENUM, 0, "ENUM", + OEQ, 0, "EQ", + OFOR, 0, "FOR", + OFUNC, 0, "FUNC", + OGE, 0, "GE", + OGOTO, 0, "GOTO", + OGT, 0, "GT", + OHI, 0, "HI", + OHS, 0, "HS", + OIF, 0, "IF", + OIND, 0, "IND", + OINDREG, 0, "INDREG", + OINIT, 0, "INIT", + OLABEL, 0, "LABEL", + OLDIV, 0, "LDIV", + OLE, 0, "LE", + OLIST, 0, "LIST", + OLMOD, 0, "LMOD", + OLMUL, 0, "LMUL", + OLO, 0, "LO", + OLS, 0, "LS", + OLSHR, 0, "LSHR", + OLT, 0, "LT", + OMOD, 0, "MOD", + OMUL, 0, "MUL", + ONAME, 0, "NAME", + ONE, 0, "NE", + ONOT, 0, "NOT", + OOR, 0, "OR", + OOROR, 0, "OROR", + OPOSTDEC, 0, "POSTDEC", + OPOSTINC, 0, "POSTINC", + OPREDEC, 0, "PREDEC", + OPREINC, 0, "PREINC", + OPROTO, 0, "PROTO", + OREGISTER, 0, "REGISTER", + ORETURN, 0, "RETURN", + OSET, 0, "SET", + OSIGN, 0, "SIGN", + OSIZE, 0, "SIZE", + OSTRING, 0, "STRING", + OLSTRING, 0, "LSTRING", + OSTRUCT, 0, "STRUCT", + OSUB, 0, "SUB", + OSWITCH, 0, "SWITCH", + OUNION, 0, "UNION", + OUSED, 0, "USED", + OWHILE, 0, "WHILE", + OXOR, 0, "XOR", + ONEG, 0, "NEG", + OCOM, 0, "COM", + OELEM, 0, "ELEM", + OTST, 0, "TST", + OINDEX, 0, "INDEX", + OFAS, 0, "FAS", + OBLK, 0, "BLK", + OPOS, 0, "POS", + ONUL, 0, "NUL", + ODOTIND, 0, "DOTIND", + OARRIND, 0, "ARRIND", + ODAS, 0, "ODAS", + OASD, 0, "OASD", + OIOTA, 0, "IOTA", + OLEN, 0, "LEN", + OBRACKET, 0, "BRACKET", + OREF, 0, "REF", + OARRAYOF, 0, "ARRAYOF", + OSLICE, 0, "SLICE", + OSADDR, 0, "SADDR", + ONIL, 0, "NIL", + OS2AB, 0, "S2AB", + OAB2S, 0, "AB2S", + OFILDES, 0, "FILDES", + OFD, 0, "FD", + OTUPLE, 0, "TUPLE", + OT0, 0, "T0", + ORETV, 0, "RETV", + OCAT, 0, "CAT", + OSBREAK, 0, "SBREAK", + OLDOT, 0, "LDOT", + OMDOT, 0, "MDOT", + OCODE, 0, "CODE", + ODECE, 0, "DECE", + ODECT, 0, "DECT", + ODECV, 0, "DECV", + ODECF, 0, "DECF", + OPUSH, 0, "PUSH", + OPOP, 0, "POP", + OEND, 0, "END", + -1, 0, 0, +}; + +char comrel[12] = +{ + ONE, OEQ, OGT, OHI, OGE, OHS, OLT, OLO, OLE, OLS, +}; +char invrel[12] = +{ + OEQ, ONE, OGE, OHS, OGT, OHI, OLE, OLS, OLT, OLO, +}; +char logrel[12] = +{ + OEQ, ONE, OLS, OLS, OLO, OLO, OHS, OHS, OHI, OHI, +}; + +char typei[NTYPE]; +int typeiinit[] = +{ + TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TVLONG, TUVLONG, -1, +}; +char typeu[NTYPE]; +int typeuinit[] = +{ + TUCHAR, TUSHORT, TUINT, TULONG, TUVLONG, TIND, -1, +}; + +char typesuv[NTYPE]; +int typesuvinit[] = +{ + TVLONG, TUVLONG, TSTRUCT, TUNION, -1, +}; + +char typeilp[NTYPE]; +int typeilpinit[] = +{ + TINT, TUINT, TLONG, TULONG, TIND, -1 +}; + +char typechl[NTYPE]; +int typechlinit[] = +{ + TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, -1, +}; + +char typechlp[NTYPE]; +int typechlpinit[] = +{ + TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TIND, -1, +}; + +char typechlpfd[NTYPE]; +int typechlpfdinit[] = +{ + TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TFLOAT, TDOUBLE, TIND, -1, +}; + +char typec[NTYPE]; +int typecinit[] = +{ + TCHAR, TUCHAR, -1 +}; + +char typeh[NTYPE]; +int typehinit[] = +{ + TSHORT, TUSHORT, -1, +}; + +char typeil[NTYPE]; +int typeilinit[] = +{ + TINT, TUINT, TLONG, TULONG, -1, +}; + +char typev[NTYPE]; +int typevinit[] = +{ + TVLONG, TUVLONG, -1, +}; + +char typefd[NTYPE]; +int typefdinit[] = +{ + TFLOAT, TDOUBLE, -1, +}; + +char typeaf[NTYPE]; +int typeafinit[] = +{ + TFUNC, TARRAY, -1, +}; + +char typesu[NTYPE]; +int typesuinit[] = +{ + TSTRUCT, TUNION, -1, +}; + +long tasign[NTYPE]; +Init tasigninit[] = +{ + TCHAR, BNUMBER, 0, + TUCHAR, BNUMBER, 0, + TSHORT, BNUMBER, 0, + TUSHORT, BNUMBER, 0, + TINT, BNUMBER, 0, + TUINT, BNUMBER, 0, + TLONG, BNUMBER, 0, + TULONG, BNUMBER, 0, + TVLONG, BNUMBER, 0, + TUVLONG, BNUMBER, 0, + TFLOAT, BNUMBER, 0, + TDOUBLE, BNUMBER, 0, + TIND, BIND, 0, + TSTRUCT, BSTRUCT, 0, + TUNION, BUNION, 0, + -1, 0, 0, +}; + +long tasadd[NTYPE]; +Init tasaddinit[] = +{ + TCHAR, BNUMBER, 0, + TUCHAR, BNUMBER, 0, + TSHORT, BNUMBER, 0, + TUSHORT, BNUMBER, 0, + TINT, BNUMBER, 0, + TUINT, BNUMBER, 0, + TLONG, BNUMBER, 0, + TULONG, BNUMBER, 0, + TVLONG, BNUMBER, 0, + TUVLONG, BNUMBER, 0, + TFLOAT, BNUMBER, 0, + TDOUBLE, BNUMBER, 0, + TIND, BINTEGER, 0, + -1, 0, 0, +}; + +long tcast[NTYPE]; +Init tcastinit[] = +{ + TCHAR, BNUMBER|BIND|BVOID, 0, + TUCHAR, BNUMBER|BIND|BVOID, 0, + TSHORT, BNUMBER|BIND|BVOID, 0, + TUSHORT, BNUMBER|BIND|BVOID, 0, + TINT, BNUMBER|BIND|BVOID, 0, + TUINT, BNUMBER|BIND|BVOID, 0, + TLONG, BNUMBER|BIND|BVOID, 0, + TULONG, BNUMBER|BIND|BVOID, 0, + TVLONG, BNUMBER|BIND|BVOID, 0, + TUVLONG, BNUMBER|BIND|BVOID, 0, + TFLOAT, BNUMBER|BVOID, 0, + TDOUBLE, BNUMBER|BVOID, 0, + TIND, BINTEGER|BIND|BVOID, 0, + TVOID, BVOID, 0, + TSTRUCT, BSTRUCT|BVOID, 0, + TUNION, BUNION|BVOID, 0, + -1, 0, 0, +}; + +long tadd[NTYPE]; +Init taddinit[] = +{ + TCHAR, BNUMBER|BIND, 0, + TUCHAR, BNUMBER|BIND, 0, + TSHORT, BNUMBER|BIND, 0, + TUSHORT, BNUMBER|BIND, 0, + TINT, BNUMBER|BIND, 0, + TUINT, BNUMBER|BIND, 0, + TLONG, BNUMBER|BIND, 0, + TULONG, BNUMBER|BIND, 0, + TVLONG, BNUMBER|BIND, 0, + TUVLONG, BNUMBER|BIND, 0, + TFLOAT, BNUMBER, 0, + TDOUBLE, BNUMBER, 0, + TIND, BINTEGER, 0, + -1, 0, 0, +}; + +long tsub[NTYPE]; +Init tsubinit[] = +{ + TCHAR, BNUMBER, 0, + TUCHAR, BNUMBER, 0, + TSHORT, BNUMBER, 0, + TUSHORT, BNUMBER, 0, + TINT, BNUMBER, 0, + TUINT, BNUMBER, 0, + TLONG, BNUMBER, 0, + TULONG, BNUMBER, 0, + TVLONG, BNUMBER, 0, + TUVLONG, BNUMBER, 0, + TFLOAT, BNUMBER, 0, + TDOUBLE, BNUMBER, 0, + TIND, BINTEGER|BIND, 0, + -1, 0, 0, +}; + +long tmul[NTYPE]; +Init tmulinit[] = +{ + TCHAR, BNUMBER, 0, + TUCHAR, BNUMBER, 0, + TSHORT, BNUMBER, 0, + TUSHORT, BNUMBER, 0, + TINT, BNUMBER, 0, + TUINT, BNUMBER, 0, + TLONG, BNUMBER, 0, + TULONG, BNUMBER, 0, + TVLONG, BNUMBER, 0, + TUVLONG, BNUMBER, 0, + TFLOAT, BNUMBER, 0, + TDOUBLE, BNUMBER, 0, + -1, 0, 0, +}; + +long tand[NTYPE]; +Init tandinit[] = +{ + TCHAR, BINTEGER, 0, + TUCHAR, BINTEGER, 0, + TSHORT, BINTEGER, 0, + TUSHORT, BINTEGER, 0, + TINT, BNUMBER, 0, + TUINT, BNUMBER, 0, + TLONG, BINTEGER, 0, + TULONG, BINTEGER, 0, + TVLONG, BINTEGER, 0, + TUVLONG, BINTEGER, 0, + -1, 0, 0, +}; + +long trel[NTYPE]; +Init trelinit[] = +{ + TCHAR, BNUMBER, 0, + TUCHAR, BNUMBER, 0, + TSHORT, BNUMBER, 0, + TUSHORT, BNUMBER, 0, + TINT, BNUMBER, 0, + TUINT, BNUMBER, 0, + TLONG, BNUMBER, 0, + TULONG, BNUMBER, 0, + TVLONG, BNUMBER, 0, + TUVLONG, BNUMBER, 0, + TFLOAT, BNUMBER, 0, + TDOUBLE, BNUMBER, 0, + TIND, BIND, 0, + -1, 0, 0, +}; + +long tfunct[1] = +{ + BFUNC, +}; + +long tindir[1] = +{ + BIND, +}; + +long tdot[1] = +{ + BSTRUCT|BUNION, +}; + +long tnot[1] = +{ + BNUMBER|BIND, +}; + +long targ[1] = +{ + BNUMBER|BIND|BSTRUCT|BUNION, +}; + +char tab[NTYPE][NTYPE] = +{ +/*TXXX*/ { 0, + }, + +/*TCHAR*/ { 0, TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, + TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TUCHAR*/ { 0, TUCHAR, TUCHAR, TUSHORT, TUSHORT, TUINT, TUINT, TULONG, + TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TSHORT*/ { 0, TSHORT, TUSHORT, TSHORT, TUSHORT, TINT, TUINT, TLONG, + TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TUSHORT*/ { 0, TUSHORT, TUSHORT, TUSHORT, TUSHORT, TUINT, TUINT, TULONG, + TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TINT*/ { 0, TINT, TUINT, TINT, TUINT, TINT, TUINT, TLONG, + TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TUINT*/ { 0, TUINT, TUINT, TUINT, TUINT, TUINT, TUINT, TULONG, + TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TLONG*/ { 0, TLONG, TULONG, TLONG, TULONG, TLONG, TULONG, TLONG, + TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TULONG*/ { 0, TULONG, TULONG, TULONG, TULONG, TULONG, TULONG, TULONG, + TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TVLONG*/ { 0, TVLONG, TUVLONG, TVLONG, TUVLONG, TVLONG, TUVLONG, TVLONG, + TUVLONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TUVLONG*/ { 0, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, + TUVLONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND, + }, +/*TFLOAT*/ { 0, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, + TFLOAT, TFLOAT, TFLOAT, TFLOAT, TDOUBLE, TIND, + }, +/*TDOUBLE*/ { 0, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, + TDOUBLE, TDOUBLE, TDOUBLE, TFLOAT, TDOUBLE, TIND, + }, +/*TIND*/ { 0, TIND, TIND, TIND, TIND, TIND, TIND, TIND, + TIND, TIND, TIND, TIND, TIND, TIND, + }, +}; + +void +urk(char *name, int max, int i) +{ + if(i >= max) { + fprint(2, "bad tinit: %s %d>=%d\n", name, i, max); + exits("init"); + } +} + +void +tinit(void) +{ + int i; + Init *p; + + for(p=thashinit; p->code >= 0; p++) { + urk("thash", nelem(thash), p->code); + thash[p->code] = p->value; + } + for(p=bnamesinit; p->code >= 0; p++) { + urk("bnames", nelem(bnames), p->code); + bnames[p->code] = p->s; + } + for(p=tnamesinit; p->code >= 0; p++) { + urk("tnames", nelem(tnames), p->code); + tnames[p->code] = p->s; + } + for(p=gnamesinit; p->code >= 0; p++) { + urk("gnames", nelem(gnames), p->code); + gnames[p->code] = p->s; + } + for(p=qnamesinit; p->code >= 0; p++) { + urk("qnames", nelem(qnames), p->code); + qnames[p->code] = p->s; + } + for(p=cnamesinit; p->code >= 0; p++) { + urk("cnames", nelem(cnames), p->code); + cnames[p->code] = p->s; + } + for(p=onamesinit; p->code >= 0; p++) { + urk("onames", nelem(onames), p->code); + onames[p->code] = p->s; + } + for(i=0; typeiinit[i] >= 0; i++) { + urk("typei", nelem(typei), typeiinit[i]); + typei[typeiinit[i]] = 1; + } + for(i=0; typeuinit[i] >= 0; i++) { + urk("typeu", nelem(typeu), typeuinit[i]); + typeu[typeuinit[i]] = 1; + } + for(i=0; typesuvinit[i] >= 0; i++) { + urk("typesuv", nelem(typesuv), typesuvinit[i]); + typesuv[typesuvinit[i]] = 1; + } + for(i=0; typeilpinit[i] >= 0; i++) { + urk("typeilp", nelem(typeilp), typeilpinit[i]); + typeilp[typeilpinit[i]] = 1; + } + for(i=0; typechlinit[i] >= 0; i++) { + urk("typechl", nelem(typechl), typechlinit[i]); + typechl[typechlinit[i]] = 1; + } + for(i=0; typechlpinit[i] >= 0; i++) { + urk("typechlp", nelem(typechlp), typechlpinit[i]); + typechlp[typechlpinit[i]] = 1; + } + for(i=0; typechlpfdinit[i] >= 0; i++) { + urk("typechlpfd", nelem(typechlpfd), typechlpfdinit[i]); + typechlpfd[typechlpfdinit[i]] = 1; + } + for(i=0; typecinit[i] >= 0; i++) { + urk("typec", nelem(typec), typecinit[i]); + typec[typecinit[i]] = 1; + } + for(i=0; typehinit[i] >= 0; i++) { + urk("typeh", nelem(typeh), typehinit[i]); + typeh[typehinit[i]] = 1; + } + for(i=0; typeilinit[i] >= 0; i++) { + urk("typeil", nelem(typeil), typeilinit[i]); + typeil[typeilinit[i]] = 1; + } + for(i=0; typevinit[i] >= 0; i++) { + urk("typev", nelem(typev), typevinit[i]); + typev[typevinit[i]] = 1; + } + for(i=0; typefdinit[i] >= 0; i++) { + urk("typefd", nelem(typefd), typefdinit[i]); + typefd[typefdinit[i]] = 1; + } + for(i=0; typeafinit[i] >= 0; i++) { + urk("typeaf", nelem(typeaf), typeafinit[i]); + typeaf[typeafinit[i]] = 1; + } + for(i=0; typesuinit[i] >= 0; i++) { + urk("typesu", nelem(typesu), typesuinit[i]); + typesu[typesuinit[i]] = 1; + } + for(p=tasigninit; p->code >= 0; p++) { + urk("tasign", nelem(tasign), p->code); + tasign[p->code] = p->value; + } + for(p=tasaddinit; p->code >= 0; p++) { + urk("tasadd", nelem(tasadd), p->code); + tasadd[p->code] = p->value; + } + for(p=tcastinit; p->code >= 0; p++) { + urk("tcast", nelem(tcast), p->code); + tcast[p->code] = p->value; + } + for(p=taddinit; p->code >= 0; p++) { + urk("tadd", nelem(tadd), p->code); + tadd[p->code] = p->value; + } + for(p=tsubinit; p->code >= 0; p++) { + urk("tsub", nelem(tsub), p->code); + tsub[p->code] = p->value; + } + for(p=tmulinit; p->code >= 0; p++) { + urk("tmul", nelem(tmul), p->code); + tmul[p->code] = p->value; + } + for(p=tandinit; p->code >= 0; p++) { + urk("tand", nelem(tand), p->code); + tand[p->code] = p->value; + } + for(p=trelinit; p->code >= 0; p++) { + urk("trel", nelem(trel), p->code); + trel[p->code] = p->value; + } +} |
