static void initialize_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 void merge_include_chains PARAMS ((cpp_reader *));
static void initialize_dependency_output PARAMS ((cpp_reader *));
/* Fourth argument to append_include_chain: chain to use */
enum { QUOTE = 0, BRACKET, SYSTEM, AFTER };
-/* If we have designated initializers (GCC >2.7) this table can be
- initialized, constant data. Otherwise, it has to be filled in at
+/* If we have designated initializers (GCC >2.7) these tables can be
+ initialized, constant data. Otherwise, they have to be filled in at
runtime. */
+#if HAVE_DESIGNATED_INITIALIZERS
-#if (GCC_VERSION >= 2007)
#define init_IStable() /* nothing */
-#define ISTABLE __extension__ const unsigned char _cpp_IStable[256] = {
+#define ISTABLE __extension__ const U_CHAR _cpp_IStable[UCHAR_MAX + 1] = {
+
+#define init_trigraph_map() /* nothing */
+#define TRIGRAPH_MAP \
+__extension__ const U_CHAR _cpp_trigraph_map[UCHAR_MAX + 1] = {
+
#define END };
#define s(p, v) [p] = v,
+
#else
-#define ISTABLE unsigned char _cpp_IStable[256] = { 0 }; \
+
+#define ISTABLE unsigned char _cpp_IStable[UCHAR_MAX + 1] = { 0 }; \
static void init_IStable PARAMS ((void)) { \
unsigned char *x = _cpp_IStable;
+
+#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
#define A(x) s(x, ISidnum|ISidstart)
S('\0') S('\v') S('\f')
END
+TRIGRAPH_MAP
+ s('=', '#') s(')', ']') s('!', '|')
+ s('(', '[') s('\'', '^') s('>', '}')
+ s('/', '\\') s('<', '{') s('-', '~')
+END
+
#undef A
#undef N
#undef H
#undef s
#undef ISTABLE
#undef END
+#undef TRIGRAPH_MAP
/* Given a colon-separated list of file names PATH,
add all the names to the search path for include files. */
}
}
+/* 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 *
+remove_dup_dir (pfile, prev)
+ cpp_reader *pfile;
+ struct file_name_list *prev;
+{
+ struct file_name_list *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 (cur);
+
+ return prev;
+}
+
+/* Remove duplicate directories from a chain. Returns the tail of the
+ 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 *
+remove_dup_dirs (pfile, head)
+ cpp_reader *pfile;
+ struct file_name_list *head;
+{
+ struct file_name_list *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)
+ {
+ cur = remove_dup_dir (pfile, prev);
+ break;
+ }
+ prev = cur;
+ }
+
+ return prev;
+}
+
/* Merge the four include chains together in the order quote, bracket,
system, after. Remove duplicate dirs (as determined by
INO_T_EQ()). The system_include and after_include chains are never
merge_include_chains (pfile)
cpp_reader *pfile;
{
- struct file_name_list *prev, *cur, *other;
- struct file_name_list *quote, *brack, *systm, *after;
- struct file_name_list *qtail, *btail, *stail, *atail;
+ struct file_name_list *quote, *brack, *systm, *qtail;
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
- qtail = pend->quote_tail;
- btail = pend->brack_tail;
- stail = pend->systm_tail;
- atail = pend->after_tail;
-
quote = pend->quote_head;
brack = pend->brack_head;
systm = pend->systm_head;
- after = pend->after_head;
+ qtail = pend->quote_tail;
- /* Paste together bracket, system, and after include chains. */
- if (stail)
- stail->next = after;
+ /* Paste together bracket, system, and after include chains. */
+ if (systm)
+ pend->systm_tail->next = pend->after_head;
else
- systm = after;
- if (btail)
- btail->next = systm;
+ systm = pend->after_head;
+
+ if (brack)
+ pend->brack_tail->next = systm;
else
brack = systm;
- /* 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 qtail.
+ /* 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.
We can't just merge the lists and then uniquify them because
then we may lose directories from the <> search path that should
be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however
safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written
- -Ibar -I- -Ifoo -Iquux.
+ -Ibar -I- -Ifoo -Iquux. */
- Note that this algorithm is quadratic in the number of -I switches,
- which is acceptable since there aren't usually that many of them. */
-
- for (cur = quote, prev = NULL; cur; cur = cur->next)
- {
- for (other = quote; other != cur; other = other->next)
- if (INO_T_EQ (cur->ino, other->ino)
- && cur->dev == other->dev)
- {
- if (CPP_OPTION (pfile, verbose))
- fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
- cur->name);
-
- prev->next = cur->next;
- free (cur->name);
- free (cur);
- cur = prev;
- break;
- }
- prev = cur;
- }
- qtail = prev;
-
- for (cur = brack; cur; cur = cur->next)
- {
- for (other = brack; other != cur; other = other->next)
- if (INO_T_EQ (cur->ino, other->ino)
- && cur->dev == other->dev)
- {
- if (CPP_OPTION (pfile, verbose))
- fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
- cur->name);
-
- prev->next = cur->next;
- free (cur->name);
- free (cur);
- cur = prev;
- break;
- }
- prev = cur;
- }
+ remove_dup_dirs (pfile, brack);
+ qtail = remove_dup_dirs (pfile, quote);
if (quote)
{
- if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev)
- {
- if (quote == qtail)
- {
- if (CPP_OPTION (pfile, verbose))
- fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
- quote->name);
+ qtail->next = brack;
- free (quote->name);
- free (quote);
- quote = brack;
- }
- else
- {
- cur = quote;
- while (cur->next != qtail)
- cur = cur->next;
- cur->next = brack;
- if (CPP_OPTION (pfile, verbose))
- fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
- qtail->name);
-
- free (qtail->name);
- free (qtail);
- }
- }
- else
- qtail->next = brack;
+ /* If brack == qtail, remove brack as it's simpler. */
+ if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev)
+ brack = remove_dup_dir (pfile, qtail);
}
else
quote = brack;
CPP_OPTION (pfile, bracket_include) = brack;
}
+/* cpp_init initializes library global state. It might not need to do
+ anything depending on the platform and compiler, so we have a static
+ flag to make sure it gets called before cpp_reader_init. */
+
+static int cpp_init_completed = 0;
+
void
-cpp_init (void)
+cpp_init ()
{
#ifdef HOST_EBCDIC
- /* For non-ASCII hosts, the array needs to be sorted at runtime. */
+ /* For non-ASCII hosts, the cl_options array needs to be sorted at
+ runtime. */
qsort (cl_options, N_OPTS, sizeof (struct cl_option), opt_comp);
#endif
- /* Set up the IStable. This doesn't do anything if we were compiled
- with a compiler that supports C99 designated initializers. */
+ /* Set up the trigraph map and the IStable. These don't need to do
+ anything if we were compiled with a compiler that supports C99
+ designated initializers. */
+ init_trigraph_map ();
init_IStable ();
+
+ cpp_init_completed = 1;
}
/* Initialize a cpp_reader structure. */
CPP_OPTION (pfile, pending) =
(struct cpp_pending *) xcalloc (1, sizeof (struct cpp_pending));
+ /* If cpp_init hasn't been called, generate a fatal error (by hand)
+ and call it here. */
+ if (!cpp_init_completed)
+ {
+ fputs ("cpp_reader_init: internal error: cpp_init not called.\n", stderr);
+ pfile->errors = CPP_FATAL_LIMIT;
+ cpp_init ();
+ }
+
_cpp_init_macros (pfile);
_cpp_init_stacks (pfile);
_cpp_init_includes (pfile);
cpp_cleanup (pfile)
cpp_reader *pfile;
{
+ struct file_name_list *dir, *next;
+
while (CPP_BUFFER (pfile) != NULL)
cpp_pop_buffer (pfile);
_cpp_cleanup_includes (pfile);
_cpp_cleanup_stacks (pfile);
_cpp_cleanup_macros (pfile);
+
+ for (dir = CPP_OPTION (pfile, quote_include); dir; dir = next)
+ {
+ next = dir->next;
+ free (dir->name);
+ free (dir);
+ }
}
cpp_reader *pfile;
{
const struct builtin *b;
+
for(b = builtin_array; b < builtin_array_end; b++)
{
if (b->flags & CPLUS && ! CPP_OPTION (pfile, cplusplus))
if (b->flags & VERS)
{
- /* Allocate enough space for 'name="value"\0'. */
- str = xmalloc (b->len + strlen (version_string) + 4);
- sprintf (str, "%s=\"%s\"", b->name, version_string);
+ /* Allocate enough space for 'name "value"\n\0'. */
+ str = alloca (b->len + strlen (version_string) + 5);
+ sprintf (str, "%s \"%s\"\n", b->name, version_string);
}
else
{
if (b->flags & ULP)
- val = user_label_prefix;
+ val = CPP_OPTION (pfile, user_label_prefix);
else
val = b->value;
- /* Allocate enough space for "name=value\0". */
- str = xmalloc (b->len + strlen (val) + 2);
- sprintf(str, "%s=%s", b->name, val);
+ /* Allocate enough space for "name value\n\0". */
+ str = alloca (b->len + strlen (val) + 3);
+ sprintf(str, "%s %s\n", b->name, val);
}
- cpp_define (pfile, str);
- free (str);
+ _cpp_define_builtin (pfile, str);
}
else
{
&& !CPP_OPTION (pfile, no_standard_cplusplus_includes)))
{
/* Does this dir start with the prefix? */
- if (!strncmp (p->fname, default_prefix, default_len))
+ if (!memcmp (p->fname, default_prefix, default_len))
{
/* Yes; change prefix and add to search list. */
int flen = strlen (p->fname);
CPP_OPTION (pfile, warn_paste) = 0;
/* Set this if it hasn't been set already. */
- if (user_label_prefix == NULL)
- user_label_prefix = USER_LABEL_PREFIX;
+ if (CPP_OPTION (pfile, user_label_prefix) == NULL)
+ CPP_OPTION (pfile, user_label_prefix) = USER_LABEL_PREFIX;
/* Figure out if we need to save function macro parameter spellings.
We don't use CPP_PEDANTIC() here because that depends on whether
md = (mn + mx) / 2;
opt_len = cl_options[md].opt_len;
- comp = strncmp (input, cl_options[md].opt_text, opt_len);
+ comp = memcmp (input, cl_options[md].opt_text, opt_len);
if (comp > 0)
mn = md + 1;
for (; mn < N_OPTS; mn++)
{
opt_len = cl_options[mn].opt_len;
- if (strncmp (input, cl_options[mn].opt_text, opt_len))
+ if (memcmp (input, cl_options[mn].opt_text, opt_len))
break;
if (input[opt_len] == '\0')
return mn;
case N_OPTS: /* shut GCC up */
break;
case OPT_fleading_underscore:
- user_label_prefix = "_";
+ CPP_OPTION (pfile, user_label_prefix) = "_";
break;
case OPT_fno_leading_underscore:
- user_label_prefix = "";
+ CPP_OPTION (pfile, user_label_prefix) = "";
break;
case OPT_fpreprocessed:
CPP_OPTION (pfile, preprocessed) = 1;