Pristine Ack-5.5
[Ack-5.5.git] / util / grind / print.c
1 /* $Id: print.c,v 1.16 1994/06/24 11:00:47 ceriel Exp $ */
2
3 #include <alloc.h>
4 #include <assert.h>
5 #include <stdio.h>
6
7 #include "type.h"
8 #include "langdep.h"
9 #include "scope.h"
10 #include "symbol.h"
11 #include "position.h"
12 #include "idf.h"
13 #include "expr.h"
14 #include "misc.h"
15
16 extern FILE *db_out;
17 extern char *strindex();
18 extern char *malloc();
19
20 static
21 print_unsigned(tp, v, format)
22   p_type        tp;
23   long          v;
24   register char *format;
25 {
26   while (format && *format) {
27         if (strindex("cdohx", *format)) break;
28         format++;
29   }
30   switch(format == 0 ? 0 : *format) {
31   case 'u':
32         fprintf(db_out, currlang->uns_fmt, v);
33         break;
34   default:
35         if (tp != uchar_type) {
36                 fprintf(db_out, currlang->uns_fmt, v);
37                 break;
38         }
39         /* fall through */
40   case 'c':
41         (*currlang->printchar)((int) v);
42         break;
43   case 'd':
44         fprintf(db_out, currlang->decint_fmt, v);
45         break;
46   case 'o':
47         fprintf(db_out, currlang->octint_fmt, v);
48         break;
49   case 'x':
50   case 'h':
51         fprintf(db_out, currlang->hexint_fmt, v);
52         break;
53   }
54 }
55
56 static
57 print_literal(tp, v, compressed, format)
58   p_type        tp;
59   long          v;
60   int           compressed;
61   char          *format;
62 {
63   register struct literal *lit = tp->ty_literals;
64   register int i;
65
66   if (format) {
67         print_unsigned(tp, v, format);
68         return;
69   }
70   for (i = tp->ty_nenums; i; i--, lit++) {
71         if (lit->lit_val == v) {
72                 fputs(lit->lit_name, db_out);
73                 break;
74         }
75   }
76   if (! i) {
77         fprintf(db_out,
78                 compressed ? "?%ld?" : "unknown enumeration value %ld",
79                 v);
80   }
81 }
82
83 static
84 print_integer(tp, v, format)
85   p_type        tp;
86   long          v;
87   register char *format;
88 {
89   while (format && *format) {
90         if (strindex("cdohx", *format)) break;
91         format++;
92   }
93   switch(format == 0 ? 0 : *format) {
94   default:
95         if (tp != char_type) {
96                 fprintf(db_out, currlang->decint_fmt, v);
97                 break;
98         }
99         /* fall through */
100   case 'c':
101         (*currlang->printchar)((int) v);
102         break;
103   case 'd':
104         fprintf(db_out, currlang->decint_fmt, v);
105         break;
106   case 'o':
107         fprintf(db_out, currlang->octint_fmt, v);
108         break;
109   case 'x':
110   case 'h':
111         fprintf(db_out, currlang->hexint_fmt, v);
112         break;
113   case 'u':
114         fprintf(db_out, currlang->uns_fmt, v);
115         break;
116   }
117 }
118
119 print_params(tp, AB, static_link)
120   p_type        tp;
121   t_addr        AB;
122 {
123   char *param_bytes;
124   register char *p;
125   register int i;
126   register struct param *par;
127   long size;
128
129   if (! tp) return;
130   assert(tp->ty_class == T_PROCEDURE);
131
132   if ((i = tp->ty_nparams) == 0) return;
133
134   /* get parameter bytes */
135   par = tp->ty_params;
136   size = tp->ty_nbparams;
137   if (static_link) size += pointer_size;
138   param_bytes = p = malloc((unsigned)size);
139   if (! p) {
140         error("could not allocate enough memory");
141         return;
142   }
143   if (! get_bytes(size, AB, p)) {
144         free(p);
145         return;
146   }
147
148   while (i--) {
149         p = param_bytes + par->par_off;
150         if (par->par_kind == 'v' || par->par_kind == 'i') {
151                 /* call by reference parameter, or
152                    call by value parameter, but address is passed;
153                    try and get value.
154                 */
155                 char    *q;
156                 t_addr  addr = get_int(p, pointer_size, T_UNSIGNED);
157
158                 if ((size = par->par_type->ty_size) == 0) {
159                         size = compute_size(par->par_type, param_bytes);
160                 }
161                 q = malloc((unsigned) size);
162                 if (! q) {
163                         error("could not allocate enough memory");
164                         free(param_bytes);
165                         return;
166                 }
167                 if (! get_bytes(size, addr, q)) {
168                         fprintf(db_out, currlang->addr_fmt, (long) addr);
169                 }
170                 else {
171                         print_val(par->par_type, size, q, 1, 0, (char *)0);
172                 }
173                 free(q);
174         }
175         else print_val(par->par_type, par->par_type->ty_size, p, 1, 0, (char *)0);
176         if (i) fputs(", ", db_out);
177         par++;
178   }
179   free(param_bytes);
180 }
181
182 print_val(tp, tp_sz, addr, compressed, indent, format)
183   p_type        tp;             /* type of value to be printed */
184   long          tp_sz;          /* size of object to be printed */
185   char          *addr;          /* address to get value from */
186   int           compressed;     /* for parameter lists */
187   int           indent;         /* indentation */
188   register char *format;        /* format given or 0 */
189 {
190   register int i;
191   long elsize;
192
193   if (indent == 0) indent = 4;
194   switch(tp->ty_class) {
195   case T_CROSS:
196         if (! tp->ty_cross) {
197                 error("unknown type");
198                 break;
199         }
200         print_val(tp->ty_cross, tp_sz, addr, compressed, indent, format);
201         break;
202   case T_SUBRANGE:
203         print_val(tp->ty_base, tp_sz, addr, compressed, indent, format);
204         break;
205   case T_ARRAY:
206         if ((!format || strindex(format, 'a') == 0) &&
207             (tp->ty_elements == char_type ||
208              tp->ty_elements == uchar_type)) {
209                 print_val(string_type, tp_sz, addr, compressed, indent, format);
210                 break;
211         }
212         if (compressed) {
213                 fprintf(db_out, currlang->open_array_display);
214         }
215         else {
216                 fprintf(db_out, "\n%*c%s%*c",
217                         indent,
218                         ' ',
219                         currlang->open_array_display,
220                         4-strlen(currlang->open_array_display), ' ');
221         }
222         indent += 4;
223         elsize = (*currlang->arrayelsize)(tp->ty_elements->ty_size);
224         for (i = tp_sz/elsize; i; i--) {
225                 print_val(tp->ty_elements, tp->ty_elements->ty_size, addr, compressed, indent, format);
226                 addr += elsize;
227                 if (compressed && i > 1) {
228                         fprintf(db_out, ", ...");
229                         break;
230                 } 
231                 if (i > 1) {
232                         putc(',', db_out);
233                 }
234                 fprintf(db_out, "\n%*c", i > 1 ? indent : indent - 4, ' ');
235         }
236         fprintf(db_out, currlang->close_array_display);
237         indent -= 4;
238         break;
239   case T_STRUCT: {
240         register struct fields *fld = tp->ty_fields;
241
242         if (compressed) {
243                 fprintf(db_out, currlang->open_struct_display);
244         }
245         else {
246                 fprintf(db_out, "\n%*c%s%*c",
247                         indent,
248                         ' ',
249                         currlang->open_struct_display,
250                         4-strlen(currlang->open_struct_display), ' ');
251         }
252         indent += 4;
253         for (i = tp->ty_nfields; i; i--, fld++) {
254                 long sz = fld->fld_type->ty_size;
255                 if (! compressed) fprintf(db_out, "%s = ", fld->fld_name);
256                 if (fld->fld_bitsize < (sz << 3)) {
257                         /* apparently a bit field */
258                         /* ??? */
259                         fprintf(db_out, "<bitfield, %ld, %ld>", fld->fld_bitsize, sz);
260                 }
261                 else print_val(fld->fld_type, sz, addr+(fld->fld_pos>>3), compressed, indent, format);
262                 if (compressed && i > 1) {
263                         fprintf(db_out, ", ...");
264                         break;
265                 } 
266                 if (i > 1) {
267                         putc(',', db_out);
268                 }
269                 fprintf(db_out, "\n%*c", i > 1 ? indent : indent - 4, ' ');
270         }
271         indent -= 4;
272         fprintf(db_out, currlang->close_struct_display);
273         break;
274         }
275   case T_UNION:
276         fprintf(db_out, "<union>");
277         break;
278   case T_ENUM:
279         print_literal(tp, get_int(addr, tp_sz, T_ENUM), compressed, format);
280         break;
281   case T_PROCEDURE: {
282         register p_scope sc = get_scope_from_addr((t_addr) get_int(addr, pointer_size, T_UNSIGNED));
283
284         if (sc && sc->sc_definedby) {
285                 fprintf(db_out, sc->sc_definedby->sy_idf->id_text);
286                 break;
287         }
288         }
289         fprintf(db_out, currlang->addr_fmt, get_int(addr, pointer_size, T_UNSIGNED));
290         break;
291   case T_POINTER: {
292         t_addr a = get_int(addr, tp_sz, T_UNSIGNED);
293
294         fprintf(db_out, currlang->addr_fmt, a);
295         if (format && strindex(format, 's') &&
296             (tp->ty_ptrto == char_type || tp->ty_ptrto == uchar_type)) {
297                 char *naddr = malloc(512);
298
299                 if (! naddr) {
300                         fputs(" (could not allocate memory)", db_out);
301                         break;
302                 }
303                 if (! get_string(511L, a, naddr)) {
304                         fputs(" (not a valid pointer)", db_out);
305                         free(naddr);
306                         break;
307                 }
308                 fputs(" (", db_out);
309                 print_val(string_type, 512L, naddr, 0, indent, format);
310                 fputs(")", db_out);
311                 free(naddr);
312                 break;
313         }
314         if (tp->ty_ptrto->ty_class == T_PROCEDURE) {
315                 p_scope sc = get_scope_from_addr(a);
316                 if (sc && sc->sc_definedby && a == sc->sc_start) {
317                         fprintf(db_out, " (%s)", sc->sc_definedby->sy_idf->id_text);
318                 }
319         }
320         break;
321         }
322   case T_FILE:
323         fprintf(db_out, "<file>");
324         break;
325   case T_SET: {
326         long    val = tp->ty_setlow;
327         p_type  base = tp->ty_setbase;
328         long    nelements = tp->ty_size << 3;
329         int     count = 0;
330         int     rsft = 3 + (int_size == 2 ? 1 : 2);
331         long    mask = int_size == 2 ? 017: 037;
332
333         if (base->ty_class == T_SUBRANGE) base = base->ty_base;
334         if (compressed) {
335                 fprintf(db_out, currlang->open_set_display);
336         }
337         else {
338                 fprintf(db_out, "\n%*c%s%*c",
339                         indent,
340                         ' ',
341                         currlang->open_set_display,
342                         4-strlen(currlang->open_set_display), ' ');
343         }
344         indent += 4;
345         for (i = 0; i < nelements; i++) {
346                 if (get_int(addr + (i >> rsft), int_size, T_UNSIGNED) & (1 << (i & mask))) {
347                         count++;
348                         if (count > 1) {
349                                 if (compressed) {
350                                         fprintf(db_out, ", ...");
351                                         break;
352                                 }
353                                 fprintf(db_out, ",\n%*c", indent , ' ');
354                         }
355                         switch(base->ty_class) {
356                         case T_INTEGER:
357                                 print_integer(base, val+i, format);
358                                 break;
359                         case T_UNSIGNED:
360                                 print_unsigned(base, val+i, format);
361                                 break;
362                         case T_ENUM:
363                                 print_literal(base, val+i, compressed, format);
364                                 break;
365                         default:
366                                 assert(0);
367                         }
368                 } 
369         }
370         if (! compressed) {
371                 fprintf(db_out, "\n%*c", indent-4 , ' ');
372         }
373         indent -= 4;
374         fprintf(db_out, currlang->close_set_display);
375         }
376         break;
377   case T_REAL:
378         fprintf(db_out, currlang->real_fmt, get_real(addr, tp->ty_size));
379         break;
380   case T_UNSIGNED:
381         print_unsigned(tp, get_int(addr, tp_sz, T_UNSIGNED), format);
382         break;
383   case T_INTEGER:
384         print_integer(tp, get_int(addr, tp_sz, T_INTEGER), format);
385         break;
386   case T_STRING:
387         (*currlang->printstring)(db_out, addr, (int) tp_sz);
388         break;
389   default:
390         assert(0);
391         break;
392   }
393 }