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 }