diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 385247107fb..b0dd7b8ea7c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,27 @@ 2007-03-26 Zack Weinberg + * gengtype.h: Remove all type definitions to gengtype.c; leave + only definitions of options_p, type_p, and pair_p as opaque + pointers. Update prototypes. + * gengtype.c: Many type definitions moved here from gengtype.h. + Consolidate type definitions at the top of the file. + (xvasprintf): Delete. + (xasprintf): Make static. + (create_nested_pointer_option): Add 'next' parameter. + (create_field_all, create_field_at): New functions. + (create_field): Now a thin wrapper around create_field_all. + (create_optional_field): Rename create_optional_field_ and add + line argument. Original name is now a macro which supplies + __LINE__. + (oprintf): Use vsnprintf directly. + (close_output_files): Use fatal rather than perror/exit. + (note_def_vec, note_def_vec_alloc): Use create_field_at. + (main): Set progname. Don't use exit. + * gengtype-yacc.y (struct_fields): Use create_field_at. + (option, optionseqopt): Delete. + (optionseq): Consolidate productions from option here so we + can use the first argument to create_option. + * gengtype-lex.l: Distinguish unions from structures in the token type. Don't call find_structure; return the tag as a string. * gengtype-yacc.y: Add new token types ENT_TYPEDEF_UNION and ENT_UNION. diff --git a/gcc/gengtype-yacc.y b/gcc/gengtype-yacc.y index 758bcaae327..292f3ef6f02 100644 --- a/gcc/gengtype-yacc.y +++ b/gcc/gengtype-yacc.y @@ -57,7 +57,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA %type

struct_fields %type type lasttype -%type optionsopt options option optionseq optionseqopt +%type optionsopt options optionseq %type type_option stringseq %% @@ -128,33 +128,17 @@ semiequal: ';' struct_fields: { $$ = NULL; } | type optionsopt ID bitfieldopt ';' struct_fields { - pair_p p = XNEW (struct pair); - p->type = adjust_field_type ($1, $2); - p->opt = $2; - p->name = $3; - p->next = $6; - p->line = lexer_line; - $$ = p; + $$ = create_field_at ($6, $1, $3, $2, &lexer_line); } | type optionsopt ID ARRAY ';' struct_fields { - pair_p p = XNEW (struct pair); - p->type = adjust_field_type (create_array ($1, $4), $2); - p->opt = $2; - p->name = $3; - p->next = $6; - p->line = lexer_line; - $$ = p; + $$ = create_field_at ($6, create_array ($1, $4), + $3, $2, &lexer_line); } | type optionsopt ID ARRAY ARRAY ';' struct_fields { - pair_p p = XNEW (struct pair); - p->type = create_array (create_array ($1, $5), $4); - p->opt = $2; - p->name = $3; - p->next = $7; - p->line = lexer_line; - $$ = p; + type_p arr = create_array (create_array ($1, $5), $4); + $$ = create_field_at ($7, arr, $3, $2, &lexer_line); } | type ':' bitfieldlen ';' struct_fields { $$ = $5; } @@ -204,7 +188,7 @@ optionsopt: { $$ = NULL; } | options { $$ = $1; } ; -options: GTY_TOKEN '(' '(' optionseqopt ')' ')' +options: GTY_TOKEN '(' '(' optionseq ')' ')' { $$ = $4; } ; @@ -214,31 +198,19 @@ type_option : ALIAS { $$ = $1; } ; -option: ID - { $$ = create_option (NULL, $1, (void *)""); } - | ID '(' stringseq ')' - { $$ = create_option (NULL, $1, (void *)$3); } - | type_option '(' type ')' - { $$ = create_option (NULL, $1, adjust_field_type ($3, NULL)); } - | NESTED_PTR '(' type ',' stringseq ',' stringseq ')' - { $$ = create_nested_ptr_option ($3, $5, $7); } - ; +optionseq: { $$ = NULL; } + | optionseq commaopt ID + { $$ = create_option ($1, $3, (void *)""); } + | optionseq commaopt ID '(' stringseq ')' + { $$ = create_option ($1, $3, (void *)$5); } + | optionseq commaopt type_option '(' type ')' + { $$ = create_option ($1, $3, adjust_field_type ($5, 0)); } + | optionseq commaopt NESTED_PTR '(' type ',' stringseq ',' stringseq ')' + { $$ = create_nested_ptr_option ($1, $5, $7, $9); } -optionseq: option - { - $1->next = NULL; - $$ = $1; - } - | optionseq ',' option - { - $3->next = $1; - $$ = $3; - } - ; - -optionseqopt: { $$ = NULL; } - | optionseq { $$ = $1; } - ; +commaopt: /* nothing */ + | ',' + ; stringseq: STRING { $$ = $1; } diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 86d72d8f0d7..604d94cf871 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -22,9 +22,153 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "bconfig.h" #include "system.h" #include "gengtype.h" -#include "gtyp-gen.h" #include "errors.h" /* for fatal */ +/* Data types, macros, etc. used only in this file. */ + +/* Kinds of types we can understand. */ +enum typekind { + TYPE_SCALAR, + TYPE_STRING, + TYPE_STRUCT, + TYPE_UNION, + TYPE_POINTER, + TYPE_ARRAY, + TYPE_LANG_STRUCT, + TYPE_PARAM_STRUCT +}; + +typedef unsigned lang_bitmap; + +/* A way to pass data through to the output end. */ +struct options +{ + struct options *next; + const char *name; + const char *info; +}; + +/* Option data for the 'nested_ptr' option. */ +struct nested_ptr_data +{ + type_p type; + const char *convert_to; + const char *convert_from; +}; + +/* A name and a type. */ +struct pair +{ + pair_p next; + const char *name; + type_p type; + struct fileloc line; + options_p opt; +}; + +#define NUM_PARAM 10 + +/* A description of a type. */ +enum gc_used_enum + { + GC_UNUSED = 0, + GC_USED, + GC_MAYBE_POINTED_TO, + GC_POINTED_TO + }; + +struct type +{ + enum typekind kind; + type_p next; + type_p pointer_to; + enum gc_used_enum gc_used; + union { + type_p p; + struct { + const char *tag; + struct fileloc line; + pair_p fields; + options_p opt; + lang_bitmap bitmap; + type_p lang_struct; + } s; + bool scalar_is_char; + struct { + type_p p; + const char *len; + } a; + struct { + type_p stru; + type_p param[NUM_PARAM]; + struct fileloc line; + } param_struct; + } u; +}; + +#define UNION_P(x) \ + ((x)->kind == TYPE_UNION || \ + ((x)->kind == TYPE_LANG_STRUCT \ + && (x)->u.s.lang_struct->kind == TYPE_UNION)) +#define UNION_OR_STRUCT_P(x) \ + ((x)->kind == TYPE_UNION \ + || (x)->kind == TYPE_STRUCT \ + || (x)->kind == TYPE_LANG_STRUCT) + +/* Structure representing an output file. */ +struct outf +{ + struct outf *next; + const char *name; + size_t buflength; + size_t bufused; + char *buf; +}; +typedef struct outf * outf_p; + +/* An output file, suitable for definitions, that can see declarations + made in INPUT_FILE and is linked into every language that uses + INPUT_FILE. */ +extern outf_p get_output_file_with_visibility + (const char *input_file); +const char *get_output_file_name (const char *); + +#include "gtyp-gen.h" + +/* A bitmap that specifies which of BASE_FILES should be used to + output a definition that is different for each language and must be + defined once in each language that uses INPUT_FILE. */ +static lang_bitmap get_base_file_bitmap (const char *input_file); + +/* Print, like fprintf, to O. */ +static void oprintf (outf_p o, const char *S, ...) + ATTRIBUTE_PRINTF_2; + +/* The list of output files. */ +static outf_p output_files; + +/* The output header file that is included into pretty much every + source file. */ +static outf_p header_file; + +/* Number of files specified in gtfiles. */ +#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1) + +/* Number of files in the language files array. */ +#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1) + +/* Length of srcdir name. */ +static int srcdir_len = 0; + +/* A list of output files suitable for definitions. There is one + BASE_FILES entry for each language. */ +#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1) +static outf_p base_files[NUM_BASE_FILES]; + +static outf_p create_file (const char *, const char *); +static const char * get_file_basename (const char *); + + /* Nonzero iff an error has occurred. */ static int hit_error = 0; @@ -50,29 +194,20 @@ error_at_line (struct fileloc *pos, const char *msg, ...) va_end (ap); } -/* vasprintf, but produces fatal message on out-of-memory. */ -int -xvasprintf (char **result, const char *format, va_list args) -{ - int ret = vasprintf (result, format, args); - if (*result == NULL || ret < 0) - { - fputs ("gengtype: out of memory", stderr); - xexit (1); - } - return ret; -} - -/* Wrapper for xvasprintf. */ -char * +/* asprintf, but produces fatal message on out-of-memory. */ +static char * ATTRIBUTE_PRINTF_1 xasprintf (const char *format, ...) { + int n; char *result; va_list ap; va_start (ap, format); - xvasprintf (&result, format, ap); + n = vasprintf (&result, format, ap); + if (result == NULL || n < 0) + fatal ("out of memory"); va_end (ap); + return result; } @@ -332,14 +467,15 @@ create_option (options_p next, const char *name, const void *info) /* Return an options structure for a "nested_ptr" option. */ options_p -create_nested_ptr_option (type_p t, const char *to, const char *from) +create_nested_ptr_option (options_p next, type_p t, + const char *to, const char *from) { struct nested_ptr_data *d = XNEW (struct nested_ptr_data); d->type = adjust_field_type (t, 0); d->convert_to = to; d->convert_from = from; - return create_option (NULL, "nested_ptr", d); + return create_option (next, "nested_ptr", d); } /* Add a variable named S of type T with options O defined at POS, @@ -358,11 +494,10 @@ note_variable (const char *s, type_p t, options_p o, struct fileloc *pos) variables = n; } -/* Create a fake field with the given type and name. NEXT is the next - field in the chain. */ - +/* Most-general structure field creator. */ static pair_p -create_field (pair_p next, type_p type, const char *name) +create_field_all (pair_p next, type_p type, const char *name, options_p opt, + const char *file, int line) { pair_p field; @@ -370,21 +505,37 @@ create_field (pair_p next, type_p type, const char *name) field->next = next; field->type = type; field->name = name; - field->opt = NULL; - field->line.file = __FILE__; - field->line.line = __LINE__; + field->opt = opt; + field->line.file = file; + field->line.line = line; return field; } +/* Create a field that came from the source code we are scanning, + i.e. we have a 'struct fileloc', and possibly options; also, + adjust_field_type should be called. */ +pair_p +create_field_at (pair_p next, type_p type, const char *name, options_p opt, + struct fileloc *pos) +{ + return create_field_all (next, adjust_field_type (type, opt), + name, opt, pos->file, pos->line); +} + +/* Create a fake field with the given type and name. NEXT is the next + field in the chain. */ +#define create_field(next,type,name) \ + create_field_all(next,type,name, 0, __FILE__, __LINE__) + /* Like create_field, but the field is only valid when condition COND is true. */ static pair_p -create_optional_field (pair_p next, type_p type, const char *name, - const char *cond) +create_optional_field_ (pair_p next, type_p type, const char *name, + const char *cond, int line) { static int id = 1; - pair_p union_fields, field; + pair_p union_fields; type_p union_type; /* Create a fake union type with a single nameless field of type TYPE. @@ -398,10 +549,12 @@ create_optional_field (pair_p next, type_p type, const char *name, /* Create the field and give it the new fake union type. Add a "desc" tag that specifies the condition under which the field is valid. */ - field = create_field (next, union_type, name); - field->opt = create_option (field->opt, "desc", cond); - return field; + return create_field_all (next, union_type, name, + create_option (0, "desc", cond), + __FILE__, line); } +#define create_optional_field(next,type,name,cond) \ + create_optional_field_(next,type,name,cond,__LINE__) /* We don't care how long a CONST_DOUBLE is. */ #define CONST_DOUBLE_FORMAT "ww" @@ -953,27 +1106,7 @@ set_gc_used (pair_p variables) (but some output files have many input files), and there is one .h file for the whole build. */ -/* The list of output files. */ -static outf_p output_files; - -/* The output header file that is included into pretty much every - source file. */ -static outf_p header_file; - -/* Number of files specified in gtfiles. */ -#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1) - -/* Number of files in the language files array. */ -#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1) - -/* Length of srcdir name. */ -static int srcdir_len = 0; - -#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1) -outf_p base_files[NUM_BASE_FILES]; - -static outf_p create_file (const char *, const char *); -static const char * get_file_basename (const char *); +/* Output file handling. */ /* Create and return an outf_p for a new file for NAME, to be called ONAME. */ @@ -1021,15 +1154,20 @@ create_file (const char *name, const char *oname) void oprintf (outf_p o, const char *format, ...) { - char *s; size_t slength; - va_list ap; - va_start (ap, format); - slength = xvasprintf (&s, format, ap); + /* Try first with the assumption that there is enough space. */ + { + va_list ap; + va_start (ap, format); + slength = vsnprintf (o->buf + o->bufused, o->buflength - o->bufused, + format, ap); + va_end (ap); + } - if (o->bufused + slength > o->buflength) + if (o->bufused + slength >= o->buflength) { + /* There wasn't enough space. */ size_t new_len = o->buflength; if (new_len == 0) new_len = 1024; @@ -1038,11 +1176,21 @@ oprintf (outf_p o, const char *format, ...) } while (o->bufused + slength >= new_len); o->buf = XRESIZEVEC (char, o->buf, new_len); o->buflength = new_len; + + /* We now know that there is enough space. */ + { + size_t slen2; + va_list ap; + va_start (ap, format); + slen2 = vsnprintf (o->buf + o->bufused, o->buflength - o->bufused, + format, ap); + va_end (ap); + + gcc_assert (slen2 == slength); + gcc_assert (o->bufused + slen2 < o->buflength); + } } - memcpy (o->buf + o->bufused, s, slength); o->bufused += slength; - free (s); - va_end (ap); } /* Open the global header file and the language-specific header files. */ @@ -1298,20 +1446,11 @@ close_output_files (void) newfile = fopen (of->name, "w"); if (newfile == NULL) - { - perror ("opening output file"); - exit (1); - } + fatal ("opening output file %s: %s", of->name, strerror (errno)); if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused) - { - perror ("writing output file"); - exit (1); - } + fatal ("writing output file %s: %s", of->name, strerror (errno)); if (fclose (newfile) != 0) - { - perror ("closing output file"); - exit (1); - } + fatal ("closing output file %s: %s", of->name, strerror (errno)); } } @@ -3029,9 +3168,10 @@ write_roots (pair_p variables) void note_def_vec (const char *typename, bool is_scalar, struct fileloc *pos) { - pair_p f, fields; + pair_p fields; type_p t; options_p o; + type_p len_ty = create_scalar_type ("unsigned"); const char *name = concat ("VEC_", typename, "_base", (char *)0); if (is_scalar) @@ -3046,29 +3186,9 @@ note_def_vec (const char *typename, bool is_scalar, struct fileloc *pos) } /* We assemble the field list in reverse order. */ - f = XNEW (struct pair); - f->type = adjust_field_type (create_array (t, "1"), o); - f->name = "vec"; - f->opt = o; - f->line = *pos; - f->next = 0; - fields = f; - - f = XNEW (struct pair); - f->type = adjust_field_type (create_scalar_type ("unsigned"), 0); - f->name = "alloc"; - f->opt = 0; - f->line = *pos; - f->next = fields; - fields = f; - - f = XNEW (struct pair); - f->type = adjust_field_type (create_scalar_type ("unsigned"), 0); - f->name = "num"; - f->opt = 0; - f->line = *pos; - f->next = fields; - fields = f; + fields = create_field_at (0, create_array (t, "1"), "vec", o, pos); + fields = create_field_at (fields, len_ty, "alloc", 0, pos); + fields = create_field_at (fields, len_ty, "num", 0, pos); do_typedef (name, new_structure (name, 0, pos, fields, 0), pos); } @@ -3086,11 +3206,8 @@ note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos) const char *astratname = concat ("VEC_", type, "_", astrat, (char *)0); const char *basename = concat ("VEC_", type, "_base", (char *)0); - pair_p field = XNEW (struct pair); - field->name = "base"; - field->type = adjust_field_type (resolve_typedef (basename, pos), 0); - field->line = *pos; - field->next = 0; + pair_p field = create_field_at (0, resolve_typedef (basename, pos), + "base", 0, pos); do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos); } @@ -3109,6 +3226,9 @@ main (int ARG_UNUSED (argc), char ** ARG_UNUSED (argv)) scalar_char.u.scalar_is_char = true; scalar_nonchar.u.scalar_is_char = false; + /* fatal uses this */ + progname = "gengtype"; + gen_rtx_next (); do_scalar_typedef ("CUMULATIVE_ARGS", &pos); @@ -3150,7 +3270,7 @@ main (int ARG_UNUSED (argc), char ** ARG_UNUSED (argv)) } if (hit_error != 0) - exit (1); + return 1; set_gc_used (variables); diff --git a/gcc/gengtype.h b/gcc/gengtype.h index f803ad3c1ee..345d80d9022 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -18,6 +18,9 @@ along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifndef GCC_GENGTYPE_H +#define GCC_GENGTYPE_H + /* A file position, mostly for error messages. The FILE element may be compared using pointer equality. */ struct fileloc { @@ -25,92 +28,10 @@ struct fileloc { int line; }; -/* Kinds of types we can understand. */ -enum typekind { - TYPE_SCALAR, - TYPE_STRING, - TYPE_STRUCT, - TYPE_UNION, - TYPE_POINTER, - TYPE_ARRAY, - TYPE_LANG_STRUCT, - TYPE_PARAM_STRUCT -}; - +/* Data types handed around within, but opaque to, the lexer and parser. */ typedef struct pair *pair_p; typedef struct type *type_p; -typedef unsigned lang_bitmap; - -/* Option data for the 'nested_ptr' option. */ -struct nested_ptr_data { - type_p type; - const char *convert_to; - const char *convert_from; -}; - -/* A way to pass data through to the output end. */ -typedef struct options { - struct options *next; - const char *name; - const char *info; -} *options_p; - -/* A name and a type. */ -struct pair { - pair_p next; - const char *name; - type_p type; - struct fileloc line; - options_p opt; -}; - -#define NUM_PARAM 10 - -/* A description of a type. */ -enum gc_used_enum - { - GC_UNUSED = 0, - GC_USED, - GC_MAYBE_POINTED_TO, - GC_POINTED_TO - }; - -struct type { - enum typekind kind; - type_p next; - type_p pointer_to; - enum gc_used_enum gc_used; - union { - type_p p; - struct { - const char *tag; - struct fileloc line; - pair_p fields; - options_p opt; - lang_bitmap bitmap; - type_p lang_struct; - } s; - bool scalar_is_char; - struct { - type_p p; - const char *len; - } a; - struct { - type_p stru; - type_p param[NUM_PARAM]; - struct fileloc line; - } param_struct; - } u; -}; - -#define UNION_P(x) \ - ((x)->kind == TYPE_UNION || \ - ((x)->kind == TYPE_LANG_STRUCT \ - && (x)->u.s.lang_struct->kind == TYPE_UNION)) -#define UNION_OR_STRUCT_P(x) \ - ((x)->kind == TYPE_UNION \ - || (x)->kind == TYPE_STRUCT \ - || (x)->kind == TYPE_LANG_STRUCT) +typedef struct options *options_p; /* Variables used to communicate between the lexer and the parser. */ extern int lexer_toplevel_done; @@ -120,13 +41,6 @@ extern struct fileloc lexer_line; extern void error_at_line (struct fileloc *pos, const char *msg, ...) ATTRIBUTE_PRINTF_2; -/* Combines xmalloc() and vasprintf(). */ -extern int xvasprintf (char **, const char *, va_list) - ATTRIBUTE_PRINTF (2, 0); -/* Like the above, but more convenient for quick coding. */ -extern char * xasprintf (const char *, ...) - ATTRIBUTE_PRINTF_1; - /* Constructor routines for types. */ extern void do_typedef (const char *s, type_p t, struct fileloc *pos); extern void do_scalar_typedef (const char *s, struct fileloc *pos); @@ -139,8 +53,10 @@ extern type_p create_scalar_type (const char *name); extern type_p create_pointer (type_p t); extern type_p create_array (type_p t, const char *len); extern options_p create_option (options_p, const char *name, const void *info); -extern options_p create_nested_ptr_option (type_p t, const char *from, - const char *to); +extern options_p create_nested_ptr_option (options_p, type_p t, + const char *from, const char *to); +extern pair_p create_field_at (pair_p next, type_p type, const char *name, + options_p opt, struct fileloc *pos); extern type_p adjust_field_type (type_p, options_p); extern void note_variable (const char *s, type_p t, options_p o, struct fileloc *pos); @@ -155,36 +71,4 @@ extern void yyerror (const char *); extern int yyparse (void); extern void parse_file (const char *name); -/* Output file handling. */ - -/* Structure representing an output file. */ -struct outf -{ - struct outf *next; - const char *name; - size_t buflength; - size_t bufused; - char *buf; -}; - -typedef struct outf * outf_p; - -/* An output file, suitable for definitions, that can see declarations - made in INPUT_FILE and is linked into every language that uses - INPUT_FILE. */ -extern outf_p get_output_file_with_visibility - (const char *input_file); -const char *get_output_file_name (const char *); - -/* A list of output files suitable for definitions. There is one - BASE_FILES entry for each language. */ -extern outf_p base_files[]; - -/* A bitmap that specifies which of BASE_FILES should be used to - output a definition that is different for each language and must be - defined once in each language that uses INPUT_FILE. */ -extern lang_bitmap get_base_file_bitmap (const char *input_file); - -/* Print, like fprintf, to O. */ -extern void oprintf (outf_p o, const char *S, ...) - ATTRIBUTE_PRINTF_2; +#endif