xref: /original-bsd/usr.bin/pascal/pdx/sym/printval.c (revision 92d3de31)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)printval.c 1.7 02/14/83";
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     double r;
25 
26     if (s->class == REF) {
27 	s = s->type;
28     }
29     switch (s->class) {
30 	case ARRAY:
31 	    t = rtype(s->type);
32 	    if (t == t_char || (t->class == RANGE && t->type == t_char)) {
33 		len = size(s);
34 		sp -= len;
35 		printf("'%.*s'", len, sp);
36 		break;
37 	    } else {
38 		printarray(s);
39 	    }
40 	    break;
41 
42 	case RECORD:
43 	    printrecord(s);
44 	    break;
45 
46 	case VARNT:
47 	    error("can't print out variant records");
48 	    break;
49 
50 	case RANGE:
51 	    if (s == t_real) {
52 		prtreal(pop(double));
53 	    } else {
54 		printordinal(popsmall(s), rtype(s->type));
55 	    }
56 	    break;
57 
58 	case FILET:
59 	case PTR:
60 	    a = pop(ADDRESS);
61 	    if (a == 0) {
62 		printf("nil");
63 	    } else {
64 		printf("0%o", a);
65 	    }
66 	    break;
67 
68 	case FIELD:
69 	    error("missing record specification");
70 	    break;
71 
72 	case SCAL:
73 	    printordinal(popsmall(s), s);
74 	    break;
75 
76 	case FPROC:
77 	case FFUNC:
78 	    a = fparamaddr(pop(long));
79 	    t = whatblock(a);
80 	    if (t == NIL) {
81 		printf("(proc %d)", a);
82 	    } else {
83 		printf("%s", t->symbol);
84 	    }
85 	    break;
86 
87 	default:
88 	    if (s->class < BADUSE || s->class > VARNT) {
89 		panic("printval: bad class %d", s->class);
90 	    }
91 	    error("don't know how to print a %s", classname(s));
92 	    /* NOTREACHED */
93     }
94 }
95 
96 /*
97  * Print out an ordinal value (either an integer, character, or
98  * an enumeration constant).
99  */
100 
101 printordinal(v, t)
102 long v;
103 SYM *t;
104 {
105     BOOLEAN found;
106     SYM *c;
107     int iv;
108 
109     iv = v;
110     if (t->class == SCAL) {
111 	c = t->chain;
112 	while (c != NIL && c->symvalue.iconval != iv) {
113 	    c = c->chain;
114 	}
115 	if (c == NIL) {
116 	    printf("(scalar = %d)", iv);
117 	} else {
118 	    printf("%s", c->symbol);
119 	}
120     } else if (t == t_char) {
121 	printf("'%c'", iv);
122     } else if (t == t_boolean) {
123 	printf("%s", (iv == TRUE) ? "true" : "false");
124     } else {
125 	printf("%ld", v);
126     }
127 }
128 
129 /*
130  * Print out the value of a record, field by field.
131  */
132 
133 LOCAL printrecord(s)
134 SYM *s;
135 {
136     SYM *t;
137 
138     if ((t = s->chain) == NIL) {
139 	error("record has no fields");
140     }
141     printf("(");
142     sp -= size(s);
143     printfield(t);
144     printf(")");
145 }
146 
147 /*
148  * Print out a field, first printing out other fields.
149  * This is done because the fields are chained together backwards.
150  */
151 
152 LOCAL printfield(s)
153 SYM *s;
154 {
155     STACK *savesp;
156 
157     if (s->chain != NIL) {
158 	printfield(s->chain);
159 	printf(", ");
160     }
161     printf("%s = ", s->symbol);
162     savesp = sp;
163     sp += (s->symvalue.offset + size(s->type));
164     printval(s->type);
165     sp = savesp;
166 }
167 
168 /*
169  * Print out the contents of an array.
170  * Haven't quite figured out what the best format is.
171  *
172  * This is rather inefficient.
173  *
174  * The "2*elsize" is there since "printval" drops the stack by elsize.
175  */
176 
177 LOCAL printarray(a)
178 SYM *a;
179 {
180     STACK *savesp, *newsp;
181     SYM *eltype;
182     long elsize;
183 
184     savesp = sp;
185     sp -= size(a);
186     newsp = sp;
187     eltype = a->type;
188     elsize = size(eltype);
189     printf("(");
190     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
191 	if (sp - elsize != newsp) {
192 	    printf(", ");
193 	}
194 	printval(eltype);
195     }
196     sp = newsp;
197     printf(")");
198 }
199 
200 /*
201  * Print out the value of a real number.
202  * Pascal notation is somewhat different that what one gets
203  * from "%g" in printf.
204  */
205 
206 LOCAL prtreal(r)
207 double r;
208 {
209     extern char *index();
210     char *p, buf[256];
211 
212     sprintf(buf, "%g", r);
213     if (buf[0] == '.') {
214 	printf("0%s", buf);
215     } else if (buf[0] == '-' && buf[1] == '.') {
216 	printf("-0%s", &buf[1]);
217     } else {
218 	printf("%s", buf);
219     }
220     if (index(buf, '.') == NIL) {
221 	printf(".0");
222     }
223 }
224