15529Slinton /* Copyright (c) 1982 Regents of the University of California */
25529Slinton 
3*11065Slinton static char sccsid[] = "@(#)printval.c 1.7 02/14/83";
45529Slinton 
55529Slinton /*
65529Slinton  * Print out the value at the top of the stack using the given type.
75529Slinton  */
85529Slinton 
95529Slinton #include "defs.h"
105529Slinton #include "sym.h"
115529Slinton #include "btypes.h"
125529Slinton #include "classes.h"
135529Slinton #include "tree.h"
145529Slinton #include "process.h"
155529Slinton #include "mappings.h"
165529Slinton #include "sym.rep"
175529Slinton 
185529Slinton printval(s)
195529Slinton SYM *s;
205529Slinton {
215783Slinton     SYM *t;
225783Slinton     ADDRESS a;
235783Slinton     int len;
245876Slinton     double r;
255529Slinton 
265783Slinton     if (s->class == REF) {
275783Slinton 	s = s->type;
285783Slinton     }
29*11065Slinton     switch (s->class) {
305783Slinton 	case ARRAY:
315783Slinton 	    t = rtype(s->type);
32*11065Slinton 	    if (t == t_char || (t->class == RANGE && t->type == t_char)) {
335783Slinton 		len = size(s);
345783Slinton 		sp -= len;
355783Slinton 		printf("'%.*s'", len, sp);
365783Slinton 		break;
375783Slinton 	    } else {
385783Slinton 		printarray(s);
395783Slinton 	    }
405783Slinton 	    break;
415529Slinton 
425783Slinton 	case RECORD:
435783Slinton 	    printrecord(s);
445783Slinton 	    break;
455529Slinton 
465783Slinton 	case VARNT:
475783Slinton 	    error("can't print out variant records");
485783Slinton 	    break;
495529Slinton 
505783Slinton 	case RANGE:
515783Slinton 	    if (s == t_real) {
526085Slinton 		prtreal(pop(double));
535783Slinton 	    } else {
54*11065Slinton 		printordinal(popsmall(s), rtype(s->type));
555783Slinton 	    }
565783Slinton 	    break;
575529Slinton 
585783Slinton 	case FILET:
59*11065Slinton 	case PTR:
60*11065Slinton 	    a = pop(ADDRESS);
61*11065Slinton 	    if (a == 0) {
625783Slinton 		printf("nil");
635783Slinton 	    } else {
64*11065Slinton 		printf("0%o", a);
655783Slinton 	    }
665783Slinton 	    break;
675529Slinton 
685783Slinton 	case FIELD:
695783Slinton 	    error("missing record specification");
705783Slinton 	    break;
715529Slinton 
72*11065Slinton 	case SCAL:
73*11065Slinton 	    printordinal(popsmall(s), s);
745783Slinton 	    break;
755529Slinton 
765783Slinton 	case FPROC:
775783Slinton 	case FFUNC:
785783Slinton 	    a = fparamaddr(pop(long));
795783Slinton 	    t = whatblock(a);
805783Slinton 	    if (t == NIL) {
815783Slinton 		printf("(proc %d)", a);
825783Slinton 	    } else {
835783Slinton 		printf("%s", t->symbol);
845783Slinton 	    }
855783Slinton 	    break;
865529Slinton 
875783Slinton 	default:
885783Slinton 	    if (s->class < BADUSE || s->class > VARNT) {
895783Slinton 		panic("printval: bad class %d", s->class);
905783Slinton 	    }
915783Slinton 	    error("don't know how to print a %s", classname(s));
925783Slinton 	    /* NOTREACHED */
935783Slinton     }
945529Slinton }
955529Slinton 
965529Slinton /*
97*11065Slinton  * Print out an ordinal value (either an integer, character, or
98*11065Slinton  * an enumeration constant).
99*11065Slinton  */
100*11065Slinton 
101*11065Slinton printordinal(v, t)
102*11065Slinton long v;
103*11065Slinton SYM *t;
104*11065Slinton {
105*11065Slinton     BOOLEAN found;
106*11065Slinton     SYM *c;
107*11065Slinton     int iv;
108*11065Slinton 
109*11065Slinton     iv = v;
110*11065Slinton     if (t->class == SCAL) {
111*11065Slinton 	c = t->chain;
112*11065Slinton 	while (c != NIL && c->symvalue.iconval != iv) {
113*11065Slinton 	    c = c->chain;
114*11065Slinton 	}
115*11065Slinton 	if (c == NIL) {
116*11065Slinton 	    printf("(scalar = %d)", iv);
117*11065Slinton 	} else {
118*11065Slinton 	    printf("%s", c->symbol);
119*11065Slinton 	}
120*11065Slinton     } else if (t == t_char) {
121*11065Slinton 	printf("'%c'", iv);
122*11065Slinton     } else if (t == t_boolean) {
123*11065Slinton 	printf("%s", (iv == TRUE) ? "true" : "false");
124*11065Slinton     } else {
125*11065Slinton 	printf("%ld", v);
126*11065Slinton     }
127*11065Slinton }
128*11065Slinton 
129*11065Slinton /*
1305529Slinton  * Print out the value of a record, field by field.
1315529Slinton  */
1325529Slinton 
1335529Slinton LOCAL printrecord(s)
1345529Slinton SYM *s;
1355529Slinton {
1365783Slinton     SYM *t;
1375529Slinton 
1385783Slinton     if ((t = s->chain) == NIL) {
1395783Slinton 	error("record has no fields");
1405783Slinton     }
1415783Slinton     printf("(");
1425783Slinton     sp -= size(s);
1435783Slinton     printfield(t);
1445783Slinton     printf(")");
1455529Slinton }
1465529Slinton 
1475529Slinton /*
1485529Slinton  * Print out a field, first printing out other fields.
1495529Slinton  * This is done because the fields are chained together backwards.
1505529Slinton  */
1515529Slinton 
1525529Slinton LOCAL printfield(s)
1535529Slinton SYM *s;
1545529Slinton {
1555783Slinton     STACK *savesp;
1565529Slinton 
1575783Slinton     if (s->chain != NIL) {
1585783Slinton 	printfield(s->chain);
1595783Slinton 	printf(", ");
1605783Slinton     }
1615783Slinton     printf("%s = ", s->symbol);
1625783Slinton     savesp = sp;
1635783Slinton     sp += (s->symvalue.offset + size(s->type));
1645783Slinton     printval(s->type);
1655783Slinton     sp = savesp;
1665529Slinton }
1675529Slinton 
1685529Slinton /*
1695529Slinton  * Print out the contents of an array.
1705529Slinton  * Haven't quite figured out what the best format is.
1715529Slinton  *
1725529Slinton  * This is rather inefficient.
1735529Slinton  *
1745529Slinton  * The "2*elsize" is there since "printval" drops the stack by elsize.
1755529Slinton  */
1765529Slinton 
1775529Slinton LOCAL printarray(a)
1785529Slinton SYM *a;
1795529Slinton {
1805783Slinton     STACK *savesp, *newsp;
1815783Slinton     SYM *eltype;
1825783Slinton     long elsize;
1835529Slinton 
1845783Slinton     savesp = sp;
1855783Slinton     sp -= size(a);
1865783Slinton     newsp = sp;
1875783Slinton     eltype = a->type;
1885783Slinton     elsize = size(eltype);
1895783Slinton     printf("(");
1905783Slinton     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
1915783Slinton 	if (sp - elsize != newsp) {
1925783Slinton 	    printf(", ");
1935529Slinton 	}
1945783Slinton 	printval(eltype);
1955783Slinton     }
1965783Slinton     sp = newsp;
1975783Slinton     printf(")");
1985529Slinton }
1995876Slinton 
2005876Slinton /*
2015876Slinton  * Print out the value of a real number.
2025876Slinton  * Pascal notation is somewhat different that what one gets
2035876Slinton  * from "%g" in printf.
2045876Slinton  */
2055876Slinton 
2066085Slinton LOCAL prtreal(r)
2075876Slinton double r;
2085876Slinton {
2095876Slinton     extern char *index();
2105876Slinton     char *p, buf[256];
2115876Slinton 
2125876Slinton     sprintf(buf, "%g", r);
2135876Slinton     if (buf[0] == '.') {
2145876Slinton 	printf("0%s", buf);
2155876Slinton     } else if (buf[0] == '-' && buf[1] == '.') {
2165876Slinton 	printf("-0%s", &buf[1]);
2175876Slinton     } else {
2185876Slinton 	printf("%s", buf);
2195876Slinton     }
2205876Slinton     if (index(buf, '.') == NIL) {
2215876Slinton 	printf(".0");
2225876Slinton     }
2235876Slinton }
224