1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)printval.c 1.3 02/13/82";
4 
5 /*
6  * Print out the value at the top of the stack using the given type.
7  */
8 
9 #include "defs.h"
10 #include "sym.h"
11 #include "btypes.h"
12 #include "classes.h"
13 #include "tree.h"
14 #include "process.h"
15 #include "mappings.h"
16 #include "sym.rep"
17 
18 printval(s)
19 SYM *s;
20 {
21     SYM *t;
22     ADDRESS a;
23     int len;
24 
25     if (s->class == REF) {
26 	s = s->type;
27     }
28     switch(s->class) {
29 	case ARRAY:
30 	    t = rtype(s->type);
31 	    if (t==t_char || (t->class==RANGE && t->type==t_char)) {
32 		len = size(s);
33 		sp -= len;
34 		printf("'%.*s'", len, sp);
35 		break;
36 	    } else {
37 		printarray(s);
38 	    }
39 	    break;
40 
41 	case RECORD:
42 	    printrecord(s);
43 	    break;
44 
45 	case VARNT:
46 	    error("can't print out variant records");
47 	    break;
48 
49 	case RANGE:
50 	    if (s == t_real) {
51 		printf("%g", pop(double));
52 	    } else if (s == t_char) {
53 		printf("'%c'", pop(char));
54 	    } else if (s == t_boolean) {
55 		printf(pop(BOOLEAN)==TRUE ? "true" : "false");
56 	    } else {
57 		printf("%ld", popsmall(s));
58 	    }
59 	    break;
60 
61 	case FILET:
62 	case PTR: {
63 	    ADDRESS addr;
64 
65 	    addr = pop(ADDRESS);
66 	    if (addr == 0) {
67 		printf("nil");
68 	    } else {
69 		printf("0%o", addr);
70 	    }
71 	    break;
72 	}
73 
74 	case FIELD:
75 	    error("missing record specification");
76 	    break;
77 
78 	case SCAL: {
79 	    int scalar;
80 	    BOOLEAN found;
81 
82 	    scalar = popsmall(s);
83 	    found = FALSE;
84 	    for (t = s->chain; t != NIL; t = t->chain) {
85 		if (t->symvalue.iconval == scalar) {
86 		    printf("%s", t->symbol);
87 		    found = TRUE;
88 		    break;
89 		}
90 	    }
91 	    if (!found) {
92 		printf("(scalar = %d)", scalar);
93 	    }
94 	    break;
95 	}
96 
97 	case FPROC:
98 	case FFUNC:
99 	{
100 	    ADDRESS a;
101 
102 	    a = fparamaddr(pop(long));
103 	    t = whatblock(a);
104 	    if (t == NIL) {
105 		printf("(proc %d)", a);
106 	    } else {
107 		printf("%s", t->symbol);
108 	    }
109 	    break;
110 	}
111 
112 	default:
113 	    if (s->class < BADUSE || s->class > VARNT) {
114 		panic("printval: bad class %d", s->class);
115 	    }
116 	    error("don't know how to print a %s", classname(s));
117 	    /* NOTREACHED */
118     }
119 }
120 
121 /*
122  * Print out the value of a record, field by field.
123  */
124 
125 LOCAL printrecord(s)
126 SYM *s;
127 {
128     SYM *t;
129 
130     if ((t = s->chain) == NIL) {
131 	error("record has no fields");
132     }
133     printf("(");
134     sp -= size(s);
135     printfield(t);
136     printf(")");
137 }
138 
139 /*
140  * Print out a field, first printing out other fields.
141  * This is done because the fields are chained together backwards.
142  */
143 
144 LOCAL printfield(s)
145 SYM *s;
146 {
147     STACK *savesp;
148 
149     if (s->chain != NIL) {
150 	printfield(s->chain);
151 	printf(", ");
152     }
153     printf("%s = ", s->symbol);
154     savesp = sp;
155     sp += (s->symvalue.offset + size(s->type));
156     printval(s->type);
157     sp = savesp;
158 }
159 
160 /*
161  * Print out the contents of an array.
162  * Haven't quite figured out what the best format is.
163  *
164  * This is rather inefficient.
165  *
166  * The "2*elsize" is there since "printval" drops the stack by elsize.
167  */
168 
169 LOCAL printarray(a)
170 SYM *a;
171 {
172     STACK *savesp, *newsp;
173     SYM *eltype;
174     long elsize;
175 
176     savesp = sp;
177     sp -= size(a);
178     newsp = sp;
179     eltype = a->type;
180     elsize = size(eltype);
181     printf("(");
182     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
183 	if (sp - elsize != newsp) {
184 	    printf(", ");
185 	}
186 	printval(eltype);
187     }
188     sp = newsp;
189     printf(")");
190 }
191