From patchwork Thu Sep 9 16:35:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Basile Starynkevitch X-Patchwork-Id: 64311 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 8FA0FB70D4 for ; Fri, 10 Sep 2010 02:35:42 +1000 (EST) Received: (qmail 22795 invoked by alias); 9 Sep 2010 16:35:38 -0000 Received: (qmail 20837 invoked by uid 22791); 9 Sep 2010 16:35:20 -0000 X-SWARE-Spam-Status: No, hits=-0.0 required=5.0 tests=AWL, BAYES_00, RCVD_IN_JMF_BL, TW_CP, TW_FL, TW_GT, TW_PF, TW_VF, TW_YY X-Spam-Check-By: sourceware.org Received: from smtp-118-thursday.nerim.net (HELO maiev.nerim.net) (62.4.16.118) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 09 Sep 2010 16:35:07 +0000 Received: from hector.lesours (ours.starynkevitch.net [213.41.244.95]) by maiev.nerim.net (Postfix) with ESMTP id 8B165B8460; Thu, 9 Sep 2010 18:35:02 +0200 (CEST) Received: from basile18 by hector.lesours with local (Exim 4.72) (envelope-from ) id 1Otk5W-0006xI-Au; Thu, 09 Sep 2010 18:35:02 +0200 Date: Thu, 9 Sep 2010 18:35:02 +0200 From: Basile Starynkevitch To: Basile Starynkevitch , gcc-patches@gcc.gnu.org Subject: gengtype improvements for plugins, completed! patch 3/N [inputfile] Message-ID: <20100909163502.GA26609@hector.lesours> References: <1283012591.3067.17.camel@glinka> <20100907222345.3083cde3.basile@starynkevitch.net> <20100908134658.GA27775@hector.lesours> <20100908175108.GA1112@hector.lesours> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20100908175108.GA1112@hector.lesours> User-Agent: Mutt/1.5.20 (2009-06-14) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello All, [join work by Basile Starynkevitch & Jeremie Salvucci] References: http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02060.html http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00616.html http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00663.html http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02063.html As I told in http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00808.html I am continuing to send the complete patch series of our gengtype work. This does not mean I am ignoring the recieved feedback. I intend to send a third round of patches once this "complete!" round is ended. I am taking into account most of Laurynas comments in http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00212.html with the important exception of INPUT_FILE_MAGIC, discussed below. Laurynas thinks that adding a magic number don't bring anything and is just a temporary trick we (Jeremie & me Basile) used to code this patch. This is indeed true, but I (Basile) believe that this trick is really useful to future gengtype hackers, since input files are painfully reachable from types in a non-trivial way (and that very fact is an occasion for bugs). I would like opinion of other people, in particular of reviewers, on that issue. As I told before sending our patch serie, gengtype is difficult to understand, and we insist on defensive programming. And this INPUT_FILE_MAGIC used in macro CHECK_INPUT_FILE_MAGIC is exactly a case of defensive programming (disabled unless ENABLE_CHECKING is configured). It will be very probably useful to future gengtype hackers, so I pray the allmighty reviewers to consider accepting it. So to please Laurynas and some potential reviewer, I am providing two variants of this patch. Both variants did take into account all Laurynas comments (except those related to INPUT_FILE_MAGIC). In a first variant, produced with diff -u -p $(svn stat . |awk '/M/{print $2}') \ --from-file ../gengtype-gcc-02-verbosity > \ $HOME/tmp/gengtype_patch_3_of_N__inputfile-relto02.diff contains the INPUT_FILE_MAGIC trick. This produce a first variant of a relative patch. It has my strong preference, and future patches patches of this patch serie will be relative to it. To please Laurynas and a potential reviewer, I am then editing manually gengtype.[ch] to remove every INPUT_FILE_MAGIC trick and running again diff -u -p $(svn stat . |awk '/M/{print $2}') \ --from-file ../gengtype-gcc-02-verbosity > \ $HOME/tmp/gengtype_patch_3_of_N__inputfile-relto02-nomagic.diff ########## gcc/ChangeLog entry is 2010-09-09 Jeremie Salvucci Basile Starynkevitch * gengtype.c (get_output_file_name, plugin_files) (get_file_srcdir_relative_path, nb_plugin_files): moved to gengtype.h. (get_file_basename, get_file_realbasename, get_file_langdir): Use an input_file as argument. (error_at_line): Use input_file-s. (gt_files, num_gt_files, this_file, system_h_file): Declared as input_file-s. (lang_dir_names, num_lang_dirs): No static. (get_lang_bitmap, set_lang_bitmap): Moved to gengtype.h. (read_input_list): Use input_file-s. (new_structure): Use system_h_file. (creat_field_all, get_file_realbasename) (get_file_srcdir_relative_path, get_file_basename) (get_file_langdir, get_file_gtfilename) (get_output_file_with_visibility, get_output_file_name) (put_mangled_filename): Use input_file-s. (struct flist): Removed name and added file field. (output_type_enum): Use input_file-s. (finish_root_table, write_roots): Use file not name field of struct flist. (dump_fileloc, parse_program_options): Use input_file-s. * gengtype.h (struct input_file_st, input_file): New structure and type. (INPUT_FILE_MAGIC, CHECK_INPUT_FILE_MAGIC): New macros. (gt_files, num_gt_files): New variables moved from gengtype.c. (this_file, system_h_file): New variables. (input_file_by_name): Declared new function. (get_input_file_name): New inline function. (get_lang_bitmap, set_lang_bitmap): Moved from gengtype.c and updated. (struct fileloc): field file changed type. (lang_dir_names, num_lang_dirs): moved from gengtype.c. (get_output_file_with_visibility, get_output_file_name): Use input_file-s. * gengtype-lex.l: Updated copyright year. Included errors.h. (yybegin): use input_file-s. * gengtype-parse.c: Updated copyright year. Included errors.h. (parse_error): Use input_file-s. (type): Generate anonymous names differently for GCC source input and other input. ########## I particularily welcome comments on this patch, especially comments by reviewers about magic or no magic. Regards. --- ../gengtype-gcc-02-verbosity/gengtype.c 2010-09-08 16:36:26.000000000 +0200 +++ gcc/gengtype.c 2010-09-09 16:05:41.000000000 +0200 @@ -123,7 +123,6 @@ struct type -const char *get_output_file_name (const char *); /* The list of output files. */ @@ -137,12 +136,12 @@ outf_p header_file; /* The name of the file containing the list of input files. */ static char* inputlist; -/* The plugin input files and their number; in that case only - a single file is produced. */ -static char** plugin_files; +/* The plugin input files and their number; in plugin mode only a + single file is produced. */ +static input_file** plugin_files; static size_t nb_plugin_files; -/* the generated plugin output file and name. */ +/* the generated plugin output file and name in plugin mode. */ static outf_p plugin_output; static char* plugin_output_filename; @@ -164,12 +163,11 @@ int verbosity_level; static outf_p create_file (const char *, const char *); -static const char * get_file_basename (const char *); -static const char * get_file_realbasename (const char *); -static const char * get_file_srcdir_relative_path (const char *); +static const char * get_file_basename (const input_file *); +static const char * get_file_realbasename (const input_file *); static int get_prefix_langdir_index (const char *); -static const char * get_file_langdir (const char *); +static const char * get_file_langdir (const input_file *); /* Nonzero iff an error has occurred. */ @@ -189,7 +187,8 @@ error_at_line (const struct fileloc *pos va_start (ap, msg); - fprintf (stderr, "%s:%d: ", pos->file, pos->line); + gcc_assert (pos != NULL && pos->file != NULL); + fprintf (stderr, "%s:%d: ", get_input_file_name (pos->file), pos->line); vfprintf (stderr, msg, ap); fputc ('\n', stderr); hit_error = true; @@ -217,18 +216,17 @@ xasprintf (const char *format, ...) /* Input file handling. */ /* Table of all input files. */ -static const char **gt_files; -static size_t num_gt_files; +input_file** gt_files; +size_t num_gt_files; + +/* Special files, initialized very early in main. */ +input_file* this_file; /* for gengtype.c */ +input_file* system_h_file; /* for system.h */ -/* 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. */ -const char this_file[] = __FILE__; -const char system_h_file[] = "system.h"; /* Vector of per-language directories. */ -static const char **lang_dir_names; -static size_t num_lang_dirs; +const char **lang_dir_names; +size_t num_lang_dirs; /* An array of output files suitable for definitions. There is one BASE_FILES entry for each language. */ @@ -246,37 +244,6 @@ static outf_p *base_files; buffer set up by read_input_list. It may be unaligned, so we have to read it byte-by-byte. */ -static lang_bitmap -get_lang_bitmap (const char *gtfile) -{ - - if (gtfile == this_file || gtfile == system_h_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 - caller of this function is read_input_list. */ -static void -set_lang_bitmap (char *gtfile, lang_bitmap n) -{ - int i; - for (i = -1; i >= -(int) sizeof (lang_bitmap); i--) - { - gtfile[i] = n & ((1U << CHAR_BIT)-1); - n >>= CHAR_BIT; - } -} - - #if ENABLE_CHECKING /* Utility debugging function, printing the various type counts within a list of types. Called thru the DBGPRINT_COUNT_TYPE macro. */ @@ -468,11 +435,11 @@ read_input_list (const char *listname) size_t nfiles = 0; lang_bitmap curlangs = (1 << num_lang_dirs) - 1; - epos.file = listname; + epos.file = input_file_by_name (listname); epos.line = 0; lang_dir_names = XNEWVEC (const char *, num_lang_dirs); - gt_files = XNEWVEC (const char *, num_gt_files); + gt_files = XNEWVEC (input_file *, num_gt_files); for (;;) { @@ -502,13 +469,16 @@ read_input_list (const char *listname) else { size_t i; + input_file *inpf = input_file_by_name (line); gcc_assert (nfiles <= num_gt_files); for (i = 0; i < nfiles; i++) - if (strcmp (gt_files[i], line) == 0) + /* Since the input_file-s are uniquely hash-consed, we + can just compare pointers! */ + if (gt_files[i] == inpf) { /* Throw away the string we just read, and add the current language to the existing string's bitmap. */ - lang_bitmap bmap = get_lang_bitmap (gt_files[i]); + lang_bitmap bmap = get_lang_bitmap (inpf); if (bmap & curlangs) error_at_line (&epos, "file %s specified more than once " "for language %s", line, langno == 0 @@ -516,13 +486,13 @@ read_input_list (const char *listname) : lang_dir_names[langno - 1]); bmap |= curlangs; - set_lang_bitmap (CONST_CAST(char *, gt_files[i]), bmap); + set_lang_bitmap (inpf, bmap); here = committed; goto next_line; } - set_lang_bitmap (line, curlangs); - gt_files[nfiles++] = line; + set_lang_bitmap (inpf, curlangs); + gt_files[nfiles++] = inpf; } } /* Update the global counts now that we know accurately how many @@ -745,16 +715,7 @@ new_structure (const char *name, int isu 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; - } - } + s->u.s.line.file = system_h_file; return s; } @@ -893,7 +854,7 @@ note_variable (const char *s, type_p t, /* Most-general structure field creator. */ static pair_p create_field_all (pair_p next, type_p type, const char *name, options_p opt, - const char *file, int line) + input_file* inpf, int line) { pair_p field; @@ -902,7 +863,7 @@ create_field_all (pair_p next, type_p ty field->type = type; field->name = name; field->opt = opt; - field->line.file = file; + field->line.file = inpf; field->line.line = line; return field; } @@ -1658,8 +1619,9 @@ open_base_files (void) components skipped. */ static const char * -get_file_realbasename (const char *f) +get_file_realbasename (const input_file *inpf) { + const char* f = get_input_file_name (inpf); const char * lastslash = strrchr (f, '/'); return (lastslash != NULL) ? lastslash + 1 : f; @@ -1668,26 +1630,27 @@ get_file_realbasename (const char *f) /* For F a filename, return the relative path to F from $(srcdir) if the latter is a prefix in F, NULL otherwise. */ -static const char * -get_file_srcdir_relative_path (const char *f) +const char * +get_file_srcdir_relative_path (const input_file *inpf) { - if (strlen (f) > srcdir_len - && IS_DIR_SEPARATOR (f[srcdir_len]) - && memcmp (f, srcdir, srcdir_len) == 0) - return f + srcdir_len + 1; + const char* fname = get_input_file_name (inpf); + if (strlen (fname) > srcdir_len + && IS_DIR_SEPARATOR (fname[srcdir_len]) + && memcmp (fname, srcdir, srcdir_len) == 0) + return fname + srcdir_len + 1; else return NULL; } -/* For F a filename, return the relative path to F from $(srcdir) if the +/* For F an input_file, return the relative path to F from $(srcdir) if the latter is a prefix in F, or the real basename of F otherwise. */ static const char * -get_file_basename (const char *f) +get_file_basename (const input_file *inpf) { - const char * srcdir_path = get_file_srcdir_relative_path (f); + const char * srcdir_path = get_file_srcdir_relative_path (inpf); - return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (f); + return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (inpf); } /* For F a filename, return the lang_dir_names relative index of the language @@ -1713,19 +1676,19 @@ get_prefix_langdir_index (const char *f) return -1; } -/* For F a filename, return the name of language directory where F is located, - if any, NULL otherwise. */ +/* For INPF an input_file, return the name of language directory where + INPF is located, if any, NULL otherwise. */ static const char * -get_file_langdir (const char *f) +get_file_langdir (const input_file *inpf) { /* Get the relative path to F from $(srcdir) and find the language by comparing the prefix with language directory names. If F is not even srcdir relative, no point in looking further. */ int lang_index; - const char * srcdir_relative_path = get_file_srcdir_relative_path (f); - const char * r; + const char *srcdir_relative_path = get_file_srcdir_relative_path (inpf); + const char *r; if (!srcdir_relative_path) return NULL; @@ -1742,16 +1705,16 @@ get_file_langdir (const char *f) return r; } -/* The gt- output file name for F. */ +/* The gt- output file name for INPF. */ static const char * -get_file_gtfilename (const char *f) +get_file_gtfilename (const input_file *inpf) { /* Cook up an initial version of the gt- file name from the file real basename and the language name, if any. */ - const char *basename = get_file_realbasename (f); - const char *langdir = get_file_langdir (f); + const char *basename = get_file_realbasename (inpf); + const char *langdir = get_file_langdir (inpf); char * result = (langdir ? xasprintf ("gt-%s-%s", langdir, basename) @@ -1777,7 +1740,7 @@ get_file_gtfilename (const char *f) INPUT_FILE. */ outf_p -get_output_file_with_visibility (const char *input_file) +get_output_file_with_visibility (input_file* inpf) { outf_p r; size_t len; @@ -1788,30 +1751,30 @@ get_output_file_with_visibility (const c /* This can happen when we need a file with visibility on a structure that we've never seen. We have to just hope that it's globally visible. */ - if (input_file == NULL) - input_file = "system.h"; + if (inpf == NULL) + inpf = system_h_file; - /* In plugin mode, return NULL unless the input_file is one of the - plugin_files. */ + /* In plugin mode, return NULL unless the INPF is one of the + plugin_files. We can compare input_file-s by pointer equality. */ if (plugin_files) { size_t i; for (i = 0; i < nb_plugin_files; i++) - if (strcmp (input_file, plugin_files[i]) == 0) + if (inpf == plugin_files[i]) return plugin_output; return NULL; } /* Determine the output file name. */ - basename = get_file_basename (input_file); + basename = get_file_basename (inpf); len = strlen (basename); if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0) || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0) || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0)) { - output_name = get_file_gtfilename (input_file); + output_name = get_file_gtfilename (inpf); for_name = basename; } /* Some headers get used by more than one front-end; hence, it @@ -1863,13 +1826,13 @@ get_output_file_with_visibility (const c } /* The name of an output file, suitable for definitions, that can see - declarations made in INPUT_FILE and is linked into every language - that uses INPUT_FILE. */ + declarations made in INPF and is linked into every language + that uses INPF. */ const char * -get_output_file_name (const char *input_file) +get_output_file_name (input_file *inpf) { - outf_p o = get_output_file_with_visibility (input_file); + outf_p o = get_output_file_with_visibility (inpf); if (o) return o->name; return NULL; @@ -1951,7 +1914,7 @@ close_output_files (void) struct flist { struct flist *next; int started_p; - const char *name; + const input_file *file; outf_p f; }; @@ -2000,7 +1963,7 @@ static void write_local (outf_p output_h type_p param_structs); static void write_enum_defn (type_p structures, type_p param_structs); static int contains_scalar_p (type_p t); -static void put_mangled_filename (outf_p , const char *); +static void put_mangled_filename (outf_p , const input_file *); static void finish_root_table (struct flist *flp, const char *pfx, const char *tname, const char *lastname, const char *name); @@ -2471,7 +2434,7 @@ walk_type (type_p t, struct walk_type_da { fprintf (stderr, "%s:%d: warning: field `%s' is missing `tag' or `default' option\n", - d->line->file, d->line->line, f->name); + get_input_file_name (d->line->file), d->line->line, f->name); continue; } else if (union_p && ! (default_p || tagid)) @@ -2639,16 +2602,27 @@ output_type_enum (outf_p of, type_p s) static outf_p get_output_file_for_structure (const_type_p s, type_p *param) { - const char * fn = s->u.s.line.file; + const input_file* fn = NULL; int i; + if (UNION_OR_STRUCT_P (s)) + fn = s->u.s.line.file; + else if (s->kind == TYPE_PARAM_STRUCT) + fn = s->u.param_struct.line.file; + + CHECK_INPUT_FILE_MAGIC (fn); + /* This is a hack, and not the good kind either. */ for (i = NUM_PARAM - 1; i >= 0; i--) if (param && param[i] && param[i]->kind == TYPE_POINTER && UNION_OR_STRUCT_P (param[i]->u.p)) fn = param[i]->u.p->u.s.line.file; - return get_output_file_with_visibility (fn); + CHECK_INPUT_FILE_MAGIC (fn); + + /* The call to get_output_file_with_visibility may update fn by + caching its result inside, so we need the CONST_CAST. */ + return get_output_file_with_visibility (CONST_CAST(input_file*, fn)); } /* For S, a structure that's part of ORIG_S, and using parameters @@ -3229,9 +3203,12 @@ contains_scalar_p (type_p t) /* Mangle FN and print it to F. */ static void -put_mangled_filename (outf_p f, const char *fn) +put_mangled_filename (outf_p f, const input_file *fn) { - const char *name = get_output_file_name (fn); + /* The call to get_output_file_name may indirectly update fn since + get_output_file_with_visibility caches its result inside, so we + need the CONST_CAST. */ + const char *name = get_output_file_name (CONST_CAST (input_file*, fn)); if (!f || !name) return; for (; *name != 0; name++) @@ -3261,7 +3238,7 @@ finish_root_table (struct flist *flp, co for (fli2 = flp; fli2 && base_files; fli2 = fli2->next) if (fli2->started_p) { - lang_bitmap bitmap = get_lang_bitmap (fli2->name); + lang_bitmap bitmap = get_lang_bitmap (fli2->file); int fnum; for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1) @@ -3270,7 +3247,7 @@ finish_root_table (struct flist *flp, co oprintf (base_files[fnum], "extern const struct %s gt_%s_", tname, pfx); - put_mangled_filename (base_files[fnum], fli2->name); + put_mangled_filename (base_files[fnum], fli2->file); oprintf (base_files[fnum], "[];\n"); } } @@ -3287,7 +3264,7 @@ finish_root_table (struct flist *flp, co for (fli2 = flp; fli2; fli2 = fli2->next) if (fli2->started_p) { - lang_bitmap bitmap = get_lang_bitmap (fli2->name); + lang_bitmap bitmap = get_lang_bitmap (fli2->file); int fnum; fli2->started_p = 0; @@ -3296,7 +3273,7 @@ finish_root_table (struct flist *flp, co if (bitmap & 1) { oprintf (base_files[fnum], " gt_%s_", pfx); - put_mangled_filename (base_files[fnum], fli2->name); + put_mangled_filename (base_files[fnum], fli2->file); oprintf (base_files[fnum], ",\n"); } } @@ -3632,8 +3609,8 @@ write_roots (pair_p variables, bool emit fli->f = f; fli->next = flp; fli->started_p = 0; - fli->name = v->line.file; - gcc_assert(fli->name); + fli->file = v->line.file; + gcc_assert(fli->file); flp = fli; oprintf (f, "\n/* GC roots. */\n\n"); @@ -4171,8 +4148,8 @@ dump_options (int indent, options_p opt) static void dump_fileloc (int indent, struct fileloc line) { - printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', line.file, - line.line); + printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', + get_input_file_name (line.file), line.line); } /* Recursively dumps the struct, union, or a language-specific @@ -4461,12 +4438,64 @@ parse_program_options (int argc, char**a for (i = 0; i < (int) nb_plugin_files; i++) { char *name = argv[i + optind]; - plugin_files[i] = name; + plugin_files[i] = input_file_by_name (name); } } } + +/******* Manage input files. ******/ + +/* Hash table of unique input file names. */ +static htab_t input_file_htab; + +/* Find or allocate a new input_file by hash-consing it. */ +input_file* +input_file_by_name (const char* name) +{ + PTR* slot; + input_file* f = NULL; + int namlen = 0; + if (!name) + return NULL; + namlen = strlen (name); + f = XCNEWVAR (input_file, sizeof(input_file)+namlen+2); + f->inpbitmap = 0; + f->inpoutf = NULL; + f->inpmagic = INPUT_FILE_MAGIC; + strcpy (f->inpname, name); + slot = htab_find_slot (input_file_htab, f, INSERT); + gcc_assert (slot != NULL); + if (*slot) { + /* Already known input file. */ + free (f); + return (input_file*)(*slot); + } + /* New input file. */ + *slot = f; + return f; +} + +/* Hash table support routines for input_file-s. */ +static hashval_t +htab_hash_inputfile (const void *p) +{ + const input_file *inpf = (const input_file *) p; + gcc_assert (inpf); + return htab_hash_string (get_input_file_name (inpf)); +} + +static int +htab_eq_inputfile (const void *x, const void *y) +{ + const input_file *inpfx = (const input_file *) x; + const input_file *inpfy = (const input_file *) y; + gcc_assert (inpfx != NULL && inpfy != NULL); + return !strcmp (get_input_file_name (inpfx), get_input_file_name (inpfy)); +} + + int main (int argc, char **argv) { @@ -4479,6 +4508,12 @@ main (int argc, char **argv) /* Set the scalar_is_char union number for predefined scalar types. */ scalar_nonchar.u.scalar_is_char = FALSE; scalar_char.u.scalar_is_char = TRUE; + /* Create the hash-table used to hash-cons input files. */ + input_file_htab = + htab_create (800, htab_hash_inputfile, htab_eq_inputfile, NULL); + /* Initialize our special input files. */ + this_file = input_file_by_name (__FILE__); + system_h_file = input_file_by_name ("system.h"); parse_program_options (argc, argv); @@ -4516,10 +4551,11 @@ main (int argc, char **argv) do_scalar_typedef ("void", &pos); pos.line++; do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos); read_input_list (inputlist); - for (i = 0; i < num_gt_files; i++) { - parse_file (gt_files[i]); - DBGPRINTF ("parsed file #%d %s", (int) i, gt_files[i]); - } + for (i = 0; i < num_gt_files; i++) + { + parse_file (get_input_file_name (gt_files[i])); + DBGPRINTF ("parsed file #%d %s", (int) i, get_input_file_name (gt_files[i])); + } DBGPRINT_COUNT_TYPE ("structures after parsing", structures); DBGPRINT_COUNT_TYPE ("param_structs after parsing", param_structs); if (verbosity_level >= 1) @@ -4546,7 +4582,11 @@ main (int argc, char **argv) /* Parse our plugin files. */ for (ix = 0; ix < nb_plugin_files; ix++) - parse_file (plugin_files[ix]); + { + parse_file (get_input_file_name (plugin_files[ix])); + DBGPRINTF ("parsed plugin file #%d %s", (int) ix, + get_input_file_name (plugin_files[ix])); + } if (hit_error) return 1; --- ../gengtype-gcc-02-verbosity/gengtype.h 2010-09-08 16:09:52.000000000 +0200 +++ gcc/gengtype.h 2010-09-09 16:31:09.000000000 +0200 @@ -25,13 +25,86 @@ along with GCC; see the file COPYING3. represented by a bitmap. */ typedef unsigned lang_bitmap; -/* A file position, mostly for error messages. - The FILE element may be compared using pointer equality. */ +/* Variable length structure representing an input file. A hash table + ensure uniqueness for a given input file name. The only function + allocating input_file-s is input_file_by_name. */ +struct input_file_st { + struct outf* inpoutf; /* Cached corresponding output file, computed + in get_output_file_with_visibility. */ + lang_bitmap inpbitmap; /* The set of languages using this file. */ + char inpname[1]; /* a flexible array, ended by a null char. */ +}; +typedef struct input_file_st input_file; + +/* Table of all input files, and its size. */ +extern input_file** gt_files; +extern size_t num_gt_files; + +/* A number of places use the name of this "gengtype.c" file for a + location for things that we can't rely on the source to define. We + also need to refer to the "system.h" file specifically. These two + pointers are initialized early in main. */ +extern input_file* this_file; +extern input_file* system_h_file; + +/* Retrieve or create the input_file for a given name, which is a file + path. This is the only function allocating input_file-s and it is + hash-consing them. */ +input_file* input_file_by_name (const char* name); + + +/* For F an input_file, return the relative path to F from $(srcdir) + if the latter is a prefix in F, NULL otherwise. */ +const char *get_file_srcdir_relative_path (const input_file *inpf); + +/* Get the name of an input file. */ +static inline const char* +get_input_file_name (const input_file *inpf) +{ + if (inpf) + return inpf->inpname; + return NULL; +} + +/* Return a bitmap which has bit `1 << BASE_FILE_' set iff + INPUT_FILE is used by . + + This function should be written to assume that a file _is_ used + if the situation is unclear. If it wrongly assumes a file _is_ used, + a linker error will result. If it wrongly assumes a file _is not_ used, + some GC roots may be missed, which is a much harder-to-debug problem. + */ + +static inline lang_bitmap +get_lang_bitmap (const input_file* inpf) +{ + if (inpf == NULL) + return 0; + return inpf->inpbitmap; +} + +/* Set the bitmap returned by get_lang_bitmap. The only legitimate + callers of this function are read_input_list & read_state_*. */ +static inline void +set_lang_bitmap (input_file* inpf, lang_bitmap n) +{ + gcc_assert (inpf); + inpf->inpbitmap = n; +} + +/* A file position, mostly for error messages. The FILE element may + be compared using pointer equality since it is hash-consed. */ struct fileloc { - const char *file; + input_file *file; int line; }; +/* Vector of per-language directories. */ +extern const char **lang_dir_names; +extern size_t num_lang_dirs; + + + /* Data types handed around within, but opaque to, the lexer and parser. */ typedef struct pair *pair_p; typedef struct type *type_p; @@ -65,10 +138,14 @@ void oprintf (outf_p o, const char *S, . ATTRIBUTE_PRINTF_2; /* An output file, suitable for definitions, that can see declarations - made in INPUT_FILE and is linked into every language that uses - INPUT_FILE. May return NULL in plugin mode. */ -extern outf_p get_output_file_with_visibility - (const char *input_file); + made in INPF and is linked into every language that uses INPF. May + return NULL in plugin mode. */ +outf_p get_output_file_with_visibility (input_file* inpf); + +/* The name of an output file, suitable for definitions, that can see + declarations made in INPF and is linked into every language that + uses INPF. May return NULL. */ +const char *get_output_file_name (input_file *inpf); /* Source directory. */ extern const char *srcdir; --- ../gengtype-gcc-02-verbosity/gengtype-lex.l 2010-08-27 07:56:01.000000000 +0200 +++ gcc/gengtype-lex.l 2010-09-09 16:01:23.000000000 +0200 @@ -1,6 +1,6 @@ /* -*- indented-text -*- */ /* Process source files and output type information. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. %{ #include "bconfig.h" #include "system.h" +#include "errors.h" /* for fatal, needed by gengtype.h */ #define malloc xmalloc #define realloc xrealloc @@ -202,7 +203,7 @@ yybegin (const char *fname) perror (fname); exit (1); } - lexer_line.file = fname; + lexer_line.file = input_file_by_name (fname); lexer_line.line = 1; } --- ../gengtype-gcc-02-verbosity/gengtype-parse.c 2010-08-27 07:56:01.000000000 +0200 +++ gcc/gengtype-parse.c 2010-09-09 16:01:41.000000000 +0200 @@ -1,5 +1,5 @@ /* Process source files and output type information. - Copyright (C) 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. #include "bconfig.h" #include "system.h" +#include "errors.h" /* for fatal, needed by gengtype.h */ #include "gengtype.h" /* This is a simple recursive-descent parser which understands a subset of @@ -135,7 +136,8 @@ parse_error (const char *msg, ...) { va_list ap; - fprintf (stderr, "%s:%d: parse error: ", lexer_line.file, lexer_line.line); + fprintf (stderr, "%s:%d: parse error: ", + get_input_file_name (lexer_line.file), lexer_line.line); va_start (ap, msg); vfprintf (stderr, msg, ap); @@ -679,6 +681,7 @@ static type_p type (options_p *optsp, bool nested) { const char *s; + static int anonymous_count; /* to generate unique pseudo-identifiers! */ *optsp = 0; switch (token ()) { @@ -695,15 +698,15 @@ type (options_p *optsp, bool nested) case UNION: { options_p opts = 0; - /* GTY annotations follow attribute syntax - GTY_BEFORE_ID is for union/struct declarations - GTY_AFTER_ID is for variable declarations. */ - enum { - NO_GTY, - GTY_BEFORE_ID, - GTY_AFTER_ID - } is_gty = NO_GTY; - bool is_union = (token () == UNION); + /* GTY annotations follow attribute syntax + GTY_BEFORE_ID is for union/struct declarations + GTY_AFTER_ID is for variable declarations. */ + enum { + NO_GTY, + GTY_BEFORE_ID, + GTY_AFTER_ID + } is_gty = NO_GTY; + bool is_union = (token () == UNION); advance (); /* Top-level structures that are not explicitly tagged GTY(()) @@ -713,40 +716,62 @@ type (options_p *optsp, bool nested) that we can't handle. */ if (nested || token () == GTY_TOKEN) { - is_gty = GTY_BEFORE_ID; - opts = gtymarker_opt (); + is_gty = GTY_BEFORE_ID; + opts = gtymarker_opt (); } if (token () == ID) s = advance (); else - s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); + { + /* We don't want to wire in the source directory (because + in plugin mode, the source directory can be unavailable + since gengtype has read its state). So if the input is + from GCC source directory, we use its relative path to + build an anonymous unique tag. */ + const char* relp = get_file_srcdir_relative_path (lexer_line.file); + anonymous_count++; + if (relp) + /* The input file is a GCC source file, we use a double + colon after anonymous. To be sure s is truly unique, + we also use anonymous_count. */ + s = xasprintf ("anonymous::%s:%d::%d", + relp, lexer_line.line, anonymous_count); + else + /* The input file is outside of GCC source tree, we use + a single colon after anonymous. To be sure s is + truly unique, we also use anonymous_count. */ + s = xasprintf ("anonymous:%s:%d::%d", + get_input_file_name (lexer_line.file), + lexer_line.line, anonymous_count); + + } /* Unfortunately above GTY_TOKEN check does not capture the typedef struct_type GTY case. */ if (token () == GTY_TOKEN) { - is_gty = GTY_AFTER_ID; - opts = gtymarker_opt (); + is_gty = GTY_AFTER_ID; + opts = gtymarker_opt (); } - if (is_gty) - { - if (token () == '{') - { - pair_p fields; - - if (is_gty == GTY_AFTER_ID) - parse_error ("GTY must be specified before identifier"); - - advance (); - fields = struct_field_seq (); - require ('}'); - return new_structure (s, is_union, &lexer_line, fields, opts); - } - } - else if (token () == '{') - consume_balanced ('{', '}'); + if (is_gty) + { + if (token () == '{') + { + pair_p fields; + + if (is_gty == GTY_AFTER_ID) + parse_error ("GTY must be specified before identifier"); + + advance (); + fields = struct_field_seq (); + require ('}'); + return new_structure (s, is_union, &lexer_line, fields, opts); + } + } + else if (token () == '{') + consume_balanced ('{', '}'); if (opts) *optsp = opts; return find_structure (s, is_union); @@ -754,11 +779,22 @@ type (options_p *optsp, bool nested) case ENUM: advance (); - if (token () == ID) - s = advance (); - else - s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); - + if (token () == ID) + s = advance (); + else + { + /* Again, we don't want to wire in the GCC source tree + directory. */ + const char* relp = get_file_srcdir_relative_path (lexer_line.file); + anonymous_count++; + if (relp) + s = xasprintf ("anonymous::%s:%d::%d", + relp, lexer_line.line, anonymous_count); + else + s = xasprintf ("anonymous:%s:%d::%d", + get_input_file_name (lexer_line.file), + lexer_line.line, anonymous_count); + } if (token () == '{') consume_balanced ('{','}'); return create_scalar_type (s);