OSDN Git Service

* config/rs6000/rs6000.md: Document why a pattern is not
[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 *);
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)
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 }
899
900 /* Set the gc_used field of T to LEVEL, and handle the types it references.  */
901
902 static void
903 set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
904 {
905   if (t->gc_used >= level)
906     return;
907
908   t->gc_used = level;
909
910   switch (t->kind)
911     {
912     case TYPE_STRUCT:
913     case TYPE_UNION:
914       {
915         pair_p f;
916         int dummy;
917
918         process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy);
919
920         for (f = t->u.s.fields; f; f = f->next)
921           {
922             int maybe_undef = 0;
923             int pass_param = 0;
924             int length = 0;
925             process_gc_options (f->opt, level, &maybe_undef, &pass_param,
926                                 &length);
927
928             if (length && f->type->kind == TYPE_POINTER)
929               set_gc_used_type (f->type->u.p, GC_USED, NULL);
930             else if (maybe_undef && f->type->kind == TYPE_POINTER)
931               set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO, NULL);
932             else if (pass_param && f->type->kind == TYPE_POINTER && param)
933               set_gc_used_type (find_param_structure (f->type->u.p, param),
934                                 GC_POINTED_TO, NULL);
935             else
936               set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
937           }
938         break;
939       }
940
941     case TYPE_POINTER:
942       set_gc_used_type (t->u.p, GC_POINTED_TO, NULL);
943       break;
944
945     case TYPE_ARRAY:
946       set_gc_used_type (t->u.a.p, GC_USED, param);
947       break;
948
949     case TYPE_LANG_STRUCT:
950       for (t = t->u.s.lang_struct; t; t = t->next)
951         set_gc_used_type (t, level, param);
952       break;
953
954     case TYPE_PARAM_STRUCT:
955       {
956         int i;
957         for (i = 0; i < NUM_PARAM; i++)
958           if (t->u.param_struct.param[i] != 0)
959             set_gc_used_type (t->u.param_struct.param[i], GC_USED, NULL);
960       }
961       if (t->u.param_struct.stru->gc_used == GC_POINTED_TO)
962         level = GC_POINTED_TO;
963       else
964         level = GC_USED;
965       t->u.param_struct.stru->gc_used = GC_UNUSED;
966       set_gc_used_type (t->u.param_struct.stru, level,
967                         t->u.param_struct.param);
968       break;
969
970     default:
971       break;
972     }
973 }
974
975 /* Set the gc_used fields of all the types pointed to by VARIABLES.  */
976
977 static void
978 set_gc_used (pair_p variables)
979 {
980   pair_p p;
981   for (p = variables; p; p = p->next)
982     set_gc_used_type (p->type, GC_USED, NULL);
983 }
984 \f
985 /* File mapping routines.  For each input file, there is one output .c file
986    (but some output files have many input files), and there is one .h file
987    for the whole build.  */
988
989 /* The list of output files.  */
990 static outf_p output_files;
991
992 /* The output header file that is included into pretty much every
993    source file.  */
994 static outf_p header_file;
995
996 /* Number of files specified in gtfiles.  */
997 #define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
998
999 /* Number of files in the language files array.  */
1000 #define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
1001
1002 /* Length of srcdir name.  */
1003 static int srcdir_len = 0;
1004
1005 #define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
1006 outf_p base_files[NUM_BASE_FILES];
1007
1008 static outf_p create_file (const char *, const char *);
1009 static const char * get_file_basename (const char *);
1010
1011 /* Create and return an outf_p for a new file for NAME, to be called
1012    ONAME.  */
1013
1014 static outf_p
1015 create_file (const char *name, const char *oname)
1016 {
1017   static const char *const hdr[] = {
1018     "   Copyright (C) 2003 Free Software Foundation, Inc.\n",
1019     "\n",
1020     "This file is part of GCC.\n",
1021     "\n",
1022     "GCC is free software; you can redistribute it and/or modify it under\n",
1023     "the terms of the GNU General Public License as published by the Free\n",
1024     "Software Foundation; either version 2, or (at your option) any later\n",
1025     "version.\n",
1026     "\n",
1027     "GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n",
1028     "WARRANTY; without even the implied warranty of MERCHANTABILITY or\n",
1029     "FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n",
1030     "for more details.\n",
1031     "\n",
1032     "You should have received a copy of the GNU General Public License\n",
1033     "along with GCC; see the file COPYING.  If not, write to the Free\n",
1034     "Software Foundation, 59 Temple Place - Suite 330, Boston, MA\n",
1035     "02111-1307, USA.  */\n",
1036     "\n",
1037     "/* This file is machine generated.  Do not edit.  */\n"
1038   };
1039   outf_p f;
1040   size_t i;
1041
1042   f = xcalloc (sizeof (*f), 1);
1043   f->next = output_files;
1044   f->name = oname;
1045   output_files = f;
1046
1047   oprintf (f, "/* Type information for %s.\n", name);
1048   for (i = 0; i < ARRAY_SIZE (hdr); i++)
1049     oprintf (f, "%s", hdr[i]);
1050   return f;
1051 }
1052
1053 /* Print, like fprintf, to O.  */
1054 void
1055 oprintf (outf_p o, const char *format, ...)
1056 {
1057   char *s;
1058   size_t slength;
1059   va_list ap;
1060
1061   va_start (ap, format);
1062   slength = xvasprintf (&s, format, ap);
1063
1064   if (o->bufused + slength > o->buflength)
1065     {
1066       size_t new_len = o->buflength;
1067       if (new_len == 0)
1068         new_len = 1024;
1069       do {
1070         new_len *= 2;
1071       } while (o->bufused + slength >= new_len);
1072       o->buf = xrealloc (o->buf, new_len);
1073       o->buflength = new_len;
1074     }
1075   memcpy (o->buf + o->bufused, s, slength);
1076   o->bufused += slength;
1077   free (s);
1078   va_end (ap);
1079 }
1080
1081 /* Open the global header file and the language-specific header files.  */
1082
1083 static void
1084 open_base_files (void)
1085 {
1086   size_t i;
1087
1088   header_file = create_file ("GCC", "gtype-desc.h");
1089
1090   for (i = 0; i < NUM_BASE_FILES; i++)
1091     base_files[i] = create_file (lang_dir_names[i],
1092                                  xasprintf ("gtype-%s.h", lang_dir_names[i]));
1093
1094   /* gtype-desc.c is a little special, so we create it here.  */
1095   {
1096     /* The order of files here matters very much.  */
1097     static const char *const ifiles [] = {
1098       "config.h", "system.h", "coretypes.h", "tm.h", "varray.h",
1099       "hashtab.h", "splay-tree.h", "bitmap.h", "tree.h", "rtl.h",
1100       "function.h", "insn-config.h", "expr.h", "hard-reg-set.h",
1101       "basic-block.h", "cselib.h", "insn-addr.h", "optabs.h",
1102       "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
1103       NULL
1104     };
1105     const char *const *ifp;
1106     outf_p gtype_desc_c;
1107
1108     gtype_desc_c = create_file ("GCC", "gtype-desc.c");
1109     for (ifp = ifiles; *ifp; ifp++)
1110       oprintf (gtype_desc_c, "#include \"%s\"\n", *ifp);
1111   }
1112 }
1113
1114 /* Determine the pathname to F relative to $(srcdir).  */
1115
1116 static const char *
1117 get_file_basename (const char *f)
1118 {
1119   const char *basename;
1120   unsigned i;
1121
1122   basename = strrchr (f, '/');
1123
1124   if (!basename)
1125     return f;
1126
1127   basename++;
1128
1129   for (i = 1; i < NUM_BASE_FILES; i++)
1130     {
1131       const char * s1;
1132       const char * s2;
1133       int l1;
1134       int l2;
1135       s1 = basename - strlen (lang_dir_names [i]) - 1;
1136       s2 = lang_dir_names [i];
1137       l1 = strlen (s1);
1138       l2 = strlen (s2);
1139       if (l1 >= l2 && !memcmp (s1, s2, l2))
1140         {
1141           basename -= l2 + 1;
1142           if ((basename - f - 1) != srcdir_len)
1143             abort (); /* Match is wrong - should be preceded by $srcdir.  */
1144           break;
1145         }
1146     }
1147
1148   return basename;
1149 }
1150
1151 /* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
1152    INPUT_FILE is used by <lang>.
1153
1154    This function should be written to assume that a file _is_ used
1155    if the situation is unclear.  If it wrongly assumes a file _is_ used,
1156    a linker error will result.  If it wrongly assumes a file _is not_ used,
1157    some GC roots may be missed, which is a much harder-to-debug problem.  */
1158
1159 unsigned
1160 get_base_file_bitmap (const char *input_file)
1161 {
1162   const char *basename = get_file_basename (input_file);
1163   const char *slashpos = strchr (basename, '/');
1164   unsigned j;
1165   unsigned k;
1166   unsigned bitmap;
1167
1168   if (slashpos)
1169     {
1170       size_t i;
1171       for (i = 1; i < NUM_BASE_FILES; i++)
1172         if ((size_t)(slashpos - basename) == strlen (lang_dir_names [i])
1173             && memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0)
1174           {
1175             /* It's in a language directory, set that language.  */
1176             bitmap = 1 << i;
1177             return bitmap;
1178           }
1179
1180       abort (); /* Should have found the language.  */
1181     }
1182
1183   /* If it's in any config-lang.in, then set for the languages
1184      specified.  */
1185
1186   bitmap = 0;
1187
1188   for (j = 0; j < NUM_LANG_FILES; j++)
1189     {
1190       if (!strcmp(input_file, lang_files[j]))
1191         {
1192           for (k = 0; k < NUM_BASE_FILES; k++)
1193             {
1194               if (!strcmp(lang_dir_names[k], langs_for_lang_files[j]))
1195                 bitmap |= (1 << k);
1196             }
1197         }
1198     }
1199
1200   /* Otherwise, set all languages.  */
1201   if (!bitmap)
1202     bitmap = (1 << NUM_BASE_FILES) - 1;
1203
1204   return bitmap;
1205 }
1206
1207 /* An output file, suitable for definitions, that can see declarations
1208    made in INPUT_FILE and is linked into every language that uses
1209    INPUT_FILE.  */
1210
1211 outf_p
1212 get_output_file_with_visibility (const char *input_file)
1213 {
1214   outf_p r;
1215   size_t len;
1216   const char *basename;
1217   const char *for_name;
1218   const char *output_name;
1219
1220   /* This can happen when we need a file with visibility on a
1221      structure that we've never seen.  We have to just hope that it's
1222      globally visible.  */
1223   if (input_file == NULL)
1224     input_file = "system.h";
1225
1226   /* Determine the output file name.  */
1227   basename = get_file_basename (input_file);
1228
1229   len = strlen (basename);
1230   if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0)
1231       || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
1232       || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
1233     {
1234       char *s;
1235
1236       output_name = s = xasprintf ("gt-%s", basename);
1237       for (; *s != '.'; s++)
1238         if (! ISALNUM (*s) && *s != '-')
1239           *s = '-';
1240       memcpy (s, ".h", sizeof (".h"));
1241       for_name = basename;
1242     }
1243   else if (strcmp (basename, "c-common.h") == 0)
1244     output_name = "gt-c-common.h", for_name = "c-common.c";
1245   else if (strcmp (basename, "c-tree.h") == 0)
1246     output_name = "gt-c-decl.h", for_name = "c-decl.c";
1247   else
1248     {
1249       size_t i;
1250
1251       for (i = 0; i < NUM_BASE_FILES; i++)
1252         if (memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0
1253             && basename[strlen(lang_dir_names[i])] == '/')
1254           return base_files[i];
1255
1256       output_name = "gtype-desc.c";
1257       for_name = NULL;
1258     }
1259
1260   /* Look through to see if we've ever seen this output filename before.  */
1261   for (r = output_files; r; r = r->next)
1262     if (strcmp (r->name, output_name) == 0)
1263       return r;
1264
1265   /* If not, create it.  */
1266   r = create_file (for_name, output_name);
1267
1268   return r;
1269 }
1270
1271 /* The name of an output file, suitable for definitions, that can see
1272    declarations made in INPUT_FILE and is linked into every language
1273    that uses INPUT_FILE.  */
1274
1275 const char *
1276 get_output_file_name (const char *input_file)
1277 {
1278   return get_output_file_with_visibility (input_file)->name;
1279 }
1280
1281 /* Copy the output to its final destination,
1282    but don't unnecessarily change modification times.  */
1283
1284 static void
1285 close_output_files (void)
1286 {
1287   outf_p of;
1288
1289   for (of = output_files; of; of = of->next)
1290     {
1291       FILE * newfile;
1292
1293       newfile = fopen (of->name, "r");
1294       if (newfile != NULL )
1295         {
1296           int no_write_p;
1297           size_t i;
1298
1299           for (i = 0; i < of->bufused; i++)
1300             {
1301               int ch;
1302               ch = fgetc (newfile);
1303               if (ch == EOF || ch != (unsigned char) of->buf[i])
1304                 break;
1305             }
1306           no_write_p = i == of->bufused && fgetc (newfile) == EOF;
1307           fclose (newfile);
1308
1309           if (no_write_p)
1310             continue;
1311         }
1312
1313       newfile = fopen (of->name, "w");
1314       if (newfile == NULL)
1315         {
1316           perror ("opening output file");
1317           exit (1);
1318         }
1319       if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
1320         {
1321           perror ("writing output file");
1322           exit (1);
1323         }
1324       if (fclose (newfile) != 0)
1325         {
1326           perror ("closing output file");
1327           exit (1);
1328         }
1329     }
1330 }
1331 \f
1332 struct flist {
1333   struct flist *next;
1334   int started_p;
1335   const char *name;
1336   outf_p f;
1337 };
1338
1339 struct walk_type_data;
1340
1341 /* For scalars and strings, given the item in 'val'.
1342    For structures, given a pointer to the item in 'val'.
1343    For misc. pointers, given the item in 'val'.
1344 */
1345 typedef void (*process_field_fn)
1346      (type_p f, const struct walk_type_data *p);
1347 typedef void (*func_name_fn)
1348      (type_p s, const struct walk_type_data *p);
1349
1350 /* Parameters for write_types.  */
1351
1352 struct write_types_data
1353 {
1354   const char *prefix;
1355   const char *param_prefix;
1356   const char *subfield_marker_routine;
1357   const char *marker_routine;
1358   const char *reorder_note_routine;
1359   const char *comment;
1360 };
1361
1362 static void output_escaped_param (struct walk_type_data *d,
1363                                   const char *, const char *);
1364 static void output_mangled_typename (outf_p, type_p);
1365 static void walk_type (type_p t, struct walk_type_data *d);
1366 static void write_func_for_structure
1367      (type_p orig_s, type_p s, type_p * param,
1368       const struct write_types_data *wtd);
1369 static void write_types_process_field
1370      (type_p f, const struct walk_type_data *d);
1371 static void write_types (type_p structures,
1372                          type_p param_structs,
1373                          const struct write_types_data *wtd);
1374 static void write_types_local_process_field
1375      (type_p f, const struct walk_type_data *d);
1376 static void write_local_func_for_structure
1377      (type_p orig_s, type_p s, type_p * param);
1378 static void write_local (type_p structures,
1379                          type_p param_structs);
1380 static void write_enum_defn (type_p structures, type_p param_structs);
1381 static int contains_scalar_p (type_p t);
1382 static void put_mangled_filename (outf_p , const char *);
1383 static void finish_root_table (struct flist *flp, const char *pfx,
1384                                const char *tname, const char *lastname,
1385                                const char *name);
1386 static void write_root (outf_p , pair_p, type_p, const char *, int,
1387                         struct fileloc *, const char *);
1388 static void write_array (outf_p f, pair_p v,
1389                          const struct write_types_data *wtd);
1390 static void write_roots (pair_p);
1391
1392 /* Parameters for walk_type.  */
1393
1394 struct walk_type_data
1395 {
1396   process_field_fn process_field;
1397   const void *cookie;
1398   outf_p of;
1399   options_p opt;
1400   const char *val;
1401   const char *prev_val[4];
1402   int indent;
1403   int counter;
1404   struct fileloc *line;
1405   lang_bitmap bitmap;
1406   type_p *param;
1407   int used_length;
1408   type_p orig_s;
1409   const char *reorder_fn;
1410   int needs_cast_p;
1411 };
1412
1413 /* Print a mangled name representing T to OF.  */
1414
1415 static void
1416 output_mangled_typename (outf_p of, type_p t)
1417 {
1418   if (t == NULL)
1419     oprintf (of, "Z");
1420   else switch (t->kind)
1421     {
1422     case TYPE_POINTER:
1423       oprintf (of, "P");
1424       output_mangled_typename (of, t->u.p);
1425       break;
1426     case TYPE_SCALAR:
1427       oprintf (of, "I");
1428       break;
1429     case TYPE_STRING:
1430       oprintf (of, "S");
1431       break;
1432     case TYPE_STRUCT:
1433     case TYPE_UNION:
1434     case TYPE_LANG_STRUCT:
1435       oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), t->u.s.tag);
1436       break;
1437     case TYPE_PARAM_STRUCT:
1438       {
1439         int i;
1440         for (i = 0; i < NUM_PARAM; i++)
1441           if (t->u.param_struct.param[i] != NULL)
1442             output_mangled_typename (of, t->u.param_struct.param[i]);
1443         output_mangled_typename (of, t->u.param_struct.stru);
1444       }
1445       break;
1446     case TYPE_ARRAY:
1447       abort ();
1448     }
1449 }
1450
1451 /* Print PARAM to D->OF processing escapes.  D->VAL references the
1452    current object, D->PREV_VAL the object containing the current
1453    object, ONAME is the name of the option and D->LINE is used to
1454    print error messages.  */
1455
1456 static void
1457 output_escaped_param (struct walk_type_data *d, const char *param,
1458                       const char *oname)
1459 {
1460   const char *p;
1461
1462   for (p = param; *p; p++)
1463     if (*p != '%')
1464       oprintf (d->of, "%c", *p);
1465     else switch (*++p)
1466       {
1467       case 'h':
1468         oprintf (d->of, "(%s)", d->prev_val[2]);
1469         break;
1470       case '0':
1471         oprintf (d->of, "(%s)", d->prev_val[0]);
1472         break;
1473       case '1':
1474         oprintf (d->of, "(%s)", d->prev_val[1]);
1475         break;
1476       case 'a':
1477         {
1478           const char *pp = d->val + strlen (d->val);
1479           while (pp[-1] == ']')
1480             while (*pp != '[')
1481               pp--;
1482           oprintf (d->of, "%s", pp);
1483         }
1484         break;
1485       default:
1486         error_at_line (d->line, "`%s' option contains bad escape %c%c",
1487                        oname, '%', *p);
1488       }
1489 }
1490
1491 /* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
1492    which is of type T.  Write code to D->OF to constrain execution (at
1493    the point that D->PROCESS_FIELD is called) to the appropriate
1494    cases.  Call D->PROCESS_FIELD on subobjects before calling it on
1495    pointers to those objects.  D->PREV_VAL lists the objects
1496    containing the current object, D->OPT is a list of options to
1497    apply, D->INDENT is the current indentation level, D->LINE is used
1498    to print error messages, D->BITMAP indicates which languages to
1499    print the structure for, and D->PARAM is the current parameter
1500    (from an enclosing param_is option).  */
1501
1502 static void
1503 walk_type (type_p t, struct walk_type_data *d)
1504 {
1505   const char *length = NULL;
1506   const char *desc = NULL;
1507   int maybe_undef_p = 0;
1508   int use_param_num = -1;
1509   int use_params_p = 0;
1510   options_p oo;
1511
1512   d->needs_cast_p = 0;
1513   for (oo = d->opt; oo; oo = oo->next)
1514     if (strcmp (oo->name, "length") == 0)
1515       length = (const char *)oo->info;
1516     else if (strcmp (oo->name, "maybe_undef") == 0)
1517       maybe_undef_p = 1;
1518     else if (strncmp (oo->name, "use_param", 9) == 0
1519              && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
1520       use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
1521     else if (strcmp (oo->name, "use_params") == 0)
1522       use_params_p = 1;
1523     else if (strcmp (oo->name, "desc") == 0)
1524       desc = (const char *)oo->info;
1525     else if (strcmp (oo->name, "dot") == 0)
1526       ;
1527     else if (strcmp (oo->name, "tag") == 0)
1528       ;
1529     else if (strcmp (oo->name, "special") == 0)
1530       ;
1531     else if (strcmp (oo->name, "skip") == 0)
1532       ;
1533     else if (strcmp (oo->name, "default") == 0)
1534       ;
1535     else if (strcmp (oo->name, "descbits") == 0)
1536       ;
1537     else if (strcmp (oo->name, "param_is") == 0)
1538       ;
1539     else if (strncmp (oo->name, "param", 5) == 0
1540              && ISDIGIT (oo->name[5])
1541              && strcmp (oo->name + 6, "_is") == 0)
1542       ;
1543     else if (strcmp (oo->name, "chain_next") == 0)
1544       ;
1545     else if (strcmp (oo->name, "chain_prev") == 0)
1546       ;
1547     else if (strcmp (oo->name, "reorder") == 0)
1548       ;
1549     else
1550       error_at_line (d->line, "unknown option `%s'\n", oo->name);
1551
1552   if (d->used_length)
1553     length = NULL;
1554
1555   if (use_params_p)
1556     {
1557       int pointer_p = t->kind == TYPE_POINTER;
1558
1559       if (pointer_p)
1560         t = t->u.p;
1561       if (! UNION_OR_STRUCT_P (t))
1562         error_at_line (d->line, "`use_params' option on unimplemented type");
1563       else
1564         t = find_param_structure (t, d->param);
1565       if (pointer_p)
1566         t = create_pointer (t);
1567     }
1568
1569   if (use_param_num != -1)
1570     {
1571       if (d->param != NULL && d->param[use_param_num] != NULL)
1572         {
1573           type_p nt = d->param[use_param_num];
1574
1575           if (t->kind == TYPE_ARRAY)
1576             nt = create_array (nt, t->u.a.len);
1577           else if (length != NULL && t->kind == TYPE_POINTER)
1578             nt = create_pointer (nt);
1579           d->needs_cast_p = (t->kind != TYPE_POINTER
1580                              && (nt->kind == TYPE_POINTER
1581                                  || nt->kind == TYPE_STRING));
1582           t = nt;
1583         }
1584       else
1585         error_at_line (d->line, "no parameter defined for `%s'",
1586                        d->val);
1587     }
1588
1589   if (maybe_undef_p
1590       && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
1591     {
1592       error_at_line (d->line,
1593                      "field `%s' has invalid option `maybe_undef_p'\n",
1594                      d->val);
1595       return;
1596     }
1597
1598   switch (t->kind)
1599     {
1600     case TYPE_SCALAR:
1601     case TYPE_STRING:
1602       d->process_field (t, d);
1603       break;
1604
1605     case TYPE_POINTER:
1606       {
1607         if (maybe_undef_p
1608             && t->u.p->u.s.line.file == NULL)
1609           {
1610             oprintf (d->of, "%*sif (%s) abort();\n", d->indent, "", d->val);
1611             break;
1612           }
1613
1614         if (! length)
1615           {
1616             if (! UNION_OR_STRUCT_P (t->u.p)
1617                 && t->u.p->kind != TYPE_PARAM_STRUCT)
1618               {
1619                 error_at_line (d->line,
1620                                "field `%s' is pointer to unimplemented type",
1621                                d->val);
1622                 break;
1623               }
1624
1625             d->process_field (t->u.p, d);
1626           }
1627         else
1628           {
1629             int loopcounter = d->counter++;
1630             const char *oldval = d->val;
1631             const char *oldprevval3 = d->prev_val[3];
1632             char *newval;
1633
1634             oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val);
1635             d->indent += 2;
1636             oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
1637             oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "",
1638                      loopcounter, loopcounter);
1639             output_escaped_param (d, length, "length");
1640             oprintf (d->of, "); i%d++) {\n", loopcounter);
1641             d->indent += 2;
1642             d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
1643             d->used_length = 1;
1644             d->prev_val[3] = oldval;
1645             walk_type (t->u.p, d);
1646             free (newval);
1647             d->val = oldval;
1648             d->prev_val[3] = oldprevval3;
1649             d->used_length = 0;
1650             d->indent -= 2;
1651             oprintf (d->of, "%*s}\n", d->indent, "");
1652             d->process_field(t, d);
1653             d->indent -= 2;
1654             oprintf (d->of, "%*s}\n", d->indent, "");
1655           }
1656       }
1657       break;
1658
1659     case TYPE_ARRAY:
1660       {
1661         int loopcounter = d->counter++;
1662         const char *oldval = d->val;
1663         char *newval;
1664
1665         /* If it's an array of scalars, we optimize by not generating
1666            any code.  */
1667         if (t->u.a.p->kind == TYPE_SCALAR)
1668           break;
1669
1670         oprintf (d->of, "%*s{\n", d->indent, "");
1671         d->indent += 2;
1672         oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
1673         oprintf (d->of, "%*sfor (i%d = 0; i%d < (size_t)(", d->indent, "",
1674                  loopcounter, loopcounter);
1675         if (length)
1676           output_escaped_param (d, length, "length");
1677         else
1678           oprintf (d->of, "%s", t->u.a.len);
1679         oprintf (d->of, "); i%d++) {\n", loopcounter);
1680         d->indent += 2;
1681         d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
1682         d->used_length = 1;
1683         walk_type (t->u.a.p, d);
1684         free (newval);
1685         d->used_length = 0;
1686         d->val = oldval;
1687         d->indent -= 2;
1688         oprintf (d->of, "%*s}\n", d->indent, "");
1689         d->indent -= 2;
1690         oprintf (d->of, "%*s}\n", d->indent, "");
1691       }
1692       break;
1693
1694     case TYPE_STRUCT:
1695     case TYPE_UNION:
1696       {
1697         pair_p f;
1698         const char *oldval = d->val;
1699         const char *oldprevval1 = d->prev_val[1];
1700         const char *oldprevval2 = d->prev_val[2];
1701         const int union_p = t->kind == TYPE_UNION;
1702         int seen_default_p = 0;
1703         options_p o;
1704
1705         if (! t->u.s.line.file)
1706           error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag);
1707
1708         if ((d->bitmap & t->u.s.bitmap) != d->bitmap)
1709           {
1710             error_at_line (d->line,
1711                            "structure `%s' defined for mismatching languages",
1712                            t->u.s.tag);
1713             error_at_line (&t->u.s.line, "one structure defined here");
1714           }
1715
1716         /* Some things may also be defined in the structure's options.  */
1717         for (o = t->u.s.opt; o; o = o->next)
1718           if (! desc && strcmp (o->name, "desc") == 0)
1719             desc = (const char *)o->info;
1720
1721         d->prev_val[2] = oldval;
1722         d->prev_val[1] = oldprevval2;
1723         if (union_p)
1724           {
1725             if (desc == NULL)
1726               {
1727                 error_at_line (d->line, "missing `desc' option for union `%s'",
1728                                t->u.s.tag);
1729                 desc = "1";
1730               }
1731             oprintf (d->of, "%*sswitch (", d->indent, "");
1732             output_escaped_param (d, desc, "desc");
1733             oprintf (d->of, ")\n");
1734             d->indent += 2;
1735             oprintf (d->of, "%*s{\n", d->indent, "");
1736           }
1737         for (f = t->u.s.fields; f; f = f->next)
1738           {
1739             options_p oo;
1740             const char *dot = ".";
1741             const char *tagid = NULL;
1742             int skip_p = 0;
1743             int default_p = 0;
1744             int use_param_p = 0;
1745             char *newval;
1746
1747             d->reorder_fn = NULL;
1748             for (oo = f->opt; oo; oo = oo->next)
1749               if (strcmp (oo->name, "dot") == 0)
1750                 dot = (const char *)oo->info;
1751               else if (strcmp (oo->name, "tag") == 0)
1752                 tagid = (const char *)oo->info;
1753               else if (strcmp (oo->name, "skip") == 0)
1754                 skip_p = 1;
1755               else if (strcmp (oo->name, "default") == 0)
1756                 default_p = 1;
1757               else if (strcmp (oo->name, "reorder") == 0)
1758                 d->reorder_fn = (const char *)oo->info;
1759               else if (strncmp (oo->name, "use_param", 9) == 0
1760                        && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
1761                 use_param_p = 1;
1762
1763             if (skip_p)
1764               continue;
1765
1766             if (union_p && tagid)
1767               {
1768                 oprintf (d->of, "%*scase %s:\n", d->indent, "", tagid);
1769                 d->indent += 2;
1770               }
1771             else if (union_p && default_p)
1772               {
1773                 oprintf (d->of, "%*sdefault:\n", d->indent, "");
1774                 d->indent += 2;
1775                 seen_default_p = 1;
1776               }
1777             else if (! union_p && (default_p || tagid))
1778               error_at_line (d->line,
1779                              "can't use `%s' outside a union on field `%s'",
1780                              default_p ? "default" : "tag", f->name);
1781             else if (union_p && ! (default_p || tagid)
1782                      && f->type->kind == TYPE_SCALAR)
1783               {
1784                 fprintf (stderr,
1785         "%s:%d: warning: field `%s' is missing `tag' or `default' option\n",
1786                          d->line->file, d->line->line, f->name);
1787                 continue;
1788               }
1789             else if (union_p && ! (default_p || tagid))
1790               error_at_line (d->line,
1791                              "field `%s' is missing `tag' or `default' option",
1792                              f->name);
1793
1794             d->line = &f->line;
1795             d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name);
1796             d->opt = f->opt;
1797
1798             if (union_p && use_param_p && d->param == NULL)
1799               oprintf (d->of, "%*sabort();\n", d->indent, "");
1800             else
1801               walk_type (f->type, d);
1802
1803             free (newval);
1804
1805             if (union_p)
1806               {
1807                 oprintf (d->of, "%*sbreak;\n", d->indent, "");
1808                 d->indent -= 2;
1809               }
1810           }
1811         d->reorder_fn = NULL;
1812
1813         d->val = oldval;
1814         d->prev_val[1] = oldprevval1;
1815         d->prev_val[2] = oldprevval2;
1816
1817         if (union_p && ! seen_default_p)
1818           {
1819             oprintf (d->of, "%*sdefault:\n", d->indent, "");
1820             oprintf (d->of, "%*s  break;\n", d->indent, "");
1821           }
1822         if (union_p)
1823           {
1824             oprintf (d->of, "%*s}\n", d->indent, "");
1825             d->indent -= 2;
1826           }
1827       }
1828       break;
1829
1830     case TYPE_LANG_STRUCT:
1831       {
1832         type_p nt;
1833         for (nt = t->u.s.lang_struct; nt; nt = nt->next)
1834           if ((d->bitmap & nt->u.s.bitmap) == d->bitmap)
1835             break;
1836         if (nt == NULL)
1837           error_at_line (d->line, "structure `%s' differs between languages",
1838                          t->u.s.tag);
1839         else
1840           walk_type (nt, d);
1841       }
1842       break;
1843
1844     case TYPE_PARAM_STRUCT:
1845       {
1846         type_p *oldparam = d->param;
1847
1848         d->param = t->u.param_struct.param;
1849         walk_type (t->u.param_struct.stru, d);
1850         d->param = oldparam;
1851       }
1852       break;
1853
1854     default:
1855       abort ();
1856     }
1857 }
1858
1859 /* process_field routine for marking routines.  */
1860
1861 static void
1862 write_types_process_field (type_p f, const struct walk_type_data *d)
1863 {
1864   const struct write_types_data *wtd;
1865   const char *cast = d->needs_cast_p ? "(void *)" : "";
1866   wtd = (const struct write_types_data *) d->cookie;
1867
1868   switch (f->kind)
1869     {
1870     case TYPE_POINTER:
1871       oprintf (d->of, "%*s%s (%s%s", d->indent, "",
1872                wtd->subfield_marker_routine, cast, d->val);
1873       if (wtd->param_prefix)
1874         {
1875           oprintf (d->of, ", %s", d->prev_val[3]);
1876           if (d->orig_s)
1877             {
1878               oprintf (d->of, ", gt_%s_", wtd->param_prefix);
1879               output_mangled_typename (d->of, d->orig_s);
1880             }
1881           else
1882             oprintf (d->of, ", gt_%sa_%s", wtd->param_prefix, d->prev_val[0]);
1883         }
1884       oprintf (d->of, ");\n");
1885       if (d->reorder_fn && wtd->reorder_note_routine)
1886         oprintf (d->of, "%*s%s (%s%s, %s, %s);\n", d->indent, "",
1887                  wtd->reorder_note_routine, cast, d->val,
1888                  d->prev_val[3], d->reorder_fn);
1889       break;
1890
1891     case TYPE_STRING:
1892       if (wtd->param_prefix == NULL)
1893         break;
1894
1895     case TYPE_STRUCT:
1896     case TYPE_UNION:
1897     case TYPE_LANG_STRUCT:
1898     case TYPE_PARAM_STRUCT:
1899       oprintf (d->of, "%*sgt_%s_", d->indent, "", wtd->prefix);
1900       output_mangled_typename (d->of, f);
1901       oprintf (d->of, " (%s%s);\n", cast, d->val);
1902       if (d->reorder_fn && wtd->reorder_note_routine)
1903         oprintf (d->of, "%*s%s (%s%s, %s%s, %s);\n", d->indent, "",
1904                  wtd->reorder_note_routine, cast, d->val, cast, d->val,
1905                  d->reorder_fn);
1906       break;
1907
1908     case TYPE_SCALAR:
1909       break;
1910
1911     default:
1912       abort ();
1913     }
1914 }
1915
1916 /* For S, a structure that's part of ORIG_S, and using parameters
1917    PARAM, write out a routine that:
1918    - Takes a parameter, a void * but actually of type *S
1919    - If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each
1920      field of S or its substructures and (in some cases) things
1921      that are pointed to by S.
1922 */
1923
1924 static void
1925 write_func_for_structure (type_p orig_s, type_p s, type_p *param,
1926                           const struct write_types_data *wtd)
1927 {
1928   const char *fn = s->u.s.line.file;
1929   int i;
1930   const char *chain_next = NULL;
1931   const char *chain_prev = NULL;
1932   options_p opt;
1933   struct walk_type_data d;
1934
1935   /* This is a hack, and not the good kind either.  */
1936   for (i = NUM_PARAM - 1; i >= 0; i--)
1937     if (param && param[i] && param[i]->kind == TYPE_POINTER
1938         && UNION_OR_STRUCT_P (param[i]->u.p))
1939       fn = param[i]->u.p->u.s.line.file;
1940
1941   memset (&d, 0, sizeof (d));
1942   d.of = get_output_file_with_visibility (fn);
1943
1944   for (opt = s->u.s.opt; opt; opt = opt->next)
1945     if (strcmp (opt->name, "chain_next") == 0)
1946       chain_next = (const char *) opt->info;
1947     else if (strcmp (opt->name, "chain_prev") == 0)
1948       chain_prev = (const char *) opt->info;
1949
1950   if (chain_prev != NULL && chain_next == NULL)
1951     error_at_line (&s->u.s.line, "chain_prev without chain_next");
1952
1953   d.process_field = write_types_process_field;
1954   d.cookie = wtd;
1955   d.orig_s = orig_s;
1956   d.opt = s->u.s.opt;
1957   d.line = &s->u.s.line;
1958   d.bitmap = s->u.s.bitmap;
1959   d.param = param;
1960   d.prev_val[0] = "*x";
1961   d.prev_val[1] = "not valid postage";  /* Guarantee an error.  */
1962   d.prev_val[3] = "x";
1963   d.val = "(*x)";
1964
1965   oprintf (d.of, "\n");
1966   oprintf (d.of, "void\n");
1967   if (param == NULL)
1968     oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
1969   else
1970     {
1971       oprintf (d.of, "gt_%s_", wtd->prefix);
1972       output_mangled_typename (d.of, orig_s);
1973     }
1974   oprintf (d.of, " (void *x_p)\n");
1975   oprintf (d.of, "{\n");
1976   oprintf (d.of, "  %s %s * %sx = (%s %s *)x_p;\n",
1977            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
1978            chain_next == NULL ? "const " : "",
1979            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
1980   if (chain_next != NULL)
1981     oprintf (d.of, "  %s %s * xlimit = x;\n",
1982              s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
1983   if (chain_next == NULL)
1984     {
1985       oprintf (d.of, "  if (%s (x", wtd->marker_routine);
1986       if (wtd->param_prefix)
1987         {
1988           oprintf (d.of, ", x, gt_%s_", wtd->param_prefix);
1989           output_mangled_typename (d.of, orig_s);
1990         }
1991       oprintf (d.of, "))\n");
1992     }
1993   else
1994     {
1995       oprintf (d.of, "  while (%s (xlimit", wtd->marker_routine);
1996       if (wtd->param_prefix)
1997         {
1998           oprintf (d.of, ", xlimit, gt_%s_", wtd->param_prefix);
1999           output_mangled_typename (d.of, orig_s);
2000         }
2001       oprintf (d.of, "))\n");
2002       oprintf (d.of, "   xlimit = (");
2003       d.prev_val[2] = "*xlimit";
2004       output_escaped_param (&d, chain_next, "chain_next");
2005       oprintf (d.of, ");\n");
2006       if (chain_prev != NULL)
2007         {
2008           oprintf (d.of, "  if (x != xlimit)\n");
2009           oprintf (d.of, "    for (;;)\n");
2010           oprintf (d.of, "      {\n");
2011           oprintf (d.of, "        %s %s * const xprev = (",
2012                    s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2013
2014           d.prev_val[2] = "*x";
2015           output_escaped_param (&d, chain_prev, "chain_prev");
2016           oprintf (d.of, ");\n");
2017           oprintf (d.of, "        if (xprev == NULL) break;\n");
2018           oprintf (d.of, "        x = xprev;\n");
2019           oprintf (d.of, "        (void) %s (xprev",
2020                    wtd->marker_routine);
2021           if (wtd->param_prefix)
2022             {
2023               oprintf (d.of, ", xprev, gt_%s_", wtd->param_prefix);
2024               output_mangled_typename (d.of, orig_s);
2025             }
2026           oprintf (d.of, ");\n");
2027           oprintf (d.of, "      }\n");
2028         }
2029       oprintf (d.of, "  while (x != xlimit)\n");
2030     }
2031   oprintf (d.of, "    {\n");
2032
2033   d.prev_val[2] = "*x";
2034   d.indent = 6;
2035   walk_type (s, &d);
2036
2037   if (chain_next != NULL)
2038     {
2039       oprintf (d.of, "      x = (");
2040       output_escaped_param (&d, chain_next, "chain_next");
2041       oprintf (d.of, ");\n");
2042     }
2043
2044   oprintf (d.of, "    }\n");
2045   oprintf (d.of, "}\n");
2046 }
2047
2048 /* Write out marker routines for STRUCTURES and PARAM_STRUCTS.  */
2049
2050 static void
2051 write_types (type_p structures, type_p param_structs,
2052              const struct write_types_data *wtd)
2053 {
2054   type_p s;
2055
2056   oprintf (header_file, "\n/* %s*/\n", wtd->comment);
2057   for (s = structures; s; s = s->next)
2058     if (s->gc_used == GC_POINTED_TO
2059         || s->gc_used == GC_MAYBE_POINTED_TO)
2060       {
2061         options_p opt;
2062
2063         if (s->gc_used == GC_MAYBE_POINTED_TO
2064             && s->u.s.line.file == NULL)
2065           continue;
2066
2067         oprintf (header_file, "#define gt_%s_", wtd->prefix);
2068         output_mangled_typename (header_file, s);
2069         oprintf (header_file, "(X) do { \\\n");
2070         oprintf (header_file,
2071                  "  if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
2072                  s->u.s.tag);
2073         oprintf (header_file,
2074                  "  } while (0)\n");
2075
2076         for (opt = s->u.s.opt; opt; opt = opt->next)
2077           if (strcmp (opt->name, "ptr_alias") == 0)
2078             {
2079               type_p t = (type_p) opt->info;
2080               if (t->kind == TYPE_STRUCT
2081                   || t->kind == TYPE_UNION
2082                   || t->kind == TYPE_LANG_STRUCT)
2083                 oprintf (header_file,
2084                          "#define gt_%sx_%s gt_%sx_%s\n",
2085                          wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
2086               else
2087                 error_at_line (&s->u.s.line,
2088                                "structure alias is not a structure");
2089               break;
2090             }
2091         if (opt)
2092           continue;
2093
2094         /* Declare the marker procedure only once.  */
2095         oprintf (header_file,
2096                  "extern void gt_%sx_%s (void *);\n",
2097                  wtd->prefix, s->u.s.tag);
2098
2099         if (s->u.s.line.file == NULL)
2100           {
2101             fprintf (stderr, "warning: structure `%s' used but not defined\n",
2102                      s->u.s.tag);
2103             continue;
2104           }
2105
2106         if (s->kind == TYPE_LANG_STRUCT)
2107           {
2108             type_p ss;
2109             for (ss = s->u.s.lang_struct; ss; ss = ss->next)
2110               write_func_for_structure (s, ss, NULL, wtd);
2111           }
2112         else
2113           write_func_for_structure (s, s, NULL, wtd);
2114       }
2115
2116   for (s = param_structs; s; s = s->next)
2117     if (s->gc_used == GC_POINTED_TO)
2118       {
2119         type_p * param = s->u.param_struct.param;
2120         type_p stru = s->u.param_struct.stru;
2121
2122         /* Declare the marker procedure.  */
2123         oprintf (header_file, "extern void gt_%s_", wtd->prefix);
2124         output_mangled_typename (header_file, s);
2125         oprintf (header_file, " (void *);\n");
2126
2127         if (stru->u.s.line.file == NULL)
2128           {
2129             fprintf (stderr, "warning: structure `%s' used but not defined\n",
2130                      s->u.s.tag);
2131             continue;
2132           }
2133
2134         if (stru->kind == TYPE_LANG_STRUCT)
2135           {
2136             type_p ss;
2137             for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
2138               write_func_for_structure (s, ss, param, wtd);
2139           }
2140         else
2141           write_func_for_structure (s, stru, param, wtd);
2142       }
2143 }
2144
2145 static const struct write_types_data ggc_wtd =
2146 {
2147   "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
2148   "GC marker procedures.  "
2149 };
2150
2151 static const struct write_types_data pch_wtd =
2152 {
2153   "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
2154   "gt_pch_note_reorder",
2155   "PCH type-walking procedures.  "
2156 };
2157
2158 /* Write out the local pointer-walking routines.  */
2159
2160 /* process_field routine for local pointer-walking.  */
2161
2162 static void
2163 write_types_local_process_field (type_p f, const struct walk_type_data *d)
2164 {
2165   switch (f->kind)
2166     {
2167     case TYPE_POINTER:
2168     case TYPE_STRUCT:
2169     case TYPE_UNION:
2170     case TYPE_LANG_STRUCT:
2171     case TYPE_PARAM_STRUCT:
2172     case TYPE_STRING:
2173       oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
2174                d->prev_val[3]);
2175       oprintf (d->of, "%*s  op (&(%s), cookie);\n", d->indent, "", d->val);
2176       break;
2177
2178     case TYPE_SCALAR:
2179       break;
2180
2181     default:
2182       abort ();
2183     }
2184 }
2185
2186 /* For S, a structure that's part of ORIG_S, and using parameters
2187    PARAM, write out a routine that:
2188    - Is of type gt_note_pointers
2189    - If calls PROCESS_FIELD on each field of S or its substructures.
2190 */
2191
2192 static void
2193 write_local_func_for_structure (type_p orig_s, type_p s, type_p *param)
2194 {
2195   const char *fn = s->u.s.line.file;
2196   int i;
2197   struct walk_type_data d;
2198
2199   /* This is a hack, and not the good kind either.  */
2200   for (i = NUM_PARAM - 1; i >= 0; i--)
2201     if (param && param[i] && param[i]->kind == TYPE_POINTER
2202         && UNION_OR_STRUCT_P (param[i]->u.p))
2203       fn = param[i]->u.p->u.s.line.file;
2204
2205   memset (&d, 0, sizeof (d));
2206   d.of = get_output_file_with_visibility (fn);
2207
2208   d.process_field = write_types_local_process_field;
2209   d.opt = s->u.s.opt;
2210   d.line = &s->u.s.line;
2211   d.bitmap = s->u.s.bitmap;
2212   d.param = param;
2213   d.prev_val[0] = d.prev_val[2] = "*x";
2214   d.prev_val[1] = "not valid postage";  /* Guarantee an error.  */
2215   d.prev_val[3] = "x";
2216   d.val = "(*x)";
2217
2218   oprintf (d.of, "\n");
2219   oprintf (d.of, "void\n");
2220   oprintf (d.of, "gt_pch_p_");
2221   output_mangled_typename (d.of, orig_s);
2222   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");
2223   oprintf (d.of, "{\n");
2224   oprintf (d.of, "  %s %s * const x ATTRIBUTE_UNUSED = (%s %s *)x_p;\n",
2225            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
2226            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
2227   d.indent = 2;
2228   walk_type (s, &d);
2229   oprintf (d.of, "}\n");
2230 }
2231
2232 /* Write out local marker routines for STRUCTURES and PARAM_STRUCTS.  */
2233
2234 static void
2235 write_local (type_p structures, type_p param_structs)
2236 {
2237   type_p s;
2238
2239   oprintf (header_file, "\n/* Local pointer-walking routines.  */\n");
2240   for (s = structures; s; s = s->next)
2241     if (s->gc_used == GC_POINTED_TO
2242         || s->gc_used == GC_MAYBE_POINTED_TO)
2243       {
2244         options_p opt;
2245
2246         if (s->u.s.line.file == NULL)
2247           continue;
2248
2249         for (opt = s->u.s.opt; opt; opt = opt->next)
2250           if (strcmp (opt->name, "ptr_alias") == 0)
2251             {
2252               type_p t = (type_p) opt->info;
2253               if (t->kind == TYPE_STRUCT
2254                   || t->kind == TYPE_UNION
2255                   || t->kind == TYPE_LANG_STRUCT)
2256                 {
2257                   oprintf (header_file, "#define gt_pch_p_");
2258                   output_mangled_typename (header_file, s);
2259                   oprintf (header_file, " gt_pch_p_");
2260                   output_mangled_typename (header_file, t);
2261                   oprintf (header_file, "\n");
2262                 }
2263               else
2264                 error_at_line (&s->u.s.line,
2265                                "structure alias is not a structure");
2266               break;
2267             }
2268         if (opt)
2269           continue;
2270
2271         /* Declare the marker procedure only once.  */
2272         oprintf (header_file, "extern void gt_pch_p_");
2273         output_mangled_typename (header_file, s);
2274         oprintf (header_file,
2275          "\n    (void *, void *, gt_pointer_operator, void *);\n");
2276
2277         if (s->kind == TYPE_LANG_STRUCT)
2278           {
2279             type_p ss;
2280             for (ss = s->u.s.lang_struct; ss; ss = ss->next)
2281               write_local_func_for_structure (s, ss, NULL);
2282           }
2283         else
2284           write_local_func_for_structure (s, s, NULL);
2285       }
2286
2287   for (s = param_structs; s; s = s->next)
2288     if (s->gc_used == GC_POINTED_TO)
2289       {
2290         type_p * param = s->u.param_struct.param;
2291         type_p stru = s->u.param_struct.stru;
2292
2293         /* Declare the marker procedure.  */
2294         oprintf (header_file, "extern void gt_pch_p_");
2295         output_mangled_typename (header_file, s);
2296         oprintf (header_file,
2297          "\n    (void *, void *, gt_pointer_operator, void *);\n");
2298
2299         if (stru->u.s.line.file == NULL)
2300           {
2301             fprintf (stderr, "warning: structure `%s' used but not defined\n",
2302                      s->u.s.tag);
2303             continue;
2304           }
2305
2306         if (stru->kind == TYPE_LANG_STRUCT)
2307           {
2308             type_p ss;
2309             for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
2310               write_local_func_for_structure (s, ss, param);
2311           }
2312         else
2313           write_local_func_for_structure (s, stru, param);
2314       }
2315 }
2316
2317 /* Write out the 'enum' definition for gt_types_enum.  */
2318
2319 static void
2320 write_enum_defn (type_p structures, type_p param_structs)
2321 {
2322   type_p s;
2323
2324   oprintf (header_file, "\n/* Enumeration of types known.  */\n");
2325   oprintf (header_file, "enum gt_types_enum {\n");
2326   for (s = structures; s; s = s->next)
2327     if (s->gc_used == GC_POINTED_TO
2328         || s->gc_used == GC_MAYBE_POINTED_TO)
2329       {
2330         if (s->gc_used == GC_MAYBE_POINTED_TO
2331             && s->u.s.line.file == NULL)
2332           continue;
2333
2334         oprintf (header_file, " gt_ggc_e_");
2335         output_mangled_typename (header_file, s);
2336         oprintf (header_file, ", \n");
2337       }
2338   for (s = param_structs; s; s = s->next)
2339     if (s->gc_used == GC_POINTED_TO)
2340       {
2341         oprintf (header_file, " gt_e_");
2342         output_mangled_typename (header_file, s);
2343         oprintf (header_file, ", \n");
2344       }
2345   oprintf (header_file, " gt_types_enum_last\n");
2346   oprintf (header_file, "};\n");
2347 }
2348
2349 /* Might T contain any non-pointer elements?  */
2350
2351 static int
2352 contains_scalar_p (type_p t)
2353 {
2354   switch (t->kind)
2355     {
2356     case TYPE_STRING:
2357     case TYPE_POINTER:
2358       return 0;
2359     case TYPE_ARRAY:
2360       return contains_scalar_p (t->u.a.p);
2361     default:
2362       /* Could also check for structures that have no non-pointer
2363          fields, but there aren't enough of those to worry about.  */
2364       return 1;
2365     }
2366 }
2367
2368 /* Mangle FN and print it to F.  */
2369
2370 static void
2371 put_mangled_filename (outf_p f, const char *fn)
2372 {
2373   const char *name = get_output_file_name (fn);
2374   for (; *name != 0; name++)
2375     if (ISALNUM (*name))
2376       oprintf (f, "%c", *name);
2377     else
2378       oprintf (f, "%c", '_');
2379 }
2380
2381 /* Finish off the currently-created root tables in FLP.  PFX, TNAME,
2382    LASTNAME, and NAME are all strings to insert in various places in
2383    the resulting code.  */
2384
2385 static void
2386 finish_root_table (struct flist *flp, const char *pfx, const char *lastname,
2387                    const char *tname, const char *name)
2388 {
2389   struct flist *fli2;
2390
2391   for (fli2 = flp; fli2; fli2 = fli2->next)
2392     if (fli2->started_p)
2393       {
2394         oprintf (fli2->f, "  %s\n", lastname);
2395         oprintf (fli2->f, "};\n\n");
2396       }
2397
2398   for (fli2 = flp; fli2; fli2 = fli2->next)
2399     if (fli2->started_p)
2400       {
2401         lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
2402         int fnum;
2403
2404         for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
2405           if (bitmap & 1)
2406             {
2407               oprintf (base_files[fnum],
2408                        "extern const struct %s gt_%s_",
2409                        tname, pfx);
2410               put_mangled_filename (base_files[fnum], fli2->name);
2411               oprintf (base_files[fnum], "[];\n");
2412             }
2413       }
2414
2415   {
2416     size_t fnum;
2417     for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
2418       oprintf (base_files [fnum],
2419                "const struct %s * const %s[] = {\n",
2420                tname, name);
2421   }
2422
2423
2424   for (fli2 = flp; fli2; fli2 = fli2->next)
2425     if (fli2->started_p)
2426       {
2427         lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
2428         int fnum;
2429
2430         fli2->started_p = 0;
2431
2432         for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
2433           if (bitmap & 1)
2434             {
2435               oprintf (base_files[fnum], "  gt_%s_", pfx);
2436               put_mangled_filename (base_files[fnum], fli2->name);
2437               oprintf (base_files[fnum], ",\n");
2438             }
2439       }
2440
2441   {
2442     size_t fnum;
2443     for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
2444       {
2445         oprintf (base_files[fnum], "  NULL\n");
2446         oprintf (base_files[fnum], "};\n");
2447       }
2448   }
2449 }
2450
2451 /* Write out to F the table entry and any marker routines needed to
2452    mark NAME as TYPE.  The original variable is V, at LINE.
2453    HAS_LENGTH is nonzero iff V was a variable-length array.  IF_MARKED
2454    is nonzero iff we are building the root table for hash table caches.  */
2455
2456 static void
2457 write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
2458             struct fileloc *line, const char *if_marked)
2459 {
2460   switch (type->kind)
2461     {
2462     case TYPE_STRUCT:
2463       {
2464         pair_p fld;
2465         for (fld = type->u.s.fields; fld; fld = fld->next)
2466           {
2467             int skip_p = 0;
2468             const char *desc = NULL;
2469             options_p o;
2470
2471             for (o = fld->opt; o; o = o->next)
2472               if (strcmp (o->name, "skip") == 0)
2473                 skip_p = 1;
2474               else if (strcmp (o->name, "desc") == 0)
2475                 desc = (const char *)o->info;
2476               else
2477                 error_at_line (line,
2478                        "field `%s' of global `%s' has unknown option `%s'",
2479                                fld->name, name, o->name);
2480
2481             if (skip_p)
2482               continue;
2483             else if (desc && fld->type->kind == TYPE_UNION)
2484               {
2485                 pair_p validf = NULL;
2486                 pair_p ufld;
2487
2488                 for (ufld = fld->type->u.s.fields; ufld; ufld = ufld->next)
2489                   {
2490                     const char *tag = NULL;
2491                     options_p oo;
2492
2493                     for (oo = ufld->opt; oo; oo = oo->next)
2494                       if (strcmp (oo->name, "tag") == 0)
2495                         tag = (const char *)oo->info;
2496                     if (tag == NULL || strcmp (tag, desc) != 0)
2497                       continue;
2498                     if (validf != NULL)
2499                       error_at_line (line,
2500                            "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'",
2501                                      name, fld->name, validf->name,
2502                                      name, fld->name, ufld->name,
2503                                      tag);
2504                     validf = ufld;
2505                   }
2506                 if (validf != NULL)
2507                   {
2508                     char *newname;
2509                     newname = xasprintf ("%s.%s.%s",
2510                                          name, fld->name, validf->name);
2511                     write_root (f, v, validf->type, newname, 0, line,
2512                                 if_marked);
2513                     free (newname);
2514                   }
2515               }
2516             else if (desc)
2517               error_at_line (line,
2518                      "global `%s.%s' has `desc' option but is not union",
2519                              name, fld->name);
2520             else
2521               {
2522                 char *newname;
2523                 newname = xasprintf ("%s.%s", name, fld->name);
2524                 write_root (f, v, fld->type, newname, 0, line, if_marked);
2525                 free (newname);
2526               }
2527           }
2528       }
2529       break;
2530
2531     case TYPE_ARRAY:
2532       {
2533         char *newname;
2534         newname = xasprintf ("%s[0]", name);
2535         write_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
2536         free (newname);
2537       }
2538       break;
2539
2540     case TYPE_POINTER:
2541       {
2542         type_p ap, tp;
2543
2544         oprintf (f, "  {\n");
2545         oprintf (f, "    &%s,\n", name);
2546         oprintf (f, "    1");
2547
2548         for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
2549           if (ap->u.a.len[0])
2550             oprintf (f, " * (%s)", ap->u.a.len);
2551           else if (ap == v->type)
2552             oprintf (f, " * ARRAY_SIZE (%s)", v->name);
2553         oprintf (f, ",\n");
2554         oprintf (f, "    sizeof (%s", v->name);
2555         for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
2556           oprintf (f, "[0]");
2557         oprintf (f, "),\n");
2558
2559         tp = type->u.p;
2560
2561         if (! has_length && UNION_OR_STRUCT_P (tp))
2562           {
2563             oprintf (f, "    &gt_ggc_mx_%s,\n", tp->u.s.tag);
2564             oprintf (f, "    &gt_pch_nx_%s", tp->u.s.tag);
2565           }
2566         else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
2567           {
2568             oprintf (f, "    &gt_ggc_m_");
2569             output_mangled_typename (f, tp);
2570             oprintf (f, ",\n    &gt_pch_n_");
2571             output_mangled_typename (f, tp);
2572           }
2573         else if (has_length
2574                  && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
2575           {
2576             oprintf (f, "    &gt_ggc_ma_%s,\n", name);
2577             oprintf (f, "    &gt_pch_na_%s", name);
2578           }
2579         else
2580           {
2581             error_at_line (line,
2582                            "global `%s' is pointer to unimplemented type",
2583                            name);
2584           }
2585         if (if_marked)
2586           oprintf (f, ",\n    &%s", if_marked);
2587         oprintf (f, "\n  },\n");
2588       }
2589       break;
2590
2591     case TYPE_STRING:
2592       {
2593         oprintf (f, "  {\n");
2594         oprintf (f, "    &%s,\n", name);
2595         oprintf (f, "    1, \n");
2596         oprintf (f, "    sizeof (%s),\n", v->name);
2597         oprintf (f, "    &gt_ggc_m_S,\n");
2598         oprintf (f, "    (gt_pointer_walker) &gt_pch_n_S\n");
2599         oprintf (f, "  },\n");
2600       }
2601       break;
2602
2603     case TYPE_SCALAR:
2604       break;
2605
2606     default:
2607       error_at_line (line,
2608                      "global `%s' is unimplemented type",
2609                      name);
2610     }
2611 }
2612
2613 /* This generates a routine to walk an array.  */
2614
2615 static void
2616 write_array (outf_p f, pair_p v, const struct write_types_data *wtd)
2617 {
2618   struct walk_type_data d;
2619   char *prevval3;
2620
2621   memset (&d, 0, sizeof (d));
2622   d.of = f;
2623   d.cookie = wtd;
2624   d.indent = 2;
2625   d.line = &v->line;
2626   d.opt = v->opt;
2627   d.bitmap = get_base_file_bitmap (v->line.file);
2628   d.param = NULL;
2629
2630   d.prev_val[3] = prevval3 = xasprintf ("&%s", v->name);
2631
2632   if (wtd->param_prefix)
2633     {
2634       oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name);
2635       oprintf (f,
2636        "    (void *, void *, gt_pointer_operator, void *);\n");
2637       oprintf (f, "static void gt_%sa_%s (void *this_obj ATTRIBUTE_UNUSED,\n",
2638                wtd->param_prefix, v->name);
2639       oprintf (d.of, "      void *x_p ATTRIBUTE_UNUSED,\n");
2640       oprintf (d.of, "      gt_pointer_operator op ATTRIBUTE_UNUSED,\n");
2641       oprintf (d.of, "      void *cookie ATTRIBUTE_UNUSED)\n");
2642       oprintf (d.of, "{\n");
2643       d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
2644       d.process_field = write_types_local_process_field;
2645       walk_type (v->type, &d);
2646       oprintf (f, "}\n\n");
2647     }
2648
2649   d.opt = v->opt;
2650   oprintf (f, "static void gt_%sa_%s (void *);\n",
2651            wtd->prefix, v->name);
2652   oprintf (f, "static void\ngt_%sa_%s (void *x_p ATTRIBUTE_UNUSED)\n",
2653            wtd->prefix, v->name);
2654   oprintf (f, "{\n");
2655   d.prev_val[0] = d.prev_val[1] = d.prev_val[2] = d.val = v->name;
2656   d.process_field = write_types_process_field;
2657   walk_type (v->type, &d);
2658   free (prevval3);
2659   oprintf (f, "}\n\n");
2660 }
2661
2662 /* Output a table describing the locations and types of VARIABLES.  */
2663
2664 static void
2665 write_roots (pair_p variables)
2666 {
2667   pair_p v;
2668   struct flist *flp = NULL;
2669
2670   for (v = variables; v; v = v->next)
2671     {
2672       outf_p f = get_output_file_with_visibility (v->line.file);
2673       struct flist *fli;
2674       const char *length = NULL;
2675       int deletable_p = 0;
2676       options_p o;
2677
2678       for (o = v->opt; o; o = o->next)
2679         if (strcmp (o->name, "length") == 0)
2680           length = (const char *)o->info;
2681         else if (strcmp (o->name, "deletable") == 0)
2682           deletable_p = 1;
2683         else if (strcmp (o->name, "param_is") == 0)
2684           ;
2685         else if (strncmp (o->name, "param", 5) == 0
2686                  && ISDIGIT (o->name[5])
2687                  && strcmp (o->name + 6, "_is") == 0)
2688           ;
2689         else if (strcmp (o->name, "if_marked") == 0)
2690           ;
2691         else
2692           error_at_line (&v->line,
2693                          "global `%s' has unknown option `%s'",
2694                          v->name, o->name);
2695
2696       for (fli = flp; fli; fli = fli->next)
2697         if (fli->f == f)
2698           break;
2699       if (fli == NULL)
2700         {
2701           fli = xmalloc (sizeof (*fli));
2702           fli->f = f;
2703           fli->next = flp;
2704           fli->started_p = 0;
2705           fli->name = v->line.file;
2706           flp = fli;
2707
2708           oprintf (f, "\n/* GC roots.  */\n\n");
2709         }
2710
2711       if (! deletable_p
2712           && length
2713           && v->type->kind == TYPE_POINTER
2714           && (v->type->u.p->kind == TYPE_POINTER
2715               || v->type->u.p->kind == TYPE_STRUCT))
2716         {
2717           write_array (f, v, &ggc_wtd);
2718           write_array (f, v, &pch_wtd);
2719         }
2720     }
2721
2722   for (v = variables; v; v = v->next)
2723     {
2724       outf_p f = get_output_file_with_visibility (v->line.file);
2725       struct flist *fli;
2726       int skip_p = 0;
2727       int length_p = 0;
2728       options_p o;
2729
2730       for (o = v->opt; o; o = o->next)
2731         if (strcmp (o->name, "length") == 0)
2732           length_p = 1;
2733         else if (strcmp (o->name, "deletable") == 0
2734                  || strcmp (o->name, "if_marked") == 0)
2735           skip_p = 1;
2736
2737       if (skip_p)
2738         continue;
2739
2740       for (fli = flp; fli; fli = fli->next)
2741         if (fli->f == f)
2742           break;
2743       if (! fli->started_p)
2744         {
2745           fli->started_p = 1;
2746
2747           oprintf (f, "const struct ggc_root_tab gt_ggc_r_");
2748           put_mangled_filename (f, v->line.file);
2749           oprintf (f, "[] = {\n");
2750         }
2751
2752       write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
2753     }
2754
2755   finish_root_table (flp, "ggc_r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2756                      "gt_ggc_rtab");
2757
2758   for (v = variables; v; v = v->next)
2759     {
2760       outf_p f = get_output_file_with_visibility (v->line.file);
2761       struct flist *fli;
2762       int skip_p = 1;
2763       options_p o;
2764
2765       for (o = v->opt; o; o = o->next)
2766         if (strcmp (o->name, "deletable") == 0)
2767           skip_p = 0;
2768         else if (strcmp (o->name, "if_marked") == 0)
2769           skip_p = 1;
2770
2771       if (skip_p)
2772         continue;
2773
2774       for (fli = flp; fli; fli = fli->next)
2775         if (fli->f == f)
2776           break;
2777       if (! fli->started_p)
2778         {
2779           fli->started_p = 1;
2780
2781           oprintf (f, "const struct ggc_root_tab gt_ggc_rd_");
2782           put_mangled_filename (f, v->line.file);
2783           oprintf (f, "[] = {\n");
2784         }
2785
2786       oprintf (f, "  { &%s, 1, sizeof (%s), NULL, NULL },\n",
2787                v->name, v->name);
2788     }
2789
2790   finish_root_table (flp, "ggc_rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2791                      "gt_ggc_deletable_rtab");
2792
2793   for (v = variables; v; v = v->next)
2794     {
2795       outf_p f = get_output_file_with_visibility (v->line.file);
2796       struct flist *fli;
2797       const char *if_marked = NULL;
2798       int length_p = 0;
2799       options_p o;
2800
2801       for (o = v->opt; o; o = o->next)
2802         if (strcmp (o->name, "length") == 0)
2803           length_p = 1;
2804         else if (strcmp (o->name, "if_marked") == 0)
2805           if_marked = (const char *) o->info;
2806
2807       if (if_marked == NULL)
2808         continue;
2809
2810       if (v->type->kind != TYPE_POINTER
2811           || v->type->u.p->kind != TYPE_PARAM_STRUCT
2812           || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0))
2813         {
2814           error_at_line (&v->line, "if_marked option used but not hash table");
2815           continue;
2816         }
2817
2818       for (fli = flp; fli; fli = fli->next)
2819         if (fli->f == f)
2820           break;
2821       if (! fli->started_p)
2822         {
2823           fli->started_p = 1;
2824
2825           oprintf (f, "const struct ggc_cache_tab gt_ggc_rc_");
2826           put_mangled_filename (f, v->line.file);
2827           oprintf (f, "[] = {\n");
2828         }
2829
2830       write_root (f, v, v->type->u.p->u.param_struct.param[0],
2831                      v->name, length_p, &v->line, if_marked);
2832     }
2833
2834   finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
2835                      "gt_ggc_cache_rtab");
2836
2837   for (v = variables; v; v = v->next)
2838     {
2839       outf_p f = get_output_file_with_visibility (v->line.file);
2840       struct flist *fli;
2841       int length_p = 0;
2842       int if_marked_p = 0;
2843       options_p o;
2844
2845       for (o = v->opt; o; o = o->next)
2846         if (strcmp (o->name, "length") == 0)
2847           length_p = 1;
2848         else if (strcmp (o->name, "if_marked") == 0)
2849           if_marked_p = 1;
2850
2851       if (! if_marked_p)
2852         continue;
2853
2854       for (fli = flp; fli; fli = fli->next)
2855         if (fli->f == f)
2856           break;
2857       if (! fli->started_p)
2858         {
2859           fli->started_p = 1;
2860
2861           oprintf (f, "const struct ggc_root_tab gt_pch_rc_");
2862           put_mangled_filename (f, v->line.file);
2863           oprintf (f, "[] = {\n");
2864         }
2865
2866       write_root (f, v, v->type, v->name, length_p, &v->line, NULL);
2867     }
2868
2869   finish_root_table (flp, "pch_rc", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2870                      "gt_pch_cache_rtab");
2871
2872   for (v = variables; v; v = v->next)
2873     {
2874       outf_p f = get_output_file_with_visibility (v->line.file);
2875       struct flist *fli;
2876       int skip_p = 0;
2877       options_p o;
2878
2879       for (o = v->opt; o; o = o->next)
2880         if (strcmp (o->name, "deletable") == 0
2881             || strcmp (o->name, "if_marked") == 0)
2882           skip_p = 1;
2883
2884       if (skip_p)
2885         continue;
2886
2887       if (! contains_scalar_p (v->type))
2888         continue;
2889
2890       for (fli = flp; fli; fli = fli->next)
2891         if (fli->f == f)
2892           break;
2893       if (! fli->started_p)
2894         {
2895           fli->started_p = 1;
2896
2897           oprintf (f, "const struct ggc_root_tab gt_pch_rs_");
2898           put_mangled_filename (f, v->line.file);
2899           oprintf (f, "[] = {\n");
2900         }
2901
2902       oprintf (f, "  { &%s, 1, sizeof (%s), NULL, NULL },\n",
2903                v->name, v->name);
2904     }
2905
2906   finish_root_table (flp, "pch_rs", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
2907                      "gt_pch_scalar_rtab");
2908 }
2909
2910 \f
2911 extern int main (int argc, char **argv);
2912 int
2913 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
2914 {
2915   unsigned i;
2916   static struct fileloc pos = { __FILE__, __LINE__ };
2917   unsigned j;
2918
2919   gen_rtx_next ();
2920
2921   srcdir_len = strlen (srcdir);
2922
2923   do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
2924   do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
2925   do_scalar_typedef ("uint8", &pos);
2926   do_scalar_typedef ("jword", &pos);
2927   do_scalar_typedef ("JCF_u2", &pos);
2928   do_scalar_typedef ("void", &pos);
2929
2930   do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
2931
2932   do_typedef ("HARD_REG_SET", create_array (
2933               create_scalar_type ("unsigned long", strlen ("unsigned long")),
2934               "2"), &pos);
2935
2936   for (i = 0; i < NUM_GT_FILES; i++)
2937     {
2938       int dupflag = 0;
2939       /* Omit if already seen.  */
2940       for (j = 0; j < i; j++)
2941         {
2942           if (!strcmp (all_files[i], all_files[j]))
2943             {
2944               dupflag = 1;
2945               break;
2946             }
2947         }
2948       if (!dupflag)
2949         parse_file (all_files[i]);
2950     }
2951
2952   if (hit_error != 0)
2953     exit (1);
2954
2955   set_gc_used (variables);
2956
2957   open_base_files ();
2958   write_enum_defn (structures, param_structs);
2959   write_types (structures, param_structs, &ggc_wtd);
2960   write_types (structures, param_structs, &pch_wtd);
2961   write_local (structures, param_structs);
2962   write_roots (variables);
2963   write_rtx_next ();
2964   close_output_files ();
2965
2966   return (hit_error != 0);
2967 }