19676Slinton /* Copyright (c) 1982 Regents of the University of California */ 29676Slinton 3*12544Scsvaf static char sccsid[] = "@(#)printsym.c 1.5 05/18/83"; 49676Slinton 59676Slinton /* 69676Slinton * Printing of symbolic information. 79676Slinton */ 89676Slinton 99676Slinton #include "defs.h" 109676Slinton #include "symbols.h" 119676Slinton #include "languages.h" 129676Slinton #include "printsym.h" 139676Slinton #include "tree.h" 149676Slinton #include "eval.h" 159676Slinton #include "mappings.h" 169676Slinton #include "process.h" 179676Slinton #include "runtime.h" 189676Slinton #include "machine.h" 199676Slinton #include "names.h" 209676Slinton #include "main.h" 219676Slinton 229676Slinton #ifndef public 239676Slinton #endif 249676Slinton 259676Slinton /* 2611863Slinton * Maximum number of arguments to a function. 2711863Slinton * This is used as a check for the possibility that the stack has been 2811863Slinton * overwritten and therefore a saved argument pointer might indicate 2911863Slinton * to an absurdly large number of arguments. 3011863Slinton */ 3111863Slinton 3211863Slinton #define MAXARGSPASSED 20 3311863Slinton 3411863Slinton /* 359676Slinton * Return a pointer to the string for the name of the class that 369676Slinton * the given symbol belongs to. 379676Slinton */ 389676Slinton 399676Slinton private String clname[] = { 409676Slinton "bad use", "constant", "type", "variable", "array", "fileptr", 419676Slinton "record", "field", "procedure", "function", "funcvar", 429676Slinton "ref", "pointer", "file", "set", "range", "label", "withptr", 439676Slinton "scalar", "string", "program", "improper", "variant", 44*12544Scsvaf "procparam", "funcparam", "module", "tag", "common", "typeref" 459676Slinton }; 469676Slinton 479676Slinton public String classname(s) 489676Slinton Symbol s; 499676Slinton { 509676Slinton return clname[ord(s->class)]; 519676Slinton } 529676Slinton 539676Slinton /* 549676Slinton * Note the entry of the given block, unless it's the main program. 559676Slinton */ 569676Slinton 579676Slinton public printentry(s) 589676Slinton Symbol s; 599676Slinton { 609676Slinton if (s != program) { 619676Slinton printf("\nentering %s %s\n", classname(s), symname(s)); 629676Slinton } 639676Slinton } 649676Slinton 659676Slinton /* 669676Slinton * Note the exit of the given block 679676Slinton */ 689676Slinton 699676Slinton public printexit(s) 709676Slinton Symbol s; 719676Slinton { 729676Slinton if (s != program) { 739676Slinton printf("leaving %s %s\n\n", classname(s), symname(s)); 749676Slinton } 759676Slinton } 769676Slinton 779676Slinton /* 789676Slinton * Note the call of s from t. 799676Slinton */ 809676Slinton 819676Slinton public printcall(s, t) 829676Slinton Symbol s, t; 839676Slinton { 849676Slinton printf("calling %s", symname(s)); 859676Slinton printparams(s, nil); 869676Slinton printf(" from %s %s\n", classname(t), symname(t)); 879676Slinton } 889676Slinton 899676Slinton /* 909676Slinton * Note the return from s. If s is a function, print the value 919676Slinton * it is returning. This is somewhat painful, since the function 929676Slinton * has actually just returned. 939676Slinton */ 949676Slinton 959676Slinton public printrtn(s) 969676Slinton Symbol s; 979676Slinton { 989676Slinton register Symbol t; 999676Slinton register int len; 1009676Slinton Boolean isindirect; 1019676Slinton 1029676Slinton printf("returning "); 1039676Slinton if (s->class == FUNC) { 1049676Slinton len = size(s->type); 1059676Slinton if (canpush(len)) { 1069676Slinton t = rtype(s->type); 1079676Slinton isindirect = (Boolean) (t->class == RECORD or t->class == VARNT); 1089676Slinton pushretval(len, isindirect); 1099676Slinton printval(s->type); 1109676Slinton putchar(' '); 1119676Slinton } else { 1129676Slinton printf("(value too large) "); 1139676Slinton } 1149676Slinton } 1159676Slinton printf("from %s\n", symname(s)); 1169676Slinton } 1179676Slinton 1189676Slinton /* 1199676Slinton * Print the values of the parameters of the given procedure or function. 1209676Slinton * The frame distinguishes recursive instances of a procedure. 1219676Slinton */ 1229676Slinton 1239676Slinton public printparams(f, frame) 1249676Slinton Symbol f; 1259676Slinton Frame frame; 1269676Slinton { 1279676Slinton Symbol param; 1289676Slinton int n, m, s; 1299676Slinton 1309676Slinton n = nargspassed(frame); 1319676Slinton param = f->chain; 1329676Slinton if (param != nil or n > 0) { 1339676Slinton printf("("); 1349676Slinton m = n; 1359676Slinton if (param != nil) { 1369676Slinton for (;;) { 1379676Slinton s = size(param) div sizeof(Word); 1389676Slinton if (s == 0) { 1399676Slinton s = 1; 1409676Slinton } 1419676Slinton m -= s; 1429676Slinton printv(param, frame); 1439676Slinton param = param->chain; 1449676Slinton if (param == nil) break; 1459676Slinton printf(", "); 1469676Slinton } 1479676Slinton } 1489676Slinton if (m > 0) { 14911863Slinton if (m > MAXARGSPASSED) { 15011863Slinton m = MAXARGSPASSED; 15111863Slinton } 1529676Slinton if (f->chain != nil) { 1539676Slinton printf(", "); 1549676Slinton } 1559676Slinton for (;;) { 1569676Slinton --m; 1579676Slinton printf("0x%x", argn(n - m, frame)); 1589676Slinton if (m <= 0) break; 1599676Slinton printf(", "); 1609676Slinton } 1619676Slinton } 1629676Slinton printf(")"); 1639676Slinton } 1649676Slinton } 1659676Slinton 1669676Slinton /* 1679676Slinton * Test if a symbol should be printed. We don't print files, 1689676Slinton * for example, simply because there's no good way to do it. 1699676Slinton * The symbol must be within the given function. 1709676Slinton */ 1719676Slinton 1729676Slinton public Boolean should_print(s) 1739676Slinton Symbol s; 1749676Slinton { 1759676Slinton Boolean b; 1769676Slinton register Symbol t; 1779676Slinton 1789676Slinton switch (s->class) { 1799676Slinton case VAR: 1809676Slinton case FVAR: 1819676Slinton t = rtype(s->type); 1829676Slinton b = (Boolean) ( 1839676Slinton not isparam(s) and 1849676Slinton t != nil and t->class != FILET and t->class != SET 1859676Slinton ); 1869676Slinton break; 1879676Slinton 1889676Slinton default: 1899676Slinton b = false; 1909676Slinton break; 1919676Slinton } 1929676Slinton return b; 1939676Slinton } 1949676Slinton 1959676Slinton /* 1969676Slinton * Print the name and value of a variable. 1979676Slinton */ 1989676Slinton 1999676Slinton public printv(s, frame) 2009676Slinton Symbol s; 2019676Slinton Frame frame; 2029676Slinton { 2039676Slinton Address addr; 2049676Slinton int len; 2059676Slinton 2069676Slinton if (isambiguous(s) and ismodule(container(s))) { 2079676Slinton printname(stdout, s); 2089676Slinton printf(" = "); 2099676Slinton } else { 2109676Slinton printf("%s = ", symname(s)); 2119676Slinton } 2129676Slinton if (isvarparam(s)) { 2139676Slinton rpush(address(s, frame), sizeof(Address)); 2149676Slinton addr = pop(Address); 2159676Slinton len = size(s->type); 2169676Slinton } else { 2179676Slinton addr = address(s, frame); 2189676Slinton len = size(s); 2199676Slinton } 2209676Slinton if (canpush(len)) { 2219676Slinton rpush(addr, len); 2229676Slinton printval(s->type); 2239676Slinton } else { 2249676Slinton printf("*** expression too large ***"); 2259676Slinton } 2269676Slinton } 2279676Slinton 2289676Slinton /* 2299676Slinton * Print out the name of a symbol. 2309676Slinton */ 2319676Slinton 2329676Slinton public printname(f, s) 2339676Slinton File f; 2349676Slinton Symbol s; 2359676Slinton { 2369676Slinton if (s == nil) { 2379676Slinton fprintf(f, "(noname)"); 2389676Slinton } else if (isredirected() or isambiguous(s)) { 2399676Slinton printwhich(f, s); 2409676Slinton } else { 2419676Slinton fprintf(f, "%s", symname(s)); 2429676Slinton } 2439676Slinton } 2449676Slinton 2459676Slinton /* 2469676Slinton * Print the fully specified variable that is described by the given identifer. 2479676Slinton */ 2489676Slinton 2499676Slinton public printwhich(f, s) 2509676Slinton File f; 2519676Slinton Symbol s; 2529676Slinton { 2539676Slinton printouter(f, container(s)); 2549676Slinton fprintf(f, "%s", symname(s)); 2559676Slinton } 2569676Slinton 2579676Slinton /* 2589676Slinton * Print the fully qualified name of each symbol that has the same name 2599676Slinton * as the given symbol. 2609676Slinton */ 2619676Slinton 2629676Slinton public printwhereis(f, s) 2639676Slinton File f; 2649676Slinton Symbol s; 2659676Slinton { 2669676Slinton register Name n; 2679676Slinton register Symbol t; 2689676Slinton 2699676Slinton checkref(s); 2709676Slinton n = s->name; 2719676Slinton t = lookup(n); 2729676Slinton printwhich(f, t); 2739676Slinton t = t->next_sym; 2749676Slinton while (t != nil) { 2759676Slinton if (t->name == n) { 2769676Slinton putc(' ', f); 2779676Slinton printwhich(f, t); 2789676Slinton } 2799676Slinton t = t->next_sym; 2809676Slinton } 2819676Slinton putc('\n', f); 2829676Slinton } 2839676Slinton 2849676Slinton private printouter(f, s) 2859676Slinton File f; 2869676Slinton Symbol s; 2879676Slinton { 2889676Slinton Symbol outer; 2899676Slinton 2909676Slinton if (s != nil) { 2919676Slinton outer = container(s); 2929676Slinton if (outer != nil and outer != program) { 2939676Slinton printouter(f, outer); 2949676Slinton } 2959676Slinton fprintf(f, "%s.", symname(s)); 2969676Slinton } 2979676Slinton } 2989676Slinton 2999676Slinton public printdecl(s) 3009676Slinton Symbol s; 3019676Slinton { 3029676Slinton checkref(s); 3039676Slinton (*language_op(s->language, L_PRINTDECL))(s); 3049676Slinton } 3059676Slinton 3069676Slinton /* 3079676Slinton * Straight dump of symbol information. 3089676Slinton */ 3099676Slinton 3109676Slinton public psym(s) 3119676Slinton Symbol s; 3129676Slinton { 3139676Slinton printf("name\t%s\n", symname(s)); 3149676Slinton printf("lang\t%s\n", language_name(s->language)); 3159676Slinton printf("level\t%d\n", s->level); 3169676Slinton printf("class\t%s\n", classname(s)); 3179676Slinton printf("type\t0x%x", s->type); 3189676Slinton if (s->type != nil and s->type->name != nil) { 3199676Slinton printf(" (%s)", symname(s->type)); 3209676Slinton } 3219676Slinton printf("\nchain\t0x%x", s->chain); 3229676Slinton if (s->chain != nil and s->chain->name != nil) { 3239676Slinton printf(" (%s)", symname(s->chain)); 3249676Slinton } 3259676Slinton printf("\nblock\t0x%x", s->block); 3269676Slinton if (s->block->name != nil) { 3279676Slinton printf(" ("); 3289676Slinton printname(stdout, s->block); 3299676Slinton putchar(')'); 3309676Slinton } 3319676Slinton putchar('\n'); 3329676Slinton switch (s->class) { 3339676Slinton case VAR: 3349676Slinton case REF: 3359676Slinton if (s->level >= 3) { 3369676Slinton printf("address\t0x%x\n", s->symvalue.offset); 3379676Slinton } else { 3389676Slinton printf("offset\t%d\n", s->symvalue.offset); 3399676Slinton } 3409676Slinton break; 3419676Slinton 3429676Slinton case RECORD: 3439676Slinton case VARNT: 3449676Slinton printf("size\t%d\n", s->symvalue.offset); 3459676Slinton break; 3469676Slinton 3479676Slinton case FIELD: 3489676Slinton printf("offset\t%d\n", s->symvalue.field.offset); 3499676Slinton printf("size\t%d\n", s->symvalue.field.length); 3509676Slinton break; 3519676Slinton 3529676Slinton case PROC: 3539676Slinton case FUNC: 3549676Slinton printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); 35511863Slinton if (nosource(s)) { 35611863Slinton printf("does not have source information\n"); 35711863Slinton } else { 35811863Slinton printf("has source information\n"); 35911863Slinton } 3609676Slinton break; 3619676Slinton 3629676Slinton case RANGE: 363*12544Scsvaf switch(s->symvalue.rangev.lowertype) { 364*12544Scsvaf 365*12544Scsvaf case R_CONST : printf("CONST"); 366*12544Scsvaf break; 367*12544Scsvaf case R_ARG : printf("ARG"); 368*12544Scsvaf break; 369*12544Scsvaf case R_TEMP : printf("TEMP"); 370*12544Scsvaf break; 371*12544Scsvaf case R_ADJUST : printf("ADJUST"); 372*12544Scsvaf break; 373*12544Scsvaf } 3749676Slinton printf("lower\t%d\n", s->symvalue.rangev.lower); 375*12544Scsvaf 376*12544Scsvaf switch(s->symvalue.rangev.uppertype) { 377*12544Scsvaf 378*12544Scsvaf case R_CONST : printf("CONST"); 379*12544Scsvaf break; 380*12544Scsvaf case R_ARG : printf("ARG"); 381*12544Scsvaf break; 382*12544Scsvaf case R_TEMP : printf("TEMP"); 383*12544Scsvaf break; 384*12544Scsvaf case R_ADJUST : printf("ADJUST"); 385*12544Scsvaf break; 386*12544Scsvaf } 387*12544Scsvaf 3889676Slinton printf("upper\t%d\n", s->symvalue.rangev.upper); 3899676Slinton break; 3909676Slinton 3919676Slinton default: 3929676Slinton /* do nothing */ 3939676Slinton break; 3949676Slinton } 3959676Slinton } 3969676Slinton 3979676Slinton /* 3989676Slinton * Print out the value on top of the stack according to the given type. 3999676Slinton */ 4009676Slinton 4019676Slinton public printval(t) 4029676Slinton Symbol t; 4039676Slinton { 4049676Slinton Symbol s; 4059676Slinton 4069676Slinton checkref(t); 4079676Slinton switch (t->class) { 4089676Slinton case PROC: 4099676Slinton case FUNC: 4109676Slinton s = pop(Symbol); 4119676Slinton printf("%s", symname(s)); 4129676Slinton break; 4139676Slinton 4149676Slinton default: 4159676Slinton if (t->language == nil) { 4169676Slinton error("unknown language"); 4179676Slinton } else { 4189676Slinton (*language_op(t->language, L_PRINTVAL))(t); 4199676Slinton } 4209676Slinton break; 4219676Slinton } 4229676Slinton } 4239676Slinton 4249676Slinton /* 4259676Slinton * Print out the value of a record, field by field. 4269676Slinton */ 4279676Slinton 4289676Slinton public printrecord(s) 4299676Slinton Symbol s; 4309676Slinton { 4319676Slinton if (s->chain == nil) { 4329676Slinton error("record has no fields"); 4339676Slinton } 4349676Slinton printf("("); 4359676Slinton sp -= size(s); 4369676Slinton printfield(s->chain); 4379676Slinton printf(")"); 4389676Slinton } 4399676Slinton 4409676Slinton /* 4419676Slinton * Print out a field, first printing out other fields. 4429676Slinton * This is done because the fields are chained together backwards. 4439676Slinton */ 4449676Slinton 4459676Slinton private printfield(s) 4469676Slinton Symbol s; 4479676Slinton { 4489676Slinton Stack *savesp; 4499676Slinton 4509676Slinton if (s->chain != nil) { 4519676Slinton printfield(s->chain); 4529676Slinton printf(", "); 4539676Slinton } 4549676Slinton printf("%s = ", symname(s)); 4559676Slinton savesp = sp; 4569676Slinton sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type)); 4579676Slinton printval(s); 4589676Slinton sp = savesp; 4599676Slinton } 4609676Slinton 4619676Slinton /* 4629676Slinton * Print out the contents of an array. 4639676Slinton * Haven't quite figured out what the best format is. 4649676Slinton * 4659676Slinton * This is rather inefficient. 4669676Slinton * 4679676Slinton * The "2*elsize" is there since "printval" drops the stack by elsize. 4689676Slinton */ 4699676Slinton 4709676Slinton public printarray(a) 4719676Slinton Symbol a; 4729676Slinton { 4739676Slinton Stack *savesp, *newsp; 4749676Slinton Symbol eltype; 4759676Slinton long elsize; 4769676Slinton String sep; 4779676Slinton 4789676Slinton savesp = sp; 479*12544Scsvaf sp -= (size(a)); 4809676Slinton newsp = sp; 4819676Slinton eltype = rtype(a->type); 4829676Slinton elsize = size(eltype); 4839676Slinton printf("("); 4849676Slinton if (eltype->class == RECORD or eltype->class == ARRAY or 4859676Slinton eltype->class == VARNT) { 4869676Slinton sep = "\n"; 4879676Slinton putchar('\n'); 4889676Slinton } else { 4899676Slinton sep = ", "; 4909676Slinton } 4919676Slinton for (sp += elsize; sp <= savesp; sp += 2*elsize) { 4929676Slinton if (sp - elsize != newsp) { 4939676Slinton fputs(sep, stdout); 4949676Slinton } 4959676Slinton printval(eltype); 4969676Slinton } 4979676Slinton sp = newsp; 4989676Slinton if (streq(sep, "\n")) { 4999676Slinton putchar('\n'); 5009676Slinton } 5019676Slinton printf(")"); 5029676Slinton } 5039676Slinton 5049676Slinton /* 5059676Slinton * Print out the value of a real number in Pascal notation. 5069676Slinton * This is, unfortunately, different than what one gets 5079676Slinton * from "%g" in printf. 5089676Slinton */ 5099676Slinton 5109676Slinton public prtreal(r) 5119676Slinton double r; 5129676Slinton { 5139676Slinton extern char *index(); 5149676Slinton char buf[256]; 5159676Slinton 5169676Slinton sprintf(buf, "%g", r); 5179676Slinton if (buf[0] == '.') { 5189676Slinton printf("0%s", buf); 5199676Slinton } else if (buf[0] == '-' and buf[1] == '.') { 5209676Slinton printf("-0%s", &buf[1]); 5219676Slinton } else { 5229676Slinton printf("%s", buf); 5239676Slinton } 5249676Slinton if (index(buf, '.') == nil) { 5259676Slinton printf(".0"); 5269676Slinton } 5279676Slinton } 5289676Slinton 5299676Slinton /* 5309676Slinton * Print out a character using ^? notation for unprintables. 5319676Slinton */ 5329676Slinton 5339676Slinton public printchar(c) 5349676Slinton char c; 5359676Slinton { 5369676Slinton if (c == 0) { 5379676Slinton putchar('\\'); 5389676Slinton putchar('0'); 5399676Slinton } else if (c == '\n') { 5409676Slinton putchar('\\'); 5419676Slinton putchar('n'); 5429676Slinton } else if (c > 0 and c < ' ') { 5439676Slinton putchar('^'); 5449676Slinton putchar(c - 1 + 'A'); 5459676Slinton } else { 5469676Slinton putchar(c); 5479676Slinton } 5489676Slinton } 549