X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libcpp%2Ffiles.c;h=29ccf3b701390b44f67d95dc3d7fd1f4e3cae161;hb=6bb01a79a81473958d449a9e04f76ea79c25d954;hp=3751184d02f092c56592604a5c171db208004fcc;hpb=248dfc421d6e30bdeb86fba2ff4c682ea5ada460;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libcpp/files.c b/libcpp/files.c index 3751184d02f..29ccf3b7013 100644 --- a/libcpp/files.c +++ b/libcpp/files.c @@ -1,7 +1,7 @@ /* Part of CPP library. File handling. Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 - Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Written by Per Bothner, 1994. Based on CCCP program by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 @@ -10,7 +10,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any +Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -19,8 +19,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +along with this program; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -74,6 +74,10 @@ struct _cpp_file /* The contents of NAME after calling read_file(). */ const uchar *buffer; + /* Pointer to the real start of BUFFER. read_file() might increment + BUFFER; when freeing, this this pointer must be used instead. */ + const uchar *buffer_start; + /* The macro, if any, preventing re-inclusion. */ const cpp_hashnode *cmacro; @@ -106,9 +110,6 @@ struct _cpp_file /* If BUFFER above contains the true contents of the file. */ bool buffer_valid; - - /* File is a PCH (on return from find_include_file). */ - bool pch; }; /* A singly-linked list for all searches for a given file name, with @@ -142,6 +143,7 @@ struct file_hash_entry { struct file_hash_entry *next; cpp_dir *start_dir; + source_location location; union { _cpp_file *file; @@ -149,6 +151,21 @@ struct file_hash_entry } u; }; +/* Number of entries to put in a file_hash_entry pool. */ +#define FILE_HASH_POOL_SIZE 127 + +/* A file hash entry pool. We allocate file_hash_entry object from + one of these. */ +struct file_hash_entry_pool +{ + /* Number of entries used from this pool. */ + unsigned int file_hash_entries_used; + /* Next pool in the chain; used when freeing. */ + struct file_hash_entry_pool *next; + /* The memory pool. */ + struct file_hash_entry pool[FILE_HASH_POOL_SIZE]; +}; + static bool open_file (_cpp_file *file); static bool pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch); @@ -228,6 +245,22 @@ open_file (_cpp_file *file) close (file->fd); file->fd = -1; } +#if defined(_WIN32) && !defined(__CYGWIN__) + else if (errno == EACCES) + { + /* On most UNIX systems, open succeeds on a directory. Above, + we check if we have opened a directory and if so, set errno + to ENOENT. However, on Windows, opening a directory + fails with EACCES. We want to return ENOENT in that + case too. */ + if (stat (file->path, &file->st) == 0 + && S_ISDIR (file->st.st_mode)) + errno = ENOENT; + else + /* The call to stat may have reset errno. */ + errno = EACCES; + } +#endif else if (errno == ENOTDIR) errno = ENOENT; @@ -255,6 +288,12 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch) if (file->name[0] == '\0' || !pfile->cb.valid_pch) return false; + /* If the file is not included as first include from either the toplevel + file or the command-line it is not a valid use of PCH. */ + if (pfile->all_files + && pfile->all_files->next_file) + return false; + flen = strlen (path); len = flen + sizeof (extension); pchname = XNEWVEC (char, len); @@ -290,9 +329,7 @@ pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch) } closedir (pchdir); } - if (valid) - file->pch = true; - else + if (!valid) *invalid_pch = true; } @@ -350,8 +387,8 @@ find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch) /* We copy the path name onto an obstack partly so that we don't leak the memory, but mostly so that we don't fragment the heap. */ - copy = obstack_copy0 (&pfile->nonexistent_file_ob, path, - strlen (path)); + copy = (char *) obstack_copy0 (&pfile->nonexistent_file_ob, path, + strlen (path)); free (path); pp = htab_find_slot_with_hash (pfile->nonexistent_file_hash, copy, hv, INSERT); @@ -457,7 +494,6 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f return file; } - open_file_failed (pfile, file, angle_brackets); if (invalid_pch) { cpp_error (pfile, CPP_DL_ERROR, @@ -466,6 +502,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f cpp_error (pfile, CPP_DL_ERROR, "use -Winvalid-pch for more information"); } + open_file_failed (pfile, file, angle_brackets); break; } @@ -505,6 +542,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f entry = new_file_hash_entry (pfile); entry->next = *hash_slot; entry->start_dir = start_dir; + entry->location = pfile->line_table->highest_location; entry->u.file = file; *hash_slot = entry; @@ -517,6 +555,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f entry = new_file_hash_entry (pfile); entry->next = *hash_slot; entry->start_dir = pfile->bracket_include; + entry->location = pfile->line_table->highest_location; entry->u.file = file; *hash_slot = entry; } @@ -527,6 +566,7 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f entry = new_file_hash_entry (pfile); entry->next = *hash_slot; entry->start_dir = pfile->quote_include; + entry->location = pfile->line_table->highest_location; entry->u.file = file; *hash_slot = entry; } @@ -555,7 +595,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file) return false; } - regular = S_ISREG (file->st.st_mode); + regular = S_ISREG (file->st.st_mode) != 0; if (regular) { /* off_t might have a wider range than ssize_t - in other words, @@ -605,8 +645,11 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file) cpp_error (pfile, CPP_DL_WARNING, "%s is shorter than expected", file->path); - file->buffer = _cpp_convert_input (pfile, CPP_OPTION (pfile, input_charset), - buf, size, total, &file->st.st_size); + file->buffer = _cpp_convert_input (pfile, + CPP_OPTION (pfile, input_charset), + buf, size, total, + &file->buffer_start, + &file->st.st_size); file->buffer_valid = true; return true; @@ -668,11 +711,12 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import) return false; /* Handle PCH files immediately; don't stack them. */ - if (file->pch) + if (file->pchname) { pfile->cb.read_pch (pfile, file->pchname, file->fd, file->path); - close (file->fd); file->fd = -1; + free ((void *) file->pchname); + file->pchname = NULL; return false; } @@ -775,7 +819,8 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import) /* Stack the buffer. */ buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size, - CPP_OPTION (pfile, preprocessed)); + CPP_OPTION (pfile, preprocessed) + && !CPP_OPTION (pfile, directives_only)); buffer->file = file; buffer->sysp = sysp; @@ -816,7 +861,8 @@ search_path_head (cpp_reader *pfile, const char *fname, int angle_brackets, /* For #include_next, skip in the search path past the dir in which the current file was found, but if it was found via an absolute path use the normal search logic. */ - if (type == IT_INCLUDE_NEXT && file->dir) + if (type == IT_INCLUDE_NEXT && file->dir + && file->dir != &pfile->no_search_path) dir = file->dir->next; else if (angle_brackets) dir = pfile->bracket_include; @@ -872,14 +918,15 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets, file = _cpp_find_file (pfile, fname, dir, false, angle_brackets); - /* Compensate for the increment in linemap_add. In the case of a - normal #include, we're currently at the start of the line - *following* the #include. A separate source_location for this - location makes no sense (until we do the LC_LEAVE), and - complicates LAST_SOURCE_LINE_LOCATION. This does not apply if we - found a PCH file (in which case linemap_add is not called) or we - were included from the command-line. */ - if (! file->pch && file->err_no == 0 && type != IT_CMDLINE) + /* Compensate for the increment in linemap_add that occurs in + _cpp_stack_file. In the case of a normal #include, we're + currently at the start of the line *following* the #include. A + separate source_location for this location makes no sense (until + we do the LC_LEAVE), and complicates LAST_SOURCE_LINE_LOCATION. + This does not apply if we found a PCH file (in which case + linemap_add is not called) or we were included from the + command-line. */ + if (file->pchname == NULL && file->err_no == 0 && type != IT_CMDLINE) pfile->line_table->highest_location--; return _cpp_stack_file (pfile, file, type == IT_IMPORT); @@ -894,15 +941,28 @@ open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets) errno = file->err_no; if (print_dep && CPP_OPTION (pfile, deps.missing_files) && errno == ENOENT) - deps_add_dep (pfile->deps, file->name); + { + deps_add_dep (pfile->deps, file->name); + /* If the preprocessor output (other than dependency information) is + being used, we must also flag an error. */ + if (CPP_OPTION (pfile, deps.need_preprocessor_output)) + cpp_errno (pfile, CPP_DL_FATAL, file->path); + } else { - /* If we are outputting dependencies but not for this file then - don't error because we can still produce correct output. */ - if (CPP_OPTION (pfile, deps.style) && ! print_dep) - cpp_errno (pfile, CPP_DL_WARNING, file->path); + /* If we are not outputting dependencies, or if we are and dependencies + were requested for this file, or if preprocessor output is needed + in addition to dependency information, this is an error. + + Otherwise (outputting dependencies but not for this file, and not + using the preprocessor output), we can still produce correct output + so it's only a warning. */ + if (CPP_OPTION (pfile, deps.style) == DEPS_NONE + || print_dep + || CPP_OPTION (pfile, deps.need_preprocessor_output)) + cpp_errno (pfile, CPP_DL_FATAL, file->path); else - cpp_errno (pfile, CPP_DL_ERROR, file->path); + cpp_errno (pfile, CPP_DL_WARNING, file->path); } } @@ -936,12 +996,24 @@ make_cpp_file (cpp_reader *pfile, cpp_dir *dir, const char *fname) static void destroy_cpp_file (_cpp_file *file) { - if (file->buffer) - free ((void *) file->buffer); + free ((void *) file->buffer_start); free ((void *) file->name); free (file); } +/* Release all the files allocated by this reader. */ +static void +destroy_all_cpp_files (cpp_reader *pfile) +{ + _cpp_file *iter = pfile->all_files; + while (iter) + { + _cpp_file *next = iter->next_file; + destroy_cpp_file (iter); + iter = next; + } +} + /* A hash of directory names. The directory names are the path names of files which contain a #include "", the included file name is appended to this directories. @@ -976,6 +1048,7 @@ make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp) entry = new_file_hash_entry (pfile); entry->next = *hash_slot; entry->start_dir = NULL; + entry->location = pfile->line_table->highest_location; entry->u.dir = dir; *hash_slot = entry; @@ -986,20 +1059,35 @@ make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp) static void allocate_file_hash_entries (cpp_reader *pfile) { - pfile->file_hash_entries_used = 0; - pfile->file_hash_entries_allocated = 127; - pfile->file_hash_entries = XNEWVEC (struct file_hash_entry, - pfile->file_hash_entries_allocated); + struct file_hash_entry_pool *pool = XNEW (struct file_hash_entry_pool); + pool->file_hash_entries_used = 0; + pool->next = pfile->file_hash_entries; + pfile->file_hash_entries = pool; } /* Return a new file hash entry. */ static struct file_hash_entry * new_file_hash_entry (cpp_reader *pfile) { - if (pfile->file_hash_entries_used == pfile->file_hash_entries_allocated) + unsigned int idx; + if (pfile->file_hash_entries->file_hash_entries_used == FILE_HASH_POOL_SIZE) allocate_file_hash_entries (pfile); - return &pfile->file_hash_entries[pfile->file_hash_entries_used++]; + idx = pfile->file_hash_entries->file_hash_entries_used++; + return &pfile->file_hash_entries->pool[idx]; +} + +/* Free the file hash entry pools. */ +static void +free_file_hash_entries (cpp_reader *pfile) +{ + struct file_hash_entry_pool *iter = pfile->file_hash_entries; + while (iter) + { + struct file_hash_entry_pool *next = iter->next; + free (iter); + iter = next; + } } /* Returns TRUE if a file FNAME has ever been successfully opened. @@ -1019,6 +1107,25 @@ cpp_included (cpp_reader *pfile, const char *fname) return entry != NULL; } +/* Returns TRUE if a file FNAME has ever been successfully opened + before LOCATION. This routine is not intended to correctly handle + filenames aliased by links or redundant . or .. traversals etc. */ +bool +cpp_included_before (cpp_reader *pfile, const char *fname, + source_location location) +{ + struct file_hash_entry *entry; + + entry = (struct file_hash_entry *) + htab_find_with_hash (pfile->file_hash, fname, htab_hash_string (fname)); + + while (entry && (entry->start_dir == NULL || entry->u.file->err_no + || entry->location > location)) + entry = entry->next; + + return entry != NULL; +} + /* Calculate the hash value of a file hash entry P. */ static hashval_t @@ -1047,7 +1154,7 @@ file_hash_eq (const void *p, const void *q) else hname = entry->u.dir->name; - return strcmp (hname, fname) == 0; + return filename_cmp (hname, fname) == 0; } /* Compare entries in the nonexistent file hash table. These are just @@ -1055,7 +1162,7 @@ file_hash_eq (const void *p, const void *q) static int nonexistent_file_hash_eq (const void *p, const void *q) { - return strcmp (p, q) == 0; + return filename_cmp ((const char *) p, (const char *) q) == 0; } /* Initialize everything in this source file. */ @@ -1083,6 +1190,19 @@ _cpp_cleanup_files (cpp_reader *pfile) htab_delete (pfile->dir_hash); htab_delete (pfile->nonexistent_file_hash); obstack_free (&pfile->nonexistent_file_ob, 0); + free_file_hash_entries (pfile); + destroy_all_cpp_files (pfile); +} + +/* Make the parser forget about files it has seen. This can be useful + for resetting the parser to start another run. */ +void +cpp_clear_file_cache (cpp_reader *pfile) +{ + _cpp_cleanup_files (pfile); + pfile->file_hash_entries = NULL; + pfile->all_files = NULL; + _cpp_init_files (pfile); } /* Enter a file name in the hash for the sake of cpp_included. */ @@ -1100,13 +1220,12 @@ cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc) { int flags = 0; const struct line_maps *line_table = pfile->line_table; - const struct line_map *map = &line_table->maps[line_table->used-1]; - + const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table); /* 1 = system header, 2 = system header to be treated as C. */ if (syshdr) flags = 1 + (externc != 0); pfile->buffer->sysp = flags; - _cpp_do_file_change (pfile, LC_RENAME, map->to_file, + _cpp_do_file_change (pfile, LC_RENAME, ORDINARY_MAP_FILE_NAME (map), SOURCE_LINE (map, pfile->line_table->highest_line), flags); } @@ -1120,12 +1239,19 @@ cpp_change_file (cpp_reader *pfile, enum lc_reason reason, _cpp_do_file_change (pfile, reason, new_name, 1, 0); } +struct report_missing_guard_data +{ + const char **paths; + size_t count; +}; + /* Callback function for htab_traverse. */ static int -report_missing_guard (void **slot, void *b) +report_missing_guard (void **slot, void *d) { struct file_hash_entry *entry = (struct file_hash_entry *) *slot; - int *bannerp = (int *) b; + struct report_missing_guard_data *data + = (struct report_missing_guard_data *) d; /* Skip directories. */ if (entry->start_dir != NULL) @@ -1133,21 +1259,28 @@ report_missing_guard (void **slot, void *b) _cpp_file *file = entry->u.file; /* We don't want MI guard advice for the main file. */ - if (file->cmacro == NULL && file->stack_count == 1 && !file->main_file) + if (!file->once_only && file->cmacro == NULL + && file->stack_count == 1 && !file->main_file) { - if (*bannerp == 0) + if (data->paths == NULL) { - fputs (_("Multiple include guards may be useful for:\n"), - stderr); - *bannerp = 1; + data->paths = XCNEWVEC (const char *, data->count); + data->count = 0; } - fputs (entry->u.file->path, stderr); - putc ('\n', stderr); + data->paths[data->count++] = file->path; } } - return 0; + /* Keep traversing the hash table. */ + return 1; +} + +/* Comparison function for qsort. */ +static int +report_missing_guard_cmp (const void *p1, const void *p2) +{ + return strcmp (*(const char *const *) p1, *(const char *const *) p2); } /* Report on all files that might benefit from a multiple include guard. @@ -1155,9 +1288,29 @@ report_missing_guard (void **slot, void *b) void _cpp_report_missing_guards (cpp_reader *pfile) { - int banner = 0; + struct report_missing_guard_data data; + + data.paths = NULL; + data.count = htab_elements (pfile->file_hash); + htab_traverse (pfile->file_hash, report_missing_guard, &data); - htab_traverse (pfile->file_hash, report_missing_guard, &banner); + if (data.paths != NULL) + { + size_t i; + + /* Sort the paths to avoid outputting them in hash table + order. */ + qsort (data.paths, data.count, sizeof (const char *), + report_missing_guard_cmp); + fputs (_("Multiple include guards may be useful for:\n"), + stderr); + for (i = 0; i < data.count; i++) + { + fputs (data.paths[i], stderr); + putc ('\n', stderr); + } + free (data.paths); + } } /* Locate HEADER, and determine whether it is newer than the current @@ -1208,14 +1361,22 @@ _cpp_pop_file_buffer (cpp_reader *pfile, _cpp_file *file) /* Invalidate control macros in the #including file. */ pfile->mi_valid = false; - if (file->buffer) + if (file->buffer_start) { - free ((void *) file->buffer); + free ((void *) file->buffer_start); + file->buffer_start = NULL; file->buffer = NULL; file->buffer_valid = false; } } +/* Return the file name associated with FILE. */ +const char * +_cpp_get_file_name (_cpp_file *file) +{ + return file->name; +} + /* Inteface to file statistics record in _cpp_file structure. */ struct stat * _cpp_get_file_stat (_cpp_file *file) @@ -1257,7 +1418,7 @@ append_file_to_dir (const char *fname, cpp_dir *dir) flen = strlen (fname); path = XNEWVEC (char, dlen + 1 + flen + 1); memcpy (path, dir->name, dlen); - if (dlen && path[dlen - 1] != '/') + if (dlen && !IS_DIR_SEPARATOR (path[dlen - 1])) path[dlen++] = '/'; memcpy (&path[dlen], fname, flen + 1); @@ -1305,7 +1466,7 @@ read_name_map (cpp_dir *dir) len = dir->len; name = (char *) alloca (len + sizeof (FILE_NAME_MAP_FILE) + 1); memcpy (name, dir->name, len); - if (len && name[len - 1] != '/') + if (len && !IS_DIR_SEPARATOR (name[len - 1])) name[len++] = '/'; strcpy (name + len, FILE_NAME_MAP_FILE); f = fopen (name, "r"); @@ -1376,10 +1537,18 @@ remap_filename (cpp_reader *pfile, _cpp_file *file) read_name_map (dir); for (index = 0; dir->name_map[index]; index += 2) - if (!strcmp (dir->name_map[index], fname)) + if (!filename_cmp (dir->name_map[index], fname)) return xstrdup (dir->name_map[index + 1]); - + if (IS_ABSOLUTE_PATH (fname)) + return NULL; p = strchr (fname, '/'); +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + { + char *p2 = strchr (fname, '\\'); + if (!p || (p > p2)) + p = p2; + } +#endif if (!p || p == fname) return NULL;