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