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