#include "config.h"
#include "system.h"
#include "cpplib.h"
#include "cpphash.h"
#include "prefix.h"
#include "intl.h"
#include "version.h"
#include "mkdeps.h"
#include "cppdefault.h"
#include "except.h"
#include <ctype.h>
#ifdef PFE
#include "pfe/pfe.h"
#include "pfe/pfe-header.h"
#endif
extern int flag_cpp_precomp;
#ifdef FRAMEWORK_HEADERS
struct { char *path; int u1; }
framework_paths_defaults_array [] = {
{"/System/Library/Frameworks", 0},
{"/Library/Frameworks", 0},
{"/Local/Library/Frameworks", 0},
{NULL, 0}
};
#endif
#ifndef GET_ENV_PATH_LIST
#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
#ifdef VMS
# define INO_T_EQ(A, B) (!memcmp (&(A), &(B), sizeof (A)))
# define INO_T_COPY(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof (SRC))
#else
# if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__
# define INO_T_EQ(A, B) 0
# else
# define INO_T_EQ(A, B) ((A) == (B))
# endif
# define INO_T_COPY(DEST, SRC) (DEST) = (SRC)
#endif
typedef void (* cl_directive_handler) PARAMS ((cpp_reader *, const char *));
struct pending_option
{
struct pending_option *next;
const char *arg;
cl_directive_handler handler;
};
struct cpp_pending
{
struct pending_option *directive_head, *directive_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;
#ifdef FRAMEWORK_HEADERS
struct search_path *framework_system_head, *framework_system_tail;
struct search_path *framework_head, *framework_tail;
#endif
struct pending_option *imacros_head, *imacros_tail;
struct pending_option *include_head, *include_tail;
};
#ifdef __STDC__
#define APPEND(pend, list, elt) \
do { if (!(pend)->list##_head) (pend)->list##_head = (elt); \
else (pend)->list##_tail->next = (elt); \
(pend)->list##_tail = (elt); \
} while (0)
#else
#define APPEND(pend, list, elt) \
do { if (!(pend)->list_head) (pend)->list_head = (elt); \
else (pend)->list_tail->next = (elt); \
(pend)->list_tail = (elt); \
} while (0)
#endif
static void print_help PARAMS ((void));
static void path_include PARAMS ((cpp_reader *,
char *, int));
static void init_library PARAMS ((void));
static void init_builtins PARAMS ((cpp_reader *));
static void append_include_chain PARAMS ((cpp_reader *,
char *, int, int));
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 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 read_original_filename PARAMS ((cpp_reader *));
static void new_pending_directive PARAMS ((struct cpp_pending *,
const char *,
cl_directive_handler));
static void output_deps PARAMS ((cpp_reader *));
static int parse_option PARAMS ((const char *));
static inline uint32 hmap_hash_string PARAMS ((const char *));
static inline unsigned hmap_compare_strings PARAMS ((const char *,
const char *));
static struct hmap_header_map * hmap_load_header_map PARAMS ((const char *));
static void hmap_free_header_map PARAMS ((cpp_reader *));
static FILE *ilog_open PARAMS ((const char *));
static void ilog_close PARAMS ((cpp_reader *));
enum { BRACKET = 0, SYSTEM, AFTER, FRAMEWORK, FRAMEWORK_SYSTEM, HMAPFILE };
#if HAVE_DESIGNATED_INITIALIZERS
#define init_trigraph_map()
#define TRIGRAPH_MAP \
__extension__ const U_CHAR _cpp_trigraph_map[UCHAR_MAX + 1] = {
#define END };
#define s(p, v) [p] = v,
#else
#define TRIGRAPH_MAP U_CHAR _cpp_trigraph_map[UCHAR_MAX + 1] = { 0 }; \
static void init_trigraph_map PARAMS ((void)) { \
unsigned char *x = _cpp_trigraph_map;
#define END }
#define s(p, v) x[p] = v;
#endif
TRIGRAPH_MAP
s('=', '#') s(')', ']') s('!', '|')
s('(', '[') s('\'', '^') s('>', '}')
s('/', '\\') s('<', '{') s('-', '~')
END
#undef s
#undef END
#undef TRIGRAPH_MAP
static void
path_include (pfile, list, path)
cpp_reader *pfile;
char *list;
int path;
{
char *p, *q, *name;
p = list;
do
{
q = p;
while (*q != 0 && *q != PATH_SEPARATOR) q++;
if (q == p)
{
name = (char *) xmalloc (2);
name[0] = '.';
name[1] = 0;
}
else
{
name = (char *) xmalloc (q - p + 1);
memcpy (name, p, q - p);
name[q - p] = 0;
}
append_include_chain (pfile, name, path, 0);
if (*q == 0)
break;
p = q + 1;
}
while (1);
}
static void
append_include_chain (pfile, dir, path, cxx_aware)
cpp_reader *pfile;
char *dir;
int path;
int cxx_aware ATTRIBUTE_UNUSED;
{
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
struct search_path *new;
struct stat st;
unsigned int len;
if (path == HMAPFILE && CPP_OPTION (pfile, hmap_path))
{
free (CPP_OPTION (pfile, hmap_path));
CPP_OPTION (pfile, hmap_path) = 0;
}
if (*dir == '\0')
{
free (dir);
dir = xstrdup (".");
}
_cpp_simplify_pathname (dir);
if (stat (dir, &st))
{
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;
}
len = strlen (dir);
if (len > pfile->max_include_len)
pfile->max_include_len = len;
new = (struct search_path *) xmalloc (sizeof (struct search_path));
new->name = dir;
new->len = len;
INO_T_COPY (new->ino, st.st_ino);
new->dev = st.st_dev;
#ifdef FRAMEWORK_HEADERS
if (path == SYSTEM || path == AFTER || path == FRAMEWORK_SYSTEM)
#else
if (path == SYSTEM || path == AFTER)
#endif
#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;
switch (path)
{
case BRACKET: APPEND (pend, brack, new); break;
case SYSTEM: APPEND (pend, systm, new); break;
case AFTER: APPEND (pend, after, new); break;
#ifdef FRAMEWORK_HEADERS
case FRAMEWORK_SYSTEM: APPEND (pend, framework_system, new); break;
case FRAMEWORK: APPEND (pend, framework, new); break;
#endif
case HMAPFILE:
new->next = CPP_OPTION (pfile, bracket_include);
CPP_OPTION (pfile, hmap_path) = new;
break;
}
}
static struct search_path *
remove_dup_dir (pfile, prev)
cpp_reader *pfile;
struct search_path *prev;
{
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 ((PTR) cur->name);
free (cur);
return prev;
}
static struct search_path *
remove_dup_dirs (pfile, head)
cpp_reader *pfile;
struct search_path *head;
{
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;
}
prev = cur;
}
return prev;
}
static void
merge_include_chains (pfile)
cpp_reader *pfile;
{
struct search_path *quote, *brack, *systm, *qtail;
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
quote = pend->quote_head;
brack = pend->brack_head;
systm = pend->systm_head;
qtail = pend->quote_tail;
if (systm)
pend->systm_tail->next = pend->after_head;
else
systm = pend->after_head;
if (brack)
pend->brack_tail->next = systm;
else
brack = systm;
remove_dup_dirs (pfile, brack);
qtail = remove_dup_dirs (pfile, quote);
if (quote)
{
qtail->next = brack;
if (brack && INO_T_EQ (qtail->ino, brack->ino)
&& qtail->dev == brack->dev)
brack = remove_dup_dir (pfile, qtail);
}
else
quote = brack;
CPP_OPTION (pfile, quote_include) = quote;
CPP_OPTION (pfile, bracket_include) = brack;
#ifdef FRAMEWORK_HEADERS
if (pend->framework_head)
pend->framework_tail->next = pend->framework_system_head;
else
pend->framework_head = pend->framework_system_head;
CPP_OPTION (pfile, framework_include) = pend->framework_head;
#endif
}
struct lang_flags
{
char c99;
char cplusplus;
char extended_numbers;
char trigraphs;
char dollars_in_ident;
char cplusplus_comments;
char digraphs;
};
static const struct lang_flags lang_defaults[] =
{
{ 0, 0, 1, 0, 1, 1, 1 },
{ 1, 0, 1, 0, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 0, 0, 1, 1 },
{ 0, 1, 1, 0, 1, 1, 1 },
{ 0, 1, 1, 0, 0, 1, 1 },
#ifdef CONFIG_DARWIN_H
{ 0, 0, 1, 0, 1, 1, 0 }
#else
{ 0, 0, 1, 0, 0, 1, 0 }
#endif
};
static void
set_lang (pfile, lang)
cpp_reader *pfile;
enum c_lang lang;
{
const struct lang_flags *l = &lang_defaults[(int) lang];
CPP_OPTION (pfile, lang) = lang;
CPP_OPTION (pfile, objc) = compiling_objc;
CPP_OPTION (pfile, c99) = l->c99;
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
static int opt_comp PARAMS ((const void *, const void *));
static int
opt_comp (p1, p2)
const void *p1, *p2;
{
return strcmp (((struct cl_option *) p1)->opt_text,
((struct cl_option *) p2)->opt_text);
}
#endif
static void
init_library ()
{
static int initialized = 0;
if (! initialized)
{
initialized = 1;
#ifdef HOST_EBCDIC
qsort (cl_options, N_OPTS, sizeof (struct cl_option), opt_comp);
#endif
init_trigraph_map ();
}
}
cpp_reader *
cpp_create_reader (lang)
enum c_lang lang;
{
cpp_reader *pfile;
init_library ();
pfile = (cpp_reader *) xcalloc (1, sizeof (cpp_reader));
set_lang (pfile, lang);
CPP_OPTION (pfile, warn_import) = 0;
CPP_OPTION (pfile, warn_pragma_once) = 0;
CPP_OPTION (pfile, warn_extra_tokens) = 0;
CPP_OPTION (pfile, warn_newline_at_eof) = 0;
CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, show_column) = 1;
CPP_OPTION (pfile, tabstop) = 8;
CPP_OPTION (pfile, operator_names) = 1;
#if DEFAULT_SIGNED_CHAR
CPP_OPTION (pfile, signed_char) = 1;
#else
CPP_OPTION (pfile, signed_char) = 0;
#endif
CPP_OPTION (pfile, pending) =
(struct cpp_pending *) xcalloc (1, sizeof (struct cpp_pending));
pfile->deps = deps_init ();
init_line_maps (&pfile->line_maps);
pfile->line = 1;
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
pfile->date.type = CPP_EOF;
pfile->avoid_paste.type = CPP_PADDING;
pfile->avoid_paste.val.source = NULL;
pfile->eof.type = CPP_EOF;
pfile->eof.flags = 0;
_cpp_init_tokenrun (&pfile->base_run, 250);
pfile->cur_run = &pfile->base_run;
pfile->cur_token = pfile->base_run.base;
pfile->context = &pfile->base_context;
pfile->base_context.macro = 0;
pfile->base_context.prev = pfile->base_context.next = 0;
pfile->a_buff = _cpp_get_buff (pfile, 0);
pfile->u_buff = _cpp_get_buff (pfile, 0);
gcc_obstack_init (&pfile->buffer_ob);
_cpp_init_includes (pfile);
return pfile;
}
int
cpp_destroy (pfile)
cpp_reader *pfile;
{
int result;
struct search_path *dir, *dirn;
cpp_context *context, *contextn;
tokenrun *run, *runn;
while (CPP_BUFFER (pfile) != NULL)
_cpp_pop_buffer (pfile);
if (pfile->macro_buffer)
{
free ((PTR) pfile->macro_buffer);
pfile->macro_buffer = NULL;
pfile->macro_buffer_len = 0;
}
deps_free (pfile->deps);
obstack_free (&pfile->buffer_ob, 0);
_cpp_destroy_hashtable (pfile);
_cpp_cleanup_includes (pfile);
_cpp_free_buff (pfile->a_buff);
_cpp_free_buff (pfile->u_buff);
_cpp_free_buff (pfile->free_buffs);
for (run = &pfile->base_run; run; run = runn)
{
runn = run->next;
free (run->base);
if (run != &pfile->base_run)
free (run);
}
for (dir = CPP_OPTION (pfile, quote_include); dir; dir = dirn)
{
dirn = dir->next;
free ((PTR) dir->name);
free (dir);
}
for (context = pfile->base_context.next; context; context = contextn)
{
contextn = context->next;
free (context);
}
free_line_maps (&pfile->line_maps);
result = pfile->errors;
free (pfile);
return result;
}
struct builtin
{
const U_CHAR *name;
const char *value;
unsigned char builtin;
unsigned char operator;
unsigned short flags;
unsigned short len;
};
#define VERS 0x01
#define ULP 0x02
#define CPLUS 0x04
#define BUILTIN 0x08
#define OPERATOR 0x10
#define B(n, t) { U n, 0, t, 0, BUILTIN, sizeof n - 1 }
#define C(n, v) { U n, v, 0, 0, 0, sizeof n - 1 }
#define X(n, f) { U n, 0, 0, 0, f, sizeof n - 1 }
#define O(n, c, f) { U n, 0, 0, c, OPERATOR | f, sizeof n - 1 }
static const struct builtin builtin_array[] =
{
B("__TIME__", BT_TIME),
B("__DATE__", BT_DATE),
B("__FILE__", BT_FILE),
B("__BASE_FILE__", BT_BASE_FILE),
B("__LINE__", BT_SPECLINE),
B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL),
B("_Pragma", BT_PRAGMA),
X("__VERSION__", VERS),
X("__USER_LABEL_PREFIX__", ULP),
C("__REGISTER_PREFIX__", REGISTER_PREFIX),
C("__HAVE_BUILTIN_SETJMP__", "1"),
#if USING_SJLJ_EXCEPTIONS
C("__USING_SJLJ_EXCEPTIONS__","1"),
#endif
#ifndef NO_BUILTIN_SIZE_TYPE
C("__SIZE_TYPE__", SIZE_TYPE),
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
C("__PTRDIFF_TYPE__", PTRDIFF_TYPE),
#endif
#ifndef NO_BUILTIN_WCHAR_TYPE
C("__WCHAR_TYPE__", WCHAR_TYPE),
#endif
#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
O("and", CPP_AND_AND, CPLUS),
O("and_eq", CPP_AND_EQ, CPLUS),
O("bitand", CPP_AND, CPLUS),
O("bitor", CPP_OR, CPLUS),
O("compl", CPP_COMPL, CPLUS),
O("not", CPP_NOT, CPLUS),
O("not_eq", CPP_NOT_EQ, CPLUS),
O("or", CPP_OR_OR, CPLUS),
O("or_eq", CPP_OR_EQ, CPLUS),
O("xor", CPP_XOR, CPLUS),
O("xor_eq", CPP_XOR_EQ, CPLUS)
};
#undef B
#undef C
#undef X
#undef O
#define builtin_array_end \
builtin_array + sizeof(builtin_array)/sizeof(struct builtin)
static void
init_builtins (pfile)
cpp_reader *pfile;
{
const struct builtin *b;
for(b = builtin_array; b < builtin_array_end; b++)
{
if ((b->flags & CPLUS) && ! CPP_OPTION (pfile, cplusplus))
continue;
if ((b->flags & OPERATOR) && ! CPP_OPTION (pfile, operator_names))
continue;
if (b->flags & (OPERATOR | BUILTIN))
{
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
if (b->flags & OPERATOR)
{
hp->flags |= NODE_OPERATOR;
hp->value.operator = b->operator;
}
else
{
hp->type = NT_MACRO;
hp->flags |= NODE_BUILTIN | NODE_WARN;
hp->value.builtin = b->builtin;
}
}
else
{
const char *val;
char *str;
if (b->flags & VERS)
{
str = alloca (b->len + strlen (version_string) + 5);
sprintf (str, "%s \"%s\"\n", b->name, version_string);
}
else
{
if (b->flags & ULP)
val = CPP_OPTION (pfile, user_label_prefix);
else
val = b->value;
str = alloca (b->len + strlen (val) + 3);
sprintf(str, "%s %s\n", b->name, val);
}
_cpp_define_builtin (pfile, str);
}
}
if (CPP_OPTION (pfile, cplusplus))
{
_cpp_define_builtin (pfile, "__cplusplus 1");
#undef SUPPORTS_ONE_ONLY
#define SUPPORTS_ONE_ONLY 0
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, signed_char) == 0)
_cpp_define_builtin (pfile, "__CHAR_UNSIGNED__ 1");
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
#undef VERS
#undef ULP
#undef CPLUS
#undef builtin_array_end
static void
init_standard_includes (pfile)
cpp_reader *pfile;
{
char *path;
const struct default_include *p;
const char *specd_prefix = CPP_OPTION (pfile, include_prefix);
GET_ENV_PATH_LIST (path, "CPATH");
if (path != 0 && *path != 0)
path_include (pfile, path, BRACKET);
switch ((CPP_OPTION (pfile, objc) ? 2 : 0) + CPP_OPTION (pfile, cplusplus))
{
case 0:
GET_ENV_PATH_LIST (path, "C_INCLUDE_PATH");
break;
case 1:
GET_ENV_PATH_LIST (path, "CPLUS_INCLUDE_PATH");
break;
case 2:
GET_ENV_PATH_LIST (path, "OBJC_INCLUDE_PATH");
break;
case 3:
GET_ENV_PATH_LIST (path, "OBJCPLUS_INCLUDE_PATH");
break;
}
if (path != 0 && *path != 0)
path_include (pfile, path, SYSTEM);
if (specd_prefix != 0 && cpp_GCC_INCLUDE_DIR_len)
{
int default_len = cpp_GCC_INCLUDE_DIR_len;
char *default_prefix = (char *) alloca (default_len + 1);
int specd_len = strlen (specd_prefix);
memcpy (default_prefix, cpp_GCC_INCLUDE_DIR, default_len);
default_prefix[default_len] = '\0';
for (p = cpp_include_defaults; p->fname; p++)
{
if (!p->cplusplus
|| (CPP_OPTION (pfile, cplusplus)
&& !CPP_OPTION (pfile, no_standard_cplusplus_includes)))
{
if (!memcmp (p->fname, default_prefix, default_len))
{
int flen = strlen (p->fname);
int this_len = specd_len + flen - default_len;
char *str = (char *) xmalloc (this_len + 1);
memcpy (str, specd_prefix, specd_len);
memcpy (str + specd_len,
p->fname + default_len,
flen - default_len + 1);
append_include_chain (pfile, str, SYSTEM, p->cxx_aware);
}
}
}
}
for (p = cpp_include_defaults; p->fname; p++)
{
if (!p->cplusplus
|| (CPP_OPTION (pfile, cplusplus)
&& !CPP_OPTION (pfile, no_standard_cplusplus_includes)))
{
char *str = update_path (p->fname, p->component);
append_include_chain (pfile, str, SYSTEM, p->cxx_aware);
}
}
#ifdef FRAMEWORK_HEADERS
{
int i = 0;
char *path;
char *next_root = getenv ("NEXT_ROOT");
if (next_root && *next_root && next_root[strlen (next_root) - 1] == '/')
next_root[strlen (next_root) - 1] = '\0';
while ((path = framework_paths_defaults_array[i++].path))
{
char *new_fname = NULL;
if (next_root && *next_root)
new_fname = (char *) xmalloc (strlen (next_root) + strlen (path) + 1);
if (new_fname)
sprintf (new_fname, "%s%s", next_root, path);
else
{
new_fname = (char *) xmalloc (strlen (path) + 1);
strcpy (new_fname, path);
}
append_include_chain (pfile, new_fname, FRAMEWORK_SYSTEM, 1);
}
}
#endif
}
static bool
push_include (pfile, p)
cpp_reader *pfile;
struct pending_option *p;
{
cpp_token header;
header.type = CPP_STRING;
header.val.str.text = (const unsigned char *) p->arg;
header.val.str.len = strlen (p->arg);
pfile->line++;
return _cpp_execute_include (pfile, &header, IT_CMDLINE);
}
static void
free_chain (head)
struct pending_option *head;
{
struct pending_option *next;
while (head)
{
next = head->next;
free (head);
head = next;
}
}
const char *
cpp_read_main_file (pfile, fname, table)
cpp_reader *pfile;
const char *fname;
hash_table *table;
{
_cpp_init_hashtable (pfile, table);
if (! CPP_OPTION (pfile, no_standard_includes))
init_standard_includes (pfile);
merge_include_chains (pfile);
if (CPP_OPTION (pfile, verbose))
{
struct search_path *l;
fprintf (stderr, _("#include \"...\" search starts here:\n"));
for (l = CPP_OPTION (pfile, quote_include); l; l = l->next)
{
if (l == CPP_OPTION (pfile, bracket_include))
fprintf (stderr, _("#include <...> search starts here:\n"));
fprintf (stderr, " %s\n", l->name);
}
fprintf (stderr, _("End of search list.\n"));
#ifdef FRAMEWORK_HEADERS
fprintf (stderr, _("Framework search starts here:\n"));
for (l = CPP_OPTION (pfile, framework_include); l; l = l->next)
{
fprintf (stderr, " %s\n", l->name);
}
fprintf (stderr, _("End of framework search list.\n"));
#endif
}
if (CPP_OPTION (pfile, print_deps))
deps_add_default_target (pfile->deps, fname);
if (!_cpp_read_file (pfile, fname))
return NULL;
pfile->line_maps.trace_includes = CPP_OPTION (pfile, print_include_names);
if (CPP_OPTION (pfile, preprocessed) || flag_cpp_precomp)
read_original_filename (pfile);
return pfile->map->to_file;
}
static void
read_original_filename (pfile)
cpp_reader *pfile;
{
const cpp_token *token, *token1;
token = _cpp_lex_direct (pfile);
if (token->type == CPP_HASH)
{
token1 = _cpp_lex_direct (pfile);
_cpp_backup_tokens (pfile, 1);
if (token1->type == CPP_NUMBER)
{
_cpp_handle_directive (pfile, token->flags & PREV_WHITE);
return;
}
}
_cpp_backup_tokens (pfile, 1);
}
void
cpp_finish_options (pfile)
cpp_reader *pfile;
{
if (! CPP_OPTION (pfile, preprocessed))
{
struct pending_option *p;
_cpp_do_file_change (pfile, LC_RENAME, _("<built-in>"), 1, 0);
#ifdef PFE
if (pfe_operation != PFE_LOAD)
#endif
init_builtins (pfile);
_cpp_do_file_change (pfile, LC_RENAME, _("<command line>"), 1, 0);
#ifdef PFE
pfe_set_cmd_ln_processing ();
#endif
for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next)
(*p->handler) (pfile, p->arg);
#ifdef PFE
pfe_reset_cmd_ln_processing ();
#endif
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);
}
}
free_chain (CPP_OPTION (pfile, pending)->directive_head);
_cpp_push_next_buffer (pfile);
}
bool
_cpp_push_next_buffer (pfile)
cpp_reader *pfile;
{
bool pushed = false;
if (CPP_OPTION (pfile, pending)
&& CPP_OPTION (pfile, pending)->imacros_head == NULL)
{
while (!pushed)
{
struct pending_option *p = CPP_OPTION (pfile, pending)->include_head;
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;
if (flag_cpp_precomp)
_cpp_do_file_change (pfile, LC_RENAME,
pfile->line_maps.maps[1].to_file, 1, 0);
else
if (! CPP_OPTION (pfile, preprocessed))
_cpp_do_file_change (pfile, LC_RENAME,
pfile->line_maps.maps[0].to_file, 1, 0);
}
}
return pushed;
}
static void
output_deps (pfile)
cpp_reader *pfile;
{
FILE *deps_stream = 0;
const char *const deps_mode =
CPP_OPTION (pfile, print_deps_append) ? "a" : "w";
if (CPP_OPTION (pfile, deps_file)[0] == '\0')
deps_stream = stdout;
else
{
deps_stream = fopen (CPP_OPTION (pfile, deps_file), deps_mode);
if (deps_stream == 0)
{
cpp_notice_from_errno (pfile, CPP_OPTION (pfile, deps_file));
return;
}
}
deps_write (pfile->deps, deps_stream, 72);
if (CPP_OPTION (pfile, deps_phony_targets))
deps_phony_targets (pfile->deps, deps_stream);
if (deps_stream != stdout)
{
if (ferror (deps_stream) || fclose (deps_stream) != 0)
cpp_fatal (pfile, "I/O error on output");
}
}
void
cpp_finish (pfile)
cpp_reader *pfile;
{
while (pfile->buffer)
_cpp_pop_buffer (pfile);
if (CPP_OPTION (pfile, print_deps) && pfile->errors == 0)
output_deps (pfile);
if (CPP_OPTION (pfile, print_include_names))
_cpp_report_missing_guards (pfile);
if (CPP_OPTION (pfile, inclusion_log_file))
ilog_close (pfile);
}
static void
new_pending_directive (pend, text, handler)
struct cpp_pending *pend;
const char *text;
cl_directive_handler handler;
{
struct pending_option *o = (struct pending_option *)
xmalloc (sizeof (struct pending_option));
o->arg = text;
o->next = NULL;
o->handler = handler;
APPEND (pend, directive, o);
}
#define no_arg N_("argument missing after %s")
#define no_ass N_("assertion missing after %s")
#define no_dir N_("directory name missing after %s")
#define no_fil N_("file name missing after %s")
#define no_mac N_("macro name missing after %s")
#define no_pth N_("path name missing after %s")
#define no_num N_("number missing after %s")
#define no_tgt N_("target missing after %s")
#define COMMAND_LINE_OPTIONS \
DEF_OPT("$", 0, OPT_dollar) \
DEF_OPT("+", 0, OPT_plus) \
DEF_OPT("-help", 0, OPT__help) \
DEF_OPT("-target-help", 0, OPT_target__help) \
DEF_OPT("-version", 0, OPT__version) \
DEF_OPT("A", no_ass, OPT_A) \
DEF_OPT("C", 0, OPT_C) \
DEF_OPT("D", no_mac, OPT_D) \
\
DEF_OPT("F", no_dir, OPT_F) \
DEF_OPT("H", 0, OPT_H) \
DEF_OPT("I", no_dir, OPT_I) \
DEF_OPT("M", 0, OPT_M) \
DEF_OPT("MD", no_fil, OPT_MD) \
DEF_OPT("MF", no_fil, OPT_MF) \
DEF_OPT("MG", 0, OPT_MG) \
DEF_OPT("MM", 0, OPT_MM) \
DEF_OPT("MMD", no_fil, OPT_MMD) \
DEF_OPT("MP", 0, OPT_MP) \
DEF_OPT("MQ", no_tgt, OPT_MQ) \
DEF_OPT("MT", no_tgt, OPT_MT) \
DEF_OPT("P", 0, OPT_P) \
DEF_OPT("U", no_mac, OPT_U) \
DEF_OPT("W", no_arg, OPT_W) \
\
DEF_OPT("arch", no_tgt, OPT_arch) \
DEF_OPT("d", no_arg, OPT_d) \
DEF_OPT("fleading-underscore", 0, OPT_fleading_underscore) \
DEF_OPT("fno-leading-underscore", 0, OPT_fno_leading_underscore) \
DEF_OPT("fno-operator-names", 0, OPT_fno_operator_names) \
DEF_OPT("fno-preprocessed", 0, OPT_fno_preprocessed) \
DEF_OPT("fno-show-column", 0, OPT_fno_show_column) \
DEF_OPT("fpreprocessed", 0, OPT_fpreprocessed) \
DEF_OPT("fshow-column", 0, OPT_fshow_column) \
DEF_OPT("fsigned-char", 0, OPT_fsigned_char) \
DEF_OPT("ftabstop=", no_num, OPT_ftabstop) \
DEF_OPT("funsigned-char", 0, OPT_funsigned_char) \
DEF_OPT("h", 0, OPT_h) \
\
DEF_OPT("header-mapfile", no_fil, OPT_header_mapfile) \
DEF_OPT("idirafter", no_dir, OPT_idirafter) \
\
DEF_OPT("iframework", no_dir, OPT_iframework) \
DEF_OPT("imacros", no_fil, OPT_imacros) \
DEF_OPT("include", no_fil, OPT_include) \
\
DEF_OPT("inclusion-log-file", no_fil, OPT_inclusion_log_file) \
DEF_OPT("iprefix", no_pth, OPT_iprefix) \
DEF_OPT("isystem", no_dir, OPT_isystem) \
DEF_OPT("iwithprefix", no_dir, OPT_iwithprefix) \
DEF_OPT("iwithprefixbefore", no_dir, OPT_iwithprefixbefore) \
DEF_OPT("lang-asm", 0, OPT_lang_asm) \
DEF_OPT("lang-c", 0, OPT_lang_c) \
DEF_OPT("lang-c++", 0, OPT_lang_cplusplus) \
DEF_OPT("lang-c89", 0, OPT_lang_c89) \
DEF_OPT("lang-objc", 0, OPT_lang_objc) \
DEF_OPT("lang-objc++", 0, OPT_lang_objcplusplus) \
DEF_OPT("nostdinc", 0, OPT_nostdinc) \
DEF_OPT("nostdinc++", 0, OPT_nostdincplusplus) \
DEF_OPT("o", no_fil, OPT_o) \
DEF_OPT("pedantic", 0, OPT_pedantic) \
DEF_OPT("pedantic-errors", 0, OPT_pedantic_errors) \
\
DEF_OPT("precomp-trustfile", no_fil, OPT_precomp_trustfile) \
DEF_OPT("remap", 0, OPT_remap) \
DEF_OPT("std=c++98", 0, OPT_std_cplusplus98) \
DEF_OPT("std=c89", 0, OPT_std_c89) \
DEF_OPT("std=c99", 0, OPT_std_c99) \
DEF_OPT("std=c9x", 0, OPT_std_c9x) \
DEF_OPT("std=gnu89", 0, OPT_std_gnu89) \
DEF_OPT("std=gnu99", 0, OPT_std_gnu99) \
DEF_OPT("std=gnu9x", 0, OPT_std_gnu9x) \
DEF_OPT("std=iso9899:1990", 0, OPT_std_iso9899_1990) \
DEF_OPT("std=iso9899:199409", 0, OPT_std_iso9899_199409) \
DEF_OPT("std=iso9899:1999", 0, OPT_std_iso9899_1999) \
DEF_OPT("std=iso9899:199x", 0, OPT_std_iso9899_199x) \
DEF_OPT("trigraphs", 0, OPT_trigraphs) \
DEF_OPT("v", 0, OPT_v) \
DEF_OPT("version", 0, OPT_version) \
DEF_OPT("w", 0, OPT_w)
#define DEF_OPT(text, msg, code) code,
enum opt_code
{
COMMAND_LINE_OPTIONS
N_OPTS
};
#undef DEF_OPT
struct cl_option
{
const char *opt_text;
const char *msg;
size_t opt_len;
enum opt_code opt_code;
};
#define DEF_OPT(text, msg, code) { text, msg, sizeof(text) - 1, code },
#ifdef HOST_EBCDIC
static struct cl_option cl_options[] =
#else
static const struct cl_option cl_options[] =
#endif
{
COMMAND_LINE_OPTIONS
};
#undef DEF_OPT
#undef COMMAND_LINE_OPTIONS
static int
parse_option (input)
const char *input;
{
unsigned int md, mn, mx;
size_t opt_len;
int comp;
mn = 0;
mx = N_OPTS;
while (mx > mn)
{
md = (mn + mx) / 2;
opt_len = cl_options[md].opt_len;
comp = memcmp (input, cl_options[md].opt_text, opt_len);
if (comp > 0)
mn = md + 1;
else if (comp < 0)
mx = md;
else
{
if (input[opt_len] == '\0')
return md;
mn = md + 1;
if (cl_options[md].msg)
{
mx = md;
for (; mn < (unsigned int) N_OPTS; mn++)
{
opt_len = cl_options[mn].opt_len;
if (memcmp (input, cl_options[mn].opt_text, opt_len))
break;
if (input[opt_len] == '\0')
return mn;
if (cl_options[mn].msg)
mx = mn;
}
return mx;
}
}
}
return -1;
}
int
cpp_handle_option (pfile, argc, argv, ignore)
cpp_reader *pfile;
int argc;
char **argv;
int ignore;
{
int i = 0;
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
if (argv[i][0] != '-' || argv[i][1] == '\0')
{
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_fatal (pfile, "too many filenames. Type %s --help for usage info",
progname);
}
else
{
enum opt_code opt_code;
int opt_index;
const char *arg = 0;
opt_index = parse_option (&argv[i][1]);
if (opt_index < 0)
return i;
opt_code = cl_options[opt_index].opt_code;
if (cl_options[opt_index].msg)
{
arg = &argv[i][cl_options[opt_index].opt_len + 1];
if (arg[0] == '\0' && opt_code != OPT_W)
{
arg = argv[++i];
if (!arg)
{
cpp_fatal (pfile, cl_options[opt_index].msg, argv[i - 1]);
return argc;
}
}
}
switch (opt_code)
{
case N_OPTS:
break;
case OPT_fleading_underscore:
CPP_OPTION (pfile, user_label_prefix) = "_";
break;
case OPT_fno_leading_underscore:
CPP_OPTION (pfile, user_label_prefix) = "";
break;
case OPT_fno_operator_names:
CPP_OPTION (pfile, operator_names) = 0;
break;
case OPT_fpreprocessed:
CPP_OPTION (pfile, preprocessed) = 1;
break;
case OPT_fno_preprocessed:
CPP_OPTION (pfile, preprocessed) = 0;
break;
case OPT_fshow_column:
CPP_OPTION (pfile, show_column) = 1;
break;
case OPT_fno_show_column:
CPP_OPTION (pfile, show_column) = 0;
break;
case OPT_fsigned_char:
CPP_OPTION (pfile, signed_char) = 1;
break;
case OPT_funsigned_char:
CPP_OPTION (pfile, signed_char) = 0;
break;
case OPT_ftabstop:
if (arg[0] != '\0')
{
char *endptr;
long tabstop = strtol (arg, &endptr, 10);
if (*endptr == '\0' && tabstop >= 1 && tabstop <= 100)
CPP_OPTION (pfile, tabstop) = tabstop;
}
break;
case OPT_w:
CPP_OPTION (pfile, inhibit_warnings) = 1;
break;
case OPT_header_mapfile:
if (CPP_OPTION (pfile, header_map) != NULL)
cpp_fatal (pfile,
"more than one `-header-mapfile' option specified; "
"only one is allowed");
else
CPP_OPTION (pfile, header_map) = hmap_load_header_map (arg);
break;
case OPT_inclusion_log_file:
if (CPP_OPTION (pfile, inclusion_log_file) != NULL)
cpp_fatal (pfile,
"more than one `-inclusion-log-file' option specified; "
"only one is allowed");
else
CPP_OPTION (pfile, inclusion_log_file) = ilog_open (arg);
break;
case OPT_h:
case OPT__help:
print_help ();
CPP_OPTION (pfile, help_only) = 1;
break;
case OPT_target__help:
CPP_OPTION (pfile, help_only) = 1;
break;
case OPT__version:
CPP_OPTION (pfile, help_only) = 1;
pfile->print_version = 1;
break;
case OPT_v:
CPP_OPTION (pfile, verbose) = 1;
pfile->print_version = 1;
break;
case OPT_version:
pfile->print_version = 1;
break;
case OPT_C:
CPP_OPTION (pfile, discard_comments) = 0;
break;
case OPT_P:
CPP_OPTION (pfile, no_line_commands) = 1;
break;
case OPT_dollar:
CPP_OPTION (pfile, dollars_in_ident) = 0;
break;
case OPT_H:
CPP_OPTION (pfile, print_include_names) = 1;
break;
case OPT_D:
new_pending_directive (pend, arg, cpp_define);
break;
case OPT_pedantic_errors:
CPP_OPTION (pfile, pedantic_errors) = 1;
case OPT_pedantic:
CPP_OPTION (pfile, pedantic) = 1;
break;
case OPT_trigraphs:
CPP_OPTION (pfile, trigraphs) = 1;
break;
case OPT_plus:
CPP_OPTION (pfile, cplusplus) = 1;
CPP_OPTION (pfile, cplusplus_comments) = 1;
break;
case OPT_precomp_trustfile:
break;
case OPT_remap:
CPP_OPTION (pfile, remap) = 1;
break;
case OPT_iprefix:
CPP_OPTION (pfile, include_prefix) = arg;
CPP_OPTION (pfile, include_prefix_len) = strlen (arg);
break;
case OPT_lang_objc:
compiling_objc = 1;
case OPT_lang_c:
set_lang (pfile, CLK_GNUC89);
break;
case OPT_lang_objcplusplus:
compiling_objc = 1;
case OPT_lang_cplusplus:
set_lang (pfile, CLK_GNUCXX);
break;
case OPT_lang_asm:
set_lang (pfile, CLK_ASM);
break;
case OPT_std_cplusplus98:
set_lang (pfile, CLK_CXX98);
break;
case OPT_std_gnu89:
set_lang (pfile, CLK_GNUC89);
break;
case OPT_std_gnu9x:
case OPT_std_gnu99:
set_lang (pfile, CLK_GNUC99);
break;
case OPT_std_iso9899_199409:
set_lang (pfile, CLK_STDC94);
break;
case OPT_std_iso9899_1990:
case OPT_std_c89:
case OPT_lang_c89:
set_lang (pfile, CLK_STDC89);
break;
case OPT_std_iso9899_199x:
case OPT_std_iso9899_1999:
case OPT_std_c9x:
case OPT_std_c99:
set_lang (pfile, CLK_STDC99);
break;
case OPT_nostdinc:
CPP_OPTION (pfile, no_standard_includes) = 1;
break;
case OPT_nostdincplusplus:
CPP_OPTION (pfile, no_standard_cplusplus_includes) = 1;
break;
case OPT_o:
if (CPP_OPTION (pfile, out_fname) == NULL)
CPP_OPTION (pfile, out_fname) = arg;
else
{
cpp_fatal (pfile, "output filename specified twice");
return argc;
}
break;
case OPT_arch:
break;
case OPT_d:
{
char c;
while ((c = *arg++) != '\0')
switch (c)
{
case 'M':
CPP_OPTION (pfile, dump_macros) = dump_only;
CPP_OPTION (pfile, no_output) = 1;
break;
case 'N':
CPP_OPTION (pfile, dump_macros) = dump_names;
break;
case 'D':
CPP_OPTION (pfile, dump_macros) = dump_definitions;
break;
case 'I':
CPP_OPTION (pfile, dump_includes) = 1;
break;
}
}
break;
case OPT_MG:
CPP_OPTION (pfile, print_deps_missing_files) = 1;
break;
case OPT_M:
CPP_OPTION (pfile, print_deps) = 2;
CPP_OPTION (pfile, no_output) = 1;
break;
case OPT_MM:
CPP_OPTION (pfile, print_deps) = 1;
CPP_OPTION (pfile, no_output) = 1;
break;
case OPT_MF:
CPP_OPTION (pfile, deps_file) = arg;
break;
case OPT_MP:
CPP_OPTION (pfile, deps_phony_targets) = 1;
break;
case OPT_MQ:
case OPT_MT:
deps_add_target (pfile->deps, arg, opt_code == OPT_MQ);
break;
case OPT_MD:
CPP_OPTION (pfile, print_deps) = 2;
CPP_OPTION (pfile, deps_file) = arg;
break;
case OPT_MMD:
CPP_OPTION (pfile, print_deps) = 1;
CPP_OPTION (pfile, deps_file) = arg;
break;
case OPT_A:
if (arg[0] == '-')
{
if (arg[1] == '\0')
{
free_chain (pend->directive_head);
pend->directive_head = NULL;
pend->directive_tail = NULL;
}
else
new_pending_directive (pend, arg + 1, cpp_unassert);
}
else
new_pending_directive (pend, arg, cpp_assert);
break;
case OPT_U:
new_pending_directive (pend, arg, cpp_undef);
break;
case OPT_I:
if (!strcmp (arg, "-"))
{
if (! CPP_OPTION (pfile, ignore_srcdir))
{
pend->quote_head = pend->brack_head;
pend->quote_tail = pend->brack_tail;
pend->brack_head = 0;
pend->brack_tail = 0;
CPP_OPTION (pfile, ignore_srcdir) = 1;
}
else
{
cpp_fatal (pfile, "-I- specified twice");
return argc;
}
}
else
append_include_chain (pfile, xstrdup (arg), BRACKET, 0);
break;
case OPT_isystem:
append_include_chain (pfile, xstrdup (arg), SYSTEM, 0);
break;
#ifdef FRAMEWORK_HEADERS
case OPT_F:
case OPT_iframework:
append_include_chain (pfile, xstrdup (arg), FRAMEWORK, 0);
break;
#endif
case OPT_include:
case OPT_imacros:
{
struct pending_option *o = (struct pending_option *)
xmalloc (sizeof (struct pending_option));
o->arg = arg;
o->next = NULL;
if (opt_code == OPT_include)
APPEND (pend, include, o);
else
APPEND (pend, imacros, o);
}
break;
case OPT_iwithprefix:
case OPT_iwithprefixbefore:
{
char *fname;
int len;
len = strlen (arg);
if (CPP_OPTION (pfile, include_prefix) != 0)
{
size_t ipl = CPP_OPTION (pfile, include_prefix_len);
fname = xmalloc (ipl + len + 1);
memcpy (fname, CPP_OPTION (pfile, include_prefix), ipl);
memcpy (fname + ipl, arg, len + 1);
}
else if (cpp_GCC_INCLUDE_DIR_len)
{
fname = xmalloc (cpp_GCC_INCLUDE_DIR_len + len + 1);
memcpy (fname, cpp_GCC_INCLUDE_DIR, cpp_GCC_INCLUDE_DIR_len);
memcpy (fname + cpp_GCC_INCLUDE_DIR_len, arg, len + 1);
}
else
fname = xstrdup (arg);
append_include_chain (pfile, fname,
opt_code == OPT_iwithprefix ? SYSTEM: BRACKET, 0);
}
break;
case OPT_idirafter:
append_include_chain (pfile, xstrdup (arg), AFTER, 0);
break;
case OPT_W:
if (!strcmp (argv[i], "-Wall"))
{
CPP_OPTION (pfile, warn_trigraphs) = 1;
CPP_OPTION (pfile, warn_comments) = 1;
}
else if (!strcmp (argv[i], "-Wtraditional"))
CPP_OPTION (pfile, warn_traditional) = 1;
else if (!strcmp (argv[i], "-Wtrigraphs"))
CPP_OPTION (pfile, warn_trigraphs) = 1;
else if (!strcmp (argv[i], "-Wcomment"))
CPP_OPTION (pfile, warn_comments) = 1;
else if (!strcmp (argv[i], "-Wcomments"))
CPP_OPTION (pfile, warn_comments) = 1;
else if (!strcmp (argv[i], "-Wundef"))
CPP_OPTION (pfile, warn_undef) = 1;
else if (!strcmp (argv[i], "-Wimport"))
CPP_OPTION (pfile, warn_import) = 1;
else if (!strcmp (argv[i], "-Wpragma-once"))
CPP_OPTION (pfile, warn_pragma_once) = 1;
else if (!strcmp (argv[i], "-Wextra-tokens"))
CPP_OPTION (pfile, warn_extra_tokens) = 1;
else if (!strcmp (argv[i], "-Wnewline-eof"))
CPP_OPTION (pfile, warn_newline_at_eof) = 1;
else if (!strcmp (argv[i], "-Werror"))
{
CPP_OPTION (pfile, warnings_are_errors) = 1;
if (getenv ("QA_DISABLE_WERROR"))
{
CPP_OPTION (pfile, warnings_are_errors) = 0;
cpp_warning (pfile, "-Werror is ignored.");
cpp_warning (pfile, "Temporarily warnings are not being treated as errors.");
}
}
else if (!strcmp (argv[i], "-Wsystem-headers"))
CPP_OPTION (pfile, warn_system_headers) = 1;
else if (!strcmp (argv[i], "-Wno-traditional"))
CPP_OPTION (pfile, warn_traditional) = 0;
else if (!strcmp (argv[i], "-Wno-trigraphs"))
CPP_OPTION (pfile, warn_trigraphs) = 0;
else if (!strcmp (argv[i], "-Wno-comment"))
CPP_OPTION (pfile, warn_comments) = 0;
else if (!strcmp (argv[i], "-Wno-comments"))
CPP_OPTION (pfile, warn_comments) = 0;
else if (!strcmp (argv[i], "-Wno-undef"))
CPP_OPTION (pfile, warn_undef) = 0;
else if (!strcmp (argv[i], "-Wno-import"))
CPP_OPTION (pfile, warn_import) = 0;
else if (!strcmp (argv[i], "-Wno-pragma-once"))
CPP_OPTION (pfile, warn_pragma_once) = 0;
else if (!strcmp (argv[i], "-Wno-extra-tokens"))
CPP_OPTION (pfile, warn_extra_tokens) = 0;
else if (!strcmp (argv[i], "-Wno-newline-eof"))
CPP_OPTION (pfile, warn_newline_at_eof) = 0;
else if (!strcmp (argv[i], "-Wno-error"))
CPP_OPTION (pfile, warnings_are_errors) = 0;
else if (!strcmp (argv[i], "-Wno-system-headers"))
CPP_OPTION (pfile, warn_system_headers) = 0;
else if (!strcmp (argv[i], "-Wno-#warnings"))
CPP_OPTION (pfile, no_pound_warnings) = 1;
else if (! ignore)
return i;
break;
}
}
return i + 1;
}
int
cpp_handle_options (pfile, argc, argv)
cpp_reader *pfile;
int argc;
char **argv;
{
int i;
int strings_processed;
for (i = 0; i < argc; i += strings_processed)
{
strings_processed = cpp_handle_option (pfile, argc - i, argv + i, 1);
if (strings_processed == 0)
break;
}
return i;
}
void
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);
}
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) = "";
if (CPP_OPTION (pfile, cplusplus))
CPP_OPTION (pfile, warn_traditional) = 0;
if (CPP_OPTION (pfile, user_label_prefix) == NULL)
CPP_OPTION (pfile, user_label_prefix) = USER_LABEL_PREFIX;
if (CPP_OPTION (pfile, preprocessed))
pfile->state.prevent_expansion = 1;
init_dependency_output (pfile);
if (CPP_OPTION (pfile, print_deps) == 0 &&
(CPP_OPTION (pfile, print_deps_missing_files)
|| CPP_OPTION (pfile, deps_file)
|| CPP_OPTION (pfile, deps_phony_targets)))
cpp_fatal (pfile, "you must additionally specify either -M or -MM");
}
static void
init_dependency_output (pfile)
cpp_reader *pfile;
{
char *spec, *s, *output_file;
if (CPP_OPTION (pfile, print_deps) == 0)
{
spec = getenv ("DEPENDENCIES_OUTPUT");
if (spec)
CPP_OPTION (pfile, print_deps) = 1;
else
{
spec = getenv ("SUNPRO_DEPENDENCIES");
if (spec)
CPP_OPTION (pfile, print_deps) = 2;
else
return;
}
s = strchr (spec, ' ');
if (s)
{
deps_add_target (pfile->deps, s + 1, 0);
output_file = (char *) xmalloc (s - spec + 1);
memcpy (output_file, spec, s - spec);
output_file[s - spec] = 0;
}
else
output_file = spec;
if (CPP_OPTION (pfile, deps_file) == 0)
CPP_OPTION (pfile, deps_file) = output_file;
CPP_OPTION (pfile, print_deps_append) = 1;
}
else if (CPP_OPTION (pfile, deps_file) == 0)
CPP_OPTION (pfile, deps_file) = CPP_OPTION (pfile, out_fname);
}
static inline
uint32 hmap_hash_string (str)
const char *str;
{
const char *sp;
unsigned hash_code = 0;
for (sp = str; *sp; sp++)
hash_code += tolower (*(const unsigned char *)sp) * 13;
return hash_code;
}
static inline unsigned
hmap_compare_strings (str1, str2)
const char *str1;
const char *str2;
{
const char *s1p;
const char *s2p;
for (s1p = str1, s2p = str2; *s1p && *s2p; s1p++, s2p++)
{
if (tolower (*s1p) != tolower (*s2p))
return 0;
}
return (*s1p == '\0' && *s2p == '\0');
}
static struct
hmap_header_map *hmap_load_header_map (filename)
const char *filename;
{
struct hmap_header_map *headermap = NULL;
if (filename != NULL && filename[0] != '\0')
{
FILE * f;
struct stat f_info;
f = fopen (filename, "rb");
if (f != NULL)
{
if (fstat (fileno (f), &f_info) == 0)
{
unsigned headermap_size = f_info.st_size;
headermap = (struct hmap_header_map *) xmalloc (headermap_size);
if (fread (headermap, 1, headermap_size, f) != headermap_size)
{
perror (filename);
free (headermap);
headermap = NULL;
}
if (headermap->magic == HMAP_OPPOSITE_ENDIANNESS_MAGIC)
{
fprintf (stderr,
"headermap \"%s\" has incompatible endianness\n",
filename);
free (headermap);
headermap = NULL;
}
else if (headermap->magic != HMAP_SAME_ENDIANNESS_MAGIC)
{
fprintf (stderr,
"\"%s\" is not a headermap file (bad magic: 0x%08lx)\n",
filename, headermap->magic);
free (headermap);
headermap = NULL;
}
}
else
perror (filename);
fclose (f);
}
else
perror (filename);
}
return headermap;
}
static void
hmap_free_header_map (pfile)
cpp_reader *pfile;
{
struct hmap_header_map *headermap = CPP_OPTION (pfile, header_map);
if (headermap != NULL)
free (headermap);
if (CPP_OPTION (pfile, hmap_path))
free (CPP_OPTION (pfile, hmap_path));
}
struct search_path *
hmap_lookup_path (pfile, filename_beg)
cpp_reader *pfile;
const char **filename_beg;
{
struct hmap_header_map *headermap = CPP_OPTION (pfile, header_map);
const char *strings;
struct hmap_bucket *buckets;
uint32 bucket_mask;
uint32 i;
uint32 key_offset;
strings = ((const char *)headermap) + headermap->strings_offset;
buckets = headermap->buckets;
bucket_mask = headermap->capacity-1;
i = hmap_hash_string (*filename_beg) & bucket_mask;
while ((key_offset = buckets[i].key) != HMAP_NOT_A_KEY)
{
if (hmap_compare_strings (*filename_beg, strings+key_offset))
{
static char *hmap_path_result_buffer = NULL;
const char *sp;
char *dp;
char *last_slash;
if (hmap_path_result_buffer == NULL)
hmap_path_result_buffer =
xmalloc (headermap->max_value_length + 1);
last_slash = dp = hmap_path_result_buffer;
sp = strings + buckets[i].value.prefix;
while (*sp != '\0')
{
if (*sp == '/')
last_slash = dp;
*dp++ = *sp++;
}
sp = strings + buckets[i].value.suffix;
while (*sp != '\0')
{
if (*sp == '/')
last_slash = dp;
*dp++ = *sp++;
}
*dp = '\0';
if (*last_slash == '/')
*last_slash++ = '\0';
append_include_chain (pfile, xstrdup (hmap_path_result_buffer),
HMAPFILE, 0);
if (!CPP_OPTION (pfile, hmap_path))
break;
*filename_beg = last_slash;
return CPP_OPTION (pfile, hmap_path);
}
i = (i + 1) & bucket_mask;
}
return CPP_OPTION (pfile, bracket_include);
}
static FILE *
ilog_open (ilog_name)
const char *ilog_name;
{
FILE *inclusion_log_file = ((ilog_name[0] != '-' || ilog_name[1] != '\0')
? fopen (ilog_name, "w")
: fdopen (dup (fileno (stdout)), "w"));
if (!inclusion_log_file)
perror (ilog_name);
return inclusion_log_file;
}
static void
ilog_close (pfile)
cpp_reader *pfile;
{
if (CPP_OPTION (pfile, inclusion_log_file))
ilog_printf (pfile, "The `-inclusion-log-file' option has not been\n"
"implemented in GCC3 just yet. Our apologies.\n");
if (CPP_OPTION (pfile, inclusion_log_file)
&& CPP_OPTION (pfile, inclusion_log_file) != stdout
&& (ferror (CPP_OPTION (pfile, inclusion_log_file))
|| fclose (CPP_OPTION (pfile, inclusion_log_file)) != 0))
cpp_fatal (pfile, "I/O error on `-inclusion-log-file' output");
}
void
ilog_printf (cpp_reader *pfile, const char * format, ...)
{
va_list ap;
va_start(ap, format);
if (CPP_OPTION (pfile, inclusion_log_file))
vfprintf(CPP_OPTION (pfile, inclusion_log_file), format, ap);
va_end(ap);
}
static void
print_help ()
{
fputs (_("\
Switches:\n\
-include <file> Include the contents of <file> before other files\n\
-imacros <file> Accept definition of macros in <file>\n\
-iprefix <path> Specify <path> as a prefix for next two options\n\
-iwithprefix <dir> Add <dir> to the end of the system include path\n\
-iwithprefixbefore <dir> Add <dir> to the end of the main include path\n\
-isystem <dir> Add <dir> to the start of the system include path\n\
"), stdout);
fputs (_("\
-idirafter <dir> Add <dir> to the end of the system include path\n\
-I <dir> Add <dir> to the end of the main include path\n\
-I- Fine-grained include path control; see info docs\n\
-nostdinc Do not search system include directories\n\
(dirs specified with -isystem will still be used)\n\
-nostdinc++ Do not search system include directories for C++\n\
-o <file> Put output into <file>\n\
"), stdout);
fputs (_("\
-pedantic Issue all warnings demanded by strict ISO C\n\
-pedantic-errors Issue -pedantic warnings as errors instead\n\
-trigraphs Support ISO C trigraphs\n\
-lang-c Assume that the input sources are in C\n\
-lang-c89 Assume that the input sources are in C89\n\
"), stdout);
fputs (_("\
-lang-c++ Assume that the input sources are in C++\n\
-lang-objc Assume that the input sources are in ObjectiveC\n\
-lang-objc++ Assume that the input sources are in ObjectiveC++\n\
-lang-asm Assume that the input sources are in assembler\n\
"), stdout);
fputs (_("\
-std=<std name> Specify the conformance standard; one of:\n\
gnu89, gnu99, c89, c99, iso9899:1990,\n\
iso9899:199409, iso9899:1999\n\
-+ Allow parsing of C++ style features\n\
-w Inhibit warning messages\n\
-Wtrigraphs Warn if trigraphs are encountered\n\
-Wno-trigraphs Do not warn about trigraphs\n\
-Wcomment{s} Warn if one comment starts inside another\n\
"), stdout);
fputs (_("\
-Wno-comment{s} Do not warn about comments\n\
-Wtraditional Warn about features not present in traditional C\n\
-Wno-traditional Do not warn about traditional C\n\
-Wundef Warn if an undefined macro is used by #if\n\
-Wno-undef Do not warn about testing undefined macros\n\
-Wimport Warn about the use of the #import directive\n\
"), stdout);
fputs (_("\
-Wno-import Do not warn about the use of #import\n\
-Werror Treat all warnings as errors\n\
-Wno-error Do not treat warnings as errors\n\
-Wsystem-headers Do not suppress warnings from system headers\n\
-Wno-system-headers Suppress warnings from system headers\n\
-Wall Enable all preprocessor warnings\n\
"), stdout);
fputs (_("\
-M Generate make dependencies\n\
-MM As -M, but ignore system header files\n\
-MD Generate make dependencies and compile\n\
-MMD As -MD, but ignore system header files\n\
-MF <file> Write dependency output to the given file\n\
-MG Treat missing header file as generated files\n\
"), stdout);
fputs (_("\
-MP Generate phony targets for all headers\n\
-MQ <target> Add a MAKE-quoted target\n\
-MT <target> Add an unquoted target\n\
"), stdout);
fputs (_("\
-D<macro> Define a <macro> with string '1' as its value\n\
-D<macro>=<val> Define a <macro> with <val> as its value\n\
-A<question>=<answer> Assert the <answer> to <question>\n\
-A-<question>=<answer> Disable the <answer> to <question>\n\
-U<macro> Undefine <macro> \n\
-v Display the version number\n\
"), stdout);
fputs (_("\
-H Print the name of header files as they are used\n\
-C Do not discard comments\n\
-dM Display a list of macro definitions active at end\n\
-dD Preserve macro definitions in output\n\
-dN As -dD except that only the names are preserved\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\
-remap Remap file names when including files\n\
--version Display version information\n\
-h or --help Display this information\n\
"), stdout);
}