github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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  		// Format the bucket struct for map[x]y as map.bucket[x]y.
   704  		// This avoids a recursive print that generates very long names.
   705  		if(t->hmap != T) {
   706  			t = t->hmap;
   707  			return fmtprint(fp, "map.bucket[%T]%T", t->down, t->type);
   708  		}
   709  
   710  		if(t->funarg) {
   711  			fmtstrcpy(fp, "(");
   712  			if(fmtmode == FTypeId || fmtmode == FErr) {	// no argument names on function signature, and no "noescape" tags
   713  				for(t1=t->type; t1!=T; t1=t1->down)
   714  					if(t1->down)
   715  						fmtprint(fp, "%hT, ", t1);
   716  					else
   717  						fmtprint(fp, "%hT", t1);
   718  			} else {
   719  				for(t1=t->type; t1!=T; t1=t1->down)
   720  					if(t1->down)
   721  						fmtprint(fp, "%T, ", t1);
   722  					else
   723  						fmtprint(fp, "%T", t1);
   724  			}
   725  			fmtstrcpy(fp, ")");
   726  		} else {
   727  			fmtstrcpy(fp, "struct {");
   728  			for(t1=t->type; t1!=T; t1=t1->down)
   729  				if(t1->down)
   730  					fmtprint(fp, " %lT;", t1);
   731  				else
   732  					fmtprint(fp, " %lT ", t1);
   733  			fmtstrcpy(fp, "}");
   734  		}
   735  		return 0;
   736  
   737  	case TFIELD:
   738  		if(!(fp->flags&FmtShort)) {
   739  			s = t->sym;
   740  
   741  			// Take the name from the original, lest we substituted it with ~anon%d
   742  			if ((fmtmode == FErr || fmtmode == FExp) && t->nname != N) {
   743  				if(t->nname->orig != N) {
   744  					s = t->nname->orig->sym;
   745  					if(s != S && s->name[0] == '~')
   746  						s = S;
   747  				} else 
   748  					s = S;
   749  			}
   750  			
   751  			if(s != S && !t->embedded) {
   752  				if(t->funarg)
   753  					fmtprint(fp, "%N ", t->nname);
   754  				else if(fp->flags&FmtLong)
   755  					fmtprint(fp, "%hhS ", s);  // qualify non-exported names (used on structs, not on funarg)
   756  				else 
   757  					fmtprint(fp, "%S ", s);
   758  			} else if(fmtmode == FExp) {
   759  				// TODO(rsc) this breaks on the eliding of unused arguments in the backend
   760  				// when this is fixed, the special case in dcl.c checkarglist can go.
   761  				//if(t->funarg)
   762  				//	fmtstrcpy(fp, "_ ");
   763  				//else
   764  				if(t->embedded && s->pkg != nil && s->pkg->path->len > 0)
   765  					fmtprint(fp, "@\"%Z\".? ", s->pkg->path);
   766  				else
   767  					fmtstrcpy(fp, "? ");
   768  			}
   769  		}
   770  
   771  		if(t->isddd)
   772  			fmtprint(fp, "...%T", t->type->type);
   773  		else
   774  			fmtprint(fp, "%T", t->type);
   775  
   776  		if(!(fp->flags&FmtShort) && t->note)
   777  			fmtprint(fp, " \"%Z\"", t->note);
   778  		return 0;
   779  
   780  	case TFORW:
   781  		if(t->sym)
   782  			return fmtprint(fp, "undefined %S", t->sym);
   783  		return fmtstrcpy(fp, "undefined");
   784  
   785  	case TUNSAFEPTR:
   786  		if(fmtmode == FExp)
   787  			return fmtprint(fp, "@\"unsafe\".Pointer");
   788  		return fmtprint(fp, "unsafe.Pointer");
   789  	}
   790  
   791  	if(fmtmode == FExp)
   792  		fatal("missing %E case during export", t->etype);
   793  	// Don't know how to handle - fall back to detailed prints.
   794  	return fmtprint(fp, "%E <%S> %T", t->etype, t->sym, t->type);
   795  }
   796  
   797  // Statements which may be rendered with a simplestmt as init.
   798  static int
   799  stmtwithinit(int op)
   800  {
   801  	switch(op) {
   802  	case OIF:
   803  	case OFOR:
   804  	case OSWITCH:
   805  		return 1;
   806  	}
   807  	return 0;
   808  }
   809  
   810  static int
   811  stmtfmt(Fmt *f, Node *n)
   812  {
   813  	int complexinit, simpleinit, extrablock;
   814  
   815  	// some statements allow for an init, but at most one,
   816  	// but we may have an arbitrary number added, eg by typecheck
   817  	// and inlining.  If it doesn't fit the syntax, emit an enclosing
   818  	// block starting with the init statements.
   819  
   820  	// if we can just say "for" n->ninit; ... then do so
   821  	simpleinit = n->ninit && !n->ninit->next && !n->ninit->n->ninit && stmtwithinit(n->op);
   822  	// otherwise, print the inits as separate statements
   823  	complexinit = n->ninit && !simpleinit && (fmtmode != FErr);
   824  	// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
   825  	extrablock = complexinit && stmtwithinit(n->op);
   826  
   827  	if(extrablock)
   828  		fmtstrcpy(f, "{");
   829  
   830  	if(complexinit)
   831  		fmtprint(f, " %H; ", n->ninit);
   832  
   833  	switch(n->op){
   834  	case ODCL:
   835  		if(fmtmode == FExp) {
   836  			switch(n->left->class&~PHEAP) {
   837  			case PPARAM:
   838  			case PPARAMOUT:
   839  			case PAUTO:
   840  				fmtprint(f, "var %N %T", n->left, n->left->type);
   841  				goto ret;
   842  			}
   843  		}			
   844  		fmtprint(f, "var %S %T", n->left->sym, n->left->type);
   845  		break;
   846  
   847  	case ODCLFIELD:
   848  		if(n->left)
   849  			fmtprint(f, "%N %N", n->left, n->right);
   850  		else
   851  			fmtprint(f, "%N", n->right);
   852  		break;
   853  
   854  	case OAS:
   855  		// Don't export "v = <N>" initializing statements, hope they're always 
   856  		// preceded by the DCL which will be re-parsed and typecheck to reproduce
   857  		// the "v = <N>" again.
   858  		if(fmtmode == FExp && n->right == N)
   859  			break;
   860  
   861  		if(n->colas && !complexinit)
   862  			fmtprint(f, "%N := %N", n->left, n->right);
   863  		else
   864  			fmtprint(f, "%N = %N", n->left, n->right);
   865  		break;
   866  
   867  	case OASOP:
   868  		fmtprint(f, "%N %#O= %N", n->left, n->etype, n->right);
   869  		break;
   870  
   871  	case OAS2:
   872  		if(n->colas && !complexinit) {
   873  			fmtprint(f, "%,H := %,H", n->list, n->rlist);
   874  			break;
   875  		}
   876  		// fallthrough
   877  	case OAS2DOTTYPE:
   878  	case OAS2FUNC:
   879  	case OAS2MAPR:
   880  	case OAS2RECV:
   881  		fmtprint(f, "%,H = %,H", n->list, n->rlist);
   882  		break;
   883  
   884  	case ORETURN:
   885  		fmtprint(f, "return %,H", n->list);
   886  		break;
   887  
   888  	case ORETJMP:
   889  		fmtprint(f, "retjmp %S", n->sym);
   890  		break;
   891  	
   892  	case OPROC:
   893  		fmtprint(f, "go %N", n->left);
   894  		break;
   895  
   896  	case ODEFER:
   897  		fmtprint(f, "defer %N", n->left);
   898  		break;
   899  
   900  	case OIF:
   901  		if(simpleinit)
   902  			fmtprint(f, "if %N; %N { %H }", n->ninit->n, n->ntest, n->nbody);
   903  		else
   904  			fmtprint(f, "if %N { %H }", n->ntest, n->nbody);
   905  		if(n->nelse)
   906  			fmtprint(f, " else { %H }", n->nelse);
   907  		break;
   908  
   909  	case OFOR:
   910  		if(fmtmode == FErr) {	// TODO maybe only if FmtShort, same below
   911  			fmtstrcpy(f, "for loop");
   912  			break;
   913  		}
   914  
   915  		fmtstrcpy(f, "for");
   916  		if(simpleinit)
   917  			fmtprint(f, " %N;", n->ninit->n);
   918  		else if(n->nincr)
   919  			fmtstrcpy(f, " ;");
   920  
   921  		if(n->ntest)
   922  			fmtprint(f, " %N", n->ntest);
   923  
   924  		if(n->nincr)
   925  			fmtprint(f, "; %N", n->nincr);
   926  		else if(simpleinit)
   927  			fmtstrcpy(f, ";");
   928  
   929  
   930  		fmtprint(f, " { %H }", n->nbody);
   931  		break;
   932  
   933  	case ORANGE:
   934  		if(fmtmode == FErr) {
   935  			fmtstrcpy(f, "for loop");
   936  			break;
   937  		}
   938  
   939  		fmtprint(f, "for %,H = range %N { %H }", n->list, n->right, n->nbody);
   940  		break;
   941  
   942  	case OSELECT:
   943  	case OSWITCH:
   944  		if(fmtmode == FErr) {
   945  			fmtprint(f, "%O statement", n->op);
   946  			break;
   947  		}
   948  
   949  		fmtprint(f, "%#O", n->op);
   950  		if(simpleinit)
   951  			fmtprint(f, " %N;", n->ninit->n);
   952  		if(n->ntest)
   953  			fmtprint(f, "%N", n->ntest);
   954  
   955  		fmtprint(f, " { %H }", n->list);
   956  		break;
   957  
   958  	case OCASE:
   959  	case OXCASE:
   960  		if(n->list)
   961  			fmtprint(f, "case %,H: %H", n->list, n->nbody);
   962  		else
   963  			fmtprint(f, "default: %H", n->nbody);
   964  		break;
   965  
   966  	case OBREAK:
   967  	case OCONTINUE:
   968  	case OGOTO:
   969  	case OFALL:
   970  	case OXFALL:
   971  		if(n->left)
   972  			fmtprint(f, "%#O %N", n->op, n->left);
   973  		else
   974  			fmtprint(f, "%#O", n->op);
   975  		break;
   976  
   977  	case OEMPTY:
   978  		break;
   979  
   980  	case OLABEL:
   981  		fmtprint(f, "%N: ", n->left);
   982  		break;
   983  	  
   984  	}
   985  ret:
   986  
   987  	if(extrablock)
   988  		fmtstrcpy(f, "}");
   989  
   990  	return 0;
   991  }
   992  
   993  
   994  static int opprec[] = {
   995  	[OAPPEND] = 8,
   996  	[OARRAYBYTESTR] = 8,
   997  	[OARRAYLIT] = 8,
   998  	[OARRAYRUNESTR] = 8,
   999  	[OCALLFUNC] = 8,
  1000  	[OCALLINTER] = 8,
  1001  	[OCALLMETH] = 8,
  1002  	[OCALL] = 8,
  1003  	[OCAP] = 8,
  1004  	[OCLOSE] = 8,
  1005  	[OCONVIFACE] = 8,
  1006  	[OCONVNOP] = 8,
  1007  	[OCONV] = 8,
  1008  	[OCOPY] = 8,
  1009  	[ODELETE] = 8,
  1010  	[OLEN] = 8,
  1011  	[OLITERAL] = 8,
  1012  	[OMAKESLICE] = 8,
  1013  	[OMAKE] = 8,
  1014  	[OMAPLIT] = 8,
  1015  	[ONAME] = 8,
  1016  	[ONEW] = 8,
  1017  	[ONONAME] = 8,
  1018  	[OPACK] = 8,
  1019  	[OPANIC] = 8,
  1020  	[OPAREN] = 8,
  1021  	[OPRINTN] = 8,
  1022  	[OPRINT] = 8,
  1023  	[ORUNESTR] = 8,
  1024  	[OSTRARRAYBYTE] = 8,
  1025  	[OSTRARRAYRUNE] = 8,
  1026  	[OSTRUCTLIT] = 8,
  1027  	[OTARRAY] = 8,
  1028  	[OTCHAN] = 8,
  1029  	[OTFUNC] = 8,
  1030  	[OTINTER] = 8,
  1031  	[OTMAP] = 8,
  1032  	[OTPAREN] = 8,
  1033  	[OTSTRUCT] = 8,
  1034  
  1035  	[OINDEXMAP] = 8,
  1036  	[OINDEX] = 8,
  1037  	[OSLICE] = 8,
  1038  	[OSLICESTR] = 8,
  1039  	[OSLICEARR] = 8,
  1040  	[OSLICE3] = 8,
  1041  	[OSLICE3ARR] = 8,
  1042  	[ODOTINTER] = 8,
  1043  	[ODOTMETH] = 8,
  1044  	[ODOTPTR] = 8,
  1045  	[ODOTTYPE2] = 8,
  1046  	[ODOTTYPE] = 8,
  1047  	[ODOT] = 8,
  1048  	[OXDOT] = 8,
  1049  	[OCALLPART] = 8,
  1050  
  1051  	[OPLUS] = 7,
  1052  	[ONOT] = 7,
  1053  	[OCOM] = 7,
  1054  	[OMINUS] = 7,
  1055  	[OADDR] = 7,
  1056  	[OIND] = 7,
  1057  	[ORECV] = 7,
  1058  
  1059  	[OMUL] = 6,
  1060  	[ODIV] = 6,
  1061  	[OMOD] = 6,
  1062  	[OLSH] = 6,
  1063  	[ORSH] = 6,
  1064  	[OAND] = 6,
  1065  	[OANDNOT] = 6,
  1066  
  1067  	[OADD] = 5,
  1068  	[OSUB] = 5,
  1069  	[OOR] = 5,
  1070  	[OXOR] = 5,
  1071  
  1072  	[OEQ] = 4,
  1073  	[OLT] = 4,
  1074  	[OLE] = 4,
  1075  	[OGE] = 4,
  1076  	[OGT] = 4,
  1077  	[ONE] = 4,
  1078  	[OCMPSTR] = 4,
  1079  	[OCMPIFACE] = 4,
  1080  
  1081  	[OSEND] = 3,
  1082  	[OANDAND] = 2,
  1083  	[OOROR] = 1,
  1084  
  1085  	// Statements handled by stmtfmt
  1086  	[OAS] = -1,
  1087  	[OAS2] = -1,
  1088  	[OAS2DOTTYPE] = -1,
  1089  	[OAS2FUNC] = -1,
  1090  	[OAS2MAPR] = -1,
  1091  	[OAS2RECV] = -1,
  1092  	[OASOP] = -1,
  1093  	[OBREAK] = -1,
  1094  	[OCASE] = -1,
  1095  	[OCONTINUE] = -1,
  1096  	[ODCL] = -1,
  1097  	[ODCLFIELD] = -1,
  1098  	[ODEFER] = -1,
  1099  	[OEMPTY] = -1,
  1100  	[OFALL] = -1,
  1101  	[OFOR] = -1,
  1102  	[OIF] = -1,
  1103  	[OLABEL] = -1,
  1104  	[OPROC] = -1,
  1105  	[ORANGE] = -1,
  1106  	[ORETURN] = -1,
  1107  	[OSELECT] = -1,
  1108  	[OSWITCH] = -1,
  1109  	[OXCASE] = -1,
  1110  	[OXFALL] = -1,
  1111  
  1112  	[OEND] = 0
  1113  };
  1114  
  1115  static int
  1116  exprfmt(Fmt *f, Node *n, int prec)
  1117  {
  1118  	int nprec;
  1119  	int ptrlit;
  1120  	NodeList *l;
  1121  
  1122  	while(n && n->implicit && (n->op == OIND || n->op == OADDR))
  1123  		n = n->left;
  1124  
  1125  	if(n == N)
  1126  		return fmtstrcpy(f, "<N>");
  1127  
  1128  	nprec = opprec[n->op];
  1129  	if(n->op == OTYPE && n->sym != S)
  1130  		nprec = 8;
  1131  
  1132  	if(prec > nprec)
  1133  		return fmtprint(f, "(%N)", n);
  1134  
  1135  	switch(n->op) {
  1136  	case OPAREN:
  1137  		return fmtprint(f, "(%N)", n->left);
  1138  
  1139  	case ODDDARG:
  1140  		return fmtprint(f, "... argument");
  1141  
  1142  	case OREGISTER:
  1143  		return fmtprint(f, "%R", n->val.u.reg);
  1144  
  1145  	case OLITERAL:  // this is a bit of a mess
  1146  		if(fmtmode == FErr && n->sym != S)
  1147  			return fmtprint(f, "%S", n->sym);
  1148  		if(n->val.ctype == CTNIL && n->orig != N && n->orig != n)
  1149  			return exprfmt(f, n->orig, prec);
  1150  		if(n->type != T && n->type != types[n->type->etype] && n->type != idealbool && n->type != idealstring) {
  1151  			// Need parens when type begins with what might
  1152  			// be misinterpreted as a unary operator: * or <-.
  1153  			if(isptr[n->type->etype] || (n->type->etype == TCHAN && n->type->chan == Crecv))
  1154  				return fmtprint(f, "(%T)(%V)", n->type, &n->val);
  1155  			else 
  1156  				return fmtprint(f, "%T(%V)", n->type, &n->val);
  1157  		}
  1158  		return fmtprint(f, "%V", &n->val);
  1159  
  1160  	case ONAME:
  1161  		// Special case: name used as local variable in export.
  1162  		switch(n->class&~PHEAP){
  1163  		case PAUTO:
  1164  		case PPARAM:
  1165  		case PPARAMOUT:
  1166  			if(fmtmode == FExp && n->sym && !isblanksym(n->sym) && n->vargen > 0)
  1167  				return fmtprint(f, "%S·%d", n->sym, n->vargen);
  1168  		}
  1169  
  1170  		// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
  1171  		// but for export, this should be rendered as (*pkg.T).meth.
  1172  		// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
  1173  		if(fmtmode == FExp && n->left && n->left->op == OTYPE && n->right && n->right->op == ONAME) {
  1174  			if(isptr[n->left->type->etype])
  1175  				return fmtprint(f, "(%T).%hhS", n->left->type, n->right->sym);
  1176  			else
  1177  				return fmtprint(f, "%T.%hhS", n->left->type, n->right->sym);
  1178  		}
  1179  		//fallthrough
  1180  	case OPACK:
  1181  	case ONONAME:
  1182  		return fmtprint(f, "%S", n->sym);
  1183  
  1184  	case OTYPE:
  1185  		if(n->type == T && n->sym != S)
  1186  			return fmtprint(f, "%S", n->sym);
  1187  		return fmtprint(f, "%T", n->type);
  1188  
  1189  	case OTARRAY:
  1190  		if(n->left)
  1191  			return fmtprint(f, "[]%N", n->left);
  1192  		return fmtprint(f, "[]%N", n->right);  // happens before typecheck
  1193  
  1194  	case OTPAREN:
  1195  		return fmtprint(f, "(%N)", n->left);
  1196  
  1197  	case OTMAP:
  1198  		return fmtprint(f, "map[%N]%N", n->left, n->right);
  1199  
  1200  	case OTCHAN:
  1201  		switch(n->etype) {
  1202  		case Crecv:
  1203  			return fmtprint(f, "<-chan %N", n->left);
  1204  		case Csend:
  1205  			return fmtprint(f, "chan<- %N", n->left);
  1206  		default:
  1207  			if(n->left != N && n->left->op == TCHAN && n->left->sym == S && n->left->etype == Crecv)
  1208  				return fmtprint(f, "chan (%N)", n->left);
  1209  			else
  1210  				return fmtprint(f, "chan %N", n->left);
  1211  		}
  1212  
  1213  	case OTSTRUCT:
  1214  		return fmtprint(f, "<struct>");
  1215  
  1216  	case OTINTER:
  1217  		return fmtprint(f, "<inter>");
  1218  
  1219  	case OTFUNC:
  1220  		return fmtprint(f, "<func>");
  1221  
  1222  	case OCLOSURE:
  1223  		if(fmtmode == FErr)
  1224  			return fmtstrcpy(f, "func literal");
  1225  		if(n->nbody)
  1226  			return fmtprint(f, "%T { %H }", n->type, n->nbody);
  1227  		return fmtprint(f, "%T { %H }", n->type, n->closure->nbody);
  1228  
  1229  	case OCOMPLIT:
  1230  		ptrlit = n->right != N && n->right->implicit && n->right->type && isptr[n->right->type->etype];
  1231  		if(fmtmode == FErr) {
  1232  			if(n->right != N && n->right->type != T && !n->implicit) {
  1233  				if(ptrlit)
  1234  					return fmtprint(f, "&%T literal", n->right->type->type);
  1235  				else
  1236  					return fmtprint(f, "%T literal", n->right->type);
  1237  			}
  1238  			return fmtstrcpy(f, "composite literal");
  1239  		}
  1240  		if(fmtmode == FExp && ptrlit)
  1241  			// typecheck has overwritten OIND by OTYPE with pointer type.
  1242  			return fmtprint(f, "(&%T{ %,H })", n->right->type->type, n->list);
  1243  		return fmtprint(f, "(%N{ %,H })", n->right, n->list);
  1244  
  1245  	case OPTRLIT:
  1246  		if(fmtmode == FExp && n->left->implicit)
  1247  			return fmtprint(f, "%N", n->left);
  1248  		return fmtprint(f, "&%N", n->left);
  1249  
  1250  	case OSTRUCTLIT:
  1251  		if(fmtmode == FExp) {   // requires special handling of field names
  1252  			if(n->implicit)
  1253  				fmtstrcpy(f, "{");
  1254  			else
  1255  				fmtprint(f, "(%T{", n->type);
  1256  			for(l=n->list; l; l=l->next) {
  1257  				fmtprint(f, " %hhS:%N", l->n->left->sym, l->n->right);
  1258  
  1259  				if(l->next)
  1260  					fmtstrcpy(f, ",");
  1261  				else
  1262  					fmtstrcpy(f, " ");
  1263  			}
  1264  			if(!n->implicit)
  1265  				return fmtstrcpy(f, "})");
  1266  			return fmtstrcpy(f, "}");
  1267  		}
  1268  		// fallthrough
  1269  
  1270  	case OARRAYLIT:
  1271  	case OMAPLIT:
  1272  		if(fmtmode == FErr)
  1273  			return fmtprint(f, "%T literal", n->type);
  1274  		if(fmtmode == FExp && n->implicit)
  1275  			return fmtprint(f, "{ %,H }", n->list);
  1276  		return fmtprint(f, "(%T{ %,H })", n->type, n->list);
  1277  
  1278  	case OKEY:
  1279  		if(n->left && n->right) {
  1280  			if(fmtmode == FExp && n->left->type && n->left->type->etype == TFIELD) {
  1281  				// requires special handling of field names
  1282  				return fmtprint(f, "%hhS:%N", n->left->sym, n->right);
  1283  			} else
  1284  				return fmtprint(f, "%N:%N", n->left, n->right);
  1285  		}
  1286  		if(!n->left && n->right)
  1287  			return fmtprint(f, ":%N", n->right);
  1288  		if(n->left && !n->right)
  1289  			return fmtprint(f, "%N:", n->left);
  1290  		return fmtstrcpy(f, ":");
  1291  
  1292  	case OXDOT:
  1293  	case ODOT:
  1294  	case ODOTPTR:
  1295  	case ODOTINTER:
  1296  	case ODOTMETH:
  1297  	case OCALLPART:
  1298  		exprfmt(f, n->left, nprec);
  1299  		if(n->right == N || n->right->sym == S)
  1300  			return fmtstrcpy(f, ".<nil>");
  1301  		return fmtprint(f, ".%hhS", n->right->sym);
  1302  
  1303  	case ODOTTYPE:
  1304  	case ODOTTYPE2:
  1305  		exprfmt(f, n->left, nprec);
  1306  		if(n->right != N)
  1307  			return fmtprint(f, ".(%N)", n->right);
  1308  		return fmtprint(f, ".(%T)", n->type);
  1309  
  1310  	case OINDEX:
  1311  	case OINDEXMAP:
  1312  	case OSLICE:
  1313  	case OSLICESTR:
  1314  	case OSLICEARR:
  1315  	case OSLICE3:
  1316  	case OSLICE3ARR:
  1317  		exprfmt(f, n->left, nprec);
  1318  		return fmtprint(f, "[%N]", n->right);
  1319  
  1320  	case OCOPY:
  1321  	case OCOMPLEX:
  1322  		return fmtprint(f, "%#O(%N, %N)", n->op, n->left, n->right);
  1323  
  1324  	case OCONV:
  1325  	case OCONVIFACE:
  1326  	case OCONVNOP:
  1327  	case OARRAYBYTESTR:
  1328  	case OARRAYRUNESTR:
  1329  	case OSTRARRAYBYTE:
  1330  	case OSTRARRAYRUNE:
  1331  	case ORUNESTR:
  1332  		if(n->type == T || n->type->sym == S)
  1333  			return fmtprint(f, "(%T)(%N)", n->type, n->left);
  1334  		if(n->left)
  1335  			return fmtprint(f, "%T(%N)", n->type, n->left);
  1336  		return fmtprint(f, "%T(%,H)", n->type, n->list);
  1337  
  1338  	case OREAL:
  1339  	case OIMAG:
  1340  	case OAPPEND:
  1341  	case OCAP:
  1342  	case OCLOSE:
  1343  	case ODELETE:
  1344  	case OLEN:
  1345  	case OMAKE:
  1346  	case ONEW:
  1347  	case OPANIC:
  1348  	case ORECOVER:
  1349  	case OPRINT:
  1350  	case OPRINTN:
  1351  		if(n->left)
  1352  			return fmtprint(f, "%#O(%N)", n->op, n->left);
  1353  		if(n->isddd)
  1354  			return fmtprint(f, "%#O(%,H...)", n->op, n->list);
  1355  		return fmtprint(f, "%#O(%,H)", n->op, n->list);
  1356  
  1357  	case OCALL:
  1358  	case OCALLFUNC:
  1359  	case OCALLINTER:
  1360  	case OCALLMETH:
  1361  		exprfmt(f, n->left, nprec);
  1362  		if(n->isddd)
  1363  			return fmtprint(f, "(%,H...)", n->list);
  1364  		return fmtprint(f, "(%,H)", n->list);
  1365  
  1366  	case OMAKEMAP:
  1367  	case OMAKECHAN:
  1368  	case OMAKESLICE:
  1369  		if(n->list) // pre-typecheck
  1370  			return fmtprint(f, "make(%T, %,H)", n->type, n->list);
  1371  		if(n->right)
  1372  			return fmtprint(f, "make(%T, %N, %N)", n->type, n->left, n->right);
  1373  		if(n->left)
  1374  			return fmtprint(f, "make(%T, %N)", n->type, n->left);
  1375  		return fmtprint(f, "make(%T)", n->type);
  1376  
  1377  	// Unary
  1378  	case OPLUS:
  1379  	case OMINUS:
  1380  	case OADDR:
  1381  	case OCOM:
  1382  	case OIND:
  1383  	case ONOT:
  1384  	case ORECV:
  1385  		if(n->left->op == n->op)
  1386  			fmtprint(f, "%#O ", n->op);
  1387  		else
  1388  			fmtprint(f, "%#O", n->op);
  1389  		return exprfmt(f, n->left, nprec+1);
  1390  
  1391  	// Binary
  1392  	case OADD:
  1393  	case OADDSTR:
  1394  	case OAND:
  1395  	case OANDAND:
  1396  	case OANDNOT:
  1397  	case ODIV:
  1398  	case OEQ:
  1399  	case OGE:
  1400  	case OGT:
  1401  	case OLE:
  1402  	case OLT:
  1403  	case OLSH:
  1404  	case OMOD:
  1405  	case OMUL:
  1406  	case ONE:
  1407  	case OOR:
  1408  	case OOROR:
  1409  	case ORSH:
  1410  	case OSEND:
  1411  	case OSUB:
  1412  	case OXOR:
  1413  		exprfmt(f, n->left, nprec);
  1414  		fmtprint(f, " %#O ", n->op);
  1415  		exprfmt(f, n->right, nprec+1);
  1416  		return 0;
  1417  
  1418  	case OCMPSTR:
  1419  	case OCMPIFACE:
  1420  		exprfmt(f, n->left, nprec);
  1421  		fmtprint(f, " %#O ", n->etype);
  1422  		exprfmt(f, n->right, nprec+1);
  1423  		return 0;
  1424  	}
  1425  
  1426  	return fmtprint(f, "<node %O>", n->op);
  1427  }
  1428  
  1429  static int
  1430  nodefmt(Fmt *f, Node *n)
  1431  {
  1432  	Type *t;
  1433  
  1434  	t = n->type;
  1435  
  1436  	// we almost always want the original, except in export mode for literals
  1437  	// this saves the importer some work, and avoids us having to redo some
  1438  	// special casing for package unsafe
  1439  	if((fmtmode != FExp || n->op != OLITERAL) && n->orig != N)
  1440  		n = n->orig;
  1441  
  1442  	if(f->flags&FmtLong && t != T) {
  1443  		if(t->etype == TNIL)
  1444  			return fmtprint(f, "nil");
  1445  		else
  1446  			return fmtprint(f, "%N (type %T)", n, t);
  1447  	}
  1448  
  1449  	// TODO inlining produces expressions with ninits. we can't print these yet.
  1450  
  1451  	if(opprec[n->op] < 0)
  1452  		return stmtfmt(f, n);
  1453  
  1454  	return exprfmt(f, n, 0);
  1455  }
  1456  
  1457  static int dumpdepth;
  1458  
  1459  static void
  1460  indent(Fmt *fp)
  1461  {
  1462  	int i;
  1463  
  1464  	fmtstrcpy(fp, "\n");
  1465  	for(i = 0; i < dumpdepth; ++i)
  1466  		fmtstrcpy(fp, ".   ");
  1467  }
  1468  
  1469  static int
  1470  nodedump(Fmt *fp, Node *n)
  1471  {
  1472  	int recur;
  1473  
  1474  	if(n == N)
  1475  		return 0;
  1476  
  1477  	recur = !(fp->flags&FmtShort);
  1478  
  1479  	if(recur) {
  1480  		indent(fp);
  1481  		if(dumpdepth > 10)
  1482  			return fmtstrcpy(fp, "...");
  1483  
  1484  		if(n->ninit != nil) {
  1485  			fmtprint(fp, "%O-init%H", n->op, n->ninit);
  1486  			indent(fp);
  1487  		}
  1488  	}
  1489  
  1490  //	fmtprint(fp, "[%p]", n);
  1491  
  1492  	switch(n->op) {
  1493  	default:
  1494  		fmtprint(fp, "%O%J", n->op, n);
  1495  		break;
  1496  	case OREGISTER:
  1497  	case OINDREG:
  1498  		fmtprint(fp, "%O-%R%J", n->op, n->val.u.reg, n);
  1499  		break;
  1500  	case OLITERAL:
  1501  		fmtprint(fp, "%O-%V%J", n->op, &n->val, n);
  1502  		break;
  1503  	case ONAME:
  1504  	case ONONAME:
  1505  		if(n->sym != S)
  1506  			fmtprint(fp, "%O-%S%J", n->op, n->sym, n);
  1507  		else
  1508  			fmtprint(fp, "%O%J", n->op, n);
  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  	case OASOP:
  1515  		fmtprint(fp, "%O-%O%J", n->op, n->etype, n);
  1516  		break;
  1517  	case OTYPE:
  1518  		fmtprint(fp, "%O %S%J type=%T", n->op, n->sym, n, n->type);
  1519  		if(recur && n->type == T && n->ntype) {
  1520  			indent(fp);
  1521  			fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
  1522  		}
  1523  		break;
  1524  	}
  1525  
  1526  	if(n->sym != S && n->op != ONAME)
  1527  		fmtprint(fp, " %S G%d", n->sym, n->vargen);
  1528  
  1529  	if(n->type != T)
  1530  		fmtprint(fp, " %T", n->type);
  1531  
  1532  	if(recur) {
  1533  		if(n->left)
  1534  			fmtprint(fp, "%N", n->left);
  1535  		if(n->right)
  1536  			fmtprint(fp, "%N", n->right);
  1537  		if(n->list) {
  1538  			indent(fp);
  1539  			fmtprint(fp, "%O-list%H", n->op, n->list);
  1540  		}
  1541  		if(n->rlist) {
  1542  			indent(fp);
  1543  			fmtprint(fp, "%O-rlist%H", n->op, n->rlist);
  1544  		}
  1545  		if(n->ntest) {
  1546  			indent(fp);
  1547  			fmtprint(fp, "%O-test%N", n->op, n->ntest);
  1548  		}
  1549  		if(n->nbody) {
  1550  			indent(fp);
  1551  			fmtprint(fp, "%O-body%H", n->op, n->nbody);
  1552  		}
  1553  		if(n->nelse) {
  1554  			indent(fp);
  1555  			fmtprint(fp, "%O-else%H", n->op, n->nelse);
  1556  		}
  1557  		if(n->nincr) {
  1558  			indent(fp);
  1559  			fmtprint(fp, "%O-incr%N", n->op, n->nincr);
  1560  		}
  1561  	}
  1562  
  1563  	return 0;
  1564  }
  1565  
  1566  // Fmt "%S": syms
  1567  // Flags:  "%hS" suppresses qualifying with package
  1568  static int
  1569  Sconv(Fmt *fp)
  1570  {
  1571  	Sym *s;
  1572  	int r, sm;
  1573  	unsigned long sf;
  1574  
  1575  	s = va_arg(fp->args, Sym*);
  1576  	if(s == S)
  1577  		return fmtstrcpy(fp, "<S>");
  1578  
  1579  	if(s->name && s->name[0] == '_' && s->name[1] == '\0')
  1580  		return fmtstrcpy(fp, "_");
  1581  
  1582  	sf = fp->flags;
  1583  	sm = setfmode(&fp->flags);
  1584  	r = symfmt(fp, s);
  1585  	fp->flags = sf;
  1586  	fmtmode = sm;
  1587  	return r;
  1588  }
  1589  
  1590  // Fmt "%T": types.
  1591  // Flags: 'l' print definition, not name
  1592  //	  'h' omit 'func' and receiver from function types, short type names
  1593  //	  'u' package name, not prefix (FTypeId mode, sticky)
  1594  static int
  1595  Tconv(Fmt *fp)
  1596  {
  1597  	Type *t;
  1598  	int r, sm;
  1599  	unsigned long sf;
  1600  
  1601  	t = va_arg(fp->args, Type*);
  1602  	if(t == T)
  1603  		return fmtstrcpy(fp, "<T>");
  1604  
  1605  	if(t->trecur > 4)
  1606  		return fmtstrcpy(fp, "<...>");
  1607  
  1608  	t->trecur++;
  1609  	sf = fp->flags;
  1610  	sm = setfmode(&fp->flags);
  1611  
  1612  	if(fmtmode == FTypeId && (sf&FmtUnsigned))
  1613  		fmtpkgpfx++;
  1614  	if(fmtpkgpfx)
  1615  		fp->flags |= FmtUnsigned;
  1616  
  1617  	r = typefmt(fp, t);
  1618  
  1619  	if(fmtmode == FTypeId && (sf&FmtUnsigned))
  1620  		fmtpkgpfx--;
  1621  
  1622  	fp->flags = sf;
  1623  	fmtmode = sm;
  1624  	t->trecur--;
  1625  	return r;
  1626  }
  1627  
  1628  // Fmt '%N': Nodes.
  1629  // Flags: 'l' suffix with "(type %T)" where possible
  1630  //	  '+h' in debug mode, don't recurse, no multiline output
  1631  static int
  1632  Nconv(Fmt *fp)
  1633  {
  1634  	Node *n;
  1635  	int r, sm;
  1636  	unsigned long sf;
  1637  
  1638  	n = va_arg(fp->args, Node*);
  1639  	if(n == N)
  1640  		return fmtstrcpy(fp, "<N>");
  1641  	sf = fp->flags;
  1642  	sm = setfmode(&fp->flags);
  1643  
  1644  	r = -1;
  1645  	switch(fmtmode) {
  1646  	case FErr:
  1647  	case FExp:
  1648  		r = nodefmt(fp, n);
  1649  		break;
  1650  	case FDbg:
  1651  		dumpdepth++;
  1652  		r = nodedump(fp, n);
  1653  		dumpdepth--;
  1654  		break;
  1655  	default:
  1656  		fatal("unhandled %%N mode");
  1657  	}
  1658  
  1659  	fp->flags = sf;
  1660  	fmtmode = sm;
  1661  	return r;
  1662  }
  1663  
  1664  // Fmt '%H': NodeList.
  1665  // Flags: all those of %N plus ',': separate with comma's instead of semicolons.
  1666  static int
  1667  Hconv(Fmt *fp)
  1668  {
  1669  	NodeList *l;
  1670  	int r, sm;
  1671  	unsigned long sf;
  1672  	char *sep;
  1673  
  1674  	l = va_arg(fp->args, NodeList*);
  1675  
  1676  	if(l == nil && fmtmode == FDbg)
  1677  		return fmtstrcpy(fp, "<nil>");
  1678  
  1679  	sf = fp->flags;
  1680  	sm = setfmode(&fp->flags);
  1681  	r = 0;
  1682  	sep = "; ";
  1683  	if(fmtmode == FDbg)
  1684  		sep = "\n";
  1685  	else if(fp->flags & FmtComma)
  1686  		sep = ", ";
  1687  
  1688  	for(;l; l=l->next) {
  1689  		r += fmtprint(fp, "%N", l->n);
  1690  		if(l->next)
  1691  			r += fmtstrcpy(fp, sep);
  1692  	}
  1693  
  1694  	fp->flags = sf;
  1695  	fmtmode = sm;
  1696  	return r;
  1697  }
  1698  
  1699  void
  1700  fmtinstallgo(void)
  1701  {
  1702  	fmtmode = FErr;
  1703  	fmtinstall('E', Econv);		// etype opcodes
  1704  	fmtinstall('J', Jconv);		// all the node flags
  1705  	fmtinstall('H', Hconv);		// node lists
  1706  	fmtinstall('L', Lconv);		// line number
  1707  	fmtinstall('N', Nconv);		// node pointer
  1708  	fmtinstall('O', Oconv);		// node opcodes
  1709  	fmtinstall('S', Sconv);		// sym pointer
  1710  	fmtinstall('T', Tconv);		// type pointer
  1711  	fmtinstall('V', Vconv);		// val pointer
  1712  	fmtinstall('Z', Zconv);		// escaped string
  1713  
  1714  	// These are in mparith1.c
  1715  	fmtinstall('B', Bconv);	// big numbers
  1716  	fmtinstall('F', Fconv);	// big float numbers
  1717  
  1718  }
  1719  
  1720  void
  1721  dumplist(char *s, NodeList *l)
  1722  {
  1723  	print("%s%+H\n", s, l);
  1724  }
  1725  
  1726  void
  1727  dump(char *s, Node *n)
  1728  {
  1729  	print("%s [%p]%+N\n", s, n, n);
  1730  }