OSDN Git Service

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