OSDN Git Service

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