| // 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 <u.h> | |
| #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("); | |
| 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; | |
| } | |
| } |