OSDN Git Service

Merge from pch-branch up to tag pch-commit-20020603.
[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 "hconfig.h"
22 #include "system.h"
23 #include <ctype.h>
24 #include "gengtype.h"
25
26 static int hit_error = 0;
27 void
28 error_at_line VPARAMS ((struct fileloc *pos, const char *msg, ...))
29 {
30   VA_OPEN (ap, msg);
31   VA_FIXEDARG (ap, struct fileloc *, pos);
32   VA_FIXEDARG (ap, const char *, msg);
33
34   fprintf (stderr, "%s:%d: ", pos->file, pos->line);
35   vfprintf (stderr, msg, ap);
36   fputc ('\n', stderr);
37   hit_error = 1;
38
39   VA_CLOSE (ap);
40 }
41
42 struct type string_type = {
43   TYPE_STRING, NULL, NULL, GC_USED
44   UNION_INIT_ZERO
45 }; 
46
47 static pair_p typedefs;
48 static type_p structures;
49 static type_p param_structs;
50 static pair_p variables;
51
52 void
53 do_typedef (s, t, pos)
54      const char *s;
55      type_p t;
56      struct fileloc *pos;
57 {
58   pair_p p;
59
60   for (p = typedefs; p != NULL; p = p->next)
61     if (strcmp (p->name, s) == 0)
62       {
63         if (p->type != t)
64           {
65             error_at_line (pos, "type `%s' previously defined", s);
66             error_at_line (&p->line, "previously defined here");
67           }
68         return;
69       }
70
71   p = xmalloc (sizeof (struct pair));
72   p->next = typedefs;
73   p->name = s;
74   p->type = t;
75   p->line = *pos;
76   typedefs = p;
77 }
78
79 type_p
80 resolve_typedef (s, pos)
81      const char *s;
82      struct fileloc *pos;
83 {
84   pair_p p;
85   for (p = typedefs; p != NULL; p = p->next)
86     if (strcmp (p->name, s) == 0)
87       return p->type;
88   error_at_line (pos, "unidentified type `%s'", s);
89   return create_scalar_type ("char", 4);
90 }
91
92 void
93 new_structure (name, isunion, pos, fields, o)
94      const char *name;
95      int isunion;
96      struct fileloc *pos;
97      pair_p fields;
98      options_p o;
99 {
100   type_p si;
101   type_p s = NULL;
102   lang_bitmap bitmap = get_base_file_bitmap (pos->file);
103
104   for (si = structures; si != NULL; si = si->next)
105     if (strcmp (name, si->u.s.tag) == 0 
106         && UNION_P (si) == isunion)
107       {
108         type_p ls = NULL;
109         if (si->kind == TYPE_LANG_STRUCT)
110           {
111             ls = si;
112             
113             for (si = ls->u.s.lang_struct; si != NULL; si = si->next)
114               if (si->u.s.bitmap == bitmap)
115                 s = si;
116           }
117         else if (si->u.s.line.file != NULL && si->u.s.bitmap != bitmap)
118           {
119             ls = si;
120             si = xcalloc (1, sizeof (struct type));
121             memcpy (si, ls, sizeof (struct type));
122             ls->kind = TYPE_LANG_STRUCT;
123             ls->u.s.lang_struct = si;
124             ls->u.s.fields = NULL;
125             si->next = NULL;
126             si->pointer_to = NULL;
127             si->u.s.lang_struct = ls;
128           }
129         else
130           s = si;
131
132         if (ls != NULL && s == NULL)
133           {
134             s = xcalloc (1, sizeof (struct type));
135             s->next = ls->u.s.lang_struct;
136             ls->u.s.lang_struct = s;
137             s->u.s.lang_struct = ls;
138           }
139         break;
140       }
141   
142   if (s == NULL)
143     {
144       s = xcalloc (1, sizeof (struct type));
145       s->next = structures;
146       structures = s;
147     }
148
149   if (s->u.s.line.file != NULL
150       || (s->u.s.lang_struct && (s->u.s.lang_struct->u.s.bitmap & bitmap)))
151     {
152       error_at_line (pos, "duplicate structure definition");
153       error_at_line (&s->u.s.line, "previous definition here");
154     }
155
156   s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
157   s->u.s.tag = name;
158   s->u.s.line = *pos;
159   s->u.s.fields = fields;
160   s->u.s.opt = o;
161   s->u.s.bitmap = bitmap;
162   if (s->u.s.lang_struct)
163     s->u.s.lang_struct->u.s.bitmap |= bitmap;
164 }
165
166 type_p
167 find_structure (name, isunion)
168      const char *name;
169      int isunion;
170 {
171   type_p s;
172
173   for (s = structures; s != NULL; s = s->next)
174     if (strcmp (name, s->u.s.tag) == 0 
175         && UNION_P (s) == isunion)
176       return s;
177
178   s = xcalloc (1, sizeof (struct type));
179   s->next = structures;
180   structures = s;
181   s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
182   s->u.s.tag = name;
183   structures = s;
184   return s;
185 }
186
187 type_p
188 create_scalar_type (name, name_len)
189      const char *name;
190      size_t name_len;
191 {
192   type_p r = xcalloc (1, sizeof (struct type));
193   r->kind = TYPE_SCALAR;
194   r->u.sc = xmemdup (name, name_len, name_len + 1);
195   return r;
196 }
197
198 type_p
199 create_pointer (t)
200      type_p t;
201 {
202   if (! t->pointer_to)
203     {
204       type_p r = xcalloc (1, sizeof (struct type));
205       r->kind = TYPE_POINTER;
206       r->u.p = t;
207       t->pointer_to = r;
208     }
209   return t->pointer_to;
210 }
211
212 type_p
213 create_array (t, len)
214      type_p t;
215      const char *len;
216 {
217   type_p v;
218   
219   v = xcalloc (1, sizeof (*v));
220   v->kind = TYPE_ARRAY;
221   v->u.a.p = t;
222   v->u.a.len = len;
223   return v;
224 }
225
226 type_p
227 adjust_field_type (t, opt)
228      type_p t;
229      options_p opt;
230 {
231   int length_p = 0;
232   const int pointer_p = t->kind == TYPE_POINTER;
233   
234   for (; opt; opt = opt->next)
235     if (strcmp (opt->name, "length") == 0)
236       length_p = 1;
237     else if (strcmp (opt->name, "param_is") == 0)
238       {
239         type_p realt;
240
241         if (pointer_p)
242           t = t->u.p;
243         
244         for (realt = param_structs; realt; realt = realt->next)
245           if (realt->u.param_struct.stru == t
246               && realt->u.param_struct.param == (type_p) opt->info)
247             return pointer_p ? create_pointer (realt) : realt;
248         realt = xcalloc (1, sizeof (*realt));
249         realt->kind = TYPE_PARAM_STRUCT;
250         realt->next = param_structs;
251         param_structs = realt;
252         realt->u.param_struct.stru = t;
253         realt->u.param_struct.param = (type_p) opt->info;
254         return pointer_p ? create_pointer (realt) : realt;
255       }
256   
257   if (! length_p
258       && pointer_p
259       && t->u.p->kind == TYPE_SCALAR
260       && (strcmp (t->u.p->u.sc, "char") == 0
261           || strcmp (t->u.p->u.sc, "unsigned char") == 0))
262     return &string_type;
263   if (t->kind == TYPE_ARRAY && t->u.a.p->kind == TYPE_POINTER
264       && t->u.a.p->u.p->kind == TYPE_SCALAR
265       && (strcmp (t->u.a.p->u.p->u.sc, "char") == 0
266           || strcmp (t->u.a.p->u.p->u.sc, "unsigned char") == 0))
267     return create_array (&string_type, t->u.a.len);
268
269   return t;
270 }
271
272 void
273 note_variable (s, t, o, pos)
274      const char *s;
275      type_p t;
276      options_p o;
277      struct fileloc *pos;
278 {
279   pair_p n;
280   n = xmalloc (sizeof (*n));
281   n->name = s;
282   n->type = t;
283   n->line = *pos;
284   n->opt = o;
285   n->next = variables;
286   variables = n;
287 }
288
289 void
290 note_yacc_type (o, fields, typeinfo, pos)
291      options_p o;
292      pair_p fields;
293      pair_p typeinfo;
294      struct fileloc *pos;
295 {
296   pair_p p;
297   pair_p *p_p;
298   
299   for (p = typeinfo; p; p = p->next)
300     {
301       pair_p m;
302       
303       if (p->name == NULL)
304         continue;
305
306       if (p->type == (type_p) 1)
307         {
308           pair_p pp;
309           int ok = 0;
310           
311           for (pp = typeinfo; pp; pp = pp->next)
312             if (pp->type != (type_p) 1
313                 && strcmp (pp->opt->info, p->opt->info) == 0)
314               {
315                 ok = 1;
316                 break;
317               }
318           if (! ok)
319             continue;
320         }
321
322       for (m = fields; m; m = m->next)
323         if (strcmp (m->name, p->name) == 0)
324           p->type = m->type;
325       if (p->type == NULL)
326         {
327           error_at_line (&p->line, 
328                          "couldn't match fieldname `%s'", p->name);
329           p->name = NULL;
330         }
331     }
332   
333   p_p = &typeinfo;
334   while (*p_p)
335     {
336       pair_p p = *p_p;
337
338       if (p->name == NULL
339           || p->type == (type_p) 1)
340         *p_p = p->next;
341       else
342         p_p = &p->next;
343     }
344
345   new_structure ("yy_union", 1, pos, typeinfo, o);
346   do_typedef ("YYSTYPE", find_structure ("yy_union", 1), pos);
347 }
348 \f
349 static void process_gc_options PARAMS ((options_p, enum gc_used_enum, int *));
350 static void set_gc_used_type PARAMS ((type_p, enum gc_used_enum));
351 static void set_gc_used PARAMS ((pair_p));
352
353 static void
354 process_gc_options (opt, level, maybe_undef)
355      options_p opt;
356      enum gc_used_enum level;
357      int *maybe_undef;
358 {
359   options_p o;
360   for (o = opt; o; o = o->next)
361     if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO)
362       set_gc_used_type ((type_p) o->info, GC_POINTED_TO);
363     else if (strcmp (o->name, "maybe_undef") == 0)
364       *maybe_undef = 1;
365 }
366
367 static void
368 set_gc_used_type (t, level)
369      type_p t;
370      enum gc_used_enum level;
371 {
372   if (t->gc_used >= level)
373     return;
374
375   t->gc_used = level;
376
377   switch (t->kind)
378     {
379     case TYPE_STRUCT:
380     case TYPE_UNION:
381       {
382         pair_p f;
383         int dummy;
384
385         process_gc_options (t->u.s.opt, level, &dummy);
386
387         for (f = t->u.s.fields; f; f = f->next)
388           {
389             int maybe_undef = 0;
390             process_gc_options (t->u.s.opt, level, &maybe_undef);
391             
392             if (maybe_undef && f->type->kind == TYPE_POINTER)
393               set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO);
394             else
395               set_gc_used_type (f->type, GC_USED);
396           }
397         break;
398       }
399
400     case TYPE_POINTER:
401       set_gc_used_type (t->u.p, GC_POINTED_TO);
402       break;
403
404     case TYPE_ARRAY:
405       set_gc_used_type (t->u.a.p, GC_USED);
406       break;
407       
408     case TYPE_LANG_STRUCT:
409       for (t = t->u.s.lang_struct; t; t = t->next)
410         set_gc_used_type (t, level);
411       break;
412
413     case TYPE_PARAM_STRUCT:
414       set_gc_used_type (t->u.param_struct.param, GC_POINTED_TO);
415       set_gc_used_type (t->u.param_struct.stru, GC_USED);
416       break;
417
418     default:
419       break;
420     }
421 }
422
423 static void
424 set_gc_used (variables)
425      pair_p variables;
426 {
427   pair_p p;
428   for (p = variables; p; p = p->next)
429     set_gc_used_type (p->type, GC_USED);
430 }
431 \f
432 /* File mapping routines.  For each input file, there is one output .c file
433    (but some output files have many input files), and there is one .h file
434    for the whole build.  */
435
436 typedef struct filemap *filemap_p;
437
438 struct filemap {
439   filemap_p next;
440   const char *input_name;
441   const char *output_name;
442   FILE *output;
443 };
444
445 static filemap_p files;
446 FILE * header_file;
447
448 enum {
449   BASE_FILE_C,
450   BASE_FILE_OBJC,
451   BASE_FILE_CPLUSPLUS
452 };
453 static const char *lang_names[] = {
454   "c", "objc", "cp", "f", "ada", "java"
455 };
456 #define NUM_BASE_FILES (sizeof (lang_names) / sizeof (lang_names[0]))
457 FILE *base_files[NUM_BASE_FILES];
458
459 static FILE * create_file PARAMS ((const char *));
460 static const char * get_file_basename PARAMS ((const char *));
461
462 static FILE *
463 create_file (name)
464      const char *name;
465 {
466   static const char *const hdr[] = {
467     "   Copyright (C) 2002 Free Software Foundation, Inc.\n",
468     "\n",
469     "This file is part of GCC.\n",
470     "\n",
471     "GCC is free software; you can redistribute it and/or modify it under\n",
472     "the terms of the GNU General Public License as published by the Free\n",
473     "Software Foundation; either version 2, or (at your option) any later\n",
474     "version.\n",
475     "\n",
476     "GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n",
477     "WARRANTY; without even the implied warranty of MERCHANTABILITY or\n",
478     "FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n",
479     "for more details.\n",
480     "\n",
481     "You should have received a copy of the GNU General Public License\n",
482     "along with GCC; see the file COPYING.  If not, write to the Free\n",
483     "Software Foundation, 59 Temple Place - Suite 330, Boston, MA\n",
484     "02111-1307, USA.  */\n",
485     "\n",
486     "/* This file is machine generated.  Do not edit.  */\n"
487   };
488   FILE *f;
489   size_t i;
490   
491   f = tmpfile();
492   if (f == NULL)
493     {
494       perror ("couldn't create temporary file");
495       exit (1);
496     }
497   fprintf (f, "/* Type information for %s.\n", name);
498   for (i = 0; i < sizeof(hdr)/sizeof(hdr[0]); i++)
499     fputs (hdr[i], f);
500   return f;
501 }
502
503 static void
504 open_base_files (void)
505 {
506   size_t i;
507   
508   header_file = create_file ("GCC");
509
510   for (i = 0; i < NUM_BASE_FILES; i++)
511     {
512       filemap_p newf;
513       char *s;
514       
515       base_files[i] = create_file (lang_names[i]);
516       newf = xmalloc (sizeof (*newf));
517       newf->next = files;
518       files = newf;
519       newf->input_name = NULL;
520       newf->output = base_files[i];
521       newf->output_name = s = xmalloc (16);
522       sprintf (s, "gtype-%s.h", lang_names[i]);
523     }
524 }
525
526 #define startswith(len, c, s)  \
527   ((size_t)(len) >= strlen (s) && memcmp (c, s, strlen (s)) == 0)
528
529 static const char *
530 get_file_basename (f)
531      const char *f;
532 {
533   size_t len;
534   const char *basename;
535   
536   /* Determine the output file name.  */
537   len = strlen (f);
538   basename = strrchr (f, '/');
539   if (basename == NULL)
540     basename = f;
541   else
542     basename++;
543   if (startswith (basename - f, basename-2, "f/"))
544     basename -= 2;
545   else if (startswith (basename - f, basename-3, "cp/"))
546     basename -= 3;
547   else if (startswith (basename - f, basename-4, "ada/"))
548     basename -= 4;
549   else if (startswith (basename - f, basename-5, "java/"))
550     basename -= 5;
551   else if (startswith (basename - f, basename-5, "objc/"))
552     basename -= 5;
553
554   return basename;
555 }
556
557 unsigned
558 get_base_file_bitmap (input_file)
559      const char *input_file;
560 {
561   const char *basename = get_file_basename (input_file);
562   const char *slashpos = strchr (basename, '/');
563   size_t len = strlen (basename);
564   
565   if (slashpos != NULL)
566     {
567       size_t i;
568       for (i = 0; i < NUM_BASE_FILES; i++)
569         if ((size_t)(slashpos - basename) == strlen (lang_names [i])
570             && memcmp (basename, lang_names[i], strlen (lang_names[i])) == 0)
571           return 1 << i;
572     }
573   else if (strcmp (basename, "c-lang.c") == 0)
574     return 1 << BASE_FILE_C;
575   else if (strcmp (basename, "c-parse.in") == 0
576            || strcmp (basename, "c-tree.h") == 0
577            || strcmp (basename, "c-decl.c") == 0
578            || strcmp (basename, "c-objc-common.c") == 0)
579     return 1 << BASE_FILE_C | 1 << BASE_FILE_OBJC;
580   else if (startswith (len, basename, "c-"))
581     return 1 << BASE_FILE_C | 1 << BASE_FILE_OBJC | 1 << BASE_FILE_CPLUSPLUS;
582   else
583     return (1 << NUM_BASE_FILES) - 1;
584   abort ();
585 }
586
587 FILE *
588 get_output_file_with_visibility (input_file)
589      const char *input_file;
590 {
591   filemap_p fm, fmo;
592   size_t len;
593   const char *basename;
594
595   /* Do we already know the file?  */
596   for (fm = files; fm; fm = fm->next)
597     if (input_file == fm->input_name)
598       return fm->output;
599
600   /* No, we'll be creating a new filemap.  */
601   fm = xmalloc (sizeof (*fm));
602   fm->next = files;
603   files = fm;
604   fm->input_name = input_file;
605   
606   /* Determine the output file name.  */
607   basename = get_file_basename (input_file);
608
609   len = strlen (basename);
610   if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0)
611       || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
612       || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
613     {
614       char *s;
615       
616       fm->output_name = s = xmalloc (sizeof ("gt-") + len);
617       sprintf (s, "gt-%s", basename);
618       for (; *s != '.'; s++)
619         if (! isalnum (*s) && *s != '-')
620           *s = '-';
621       memcpy (s, ".h", sizeof (".h"));
622     }
623   else if (strcmp (basename, "c-common.h") == 0)
624     fm->output_name = "gt-c-common.h";
625   else if (strcmp (basename, "c-tree.h") == 0)
626     fm->output_name = "gt-c-decl.h";
627   else 
628     {
629       size_t i;
630       
631       fm->output_name = "gtype-desc.c";
632       for (i = 0; i < NUM_BASE_FILES; i++)
633         if (memcmp (basename, lang_names[i], strlen (lang_names[i])) == 0
634             && basename[strlen(lang_names[i])] == '/')
635           {
636             char *s;
637             
638             s = xmalloc (16);
639             sprintf (s, "gtype-%s.h", lang_names[i]);
640             fm->output_name = s;
641             break;
642           }
643     }
644
645   /* Look through to see if we've ever seen this output filename before.  */
646   for (fmo = fm->next; fmo; fmo = fmo->next)
647     if (strcmp (fmo->output_name, fm->output_name) == 0)
648       {
649         fm->output = fmo->output;
650         break;
651       }
652
653   /* If not, create it.  */
654   if (fmo == NULL)
655     {
656       fm->output = create_file (fm->output_name);
657       if (strcmp (fm->output_name, "gtype-desc.c") == 0)
658         {
659           fputs ("#include \"config.h\"\n", fm->output);
660           fputs ("#include \"system.h\"\n", fm->output);
661           fputs ("#include \"varray.h\"\n", fm->output);
662           fputs ("#include \"hashtab.h\"\n", fm->output);
663           fputs ("#include \"bitmap.h\"\n", fm->output);
664           fputs ("#include \"tree.h\"\n", fm->output);
665           fputs ("#include \"rtl.h\"\n", fm->output);
666           fputs ("#include \"function.h\"\n", fm->output);
667           fputs ("#include \"insn-config.h\"\n", fm->output);
668           fputs ("#include \"expr.h\"\n", fm->output);
669           fputs ("#include \"hard-reg-set.h\"\n", fm->output);
670           fputs ("#include \"basic-block.h\"\n", fm->output);
671           fputs ("#include \"cselib.h\"\n", fm->output);
672           fputs ("#include \"insn-addr.h\"\n", fm->output);
673           fputs ("#include \"ssa.h\"\n", fm->output);
674           fputs ("#include \"optabs.h\"\n", fm->output);
675           fputs ("#include \"libfuncs.h\"\n", fm->output);
676           fputs ("#include \"debug.h\"\n", fm->output);
677           fputs ("#include \"ggc.h\"\n", fm->output);
678         }
679     }
680
681   return fm->output;
682 }
683
684 const char *
685 get_output_file_name (input_file)
686      const char *input_file;
687 {
688   filemap_p fm;
689
690   for (fm = files; fm; fm = fm->next)
691     if (input_file == fm->input_name)
692       return fm->output_name;
693   (void) get_output_file_with_visibility (input_file);
694   return get_output_file_name (input_file);
695 }
696
697 static void
698 close_output_files PARAMS ((void))
699 {
700   filemap_p fm;
701   struct filemap header;
702   header.next = files;
703   header.output_name = "gtype-desc.h";
704   header.output = header_file;
705   
706   for (fm = &header; fm; fm = fm->next)
707     {
708       int no_write_p;
709       filemap_p ofm;
710       FILE *newfile;
711       
712       /* Handle each output file once.  */
713       if (fm->output == NULL)
714         continue;
715       
716       for (ofm = fm->next; ofm; ofm = ofm->next)
717         if (fm->output == ofm->output)
718           ofm->output = NULL;
719       
720       /* Compare the output file with the file to be created, avoiding
721          unnecessarily changing timestamps.  */
722       newfile = fopen (fm->output_name, "r");
723       if (newfile != NULL)
724         {
725           int ch1, ch2;
726           
727           rewind (fm->output);
728           do {
729             ch1 = fgetc (fm->output);
730             ch2 = fgetc (newfile);
731           } while (ch1 != EOF && ch1 == ch2);
732
733           fclose (newfile);
734           
735           no_write_p = ch1 == ch2;
736         }
737       else
738         no_write_p = 0;
739      
740       /* Nothing interesting to do.  Close the output file.  */
741       if (no_write_p)
742         {
743           fclose (fm->output);
744           continue;
745         }
746
747       newfile = fopen (fm->output_name, "w");
748       if (newfile == NULL)
749         {
750           perror ("opening output file");
751           exit (1);
752         }
753       {
754         int ch;
755         rewind (fm->output);
756         while ((ch = fgetc (fm->output)) != EOF)
757           fputc (ch, newfile);
758       }
759       fclose (newfile);
760       fclose (fm->output);
761     }
762 }
763 \f
764 struct flist {
765   struct flist *next;
766   int started_p;
767   const char *name;
768   FILE *f;
769 };
770
771 static void output_escaped_param PARAMS ((FILE *, const char *, const char *,
772                                           const char *, const char *,
773                                           struct fileloc *));
774 static void write_gc_structure_fields 
775   PARAMS ((FILE *, type_p, const char *, const char *, options_p, 
776            int, struct fileloc *, lang_bitmap, type_p));
777 static void write_gc_marker_routine_for_structure PARAMS ((type_p, type_p));
778 static void write_gc_types PARAMS ((type_p structures, type_p param_structs));
779 static void put_mangled_filename PARAMS ((FILE *, const char *));
780 static void finish_root_table PARAMS ((struct flist *flp, const char *pfx, 
781                                        const char *tname, const char *lastname,
782                                        const char *name));
783 static void write_gc_root PARAMS ((FILE *, pair_p, type_p, const char *, int,
784                                    struct fileloc *, const char *));
785 static void write_gc_roots PARAMS ((pair_p));
786
787 static int gc_counter;
788
789 static void
790 output_escaped_param (of, param, val, prev_val, oname, line)
791      FILE *of;
792      const char *param;
793      const char *val;
794      const char *prev_val;
795      const char *oname;
796      struct fileloc *line;
797 {
798   const char *p;
799   
800   for (p = param; *p; p++)
801     if (*p != '%')
802       fputc (*p, of);
803     else if (*++p == 'h')
804       fprintf (of, "(%s)", val);
805     else if (*p == '0')
806       fputs ("(*x)", of);
807     else if (*p == '1')
808       fprintf (of, "(%s)", prev_val);
809     else
810       error_at_line (line, "`%s' option contains bad escape %c%c",
811                      oname, '%', *p);
812 }
813
814 static void
815 write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
816                            param)
817      FILE *of;
818      type_p s;
819      const char *val;
820      const char *prev_val;
821      options_p opts;
822      int indent;
823      struct fileloc *line;
824      lang_bitmap bitmap;
825      type_p param;
826 {
827   pair_p f;
828   int tagcounter = -1;
829
830   if (! s->u.s.line.file)
831     error_at_line (line, "incomplete structure `%s'", s->u.s.tag);
832   else if ((s->u.s.bitmap & bitmap) != bitmap)
833     {
834       error_at_line (line, "structure defined for mismatching languages");
835       error_at_line (&s->u.s.line, "one structure defined here");
836     }
837   
838   if (s->kind == TYPE_UNION)
839     {
840       const char *tagexpr = NULL;
841       options_p oo;
842       
843       tagcounter = ++gc_counter;
844       for (oo = opts; oo; oo = oo->next)
845         if (strcmp (oo->name, "desc") == 0)
846           tagexpr = (const char *)oo->info;
847       if (tagexpr == NULL)
848         {
849           tagexpr = "1";
850           error_at_line (line, "missing `desc' option");
851         }
852
853       fprintf (of, "%*s{\n", indent, "");
854       indent += 2;
855       fprintf (of, "%*sunsigned int tag%d = (", indent, "", tagcounter);
856       output_escaped_param (of, tagexpr, val, prev_val, "desc", line);
857       fputs (");\n", of);
858     }
859   
860   for (f = s->u.s.fields; f; f = f->next)
861     {
862       const char *tagid = NULL;
863       const char *length = NULL;
864       const char *special = NULL;
865       int skip_p = 0;
866       int always_p = 0;
867       int maybe_undef_p = 0;
868       int use_param_p = 0;
869       options_p oo;
870       type_p t = f->type;
871       
872       if (t->kind == TYPE_SCALAR
873           || (t->kind == TYPE_ARRAY 
874               && t->u.a.p->kind == TYPE_SCALAR))
875         continue;
876       
877       for (oo = f->opt; oo; oo = oo->next)
878         if (strcmp (oo->name, "length") == 0)
879           length = (const char *)oo->info;
880         else if (strcmp (oo->name, "maybe_undef") == 0)
881           maybe_undef_p = 1;
882         else if (strcmp (oo->name, "tag") == 0)
883           tagid = (const char *)oo->info;
884         else if (strcmp (oo->name, "special") == 0)
885           special = (const char *)oo->info;
886         else if (strcmp (oo->name, "skip") == 0)
887           skip_p = 1;
888         else if (strcmp (oo->name, "always") == 0)
889           always_p = 1;
890         else if (strcmp (oo->name, "desc") == 0 && UNION_P (t))
891           ;
892         else if (strcmp (oo->name, "descbits") == 0 && UNION_P (t))
893           ;
894         else if (strcmp (oo->name, "param_is") == 0)
895           ;
896         else if (strcmp (oo->name, "use_param") == 0)
897           use_param_p = 1;
898         else
899           error_at_line (&f->line, "unknown field option `%s'\n", oo->name);
900
901       if (skip_p)
902         continue;
903       
904       if (use_param_p)
905         {
906           if (param != NULL)
907             {
908               type_p t1;
909               type_p nt = param;
910               int arraycount = 0;
911               
912               for (t1 = t; t->kind == TYPE_ARRAY; t = t->u.a.p)
913                 arraycount++;
914               for (; t->kind == TYPE_POINTER; t = t->u.p)
915                 nt = create_pointer (nt);
916               while (arraycount-- > 0)
917                 nt = create_array (nt, t->u.a.len);
918               t = nt;
919             }
920           else if (s->kind == TYPE_UNION && ! always_p && tagid)
921             ;
922           else
923             error_at_line (&f->line, "no parameter defined");
924         }
925
926       if (maybe_undef_p
927           && (t->kind != TYPE_POINTER
928               || t->u.p->kind != TYPE_STRUCT))
929         error_at_line (&f->line, 
930                        "field `%s' has invalid option `maybe_undef_p'\n",
931                        f->name);
932       if (s->kind == TYPE_UNION && ! always_p )
933         {
934           if (! tagid)
935             {
936               error_at_line (&f->line, "field `%s' has no tag", f->name);
937               continue;
938             }
939           fprintf (of, "%*sif (tag%d == (%s)) {\n", indent, "", 
940                    tagcounter, tagid);
941           indent += 2;
942         }
943       
944       switch (t->kind)
945         {
946         case TYPE_STRING:
947           /* Do nothing; strings go in the string pool.  */
948           break;
949
950         case TYPE_LANG_STRUCT:
951           {
952             type_p ti;
953             for (ti = t->u.s.lang_struct; ti; ti = ti->next)
954               if (ti->u.s.bitmap & bitmap)
955                 {
956                   t = ti;
957                   break;
958                 }
959             if (ti == NULL)
960               {
961                 error_at_line (&f->line, 
962                                "structure not defined for this language");
963                 break;
964               }
965           }
966           /* Fall through... */
967         case TYPE_STRUCT:
968         case TYPE_UNION:
969           {
970             char *newval;
971
972             newval = xmalloc (strlen (val) + sizeof (".") + strlen (f->name));
973             sprintf (newval, "%s.%s", val, f->name);
974             write_gc_structure_fields (of, t, newval, val, f->opt, indent, 
975                                        &f->line, bitmap, param);
976             free (newval);
977             break;
978           }
979
980         case TYPE_POINTER:
981           if (! length)
982             {
983               if (maybe_undef_p
984                   && t->u.p->u.s.line.file == NULL)
985                 fprintf (of, "%*sif (%s.%s) abort();\n", indent, "",
986                          val, f->name);
987               else if (UNION_OR_STRUCT_P (t->u.p))
988                 fprintf (of, "%*sgt_ggc_m_%s (%s.%s);\n", indent, "", 
989                          t->u.p->u.s.tag, val, f->name);
990               else if (t->u.p->kind == TYPE_PARAM_STRUCT)
991                 fprintf (of, "%*sgt_ggc_mm_%d%s_%s (%s.%s);\n", indent, "",
992                          (int) strlen (t->u.p->u.param_struct.param->u.s.tag),
993                          t->u.p->u.param_struct.param->u.s.tag,
994                          t->u.p->u.param_struct.stru->u.s.tag,
995                          val, f->name);
996               else
997                 error_at_line (&f->line, "field `%s' is pointer to scalar",
998                                f->name);
999               break;
1000             }
1001           else if (t->u.p->kind == TYPE_SCALAR
1002                    || t->u.p->kind == TYPE_STRING)
1003             fprintf (of, "%*sggc_mark (%s.%s);\n", indent, "", 
1004                      val, f->name);
1005           else
1006             {
1007               int loopcounter = ++gc_counter;
1008               
1009               fprintf (of, "%*sif (%s.%s != NULL) {\n", indent, "",
1010                        val, f->name);
1011               indent += 2;
1012               fprintf (of, "%*ssize_t i%d;\n", indent, "", loopcounter);
1013               fprintf (of, "%*sggc_set_mark (%s.%s);\n", indent, "", 
1014                        val, f->name);
1015               fprintf (of, "%*sfor (i%d = 0; i%d < (", indent, "", 
1016                        loopcounter, loopcounter);
1017               output_escaped_param (of, length, val, prev_val, "length", line);
1018               fprintf (of, "); i%d++) {\n", loopcounter);
1019               indent += 2;
1020               switch (t->u.p->kind)
1021                 {
1022                 case TYPE_STRUCT:
1023                 case TYPE_UNION:
1024                   {
1025                     char *newval;
1026                     
1027                     newval = xmalloc (strlen (val) + 8 + strlen (f->name));
1028                     sprintf (newval, "%s.%s[i%d]", val, f->name, loopcounter);
1029                     write_gc_structure_fields (of, t->u.p, newval, val,
1030                                                f->opt, indent, &f->line,
1031                                                bitmap, param);
1032                     free (newval);
1033                     break;
1034                   }
1035                 case TYPE_POINTER:
1036                   if (UNION_OR_STRUCT_P (t->u.p->u.p))
1037                     fprintf (of, "%*sgt_ggc_m_%s (%s.%s[i%d]);\n", indent, "", 
1038                              t->u.p->u.p->u.s.tag, val, f->name,
1039                              loopcounter);
1040                   else
1041                     error_at_line (&f->line, 
1042                                    "field `%s' is array of pointer to scalar",
1043                                    f->name);
1044                   break;
1045                 default:
1046                   error_at_line (&f->line, 
1047                                  "field `%s' is array of unimplemented type",
1048                                  f->name);
1049                   break;
1050                 }
1051               indent -= 2;
1052               fprintf (of, "%*s}\n", indent, "");
1053               indent -= 2;
1054               fprintf (of, "%*s}\n", indent, "");
1055             }
1056           break;
1057
1058         case TYPE_ARRAY:
1059           {
1060             int loopcounter = ++gc_counter;
1061             type_p ta;
1062             int i;
1063
1064             if (! length &&
1065                 (strcmp (t->u.a.len, "0") == 0
1066                  || strcmp (t->u.a.len, "1") == 0))
1067               error_at_line (&f->line, 
1068                              "field `%s' is array of size %s",
1069                              f->name, t->u.a.len);
1070             
1071             /* Arrays of scalars can be ignored.  */
1072             for (ta = t; ta->kind == TYPE_ARRAY; ta = ta->u.a.p)
1073               ;
1074             if (ta->kind == TYPE_SCALAR
1075                 || ta->kind == TYPE_STRING)
1076               break;
1077
1078             fprintf (of, "%*s{\n", indent, "");
1079             indent += 2;
1080
1081             if (special != NULL && strcmp (special, "tree_exp") == 0)
1082               {
1083                 fprintf (of, "%*sconst size_t tree_exp_size = (",
1084                          indent, "");
1085                 output_escaped_param (of, length, val, prev_val,
1086                                       "length", line);
1087                 fputs (");\n", of);
1088
1089                 length = "first_rtl_op (TREE_CODE ((tree)&%h))";
1090               }
1091
1092             for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
1093               {
1094                 fprintf (of, "%*ssize_t i%d_%d;\n", 
1095                          indent, "", loopcounter, i);
1096                 fprintf (of, "%*sconst size_t ilimit%d_%d = (",
1097                          indent, "", loopcounter, i);
1098                 if (i == 0 && length != NULL)
1099                   output_escaped_param (of, length, val, prev_val, 
1100                                         "length", line);
1101                 else
1102                   fputs (ta->u.a.len, of);
1103                 fputs (");\n", of);
1104               }
1105                 
1106             for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
1107               {
1108                 fprintf (of, 
1109                  "%*sfor (i%d_%d = 0; i%d_%d < ilimit%d_%d; i%d_%d++) {\n",
1110                          indent, "", loopcounter, i, loopcounter, i,
1111                          loopcounter, i, loopcounter, i);
1112                 indent += 2;
1113               }
1114
1115             if (ta->kind == TYPE_POINTER
1116                 && (ta->u.p->kind == TYPE_STRUCT
1117                     || ta->u.p->kind == TYPE_UNION))
1118               {
1119                 fprintf (of, "%*sgt_ggc_m_%s (%s.%s", 
1120                          indent, "", ta->u.p->u.s.tag, val, f->name);
1121                 for (ta = t, i = 0; 
1122                      ta->kind == TYPE_ARRAY; 
1123                      ta = ta->u.a.p, i++)
1124                   fprintf (of, "[i%d_%d]", loopcounter, i);
1125                 fputs (");\n", of);
1126               }
1127             else if (ta->kind == TYPE_STRUCT || ta->kind == TYPE_UNION)
1128               {
1129                 char *newval;
1130                 int len;
1131                 
1132                 len = strlen (val) + strlen (f->name) + 2;
1133                 for (ta = t; ta->kind == TYPE_ARRAY; ta = ta->u.a.p)
1134                   len += sizeof ("[i_]") + 2*6;
1135                 
1136                 newval = xmalloc (len);
1137                 sprintf (newval, "%s.%s", val, f->name);
1138                 for (ta = t, i = 0; 
1139                      ta->kind == TYPE_ARRAY; 
1140                      ta = ta->u.a.p, i++)
1141                   sprintf (newval + strlen (newval), "[i%d_%d]", 
1142                            loopcounter, i);
1143                 write_gc_structure_fields (of, t->u.p, newval, val,
1144                                            f->opt, indent, &f->line, bitmap,
1145                                            param);
1146                 free (newval);
1147               }
1148             else if (ta->kind == TYPE_POINTER && ta->u.p->kind == TYPE_SCALAR
1149                      && use_param_p && param == NULL)
1150               fprintf (of, "%*sabort();\n", indent, "");
1151             else
1152               error_at_line (&f->line, 
1153                              "field `%s' is array of unimplemented type",
1154                              f->name);
1155             for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
1156               {
1157                 indent -= 2;
1158                 fprintf (of, "%*s}\n", indent, "");
1159               }
1160
1161             if (special != NULL && strcmp (special, "tree_exp") == 0)
1162               {
1163                 fprintf (of, 
1164                  "%*sfor (; i%d_0 < tree_exp_size; i%d_0++)\n",
1165                          indent, "", loopcounter, loopcounter);
1166                 fprintf (of, "%*s  gt_ggc_m_rtx_def (%s.%s[i%d_0]);\n",
1167                          indent, "", val, f->name, loopcounter);
1168                 special = NULL;
1169               }
1170
1171             indent -= 2;
1172             fprintf (of, "%*s}\n", indent, "");
1173             break;
1174           }
1175
1176         default:
1177           error_at_line (&f->line, 
1178                          "field `%s' is unimplemented type",
1179                          f->name);
1180           break;
1181         }
1182       
1183       if (s->kind == TYPE_UNION && ! always_p )
1184         {
1185           indent -= 2;
1186           fprintf (of, "%*s}\n", indent, "");
1187         }
1188       if (special)
1189         error_at_line (&f->line, "unhandled special `%s'", special);
1190     }
1191   if (s->kind == TYPE_UNION)
1192     {
1193       indent -= 2;
1194       fprintf (of, "%*s}\n", indent, "");
1195     }
1196 }
1197
1198 static void
1199 write_gc_marker_routine_for_structure (s, param)
1200      type_p s;
1201      type_p param;
1202 {
1203   FILE *f;
1204   if (param == NULL)
1205     f = get_output_file_with_visibility (s->u.s.line.file);
1206   else
1207     f = get_output_file_with_visibility (param->u.s.line.file);
1208   
1209   fputc ('\n', f);
1210   fputs ("void\n", f);
1211   if (param == NULL)
1212     fprintf (f, "gt_ggc_mx_%s (x_p)\n", s->u.s.tag);
1213   else
1214     fprintf (f, "gt_ggc_mm_%d%s_%s (x_p)\n", (int) strlen (param->u.s.tag),
1215              param->u.s.tag, s->u.s.tag);
1216   fputs ("      void *x_p;\n", f);
1217   fputs ("{\n", f);
1218   fprintf (f, "  %s %s * const x = (%s %s *)x_p;\n",
1219            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
1220            s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
1221   fputs ("  if (! ggc_test_and_set_mark (x))\n", f);
1222   fputs ("    return;\n", f);
1223   
1224   gc_counter = 0;
1225   write_gc_structure_fields (f, s, "(*x)", "not valid postage",
1226                              s->u.s.opt, 2, &s->u.s.line, s->u.s.bitmap,
1227                              param);
1228   
1229   fputs ("}\n", f);
1230 }
1231      
1232
1233 static void
1234 write_gc_types (structures, param_structs)
1235      type_p structures;
1236      type_p param_structs;
1237 {
1238   type_p s;
1239   
1240   fputs ("\n/* GC marker procedures.  */\n", header_file);
1241   for (s = structures; s; s = s->next)
1242     if (s->gc_used == GC_POINTED_TO
1243         || s->gc_used == GC_MAYBE_POINTED_TO)
1244       {
1245         options_p opt;
1246         
1247         if (s->gc_used == GC_MAYBE_POINTED_TO
1248             && s->u.s.line.file == NULL)
1249           continue;
1250
1251         fprintf (header_file,
1252                  "#define gt_ggc_m_%s(X) do { \\\n", s->u.s.tag);
1253         fprintf (header_file,
1254                  "  if (X != NULL) gt_ggc_mx_%s (X);\\\n", s->u.s.tag);
1255         fprintf (header_file,
1256                  "  } while (0)\n");
1257         
1258         for (opt = s->u.s.opt; opt; opt = opt->next)
1259           if (strcmp (opt->name, "ptr_alias") == 0)
1260             {
1261               type_p t = (type_p) opt->info;
1262               if (t->kind == TYPE_STRUCT 
1263                   || t->kind == TYPE_UNION
1264                   || t->kind == TYPE_LANG_STRUCT)
1265                 fprintf (header_file,
1266                          "#define gt_ggc_mx_%s gt_ggc_mx_%s\n",
1267                          s->u.s.tag, t->u.s.tag);
1268               else
1269                 error_at_line (&s->u.s.line, 
1270                                "structure alias is not a structure");
1271               break;
1272             }
1273         if (opt)
1274           continue;
1275
1276         /* Declare the marker procedure only once.  */
1277         fprintf (header_file, 
1278                  "extern void gt_ggc_mx_%s PARAMS ((void *));\n",
1279                  s->u.s.tag);
1280   
1281         if (s->u.s.line.file == NULL)
1282           {
1283             fprintf (stderr, "warning: structure `%s' used but not defined\n", 
1284                      s->u.s.tag);
1285             continue;
1286           }
1287   
1288         if (s->kind == TYPE_LANG_STRUCT)
1289           {
1290             type_p ss;
1291             for (ss = s->u.s.lang_struct; ss; ss = ss->next)
1292               write_gc_marker_routine_for_structure (ss, NULL);
1293           }
1294         else
1295           write_gc_marker_routine_for_structure (s, NULL);
1296       }
1297
1298   for (s = param_structs; s; s = s->next)
1299     if (s->gc_used == GC_POINTED_TO)
1300       {
1301         type_p param = s->u.param_struct.param;
1302         type_p stru = s->u.param_struct.stru;
1303
1304         if (param->kind != TYPE_STRUCT && param->kind != TYPE_UNION
1305             && param->kind != TYPE_LANG_STRUCT)
1306           {
1307             error_at_line (&s->u.param_struct.line,
1308                            "unsupported parameter type");
1309             continue;
1310           }
1311         
1312         /* Declare the marker procedure.  */
1313         fprintf (header_file, 
1314                  "extern void gt_ggc_mm_%d%s_%s PARAMS ((void *));\n",
1315                  (int) strlen (param->u.s.tag), param->u.s.tag,
1316                  stru->u.s.tag);
1317   
1318         if (stru->u.s.line.file == NULL)
1319           {
1320             fprintf (stderr, "warning: structure `%s' used but not defined\n", 
1321                      s->u.s.tag);
1322             continue;
1323           }
1324   
1325         if (stru->kind == TYPE_LANG_STRUCT)
1326           {
1327             type_p ss;
1328             for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
1329               write_gc_marker_routine_for_structure (ss, param);
1330           }
1331         else
1332           write_gc_marker_routine_for_structure (stru, param);
1333       }
1334 }
1335
1336 static void
1337 put_mangled_filename (f, fn)
1338      FILE *f;
1339      const char *fn;
1340 {
1341   const char *name = get_output_file_name (fn);
1342   for (; *name != 0; name++)
1343     if (isalnum (*name))
1344       fputc (*name, f);
1345     else
1346       fputc ('_', f);
1347 }
1348
1349 static void
1350 finish_root_table (flp, pfx, lastname, tname, name)
1351      struct flist *flp;
1352      const char *pfx;
1353      const char *tname;
1354      const char *lastname;
1355      const char *name;
1356 {
1357   struct flist *fli2;
1358   unsigned started_bitmap = 0;
1359   
1360   for (fli2 = flp; fli2; fli2 = fli2->next)
1361     if (fli2->started_p)
1362       {
1363         fprintf (fli2->f, "  %s\n", lastname);
1364         fputs ("};\n\n", fli2->f);
1365       }
1366
1367   for (fli2 = flp; fli2; fli2 = fli2->next)
1368     if (fli2->started_p)
1369       {
1370         lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
1371         int fnum;
1372
1373         for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
1374           if (bitmap & 1)
1375             {
1376               fprintf (base_files[fnum],
1377                        "extern const struct %s gt_ggc_%s_",
1378                        tname, pfx);
1379               put_mangled_filename (base_files[fnum], fli2->name);
1380               fputs ("[];\n", base_files[fnum]);
1381             }
1382       }
1383
1384   for (fli2 = flp; fli2; fli2 = fli2->next)
1385     if (fli2->started_p)
1386       {
1387         lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
1388         int fnum;
1389
1390         fli2->started_p = 0;
1391
1392         for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
1393           if (bitmap & 1)
1394             {
1395               if (! (started_bitmap & (1 << fnum)))
1396                 {
1397                   fprintf (base_files [fnum],
1398                            "const struct %s * const %s[] = {\n",
1399                            tname, name);
1400                   started_bitmap |= 1 << fnum;
1401                 }
1402               fprintf (base_files[fnum], "  gt_ggc_%s_", pfx);
1403               put_mangled_filename (base_files[fnum], fli2->name);
1404               fputs (",\n", base_files[fnum]);
1405             }
1406       }
1407
1408   {
1409     unsigned bitmap;
1410     int fnum;
1411     
1412     for (bitmap = started_bitmap, fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
1413       if (bitmap & 1)
1414         {
1415           fputs ("  NULL\n", base_files[fnum]);
1416           fputs ("};\n\n", base_files[fnum]);
1417         }
1418   }
1419 }
1420
1421 static void
1422 write_gc_root (f, v, type, name, has_length, line, if_marked)
1423      FILE *f;
1424      pair_p v;
1425      type_p type;
1426      const char *name;
1427      int has_length;
1428      struct fileloc *line;
1429      const char *if_marked;
1430 {
1431   switch (type->kind)
1432     {
1433     case TYPE_STRUCT:
1434       {
1435         pair_p fld;
1436         for (fld = type->u.s.fields; fld; fld = fld->next)
1437           {
1438             int skip_p = 0;
1439             const char *desc = NULL;
1440             options_p o;
1441             
1442             for (o = fld->opt; o; o = o->next)
1443               if (strcmp (o->name, "skip") == 0)
1444                 skip_p = 1;
1445               else if (strcmp (o->name, "desc") == 0)
1446                 desc = (const char *)o->info;
1447               else
1448                 error_at_line (line,
1449                        "field `%s' of global `%s' has unknown option `%s'",
1450                                fld->name, name, o->name);
1451             
1452             if (skip_p)
1453               continue;
1454             else if (desc && fld->type->kind == TYPE_UNION)
1455               {
1456                 pair_p validf = NULL;
1457                 pair_p ufld;
1458                 
1459                 for (ufld = fld->type->u.s.fields; ufld; ufld = ufld->next)
1460                   {
1461                     const char *tag = NULL;
1462                     options_p oo;
1463                     
1464                     for (oo = ufld->opt; oo; oo = oo->next)
1465                       if (strcmp (oo->name, "tag") == 0)
1466                         tag = (const char *)oo->info;
1467                     if (tag == NULL || strcmp (tag, desc) != 0)
1468                       continue;
1469                     if (validf != NULL)
1470                       error_at_line (line, 
1471                            "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'",
1472                                      name, fld->name, validf->name,
1473                                      name, fld->name, ufld->name,
1474                                      tag);
1475                     validf = ufld;
1476                   }
1477                 if (validf != NULL)
1478                   {
1479                     char *newname;
1480                     newname = xmalloc (strlen (name) + 3 + strlen (fld->name)
1481                                        + strlen (validf->name));
1482                     sprintf (newname, "%s.%s.%s", 
1483                              name, fld->name, validf->name);
1484                     write_gc_root (f, v, validf->type, newname, 0, line,
1485                                    if_marked);
1486                     free (newname);
1487                   }
1488               }
1489             else if (desc)
1490               error_at_line (line, 
1491                      "global `%s.%s' has `desc' option but is not union",
1492                              name, fld->name);
1493             else
1494               {
1495                 char *newname;
1496                 newname = xmalloc (strlen (name) + 2 + strlen (fld->name));
1497                 sprintf (newname, "%s.%s", name, fld->name);
1498                 write_gc_root (f, v, fld->type, newname, 0, line, if_marked);
1499                 free (newname);
1500               }
1501           }
1502       }
1503       break;
1504
1505     case TYPE_ARRAY:
1506       {
1507         char *newname;
1508         newname = xmalloc (strlen (name) + 4);
1509         sprintf (newname, "%s[0]", name);
1510         write_gc_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
1511         free (newname);
1512       }
1513       break;
1514       
1515     case TYPE_POINTER:
1516       {
1517         type_p ap, tp;
1518         
1519         fputs ("  {\n", f);
1520         fprintf (f, "    &%s,\n", name);
1521         fputs ("    1", f);
1522         
1523         for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
1524           if (ap->u.a.len[0])
1525             fprintf (f, " * (%s)", ap->u.a.len);
1526           else if (ap == v->type)
1527             fprintf (f, " * (sizeof (%s) / sizeof (%s[0]))",
1528                      v->name, v->name);
1529         fputs (",\n", f);
1530         fprintf (f, "    sizeof (%s", v->name);
1531         for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
1532           fputs ("[0]", f);
1533         fputs ("),\n", f);
1534         
1535         tp = type->u.p;
1536         
1537         if (! has_length && UNION_OR_STRUCT_P (tp))
1538           {
1539             fprintf (f, "    &gt_ggc_mx_%s\n", tp->u.s.tag);
1540           }
1541         else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
1542           {
1543             fprintf (f, "    &gt_ggc_mm_%d%s_%s",
1544                      (int) strlen (tp->u.param_struct.param->u.s.tag),
1545                      tp->u.param_struct.param->u.s.tag,
1546                      tp->u.param_struct.stru->u.s.tag);
1547           }
1548         else if (has_length
1549                  && tp->kind == TYPE_POINTER)
1550           {
1551             fprintf (f, "    &gt_ggc_ma_%s", name);
1552           }
1553         else
1554           {
1555             error_at_line (line, 
1556                            "global `%s' is pointer to unimplemented type",
1557                            name);
1558           }
1559         if (if_marked)
1560           fprintf (f, ",\n    &%s", if_marked);
1561         fputs ("\n  },\n", f);
1562       }
1563       break;
1564
1565     case TYPE_SCALAR:
1566     case TYPE_STRING:
1567       break;
1568       
1569     default:
1570       error_at_line (line, 
1571                      "global `%s' is unimplemented type",
1572                      name);
1573     }
1574 }
1575
1576 static void
1577 write_gc_roots (variables)
1578      pair_p variables;
1579 {
1580   pair_p v;
1581   struct flist *flp = NULL;
1582
1583   for (v = variables; v; v = v->next)
1584     {
1585       FILE *f = get_output_file_with_visibility (v->line.file);
1586       struct flist *fli;
1587       const char *length = NULL;
1588       int deletable_p = 0;
1589       options_p o;
1590
1591       for (o = v->opt; o; o = o->next)
1592         if (strcmp (o->name, "length") == 0)
1593           length = (const char *)o->info;
1594         else if (strcmp (o->name, "deletable") == 0)
1595           deletable_p = 1;
1596         else if (strcmp (o->name, "param_is") == 0)
1597           ;
1598         else if (strcmp (o->name, "if_marked") == 0)
1599           ;
1600         else
1601           error_at_line (&v->line, 
1602                          "global `%s' has unknown option `%s'",
1603                          v->name, o->name);
1604
1605       for (fli = flp; fli; fli = fli->next)
1606         if (fli->f == f)
1607           break;
1608       if (fli == NULL)
1609         {
1610           fli = xmalloc (sizeof (*fli));
1611           fli->f = f;
1612           fli->next = flp;
1613           fli->started_p = 0;
1614           fli->name = v->line.file;
1615           flp = fli;
1616
1617           fputs ("\n/* GC roots.  */\n\n", f);
1618         }
1619
1620       if (! deletable_p
1621           && length
1622           && v->type->kind == TYPE_POINTER
1623           && (v->type->u.p->kind == TYPE_POINTER
1624               || v->type->u.p->kind == TYPE_STRUCT))
1625         {
1626           fprintf (f, "static void gt_ggc_ma_%s PARAMS ((void *));\n",
1627                    v->name);
1628           fprintf (f, "static void\ngt_ggc_ma_%s (x_p)\n      void *x_p;\n",
1629                    v->name);
1630           fputs ("{\n", f);
1631           fputs ("  size_t i;\n", f);
1632
1633           if (v->type->u.p->kind == TYPE_POINTER)
1634             {
1635               type_p s = v->type->u.p->u.p;
1636
1637               fprintf (f, "  %s %s ** const x = (%s %s **)x_p;\n",
1638                        s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
1639                        s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
1640               fputs ("  if (ggc_test_and_set_mark (x))\n", f);
1641               fprintf (f, "    for (i = 0; i < (%s); i++)\n", length);
1642               if (s->kind != TYPE_STRUCT && s->kind != TYPE_UNION)
1643                 {
1644                   error_at_line (&v->line, 
1645                                  "global `%s' has unsupported ** type",
1646                                  v->name);
1647                   continue;
1648                 }
1649
1650               fprintf (f, "      gt_ggc_m_%s (x[i]);\n", s->u.s.tag);
1651             }
1652           else
1653             {
1654               type_p s = v->type->u.p;
1655
1656               fprintf (f, "  %s %s * const x = (%s %s *)x_p;\n",
1657                        s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
1658                        s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
1659               fputs ("  if (ggc_test_and_set_mark (x))\n", f);
1660               fprintf (f, "    for (i = 0; i < (%s); i++)\n", length);
1661               fputs ("      {\n", f);
1662               write_gc_structure_fields (f, s, "x[i]", "x[i]",
1663                                          v->opt, 8, &v->line, s->u.s.bitmap,
1664                                          NULL);
1665               fputs ("      }\n", f);
1666             }
1667
1668           fputs ("}\n\n", f);
1669         }
1670     }
1671
1672   for (v = variables; v; v = v->next)
1673     {
1674       FILE *f = get_output_file_with_visibility (v->line.file);
1675       struct flist *fli;
1676       int skip_p = 0;
1677       int length_p = 0;
1678       options_p o;
1679       
1680       for (o = v->opt; o; o = o->next)
1681         if (strcmp (o->name, "length") == 0)
1682           length_p = 1;
1683         else if (strcmp (o->name, "deletable") == 0
1684                  || strcmp (o->name, "if_marked") == 0)
1685           skip_p = 1;
1686
1687       if (skip_p)
1688         continue;
1689
1690       for (fli = flp; fli; fli = fli->next)
1691         if (fli->f == f)
1692           break;
1693       if (! fli->started_p)
1694         {
1695           fli->started_p = 1;
1696
1697           fputs ("const struct ggc_root_tab gt_ggc_r_", f);
1698           put_mangled_filename (f, v->line.file);
1699           fputs ("[] = {\n", f);
1700         }
1701
1702       write_gc_root (f, v, v->type, v->name, length_p, &v->line, NULL);
1703     }
1704
1705   finish_root_table (flp, "r", "LAST_GGC_ROOT_TAB", "ggc_root_tab", 
1706                      "gt_ggc_rtab");
1707
1708   for (v = variables; v; v = v->next)
1709     {
1710       FILE *f = get_output_file_with_visibility (v->line.file);
1711       struct flist *fli;
1712       int skip_p = 1;
1713       options_p o;
1714
1715       for (o = v->opt; o; o = o->next)
1716         if (strcmp (o->name, "deletable") == 0)
1717           skip_p = 0;
1718         else if (strcmp (o->name, "if_marked") == 0)
1719           skip_p = 1;
1720
1721       if (skip_p)
1722         continue;
1723
1724       for (fli = flp; fli; fli = fli->next)
1725         if (fli->f == f)
1726           break;
1727       if (! fli->started_p)
1728         {
1729           fli->started_p = 1;
1730
1731           fputs ("const struct ggc_root_tab gt_ggc_rd_", f);
1732           put_mangled_filename (f, v->line.file);
1733           fputs ("[] = {\n", f);
1734         }
1735       
1736       fprintf (f, "  { &%s, 1, sizeof (%s), NULL },\n",
1737                v->name, v->name);
1738     }
1739   
1740   finish_root_table (flp, "rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
1741                      "gt_ggc_deletable_rtab");
1742
1743   for (v = variables; v; v = v->next)
1744     {
1745       FILE *f = get_output_file_with_visibility (v->line.file);
1746       struct flist *fli;
1747       const char *if_marked = NULL;
1748       int length_p = 0;
1749       options_p o;
1750       
1751       for (o = v->opt; o; o = o->next)
1752         if (strcmp (o->name, "length") == 0)
1753           length_p = 1;
1754         else if (strcmp (o->name, "if_marked") == 0)
1755           if_marked = (const char *) o->info;
1756
1757       if (if_marked == NULL)
1758         continue;
1759
1760       if (v->type->kind != TYPE_POINTER
1761           || v->type->u.p->kind != TYPE_PARAM_STRUCT
1762           || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0))
1763         {
1764           error_at_line (&v->line, "if_marked option used but not hash table");
1765           continue;
1766         }
1767
1768       for (fli = flp; fli; fli = fli->next)
1769         if (fli->f == f)
1770           break;
1771       if (! fli->started_p)
1772         {
1773           fli->started_p = 1;
1774
1775           fputs ("const struct ggc_cache_tab gt_ggc_rc_", f);
1776           put_mangled_filename (f, v->line.file);
1777           fputs ("[] = {\n", f);
1778         }
1779       
1780       write_gc_root (f, v, create_pointer (v->type->u.p->u.param_struct.param),
1781                      v->name, length_p, &v->line, if_marked);
1782     }
1783   
1784   finish_root_table (flp, "rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
1785                      "gt_ggc_cache_rtab");
1786 }
1787
1788 \f
1789 extern int main PARAMS ((int argc, char **argv));
1790 int 
1791 main(argc, argv)
1792      int argc;
1793      char **argv;
1794 {
1795   int i;
1796   static struct fileloc pos = { __FILE__, __LINE__ };
1797
1798   do_typedef ("CUMULATIVE_ARGS",
1799               create_scalar_type ("CUMULATIVE_ARGS", 
1800                                   strlen ("CUMULATIVE_ARGS")),
1801               &pos);
1802   do_typedef ("REAL_VALUE_TYPE",
1803               create_scalar_type ("REAL_VALUE_TYPE", 
1804                                   strlen ("REAL_VALUE_TYPE")),
1805               &pos);
1806   do_typedef ("PTR", create_pointer (create_scalar_type ("void",
1807                                                          strlen ("void"))),
1808               &pos);
1809
1810   for (i = 1; i < argc; i++)
1811     parse_file (argv[i]);
1812
1813   if (hit_error != 0)
1814     exit (1);
1815
1816   set_gc_used (variables);
1817
1818   open_base_files ();
1819   write_gc_types (structures, param_structs);
1820   write_gc_roots (variables);
1821   close_output_files ();
1822
1823   return (hit_error != 0);
1824 }