diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 05c173677a0..0dc2ec55301 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,37 @@ 2007-03-26 Zack Weinberg + * gengtype-parse.c: New file. + * gengtype-yacc.y: Delete. + * gengtype-lex.l: Don't include gengtype-yacc.h. + Define YY_DECL and yyterminate appropriately for recursive + descent parser. yylval is now a string out-parameter to yylex. + (HWS, EOID): New shorthand. + (IWORD): Add a couple more types. + (yylex): Add a setup stanza. Remove the complex rules for + detecting GTY'ed types and typedefs; replace with simple + keyword detectors. Adjust everything for the changed + definition of yylval. Ignore all pp-directives, not just #define. + (yyerror): Delete. + (parse_file): Rename yybegin; do not call yyparse. + (yyend): New. + * gengtype.c (xasprintf): Export again. + (this_file): New. Use everywhere __FILE__ was being used. + (get_lang_bitmap): Special case types defined in gengtype.c. + (do_typedef, new_structure): Suppress definition of certain types. + (new_structure): Improve diagnostics of duplicate definitions. + Make sure location_s is associated with input.h. + (nreverse_pairs, define_location_structures): New functions. + (main): Improve tagging of kludge types. Remove old kludges + for input.h types; use define_location_structures. + * gengtype.h: Update prototypes. Define token codes here. + * Makefile.in: Remove all references to gengtype-yacc. + Add rules for gengtype-parse.o. Adjust rules for gengtype-lex.o + and gengtype. + * bitmap.h (struct bitmap_head_def): Coalesce definitions, + add GTY((skip)) to the field that's only conditionally there. + * doc/install.texi: Document that Bison is no longer required + unless building treelang. + * gengtype.c: Don't include gtyp-gen.h. (srcdir): Declare here. (base_files, lang_dir_names): Allocate dynamically. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 2236f3bfd4c..4c351908270 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -188,8 +188,6 @@ GCC_WARN_CFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn) # These files are to have specific diagnostics suppressed, or are not to # be subject to -Werror: -# Bison-1.75 output often yields (harmless) -Wtraditional warnings -build/gengtype-yacc.o-warn = -Wno-error # flex output may yield harmless "no previous prototype" warnings build/gengtype-lex.o-warn = -Wno-error # SYSCALLS.c misses prototypes @@ -1699,7 +1697,7 @@ c-parser.o : c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ srcextra: gcc.srcextra lang.srcextra -gcc.srcextra: gengtype-lex.c gengtype-yacc.c gengtype-yacc.h +gcc.srcextra: gengtype-lex.c -cp -p $^ $(srcdir) c-incpath.o: c-incpath.c c-incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \ @@ -3105,9 +3103,8 @@ build/genextract.o : genextract.c $(RTL_BASE_H) $(BCONFIG_H) \ build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H) \ $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def -build/gengtype-lex.o : gengtype-lex.c gengtype.h gengtype-yacc.h \ - $(BCONFIG_H) $(SYSTEM_H) -build/gengtype-yacc.o : gengtype-yacc.c gengtype.h $(BCONFIG_H) \ +build/gengtype-lex.o : gengtype-lex.c gengtype.h $(BCONFIG_H) $(SYSTEM_H) +build/gengtype-parse.o : gengtype-parse.c gengtype.h $(BCONFIG_H) \ $(SYSTEM_H) build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) gengtype.h \ rtl.def insn-notes.def errors.h @@ -3147,18 +3144,12 @@ build/genautomata$(build_exeext) : BUILD_LIBS += -lm # These programs are not linked with the MD reader. build/gengenrtl$(build_exeext) : $(BUILD_ERRORS) build/genmodes$(build_exeext) : $(BUILD_ERRORS) -build/gengtype$(build_exeext) : build/gengtype-lex.o \ - build/gengtype-yacc.o $(BUILD_ERRORS) +build/gengtype$(build_exeext) : build/gengtype-lex.o build/gengtype-parse.o \ + $(BUILD_ERRORS) # Generated source files for gengtype. gengtype-lex.c : gengtype-lex.l -$(FLEX) $(FLEXFLAGS) -o$@ $< -# This is a pattern rule solely so that Make knows it need not run the -# command twice. The modifier to $@ ensures that Bison is asked to -# produce a .c file, whether or not Make decides it needs the .h file -# first. -gengtype-y%.c gengtype-y%.h: gengtype-y%.y - -$(BISON) $(BISONFLAGS) -d -o $(@:.h=.c) $< # # Remake internationalization support. diff --git a/gcc/bitmap.h b/gcc/bitmap.h index 515527c08e8..9a33646ccb1 100644 --- a/gcc/bitmap.h +++ b/gcc/bitmap.h @@ -70,29 +70,20 @@ typedef struct bitmap_element_def GTY(()) } bitmap_element; struct bitmap_descriptor; -/* Head of bitmap linked list. - The gengtype doesn't cope with ifdefs inside the definition, - but for statistics we need bitmap descriptor pointer in. - Trick it by two copies of the definition. This is safe - because the bitmap descriptor is not grabagecollected. */ -#ifndef GATHER_STATISTICS +/* Head of bitmap linked list. gengtype ignores ifdefs, but for + statistics we need to add a bitmap descriptor pointer. As it is + not collected, we can just GTY((skip)) it. */ + typedef struct bitmap_head_def GTY(()) { bitmap_element *first; /* First element in linked list. */ bitmap_element *current; /* Last element looked at. */ unsigned int indx; /* Index of last element looked at. */ bitmap_obstack *obstack; /* Obstack to allocate elements from. If NULL, then use ggc_alloc. */ -} bitmap_head; -#else -typedef struct bitmap_head_def { - bitmap_element *first; /* First element in linked list. */ - bitmap_element *current; /* Last element looked at. */ - unsigned int indx; /* Index of last element looked at. */ - bitmap_obstack *obstack; /* Obstack to allocate elements from. - If NULL, then use ggc_alloc. */ - struct bitmap_descriptor *desc; -} bitmap_head; +#ifndef GATHER_STATISTICS + struct bitmap_descriptor GTY((skip)) *desc; #endif +} bitmap_head; /* Global data */ extern bitmap_element bitmap_zero_bits; /* Zero bitmap element */ diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 76545c08996..fa17564574c 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -375,14 +375,14 @@ Necessary to regenerate the top level @file{Makefile.in} file from @file{Makefile.tpl} and @file{Makefile.def}. @item GNU Bison version 1.28 (or later) -Berkeley @command{yacc} (@command{byacc}) is also reported to work other -than for GCJ. -Necessary when modifying @file{*.y} files. +Necessary when modifying @file{*.y} files. Necessary to build the +@code{treelang} front end (which is not enabled by default) from a +checkout of the SVN repository; the generated files are not in the +repository. They are included in releases. -Necessary to build GCC during development because the generated output -files are not included in the SVN repository. They are included in -releases. +Berkeley @command{yacc} (@command{byacc}) has been reported to work +as well. @item Flex version 2.5.4 (or later) @@ -1650,10 +1650,18 @@ that type mismatches occur, this could be the cause. The solution is not to use such a directory for building GCC@. -When building from SVN or snapshots, or if you modify parser sources, -you need the Bison parser generator installed. If you do not modify -parser sources, releases contain the Bison-generated files and you do -not need Bison installed to build them. +When building from SVN or snapshots and enabling the @code{treelang} +front end, or if you modify @file{*.y} files, you need the Bison parser +generator installed. If you do not modify @file{*.y} files, releases +contain the Bison-generated files and you do not need Bison installed +to build them. Note that most front ends now use hand-written parsers, +which can be modified with no need for Bison. + +Similarly, when building from SVN or snapshots, or if you modify +@file{*.l} files, you need the Flex lexical analyzer generator installed. +There is still one Flex-based lexical analyzer (part of the build +machinery, not of GCC itself) that is used even if you only build the +C front end. When building from SVN or snapshots, or if you modify Texinfo documentation, you need version 4.4 or later of Texinfo installed if you diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l index baf09bcd5fe..2d003e0c5fa 100644 --- a/gcc/gengtype-lex.l +++ b/gcc/gengtype-lex.l @@ -27,7 +27,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define realloc xrealloc #include "gengtype.h" -#include "gengtype-yacc.h" + +#define YY_DECL int yylex (const char **yylval) +#define yyterminate() return EOF_TOKEN struct fileloc lexer_line; int lexer_toplevel_done; @@ -44,199 +46,58 @@ update_lineno (const char *l, size_t len) ID [[:alpha:]_][[:alnum:]_]* WS [[:space:]]+ -IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD +HWS [ \t\r\v\f]* +IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t ITYPE {IWORD}({WS}{IWORD})* +EOID [^[:alnum:]_] %x in_struct in_struct_comment in_comment %option warn noyywrap nounput nodefault perf-report %option 8bit never-interactive %% + /* Do this on entry to yylex(): */ + *yylval = 0; + if (lexer_toplevel_done) + { + BEGIN(INITIAL); + lexer_toplevel_done = 0; + } -[^[:alnum:]_]typedef{WS}(struct|union){WS}{ID}{WS}?[*[:space:]]{WS}?{ID}{WS}?";" { - char *tagstart; - size_t taglen; - char *namestart; - size_t namelen; - int is_pointer = 0; - struct type *t; - int union_p; - - tagstart = yytext + strlen (" typedef "); - while (ISSPACE (*tagstart)) - tagstart++; - union_p = tagstart[0] == 'u'; - tagstart += strlen ("union "); - while (ISSPACE (*tagstart)) - tagstart++; - for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++) - ; - for (namestart = tagstart + taglen; - ! ISIDNUM (*namestart); - namestart++) - if (*namestart == '*') - is_pointer = 1; - for (namelen = 1; ISIDNUM (namestart[namelen]); namelen++) - ; - t = find_structure ((const char *) xmemdup (tagstart, taglen, taglen+1), - union_p); - if (is_pointer) - t = create_pointer (t); - namestart = (char *) xmemdup (namestart, namelen, namelen+1); -#ifdef USE_MAPPED_LOCATION - /* temporary kludge - gentype doesn't handle cpp conditionals */ - if (strcmp (namestart, "location_t") != 0 - && strcmp (namestart, "expanded_location") != 0) -#endif - do_typedef (namestart, t, &lexer_line); - update_lineno (yytext, yyleng); -} - -[^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" { - - char *namestart; - size_t namelen; - char *typestart; - size_t typelen; - - for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--) - ; - for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++) - ; - namestart -= namelen - 1; - for (typestart = yytext + strlen (" typedef "); - ISSPACE(*typestart); - typestart++) - ; - for (typelen = namestart - typestart; - ISSPACE (typestart[typelen-1]); - typelen--) - ; - typestart[typelen] = '\0'; - - do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), - create_scalar_type (typestart), - &lexer_line); - update_lineno (yytext, yyleng); -} - -[^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" { - char *namestart; - size_t namelen; - - for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--) - ; - for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++) - ; - namestart -= namelen - 1; - - do_scalar_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), - &lexer_line); - update_lineno (yytext, yyleng); -} - -[^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" { - char *namestart; - size_t namelen; - - for (namestart = yytext + yyleng - 2; !ISIDNUM (*namestart); namestart--) - ; - for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++) - ; - namestart -= namelen - 1; - - do_scalar_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), - &lexer_line); - update_lineno (yytext, yyleng); -} - -[^[:alnum:]_](typedef{WS})?(struct|union){WS}{ID}{WS}/"GTY" { - char *tagstart; - size_t taglen; - int typedef_p; - int union_p; - - typedef_p = yytext[1] == 't'; - if (typedef_p) - for (tagstart = yytext + strlen (" typedef "); - ISSPACE(*tagstart); - tagstart++) - ; - else - tagstart = yytext + 1; - - union_p = tagstart[0] == 'u'; - tagstart += strlen ("union "); - while (ISSPACE (*tagstart)) - tagstart++; - for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++) - ; - - yylval.s = (const char *) xmemdup (tagstart, taglen, taglen + 1); - + /* Things we look for in skipping mode: */ +{ +^typedef/{EOID} { BEGIN(in_struct); - update_lineno (yytext, yyleng); - return union_p ? (typedef_p ? ENT_TYPEDEF_UNION : ENT_UNION) - : (typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT); + return TYPEDEF; } - -[^[:alnum:]_](extern|static){WS}/"GTY" { +^struct/{EOID} { BEGIN(in_struct); - update_lineno (yytext, yyleng); - return ENT_EXTERNSTATIC; + return STRUCT; +} +^union/{EOID} { + BEGIN(in_struct); + return UNION; +} +^extern/{EOID} { + BEGIN(in_struct); + return EXTERN; +} +^static/{EOID} { + BEGIN(in_struct); + return STATIC; } -^"DEF_VEC_"[IPO]{WS}?"("{WS}?{ID}{WS}?")" { - /* Definition of a generic VEC structure. If the letter after - DEF_VEC_ is "I", the structure definition is slightly different - than if it is "P" or "O". */ - - char *p = yytext + sizeof("DEF_VEC_") - 1; - char *q; - const char *type; - bool is_I = (*p == 'I'); - - /* Extract the argument to the macro. */ - p++; - while (!ISALNUM(*p) && *p != '_') - p++; - q = p; - while (ISALNUM(*q) || *q == '_') - ++; - type = xmemdup (p, q - p, q - p + 1); - - note_def_vec (type, is_I, &lexer_line); - note_def_vec_alloc (type, "none", &lexer_line); +^DEF_VEC_[OP]/{EOID} { + BEGIN(in_struct); + return DEFVEC_OP; +} +^DEF_VEC_I/{EOID} { + BEGIN(in_struct); + return DEFVEC_I; +} +^DEF_VEC_ALLOC_[IOP]/{EOID} { + BEGIN(in_struct); + return DEFVEC_ALLOC; } - -^"DEF_VEC_ALLOC_"[IPO]{WS}?"("{WS}?{ID}{WS}?","{WS}?{ID}{WS}?")" { - /* Definition of an allocation strategy for a VEC structure. For - purposes of gengtype, this just declares a wrapper structure. */ - - char *p = yytext + sizeof("DEF_VEC_ALLOC_I") - 1; - char *q; - char *type, *astrat; - - /* Extract the two arguments to the macro. */ - while (!ISALNUM(*p) && *p != '_') - p++; - q = p; - while (ISALNUM(*q) || *q == '_') - q++; - type = alloca (q - p + 1); - memcpy (type, p, q - p); - type[q - p] = '\0'; - p = q; - - while (!ISALNUM(*p) && *p != '_') - p++; - q = p; - while (ISALNUM(*q) || *q == '_') - q++; - astrat = alloca (q - p + 1); - memcpy (astrat, p, q - p); - astrat[q - p] = '\0'; - - note_def_vec_alloc (type, astrat, &lexer_line); } { @@ -245,63 +106,57 @@ ITYPE {IWORD}({WS}{IWORD})* {WS} { update_lineno (yytext, yyleng); } -"const"/[^[:alnum:]_] /* don't care */ -"GTY"/[^[:alnum:]_] { return GTY_TOKEN; } -"VEC"/[^[:alnum:]_] { return VEC_TOKEN; } -"union"/[^[:alnum:]_] { return UNION; } -"struct"/[^[:alnum:]_] { return STRUCT; } -"enum"/[^[:alnum:]_] { return ENUM; } -"ptr_alias"/[^[:alnum:]_] { return ALIAS; } -"nested_ptr"/[^[:alnum:]_] { return NESTED_PTR; } +"const"/{EOID} /* don't care */ +"GTY"/{EOID} { return GTY_TOKEN; } +"VEC"/{EOID} { return VEC_TOKEN; } +"union"/{EOID} { return UNION; } +"struct"/{EOID} { return STRUCT; } +"enum"/{EOID} { return ENUM; } +"ptr_alias"/{EOID} { return PTR_ALIAS; } +"nested_ptr"/{EOID} { return NESTED_PTR; } [0-9]+ { return NUM; } -"param"[0-9]*"_is"/[^[:alnum:]_] { - yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1); +"param"[0-9]*"_is"/{EOID} { + *yylval = xmemdup (yytext, yyleng, yyleng+1); return PARAM_IS; } -{IWORD}({WS}{IWORD})*/[^[:alnum:]_] | +{IWORD}({WS}{IWORD})*/{EOID} | "ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")" { size_t len; for (len = yyleng; ISSPACE (yytext[len-1]); len--) ; - yylval.s = (const char *) xmemdup (yytext, len, len+1); + *yylval = xmemdup (yytext, len, len+1); update_lineno (yytext, yyleng); return SCALAR; } -{ID}/[^[:alnum:]_] { - yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1); +{ID}/{EOID} { + *yylval = xmemdup (yytext, yyleng, yyleng+1); return ID; } \"([^"\\]|\\.)*\" { - yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1); + *yylval = xmemdup (yytext+1, yyleng-2, yyleng-1); return STRING; } + /* This "terminal" avoids having to parse integer constant expressions. */ "["[^\[\]]*"]" { - yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1); + *yylval = xmemdup (yytext+1, yyleng-2, yyleng-1); return ARRAY; } "'"("\\".|[^\\])"'" { - yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng); + *yylval = xmemdup (yytext+1, yyleng-2, yyleng); return CHAR; } -[(){},*:<>] { return yytext[0]; } +"..." { return ELLIPSIS; } +[(){},*:<>;=%|-] { return yytext[0]; } -[;=] { - if (lexer_toplevel_done) - { - BEGIN(INITIAL); - lexer_toplevel_done = 0; - } - return yytext[0]; -} - -"#define"[^\n]*\n {lexer_line.line++;} + /* ignore pp-directives */ +^{HWS}"#"{HWS}[a-z_]+[^\n]*\n {lexer_line.line++;} . { error_at_line (&lexer_line, "unexpected character `%s'", yytext); @@ -339,23 +194,20 @@ ITYPE {IWORD}({WS}{IWORD})* %% void -yyerror (const char *s) -{ - error_at_line (&lexer_line, s); -} - -void -parse_file (const char *fname) +yybegin (const char *fname) { yyin = fopen (fname, "r"); - lexer_line.file = fname; - lexer_line.line = 1; if (yyin == NULL) { perror (fname); exit (1); } - if (yyparse() != 0) - exit (1); + lexer_line.file = fname; + lexer_line.line = 1; +} + +void +yyend (void) +{ fclose (yyin); } diff --git a/gcc/gengtype.c b/gcc/gengtype.c index ce34d0016f6..e0cd6c2599f 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -155,7 +155,7 @@ static const char * get_file_basename (const char *); /* Nonzero iff an error has occurred. */ -static int hit_error = 0; +bool hit_error = false; static void gen_rtx_next (void); static void write_rtx_next (void); @@ -174,13 +174,13 @@ error_at_line (struct fileloc *pos, const char *msg, ...) fprintf (stderr, "%s:%d: ", pos->file, pos->line); vfprintf (stderr, msg, ap); fputc ('\n', stderr); - hit_error = 1; + hit_error = true; va_end (ap); } /* asprintf, but produces fatal message on out-of-memory. */ -static char * ATTRIBUTE_PRINTF_1 +char * xasprintf (const char *format, ...) { int n; @@ -202,6 +202,11 @@ xasprintf (const char *format, ...) static const char **gt_files; static size_t num_gt_files; +/* A number of places use the name of this file for a location for + things that we can't rely on the source to define. Make sure we + can still use pointer comparison on filenames. */ +static const char this_file[] = __FILE__; + /* Vector of per-language directories. */ static const char **lang_dir_names; static size_t num_lang_dirs; @@ -225,11 +230,18 @@ static outf_p *base_files; static lang_bitmap get_lang_bitmap (const char *gtfile) { - lang_bitmap n = 0; - int i; - for (i = -(int) sizeof (lang_bitmap); i < 0; i++) - n = (n << CHAR_BIT) + (unsigned char)gtfile[i]; - return n; + + if (gtfile == this_file) + /* Things defined in this file are universal. */ + return (((lang_bitmap)1) << num_lang_dirs) - 1; + else + { + lang_bitmap n = 0; + int i; + for (i = -(int) sizeof (lang_bitmap); i < 0; i++) + n = (n << CHAR_BIT) + (unsigned char)gtfile[i]; + return n; + } } /* Set the bitmap returned by get_lang_bitmap. The only legitimate @@ -509,6 +521,18 @@ do_typedef (const char *s, type_p t, struct fileloc *pos) { pair_p p; + /* temporary kludge - gengtype doesn't handle conditionals or macros. + Ignore any attempt to typedef CUMULATIVE_ARGS, location_t, + expanded_location, or source_locus, unless it is coming from + this file (main() sets them up with safe dummy definitions). */ + if ((!strcmp (s, "CUMULATIVE_ARGS") + || !strcmp (s, "location_t") + || !strcmp (s, "source_locus") + || !strcmp (s, "source_location") + || !strcmp (s, "expanded_location")) + && pos->file != this_file) + return; + for (p = typedefs; p != NULL; p = p->next) if (strcmp (p->name, s) == 0) { @@ -562,6 +586,13 @@ new_structure (const char *name, int isunion, struct fileloc *pos, type_p s = NULL; lang_bitmap bitmap = get_lang_bitmap (pos->file); + /* temporary kludge - gengtype doesn't handle conditionals or + macros. Ignore any attempt to define struct location_s, unless + it is coming from this file (main() sets it up safely). */ + if (!strcmp (name, "location_s") && !isunion + && pos->file != this_file) + return find_structure (name, 0); + for (si = structures; si != NULL; si = si->next) if (strcmp (name, si->u.s.tag) == 0 && UNION_P (si) == isunion) @@ -610,7 +641,8 @@ new_structure (const char *name, int isunion, struct fileloc *pos, if (s->u.s.line.file != NULL || (s->u.s.lang_struct && (s->u.s.lang_struct->u.s.bitmap & bitmap))) { - error_at_line (pos, "duplicate structure definition"); + error_at_line (pos, "duplicate definition of '%s %s'", + isunion ? "union" : "struct", s->u.s.tag); error_at_line (&s->u.s.line, "previous definition here"); } @@ -623,7 +655,22 @@ new_structure (const char *name, int isunion, struct fileloc *pos, if (s->u.s.lang_struct) s->u.s.lang_struct->u.s.bitmap |= bitmap; - return s; + /* Reset location_s's location to input.h so that we know where to + write out its mark routine. */ + if (!strcmp (name, "location_s") && !isunion + && pos->file == this_file) + { + size_t n; + for (n = 0; n < num_gt_files; n++) + if (!strcmp (gt_files[n] + strlen (gt_files[n]) - strlen ("input.h"), + "input.h")) + { + s->u.s.line.file = gt_files[n]; + break; + } + } + + return s; } /* Return the previously-defined structure with tag NAME (or a union @@ -788,7 +835,7 @@ create_field_at (pair_p next, type_p type, const char *name, options_p opt, /* 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__) + create_field_all(next,type,name, 0, this_file, __LINE__) /* Like create_field, but the field is only valid when condition COND is true. */ @@ -814,11 +861,26 @@ create_optional_field_ (pair_p next, type_p type, const char *name, tag that specifies the condition under which the field is valid. */ return create_field_all (next, union_type, name, create_option (0, "desc", cond), - __FILE__, line); + this_file, line); } #define create_optional_field(next,type,name,cond) \ create_optional_field_(next,type,name,cond,__LINE__) +/* Reverse a linked list of 'struct pair's in place. */ +pair_p +nreverse_pairs (pair_p list) +{ + pair_p prev = 0, p, next; + for (p = list; p; p = next) + { + next = p->next; + p->next = prev; + prev = p; + } + return prev; +} + + /* We don't care how long a CONST_DOUBLE is. */ #define CONST_DOUBLE_FORMAT "ww" /* We don't want to see codes that are only for generator files. */ @@ -3420,12 +3482,42 @@ note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos) do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos); } +/* Yet more temporary kludge since gengtype doesn't understand conditionals. + This must be kept in sync with input.h. */ +static void +define_location_structures (void) +{ + pair_p fields; + type_p locs; + static struct fileloc pos = { this_file, __LINE__ }; + do_scalar_typedef ("source_location", &pos); + +#ifdef USE_MAPPED_LOCATION + fields = create_field (0, &scalar_nonchar, "column"); + fields = create_field (fields, &scalar_nonchar, "line"); + fields = create_field (fields, &string_type, "file"); + locs = new_structure ("anon:expanded_location", 0, &pos, fields, 0); + + do_typedef ("expanded_location", locs, &pos); + do_scalar_typedef ("location_t", &pos); + do_scalar_typedef ("source_locus", &pos); +#else + fields = create_field (0, &scalar_nonchar, "line"); + fields = create_field (fields, &string_type, "file"); + locs = new_structure ("location_s", 0, &pos, fields, 0); + + do_typedef ("expanded_location", locs, &pos); + do_typedef ("location_t", locs, &pos); + do_typedef ("source_locus", create_pointer (locs), &pos); +#endif +} + int main (int argc, char **argv) { size_t i; - static struct fileloc pos = { __FILE__, __LINE__ }; + static struct fileloc pos = { this_file, 0 }; /* fatal uses this */ progname = "gengtype"; @@ -3444,34 +3536,23 @@ main (int argc, char **argv) scalar_nonchar.u.scalar_is_char = false; gen_rtx_next (); - do_scalar_typedef ("CUMULATIVE_ARGS", &pos); - do_scalar_typedef ("REAL_VALUE_TYPE", &pos); - do_scalar_typedef ("double_int", &pos); - do_scalar_typedef ("uint8", &pos); - do_scalar_typedef ("jword", &pos); - do_scalar_typedef ("JCF_u2", &pos); -#ifdef USE_MAPPED_LOCATION - do_scalar_typedef ("location_t", &pos); - do_scalar_typedef ("source_locus", &pos); -#endif - do_scalar_typedef ("void", &pos); - + /* These types are set up with #define or else outside of where + we can see them. */ + pos.line = __LINE__ + 1; + do_scalar_typedef ("CUMULATIVE_ARGS", &pos); pos.line++; + do_scalar_typedef ("REAL_VALUE_TYPE", &pos); pos.line++; + do_scalar_typedef ("double_int", &pos); pos.line++; + do_scalar_typedef ("uint8", &pos); pos.line++; + do_scalar_typedef ("jword", &pos); pos.line++; + do_scalar_typedef ("JCF_u2", &pos); pos.line++; + do_scalar_typedef ("void", &pos); pos.line++; do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos); - - do_typedef ("HARD_REG_SET", create_array (&scalar_nonchar, "2"), &pos); + define_location_structures (); for (i = 0; i < num_gt_files; i++) - { - parse_file (gt_files[i]); -#ifndef USE_MAPPED_LOCATION - /* temporary kludge - gengtype doesn't handle conditionals. - Manually add source_locus *after* we've processed input.h. */ - if (i == 0) - do_typedef ("source_locus", create_pointer (resolve_typedef ("location_t", &pos)), &pos); -#endif - } + parse_file (gt_files[i]); - if (hit_error != 0) + if (hit_error) return 1; set_gc_used (variables); @@ -3485,5 +3566,7 @@ main (int argc, char **argv) write_rtx_next (); close_output_files (); - return (hit_error != 0); + if (hit_error) + return 1; + return 0; } diff --git a/gcc/gengtype.h b/gcc/gengtype.h index 345d80d9022..a23e2778e93 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -41,6 +41,9 @@ extern struct fileloc lexer_line; extern void error_at_line (struct fileloc *pos, const char *msg, ...) ATTRIBUTE_PRINTF_2; +/* Like asprintf, but calls fatal() on out of memory. */ +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); @@ -57,6 +60,7 @@ 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 pair_p nreverse_pairs (pair_p list); 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); @@ -65,10 +69,45 @@ extern void note_def_vec (const char *typename, bool is_scalar, extern void note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos); -/* Lexer and parser routines, most automatically generated. */ -extern int yylex (void); -extern void yyerror (const char *); -extern int yyparse (void); +/* Lexer and parser routines. */ +extern int yylex (const char **yylval); +extern void yybegin (const char *fname); +extern void yyend (void); extern void parse_file (const char *name); +extern bool hit_error; +/* Token codes. */ +enum { + EOF_TOKEN = 0, + + /* Per standard convention, codes in the range (0, UCHAR_MAX] + represent single characters with those character codes. */ + + CHAR_TOKEN_OFFSET = UCHAR_MAX + 1, + GTY_TOKEN = CHAR_TOKEN_OFFSET, + TYPEDEF, + EXTERN, + STATIC, + UNION, + STRUCT, + ENUM, + VEC_TOKEN, + DEFVEC_OP, + DEFVEC_I, + DEFVEC_ALLOC, + ELLIPSIS, + PTR_ALIAS, + NESTED_PTR, + PARAM_IS, + NUM, + SCALAR, + ID, + STRING, + CHAR, + ARRAY, + + /* print_token assumes that any token >= FIRST_TOKEN_WITH_VALUE may have + a meaningful value to be printed. */ + FIRST_TOKEN_WITH_VALUE = PARAM_IS +}; #endif diff --git a/gcc/input.h b/gcc/input.h index 2fea1a65c9b..efdfbd33854 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -28,6 +28,9 @@ extern struct line_maps line_table; /* The location for declarations in "" */ #define BUILTINS_LOCATION ((source_location) 2) +/* Note: if any of the types defined inside this #ifdef are changed, + gengtype.c:define_location_structures must be updated to match. */ + #ifdef USE_MAPPED_LOCATION typedef struct