| //   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((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; 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, "int32"); | 
 | 		break; | 
 | 	case TUINT: | 
 | 		Bprint(&outbuf, "uint32"); | 
 | 		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; | 
 | 	} | 
 | } |