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