1*9676Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*9676Slinton 3*9676Slinton static char sccsid[] = "@(#)@(#)printsym.c 1.1 12/15/82"; 4*9676Slinton 5*9676Slinton /* 6*9676Slinton * Printing of symbolic information. 7*9676Slinton */ 8*9676Slinton 9*9676Slinton #include "defs.h" 10*9676Slinton #include "symbols.h" 11*9676Slinton #include "languages.h" 12*9676Slinton #include "printsym.h" 13*9676Slinton #include "tree.h" 14*9676Slinton #include "eval.h" 15*9676Slinton #include "mappings.h" 16*9676Slinton #include "process.h" 17*9676Slinton #include "runtime.h" 18*9676Slinton #include "machine.h" 19*9676Slinton #include "names.h" 20*9676Slinton #include "main.h" 21*9676Slinton 22*9676Slinton #ifndef public 23*9676Slinton #endif 24*9676Slinton 25*9676Slinton /* 26*9676Slinton * Return a pointer to the string for the name of the class that 27*9676Slinton * the given symbol belongs to. 28*9676Slinton */ 29*9676Slinton 30*9676Slinton private String clname[] = { 31*9676Slinton "bad use", "constant", "type", "variable", "array", "fileptr", 32*9676Slinton "record", "field", "procedure", "function", "funcvar", 33*9676Slinton "ref", "pointer", "file", "set", "range", "label", "withptr", 34*9676Slinton "scalar", "string", "program", "improper", "variant", 35*9676Slinton "procparam", "funcparam", "module", "typeref", "tag" 36*9676Slinton }; 37*9676Slinton 38*9676Slinton public String classname(s) 39*9676Slinton Symbol s; 40*9676Slinton { 41*9676Slinton return clname[ord(s->class)]; 42*9676Slinton } 43*9676Slinton 44*9676Slinton /* 45*9676Slinton * Note the entry of the given block, unless it's the main program. 46*9676Slinton */ 47*9676Slinton 48*9676Slinton public printentry(s) 49*9676Slinton Symbol s; 50*9676Slinton { 51*9676Slinton if (s != program) { 52*9676Slinton printf("\nentering %s %s\n", classname(s), symname(s)); 53*9676Slinton } 54*9676Slinton } 55*9676Slinton 56*9676Slinton /* 57*9676Slinton * Note the exit of the given block 58*9676Slinton */ 59*9676Slinton 60*9676Slinton public printexit(s) 61*9676Slinton Symbol s; 62*9676Slinton { 63*9676Slinton if (s != program) { 64*9676Slinton printf("leaving %s %s\n\n", classname(s), symname(s)); 65*9676Slinton } 66*9676Slinton } 67*9676Slinton 68*9676Slinton /* 69*9676Slinton * Note the call of s from t. 70*9676Slinton */ 71*9676Slinton 72*9676Slinton public printcall(s, t) 73*9676Slinton Symbol s, t; 74*9676Slinton { 75*9676Slinton printf("calling %s", symname(s)); 76*9676Slinton printparams(s, nil); 77*9676Slinton printf(" from %s %s\n", classname(t), symname(t)); 78*9676Slinton } 79*9676Slinton 80*9676Slinton /* 81*9676Slinton * Note the return from s. If s is a function, print the value 82*9676Slinton * it is returning. This is somewhat painful, since the function 83*9676Slinton * has actually just returned. 84*9676Slinton */ 85*9676Slinton 86*9676Slinton public printrtn(s) 87*9676Slinton Symbol s; 88*9676Slinton { 89*9676Slinton register Symbol t; 90*9676Slinton register int len; 91*9676Slinton Boolean isindirect; 92*9676Slinton 93*9676Slinton printf("returning "); 94*9676Slinton if (s->class == FUNC) { 95*9676Slinton len = size(s->type); 96*9676Slinton if (canpush(len)) { 97*9676Slinton t = rtype(s->type); 98*9676Slinton isindirect = (Boolean) (t->class == RECORD or t->class == VARNT); 99*9676Slinton pushretval(len, isindirect); 100*9676Slinton printval(s->type); 101*9676Slinton putchar(' '); 102*9676Slinton } else { 103*9676Slinton printf("(value too large) "); 104*9676Slinton } 105*9676Slinton } 106*9676Slinton printf("from %s\n", symname(s)); 107*9676Slinton } 108*9676Slinton 109*9676Slinton /* 110*9676Slinton * Print the values of the parameters of the given procedure or function. 111*9676Slinton * The frame distinguishes recursive instances of a procedure. 112*9676Slinton */ 113*9676Slinton 114*9676Slinton public printparams(f, frame) 115*9676Slinton Symbol f; 116*9676Slinton Frame frame; 117*9676Slinton { 118*9676Slinton Symbol param; 119*9676Slinton int n, m, s; 120*9676Slinton 121*9676Slinton n = nargspassed(frame); 122*9676Slinton param = f->chain; 123*9676Slinton if (param != nil or n > 0) { 124*9676Slinton printf("("); 125*9676Slinton m = n; 126*9676Slinton if (param != nil) { 127*9676Slinton for (;;) { 128*9676Slinton s = size(param) div sizeof(Word); 129*9676Slinton if (s == 0) { 130*9676Slinton s = 1; 131*9676Slinton } 132*9676Slinton m -= s; 133*9676Slinton printv(param, frame); 134*9676Slinton param = param->chain; 135*9676Slinton if (param == nil) break; 136*9676Slinton printf(", "); 137*9676Slinton } 138*9676Slinton } 139*9676Slinton if (m > 0) { 140*9676Slinton if (f->chain != nil) { 141*9676Slinton printf(", "); 142*9676Slinton } 143*9676Slinton for (;;) { 144*9676Slinton --m; 145*9676Slinton printf("0x%x", argn(n - m, frame)); 146*9676Slinton if (m <= 0) break; 147*9676Slinton printf(", "); 148*9676Slinton } 149*9676Slinton } 150*9676Slinton printf(")"); 151*9676Slinton } 152*9676Slinton } 153*9676Slinton 154*9676Slinton /* 155*9676Slinton * Test if a symbol should be printed. We don't print files, 156*9676Slinton * for example, simply because there's no good way to do it. 157*9676Slinton * The symbol must be within the given function. 158*9676Slinton */ 159*9676Slinton 160*9676Slinton public Boolean should_print(s) 161*9676Slinton Symbol s; 162*9676Slinton { 163*9676Slinton Boolean b; 164*9676Slinton register Symbol t; 165*9676Slinton 166*9676Slinton switch (s->class) { 167*9676Slinton case VAR: 168*9676Slinton case FVAR: 169*9676Slinton t = rtype(s->type); 170*9676Slinton b = (Boolean) ( 171*9676Slinton not isparam(s) and 172*9676Slinton t != nil and t->class != FILET and t->class != SET 173*9676Slinton ); 174*9676Slinton break; 175*9676Slinton 176*9676Slinton default: 177*9676Slinton b = false; 178*9676Slinton break; 179*9676Slinton } 180*9676Slinton return b; 181*9676Slinton } 182*9676Slinton 183*9676Slinton /* 184*9676Slinton * Print the name and value of a variable. 185*9676Slinton */ 186*9676Slinton 187*9676Slinton public printv(s, frame) 188*9676Slinton Symbol s; 189*9676Slinton Frame frame; 190*9676Slinton { 191*9676Slinton Address addr; 192*9676Slinton int len; 193*9676Slinton 194*9676Slinton if (isambiguous(s) and ismodule(container(s))) { 195*9676Slinton printname(stdout, s); 196*9676Slinton printf(" = "); 197*9676Slinton } else { 198*9676Slinton printf("%s = ", symname(s)); 199*9676Slinton } 200*9676Slinton if (isvarparam(s)) { 201*9676Slinton rpush(address(s, frame), sizeof(Address)); 202*9676Slinton addr = pop(Address); 203*9676Slinton len = size(s->type); 204*9676Slinton } else { 205*9676Slinton addr = address(s, frame); 206*9676Slinton len = size(s); 207*9676Slinton } 208*9676Slinton if (canpush(len)) { 209*9676Slinton rpush(addr, len); 210*9676Slinton printval(s->type); 211*9676Slinton } else { 212*9676Slinton printf("*** expression too large ***"); 213*9676Slinton } 214*9676Slinton } 215*9676Slinton 216*9676Slinton /* 217*9676Slinton * Print out the name of a symbol. 218*9676Slinton */ 219*9676Slinton 220*9676Slinton public printname(f, s) 221*9676Slinton File f; 222*9676Slinton Symbol s; 223*9676Slinton { 224*9676Slinton if (s == nil) { 225*9676Slinton fprintf(f, "(noname)"); 226*9676Slinton } else if (isredirected() or isambiguous(s)) { 227*9676Slinton printwhich(f, s); 228*9676Slinton } else { 229*9676Slinton fprintf(f, "%s", symname(s)); 230*9676Slinton } 231*9676Slinton } 232*9676Slinton 233*9676Slinton /* 234*9676Slinton * Print the fully specified variable that is described by the given identifer. 235*9676Slinton */ 236*9676Slinton 237*9676Slinton public printwhich(f, s) 238*9676Slinton File f; 239*9676Slinton Symbol s; 240*9676Slinton { 241*9676Slinton printouter(f, container(s)); 242*9676Slinton fprintf(f, "%s", symname(s)); 243*9676Slinton } 244*9676Slinton 245*9676Slinton /* 246*9676Slinton * Print the fully qualified name of each symbol that has the same name 247*9676Slinton * as the given symbol. 248*9676Slinton */ 249*9676Slinton 250*9676Slinton public printwhereis(f, s) 251*9676Slinton File f; 252*9676Slinton Symbol s; 253*9676Slinton { 254*9676Slinton register Name n; 255*9676Slinton register Symbol t; 256*9676Slinton 257*9676Slinton checkref(s); 258*9676Slinton n = s->name; 259*9676Slinton t = lookup(n); 260*9676Slinton printwhich(f, t); 261*9676Slinton t = t->next_sym; 262*9676Slinton while (t != nil) { 263*9676Slinton if (t->name == n) { 264*9676Slinton putc(' ', f); 265*9676Slinton printwhich(f, t); 266*9676Slinton } 267*9676Slinton t = t->next_sym; 268*9676Slinton } 269*9676Slinton putc('\n', f); 270*9676Slinton } 271*9676Slinton 272*9676Slinton private printouter(f, s) 273*9676Slinton File f; 274*9676Slinton Symbol s; 275*9676Slinton { 276*9676Slinton Symbol outer; 277*9676Slinton 278*9676Slinton if (s != nil) { 279*9676Slinton outer = container(s); 280*9676Slinton if (outer != nil and outer != program) { 281*9676Slinton printouter(f, outer); 282*9676Slinton } 283*9676Slinton fprintf(f, "%s.", symname(s)); 284*9676Slinton } 285*9676Slinton } 286*9676Slinton 287*9676Slinton public printdecl(s) 288*9676Slinton Symbol s; 289*9676Slinton { 290*9676Slinton checkref(s); 291*9676Slinton (*language_op(s->language, L_PRINTDECL))(s); 292*9676Slinton } 293*9676Slinton 294*9676Slinton /* 295*9676Slinton * Straight dump of symbol information. 296*9676Slinton */ 297*9676Slinton 298*9676Slinton public psym(s) 299*9676Slinton Symbol s; 300*9676Slinton { 301*9676Slinton printf("name\t%s\n", symname(s)); 302*9676Slinton printf("lang\t%s\n", language_name(s->language)); 303*9676Slinton printf("level\t%d\n", s->level); 304*9676Slinton printf("class\t%s\n", classname(s)); 305*9676Slinton printf("type\t0x%x", s->type); 306*9676Slinton if (s->type != nil and s->type->name != nil) { 307*9676Slinton printf(" (%s)", symname(s->type)); 308*9676Slinton } 309*9676Slinton printf("\nchain\t0x%x", s->chain); 310*9676Slinton if (s->chain != nil and s->chain->name != nil) { 311*9676Slinton printf(" (%s)", symname(s->chain)); 312*9676Slinton } 313*9676Slinton printf("\nblock\t0x%x", s->block); 314*9676Slinton if (s->block->name != nil) { 315*9676Slinton printf(" ("); 316*9676Slinton printname(stdout, s->block); 317*9676Slinton putchar(')'); 318*9676Slinton } 319*9676Slinton putchar('\n'); 320*9676Slinton switch (s->class) { 321*9676Slinton case VAR: 322*9676Slinton case REF: 323*9676Slinton if (s->level >= 3) { 324*9676Slinton printf("address\t0x%x\n", s->symvalue.offset); 325*9676Slinton } else { 326*9676Slinton printf("offset\t%d\n", s->symvalue.offset); 327*9676Slinton } 328*9676Slinton break; 329*9676Slinton 330*9676Slinton case RECORD: 331*9676Slinton case VARNT: 332*9676Slinton printf("size\t%d\n", s->symvalue.offset); 333*9676Slinton break; 334*9676Slinton 335*9676Slinton case FIELD: 336*9676Slinton printf("offset\t%d\n", s->symvalue.field.offset); 337*9676Slinton printf("size\t%d\n", s->symvalue.field.length); 338*9676Slinton break; 339*9676Slinton 340*9676Slinton case PROC: 341*9676Slinton case FUNC: 342*9676Slinton printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); 343*9676Slinton break; 344*9676Slinton 345*9676Slinton case RANGE: 346*9676Slinton printf("lower\t%d\n", s->symvalue.rangev.lower); 347*9676Slinton printf("upper\t%d\n", s->symvalue.rangev.upper); 348*9676Slinton break; 349*9676Slinton 350*9676Slinton default: 351*9676Slinton /* do nothing */ 352*9676Slinton break; 353*9676Slinton } 354*9676Slinton } 355*9676Slinton 356*9676Slinton /* 357*9676Slinton * Print out the value on top of the stack according to the given type. 358*9676Slinton */ 359*9676Slinton 360*9676Slinton public printval(t) 361*9676Slinton Symbol t; 362*9676Slinton { 363*9676Slinton Symbol s; 364*9676Slinton 365*9676Slinton checkref(t); 366*9676Slinton switch (t->class) { 367*9676Slinton case PROC: 368*9676Slinton case FUNC: 369*9676Slinton s = pop(Symbol); 370*9676Slinton printf("%s", symname(s)); 371*9676Slinton break; 372*9676Slinton 373*9676Slinton default: 374*9676Slinton if (t->language == nil) { 375*9676Slinton error("unknown language"); 376*9676Slinton } else { 377*9676Slinton (*language_op(t->language, L_PRINTVAL))(t); 378*9676Slinton } 379*9676Slinton break; 380*9676Slinton } 381*9676Slinton } 382*9676Slinton 383*9676Slinton /* 384*9676Slinton * Print out the value of a record, field by field. 385*9676Slinton */ 386*9676Slinton 387*9676Slinton public printrecord(s) 388*9676Slinton Symbol s; 389*9676Slinton { 390*9676Slinton if (s->chain == nil) { 391*9676Slinton error("record has no fields"); 392*9676Slinton } 393*9676Slinton printf("("); 394*9676Slinton sp -= size(s); 395*9676Slinton printfield(s->chain); 396*9676Slinton printf(")"); 397*9676Slinton } 398*9676Slinton 399*9676Slinton /* 400*9676Slinton * Print out a field, first printing out other fields. 401*9676Slinton * This is done because the fields are chained together backwards. 402*9676Slinton */ 403*9676Slinton 404*9676Slinton private printfield(s) 405*9676Slinton Symbol s; 406*9676Slinton { 407*9676Slinton Stack *savesp; 408*9676Slinton 409*9676Slinton if (s->chain != nil) { 410*9676Slinton printfield(s->chain); 411*9676Slinton printf(", "); 412*9676Slinton } 413*9676Slinton printf("%s = ", symname(s)); 414*9676Slinton savesp = sp; 415*9676Slinton sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type)); 416*9676Slinton printval(s); 417*9676Slinton sp = savesp; 418*9676Slinton } 419*9676Slinton 420*9676Slinton /* 421*9676Slinton * Print out the contents of an array. 422*9676Slinton * Haven't quite figured out what the best format is. 423*9676Slinton * 424*9676Slinton * This is rather inefficient. 425*9676Slinton * 426*9676Slinton * The "2*elsize" is there since "printval" drops the stack by elsize. 427*9676Slinton */ 428*9676Slinton 429*9676Slinton public printarray(a) 430*9676Slinton Symbol a; 431*9676Slinton { 432*9676Slinton Stack *savesp, *newsp; 433*9676Slinton Symbol eltype; 434*9676Slinton long elsize; 435*9676Slinton String sep; 436*9676Slinton 437*9676Slinton savesp = sp; 438*9676Slinton sp -= size(a); 439*9676Slinton newsp = sp; 440*9676Slinton eltype = rtype(a->type); 441*9676Slinton elsize = size(eltype); 442*9676Slinton printf("("); 443*9676Slinton if (eltype->class == RECORD or eltype->class == ARRAY or 444*9676Slinton eltype->class == VARNT) { 445*9676Slinton sep = "\n"; 446*9676Slinton putchar('\n'); 447*9676Slinton } else { 448*9676Slinton sep = ", "; 449*9676Slinton } 450*9676Slinton for (sp += elsize; sp <= savesp; sp += 2*elsize) { 451*9676Slinton if (sp - elsize != newsp) { 452*9676Slinton fputs(sep, stdout); 453*9676Slinton } 454*9676Slinton printval(eltype); 455*9676Slinton } 456*9676Slinton sp = newsp; 457*9676Slinton if (streq(sep, "\n")) { 458*9676Slinton putchar('\n'); 459*9676Slinton } 460*9676Slinton printf(")"); 461*9676Slinton } 462*9676Slinton 463*9676Slinton /* 464*9676Slinton * Print out the value of a real number in Pascal notation. 465*9676Slinton * This is, unfortunately, different than what one gets 466*9676Slinton * from "%g" in printf. 467*9676Slinton */ 468*9676Slinton 469*9676Slinton public prtreal(r) 470*9676Slinton double r; 471*9676Slinton { 472*9676Slinton extern char *index(); 473*9676Slinton char buf[256]; 474*9676Slinton 475*9676Slinton sprintf(buf, "%g", r); 476*9676Slinton if (buf[0] == '.') { 477*9676Slinton printf("0%s", buf); 478*9676Slinton } else if (buf[0] == '-' and buf[1] == '.') { 479*9676Slinton printf("-0%s", &buf[1]); 480*9676Slinton } else { 481*9676Slinton printf("%s", buf); 482*9676Slinton } 483*9676Slinton if (index(buf, '.') == nil) { 484*9676Slinton printf(".0"); 485*9676Slinton } 486*9676Slinton } 487*9676Slinton 488*9676Slinton /* 489*9676Slinton * Print out a character using ^? notation for unprintables. 490*9676Slinton */ 491*9676Slinton 492*9676Slinton public printchar(c) 493*9676Slinton char c; 494*9676Slinton { 495*9676Slinton if (c == 0) { 496*9676Slinton putchar('\\'); 497*9676Slinton putchar('0'); 498*9676Slinton } else if (c == '\n') { 499*9676Slinton putchar('\\'); 500*9676Slinton putchar('n'); 501*9676Slinton } else if (c > 0 and c < ' ') { 502*9676Slinton putchar('^'); 503*9676Slinton putchar(c - 1 + 'A'); 504*9676Slinton } else { 505*9676Slinton putchar(c); 506*9676Slinton } 507*9676Slinton } 508