/* Windows does not natively support inodes, and neither does MSDOS.
Cygwin's emulation can generate non-unique inodes, so don't use it.
- VMS has non-numeric inodes. */
+ VMS has non-numeric inodes. */
#ifdef VMS
-#define INO_T_EQ(a, b) (!memcmp (&(a), &(b), sizeof (a)))
-#elif (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__
-#define INO_T_EQ(a, b) 0
+# define INO_T_EQ(a, b) (!memcmp (&(a), &(b), sizeof (a)))
#else
-#define INO_T_EQ(a, b) ((a) == (b))
+# if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__
+# define INO_T_EQ(a, b) 0
+# else
+# define INO_T_EQ(a, b) ((a) == (b))
+# endif
#endif
/* Internal structures and prototypes. */
{
struct pending_option *directive_head, *directive_tail;
- struct file_name_list *quote_head, *quote_tail;
- struct file_name_list *brack_head, *brack_tail;
- struct file_name_list *systm_head, *systm_tail;
- struct file_name_list *after_head, *after_tail;
+ struct search_path *quote_head, *quote_tail;
+ struct search_path *brack_head, *brack_tail;
+ struct search_path *systm_head, *systm_tail;
+ struct search_path *after_head, *after_tail;
struct pending_option *imacros_head, *imacros_tail;
struct pending_option *include_head, *include_tail;
static void init_builtins PARAMS ((cpp_reader *));
static void append_include_chain PARAMS ((cpp_reader *,
char *, int, int));
-struct file_name_list * remove_dup_dir PARAMS ((cpp_reader *,
- struct file_name_list *));
-struct file_name_list * remove_dup_dirs PARAMS ((cpp_reader *,
- struct file_name_list *));
+static struct search_path * remove_dup_dir PARAMS ((cpp_reader *,
+ struct search_path *));
+static struct search_path * remove_dup_dirs PARAMS ((cpp_reader *,
+ struct search_path *));
static void merge_include_chains PARAMS ((cpp_reader *));
-static void do_includes PARAMS ((cpp_reader *,
- struct pending_option *,
- int));
+static bool push_include PARAMS ((cpp_reader *,
+ struct pending_option *));
+static void free_chain PARAMS ((struct pending_option *));
static void set_lang PARAMS ((cpp_reader *, enum c_lang));
static void init_dependency_output PARAMS ((cpp_reader *));
static void init_standard_includes PARAMS ((cpp_reader *));
static void output_deps PARAMS ((cpp_reader *));
static int parse_option PARAMS ((const char *));
-/* Fourth argument to append_include_chain: chain to use. */
-enum { QUOTE = 0, BRACKET, SYSTEM, AFTER };
+/* Fourth argument to append_include_chain: chain to use.
+ Note it's never asked to append to the quote chain. */
+enum { BRACKET = 0, SYSTEM, AFTER };
/* If we have designated initializers (GCC >2.7) these tables can be
initialized, constant data. Otherwise, they have to be filled in at
while (1);
}
-/* Append DIR to include path PATH. DIR must be permanently allocated
- and writable. */
+/* Append DIR to include path PATH. DIR must be allocated on the
+ heap; this routine takes responsibility for freeing it. */
static void
append_include_chain (pfile, dir, path, cxx_aware)
cpp_reader *pfile;
char *dir;
int path;
- int cxx_aware;
+ int cxx_aware ATTRIBUTE_UNUSED;
{
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
- struct file_name_list *new;
+ struct search_path *new;
struct stat st;
unsigned int len;
+ if (*dir == '\0')
+ {
+ free (dir);
+ dir = xstrdup (".");
+ }
_cpp_simplify_pathname (dir);
+
if (stat (dir, &st))
{
- /* Dirs that don't exist are silently ignored. */
+ /* Dirs that don't exist are silently ignored. */
if (errno != ENOENT)
cpp_notice_from_errno (pfile, dir);
else if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"), dir);
+ free (dir);
return;
}
if (!S_ISDIR (st.st_mode))
{
cpp_notice (pfile, "%s: Not a directory", dir);
+ free (dir);
return;
}
if (len > pfile->max_include_len)
pfile->max_include_len = len;
- new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
+ new = (struct search_path *) xmalloc (sizeof (struct search_path));
new->name = dir;
- new->nlen = len;
+ new->len = len;
new->ino = st.st_ino;
new->dev = st.st_dev;
- if (path == SYSTEM)
+ /* Both systm and after include file lists should be treated as system
+ include files since these two lists are really just a concatenation
+ of one "system" list. */
+ if (path == SYSTEM || path == AFTER)
+#ifdef NO_IMPLICIT_EXTERN_C
+ new->sysp = 1;
+#else
new->sysp = cxx_aware ? 1 : 2;
+#endif
else
new->sysp = 0;
new->name_map = NULL;
new->next = NULL;
- new->alloc = NULL;
switch (path)
{
- case QUOTE: APPEND (pend, quote, new); break;
case BRACKET: APPEND (pend, brack, new); break;
case SYSTEM: APPEND (pend, systm, new); break;
case AFTER: APPEND (pend, after, new); break;
/* Handle a duplicated include path. PREV is the link in the chain
before the duplicate. The duplicate is removed from the chain and
freed. Returns PREV. */
-struct file_name_list *
+static struct search_path *
remove_dup_dir (pfile, prev)
cpp_reader *pfile;
- struct file_name_list *prev;
+ struct search_path *prev;
{
- struct file_name_list *cur = prev->next;
+ struct search_path *cur = prev->next;
if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"), cur->name);
prev->next = cur->next;
- free (cur->name);
+ free ((PTR) cur->name);
free (cur);
return prev;
chain, or NULL if the chain is empty. This algorithm is quadratic
in the number of -I switches, which is acceptable since there
aren't usually that many of them. */
-struct file_name_list *
+static struct search_path *
remove_dup_dirs (pfile, head)
cpp_reader *pfile;
- struct file_name_list *head;
+ struct search_path *head;
{
- struct file_name_list *prev = NULL, *cur, *other;
+ struct search_path *prev = NULL, *cur, *other;
for (cur = head; cur; cur = cur->next)
{
for (other = head; other != cur; other = other->next)
if (INO_T_EQ (cur->ino, other->ino) && cur->dev == other->dev)
{
+ if (cur->sysp && !other->sysp)
+ {
+ cpp_warning (pfile,
+ "changing search order for system directory \"%s\"",
+ cur->name);
+ if (strcmp (cur->name, other->name))
+ cpp_warning (pfile,
+ " as it is the same as non-system directory \"%s\"",
+ other->name);
+ else
+ cpp_warning (pfile,
+ " as it has already been specified as a non-system directory");
+ }
cur = remove_dup_dir (pfile, prev);
break;
}
merge_include_chains (pfile)
cpp_reader *pfile;
{
- struct file_name_list *quote, *brack, *systm, *qtail;
+ struct search_path *quote, *brack, *systm, *qtail;
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
/* This is a bit tricky. First we drop dupes from the quote-include
list. Then we drop dupes from the bracket-include list.
Finally, if qtail and brack are the same directory, we cut out
- brack.
+ brack and move brack up to point to qtail.
We can't just merge the lists and then uniquify them because
then we may lose directories from the <> search path that should
brack = remove_dup_dir (pfile, qtail);
}
else
- quote = brack;
+ quote = brack;
CPP_OPTION (pfile, quote_include) = quote;
CPP_OPTION (pfile, bracket_include) = brack;
/* Sets internal flags correctly for a given language, and defines
macros if necessary. */
+
+struct lang_flags
+{
+ char c99;
+ char objc;
+ char cplusplus;
+ char extended_numbers;
+ char trigraphs;
+ char dollars_in_ident;
+ char cplusplus_comments;
+ char digraphs;
+};
+
+/* ??? Enable $ in identifiers in assembly? */
+static const struct lang_flags lang_defaults[] =
+{ /* c99 objc c++ xnum trig dollar c++comm digr */
+ /* GNUC89 */ { 0, 0, 0, 1, 0, 1, 1, 1 },
+ /* GNUC99 */ { 1, 0, 0, 1, 0, 1, 1, 1 },
+ /* STDC89 */ { 0, 0, 0, 0, 1, 0, 0, 0 },
+ /* STDC94 */ { 0, 0, 0, 0, 1, 0, 0, 1 },
+ /* STDC99 */ { 1, 0, 0, 1, 1, 0, 1, 1 },
+ /* GNUCXX */ { 0, 0, 1, 1, 0, 1, 1, 1 },
+ /* CXX98 */ { 0, 0, 1, 1, 1, 0, 1, 1 },
+ /* OBJC */ { 0, 1, 0, 1, 0, 1, 1, 1 },
+ /* OBJCXX */ { 0, 1, 1, 1, 0, 1, 1, 1 },
+ /* ASM */ { 0, 0, 0, 1, 0, 0, 1, 0 }
+};
+
static void
set_lang (pfile, lang)
cpp_reader *pfile;
enum c_lang lang;
{
- struct cpp_pending *pend = CPP_OPTION (pfile, pending);
-
- /* Defaults. */
+ const struct lang_flags *l = &lang_defaults[(int) lang];
+
CPP_OPTION (pfile, lang) = lang;
- CPP_OPTION (pfile, objc) = 0;
- CPP_OPTION (pfile, cplusplus) = 0;
- CPP_OPTION (pfile, extended_numbers) = 1; /* Allowed in GNU C and C99. */
-
- switch (lang)
- {
- /* GNU C. */
- case CLK_GNUC99:
- CPP_OPTION (pfile, trigraphs) = 0;
- CPP_OPTION (pfile, dollars_in_ident) = 1;
- CPP_OPTION (pfile, cplusplus_comments) = 1;
- CPP_OPTION (pfile, digraphs) = 1;
- CPP_OPTION (pfile, c99) = 1;
- new_pending_directive (pend, "__STDC_VERSION__=199901L", cpp_define);
- break;
- case CLK_GNUC89:
- CPP_OPTION (pfile, trigraphs) = 0;
- CPP_OPTION (pfile, dollars_in_ident) = 1;
- CPP_OPTION (pfile, cplusplus_comments) = 1;
- CPP_OPTION (pfile, digraphs) = 1;
- CPP_OPTION (pfile, c99) = 0;
- break;
-
- /* ISO C. */
- case CLK_STDC94:
- new_pending_directive (pend, "__STDC_VERSION__=199409L", cpp_define);
- case CLK_STDC89:
- CPP_OPTION (pfile, trigraphs) = 1;
- CPP_OPTION (pfile, dollars_in_ident) = 0;
- CPP_OPTION (pfile, cplusplus_comments) = 0;
- CPP_OPTION (pfile, digraphs) = lang == CLK_STDC94;
- CPP_OPTION (pfile, c99) = 0;
- CPP_OPTION (pfile, extended_numbers) = 0;
- new_pending_directive (pend, "__STRICT_ANSI__", cpp_define);
- break;
- case CLK_STDC99:
- CPP_OPTION (pfile, trigraphs) = 1;
- CPP_OPTION (pfile, dollars_in_ident) = 0;
- CPP_OPTION (pfile, cplusplus_comments) = 1;
- CPP_OPTION (pfile, digraphs) = 1;
- CPP_OPTION (pfile, c99) = 1;
- new_pending_directive (pend, "__STRICT_ANSI__", cpp_define);
- new_pending_directive (pend, "__STDC_VERSION__=199901L", cpp_define);
- break;
- /* Objective C. */
- case CLK_OBJCXX:
- new_pending_directive (pend, "__cplusplus", cpp_define);
- CPP_OPTION (pfile, cplusplus) = 1;
- case CLK_OBJC:
- CPP_OPTION (pfile, trigraphs) = 0;
- CPP_OPTION (pfile, dollars_in_ident) = 1;
- CPP_OPTION (pfile, cplusplus_comments) = 1;
- CPP_OPTION (pfile, digraphs) = 1;
- CPP_OPTION (pfile, c99) = 0;
- CPP_OPTION (pfile, objc) = 1;
- new_pending_directive (pend, "__OBJC__", cpp_define);
- break;
-
- /* C++. */
- case CLK_GNUCXX:
- case CLK_CXX98:
- CPP_OPTION (pfile, cplusplus) = 1;
- CPP_OPTION (pfile, trigraphs) = lang == CLK_CXX98;
- CPP_OPTION (pfile, dollars_in_ident) = lang == CLK_GNUCXX;
- CPP_OPTION (pfile, cplusplus_comments) = 1;
- CPP_OPTION (pfile, digraphs) = 1;
- CPP_OPTION (pfile, c99) = 0;
- new_pending_directive (pend, "__cplusplus", cpp_define);
- break;
-
- /* Assembler. */
- case CLK_ASM:
- CPP_OPTION (pfile, trigraphs) = 0;
- CPP_OPTION (pfile, dollars_in_ident) = 0; /* Maybe not? */
- CPP_OPTION (pfile, cplusplus_comments) = 1;
- CPP_OPTION (pfile, digraphs) = 0;
- CPP_OPTION (pfile, c99) = 0;
- new_pending_directive (pend, "__ASSEMBLER__", cpp_define);
- break;
- }
+ CPP_OPTION (pfile, c99) = l->c99;
+ CPP_OPTION (pfile, objc) = l->objc;
+ CPP_OPTION (pfile, cplusplus) = l->cplusplus;
+ CPP_OPTION (pfile, extended_numbers) = l->extended_numbers;
+ CPP_OPTION (pfile, trigraphs) = l->trigraphs;
+ CPP_OPTION (pfile, dollars_in_ident) = l->dollars_in_ident;
+ CPP_OPTION (pfile, cplusplus_comments) = l->cplusplus_comments;
+ CPP_OPTION (pfile, digraphs) = l->digraphs;
}
#ifdef HOST_EBCDIC
}
}
-/* Initialize a cpp_reader structure. */
+/* Initialize a cpp_reader structure. */
cpp_reader *
-cpp_create_reader (lang)
+cpp_create_reader (table, lang)
+ hash_table *table;
enum c_lang lang;
{
struct spec_nodes *s;
pfile = (cpp_reader *) xcalloc (1, sizeof (cpp_reader));
+ set_lang (pfile, lang);
CPP_OPTION (pfile, warn_import) = 1;
CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, show_column) = 1;
CPP_OPTION (pfile, pending) =
(struct cpp_pending *) xcalloc (1, sizeof (struct cpp_pending));
- /* After creating pfile->pending. */
- set_lang (pfile, lang);
-
/* It's simplest to just create this struct whether or not it will
be needed. */
pfile->deps = deps_init ();
+ /* Initialise the line map. */
+ init_line_maps (&pfile->line_maps);
+
/* Initialize lexer state. */
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
/* Indicate date and time not yet calculated. */
pfile->date.type = CPP_EOF;
+ /* Create a token buffer for the lexer. */
+ _cpp_init_tokenrun (&pfile->base_run, 250);
+ pfile->cur_run = &pfile->base_run;
+ pfile->cur_token = pfile->base_run.base;
+
/* Initialise the base context. */
pfile->context = &pfile->base_context;
pfile->base_context.macro = 0;
/* Macro pool initially 8K. Aligned, permanent pool. */
_cpp_init_pool (&pfile->macro_pool, 8 * 1024, 0, 0);
- _cpp_init_hashtable (pfile);
- _cpp_init_stacks (pfile);
+ /* Initialise the buffer obstack. */
+ gcc_obstack_init (&pfile->buffer_ob);
+
+ /* Initialise the hashtable. */
+ _cpp_init_hashtable (pfile, table);
+
+ _cpp_init_directives (pfile);
_cpp_init_includes (pfile);
_cpp_init_internal_pragmas (pfile);
s = &pfile->spec_nodes;
s->n_L = cpp_lookup (pfile, DSC("L"));
s->n_defined = cpp_lookup (pfile, DSC("defined"));
+ s->n_true = cpp_lookup (pfile, DSC("true"));
+ s->n_false = cpp_lookup (pfile, DSC("false"));
s->n__Pragma = cpp_lookup (pfile, DSC("_Pragma"));
s->n__STRICT_ANSI__ = cpp_lookup (pfile, DSC("__STRICT_ANSI__"));
s->n__CHAR_UNSIGNED__ = cpp_lookup (pfile, DSC("__CHAR_UNSIGNED__"));
return pfile;
}
-/* Free resources used by PFILE.
- This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology). */
-void
-cpp_cleanup (pfile)
+/* Free resources used by PFILE. Accessing PFILE after this function
+ returns leads to undefined behaviour. */
+int
+cpp_destroy (pfile)
cpp_reader *pfile;
{
- struct file_name_list *dir, *dirn;
+ int result;
+ struct search_path *dir, *dirn;
cpp_context *context, *contextn;
while (CPP_BUFFER (pfile) != NULL)
- cpp_pop_buffer (pfile);
+ _cpp_pop_buffer (pfile);
if (pfile->macro_buffer)
{
}
deps_free (pfile->deps);
+ obstack_free (&pfile->buffer_ob, 0);
+ _cpp_destroy_hashtable (pfile);
_cpp_cleanup_includes (pfile);
- _cpp_cleanup_stacks (pfile);
- _cpp_cleanup_hashtable (pfile);
-
- _cpp_free_lookaheads (pfile);
_cpp_free_pool (&pfile->ident_pool);
_cpp_free_pool (&pfile->macro_pool);
for (dir = CPP_OPTION (pfile, quote_include); dir; dir = dirn)
{
dirn = dir->next;
- free (dir->name);
+ free ((PTR) dir->name);
free (dir);
}
contextn = context->next;
free (context);
}
+
+ free_line_maps (&pfile->line_maps);
+
+ result = pfile->errors;
+ free (pfile);
+
+ return result;
}
/* This structure defines one built-in identifier. A node will be
entered in the hash table under the name NAME, with value VALUE (if
any). If flags has OPERATOR, the node's operator field is used; if
- flags has BUILTIN the node's builtin field is used.
+ flags has BUILTIN the node's builtin field is used. Macros that are
+ known at build time should not be flagged BUILTIN, as then they do
+ not appear in macro dumps with e.g. -dM or -dD.
Two values are not compile time constants, so we tag
them in the FLAGS field instead:
B("__BASE_FILE__", BT_BASE_FILE),
B("__LINE__", BT_SPECLINE),
B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL),
- B("__STDC__", BT_STDC),
X("__VERSION__", VERS),
X("__USER_LABEL_PREFIX__", ULP),
#ifndef NO_BUILTIN_WINT_TYPE
C("__WINT_TYPE__", WINT_TYPE),
#endif
+#ifdef STDC_0_IN_SYSTEM_HEADERS
+ B("__STDC__", BT_STDC),
+#else
+ C("__STDC__", "1"),
+#endif
/* Named operators known to the preprocessor. These cannot be #defined
and always have their stated meaning. They are treated like normal
else
{
hp->type = NT_MACRO;
- hp->flags |= NODE_BUILTIN;
+ hp->flags |= NODE_BUILTIN | NODE_WARN;
hp->value.builtin = b->builtin;
}
}
_cpp_define_builtin (pfile, str);
}
}
+
+ if (CPP_OPTION (pfile, cplusplus))
+ {
+ _cpp_define_builtin (pfile, "__cplusplus 1");
+ if (SUPPORTS_ONE_ONLY)
+ _cpp_define_builtin (pfile, "__GXX_WEAK__ 1");
+ else
+ _cpp_define_builtin (pfile, "__GXX_WEAK__ 0");
+ }
+ if (CPP_OPTION (pfile, objc))
+ _cpp_define_builtin (pfile, "__OBJC__ 1");
+
+ if (CPP_OPTION (pfile, lang) == CLK_STDC94)
+ _cpp_define_builtin (pfile, "__STDC_VERSION__ 199409L");
+ else if (CPP_OPTION (pfile, c99))
+ _cpp_define_builtin (pfile, "__STDC_VERSION__ 199901L");
+
+ if (CPP_OPTION (pfile, lang) == CLK_STDC89
+ || CPP_OPTION (pfile, lang) == CLK_STDC94
+ || CPP_OPTION (pfile, lang) == CLK_STDC99)
+ _cpp_define_builtin (pfile, "__STRICT_ANSI__ 1");
+ else if (CPP_OPTION (pfile, lang) == CLK_ASM)
+ _cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
}
#undef BUILTIN
#undef OPERATOR
if (specd_prefix != 0 && cpp_GCC_INCLUDE_DIR_len)
{
/* Remove the `include' from /usr/local/lib/gcc.../include.
- GCC_INCLUDE_DIR will always end in /include. */
+ GCC_INCLUDE_DIR will always end in /include. */
int default_len = cpp_GCC_INCLUDE_DIR_len;
char *default_prefix = (char *) alloca (default_len + 1);
int specd_len = strlen (specd_prefix);
|| (CPP_OPTION (pfile, cplusplus)
&& !CPP_OPTION (pfile, no_standard_cplusplus_includes)))
{
- char *str = xstrdup (update_path (p->fname, p->component));
+ char *str = update_path (p->fname, p->component);
append_include_chain (pfile, str, SYSTEM, p->cxx_aware);
}
}
}
-/* Handles -imacro and -include from the command line. */
-static void
-do_includes (pfile, p, scan)
+/* Pushes a -imacro and -include file given on the command line onto
+ the buffer stack. Returns non-zero if successful. */
+static bool
+push_include (pfile, p)
cpp_reader *pfile;
struct pending_option *p;
- int scan;
{
- while (p)
+ cpp_token header;
+
+ /* Later: maybe update this to use the #include "" search path
+ if cpp_read_file fails. */
+ header.type = CPP_STRING;
+ header.val.str.text = (const unsigned char *) p->arg;
+ header.val.str.len = strlen (p->arg);
+ /* Make the command line directive take up a line. */
+ pfile->lexer_pos.line = pfile->lexer_pos.output_line = ++pfile->line;
+
+ return _cpp_execute_include (pfile, &header, IT_CMDLINE);
+}
+
+/* Frees a pending_option chain. */
+static void
+free_chain (head)
+ struct pending_option *head;
+{
+ struct pending_option *next;
+
+ while (head)
{
- struct pending_option *q;
-
- /* Don't handle if -fpreprocessed. Later: maybe update this to
- use the #include "" search path if cpp_read_file fails. */
- if (CPP_OPTION (pfile, preprocessed))
- cpp_error (pfile, "-include and -imacros cannot be used with -fpreprocessed");
- else if (_cpp_read_file (pfile, p->arg) && scan)
- cpp_scan_buffer_nooutput (pfile, 0);
- q = p->next;
- free (p);
- p = q;
+ next = head->next;
+ free (head);
+ head = next;
}
}
/* This is called after options have been processed. Setup for
- processing input from the file named FNAME. (Use standard input if
- FNAME == NULL.) Return 1 on success, 0 on failure. */
-
+ processing input from the file named FNAME, or stdin if it is the
+ empty string. Return 1 on success, 0 on failure. */
int
cpp_start_read (pfile, fname)
cpp_reader *pfile;
const char *fname;
{
- struct pending_option *p, *q;
-
/* Set up the include search path now. */
if (! CPP_OPTION (pfile, no_standard_includes))
init_standard_includes (pfile);
/* With -v, print the list of dirs to search. */
if (CPP_OPTION (pfile, verbose))
{
- struct file_name_list *l;
+ struct search_path *l;
fprintf (stderr, _("#include \"...\" search starts here:\n"));
for (l = CPP_OPTION (pfile, quote_include); l; l = l->next)
{
fprintf (stderr, _("End of search list.\n"));
}
- if (CPP_OPTION (pfile, in_fname) == NULL
- || *CPP_OPTION (pfile, in_fname) == 0)
- {
- CPP_OPTION (pfile, in_fname) = fname;
- if (CPP_OPTION (pfile, in_fname) == NULL)
- CPP_OPTION (pfile, in_fname) = "";
- }
- if (CPP_OPTION (pfile, out_fname) == NULL)
- CPP_OPTION (pfile, out_fname) = "";
-
if (CPP_OPTION (pfile, print_deps))
- {
- /* Set the default target (if there is none already), and
- the dependency on the main file. */
- deps_add_default_target (pfile->deps, CPP_OPTION (pfile, in_fname));
-
- deps_add_dep (pfile->deps, CPP_OPTION (pfile, in_fname));
- }
+ /* Set the default target (if there is none already). */
+ deps_add_default_target (pfile->deps, fname);
/* Open the main input file. This must be done early, so we have a
buffer to stand on. */
if (!_cpp_read_file (pfile, fname))
return 0;
- /* If already preprocessed, don't install __LINE__, etc., and ignore
- command line definitions and assertions. Handle -U's, -D's and
- -A's in the order they were seen. */
- if (! CPP_OPTION (pfile, preprocessed))
- init_builtins (pfile);
+ /* Set this after cpp_post_options 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);
- p = CPP_OPTION (pfile, pending)->directive_head;
- while (p)
+ /* Install builtins and process command line macros etc. in the order
+ they appeared, but only if not already preprocessed. */
+ if (! CPP_OPTION (pfile, preprocessed))
{
- if (! CPP_OPTION (pfile, preprocessed))
+ struct pending_option *p;
+
+ _cpp_do_file_change (pfile, LC_RENAME, _("<builtin>"), 1, 0);
+ init_builtins (pfile);
+ _cpp_do_file_change (pfile, LC_RENAME, _("<command line>"), 1, 0);
+ for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next)
(*p->handler) (pfile, p->arg);
- q = p->next;
- free (p);
- p = q;
+
+ /* Scan -imacros files after command line defines, but before
+ files given with -include. */
+ while ((p = CPP_OPTION (pfile, pending)->imacros_head) != NULL)
+ {
+ if (push_include (pfile, p))
+ {
+ pfile->buffer->return_at_eof = true;
+ cpp_scan_nooutput (pfile);
+ }
+ CPP_OPTION (pfile, pending)->imacros_head = p->next;
+ free (p);
+ }
}
- pfile->done_initializing = 1;
+ free_chain (CPP_OPTION (pfile, pending)->directive_head);
+ _cpp_push_next_buffer (pfile);
- /* The -imacros files can be scanned now, but the -include files
- have to be pushed onto the buffer stack and processed later,
- otherwise cppmain.c won't see the tokens. include_head was built
- up as a stack, and popping this stack onto the buffer stack means
- we preserve the order of the command line. */
- do_includes (pfile, CPP_OPTION (pfile, pending)->imacros_head, 1);
- do_includes (pfile, CPP_OPTION (pfile, pending)->include_head, 0);
+ return 1;
+}
- free (CPP_OPTION (pfile, pending));
- CPP_OPTION (pfile, pending) = NULL;
+/* Called to push the next buffer on the stack given by -include. If
+ there are none, free the pending structure and restore the line map
+ for the main file. */
+bool
+_cpp_push_next_buffer (pfile)
+ cpp_reader *pfile;
+{
+ bool pushed = false;
+
+ /* This is't pretty; we'd rather not be relying on this as a boolean
+ for reverting the line map. Further, we only free the chains in
+ this conditional, so an early call to cpp_finish / cpp_destroy
+ will leak that memory. */
+ if (CPP_OPTION (pfile, pending)
+ && CPP_OPTION (pfile, pending)->imacros_head == NULL)
+ {
+ while (!pushed)
+ {
+ struct pending_option *p = CPP_OPTION (pfile, pending)->include_head;
- return 1;
+ if (p == NULL)
+ break;
+ if (! CPP_OPTION (pfile, preprocessed))
+ pushed = push_include (pfile, p);
+ CPP_OPTION (pfile, pending)->include_head = p->next;
+ free (p);
+ }
+
+ if (!pushed)
+ {
+ free (CPP_OPTION (pfile, pending));
+ CPP_OPTION (pfile, pending) = NULL;
+
+ /* Restore the line map for the main file. */
+ if (! CPP_OPTION (pfile, preprocessed))
+ _cpp_do_file_change (pfile, LC_RENAME,
+ pfile->line_maps.maps[0].to_file, 1, 0);
+ }
+ }
+
+ return pushed;
}
/* Use mkdeps.c to output dependency information. */
{
/* Stream on which to print the dependency information. */
FILE *deps_stream = 0;
- const char *deps_mode = CPP_OPTION (pfile, print_deps_append) ? "a" : "w";
+ const char *const deps_mode =
+ CPP_OPTION (pfile, print_deps_append) ? "a" : "w";
if (CPP_OPTION (pfile, deps_file) == 0)
deps_stream = stdout;
cpp_finish (pfile)
cpp_reader *pfile;
{
- if (CPP_BUFFER (pfile))
- {
- cpp_ice (pfile, "buffers still stacked in cpp_finish");
- while (CPP_BUFFER (pfile))
- cpp_pop_buffer (pfile);
- }
+ /* cpplex.c leaves the final buffer on the stack. This it so that
+ it returns an unending stream of CPP_EOFs to the client. If we
+ popped the buffer, we'd derefence a NULL buffer pointer and
+ segfault. It's nice to allow the client to do worry-free excess
+ cpp_get_token calls. */
+ while (pfile->buffer)
+ _cpp_pop_buffer (pfile);
/* Don't write the deps file if preprocessing has failed. */
if (CPP_OPTION (pfile, print_deps) && pfile->errors == 0)
/* This is the list of all command line options, with the leading
"-" removed. It must be sorted in ASCII collating order. */
#define COMMAND_LINE_OPTIONS \
- DEF_OPT("", 0, OPT_stdin_stdout) \
DEF_OPT("$", 0, OPT_dollar) \
DEF_OPT("+", 0, OPT_plus) \
DEF_OPT("-help", 0, OPT__help) \
Otherwise, return the longest option-accepting match.
This loops no more than twice with current options. */
mx = md;
- for (; mn < N_OPTS; mn++)
+ for (; mn < (unsigned int) N_OPTS; mn++)
{
opt_len = cl_options[mn].opt_len;
if (memcmp (input, cl_options[mn].opt_text, opt_len))
int i = 0;
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
- if (argv[i][0] != '-')
+ /* Interpret "-" or a non-option as a file name. */
+ if (argv[i][0] != '-' || argv[i][1] == '\0')
{
- if (CPP_OPTION (pfile, out_fname) != NULL)
- cpp_fatal (pfile, "Too many arguments. Type %s --help for usage info",
- progname);
- else if (CPP_OPTION (pfile, in_fname) != NULL)
+ if (CPP_OPTION (pfile, in_fname) == NULL)
+ CPP_OPTION (pfile, in_fname) = argv[i];
+ else if (CPP_OPTION (pfile, out_fname) == NULL)
CPP_OPTION (pfile, out_fname) = argv[i];
else
- CPP_OPTION (pfile, in_fname) = argv[i];
+ cpp_fatal (pfile, "Too many filenames. Type %s --help for usage info",
+ progname);
}
else
{
case OPT_h:
case OPT__help:
print_help ();
- pfile->help_only = 1;
+ CPP_OPTION (pfile, help_only) = 1;
break;
case OPT_target__help:
/* Print if any target specific options. cpplib has none, but
make sure help_only gets set. */
- pfile->help_only = 1;
+ CPP_OPTION (pfile, help_only) = 1;
break;
/* --version inhibits compilation, -version doesn't. -v means
verbose and -version. Historical reasons, don't ask. */
case OPT__version:
- pfile->help_only = 1;
- goto version;
+ CPP_OPTION (pfile, help_only) = 1;
+ pfile->print_version = 1;
+ break;
case OPT_v:
CPP_OPTION (pfile, verbose) = 1;
- goto version;
-
+ pfile->print_version = 1;
+ break;
case OPT_version:
- version:
- fprintf (stderr, _("GNU CPP version %s (cpplib)"), version_string);
-#ifdef TARGET_VERSION
- TARGET_VERSION;
-#endif
- fputc ('\n', stderr);
+ pfile->print_version = 1;
break;
case OPT_C:
CPP_OPTION (pfile, no_standard_includes) = 1;
break;
case OPT_nostdincplusplus:
- /* -nostdinc++ causes no default C++-specific include directories. */
+ /* -nostdinc++ causes no default C++-specific include directories. */
CPP_OPTION (pfile, no_standard_cplusplus_includes) = 1;
break;
case OPT_o:
- if (CPP_OPTION (pfile, out_fname) != NULL)
+ if (CPP_OPTION (pfile, out_fname) == NULL)
+ CPP_OPTION (pfile, out_fname) = arg;
+ else
{
cpp_fatal (pfile, "Output filename specified twice");
return argc;
}
- CPP_OPTION (pfile, out_fname) = arg;
- if (!strcmp (CPP_OPTION (pfile, out_fname), "-"))
- CPP_OPTION (pfile, out_fname) = "";
- break;
- case OPT_stdin_stdout:
- /* JF handle '-' as file name meaning stdin or stdout. */
- if (CPP_OPTION (pfile, in_fname) == NULL)
- CPP_OPTION (pfile, in_fname) = "";
- else if (CPP_OPTION (pfile, out_fname) == NULL)
- CPP_OPTION (pfile, out_fname) = "";
break;
case OPT_d:
/* Args to -d specify what parts of macros to dump.
if (arg[1] == '\0')
{
- struct pending_option *o1, *o2;
-
- o1 = pend->directive_head;
- while (o1)
- {
- o2 = o1->next;
- free (o1);
- o1 = o2;
- }
+ free_chain (pend->directive_head);
pend->directive_head = NULL;
pend->directive_tail = NULL;
}
append_include_chain (pfile, xstrdup (arg), SYSTEM, 0);
break;
case OPT_include:
- {
- struct pending_option *o = (struct pending_option *)
- xmalloc (sizeof (struct pending_option));
- o->arg = arg;
-
- /* This list has to be built in reverse order so that
- when cpp_start_read pushes all the -include files onto
- the buffer stack, they will be scanned in forward order. */
- o->next = pend->include_head;
- pend->include_head = o;
- }
- break;
case OPT_imacros:
{
struct pending_option *o = (struct pending_option *)
o->arg = arg;
o->next = NULL;
- APPEND (pend, imacros, o);
+ if (opt_code == OPT_include)
+ APPEND (pend, include, o);
+ else
+ APPEND (pend, imacros, o);
}
break;
case OPT_iwithprefix:
cpp_post_options (pfile)
cpp_reader *pfile;
{
+ if (pfile->print_version)
+ {
+ fprintf (stderr, _("GNU CPP version %s (cpplib)"), version_string);
+#ifdef TARGET_VERSION
+ TARGET_VERSION;
+#endif
+ fputc ('\n', stderr);
+ }
+
+ /* Canonicalize in_fname and out_fname. We guarantee they are not
+ NULL, and that the empty string represents stdin / stdout. */
+ if (CPP_OPTION (pfile, in_fname) == NULL
+ || !strcmp (CPP_OPTION (pfile, in_fname), "-"))
+ CPP_OPTION (pfile, in_fname) = "";
+
+ if (CPP_OPTION (pfile, out_fname) == NULL
+ || !strcmp (CPP_OPTION (pfile, out_fname), "-"))
+ CPP_OPTION (pfile, out_fname) = "";
+
/* -Wtraditional is not useful in C++ mode. */
if (CPP_OPTION (pfile, cplusplus))
CPP_OPTION (pfile, warn_traditional) = 0;
- /* Set this if it hasn't been set already. */
+ /* Set this if it hasn't been set already. */
if (CPP_OPTION (pfile, user_label_prefix) == NULL)
CPP_OPTION (pfile, user_label_prefix) = USER_LABEL_PREFIX;
+ /* Permanently disable macro expansion if we are rescanning
+ preprocessed text. */
+ if (CPP_OPTION (pfile, preprocessed))
+ pfile->state.prevent_expansion = 1;
+
/* We need to do this after option processing and before
cpp_start_read, as cppmain.c relies on the options->no_output to
set its callbacks correctly before calling cpp_start_read. */
}
/* If dependencies go to standard output, or -MG is used, we should
- suppress output. The user may be requesting other stuff to
- stdout, with -dM, -v etc. We let them shoot themselves in the
- foot. */
+ suppress output, including -dM, -dI etc. */
if (CPP_OPTION (pfile, deps_file) == 0
|| CPP_OPTION (pfile, print_deps_missing_files))
- CPP_OPTION (pfile, no_output) = 1;
+ {
+ CPP_OPTION (pfile, no_output) = 1;
+ CPP_OPTION (pfile, dump_macros) = 0;
+ CPP_OPTION (pfile, dump_includes) = 0;
+ }
}
static void
{
fprintf (stderr, _("Usage: %s [switches] input output\n"), progname);
/* To keep the lines from getting too long for some compilers, limit
- to about 500 characters (6 lines) per chunk. */
+ to about 500 characters (6 lines) per chunk. */
fputs (_("\
Switches:\n\
-include <file> Include the contents of <file> before other files\n\
-dI Include #include directives in the output\n\
"), stdout);
fputs (_("\
+ -fpreprocessed Treat the input file as already preprocessed\n\
-ftabstop=<number> Distance between tab stops for column reporting\n\
-P Do not generate #line directives\n\
-$ Do not allow '$' in identifiers\n\