xref: /csrg-svn/old/dbx/printsym.c (revision 33330)
121619Sdist /*
221619Sdist  * Copyright (c) 1983 Regents of the University of California.
321619Sdist  * All rights reserved.  The Berkeley software License Agreement
421619Sdist  * specifies the terms and conditions for redistribution.
521619Sdist  */
69676Slinton 
721619Sdist #ifndef lint
8*33330Sdonn static char sccsid[] = "@(#)printsym.c	5.5 (Berkeley) 01/12/88";
921619Sdist #endif not lint
109676Slinton 
11*33330Sdonn static char rcsid[] = "$Header: printsym.c,v 1.4 87/04/15 00:23:35 donn Exp $";
1218229Slinton 
139676Slinton /*
149676Slinton  * Printing of symbolic information.
159676Slinton  */
169676Slinton 
179676Slinton #include "defs.h"
189676Slinton #include "symbols.h"
199676Slinton #include "languages.h"
209676Slinton #include "printsym.h"
219676Slinton #include "tree.h"
229676Slinton #include "eval.h"
239676Slinton #include "mappings.h"
249676Slinton #include "process.h"
259676Slinton #include "runtime.h"
269676Slinton #include "machine.h"
279676Slinton #include "names.h"
2818229Slinton #include "keywords.h"
299676Slinton #include "main.h"
3029820Ssam #include <ctype.h>
319676Slinton 
329676Slinton #ifndef public
339676Slinton #endif
349676Slinton 
359676Slinton /*
3611863Slinton  * Maximum number of arguments to a function.
3711863Slinton  * This is used as a check for the possibility that the stack has been
3811863Slinton  * overwritten and therefore a saved argument pointer might indicate
3911863Slinton  * to an absurdly large number of arguments.
4011863Slinton  */
4111863Slinton 
4211863Slinton #define MAXARGSPASSED 20
4311863Slinton 
4411863Slinton /*
459676Slinton  * Return a pointer to the string for the name of the class that
469676Slinton  * the given symbol belongs to.
479676Slinton  */
489676Slinton 
499676Slinton private String clname[] = {
50*33330Sdonn     "bad use", "constant", "type", "variable", "array", "array",
51*33330Sdonn     "dynarray", "subarray", "fileptr", "record", "field",
5218229Slinton     "procedure", "function", "funcvar",
539676Slinton     "ref", "pointer", "file", "set", "range", "label", "withptr",
549676Slinton     "scalar", "string", "program", "improper", "variant",
5516616Ssam     "procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
569676Slinton };
579676Slinton 
589676Slinton public String classname(s)
599676Slinton Symbol s;
609676Slinton {
619676Slinton     return clname[ord(s->class)];
629676Slinton }
639676Slinton 
649676Slinton /*
659676Slinton  * Note the entry of the given block, unless it's the main program.
669676Slinton  */
679676Slinton 
689676Slinton public printentry(s)
699676Slinton Symbol s;
709676Slinton {
719676Slinton     if (s != program) {
7218229Slinton 	printf("\nentering %s ", classname(s));
7318229Slinton 	printname(stdout, s);
7418229Slinton 	printf("\n");
759676Slinton     }
769676Slinton }
779676Slinton 
789676Slinton /*
799676Slinton  * Note the exit of the given block
809676Slinton  */
819676Slinton 
829676Slinton public printexit(s)
839676Slinton Symbol s;
849676Slinton {
859676Slinton     if (s != program) {
8618229Slinton 	printf("leaving %s ", classname(s));
8718229Slinton 	printname(stdout, s);
8818229Slinton 	printf("\n\n");
899676Slinton     }
909676Slinton }
919676Slinton 
929676Slinton /*
939676Slinton  * Note the call of s from t.
949676Slinton  */
959676Slinton 
969676Slinton public printcall(s, t)
979676Slinton Symbol s, t;
989676Slinton {
9918229Slinton     printf("calling ");
10018229Slinton     printname(stdout, s);
1019676Slinton     printparams(s, nil);
10218229Slinton     printf(" from %s ", classname(t));
10318229Slinton     printname(stdout, t);
10418229Slinton     printf("\n");
1059676Slinton }
1069676Slinton 
1079676Slinton /*
1089676Slinton  * Note the return from s.  If s is a function, print the value
1099676Slinton  * it is returning.  This is somewhat painful, since the function
1109676Slinton  * has actually just returned.
1119676Slinton  */
1129676Slinton 
1139676Slinton public printrtn(s)
1149676Slinton Symbol s;
1159676Slinton {
1169676Slinton     register Symbol t;
1179676Slinton     register int len;
1189676Slinton     Boolean isindirect;
1199676Slinton 
1209676Slinton     printf("returning ");
12112628Scsvaf     if (s->class == FUNC && (!istypename(s->type,"void"))) {
1229676Slinton 	len = size(s->type);
1239676Slinton 	if (canpush(len)) {
1249676Slinton 	    t = rtype(s->type);
1259676Slinton 	    isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
1269676Slinton 	    pushretval(len, isindirect);
1279676Slinton 	    printval(s->type);
1289676Slinton 	    putchar(' ');
1299676Slinton 	} else {
1309676Slinton 	    printf("(value too large) ");
1319676Slinton 	}
1329676Slinton     }
13318229Slinton     printf("from ");
13418229Slinton     printname(stdout, s);
13518229Slinton     printf("\n");
1369676Slinton }
1379676Slinton 
1389676Slinton /*
1399676Slinton  * Print the values of the parameters of the given procedure or function.
1409676Slinton  * The frame distinguishes recursive instances of a procedure.
14116616Ssam  *
14216616Ssam  * If the procedure or function is internal, the argument count is
14316616Ssam  * not valid so we ignore it.
1449676Slinton  */
1459676Slinton 
1469676Slinton public printparams(f, frame)
1479676Slinton Symbol f;
1489676Slinton Frame frame;
1499676Slinton {
1509676Slinton     Symbol param;
1519676Slinton     int n, m, s;
1529676Slinton 
1539676Slinton     n = nargspassed(frame);
15416616Ssam     if (isinternal(f)) {
15516616Ssam 	n = 0;
15616616Ssam     }
15718229Slinton     printf("(");
1589676Slinton     param = f->chain;
1599676Slinton     if (param != nil or n > 0) {
1609676Slinton 	m = n;
1619676Slinton 	if (param != nil) {
1629676Slinton 	    for (;;) {
16318229Slinton 		s = psize(param) div sizeof(Word);
1649676Slinton 		if (s == 0) {
1659676Slinton 		    s = 1;
1669676Slinton 		}
1679676Slinton 		m -= s;
16818229Slinton 		if (showaggrs) {
16918229Slinton 		    printv(param, frame);
17018229Slinton 		} else {
17118229Slinton 		    printparamv(param, frame);
17218229Slinton 		}
1739676Slinton 		param = param->chain;
1749676Slinton 	    if (param == nil) break;
1759676Slinton 		printf(", ");
1769676Slinton 	    }
1779676Slinton 	}
1789676Slinton 	if (m > 0) {
17911863Slinton 	    if (m > MAXARGSPASSED) {
18011863Slinton 		m = MAXARGSPASSED;
18111863Slinton 	    }
1829676Slinton 	    if (f->chain != nil) {
1839676Slinton 		printf(", ");
1849676Slinton 	    }
1859676Slinton 	    for (;;) {
1869676Slinton 		--m;
1879676Slinton 		printf("0x%x", argn(n - m, frame));
1889676Slinton 	    if (m <= 0) break;
1899676Slinton 		printf(", ");
1909676Slinton 	    }
1919676Slinton 	}
1929676Slinton     }
19318229Slinton     printf(")");
1949676Slinton }
1959676Slinton 
1969676Slinton /*
1979676Slinton  * Test if a symbol should be printed.  We don't print files,
1989676Slinton  * for example, simply because there's no good way to do it.
1999676Slinton  * The symbol must be within the given function.
2009676Slinton  */
2019676Slinton 
2029676Slinton public Boolean should_print(s)
2039676Slinton Symbol s;
2049676Slinton {
2059676Slinton     Boolean b;
2069676Slinton     register Symbol t;
2079676Slinton 
2089676Slinton     switch (s->class) {
2099676Slinton 	case VAR:
2109676Slinton 	case FVAR:
21114339Slinton 	    if (isparam(s)) {
21214339Slinton 		b = false;
21314339Slinton 	    } else {
21414339Slinton 		t = rtype(s->type);
21514339Slinton 		if (t == nil) {
21614339Slinton 		    b = false;
21714339Slinton 		} else {
21814339Slinton 		    switch (t->class) {
21914339Slinton 			case FILET:
22014339Slinton 			case SET:
22114339Slinton 			case BADUSE:
22214339Slinton 			    b = false;
22314339Slinton 			    break;
22414339Slinton 
22514339Slinton 			default:
22614339Slinton 			    b = true;
22714339Slinton 			    break;
22814339Slinton 		    }
22914339Slinton 		}
23014339Slinton 	    }
2319676Slinton 	    break;
2329676Slinton 
2339676Slinton 	default:
2349676Slinton 	    b = false;
2359676Slinton 	    break;
2369676Slinton     }
2379676Slinton     return b;
2389676Slinton }
2399676Slinton 
2409676Slinton /*
24118229Slinton  * Print out a parameter value.
24218229Slinton  *
24318229Slinton  * Since this is intended to be printed on a single line with other information
24418229Slinton  * aggregate values are not printed.
24518229Slinton  */
24618229Slinton 
24718229Slinton public printparamv (p, frame)
24818229Slinton Symbol p;
24918229Slinton Frame frame;
25018229Slinton {
25118229Slinton     Symbol t;
25218229Slinton 
25318229Slinton     t = rtype(p->type);
25418229Slinton     switch (t->class) {
25518229Slinton 	case ARRAY:
256*33330Sdonn 	case OPENARRAY:
25718229Slinton 	case DYNARRAY:
25818229Slinton 	case SUBARRAY:
25918229Slinton 	    t = rtype(t->type);
26018229Slinton 	    if (compatible(t, t_char)) {
26118229Slinton 		printv(p, frame);
26218229Slinton 	    } else {
26318229Slinton 		printf("%s = (...)", symname(p));
26418229Slinton 	    }
26518229Slinton 	    break;
26618229Slinton 
26718229Slinton 	case RECORD:
26818229Slinton 	    printf("%s = (...)", symname(p));
26918229Slinton 	    break;
27018229Slinton 
27118229Slinton 	default:
27218229Slinton 	    printv(p, frame);
27318229Slinton 	    break;
27418229Slinton     }
27518229Slinton }
27618229Slinton 
27718229Slinton /*
2789676Slinton  * Print the name and value of a variable.
2799676Slinton  */
2809676Slinton 
2819676Slinton public printv(s, frame)
2829676Slinton Symbol s;
2839676Slinton Frame frame;
2849676Slinton {
2859676Slinton     Address addr;
2869676Slinton     int len;
2879676Slinton 
2889676Slinton     if (isambiguous(s) and ismodule(container(s))) {
2899676Slinton 	printname(stdout, s);
2909676Slinton 	printf(" = ");
2919676Slinton     } else {
2929676Slinton 	printf("%s = ", symname(s));
2939676Slinton     }
29418229Slinton     if (isvarparam(s) and not isopenarray(s)) {
29518229Slinton 	rpush(address(s, frame), sizeof(Address));
29618229Slinton 	addr = pop(Address);
2979676Slinton     } else {
29818229Slinton 	addr = address(s, frame);
29918229Slinton     }
30018229Slinton     len = size(s);
30124554Smckusick     if (not canpush(len)) {
30224554Smckusick 	printf("*** expression too large ***");
30324554Smckusick     } else if (isreg(s)) {
30424554Smckusick 	push(Address, addr);
30524554Smckusick 	printval(s->type);
30624554Smckusick     } else {
30718229Slinton 	rpush(addr, len);
30818229Slinton 	printval(s->type);
30918229Slinton     }
3109676Slinton }
3119676Slinton 
3129676Slinton /*
3139676Slinton  * Print out the name of a symbol.
3149676Slinton  */
3159676Slinton 
3169676Slinton public printname(f, s)
3179676Slinton File f;
3189676Slinton Symbol s;
3199676Slinton {
3209676Slinton     if (s == nil) {
3219676Slinton 	fprintf(f, "(noname)");
32216616Ssam     } else if (s == program) {
32316616Ssam 	fprintf(f, ".");
3249676Slinton     } else if (isredirected() or isambiguous(s)) {
3259676Slinton 	printwhich(f, s);
3269676Slinton     } else {
3279676Slinton 	fprintf(f, "%s", symname(s));
3289676Slinton     }
3299676Slinton }
3309676Slinton 
3319676Slinton /*
3329676Slinton  * Print the fully specified variable that is described by the given identifer.
3339676Slinton  */
3349676Slinton 
3359676Slinton public printwhich(f, s)
3369676Slinton File f;
3379676Slinton Symbol s;
3389676Slinton {
3399676Slinton     printouter(f, container(s));
3409676Slinton     fprintf(f, "%s", symname(s));
3419676Slinton }
3429676Slinton 
3439676Slinton /*
3449676Slinton  * Print the fully qualified name of each symbol that has the same name
3459676Slinton  * as the given symbol.
3469676Slinton  */
3479676Slinton 
3489676Slinton public printwhereis(f, s)
3499676Slinton File f;
3509676Slinton Symbol s;
3519676Slinton {
3529676Slinton     register Name n;
3539676Slinton     register Symbol t;
3549676Slinton 
3559676Slinton     checkref(s);
3569676Slinton     n = s->name;
3579676Slinton     t = lookup(n);
3589676Slinton     printwhich(f, t);
3599676Slinton     t = t->next_sym;
3609676Slinton     while (t != nil) {
3619676Slinton 	if (t->name == n) {
3629676Slinton 	    putc(' ', f);
3639676Slinton 	    printwhich(f, t);
3649676Slinton 	}
3659676Slinton 	t = t->next_sym;
3669676Slinton     }
3679676Slinton     putc('\n', f);
3689676Slinton }
3699676Slinton 
3709676Slinton private printouter(f, s)
3719676Slinton File f;
3729676Slinton Symbol s;
3739676Slinton {
3749676Slinton     Symbol outer;
3759676Slinton 
3769676Slinton     if (s != nil) {
3779676Slinton 	outer = container(s);
3789676Slinton 	if (outer != nil and outer != program) {
3799676Slinton 	    printouter(f, outer);
3809676Slinton 	}
3819676Slinton 	fprintf(f, "%s.", symname(s));
3829676Slinton     }
3839676Slinton }
3849676Slinton 
3859676Slinton public printdecl(s)
3869676Slinton Symbol s;
3879676Slinton {
38818229Slinton     Language lang;
38918229Slinton 
3909676Slinton     checkref(s);
39118229Slinton     if (s->language == nil or s->language == primlang) {
39218229Slinton 	lang = findlanguage(".s");
39318229Slinton     } else {
39418229Slinton 	lang = s->language;
39518229Slinton     }
39618229Slinton     (*language_op(lang, L_PRINTDECL))(s);
3979676Slinton }
3989676Slinton 
3999676Slinton /*
4009676Slinton  * Straight dump of symbol information.
4019676Slinton  */
4029676Slinton 
4039676Slinton public psym(s)
4049676Slinton Symbol s;
4059676Slinton {
4069676Slinton     printf("name\t%s\n", symname(s));
4079676Slinton     printf("lang\t%s\n", language_name(s->language));
4089676Slinton     printf("level\t%d\n", s->level);
4099676Slinton     printf("class\t%s\n", classname(s));
4109676Slinton     printf("type\t0x%x", s->type);
4119676Slinton     if (s->type != nil and s->type->name != nil) {
4129676Slinton 	printf(" (%s)", symname(s->type));
4139676Slinton     }
4149676Slinton     printf("\nchain\t0x%x", s->chain);
4159676Slinton     if (s->chain != nil and s->chain->name != nil) {
4169676Slinton 	printf(" (%s)", symname(s->chain));
4179676Slinton     }
4189676Slinton     printf("\nblock\t0x%x", s->block);
419*33330Sdonn     if (s->block != nil and s->block->name != nil) {
4209676Slinton 	printf(" (");
4219676Slinton 	printname(stdout, s->block);
4229676Slinton 	putchar(')');
4239676Slinton     }
4249676Slinton     putchar('\n');
4259676Slinton     switch (s->class) {
42618229Slinton 	case TYPE:
42718229Slinton 	    printf("size\t%d\n", size(s));
42818229Slinton 	    break;
42918229Slinton 
4309676Slinton 	case VAR:
4319676Slinton 	case REF:
432*33330Sdonn 	    switch (s->storage) {
433*33330Sdonn 		case INREG:
434*33330Sdonn 		    printf("reg\t%d\n", s->symvalue.offset);
435*33330Sdonn 		    break;
436*33330Sdonn 
437*33330Sdonn 		case STK:
438*33330Sdonn 		    printf("offset\t%d\n", s->symvalue.offset);
439*33330Sdonn 		    break;
440*33330Sdonn 
441*33330Sdonn 		case EXT:
442*33330Sdonn 		    printf("address\t0x%x\n", s->symvalue.offset);
443*33330Sdonn 		    break;
4449676Slinton 	    }
44512545Scsvaf 	    printf("size\t%d\n", size(s));
4469676Slinton 	    break;
4479676Slinton 
4489676Slinton 	case RECORD:
4499676Slinton 	case VARNT:
4509676Slinton 	    printf("size\t%d\n", s->symvalue.offset);
4519676Slinton 	    break;
4529676Slinton 
4539676Slinton 	case FIELD:
4549676Slinton 	    printf("offset\t%d\n", s->symvalue.field.offset);
4559676Slinton 	    printf("size\t%d\n", s->symvalue.field.length);
4569676Slinton 	    break;
4579676Slinton 
45814381Slinton 	case PROG:
4599676Slinton 	case PROC:
4609676Slinton 	case FUNC:
4619676Slinton 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
46214438Slinton 	    if (isinline(s)) {
46314440Slinton 		printf("inline procedure\n");
46414438Slinton 	    }
46511863Slinton 	    if (nosource(s)) {
46611863Slinton 		printf("does not have source information\n");
46711863Slinton 	    } else {
46811863Slinton 		printf("has source information\n");
46911863Slinton 	    }
4709676Slinton 	    break;
4719676Slinton 
4729676Slinton 	case RANGE:
47314381Slinton 	    prangetype(s->symvalue.rangev.lowertype);
4749676Slinton 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
47514381Slinton 	    prangetype(s->symvalue.rangev.uppertype);
4769676Slinton 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
4779676Slinton 	    break;
4789676Slinton 
4799676Slinton 	default:
4809676Slinton 	    /* do nothing */
4819676Slinton 	    break;
4829676Slinton     }
4839676Slinton }
4849676Slinton 
48514381Slinton private prangetype(r)
48614381Slinton Rangetype r;
48714381Slinton {
48814381Slinton     switch (r) {
48914381Slinton 	case R_CONST:
49014381Slinton 	    printf("CONST");
49114381Slinton 	    break;
49214381Slinton 
49314381Slinton 	case R_ARG:
49414381Slinton 	    printf("ARG");
49514381Slinton 	    break;
49614381Slinton 
49714381Slinton 	case R_TEMP:
49814381Slinton 	    printf("TEMP");
49914381Slinton 	    break;
50014381Slinton 
50114381Slinton 	case R_ADJUST:
50214381Slinton 	    printf("ADJUST");
50314381Slinton 	    break;
50414381Slinton     }
50514381Slinton }
50614381Slinton 
5079676Slinton /*
5089676Slinton  * Print out the value on top of the stack according to the given type.
5099676Slinton  */
5109676Slinton 
5119676Slinton public printval(t)
5129676Slinton Symbol t;
5139676Slinton {
5149676Slinton     Symbol s;
5159676Slinton 
5169676Slinton     checkref(t);
51716616Ssam     if (t->class == TYPEREF) {
51816616Ssam 	resolveRef(t);
51916616Ssam     }
5209676Slinton     switch (t->class) {
5219676Slinton 	case PROC:
5229676Slinton 	case FUNC:
5239676Slinton 	    s = pop(Symbol);
5249676Slinton 	    printf("%s", symname(s));
5259676Slinton 	    break;
5269676Slinton 
5279676Slinton 	default:
52818229Slinton 	    if (t->language == nil or t->language == primlang) {
52926478Ssam 		(*language_op(findlanguage(".c"), L_PRINTVAL))(t);
5309676Slinton 	    } else {
5319676Slinton 		(*language_op(t->language, L_PRINTVAL))(t);
5329676Slinton 	    }
5339676Slinton 	    break;
5349676Slinton     }
5359676Slinton }
5369676Slinton 
5379676Slinton /*
5389676Slinton  * Print out the value of a record, field by field.
5399676Slinton  */
5409676Slinton 
5419676Slinton public printrecord(s)
5429676Slinton Symbol s;
5439676Slinton {
54416616Ssam     Symbol f;
54516616Ssam 
5469676Slinton     if (s->chain == nil) {
5479676Slinton 	error("record has no fields");
5489676Slinton     }
5499676Slinton     printf("(");
5509676Slinton     sp -= size(s);
55116616Ssam     f = s->chain;
55216616Ssam     if (f != nil) {
55316616Ssam 	for (;;) {
55416616Ssam 	    printfield(f);
55516616Ssam 	    f = f->chain;
55616616Ssam 	if (f == nil) break;
55716616Ssam 	    printf(", ");
55816616Ssam 	}
55916616Ssam     }
5609676Slinton     printf(")");
5619676Slinton }
5629676Slinton 
5639676Slinton /*
56416616Ssam  * Print out a field.
5659676Slinton  */
5669676Slinton 
56716616Ssam private printfield(f)
56816616Ssam Symbol f;
5699676Slinton {
5709676Slinton     Stack *savesp;
57116616Ssam     register int off, len;
5729676Slinton 
57316616Ssam     printf("%s = ", symname(f));
5749676Slinton     savesp = sp;
57516616Ssam     off = f->symvalue.field.offset;
57616616Ssam     len = f->symvalue.field.length;
57716616Ssam     sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
57816616Ssam     printval(f);
5799676Slinton     sp = savesp;
5809676Slinton }
5819676Slinton 
5829676Slinton /*
5839676Slinton  * Print out the contents of an array.
5849676Slinton  * Haven't quite figured out what the best format is.
5859676Slinton  *
5869676Slinton  * This is rather inefficient.
5879676Slinton  *
5889676Slinton  * The "2*elsize" is there since "printval" drops the stack by elsize.
5899676Slinton  */
5909676Slinton 
5919676Slinton public printarray(a)
5929676Slinton Symbol a;
5939676Slinton {
5949676Slinton     Stack *savesp, *newsp;
5959676Slinton     Symbol eltype;
5969676Slinton     long elsize;
5979676Slinton     String sep;
5989676Slinton 
5999676Slinton     savesp = sp;
60012544Scsvaf     sp -= (size(a));
6019676Slinton     newsp = sp;
6029676Slinton     eltype = rtype(a->type);
6039676Slinton     elsize = size(eltype);
6049676Slinton     printf("(");
6059676Slinton     if (eltype->class == RECORD or eltype->class == ARRAY or
6069676Slinton       eltype->class == VARNT) {
6079676Slinton 	sep = "\n";
6089676Slinton 	putchar('\n');
6099676Slinton     } else {
6109676Slinton 	sep = ", ";
6119676Slinton     }
6129676Slinton     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
6139676Slinton 	if (sp - elsize != newsp) {
6149676Slinton 	    fputs(sep, stdout);
6159676Slinton 	}
6169676Slinton 	printval(eltype);
6179676Slinton     }
6189676Slinton     sp = newsp;
6199676Slinton     if (streq(sep, "\n")) {
6209676Slinton 	putchar('\n');
6219676Slinton     }
6229676Slinton     printf(")");
6239676Slinton }
6249676Slinton 
6259676Slinton /*
6269676Slinton  * Print out the value of a real number in Pascal notation.
6279676Slinton  * This is, unfortunately, different than what one gets
6289676Slinton  * from "%g" in printf.
6299676Slinton  */
6309676Slinton 
6319676Slinton public prtreal(r)
6329676Slinton double r;
6339676Slinton {
6349676Slinton     extern char *index();
6359676Slinton     char buf[256];
6369676Slinton 
637*33330Sdonn #   ifdef IRIS
638*33330Sdonn 	sprintf(buf, "%lg", r);
639*33330Sdonn #   else
640*33330Sdonn 	sprintf(buf, "%g", r);
641*33330Sdonn #   endif
6429676Slinton     if (buf[0] == '.') {
6439676Slinton 	printf("0%s", buf);
6449676Slinton     } else if (buf[0] == '-' and buf[1] == '.') {
6459676Slinton 	printf("-0%s", &buf[1]);
6469676Slinton     } else {
6479676Slinton 	printf("%s", buf);
6489676Slinton     }
6499676Slinton     if (index(buf, '.') == nil) {
6509676Slinton 	printf(".0");
6519676Slinton     }
6529676Slinton }
6539676Slinton 
6549676Slinton /*
6559676Slinton  * Print out a character using ^? notation for unprintables.
6569676Slinton  */
6579676Slinton 
6589676Slinton public printchar(c)
6599676Slinton char c;
6609676Slinton {
6619676Slinton     if (c == 0) {
6629676Slinton 	putchar('\\');
6639676Slinton 	putchar('0');
6649676Slinton     } else if (c == '\n') {
6659676Slinton 	putchar('\\');
6669676Slinton 	putchar('n');
6679676Slinton     } else if (c > 0 and c < ' ') {
6689676Slinton 	putchar('^');
6699676Slinton 	putchar(c - 1 + 'A');
67016616Ssam     } else if (c >= ' ' && c <= '~') {
67116616Ssam 	putchar(c);
6729676Slinton     } else {
67329820Ssam 	printf("\\0%o",c&0xff);
6749676Slinton     }
6759676Slinton }
67618229Slinton 
67718229Slinton /*
67818229Slinton  * Print out a value for a range type (integer, char, or boolean).
67918229Slinton  */
68018229Slinton 
68118229Slinton public printRangeVal (val, t)
68218229Slinton long val;
68318229Slinton Symbol t;
68418229Slinton {
68518229Slinton     if (t == t_boolean->type or istypename(t->type, "boolean")) {
68618229Slinton 	if ((boolean) val) {
68718229Slinton 	    printf("true");
68818229Slinton 	} else {
68918229Slinton 	    printf("false");
69018229Slinton 	}
69118229Slinton     } else if (t == t_char->type or istypename(t->type, "char")) {
69218229Slinton 	if (varIsSet("$hexchars")) {
69318229Slinton 	    printf("0x%lx", val);
69418229Slinton 	} else {
69518229Slinton 	    putchar('\'');
69618229Slinton 	    printchar(val);
69718229Slinton 	    putchar('\'');
69818229Slinton 	}
69918229Slinton     } else if (varIsSet("$hexints")) {
70018229Slinton 	printf("0x%lx", val);
70118229Slinton     } else if (t->symvalue.rangev.lower >= 0) {
70218229Slinton 	printf("%lu", val);
70318229Slinton     } else {
70418229Slinton 	printf("%ld", val);
70518229Slinton     }
70618229Slinton }
70718229Slinton 
70818229Slinton /*
70918229Slinton  * Print out an enumerated value by finding the corresponding
71018229Slinton  * name in the enumeration list.
71118229Slinton  */
71218229Slinton 
71318229Slinton public printEnum (i, t)
71418229Slinton integer i;
71518229Slinton Symbol t;
71618229Slinton {
71718229Slinton     register Symbol e;
71818229Slinton 
71918229Slinton     e = t->chain;
72018229Slinton     while (e != nil and e->symvalue.constval->value.lcon != i) {
72118229Slinton 	e = e->chain;
72218229Slinton     }
72318229Slinton     if (e != nil) {
72418229Slinton 	printf("%s", symname(e));
72518229Slinton     } else {
72618229Slinton 	printf("%d", i);
72718229Slinton     }
72818229Slinton }
72918229Slinton 
73018229Slinton /*
73118229Slinton  * Print out a null-terminated string (pointer to char)
73218229Slinton  * starting at the given address.
73318229Slinton  */
73418229Slinton 
73518229Slinton public printString (addr, quotes)
73618229Slinton Address addr;
73718229Slinton boolean quotes;
73818229Slinton {
73918229Slinton     register Address a;
74018229Slinton     register integer i, len;
74118229Slinton     register boolean endofstring;
74229820Ssam     register int unprintables;
74329820Ssam #define	MAXGARBAGE	4
74418229Slinton     union {
74518229Slinton 	char ch[sizeof(Word)];
74618229Slinton 	int word;
74718229Slinton     } u;
74818229Slinton 
74918229Slinton     if (varIsSet("$hexstrings")) {
75018229Slinton 	printf("0x%x", addr);
75118229Slinton     } else {
75218229Slinton 	if (quotes) {
75318229Slinton 	    putchar('"');
75418229Slinton 	}
75518229Slinton 	a = addr;
75629820Ssam 	unprintables = 0;
75718229Slinton 	endofstring = false;
75818229Slinton 	while (not endofstring) {
75918229Slinton 	    dread(&u, a, sizeof(u));
76018229Slinton 	    i = 0;
76118229Slinton 	    do {
76218229Slinton 		if (u.ch[i] == '\0') {
76318229Slinton 		    endofstring = true;
76418229Slinton 		} else {
76518229Slinton 		    printchar(u.ch[i]);
76629820Ssam 		    if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
76729820Ssam 			endofstring = true;
76829820Ssam 			printf("...");
76929820Ssam 		    }
77018229Slinton 		}
77118229Slinton 		++i;
77218229Slinton 	    } while (i < sizeof(Word) and not endofstring);
77318229Slinton 	    a += sizeof(Word);
77418229Slinton 	}
77518229Slinton 	if (quotes) {
77618229Slinton 	    putchar('"');
77718229Slinton 	}
77818229Slinton     }
77918229Slinton }
780