Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / dumpidf.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: dumpidf.c,v 1.13 1994/06/27 07:59:26 ceriel Exp $ */
6 /*      DUMP ROUTINES   */
7
8 #include        "debug.h"
9
10 #ifdef  DEBUG
11 #include        <alloc.h>
12 #include        "nopp.h"
13 #include        "nobitfield.h"
14 #include        <flt_arith.h>
15 #include        "arith.h"
16 #include        "stack.h"
17 #include        "idf.h"
18 #include        "def.h"
19 #include        "type.h"
20 #include        "proto.h"
21 #include        "struct.h"
22 #include        "field.h"
23 #include        "Lpars.h"
24 #include        "label.h"
25 #include        "expr.h"
26 #include        "static.h"
27 #include        "declar.h"
28
29 /*      Some routines (symbol2str, type2str, qual2str) which should have
30  *      yielded strings are written to yield a pointer to a transient piece
31  *      of memory, containing the string, since this is the only reasonable
32  *      thing to do in C. `Transient' means that the result may soon
33  *      disappear, which is generally not a problem, since normally it is
34  *      consumed immediately. Sometimes we need more than one of them, and
35  *      MAXTRANS is the maximum number we will need simultaneously.
36  */
37 #define MAXTRANS        6
38
39 extern char options[];
40
41 extern char *sprint();
42
43 extern struct idf *idf_hashtable[];
44 extern char *symbol2str(), *type2str(), *qual2str(), *next_transient();
45
46 enum sdef_kind {selector, field};               /* parameter for dumpsdefs */
47
48 static int dumplevel;
49
50 newline()       {
51         register int dl = dumplevel;
52         
53         print("\n");
54         while (dl >= 2) {
55                 print("\t");
56                 dl -= 2;
57         }
58         if (dl)
59                 print("    ");
60 }
61
62 int     dumpidf();
63
64 dumpidftab(msg, opt)
65         char msg[];
66 {
67         /*      Dumps the identifier table in readable form (but in
68                 arbitrary order).
69                 Unless opt & 1, macros are not dumped.
70                 Unless opt & 2, reserved identifiers are not dumped.
71                 Unless opt & 4, universal identifiers are not dumped.
72         */
73
74         print(">>> DUMPIDF, %s (start)", msg);
75         dumpstack();
76         idfappfun(dumpidf, opt);
77         newline();
78         print(">>> DUMPIDF, %s (end)\n", msg);
79 }
80
81 dumpstack()
82 {
83         /*      Dumps the identifier stack, starting at the top.
84         */
85         register struct stack_level *stl = local_level;
86         
87         while (stl)     {
88                 register struct stack_entry *se = stl->sl_entry;
89                 
90                 newline();
91                 print("%3d: ", stl->sl_level);
92                 while (se)      {
93                         print("%s ", se->se_idf->id_text);
94                         se = se->next;
95                 }
96                 stl = stl->sl_previous;
97         }
98         print("\n");
99 }
100
101 dumpidf(idf, opt)
102         register struct idf *idf;
103 {
104         /*      All information about the identifier idf is divulged in a
105                 hopefully readable format.
106         */
107         int started = 0;
108         
109         if (!idf)
110                 return;
111 #ifndef NOPP
112         if ((opt&1) && idf->id_macro)   {
113                 if (!started++) {
114                         newline();
115                         print("%s:", idf->id_text);
116                 }
117                 print(" macro");
118         }
119 #endif /* NOPP */
120         if ((opt&2) && idf->id_reserved)        {
121                 if (!started++) {
122                         newline();
123                         print("%s:", idf->id_text);
124                 }
125                 print(" reserved: %d;", idf->id_reserved);
126         }
127         if (idf->id_def && ((opt&4) || idf->id_def->df_level))  {
128                 if (!started++) {
129                         newline();
130                         print("%s:", idf->id_text);
131                 }
132                 dumpdefs(idf->id_def, opt);
133         }
134         if (idf->id_sdef)       {
135                 if (!started++) {
136                         newline();
137                         print("%s:", idf->id_text);
138                 }
139                 dumpsdefs(idf->id_sdef, selector);
140         }
141         if (idf->id_tag)        {
142                 if (!started++) {
143                         newline();
144                         print("%s:", idf->id_text);
145                 }
146                 dumptags(idf->id_tag);
147         }
148 }
149
150 dumpdefs(def, opt)
151         register struct def *def;
152 {
153         dumplevel++;
154         while (def && ((opt&4) || def->df_level))       {
155                 newline();
156                 print("L%d: %s %s%stype%s %lo; ",
157                         def->df_level,
158                         symbol2str(def->df_sc),
159                         def->df_initialized ? "init'd " : "",
160                         def->df_used ? "used " : "",
161                         def->df_sc == ENUM ? ", =" : " at",
162                         def->df_address
163                 );
164                 print("%s, line %u",
165                         def->df_file ? def->df_file : "NO_FILE", def->df_line);
166                 dumptype(def->df_type);
167                 def = def->next;
168         }
169         dumplevel--;
170 }
171
172 dumptags(tag)
173         register struct tag *tag;
174 {
175         dumplevel++;
176         while (tag)     {
177                 register struct type *tp = tag->tg_type;
178                 register int fund = tp->tp_fund;
179
180                 newline();
181                 print("L%d: %s %s",
182                         tag->tg_level,
183                         fund == STRUCT ? "struct" :
184                         fund == UNION ? "union" :
185                         fund == ENUM ? "enum" : "<UNKNOWN>",
186                         tp->tp_idf->id_text
187                 );
188                 if (is_struct_or_union(fund))   {
189                         print(" {");
190                         dumpsdefs(tp->tp_sdef, field);
191                         newline();
192                         print("}");
193                 }
194                 print(";");
195                 tag = tag->next;
196         }
197         dumplevel--;
198 }
199
200 dumpsdefs(sdef, sdk)
201         register struct sdef *sdef;
202         enum sdef_kind sdk;
203 {
204         /*      Since sdef's are members of two chains, there are actually
205                 two dumpsdefs's, one following the chain of all selectors
206                 belonging to the same idf, starting at idf->id_sdef;
207                 and the other following the chain of all selectors belonging
208                 to the same struct, starting at stp->tp_sdef.
209         */
210
211         dumplevel++;
212         while (sdef)    {
213                 newline();
214                 print("L%d: ", sdef->sd_level);
215 #ifndef NOBITFIELD
216                 if (sdk == selector)
217 #endif /* NOBITFIELD */
218                         print("selector %s at offset %lu in %s;",
219                                 type2str(sdef->sd_type),
220                                 sdef->sd_offset, type2str(sdef->sd_stype)
221                         );
222 #ifndef NOBITFIELD
223                 else    print("field %s at offset %lu;",
224                                 type2str(sdef->sd_type), sdef->sd_offset
225                         );
226 #endif /* NOBITFIELD */
227                 sdef = (sdk == selector ? sdef->next : sdef->sd_sdef);
228         }
229         dumplevel--;
230 }
231
232 dumpproto(pl)
233         register struct proto *pl;
234 {
235         register struct type *type;
236         register int argcnt = 0;
237
238         newline();
239         print("dump proto type list (start)");
240         newline();
241         while (pl) {
242                 print("%d: %s", argcnt++,
243                         pl->pl_flag & PL_FORMAL ?
244                         (pl->pl_flag & PL_VOID ? "void" : "formal")
245                         : (pl->pl_flag & PL_ELLIPSIS
246                                 ? "ellipsis" : "unknown" ));
247                 newline();
248                 if (type = pl->pl_type){
249                         dumptype(type);
250                         newline();
251                 }
252                 if (pl->pl_idf) {
253                         dumplevel++;
254                         print("idf:");
255                         dumpidf(pl->pl_idf, 7);
256                         dumplevel--;
257                 }
258                 newline();
259                 pl = pl->next;
260         }
261         print("dump proto type list (end)\n");
262 }
263
264 dumptype(tp)
265         register struct type *tp;
266 {
267         int ops = 1;
268
269         dumplevel++;
270         newline();
271         if (!tp) {
272                 print("<NILTYPE>");
273                 newline();
274                 dumplevel--;
275                 return;
276         }
277
278         print("(@%lx, #%ld, &%d) ", tp, (long)tp->tp_size, tp->tp_align);
279
280         while (ops)     {
281                 print("%s", qual2str(tp->tp_typequal));
282                 switch (tp->tp_fund)    {
283                 case POINTER:
284                         print("pointer to ");
285                         break;
286                 case ARRAY:
287                         print("array [%ld] of ", tp->tp_size);
288                         break;
289                 case FUNCTION:
290                         print("function ");
291                         if (tp->tp_proto) {
292                                 print("with prototype");
293                                 dumplevel++;
294                                 dumpproto(tp->tp_proto);
295                                 dumplevel--;
296                                 newline();
297                         }
298                         print("yielding ");
299                         break;
300                 default:
301                         print("%s%s ", tp->tp_unsigned ? "unsigned " : "",
302                                        symbol2str(tp->tp_fund));
303                         if (tp->tp_idf)
304                                 print("%s ", tp->tp_idf->id_text);
305 #ifndef NOBITFIELD
306                         if (tp->tp_fund == FIELD && tp->tp_field)       {
307                                 struct field *fd = tp->tp_field;
308                                 
309                                 print("[s=%ld,w=%ld] of ",
310                                         fd->fd_shift, fd->fd_width);
311                         }
312                         else
313 #endif /* NOBITFIELD */
314                         ops = 0;
315                         break;
316                 }
317                 if (ops) tp = tp->tp_up;
318         }
319         dumplevel--;
320 }
321
322 char *
323 type2str(tp)
324         register struct type *tp;
325 {
326         /*      Yields a pointer to a one-line description of the type tp.
327         */
328         char *buf = next_transient();
329         int ops = 1;
330
331         buf[0] = '\0';
332         if (!tp)        {
333                 sprint(buf, "<NILTYPE>");
334                 return buf;
335         }
336         sprint(buf, "%s(@%lx, #%ld, &%d) ",
337                         buf, tp, (long)tp->tp_size, tp->tp_align);
338
339         while (ops)     {
340                 sprint(buf, "%s%s", buf, qual2str(tp->tp_typequal));
341                 switch (tp->tp_fund)    {
342                 case POINTER:
343                         sprint(buf, "%spointer to ", buf);
344                         break;
345                 case ARRAY:
346                         sprint(buf, "%sarray [%ld] of ", buf, tp->tp_size);
347                         break;
348                 case FUNCTION:
349                         sprint(buf, "%sfunction yielding ", buf);
350                         break;
351                 default:
352                         sprint(buf, "%s%s%s ", buf,
353                                         tp->tp_unsigned ? "unsigned " : "",
354                                         symbol2str(tp->tp_fund)
355                         );
356                         if (tp->tp_idf)
357                                 sprint(buf, "%s %s ", buf,
358                                         tp->tp_idf->id_text);
359 #ifndef NOBITFIELD
360                         if (tp->tp_fund == FIELD && tp->tp_field)       {
361                                 struct field *fd = tp->tp_field;
362                                 
363                                 sprint(buf, "%s [s=%ld,w=%ld] of ", buf,
364                                         fd->fd_shift, fd->fd_width);
365                         }
366                         else
367 #endif /* NOBITFIELD */
368                         ops = 0;
369                         break;
370                 }
371                 if (ops) tp = tp->tp_up;
372         }
373         return buf;
374 }
375
376 char *
377 qual2str(qual)
378         int qual;
379 {
380         char *buf = next_transient();
381
382         *buf = '\0';
383         if (qual == 0)
384                 sprint(buf, "(none)");
385         if (qual & TQ_CONST)
386                 sprint(buf, "%sconst ", buf);
387         if (qual & TQ_VOLATILE)
388                 sprint(buf, "%svolatile ", buf);
389
390         return qual == 0 ? "" : buf;
391 }
392
393 GSTATIC char trans_buf[MAXTRANS][300];
394
395 char *          /* the ultimate transient buffer supplier */
396 next_transient()
397 {
398         static int bnum;
399
400         if (++bnum == MAXTRANS)
401                 bnum = 0;
402         return trans_buf[bnum];
403 }
404
405 print_expr(msg, expr)
406         char msg[];
407         struct expr *expr;
408 {
409         /*      Provisional routine to print an expression preceded by a
410                 message msg.
411         */
412         if (options['x'])       {
413                 print("\n%s: ", msg);
414                 print("(L=line, T=type, r/lV=r/lvalue, F=flags, D=depth)\n");
415                 p1_expr(0, expr);
416         }
417 }
418
419 p1_expr(lvl, expr)
420         register struct expr *expr;
421 {
422         p1_indent(lvl);
423         if (!expr)      {
424                 print("NILEXPR\n");
425                 return;
426         }
427         print("expr: L=%u, T=%s, %cV, F=%03o, D=%d, %s: ",
428                 expr->ex_line,
429                 type2str(expr->ex_type),
430                 expr->ex_lvalue ? 'l' : 'r',
431                 expr->ex_flags & 0xFF,
432                 expr->ex_depth,
433                 expr->ex_class == Value ? "Value" :
434                 expr->ex_class == String ? "String" :
435                 expr->ex_class == Float ? "Float" :
436                 expr->ex_class == Oper ? "Oper" :
437                 expr->ex_class == Type ? "Type" : "UNKNOWN CLASS"
438         );
439         switch (expr->ex_class) {
440                 struct oper *o;
441         case Value:
442                 switch (expr->VL_CLASS) {
443                 case Const:
444                         print("(Const) ");
445                         break;
446                 case Name:
447                         print("(Name) %s + ", expr->VL_IDF->id_text);
448                         break;
449                 case Label:
450                         print("(Label) .%lu + ", expr->VL_LBL);
451                         break;
452                 default:
453                         print("(Unknown) ");
454                         break;
455                 }
456                 print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n",
457                         expr->VL_VALUE);
458                 break;
459         case String:
460         {
461                 char *bts2str();
462
463                 print(
464                         "\"%s\"\n",
465                         bts2str(expr->SG_VALUE, expr->SG_LEN-1,
466                                                         next_transient())
467                 );
468                 break;
469         }
470         case Float:
471         {
472                 char buf[FLT_STRLEN];
473
474                 flt_flt2str(&(expr->FL_ARITH), buf, FLT_STRLEN);
475                 print("%s\n", buf);
476                 break;
477         }
478         case Oper:
479                 o = &expr->ex_object.ex_oper;
480                 print("\n");
481                 p1_expr(lvl+1, o->op_left);
482                 p1_indent(lvl);
483                 print("%s <%s>\n", symbol2str(o->op_oper),
484                         type2str(o->op_type)
485                 );
486                 p1_expr(lvl+1, o->op_right);
487                 break;
488         case Type:
489                 print("\n");
490                 break;
491         default:
492                 print("UNKNOWN CLASS\n");
493                 break;
494         }
495 }
496
497 p1_indent(lvl)
498         register int lvl;
499 {
500         while (lvl--)
501                 print("  ");
502 }
503 #endif  /* DEBUG */