#include "config.h"
#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
#include "cpplib.h"
#include "cpphash.h"
#include "mkdeps.h"
static void init_library (void);
static void mark_named_operators (cpp_reader *);
static void read_original_filename (cpp_reader *);
+static void read_original_directory (cpp_reader *);
static void post_options (cpp_reader *);
/* If we have designated initializers (GCC >2.7) these tables can be
/* Initialize this instance of the library if it hasn't been already. */
init_library ();
- pfile = (cpp_reader *) xcalloc (1, sizeof (cpp_reader));
+ pfile = xcalloc (1, sizeof (cpp_reader));
cpp_set_lang (pfile, lang);
- CPP_OPTION (pfile, warn_import) = 1;
CPP_OPTION (pfile, warn_multichar) = 1;
CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
CPP_OPTION (pfile, int_precision) = CHAR_BIT * sizeof (int);
CPP_OPTION (pfile, unsigned_char) = 0;
CPP_OPTION (pfile, unsigned_wchar) = 1;
+ CPP_OPTION (pfile, bytes_big_endian) = 1; /* does not matter */
+
+ /* Default to no charset conversion. */
+ CPP_OPTION (pfile, narrow_charset) = 0;
+ CPP_OPTION (pfile, wide_charset) = 0;
+
+ /* A fake empty "directory" used as the starting point for files
+ looked up without a search path. Name cannot be '/' because we
+ don't want to prepend anything at all to filenames using it. All
+ other entries are correct zero-initialized. */
+ pfile->no_search_path.name = (char *) "";
/* Initialize the line map. Start at logical line 1, so we can use
a line number of zero for special states. */
- init_line_maps (&pfile->line_maps);
+ linemap_init (&pfile->line_maps);
+ pfile->line = 1;
/* Initialize lexer state. */
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
_cpp_expand_op_stack (pfile);
/* Initialize the buffer obstack. */
- gcc_obstack_init (&pfile->buffer_ob);
+ _obstack_begin (&pfile->buffer_ob, 0, 0,
+ (void *(*) (long)) xmalloc,
+ (void (*) (void *)) free);
- _cpp_init_includes (pfile);
+ _cpp_init_files (pfile);
_cpp_init_hashtable (pfile, table);
obstack_free (&pfile->buffer_ob, 0);
_cpp_destroy_hashtable (pfile);
- _cpp_cleanup_includes (pfile);
+ _cpp_cleanup_files (pfile);
+ _cpp_destroy_iconv (pfile);
_cpp_free_buff (pfile->a_buff);
_cpp_free_buff (pfile->u_buff);
free (context);
}
- free_line_maps (&pfile->line_maps);
+ linemap_free (&pfile->line_maps);
free (pfile);
}
type precisions made by cpplib. */
test--;
if (test < 1)
- cpp_error (pfile, DL_ICE, "cppchar_t must be an unsigned type");
+ cpp_error (pfile, CPP_DL_ICE, "cppchar_t must be an unsigned type");
if (CPP_OPTION (pfile, precision) > max_precision)
- cpp_error (pfile, DL_ICE,
+ cpp_error (pfile, CPP_DL_ICE,
"preprocessor arithmetic has maximum precision of %lu bits;"
" target requires %lu bits",
(unsigned long) max_precision,
(unsigned long) CPP_OPTION (pfile, precision));
if (CPP_OPTION (pfile, precision) < CPP_OPTION (pfile, int_precision))
- cpp_error (pfile, DL_ICE,
+ cpp_error (pfile, CPP_DL_ICE,
"CPP arithmetic must be at least as precise as a target int");
if (CPP_OPTION (pfile, char_precision) < 8)
- cpp_error (pfile, DL_ICE, "target char is less than 8 bits wide");
+ cpp_error (pfile, CPP_DL_ICE, "target char is less than 8 bits wide");
if (CPP_OPTION (pfile, wchar_precision) < CPP_OPTION (pfile, char_precision))
- cpp_error (pfile, DL_ICE,
+ cpp_error (pfile, CPP_DL_ICE,
"target wchar_t is narrower than target char");
if (CPP_OPTION (pfile, int_precision) < CPP_OPTION (pfile, char_precision))
- cpp_error (pfile, DL_ICE,
+ cpp_error (pfile, CPP_DL_ICE,
"target int is narrower than target char");
/* This is assumed in eval_token() and could be fixed if necessary. */
if (sizeof (cppchar_t) > sizeof (cpp_num_part))
- cpp_error (pfile, DL_ICE, "CPP half-integer narrower than CPP character");
+ cpp_error (pfile, CPP_DL_ICE,
+ "CPP half-integer narrower than CPP character");
if (CPP_OPTION (pfile, wchar_precision) > BITS_PER_CPPCHAR_T)
- cpp_error (pfile, DL_ICE,
+ cpp_error (pfile, CPP_DL_ICE,
"CPP on this host cannot handle wide character constants over"
" %lu bits, but the target requires %lu bits",
(unsigned long) BITS_PER_CPPCHAR_T,
}
/* This is called after options have been parsed, and partially
- processed. Setup for processing input from the file named FNAME,
- or stdin if it is the empty string. Return the original filename
- on success (e.g. foo.i->foo.c), or NULL on failure. */
-const char *
-cpp_read_main_file (cpp_reader *pfile, const char *fname)
+ processed. */
+void
+cpp_post_options (cpp_reader *pfile)
{
sanity_checks (pfile);
/* Mark named operators before handling command line macros. */
if (CPP_OPTION (pfile, cplusplus) && CPP_OPTION (pfile, operator_names))
mark_named_operators (pfile);
+}
+/* Setup for processing input from the file named FNAME, or stdin if
+ it is the empty string. Returns true if the file was found. */
+bool
+cpp_find_main_file (cpp_reader *pfile, const char *fname)
+{
if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)
{
if (!pfile->deps)
deps_add_default_target (pfile->deps, fname);
}
- /* Open the main input file. */
- pfile->line = 1;
- if (!_cpp_read_file (pfile, fname))
- return NULL;
+ pfile->main_file
+ = _cpp_find_file (pfile, fname, &pfile->no_search_path, false);
+ if (_cpp_find_failed (pfile->main_file))
+ return false;
- /* Set this here so the client can change the option if it wishes,
- and after stacking the main file so we don't trace the main
- file. */
- pfile->line_maps.trace_includes = CPP_OPTION (pfile, print_include_names);
+ if (CPP_OPTION (pfile, working_directory))
+ {
+ const char *dir = getpwd ();
+ char *dir_with_slashes = alloca (strlen (dir) + 3);
+
+ memcpy (dir_with_slashes, dir, strlen (dir));
+ memcpy (dir_with_slashes + strlen (dir), "//", 3);
+
+ if (pfile->cb.dir_change)
+ pfile->cb.dir_change (pfile, dir);
+ }
+ return true;
+}
+
+/* This function reads the file, but does not start preprocessing.
+ This will generate at least one file change callback, and possibly
+ a line change callback. */
+void
+cpp_push_main_file (cpp_reader *pfile)
+{
+ _cpp_stack_file (pfile, pfile->main_file, false);
/* For foo.i, read the original filename foo.c now, for the benefit
of the front ends. */
if (CPP_OPTION (pfile, preprocessed))
read_original_filename (pfile);
- return pfile->map->to_file;
+ /* Set this here so the client can change the option if it wishes,
+ and after stacking the main file so we don't trace the main
+ file. */
+ pfile->line_maps.trace_includes = CPP_OPTION (pfile, print_include_names);
}
/* For preprocessed files, if the first tokens are of the form # NUM.
if (token1->type == CPP_NUMBER)
{
_cpp_handle_directive (pfile, token->flags & PREV_WHITE);
+ read_original_directory (pfile);
return;
}
}
_cpp_backup_tokens (pfile, 1);
}
+/* For preprocessed files, if the tokens following the first filename
+ line is of the form # <line> "/path/name//", handle the
+ directive so we know the original current directory. */
+static void
+read_original_directory (cpp_reader *pfile)
+{
+ const cpp_token *hash, *token;
+
+ /* Lex ahead; if the first tokens are of the form # NUM, then
+ process the directive, otherwise back up. */
+ hash = _cpp_lex_direct (pfile);
+ if (hash->type != CPP_HASH)
+ {
+ _cpp_backup_tokens (pfile, 1);
+ return;
+ }
+
+ token = _cpp_lex_direct (pfile);
+
+ if (token->type != CPP_NUMBER)
+ {
+ _cpp_backup_tokens (pfile, 2);
+ return;
+ }
+
+ token = _cpp_lex_direct (pfile);
+
+ if (token->type != CPP_STRING
+ || ! (token->val.str.len >= 5
+ && token->val.str.text[token->val.str.len-2] == '/'
+ && token->val.str.text[token->val.str.len-3] == '/'))
+ {
+ _cpp_backup_tokens (pfile, 3);
+ return;
+ }
+
+ if (pfile->cb.dir_change)
+ {
+ char *debugdir = alloca (token->val.str.len - 3);
+
+ memcpy (debugdir, (const char *) token->val.str.text + 1,
+ token->val.str.len - 4);
+ debugdir[token->val.str.len - 4] = '\0';
+
+ pfile->cb.dir_change (pfile, debugdir);
+ }
+
+ /* We want to process the fake line changes as regular changes, to
+ get them output. */
+ _cpp_backup_tokens (pfile, 3);
+
+ CPP_OPTION (pfile, working_directory) = false;
+}
+
/* This is called at the end of preprocessing. It pops the last
buffer and writes dependency output, and returns the number of
errors.