--- /dev/null
+// 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",
+ "_complex32",
+ "_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",
+ "_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;
+ char *n;
+
+ if (!upper) {
+ 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;
+ }
+ }
+
+ // strip package name
+ n = strrchr(s, '.');
+ if(n != nil)
+ s = n + 1;
+
+ return s;
+}
+
+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 = pmap(s->name);
+ else if(t->tag)
+ n = t->tag->name;
+ if(strcmp(n, "String") == 0){
+ n = "string";
+ } else if(strcmp(n, "Slice") == 0){
+ n = "[]byte";
+ }
+ Bprint(&outbuf, 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;
+}
+
+int
+Uconv(Fmt *fp)
+{
+ char str[STRINGSZ+1];
+ char *s;
+ int i;
+
+ str[0] = 0;
+ s = va_arg(fp->args, char*);
+ 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, str);
+}
+
+void
+godeftype(Type *t)
+{
+ Sym *s;
+ Type *l;
+ char *an;
+ int gotone;
+
+ if(dontrun())
+ return;
+
+ switch(t->etype) {
+ case TUNION:
+ case TSTRUCT:
+ s = findsue(t->link);
+ if(s == S) {
+ Bprint(&outbuf, "/* can't find Sue for %T */\n\n", t);
+ return;
+ }
+ an = pmap(s->name);
+ gotone = 0; // for unions, take first member of size equal to union
+
+ Bprint(&outbuf, "type %U struct {\n", an);
+ 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", pmap(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('q'))
+ return;
+
+ t = s->type;
+ if(t == nil)
+ return;
+
+ switch(t->etype) {
+ case TENUM:
+ if(!typefd[t->etype])
+ Bprint(&outbuf, "const %U = %lld\n", pmap(s->name), s->vconst);
+ else
+ Bprint(&outbuf, "const %U = %f\n;", pmap(s->name), s->fconst);
+ break;
+
+ case TFUNC:
+ Bprint(&outbuf, "func %U(", pmap(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", pmap(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", pmap(s->name));
+ printtypename(t);
+ Bprint(&outbuf, "\n");
+ break;
+ }
+ break;
+ }
+}
* -d print declarations
* -D name define
* -F format specification check
+ * -G print pgen stuff
+ * -g print cgen trees
* -i print initialization
* -I path include
* -l generate little-endian code
* -L print every NAME symbol
* -M constant multiplication
* -m print add/sub/mul trees
- * -n print acid to file (%.c=%.acid) (with -a or -aa)
+ * -n print acid or godefs to file (%.c=%.acid) (with -a or -aa)
* -o file output file
* -p use standard cpp ANSI preprocessor (not on windows)
+ * -p something with peepholes
+ * -q print equivalent Go code for variables and types (lower-case identifiers)
+ * -Q print equivalent Go code for variables and types (upper-case identifiers)
* -r print registerization
* -s print structure offsets (with -a or -aa)
* -S print assembly
p = ARGF();
if(p) {
if(ndef%8 == 0)
- defs = allocn(defs, ndef*sizeof(char *),
+ defs = allocn(defs, ndef*sizeof(char *),
8*sizeof(char *));
defs[ndef++] = p;
dodefine(p);
* if we're writing acid to standard output, don't compile
* concurrently, to avoid interleaving output.
*/
- if((!debug['a'] || debug['n']) &&
+ if(((!debug['a'] && !debug['q'] && !debug['Q']) || debug['n']) &&
(p = getenv("NPROC")) != nil)
nproc = atol(p); /* */
c = 0;
p = utfrune(outfile, 0);
if(debug['a'] && debug['n'])
strcat(p, ".acid");
+ else if((debug['q'] || debug['Q']) && debug['n'])
+ strcat(p, ".go");
else {
p[0] = '.';
p[1] = thechar;
* if we're writing acid to standard output, don't keep scratching
* outbuf.
*/
- if(debug['a'] && !debug['n']) {
+ if((debug['a'] || debug['q'] || debug['Q']) && !debug['n']) {
if (first) {
outfile = 0;
Binit(&outbuf, dup(1, -1), OWRITE);
newfile(file, -1);
}
yyparse();
- if(!debug['a'])
+ if(!debug['a'] && !debug['q'] && !debug['Q'])
gclean();
return nerrors;
}
fmtinstall('L', Lconv);
fmtinstall('Q', Qconv);
fmtinstall('|', VBconv);
+ fmtinstall('U', Uconv);
}
int
return;
if(ninclude%8 == 0)
- include = allocn(include, ninclude*sizeof(char *),
+ include = allocn(include, ninclude*sizeof(char *),
8*sizeof(char *));
include[ninclude++] = p;
}
if(symb == nil) {
symb = alloc(NSYMB+1);
nsymb = NSYMB;
- }
+ }
if(n > nsymb) {
symb = allocn(symb, nsymb, n+1-nsymb);