OSDN Git Service

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