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