// 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 #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((uchar)*s); else str[0] = tolower((uchar)*s); for(i = 1; i < STRINGSZ && s[i] != 0; i++) str[i] = tolower((uchar)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; hlink) if(s->suetag && s->suetag->link == t) return s; return 0; } static void printtypename(Type *t) { Sym *s; 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: case TUINT: case TCHAR: case TUCHAR: case TSHORT: case TUSHORT: case TLONG: case TULONG: case TVLONG: case TUVLONG: case TFLOAT: case TDOUBLE: // All names used in the runtime code should be typedefs. if(t->tag != nil) { if(strcmp(t->tag->name, "intgo") == 0) Bprint(&outbuf, "int"); else if(strcmp(t->tag->name, "uintgo") == 0) Bprint(&outbuf, "uint"); else Bprint(&outbuf, "%s", t->tag->name); } else Bprint(&outbuf, "C.%T", t); 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 if(strcmp(n, "Eface") == 0) Bprint(&outbuf, "interface{}"); else Bprint(&outbuf, "%U", n); break; case TFUNC: // There's no equivalent to a C function in the Go world. Bprint(&outbuf, "unsafe.Pointer"); 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 %s = %lld\n", s->name, s->vconst); else Bprint(&outbuf, "const %s = %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) break; if(strncmp(s->name, "go.weak.", 8) == 0) break; Bprint(&outbuf, "var %U\t", s->name); printtypename(t); Bprint(&outbuf, "\n"); break; } break; } }