#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 PARAMS ((void));
-static void mark_named_operators PARAMS ((cpp_reader *));
-static void read_original_filename PARAMS ((cpp_reader *));
-static void post_options PARAMS ((cpp_reader *));
+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
initialized, constant data. Otherwise, they have to be filled in at
#else
#define TRIGRAPH_MAP uchar _cpp_trigraph_map[UCHAR_MAX + 1] = { 0 }; \
- static void init_trigraph_map PARAMS ((void)) { \
+ static void init_trigraph_map (void) { \
unsigned char *x = _cpp_trigraph_map;
#define END }
char cplusplus;
char extended_numbers;
char std;
- char dollars_in_ident;
char cplusplus_comments;
char digraphs;
};
-/* ??? Enable $ in identifiers in assembly? */
static const struct lang_flags lang_defaults[] =
-{ /* c99 c++ xnum std dollar c++comm digr */
- /* GNUC89 */ { 0, 0, 1, 0, 1, 1, 1 },
- /* GNUC99 */ { 1, 0, 1, 0, 1, 1, 1 },
- /* STDC89 */ { 0, 0, 0, 1, 0, 0, 0 },
- /* STDC94 */ { 0, 0, 0, 1, 0, 0, 1 },
- /* STDC99 */ { 1, 0, 1, 1, 0, 1, 1 },
- /* GNUCXX */ { 0, 1, 1, 0, 1, 1, 1 },
- /* CXX98 */ { 0, 1, 1, 1, 0, 1, 1 },
- /* ASM */ { 0, 0, 1, 0, 0, 1, 0 }
+{ /* c99 c++ xnum std // digr */
+ /* GNUC89 */ { 0, 0, 1, 0, 1, 1 },
+ /* GNUC99 */ { 1, 0, 1, 0, 1, 1 },
+ /* STDC89 */ { 0, 0, 0, 1, 0, 0 },
+ /* STDC94 */ { 0, 0, 0, 1, 0, 1 },
+ /* STDC99 */ { 1, 0, 1, 1, 1, 1 },
+ /* GNUCXX */ { 0, 1, 1, 0, 1, 1 },
+ /* CXX98 */ { 0, 1, 1, 1, 1, 1 },
+ /* ASM */ { 0, 0, 1, 0, 1, 0 }
};
/* Sets internal flags correctly for a given language. */
void
-cpp_set_lang (pfile, lang)
- cpp_reader *pfile;
- enum c_lang lang;
+cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
{
const struct lang_flags *l = &lang_defaults[(int) lang];
CPP_OPTION (pfile, extended_numbers) = l->extended_numbers;
CPP_OPTION (pfile, std) = l->std;
CPP_OPTION (pfile, trigraphs) = l->std;
- CPP_OPTION (pfile, dollars_in_ident) = l->dollars_in_ident;
CPP_OPTION (pfile, cplusplus_comments) = l->cplusplus_comments;
CPP_OPTION (pfile, digraphs) = l->digraphs;
}
/* Initialize library global state. */
static void
-init_library ()
+init_library (void)
{
static int initialized = 0;
/* Initialize a cpp_reader structure. */
cpp_reader *
-cpp_create_reader (lang, table)
- enum c_lang lang;
- hash_table *table;
+cpp_create_reader (enum c_lang lang, hash_table *table)
{
cpp_reader *pfile;
/* 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, show_column) = 1;
CPP_OPTION (pfile, tabstop) = 8;
CPP_OPTION (pfile, operator_names) = 1;
+ CPP_OPTION (pfile, warn_trigraphs) = 2;
CPP_OPTION (pfile, warn_endif_labels) = 1;
CPP_OPTION (pfile, warn_deprecated) = 1;
CPP_OPTION (pfile, warn_long_long) = !CPP_OPTION (pfile, c99);
+ CPP_OPTION (pfile, dollars_in_ident) = 1;
+ CPP_OPTION (pfile, warn_dollars) = 1;
/* Default CPP arithmetic to something sensible for the host for the
benefit of dumb users like fix-header. */
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);
/* Free resources used by PFILE. Accessing PFILE after this function
returns leads to undefined behavior. Returns the error count. */
void
-cpp_destroy (pfile)
- cpp_reader *pfile;
+cpp_destroy (cpp_reader *pfile)
{
cpp_context *context, *contextn;
tokenrun *run, *runn;
if (pfile->macro_buffer)
{
- free ((PTR) pfile->macro_buffer);
+ free (pfile->macro_buffer);
pfile->macro_buffer = NULL;
pfile->macro_buffer_len = 0;
}
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);
}
/* Mark the C++ named operators in the hash table. */
static void
-mark_named_operators (pfile)
- cpp_reader *pfile;
+mark_named_operators (cpp_reader *pfile)
{
const struct builtin *b;
}
/* Read the builtins table above and enter them, and language-specific
- macros, into the hash table. */
+ macros, into the hash table. HOSTED is true if this is a hosted
+ environment. */
void
-cpp_init_builtins (pfile)
- cpp_reader *pfile;
+cpp_init_builtins (cpp_reader *pfile, int hosted)
{
const struct builtin *b;
size_t n = ARRAY_SIZE (builtin_array);
else if (CPP_OPTION (pfile, c99))
_cpp_define_builtin (pfile, "__STDC_VERSION__ 199901L");
+ if (hosted)
+ _cpp_define_builtin (pfile, "__STDC_HOSTED__ 1");
+ else
+ _cpp_define_builtin (pfile, "__STDC_HOSTED__ 0");
+
if (CPP_OPTION (pfile, objc))
_cpp_define_builtin (pfile, "__OBJC__ 1");
}
/* Sanity-checks are dependent on command-line options, so it is
called as a subroutine of cpp_read_main_file (). */
#if ENABLE_CHECKING
-static void sanity_checks PARAMS ((cpp_reader *));
-static void sanity_checks (pfile)
- cpp_reader *pfile;
+static void sanity_checks (cpp_reader *);
+static void sanity_checks (cpp_reader *pfile)
{
cppchar_t test = 0;
size_t max_precision = 2 * CHAR_BIT * sizeof (cpp_num_part);
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,
- "preprocessor arithmetic has maximum precision of %lu bits; target requires %lu bits",
+ 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 on this host cannot handle wide character constants over %lu bits, but the target requires %lu bits",
+ 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,
(unsigned long) CPP_OPTION (pfile, wchar_precision));
}
cpp_read_main_file(). If no targets have been added before
cpp_read_main_file(), then the default target is used. */
void
-cpp_add_dependency_target (pfile, target, quote)
- cpp_reader *pfile;
- const char *target;
- int quote;
+cpp_add_dependency_target (cpp_reader *pfile, const char *target, int quote)
{
if (!pfile->deps)
pfile->deps = deps_init ();
}
/* 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 (pfile, fname)
- 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.
generate file_change callbacks, which the front ends must handle
appropriately given their state of initialization. */
static void
-read_original_filename (pfile)
- cpp_reader *pfile;
+read_original_filename (cpp_reader *pfile)
{
const cpp_token *token, *token1;
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.
Maybe it should also reset state, such that you could call
cpp_start_read with a new filename to restart processing. */
int
-cpp_finish (pfile, deps_stream)
- cpp_reader *pfile;
- FILE *deps_stream;
+cpp_finish (cpp_reader *pfile, FILE *deps_stream)
{
/* Warn about unused macros before popping the final buffer. */
if (CPP_OPTION (pfile, warn_unused_macros))
}
static void
-post_options (pfile)
- cpp_reader *pfile;
+post_options (cpp_reader *pfile)
{
/* -Wtraditional is not useful in C++ mode. */
if (CPP_OPTION (pfile, cplusplus))
CPP_OPTION (pfile, traditional) = 0;
}
+ if (CPP_OPTION (pfile, warn_trigraphs) == 2)
+ CPP_OPTION (pfile, warn_trigraphs) = !CPP_OPTION (pfile, trigraphs);
+
if (CPP_OPTION (pfile, traditional))
{
/* Traditional CPP does not accurately track column information. */