|  | /* Part of CPP library.  File handling. | 
|  | Copyright (C) 1986-2021 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 | 
|  | Split out of cpplib.c, Zack Weinberg, Oct 1998 | 
|  | Reimplemented, Neil Booth, Jul 2003 | 
|  |  | 
|  | 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 3, or (at your option) any | 
|  | later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 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; see the file COPYING3.  If not see | 
|  | <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include "config.h" | 
|  | #include "system.h" | 
|  | #include "cpplib.h" | 
|  | #include "internal.h" | 
|  | #include "mkdeps.h" | 
|  | #include "obstack.h" | 
|  | #include "hashtab.h" | 
|  | #include "md5.h" | 
|  | #include <dirent.h> | 
|  |  | 
|  | /* Variable length record files on VMS will have a stat size that includes | 
|  | record control characters that won't be included in the read size.  */ | 
|  | #ifdef VMS | 
|  | # define FAB_C_VAR 2 /* variable length records (see Starlet fabdef.h) */ | 
|  | # define STAT_SIZE_RELIABLE(ST) ((ST).st_fab_rfm != FAB_C_VAR) | 
|  | #else | 
|  | # define STAT_SIZE_RELIABLE(ST) true | 
|  | #endif | 
|  |  | 
|  | #ifdef __DJGPP__ | 
|  | #include <io.h> | 
|  | /* For DJGPP redirected input is opened in text mode.  */ | 
|  | #  define set_stdin_to_binary_mode() \ | 
|  | if (! isatty (0)) setmode (0, O_BINARY) | 
|  | #else | 
|  | #  define set_stdin_to_binary_mode() /* Nothing */ | 
|  | #endif | 
|  |  | 
|  | /* This structure represents a file searched for by CPP, whether it | 
|  | exists or not.  An instance may be pointed to by more than one | 
|  | cpp_file_hash_entry; at present no reference count is kept.  */ | 
|  | struct _cpp_file | 
|  | { | 
|  | /* Filename as given to #include or command line switch.  */ | 
|  | const char *name; | 
|  |  | 
|  | /* The full path used to find the file.  */ | 
|  | const char *path; | 
|  |  | 
|  | /* The full path of the pch file.  */ | 
|  | const char *pchname; | 
|  |  | 
|  | /* The file's path with the basename stripped.  NULL if it hasn't | 
|  | been calculated yet.  */ | 
|  | const char *dir_name; | 
|  |  | 
|  | /* Chain through all files.  */ | 
|  | struct _cpp_file *next_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; | 
|  |  | 
|  | /* The directory in the search path where FILE was found.  Used for | 
|  | #include_next and determining whether a header is a system | 
|  | header.  */ | 
|  | cpp_dir *dir; | 
|  |  | 
|  | /* As filled in by stat(2) for the file.  */ | 
|  | struct stat st; | 
|  |  | 
|  | /* File descriptor.  Invalid if -1, otherwise open.  */ | 
|  | int fd; | 
|  |  | 
|  | /* Zero if this file was successfully opened and stat()-ed, | 
|  | otherwise errno obtained from failure.  */ | 
|  | int err_no; | 
|  |  | 
|  | /* Number of times the file has been stacked for preprocessing.  */ | 
|  | unsigned short stack_count; | 
|  |  | 
|  | /* If opened with #import or contains #pragma once.  */ | 
|  | bool once_only : 1; | 
|  |  | 
|  | /* If read() failed before.  */ | 
|  | bool dont_read : 1; | 
|  |  | 
|  | /* If BUFFER above contains the true contents of the file.  */ | 
|  | bool buffer_valid : 1; | 
|  |  | 
|  | /* If this file is implicitly preincluded.  */ | 
|  | bool implicit_preinclude : 1; | 
|  |  | 
|  | /* > 0: Known C++ Module header unit, <0: known not.  ==0, unknown  */ | 
|  | int header_unit : 2; | 
|  | }; | 
|  |  | 
|  | /* A singly-linked list for all searches for a given file name, with | 
|  | its head pointed to by a slot in FILE_HASH.  The file name is what | 
|  | appeared between the quotes in a #include directive; it can be | 
|  | determined implicitly from the hash table location or explicitly | 
|  | from FILE->name. | 
|  |  | 
|  | FILE is a structure containing details about the file that was | 
|  | found with that search, or details of how the search failed. | 
|  |  | 
|  | START_DIR is the starting location of the search in the include | 
|  | chain.  The current directories for "" includes are also hashed in | 
|  | the hash table and therefore unique.  Files that are looked up | 
|  | without using a search path, such as absolute filenames and file | 
|  | names from the command line share a special starting directory so | 
|  | they don't cause cache hits with normal include-chain lookups. | 
|  |  | 
|  | If START_DIR is NULL then the entry is for a directory, not a file, | 
|  | and the directory is in DIR.  Since the starting point in a file | 
|  | lookup chain is never NULL, this means that simple pointer | 
|  | comparisons against START_DIR can be made to determine cache hits | 
|  | in file lookups. | 
|  |  | 
|  | If a cache lookup fails because of e.g. an extra "./" in the path, | 
|  | then nothing will break.  It is just less efficient as CPP will | 
|  | have to do more work re-preprocessing the file, and/or comparing | 
|  | its contents against earlier once-only files. | 
|  | */ | 
|  | struct cpp_file_hash_entry | 
|  | { | 
|  | struct cpp_file_hash_entry *next; | 
|  | cpp_dir *start_dir; | 
|  | location_t location; | 
|  | union | 
|  | { | 
|  | _cpp_file *file; | 
|  | cpp_dir *dir; | 
|  | } u; | 
|  | }; | 
|  |  | 
|  | /* Number of entries to put in a cpp_file_hash_entry pool.  */ | 
|  | #define FILE_HASH_POOL_SIZE 127 | 
|  |  | 
|  | /* A file hash entry pool.  We allocate cpp_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 cpp_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); | 
|  | static bool find_file_in_dir (cpp_reader *pfile, _cpp_file *file, | 
|  | bool *invalid_pch, location_t loc); | 
|  | static bool read_file_guts (cpp_reader *pfile, _cpp_file *file, | 
|  | location_t loc, const char *input_charset); | 
|  | static bool read_file (cpp_reader *pfile, _cpp_file *file, | 
|  | location_t loc); | 
|  | static struct cpp_dir *search_path_head (cpp_reader *, const char *fname, | 
|  | int angle_brackets, enum include_type); | 
|  | static const char *dir_name_of_file (_cpp_file *file); | 
|  | static void open_file_failed (cpp_reader *pfile, _cpp_file *file, int, | 
|  | location_t); | 
|  | static struct cpp_file_hash_entry *search_cache (struct cpp_file_hash_entry *head, | 
|  | const cpp_dir *start_dir); | 
|  | static _cpp_file *make_cpp_file (cpp_dir *, const char *fname); | 
|  | static void destroy_cpp_file (_cpp_file *); | 
|  | static cpp_dir *make_cpp_dir (cpp_reader *, const char *dir_name, int sysp); | 
|  | static void allocate_file_hash_entries (cpp_reader *pfile); | 
|  | static struct cpp_file_hash_entry *new_file_hash_entry (cpp_reader *pfile); | 
|  | static int report_missing_guard (void **slot, void *b); | 
|  | static hashval_t file_hash_hash (const void *p); | 
|  | static int file_hash_eq (const void *p, const void *q); | 
|  | static char *read_filename_string (int ch, FILE *f); | 
|  | static void read_name_map (cpp_dir *dir); | 
|  | static char *remap_filename (cpp_reader *pfile, _cpp_file *file); | 
|  | static char *append_file_to_dir (const char *fname, cpp_dir *dir); | 
|  | static bool validate_pch (cpp_reader *, _cpp_file *file, const char *pchname); | 
|  | static int pchf_save_compare (const void *e1, const void *e2); | 
|  | static int pchf_compare (const void *d_p, const void *e_p); | 
|  | static bool check_file_against_entries (cpp_reader *, _cpp_file *, bool); | 
|  |  | 
|  | /* Given a filename in FILE->PATH, with the empty string interpreted | 
|  | as <stdin>, open it. | 
|  |  | 
|  | On success FILE contains an open file descriptor and stat | 
|  | information for the file.  On failure the file descriptor is -1 and | 
|  | the appropriate errno is also stored in FILE.  Returns TRUE iff | 
|  | successful. | 
|  |  | 
|  | We used to open files in nonblocking mode, but that caused more | 
|  | problems than it solved.  Do take care not to acquire a controlling | 
|  | terminal by mistake (this can't happen on sane systems, but | 
|  | paranoia is a virtue). | 
|  |  | 
|  | Use the three-argument form of open even though we aren't | 
|  | specifying O_CREAT, to defend against broken system headers. | 
|  |  | 
|  | O_BINARY tells some runtime libraries (notably DJGPP) not to do | 
|  | newline translation; we can handle DOS line breaks just fine | 
|  | ourselves.  */ | 
|  | static bool | 
|  | open_file (_cpp_file *file) | 
|  | { | 
|  | if (file->path[0] == '\0') | 
|  | { | 
|  | file->fd = 0; | 
|  | set_stdin_to_binary_mode (); | 
|  | } | 
|  | else | 
|  | file->fd = open (file->path, O_RDONLY | O_NOCTTY | O_BINARY, 0666); | 
|  |  | 
|  | if (file->fd != -1) | 
|  | { | 
|  | if (fstat (file->fd, &file->st) == 0) | 
|  | { | 
|  | if (!S_ISDIR (file->st.st_mode)) | 
|  | { | 
|  | file->err_no = 0; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Ignore a directory and continue the search.  The file we're | 
|  | looking for may be elsewhere in the search path.  */ | 
|  | errno = ENOENT; | 
|  | } | 
|  |  | 
|  | 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; | 
|  |  | 
|  | file->err_no = errno; | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* Temporary PCH intercept of opening a file.  Try to find a PCH file | 
|  | based on FILE->name and FILE->dir, and test those found for | 
|  | validity using PFILE->cb.valid_pch.  Return true iff a valid file is | 
|  | found.  Set *INVALID_PCH if a PCH file is found but wasn't valid.  */ | 
|  |  | 
|  | static bool | 
|  | pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch) | 
|  | { | 
|  | static const char extension[] = ".gch"; | 
|  | const char *path = file->path; | 
|  | size_t len, flen; | 
|  | char *pchname; | 
|  | struct stat st; | 
|  | bool valid = false; | 
|  |  | 
|  | /* No PCH on <stdin> or if not requested.  */ | 
|  | 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.  */ | 
|  | for (_cpp_file *f = pfile->all_files; f; f = f->next_file) | 
|  | if (f->implicit_preinclude) | 
|  | continue; | 
|  | else if (pfile->main_file == f) | 
|  | break; | 
|  | else | 
|  | return false; | 
|  |  | 
|  | flen = strlen (path); | 
|  | len = flen + sizeof (extension); | 
|  | pchname = XNEWVEC (char, len); | 
|  | memcpy (pchname, path, flen); | 
|  | memcpy (pchname + flen, extension, sizeof (extension)); | 
|  |  | 
|  | if (stat (pchname, &st) == 0) | 
|  | { | 
|  | DIR *pchdir; | 
|  | struct dirent *d; | 
|  | size_t dlen, plen = len; | 
|  |  | 
|  | if (!S_ISDIR (st.st_mode)) | 
|  | valid = validate_pch (pfile, file, pchname); | 
|  | else if ((pchdir = opendir (pchname)) != NULL) | 
|  | { | 
|  | pchname[plen - 1] = '/'; | 
|  | while ((d = readdir (pchdir)) != NULL) | 
|  | { | 
|  | dlen = strlen (d->d_name) + 1; | 
|  | if ((strcmp (d->d_name, ".") == 0) | 
|  | || (strcmp (d->d_name, "..") == 0)) | 
|  | continue; | 
|  | if (dlen + plen > len) | 
|  | { | 
|  | len += dlen + 64; | 
|  | pchname = XRESIZEVEC (char, pchname, len); | 
|  | } | 
|  | memcpy (pchname + plen, d->d_name, dlen); | 
|  | valid = validate_pch (pfile, file, pchname); | 
|  | if (valid) | 
|  | break; | 
|  | } | 
|  | closedir (pchdir); | 
|  | } | 
|  | if (!valid) | 
|  | *invalid_pch = true; | 
|  | } | 
|  |  | 
|  | if (valid) | 
|  | file->pchname = pchname; | 
|  | else | 
|  | free (pchname); | 
|  |  | 
|  | return valid; | 
|  | } | 
|  |  | 
|  | /* Canonicalize the path to FILE.  Return the canonical form if it is | 
|  | shorter, otherwise return NULL.  This function does NOT free the | 
|  | memory pointed by FILE.  */ | 
|  |  | 
|  | static char * | 
|  | maybe_shorter_path (const char * file) | 
|  | { | 
|  | char * file2 = lrealpath (file); | 
|  | if (file2 && strlen (file2) < strlen (file)) | 
|  | { | 
|  | return file2; | 
|  | } | 
|  | else | 
|  | { | 
|  | free (file2); | 
|  | return NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Try to open the path FILE->name appended to FILE->dir.  This is | 
|  | where remap and PCH intercept the file lookup process.  Return true | 
|  | if the file was found, whether or not the open was successful. | 
|  | Set *INVALID_PCH to true if a PCH file is found but wasn't valid. | 
|  | Use LOC when emitting any diagnostics.  */ | 
|  |  | 
|  | static bool | 
|  | find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch, | 
|  | location_t loc) | 
|  | { | 
|  | char *path; | 
|  |  | 
|  | if (CPP_OPTION (pfile, remap) && (path = remap_filename (pfile, file))) | 
|  | ; | 
|  | else | 
|  | if (file->dir->construct) | 
|  | path = file->dir->construct (file->name, file->dir); | 
|  | else | 
|  | path = append_file_to_dir (file->name, file->dir); | 
|  |  | 
|  | if (path) | 
|  | { | 
|  | hashval_t hv; | 
|  | char *copy; | 
|  | void **pp; | 
|  |  | 
|  | /* We try to canonicalize system headers.  For DOS based file | 
|  | * system, we always try to shorten non-system headers, as DOS | 
|  | * has a tighter constraint on max path length.  */ | 
|  | if ((CPP_OPTION (pfile, canonical_system_headers) && file->dir->sysp) | 
|  | #ifdef HAVE_DOS_BASED_FILE_SYSTEM | 
|  | || !file->dir->sysp | 
|  | #endif | 
|  | ) | 
|  | { | 
|  | char * canonical_path = maybe_shorter_path (path); | 
|  | if (canonical_path) | 
|  | { | 
|  | /* The canonical path was newly allocated.  Let's free the | 
|  | non-canonical one.  */ | 
|  | free (path); | 
|  | path = canonical_path; | 
|  | } | 
|  | } | 
|  |  | 
|  | hv = htab_hash_string (path); | 
|  | if (htab_find_with_hash (pfile->nonexistent_file_hash, path, hv) != NULL) | 
|  | { | 
|  | file->err_no = ENOENT; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | file->path = path; | 
|  | if (pch_open_file (pfile, file, invalid_pch)) | 
|  | return true; | 
|  |  | 
|  | if (open_file (file)) | 
|  | return true; | 
|  |  | 
|  | if (file->err_no != ENOENT) | 
|  | { | 
|  | open_file_failed (pfile, file, 0, loc); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* 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 = (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); | 
|  | *pp = copy; | 
|  |  | 
|  | file->path = file->name; | 
|  | } | 
|  | else | 
|  | { | 
|  | file->err_no = ENOENT; | 
|  | file->path = NULL; | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* Return true iff the missing_header callback found the given HEADER.  */ | 
|  | static bool | 
|  | search_path_exhausted (cpp_reader *pfile, const char *header, _cpp_file *file) | 
|  | { | 
|  | missing_header_cb func = pfile->cb.missing_header; | 
|  |  | 
|  | /* When the regular search path doesn't work, try context dependent | 
|  | headers search paths.  */ | 
|  | if (func | 
|  | && file->dir == NULL) | 
|  | { | 
|  | if ((file->path = func (pfile, header, &file->dir)) != NULL) | 
|  | { | 
|  | if (open_file (file)) | 
|  | return true; | 
|  | free ((void *)file->path); | 
|  | } | 
|  | file->path = file->name; | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool | 
|  | _cpp_find_failed (_cpp_file *file) | 
|  | { | 
|  | return file->err_no != 0; | 
|  | } | 
|  |  | 
|  | /* Given a filename FNAME search for such a file in the include path | 
|  | starting from START_DIR.  If FNAME is the empty string it is | 
|  | interpreted as STDIN if START_DIR is PFILE->no_search_path. | 
|  |  | 
|  | If the file is not found in the file cache fall back to the O/S and | 
|  | add the result to our cache. | 
|  |  | 
|  | If the file was not found in the filesystem, or there was an error | 
|  | opening it, then ERR_NO is nonzero and FD is -1.  If the file was | 
|  | found, then ERR_NO is zero and FD could be -1 or an open file | 
|  | descriptor.  FD can be -1 if the file was found in the cache and | 
|  | had previously been closed.  To open it again pass the return value | 
|  | to open_file(). | 
|  |  | 
|  | If KIND is _cpp_FFK_PRE_INCLUDE then it is OK for the file to be | 
|  | missing.  If present, it is OK for a precompiled header to be | 
|  | included after it. | 
|  |  | 
|  | Use LOC as the location for any errors.  */ | 
|  |  | 
|  | _cpp_file * | 
|  | _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, | 
|  | int angle_brackets, _cpp_find_file_kind kind, location_t loc) | 
|  | { | 
|  | bool invalid_pch = false; | 
|  | bool saw_bracket_include = false; | 
|  | bool saw_quote_include = false; | 
|  | struct cpp_dir *found_in_cache = NULL; | 
|  |  | 
|  | /* Ensure we get no confusion between cached files and directories.  */ | 
|  | if (start_dir == NULL) | 
|  | cpp_error_at (pfile, CPP_DL_ICE, loc, "NULL directory in find_file"); | 
|  |  | 
|  | void **hash_slot | 
|  | = htab_find_slot_with_hash (pfile->file_hash, fname, | 
|  | htab_hash_string (fname), INSERT); | 
|  |  | 
|  | /* First check the cache before we resort to memory allocation.  */ | 
|  | cpp_file_hash_entry *entry | 
|  | = search_cache ((struct cpp_file_hash_entry *) *hash_slot, start_dir); | 
|  | if (entry) | 
|  | return entry->u.file; | 
|  |  | 
|  | _cpp_file *file = make_cpp_file (start_dir, fname); | 
|  | file->implicit_preinclude | 
|  | = (kind == _cpp_FFK_PRE_INCLUDE | 
|  | || (pfile->buffer && pfile->buffer->file->implicit_preinclude)); | 
|  |  | 
|  | if (kind != _cpp_FFK_FAKE) | 
|  | /* Try each path in the include chain.  */ | 
|  | for (;;) | 
|  | { | 
|  | if (find_file_in_dir (pfile, file, &invalid_pch, loc)) | 
|  | break; | 
|  |  | 
|  | file->dir = file->dir->next; | 
|  | if (file->dir == NULL) | 
|  | { | 
|  | if (search_path_exhausted (pfile, fname, file)) | 
|  | { | 
|  | /* Although this file must not go in the cache, | 
|  | because the file found might depend on things (like | 
|  | the current file) that aren't represented in the | 
|  | cache, it still has to go in the list of all files | 
|  | so that #import works.  */ | 
|  | file->next_file = pfile->all_files; | 
|  | pfile->all_files = file; | 
|  | if (*hash_slot == NULL) | 
|  | { | 
|  | /* If *hash_slot is NULL, the above | 
|  | htab_find_slot_with_hash call just created the | 
|  | slot, but we aren't going to store there | 
|  | anything, so need to remove the newly created | 
|  | entry.  htab_clear_slot requires that it is | 
|  | non-NULL, so store there some non-NULL pointer, | 
|  | htab_clear_slot will overwrite it | 
|  | immediately.  */ | 
|  | *hash_slot = file; | 
|  | htab_clear_slot (pfile->file_hash, hash_slot); | 
|  | } | 
|  | return file; | 
|  | } | 
|  |  | 
|  | if (invalid_pch) | 
|  | { | 
|  | cpp_error (pfile, CPP_DL_ERROR, | 
|  | "one or more PCH files were found," | 
|  | " but they were invalid"); | 
|  | if (!cpp_get_options (pfile)->warn_invalid_pch) | 
|  | cpp_error (pfile, CPP_DL_NOTE, | 
|  | "use -Winvalid-pch for more information"); | 
|  | } | 
|  |  | 
|  | if (kind == _cpp_FFK_PRE_INCLUDE) | 
|  | { | 
|  | free ((char *) file->name); | 
|  | free (file); | 
|  | if (*hash_slot == NULL) | 
|  | { | 
|  | /* See comment on the above htab_clear_slot call.  */ | 
|  | *hash_slot = file; | 
|  | htab_clear_slot (pfile->file_hash, hash_slot); | 
|  | } | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | if (kind != _cpp_FFK_HAS_INCLUDE) | 
|  | open_file_failed (pfile, file, angle_brackets, loc); | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* Only check the cache for the starting location (done above) | 
|  | and the quote and bracket chain heads because there are no | 
|  | other possible starting points for searches.  */ | 
|  | if (file->dir == pfile->bracket_include) | 
|  | saw_bracket_include = true; | 
|  | else if (file->dir == pfile->quote_include) | 
|  | saw_quote_include = true; | 
|  | else | 
|  | continue; | 
|  |  | 
|  | entry | 
|  | = search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir); | 
|  | if (entry) | 
|  | { | 
|  | found_in_cache = file->dir; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (entry) | 
|  | { | 
|  | /* Cache for START_DIR too, sharing the _cpp_file structure.  */ | 
|  | free ((char *) file->name); | 
|  | free (file); | 
|  | file = entry->u.file; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* This is a new file; put it in the list.  */ | 
|  | file->next_file = pfile->all_files; | 
|  | pfile->all_files = file; | 
|  | } | 
|  |  | 
|  | /* Store this new result in the hash table.  */ | 
|  | entry = new_file_hash_entry (pfile); | 
|  | entry->next = (struct cpp_file_hash_entry *) *hash_slot; | 
|  | entry->start_dir = start_dir; | 
|  | entry->location = loc; | 
|  | entry->u.file = file; | 
|  | *hash_slot = (void *) entry; | 
|  |  | 
|  | /* If we passed the quote or bracket chain heads, cache them also. | 
|  | This speeds up processing if there are lots of -I options.  */ | 
|  | if (saw_bracket_include | 
|  | && pfile->bracket_include != start_dir | 
|  | && found_in_cache != pfile->bracket_include) | 
|  | { | 
|  | entry = new_file_hash_entry (pfile); | 
|  | entry->next = (struct cpp_file_hash_entry *) *hash_slot; | 
|  | entry->start_dir = pfile->bracket_include; | 
|  | entry->location = loc; | 
|  | entry->u.file = file; | 
|  | *hash_slot = (void *) entry; | 
|  | } | 
|  | if (saw_quote_include | 
|  | && pfile->quote_include != start_dir | 
|  | && found_in_cache != pfile->quote_include) | 
|  | { | 
|  | entry = new_file_hash_entry (pfile); | 
|  | entry->next = (struct cpp_file_hash_entry *) *hash_slot; | 
|  | entry->start_dir = pfile->quote_include; | 
|  | entry->location = loc; | 
|  | entry->u.file = file; | 
|  | *hash_slot = (void *) entry; | 
|  | } | 
|  |  | 
|  | return file; | 
|  | } | 
|  |  | 
|  | /* Read a file into FILE->buffer, returning true on success. | 
|  |  | 
|  | If FILE->fd is something weird, like a block device, we don't want | 
|  | to read it at all.  Don't even try to figure out what something is, | 
|  | except for plain files and block devices, since there is no | 
|  | reliable portable way of doing this. | 
|  |  | 
|  | Use LOC for any diagnostics. | 
|  |  | 
|  | PFILE may be NULL.  In this case, no diagnostics are issued. | 
|  |  | 
|  | FIXME: Flush file cache and try again if we run out of memory.  */ | 
|  | static bool | 
|  | read_file_guts (cpp_reader *pfile, _cpp_file *file, location_t loc, | 
|  | const char *input_charset) | 
|  | { | 
|  | ssize_t size, total, count; | 
|  | uchar *buf; | 
|  | bool regular; | 
|  |  | 
|  | if (S_ISBLK (file->st.st_mode)) | 
|  | { | 
|  | if (pfile) | 
|  | cpp_error_at (pfile, CPP_DL_ERROR, loc, | 
|  | "%s is a block device", file->path); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | regular = S_ISREG (file->st.st_mode) != 0; | 
|  | if (regular) | 
|  | { | 
|  | /* off_t might have a wider range than ssize_t - in other words, | 
|  | the max size of a file might be bigger than the address | 
|  | space.  We can't handle a file that large.  (Anyone with | 
|  | a single source file bigger than 2GB needs to rethink | 
|  | their coding style.)  Some systems (e.g. AIX 4.1) define | 
|  | SSIZE_MAX to be much smaller than the actual range of the | 
|  | type.  Use INTTYPE_MAXIMUM unconditionally to ensure this | 
|  | does not bite us.  */ | 
|  | if (file->st.st_size > INTTYPE_MAXIMUM (ssize_t)) | 
|  | { | 
|  | if (pfile) | 
|  | cpp_error_at (pfile, CPP_DL_ERROR, loc, | 
|  | "%s is too large", file->path); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | size = file->st.st_size; | 
|  | } | 
|  | else | 
|  | /* 8 kilobytes is a sensible starting size.  It ought to be bigger | 
|  | than the kernel pipe buffer, and it's definitely bigger than | 
|  | the majority of C source files.  */ | 
|  | size = 8 * 1024; | 
|  |  | 
|  | /* The + 16 here is space for the final '\n' and 15 bytes of padding, | 
|  | used to quiet warnings from valgrind or Address Sanitizer, when the | 
|  | optimized lexer accesses aligned 16-byte memory chunks, including | 
|  | the bytes after the malloced, area, and stops lexing on '\n'.  */ | 
|  | buf = XNEWVEC (uchar, size + 16); | 
|  | total = 0; | 
|  | while ((count = read (file->fd, buf + total, size - total)) > 0) | 
|  | { | 
|  | total += count; | 
|  |  | 
|  | if (total == size) | 
|  | { | 
|  | if (regular) | 
|  | break; | 
|  | size *= 2; | 
|  | buf = XRESIZEVEC (uchar, buf, size + 16); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (count < 0) | 
|  | { | 
|  | if (pfile) | 
|  | cpp_errno_filename (pfile, CPP_DL_ERROR, file->path, loc); | 
|  | free (buf); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (pfile && regular && total != size && STAT_SIZE_RELIABLE (file->st)) | 
|  | cpp_error_at (pfile, CPP_DL_WARNING, loc, | 
|  | "%s is shorter than expected", file->path); | 
|  |  | 
|  | file->buffer = _cpp_convert_input (pfile, | 
|  | input_charset, | 
|  | buf, size + 16, total, | 
|  | &file->buffer_start, | 
|  | &file->st.st_size); | 
|  | file->buffer_valid = file->buffer; | 
|  | return file->buffer_valid; | 
|  | } | 
|  |  | 
|  | /* Convenience wrapper around read_file_guts that opens the file if | 
|  | necessary and closes the file descriptor after reading.  FILE must | 
|  | have been passed through find_file() at some stage.  Use LOC for | 
|  | any diagnostics.  Unlike read_file_guts(), PFILE may not be NULL.  */ | 
|  | static bool | 
|  | read_file (cpp_reader *pfile, _cpp_file *file, location_t loc) | 
|  | { | 
|  | /* If we already have its contents in memory, succeed immediately.  */ | 
|  | if (file->buffer_valid) | 
|  | return true; | 
|  |  | 
|  | /* If an earlier read failed for some reason don't try again.  */ | 
|  | if (file->dont_read || file->err_no) | 
|  | return false; | 
|  |  | 
|  | if (file->fd == -1 && !open_file (file)) | 
|  | { | 
|  | open_file_failed (pfile, file, 0, loc); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | file->dont_read = !read_file_guts (pfile, file, loc, | 
|  | CPP_OPTION (pfile, input_charset)); | 
|  | close (file->fd); | 
|  | file->fd = -1; | 
|  |  | 
|  | return !file->dont_read; | 
|  | } | 
|  |  | 
|  | /* Returns TRUE if FILE is already known to be idempotent, and should | 
|  | therefore not be read again.  */ | 
|  | static bool | 
|  | is_known_idempotent_file (cpp_reader *pfile, _cpp_file *file, bool import) | 
|  | { | 
|  | /* Skip once-only files.  */ | 
|  | if (file->once_only) | 
|  | return true; | 
|  |  | 
|  | /* We must mark the file once-only if #import now, before header | 
|  | guard checks.  Otherwise, undefining the header guard might | 
|  | cause the file to be re-stacked.  */ | 
|  | if (import) | 
|  | { | 
|  | _cpp_mark_file_once_only (pfile, file); | 
|  |  | 
|  | /* Don't stack files that have been stacked before.  */ | 
|  | if (file->stack_count) | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Skip if the file had a header guard and the macro is defined. | 
|  | PCH relies on this appearing before the PCH handler below.  */ | 
|  | if (file->cmacro && cpp_macro_p (file->cmacro)) | 
|  | return true; | 
|  |  | 
|  | /* Handle PCH files immediately; don't stack them.  */ | 
|  | if (file->pchname) | 
|  | { | 
|  | pfile->cb.read_pch (pfile, file->pchname, file->fd, file->path); | 
|  | file->fd = -1; | 
|  | free ((void *) file->pchname); | 
|  | file->pchname = NULL; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* Return TRUE if file has unique contents, so we should read process | 
|  | it.  The file's contents must already have been read.  */ | 
|  |  | 
|  | static bool | 
|  | has_unique_contents (cpp_reader *pfile, _cpp_file *file, bool import, | 
|  | location_t loc) | 
|  | { | 
|  | /* Check the file against the PCH file.  This is done before | 
|  | checking against files we've already seen, since it may save on | 
|  | I/O.  */ | 
|  | if (check_file_against_entries (pfile, file, import)) | 
|  | { | 
|  | /* If this isn't a #import, but yet we can't include the file, | 
|  | that means that it was #import-ed in the PCH file, | 
|  | so we can never include it again.  */ | 
|  | if (! import) | 
|  | _cpp_mark_file_once_only (pfile, file); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* Now we've read the file's contents, we can stack it if there | 
|  | are no once-only files.  */ | 
|  | if (!pfile->seen_once_only) | 
|  | return true; | 
|  |  | 
|  | /* We may have read the file under a different name.  Look | 
|  | for likely candidates and compare file contents to be sure.  */ | 
|  | for (_cpp_file *f = pfile->all_files; f; f = f->next_file) | 
|  | { | 
|  | if (f == file) | 
|  | continue; /* It'sa me!  */ | 
|  |  | 
|  | if ((import || f->once_only) | 
|  | && f->err_no == 0 | 
|  | && f->st.st_mtime == file->st.st_mtime | 
|  | && f->st.st_size == file->st.st_size) | 
|  | { | 
|  | _cpp_file *ref_file; | 
|  |  | 
|  | if (f->buffer && !f->buffer_valid) | 
|  | { | 
|  | /* We already have a buffer but it is not valid, because | 
|  | the file is still stacked.  Make a new one.  */ | 
|  | ref_file = make_cpp_file (f->dir, f->name); | 
|  | ref_file->path = f->path; | 
|  | } | 
|  | else | 
|  | /* The file is not stacked anymore.  We can reuse it.  */ | 
|  | ref_file = f; | 
|  |  | 
|  | bool same_file_p = (read_file (pfile, ref_file, loc) | 
|  | /* Size might have changed in read_file().  */ | 
|  | && ref_file->st.st_size == file->st.st_size | 
|  | && !memcmp (ref_file->buffer, file->buffer, | 
|  | file->st.st_size)); | 
|  |  | 
|  | if (f->buffer && !f->buffer_valid) | 
|  | { | 
|  | ref_file->path = 0; | 
|  | destroy_cpp_file (ref_file); | 
|  | } | 
|  |  | 
|  | if (same_file_p) | 
|  | /* Already seen under a different name.  */ | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Place the file referenced by FILE into a new buffer on the buffer | 
|  | stack if possible.  Returns true if a buffer is stacked.  Use LOC | 
|  | for any diagnostics.  */ | 
|  |  | 
|  | bool | 
|  | _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type, | 
|  | location_t loc) | 
|  | { | 
|  | if (is_known_idempotent_file (pfile, file, type == IT_IMPORT)) | 
|  | return false; | 
|  |  | 
|  | int sysp = 0; | 
|  | char *buf = nullptr; | 
|  |  | 
|  | /* Check C++ module include translation.  */ | 
|  | if (!file->header_unit && type < IT_HEADER_HWM | 
|  | /* Do not include translate include-next.  */ | 
|  | && type != IT_INCLUDE_NEXT | 
|  | && pfile->cb.translate_include) | 
|  | buf = (pfile->cb.translate_include | 
|  | (pfile, pfile->line_table, loc, file->path)); | 
|  |  | 
|  | if (buf) | 
|  | { | 
|  | /* We don't increment the line number at the end of a buffer, | 
|  | because we don't usually need that location (we're popping an | 
|  | include file).  However in this case we do want to do the | 
|  | increment.  So push a writable buffer of two newlines to acheive | 
|  | that.  (We also need an extra newline, so this looks like a regular | 
|  | file, which we do that to to make sure we don't fall off the end in the | 
|  | middle of a line.  */ | 
|  | static uchar newlines[] = "\n\n\n"; | 
|  | cpp_push_buffer (pfile, newlines, 2, true); | 
|  |  | 
|  | size_t len = strlen (buf); | 
|  | buf[len] = '\n'; /* See above  */ | 
|  | cpp_buffer *buffer | 
|  | = cpp_push_buffer (pfile, reinterpret_cast<unsigned char *> (buf), | 
|  | len, true); | 
|  | buffer->to_free = buffer->buf; | 
|  |  | 
|  | file->header_unit = +1; | 
|  | _cpp_mark_file_once_only (pfile, file); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Not a header unit, and we know it.  */ | 
|  | file->header_unit = -1; | 
|  |  | 
|  | if (!read_file (pfile, file, loc)) | 
|  | return false; | 
|  |  | 
|  | if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc)) | 
|  | return false; | 
|  |  | 
|  | if (pfile->buffer && file->dir) | 
|  | sysp = MAX (pfile->buffer->sysp, file->dir->sysp); | 
|  |  | 
|  | /* Add the file to the dependencies on its first inclusion.  */ | 
|  | if (CPP_OPTION (pfile, deps.style) > (sysp != 0) | 
|  | && !file->stack_count | 
|  | && file->path[0] | 
|  | && !(pfile->main_file == file | 
|  | && CPP_OPTION (pfile, deps.ignore_main_file))) | 
|  | deps_add_dep (pfile->deps, file->path); | 
|  |  | 
|  | /* Clear buffer_valid since _cpp_clean_line messes it up.  */ | 
|  | file->buffer_valid = false; | 
|  | file->stack_count++; | 
|  |  | 
|  | /* Stack the buffer.  */ | 
|  | cpp_buffer *buffer | 
|  | = cpp_push_buffer (pfile, file->buffer, file->st.st_size, | 
|  | CPP_OPTION (pfile, preprocessed) | 
|  | && !CPP_OPTION (pfile, directives_only)); | 
|  | buffer->file = file; | 
|  | buffer->sysp = sysp; | 
|  | buffer->to_free = file->buffer_start; | 
|  |  | 
|  | /* Initialize controlling macro state.  */ | 
|  | pfile->mi_valid = true; | 
|  | pfile->mi_cmacro = 0; | 
|  | } | 
|  |  | 
|  | /* In the case of a normal #include, we're now at the start of the | 
|  | line *following* the #include.  A separate location_t for this | 
|  | location makes no sense, until we do the LC_LEAVE. | 
|  |  | 
|  | This does not apply if we found a PCH file, we're not a regular | 
|  | include, or we ran out of locations.  */ | 
|  | bool decrement = (file->pchname == NULL | 
|  | && type < IT_DIRECTIVE_HWM | 
|  | && (pfile->line_table->highest_location | 
|  | != LINE_MAP_MAX_LOCATION - 1)); | 
|  | if (decrement) | 
|  | pfile->line_table->highest_location--; | 
|  |  | 
|  | if (file->header_unit <= 0) | 
|  | /* Add line map and do callbacks.  */ | 
|  | _cpp_do_file_change (pfile, LC_ENTER, file->path, | 
|  | /* With preamble injection, start on line zero, | 
|  | so the preamble doesn't appear to have been | 
|  | included from line 1.  Likewise when | 
|  | starting preprocessed, we expect an initial | 
|  | locating line.  */ | 
|  | type == IT_PRE_MAIN ? 0 : 1, sysp); | 
|  | else if (decrement) | 
|  | { | 
|  | /* Adjust the line back one so we appear on the #include line itself.  */ | 
|  | const line_map_ordinary *map | 
|  | = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table); | 
|  | linenum_type line = SOURCE_LINE (map, pfile->line_table->highest_line); | 
|  | linemap_line_start (pfile->line_table, line - 1, 0); | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Mark FILE to be included once only.  */ | 
|  | void | 
|  | _cpp_mark_file_once_only (cpp_reader *pfile, _cpp_file *file) | 
|  | { | 
|  | pfile->seen_once_only = true; | 
|  | file->once_only = true; | 
|  | } | 
|  |  | 
|  | /* Return the directory from which searching for FNAME should start, | 
|  | considering the directive TYPE and ANGLE_BRACKETS.  If there is | 
|  | nothing left in the path, returns NULL.  */ | 
|  | static struct cpp_dir * | 
|  | search_path_head (cpp_reader *pfile, const char *fname, int angle_brackets, | 
|  | enum include_type type) | 
|  | { | 
|  | cpp_dir *dir; | 
|  | _cpp_file *file; | 
|  |  | 
|  | if (IS_ABSOLUTE_PATH (fname)) | 
|  | return &pfile->no_search_path; | 
|  |  | 
|  | /* pfile->buffer is NULL when processing an -include command-line flag.  */ | 
|  | file = pfile->buffer == NULL ? pfile->main_file : pfile->buffer->file; | 
|  |  | 
|  | /* 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 | 
|  | && file->dir != &pfile->no_search_path) | 
|  | dir = file->dir->next; | 
|  | else if (angle_brackets) | 
|  | dir = pfile->bracket_include; | 
|  | else if (type == IT_CMDLINE) | 
|  | /* -include and -imacros use the #include "" chain with the | 
|  | preprocessor's cwd prepended.  */ | 
|  | return make_cpp_dir (pfile, "./", false); | 
|  | else if (pfile->quote_ignores_source_dir) | 
|  | dir = pfile->quote_include; | 
|  | else | 
|  | return make_cpp_dir (pfile, dir_name_of_file (file), | 
|  | pfile->buffer ? pfile->buffer->sysp : 0); | 
|  |  | 
|  | if (dir == NULL) | 
|  | cpp_error (pfile, CPP_DL_ERROR, | 
|  | "no include path in which to search for %s", fname); | 
|  |  | 
|  | return dir; | 
|  | } | 
|  |  | 
|  | /* Strip the basename from the file's path.  It ends with a slash if | 
|  | of nonzero length.  Note that this procedure also works for | 
|  | <stdin>, which is represented by the empty string.  */ | 
|  | static const char * | 
|  | dir_name_of_file (_cpp_file *file) | 
|  | { | 
|  | if (!file->dir_name) | 
|  | { | 
|  | size_t len = lbasename (file->path) - file->path; | 
|  | char *dir_name = XNEWVEC (char, len + 1); | 
|  |  | 
|  | memcpy (dir_name, file->path, len); | 
|  | dir_name[len] = '\0'; | 
|  | file->dir_name = dir_name; | 
|  | } | 
|  |  | 
|  | return file->dir_name; | 
|  | } | 
|  |  | 
|  | /* Handles #include-family directives (distinguished by TYPE), | 
|  | including HEADER, and the command line -imacros and -include. | 
|  | Returns true if a buffer was stacked.  */ | 
|  | bool | 
|  | _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets, | 
|  | enum include_type type, location_t loc) | 
|  | { | 
|  | /* For -include command-line flags we have type == IT_CMDLINE. | 
|  | When the first -include file is processed we have the case, where | 
|  | pfile->cur_token == pfile->cur_run->base, we are directly called up | 
|  | by the front end.  However in the case of the second -include file, | 
|  | we are called from _cpp_lex_token -> _cpp_get_fresh_line -> | 
|  | cpp_push_include, with pfile->cur_token != pfile->cur_run->base, | 
|  | and pfile->cur_token[-1].src_loc not (yet) initialized. | 
|  | However, when the include file cannot be found, we need src_loc to | 
|  | be initialized to some safe value: 0 means UNKNOWN_LOCATION.  */ | 
|  | if (type == IT_CMDLINE && pfile->cur_token != pfile->cur_run->base) | 
|  | pfile->cur_token[-1].src_loc = 0; | 
|  |  | 
|  | cpp_dir *dir = search_path_head (pfile, fname, angle_brackets, type); | 
|  | if (!dir) | 
|  | return false; | 
|  |  | 
|  | _cpp_file *file = _cpp_find_file (pfile, fname, dir, angle_brackets, | 
|  | type == IT_DEFAULT ? _cpp_FFK_PRE_INCLUDE | 
|  | : _cpp_FFK_NORMAL, loc); | 
|  | if (type == IT_DEFAULT && file == NULL) | 
|  | return false; | 
|  |  | 
|  | return _cpp_stack_file (pfile, file, type, loc); | 
|  | } | 
|  |  | 
|  | /* NAME is a header file name, find the _cpp_file, if any.  */ | 
|  |  | 
|  | static _cpp_file * | 
|  | test_header_unit (cpp_reader *pfile, const char *name, bool angle, | 
|  | location_t loc) | 
|  | { | 
|  | if (cpp_dir *dir = search_path_head (pfile, name, angle, IT_INCLUDE)) | 
|  | return _cpp_find_file (pfile, name, dir, angle, _cpp_FFK_NORMAL, loc); | 
|  |  | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | /* NAME is a header file name, find the path we'll use to open it and infer that | 
|  | it is a header-unit.  */ | 
|  |  | 
|  | const char * | 
|  | _cpp_find_header_unit (cpp_reader *pfile, const char *name, bool angle, | 
|  | location_t loc) | 
|  | { | 
|  | if (_cpp_file *file = test_header_unit (pfile, name, angle, loc)) | 
|  | { | 
|  | if (file->fd > 0) | 
|  | { | 
|  | /* Don't leave it open.  */ | 
|  | close (file->fd); | 
|  | file->fd = 0; | 
|  | } | 
|  |  | 
|  | file->header_unit = +1; | 
|  | _cpp_mark_file_once_only (pfile, file); | 
|  |  | 
|  | return file->path; | 
|  | } | 
|  |  | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | /* NAME is a header file name, find the path we'll use to open it.  But do not | 
|  | infer it is a header unit.  */ | 
|  |  | 
|  | const char * | 
|  | cpp_probe_header_unit (cpp_reader *pfile, const char *name, bool angle, | 
|  | location_t loc) | 
|  | { | 
|  | if (_cpp_file *file = test_header_unit (pfile, name, angle, loc)) | 
|  | return file->path; | 
|  |  | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | /* Retrofit the just-entered main file asif it was an include.  This | 
|  | will permit correct include_next use, and mark it as a system | 
|  | header if that's where it resides.  We use filesystem-appropriate | 
|  | prefix matching of the include path to locate the main file.  */ | 
|  | void | 
|  | cpp_retrofit_as_include (cpp_reader *pfile) | 
|  | { | 
|  | /* We should be the outermost.  */ | 
|  | gcc_assert (!pfile->buffer->prev); | 
|  |  | 
|  | if (const char *name = pfile->main_file->name) | 
|  | { | 
|  | /* Locate name on the include dir path, using a prefix match.  */ | 
|  | size_t name_len = strlen (name); | 
|  | for (cpp_dir *dir = pfile->quote_include; dir; dir = dir->next) | 
|  | if (dir->len < name_len | 
|  | && IS_DIR_SEPARATOR (name[dir->len]) | 
|  | && !filename_ncmp (name, dir->name, dir->len)) | 
|  | { | 
|  | pfile->main_file->dir = dir; | 
|  | if (dir->sysp) | 
|  | cpp_make_system_header (pfile, 1, 0); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Initialize controlling macro state.  */ | 
|  | pfile->mi_valid = true; | 
|  | pfile->mi_cmacro = 0; | 
|  | } | 
|  |  | 
|  | /* Could not open FILE.  The complication is dependency output.  */ | 
|  | static void | 
|  | open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets, | 
|  | location_t loc) | 
|  | { | 
|  | int sysp = pfile->line_table->highest_line > 1 && pfile->buffer ? pfile->buffer->sysp : 0; | 
|  | bool print_dep = CPP_OPTION (pfile, deps.style) > (angle_brackets || !!sysp); | 
|  |  | 
|  | errno = file->err_no; | 
|  | if (print_dep && CPP_OPTION (pfile, deps.missing_files) && errno == ENOENT) | 
|  | { | 
|  | 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_filename (pfile, CPP_DL_FATAL, | 
|  | file->path ? file->path : file->name, | 
|  | loc); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* 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_filename (pfile, CPP_DL_FATAL, | 
|  | file->path ? file->path : file->name, | 
|  | loc); | 
|  | else | 
|  | cpp_errno_filename (pfile, CPP_DL_WARNING, | 
|  | file->path ? file->path : file->name, | 
|  | loc); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Search in the chain beginning at HEAD for a file whose search path | 
|  | started at START_DIR != NULL.  */ | 
|  | static struct cpp_file_hash_entry * | 
|  | search_cache (struct cpp_file_hash_entry *head, const cpp_dir *start_dir) | 
|  | { | 
|  | while (head && head->start_dir != start_dir) | 
|  | head = head->next; | 
|  |  | 
|  | return head; | 
|  | } | 
|  |  | 
|  | /* Allocate a new _cpp_file structure.  */ | 
|  | static _cpp_file * | 
|  | make_cpp_file (cpp_dir *dir, const char *fname) | 
|  | { | 
|  | _cpp_file *file = XCNEW (_cpp_file); | 
|  | file->fd = -1; | 
|  | file->dir = dir; | 
|  | file->name = xstrdup (fname); | 
|  |  | 
|  | return file; | 
|  | } | 
|  |  | 
|  | /* Release a _cpp_file structure.  */ | 
|  | static void | 
|  | destroy_cpp_file (_cpp_file *file) | 
|  | { | 
|  | free ((void *) file->buffer_start); | 
|  | free ((void *) file->name); | 
|  | free ((void *) file->path); | 
|  | 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. | 
|  |  | 
|  | To avoid duplicate entries we follow the convention that all | 
|  | non-empty directory names should end in a '/'.  DIR_NAME must be | 
|  | stored in permanently allocated memory.  */ | 
|  | static cpp_dir * | 
|  | make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp) | 
|  | { | 
|  | struct cpp_file_hash_entry *entry, **hash_slot; | 
|  | cpp_dir *dir; | 
|  |  | 
|  | hash_slot = (struct cpp_file_hash_entry **) | 
|  | htab_find_slot_with_hash (pfile->dir_hash, dir_name, | 
|  | htab_hash_string (dir_name), | 
|  | INSERT); | 
|  |  | 
|  | /* Have we already hashed this directory?  */ | 
|  | for (entry = *hash_slot; entry; entry = entry->next) | 
|  | if (entry->start_dir == NULL) | 
|  | return entry->u.dir; | 
|  |  | 
|  | dir = XCNEW (cpp_dir); | 
|  | dir->next = pfile->quote_include; | 
|  | dir->name = (char *) dir_name; | 
|  | dir->len = strlen (dir_name); | 
|  | dir->sysp = sysp; | 
|  | dir->construct = 0; | 
|  |  | 
|  | /* Store this new result in the hash table.  */ | 
|  | 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; | 
|  |  | 
|  | return dir; | 
|  | } | 
|  |  | 
|  | /* Create a new block of memory for file hash entries.  */ | 
|  | static void | 
|  | allocate_file_hash_entries (cpp_reader *pfile) | 
|  | { | 
|  | 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 cpp_file_hash_entry * | 
|  | new_file_hash_entry (cpp_reader *pfile) | 
|  | { | 
|  | unsigned int idx; | 
|  | if (pfile->file_hash_entries->file_hash_entries_used == FILE_HASH_POOL_SIZE) | 
|  | allocate_file_hash_entries (pfile); | 
|  |  | 
|  | 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. | 
|  | This routine is not intended to correctly handle filenames aliased | 
|  | by links or redundant . or .. traversals etc.  */ | 
|  | bool | 
|  | cpp_included (cpp_reader *pfile, const char *fname) | 
|  | { | 
|  | struct cpp_file_hash_entry *entry; | 
|  |  | 
|  | entry = (struct cpp_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 = entry->next; | 
|  |  | 
|  | 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, | 
|  | location_t location) | 
|  | { | 
|  | struct cpp_file_hash_entry *entry | 
|  | = (struct cpp_file_hash_entry *) | 
|  | htab_find_with_hash (pfile->file_hash, fname, htab_hash_string (fname)); | 
|  |  | 
|  | if (IS_ADHOC_LOC (location)) | 
|  | location = get_location_from_adhoc_loc (pfile->line_table, location); | 
|  |  | 
|  | 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 | 
|  | file_hash_hash (const void *p) | 
|  | { | 
|  | struct cpp_file_hash_entry *entry = (struct cpp_file_hash_entry *) p; | 
|  | const char *hname; | 
|  | if (entry->start_dir) | 
|  | hname = entry->u.file->name; | 
|  | else | 
|  | hname = entry->u.dir->name; | 
|  |  | 
|  | return htab_hash_string (hname); | 
|  | } | 
|  |  | 
|  | /* Compare a string Q against a file hash entry P.  */ | 
|  | static int | 
|  | file_hash_eq (const void *p, const void *q) | 
|  | { | 
|  | struct cpp_file_hash_entry *entry = (struct cpp_file_hash_entry *) p; | 
|  | const char *fname = (const char *) q; | 
|  | const char *hname; | 
|  |  | 
|  | if (entry->start_dir) | 
|  | hname = entry->u.file->name; | 
|  | else | 
|  | hname = entry->u.dir->name; | 
|  |  | 
|  | return filename_cmp (hname, fname) == 0; | 
|  | } | 
|  |  | 
|  | /* Compare entries in the nonexistent file hash table.  These are just | 
|  | strings.  */ | 
|  | static int | 
|  | nonexistent_file_hash_eq (const void *p, const void *q) | 
|  | { | 
|  | return filename_cmp ((const char *) p, (const char *) q) == 0; | 
|  | } | 
|  |  | 
|  | /* Initialize everything in this source file.  */ | 
|  | void | 
|  | _cpp_init_files (cpp_reader *pfile) | 
|  | { | 
|  | pfile->file_hash = htab_create_alloc (127, file_hash_hash, file_hash_eq, | 
|  | NULL, xcalloc, free); | 
|  | pfile->dir_hash = htab_create_alloc (127, file_hash_hash, file_hash_eq, | 
|  | NULL, xcalloc, free); | 
|  | allocate_file_hash_entries (pfile); | 
|  | pfile->nonexistent_file_hash = htab_create_alloc (127, htab_hash_string, | 
|  | nonexistent_file_hash_eq, | 
|  | NULL, xcalloc, free); | 
|  | obstack_specify_allocation (&pfile->nonexistent_file_ob, 0, 0, | 
|  | xmalloc, free); | 
|  | } | 
|  |  | 
|  | /* Finalize everything in this source file.  */ | 
|  | void | 
|  | _cpp_cleanup_files (cpp_reader *pfile) | 
|  | { | 
|  | htab_delete (pfile->file_hash); | 
|  | 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.  */ | 
|  | void | 
|  | _cpp_fake_include (cpp_reader *pfile, const char *fname) | 
|  | { | 
|  | _cpp_find_file (pfile, fname, pfile->buffer->file->dir, 0, _cpp_FFK_FAKE, 0); | 
|  | } | 
|  |  | 
|  | /* Not everyone who wants to set system-header-ness on a buffer can | 
|  | see the details of a buffer.  This is an exported interface because | 
|  | fix-header needs it.  */ | 
|  | void | 
|  | cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc) | 
|  | { | 
|  | int flags = 0; | 
|  | const class line_maps *line_table = pfile->line_table; | 
|  | const line_map_ordinary *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, ORDINARY_MAP_FILE_NAME (map), | 
|  | SOURCE_LINE (map, pfile->line_table->highest_line), | 
|  | flags); | 
|  | } | 
|  |  | 
|  | /* Allow the client to change the current file.  Used by the front end | 
|  | to achieve pseudo-file names like <built-in>. | 
|  | If REASON is LC_LEAVE, then NEW_NAME must be NULL.  */ | 
|  | void | 
|  | cpp_change_file (cpp_reader *pfile, enum lc_reason reason, | 
|  | const char *new_name) | 
|  | { | 
|  | _cpp_do_file_change (pfile, reason, new_name, 1, 0); | 
|  | } | 
|  |  | 
|  | struct report_missing_guard_data | 
|  | { | 
|  | cpp_reader *pfile; | 
|  | const char **paths; | 
|  | size_t count; | 
|  | }; | 
|  |  | 
|  | /* Callback function for htab_traverse.  */ | 
|  | static int | 
|  | report_missing_guard (void **slot, void *d) | 
|  | { | 
|  | struct cpp_file_hash_entry *entry = (struct cpp_file_hash_entry *) *slot; | 
|  | struct report_missing_guard_data *data | 
|  | = (struct report_missing_guard_data *) d; | 
|  |  | 
|  | /* Skip directories.  */ | 
|  | if (entry->start_dir != NULL) | 
|  | { | 
|  | _cpp_file *file = entry->u.file; | 
|  |  | 
|  | /* We don't want MI guard advice for the main file.  */ | 
|  | if (!file->once_only | 
|  | && file->cmacro == NULL | 
|  | && file->stack_count == 1 | 
|  | && data->pfile->main_file != file) | 
|  | { | 
|  | if (data->paths == NULL) | 
|  | { | 
|  | data->paths = XCNEWVEC (const char *, data->count); | 
|  | data->count = 0; | 
|  | } | 
|  |  | 
|  | data->paths[data->count++] = file->path; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* 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. | 
|  | Triggered by -H.  */ | 
|  | void | 
|  | _cpp_report_missing_guards (cpp_reader *pfile) | 
|  | { | 
|  | struct report_missing_guard_data data; | 
|  |  | 
|  | data.pfile = pfile; | 
|  | data.paths = NULL; | 
|  | data.count = htab_elements (pfile->file_hash); | 
|  | htab_traverse (pfile->file_hash, report_missing_guard, &data); | 
|  |  | 
|  | 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 | 
|  | file.  If it cannot be located or dated, return -1, if it is | 
|  | newer, return 1, otherwise 0.  */ | 
|  | int | 
|  | _cpp_compare_file_date (cpp_reader *pfile, const char *fname, | 
|  | int angle_brackets) | 
|  | { | 
|  | _cpp_file *file; | 
|  | struct cpp_dir *dir; | 
|  |  | 
|  | dir = search_path_head (pfile, fname, angle_brackets, IT_INCLUDE); | 
|  | if (!dir) | 
|  | return -1; | 
|  |  | 
|  | file = _cpp_find_file (pfile, fname, dir, angle_brackets, _cpp_FFK_NORMAL, 0); | 
|  | if (file->err_no) | 
|  | return -1; | 
|  |  | 
|  | if (file->fd != -1) | 
|  | { | 
|  | close (file->fd); | 
|  | file->fd = -1; | 
|  | } | 
|  |  | 
|  | return file->st.st_mtime > pfile->buffer->file->st.st_mtime; | 
|  | } | 
|  |  | 
|  | /* Pushes the given file onto the buffer stack.  Returns nonzero if | 
|  | successful.  */ | 
|  | bool | 
|  | cpp_push_include (cpp_reader *pfile, const char *fname) | 
|  | { | 
|  | return _cpp_stack_include (pfile, fname, false, IT_CMDLINE, | 
|  | pfile->line_table->highest_line); | 
|  | } | 
|  |  | 
|  | /* Pushes the given file, implicitly included at the start of a | 
|  | compilation, onto the buffer stack but without any errors if the | 
|  | file is not found.  Returns nonzero if successful.  */ | 
|  | bool | 
|  | cpp_push_default_include (cpp_reader *pfile, const char *fname) | 
|  | { | 
|  | return _cpp_stack_include (pfile, fname, true, IT_DEFAULT, | 
|  | pfile->line_table->highest_line); | 
|  | } | 
|  |  | 
|  | /* Do appropriate cleanup when a file INC's buffer is popped off the | 
|  | input stack.  */ | 
|  | void | 
|  | _cpp_pop_file_buffer (cpp_reader *pfile, _cpp_file *file, | 
|  | const unsigned char *to_free) | 
|  | { | 
|  | /* Record the inclusion-preventing macro, which could be NULL | 
|  | meaning no controlling macro.  */ | 
|  | if (pfile->mi_valid && file->cmacro == NULL) | 
|  | file->cmacro = pfile->mi_cmacro; | 
|  |  | 
|  | /* Invalidate control macros in the #including file.  */ | 
|  | pfile->mi_valid = false; | 
|  |  | 
|  | if (to_free) | 
|  | { | 
|  | if (to_free == file->buffer_start) | 
|  | { | 
|  | file->buffer_start = NULL; | 
|  | file->buffer = NULL; | 
|  | file->buffer_valid = false; | 
|  | } | 
|  | free ((void *) to_free); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* 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) | 
|  | { | 
|  | return &file->st; | 
|  | } | 
|  |  | 
|  | /* Set the include chain for "" to QUOTE, for <> to BRACKET.  If | 
|  | QUOTE_IGNORES_SOURCE_DIR, then "" includes do not look in the | 
|  | directory of the including file. | 
|  |  | 
|  | If BRACKET does not lie in the QUOTE chain, it is set to QUOTE.  */ | 
|  | void | 
|  | cpp_set_include_chains (cpp_reader *pfile, cpp_dir *quote, cpp_dir *bracket, | 
|  | int quote_ignores_source_dir) | 
|  | { | 
|  | pfile->quote_include = quote; | 
|  | pfile->bracket_include = quote; | 
|  | pfile->quote_ignores_source_dir = quote_ignores_source_dir; | 
|  |  | 
|  | for (; quote; quote = quote->next) | 
|  | { | 
|  | quote->name_map = NULL; | 
|  | quote->len = strlen (quote->name); | 
|  | if (quote == bracket) | 
|  | pfile->bracket_include = bracket; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Append the file name to the directory to create the path, but don't | 
|  | turn / into // or // into ///; // may be a namespace escape.  */ | 
|  | static char * | 
|  | append_file_to_dir (const char *fname, cpp_dir *dir) | 
|  | { | 
|  | size_t dlen, flen; | 
|  | char *path; | 
|  |  | 
|  | dlen = dir->len; | 
|  | flen = strlen (fname); | 
|  | path = XNEWVEC (char, dlen + 1 + flen + 1); | 
|  | memcpy (path, dir->name, dlen); | 
|  | if (dlen && !IS_DIR_SEPARATOR (path[dlen - 1])) | 
|  | path[dlen++] = '/'; | 
|  | memcpy (&path[dlen], fname, flen + 1); | 
|  |  | 
|  | return path; | 
|  | } | 
|  |  | 
|  | /* Read a space delimited string of unlimited length from a stdio | 
|  | file F.  */ | 
|  | static char * | 
|  | read_filename_string (int ch, FILE *f) | 
|  | { | 
|  | char *alloc, *set; | 
|  | int len; | 
|  |  | 
|  | len = 20; | 
|  | set = alloc = XNEWVEC (char, len + 1); | 
|  | if (! is_space (ch)) | 
|  | { | 
|  | *set++ = ch; | 
|  | while ((ch = getc (f)) != EOF && ! is_space (ch)) | 
|  | { | 
|  | if (set - alloc == len) | 
|  | { | 
|  | len *= 2; | 
|  | alloc = XRESIZEVEC (char, alloc, len + 1); | 
|  | set = alloc + len / 2; | 
|  | } | 
|  | *set++ = ch; | 
|  | } | 
|  | } | 
|  | *set = '\0'; | 
|  | ungetc (ch, f); | 
|  | return alloc; | 
|  | } | 
|  |  | 
|  | /* Read the file name map file for DIR.  */ | 
|  | static void | 
|  | read_name_map (cpp_dir *dir) | 
|  | { | 
|  | static const char FILE_NAME_MAP_FILE[] = "header.gcc"; | 
|  | char *name; | 
|  | FILE *f; | 
|  | size_t len, count = 0, room = 9; | 
|  |  | 
|  | len = dir->len; | 
|  | name = (char *) alloca (len + sizeof (FILE_NAME_MAP_FILE) + 1); | 
|  | memcpy (name, dir->name, len); | 
|  | if (len && !IS_DIR_SEPARATOR (name[len - 1])) | 
|  | name[len++] = '/'; | 
|  | strcpy (name + len, FILE_NAME_MAP_FILE); | 
|  | f = fopen (name, "r"); | 
|  |  | 
|  | dir->name_map = XNEWVEC (const char *, room); | 
|  |  | 
|  | /* Silently return NULL if we cannot open.  */ | 
|  | if (f) | 
|  | { | 
|  | int ch; | 
|  |  | 
|  | while ((ch = getc (f)) != EOF) | 
|  | { | 
|  | char *to; | 
|  |  | 
|  | if (is_space (ch)) | 
|  | continue; | 
|  |  | 
|  | if (count + 2 > room) | 
|  | { | 
|  | room += 8; | 
|  | dir->name_map = XRESIZEVEC (const char *, dir->name_map, room); | 
|  | } | 
|  |  | 
|  | dir->name_map[count] = read_filename_string (ch, f); | 
|  | while ((ch = getc (f)) != EOF && is_hspace (ch)) | 
|  | ; | 
|  |  | 
|  | to = read_filename_string (ch, f); | 
|  | if (IS_ABSOLUTE_PATH (to)) | 
|  | dir->name_map[count + 1] = to; | 
|  | else | 
|  | { | 
|  | dir->name_map[count + 1] = append_file_to_dir (to, dir); | 
|  | free (to); | 
|  | } | 
|  |  | 
|  | count += 2; | 
|  | while ((ch = getc (f)) != '\n') | 
|  | if (ch == EOF) | 
|  | break; | 
|  | } | 
|  |  | 
|  | fclose (f); | 
|  | } | 
|  |  | 
|  | /* Terminate the list of maps.  */ | 
|  | dir->name_map[count] = NULL; | 
|  | } | 
|  |  | 
|  | /* Remap a FILE's name based on the file_name_map, if any, for | 
|  | FILE->dir.  If the file name has any directory separators, | 
|  | recursively check those directories too.  */ | 
|  | static char * | 
|  | remap_filename (cpp_reader *pfile, _cpp_file *file) | 
|  | { | 
|  | const char *fname, *p; | 
|  | char *new_dir, *p3; | 
|  | cpp_dir *dir; | 
|  | size_t index, len; | 
|  |  | 
|  | dir = file->dir; | 
|  | fname = file->name; | 
|  |  | 
|  | for (;;) | 
|  | { | 
|  | if (!dir->name_map) | 
|  | read_name_map (dir); | 
|  |  | 
|  | for (index = 0; dir->name_map[index]; index += 2) | 
|  | 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 | 
|  | { | 
|  | const char *p2 = strchr (fname, '\\'); | 
|  | if (!p || (p > p2)) | 
|  | p = p2; | 
|  | } | 
|  | #endif | 
|  | if (!p || p == fname) | 
|  | return NULL; | 
|  |  | 
|  | len = dir->len + (p - fname + 1); | 
|  | new_dir = XNEWVEC (char, len + 2); | 
|  | p3 = new_dir + dir->len; | 
|  | memcpy (new_dir, dir->name, dir->len); | 
|  | if (dir->len && !IS_DIR_SEPARATOR (dir->name[dir->len - 1])) | 
|  | { | 
|  | *p3++ = '/'; | 
|  | len++; | 
|  | } | 
|  | memcpy (p3, fname, p - fname + 1); | 
|  | new_dir[len] = '\0'; | 
|  |  | 
|  | dir = make_cpp_dir (pfile, new_dir, dir->sysp); | 
|  | fname = p + 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Returns true if PCHNAME is a valid PCH file for FILE.  */ | 
|  | static bool | 
|  | validate_pch (cpp_reader *pfile, _cpp_file *file, const char *pchname) | 
|  | { | 
|  | const char *saved_path = file->path; | 
|  | bool valid = false; | 
|  |  | 
|  | file->path = pchname; | 
|  | if (open_file (file)) | 
|  | { | 
|  | valid = 1 & pfile->cb.valid_pch (pfile, pchname, file->fd); | 
|  |  | 
|  | if (!valid) | 
|  | { | 
|  | close (file->fd); | 
|  | file->fd = -1; | 
|  | } | 
|  |  | 
|  | if (CPP_OPTION (pfile, print_include_names)) | 
|  | { | 
|  | unsigned int i; | 
|  | for (i = 1; i < pfile->line_table->depth; i++) | 
|  | putc ('.', stderr); | 
|  | fprintf (stderr, "%c %s\n", | 
|  | valid ? '!' : 'x', pchname); | 
|  | } | 
|  | } | 
|  |  | 
|  | file->path = saved_path; | 
|  | return valid; | 
|  | } | 
|  |  | 
|  | /* Get the path associated with the _cpp_file F.  The path includes | 
|  | the base name from the include directive and the directory it was | 
|  | found in via the search path.  */ | 
|  |  | 
|  | const char * | 
|  | cpp_get_path (struct _cpp_file *f) | 
|  | { | 
|  | return f->path; | 
|  | } | 
|  |  | 
|  | /* Get the directory associated with the _cpp_file F.  */ | 
|  |  | 
|  | cpp_dir * | 
|  | cpp_get_dir (struct _cpp_file *f) | 
|  | { | 
|  | return f->dir; | 
|  | } | 
|  |  | 
|  | /* Get the cpp_buffer currently associated with the cpp_reader | 
|  | PFILE.  */ | 
|  |  | 
|  | cpp_buffer * | 
|  | cpp_get_buffer (cpp_reader *pfile) | 
|  | { | 
|  | return pfile->buffer; | 
|  | } | 
|  |  | 
|  | /* Get the _cpp_file associated with the cpp_buffer B.  */ | 
|  |  | 
|  | _cpp_file * | 
|  | cpp_get_file (cpp_buffer *b) | 
|  | { | 
|  | return b->file; | 
|  | } | 
|  |  | 
|  | /* Get the previous cpp_buffer given a cpp_buffer B.  The previous | 
|  | buffer is the buffer that included the given buffer.  */ | 
|  |  | 
|  | cpp_buffer * | 
|  | cpp_get_prev (cpp_buffer *b) | 
|  | { | 
|  | return b->prev; | 
|  | } | 
|  |  | 
|  | /* This data structure holds the list of header files that were seen | 
|  | while the PCH was being built.  The 'entries' field is kept sorted | 
|  | in memcmp() order; yes, this means that on little-endian systems, | 
|  | it's sorted initially by the least-significant byte of 'size', but | 
|  | that's OK.  The code does rely on having entries with the same size | 
|  | next to each other.  */ | 
|  |  | 
|  | struct pchf_entry { | 
|  | /* The size of this file.  This is used to save running a MD5 checksum | 
|  | if the sizes don't match.  */ | 
|  | off_t size; | 
|  | /* The MD5 checksum of this file.  */ | 
|  | unsigned char sum[16]; | 
|  | /* Is this file to be included only once?  */ | 
|  | bool once_only; | 
|  | }; | 
|  |  | 
|  | struct pchf_data { | 
|  | /* Number of pchf_entry structures.  */ | 
|  | size_t count; | 
|  |  | 
|  | /* Are there any values with once_only set? | 
|  | This is used as an optimisation, it means we don't have to search | 
|  | the structure if we're processing a regular #include.  */ | 
|  | bool have_once_only; | 
|  |  | 
|  | struct pchf_entry entries[1]; | 
|  | }; | 
|  |  | 
|  | static struct pchf_data *pchf; | 
|  |  | 
|  | /* A qsort ordering function for pchf_entry structures.  */ | 
|  |  | 
|  | static int | 
|  | pchf_save_compare (const void *e1, const void *e2) | 
|  | { | 
|  | return memcmp (e1, e2, sizeof (struct pchf_entry)); | 
|  | } | 
|  |  | 
|  | /* Create and write to F a pchf_data structure.  */ | 
|  |  | 
|  | bool | 
|  | _cpp_save_file_entries (cpp_reader *pfile, FILE *fp) | 
|  | { | 
|  | size_t count = 0; | 
|  | struct pchf_data *result; | 
|  | size_t result_size; | 
|  | _cpp_file *f; | 
|  | bool ret; | 
|  |  | 
|  | for (f = pfile->all_files; f; f = f->next_file) | 
|  | ++count; | 
|  |  | 
|  | result_size = (sizeof (struct pchf_data) | 
|  | + sizeof (struct pchf_entry) * (count - 1)); | 
|  | result = XCNEWVAR (struct pchf_data, result_size); | 
|  |  | 
|  | result->count = 0; | 
|  | result->have_once_only = false; | 
|  |  | 
|  | for (f = pfile->all_files; f; f = f->next_file) | 
|  | { | 
|  | size_t count; | 
|  |  | 
|  | /* This should probably never happen, since if a read error occurred | 
|  | the PCH file shouldn't be written...  */ | 
|  | if (f->dont_read || f->err_no) | 
|  | continue; | 
|  |  | 
|  | if (f->stack_count == 0) | 
|  | continue; | 
|  |  | 
|  | count = result->count++; | 
|  |  | 
|  | result->entries[count].once_only = f->once_only; | 
|  | /* |= is avoided in the next line because of an HP C compiler bug */ | 
|  | result->have_once_only = result->have_once_only | f->once_only; | 
|  | if (f->buffer_valid) | 
|  | md5_buffer ((const char *)f->buffer, | 
|  | f->st.st_size, result->entries[count].sum); | 
|  | else | 
|  | { | 
|  | FILE *ff; | 
|  | int oldfd = f->fd; | 
|  |  | 
|  | if (!open_file (f)) | 
|  | { | 
|  | open_file_failed (pfile, f, 0, 0); | 
|  | free (result); | 
|  | return false; | 
|  | } | 
|  | ff = fdopen (f->fd, "rb"); | 
|  | md5_stream (ff, result->entries[count].sum); | 
|  | fclose (ff); | 
|  | f->fd = oldfd; | 
|  | } | 
|  | result->entries[count].size = f->st.st_size; | 
|  | } | 
|  |  | 
|  | result_size = (sizeof (struct pchf_data) | 
|  | + sizeof (struct pchf_entry) * (result->count - 1)); | 
|  |  | 
|  | qsort (result->entries, result->count, sizeof (struct pchf_entry), | 
|  | pchf_save_compare); | 
|  |  | 
|  | ret = fwrite (result, result_size, 1, fp) == 1; | 
|  | free (result); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Read the pchf_data structure from F.  */ | 
|  |  | 
|  | bool | 
|  | _cpp_read_file_entries (cpp_reader *pfile ATTRIBUTE_UNUSED, FILE *f) | 
|  | { | 
|  | struct pchf_data d; | 
|  |  | 
|  | if (fread (&d, sizeof (struct pchf_data) - sizeof (struct pchf_entry), 1, f) | 
|  | != 1) | 
|  | return false; | 
|  |  | 
|  | pchf = XNEWVAR (struct pchf_data, sizeof (struct pchf_data) | 
|  | + sizeof (struct pchf_entry) * (d.count - 1)); | 
|  | memcpy (pchf, &d, sizeof (struct pchf_data) - sizeof (struct pchf_entry)); | 
|  | if (fread (pchf->entries, sizeof (struct pchf_entry), d.count, f) | 
|  | != d.count) | 
|  | return false; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* The parameters for pchf_compare.  */ | 
|  |  | 
|  | struct pchf_compare_data | 
|  | { | 
|  | /* The size of the file we're looking for.  */ | 
|  | off_t size; | 
|  |  | 
|  | /* The MD5 checksum of the file, if it's been computed.  */ | 
|  | unsigned char sum[16]; | 
|  |  | 
|  | /* Is SUM valid?  */ | 
|  | bool sum_computed; | 
|  |  | 
|  | /* Do we need to worry about entries that don't have ONCE_ONLY set?  */ | 
|  | bool check_included; | 
|  |  | 
|  | /* The file that we're searching for.  */ | 
|  | _cpp_file *f; | 
|  | }; | 
|  |  | 
|  | /* bsearch comparison function; look for D_P in E_P.  */ | 
|  |  | 
|  | static int | 
|  | pchf_compare (const void *d_p, const void *e_p) | 
|  | { | 
|  | const struct pchf_entry *e = (const struct pchf_entry *)e_p; | 
|  | struct pchf_compare_data *d = (struct pchf_compare_data *)d_p; | 
|  | int result; | 
|  |  | 
|  | result = memcmp (&d->size, &e->size, sizeof (off_t)); | 
|  | if (result != 0) | 
|  | return result; | 
|  |  | 
|  | if (! d->sum_computed) | 
|  | { | 
|  | _cpp_file *const f = d->f; | 
|  |  | 
|  | md5_buffer ((const char *)f->buffer, f->st.st_size, d->sum); | 
|  | d->sum_computed = true; | 
|  | } | 
|  |  | 
|  | result = memcmp (d->sum, e->sum, 16); | 
|  | if (result != 0) | 
|  | return result; | 
|  |  | 
|  | if (d->check_included || e->once_only) | 
|  | return 0; | 
|  | else | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* Check that F is not in a list read from a PCH file (if any). | 
|  | Assumes that f->buffer_valid is true.  Return TRUE if the file | 
|  | should not be read.  */ | 
|  |  | 
|  | static bool | 
|  | check_file_against_entries (cpp_reader *pfile ATTRIBUTE_UNUSED, | 
|  | _cpp_file *f, | 
|  | bool check_included) | 
|  | { | 
|  | struct pchf_compare_data d; | 
|  |  | 
|  | if (pchf == NULL | 
|  | || (! check_included && ! pchf->have_once_only)) | 
|  | return false; | 
|  |  | 
|  | d.size = f->st.st_size; | 
|  | d.sum_computed = false; | 
|  | d.f = f; | 
|  | d.check_included = check_included; | 
|  | return bsearch (&d, pchf->entries, pchf->count, sizeof (struct pchf_entry), | 
|  | pchf_compare) != NULL; | 
|  | } | 
|  |  | 
|  | /* Return true if the file FNAME is found in the appropriate include file path | 
|  | as indicated by ANGLE_BRACKETS.  */ | 
|  |  | 
|  | bool | 
|  | _cpp_has_header (cpp_reader *pfile, const char *fname, int angle_brackets, | 
|  | enum include_type type) | 
|  | { | 
|  | cpp_dir *start_dir = search_path_head (pfile, fname, angle_brackets, type); | 
|  | _cpp_file *file = _cpp_find_file (pfile, fname, start_dir, angle_brackets, | 
|  | _cpp_FFK_HAS_INCLUDE, 0); | 
|  | return file->err_no != ENOENT; | 
|  | } | 
|  |  | 
|  | /* Read a file and convert to input charset, the same as if it were being read | 
|  | by a cpp_reader.  */ | 
|  |  | 
|  | cpp_converted_source | 
|  | cpp_get_converted_source (const char *fname, const char *input_charset) | 
|  | { | 
|  | cpp_converted_source res = {}; | 
|  | _cpp_file file = {}; | 
|  | file.fd = -1; | 
|  | file.name = lbasename (fname); | 
|  | file.path = fname; | 
|  | if (!open_file (&file)) | 
|  | return res; | 
|  | const bool ok = read_file_guts (NULL, &file, 0, input_charset); | 
|  | close (file.fd); | 
|  | if (!ok) | 
|  | return res; | 
|  | res.to_free = (char *) file.buffer_start; | 
|  | res.data = (char *) file.buffer; | 
|  | res.len = file.st.st_size; | 
|  | return res; | 
|  | } |