15529Slinton /* Copyright (c) 1982 Regents of the University of California */
25529Slinton 
3*6085Slinton static char sccsid[] = "@(#)printval.c 1.6 03/09/82";
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     }
295783Slinton     switch(s->class) {
305783Slinton 	case ARRAY:
315783Slinton 	    t = rtype(s->type);
325783Slinton 	    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) {
52*6085Slinton 		prtreal(pop(double));
535783Slinton 	    } else if (s == t_char) {
545783Slinton 		printf("'%c'", pop(char));
555783Slinton 	    } else if (s == t_boolean) {
566075Slinton 		printf(popsmall(s) == TRUE ? "true" : "false");
575783Slinton 	    } else {
585783Slinton 		printf("%ld", popsmall(s));
595783Slinton 	    }
605783Slinton 	    break;
615529Slinton 
625783Slinton 	case FILET:
635783Slinton 	case PTR: {
645783Slinton 	    ADDRESS addr;
655529Slinton 
665783Slinton 	    addr = pop(ADDRESS);
675783Slinton 	    if (addr == 0) {
685783Slinton 		printf("nil");
695783Slinton 	    } else {
705783Slinton 		printf("0%o", addr);
715783Slinton 	    }
725783Slinton 	    break;
735783Slinton 	}
745529Slinton 
755783Slinton 	case FIELD:
765783Slinton 	    error("missing record specification");
775783Slinton 	    break;
785529Slinton 
795783Slinton 	case SCAL: {
805783Slinton 	    int scalar;
815783Slinton 	    BOOLEAN found;
825529Slinton 
835783Slinton 	    scalar = popsmall(s);
845783Slinton 	    found = FALSE;
855783Slinton 	    for (t = s->chain; t != NIL; t = t->chain) {
865783Slinton 		if (t->symvalue.iconval == scalar) {
875783Slinton 		    printf("%s", t->symbol);
885783Slinton 		    found = TRUE;
895783Slinton 		    break;
905529Slinton 		}
915783Slinton 	    }
925783Slinton 	    if (!found) {
935783Slinton 		printf("(scalar = %d)", scalar);
945783Slinton 	    }
955783Slinton 	    break;
965783Slinton 	}
975529Slinton 
985783Slinton 	case FPROC:
995783Slinton 	case FFUNC:
1005783Slinton 	{
1015783Slinton 	    ADDRESS a;
1025529Slinton 
1035783Slinton 	    a = fparamaddr(pop(long));
1045783Slinton 	    t = whatblock(a);
1055783Slinton 	    if (t == NIL) {
1065783Slinton 		printf("(proc %d)", a);
1075783Slinton 	    } else {
1085783Slinton 		printf("%s", t->symbol);
1095783Slinton 	    }
1105783Slinton 	    break;
1115783Slinton 	}
1125529Slinton 
1135783Slinton 	default:
1145783Slinton 	    if (s->class < BADUSE || s->class > VARNT) {
1155783Slinton 		panic("printval: bad class %d", s->class);
1165783Slinton 	    }
1175783Slinton 	    error("don't know how to print a %s", classname(s));
1185783Slinton 	    /* NOTREACHED */
1195783Slinton     }
1205529Slinton }
1215529Slinton 
1225529Slinton /*
1235529Slinton  * Print out the value of a record, field by field.
1245529Slinton  */
1255529Slinton 
1265529Slinton LOCAL printrecord(s)
1275529Slinton SYM *s;
1285529Slinton {
1295783Slinton     SYM *t;
1305529Slinton 
1315783Slinton     if ((t = s->chain) == NIL) {
1325783Slinton 	error("record has no fields");
1335783Slinton     }
1345783Slinton     printf("(");
1355783Slinton     sp -= size(s);
1365783Slinton     printfield(t);
1375783Slinton     printf(")");
1385529Slinton }
1395529Slinton 
1405529Slinton /*
1415529Slinton  * Print out a field, first printing out other fields.
1425529Slinton  * This is done because the fields are chained together backwards.
1435529Slinton  */
1445529Slinton 
1455529Slinton LOCAL printfield(s)
1465529Slinton SYM *s;
1475529Slinton {
1485783Slinton     STACK *savesp;
1495529Slinton 
1505783Slinton     if (s->chain != NIL) {
1515783Slinton 	printfield(s->chain);
1525783Slinton 	printf(", ");
1535783Slinton     }
1545783Slinton     printf("%s = ", s->symbol);
1555783Slinton     savesp = sp;
1565783Slinton     sp += (s->symvalue.offset + size(s->type));
1575783Slinton     printval(s->type);
1585783Slinton     sp = savesp;
1595529Slinton }
1605529Slinton 
1615529Slinton /*
1625529Slinton  * Print out the contents of an array.
1635529Slinton  * Haven't quite figured out what the best format is.
1645529Slinton  *
1655529Slinton  * This is rather inefficient.
1665529Slinton  *
1675529Slinton  * The "2*elsize" is there since "printval" drops the stack by elsize.
1685529Slinton  */
1695529Slinton 
1705529Slinton LOCAL printarray(a)
1715529Slinton SYM *a;
1725529Slinton {
1735783Slinton     STACK *savesp, *newsp;
1745783Slinton     SYM *eltype;
1755783Slinton     long elsize;
1765529Slinton 
1775783Slinton     savesp = sp;
1785783Slinton     sp -= size(a);
1795783Slinton     newsp = sp;
1805783Slinton     eltype = a->type;
1815783Slinton     elsize = size(eltype);
1825783Slinton     printf("(");
1835783Slinton     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
1845783Slinton 	if (sp - elsize != newsp) {
1855783Slinton 	    printf(", ");
1865529Slinton 	}
1875783Slinton 	printval(eltype);
1885783Slinton     }
1895783Slinton     sp = newsp;
1905783Slinton     printf(")");
1915529Slinton }
1925876Slinton 
1935876Slinton /*
1945876Slinton  * Print out the value of a real number.
1955876Slinton  * Pascal notation is somewhat different that what one gets
1965876Slinton  * from "%g" in printf.
1975876Slinton  */
1985876Slinton 
199*6085Slinton LOCAL prtreal(r)
2005876Slinton double r;
2015876Slinton {
2025876Slinton     extern char *index();
2035876Slinton     char *p, buf[256];
2045876Slinton 
2055876Slinton     sprintf(buf, "%g", r);
2065876Slinton     if (buf[0] == '.') {
2075876Slinton 	printf("0%s", buf);
2085876Slinton     } else if (buf[0] == '-' && buf[1] == '.') {
2095876Slinton 	printf("-0%s", &buf[1]);
2105876Slinton     } else {
2115876Slinton 	printf("%s", buf);
2125876Slinton     }
2135876Slinton     if (index(buf, '.') == NIL) {
2145876Slinton 	printf(".0");
2155876Slinton     }
2165876Slinton }
217