diff options
Diffstat (limited to 'src/cmd/cc/godefs.c')
-rw-r--r-- | src/cmd/cc/godefs.c | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c new file mode 100644 index 000000000..9503cb2f2 --- /dev/null +++ b/src/cmd/cc/godefs.c @@ -0,0 +1,387 @@ +// cmd/cc/godefs.cc +// +// derived from pickle.cc which itself was derived from acid.cc. +// +// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. +// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) +// Portions Copyright © 1997-1999 Vita Nuova Limited +// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) +// Portions Copyright © 2004,2006 Bruce Ellis +// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) +// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others +// Portions Copyright © 2009-2011 The Go Authors. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "cc.h" + +static int upper; + +static char *kwd[] = +{ + "_bool", + "_break", + "_byte", + "_case", + "_chan", + "_complex128", + "_complex64", + "_const", + "_continue", + "_default", + "_defer", + "_else", + "_fallthrough", + "_false", + "_float32", + "_float64", + "_for", + "_func", + "_go", + "_goto", + "_if", + "_import", + "_int", + "_int16", + "_int32", + "_int64", + "_int8", + "_interface", + "_intptr", + "_map", + "_package", + "_panic", + "_range", + "_return", + "_select", + "_string", + "_struct", + "_switch", + "_true", + "_type", + "_uint", + "_uint16", + "_uint32", + "_uint64", + "_uint8", + "_uintptr", + "_var", +}; + +static char* +pmap(char *s) +{ + int i, bot, top, mid; + + bot = -1; + top = nelem(kwd); + while(top - bot > 1){ + mid = (bot + top) / 2; + i = strcmp(kwd[mid]+1, s); + if(i == 0) + return kwd[mid]; + if(i < 0) + bot = mid; + else + top = mid; + } + + return s; +} + + +int +Uconv(Fmt *fp) +{ + char str[STRINGSZ+1]; + char *s, *n; + int i; + + str[0] = 0; + s = va_arg(fp->args, char*); + + // strip package name + n = strrchr(s, '.'); + if(n != nil) + s = n + 1; + + if(s && *s) { + if(upper) + str[0] = toupper(*s); + else + str[0] = tolower(*s); + for(i = 1; i < STRINGSZ && s[i] != 0; i++) + str[i] = tolower(s[i]); + str[i] = 0; + } + + return fmtstrcpy(fp, pmap(str)); +} + + +static Sym* +findsue(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 0; +} + +static void +printtypename(Type *t) +{ + Sym *s; + Type *t1; + int w; + char *n; + + for( ; t != nil; t = t->link) { + switch(t->etype) { + case TIND: + // Special handling of *void. + if(t->link != nil && t->link->etype==TVOID) { + Bprint(&outbuf, "unsafe.Pointer"); + return; + } + // *func == func + if(t->link != nil && t->link->etype==TFUNC) + continue; + Bprint(&outbuf, "*"); + continue; + case TARRAY: + w = t->width; + if(t->link && t->link->width) + w /= t->link->width; + Bprint(&outbuf, "[%d]", w); + continue; + } + break; + } + + if(t == nil) { + Bprint(&outbuf, "bad // should not happen"); + return; + } + + switch(t->etype) { + case TINT: + Bprint(&outbuf, "int"); + break; + case TUINT: + Bprint(&outbuf, "uint"); + break; + case TCHAR: + Bprint(&outbuf, "int8"); + break; + case TUCHAR: + Bprint(&outbuf, "uint8"); + break; + case TSHORT: + Bprint(&outbuf, "int16"); + break; + case TUSHORT: + Bprint(&outbuf, "uint16"); + break; + case TLONG: + Bprint(&outbuf, "int32"); + break; + case TULONG: + Bprint(&outbuf, "uint32"); + break; + case TVLONG: + Bprint(&outbuf, "int64"); + break; + case TUVLONG: + Bprint(&outbuf, "uint64"); + break; + case TFLOAT: + Bprint(&outbuf, "float32"); + break; + case TDOUBLE: + Bprint(&outbuf, "float64"); + break; + case TUNION: + case TSTRUCT: + s = findsue(t->link); + n = "bad"; + if(s != S) + n = s->name; + else if(t->tag) + n = t->tag->name; + if(strcmp(n, "String") == 0){ + Bprint(&outbuf, "string"); + } else if(strcmp(n, "Slice") == 0){ + Bprint(&outbuf, "[]byte"); + } else + Bprint(&outbuf, "%U", n); + break; + case TFUNC: + Bprint(&outbuf, "func(", t); + for(t1 = t->down; t1 != T; t1 = t1->down) { + if(t1->etype == TVOID) + break; + if(t1 != t->down) + Bprint(&outbuf, ", "); + printtypename(t1); + } + Bprint(&outbuf, ")"); + if(t->link && t->link->etype != TVOID) { + Bprint(&outbuf, " "); + printtypename(t->link); + } + break; + case TDOT: + Bprint(&outbuf, "...interface{}"); + break; + default: + Bprint(&outbuf, " weird<%T>", t); + } +} + +static int +dontrun(void) +{ + Io *i; + int n; + + if(!debug['q'] && !debug['Q']) + return 1; + if(debug['q'] + debug['Q'] > 1) { + n = 0; + for(i=iostack; i; i=i->link) + n++; + if(n > 1) + return 1; + } + + upper = debug['Q']; + return 0; +} + +void +godeftype(Type *t) +{ + Sym *s; + Type *l; + int gotone; + + if(dontrun()) + return; + + switch(t->etype) { + case TUNION: + case TSTRUCT: + s = findsue(t->link); + if(s == S) { + Bprint(&outbuf, "/* can't find %T */\n\n", t); + return; + } + + gotone = 0; // for unions, take first member of size equal to union + Bprint(&outbuf, "type %U struct {\n", s->name); + for(l = t->link; l != T; l = l->down) { + Bprint(&outbuf, "\t"); + if(t->etype == TUNION) { + if(!gotone && l->width == t->width) + gotone = 1; + else + Bprint(&outbuf, "// (union)\t"); + } + if(l->sym != nil) // not anonymous field + Bprint(&outbuf, "%U\t", l->sym->name); + printtypename(l); + Bprint(&outbuf, "\n"); + } + Bprint(&outbuf, "}\n\n"); + break; + + default: + Bprint(&outbuf, "/* %T */\n\n", t); + break; + } +} + +void +godefvar(Sym *s) +{ + Type *t, *t1; + char n; + + if(dontrun()) + return; + + t = s->type; + if(t == nil) + return; + + switch(t->etype) { + case TENUM: + if(!typefd[t->etype]) + Bprint(&outbuf, "const %U = %lld\n", s->name, s->vconst); + else + Bprint(&outbuf, "const %U = %f\n;", s->name, s->fconst); + break; + + case TFUNC: + Bprint(&outbuf, "func %U(", s->name); + n = 'a'; + for(t1 = t->down; t1 != T; t1 = t1->down) { + if(t1->etype == TVOID) + break; + if(t1 != t->down) + Bprint(&outbuf, ", "); + Bprint(&outbuf, "%c ", n++); + printtypename(t1); + } + Bprint(&outbuf, ")"); + if(t->link && t->link->etype != TVOID) { + Bprint(&outbuf, " "); + printtypename(t->link); + } + Bprint(&outbuf, "\n"); + break; + + default: + switch(s->class) { + case CTYPEDEF: + if(!typesu[t->etype]) { + Bprint(&outbuf, "// type %U\t", s->name); + printtypename(t); + Bprint(&outbuf, "\n"); + } + break; + case CSTATIC: + case CEXTERN: + case CGLOBL: + if(strchr(s->name, '$') != nil) // TODO(lvd) + break; + Bprint(&outbuf, "var %U\t", s->name); + printtypename(t); + Bprint(&outbuf, "\n"); + break; + } + break; + } +} |