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