diff options
author | Rob Pike <r@golang.org> | 2008-06-04 14:46:07 -0700 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2008-06-04 14:46:07 -0700 |
commit | 5cf1e37b96825023b2da8de9be3a07d1987bb306 (patch) | |
tree | fda9e615c7d6ddb748cee567027fae05ba9215ae /src/old/c/subr.c | |
parent | 0a2697043d69739b27b6ba872b2092a4c2bb61a8 (diff) | |
download | golang-5cf1e37b96825023b2da8de9be3a07d1987bb306.tar.gz |
move old code into 'old' directory
add src/test dir
SVN=121166
Diffstat (limited to 'src/old/c/subr.c')
-rw-r--r-- | src/old/c/subr.c | 1522 |
1 files changed, 1522 insertions, 0 deletions
diff --git a/src/old/c/subr.c b/src/old/c/subr.c new file mode 100644 index 000000000..1bb6ac520 --- /dev/null +++ b/src/old/c/subr.c @@ -0,0 +1,1522 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "go.h" +#include "y.tab.h" + +void +errorexit(void) +{ + if(outfile) + remove(outfile); + myexit(1); +} + +void +myexit(int x) +{ + if(x) + exits("error"); + exits(nil); +} + +void +yyerror(char *fmt, ...) +{ + va_list arg; + long lno; + + lno = dynlineno; + if(lno == 0) + lno = curio.lineno; + + print("%s:%ld: ", curio.infile, lno); + va_start(arg, fmt); + vfprint(1, fmt, arg); + va_end(arg); + print("\n"); + if(debug['h']) + *(int*)0 = 0; + + nerrors++; + if(nerrors >= 10) + fatal("too many errors"); +} + +void +warn(char *fmt, ...) +{ + va_list arg; + long lno; + + lno = dynlineno; + if(lno == 0) + lno = curio.lineno; + + print("%s:%ld: ", curio.infile, lno); + va_start(arg, fmt); + vfprint(1, fmt, arg); + va_end(arg); + print("\n"); + if(debug['h']) + *(int*)0 = 0; +} + +void +fatal(char *fmt, ...) +{ + va_list arg; + long lno; + + lno = dynlineno; + if(lno == 0) + lno = curio.lineno; + + print("%s:%ld: fatal error: ", curio.infile, lno); + va_start(arg, fmt); + vfprint(1, fmt, arg); + va_end(arg); + print("\n"); + if(debug['h']) + *(int*)0 = 0; + myexit(1); +} + +ulong +stringhash(char *p) +{ + long h; + int c; + + h = 0; + for(;;) { + c = *p++; + if(c == 0) + break; + h = h*PRIME1 + c; + } + + if(h < 0) { + h = -h; + if(h < 0) + h = 0; + } + return h; +} + +Sym* +lookup(char *p) +{ + Sym *s; + ulong h; + int c; + + h = stringhash(p) % NHASH; + c = p[0]; + + for(s = hash[h]; s != S; s = s->link) { + if(s->name[0] != c) + continue; + if(strcmp(s->name, p) == 0) + if(strcmp(s->package, package) == 0) + return s; + } + + s = mal(sizeof(*s)); + s->lexical = LNAME; + s->name = mal(strlen(p)+1); + s->opackage = package; + s->package = package; + + strcpy(s->name, p); + + s->link = hash[h]; + hash[h] = s; + + return s; +} + +Sym* +pkglookup(char *p, char *k) +{ + Sym *s; + ulong h; + int c; + + h = stringhash(p) % NHASH; + c = p[0]; + for(s = hash[h]; s != S; s = s->link) { + if(s->name[0] != c) + continue; + if(strcmp(s->name, p) == 0) + if(strcmp(s->package, k) == 0) + return s; + } + + s = mal(sizeof(*s)); + s->lexical = LNAME; + s->name = mal(strlen(p)+1); + strcpy(s->name, p); + + s->package = mal(strlen(k)+1); + s->opackage = s->package; + strcpy(s->package, k); + + s->link = hash[h]; + hash[h] = s; + + return s; +} + +void +gethunk(void) +{ + char *h; + long nh; + + nh = NHUNK; + if(thunk >= 10L*NHUNK) + nh = 10L*NHUNK; + h = (char*)malloc(nh); + if(h == (char*)-1) { + yyerror("out of memory"); + errorexit(); + } + hunk = h; + nhunk = nh; + thunk += nh; +} + +void* +mal(long n) +{ + void *p; + + while((ulong)hunk & MAXALIGN) { + hunk++; + nhunk--; + } + while(nhunk < n) + gethunk(); + + p = hunk; + nhunk -= n; + hunk += n; + memset(p, 0, n); + return p; +} + +void* +remal(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; +} + +Dcl* +dcl(void) +{ + Dcl *d; + + d = mal(sizeof(*d)); + d->lineno = dynlineno; + return d; +} + +Node* +nod(int op, Node *nleft, Node *nright) +{ + Node *n; + + n = mal(sizeof(*n)); + n->op = op; + n->left = nleft; + n->right = nright; + n->lineno = dynlineno; + if(dynlineno == 0) + n->lineno = curio.lineno; + return n; +} + +Node* +dobad(void) +{ + return nod(OBAD, N, N); +} + +Node* +rev(Node *na) +{ + Node *i, *n; + + /* + * since yacc wants to build lists + * stacked down on the left - + * this routine converts them to + * stack down on the right - + * in memory without recursion + */ + + if(na == N || na->op != OLIST) + return na; + i = na; + for(n = na->left; n != N; n = n->left) { + if(n->op != OLIST) + break; + i->left = n->right; + n->right = i; + i = n; + } + i->left = n; + return i; +} + +Node* +unrev(Node *na) +{ + Node *i, *n; + + /* + * this restores a reverse list + */ + if(na == N || na->op != OLIST) + return na; + i = na; + for(n = na->right; n != N; n = n->right) { + if(n->op != OLIST) + break; + i->right = n->left; + n->left = i; + i = n; + } + i->right = n; + return i; +} + +Node* +aindex(Node *b, Node *t) +{ + Node *r; + + r = nod(OTYPE, N, N); + r->type = t; + r->etype = TARRAY; + + if(t->etype == TDARRAY) + yyerror("dynamic array type cannot be a dynamic array"); + + walktype(b, 0); + switch(whatis(b)) { + default: + yyerror("array bound must be a constant integer expression"); + break; + + case Wnil: // default zero lb + r->bound = 0; + break; + + case Wlitint: // fixed lb + r->bound = b->val.vval; + break; + } + return r; +} + +void +indent(int dep) +{ + int i; + + for(i=0; i<dep; i++) + print(". "); +} + +void +dodump(Node *n, int dep) +{ + +loop: + if(n == N) + return; + + switch(n->op) { + case OLIST: + if(n->left != N && n->left->op == OLIST) + dodump(n->left, dep+1); + else + dodump(n->left, dep); + n = n->right; + goto loop; + + case ODCLFUNC: + dodump(n->nname, dep); + if(n->this) { + indent(dep); + print("%O-this\n", n->op); + dodump(n->this, dep+1); + } + if(n->argout) { + indent(dep); + print("%O-outarg\n", n->op); + dodump(n->argout, dep+1); + } + if(n->argin) { + indent(dep); + print("%O-inarg\n", n->op); + dodump(n->argin, dep+1); + } + n = n->nbody; + goto loop; + + case OIF: + case OSWITCH: + case OFOR: + dodump(n->ninit, dep); + break; + } + + indent(dep); + if(dep > 10) { + print("...\n"); + return; + } + + switch(n->op) { + default: + print("%N\n", n); + break; + + case OTYPE: + print("%O-%E %lT\n", n->op, n->etype, n); + break; + + case OIF: + print("%O%J\n", n->op, n); + dodump(n->ntest, dep+1); + if(n->nbody != N) { + indent(dep); + print("%O-then\n", n->op); + dodump(n->nbody, dep+1); + } + if(n->nelse != N) { + indent(dep); + print("%O-else\n", n->op); + dodump(n->nelse, dep+1); + } + return; + + case OSWITCH: + case OFOR: + print("%O%J\n", n->op, n); + dodump(n->ntest, dep+1); + + if(n->nbody != N) { + indent(dep); + print("%O-body\n", n->op); + dodump(n->nbody, dep+1); + } + + if(n->nincr != N) { + indent(dep); + print("%O-incr\n", n->op); + dodump(n->nincr, dep+1); + } + return; + + case OCASE: + // the right side points to the next case + print("%O%J\n", n->op, n); + dodump(n->left, dep+1); + return; + } + + dodump(n->left, dep+1); + n = n->right; + dep++; + goto loop; +} + +void +dump(char *s, Node *n) +{ + print("%s\n", s); + dodump(n, 1); +} + +int +whatis(Node *n) +{ + Node *t; + + if(n == N) + return Wnil; + + if(n->op == OLITERAL) { + switch(n->val.ctype) { + default: + break; + case CTINT: + case CTSINT: + case CTUINT: + return Wlitint; + case CTFLT: + return Wlitfloat; + case CTBOOL: + return Wlitbool; + case CTSTR: + return Wlitstr; + } + return Wtunkn; + } + + t = n->type; + if(t == N) + return Wtnil; + + switch(t->etype) { + case TINT8: + case TINT16: + case TINT32: + case TINT64: + case TUINT8: + case TUINT16: + case TUINT32: + case TUINT64: + return Wtint; + case TFLOAT32: + case TFLOAT64: + case TFLOAT80: + return Wtfloat; + case TBOOL: + return Wtbool; + + case TPTR: + if(isptrto(t, TSTRING)) + return Wtstr; + break; + } + return Wtunkn; +} + +/* +s%,%,\n%g +s%\n+%\n%g +s%^[ ]*O%%g +s%,.*%%g +s%.+% [O&] = "&",%g +s%^ ........*\]%&~%g +s%~ %%g +*/ + +static char* +opnames[] = +{ + [OADDR] = "ADDR", + [OADD] = "ADD", + [OANDAND] = "ANDAND", + [OAND] = "AND", + [OARRAY] = "ARRAY", + [OASOP] = "ASOP", + [OAS] = "AS", + [OBAD] = "BAD", + [OBREAK] = "BREAK", + [OCALL] = "CALL", + [OCALLPTR] = "CALLPTR", + [OCALLMETH] = "CALLMETH", + [OCALLINTER] = "CALLINTER", + [OCAT] = "CAT", + [OCASE] = "CASE", + [OXCASE] = "XCASE", + [OFALL] = "FALL", + [OCONV] = "CONV", + [OCOM] = "COM", + [OCONST] = "CONST", + [OCONTINUE] = "CONTINUE", + [ODCLARG] = "DCLARG", + [ODCLFIELD] = "DCLFIELD", + [ODCLFUNC] = "DCLFUNC", + [ODIV] = "DIV", + [ODOT] = "DOT", + [ODOTPTR] = "DOTPTR", + [ODOTMETH] = "DOTMETH", + [ODOTINTER] = "DOTINTER", + [OEMPTY] = "EMPTY", + [OEND] = "END", + [OEQ] = "EQ", + [OFOR] = "FOR", + [OFUNC] = "FUNC", + [OGE] = "GE", + [OPROC] = "PROC", + [OGOTO] = "GOTO", + [OGT] = "GT", + [OIF] = "IF", + [OINDEX] = "INDEX", + [OINDEXPTR] = "INDEXPTR", + [OINDEXSTR] = "INDEXSTR", + [OINDEXPTRSTR] = "INDEXPTRSTR", + [OINDEXMAP] = "INDEXMAP", + [OINDEXPTRMAP] = "INDEXPTRMAP", + [OIND] = "IND", + [OLABEL] = "LABEL", + [OLE] = "LE", + [OLEN] = "LEN", + [OLIST] = "LIST", + [OLITERAL] = "LITERAL", + [OLSH] = "LSH", + [OLT] = "LT", + [OMINUS] = "MINUS", + [OMOD] = "MOD", + [OMUL] = "MUL", + [ONAME] = "NAME", + [ONE] = "NE", + [ONOT] = "NOT", + [OOROR] = "OROR", + [OOR] = "OR", + [OPLUS] = "PLUS", + [ODEC] = "DEC", + [OINC] = "INC", + [OSEND] = "SEND", + [ORECV] = "RECV", + [OPTR] = "PTR", + [ORETURN] = "RETURN", + [ORSH] = "RSH", + [OSLICE] = "SLICE", + [OSLICESTR] = "SLICESTR", + [OSLICEPTRSTR] = "SLICEPTRSTR", + [OSUB] = "SUB", + [OSWITCH] = "SWITCH", + [OTYPE] = "TYPE", + [OVAR] = "VAR", + [OEXPORT] = "EXPORT", + [OIMPORT] = "IMPORT", + [OXOR] = "XOR", + [ONEW] = "NEW", + [OFALL] = "FALL", + [OXFALL] = "XFALL", + [OPANIC] = "PANIC", + [OPRINT] = "PRINT", + [OXXX] = "XXX", +}; + +int +Oconv(Fmt *fp) +{ + char buf[500]; + int o; + + o = va_arg(fp->args, int); + if(o < 0 || o >= nelem(opnames) || opnames[o] == nil) { + snprint(buf, sizeof(buf), "O-%d", o); + return fmtstrcpy(fp, buf); + } + return fmtstrcpy(fp, opnames[o]); +} + +/* +s%,%,\n%g +s%\n+%\n%g +s%^[ ]*T%%g +s%,.*%%g +s%.+% [T&] = "&",%g +s%^ ........*\]%&~%g +s%~ %%g +*/ + +static char* +etnames[] = +{ + [TINT8] = "INT8", + [TUINT8] = "UINT8", + [TINT16] = "INT16", + [TUINT16] = "UINT16", + [TINT32] = "INT32", + [TUINT32] = "UINT32", + [TINT64] = "INT64", + [TUINT64] = "UINT64", + [TFLOAT32] = "FLOAT32", + [TFLOAT64] = "FLOAT64", + [TFLOAT80] = "FLOAT80", + [TBOOL] = "BOOL", + [TPTR] = "PTR", + [TFUNC] = "FUNC", + [TARRAY] = "ARRAY", + [TDARRAY] = "DARRAY", + [TSTRUCT] = "STRUCT", + [TCHAN] = "CHAN", + [TMAP] = "MAP", + [TINTER] = "INTER", + [TFORW] = "FORW", + [TFIELD] = "FIELD", + [TSTRING] = "STRING", + [TCHAN] = "CHAN", +}; + +int +Econv(Fmt *fp) +{ + char buf[500]; + int et; + + et = va_arg(fp->args, int); + if(et < 0 || et >= nelem(etnames) || etnames[et] == nil) { + snprint(buf, sizeof(buf), "E-%d", et); + return fmtstrcpy(fp, buf); + } + return fmtstrcpy(fp, etnames[et]); +} + +int +Jconv(Fmt *fp) +{ + char buf[500], buf1[100]; + Node *n; + + n = va_arg(fp->args, Node*); + strcpy(buf, ""); + + if(n->ullman != 0) { + snprint(buf1, sizeof(buf1), " u(%d)", n->ullman); + strncat(buf, buf1, sizeof(buf)); + } + + if(n->addable != 0) { + snprint(buf1, sizeof(buf1), " a(%d)", n->addable); + strncat(buf, buf1, sizeof(buf)); + } + + if(n->vargen != 0) { + snprint(buf1, sizeof(buf1), " g(%ld)", n->vargen); + strncat(buf, buf1, sizeof(buf)); + } + + if(n->lineno != 0) { + snprint(buf1, sizeof(buf1), " l(%ld)", n->lineno); + strncat(buf, buf1, sizeof(buf)); + } + + return fmtstrcpy(fp, buf); +} + +int +Gconv(Fmt *fp) +{ + char buf[100]; + Node *t; + + t = va_arg(fp->args, Node*); + + if(t->etype == TFUNC) { + if(t->vargen != 0) { + snprint(buf, sizeof(buf), "-%d%d%d g(%ld)", + t->thistuple, t->outtuple, t->intuple, t->vargen); + goto out; + } + snprint(buf, sizeof(buf), "-%d%d%d", + t->thistuple, t->outtuple, t->intuple); + goto out; + } + if(t->vargen != 0) { + snprint(buf, sizeof(buf), " g(%ld)", t->vargen); + goto out; + } + strcpy(buf, ""); + +out: + return fmtstrcpy(fp, buf); +} + +int +Sconv(Fmt *fp) +{ + char buf[500]; + Sym *s; + char *opk, *pkg, *nam; + + s = va_arg(fp->args, Sym*); + if(s == S) { + snprint(buf, sizeof(buf), "<S>"); + goto out; + } + + pkg = "<nil>"; + nam = pkg; + opk = pkg; + + if(s->opackage != nil) + opk = s->opackage; + if(s->package != nil) + pkg = s->package; + if(s->name != nil) + nam = s->name; + + if(strcmp(pkg, package) || strcmp(opk, package) || (fp->flags & FmtLong)) { + if(strcmp(opk, pkg) == 0) { + snprint(buf, sizeof(buf), "%s.%s", pkg, nam); + goto out; + } + snprint(buf, sizeof(buf), "(%s)%s.%s", opk, pkg, nam); + goto out; + } + snprint(buf, sizeof(buf), "%s", nam); + +out: + return fmtstrcpy(fp, buf); +} + +int +Tconv(Fmt *fp) +{ + char buf[500], buf1[500]; + Node *t, *t1; + int et; + + t = va_arg(fp->args, Node*); + if(t == N) + return fmtstrcpy(fp, "<T>"); + + t->trecur++; + if(t->op != OTYPE) { + snprint(buf, sizeof(buf), "T-%O", t->op); + goto out; + } + et = t->etype; + + strcpy(buf, ""); + if(t->sym != S) { + snprint(buf, sizeof(buf), "<%S>", t->sym); + } + if(t->trecur > 5) { + strncat(buf, "...", sizeof(buf)); + goto out; + } + + switch(et) { + default: + snprint(buf1, sizeof(buf1), "%E", et); + strncat(buf, buf1, sizeof(buf)); + if(t->type != N) { + snprint(buf1, sizeof(buf1), " %T", t->type); + strncat(buf, buf1, sizeof(buf)); + } + break; + + case TFIELD: + snprint(buf1, sizeof(buf1), "%T", t->type); + strncat(buf, buf1, sizeof(buf)); + break; + + case TFUNC: + snprint(buf1, sizeof(buf1), "%d%d%d(%lT,%lT,%lT)", + t->thistuple, t->outtuple, t->intuple, + t->type, t->type->down, t->type->down->down); + strncat(buf, buf1, sizeof(buf)); + break; + + case TINTER: + strncat(buf, "I{", sizeof(buf)); + if(fp->flags & FmtLong) { + for(t1=t->type; t1!=N; t1=t1->down) { + snprint(buf1, sizeof(buf1), "%T;", t1); + strncat(buf, buf1, sizeof(buf)); + } + } + strncat(buf, "}", sizeof(buf)); + break; + + case TSTRUCT: + strncat(buf, "{", sizeof(buf)); + if(fp->flags & FmtLong) { + for(t1=t->type; t1!=N; t1=t1->down) { + snprint(buf1, sizeof(buf1), "%T;", t1); + strncat(buf, buf1, sizeof(buf)); + } + } + strncat(buf, "}", sizeof(buf)); + break; + + case TMAP: + snprint(buf, sizeof(buf), "[%T]%T", t->down, t->type); + break; + + case TARRAY: + snprint(buf1, sizeof(buf1), "[%ld]%T", t->bound, t->type); + strncat(buf, buf1, sizeof(buf)); + break; + + case TDARRAY: + snprint(buf1, sizeof(buf1), "[]%T", t->type); + strncat(buf, buf1, sizeof(buf)); + break; + + case TPTR: + snprint(buf1, sizeof(buf1), "*%T", t->type); + strncat(buf, buf1, sizeof(buf)); + break; + } + +out: + t->trecur--; + return fmtstrcpy(fp, buf); +} + +int +Nconv(Fmt *fp) +{ + char buf[500], buf1[500]; + Node *n; + + n = va_arg(fp->args, Node*); + if(n == N) { + snprint(buf, sizeof(buf), "<N>"); + goto out; + } + + switch(n->op) { + default: + snprint(buf, sizeof(buf), "%O%J", n->op, n); + break; + + case ONAME: + if(n->sym == S) { + snprint(buf, sizeof(buf), "%O%J", n->op, n); + break; + } + snprint(buf, sizeof(buf), "%O-%S G%ld%J", n->op, + n->sym, n->sym->vargen, n); + goto ptyp; + + case OLITERAL: + switch(n->val.ctype) { + default: + snprint(buf1, sizeof(buf1), "LITERAL-%d", n->val.ctype); + break; + case CTINT: + snprint(buf1, sizeof(buf1), "I%lld", n->val.vval); + break; + case CTSINT: + snprint(buf1, sizeof(buf1), "S%lld", n->val.vval); + break; + case CTUINT: + snprint(buf1, sizeof(buf1), "U%lld", n->val.vval); + break; + case CTFLT: + snprint(buf1, sizeof(buf1), "F%g", n->val.dval); + break; + case CTSTR: + snprint(buf1, sizeof(buf1), "S\"%Z\"", n->val.sval); + break; + case CTBOOL: + snprint(buf1, sizeof(buf1), "B%lld", n->val.vval); + break; + case CTNIL: + snprint(buf1, sizeof(buf1), "N"); + break; + } + snprint(buf, sizeof(buf1), "%O-%s%J", n->op, buf1, n); + break; + + case OASOP: + snprint(buf, sizeof(buf), "%O-%O%J", n->op, n->kaka, n); + break; + + case OTYPE: + snprint(buf, sizeof(buf), "%O-%E%J", n->op, n->etype, n); + break; + } + if(n->sym != S) { + snprint(buf1, sizeof(buf1), " %S G%ld", n->sym, n->sym->vargen); + strncat(buf, buf1, sizeof(buf)); + } + +ptyp: + if(n->type != N) { + snprint(buf1, sizeof(buf1), " %T", n->type); + strncat(buf, buf1, sizeof(buf)); + } + +out: + return fmtstrcpy(fp, buf); +} + +int +Zconv(Fmt *fp) +{ + uchar *s, *se; + char *p; + char buf[500]; + int c; + String *sp; + + sp = va_arg(fp->args, String*); + if(sp == nil) { + snprint(buf, sizeof(buf), "<nil>"); + goto out; + } + s = sp->s; + se = s + sp->len; + + p = buf; + +loop: + c = *s++; + if(s > se) + c = 0; + switch(c) { + default: + *p++ = c; + break; + case 0: + *p = 0; + goto out; + case '\t': + *p++ = '\\'; + *p++ = 't'; + break; + case '\n': + *p++ = '\\'; + *p++ = 'n'; + break; + } + goto loop; + +out: + return fmtstrcpy(fp, buf); +} + +int +isnil(Node *n) +{ + if(n == N) + return 0; + if(n->op != OLITERAL) + return 0; + if(n->val.ctype != CTNIL) + return 0; + return 1; +} + +int +isptrto(Node *t, int et) +{ + if(t == N) + return 0; + if(t->etype != TPTR) + return 0; + t = t->type; + if(t == N) + return 0; + if(t->etype != et) + return 0; + return 1; +} + +int +isinter(Node *t) +{ + if(t != N && t->etype == TINTER) + return 1; + return 0; +} + +int +isbytearray(Node *t) +{ + if(t == N) + return 0; + if(t->etype == TPTR) { + t = t->type; + if(t == N) + return 0; + } + if(t->etype != TARRAY) + return 0; + return t->bound+1; +} + +int +eqtype(Node *t1, Node *t2, int d) +{ + if(d >= 10) + return 1; + + if(t1 == t2) + return 1; + if(t1 == N || t2 == N) + return 0; + if(t1->op != OTYPE || t2->op != OTYPE) + fatal("eqtype: oops %O %O", t1->op, t2->op); + + if(t1->etype != t2->etype) + return 0; + + switch(t1->etype) { + case TINTER: + case TSTRUCT: + t1 = t1->type; + t2 = t2->type; + for(;;) { + if(!eqtype(t1, t2, 0)) + return 0; + if(t1 == N) + return 1; + if(t1->nname != N && t1->nname->sym != S) { + if(t2->nname == N || t2->nname->sym == S) + return 0; + if(strcmp(t1->nname->sym->name, t2->nname->sym->name) != 0) { + // assigned names dont count + if(t1->nname->sym->name[0] != '_' || + t2->nname->sym->name[0] != '_') + return 0; + } + } + t1 = t1->down; + t2 = t2->down; + } + return 1; + + case TFUNC: + t1 = t1->type; + t2 = t2->type; + for(;;) { + if(t1 == t2) + break; + if(t1 == N || t2 == N) + return 0; + if(t1->etype != TSTRUCT || t2->etype != TSTRUCT) + return 0; + + if(!eqtype(t1->type, t2->type, 0)) + return 0; + + t1 = t1->down; + t2 = t2->down; + } + return 1; + } + return eqtype(t1->type, t2->type, d+1); +} + +/* + * are the arg names of two + * functions the same. we know + * that eqtype has been called + * and has returned true. + */ +int +eqargs(Node *t1, Node *t2) +{ + if(t1 == t2) + return 1; + if(t1 == N || t2 == N) + return 0; + if(t1->op != OTYPE || t2->op != OTYPE) + fatal("eqargs: oops %O %O", t1->op, t2->op); + + if(t1->etype != t2->etype) + return 0; + + if(t1->etype != TFUNC) + fatal("eqargs: oops %E", t1->etype); + + t1 = t1->type; + t2 = t2->type; + for(;;) { + if(t1 == t2) + break; + if(!eqtype(t1, t2, 0)) + return 0; + t1 = t1->down; + t2 = t2->down; + } + return 1; +} + +ulong +typehash(Node *at, int d) +{ + ulong h; + Node *t; + + if(at == N) + return PRIME2; + if(d >= 5) + return PRIME3; + + if(at->op != OTYPE) + fatal("typehash: oops %O", at->op); + + if(at->recur) + return 0; + at->recur = 1; + + h = at->etype*PRIME4; + + switch(at->etype) { + default: + h += PRIME5 * typehash(at->type, d+1); + break; + + case TINTER: + // botch -- should be sorted? + for(t=at->type; t!=N; t=t->down) + h += PRIME6 * typehash(t, d+1); + break; + + case TSTRUCT: + for(t=at->type; t!=N; t=t->down) + h += PRIME7 * typehash(t, d+1); + break; + + case TFUNC: + t = at->type; + // skip this argument + if(t != N) + t = t->down; + for(; t!=N; t=t->down) + h += PRIME7 * typehash(t, d+1); + break; + } + + at->recur = 0; + return h; +} + +Node* +ptrto(Node *t) +{ + Node *p; + + p = nod(OTYPE, N, N); + p->etype = TPTR; + p->type = t; + return p; +} + +Node* +literal(long v) +{ + Node *n; + + n = nod(OLITERAL, N, N); + n->val.ctype = CTINT; + n->val.vval = v; + return n; +} + +void +frame(int context) +{ + char *p; + Dcl *d; + int flag; + + p = "stack"; + d = autodcl; + if(context) { + p = "external"; + d = externdcl; + } + + flag = 1; + for(; d!=D; d=d->forw) { + switch(d->op) { + case ONAME: + if(flag) + print("--- %s frame ---\n", p); + print("%O %S G%ld T\n", d->op, d->dsym, d->dnode->vargen, d->dnode->type); + flag = 0; + break; + + case OTYPE: + if(flag) + print("--- %s frame ---\n", p); + print("%O %lT\n", d->op, d->dnode); + flag = 0; + break; + } + } +} + +/* + * calculate sethi/ullman number + * roughly how many registers needed to + * compile a node. used to compile the + * hardest side first to minimize registers. + */ +void +ullmancalc(Node *n) +{ + int ul, ur; + + if(n == N) + return; + + switch(n->op) { + case OLITERAL: + case ONAME: + ul = 0; + goto out; + case OCALL: + ul = UINF; + goto out; + } + ul = 0; + if(n->left != N) + ul = n->left->ullman; + ur = 0; + if(n->right != N) + ur = n->right->ullman; + if(ul == ur) + ul += 1; + if(ur > ul) + ul = ur; + +out: + n->ullman = ul; +} + +void +badtype(int o, Node *tl, Node *tr) +{ + yyerror("illegal types for operand"); + if(tl != N) + print(" (%T)", tl); + print(" %O ", o); + if(tr != N) + print("(%T)", tr); + print("\n"); +} + +/* + * this routine gets the parsing of + * a parameter list that can have + * name, type and name-type. + * it must distribute lone names + * with trailing types to give every + * name a type. (a,b,c int) comes out + * (a int, b int, c int). + */ +Node* +cleanidlist(Node *r) +{ + Node *t, *l, *n, *nn; + + t = N; // untyped name + nn = r; // next node to take + +loop: + n = nn; + if(n == N) { + if(t != N) { + yyerror("syntax error in parameter list"); + l = types[TINT32]; + goto distrib; + } + return r; + } + + l = n; + nn = N; + if(l->op == OLIST) { + nn = l->right; + l = l->left; + } + + if(l->op != ODCLFIELD) + fatal("cleanformal: %O", n->op); + + if(l->type == N) { + if(t == N) + t = n; + goto loop; + } + + if(t == N) + goto loop; + + l = l->type; // type to be distributed + +distrib: + while(t != n) { + if(t->op != OLIST) { + if(t->type == N) + t->type = l; + break; + } + if(t->left->type == N) + t->left->type = l; + t = t->right; + } + + t = N; + goto loop; +} + +/* + * iterator to walk a structure declaration + */ +Node* +structfirst(Iter *s, Node **nn) +{ + Node *r, *n; + + n = *nn; + if(n == N || n->op != OTYPE) + goto bad; + + switch(n->etype) { + default: + goto bad; + + case TSTRUCT: + case TINTER: + case TFUNC: + break; + } + + r = n->type; + if(r == N) + goto rnil; + + if(r->op != OTYPE || r->etype != TFIELD) + fatal("structfirst: not field %N", r); + + s->n = r; + return r; + +bad: + fatal("structfirst: not struct %N", n); + +rnil: + return N; +} + +Node* +structnext(Iter *s) +{ + Node *n, *r; + + n = s->n; + r = n->down; + if(r == N) + goto rnil; + + if(r->op != OTYPE || r->etype != TFIELD) + goto bad; + + s->n = r; + return r; + +bad: + fatal("structnext: not struct %N", n); + +rnil: + return N; +} + +/* + * iterator to walk a list + */ +Node* +listfirst(Iter *s, Node **nn) +{ + Node *n; + + n = *nn; + if(n == N) { + s->done = 1; + s->an = &s->n; + s->n = N; + return N; + } + + if(n->op == OLIST) { + s->done = 0; + s->n = n; + s->an = &n->left; + return n->left; + } + + s->done = 1; + s->an = nn; + return n; +} + +Node* +listnext(Iter *s) +{ + Node *n, *r; + + if(s->done) { + s->an = &s->n; + s->n = N; + return N; + } + + n = s->n; + r = n->right; + if(r->op == OLIST) { + s->n = r; + s->an = &r->left; + return r->left; + } + + s->done = 1; + s->an = &n->right; + return n->right; +} + +Node** +getthis(Node *t) +{ + if(t->etype != TFUNC) + fatal("getthis: not a func %N", t); + return &t->type; +} + +Node** +getoutarg(Node *t) +{ + if(t->etype != TFUNC) + fatal("getoutarg: not a func %N", t); + return &t->type->down; +} + +Node** +getinarg(Node *t) +{ + if(t->etype != TFUNC) + fatal("getinarg: not a func %N", t); + return &t->type->down->down; +} + +Node* +getthisx(Node *t) +{ + return *getthis(t); +} + +Node* +getoutargx(Node *t) +{ + return *getoutarg(t); +} + +Node* +getinargx(Node *t) +{ + return *getinarg(t); +} |