19676Slinton /* Copyright (c) 1982 Regents of the University of California */ 29676Slinton 3*11863Slinton static char sccsid[] = "@(#)printsym.c 1.3 04/08/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 /* 26*11863Slinton * Maximum number of arguments to a function. 27*11863Slinton * This is used as a check for the possibility that the stack has been 28*11863Slinton * overwritten and therefore a saved argument pointer might indicate 29*11863Slinton * to an absurdly large number of arguments. 30*11863Slinton */ 31*11863Slinton 32*11863Slinton #define MAXARGSPASSED 20 33*11863Slinton 34*11863Slinton /* 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", 449676Slinton "procparam", "funcparam", "module", "typeref", "tag" 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) { 149*11863Slinton if (m > MAXARGSPASSED) { 150*11863Slinton m = MAXARGSPASSED; 151*11863Slinton } 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); 355*11863Slinton if (nosource(s)) { 356*11863Slinton printf("does not have source information\n"); 357*11863Slinton } else { 358*11863Slinton printf("has source information\n"); 359*11863Slinton } 3609676Slinton break; 3619676Slinton 3629676Slinton case RANGE: 3639676Slinton printf("lower\t%d\n", s->symvalue.rangev.lower); 3649676Slinton printf("upper\t%d\n", s->symvalue.rangev.upper); 3659676Slinton break; 3669676Slinton 3679676Slinton default: 3689676Slinton /* do nothing */ 3699676Slinton break; 3709676Slinton } 3719676Slinton } 3729676Slinton 3739676Slinton /* 3749676Slinton * Print out the value on top of the stack according to the given type. 3759676Slinton */ 3769676Slinton 3779676Slinton public printval(t) 3789676Slinton Symbol t; 3799676Slinton { 3809676Slinton Symbol s; 3819676Slinton 3829676Slinton checkref(t); 3839676Slinton switch (t->class) { 3849676Slinton case PROC: 3859676Slinton case FUNC: 3869676Slinton s = pop(Symbol); 3879676Slinton printf("%s", symname(s)); 3889676Slinton break; 3899676Slinton 3909676Slinton default: 3919676Slinton if (t->language == nil) { 3929676Slinton error("unknown language"); 3939676Slinton } else { 3949676Slinton (*language_op(t->language, L_PRINTVAL))(t); 3959676Slinton } 3969676Slinton break; 3979676Slinton } 3989676Slinton } 3999676Slinton 4009676Slinton /* 4019676Slinton * Print out the value of a record, field by field. 4029676Slinton */ 4039676Slinton 4049676Slinton public printrecord(s) 4059676Slinton Symbol s; 4069676Slinton { 4079676Slinton if (s->chain == nil) { 4089676Slinton error("record has no fields"); 4099676Slinton } 4109676Slinton printf("("); 4119676Slinton sp -= size(s); 4129676Slinton printfield(s->chain); 4139676Slinton printf(")"); 4149676Slinton } 4159676Slinton 4169676Slinton /* 4179676Slinton * Print out a field, first printing out other fields. 4189676Slinton * This is done because the fields are chained together backwards. 4199676Slinton */ 4209676Slinton 4219676Slinton private printfield(s) 4229676Slinton Symbol s; 4239676Slinton { 4249676Slinton Stack *savesp; 4259676Slinton 4269676Slinton if (s->chain != nil) { 4279676Slinton printfield(s->chain); 4289676Slinton printf(", "); 4299676Slinton } 4309676Slinton printf("%s = ", symname(s)); 4319676Slinton savesp = sp; 4329676Slinton sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type)); 4339676Slinton printval(s); 4349676Slinton sp = savesp; 4359676Slinton } 4369676Slinton 4379676Slinton /* 4389676Slinton * Print out the contents of an array. 4399676Slinton * Haven't quite figured out what the best format is. 4409676Slinton * 4419676Slinton * This is rather inefficient. 4429676Slinton * 4439676Slinton * The "2*elsize" is there since "printval" drops the stack by elsize. 4449676Slinton */ 4459676Slinton 4469676Slinton public printarray(a) 4479676Slinton Symbol a; 4489676Slinton { 4499676Slinton Stack *savesp, *newsp; 4509676Slinton Symbol eltype; 4519676Slinton long elsize; 4529676Slinton String sep; 4539676Slinton 4549676Slinton savesp = sp; 4559676Slinton sp -= size(a); 4569676Slinton newsp = sp; 4579676Slinton eltype = rtype(a->type); 4589676Slinton elsize = size(eltype); 4599676Slinton printf("("); 4609676Slinton if (eltype->class == RECORD or eltype->class == ARRAY or 4619676Slinton eltype->class == VARNT) { 4629676Slinton sep = "\n"; 4639676Slinton putchar('\n'); 4649676Slinton } else { 4659676Slinton sep = ", "; 4669676Slinton } 4679676Slinton for (sp += elsize; sp <= savesp; sp += 2*elsize) { 4689676Slinton if (sp - elsize != newsp) { 4699676Slinton fputs(sep, stdout); 4709676Slinton } 4719676Slinton printval(eltype); 4729676Slinton } 4739676Slinton sp = newsp; 4749676Slinton if (streq(sep, "\n")) { 4759676Slinton putchar('\n'); 4769676Slinton } 4779676Slinton printf(")"); 4789676Slinton } 4799676Slinton 4809676Slinton /* 4819676Slinton * Print out the value of a real number in Pascal notation. 4829676Slinton * This is, unfortunately, different than what one gets 4839676Slinton * from "%g" in printf. 4849676Slinton */ 4859676Slinton 4869676Slinton public prtreal(r) 4879676Slinton double r; 4889676Slinton { 4899676Slinton extern char *index(); 4909676Slinton char buf[256]; 4919676Slinton 4929676Slinton sprintf(buf, "%g", r); 4939676Slinton if (buf[0] == '.') { 4949676Slinton printf("0%s", buf); 4959676Slinton } else if (buf[0] == '-' and buf[1] == '.') { 4969676Slinton printf("-0%s", &buf[1]); 4979676Slinton } else { 4989676Slinton printf("%s", buf); 4999676Slinton } 5009676Slinton if (index(buf, '.') == nil) { 5019676Slinton printf(".0"); 5029676Slinton } 5039676Slinton } 5049676Slinton 5059676Slinton /* 5069676Slinton * Print out a character using ^? notation for unprintables. 5079676Slinton */ 5089676Slinton 5099676Slinton public printchar(c) 5109676Slinton char c; 5119676Slinton { 5129676Slinton if (c == 0) { 5139676Slinton putchar('\\'); 5149676Slinton putchar('0'); 5159676Slinton } else if (c == '\n') { 5169676Slinton putchar('\\'); 5179676Slinton putchar('n'); 5189676Slinton } else if (c > 0 and c < ' ') { 5199676Slinton putchar('^'); 5209676Slinton putchar(c - 1 + 'A'); 5219676Slinton } else { 5229676Slinton putchar(c); 5239676Slinton } 5249676Slinton } 525