summaryrefslogtreecommitdiff
path: root/src/cmd/cc/godefs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/cc/godefs.c')
-rw-r--r--src/cmd/cc/godefs.c387
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;
+ }
+}