/* Part of CPP library. File handling.
- Copyright (C) 1986-2013 Free Software Foundation, Inc.
+ Copyright (C) 1986-2020 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
/* This structure represents a file searched for by CPP, whether it
exists or not. An instance may be pointed to by more than one
- file_hash_entry; at present no reference count is kept. */
+ cpp_file_hash_entry; at present no reference count is kept. */
struct _cpp_file
{
/* Filename as given to #include or command line switch. */
unsigned short stack_count;
/* If opened with #import or contains #pragma once. */
- bool once_only;
+ bool once_only : 1;
/* If read() failed before. */
- bool dont_read;
+ bool dont_read : 1;
/* If this file is the main file. */
- bool main_file;
+ bool main_file : 1;
/* If BUFFER above contains the true contents of the file. */
- bool buffer_valid;
+ bool buffer_valid : 1;
/* If this file is implicitly preincluded. */
- bool implicit_preinclude;
+ bool implicit_preinclude : 1;
};
/* A singly-linked list for all searches for a given file name, with
have to do more work re-preprocessing the file, and/or comparing
its contents against earlier once-only files.
*/
-struct file_hash_entry
+struct cpp_file_hash_entry
{
- struct file_hash_entry *next;
+ struct cpp_file_hash_entry *next;
cpp_dir *start_dir;
- source_location location;
+ location_t location;
union
{
_cpp_file *file;
} u;
};
-/* Number of entries to put in a file_hash_entry pool. */
+/* 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 file_hash_entry object from
+/* A file hash entry pool. We allocate cpp_file_hash_entry object from
one of these. */
struct file_hash_entry_pool
{
/* 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];
+ 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);
-static bool read_file_guts (cpp_reader *pfile, _cpp_file *file);
-static bool read_file (cpp_reader *pfile, _cpp_file *file);
-static bool should_stack_file (cpp_reader *, _cpp_file *file, bool import);
+ bool *invalid_pch, location_t loc);
+static bool read_file_guts (cpp_reader *pfile, _cpp_file *file,
+ location_t loc);
+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);
-static struct file_hash_entry *search_cache (struct file_hash_entry *head,
+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_reader *, 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 file_hash_entry *new_file_hash_entry (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);
/* 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
- && !(pfile->all_files->implicit_preinclude
- || pfile->all_files->next_file->implicit_preinclude))
- return false;
+ for (_cpp_file *f = pfile->all_files; f; f = f->next_file)
+ if (f->implicit_preinclude)
+ continue;
+ else if (f->main_file)
+ break;
+ else
+ return false;
flen = strlen (path);
len = flen + sizeof (extension);
/* 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. */
+ 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)
+find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch,
+ location_t loc)
{
char *path;
char *copy;
void **pp;
- /* We try to canonicalize system headers. */
- if (CPP_OPTION (pfile, canonical_system_headers) && file->dir->sysp)
+ /* 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)
if (file->err_no != ENOENT)
{
- open_file_failed (pfile, file, 0);
+ open_file_failed (pfile, file, 0, loc);
return true;
}
return false;
}
-/* Return tue iff the missing_header callback found the given HEADER. */
+/* 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)
{
had previously been closed. To open it again pass the return value
to open_file().
- If IMPLICIT_PREINCLUDE then it is OK for the file to be missing.
- If present, it is OK for a precompiled header to be included after
- it.
-*/
+ 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,
- bool fake, int angle_brackets, bool implicit_preinclude)
+ int angle_brackets, _cpp_find_file_kind kind, location_t loc)
{
- struct file_hash_entry *entry;
- void **hash_slot;
- _cpp_file *file;
bool invalid_pch = false;
bool saw_bracket_include = false;
bool saw_quote_include = false;
/* Ensure we get no confusion between cached files and directories. */
if (start_dir == NULL)
- cpp_error (pfile, CPP_DL_ICE, "NULL directory in find_file");
+ cpp_error_at (pfile, CPP_DL_ICE, loc, "NULL directory in find_file");
- hash_slot
+ 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. */
- entry = search_cache ((struct file_hash_entry *) *hash_slot, start_dir);
+ cpp_file_hash_entry *entry
+ = search_cache ((struct cpp_file_hash_entry *) *hash_slot, start_dir);
if (entry)
return entry->u.file;
- file = make_cpp_file (pfile, start_dir, fname);
- file->implicit_preinclude = implicit_preinclude;
-
- /* Try each path in the include chain. */
- for (; !fake ;)
- {
- if (find_file_in_dir (pfile, file, &invalid_pch))
- break;
+ _cpp_file *file = make_cpp_file (pfile, start_dir, fname);
+ file->implicit_preinclude
+ = (kind == _cpp_FFK_PRE_INCLUDE
+ || (pfile->buffer && pfile->buffer->file->implicit_preinclude));
- 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_ERROR,
- "use -Winvalid-pch for more information");
- }
- if (implicit_preinclude)
- {
- 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;
- }
- else
- open_file_failed (pfile, file, angle_brackets);
+ if (kind != _cpp_FFK_FAKE)
+ /* Try each path in the include chain. */
+ for (;;)
+ {
+ if (find_file_in_dir (pfile, file, &invalid_pch, 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 file_hash_entry *) *hash_slot, file->dir);
- if (entry)
- {
- found_in_cache = file->dir;
- 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_ERROR,
+ "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)
{
/* Store this new result in the hash table. */
entry = new_file_hash_entry (pfile);
- entry->next = (struct file_hash_entry *) *hash_slot;
+ entry->next = (struct cpp_file_hash_entry *) *hash_slot;
entry->start_dir = start_dir;
- entry->location = pfile->line_table->highest_location;
+ entry->location = loc;
entry->u.file = file;
*hash_slot = (void *) entry;
&& found_in_cache != pfile->bracket_include)
{
entry = new_file_hash_entry (pfile);
- entry->next = (struct file_hash_entry *) *hash_slot;
+ entry->next = (struct cpp_file_hash_entry *) *hash_slot;
entry->start_dir = pfile->bracket_include;
- entry->location = pfile->line_table->highest_location;
+ entry->location = loc;
entry->u.file = file;
*hash_slot = (void *) entry;
}
&& found_in_cache != pfile->quote_include)
{
entry = new_file_hash_entry (pfile);
- entry->next = (struct file_hash_entry *) *hash_slot;
+ entry->next = (struct cpp_file_hash_entry *) *hash_slot;
entry->start_dir = pfile->quote_include;
- entry->location = pfile->line_table->highest_location;
+ entry->location = loc;
entry->u.file = file;
*hash_slot = (void *) entry;
}
except for plain files and block devices, since there is no
reliable portable way of doing this.
+ Use LOC for any diagnostics.
+
FIXME: Flush file cache and try again if we run out of memory. */
static bool
-read_file_guts (cpp_reader *pfile, _cpp_file *file)
+read_file_guts (cpp_reader *pfile, _cpp_file *file, location_t loc)
{
ssize_t size, total, count;
uchar *buf;
if (S_ISBLK (file->st.st_mode))
{
- cpp_error (pfile, CPP_DL_ERROR, "%s is a block device", file->path);
+ cpp_error_at (pfile, CPP_DL_ERROR, loc,
+ "%s is a block device", file->path);
return false;
}
does not bite us. */
if (file->st.st_size > INTTYPE_MAXIMUM (ssize_t))
{
- cpp_error (pfile, CPP_DL_ERROR, "%s is too large", file->path);
+ cpp_error_at (pfile, CPP_DL_ERROR, loc,
+ "%s is too large", file->path);
return false;
}
if (count < 0)
{
- cpp_errno (pfile, CPP_DL_ERROR, file->path);
+ cpp_errno_filename (pfile, CPP_DL_ERROR, file->path, loc);
free (buf);
return false;
}
if (regular && total != size && STAT_SIZE_RELIABLE (file->st))
- cpp_error (pfile, CPP_DL_WARNING,
+ cpp_error_at (pfile, CPP_DL_WARNING, loc,
"%s is shorter than expected", file->path);
file->buffer = _cpp_convert_input (pfile,
/* 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. */
+ have been passed through find_file() at some stage. Use LOC for
+ any diagnostics. */
static bool
-read_file (cpp_reader *pfile, _cpp_file *file)
+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)
if (file->fd == -1 && !open_file (file))
{
- open_file_failed (pfile, file, 0);
+ open_file_failed (pfile, file, 0, loc);
return false;
}
- file->dont_read = !read_file_guts (pfile, file);
+ file->dont_read = !read_file_guts (pfile, file, loc);
close (file->fd);
file->fd = -1;
return !file->dont_read;
}
-/* Returns TRUE if FILE's contents have been successfully placed in
- FILE->buffer and the file should be stacked, otherwise false. */
+/* Returns TRUE if FILE is already known to be idempotent, and should
+ therefore not be read again. */
static bool
-should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
+is_known_idempotent_file (cpp_reader *pfile, _cpp_file *file, bool import)
{
- _cpp_file *f;
-
/* Skip once-only files. */
if (file->once_only)
- return false;
+ return true;
/* We must mark the file once-only if #import now, before header
guard checks. Otherwise, undefining the header guard might
/* Don't stack files that have been stacked before. */
if (file->stack_count)
- return false;
+ 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 && file->cmacro->type == NT_MACRO)
- return false;
+ if (file->cmacro && cpp_macro_p (file->cmacro))
+ return true;
/* Handle PCH files immediately; don't stack them. */
if (file->pchname)
file->fd = -1;
free ((void *) file->pchname);
file->pchname = NULL;
- return false;
+ return true;
}
- if (!read_file (pfile, file))
- return false;
+ 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. */
/* We may have read the file under a different name. Look
for likely candidates and compare file contents to be sure. */
- for (f = pfile->all_files; f; f = f->next_file)
+ for (_cpp_file *f = pfile->all_files; f; f = f->next_file)
{
if (f == file)
- continue;
+ continue; /* It'sa me! */
if ((import || f->once_only)
&& f->err_no == 0
&& f->st.st_size == file->st.st_size)
{
_cpp_file *ref_file;
- bool same_file_p = false;
if (f->buffer && !f->buffer_valid)
{
/* The file is not stacked anymore. We can reuse it. */
ref_file = f;
- same_file_p = read_file (pfile, ref_file)
- /* 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);
+ 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)
{
}
if (same_file_p)
- break;
+ /* Already seen under a different name. */
+ return false;
}
}
- return f == NULL;
+ return true;
}
/* Place the file referenced by FILE into a new buffer on the buffer
stack if possible. IMPORT is true if this stacking attempt is
because of a #import directive. Returns true if a buffer is
- stacked. */
+ stacked. Use LOC for any diagnostics. */
bool
-_cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
+_cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
+ location_t loc)
{
- cpp_buffer *buffer;
- int sysp;
+ if (is_known_idempotent_file (pfile, file, type == IT_IMPORT))
+ return false;
- if (!should_stack_file (pfile, file, import))
- return false;
+ if (!read_file (pfile, file, loc))
+ return false;
- if (pfile->buffer == NULL || file->dir == NULL)
- sysp = 0;
- else
- sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
+ if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc))
+ return false;
+
+ int sysp = 0;
+ 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 && !file->stack_count)
- {
- if (!file->main_file || !CPP_OPTION (pfile, deps.ignore_main_file))
- deps_add_dep (pfile->deps, file->path);
- }
+ if (CPP_OPTION (pfile, deps.style) > (sysp != 0)
+ && !file->stack_count
+ && file->path[0]
+ && !(file->main_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. */
- buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
- CPP_OPTION (pfile, preprocessed)
- && !CPP_OPTION (pfile, directives_only));
+ 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;
pfile->mi_valid = true;
pfile->mi_cmacro = 0;
- /* Generate the call back. */
+ /* 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. */
+ if (file->pchname == NULL
+ && type < IT_DIRECTIVE_HWM
+ && pfile->line_table->highest_location != LINE_MAP_MAX_LOCATION - 1)
+ pfile->line_table->highest_location--;
+
+ /* Add line map and do callbacks. */
_cpp_do_file_change (pfile, LC_ENTER, file->path, 1, sysp);
return true;
Returns true if a buffer was stacked. */
bool
_cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
- enum include_type type)
-{
- struct cpp_dir *dir;
- _cpp_file *file;
- bool stacked;
-
- dir = search_path_head (pfile, fname, angle_brackets, type);
+ 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;
- file = _cpp_find_file (pfile, fname, dir, false, angle_brackets,
- type == IT_DEFAULT);
+ _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;
- /* Compensate for the increment in linemap_add that occurs if
- _cpp_stack_file actually stacks the 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 && type != IT_DEFAULT)
- pfile->line_table->highest_location--;
-
- stacked = _cpp_stack_file (pfile, file, type == IT_IMPORT);
-
- if (!stacked)
- /* _cpp_stack_file didn't stack the file, so let's rollback the
- compensation dance we performed above. */
- pfile->line_table->highest_location++;
-
- return stacked;
+ return _cpp_stack_file (pfile, file, type, loc);
}
/* Could not open FILE. The complication is dependency output. */
static void
-open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets)
+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);
/* 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);
+ cpp_errno_filename (pfile, CPP_DL_FATAL,
+ file->path ? file->path : file->name,
+ loc);
}
else
{
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);
+ cpp_errno_filename (pfile, CPP_DL_FATAL,
+ file->path ? file->path : file->name,
+ loc);
else
- cpp_errno (pfile, CPP_DL_WARNING, file->path);
+ 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 file_hash_entry *
-search_cache (struct file_hash_entry *head, const cpp_dir *start_dir)
+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;
{
free ((void *) file->buffer_start);
free ((void *) file->name);
+ free ((void *) file->path);
free (file);
}
static cpp_dir *
make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp)
{
- struct file_hash_entry *entry, **hash_slot;
+ struct cpp_file_hash_entry *entry, **hash_slot;
cpp_dir *dir;
- hash_slot = (struct file_hash_entry **)
+ hash_slot = (struct cpp_file_hash_entry **)
htab_find_slot_with_hash (pfile->dir_hash, dir_name,
htab_hash_string (dir_name),
INSERT);
}
/* Return a new file hash entry. */
-static struct file_hash_entry *
+static struct cpp_file_hash_entry *
new_file_hash_entry (cpp_reader *pfile)
{
unsigned int idx;
bool
cpp_included (cpp_reader *pfile, const char *fname)
{
- struct file_hash_entry *entry;
+ struct cpp_file_hash_entry *entry;
- entry = (struct file_hash_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))
filenames aliased by links or redundant . or .. traversals etc. */
bool
cpp_included_before (cpp_reader *pfile, const char *fname,
- source_location location)
+ location_t location)
{
- struct file_hash_entry *entry;
+ struct cpp_file_hash_entry *entry
+ = (struct cpp_file_hash_entry *)
+ htab_find_with_hash (pfile->file_hash, fname, htab_hash_string (fname));
- entry = (struct 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))
static hashval_t
file_hash_hash (const void *p)
{
- struct file_hash_entry *entry = (struct file_hash_entry *) 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;
static int
file_hash_eq (const void *p, const void *q)
{
- struct file_hash_entry *entry = (struct file_hash_entry *) p;
+ struct cpp_file_hash_entry *entry = (struct cpp_file_hash_entry *) p;
const char *fname = (const char *) q;
const char *hname;
pfile->nonexistent_file_hash = htab_create_alloc (127, htab_hash_string,
nonexistent_file_hash_eq,
NULL, xcalloc, free);
- _obstack_begin (&pfile->nonexistent_file_ob, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
+ obstack_specify_allocation (&pfile->nonexistent_file_ob, 0, 0,
+ xmalloc, free);
}
/* Finalize everything in this source file. */
void
_cpp_fake_include (cpp_reader *pfile, const char *fname)
{
- _cpp_find_file (pfile, fname, pfile->buffer->file->dir, true, 0, false);
+ _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
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 = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+ 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);
+ SOURCE_LINE (map, pfile->line_table->highest_line),
+ flags);
}
/* Allow the client to change the current file. Used by the front end
static int
report_missing_guard (void **slot, void *d)
{
- struct file_hash_entry *entry = (struct file_hash_entry *) *slot;
+ struct cpp_file_hash_entry *entry = (struct cpp_file_hash_entry *) *slot;
struct report_missing_guard_data *data
= (struct report_missing_guard_data *) d;
if (!dir)
return -1;
- file = _cpp_find_file (pfile, fname, dir, false, angle_brackets, false);
+ file = _cpp_find_file (pfile, fname, dir, angle_brackets, _cpp_FFK_NORMAL, 0);
if (file->err_no)
return -1;
bool
cpp_push_include (cpp_reader *pfile, const char *fname)
{
- return _cpp_stack_include (pfile, fname, false, IT_CMDLINE);
+ return _cpp_stack_include (pfile, fname, false, IT_CMDLINE, 0);
}
/* Pushes the given file, implicitly included at the start of a
bool
cpp_push_default_include (cpp_reader *pfile, const char *fname)
{
- return _cpp_stack_include (pfile, fname, true, IT_DEFAULT);
+ return _cpp_stack_include (pfile, fname, true, IT_DEFAULT, 0);
}
/* Do appropriate cleanup when a file INC's buffer is popped off the
remap_filename (cpp_reader *pfile, _cpp_file *file)
{
const char *fname, *p;
- char *new_dir;
+ char *new_dir, *p3;
cpp_dir *dir;
size_t index, len;
return NULL;
len = dir->len + (p - fname + 1);
- new_dir = XNEWVEC (char, len + 1);
+ new_dir = XNEWVEC (char, len + 2);
+ p3 = new_dir + dir->len;
memcpy (new_dir, dir->name, dir->len);
- memcpy (new_dir + dir->len, fname, p - fname + 1);
+ 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);
if (!open_file (f))
{
- open_file_failed (pfile, f, 0);
+ open_file_failed (pfile, f, 0, 0);
free (result);
return false;
}
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;
+}
+