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