OSDN Git Service

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