OSDN Git Service

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