OSDN Git Service

* emit-rtl.c (reg_attrs_htab): New static variable.
[pf3gnuchains/gcc-fork.git] / gcc / gengtype.c
1 /* Process source files and output type information.
2    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.  */
20
21 #include "bconfig.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "gengtype.h"
26 #include "gtyp-gen.h"
27
28 /* Nonzero iff an error has occurred.  */
29 static int hit_error = 0;
30
31 static void gen_rtx_next PARAMS ((void));
32 static void write_rtx_next PARAMS ((void));
33 static void open_base_files PARAMS ((void));
34 static void close_output_files PARAMS ((void));
35
36 /* Report an error at POS, printing MSG.  */
37
38 void
39 error_at_line VPARAMS ((struct fileloc *pos, const char *msg, ...))
40 {
41   VA_OPEN (ap, msg);
42   VA_FIXEDARG (ap, struct fileloc *, pos);
43   VA_FIXEDARG (ap, const char *, msg);
44
45   fprintf (stderr, "%s:%d: ", pos->file, pos->line);
46   vfprintf (stderr, msg, ap);
47   fputc ('\n', stderr);
48   hit_error = 1;
49
50   VA_CLOSE (ap);
51 }
52
53 /* vasprintf, but produces fatal message on out-of-memory.  */
54 int
55 xvasprintf (result, format, args)
56      char ** result;
57      const char *format;
58      va_list args;
59 {
60   int ret = vasprintf (result, format, args);
61   if (*result == NULL || ret < 0)
62     {
63       fputs ("gengtype: out of memory", stderr);
64       xexit (1);
65     }
66   return ret;
67 }
68
69 /* Wrapper for xvasprintf.  */
70 char *
71 xasprintf VPARAMS ((const char *format, ...))
72 {
73   char *result;
74   VA_OPEN (ap, format);
75   VA_FIXEDARG (ap, const char *, format);
76   xvasprintf (&result, format, ap);
77   VA_CLOSE (ap);
78   return result;
79 }
80
81 /* The one and only TYPE_STRING.  */
82
83 struct type string_type = {
84   TYPE_STRING, NULL, NULL, GC_USED
85   UNION_INIT_ZERO
86 }; 
87
88 /* Lists of various things.  */
89
90 static pair_p typedefs;
91 static type_p structures;
92 static type_p param_structs;
93 static pair_p variables;
94
95 static void do_scalar_typedef PARAMS ((const char *, struct fileloc *));
96 static type_p find_param_structure 
97   PARAMS ((type_p t, type_p param[NUM_PARAM]));
98 static type_p adjust_field_tree_exp PARAMS ((type_p t, options_p opt));
99 static type_p adjust_field_rtx_def PARAMS ((type_p t, options_p opt));
100
101 /* Define S as a typedef to T at POS.  */
102
103 void
104 do_typedef (s, t, pos)
105      const char *s;
106      type_p t;
107      struct fileloc *pos;
108 {
109   pair_p p;
110
111   for (p = typedefs; p != NULL; p = p->next)
112     if (strcmp (p->name, s) == 0)
113       {
114         if (p->type != t)
115           {
116             error_at_line (pos, "type `%s' previously defined", s);
117             error_at_line (&p->line, "previously defined here");
118           }
119         return;
120       }
121
122   p = xmalloc (sizeof (struct pair));
123   p->next = typedefs;
124   p->name = s;
125   p->type = t;
126   p->line = *pos;
127   typedefs = p;
128 }
129
130 /* Define S as a typename of a scalar.  */
131
132 static void
133 do_scalar_typedef (s, pos)
134      const char *s;
135      struct fileloc *pos;
136 {
137   do_typedef (s, create_scalar_type (s, strlen (s)), pos);
138 }
139
140 /* Return the type previously defined for S.  Use POS to report errors.  */
141
142 type_p
143 resolve_typedef (s, pos)
144      const char *s;
145      struct fileloc *pos;
146 {
147   pair_p p;
148   for (p = typedefs; p != NULL; p = p->next)
149     if (strcmp (p->name, s) == 0)
150       return p->type;
151   error_at_line (pos, "unidentified type `%s'", s);
152   return create_scalar_type ("char", 4);
153 }
154
155 /* Create a new structure with tag NAME (or a union iff ISUNION is nonzero),
156    at POS with fields FIELDS and options O.  */
157
158 void
159 new_structure (name, isunion, pos, fields, o)
160      const char *name;
161      int isunion;
162      struct fileloc *pos;
163      pair_p fields;
164      options_p o;
165 {
166   type_p si;
167   type_p s = NULL;
168   lang_bitmap bitmap = get_base_file_bitmap (pos->file);
169
170   for (si = structures; si != NULL; si = si->next)
171     if (strcmp (name, si->u.s.tag) == 0 
172         && UNION_P (si) == isunion)
173       {
174         type_p ls = NULL;
175         if (si->kind == TYPE_LANG_STRUCT)
176           {
177             ls = si;
178             
179             for (si = ls->u.s.lang_struct; si != NULL; si = si->next)
180               if (si->u.s.bitmap == bitmap)
181                 s = si;
182           }
183         else if (si->u.s.line.file != NULL && si->u.s.bitmap != bitmap)
184           {
185             ls = si;
186             si = xcalloc (1, sizeof (struct type));
187             memcpy (si, ls, sizeof (struct type));
188             ls->kind = TYPE_LANG_STRUCT;
189             ls->u.s.lang_struct = si;
190             ls->u.s.fields = NULL;
191             si->next = NULL;
192             si->pointer_to = NULL;
193             si->u.s.lang_struct = ls;
194           }
195         else
196           s = si;
197
198         if (ls != NULL && s == NULL)
199           {
200             s = xcalloc (1, sizeof (struct type));
201             s->next = ls->u.s.lang_struct;
202             ls->u.s.lang_struct = s;
203             s->u.s.lang_struct = ls;
204           }
205         break;
206       }
207   
208   if (s == NULL)
209     {
210       s = xcalloc (1, sizeof (struct type));
211       s->next = structures;
212       structures = s;
213     }
214
215   if (s->u.s.line.file != NULL
216       || (s->u.s.lang_struct && (s->u.s.lang_struct->u.s.bitmap & bitmap)))
217     {
218       error_at_line (pos, "duplicate structure definition");
219       error_at_line (&s->u.s.line, "previous definition here");
220     }
221
222   s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
223   s->u.s.tag = name;
224   s->u.s.line = *pos;
225   s->u.s.fields = fields;
226   s->u.s.opt = o;
227   s->u.s.bitmap = bitmap;
228   if (s->u.s.lang_struct)
229     s->u.s.lang_struct->u.s.bitmap |= bitmap;
230 }
231
232 /* Return the previously-defined structure with tag NAME (or a union
233    iff ISUNION is nonzero), or a new empty structure or union if none
234    was defined previously.  */
235
236 type_p
237 find_structure (name, isunion)
238      const char *name;
239      int isunion;
240 {
241   type_p s;
242
243   for (s = structures; s != NULL; s = s->next)
244     if (strcmp (name, s->u.s.tag) == 0 
245         && UNION_P (s) == isunion)
246       return s;
247
248   s = xcalloc (1, sizeof (struct type));
249   s->next = structures;
250   structures = s;
251   s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
252   s->u.s.tag = name;
253   structures = s;
254   return s;
255 }
256
257 /* Return the previously-defined parameterized structure for structure
258    T and parameters PARAM, or a new parameterized empty structure or
259    union if none was defined previously.  */
260
261 static type_p
262 find_param_structure (t, param)
263      type_p t;
264      type_p param[NUM_PARAM];
265 {
266   type_p res;
267   
268   for (res = param_structs; res; res = res->next)
269     if (res->u.param_struct.stru == t
270         && memcmp (res->u.param_struct.param, param, 
271                    sizeof (type_p) * NUM_PARAM) == 0)
272       break;
273   if (res == NULL)
274     {
275       res = xcalloc (1, sizeof (*res));
276       res->kind = TYPE_PARAM_STRUCT;
277       res->next = param_structs;
278       param_structs = res;
279       res->u.param_struct.stru = t;
280       memcpy (res->u.param_struct.param, param, sizeof (type_p) * NUM_PARAM);
281     }
282   return res;
283 }
284
285 /* Return a scalar type with name NAME.  */
286
287 type_p
288 create_scalar_type (name, name_len)
289      const char *name;
290      size_t name_len;
291 {
292   type_p r = xcalloc (1, sizeof (struct type));
293   r->kind = TYPE_SCALAR;
294   r->u.sc = xmemdup (name, name_len, name_len + 1);
295   return r;
296 }
297
298 /* Return a pointer to T.  */
299
300 type_p
301 create_pointer (t)
302      type_p t;
303 {
304   if (! t->pointer_to)
305     {
306       type_p r = xcalloc (1, sizeof (struct type));
307       r->kind = TYPE_POINTER;
308       r->u.p = t;
309       t->pointer_to = r;
310     }
311   return t->pointer_to;
312 }
313
314 /* Return an array of length LEN.  */
315
316 type_p
317 create_array (t, len)
318      type_p t;
319      const char *len;
320 {
321   type_p v;
322   
323   v = xcalloc (1, sizeof (*v));
324   v->kind = TYPE_ARRAY;
325   v->u.a.p = t;
326   v->u.a.len = len;
327   return v;
328 }
329
330 /* Add a variable named S of type T with options O defined at POS,
331    to `variables'.  */
332
333 void
334 note_variable (s, t, o, pos)
335      const char *s;
336      type_p t;
337      options_p o;
338      struct fileloc *pos;
339 {
340   pair_p n;
341   n = xmalloc (sizeof (*n));
342   n->name = s;
343   n->type = t;
344   n->line = *pos;
345   n->opt = o;
346   n->next = variables;
347   variables = n;
348 }
349
350 enum rtx_code {
351 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   ENUM ,
352 #include "rtl.def"
353 #undef DEF_RTL_EXPR
354     NUM_RTX_CODE
355 };
356
357 /* We really don't care how long a CONST_DOUBLE is.  */
358 #define CONST_DOUBLE_FORMAT "ww"
359 static const char * const rtx_format[NUM_RTX_CODE] = {
360 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
361 #include "rtl.def"
362 #undef DEF_RTL_EXPR
363 };
364
365 static int rtx_next[NUM_RTX_CODE];
366
367 /* Generate the contents of the rtx_next array.  This really doesn't belong
368    in gengtype at all, but it's needed for adjust_field_rtx_def.  */
369
370 static void
371 gen_rtx_next ()
372 {
373   int i;
374   for (i = 0; i < NUM_RTX_CODE; i++)
375     {
376       int k;
377       
378       rtx_next[i] = -1;
379       if (strncmp (rtx_format[i], "iuu", 3) == 0)
380         rtx_next[i] = 2;
381       else if (i == COND_EXEC || i == SET || i == EXPR_LIST || i == INSN_LIST)
382         rtx_next[i] = 1;
383       else 
384         for (k = strlen (rtx_format[i]) - 1; k >= 0; k--)
385           if (rtx_format[i][k] == 'e' || rtx_format[i][k] == 'u')
386             rtx_next[i] = k;
387     }
388 }
389
390 /* Write out the contents of the rtx_next array.  */
391 static void
392 write_rtx_next ()
393 {
394   outf_p f = get_output_file_with_visibility (NULL);
395   int i;
396   
397   oprintf (f, "\n/* Used to implement the RTX_NEXT macro.  */\n");
398   oprintf (f, "const unsigned char rtx_next[NUM_RTX_CODE] = {\n");
399   for (i = 0; i < NUM_RTX_CODE; i++)
400     if (rtx_next[i] == -1)
401       oprintf (f, "  0,\n");
402     else
403       oprintf (f, 
404                "  offsetof (struct rtx_def, fld) + %d * sizeof (rtunion),\n",
405                rtx_next[i]);
406   oprintf (f, "};\n");
407 }
408
409 /* Handle `special("rtx_def")'.  This is a special case for field
410    `fld' of struct rtx_def, which is an array of unions whose values
411    are based in a complex way on the type of RTL.  */
412
413 static type_p
414 adjust_field_rtx_def (t, opt)
415      type_p t;
416      options_p opt ATTRIBUTE_UNUSED;
417 {
418   pair_p flds = NULL;
419   options_p nodot;
420   int i;
421   type_p rtx_tp, rtvec_tp, tree_tp, mem_attrs_tp, note_union_tp, scalar_tp;
422   type_p bitmap_tp, basic_block_tp, reg_attrs_tp;
423
424   static const char * const rtx_name[NUM_RTX_CODE] = {
425 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   NAME ,
426 #include "rtl.def"
427 #undef DEF_RTL_EXPR
428   };
429   
430   if (t->kind != TYPE_ARRAY)
431     {
432       error_at_line (&lexer_line, 
433                      "special `rtx_def' must be applied to an array");
434       return &string_type;
435     }
436   
437   nodot = xmalloc (sizeof (*nodot));
438   nodot->next = NULL;
439   nodot->name = "dot";
440   nodot->info = "";
441
442   rtx_tp = create_pointer (find_structure ("rtx_def", 0));
443   rtvec_tp = create_pointer (find_structure ("rtvec_def", 0));
444   tree_tp = create_pointer (find_structure ("tree_node", 1));
445   mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0));
446   reg_attrs_tp = create_pointer (find_structure ("reg_attrs", 0));
447   bitmap_tp = create_pointer (find_structure ("bitmap_element_def", 0));
448   basic_block_tp = create_pointer (find_structure ("basic_block_def", 0));
449   scalar_tp = create_scalar_type ("rtunion scalar", 14);
450
451   {
452     pair_p note_flds = NULL;
453     int c;
454     
455     for (c = 0; c < 3; c++)
456       {
457         pair_p old_note_flds = note_flds;
458         
459         note_flds = xmalloc (sizeof (*note_flds));
460         note_flds->line.file = __FILE__;
461         note_flds->line.line = __LINE__;
462         note_flds->name = "rttree";
463         note_flds->type = tree_tp;
464         note_flds->opt = xmalloc (sizeof (*note_flds->opt));
465         note_flds->opt->next = nodot;
466         note_flds->opt->name = "tag";
467         note_flds->next = old_note_flds;
468       }
469     
470     note_flds->type = rtx_tp;
471     note_flds->name = "rtx";
472     note_flds->opt->info = "NOTE_INSN_EXPECTED_VALUE";
473     note_flds->next->opt->info = "NOTE_INSN_BLOCK_BEG";
474     note_flds->next->next->opt->info = "NOTE_INSN_BLOCK_END";
475     
476     new_structure ("rtx_def_note_subunion", 1, &lexer_line, note_flds, NULL);
477   }
478   
479   note_union_tp = find_structure ("rtx_def_note_subunion", 1);
480
481   for (i = 0; i < NUM_RTX_CODE; i++)
482     {
483       pair_p old_flds = flds;
484       pair_p subfields = NULL;
485       size_t aindex, nmindex;
486       const char *sname;
487       char *ftag;
488
489       for (aindex = 0; aindex < strlen (rtx_format[i]); aindex++)
490         {
491           pair_p old_subf = subfields;
492           type_p t;
493           const char *subname;
494
495           switch (rtx_format[i][aindex])
496             {
497             case '*':
498             case 'i':
499             case 'n':
500             case 'w':
501               t = scalar_tp;
502               subname = "rtint";
503               break;
504
505             case '0':
506               if (i == MEM && aindex == 1)
507                 t = mem_attrs_tp, subname = "rtmem";
508               else if (i == JUMP_INSN && aindex == 9)
509                 t = rtx_tp, subname = "rtx";
510               else if (i == CODE_LABEL && aindex == 4)
511                 t = scalar_tp, subname = "rtint";
512               else if (i == CODE_LABEL && aindex == 5)
513                 t = rtx_tp, subname = "rtx";
514               else if (i == LABEL_REF
515                        && (aindex == 1 || aindex == 2))
516                 t = rtx_tp, subname = "rtx";
517               else if (i == NOTE && aindex == 4)
518                 t = note_union_tp, subname = "";
519               else if (i == NOTE && aindex >= 7)
520                 t = scalar_tp, subname = "rtint";
521               else if (i == ADDR_DIFF_VEC && aindex == 4)
522                 t = scalar_tp, subname = "rtint";
523               else if (i == VALUE && aindex == 0)
524                 t = scalar_tp, subname = "rtint";
525               else if (i == REG && aindex == 1)
526                 t = scalar_tp, subname = "rtint";
527               else if (i == REG && aindex == 2)
528                 t = reg_attrs_tp, subname = "rtreg";
529               else if (i == SCRATCH && aindex == 0)
530                 t = scalar_tp, subname = "rtint";
531               else if (i == BARRIER && aindex >= 3)
532                 t = scalar_tp, subname = "rtint";
533               else
534                 {
535                   error_at_line (&lexer_line, 
536                         "rtx type `%s' has `0' in position %lu, can't handle",
537                                  rtx_name[i], (unsigned long) aindex);
538                   t = &string_type;
539                   subname = "rtint";
540                 }
541               break;
542               
543             case 's':
544             case 'S':
545             case 'T':
546               t = &string_type;
547               subname = "rtstr";
548               break;
549
550             case 'e':
551             case 'u':
552               t = rtx_tp;
553               subname = "rtx";
554               break;
555
556             case 'E':
557             case 'V':
558               t = rtvec_tp;
559               subname = "rtvec";
560               break;
561
562             case 't':
563               t = tree_tp;
564               subname = "rttree";
565               break;
566
567             case 'b':
568               t = bitmap_tp;
569               subname = "rtbit";
570               break;
571
572             case 'B':
573               t = basic_block_tp;
574               subname = "bb";
575               break;
576
577             default:
578               error_at_line (&lexer_line, 
579                      "rtx type `%s' has `%c' in position %lu, can't handle",
580                              rtx_name[i], rtx_format[i][aindex],
581                              (unsigned long)aindex);
582               t = &string_type;
583               subname = "rtint";
584               break;
585             }
586
587           subfields = xmalloc (sizeof (*subfields));
588           subfields->next = old_subf;
589           subfields->type = t;
590           subfields->name = xasprintf ("[%lu].%s", (unsigned long)aindex,
591                                        subname);
592           subfields->line.file = __FILE__;
593           subfields->line.line = __LINE__;
594           if (t == note_union_tp)
595             {
596               subfields->opt = xmalloc (sizeof (*subfields->opt));
597               subfields->opt->next = nodot;
598               subfields->opt->name = "desc";
599               subfields->opt->info = "NOTE_LINE_NUMBER (&%0)";
600             }
601           else if (t == basic_block_tp)
602             {
603               /* We don't presently GC basic block structures...  */
604               subfields->opt = xmalloc (sizeof (*subfields->opt));
605               subfields->opt->next = nodot;
606               subfields->opt->name = "skip";
607               subfields->opt->info = NULL;
608             }
609           else
610             subfields->opt = nodot;
611         }
612
613       flds = xmalloc (sizeof (*flds));
614       flds->next = old_flds;
615       flds->name = "";
616       sname = xasprintf ("rtx_def_%s", rtx_name[i]);
617       new_structure (sname, 0, &lexer_line, subfields, NULL);
618       flds->type = find_structure (sname, 0);
619       flds->line.file = __FILE__;
620       flds->line.line = __LINE__;
621       flds->opt = xmalloc (sizeof (*flds->opt));
622       flds->opt->next = nodot;
623       flds->opt->name = "tag";
624       ftag = xstrdup (rtx_name[i]);
625       for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
626         ftag[nmindex] = TOUPPER (ftag[nmindex]);
627       flds->opt->info = ftag;
628     }
629
630   new_structure ("rtx_def_subunion", 1, &lexer_line, flds, nodot);
631   return find_structure ("rtx_def_subunion", 1);
632 }
633
634 /* Handle `special("tree_exp")'.  This is a special case for
635    field `operands' of struct tree_exp, which although it claims to contain
636    pointers to trees, actually sometimes contains pointers to RTL too.  
637    Passed T, the old type of the field, and OPT its options.  Returns
638    a new type for the field.  */
639
640 static type_p
641 adjust_field_tree_exp (t, opt)
642      type_p t;
643      options_p opt ATTRIBUTE_UNUSED;
644 {
645   pair_p flds;
646   options_p nodot;
647   size_t i;
648   static const struct {
649     const char *name;
650     int first_rtl;
651     int num_rtl;
652   } data[] = {
653     { "SAVE_EXPR", 2, 1 },
654     { "GOTO_SUBROUTINE_EXPR", 0, 2 },
655     { "RTL_EXPR", 0, 2 },
656     { "WITH_CLEANUP_EXPR", 2, 1 },
657     { "METHOD_CALL_EXPR", 3, 1 }
658   };
659   
660   if (t->kind != TYPE_ARRAY)
661     {
662       error_at_line (&lexer_line, 
663                      "special `tree_exp' must be applied to an array");
664       return &string_type;
665     }
666   
667   nodot = xmalloc (sizeof (*nodot));
668   nodot->next = NULL;
669   nodot->name = "dot";
670   nodot->info = "";
671
672   flds = xmalloc (sizeof (*flds));
673   flds->next = NULL;
674   flds->name = "";
675   flds->type = t;
676   flds->line.file = __FILE__;
677   flds->line.line = __LINE__;
678   flds->opt = xmalloc (sizeof (*flds->opt));
679   flds->opt->next = nodot;
680   flds->opt->name = "length";
681   flds->opt->info = "TREE_CODE_LENGTH (TREE_CODE ((tree) &%0))";
682   {
683     options_p oldopt = flds->opt;
684     flds->opt = xmalloc (sizeof (*flds->opt));
685     flds->opt->next = oldopt;
686     flds->opt->name = "default";
687     flds->opt->info = "";
688   }
689   
690   for (i = 0; i < ARRAY_SIZE (data); i++)
691     {
692       pair_p old_flds = flds;
693       pair_p subfields = NULL;
694       int r_index;
695       const char *sname;
696       
697       for (r_index = 0; 
698            r_index < data[i].first_rtl + data[i].num_rtl; 
699            r_index++)
700         {
701           pair_p old_subf = subfields;
702           subfields = xmalloc (sizeof (*subfields));
703           subfields->next = old_subf;
704           subfields->name = xasprintf ("[%d]", r_index);
705           if (r_index < data[i].first_rtl)
706             subfields->type = t->u.a.p;
707           else
708             subfields->type = create_pointer (find_structure ("rtx_def", 0));
709           subfields->line.file = __FILE__;
710           subfields->line.line = __LINE__;
711           subfields->opt = nodot;
712         }
713
714       flds = xmalloc (sizeof (*flds));
715       flds->next = old_flds;
716       flds->name = "";
717       sname = xasprintf ("tree_exp_%s", data[i].name);
718       new_structure (sname, 0, &lexer_line, subfields, NULL);
719       flds->type = find_structure (sname, 0);
720       flds->line.file = __FILE__;
721       flds->line.line = __LINE__;
722       flds->opt = xmalloc (sizeof (*flds->opt));
723       flds->opt->next = nodot;
724       flds->opt->name = "tag";
725       flds->opt->info = data[i].name;
726     }
727
728   new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot);
729   return find_structure ("tree_exp_subunion", 1);
730 }
731
732 /* Perform any special processing on a type T, about to become the type
733    of a field.  Return the appropriate type for the field.
734    At present:
735    - Converts pointer-to-char, with no length parameter, to TYPE_STRING;
736    - Similarly for arrays of pointer-to-char;
737    - Converts structures for which a parameter is provided to
738      TYPE_PARAM_STRUCT;
739    - Handles "special" options.
740 */   
741
742 type_p
743 adjust_field_type (t, opt)
744      type_p t;
745      options_p opt;
746 {
747   int length_p = 0;
748   const int pointer_p = t->kind == TYPE_POINTER;
749   type_p params[NUM_PARAM];
750   int params_p = 0;
751   int i;
752
753   for (i = 0; i < NUM_PARAM; i++)
754     params[i] = NULL;
755   
756   for (; opt; opt = opt->next)
757     if (strcmp (opt->name, "length") == 0)
758       length_p = 1;
759     else if (strcmp (opt->name, "param_is") == 0
760              || (strncmp (opt->name, "param", 5) == 0
761                  && ISDIGIT (opt->name[5])
762                  && strcmp (opt->name + 6, "_is") == 0))
763       {
764         int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0;
765
766         if (! UNION_OR_STRUCT_P (t)
767             && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
768           {
769             error_at_line (&lexer_line, 
770    "option `%s' may only be applied to structures or structure pointers",
771                            opt->name);
772             return t;
773           }
774
775         params_p = 1;
776         if (params[num] != NULL)
777           error_at_line (&lexer_line, "duplicate `%s' option", opt->name);
778         if (! ISDIGIT (opt->name[5]))
779           params[num] = create_pointer ((type_p) opt->info);
780         else
781           params[num] = (type_p) opt->info;
782       }
783     else if (strcmp (opt->name, "special") == 0)
784       {
785         const char *special_name = (const char *)opt->info;
786         if (strcmp (special_name, "tree_exp") == 0)
787           t = adjust_field_tree_exp (t, opt);
788         else if (strcmp (special_name, "rtx_def") == 0)
789           t = adjust_field_rtx_def (t, opt);
790         else
791           error_at_line (&lexer_line, "unknown special `%s'", special_name);
792       }
793
794   if (params_p)
795     {
796       type_p realt;
797       
798       if (pointer_p)
799         t = t->u.p;
800       realt = find_param_structure (t, params);
801       t = pointer_p ? create_pointer (realt) : realt;
802     }
803
804   if (! length_p
805       && pointer_p
806       && t->u.p->kind == TYPE_SCALAR
807       && (strcmp (t->u.p->u.sc, "char") == 0
808           || strcmp (t->u.p->u.sc, "unsigned char") == 0))
809     return &string_type;
810   if (t->kind == TYPE_ARRAY && t->u.a.p->kind == TYPE_POINTER
811       && t->u.a.p->u.p->kind == TYPE_SCALAR
812       && (strcmp (t->u.a.p->u.p->u.sc, "char") == 0
813           || strcmp (t->u.a.p->u.p->u.sc, "unsigned char") == 0))
814     return create_array (&string_type, t->u.a.len);
815
816   return t;
817 }
818
819 /* Create a union for YYSTYPE, as yacc would do it, given a fieldlist FIELDS
820    and information about the correspondence between token types and fields
821    in TYPEINFO.  POS is used for error messages.  */
822
823 void
824 note_yacc_type (o, fields, typeinfo, pos)
825      options_p o;
826      pair_p fields;
827      pair_p typeinfo;
828      struct fileloc *pos;
829 {
830   pair_p p;
831   pair_p *p_p;
832   
833   for (p = typeinfo; p; p = p->next)
834     {
835       pair_p m;
836       
837       if (p->name == NULL)
838         continue;
839
840       if (p->type == (type_p) 1)
841         {
842           pair_p pp;
843           int ok = 0;
844           
845           for (pp = typeinfo; pp; pp = pp->next)
846             if (pp->type != (type_p) 1
847                 && strcmp (pp->opt->info, p->opt->info) == 0)
848               {
849                 ok = 1;
850                 break;
851               }
852           if (! ok)
853             continue;
854         }
855
856       for (m = fields; m; m = m->next)
857         if (strcmp (m->name, p->name) == 0)
858           p->type = m->type;
859       if (p->type == NULL)
860         {
861           error_at_line (&p->line, 
862                          "couldn't match fieldname `%s'", p->name);
863           p->name = NULL;
864         }
865     }
866   
867   p_p = &typeinfo;
868   while (*p_p)
869     {
870       pair_p p = *p_p;
871
872       if (p->name == NULL
873           || p->type == (type_p) 1)
874         *p_p = p->next;
875       else
876         p_p = &p->next;
877     }
878
879   new_structure ("yy_union", 1, pos, typeinfo, o);
880   do_typedef ("YYSTYPE", find_structure ("yy_union", 1), pos);
881 }
882 \f
883 static void process_gc_options PARAMS ((options_p, enum gc_used_enum, 
884                                         int *, int *, int *));
885 static void set_gc_used_type PARAMS ((type_p, enum gc_used_enum, type_p *));
886 static void set_gc_used PARAMS ((pair_p));
887
888 /* Handle OPT for set_gc_used_type.  */
889
890 static void
891 process_gc_options (opt, level, maybe_undef, pass_param, length)
892      options_p opt;
893      enum gc_used_enum level;
894      int *maybe_undef;
895      int *pass_param;
896      int *length;
897 {
898   options_p o;
899   for (o = opt; o; o = o->next)
900     if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO)
901       set_gc_used_type ((type_p) o->info, GC_POINTED_TO, NULL);
902     else if (strcmp (o->name, "maybe_undef") == 0)
903       *maybe_undef = 1;
904     else if (strcmp (o->name, "use_params") == 0)
905       *pass_param = 1;
906     else if (strcmp (o->name, "length") == 0)
907       *length = 1;
908 }
909
910 /* Set the gc_used field of T to LEVEL, and handle the types it references.  */
911
912 static void
913 set_gc_used_type (t, level, param)
914      type_p t;
915      enum gc_used_enum level;
916      type_p param[NUM_PARAM];
917 {
918   if (t->gc_used >= level)
919     return;
920   
921   t->gc_used = level;
922
923   switch (t->kind)
924     {
925     case TYPE_STRUCT:
926     case TYPE_UNION:
927       {
928         pair_p f;
929         int dummy;
930
931         process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy);
932
933         for (f = t->u.s.fields; f; f = f->next)
934           {
935             int maybe_undef = 0;
936             int pass_param = 0;
937             int length = 0;
938             process_gc_options (f->opt, level, &maybe_undef, &pass_param,
939                                 &length);
940             
941             if (length && f->type->kind == TYPE_POINTER)
942               set_gc_used_type (f->type->u.p, GC_USED, NULL);
943             else if (maybe_undef && f->type->kind == TYPE_POINTER)
944               set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO, NULL);
945             else if (pass_param && f->type->kind == TYPE_POINTER && param)
946               set_gc_used_type (find_param_structure (f->type->u.p, param),
947                                 GC_POINTED_TO, NULL);
948             else
949               set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
950           }
951         break;
952       }
953
954     case TYPE_POINTER:
955       set_gc_used_type (t->u.p, GC_POINTED_TO, NULL);
956       break;
957
958     case TYPE_ARRAY:
959       set_gc_used_type (t->u.a.p, GC_USED, param);
960       break;
961       
962     case TYPE_LANG_STRUCT:
963       for (t = t->u.s.lang_struct; t; t = t->next)
964         set_gc_used_type (t, level, param);
965       break;
966
967     case TYPE_PARAM_STRUCT:
968       {
969         int i;
970         for (i = 0; i < NUM_PARAM; i++)
971           if (t->u.param_struct.param[i] != 0)
972             set_gc_used_type (t->u.param_struct.param[i], GC_USED, NULL);
973       }
974       if (t->u.param_struct.stru->gc_used == GC_POINTED_TO)
975         level = GC_POINTED_TO;
976       else
977         level = GC_USED;
978       t->u.param_struct.stru->gc_used = GC_UNUSED;
979       set_gc_used_type (t->u.param_struct.stru, level, 
980                         t->u.param_struct.param);
981       break;
982
983     default:
984       break;
985     }
986 }
987
988 /* Set the gc_used fields of all the types pointed to by VARIABLES.  */
989
990 static void
991 set_gc_used (variables)
992      pair_p variables;
993 {
994   pair_p p;
995   for (p = variables; p; p = p->next)
996     set_gc_used_type (p->type, GC_USED, NULL);
997 }
998 \f
999 /* File mapping routines.  For each input file, there is one output .c file
1000    (but some output files have many input files), and there is one .h file
1001    for the whole build.  */
1002
1003 /* The list of output files.  */
1004 static outf_p output_files;
1005
1006 /* The output header file that is included into pretty much every
1007    source file.  */
1008 outf_p header_file;
1009
1010 /* Number of files specified in gtfiles.  */
1011 #define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
1012
1013 /* Number of files in the language files array.  */
1014 #define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
1015
1016 /* Length of srcdir name.  */
1017 static int srcdir_len = 0;
1018
1019 #define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
1020 outf_p base_files[NUM_BASE_FILES];
1021
1022 static outf_p create_file PARAMS ((const char *, const char *));
1023 static const char * get_file_basename PARAMS ((const char *));
1024
1025 /* Create and return an outf_p for a new file for NAME, to be called
1026    ONAME.  */
1027
1028 static outf_p
1029 create_file (name, oname)
1030      const char *name;
1031      const char *oname;
1032 {
1033   static const char *const hdr[] = {
1034     "   Copyright (C) 2002 Free Software Foundation, Inc.\n",
1035     "\n",
1036     "This file is part of GCC.\n",
1037     "\n",
1038     "GCC is free software; you can redistribute it and/or modify it under\n",
1039     "the terms of the GNU General Public License as published by the Free\n",
1040     "Software Foundation; either version 2, or (at your option) any later\n",
1041     "version.\n",
1042     "\n",
1043     "GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n",
1044     "WARRANTY; without even the implied warranty of MERCHANTABILITY or\n",
1045     "FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n",
1046     "for more details.\n",
1047     "\n",
1048     "You should have received a copy of the GNU General Public License\n",
1049     "along with GCC; see the file COPYING.  If not, write to the Free\n",
1050     "Software Foundation, 59 Temple Place - Suite 330, Boston, MA\n",
1051     "02111-1307, USA.  */\n",
1052     "\n",
1053     "/* This file is machine generated.  Do not edit.  */\n"
1054   };
1055   outf_p f;
1056   size_t i;
1057   
1058   f = xcalloc (sizeof (*f), 1);
1059   f->next = output_files;
1060   f->name = oname;
1061   output_files = f;
1062
1063   oprintf (f, "/* Type information for %s.\n", name);
1064   for (i = 0; i < ARRAY_SIZE (hdr); i++)
1065     oprintf (f, "%s", hdr[i]);
1066   return f;
1067 }
1068
1069 /* Print, like fprintf, to O.  */
1070 void 
1071 oprintf VPARAMS ((outf_p o, const char *format, ...))
1072 {
1073   char *s;
1074   size_t slength;
1075   
1076   VA_OPEN (ap, format);
1077   VA_FIXEDARG (ap, outf_p, o);
1078   VA_FIXEDARG (ap, const char *, format);
1079   slength = xvasprintf (&s, format, ap);
1080
1081   if (o->bufused + slength > o->buflength)
1082     {
1083       size_t new_len = o->buflength;
1084       if (new_len == 0)
1085         new_len = 1024;
1086       do {
1087         new_len *= 2;
1088       } while (o->bufused + slength >= new_len);
1089       o->buf = xrealloc (o->buf, new_len);
1090       o->buflength = new_len;
1091     }
1092   memcpy (o->buf + o->bufused, s, slength);
1093   o->bufused += slength;
1094   free (s);
1095   VA_CLOSE (ap);
1096 }
1097
1098 /* Open the global header file and the language-specific header files.  */
1099
1100 static void
1101 open_base_files ()
1102 {
1103   size_t i;
1104   
1105   header_file = create_file ("GCC", "gtype-desc.h");
1106
1107   for (i = 0; i < NUM_BASE_FILES; i++)
1108     base_files[i] = create_file (lang_dir_names[i], 
1109                                  xasprintf ("gtype-%s.h", lang_dir_names[i]));
1110
1111   /* gtype-desc.c is a little special, so we create it here.  */
1112   {
1113     /* The order of files here matters very much.  */
1114     static const char *const ifiles [] = {
1115       "config.h", "system.h", "coretypes.h", "tm.h", "varray.h",
1116       "hashtab.h", "splay-tree.h", "bitmap.h", "tree.h", "rtl.h",
1117       "function.h", "insn-config.h", "expr.h", "hard-reg-set.h",
1118       "basic-block.h", "cselib.h", "insn-addr.h", "ssa.h", "optabs.h",
1119       "libfuncs.h", "debug.h", "ggc.h",
1120       NULL
1121     };
1122     const char *const *ifp;
1123     outf_p gtype_desc_c;
1124       
1125     gtype_desc_c = create_file ("GCC", "gtype-desc.c");
1126     for (ifp = ifiles; *ifp; ifp++)
1127       oprintf (gtype_desc_c, "#include \"%s\"\n", *ifp);
1128   }
1129 }
1130
1131 /* Determine the pathname to F relative to $(srcdir).  */
1132
1133 static const char *
1134 get_file_basename (f)
1135      const char *f;
1136 {
1137   const char *basename;
1138   unsigned i;
1139   
1140   basename = strrchr (f, '/');
1141   
1142   if (!basename)
1143     return f;
1144   
1145   basename++;
1146   
1147   for (i = 1; i < NUM_BASE_FILES; i++)
1148     {
1149       const char * s1;
1150       const char * s2;
1151       int l1;
1152       int l2;
1153       s1 = basename - strlen (lang_dir_names [i]) - 1;
1154       s2 = lang_dir_names [i];
1155       l1 = strlen (s1);
1156       l2 = strlen (s2);
1157       if (l1 >= l2 && !memcmp (s1, s2, l2))
1158         {
1159           basename -= l2 + 1;
1160           if ((basename - f - 1) != srcdir_len)
1161             abort (); /* Match is wrong - should be preceded by $srcdir.  */
1162           break;
1163         }
1164     }
1165   
1166   return basename;
1167 }
1168
1169 /* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
1170    INPUT_FILE is used by <lang>.  
1171
1172    This function should be written to assume that a file _is_ used
1173    if the situation is unclear.  If it wrongly assumes a file _is_ used,
1174    a linker error will result.  If it wrongly assumes a file _is not_ used,
1175    some GC roots may be missed, which is a much harder-to-debug problem.  */
1176
1177 unsigned
1178 get_base_file_bitmap (input_file)
1179      const char *input_file;
1180 {
1181   const char *basename = get_file_basename (input_file);
1182   const char *slashpos = strchr (basename, '/');
1183   unsigned j;
1184   unsigned k;
1185   unsigned bitmap;
1186   
1187   if (slashpos)
1188     {
1189       size_t i;
1190       for (i = 1; i < NUM_BASE_FILES; i++)
1191         if ((size_t)(slashpos - basename) == strlen (lang_dir_names [i])
1192             && memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0)
1193           {
1194             /* It's in a language directory, set that language.  */
1195             bitmap = 1 << i;
1196             return bitmap;
1197           }
1198
1199       abort (); /* Should have found the language.  */
1200     }
1201
1202   /* If it's in any config-lang.in, then set for the languages
1203      specified.  */
1204
1205   bitmap = 0;
1206
1207   for (j = 0; j < NUM_LANG_FILES; j++)
1208     {
1209       if (!strcmp(input_file, lang_files[j]))
1210         {
1211           for (k = 0; k < NUM_BASE_FILES; k++)
1212             {
1213               if (!strcmp(lang_dir_names[k], langs_for_lang_files[j]))
1214                 bitmap |= (1 << k);
1215             }
1216         }
1217     }
1218     
1219   /* Otherwise, set all languages.  */
1220   if (!bitmap)
1221     bitmap = (1 << NUM_BASE_FILES) - 1;
1222
1223   return bitmap;
1224 }
1225
1226 /* An output file, suitable for definitions, that can see declarations
1227    made in INPUT_FILE and is linked into every language that uses
1228    INPUT_FILE.  */
1229
1230 outf_p
1231 get_output_file_with_visibility (input_file)
1232      const char *input_file;
1233 {
1234   outf_p r;
1235   size_t len;
1236   const char *basename;
1237   const char *for_name;
1238   const char *output_name;
1239
1240   /* This can happen when we need a file with visibility on a
1241      structure that we've never seen.  We have to just hope that it's
1242      globally visible.  */
1243   if (input_file == NULL)
1244     input_file = "system.h";
1245
1246   /* Determine the output file name.  */
1247   basename = get_file_basename (input_file);
1248
1249   len = strlen (basename);
1250   if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0)
1251       || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
1252       || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
1253     {
1254       char *s;
1255       
1256       output_name = s = xasprintf ("gt-%s", basename);
1257       for (; *s != '.'; s++)
1258         if (! ISALNUM (*s) && *s != '-')
1259           *s = '-';
1260       memcpy (s, ".h", sizeof (".h"));
1261       for_name = basename;
1262     }
1263   else if (strcmp (basename, "c-common.h") == 0)
1264     output_name = "gt-c-common.h", for_name = "c-common.c";
1265   else if (strcmp (basename, "c-tree.h") == 0)
1266     output_name = "gt-c-decl.h", for_name = "c-decl.c";
1267   else 
1268     {
1269       size_t i;
1270       
1271       for (i = 0; i < NUM_BASE_FILES; i++)
1272         if (memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0
1273             && basename[strlen(lang_dir_names[i])] == '/')
1274           return base_files[i];
1275
1276       output_name = "gtype-desc.c";
1277       for_name = NULL;
1278     }
1279
1280   /* Look through to see if we've ever seen this output filename before.  */
1281   for (r = output_files; r; r = r->next)
1282     if (strcmp (r->name, output_name) == 0)
1283       return r;
1284
1285   /* If not, create it.  */
1286   r = create_file (for_name, output_name);
1287
1288   return r;
1289 }
1290
1291 /* The name of an output file, suitable for definitions, that can see
1292    declarations made in INPUT_FILE and is linked into every language
1293    that uses INPUT_FILE.  */
1294
1295 const char *
1296 get_output_file_name (input_file)
1297      const char *input_file;
1298 {
1299   return get_output_file_with_visibility (input_file)->name;
1300 }
1301
1302 /* Copy the output to its final destination,
1303    but don't unnecessarily change modification times.  */
1304
1305 static void close_output_files PARAMS ((void));
1306
1307 static void
1308 close_output_files ()
1309 {
1310   outf_p of;
1311   
1312   for (of = output_files; of; of = of->next)
1313     {
1314       FILE * newfile;
1315
1316       newfile = fopen (of->name, "r");
1317       if (newfile != NULL )
1318         {
1319           int no_write_p;
1320           size_t i;
1321
1322           for (i = 0; i < of->bufused; i++)
1323             {
1324               int ch;
1325               ch = fgetc (newfile);
1326               if (ch == EOF || ch != (unsigned char) of->buf[i])
1327                 break;
1328             }
1329           no_write_p = i == of->bufused && fgetc (newfile) == EOF;
1330           fclose (newfile);
1331
1332           if (no_write_p)
1333             continue;
1334         }
1335
1336       newfile = fopen (of->name, "w");
1337       if (newfile == NULL)
1338         {
1339           perror ("opening output file");
1340           exit (1);
1341         }
1342       if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
1343         {
1344           perror ("writing output file");
1345           exit (1);
1346         }
1347       if (fclose (newfile) != 0)
1348         {
1349           perror ("closing output file");
1350           exit (1);
1351         }
1352     }
1353 }
1354 \f
1355 struct flist {
1356   struct flist *next;
1357   int started_p;
1358   const char *name;
1359   outf_p f;
1360 };
1361
1362 struct walk_type_data;
1363
1364 /* For scalars and strings, given the item in 'val'.
1365    For structures, given a pointer to the item in 'val'.
1366    For misc. pointers, given the item in 'val'.
1367 */
1368 typedef void (*process_field_fn) 
1369      PARAMS ((type_p f, const struct walk_type_data *p));
1370 typedef void (*func_name_fn)
1371      PARAMS ((type_p s, const struct walk_type_data *p));
1372
1373 /* Parameters for write_types.  */
1374
1375 struct write_types_data 
1376 {
1377   const char *prefix;
1378   const char *param_prefix;
1379   const char *subfield_marker_routine;
1380   const char *marker_routine;
1381   const char *reorder_note_routine;
1382   const char *comment;
1383 };
1384
1385 static void output_escaped_param PARAMS ((struct walk_type_data *d, 
1386                                           const char *, const char *));
1387 static void output_mangled_typename PARAMS ((outf_p, type_p));
1388 static void walk_type PARAMS ((type_p t, struct walk_type_data *d));
1389 static void write_func_for_structure
1390      PARAMS ((type_p orig_s, type_p s, type_p * param,
1391               const struct write_types_data *wtd));
1392 static void write_types_process_field 
1393      PARAMS ((type_p f, const struct walk_type_data *d));
1394 static void write_types PARAMS ((type_p structures, 
1395                                  type_p param_structs,
1396                                  const struct write_types_data *wtd));
1397 static void write_types_local_process_field
1398      PARAMS ((type_p f, const struct walk_type_data *d));
1399 static void write_local_func_for_structure
1400      PARAMS ((type_p orig_s, type_p s, type_p * param));
1401 static void write_local PARAMS ((type_p structures, 
1402                                  type_p param_structs));
1403 static void write_enum_defn PARAMS ((type_p structures, type_p param_structs));
1404 static int contains_scalar_p PARAMS ((type_p t));
1405 static void put_mangled_filename PARAMS ((outf_p , const char *));
1406 static void finish_root_table PARAMS ((struct flist *flp, const char *pfx, 
1407                                        const char *tname, const char *lastname,
1408                                        const char *name));
1409 static void write_root PARAMS ((outf_p , pair_p, type_p, const char *, int,
1410                                    struct fileloc *, const char *));
1411 static void write_array PARAMS ((outf_p f, pair_p v,
1412                                  const struct write_types_data *wtd));
1413 static void write_roots PARAMS ((pair_p));
1414
1415 /* Parameters for walk_type.  */
1416
1417 struct walk_type_data
1418 {
1419   process_field_fn process_field;
1420   const void *cookie;
1421   outf_p of;
1422   options_p opt;
1423   const char *val;
1424   const char *prev_val[4];
1425   int indent;
1426   int counter;
1427   struct fileloc *line;
1428   lang_bitmap bitmap;
1429   type_p *param;
1430   int used_length;
1431   type_p orig_s;
1432   const char *reorder_fn;
1433 };
1434
1435 /* Print a mangled name representing T to OF.  */
1436
1437 static void
1438 output_mangled_typename (of, t)
1439      outf_p of;
1440      type_p t;
1441 {
1442   if (t == NULL)
1443     oprintf (of, "Z");
1444   else switch (t->kind)
1445     {
1446     case TYPE_POINTER:
1447       oprintf (of, "P");
1448       output_mangled_typename (of, t->u.p);
1449       break;
1450     case TYPE_SCALAR:
1451       oprintf (of, "I");
1452       break;
1453     case TYPE_STRING:
1454       oprintf (of, "S");
1455       break;
1456     case TYPE_STRUCT:
1457     case TYPE_UNION:
1458     case TYPE_LANG_STRUCT:
1459       oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), t->u.s.tag);
1460       break;
1461     case TYPE_PARAM_STRUCT:
1462       {
1463         int i;
1464         for (i = 0; i < NUM_PARAM; i++)
1465           if (t->u.param_struct.param[i] != NULL)
1466             output_mangled_typename (of, t->u.param_struct.param[i]);
1467         output_mangled_typename (of, t->u.param_struct.stru);   
1468       }
1469       break;
1470     case TYPE_ARRAY:
1471       abort ();
1472     }
1473 }
1474
1475 /* Print PARAM to D->OF processing escapes.  D->VAL references the
1476    current object, D->PREV_VAL the object containing the current
1477    object, ONAME is the name of the option and D->LINE is used to
1478    print error messages.  */
1479
1480 static void
1481 output_escaped_param (d, param, oname)
1482      struct walk_type_data *d;
1483      const char *param;
1484      const char *oname;
1485 {
1486   const char *p;
1487   
1488   for (p = param; *p; p++)
1489     if (*p != '%')
1490       oprintf (d->of, "%c", *p);
1491     else switch (*++p)
1492       {
1493       case 'h':
1494         oprintf (d->of, "(%s)", d->prev_val[2]);
1495         break;
1496       case '0':
1497         oprintf (d->of, "(%s)", d->prev_val[0]);
1498         break;
1499       case '1':
1500         oprintf (d->of, "(%s)", d->prev_val[1]);
1501         break;
1502       case 'a':
1503         {
1504           const char *pp = d->val + strlen (d->val);
1505           while (pp[-1] == ']')
1506             while (*pp != '[')
1507               pp--;
1508           oprintf (d->of, "%s", pp);
1509         }
1510         break;
1511       default:
1512         error_at_line (d->line, "`%s' option contains bad escape %c%c",
1513                        oname, '%', *p);
1514       }
1515 }
1516
1517 /* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
1518    which is of type T.  Write code to D->OF to constrain execution (at
1519    the point that D->PROCESS_FIELD is called) to the appropriate
1520    cases.  D->PREV_VAL lists the objects containing the current object,
1521    D->OPT is a list of options to apply, D->INDENT is the current
1522    indentation level, D->LINE is used to print error messages,
1523    D->BITMAP indicates which languages to print the structure for, and
1524    D->PARAM is the current parameter (from an enclosing param_is
1525    option).  */
1526
1527 static void
1528 walk_type (t, d)
1529      type_p t;
1530      struct walk_type_data *d;
1531 {
1532   const char *length = NULL;
1533   const char *desc = NULL;
1534   int maybe_undef_p = 0;
1535   int use_param_num = -1;
1536   int use_params_p = 0;
1537   int needs_cast_p = 0;
1538   options_p oo;
1539   
1540   for (oo = d->opt; oo; oo = oo->next)
1541     if (strcmp (oo->name, "length") == 0)
1542       length = (const char *)oo->info;
1543     else if (strcmp (oo->name, "maybe_undef") == 0)
1544       maybe_undef_p = 1;
1545     else if (strncmp (oo->name, "use_param", 9) == 0
1546              && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
1547       use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
1548     else if (strcmp (oo->name, "use_params") == 0)
1549       use_params_p = 1;
1550     else if (strcmp (oo->name, "desc") == 0)
1551       desc = (const char *)oo->info;
1552     else if (strcmp (oo->name, "dot") == 0)
1553       ;
1554     else if (strcmp (oo->name, "tag") == 0)
1555       ;
1556     else if (strcmp (oo->name, "special") == 0)
1557       ;
1558     else if (strcmp (oo->name, "skip") == 0)
1559       ;
1560     else if (strcmp (oo->name, "default") == 0)
1561       ;
1562     else if (strcmp (oo->name, "descbits") == 0)
1563       ;
1564     else if (strcmp (oo->name, "param_is") == 0)
1565       ;
1566     else if (strncmp (oo->name, "param", 5) == 0
1567              && ISDIGIT (oo->name[5])
1568              && strcmp (oo->name + 6, "_is") == 0)
1569       ;
1570     else if (strcmp (oo->name, "chain_next") == 0)
1571       ;
1572     else if (strcmp (oo->name, "chain_prev") == 0)
1573       ;
1574     else if (strcmp (oo->name, "reorder") == 0)
1575       ;
1576     else
1577       error_at_line (d->line, "unknown option `%s'\n", oo->name);
1578
1579   if (d->used_length)
1580     length = NULL;
1581
1582   if (use_params_p)
1583     {
1584       int pointer_p = t->kind == TYPE_POINTER;
1585       
1586       if (pointer_p)
1587         t = t->u.p;
1588       if (! UNION_OR_STRUCT_P (t))
1589         error_at_line (d->line, "`use_params' option on unimplemented type");
1590       else 
1591         t = find_param_structure (t, d->param);
1592       if (pointer_p)
1593         t = create_pointer (t);
1594     }
1595       
1596   if (use_param_num != -1)
1597     {
1598       if (d->param != NULL && d->param[use_param_num] != NULL)
1599         {
1600           type_p nt = d->param[use_param_num];
1601           
1602           if (t->kind == TYPE_ARRAY)
1603             nt = create_array (nt, t->u.a.len);
1604           else if (length != NULL && t->kind == TYPE_POINTER)
1605             nt = create_pointer (nt);
1606           needs_cast_p = (t->kind != TYPE_POINTER
1607                           && nt->kind == TYPE_POINTER);
1608           t = nt;
1609         }
1610       else
1611         error_at_line (d->line, "no parameter defined for `%s'",
1612                        d->val);
1613     }
1614   
1615   if (maybe_undef_p 
1616       && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
1617     {
1618       error_at_line (d->line, 
1619                      "field `%s' has invalid option `maybe_undef_p'\n",
1620                      d->val);
1621       return;
1622     }
1623   
1624   switch (t->kind)
1625     {
1626     case TYPE_SCALAR:
1627     case TYPE_STRING:
1628       d->process_field (t, d);
1629       break;
1630       
1631     case TYPE_POINTER:
1632       {
1633         if (maybe_undef_p
1634             && t->u.p->u.s.line.file == NULL)
1635           {
1636             oprintf (d->of, "%*sif (%s) abort();\n", d->indent, "", d->val);
1637             break;
1638           }
1639
1640         if (! length)
1641           {
1642             if (! UNION_OR_STRUCT_P (t->u.p)
1643                 && t->u.p->kind != TYPE_PARAM_STRUCT)
1644               {
1645                 error_at_line (d->line, 
1646                                "field `%s' is pointer to unimplemented type",
1647                                d->val);
1648                 break;
1649               }
1650             
1651             d->process_field (t->u.p, d);
1652           }
1653         else 
1654           {
1655             int loopcounter = d->counter++;
1656             const char *oldval = d->val;
1657             const char *oldprevval3 = d->prev_val[3];
1658             char *newval;
1659
1660             oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val);
1661             d->indent += 2;
1662             oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
1663             d->process_field(t, d);
1664             oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "", 
1665                      loopcounter, loopcounter);
1666             output_escaped_param (d, length, "length");
1667             oprintf (d->of, "); i%d++) {\n", loopcounter);
1668             d->indent += 2;
1669             d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
1670             d->used_length = 1;
1671             d->prev_val[3] = oldval;
1672             walk_type (t->u.p, d);
1673             free (newval);
1674             d->val = oldval;
1675             d->prev_val[3] = oldprevval3;
1676             d->used_length = 0;
1677             d->indent -= 2;
1678             oprintf (d->of, "%*s}\n", d->indent, "");
1679             d->indent -= 2;
1680             oprintf (d->of, "%*s}\n", d->indent, "");
1681           }
1682       }
1683       break;
1684
1685     case TYPE_ARRAY:
1686       {
1687         int loopcounter = d->counter++;
1688         const char *oldval = d->val;
1689         char *newval;
1690
1691         /* If it's an array of scalars, we optimise by not generating
1692            any code.  */
1693         if (t->u.a.p->kind == TYPE_SCALAR)
1694           break;
1695         
1696         oprintf (d->of, "%*s{\n", d->indent, "");
1697         d->indent += 2;
1698         oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
1699         oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "", 
1700                  loopcounter, loopcounter);
1701         if (length)
1702           output_escaped_param (d, length, "length");
1703         else
1704           oprintf (d->of, "%s", t->u.a.len);
1705         oprintf (d->of, "); i%d++) {\n", loopcounter);
1706         d->indent += 2;
1707         d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
1708         d->used_length = 1;
1709         walk_type (t->u.a.p, d);
1710         free (newval);
1711         d->used_length = 0;
1712         d->val = oldval;
1713         d->indent -= 2;
1714         oprintf (d->of, "%*s}\n", d->indent, "");
1715         d->indent -= 2;
1716         oprintf (d->of, "%*s}\n", d->indent, "");
1717       }
1718       break;
1719       
1720     case TYPE_STRUCT:
1721     case TYPE_UNION:
1722       {
1723         pair_p f;
1724         const char *oldval = d->val;
1725         const char *oldprevval1 = d->prev_val[1];
1726         const char *oldprevval2 = d->prev_val[2];
1727         const int union_p = t->kind == TYPE_UNION;
1728         int seen_default_p = 0;
1729         options_p o;
1730
1731         if (! t->u.s.line.file)
1732           error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag);
1733
1734         if ((d->bitmap & t->u.s.bitmap) != d->bitmap)
1735           {
1736             error_at_line (d->line,
1737                            "structure `%s' defined for mismatching languages",
1738                            t->u.s.tag);
1739             error_at_line (&t->u.s.line, "one structure defined here");
1740           }
1741
1742         /* Some things may also be defined in the structure's options.  */
1743         for (o = t->u.s.opt; o; o = o->next)
1744           if (! desc && strcmp (o->name, "desc") == 0)
1745             desc = (const char *)o->info;
1746
1747         d->prev_val[2] = oldval;
1748         d->prev_val[1] = oldprevval2;
1749         if (union_p)
1750           {
1751             if (desc == NULL)
1752               {
1753                 error_at_line (d->line, "missing `desc' option for union `%s'",
1754                                t->u.s.tag);
1755                 desc = "1";
1756               }
1757             oprintf (d->of, "%*sswitch (", d->indent, "");
1758             output_escaped_param (d, desc, "desc");
1759             oprintf (d->of, ")\n");
1760             d->indent += 2;
1761             oprintf (d->of, "%*s{\n", d->indent, "");
1762           }
1763         for (f = t->u.s.fields; f; f = f->next)
1764           {
1765             options_p oo;
1766             const char *dot = ".";
1767             const char *tagid = NULL;
1768             int skip_p = 0;
1769             int default_p = 0;
1770             int use_param_p = 0;
1771             char *newval;
1772
1773             d->reorder_fn = NULL;
1774             for (oo = f->opt; oo; oo = oo->next)
1775               if (strcmp (oo->name, "dot") == 0)
1776                 dot = (const char *)oo->info;
1777               else if (strcmp (oo->name, "tag") == 0)
1778                 tagid = (const char *)oo->info;
1779               else if (strcmp (oo->name, "skip") == 0)
1780                 skip_p = 1;
1781               else if (strcmp (oo->name, "default") == 0)
1782                 default_p = 1;
1783               else if (strcmp (oo->name, "reorder") == 0)
1784                 d->reorder_fn = (const char *)oo->info;
1785               else if (strncmp (oo->name, "use_param", 9) == 0
1786                        && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
1787                 use_param_p = 1;
1788
1789             if (skip_p)
1790               continue;
1791
1792             if (union_p && tagid)
1793               {
1794                 oprintf (d->of, "%*scase %s:\n", d->indent, "", tagid);
1795                 d->indent += 2;
1796               }
1797             else if (union_p && default_p)
1798               {
1799                 oprintf (d->of, "%*sdefault:\n", d->indent, "");
1800                 d->indent += 2;
1801                 seen_default_p = 1;
1802               }
1803             else if (! union_p && (default_p || tagid))
1804               error_at_line (d->line, 
1805                              "can't use `%s' outside a union on field `%s'",
1806                              default_p ? "default" : "tag", f->name);
1807             else if (union_p && ! (default_p || tagid)
1808                      && f->type->kind == TYPE_SCALAR)
1809               {
1810                 fprintf (stderr,
1811         "%s:%d: warning: field `%s' is missing `tag' or `default' option\n",
1812                          d->line->file, d->line->line, f->name);
1813                 continue;
1814               }
1815             else if (union_p && ! (default_p || tagid))
1816               error_at_line (d->line, 
1817                              "field `%s' is missing `tag' or `default' option",
1818                              f->name);
1819             
1820             d->line = &f->line;
1821             d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name);
1822             d->opt = f->opt;
1823
1824             if (union_p && use_param_p && d->param == NULL)
1825               oprintf (d->of, "%*sabort();\n", d->indent, "");
1826             else
1827               walk_type (f->type, d);
1828
1829             free (newval);
1830
1831             if (union_p)
1832               {
1833                 oprintf (d->of, "%*sbreak;\n", d->indent, "");
1834                 d->indent -= 2;
1835               }
1836           }
1837         d->reorder_fn = NULL;
1838
1839         d->val = oldval;
1840         d->prev_val[1] = oldprevval1;
1841         d->prev_val[2] = oldprevval2;
1842
1843         if (union_p && ! seen_default_p)
1844           {
1845             oprintf (d->of, "%*sdefault:\n", d->indent, "");
1846             oprintf (d->of, "%*s  break;\n", d->indent, "");
1847           }
1848         if (union_p)
1849           {
1850             oprintf (d->of, "%*s}\n", d->indent, "");
1851             d->indent -= 2;
1852           }
1853       }
1854       break;
1855
1856     case TYPE_LANG_STRUCT:
1857       {
1858         type_p nt;
1859         for (nt = t->u.s.lang_struct; nt; nt = nt->next)
1860           if ((d->bitmap & nt->u.s.bitmap) == d->bitmap)
1861             break;
1862         if (nt == NULL)
1863           error_at_line (d->line, "structure `%s' differs between languages",
1864                          t->u.s.tag);
1865         else
1866           walk_type (nt, d);
1867       }
1868       break;
1869
1870     case TYPE_PARAM_STRUCT:
1871       {
1872         type_p *oldparam = d->param;
1873         
1874         d->param = t->u.param_struct.param;
1875         walk_type (t->u.param_struct.stru, d);
1876         d->param = oldparam;
1877       }
1878       break;
1879       
1880     default:
1881       abort ();
1882     }
1883 }
1884
1885 /* process_field routine for marking routines.  */
1886
1887 static void
1888 write_types_process_field (f, d)
1889      type_p f;
1890      const struct walk_type_data *d;
1891 {
1892   const struct write_types_data *wtd;
1893   wtd = (const struct write_types_data *) d->cookie;
1894   
1895   switch (f->kind)
1896     {
1897     case TYPE_POINTER:
1898       oprintf (d->of, "%*s%s (%s", d->indent, "", 
1899                wtd->subfield_marker_routine, d->val);
1900       if (wtd->param_prefix)
1901         {
1902           oprintf (d->of, ", %s", d->prev_val[3]);
1903           if (d->orig_s)
1904             {
1905               oprintf (d->of, ", gt_%s_", wtd->param_prefix);
1906               output_mangled_typename (d->of, d->orig_s);
1907             }
1908           else
1909             oprintf (d->of, ", gt_%sa_%s", wtd->param_prefix, d->prev_val[0]);
1910         }
1911       oprintf (d->of, ");\n");
1912       if (d->reorder_fn && wtd->reorder_note_routine)
1913         oprintf (d->of, "%*s%s (%s, %s, %s);\n", d->indent, "", 
1914                  wtd->reorder_note_routine, d->val,
1915                  d->prev_val[3], d->reorder_fn);
1916       break;
1917
1918     case TYPE_STRING:
1919       if (wtd->param_prefix == NULL)
1920         break;
1921
1922     case TYPE_STRUCT:
1923     case TYPE_UNION:
1924     case TYPE_LANG_STRUCT:
1925     case TYPE_PARAM_STRUCT:
1926       oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
1927       output_mangled_typename (d->of, f);
1928       oprintf (d->of, " (%s);\n", d->val);
1929       if (d->reorder_fn && wtd->reorder_note_routine)
1930         oprintf (d->of, "%*s%s (%s, %s, %s);\n", d->indent, "", 
1931                  wtd->reorder_note_routine, d->val, d->val,
1932                  d->reorder_fn);
1933       break;
1934
1935     case TYPE_SCALAR:
1936       break;
1937       
1938     default:
1939       abort ();
1940     }
1941 }
1942
1943 /* For S, a structure that's part of ORIG_S, and using parameters
1944    PARAM, write out a routine that:
1945    - Takes a parameter, a void * but actually of type *S
1946    - If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each
1947      field of S or its substructures and (in some cases) things
1948      that are pointed to by S.
1949 */
1950
1951 static void
1952 write_func_for_structure (orig_s, s, param, wtd)
1953      type_p orig_s;
1954      type_p s;
1955      type_p * param;
1956      const struct write_types_data *wtd;
1957 {
1958   const char *fn = s->u.s.line.file;
1959   int i;
1960   const char *chain_next = NULL;
1961   const char *chain_prev = NULL;
1962   options_p opt;
1963   struct walk_type_data d;
1964   
1965   /* This is a hack, and not the good kind either.  */
1966   for (i = NUM_PARAM - 1; i >= 0; i--)
1967     if (param && param[i] && param[i]->kind == TYPE_POINTER 
1968         && UNION_OR_STRUCT_P (param[i]->u.p))
1969       fn = param[i]->u.p->u.s.line.file;
1970   
1971   memset (&d, 0, sizeof (d));
1972   d.of = get_output_file_with_visibility (fn);
1973   
1974   for (opt = s->u.s.opt; opt; opt = opt->next)
1975     if (strcmp (opt->name, "chain_next") == 0)
1976       chain_next = (const char *) opt->info;
1977     else if (strcmp (opt->name, "chain_prev") == 0)
1978       chain_prev = (const char *) opt->info;
1979
1980   if (chain_prev != NULL && chain_next == NULL)
1981     error_at_line (&s->u.s.line, "chain_prev without chain_next");
1982
1983   d.process_field = write_types_process_field;
1984   d.cookie = wtd;
1985   d.orig_s = orig_s;
1986   d.opt = s->u.s.opt;
1987   d.line = &s->u.s.line;
1988   d.bitmap = s->u.s.bitmap;
1989   d.param = param;
1990   d.prev_val[0] = "*x";
1991   d.prev_val[1] = "not valid postage";  /* guarantee an error */
1992   d.prev_val[3] = "x";
1993   d.val = "(*x)";
1994
1995   oprintf (d.of, "\n");
1996   oprintf (d.of, "void\n");
1997   if (param == NULL)
1998     oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
1999   else
2000     {
2001       oprintf (d.of, "gt_%s_", wtd->prefix);
2002       output_mangled_typename (d.of, orig_s);
2003     }
2004   oprintf (d.of, " (x_p)\n");
2005   oprintf (d.of, "      void *x_p;\n");
2006   oprintf (d.of, "{\n");
2007   oprintf (d.of, "  %s %s * %sx = (%s %s *)x_p;\n",
2008            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
2009            chain_next == NULL ? "const " : "",
2010            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2011   if (chain_next != NULL)
2012     oprintf (d.of, "  %s %s * xlimit = x;\n",
2013              s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2014   if (chain_next == NULL)
2015     {
2016       oprintf (d.of, "  if (%s (x", wtd->marker_routine);
2017       if (wtd->param_prefix)
2018         {
2019           oprintf (d.of, ", x, gt_%s_", wtd->param_prefix);
2020           output_mangled_typename (d.of, orig_s);
2021         }
2022       oprintf (d.of, "))\n");
2023     }
2024   else
2025     {
2026       oprintf (d.of, "  while (%s (xlimit", wtd->marker_routine);
2027       if (wtd->param_prefix)
2028         {
2029           oprintf (d.of, ", xlimit, gt_%s_", wtd->param_prefix);
2030           output_mangled_typename (d.of, orig_s);
2031         }
2032       oprintf (d.of, "))\n");
2033       oprintf (d.of, "   xlimit = (");
2034       d.prev_val[2] = "*xlimit";
2035       output_escaped_param (&d, chain_next, "chain_next");
2036       oprintf (d.of, ");\n");
2037       if (chain_prev != NULL)
2038         {
2039           oprintf (d.of, "  if (x != xlimit)\n");
2040           oprintf (d.of, "    for (;;)\n");
2041           oprintf (d.of, "      {\n");
2042           oprintf (d.of, "        %s %s * const xprev = (",
2043                    s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2044           
2045           d.prev_val[2] = "*x";
2046           output_escaped_param (&d, chain_prev, "chain_prev");
2047           oprintf (d.of, ");\n");
2048           oprintf (d.of, "        if (xprev == NULL) break;\n");
2049           oprintf (d.of, "        x = xprev;\n");
2050           oprintf (d.of, "        (void) %s (xprev", 
2051                    wtd->marker_routine);
2052           if (wtd->param_prefix)
2053             {
2054               oprintf (d.of, ", xprev, gt_%s_", wtd->param_prefix);
2055               output_mangled_typename (d.of, orig_s);
2056             }
2057           oprintf (d.of, ");\n");
2058           oprintf (d.of, "      }\n");
2059         }
2060       oprintf (d.of, "  while (x != xlimit)\n");
2061     }
2062   oprintf (d.of, "    {\n");
2063   
2064   d.prev_val[2] = "*x";
2065   d.indent = 6;
2066   walk_type (s, &d);
2067   
2068   if (chain_next != NULL)
2069     {
2070       oprintf (d.of, "      x = (");
2071       output_escaped_param (&d, chain_next, "chain_next");
2072       oprintf (d.of, ");\n");
2073     }
2074
2075   oprintf (d.of, "    }\n");
2076   oprintf (d.of, "}\n");
2077 }
2078
2079 /* Write out marker routines for STRUCTURES and PARAM_STRUCTS.  */
2080
2081 static void
2082 write_types (structures, param_structs, wtd)
2083      type_p structures;
2084      type_p param_structs;
2085      const struct write_types_data *wtd;
2086 {
2087   type_p s;
2088   
2089   oprintf (header_file, "\n/* %s*/\n", wtd->comment);
2090   for (s = structures; s; s = s->next)
2091     if (s->gc_used == GC_POINTED_TO
2092         || s->gc_used == GC_MAYBE_POINTED_TO)
2093       {
2094         options_p opt;
2095         
2096         if (s->gc_used == GC_MAYBE_POINTED_TO
2097             && s->u.s.line.file == NULL)
2098           continue;
2099
2100         oprintf (header_file, "#define gt_%s_", wtd->prefix);
2101         output_mangled_typename (header_file, s);
2102         oprintf (header_file, "(X) do { \\\n");
2103         oprintf (header_file,
2104                  "  if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix, 
2105                  s->u.s.tag);
2106         oprintf (header_file,
2107                  "  } while (0)\n");
2108         
2109         for (opt = s->u.s.opt; opt; opt = opt->next)
2110           if (strcmp (opt->name, "ptr_alias") == 0)
2111             {
2112               type_p t = (type_p) opt->info;
2113               if (t->kind == TYPE_STRUCT 
2114                   || t->kind == TYPE_UNION
2115                   || t->kind == TYPE_LANG_STRUCT)
2116                 oprintf (header_file,
2117                          "#define gt_%sx_%s gt_%sx_%s\n",
2118                          wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
2119               else
2120                 error_at_line (&s->u.s.line, 
2121                                "structure alias is not a structure");
2122               break;
2123             }
2124         if (opt)
2125           continue;
2126
2127         /* Declare the marker procedure only once.  */
2128         oprintf (header_file, 
2129                  "extern void gt_%sx_%s PARAMS ((void *));\n",
2130                  wtd->prefix, s->u.s.tag);
2131   
2132         if (s->u.s.line.file == NULL)
2133           {
2134             fprintf (stderr, "warning: structure `%s' used but not defined\n", 
2135                      s->u.s.tag);
2136             continue;
2137           }
2138   
2139         if (s->kind == TYPE_LANG_STRUCT)
2140           {
2141             type_p ss;
2142             for (ss = s->u.s.lang_struct; ss; ss = ss->next)
2143               write_func_for_structure (s, ss, NULL, wtd);
2144           }
2145         else
2146           write_func_for_structure (s, s, NULL, wtd);
2147       }
2148
2149   for (s = param_structs; s; s = s->next)
2150     if (s->gc_used == GC_POINTED_TO)
2151       {
2152         type_p * param = s->u.param_struct.param;
2153         type_p stru = s->u.param_struct.stru;
2154
2155         /* Declare the marker procedure.  */
2156         oprintf (header_file, "extern void gt_%s_", wtd->prefix);
2157         output_mangled_typename (header_file, s);
2158         oprintf (header_file, " PARAMS ((void *));\n");
2159   
2160         if (stru->u.s.line.file == NULL)
2161           {
2162             fprintf (stderr, "warning: structure `%s' used but not defined\n", 
2163                      s->u.s.tag);
2164             continue;
2165           }
2166   
2167         if (stru->kind == TYPE_LANG_STRUCT)
2168           {
2169             type_p ss;
2170             for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
2171               write_func_for_structure (s, ss, param, wtd);
2172           }
2173         else
2174           write_func_for_structure (s, stru, param, wtd);
2175       }
2176 }
2177
2178 static const struct write_types_data ggc_wtd =
2179 {
2180   "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
2181   "GC marker procedures.  "
2182 };
2183
2184 static const struct write_types_data pch_wtd =
2185 {
2186   "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
2187   "gt_pch_note_reorder",
2188   "PCH type-walking procedures.  "
2189 };
2190
2191 /* Write out the local pointer-walking routines.  */
2192
2193 /* process_field routine for local pointer-walking.  */
2194
2195 static void
2196 write_types_local_process_field (f, d)
2197      type_p f;
2198      const struct walk_type_data *d;
2199 {
2200   switch (f->kind)
2201     {
2202     case TYPE_POINTER:
2203     case TYPE_STRUCT:
2204     case TYPE_UNION:
2205     case TYPE_LANG_STRUCT:
2206     case TYPE_PARAM_STRUCT:
2207     case TYPE_STRING:
2208       oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
2209                d->prev_val[3]);
2210       oprintf (d->of, "%*s  op (&(%s), cookie);\n", d->indent, "", d->val);
2211       break;
2212
2213     case TYPE_SCALAR:
2214       break;
2215       
2216     default:
2217       abort ();
2218     }
2219 }
2220
2221 /* For S, a structure that's part of ORIG_S, and using parameters
2222    PARAM, write out a routine that:
2223    - Is of type gt_note_pointers
2224    - If calls PROCESS_FIELD on each field of S or its substructures.
2225 */
2226
2227 static void
2228 write_local_func_for_structure (orig_s, s, param)
2229      type_p orig_s;
2230      type_p s;
2231      type_p * param;
2232 {
2233   const char *fn = s->u.s.line.file;
2234   int i;
2235   struct walk_type_data d;
2236   
2237   /* This is a hack, and not the good kind either.  */
2238   for (i = NUM_PARAM - 1; i >= 0; i--)
2239     if (param && param[i] && param[i]->kind == TYPE_POINTER 
2240         && UNION_OR_STRUCT_P (param[i]->u.p))
2241       fn = param[i]->u.p->u.s.line.file;
2242   
2243   memset (&d, 0, sizeof (d));
2244   d.of = get_output_file_with_visibility (fn);
2245   
2246   d.process_field = write_types_local_process_field;
2247   d.opt = s->u.s.opt;
2248   d.line = &s->u.s.line;
2249   d.bitmap = s->u.s.bitmap;
2250   d.param = param;
2251   d.prev_val[0] = d.prev_val[2] = "*x";
2252   d.prev_val[1] = "not valid postage";  /* guarantee an error */
2253   d.prev_val[3] = "x";
2254   d.val = "(*x)";
2255
2256   oprintf (d.of, "\n");
2257   oprintf (d.of, "void\n");
2258   oprintf (d.of, "gt_pch_p_");
2259   output_mangled_typename (d.of, orig_s);
2260   oprintf (d.of, " (this_obj, x_p, op, cookie)\n");
2261   oprintf (d.of, "      void *this_obj ATTRIBUTE_UNUSED;\n");
2262   oprintf (d.of, "      void *x_p;\n");
2263   oprintf (d.of, "      gt_pointer_operator op ATTRIBUTE_UNUSED;\n");
2264   oprintf (d.of, "      void *cookie ATTRIBUTE_UNUSED;\n");
2265   oprintf (d.of, "{\n");
2266   oprintf (d.of, "  %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
2267            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
2268            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2269   d.indent = 2;
2270   walk_type (s, &d);
2271   oprintf (d.of, "}\n");
2272 }
2273
2274 /* Write out local marker routines for STRUCTURES and PARAM_STRUCTS.  */
2275
2276 static void
2277 write_local (structures, param_structs)
2278      type_p structures;
2279      type_p param_structs;
2280 {
2281   type_p s;
2282   
2283   oprintf (header_file, "\n/* Local pointer-walking routines.  */\n");
2284   for (s = structures; s; s = s->next)
2285     if (s->gc_used == GC_POINTED_TO
2286         || s->gc_used == GC_MAYBE_POINTED_TO)
2287       {
2288         options_p opt;
2289         
2290         if (s->u.s.line.file == NULL)
2291           continue;
2292
2293         for (opt = s->u.s.opt; opt; opt = opt->next)
2294           if (strcmp (opt->name, "ptr_alias") == 0)
2295             {
2296               type_p t = (type_p) opt->info;
2297               if (t->kind == TYPE_STRUCT 
2298                   || t->kind == TYPE_UNION
2299                   || t->kind == TYPE_LANG_STRUCT)
2300                 {
2301                   oprintf (header_file, "#define gt_pch_p_");
2302                   output_mangled_typename (header_file, s);
2303                   oprintf (header_file, " gt_pch_p_");
2304                   output_mangled_typename (header_file, t);
2305                   oprintf (header_file, "\n");
2306                 }
2307               else
2308                 error_at_line (&s->u.s.line, 
2309                                "structure alias is not a structure");
2310               break;
2311             }
2312         if (opt)
2313           continue;
2314
2315         /* Declare the marker procedure only once.  */
2316         oprintf (header_file, "extern void gt_pch_p_");
2317         output_mangled_typename (header_file, s);
2318         oprintf (header_file, 
2319          "\n    PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
2320   
2321         if (s->kind == TYPE_LANG_STRUCT)
2322           {
2323             type_p ss;
2324             for (ss = s->u.s.lang_struct; ss; ss = ss->next)
2325               write_local_func_for_structure (s, ss, NULL);
2326           }
2327         else
2328           write_local_func_for_structure (s, s, NULL);
2329       }
2330
2331   for (s = param_structs; s; s = s->next)
2332     if (s->gc_used == GC_POINTED_TO)
2333       {
2334         type_p * param = s->u.param_struct.param;
2335         type_p stru = s->u.param_struct.stru;
2336
2337         /* Declare the marker procedure.  */
2338         oprintf (header_file, "extern void gt_pch_p_");
2339         output_mangled_typename (header_file, s);
2340         oprintf (header_file, 
2341          "\n    PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
2342   
2343         if (stru->u.s.line.file == NULL)
2344           {
2345             fprintf (stderr, "warning: structure `%s' used but not defined\n", 
2346                      s->u.s.tag);
2347             continue;
2348           }
2349   
2350         if (stru->kind == TYPE_LANG_STRUCT)
2351           {
2352             type_p ss;
2353             for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
2354               write_local_func_for_structure (s, ss, param);
2355           }
2356         else
2357           write_local_func_for_structure (s, stru, param);
2358       }
2359 }
2360
2361 /* Write out the 'enum' definition for gt_types_enum.  */
2362
2363 static void
2364 write_enum_defn (structures, param_structs)
2365      type_p structures;
2366      type_p param_structs;
2367 {
2368   type_p s;
2369   
2370   oprintf (header_file, "\n/* Enumeration of types known.  */\n");
2371   oprintf (header_file, "enum gt_types_enum {\n");
2372   for (s = structures; s; s = s->next)
2373     if (s->gc_used == GC_POINTED_TO
2374         || s->gc_used == GC_MAYBE_POINTED_TO)
2375       {
2376         if (s->gc_used == GC_MAYBE_POINTED_TO
2377             && s->u.s.line.file == NULL)
2378           continue;
2379
2380         oprintf (header_file, " gt_ggc_e_");
2381         output_mangled_typename (header_file, s);
2382         oprintf (header_file, ", \n");
2383       }
2384   for (s = param_structs; s; s = s->next)
2385     if (s->gc_used == GC_POINTED_TO)
2386       {
2387         oprintf (header_file, " gt_e_");
2388         output_mangled_typename (header_file, s);
2389         oprintf (header_file, ", \n");
2390       }
2391   oprintf (header_file, " gt_types_enum_last\n");
2392   oprintf (header_file, "};\n");
2393 }
2394
2395 /* Might T contain any non-pointer elements?  */
2396
2397 static int
2398 contains_scalar_p (t)
2399      type_p t;
2400 {
2401   switch (t->kind)
2402     {
2403     case TYPE_STRING:
2404     case TYPE_POINTER:
2405       return 0;
2406     case TYPE_ARRAY:
2407       return contains_scalar_p (t->u.a.p);
2408     default:
2409       /* Could also check for structures that have no non-pointer
2410          fields, but there aren't enough of those to worry about.  */
2411       return 1;
2412     }
2413 }
2414
2415 /* Mangle FN and print it to F.  */
2416
2417 static void
2418 put_mangled_filename (f, fn)
2419      outf_p f;
2420      const char *fn;
2421 {
2422   const char *name = get_output_file_name (fn);
2423   for (; *name != 0; name++)
2424     if (ISALNUM (*name))
2425       oprintf (f, "%c", *name);
2426     else
2427       oprintf (f, "%c", '_');
2428 }
2429
2430 /* Finish off the currently-created root tables in FLP.  PFX, TNAME,
2431    LASTNAME, and NAME are all strings to insert in various places in
2432    the resulting code.  */
2433
2434 static void
2435 finish_root_table (flp, pfx, lastname, tname, name)
2436      struct flist *flp;
2437      const char *pfx;
2438      const char *tname;
2439      const char *lastname;
2440      const char *name;
2441 {
2442   struct flist *fli2;
2443   
2444   for (fli2 = flp; fli2; fli2 = fli2->next)
2445     if (fli2->started_p)
2446       {
2447         oprintf (fli2->f, "  %s\n", lastname);
2448         oprintf (fli2->f, "};\n\n");
2449       }
2450
2451   for (fli2 = flp; fli2; fli2 = fli2->next)
2452     if (fli2->started_p)
2453       {
2454         lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
2455         int fnum;
2456
2457         for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
2458           if (bitmap & 1)
2459             {
2460               oprintf (base_files[fnum],
2461                        "extern const struct %s gt_%s_",
2462                        tname, pfx);
2463               put_mangled_filename (base_files[fnum], fli2->name);
2464               oprintf (base_files[fnum], "[];\n");
2465             }
2466       }
2467   
2468   {
2469     size_t fnum;
2470     for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
2471       oprintf (base_files [fnum],
2472                "const struct %s * const %s[] = {\n",
2473                tname, name);
2474   }
2475   
2476
2477   for (fli2 = flp; fli2; fli2 = fli2->next)
2478     if (fli2->started_p)
2479       {
2480         lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
2481         int fnum;
2482
2483         fli2->started_p = 0;
2484
2485         for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
2486           if (bitmap & 1)
2487             {
2488               oprintf (base_files[fnum], "  gt_%s_", pfx);
2489               put_mangled_filename (base_files[fnum], fli2->name);
2490               oprintf (base_files[fnum], ",\n");
2491             }
2492       }
2493
2494   {
2495     size_t fnum;
2496     for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
2497       {
2498         oprintf (base_files[fnum], "  NULL\n");
2499         oprintf (base_files[fnum], "};\n");
2500       }
2501   }
2502 }
2503
2504 /* Write out to F the table entry and any marker routines needed to
2505    mark NAME as TYPE.  The original variable is V, at LINE.
2506    HAS_LENGTH is nonzero iff V was a variable-length array.  IF_MARKED
2507    is nonzero iff we are building the root table for hash table caches.  */
2508
2509 static void
2510 write_root (f, v, type, name, has_length, line, if_marked)
2511      outf_p f;
2512      pair_p v;
2513      type_p type;
2514      const char *name;
2515      int has_length;
2516      struct fileloc *line;
2517      const char *if_marked;
2518 {
2519   switch (type->kind)
2520     {
2521     case TYPE_STRUCT:
2522       {
2523         pair_p fld;
2524         for (fld = type->u.s.fields; fld; fld = fld->next)
2525           {
2526             int skip_p = 0;
2527             const char *desc = NULL;
2528             options_p o;
2529             
2530             for (o = fld->opt; o; o = o->next)
2531               if (strcmp (o->name, "skip") == 0)
2532                 skip_p = 1;
2533               else if (strcmp (o->name, "desc") == 0)
2534                 desc = (const char *)o->info;
2535               else
2536                 error_at_line (line,
2537                        "field `%s' of global `%s' has unknown option `%s'",
2538                                fld->name, name, o->name);
2539             
2540             if (skip_p)
2541               continue;
2542             else if (desc && fld->type->kind == TYPE_UNION)
2543               {
2544                 pair_p validf = NULL;
2545                 pair_p ufld;
2546                 
2547                 for (ufld = fld->type->u.s.fields; ufld; ufld = ufld->next)
2548                   {
2549                     const char *tag = NULL;
2550                     options_p oo;
2551                     
2552                     for (oo = ufld->opt; oo; oo = oo->next)
2553                       if (strcmp (oo->name, "tag") == 0)
2554                         tag = (const char *)oo->info;
2555                     if (tag == NULL || strcmp (tag, desc) != 0)
2556                       continue;
2557                     if (validf != NULL)
2558                       error_at_line (line, 
2559                            "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'",
2560                                      name, fld->name, validf->name,
2561                                      name, fld->name, ufld->name,
2562                                      tag);
2563                     validf = ufld;
2564                   }
2565                 if (validf != NULL)
2566                   {
2567                     char *newname;
2568                     newname = xasprintf ("%s.%s.%s", 
2569                                          name, fld->name, validf->name);
2570                     write_root (f, v, validf->type, newname, 0, line,
2571                                 if_marked);
2572                     free (newname);
2573                   }
2574               }
2575             else if (desc)
2576               error_at_line (line, 
2577                      "global `%s.%s' has `desc' option but is not union",
2578                              name, fld->name);
2579             else
2580               {
2581                 char *newname;
2582                 newname = xasprintf ("%s.%s", name, fld->name);
2583                 write_root (f, v, fld->type, newname, 0, line, if_marked);
2584                 free (newname);
2585               }
2586           }
2587       }
2588       break;
2589
2590     case TYPE_ARRAY:
2591       {
2592         char *newname;
2593         newname = xasprintf ("%s[0]", name);
2594         write_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
2595         free (newname);
2596       }
2597       break;
2598       
2599     case TYPE_POINTER:
2600       {
2601         type_p ap, tp;
2602         
2603         oprintf (f, "  {\n");
2604         oprintf (f, "    &%s,\n", name);
2605         oprintf (f, "    1");
2606         
2607         for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
2608           if (ap->u.a.len[0])
2609             oprintf (f, " * (%s)", ap->u.a.len);
2610           else if (ap == v->type)
2611             oprintf (f, " * ARRAY_SIZE (%s)", v->name);
2612         oprintf (f, ",\n");
2613         oprintf (f, "    sizeof (%s", v->name);
2614         for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
2615           oprintf (f, "[0]");
2616         oprintf (f, "),\n");
2617         
2618         tp = type->u.p;
2619         
2620         if (! has_length && UNION_OR_STRUCT_P (tp))
2621           {
2622             oprintf (f, "    &gt_ggc_mx_%s,\n", tp->u.s.tag);
2623             oprintf (f, "    &gt_pch_nx_%s", tp->u.s.tag);
2624           }
2625         else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
2626           {
2627             oprintf (f, "    &gt_ggc_m_");
2628             output_mangled_typename (f, tp);
2629             oprintf (f, ",\n    &gt_pch_n_");
2630             output_mangled_typename (f, tp);
2631           }
2632         else if (has_length
2633                  && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
2634           {
2635             oprintf (f, "    &gt_ggc_ma_%s,\n", name);
2636             oprintf (f, "    &gt_pch_na_%s", name);
2637           }
2638         else
2639           {
2640             error_at_line (line, 
2641                            "global `%s' is pointer to unimplemented type",
2642                            name);
2643           }
2644         if (if_marked)
2645           oprintf (f, ",\n    &%s", if_marked);
2646         oprintf (f, "\n  },\n");
2647       }
2648       break;
2649
2650     case TYPE_STRING:
2651       {
2652         oprintf (f, "  {\n");
2653         oprintf (f, "    &%s,\n", name);
2654         oprintf (f, "    1, \n");
2655         oprintf (f, "    sizeof (%s),\n", v->name);
2656         oprintf (f, "    &gt_ggc_m_S,\n");
2657         oprintf (f, "    &gt_pch_n_S\n");
2658         oprintf (f, "  },\n");
2659       }
2660       break;
2661         
2662     case TYPE_SCALAR:
2663       break;
2664       
2665     default:
2666       error_at_line (line, 
2667                      "global `%s' is unimplemented type",
2668                      name);
2669     }
2670 }
2671
2672 /* This generates a routine to walk an array.  */
2673
2674 static void
2675 write_array (f, v, wtd)
2676      outf_p f;
2677      pair_p v;
2678      const struct write_types_data *wtd;
2679 {
2680   struct walk_type_data d;
2681   char *prevval3;
2682   
2683   memset (&d, 0, sizeof (d));
2684   d.of = f;
2685   d.cookie = wtd;
2686   d.indent = 2;
2687   d.line = &v->line;
2688   d.opt = v->opt;
2689   d.bitmap = get_base_file_bitmap (v->line.file);
2690   d.param = NULL;
2691
2692   d.prev_val[3] = prevval3 = xasprintf ("&%s", v->name);
2693
2694   if (wtd->param_prefix)
2695     {
2696       oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name);
2697       oprintf (f, 
2698        "    PARAMS ((void *, void *, gt_pointer_operator, void *));\n");
2699       oprintf (f, "static void gt_%sa_%s (this_obj, x_p, op, cookie)\n", 
2700                wtd->param_prefix, v->name);
2701       oprintf (d.of, "      void *this_obj ATTRIBUTE_UNUSED;\n");
2702       oprintf (d.of, "      void *x_p ATTRIBUTE_UNUSED;\n");
2703       oprintf (d.of, "      gt_pointer_operator op ATTRIBUTE_UNUSED;\n");
2704       oprintf (d.of, "      void *cookie ATTRIBUTE_UNUSED;\n");
2705       oprintf (d.of, "{\n");
2706       d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
2707       d.process_field = write_types_local_process_field;
2708       walk_type (v->type, &d);
2709       oprintf (f, "}\n\n");
2710     }
2711
2712   d.opt = v->opt;
2713   oprintf (f, "static void gt_%sa_%s PARAMS ((void *));\n",
2714            wtd->prefix, v->name);
2715   oprintf (f, "static void\ngt_%sa_%s (x_p)\n",
2716            wtd->prefix, v->name);
2717   oprintf (f, "      void *x_p ATTRIBUTE_UNUSED;\n");
2718   oprintf (f, "{\n");
2719   d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
2720   d.process_field = write_types_process_field;
2721   walk_type (v->type, &d);
2722   free (prevval3);
2723   oprintf (f, "}\n\n");
2724 }
2725
2726 /* Output a table describing the locations and types of VARIABLES.  */
2727
2728 static void
2729 write_roots (variables)
2730      pair_p variables;
2731 {
2732   pair_p v;
2733   struct flist *flp = NULL;
2734
2735   for (v = variables; v; v = v->next)
2736     {
2737       outf_p f = get_output_file_with_visibility (v->line.file);
2738       struct flist *fli;
2739       const char *length = NULL;
2740       int deletable_p = 0;
2741       options_p o;
2742
2743       for (o = v->opt; o; o = o->next)
2744         if (strcmp (o->name, "length") == 0)
2745           length = (const char *)o->info;
2746         else if (strcmp (o->name, "deletable") == 0)
2747           deletable_p = 1;
2748         else if (strcmp (o->name, "param_is") == 0)
2749           ;
2750         else if (strncmp (o->name, "param", 5) == 0
2751                  && ISDIGIT (o->name[5])
2752                  && strcmp (o->name + 6, "_is") == 0)
2753           ;
2754         else if (strcmp (o->name, "if_marked") == 0)
2755           ;
2756         else
2757           error_at_line (&v->line, 
2758                          "global `%s' has unknown option `%s'",
2759                          v->name, o->name);
2760
2761       for (fli = flp; fli; fli = fli->next)
2762         if (fli->f == f)
2763           break;
2764       if (fli == NULL)
2765         {
2766           fli = xmalloc (sizeof (*fli));
2767           fli->f = f;
2768           fli->next = flp;
2769           fli->started_p = 0;
2770           fli->name = v->line.file;
2771           flp = fli;
2772
2773           oprintf (f, "\n/* GC roots.  */\n\n");
2774         }
2775
2776       if (! deletable_p
2777           && length
2778           && v->type->kind == TYPE_POINTER
2779           && (v->type->u.p->kind == TYPE_POINTER
2780               || v->type->u.p->kind == TYPE_STRUCT))
2781         {
2782           write_array (f, v, &ggc_wtd);
2783           write_array (f, v, &pch_wtd);
2784         }
2785     }
2786
2787   for (v = variables; v; v = v->next)
2788     {
2789       outf_p f = get_output_file_with_visibility (v->line.file);
2790       struct flist *fli;
2791       int skip_p = 0;
2792       int length_p = 0;
2793       options_p o;
2794       
2795       for (o = v->opt; o; o = o->next)
2796         if (strcmp (o->name, "length") == 0)
2797           length_p = 1;
2798         else if (strcmp (o->name, "deletable") == 0
2799                  || strcmp (o->name, "if_marked") == 0)
2800           skip_p = 1;
2801
2802       if (skip_p)
2803         continue;
2804
2805       for (fli = flp; fli; fli = fli->next)
2806         if (fli->f == f)
2807           break;
2808       if (! fli->started_p)
2809         {
2810           fli->started_p = 1;
2811
2812           oprintf (f, "const struct ggc_root_tab gt_ggc_r_");
2813           put_mangled_filename (f, v->line.file);
2814           oprintf (f, "[] = {\n");
2815         }
2816
2817       write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
2818     }
2819
2820   finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab", 
2821                      "gt_ggc_rtab");
2822
2823   for (v = variables; v; v = v->next)
2824     {
2825       outf_p f = get_output_file_with_visibility (v->line.file);
2826       struct flist *fli;
2827       int skip_p = 1;
2828       options_p o;
2829
2830       for (o = v->opt; o; o = o->next)
2831         if (strcmp (o->name, "deletable") == 0)
2832           skip_p = 0;
2833         else if (strcmp (o->name, "if_marked") == 0)
2834           skip_p = 1;
2835
2836       if (skip_p)
2837         continue;
2838
2839       for (fli = flp; fli; fli = fli->next)
2840         if (fli->f == f)
2841           break;
2842       if (! fli->started_p)
2843         {
2844           fli->started_p = 1;
2845
2846           oprintf (f, "const struct ggc_root_tab gt_ggc_rd_");
2847           put_mangled_filename (f, v->line.file);
2848           oprintf (f, "[] = {\n");
2849         }
2850       
2851       oprintf (f, "  { &%s, 1, sizeof (%s), NULL, NULL },\n",
2852                v->name, v->name);
2853     }
2854   
2855   finish_root_table (flp, "ggc_rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2856                      "gt_ggc_deletable_rtab");
2857
2858   for (v = variables; v; v = v->next)
2859     {
2860       outf_p f = get_output_file_with_visibility (v->line.file);
2861       struct flist *fli;
2862       const char *if_marked = NULL;
2863       int length_p = 0;
2864       options_p o;
2865       
2866       for (o = v->opt; o; o = o->next)
2867         if (strcmp (o->name, "length") == 0)
2868           length_p = 1;
2869         else if (strcmp (o->name, "if_marked") == 0)
2870           if_marked = (const char *) o->info;
2871
2872       if (if_marked == NULL)
2873         continue;
2874
2875       if (v->type->kind != TYPE_POINTER
2876           || v->type->u.p->kind != TYPE_PARAM_STRUCT
2877           || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0))
2878         {
2879           error_at_line (&v->line, "if_marked option used but not hash table");
2880           continue;
2881         }
2882
2883       for (fli = flp; fli; fli = fli->next)
2884         if (fli->f == f)
2885           break;
2886       if (! fli->started_p)
2887         {
2888           fli->started_p = 1;
2889
2890           oprintf (f, "const struct ggc_cache_tab gt_ggc_rc_");
2891           put_mangled_filename (f, v->line.file);
2892           oprintf (f, "[] = {\n");
2893         }
2894       
2895       write_root (f, v, v->type->u.p->u.param_struct.param[0],
2896                      v->name, length_p, &v->line, if_marked);
2897     }
2898   
2899   finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
2900                      "gt_ggc_cache_rtab");
2901
2902   for (v = variables; v; v = v->next)
2903     {
2904       outf_p f = get_output_file_with_visibility (v->line.file);
2905       struct flist *fli;
2906       int length_p = 0;
2907       int if_marked_p = 0;
2908       options_p o;
2909       
2910       for (o = v->opt; o; o = o->next)
2911         if (strcmp (o->name, "length") == 0)
2912           length_p = 1;
2913         else if (strcmp (o->name, "if_marked") == 0)
2914           if_marked_p = 1;
2915
2916       if (! if_marked_p)
2917         continue;
2918
2919       for (fli = flp; fli; fli = fli->next)
2920         if (fli->f == f)
2921           break;
2922       if (! fli->started_p)
2923         {
2924           fli->started_p = 1;
2925
2926           oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
2927           put_mangled_filename (f, v->line.file);
2928           oprintf (f, "[] = {\n");
2929         }
2930
2931       write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
2932     }
2933   
2934   finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2935                      "gt_pch_cache_rtab");
2936
2937   for (v = variables; v; v = v->next)
2938     {
2939       outf_p f = get_output_file_with_visibility (v->line.file);
2940       struct flist *fli;
2941       int skip_p = 0;
2942       options_p o;
2943
2944       for (o = v->opt; o; o = o->next)
2945         if (strcmp (o->name, "deletable") == 0
2946             || strcmp (o->name, "if_marked") == 0)
2947           skip_p = 1;
2948
2949       if (skip_p)
2950         continue;
2951
2952       if (! contains_scalar_p (v->type))
2953         continue;
2954
2955       for (fli = flp; fli; fli = fli->next)
2956         if (fli->f == f)
2957           break;
2958       if (! fli->started_p)
2959         {
2960           fli->started_p = 1;
2961
2962           oprintf (f, "const struct ggc_root_tab gt_pch_rs_");
2963           put_mangled_filename (f, v->line.file);
2964           oprintf (f, "[] = {\n");
2965         }
2966       
2967       oprintf (f, "  { &%s, 1, sizeof (%s), NULL, NULL },\n",
2968                v->name, v->name);
2969     }
2970   
2971   finish_root_table (flp, "pch_rs", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2972                      "gt_pch_scalar_rtab");
2973 }
2974
2975 \f
2976 extern int main PARAMS ((int argc, char **argv));
2977 int 
2978 main(argc, argv)
2979      int argc ATTRIBUTE_UNUSED;
2980      char **argv ATTRIBUTE_UNUSED;
2981 {
2982   unsigned i;
2983   static struct fileloc pos = { __FILE__, __LINE__ };
2984   unsigned j;
2985   
2986   gen_rtx_next ();
2987
2988   srcdir_len = strlen (srcdir);
2989
2990   do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
2991   do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
2992   do_scalar_typedef ("uint8", &pos);
2993   do_scalar_typedef ("jword", &pos);
2994   do_scalar_typedef ("JCF_u2", &pos);
2995
2996   do_typedef ("PTR", create_pointer (create_scalar_type ("void",
2997                                                          strlen ("void"))),
2998               &pos);
2999   do_typedef ("HARD_REG_SET", create_array (
3000               create_scalar_type ("unsigned long", strlen ("unsigned long")),
3001               "2"), &pos);
3002
3003   for (i = 0; i < NUM_GT_FILES; i++)
3004     {
3005       int dupflag = 0;
3006       /* Omit if already seen.  */
3007       for (j = 0; j < i; j++)
3008         {
3009           if (!strcmp (all_files[i], all_files[j]))
3010             {
3011               dupflag = 1;
3012               break;
3013             }
3014         }
3015       if (!dupflag)
3016         parse_file (all_files[i]);
3017     }
3018
3019   if (hit_error != 0)
3020     exit (1);
3021
3022   set_gc_used (variables);
3023
3024   open_base_files ();
3025   write_enum_defn (structures, param_structs);
3026   write_types (structures, param_structs, &ggc_wtd);
3027   write_types (structures, param_structs, &pch_wtd);
3028   write_local (structures, param_structs);
3029   write_roots (variables);
3030   write_rtx_next ();
3031   close_output_files ();
3032
3033   return (hit_error != 0);
3034 }