github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/gc/fmt.c (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include	<u.h>
     6  #include	<libc.h>
     7  #include	"go.h"
     8  #include	"opnames.h"
     9  
    10  //
    11  // Format conversions
    12  //	%L int		Line numbers
    13  //
    14  //	%E int		etype values (aka 'Kind')
    15  //
    16  //	%O int		Node Opcodes
    17  //		Flags: "%#O": print go syntax. (automatic unless fmtmode == FDbg)
    18  //
    19  //	%J Node*	Node details
    20  //		Flags: "%hJ" suppresses things not relevant until walk.
    21  //
    22  //	%V Val*		Constant values
    23  //
    24  //	%S Sym*		Symbols
    25  //		Flags: +,- #: mode (see below)
    26  //			"%hS"	unqualified identifier in any mode
    27  //			"%hhS"  in export mode: unqualified identifier if exported, qualified if not
    28  //
    29  //	%T Type*	Types
    30  //		Flags: +,- #: mode (see below)
    31  //			'l' definition instead of name.
    32  //			'h' omit "func" and receiver in function types
    33  //			'u' (only in -/Sym mode) print type identifiers wit package name instead of prefix.
    34  //
    35  //	%N Node*	Nodes
    36  //		Flags: +,- #: mode (see below)
    37  //			'h' (only in +/debug mode) suppress recursion
    38  //			'l' (only in Error mode) print "foo (type Bar)"
    39  //
    40  //	%H NodeList*	NodeLists
    41  //		Flags: those of %N
    42  //			','  separate items with ',' instead of ';'
    43  //
    44  //	%Z Strlit*	String literals
    45  //
    46  //   In mparith1.c:
    47  //      %B Mpint*	Big integers
    48  //	%F Mpflt*	Big floats
    49  //
    50  //   %S, %T and %N obey use the following flags to set the format mode:
    51  enum {
    52  	FErr,	//     error mode (default)
    53  	FDbg,	//     "%+N" debug mode
    54  	FExp,	//     "%#N" export mode
    55  	FTypeId,  //   "%-N" turning-types-into-symbols-mode: identical types give identical strings
    56  };
    57  static int fmtmode;
    58  static int fmtpkgpfx;	// %uT stickyness
    59  //
    60  // E.g. for %S:	%+S %#S %-S	print an identifier properly qualified for debug/export/internal mode.
    61  //
    62  // The mode flags  +, - and # are sticky, meaning they persist through
    63  // recursions of %N, %T and %S, but not the h and l flags.  The u flag is
    64  // sticky only on %T recursions and only used in %-/Sym mode.
    65  
    66  //
    67  // Useful format combinations:
    68  //
    69  //	%+N   %+H	multiline recursive debug dump of node/nodelist
    70  //	%+hN  %+hH	non recursive debug dump
    71  //
    72  //	%#N   %#T	export format
    73  //	%#lT		type definition instead of name
    74  //	%#hT		omit"func" and receiver in function signature
    75  //
    76  //	%lN		"foo (type Bar)" for error messages
    77  //
    78  //	%-T		type identifiers
    79  //	%-hT		type identifiers without "func" and arg names in type signatures (methodsym)
    80  //	%-uT		type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
    81  //
    82  
    83  
    84  static int
    85  setfmode(unsigned long *flags)
    86  {
    87  	int fm;
    88  
    89  	fm = fmtmode;
    90  	if(*flags & FmtSign)
    91  		fmtmode = FDbg;
    92  	else if(*flags & FmtSharp)
    93  		fmtmode = FExp;
    94  	else if(*flags & FmtLeft)
    95  		fmtmode = FTypeId;
    96  
    97  	*flags &= ~(FmtSharp|FmtLeft|FmtSign);
    98  	return fm;
    99  }
   100  
   101  // Fmt "%L": Linenumbers
   102  static int
   103  Lconv(Fmt *fp)
   104  {
   105  	return linklinefmt(ctxt, fp);
   106  }
   107  
   108  static char*
   109  goopnames[] =
   110  {
   111  	[OADDR]		= "&",
   112  	[OADD]		= "+",
   113  	[OADDSTR]	= "+",
   114  	[OANDAND]	= "&&",
   115  	[OANDNOT]	= "&^",
   116  	[OAND]		= "&",
   117  	[OAPPEND]	= "append",
   118  	[OAS]		= "=",
   119  	[OAS2]		= "=",
   120  	[OBREAK]	= "break",
   121  	[OCALL]		= "function call",	// not actual syntax
   122  	[OCAP]		= "cap",
   123  	[OCASE]		= "case",
   124  	[OCLOSE]	= "close",
   125  	[OCOMPLEX]	= "complex",
   126  	[OCOM]		= "^",
   127  	[OCONTINUE]	= "continue",
   128  	[OCOPY]		= "copy",
   129  	[ODEC]		= "--",
   130  	[ODELETE]	= "delete",
   131  	[ODEFER]	= "defer",
   132  	[ODIV]		= "/",
   133  	[OEQ]		= "==",
   134  	[OFALL]		= "fallthrough",
   135  	[OFOR]		= "for",
   136  	[OGE]		= ">=",
   137  	[OGOTO]		= "goto",
   138  	[OGT]		= ">",
   139  	[OIF]		= "if",
   140  	[OIMAG]		= "imag",
   141  	[OINC]		= "++",
   142  	[OIND]		= "*",
   143  	[OLEN]		= "len",
   144  	[OLE]		= "<=",
   145  	[OLSH]		= "<<",
   146  	[OLT]		= "<",
   147  	[OMAKE]		= "make",
   148  	[OMINUS]	= "-",
   149  	[OMOD]		= "%",
   150  	[OMUL]		= "*",
   151  	[ONEW]		= "new",
   152  	[ONE]		= "!=",
   153  	[ONOT]		= "!",
   154  	[OOROR]		= "||",
   155  	[OOR]		= "|",
   156  	[OPANIC]	= "panic",
   157  	[OPLUS]		= "+",
   158  	[OPRINTN]	= "println",
   159  	[OPRINT]	= "print",
   160  	[ORANGE]	= "range",
   161  	[OREAL]		= "real",
   162  	[ORECV]		= "<-",
   163  	[ORECOVER]	= "recover",
   164  	[ORETURN]	= "return",
   165  	[ORSH]		= ">>",
   166  	[OSELECT]	= "select",
   167  	[OSEND]		= "<-",
   168  	[OSUB]		= "-",
   169  	[OSWITCH]	= "switch",
   170  	[OXOR]		= "^",
   171  };
   172  
   173  // Fmt "%O":  Node opcodes
   174  static int
   175  Oconv(Fmt *fp)
   176  {
   177  	int o;
   178  
   179  	o = va_arg(fp->args, int);
   180  	if((fp->flags & FmtSharp) || fmtmode != FDbg)
   181  		if(o >= 0 && o < nelem(goopnames) && goopnames[o] != nil)
   182  			return fmtstrcpy(fp, goopnames[o]);
   183  
   184  	if(o >= 0 && o < nelem(opnames) && opnames[o] != nil)
   185  		return fmtstrcpy(fp, opnames[o]);
   186  
   187  	return fmtprint(fp, "O-%d", o);
   188  }
   189  
   190  static const char* classnames[] = {
   191  	"Pxxx",
   192  	"PEXTERN",
   193  	"PAUTO",
   194  	"PPARAM",
   195  	"PPARAMOUT",
   196  	"PPARAMREF",
   197  	"PFUNC",
   198  };
   199  
   200  // Fmt "%J": Node details.
   201  static int
   202  Jconv(Fmt *fp)
   203  {
   204  	Node *n;
   205  	char *s;
   206  	int c;
   207  
   208  	n = va_arg(fp->args, Node*);
   209  
   210  	c = fp->flags&FmtShort;
   211  
   212  	if(!c && n->ullman != 0)
   213  		fmtprint(fp, " u(%d)", n->ullman);
   214  
   215  	if(!c && n->addable != 0)
   216  		fmtprint(fp, " a(%d)", n->addable);
   217  
   218  	if(!c && n->vargen != 0)
   219  		fmtprint(fp, " g(%d)", n->vargen);
   220  
   221  	if(n->lineno != 0)
   222  		fmtprint(fp, " l(%d)", n->lineno);
   223  
   224  	if(!c && n->xoffset != BADWIDTH)
   225  		fmtprint(fp, " x(%lld%+lld)", n->xoffset, n->stkdelta);
   226  
   227  	if(n->class != 0) {
   228  		s = "";
   229  		if(n->class & PHEAP) s = ",heap";
   230  		if((n->class & ~PHEAP) < nelem(classnames))
   231  			fmtprint(fp, " class(%s%s)", classnames[n->class&~PHEAP], s);
   232  		else
   233  			fmtprint(fp, " class(%d?%s)", n->class&~PHEAP, s);
   234  	}
   235  
   236  	if(n->colas != 0)
   237  		fmtprint(fp, " colas(%d)", n->colas);
   238  
   239  	if(n->funcdepth != 0)
   240  		fmtprint(fp, " f(%d)", n->funcdepth);
   241  
   242  	switch(n->esc) {
   243  	case EscUnknown:
   244  		break;
   245  	case EscHeap:
   246  		fmtprint(fp, " esc(h)");
   247  		break;
   248  	case EscScope:
   249  		fmtprint(fp, " esc(s)");
   250  		break;
   251  	case EscNone:
   252  		fmtprint(fp, " esc(no)");
   253  		break;
   254  	case EscNever:
   255  		if(!c)
   256  			fmtprint(fp, " esc(N)");
   257  		break;
   258  	default:
   259  		fmtprint(fp, " esc(%d)", n->esc);
   260  		break;
   261  	}
   262  
   263  	if(n->escloopdepth)
   264  		fmtprint(fp, " ld(%d)", n->escloopdepth);
   265  
   266  	if(!c && n->typecheck != 0)
   267  		fmtprint(fp, " tc(%d)", n->typecheck);
   268  
   269  	if(!c && n->dodata != 0)
   270  		fmtprint(fp, " dd(%d)", n->dodata);
   271  
   272  	if(n->isddd != 0)
   273  		fmtprint(fp, " isddd(%d)", n->isddd);
   274  
   275  	if(n->implicit != 0)
   276  		fmtprint(fp, " implicit(%d)", n->implicit);
   277  
   278  	if(n->embedded != 0)
   279  		fmtprint(fp, " embedded(%d)", n->embedded);
   280  
   281  	if(!c && n->used != 0)
   282  		fmtprint(fp, " used(%d)", n->used);
   283  	return 0;
   284  }
   285  
   286  // Fmt "%V": Values
   287  static int
   288  Vconv(Fmt *fp)
   289  {
   290  	Val *v;
   291  	vlong x;
   292  
   293  	v = va_arg(fp->args, Val*);
   294  
   295  	switch(v->ctype) {
   296  	case CTINT:
   297  		if((fp->flags & FmtSharp) || fmtmode == FExp)
   298  			return fmtprint(fp, "%#B", v->u.xval);
   299  		return fmtprint(fp, "%B", v->u.xval);
   300  	case CTRUNE:
   301  		x = mpgetfix(v->u.xval);
   302  		if(' ' <= x && x < 0x80 && x != '\\' && x != '\'')
   303  			return fmtprint(fp, "'%c'", (int)x);
   304  		if(0 <= x && x < (1<<16))
   305  			return fmtprint(fp, "'\\u%04ux'", (int)x);
   306  		if(0 <= x && x <= Runemax)
   307  			return fmtprint(fp, "'\\U%08llux'", x);
   308  		return fmtprint(fp, "('\\x00' + %B)", v->u.xval);
   309  	case CTFLT:
   310  		if((fp->flags & FmtSharp) || fmtmode == FExp)
   311  			return fmtprint(fp, "%F", v->u.fval);
   312  		return fmtprint(fp, "%#F", v->u.fval);
   313  	case CTCPLX:
   314  		if((fp->flags & FmtSharp) || fmtmode == FExp)
   315  			return fmtprint(fp, "(%F+%Fi)", &v->u.cval->real, &v->u.cval->imag);
   316  		if(mpcmpfltc(&v->u.cval->real, 0) == 0)
   317  			return fmtprint(fp, "%#Fi", &v->u.cval->imag);
   318  		if(mpcmpfltc(&v->u.cval->imag, 0) == 0)
   319  			return fmtprint(fp, "%#F", &v->u.cval->real);
   320  		if(mpcmpfltc(&v->u.cval->imag, 0) < 0)
   321  			return fmtprint(fp, "(%#F%#Fi)", &v->u.cval->real, &v->u.cval->imag);
   322  		return fmtprint(fp, "(%#F+%#Fi)", &v->u.cval->real, &v->u.cval->imag);
   323  	case CTSTR:
   324  		return fmtprint(fp, "\"%Z\"", v->u.sval);
   325  	case CTBOOL:
   326  		if( v->u.bval)
   327  			return fmtstrcpy(fp, "true");
   328  		return fmtstrcpy(fp, "false");
   329  	case CTNIL:
   330  		return fmtstrcpy(fp, "nil");
   331  	}
   332  	return fmtprint(fp, "<ctype=%d>", v->ctype);
   333  }
   334  
   335  // Fmt "%Z": escaped string literals
   336  static int
   337  Zconv(Fmt *fp)
   338  {
   339  	Rune r;
   340  	Strlit *sp;
   341  	char *s, *se;
   342  	int n;
   343  
   344  	sp = va_arg(fp->args, Strlit*);
   345  	if(sp == nil)
   346  		return fmtstrcpy(fp, "<nil>");
   347  
   348  	s = sp->s;
   349  	se = s + sp->len;
   350  
   351  	// NOTE: Keep in sync with ../ld/go.c:/^Zconv.
   352  	while(s < se) {
   353  		n = chartorune(&r, s);
   354  		s += n;
   355  		switch(r) {
   356  		case Runeerror:
   357  			if(n == 1) {
   358  				fmtprint(fp, "\\x%02x", (uchar)*(s-1));
   359  				break;
   360  			}
   361  			// fall through
   362  		default:
   363  			if(r < ' ') {
   364  				fmtprint(fp, "\\x%02x", r);
   365  				break;
   366  			}
   367  			fmtrune(fp, r);
   368  			break;
   369  		case '\t':
   370  			fmtstrcpy(fp, "\\t");
   371  			break;
   372  		case '\n':
   373  			fmtstrcpy(fp, "\\n");
   374  			break;
   375  		case '\"':
   376  		case '\\':
   377  			fmtrune(fp, '\\');
   378  			fmtrune(fp, r);
   379  			break;
   380  		case 0xFEFF: // BOM, basically disallowed in source code
   381  			fmtstrcpy(fp, "\\uFEFF");
   382  			break;
   383  		}
   384  	}
   385  	return 0;
   386  }
   387  
   388  /*
   389  s%,%,\n%g
   390  s%\n+%\n%g
   391  s%^[	]*T%%g
   392  s%,.*%%g
   393  s%.+%	[T&]		= "&",%g
   394  s%^	........*\]%&~%g
   395  s%~	%%g
   396  */
   397  
   398  static char*
   399  etnames[] =
   400  {
   401  	[TINT]		= "INT",
   402  	[TUINT]		= "UINT",
   403  	[TINT8]		= "INT8",
   404  	[TUINT8]	= "UINT8",
   405  	[TINT16]	= "INT16",
   406  	[TUINT16]	= "UINT16",
   407  	[TINT32]	= "INT32",
   408  	[TUINT32]	= "UINT32",
   409  	[TINT64]	= "INT64",
   410  	[TUINT64]	= "UINT64",
   411  	[TUINTPTR]	= "UINTPTR",
   412  	[TFLOAT32]	= "FLOAT32",
   413  	[TFLOAT64]	= "FLOAT64",
   414  	[TCOMPLEX64]	= "COMPLEX64",
   415  	[TCOMPLEX128]	= "COMPLEX128",
   416  	[TBOOL]		= "BOOL",
   417  	[TPTR32]	= "PTR32",
   418  	[TPTR64]	= "PTR64",
   419  	[TFUNC]		= "FUNC",
   420  	[TARRAY]	= "ARRAY",
   421  	[TSTRUCT]	= "STRUCT",
   422  	[TCHAN]		= "CHAN",
   423  	[TMAP]		= "MAP",
   424  	[TINTER]	= "INTER",
   425  	[TFORW]		= "FORW",
   426  	[TFIELD]	= "FIELD",
   427  	[TSTRING]	= "STRING",
   428  	[TANY]		= "ANY",
   429  };
   430  
   431  // Fmt "%E": etype
   432  static int
   433  Econv(Fmt *fp)
   434  {
   435  	int et;
   436  
   437  	et = va_arg(fp->args, int);
   438  	if(et >= 0 && et < nelem(etnames) && etnames[et] != nil)
   439  		return fmtstrcpy(fp, etnames[et]);
   440  	return fmtprint(fp, "E-%d", et);
   441  }
   442  
   443  // Fmt "%S": syms
   444  static int
   445  symfmt(Fmt *fp, Sym *s)
   446  {
   447  	char *p;
   448  
   449  	if(s->pkg && !(fp->flags&FmtShort)) {
   450  		switch(fmtmode) {
   451  		case FErr:	// This is for the user
   452  			if(s->pkg == localpkg)
   453  				return fmtstrcpy(fp, s->name);
   454  			// If the name was used by multiple packages, display the full path,
   455  			if(s->pkg->name && pkglookup(s->pkg->name, nil)->npkg > 1)
   456  				return fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name);
   457  			return fmtprint(fp, "%s.%s", s->pkg->name, s->name);
   458  		case FDbg:
   459  			return fmtprint(fp, "%s.%s", s->pkg->name, s->name);
   460  		case FTypeId:
   461  			if(fp->flags&FmtUnsigned)
   462  				return fmtprint(fp, "%s.%s", s->pkg->name, s->name);	// dcommontype, typehash
   463  			return fmtprint(fp, "%s.%s", s->pkg->prefix, s->name);	// (methodsym), typesym, weaksym
   464  		case FExp:
   465  			if(s->name && s->name[0] == '.')
   466  				fatal("exporting synthetic symbol %s", s->name);
   467  			if(s->pkg != builtinpkg)
   468  				return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, s->name);
   469  		}
   470  	}
   471  
   472  	if(fp->flags&FmtByte) {  // FmtByte (hh) implies FmtShort (h)
   473  		// skip leading "type." in method name
   474  		p = utfrrune(s->name, '.');
   475  		if(p)
   476  			p++;
   477  		else
   478  			p = s->name;
   479  
   480  		// exportname needs to see the name without the prefix too.
   481  		if((fmtmode == FExp && !exportname(p)) || fmtmode == FDbg)
   482  			return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, p);
   483  
   484  		return fmtstrcpy(fp, p);
   485  	}
   486  
   487  	return fmtstrcpy(fp, s->name);
   488  }
   489  
   490  static char*
   491  basicnames[] =
   492  {
   493  	[TINT]		= "int",
   494  	[TUINT]		= "uint",
   495  	[TINT8]		= "int8",
   496  	[TUINT8]	= "uint8",
   497  	[TINT16]	= "int16",
   498  	[TUINT16]	= "uint16",
   499  	[TINT32]	= "int32",
   500  	[TUINT32]	= "uint32",
   501  	[TINT64]	= "int64",
   502  	[TUINT64]	= "uint64",
   503  	[TUINTPTR]	= "uintptr",
   504  	[TFLOAT32]	= "float32",
   505  	[TFLOAT64]	= "float64",
   506  	[TCOMPLEX64]	= "complex64",
   507  	[TCOMPLEX128]	= "complex128",
   508  	[TBOOL]		= "bool",
   509  	[TANY]		= "any",
   510  	[TSTRING]	= "string",
   511  	[TNIL]		= "nil",
   512  	[TIDEAL]	= "untyped number",
   513  	[TBLANK]	= "blank",
   514  };
   515  
   516  static int
   517  typefmt(Fmt *fp, Type *t)
   518  {
   519  	Type *t1;
   520  	Sym *s;
   521  
   522  	if(t == T)
   523  		return fmtstrcpy(fp, "<T>");
   524  
   525  	if (t == bytetype || t == runetype) {
   526  		// in %-T mode collapse rune and byte with their originals.
   527  		if(fmtmode != FTypeId)
   528  			return fmtprint(fp, "%hS", t->sym);
   529  		t = types[t->etype];
   530  	}
   531  
   532  	if(t == errortype)
   533  		return fmtstrcpy(fp, "error");
   534  
   535  	// Unless the 'l' flag was specified, if the type has a name, just print that name.
   536  	if(!(fp->flags&FmtLong) && t->sym && t->etype != TFIELD && t != types[t->etype]) {
   537  		switch(fmtmode) {
   538  		case FTypeId:
   539  			if(fp->flags&FmtShort) {
   540  				if(t->vargen)
   541  					return fmtprint(fp, "%hS·%d", t->sym, t->vargen);
   542  				return fmtprint(fp, "%hS", t->sym);
   543  			}
   544  			if(fp->flags&FmtUnsigned)
   545  				return fmtprint(fp, "%uS", t->sym);
   546  			// fallthrough
   547  		case FExp:
   548  			if(t->sym->pkg == localpkg && t->vargen)
   549  				return fmtprint(fp, "%S·%d", t->sym, t->vargen);
   550  			break;
   551  		}
   552  		return fmtprint(fp, "%S", t->sym);
   553  	}
   554  
   555  	if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil) {
   556  		if(fmtmode == FErr && (t == idealbool || t == idealstring))
   557  			fmtstrcpy(fp, "untyped ");
   558  		return fmtstrcpy(fp, basicnames[t->etype]);
   559  	}
   560  
   561  	if(fmtmode == FDbg)
   562  		fmtprint(fp, "%E-", t->etype);
   563  
   564  	switch(t->etype) {
   565  	case TPTR32:
   566  	case TPTR64:
   567  		if(fmtmode == FTypeId && (fp->flags&FmtShort))
   568  			return fmtprint(fp, "*%hT", t->type);
   569  		return fmtprint(fp, "*%T", t->type);
   570  
   571  	case TARRAY:
   572  		if(t->bound >= 0)
   573  			return fmtprint(fp, "[%lld]%T", t->bound, t->type);
   574  		if(t->bound == -100)
   575  			return fmtprint(fp, "[...]%T", t->type);
   576  		return fmtprint(fp, "[]%T", t->type);
   577  
   578  	case TCHAN:
   579  		switch(t->chan) {
   580  		case Crecv:
   581  			return fmtprint(fp, "<-chan %T", t->type);
   582  		case Csend:
   583  			return fmtprint(fp, "chan<- %T", t->type);
   584  		}
   585  
   586  		if(t->type != T && t->type->etype == TCHAN && t->type->sym == S && t->type->chan == Crecv)
   587  			return fmtprint(fp, "chan (%T)", t->type);
   588  		return fmtprint(fp, "chan %T", t->type);
   589  
   590  	case TMAP:
   591  		return fmtprint(fp, "map[%T]%T", t->down, t->type);
   592  
   593  	case TINTER:
   594  		fmtstrcpy(fp, "interface {");
   595  		for(t1=t->type; t1!=T; t1=t1->down)
   596  			if(exportname(t1->sym->name)) {
   597  				if(t1->down)
   598  					fmtprint(fp, " %hS%hT;", t1->sym, t1->type);
   599  				else
   600  					fmtprint(fp, " %hS%hT ", t1->sym, t1->type);
   601  			} else {
   602  				// non-exported method names must be qualified
   603  				if(t1->down)
   604  					fmtprint(fp, " %uS%hT;", t1->sym, t1->type);
   605  				else
   606  					fmtprint(fp, " %uS%hT ", t1->sym, t1->type);
   607  			}
   608  		fmtstrcpy(fp, "}");
   609  		return 0;
   610  
   611  	case TFUNC:
   612  		if(fp->flags & FmtShort) {
   613  			fmtprint(fp, "%T", getinargx(t));
   614  		} else {
   615  			if(t->thistuple)
   616  				fmtprint(fp, "method%T func%T", getthisx(t), getinargx(t));
   617  			else
   618  				fmtprint(fp, "func%T", getinargx(t));
   619  		}
   620  		switch(t->outtuple) {
   621  		case 0:
   622  			break;
   623  		case 1:
   624  			if(fmtmode != FExp) {
   625  				fmtprint(fp, " %T", getoutargx(t)->type->type);	 // struct->field->field's type
   626  				break;
   627  			}
   628  		default:
   629  			fmtprint(fp, " %T", getoutargx(t));
   630  			break;
   631  		}
   632  		return 0;
   633  
   634  	case TSTRUCT:
   635  		// Format the bucket struct for map[x]y as map.bucket[x]y.
   636  		// This avoids a recursive print that generates very long names.
   637  		if(t->map != T) {
   638  			if(t->map->bucket == t) {
   639  				return fmtprint(fp, "map.bucket[%T]%T", t->map->down, t->map->type);
   640  			}
   641  			if(t->map->hmap == t) {
   642  				return fmtprint(fp, "map.hdr[%T]%T", t->map->down, t->map->type);
   643  			}
   644  			if(t->map->hiter == t) {
   645  				return fmtprint(fp, "map.iter[%T]%T", t->map->down, t->map->type);
   646  			}
   647  			yyerror("unknown internal map type");
   648  		}
   649  
   650  		if(t->funarg) {
   651  			fmtstrcpy(fp, "(");
   652  			if(fmtmode == FTypeId || fmtmode == FErr) {	// no argument names on function signature, and no "noescape"/"nosplit" tags
   653  				for(t1=t->type; t1!=T; t1=t1->down)
   654  					if(t1->down)
   655  						fmtprint(fp, "%hT, ", t1);
   656  					else
   657  						fmtprint(fp, "%hT", t1);
   658  			} else {
   659  				for(t1=t->type; t1!=T; t1=t1->down)
   660  					if(t1->down)
   661  						fmtprint(fp, "%T, ", t1);
   662  					else
   663  						fmtprint(fp, "%T", t1);
   664  			}
   665  			fmtstrcpy(fp, ")");
   666  		} else {
   667  			fmtstrcpy(fp, "struct {");
   668  			for(t1=t->type; t1!=T; t1=t1->down)
   669  				if(t1->down)
   670  					fmtprint(fp, " %lT;", t1);
   671  				else
   672  					fmtprint(fp, " %lT ", t1);
   673  			fmtstrcpy(fp, "}");
   674  		}
   675  		return 0;
   676  
   677  	case TFIELD:
   678  		if(!(fp->flags&FmtShort)) {
   679  			s = t->sym;
   680  
   681  			// Take the name from the original, lest we substituted it with ~r%d or ~b%d.
   682  			// ~r%d is a (formerly) unnamed result.
   683  			if ((fmtmode == FErr || fmtmode == FExp) && t->nname != N) {
   684  				if(t->nname->orig != N) {
   685  					s = t->nname->orig->sym;
   686  					if(s != S && s->name[0] == '~') {
   687  						if(s->name[1] == 'r') // originally an unnamed result
   688  							s = S;
   689  						else if(s->name[1] == 'b') // originally the blank identifier _
   690  							s = lookup("_");
   691  					}
   692  				} else 
   693  					s = S;
   694  			}
   695  			
   696  			if(s != S && !t->embedded) {
   697  				if(t->funarg)
   698  					fmtprint(fp, "%N ", t->nname);
   699  				else if(fp->flags&FmtLong)
   700  					fmtprint(fp, "%hhS ", s);  // qualify non-exported names (used on structs, not on funarg)
   701  				else 
   702  					fmtprint(fp, "%S ", s);
   703  			} else if(fmtmode == FExp) {
   704  				// TODO(rsc) this breaks on the eliding of unused arguments in the backend
   705  				// when this is fixed, the special case in dcl.c checkarglist can go.
   706  				//if(t->funarg)
   707  				//	fmtstrcpy(fp, "_ ");
   708  				//else
   709  				if(t->embedded && s->pkg != nil && s->pkg->path->len > 0)
   710  					fmtprint(fp, "@\"%Z\".? ", s->pkg->path);
   711  				else
   712  					fmtstrcpy(fp, "? ");
   713  			}
   714  		}
   715  
   716  		if(t->isddd)
   717  			fmtprint(fp, "...%T", t->type->type);
   718  		else
   719  			fmtprint(fp, "%T", t->type);
   720  
   721  		if(!(fp->flags&FmtShort) && t->note)
   722  			fmtprint(fp, " \"%Z\"", t->note);
   723  		return 0;
   724  
   725  	case TFORW:
   726  		if(t->sym)
   727  			return fmtprint(fp, "undefined %S", t->sym);
   728  		return fmtstrcpy(fp, "undefined");
   729  
   730  	case TUNSAFEPTR:
   731  		if(fmtmode == FExp)
   732  			return fmtprint(fp, "@\"unsafe\".Pointer");
   733  		return fmtprint(fp, "unsafe.Pointer");
   734  	}
   735  
   736  	if(fmtmode == FExp)
   737  		fatal("missing %E case during export", t->etype);
   738  	// Don't know how to handle - fall back to detailed prints.
   739  	return fmtprint(fp, "%E <%S> %T", t->etype, t->sym, t->type);
   740  }
   741  
   742  // Statements which may be rendered with a simplestmt as init.
   743  static int
   744  stmtwithinit(int op)
   745  {
   746  	switch(op) {
   747  	case OIF:
   748  	case OFOR:
   749  	case OSWITCH:
   750  		return 1;
   751  	}
   752  	return 0;
   753  }
   754  
   755  static int
   756  stmtfmt(Fmt *f, Node *n)
   757  {
   758  	int complexinit, simpleinit, extrablock;
   759  
   760  	// some statements allow for an init, but at most one,
   761  	// but we may have an arbitrary number added, eg by typecheck
   762  	// and inlining.  If it doesn't fit the syntax, emit an enclosing
   763  	// block starting with the init statements.
   764  
   765  	// if we can just say "for" n->ninit; ... then do so
   766  	simpleinit = n->ninit && !n->ninit->next && !n->ninit->n->ninit && stmtwithinit(n->op);
   767  	// otherwise, print the inits as separate statements
   768  	complexinit = n->ninit && !simpleinit && (fmtmode != FErr);
   769  	// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
   770  	extrablock = complexinit && stmtwithinit(n->op);
   771  
   772  	if(extrablock)
   773  		fmtstrcpy(f, "{");
   774  
   775  	if(complexinit)
   776  		fmtprint(f, " %H; ", n->ninit);
   777  
   778  	switch(n->op){
   779  	case ODCL:
   780  		if(fmtmode == FExp) {
   781  			switch(n->left->class&~PHEAP) {
   782  			case PPARAM:
   783  			case PPARAMOUT:
   784  			case PAUTO:
   785  				fmtprint(f, "var %N %T", n->left, n->left->type);
   786  				goto ret;
   787  			}
   788  		}			
   789  		fmtprint(f, "var %S %T", n->left->sym, n->left->type);
   790  		break;
   791  
   792  	case ODCLFIELD:
   793  		if(n->left)
   794  			fmtprint(f, "%N %N", n->left, n->right);
   795  		else
   796  			fmtprint(f, "%N", n->right);
   797  		break;
   798  
   799  	case OAS:
   800  		// Don't export "v = <N>" initializing statements, hope they're always 
   801  		// preceded by the DCL which will be re-parsed and typecheck to reproduce
   802  		// the "v = <N>" again.
   803  		if(fmtmode == FExp && n->right == N)
   804  			break;
   805  
   806  		if(n->colas && !complexinit)
   807  			fmtprint(f, "%N := %N", n->left, n->right);
   808  		else
   809  			fmtprint(f, "%N = %N", n->left, n->right);
   810  		break;
   811  
   812  	case OASOP:
   813  		if(n->implicit) {
   814  			if(n->etype == OADD)
   815  				fmtprint(f, "%N++", n->left);
   816  			else
   817  				fmtprint(f, "%N--", n->left);
   818  			break;
   819  		}
   820  		fmtprint(f, "%N %#O= %N", n->left, n->etype, n->right);
   821  		break;
   822  
   823  	case OAS2:
   824  		if(n->colas && !complexinit) {
   825  			fmtprint(f, "%,H := %,H", n->list, n->rlist);
   826  			break;
   827  		}
   828  		// fallthrough
   829  	case OAS2DOTTYPE:
   830  	case OAS2FUNC:
   831  	case OAS2MAPR:
   832  	case OAS2RECV:
   833  		fmtprint(f, "%,H = %,H", n->list, n->rlist);
   834  		break;
   835  
   836  	case ORETURN:
   837  		fmtprint(f, "return %,H", n->list);
   838  		break;
   839  
   840  	case ORETJMP:
   841  		fmtprint(f, "retjmp %S", n->sym);
   842  		break;
   843  	
   844  	case OPROC:
   845  		fmtprint(f, "go %N", n->left);
   846  		break;
   847  
   848  	case ODEFER:
   849  		fmtprint(f, "defer %N", n->left);
   850  		break;
   851  
   852  	case OIF:
   853  		if(simpleinit)
   854  			fmtprint(f, "if %N; %N { %H }", n->ninit->n, n->ntest, n->nbody);
   855  		else
   856  			fmtprint(f, "if %N { %H }", n->ntest, n->nbody);
   857  		if(n->nelse)
   858  			fmtprint(f, " else { %H }", n->nelse);
   859  		break;
   860  
   861  	case OFOR:
   862  		if(fmtmode == FErr) {	// TODO maybe only if FmtShort, same below
   863  			fmtstrcpy(f, "for loop");
   864  			break;
   865  		}
   866  
   867  		fmtstrcpy(f, "for");
   868  		if(simpleinit)
   869  			fmtprint(f, " %N;", n->ninit->n);
   870  		else if(n->nincr)
   871  			fmtstrcpy(f, " ;");
   872  
   873  		if(n->ntest)
   874  			fmtprint(f, " %N", n->ntest);
   875  
   876  		if(n->nincr)
   877  			fmtprint(f, "; %N", n->nincr);
   878  		else if(simpleinit)
   879  			fmtstrcpy(f, ";");
   880  
   881  
   882  		fmtprint(f, " { %H }", n->nbody);
   883  		break;
   884  
   885  	case ORANGE:
   886  		if(fmtmode == FErr) {
   887  			fmtstrcpy(f, "for loop");
   888  			break;
   889  		}
   890  		
   891  		if(n->list == nil) {
   892  			fmtprint(f, "for range %N { %H }", n->right, n->nbody);
   893  			break;
   894  		}
   895  		fmtprint(f, "for %,H = range %N { %H }", n->list, n->right, n->nbody);
   896  		break;
   897  
   898  	case OSELECT:
   899  	case OSWITCH:
   900  		if(fmtmode == FErr) {
   901  			fmtprint(f, "%O statement", n->op);
   902  			break;
   903  		}
   904  
   905  		fmtprint(f, "%#O", n->op);
   906  		if(simpleinit)
   907  			fmtprint(f, " %N;", n->ninit->n);
   908  		if(n->ntest)
   909  			fmtprint(f, "%N", n->ntest);
   910  
   911  		fmtprint(f, " { %H }", n->list);
   912  		break;
   913  
   914  	case OCASE:
   915  	case OXCASE:
   916  		if(n->list)
   917  			fmtprint(f, "case %,H: %H", n->list, n->nbody);
   918  		else
   919  			fmtprint(f, "default: %H", n->nbody);
   920  		break;
   921  
   922  	case OBREAK:
   923  	case OCONTINUE:
   924  	case OGOTO:
   925  	case OFALL:
   926  	case OXFALL:
   927  		if(n->left)
   928  			fmtprint(f, "%#O %N", n->op, n->left);
   929  		else
   930  			fmtprint(f, "%#O", n->op);
   931  		break;
   932  
   933  	case OEMPTY:
   934  		break;
   935  
   936  	case OLABEL:
   937  		fmtprint(f, "%N: ", n->left);
   938  		break;
   939  	  
   940  	}
   941  ret:
   942  
   943  	if(extrablock)
   944  		fmtstrcpy(f, "}");
   945  
   946  	return 0;
   947  }
   948  
   949  
   950  static int opprec[] = {
   951  	[OAPPEND] = 8,
   952  	[OARRAYBYTESTR] = 8,
   953  	[OARRAYLIT] = 8,
   954  	[OARRAYRUNESTR] = 8,
   955  	[OCALLFUNC] = 8,
   956  	[OCALLINTER] = 8,
   957  	[OCALLMETH] = 8,
   958  	[OCALL] = 8,
   959  	[OCAP] = 8,
   960  	[OCLOSE] = 8,
   961  	[OCONVIFACE] = 8,
   962  	[OCONVNOP] = 8,
   963  	[OCONV] = 8,
   964  	[OCOPY] = 8,
   965  	[ODELETE] = 8,
   966  	[OLEN] = 8,
   967  	[OLITERAL] = 8,
   968  	[OMAKESLICE] = 8,
   969  	[OMAKE] = 8,
   970  	[OMAPLIT] = 8,
   971  	[ONAME] = 8,
   972  	[ONEW] = 8,
   973  	[ONONAME] = 8,
   974  	[OPACK] = 8,
   975  	[OPANIC] = 8,
   976  	[OPAREN] = 8,
   977  	[OPRINTN] = 8,
   978  	[OPRINT] = 8,
   979  	[ORUNESTR] = 8,
   980  	[OSTRARRAYBYTE] = 8,
   981  	[OSTRARRAYRUNE] = 8,
   982  	[OSTRUCTLIT] = 8,
   983  	[OTARRAY] = 8,
   984  	[OTCHAN] = 8,
   985  	[OTFUNC] = 8,
   986  	[OTINTER] = 8,
   987  	[OTMAP] = 8,
   988  	[OTSTRUCT] = 8,
   989  
   990  	[OINDEXMAP] = 8,
   991  	[OINDEX] = 8,
   992  	[OSLICE] = 8,
   993  	[OSLICESTR] = 8,
   994  	[OSLICEARR] = 8,
   995  	[OSLICE3] = 8,
   996  	[OSLICE3ARR] = 8,
   997  	[ODOTINTER] = 8,
   998  	[ODOTMETH] = 8,
   999  	[ODOTPTR] = 8,
  1000  	[ODOTTYPE2] = 8,
  1001  	[ODOTTYPE] = 8,
  1002  	[ODOT] = 8,
  1003  	[OXDOT] = 8,
  1004  	[OCALLPART] = 8,
  1005  
  1006  	[OPLUS] = 7,
  1007  	[ONOT] = 7,
  1008  	[OCOM] = 7,
  1009  	[OMINUS] = 7,
  1010  	[OADDR] = 7,
  1011  	[OIND] = 7,
  1012  	[ORECV] = 7,
  1013  
  1014  	[OMUL] = 6,
  1015  	[ODIV] = 6,
  1016  	[OMOD] = 6,
  1017  	[OLSH] = 6,
  1018  	[ORSH] = 6,
  1019  	[OAND] = 6,
  1020  	[OANDNOT] = 6,
  1021  
  1022  	[OADD] = 5,
  1023  	[OSUB] = 5,
  1024  	[OOR] = 5,
  1025  	[OXOR] = 5,
  1026  
  1027  	[OEQ] = 4,
  1028  	[OLT] = 4,
  1029  	[OLE] = 4,
  1030  	[OGE] = 4,
  1031  	[OGT] = 4,
  1032  	[ONE] = 4,
  1033  	[OCMPSTR] = 4,
  1034  	[OCMPIFACE] = 4,
  1035  
  1036  	[OSEND] = 3,
  1037  	[OANDAND] = 2,
  1038  	[OOROR] = 1,
  1039  
  1040  	// Statements handled by stmtfmt
  1041  	[OAS] = -1,
  1042  	[OAS2] = -1,
  1043  	[OAS2DOTTYPE] = -1,
  1044  	[OAS2FUNC] = -1,
  1045  	[OAS2MAPR] = -1,
  1046  	[OAS2RECV] = -1,
  1047  	[OASOP] = -1,
  1048  	[OBREAK] = -1,
  1049  	[OCASE] = -1,
  1050  	[OCONTINUE] = -1,
  1051  	[ODCL] = -1,
  1052  	[ODCLFIELD] = -1,
  1053  	[ODEFER] = -1,
  1054  	[OEMPTY] = -1,
  1055  	[OFALL] = -1,
  1056  	[OFOR] = -1,
  1057  	[OGOTO] = -1,
  1058  	[OIF] = -1,
  1059  	[OLABEL] = -1,
  1060  	[OPROC] = -1,
  1061  	[ORANGE] = -1,
  1062  	[ORETURN] = -1,
  1063  	[OSELECT] = -1,
  1064  	[OSWITCH] = -1,
  1065  	[OXCASE] = -1,
  1066  	[OXFALL] = -1,
  1067  
  1068  	[OEND] = 0
  1069  };
  1070  
  1071  static int
  1072  exprfmt(Fmt *f, Node *n, int prec)
  1073  {
  1074  	int nprec;
  1075  	int ptrlit;
  1076  	NodeList *l;
  1077  
  1078  	while(n && n->implicit && (n->op == OIND || n->op == OADDR))
  1079  		n = n->left;
  1080  
  1081  	if(n == N)
  1082  		return fmtstrcpy(f, "<N>");
  1083  
  1084  	nprec = opprec[n->op];
  1085  	if(n->op == OTYPE && n->sym != S)
  1086  		nprec = 8;
  1087  
  1088  	if(prec > nprec)
  1089  		return fmtprint(f, "(%N)", n);
  1090  
  1091  	switch(n->op) {
  1092  	case OPAREN:
  1093  		return fmtprint(f, "(%N)", n->left);
  1094  
  1095  	case ODDDARG:
  1096  		return fmtprint(f, "... argument");
  1097  
  1098  	case OREGISTER:
  1099  		return fmtprint(f, "%R", n->val.u.reg);
  1100  
  1101  	case OLITERAL:  // this is a bit of a mess
  1102  		if(fmtmode == FErr && n->sym != S)
  1103  			return fmtprint(f, "%S", n->sym);
  1104  		if(n->val.ctype == CTNIL && n->orig != N && n->orig != n)
  1105  			return exprfmt(f, n->orig, prec);
  1106  		if(n->type != T && n->type != types[n->type->etype] && n->type != idealbool && n->type != idealstring) {
  1107  			// Need parens when type begins with what might
  1108  			// be misinterpreted as a unary operator: * or <-.
  1109  			if(isptr[n->type->etype] || (n->type->etype == TCHAN && n->type->chan == Crecv))
  1110  				return fmtprint(f, "(%T)(%V)", n->type, &n->val);
  1111  			else 
  1112  				return fmtprint(f, "%T(%V)", n->type, &n->val);
  1113  		}
  1114  		return fmtprint(f, "%V", &n->val);
  1115  
  1116  	case ONAME:
  1117  		// Special case: name used as local variable in export.
  1118  		// _ becomes ~b%d internally; print as _ for export
  1119  		if(fmtmode == FExp && n->sym && n->sym->name[0] == '~' && n->sym->name[1] == 'b')
  1120  			return fmtprint(f, "_");
  1121  		if(fmtmode == FExp && n->sym && !isblank(n) && n->vargen > 0)
  1122  			return fmtprint(f, "%S·%d", n->sym, n->vargen);
  1123  
  1124  		// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
  1125  		// but for export, this should be rendered as (*pkg.T).meth.
  1126  		// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
  1127  		if(fmtmode == FExp && n->left && n->left->op == OTYPE && n->right && n->right->op == ONAME) {
  1128  			if(isptr[n->left->type->etype])
  1129  				return fmtprint(f, "(%T).%hhS", n->left->type, n->right->sym);
  1130  			else
  1131  				return fmtprint(f, "%T.%hhS", n->left->type, n->right->sym);
  1132  		}
  1133  		//fallthrough
  1134  	case OPACK:
  1135  	case ONONAME:
  1136  		return fmtprint(f, "%S", n->sym);
  1137  
  1138  	case OTYPE:
  1139  		if(n->type == T && n->sym != S)
  1140  			return fmtprint(f, "%S", n->sym);
  1141  		return fmtprint(f, "%T", n->type);
  1142  
  1143  	case OTARRAY:
  1144  		if(n->left)
  1145  			return fmtprint(f, "[]%N", n->left);
  1146  		return fmtprint(f, "[]%N", n->right);  // happens before typecheck
  1147  
  1148  	case OTMAP:
  1149  		return fmtprint(f, "map[%N]%N", n->left, n->right);
  1150  
  1151  	case OTCHAN:
  1152  		switch(n->etype) {
  1153  		case Crecv:
  1154  			return fmtprint(f, "<-chan %N", n->left);
  1155  		case Csend:
  1156  			return fmtprint(f, "chan<- %N", n->left);
  1157  		default:
  1158  			if(n->left != N && n->left->op == OTCHAN && n->left->sym == S && n->left->etype == Crecv)
  1159  				return fmtprint(f, "chan (%N)", n->left);
  1160  			else
  1161  				return fmtprint(f, "chan %N", n->left);
  1162  		}
  1163  
  1164  	case OTSTRUCT:
  1165  		return fmtprint(f, "<struct>");
  1166  
  1167  	case OTINTER:
  1168  		return fmtprint(f, "<inter>");
  1169  
  1170  	case OTFUNC:
  1171  		return fmtprint(f, "<func>");
  1172  
  1173  	case OCLOSURE:
  1174  		if(fmtmode == FErr)
  1175  			return fmtstrcpy(f, "func literal");
  1176  		if(n->nbody)
  1177  			return fmtprint(f, "%T { %H }", n->type, n->nbody);
  1178  		return fmtprint(f, "%T { %H }", n->type, n->closure->nbody);
  1179  
  1180  	case OCOMPLIT:
  1181  		ptrlit = n->right != N && n->right->implicit && n->right->type && isptr[n->right->type->etype];
  1182  		if(fmtmode == FErr) {
  1183  			if(n->right != N && n->right->type != T && !n->implicit) {
  1184  				if(ptrlit)
  1185  					return fmtprint(f, "&%T literal", n->right->type->type);
  1186  				else
  1187  					return fmtprint(f, "%T literal", n->right->type);
  1188  			}
  1189  			return fmtstrcpy(f, "composite literal");
  1190  		}
  1191  		if(fmtmode == FExp && ptrlit)
  1192  			// typecheck has overwritten OIND by OTYPE with pointer type.
  1193  			return fmtprint(f, "(&%T{ %,H })", n->right->type->type, n->list);
  1194  		return fmtprint(f, "(%N{ %,H })", n->right, n->list);
  1195  
  1196  	case OPTRLIT:
  1197  		if(fmtmode == FExp && n->left->implicit)
  1198  			return fmtprint(f, "%N", n->left);
  1199  		return fmtprint(f, "&%N", n->left);
  1200  
  1201  	case OSTRUCTLIT:
  1202  		if(fmtmode == FExp) {   // requires special handling of field names
  1203  			if(n->implicit)
  1204  				fmtstrcpy(f, "{");
  1205  			else
  1206  				fmtprint(f, "(%T{", n->type);
  1207  			for(l=n->list; l; l=l->next) {
  1208  				fmtprint(f, " %hhS:%N", l->n->left->sym, l->n->right);
  1209  
  1210  				if(l->next)
  1211  					fmtstrcpy(f, ",");
  1212  				else
  1213  					fmtstrcpy(f, " ");
  1214  			}
  1215  			if(!n->implicit)
  1216  				return fmtstrcpy(f, "})");
  1217  			return fmtstrcpy(f, "}");
  1218  		}
  1219  		// fallthrough
  1220  
  1221  	case OARRAYLIT:
  1222  	case OMAPLIT:
  1223  		if(fmtmode == FErr)
  1224  			return fmtprint(f, "%T literal", n->type);
  1225  		if(fmtmode == FExp && n->implicit)
  1226  			return fmtprint(f, "{ %,H }", n->list);
  1227  		return fmtprint(f, "(%T{ %,H })", n->type, n->list);
  1228  
  1229  	case OKEY:
  1230  		if(n->left && n->right) {
  1231  			if(fmtmode == FExp && n->left->type && n->left->type->etype == TFIELD) {
  1232  				// requires special handling of field names
  1233  				return fmtprint(f, "%hhS:%N", n->left->sym, n->right);
  1234  			} else
  1235  				return fmtprint(f, "%N:%N", n->left, n->right);
  1236  		}
  1237  		if(!n->left && n->right)
  1238  			return fmtprint(f, ":%N", n->right);
  1239  		if(n->left && !n->right)
  1240  			return fmtprint(f, "%N:", n->left);
  1241  		return fmtstrcpy(f, ":");
  1242  
  1243  	case OXDOT:
  1244  	case ODOT:
  1245  	case ODOTPTR:
  1246  	case ODOTINTER:
  1247  	case ODOTMETH:
  1248  	case OCALLPART:
  1249  		exprfmt(f, n->left, nprec);
  1250  		if(n->right == N || n->right->sym == S)
  1251  			return fmtstrcpy(f, ".<nil>");
  1252  		return fmtprint(f, ".%hhS", n->right->sym);
  1253  
  1254  	case ODOTTYPE:
  1255  	case ODOTTYPE2:
  1256  		exprfmt(f, n->left, nprec);
  1257  		if(n->right != N)
  1258  			return fmtprint(f, ".(%N)", n->right);
  1259  		return fmtprint(f, ".(%T)", n->type);
  1260  
  1261  	case OINDEX:
  1262  	case OINDEXMAP:
  1263  	case OSLICE:
  1264  	case OSLICESTR:
  1265  	case OSLICEARR:
  1266  	case OSLICE3:
  1267  	case OSLICE3ARR:
  1268  		exprfmt(f, n->left, nprec);
  1269  		return fmtprint(f, "[%N]", n->right);
  1270  
  1271  	case OCOPY:
  1272  	case OCOMPLEX:
  1273  		return fmtprint(f, "%#O(%N, %N)", n->op, n->left, n->right);
  1274  
  1275  	case OCONV:
  1276  	case OCONVIFACE:
  1277  	case OCONVNOP:
  1278  	case OARRAYBYTESTR:
  1279  	case OARRAYRUNESTR:
  1280  	case OSTRARRAYBYTE:
  1281  	case OSTRARRAYRUNE:
  1282  	case ORUNESTR:
  1283  		if(n->type == T || n->type->sym == S)
  1284  			return fmtprint(f, "(%T)(%N)", n->type, n->left);
  1285  		if(n->left)
  1286  			return fmtprint(f, "%T(%N)", n->type, n->left);
  1287  		return fmtprint(f, "%T(%,H)", n->type, n->list);
  1288  
  1289  	case OREAL:
  1290  	case OIMAG:
  1291  	case OAPPEND:
  1292  	case OCAP:
  1293  	case OCLOSE:
  1294  	case ODELETE:
  1295  	case OLEN:
  1296  	case OMAKE:
  1297  	case ONEW:
  1298  	case OPANIC:
  1299  	case ORECOVER:
  1300  	case OPRINT:
  1301  	case OPRINTN:
  1302  		if(n->left)
  1303  			return fmtprint(f, "%#O(%N)", n->op, n->left);
  1304  		if(n->isddd)
  1305  			return fmtprint(f, "%#O(%,H...)", n->op, n->list);
  1306  		return fmtprint(f, "%#O(%,H)", n->op, n->list);
  1307  
  1308  	case OCALL:
  1309  	case OCALLFUNC:
  1310  	case OCALLINTER:
  1311  	case OCALLMETH:
  1312  		exprfmt(f, n->left, nprec);
  1313  		if(n->isddd)
  1314  			return fmtprint(f, "(%,H...)", n->list);
  1315  		return fmtprint(f, "(%,H)", n->list);
  1316  
  1317  	case OMAKEMAP:
  1318  	case OMAKECHAN:
  1319  	case OMAKESLICE:
  1320  		if(n->list) // pre-typecheck
  1321  			return fmtprint(f, "make(%T, %,H)", n->type, n->list);
  1322  		if(n->right)
  1323  			return fmtprint(f, "make(%T, %N, %N)", n->type, n->left, n->right);
  1324  		if(n->left)
  1325  			return fmtprint(f, "make(%T, %N)", n->type, n->left);
  1326  		return fmtprint(f, "make(%T)", n->type);
  1327  
  1328  	// Unary
  1329  	case OPLUS:
  1330  	case OMINUS:
  1331  	case OADDR:
  1332  	case OCOM:
  1333  	case OIND:
  1334  	case ONOT:
  1335  	case ORECV:
  1336  		if(n->left->op == n->op)
  1337  			fmtprint(f, "%#O ", n->op);
  1338  		else
  1339  			fmtprint(f, "%#O", n->op);
  1340  		return exprfmt(f, n->left, nprec+1);
  1341  
  1342  	// Binary
  1343  	case OADD:
  1344  	case OAND:
  1345  	case OANDAND:
  1346  	case OANDNOT:
  1347  	case ODIV:
  1348  	case OEQ:
  1349  	case OGE:
  1350  	case OGT:
  1351  	case OLE:
  1352  	case OLT:
  1353  	case OLSH:
  1354  	case OMOD:
  1355  	case OMUL:
  1356  	case ONE:
  1357  	case OOR:
  1358  	case OOROR:
  1359  	case ORSH:
  1360  	case OSEND:
  1361  	case OSUB:
  1362  	case OXOR:
  1363  		exprfmt(f, n->left, nprec);
  1364  		fmtprint(f, " %#O ", n->op);
  1365  		exprfmt(f, n->right, nprec+1);
  1366  		return 0;
  1367  
  1368  	case OADDSTR:
  1369  		for(l=n->list; l; l=l->next) {
  1370  			if(l != n->list)
  1371  				fmtprint(f, " + ");
  1372  			exprfmt(f, l->n, nprec);
  1373  		}
  1374  		return 0;
  1375  
  1376  	case OCMPSTR:
  1377  	case OCMPIFACE:
  1378  		exprfmt(f, n->left, nprec);
  1379  		fmtprint(f, " %#O ", n->etype);
  1380  		exprfmt(f, n->right, nprec+1);
  1381  		return 0;
  1382  	}
  1383  
  1384  	return fmtprint(f, "<node %O>", n->op);
  1385  }
  1386  
  1387  static int
  1388  nodefmt(Fmt *f, Node *n)
  1389  {
  1390  	Type *t;
  1391  
  1392  	t = n->type;
  1393  
  1394  	// we almost always want the original, except in export mode for literals
  1395  	// this saves the importer some work, and avoids us having to redo some
  1396  	// special casing for package unsafe
  1397  	if((fmtmode != FExp || n->op != OLITERAL) && n->orig != N)
  1398  		n = n->orig;
  1399  
  1400  	if(f->flags&FmtLong && t != T) {
  1401  		if(t->etype == TNIL)
  1402  			return fmtprint(f, "nil");
  1403  		else
  1404  			return fmtprint(f, "%N (type %T)", n, t);
  1405  	}
  1406  
  1407  	// TODO inlining produces expressions with ninits. we can't print these yet.
  1408  
  1409  	if(opprec[n->op] < 0)
  1410  		return stmtfmt(f, n);
  1411  
  1412  	return exprfmt(f, n, 0);
  1413  }
  1414  
  1415  static int dumpdepth;
  1416  
  1417  static void
  1418  indent(Fmt *fp)
  1419  {
  1420  	int i;
  1421  
  1422  	fmtstrcpy(fp, "\n");
  1423  	for(i = 0; i < dumpdepth; ++i)
  1424  		fmtstrcpy(fp, ".   ");
  1425  }
  1426  
  1427  static int
  1428  nodedump(Fmt *fp, Node *n)
  1429  {
  1430  	int recur;
  1431  
  1432  	if(n == N)
  1433  		return 0;
  1434  
  1435  	recur = !(fp->flags&FmtShort);
  1436  
  1437  	if(recur) {
  1438  		indent(fp);
  1439  		if(dumpdepth > 10)
  1440  			return fmtstrcpy(fp, "...");
  1441  
  1442  		if(n->ninit != nil) {
  1443  			fmtprint(fp, "%O-init%H", n->op, n->ninit);
  1444  			indent(fp);
  1445  		}
  1446  	}
  1447  
  1448  //	fmtprint(fp, "[%p]", n);
  1449  
  1450  	switch(n->op) {
  1451  	default:
  1452  		fmtprint(fp, "%O%J", n->op, n);
  1453  		break;
  1454  	case OREGISTER:
  1455  	case OINDREG:
  1456  		fmtprint(fp, "%O-%R%J", n->op, n->val.u.reg, n);
  1457  		break;
  1458  	case OLITERAL:
  1459  		fmtprint(fp, "%O-%V%J", n->op, &n->val, n);
  1460  		break;
  1461  	case ONAME:
  1462  	case ONONAME:
  1463  		if(n->sym != S)
  1464  			fmtprint(fp, "%O-%S%J", n->op, n->sym, n);
  1465  		else
  1466  			fmtprint(fp, "%O%J", n->op, n);
  1467  		if(recur && n->type == T && n->ntype) {
  1468  			indent(fp);
  1469  			fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
  1470  		}
  1471  		break;
  1472  	case OASOP:
  1473  		fmtprint(fp, "%O-%O%J", n->op, n->etype, n);
  1474  		break;
  1475  	case OTYPE:
  1476  		fmtprint(fp, "%O %S%J type=%T", n->op, n->sym, n, n->type);
  1477  		if(recur && n->type == T && n->ntype) {
  1478  			indent(fp);
  1479  			fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
  1480  		}
  1481  		break;
  1482  	}
  1483  
  1484  	if(n->sym != S && n->op != ONAME)
  1485  		fmtprint(fp, " %S G%d", n->sym, n->vargen);
  1486  
  1487  	if(n->type != T)
  1488  		fmtprint(fp, " %T", n->type);
  1489  
  1490  	if(recur) {
  1491  		if(n->left)
  1492  			fmtprint(fp, "%N", n->left);
  1493  		if(n->right)
  1494  			fmtprint(fp, "%N", n->right);
  1495  		if(n->list) {
  1496  			indent(fp);
  1497  			fmtprint(fp, "%O-list%H", n->op, n->list);
  1498  		}
  1499  		if(n->rlist) {
  1500  			indent(fp);
  1501  			fmtprint(fp, "%O-rlist%H", n->op, n->rlist);
  1502  		}
  1503  		if(n->ntest) {
  1504  			indent(fp);
  1505  			fmtprint(fp, "%O-test%N", n->op, n->ntest);
  1506  		}
  1507  		if(n->nbody) {
  1508  			indent(fp);
  1509  			fmtprint(fp, "%O-body%H", n->op, n->nbody);
  1510  		}
  1511  		if(n->nelse) {
  1512  			indent(fp);
  1513  			fmtprint(fp, "%O-else%H", n->op, n->nelse);
  1514  		}
  1515  		if(n->nincr) {
  1516  			indent(fp);
  1517  			fmtprint(fp, "%O-incr%N", n->op, n->nincr);
  1518  		}
  1519  	}
  1520  
  1521  	return 0;
  1522  }
  1523  
  1524  // Fmt "%S": syms
  1525  // Flags:  "%hS" suppresses qualifying with package
  1526  static int
  1527  Sconv(Fmt *fp)
  1528  {
  1529  	Sym *s;
  1530  	int r, sm;
  1531  	unsigned long sf;
  1532  
  1533  	if(fp->flags&FmtLong)
  1534  		return linksymfmt(fp);
  1535  
  1536  	s = va_arg(fp->args, Sym*);
  1537  	if(s == S)
  1538  		return fmtstrcpy(fp, "<S>");
  1539  
  1540  	if(s->name && s->name[0] == '_' && s->name[1] == '\0')
  1541  		return fmtstrcpy(fp, "_");
  1542  
  1543  	sf = fp->flags;
  1544  	sm = setfmode(&fp->flags);
  1545  	r = symfmt(fp, s);
  1546  	fp->flags = sf;
  1547  	fmtmode = sm;
  1548  	return r;
  1549  }
  1550  
  1551  // Fmt "%T": types.
  1552  // Flags: 'l' print definition, not name
  1553  //	  'h' omit 'func' and receiver from function types, short type names
  1554  //	  'u' package name, not prefix (FTypeId mode, sticky)
  1555  static int
  1556  Tconv(Fmt *fp)
  1557  {
  1558  	Type *t;
  1559  	int r, sm;
  1560  	unsigned long sf;
  1561  
  1562  	t = va_arg(fp->args, Type*);
  1563  	if(t == T)
  1564  		return fmtstrcpy(fp, "<T>");
  1565  
  1566  	if(t->trecur > 4)
  1567  		return fmtstrcpy(fp, "<...>");
  1568  
  1569  	t->trecur++;
  1570  	sf = fp->flags;
  1571  	sm = setfmode(&fp->flags);
  1572  
  1573  	if(fmtmode == FTypeId && (sf&FmtUnsigned))
  1574  		fmtpkgpfx++;
  1575  	if(fmtpkgpfx)
  1576  		fp->flags |= FmtUnsigned;
  1577  
  1578  	r = typefmt(fp, t);
  1579  
  1580  	if(fmtmode == FTypeId && (sf&FmtUnsigned))
  1581  		fmtpkgpfx--;
  1582  
  1583  	fp->flags = sf;
  1584  	fmtmode = sm;
  1585  	t->trecur--;
  1586  	return r;
  1587  }
  1588  
  1589  // Fmt '%N': Nodes.
  1590  // Flags: 'l' suffix with "(type %T)" where possible
  1591  //	  '+h' in debug mode, don't recurse, no multiline output
  1592  static int
  1593  Nconv(Fmt *fp)
  1594  {
  1595  	Node *n;
  1596  	int r, sm;
  1597  	unsigned long sf;
  1598  
  1599  	n = va_arg(fp->args, Node*);
  1600  	if(n == N)
  1601  		return fmtstrcpy(fp, "<N>");
  1602  	sf = fp->flags;
  1603  	sm = setfmode(&fp->flags);
  1604  
  1605  	r = -1;
  1606  	switch(fmtmode) {
  1607  	case FErr:
  1608  	case FExp:
  1609  		r = nodefmt(fp, n);
  1610  		break;
  1611  	case FDbg:
  1612  		dumpdepth++;
  1613  		r = nodedump(fp, n);
  1614  		dumpdepth--;
  1615  		break;
  1616  	default:
  1617  		fatal("unhandled %%N mode");
  1618  	}
  1619  
  1620  	fp->flags = sf;
  1621  	fmtmode = sm;
  1622  	return r;
  1623  }
  1624  
  1625  // Fmt '%H': NodeList.
  1626  // Flags: all those of %N plus ',': separate with comma's instead of semicolons.
  1627  static int
  1628  Hconv(Fmt *fp)
  1629  {
  1630  	NodeList *l;
  1631  	int r, sm;
  1632  	unsigned long sf;
  1633  	char *sep;
  1634  
  1635  	l = va_arg(fp->args, NodeList*);
  1636  
  1637  	if(l == nil && fmtmode == FDbg)
  1638  		return fmtstrcpy(fp, "<nil>");
  1639  
  1640  	sf = fp->flags;
  1641  	sm = setfmode(&fp->flags);
  1642  	r = 0;
  1643  	sep = "; ";
  1644  	if(fmtmode == FDbg)
  1645  		sep = "\n";
  1646  	else if(fp->flags & FmtComma)
  1647  		sep = ", ";
  1648  
  1649  	for(;l; l=l->next) {
  1650  		r += fmtprint(fp, "%N", l->n);
  1651  		if(l->next)
  1652  			r += fmtstrcpy(fp, sep);
  1653  	}
  1654  
  1655  	fp->flags = sf;
  1656  	fmtmode = sm;
  1657  	return r;
  1658  }
  1659  
  1660  void
  1661  fmtinstallgo(void)
  1662  {
  1663  	fmtmode = FErr;
  1664  	fmtinstall('E', Econv);		// etype opcodes
  1665  	fmtinstall('J', Jconv);		// all the node flags
  1666  	fmtinstall('H', Hconv);		// node lists
  1667  	fmtinstall('L', Lconv);		// line number
  1668  	fmtinstall('N', Nconv);		// node pointer
  1669  	fmtinstall('O', Oconv);		// node opcodes
  1670  	fmtinstall('S', Sconv);		// sym pointer
  1671  	fmtinstall('T', Tconv);		// type pointer
  1672  	fmtinstall('V', Vconv);		// val pointer
  1673  	fmtinstall('Z', Zconv);		// escaped string
  1674  
  1675  	// These are in mparith1.c
  1676  	fmtinstall('B', Bconv);	// big numbers
  1677  	fmtinstall('F', Fconv);	// big float numbers
  1678  
  1679  }
  1680  
  1681  void
  1682  dumplist(char *s, NodeList *l)
  1683  {
  1684  	print("%s%+H\n", s, l);
  1685  }
  1686  
  1687  void
  1688  dump(char *s, Node *n)
  1689  {
  1690  	print("%s [%p]%+N\n", s, n, n);
  1691  }