Commit 6de1e2a9 by Zack Weinberg Committed by Zack Weinberg

cpplib.c: Kill define of STDC_VALUE.

1999-02-18 18:32 -0500  Zack Weinberg  <zack@rabi.columbia.edu>
	* cpplib.c: Kill define of STDC_VALUE.  Don't include output.h
          or prefix.h. Change CPP_IS_MACRO_BUFFER to not refer to
          macro_cleanup.
	  (GET_ENV_PATH_LIST, PATH_SEPARATOR, STANDARD_INCLUDE_DIR,
          predefs, SIZE_TYPE, PTRDIFF_TYPE, WCHAR_TYPE,
          CPP_WCHAR_TYPE, USER_LABEL_PREFIX, REGISTER_PREFIX, struct
          cpp_pending, version_string, struct default_include,
          include_defaults_array, path_include, cpp_options_init,
          dump_special_to_buffer, initialize_builtins, cpp_start_read,
          cpp_reader_init, nreverse_pending, push_pending, print_help,
          cpp_handle_option, cpp_handle_options, cpp_finish,
          cpp_cleanup): Move to cppinit.c.
	  (macro_cleanup, struct arglist, collect_expansion,
	  create_definition, compare_defs, comp_def_part, ARG_BASE,
	  struct argdata, macarg, change_newlines, timestamp,
	  monthnames, special_symbol, unsafe_chars, macroexpand,
	  push_macro_expansion): Move to cpphash.c.
	  (quote_string, check_macro_name, cpp_expand_to_buffer,
	  output_line_command, cpp_undef): Export.
	  (null_underflow, null_cleanup, handle_directive): Make static.
	* cpplib.h: Prototype now-exported functions.  Adjust decls of
          syntax tables so we can include cpplib.h in cppinit.c.
	* cpphash.h: Prototype all functions exported by cpphash.c.
	* cppinit.c: Make syntax tables initialized data if possible
          (uses GCC designated-initializer extension).
	* cppexp.c:  Make cpp_lex static.
	* Makefile.in: Move -D switches for the various include dirs
          from cpplib.o rule to cppinit.o rule.  Adjust dependencies.

From-SVN: r25287
parent 43c5ec70
1999-02-18 18:32 -0500 Zack Weinberg <zack@rabi.columbia.edu>
* cpplib.c: Kill define of STDC_VALUE. Don't include output.h
or prefix.h. Change CPP_IS_MACRO_BUFFER to not refer to
macro_cleanup.
(GET_ENV_PATH_LIST, PATH_SEPARATOR, STANDARD_INCLUDE_DIR,
predefs, SIZE_TYPE, PTRDIFF_TYPE, WCHAR_TYPE,
CPP_WCHAR_TYPE, USER_LABEL_PREFIX, REGISTER_PREFIX, struct
cpp_pending, version_string, struct default_include,
include_defaults_array, path_include, cpp_options_init,
dump_special_to_buffer, initialize_builtins, cpp_start_read,
cpp_reader_init, nreverse_pending, push_pending, print_help,
cpp_handle_option, cpp_handle_options, cpp_finish,
cpp_cleanup): Move to cppinit.c.
(macro_cleanup, struct arglist, collect_expansion,
create_definition, compare_defs, comp_def_part, ARG_BASE,
struct argdata, macarg, change_newlines, timestamp,
monthnames, special_symbol, unsafe_chars, macroexpand,
push_macro_expansion): Move to cpphash.c.
(quote_string, check_macro_name, cpp_expand_to_buffer,
output_line_command, cpp_undef): Export.
(null_underflow, null_cleanup, handle_directive): Make static.
* cpplib.h: Prototype now-exported functions. Adjust decls of
syntax tables so we can include cpplib.h in cppinit.c.
* cpphash.h: Prototype all functions exported by cpphash.c.
* cppinit.c: Make syntax tables initialized data if possible
(uses GCC designated-initializer extension).
* cppexp.c: Make cpp_lex static.
* Makefile.in: Move -D switches for the various include dirs
from cpplib.o rule to cppinit.o rule. Adjust dependencies.
Thu Feb 18 13:15:56 1999 Marc Espie <espie@cvs.openbsd.org>
* alpha/openbsd.h: New file.
......
......@@ -1970,23 +1970,23 @@ cppmain$(exeext): cppmain.o libcpp.a $(LIBDEPS)
cppmain.o: cppmain.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
cpplib.o: cpplib.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h cpphash.h \
prefix.h output.h Makefile
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
-DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \
-DLOCAL_INCLUDE_DIR=\"$(includedir)\" \
-DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
-c `echo $(srcdir)/cpplib.c | sed 's,^\./,,'`
cppulp.o: cppulp.c $(CONFIG_H) system.h output.h
cpplib.o: cpplib.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h cpphash.h
cpphash.o: cpphash.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h cpphash.h
cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
cpperror.o: cpperror.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
cppexp.o: cppexp.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
cppinit.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h
cppinit.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h machmode.h system.h \
cpphash.h prefix.h output.h Makefile
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
-DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \
-DLOCAL_INCLUDE_DIR=\"$(includedir)\" \
-DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
-c `echo $(srcdir)/cppinit.c | sed 's,^\./,,'`
# Note for the stamp targets, we run the program `true' instead of
# having an empty command (nothing following the semicolon).
......
......@@ -376,7 +376,7 @@ static struct token tokentab2[] = {
/* Read one token. */
struct operation
static struct operation
cpp_lex (pfile, skip_evaluation)
cpp_reader *pfile;
int skip_evaluation;
......
/* Part of CPP library. (Macro hash table support.)
/* Part of CPP library. (Macro handling.)
Copyright (C) 1986, 87, 89, 92-95, 1996, 1998 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
......@@ -29,6 +29,63 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static HASHNODE *hashtab[HASHSIZE];
static int comp_def_part PARAMS ((int, U_CHAR *, int, U_CHAR *,
int, int));
static int change_newlines PARAMS ((U_CHAR *, int));
static void push_macro_expansion PARAMS ((cpp_reader *,
U_CHAR *, int, HASHNODE *));
static int unsafe_chars PARAMS ((int, int));
#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
#define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N))
extern char *version_string;
/* The arglist structure is built by create_definition to tell
collect_expansion where the argument names begin. That
is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
would contain pointers to the strings x, y, and z.
collect_expansion would then build a DEFINITION node,
with reflist nodes pointing to the places x, y, and z had
appeared. So the arglist is just convenience data passed
between these two routines. It is not kept around after
the current #define has been processed and entered into the
hash table. */
struct arglist
{
struct arglist *next;
U_CHAR *name;
int length;
int argno;
char rest_args;
};
/* This structure represents one parsed argument in a macro call.
`raw' points to the argument text as written (`raw_length' is its length).
`expanded' points to the argument's macro-expansion
(its length is `expand_length').
`stringified_length' is the length the argument would have
if stringified.
`use_count' is the number of times this macro arg is substituted
into the macro. If the actual use count exceeds 10,
the value stored is 10. */
/* raw and expanded are relative to ARG_BASE */
#define ARG_BASE ((pfile)->token_buffer)
struct argdata
{
/* Strings relative to pfile->token_buffer */
long raw, expanded, stringified;
int raw_length, expand_length;
int stringified_length;
char newlines;
char use_count;
};
/* Return hash function on name. must be compatible with the one
computed a step at a time, elsewhere */
......@@ -67,7 +124,7 @@ cpp_lookup (pfile, name, len, hash)
if (len < 0)
{
for (bp = name; is_idchar[*bp]; bp++) ;
for (bp = name; is_idchar[*bp]; bp++);
len = bp - name;
}
......@@ -75,7 +132,8 @@ cpp_lookup (pfile, name, len, hash)
hash = hashf (name, len, HASHSIZE);
bucket = hashtab[hash];
while (bucket) {
while (bucket)
{
if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
return bucket;
bucket = bucket->next;
......@@ -155,7 +213,8 @@ install (name, len, type, value, hash)
register int i, bucket;
register U_CHAR *p;
if (len < 0) {
if (len < 0)
{
p = name;
while (is_idchar[*p])
p++;
......@@ -188,9 +247,1426 @@ cpp_hash_cleanup (pfile)
cpp_reader *pfile ATTRIBUTE_UNUSED;
{
register int i;
for (i = HASHSIZE; --i >= 0; )
for (i = HASHSIZE; --i >= 0;)
{
while (hashtab[i])
delete_macro (hashtab[i]);
}
}
static int
macro_cleanup (pbuf, pfile)
cpp_buffer *pbuf;
cpp_reader *pfile ATTRIBUTE_UNUSED;
{
HASHNODE *macro = (HASHNODE *) pbuf->data;
if (macro->type == T_DISABLED)
macro->type = T_MACRO;
if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
free (pbuf->buf);
return 0;
}
/* Read a replacement list for a macro with parameters.
Build the DEFINITION structure.
Reads characters of text starting at BUF until END.
ARGLIST specifies the formal parameters to look for
in the text of the definition; NARGS is the number of args
in that list, or -1 for a macro name that wants no argument list.
MACRONAME is the macro name itself (so we can avoid recursive expansion)
and NAMELEN is its length in characters.
Note that comments, backslash-newlines, and leading white space
have already been deleted from the argument. */
static DEFINITION *
collect_expansion (pfile, buf, limit, nargs, arglist)
cpp_reader *pfile;
U_CHAR *buf, *limit;
int nargs;
struct arglist *arglist;
{
DEFINITION *defn;
register U_CHAR *p, *lastp, *exp_p;
struct reflist *endpat = NULL;
/* Pointer to first nonspace after last ## seen. */
U_CHAR *concat = 0;
/* Pointer to first nonspace after last single-# seen. */
U_CHAR *stringify = 0;
int maxsize;
int expected_delimiter = '\0';
/* Scan thru the replacement list, ignoring comments and quoted
strings, picking up on the macro calls. It does a linear search
thru the arg list on every potential symbol. Profiling might say
that something smarter should happen. */
if (limit < buf)
abort ();
/* Find the beginning of the trailing whitespace. */
p = buf;
while (p < limit && is_space[limit[-1]])
limit--;
/* Allocate space for the text in the macro definition.
Leading and trailing whitespace chars need 2 bytes each.
Each other input char may or may not need 1 byte,
so this is an upper bound. The extra 5 are for invented
leading and trailing newline-marker and final null. */
maxsize = (sizeof (DEFINITION)
+ (limit - p) + 5);
/* Occurrences of '@' get doubled, so allocate extra space for them. */
while (p < limit)
if (*p++ == '@')
maxsize++;
defn = (DEFINITION *) xcalloc (1, maxsize);
defn->nargs = nargs;
exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
lastp = exp_p;
p = buf;
/* Add one initial space escape-marker to prevent accidental
token-pasting (often removed by macroexpand). */
*exp_p++ = '@';
*exp_p++ = ' ';
if (limit - p >= 2 && p[0] == '#' && p[1] == '#')
{
cpp_error (pfile, "`##' at start of macro definition");
p += 2;
}
/* Process the main body of the definition. */
while (p < limit)
{
int skipped_arg = 0;
register U_CHAR c = *p++;
*exp_p++ = c;
if (!CPP_TRADITIONAL (pfile))
{
switch (c)
{
case '\'':
case '\"':
if (expected_delimiter != '\0')
{
if (c == expected_delimiter)
expected_delimiter = '\0';
}
else
expected_delimiter = c;
break;
case '\\':
if (p < limit && expected_delimiter)
{
/* In a string, backslash goes through
and makes next char ordinary. */
*exp_p++ = *p++;
}
break;
case '@':
/* An '@' in a string or character constant stands for itself,
and does not need to be escaped. */
if (!expected_delimiter)
*exp_p++ = c;
break;
case '#':
/* # is ordinary inside a string. */
if (expected_delimiter)
break;
if (p < limit && *p == '#')
{
/* ##: concatenate preceding and following tokens. */
/* Take out the first #, discard preceding whitespace. */
exp_p--;
while (exp_p > lastp && is_hor_space[exp_p[-1]])
--exp_p;
/* Skip the second #. */
p++;
/* Discard following whitespace. */
SKIP_WHITE_SPACE (p);
concat = p;
if (p == limit)
cpp_error (pfile, "`##' at end of macro definition");
}
else if (nargs >= 0)
{
/* Single #: stringify following argument ref.
Don't leave the # in the expansion. */
exp_p--;
SKIP_WHITE_SPACE (p);
if (p == limit || !is_idstart[*p]
|| (*p == 'L' && p + 1 < limit && (p[1] == '\'' ||
p[1] == '"')))
cpp_error (pfile,
"`#' operator is not followed by a macro argument name");
else
stringify = p;
}
break;
}
}
else
{
/* In -traditional mode, recognize arguments inside strings and
character constants, and ignore special properties of #.
Arguments inside strings are considered "stringified", but no
extra quote marks are supplied. */
switch (c)
{
case '\'':
case '\"':
if (expected_delimiter != '\0')
{
if (c == expected_delimiter)
expected_delimiter = '\0';
}
else
expected_delimiter = c;
break;
case '\\':
/* Backslash quotes delimiters and itself,
but not macro args. */
if (expected_delimiter != 0 && p < limit
&& (*p == expected_delimiter || *p == '\\'))
{
*exp_p++ = *p++;
continue;
}
break;
case '/':
if (expected_delimiter != '\0')
/* No comments inside strings. */
break;
if (*p == '*')
{
/* If we find a comment that wasn't removed by
handle_directive, this must be -traditional.
So replace the comment with nothing at all. */
exp_p--;
p += 1;
while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
p++;
#if 0
/* Mark this as a concatenation-point,
as if it had been ##. */
concat = p;
#endif
}
break;
}
}
/* Handle the start of a symbol. */
if (is_idchar[c] && nargs > 0)
{
U_CHAR *id_beg = p - 1;
int id_len;
--exp_p;
while (p != limit && is_idchar[*p])
p++;
id_len = p - id_beg;
if (is_idstart[c]
&& !(id_len == 1 && c == 'L' && (*p == '\'' || *p == '"')))
{
register struct arglist *arg;
for (arg = arglist; arg != NULL; arg = arg->next)
{
struct reflist *tpat;
if (arg->name[0] == c
&& arg->length == id_len
&& strncmp (arg->name, id_beg, id_len) == 0)
{
if (expected_delimiter && CPP_OPTIONS
(pfile)->warn_stringify)
{
if (CPP_TRADITIONAL (pfile))
{
cpp_warning (pfile,
"macro argument `%.*s' is stringified.",
id_len, arg->name);
}
else
{
cpp_warning (pfile,
"macro arg `%.*s' would be stringified with -traditional.",
id_len, arg->name);
}
}
/* If ANSI, don't actually substitute
inside a string. */
if (!CPP_TRADITIONAL (pfile) && expected_delimiter)
break;
/* make a pat node for this arg and append it
to the end of the pat list */
tpat = (struct reflist *)
xmalloc (sizeof (struct reflist));
tpat->next = NULL;
tpat->raw_before = concat == id_beg;
tpat->raw_after = 0;
tpat->rest_args = arg->rest_args;
tpat->stringify = (CPP_TRADITIONAL (pfile)
? expected_delimiter != '\0'
: stringify == id_beg);
if (endpat == NULL)
defn->pattern = tpat;
else
endpat->next = tpat;
endpat = tpat;
tpat->argno = arg->argno;
tpat->nchars = exp_p - lastp;
{
register U_CHAR *p1 = p;
SKIP_WHITE_SPACE (p1);
if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
tpat->raw_after = 1;
}
lastp = exp_p;
skipped_arg = 1;
break;
}
}
}
/* If this was not a macro arg, copy it into the expansion. */
if (!skipped_arg)
{
register U_CHAR *lim1 = p;
p = id_beg;
while (p != lim1)
*exp_p++ = *p++;
if (stringify == id_beg)
cpp_error (pfile,
"`#' operator should be followed by a macro argument name");
}
}
}
if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0)
{
/* If ANSI, put in a "@ " marker to prevent token pasting.
But not if "inside a string" (which in ANSI mode
happens only for -D option). */
*exp_p++ = '@';
*exp_p++ = ' ';
}
*exp_p = '\0';
defn->length = exp_p - defn->expansion;
/* Crash now if we overrun the allocated size. */
if (defn->length + 1 > maxsize)
abort ();
#if 0
/* This isn't worth the time it takes. */
/* give back excess storage */
defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
#endif
return defn;
}
/*
* special extension string that can be added to the last macro argument to
* allow it to absorb the "rest" of the arguments when expanded. Ex:
* #define wow(a, b...) process (b, a, b)
* { wow (1, 2, 3); } -> { process (2, 3, 1, 2, 3); }
* { wow (one, two); } -> { process (two, one, two); }
* if this "rest_arg" is used with the concat token '##' and if it is not
* supplied then the token attached to with ## will not be outputted. Ex:
* #define wow (a, b...) process (b ## , a, ## b)
* { wow (1, 2); } -> { process (2, 1, 2); }
* { wow (one); } -> { process (one); {
*/
static char rest_extension[] = "...";
#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)
/* Create a DEFINITION node from a #define directive. Arguments are
as for do_define. */
MACRODEF
create_definition (buf, limit, pfile, predefinition)
U_CHAR *buf, *limit;
cpp_reader *pfile;
int predefinition;
{
U_CHAR *bp; /* temp ptr into input buffer */
U_CHAR *symname; /* remember where symbol name starts */
int sym_length; /* and how long it is */
int rest_args = 0;
long line, col;
char *file = CPP_BUFFER (pfile) ? CPP_BUFFER (pfile)->nominal_fname : "";
DEFINITION *defn;
int arglengths = 0; /* Accumulate lengths of arg names
plus number of args. */
MACRODEF mdef;
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
bp = buf;
while (is_hor_space[*bp])
bp++;
symname = bp; /* remember where it starts */
sym_length = check_macro_name (pfile, bp, 0);
bp += sym_length;
/* Lossage will occur if identifiers or control keywords are broken
across lines using backslash. This is not the right place to take
care of that. */
if (*bp == '(')
{
struct arglist *arg_ptrs = NULL;
int argno = 0;
bp++; /* skip '(' */
SKIP_WHITE_SPACE (bp);
/* Loop over macro argument names. */
while (*bp != ')')
{
struct arglist *temp;
temp = (struct arglist *) alloca (sizeof (struct arglist));
temp->name = bp;
temp->next = arg_ptrs;
temp->argno = argno++;
temp->rest_args = 0;
arg_ptrs = temp;
if (rest_args)
cpp_pedwarn (pfile, "another parameter follows `%s'",
rest_extension);
if (!is_idstart[*bp])
cpp_pedwarn (pfile, "invalid character in macro parameter name");
/* Find the end of the arg name. */
while (is_idchar[*bp])
{
bp++;
/* do we have a "special" rest-args extension here? */
if ((size_t) (limit - bp) > REST_EXTENSION_LENGTH
&& !strncmp (rest_extension, bp, REST_EXTENSION_LENGTH))
{
rest_args = 1;
temp->rest_args = 1;
break;
}
}
temp->length = bp - temp->name;
if (rest_args == 1)
bp += REST_EXTENSION_LENGTH;
arglengths += temp->length + 2;
SKIP_WHITE_SPACE (bp);
if (temp->length == 0 || (*bp != ',' && *bp != ')'))
{
cpp_error (pfile,
"badly punctuated parameter list in `#define'");
goto nope;
}
if (*bp == ',')
{
bp++;
SKIP_WHITE_SPACE (bp);
}
if (bp >= limit)
{
cpp_error (pfile, "unterminated parameter list in `#define'");
goto nope;
}
{
struct arglist *otemp;
for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
if (temp->length == otemp->length
&& strncmp (temp->name, otemp->name, temp->length) == 0)
{
U_CHAR *name;
name = (U_CHAR *) alloca (temp->length + 1);
(void) strncpy (name, temp->name, temp->length);
name[temp->length] = '\0';
cpp_error (pfile,
"duplicate argument name `%s' in `#define'",
name);
goto nope;
}
}
}
++bp; /* skip paren */
SKIP_WHITE_SPACE (bp);
/* now everything from bp before limit is the definition. */
defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
defn->rest_args = rest_args;
/* Now set defn->args.argnames to the result of concatenating
the argument names in reverse order
with comma-space between them. */
defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1);
{
struct arglist *temp;
int i = 0;
for (temp = arg_ptrs; temp; temp = temp->next)
{
bcopy (temp->name, &defn->args.argnames[i], temp->length);
i += temp->length;
if (temp->next != 0)
{
defn->args.argnames[i++] = ',';
defn->args.argnames[i++] = ' ';
}
}
defn->args.argnames[i] = 0;
}
}
else
{
/* Simple expansion or empty definition. */
if (bp < limit)
{
if (is_hor_space[*bp])
{
bp++;
SKIP_WHITE_SPACE (bp);
}
else
/* Per C9x, missing white space after the name in a #define
of an object-like macro is always a constraint violation. */
cpp_pedwarn (pfile,
"missing white space after `#define %.*s'",
sym_length, symname);
}
/* now everything from bp before limit is the definition. */
defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
defn->args.argnames = (U_CHAR *) "";
}
defn->line = line;
defn->file = file;
/* OP is null if this is a predefinition */
defn->predefined = predefinition;
mdef.defn = defn;
mdef.symnam = symname;
mdef.symlen = sym_length;
return mdef;
nope:
mdef.defn = 0;
return mdef;
}
/*
* Parse a macro argument and append the info on PFILE's token_buffer.
* REST_ARGS means to absorb the rest of the args.
* Return nonzero to indicate a syntax error.
*/
static enum cpp_token
macarg (pfile, rest_args)
cpp_reader *pfile;
int rest_args;
{
int paren = 0;
enum cpp_token token;
char save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
CPP_OPTIONS (pfile)->put_out_comments = 0;
/* Try to parse as much of the argument as exists at this
input stack level. */
pfile->no_macro_expand++;
for (;;)
{
token = cpp_get_token (pfile);
switch (token)
{
case CPP_EOF:
goto done;
case CPP_POP:
/* If we've hit end of file, it's an error (reported by caller).
Ditto if it's the end of cpp_expand_to_buffer text.
If we've hit end of macro, just continue. */
if (!CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
goto done;
break;
case CPP_LPAREN:
paren++;
break;
case CPP_RPAREN:
if (--paren < 0)
goto found;
break;
case CPP_COMMA:
/* if we've returned to lowest level and
we aren't absorbing all args */
if (paren == 0 && rest_args == 0)
goto found;
break;
found:
/* Remove ',' or ')' from argument buffer. */
CPP_ADJUST_WRITTEN (pfile, -1);
goto done;
default:;
}
}
done:
CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
pfile->no_macro_expand--;
return token;
}
/* Turn newlines to spaces in the string of length LENGTH at START,
except inside of string constants.
The string is copied into itself with its beginning staying fixed. */
static int
change_newlines (start, length)
U_CHAR *start;
int length;
{
register U_CHAR *ibp;
register U_CHAR *obp;
register U_CHAR *limit;
register int c;
ibp = start;
limit = start + length;
obp = start;
while (ibp < limit)
{
*obp++ = c = *ibp++;
switch (c)
{
case '\'':
case '\"':
/* Notice and skip strings, so that we don't
delete newlines in them. */
{
int quotec = c;
while (ibp < limit)
{
*obp++ = c = *ibp++;
if (c == quotec)
break;
if (c == '\n' && quotec == '\'')
break;
}
}
break;
}
}
return obp - start;
}
static struct tm *
timestamp (pfile)
cpp_reader *pfile;
{
if (!pfile->timebuf)
{
time_t t = time ((time_t *) 0);
pfile->timebuf = localtime (&t);
}
return pfile->timebuf;
}
static char *monthnames[] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
/*
* expand things like __FILE__. Place the expansion into the output
* buffer *without* rescanning.
*/
static void
special_symbol (hp, pfile)
HASHNODE *hp;
cpp_reader *pfile;
{
const char *buf;
int len;
cpp_buffer *ip;
switch (hp->type)
{
case T_FILE:
case T_BASE_FILE:
{
ip = CPP_BUFFER (pfile);
if (hp->type == T_BASE_FILE)
{
while (CPP_PREV_BUFFER (ip) != CPP_NULL_BUFFER (pfile))
ip = CPP_PREV_BUFFER (ip);
}
else
{
ip = CPP_BUFFER (pfile);
while (!ip->nominal_fname && ip != CPP_NULL_BUFFER (pfile))
ip = CPP_PREV_BUFFER (ip);
}
buf = ip->nominal_fname;
if (!buf)
buf = "";
CPP_RESERVE (pfile, 3 + 4 * strlen (buf));
quote_string (pfile, buf);
return;
}
case T_INCLUDE_LEVEL:
{
int true_indepth = 0;
ip = CPP_BUFFER (pfile);
for (; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
if (ip->fname != NULL)
true_indepth++;
CPP_RESERVE (pfile, 10);
sprintf (CPP_PWRITTEN (pfile), "%d", true_indepth);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
return;
}
case T_VERSION:
len = strlen (version_string);
CPP_RESERVE (pfile, 3 + len);
CPP_PUTC_Q (pfile, '"');
CPP_PUTS_Q (pfile, version_string, len);
CPP_PUTC_Q (pfile, '"');
CPP_NUL_TERMINATE_Q (pfile);
return;
case T_CONST:
buf = hp->value.cpval;
if (!buf)
return;
if (*buf == '\0')
buf = "@ ";
len = strlen (buf);
CPP_RESERVE (pfile, len + 1);
CPP_PUTS_Q (pfile, buf, len);
CPP_NUL_TERMINATE_Q (pfile);
return;
case T_STDC:
CPP_RESERVE (pfile, 2);
#ifdef STDC_0_IN_SYSTEM_HEADERS
ip = CPP_BUFFER (pfile);
while (!ip->nominal_fname && ip != CPP_NULL_BUFFER (pfile))
ip = CPP_PREV_BUFFER (ip);
if (ip->system_header_p
&& !cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", 15, -1))
CPP_PUTC_Q (pfile, '0');
else
#endif
CPP_PUTC_Q (pfile, '1');
CPP_NUL_TERMINATE_Q (pfile);
return;
case T_SPECLINE:
{
long line;
cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, NULL);
CPP_RESERVE (pfile, 10);
sprintf (CPP_PWRITTEN (pfile), "%ld", line);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
return;
}
case T_DATE:
case T_TIME:
{
struct tm *timebuf;
CPP_RESERVE (pfile, 20);
timebuf = timestamp (pfile);
if (hp->type == T_DATE)
sprintf (CPP_PWRITTEN (pfile), "\"%s %2d %4d\"",
monthnames[timebuf->tm_mon],
timebuf->tm_mday, timebuf->tm_year + 1900);
else
sprintf (CPP_PWRITTEN (pfile), "\"%02d:%02d:%02d\"",
timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
return;
}
default:
cpp_fatal (pfile, "cpplib internal error: invalid special hash type");
return;
}
/* This point should be unreachable. */
abort ();
}
/* Expand a macro call.
HP points to the symbol that is the macro being called.
Put the result of expansion onto the input stack
so that subsequent input by our caller will use it.
If macro wants arguments, caller has already verified that
an argument list follows; arguments come from the input stack. */
void
macroexpand (pfile, hp)
cpp_reader *pfile;
HASHNODE *hp;
{
int nargs;
DEFINITION *defn;
register U_CHAR *xbuf;
long start_line, start_column;
int xbuf_len;
struct argdata *args;
long old_written = CPP_WRITTEN (pfile);
#if 0
int start_line = instack[indepth].lineno;
#endif
int rest_args, rest_zero;
register int i;
#if 0
/* This macro is being used inside a #if, which means it must be */
/* recorded as a precondition. */
if (pcp_inside_if && pcp_outfile && defn->predefined)
dump_single_macro (hp, pcp_outfile);
#endif
cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
/* Check for and handle special symbols. */
if (hp->type != T_MACRO)
{
special_symbol (hp, pfile);
xbuf_len = CPP_WRITTEN (pfile) - old_written;
xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
CPP_SET_WRITTEN (pfile, old_written);
bcopy (CPP_PWRITTEN (pfile), xbuf, xbuf_len + 1);
push_macro_expansion (pfile, xbuf, xbuf_len, hp);
CPP_BUFFER (pfile)->has_escapes = 1;
return;
}
defn = hp->value.defn;
nargs = defn->nargs;
pfile->output_escapes++;
if (nargs >= 0)
{
enum cpp_token token;
args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
for (i = 0; i < nargs; i++)
{
args[i].raw = args[i].expanded = 0;
args[i].raw_length = 0;
args[i].expand_length = args[i].stringified_length = -1;
args[i].use_count = 0;
}
/* Parse all the macro args that are supplied. I counts them.
The first NARGS args are stored in ARGS.
The rest are discarded. If rest_args is set then we assume
macarg absorbed the rest of the args. */
i = 0;
rest_args = 0;
rest_args = 0;
FORWARD (1); /* Discard open-parenthesis before first arg. */
do
{
if (rest_args)
continue;
if (i < nargs || (nargs == 0 && i == 0))
{
/* if we are working on last arg which absorbs rest of args... */
if (i == nargs - 1 && defn->rest_args)
rest_args = 1;
args[i].raw = CPP_WRITTEN (pfile);
token = macarg (pfile, rest_args);
args[i].raw_length = CPP_WRITTEN (pfile) - args[i].raw;
args[i].newlines = 0; /* FIXME */
}
else
token = macarg (pfile, 0);
if (token == CPP_EOF || token == CPP_POP)
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated macro call");
return;
}
i++;
}
while (token == CPP_COMMA);
/* If we got one arg but it was just whitespace, call that 0 args. */
if (i == 1)
{
register U_CHAR *bp = ARG_BASE + args[0].raw;
register U_CHAR *lim = bp + args[0].raw_length;
/* cpp.texi says for foo ( ) we provide one argument.
However, if foo wants just 0 arguments, treat this as 0. */
if (nargs == 0)
while (bp != lim && is_space[*bp])
bp++;
if (bp == lim)
i = 0;
}
/* Don't output an error message if we have already output one for
a parse error above. */
rest_zero = 0;
if (nargs == 0 && i > 0)
{
cpp_error (pfile, "arguments given to macro `%s'", hp->name);
}
else if (i < nargs)
{
/* traditional C allows foo() if foo wants one argument. */
if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile))
;
/* the rest args token is allowed to absorb 0 tokens */
else if (i == nargs - 1 && defn->rest_args)
rest_zero = 1;
else if (i == 0)
cpp_error (pfile, "macro `%s' used without args", hp->name);
else if (i == 1)
cpp_error (pfile, "macro `%s' used with just one arg", hp->name);
else
cpp_error (pfile, "macro `%s' used with only %d args",
hp->name, i);
}
else if (i > nargs)
{
cpp_error (pfile,
"macro `%s' used with too many (%d) args", hp->name, i);
}
}
/* If macro wants zero args, we parsed the arglist for checking only.
Read directly from the macro definition. */
if (nargs <= 0)
{
xbuf = defn->expansion;
xbuf_len = defn->length;
}
else
{
register U_CHAR *exp = defn->expansion;
register int offset; /* offset in expansion,
copied a piece at a time */
register int totlen; /* total amount of exp buffer filled so far */
register struct reflist *ap, *last_ap;
/* Macro really takes args. Compute the expansion of this call. */
/* Compute length in characters of the macro's expansion.
Also count number of times each arg is used. */
xbuf_len = defn->length;
for (ap = defn->pattern; ap != NULL; ap = ap->next)
{
if (ap->stringify)
{
register struct argdata *arg = &args[ap->argno];
/* Stringify if it hasn't already been */
if (arg->stringified_length < 0)
{
int arglen = arg->raw_length;
int escaped = 0;
int in_string = 0;
int c;
/* Initially need_space is -1. Otherwise, 1 means the
previous character was a space, but we suppressed it;
0 means the previous character was a non-space. */
int need_space = -1;
i = 0;
arg->stringified = CPP_WRITTEN (pfile);
if (!CPP_TRADITIONAL (pfile))
CPP_PUTC (pfile, '\"'); /* insert beginning quote */
for (; i < arglen; i++)
{
c = (ARG_BASE + arg->raw)[i];
if (!in_string)
{
/* Internal sequences of whitespace are
replaced by one space except within
a string or char token. */
if (is_space[c])
{
if (CPP_WRITTEN (pfile) > (unsigned) arg->stringified
&& (CPP_PWRITTEN (pfile))[-1] == '@')
{
/* "@ " escape markers are removed */
CPP_ADJUST_WRITTEN (pfile, -1);
continue;
}
if (need_space == 0)
need_space = 1;
continue;
}
else if (need_space > 0)
CPP_PUTC (pfile, ' ');
need_space = 0;
}
if (escaped)
escaped = 0;
else
{
if (c == '\\')
escaped = 1;
if (in_string)
{
if (c == in_string)
in_string = 0;
}
else if (c == '\"' || c == '\'')
in_string = c;
}
/* Escape these chars */
if (c == '\"' || (in_string && c == '\\'))
CPP_PUTC (pfile, '\\');
if (ISPRINT (c))
CPP_PUTC (pfile, c);
else
{
CPP_RESERVE (pfile, 4);
sprintf ((char *) CPP_PWRITTEN (pfile), "\\%03o",
(unsigned int) c);
CPP_ADJUST_WRITTEN (pfile, 4);
}
}
if (!CPP_TRADITIONAL (pfile))
CPP_PUTC (pfile, '\"'); /* insert ending quote */
arg->stringified_length
= CPP_WRITTEN (pfile) - arg->stringified;
}
xbuf_len += args[ap->argno].stringified_length;
}
else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
/* Add 4 for two newline-space markers to prevent
token concatenation. */
xbuf_len += args[ap->argno].raw_length + 4;
else
{
/* We have an ordinary (expanded) occurrence of the arg.
So compute its expansion, if we have not already. */
if (args[ap->argno].expand_length < 0)
{
args[ap->argno].expanded = CPP_WRITTEN (pfile);
cpp_expand_to_buffer (pfile,
ARG_BASE + args[ap->argno].raw,
args[ap->argno].raw_length);
args[ap->argno].expand_length
= CPP_WRITTEN (pfile) - args[ap->argno].expanded;
}
/* Add 4 for two newline-space markers to prevent
token concatenation. */
xbuf_len += args[ap->argno].expand_length + 4;
}
if (args[ap->argno].use_count < 10)
args[ap->argno].use_count++;
}
xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
/* Generate in XBUF the complete expansion
with arguments substituted in.
TOTLEN is the total size generated so far.
OFFSET is the index in the definition
of where we are copying from. */
offset = totlen = 0;
for (last_ap = NULL, ap = defn->pattern; ap != NULL;
last_ap = ap, ap = ap->next)
{
register struct argdata *arg = &args[ap->argno];
int count_before = totlen;
/* Add chars to XBUF. */
for (i = 0; i < ap->nchars; i++, offset++)
xbuf[totlen++] = exp[offset];
/* If followed by an empty rest arg with concatenation,
delete the last run of nonwhite chars. */
if (rest_zero && totlen > count_before
&& ((ap->rest_args && ap->raw_before)
|| (last_ap != NULL && last_ap->rest_args
&& last_ap->raw_after)))
{
/* Delete final whitespace. */
while (totlen > count_before && is_space[xbuf[totlen - 1]])
totlen--;
/* Delete the nonwhites before them. */
while (totlen > count_before && !is_space[xbuf[totlen - 1]])
totlen--;
}
if (ap->stringify != 0)
{
bcopy (ARG_BASE + arg->stringified,
xbuf + totlen, arg->stringified_length);
totlen += arg->stringified_length;
}
else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
{
U_CHAR *p1 = ARG_BASE + arg->raw;
U_CHAR *l1 = p1 + arg->raw_length;
if (ap->raw_before)
{
while (p1 != l1 && is_space[*p1])
p1++;
while (p1 != l1 && is_idchar[*p1])
xbuf[totlen++] = *p1++;
}
if (ap->raw_after)
{
/* Arg is concatenated after: delete trailing whitespace,
whitespace markers, and no-reexpansion markers. */
while (p1 != l1)
{
if (is_space[l1[-1]])
l1--;
else if (l1[-1] == '@')
{
U_CHAR *p2 = l1 - 1;
/* If whitespace is preceded by an odd number
of `@' signs, the last `@' was a whitespace
marker; drop it too. */
while (p2 != p1 && p2[0] == '@')
p2--;
if ((l1 - p2) & 1)
l1--;
break;
}
else if (l1[-1] == '-')
{
U_CHAR *p2 = l1 - 1;
/* If a `-' is preceded by an odd number of
`@' signs then it and the last `@' are
a no-reexpansion marker. */
while (p2 != p1 && p2[0] == '@')
p2--;
if ((l1 - p2) & 1)
l1 -= 2;
else
break;
}
else
break;
}
}
/* Delete any no-reexpansion marker that precedes
an identifier at the beginning of the argument. */
if (p1[0] == '@' && p1[1] == '-')
p1 += 2;
bcopy (p1, xbuf + totlen, l1 - p1);
totlen += l1 - p1;
}
else
{
U_CHAR *expanded = ARG_BASE + arg->expanded;
if (!ap->raw_before && totlen > 0 && arg->expand_length
&& !CPP_TRADITIONAL (pfile)
&& unsafe_chars (xbuf[totlen - 1], expanded[0]))
{
xbuf[totlen++] = '@';
xbuf[totlen++] = ' ';
}
bcopy (expanded, xbuf + totlen, arg->expand_length);
totlen += arg->expand_length;
if (!ap->raw_after && totlen > 0 && offset < defn->length
&& !CPP_TRADITIONAL (pfile)
&& unsafe_chars (xbuf[totlen - 1], exp[offset]))
{
xbuf[totlen++] = '@';
xbuf[totlen++] = ' ';
}
/* If a macro argument with newlines is used multiple times,
then only expand the newlines once. This avoids creating
output lines which don't correspond to any input line,
which confuses gdb and gcov. */
if (arg->use_count > 1 && arg->newlines > 0)
{
/* Don't bother doing change_newlines for subsequent
uses of arg. */
arg->use_count = 1;
arg->expand_length
= change_newlines (expanded, arg->expand_length);
}
}
if (totlen > xbuf_len)
abort ();
}
/* if there is anything left of the definition
after handling the arg list, copy that in too. */
for (i = offset; i < defn->length; i++)
{
/* if we've reached the end of the macro */
if (exp[i] == ')')
rest_zero = 0;
if (!(rest_zero && last_ap != NULL && last_ap->rest_args
&& last_ap->raw_after))
xbuf[totlen++] = exp[i];
}
xbuf[totlen] = 0;
xbuf_len = totlen;
}
pfile->output_escapes--;
/* Now put the expansion on the input stack
so our caller will commence reading from it. */
push_macro_expansion (pfile, xbuf, xbuf_len, hp);
CPP_BUFFER (pfile)->has_escapes = 1;
/* Pop the space we've used in the token_buffer for argument expansion. */
CPP_SET_WRITTEN (pfile, old_written);
/* Recursive macro use sometimes works traditionally.
#define foo(x,y) bar (x (y,0), y)
foo (foo, baz) */
if (!CPP_TRADITIONAL (pfile))
hp->type = T_DISABLED;
}
/* Return 1 iff a token ending in C1 followed directly by a token C2
could cause mis-tokenization. */
static int
unsafe_chars (c1, c2)
int c1, c2;
{
switch (c1)
{
case '+':
case '-':
if (c2 == c1 || c2 == '=')
return 1;
goto letter;
case '.': case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7': case '8':
case '9': case 'e': case 'E': case 'p': case 'P':
if (c2 == '-' || c2 == '+')
return 1; /* could extend a pre-processing number */
goto letter;
case 'L':
if (c2 == '\'' || c2 == '\"')
return 1; /* Could turn into L"xxx" or L'xxx'. */
goto letter;
case '_': case 'a': case 'b': case 'c': case 'd': case 'f':
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
case 'm': case 'n': case 'o': case 'q': case 'r': case 's':
case 't': case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z': case 'A': case 'B': case 'C': case 'D': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K': case 'M':
case 'N': case 'O': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
letter:
/* We're in the middle of either a name or a pre-processing number. */
return (is_idchar[c2] || c2 == '.');
case '<': case '>': case '!': case '%': case '#': case ':':
case '^': case '&': case '|': case '*': case '/': case '=':
return (c2 == c1 || c2 == '=');
}
return 0;
}
static void
push_macro_expansion (pfile, xbuf, xbuf_len, hp)
cpp_reader *pfile;
register U_CHAR *xbuf;
int xbuf_len;
HASHNODE *hp;
{
register cpp_buffer *mbuf = cpp_push_buffer (pfile, xbuf, xbuf_len);
if (mbuf == NULL)
return;
mbuf->cleanup = macro_cleanup;
mbuf->data = hp;
/* The first chars of the expansion should be a "@ " added by
collect_expansion. This is to prevent accidental token-pasting
between the text preceding the macro invocation, and the macro
expansion text.
We would like to avoid adding unneeded spaces (for the sake of
tools that use cpp, such as imake). In some common cases we can
tell that it is safe to omit the space.
The character before the macro invocation cannot have been an
idchar (or else it would have been pasted with the idchars of
the macro name). Therefore, if the first non-space character
of the expansion is an idchar, we do not need the extra space
to prevent token pasting.
Also, we don't need the extra space if the first char is '(',
or some other (less common) characters. */
if (xbuf[0] == '@' && xbuf[1] == ' '
&& (is_idchar[xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
|| xbuf[2] == '\"'))
mbuf->cur += 2;
/* Likewise, avoid the extra space at the end of the macro expansion
if this is safe. We can do a better job here since we can know
what the next char will be. */
if (xbuf_len >= 3
&& mbuf->rlimit[-2] == '@'
&& mbuf->rlimit[-1] == ' ')
{
int c1 = mbuf->rlimit[-3];
int c2 = CPP_BUF_PEEK (CPP_PREV_BUFFER (CPP_BUFFER (pfile)));
if (c2 == EOF || !unsafe_chars (c1, c2))
mbuf->rlimit -= 2;
}
}
/* Return zero if two DEFINITIONs are isomorphic. */
int
compare_defs (pfile, d1, d2)
cpp_reader *pfile;
DEFINITION *d1, *d2;
{
register struct reflist *a1, *a2;
register U_CHAR *p1 = d1->expansion;
register U_CHAR *p2 = d2->expansion;
int first = 1;
if (d1->nargs != d2->nargs)
return 1;
if (CPP_PEDANTIC (pfile)
&& strcmp ((char *) d1->args.argnames, (char *) d2->args.argnames))
return 1;
for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
a1 = a1->next, a2 = a2->next)
{
if (!((a1->nchars == a2->nchars && !strncmp (p1, p2, a1->nchars))
|| !comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
|| a1->argno != a2->argno
|| a1->stringify != a2->stringify
|| a1->raw_before != a2->raw_before
|| a1->raw_after != a2->raw_after)
return 1;
first = 0;
p1 += a1->nchars;
p2 += a2->nchars;
}
if (a1 != a2)
return 1;
return comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
p2, d2->length - (p2 - d2->expansion), 1);
}
/* Return 1 if two parts of two macro definitions are effectively different.
One of the parts starts at BEG1 and has LEN1 chars;
the other has LEN2 chars at BEG2.
Any sequence of whitespace matches any other sequence of whitespace.
FIRST means these parts are the first of a macro definition;
so ignore leading whitespace entirely.
LAST means these parts are the last of a macro definition;
so ignore trailing whitespace entirely. */
static int
comp_def_part (first, beg1, len1, beg2, len2, last)
int first;
U_CHAR *beg1, *beg2;
int len1, len2;
int last;
{
register U_CHAR *end1 = beg1 + len1;
register U_CHAR *end2 = beg2 + len2;
if (first)
{
while (beg1 != end1 && is_space[*beg1])
beg1++;
while (beg2 != end2 && is_space[*beg2])
beg2++;
}
if (last)
{
while (beg1 != end1 && is_space[end1[-1]])
end1--;
while (beg2 != end2 && is_space[end2[-1]])
end2--;
}
while (beg1 != end1 && beg2 != end2)
{
if (is_space[*beg1] && is_space[*beg2])
{
while (beg1 != end1 && is_space[*beg1])
beg1++;
while (beg2 != end2 && is_space[*beg2])
beg2++;
}
else if (*beg1 == *beg2)
{
beg1++;
beg2++;
}
else
break;
}
return (beg1 != end1) || (beg2 != end2);
}
......@@ -53,3 +53,10 @@ extern HASHNODE *install PARAMS ((U_CHAR *, int, enum node_type,
const char *, int));
extern int hashf PARAMS ((const U_CHAR *, int, int));
extern void delete_macro PARAMS ((HASHNODE *));
extern MACRODEF create_definition PARAMS ((U_CHAR *, U_CHAR *,
cpp_reader *, int));
extern int compare_defs PARAMS ((cpp_reader *, DEFINITION *,
DEFINITION *));
extern void macroexpand PARAMS ((cpp_reader *, HASHNODE *));
extern void cpp_hash_cleanup PARAMS ((cpp_reader *));
......@@ -18,24 +18,206 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file will have more stuff in it eventually, but right now
we just have one hack: we move all the is_* table initialization
in here, and we can declare them const in cpplib.h, which improves
code a bit. */
#include "config.h"
#include "system.h"
typedef unsigned char U_CHAR;
#define FAKE_CONST
#include "cpplib.h"
#include "cpphash.h"
#include "output.h"
#include "prefix.h"
#include "intl.h"
/* table to tell if char can be part of a C identifier. */
U_CHAR is_idchar[256] = { 0 };
/* table to tell if char can be first char of a c identifier. */
U_CHAR is_idstart[256] = { 0 };
/* table to tell if c is horizontal space. */
U_CHAR is_hor_space[256] = { 0 };
/* table to tell if c is horizontal or vertical space. */
U_CHAR is_space[256] = { 0 };
/* XXX Should be in a header file. */
extern char *version_string;
/* Predefined symbols, built-in macros, and the default include path. */
#ifndef GET_ENV_PATH_LIST
#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
/* By default, colon separates directories in a path. */
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR ':'
#endif
#ifndef STANDARD_INCLUDE_DIR
#define STANDARD_INCLUDE_DIR "/usr/include"
#endif
/* Symbols to predefine. */
#ifdef CPP_PREDEFINES
static char *predefs = CPP_PREDEFINES;
#else
static char *predefs = "";
#endif
/* We let tm.h override the types used here, to handle trivial differences
such as the choice of unsigned int or long unsigned int for size_t.
When machines start needing nontrivial differences in the size type,
it would be best to do something here to figure out automatically
from other information what type to use. */
/* The string value for __SIZE_TYPE__. */
#ifndef SIZE_TYPE
#define SIZE_TYPE "long unsigned int"
#endif
/* The string value for __PTRDIFF_TYPE__. */
#ifndef PTRDIFF_TYPE
#define PTRDIFF_TYPE "long int"
#endif
/* The string value for __WCHAR_TYPE__. */
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
#define CPP_WCHAR_TYPE(PFILE) \
(CPP_OPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)
/* The string value for __USER_LABEL_PREFIX__ */
#ifndef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
#endif
/* The string value for __REGISTER_PREFIX__ */
#ifndef REGISTER_PREFIX
#define REGISTER_PREFIX ""
#endif
/* #include "file" looks in source file dir, then stack. */
/* #include <file> just looks in the stack. */
/* -I directories are added to the end, then the defaults are added. */
/* The */
static struct default_include {
char *fname; /* The name of the directory. */
char *component; /* The component containing the directory */
int cplusplus; /* Only look here if we're compiling C++. */
int cxx_aware; /* Includes in this directory don't need to
be wrapped in extern "C" when compiling
C++. */
} include_defaults_array[]
#ifdef INCLUDE_DEFAULTS
= INCLUDE_DEFAULTS;
#else
= {
/* Pick up GNU C++ specific include files. */
{ GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
#ifdef CROSS_COMPILE
/* This is the dir for fixincludes. Put it just before
the files that we fix. */
{ GCC_INCLUDE_DIR, "GCC", 0, 0 },
/* For cross-compilation, this dir name is generated
automatically in Makefile.in. */
{ CROSS_INCLUDE_DIR, "GCC",0, 0 },
#ifdef TOOL_INCLUDE_DIR
/* This is another place that the target system's headers might be. */
{ TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
#endif
#else /* not CROSS_COMPILE */
#ifdef LOCAL_INCLUDE_DIR
/* This should be /usr/local/include and should come before
the fixincludes-fixed header files. */
{ LOCAL_INCLUDE_DIR, 0, 0, 1 },
#endif
#ifdef TOOL_INCLUDE_DIR
/* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */
{ TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
#endif
/* This is the dir for fixincludes. Put it just before
the files that we fix. */
{ GCC_INCLUDE_DIR, "GCC", 0, 0 },
/* Some systems have an extra dir of include files. */
#ifdef SYSTEM_INCLUDE_DIR
{ SYSTEM_INCLUDE_DIR, 0, 0, 0 },
#endif
#ifndef STANDARD_INCLUDE_COMPONENT
#define STANDARD_INCLUDE_COMPONENT 0
#endif
{ STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
#endif /* not CROSS_COMPILE */
{ 0, 0, 0, 0 }
};
#endif /* no INCLUDE_DEFAULTS */
/* Internal structures and prototypes. */
struct cpp_pending
{
struct cpp_pending *next;
char *cmd;
char *arg;
};
static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
static void initialize_char_syntax PARAMS ((int));
static void print_help PARAMS ((void));
static void path_include PARAMS ((cpp_reader *, char *));
static void initialize_builtins PARAMS ((cpp_reader *));
/* If gcc is in use (stage2/stage3) we can make these tables initialized
data. */
#if defined __GNUC__ && __GNUC__ >= 2
/* Table to tell if a character is legal as the second or later character
of a C identifier. */
U_CHAR is_idchar[256] =
{
['a'] = 1, ['b'] = 1, ['c'] = 1, ['d'] = 1, ['e'] = 1, ['f'] = 1,
['g'] = 1, ['h'] = 1, ['i'] = 1, ['j'] = 1, ['k'] = 1, ['l'] = 1,
['m'] = 1, ['n'] = 1, ['o'] = 1, ['p'] = 1, ['q'] = 1, ['r'] = 1,
['s'] = 1, ['t'] = 1, ['u'] = 1, ['v'] = 1, ['w'] = 1, ['x'] = 1,
['y'] = 1, ['z'] = 1,
['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1, ['F'] = 1,
['G'] = 1, ['H'] = 1, ['I'] = 1, ['J'] = 1, ['K'] = 1, ['L'] = 1,
['M'] = 1, ['N'] = 1, ['O'] = 1, ['P'] = 1, ['Q'] = 1, ['R'] = 1,
['S'] = 1, ['T'] = 1, ['U'] = 1, ['V'] = 1, ['W'] = 1, ['X'] = 1,
['Y'] = 1, ['Z'] = 1,
['1'] = 1, ['2'] = 1, ['3'] = 1, ['4'] = 1, ['5'] = 1, ['6'] = 1,
['7'] = 1, ['8'] = 1, ['9'] = 1, ['0'] = 1,
['_'] = 1,
};
/* Table to tell if a character is legal as the first character of
a C identifier. */
U_CHAR is_idstart[256] =
{
['a'] = 1, ['b'] = 1, ['c'] = 1, ['d'] = 1, ['e'] = 1, ['f'] = 1,
['g'] = 1, ['h'] = 1, ['i'] = 1, ['j'] = 1, ['k'] = 1, ['l'] = 1,
['m'] = 1, ['n'] = 1, ['o'] = 1, ['p'] = 1, ['q'] = 1, ['r'] = 1,
['s'] = 1, ['t'] = 1, ['u'] = 1, ['v'] = 1, ['w'] = 1, ['x'] = 1,
['y'] = 1, ['z'] = 1,
['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1, ['F'] = 1,
['G'] = 1, ['H'] = 1, ['I'] = 1, ['J'] = 1, ['K'] = 1, ['L'] = 1,
['M'] = 1, ['N'] = 1, ['O'] = 1, ['P'] = 1, ['Q'] = 1, ['R'] = 1,
['S'] = 1, ['T'] = 1, ['U'] = 1, ['V'] = 1, ['W'] = 1, ['X'] = 1,
['Y'] = 1, ['Z'] = 1,
['_'] = 1,
};
/* Table to tell if a character is horizontal space. */
U_CHAR is_hor_space[256] =
{
[' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1, ['\r'] = 1
};
/* table to tell if a character is horizontal or vertical space. */
U_CHAR is_space[256] =
{
[' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1, ['\r'] = 1, ['\n'] = 1,
};
/* Table to handle trigraph conversion, which occurs before all other
processing, everywhere in the file. (This is necessary since one
of the trigraphs encodes backslash.) Note it's off by default.
......@@ -47,10 +229,32 @@ U_CHAR is_space[256] = { 0 };
There is not a space between the ?? and the third char. I put spaces
there to avoid warnings when compiling this file. */
U_CHAR trigraph_table[256] =
{
['='] = '#', [')'] = ']', ['!'] = '|',
['('] = '[', ['\''] = '^', ['>'] = '}',
['/'] = '\\', ['<'] = '{', ['-'] = '~',
};
/* This function will be entirely removed soon. */
static inline void
initialize_char_syntax (dollar_in_ident)
int dollar_in_ident;
{
is_idchar['$'] = dollar_in_ident;
is_idstart['$'] = dollar_in_ident;
}
#else /* Not GCC. */
U_CHAR is_idchar[256] = { 0 };
U_CHAR is_idstart[256] = { 0 };
U_CHAR is_hor_space[256] = { 0 };
U_CHAR is_space[256] = { 0 };
U_CHAR trigraph_table[256] = { 0 };
/* Initialize syntactic classifications of characters. */
void
static void
initialize_char_syntax (dollar_in_ident)
int dollar_in_ident;
{
......@@ -103,11 +307,10 @@ initialize_char_syntax (dollar_in_ident)
is_idchar['_'] = 1;
/* These will be reset later if -$ is in effect. */
is_idchar['$'] = dollar_in_ident;
is_idstart['$'] = dollar_in_ident;
/* horizontal space table */
/* white space tables */
is_hor_space[' '] = 1;
is_hor_space['\t'] = 1;
is_hor_space['\v'] = 1;
......@@ -128,3 +331,1363 @@ initialize_char_syntax (dollar_in_ident)
trigraph_table['/'] = '\\'; trigraph_table['<'] = '{';
trigraph_table['-'] = '~';
}
#endif /* Not GCC. */
/* Given a colon-separated list of file names PATH,
add all the names to the search path for include files. */
static void
path_include (pfile, path)
cpp_reader *pfile;
char *path;
{
char *p;
p = path;
if (*p)
while (1) {
char *q = p;
char *name;
/* Find the end of this name. */
while (*q != 0 && *q != PATH_SEPARATOR) q++;
if (p == q) {
/* An empty name in the path stands for the current directory. */
name = (char *) xmalloc (2);
name[0] = '.';
name[1] = 0;
} else {
/* Otherwise use the directory that is named. */
name = (char *) xmalloc (q - p + 1);
bcopy (p, name, q - p);
name[q - p] = 0;
}
append_include_chain (pfile,
&(CPP_OPTIONS (pfile)->bracket_include), name, 0);
/* Advance past this name. */
p = q;
if (*p == 0)
break;
/* Skip the colon. */
p++;
}
}
/* Write out a #define command for the special named MACRO_NAME
to PFILE's token_buffer. */
static void
dump_special_to_buffer (pfile, macro_name)
cpp_reader *pfile;
char *macro_name;
{
static char define_directive[] = "#define ";
int macro_name_length = strlen (macro_name);
output_line_command (pfile, 0, same_file);
CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
CPP_PUTS_Q (pfile, macro_name, macro_name_length);
CPP_PUTC_Q (pfile, ' ');
cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
CPP_PUTC (pfile, '\n');
}
/* Pending-list utility routines. Will go away soon. */
static struct cpp_pending *
nreverse_pending (list)
struct cpp_pending *list;
{
register struct cpp_pending *prev = 0, *next, *pend;
for (pend = list; pend; pend = next)
{
next = pend->next;
pend->next = prev;
prev = pend;
}
return prev;
}
static void
push_pending (pfile, cmd, arg)
cpp_reader *pfile;
char *cmd;
char *arg;
{
struct cpp_pending *pend
= (struct cpp_pending *) xmalloc (sizeof (struct cpp_pending));
pend->cmd = cmd;
pend->arg = arg;
pend->next = CPP_OPTIONS (pfile)->pending;
CPP_OPTIONS (pfile)->pending = pend;
}
/* Initialize a cpp_options structure. */
void
cpp_options_init (opts)
cpp_options *opts;
{
bzero ((char *) opts, sizeof *opts);
opts->dollars_in_ident = 1;
opts->cplusplus_comments = 1;
opts->warn_import = 1;
}
/* Initialize a cpp_reader structure. */
void
cpp_reader_init (pfile)
cpp_reader *pfile;
{
bzero ((char *) pfile, sizeof (cpp_reader));
#if 0
pfile->get_token = cpp_get_token;
#endif
pfile->token_buffer_size = 200;
pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
CPP_SET_WRITTEN (pfile, 0);
}
/* Free resources used by PFILE.
This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology). */
void
cpp_cleanup (pfile)
cpp_reader *pfile;
{
int i;
while (CPP_BUFFER (pfile) != CPP_NULL_BUFFER (pfile))
cpp_pop_buffer (pfile);
if (pfile->token_buffer)
{
free (pfile->token_buffer);
pfile->token_buffer = NULL;
}
if (pfile->deps_buffer)
{
free (pfile->deps_buffer);
pfile->deps_buffer = NULL;
pfile->deps_allocated_size = 0;
}
while (pfile->if_stack)
{
IF_STACK_FRAME *temp = pfile->if_stack;
pfile->if_stack = temp->next;
free (temp);
}
for (i = ALL_INCLUDE_HASHSIZE; --i >= 0; )
{
struct include_hash *imp = pfile->all_include_files[i];
while (imp)
{
struct include_hash *next = imp->next;
#if 0
/* This gets freed elsewhere - I think. */
free (imp->name);
#endif
free (imp);
imp = next;
}
pfile->all_include_files[i] = 0;
}
cpp_hash_cleanup (pfile);
}
/* Initialize the built-in macros. */
static void
initialize_builtins (pfile)
cpp_reader *pfile;
{
#define NAME(str) (U_CHAR *)str, sizeof str - 1
install (NAME("__TIME__"), T_TIME, 0, -1);
install (NAME("__DATE__"), T_DATE, 0, -1);
install (NAME("__FILE__"), T_FILE, 0, -1);
install (NAME("__BASE_FILE__"), T_BASE_FILE, 0, -1);
install (NAME("__LINE__"), T_SPECLINE, 0, -1);
install (NAME("__INCLUDE_LEVEL__"), T_INCLUDE_LEVEL, 0, -1);
install (NAME("__VERSION__"), T_VERSION, 0, -1);
#ifndef NO_BUILTIN_SIZE_TYPE
install (NAME("__SIZE_TYPE__"), T_CONST, SIZE_TYPE, -1);
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
install (NAME("__PTRDIFF_TYPE__ "), T_CONST, PTRDIFF_TYPE, -1);
#endif
install (NAME("__WCHAR_TYPE__"), T_CONST, WCHAR_TYPE, -1);
install (NAME("__USER_LABEL_PREFIX__"), T_CONST, user_label_prefix, -1);
install (NAME("__REGISTER_PREFIX__"), T_CONST, REGISTER_PREFIX, -1);
if (!CPP_TRADITIONAL (pfile))
{
install (NAME("__STDC__"), T_STDC, 0, -1);
#if 0
if (CPP_OPTIONS (pfile)->c9x)
install (NAME("__STDC_VERSION__"),T_CONST, "199909L", -1);
else
#endif
install (NAME("__STDC_VERSION__"),T_CONST, "199409L", -1);
}
#undef NAME
if (CPP_OPTIONS (pfile)->debug_output)
{
dump_special_to_buffer (pfile, "__BASE_FILE__");
dump_special_to_buffer (pfile, "__VERSION__");
#ifndef NO_BUILTIN_SIZE_TYPE
dump_special_to_buffer (pfile, "__SIZE_TYPE__");
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
#endif
dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
dump_special_to_buffer (pfile, "__DATE__");
dump_special_to_buffer (pfile, "__TIME__");
if (!CPP_TRADITIONAL (pfile))
dump_special_to_buffer (pfile, "__STDC__");
}
}
/* This is called after options have been processed.
* Check options for consistency, and setup for processing input
* from the file named FNAME. (Use standard input if FNAME==NULL.)
* Return 1 on success, 0 on failure.
*/
int
cpp_start_read (pfile, fname)
cpp_reader *pfile;
char *fname;
{
struct cpp_options *opts = CPP_OPTIONS (pfile);
struct cpp_pending *pend;
char *p;
int f;
cpp_buffer *fp;
struct include_hash *ih_fake;
/* The code looks at the defaults through this pointer, rather than
through the constant structure above. This pointer gets changed
if an environment variable specifies other defaults. */
struct default_include *include_defaults = include_defaults_array;
/* Now that we know dollars_in_ident, we can initialize the syntax
tables. */
initialize_char_syntax (opts->dollars_in_ident);
/* Add dirs from CPATH after dirs from -I. */
/* There seems to be confusion about what CPATH should do,
so for the moment it is not documented. */
/* Some people say that CPATH should replace the standard include
dirs, but that seems pointless: it comes before them, so it
overrides them anyway. */
GET_ENV_PATH_LIST (p, "CPATH");
if (p != 0 && ! opts->no_standard_includes)
path_include (pfile, p);
/* Do partial setup of input buffer for the sake of generating
early #line directives (when -g is in effect). */
fp = cpp_push_buffer (pfile, NULL, 0);
if (!fp)
return 0;
if (opts->in_fname == NULL || *opts->in_fname == 0)
{
opts->in_fname = fname;
if (opts->in_fname == NULL)
opts->in_fname = "";
}
fp->nominal_fname = fp->fname = opts->in_fname;
fp->lineno = 0;
/* Install __LINE__, etc. Must follow initialize_char_syntax
and option processing. */
initialize_builtins (pfile);
/* Do standard #defines and assertions
that identify system and machine type. */
if (!opts->inhibit_predefs) {
char *p = (char *) alloca (strlen (predefs) + 1);
strcpy (p, predefs);
while (*p) {
char *q;
while (*p == ' ' || *p == '\t')
p++;
/* Handle -D options. */
if (p[0] == '-' && p[1] == 'D') {
q = &p[2];
while (*p && *p != ' ' && *p != '\t')
p++;
if (*p != 0)
*p++= 0;
if (opts->debug_output)
output_line_command (pfile, 0, same_file);
cpp_define (pfile, q);
while (*p == ' ' || *p == '\t')
p++;
} else if (p[0] == '-' && p[1] == 'A') {
/* Handle -A options (assertions). */
char *assertion;
char *past_name;
char *value;
char *past_value;
char *termination;
int save_char;
assertion = &p[2];
past_name = assertion;
/* Locate end of name. */
while (*past_name && *past_name != ' '
&& *past_name != '\t' && *past_name != '(')
past_name++;
/* Locate `(' at start of value. */
value = past_name;
while (*value && (*value == ' ' || *value == '\t'))
value++;
if (*value++ != '(')
abort ();
while (*value && (*value == ' ' || *value == '\t'))
value++;
past_value = value;
/* Locate end of value. */
while (*past_value && *past_value != ' '
&& *past_value != '\t' && *past_value != ')')
past_value++;
termination = past_value;
while (*termination && (*termination == ' ' || *termination == '\t'))
termination++;
if (*termination++ != ')')
abort ();
if (*termination && *termination != ' ' && *termination != '\t')
abort ();
/* Temporarily null-terminate the value. */
save_char = *termination;
*termination = '\0';
/* Install the assertion. */
cpp_assert (pfile, assertion);
*termination = (char) save_char;
p = termination;
while (*p == ' ' || *p == '\t')
p++;
} else {
abort ();
}
}
}
/* Now handle the command line options. */
/* Do -U's, -D's and -A's in the order they were seen. */
/* First reverse the list. */
opts->pending = nreverse_pending (opts->pending);
for (pend = opts->pending; pend; pend = pend->next)
{
if (pend->cmd != NULL && pend->cmd[0] == '-')
{
switch (pend->cmd[1])
{
case 'U':
if (opts->debug_output)
output_line_command (pfile, 0, same_file);
cpp_undef (pfile, pend->arg);
break;
case 'D':
if (opts->debug_output)
output_line_command (pfile, 0, same_file);
cpp_define (pfile, pend->arg);
break;
case 'A':
cpp_assert (pfile, pend->arg);
break;
}
}
}
opts->done_initializing = 1;
{ /* Read the appropriate environment variable and if it exists
replace include_defaults with the listed path. */
char *epath = 0;
switch ((opts->objc << 1) + opts->cplusplus)
{
case 0:
GET_ENV_PATH_LIST (epath, "C_INCLUDE_PATH");
break;
case 1:
GET_ENV_PATH_LIST (epath, "CPLUS_INCLUDE_PATH");
break;
case 2:
GET_ENV_PATH_LIST (epath, "OBJC_INCLUDE_PATH");
break;
case 3:
GET_ENV_PATH_LIST (epath, "OBJCPLUS_INCLUDE_PATH");
break;
}
/* If the environment var for this language is set,
add to the default list of include directories. */
if (epath) {
char *nstore = (char *) alloca (strlen (epath) + 2);
int num_dirs;
char *startp, *endp;
for (num_dirs = 1, startp = epath; *startp; startp++)
if (*startp == PATH_SEPARATOR)
num_dirs++;
include_defaults
= (struct default_include *) xmalloc ((num_dirs
* sizeof (struct default_include))
+ sizeof (include_defaults_array));
startp = endp = epath;
num_dirs = 0;
while (1) {
/* Handle cases like c:/usr/lib:d:/gcc/lib */
if ((*endp == PATH_SEPARATOR)
|| *endp == 0) {
strncpy (nstore, startp, endp-startp);
if (endp == startp)
strcpy (nstore, ".");
else
nstore[endp-startp] = '\0';
include_defaults[num_dirs].fname = xstrdup (nstore);
include_defaults[num_dirs].component = 0;
include_defaults[num_dirs].cplusplus = opts->cplusplus;
include_defaults[num_dirs].cxx_aware = 1;
num_dirs++;
if (*endp == '\0')
break;
endp = startp = endp + 1;
} else
endp++;
}
/* Put the usual defaults back in at the end. */
bcopy ((char *) include_defaults_array,
(char *) &include_defaults[num_dirs],
sizeof (include_defaults_array));
}
}
/* Unless -fnostdinc,
tack on the standard include file dirs to the specified list */
if (!opts->no_standard_includes) {
struct default_include *p = include_defaults;
char *specd_prefix = opts->include_prefix;
char *default_prefix = xstrdup (GCC_INCLUDE_DIR);
int default_len = 0;
/* Remove the `include' from /usr/local/lib/gcc.../include. */
if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
default_len = strlen (default_prefix) - 7;
default_prefix[default_len] = 0;
}
/* Search "translated" versions of GNU directories.
These have /usr/local/lib/gcc... replaced by specd_prefix. */
if (specd_prefix != 0 && default_len != 0)
for (p = include_defaults; p->fname; p++) {
/* Some standard dirs are only for C++. */
if (!p->cplusplus
|| (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
/* Does this dir start with the prefix? */
if (!strncmp (p->fname, default_prefix, default_len)) {
/* Yes; change prefix and add to search list. */
int this_len = strlen (specd_prefix)
+ strlen (p->fname) - default_len;
char *str = (char *) xmalloc (this_len + 1);
strcpy (str, specd_prefix);
strcat (str, p->fname + default_len);
append_include_chain (pfile, &opts->system_include,
str, !p->cxx_aware);
}
}
}
/* Search ordinary names for GNU include directories. */
for (p = include_defaults; p->fname; p++) {
/* Some standard dirs are only for C++. */
if (!p->cplusplus
|| (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
const char *str = update_path (p->fname, p->component);
append_include_chain (pfile, &opts->system_include,
str, !p->cxx_aware);
}
}
}
merge_include_chains (opts);
/* With -v, print the list of dirs to search. */
if (opts->verbose) {
struct file_name_list *p;
cpp_notice ("#include \"...\" search starts here:\n");
for (p = opts->quote_include; p; p = p->next) {
if (p == opts->bracket_include)
cpp_notice ("#include <...> search starts here:\n");
fprintf (stderr, " %s\n", p->name);
}
cpp_notice ("End of search list.\n");
}
/* Copy the entire contents of the main input file into
the stacked input buffer previously allocated for it. */
if (fname == NULL || *fname == 0) {
fname = "";
f = 0;
} else if ((f = open (fname, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666)) < 0)
cpp_pfatal_with_name (pfile, fname);
/* -MG doesn't select the form of output and must be specified with one of
-M or -MM. -MG doesn't make sense with -MD or -MMD since they don't
inhibit compilation. */
if (opts->print_deps_missing_files
&& (opts->print_deps == 0 || !opts->no_output))
{
cpp_fatal (pfile, "-MG must be specified with one of -M or -MM");
return 0;
}
/* Either of two environment variables can specify output of deps.
Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
where OUTPUT_FILE is the file to write deps info to
and DEPS_TARGET is the target to mention in the deps. */
if (opts->print_deps == 0
&& (getenv ("SUNPRO_DEPENDENCIES") != 0
|| getenv ("DEPENDENCIES_OUTPUT") != 0)) {
char *spec = getenv ("DEPENDENCIES_OUTPUT");
char *s;
char *output_file;
if (spec == 0)
{
spec = getenv ("SUNPRO_DEPENDENCIES");
opts->print_deps = 2;
}
else
opts->print_deps = 1;
s = spec;
/* Find the space before the DEPS_TARGET, if there is one. */
/* This should use index. (mrs) */
while (*s != 0 && *s != ' ') s++;
if (*s != 0)
{
opts->deps_target = s + 1;
output_file = (char *) xmalloc (s - spec + 1);
bcopy (spec, output_file, s - spec);
output_file[s - spec] = 0;
}
else
{
opts->deps_target = 0;
output_file = spec;
}
opts->deps_file = output_file;
opts->print_deps_append = 1;
}
/* For -M, print the expected object file name
as the target of this Make-rule. */
if (opts->print_deps)
{
pfile->deps_allocated_size = 200;
pfile->deps_buffer = (char *) xmalloc (pfile->deps_allocated_size);
pfile->deps_buffer[0] = 0;
pfile->deps_size = 0;
pfile->deps_column = 0;
if (opts->deps_target)
deps_output (pfile, opts->deps_target, ':');
else if (*opts->in_fname == 0)
deps_output (pfile, "-", ':');
else
{
char *p, *q, *r;
int len, x;
static char *known_suffixes[] = { ".c", ".C", ".s", ".S", ".m",
".cc", ".cxx", ".cpp", ".cp",
".c++", 0
};
/* Discard all directory prefixes from filename. */
if ((q = rindex (opts->in_fname, '/')) != NULL
#ifdef DIR_SEPARATOR
&& (q = rindex (opts->in_fname, DIR_SEPARATOR)) != NULL
#endif
)
++q;
else
q = opts->in_fname;
/* Copy remainder to mungable area. */
p = (char *) alloca (strlen(q) + 8);
strcpy (p, q);
/* Output P, but remove known suffixes. */
len = strlen (p);
q = p + len;
/* Point to the filename suffix. */
r = rindex (p, '.');
/* Compare against the known suffixes. */
x = 0;
while (known_suffixes[x] != 0)
{
if (strncmp (known_suffixes[x], r, q - r) == 0)
{
/* Make q point to the bit we're going to overwrite
with an object suffix. */
q = r;
break;
}
x++;
}
/* Supply our own suffix. */
#ifndef VMS
strcpy (q, ".o");
#else
strcpy (q, ".obj");
#endif
deps_output (pfile, p, ':');
deps_output (pfile, opts->in_fname, ' ');
}
}
/* Must call finclude() on the main input before processing
-include switches; otherwise the -included text winds up
after the main input. */
ih_fake = (struct include_hash *) xmalloc (sizeof (struct include_hash));
ih_fake->next = 0;
ih_fake->next_this_file = 0;
ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */
ih_fake->name = fname;
ih_fake->control_macro = 0;
ih_fake->buf = (char *)-1;
ih_fake->limit = 0;
if (!finclude (pfile, f, ih_fake))
return 0;
output_line_command (pfile, 0, same_file);
pfile->only_seen_white = 2;
/* The -imacros files can be scanned now, but the -include files
have to be pushed onto the include stack and processed later,
in the main loop calling cpp_get_token. That means the -include
files have to be processed in reverse order of the pending list,
which means the pending list has to be reversed again, which
means the -imacros files have to be done separately and first. */
pfile->no_record_file++;
opts->no_output++;
for (pend = opts->pending; pend; pend = pend->next)
{
if (pend->cmd != NULL)
{
if (strcmp (pend->cmd, "-imacros") == 0)
{
int fd = open (pend->arg, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
if (fd < 0)
{
cpp_perror_with_name (pfile, pend->arg);
return 0;
}
if (!cpp_push_buffer (pfile, NULL, 0))
return 0;
ih_fake = (struct include_hash *)
xmalloc (sizeof (struct include_hash));
ih_fake->next = 0;
ih_fake->next_this_file = 0;
ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */
ih_fake->name = pend->arg;
ih_fake->control_macro = 0;
ih_fake->buf = (char *)-1;
ih_fake->limit = 0;
if (!finclude (pfile, fd, ih_fake))
cpp_scan_buffer (pfile);
free (ih_fake);
}
}
}
opts->no_output--;
opts->pending = nreverse_pending (opts->pending);
for (pend = opts->pending; pend; pend = pend->next)
{
if (pend->cmd != NULL)
{
if (strcmp (pend->cmd, "-include") == 0)
{
int fd = open (pend->arg, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
if (fd < 0)
{
cpp_perror_with_name (pfile, pend->arg);
return 0;
}
if (!cpp_push_buffer (pfile, NULL, 0))
return 0;
ih_fake = (struct include_hash *)
xmalloc (sizeof (struct include_hash));
ih_fake->next = 0;
ih_fake->next_this_file = 0;
ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */
ih_fake->name = pend->arg;
ih_fake->control_macro = 0;
ih_fake->buf = (char *)-1;
ih_fake->limit = 0;
if (finclude (pfile, fd, ih_fake))
output_line_command (pfile, 0, enter_file);
}
}
}
pfile->no_record_file--;
/* Free the pending list. */
for (pend = opts->pending; pend; )
{
struct cpp_pending *next = pend->next;
free (pend);
pend = next;
}
opts->pending = NULL;
return 1;
}
/* This is called at the end of preprocessing. It pops the
last buffer and writes dependency output. It should also
clear macro definitions, such that you could call cpp_start_read
with a new filename to restart processing. */
void
cpp_finish (pfile)
cpp_reader *pfile;
{
struct cpp_options *opts = CPP_OPTIONS (pfile);
if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != CPP_NULL_BUFFER (pfile))
cpp_fatal (pfile,
"cpplib internal error: buffers still stacked in cpp_finish");
cpp_pop_buffer (pfile);
if (opts->print_deps)
{
/* Stream on which to print the dependency information. */
FILE *deps_stream;
/* Don't actually write the deps file if compilation has failed. */
if (pfile->errors == 0)
{
char *deps_mode = opts->print_deps_append ? "a" : "w";
if (opts->deps_file == 0)
deps_stream = stdout;
else if ((deps_stream = fopen (opts->deps_file, deps_mode)) == 0)
cpp_pfatal_with_name (pfile, opts->deps_file);
fputs (pfile->deps_buffer, deps_stream);
putc ('\n', deps_stream);
if (opts->deps_file)
{
if (ferror (deps_stream) || fclose (deps_stream) != 0)
cpp_fatal (pfile, "I/O error on output");
}
}
}
}
/* Handle one command-line option in (argc, argv).
Can be called multiple times, to handle multiple sets of options.
Returns number of strings consumed. */
int
cpp_handle_option (pfile, argc, argv)
cpp_reader *pfile;
int argc;
char **argv;
{
struct cpp_options *opts = CPP_OPTIONS (pfile);
int i = 0;
if (user_label_prefix == NULL)
user_label_prefix = USER_LABEL_PREFIX;
if (argv[i][0] != '-') {
if (opts->out_fname != NULL)
{
print_help ();
cpp_fatal (pfile, "Too many arguments");
}
else if (opts->in_fname != NULL)
opts->out_fname = argv[i];
else
opts->in_fname = argv[i];
} else {
switch (argv[i][1]) {
missing_filename:
cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
return argc;
missing_dirname:
cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
return argc;
case 'f':
if (!strcmp (argv[i], "-fleading-underscore"))
user_label_prefix = "_";
else if (!strcmp (argv[i], "-fno-leading-underscore"))
user_label_prefix = "";
break;
case 'I': /* Add directory to path for includes. */
if (!strcmp (argv[i] + 2, "-"))
{
if (! opts->ignore_srcdir)
{
opts->ignore_srcdir = 1;
/* Don't use any preceding -I directories for #include <...>. */
opts->quote_include = opts->bracket_include;
opts->bracket_include = 0;
}
}
else
{
char *fname;
if (argv[i][2] != 0)
fname = argv[i] + 2;
else if (i + 1 == argc)
goto missing_dirname;
else
fname = argv[++i];
append_include_chain (pfile, &opts->bracket_include, fname, 0);
}
break;
case 'i':
/* Add directory to beginning of system include path, as a system
include directory. */
if (!strcmp (argv[i], "-isystem"))
{
if (i + 1 == argc)
goto missing_filename;
append_include_chain (pfile, &opts->system_include, argv[++i], 1);
}
/* Add directory to end of path for includes,
with the default prefix at the front of its name. */
else if (!strcmp (argv[i], "-iwithprefix"))
{
char *fname;
if (i + 1 == argc)
goto missing_dirname;
++i;
if (opts->include_prefix != 0)
{
fname = xmalloc (strlen (opts->include_prefix)
+ strlen (argv[i]) + 1);
strcpy (fname, opts->include_prefix);
strcat (fname, argv[i]);
}
else
{
fname = xmalloc (strlen (GCC_INCLUDE_DIR)
+ strlen (argv[i]) + 1);
strcpy (fname, GCC_INCLUDE_DIR);
/* Remove the `include' from /usr/local/lib/gcc.../include. */
if (!strcmp (fname + strlen (fname) - 8, "/include"))
fname[strlen (fname) - 7] = 0;
strcat (fname, argv[i]);
}
append_include_chain (pfile, &opts->system_include, fname, 0);
}
/* Add directory to main path for includes,
with the default prefix at the front of its name. */
else if (!strcmp (argv[i], "-iwithprefix"))
{
char *fname;
if (i + 1 == argc)
goto missing_dirname;
++i;
if (opts->include_prefix != 0)
{
fname = xmalloc (strlen (opts->include_prefix)
+ strlen (argv[i]) + 1);
strcpy (fname, opts->include_prefix);
strcat (fname, argv[i]);
}
else
{
fname = xmalloc (strlen (GCC_INCLUDE_DIR)
+ strlen (argv[i]) + 1);
strcpy (fname, GCC_INCLUDE_DIR);
/* Remove the `include' from /usr/local/lib/gcc.../include. */
if (!strcmp (fname + strlen (fname) - 8, "/include"))
fname[strlen (fname) - 7] = 0;
strcat (fname, argv[i]);
}
append_include_chain (pfile, &opts->bracket_include, fname, 0);
}
/* Add directory to end of path for includes. */
else if (!strcmp (argv[i], "-idirafter"))
{
if (i + 1 == argc)
goto missing_dirname;
append_include_chain (pfile, &opts->after_include, argv[++i], 0);
}
else if (!strcmp (argv[i], "-include") || !strcmp (argv[i], "-imacros"))
{
if (i + 1 == argc)
goto missing_filename;
else
push_pending (pfile, argv[i], argv[i+1]), i++;
}
else if (!strcmp (argv[i], "-iprefix"))
{
if (i + 1 == argc)
goto missing_filename;
else
opts->include_prefix = argv[++i];
}
else if (!strcmp (argv[i], "-ifoutput"))
opts->output_conditionals = 1;
break;
case 'o':
if (opts->out_fname != NULL)
{
cpp_fatal (pfile, "Output filename specified twice");
return argc;
}
if (i + 1 == argc)
goto missing_filename;
opts->out_fname = argv[++i];
if (!strcmp (opts->out_fname, "-"))
opts->out_fname = "";
break;
case 'p':
if (!strcmp (argv[i], "-pedantic"))
CPP_PEDANTIC (pfile) = 1;
else if (!strcmp (argv[i], "-pedantic-errors")) {
CPP_PEDANTIC (pfile) = 1;
opts->pedantic_errors = 1;
}
#if 0
else if (!strcmp (argv[i], "-pcp")) {
char *pcp_fname = argv[++i];
pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
? fopen (pcp_fname, "w")
: fdopen (dup (fileno (stdout)), "w"));
if (pcp_outfile == 0)
cpp_pfatal_with_name (pfile, pcp_fname);
no_precomp = 1;
}
#endif
break;
case 't':
if (!strcmp (argv[i], "-traditional")) {
opts->traditional = 1;
opts->cplusplus_comments = 0;
} else if (!strcmp (argv[i], "-trigraphs")) {
if (!opts->chill)
opts->trigraphs = 1;
}
break;
case 'l':
if (! strcmp (argv[i], "-lang-c"))
opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
opts->c9x = 1, opts->objc = 0;
if (! strcmp (argv[i], "-lang-c89"))
opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->c89 = 1,
opts->c9x = 0, opts->objc = 0;
if (! strcmp (argv[i], "-lang-c++"))
opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
opts->c9x = 0, opts->objc = 0;
if (! strcmp (argv[i], "-lang-objc"))
opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
opts->c9x = 0, opts->objc = 1;
if (! strcmp (argv[i], "-lang-objc++"))
opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
opts->c9x = 0, opts->objc = 1;
if (! strcmp (argv[i], "-lang-asm"))
opts->lang_asm = 1;
if (! strcmp (argv[i], "-lint"))
opts->for_lint = 1;
if (! strcmp (argv[i], "-lang-chill"))
opts->objc = 0, opts->cplusplus = 0, opts->chill = 1,
opts->traditional = 1, opts->trigraphs = 0;
break;
case '+':
opts->cplusplus = 1, opts->cplusplus_comments = 1;
break;
case 's':
if (!strcmp (argv[i], "-std=iso9899:1990")
|| !strcmp (argv[i], "-std=iso9899:199409")
|| !strcmp (argv[i], "-std=c89")
|| !strcmp (argv[i], "-std=gnu89"))
opts->cplusplus = 0, opts->cplusplus_comments = 0,
opts->c89 = 1, opts->c9x = 0, opts->objc = 0;
else if (!strcmp (argv[i], "-std=iso9899:199x")
|| !strcmp (argv[i], "-std=c9x")
|| !strcmp (argv[i], "-std=gnu9x"))
opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
opts->c9x = 1, opts->objc = 0;
break;
case 'w':
opts->inhibit_warnings = 1;
break;
case 'W':
if (!strcmp (argv[i], "-Wtrigraphs"))
opts->warn_trigraphs = 1;
else if (!strcmp (argv[i], "-Wno-trigraphs"))
opts->warn_trigraphs = 0;
else if (!strcmp (argv[i], "-Wcomment"))
opts->warn_comments = 1;
else if (!strcmp (argv[i], "-Wno-comment"))
opts->warn_comments = 0;
else if (!strcmp (argv[i], "-Wcomments"))
opts->warn_comments = 1;
else if (!strcmp (argv[i], "-Wno-comments"))
opts->warn_comments = 0;
else if (!strcmp (argv[i], "-Wtraditional"))
opts->warn_stringify = 1;
else if (!strcmp (argv[i], "-Wno-traditional"))
opts->warn_stringify = 0;
else if (!strcmp (argv[i], "-Wundef"))
opts->warn_undef = 1;
else if (!strcmp (argv[i], "-Wno-undef"))
opts->warn_undef = 0;
else if (!strcmp (argv[i], "-Wimport"))
opts->warn_import = 1;
else if (!strcmp (argv[i], "-Wno-import"))
opts->warn_import = 0;
else if (!strcmp (argv[i], "-Werror"))
opts->warnings_are_errors = 1;
else if (!strcmp (argv[i], "-Wno-error"))
opts->warnings_are_errors = 0;
else if (!strcmp (argv[i], "-Wall"))
{
opts->warn_trigraphs = 1;
opts->warn_comments = 1;
}
break;
case 'M':
/* The style of the choices here is a bit mixed.
The chosen scheme is a hybrid of keeping all options in one string
and specifying each option in a separate argument:
-M|-MM|-MD file|-MMD file [-MG]. An alternative is:
-M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely:
-M[M][G][D file]. This is awkward to handle in specs, and is not
as extensible. */
/* ??? -MG must be specified in addition to one of -M or -MM.
This can be relaxed in the future without breaking anything.
The converse isn't true. */
/* -MG isn't valid with -MD or -MMD. This is checked for later. */
if (!strcmp (argv[i], "-MG"))
{
opts->print_deps_missing_files = 1;
break;
}
if (!strcmp (argv[i], "-M"))
opts->print_deps = 2;
else if (!strcmp (argv[i], "-MM"))
opts->print_deps = 1;
else if (!strcmp (argv[i], "-MD"))
opts->print_deps = 2;
else if (!strcmp (argv[i], "-MMD"))
opts->print_deps = 1;
/* For -MD and -MMD options, write deps on file named by next arg. */
if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
{
if (i+1 == argc)
goto missing_filename;
opts->deps_file = argv[++i];
}
else
{
/* For -M and -MM, write deps on standard output
and suppress the usual output. */
opts->no_output = 1;
}
break;
case 'd':
{
char *p = argv[i] + 2;
char c;
while ((c = *p++) != 0) {
/* Arg to -d specifies what parts of macros to dump */
switch (c) {
case 'M':
opts->dump_macros = dump_only;
opts->no_output = 1;
break;
case 'N':
opts->dump_macros = dump_names;
break;
case 'D':
opts->dump_macros = dump_definitions;
break;
case 'I':
opts->dump_includes = 1;
break;
}
}
}
break;
case 'g':
if (argv[i][2] == '3')
opts->debug_output = 1;
break;
case '-':
if (strcmp (argv[i], "--help") != 0)
return i;
print_help ();
break;
case 'v':
cpp_notice ("GNU CPP version %s", version_string);
#ifdef TARGET_VERSION
TARGET_VERSION;
#endif
fprintf (stderr, "\n");
opts->verbose = 1;
break;
case 'H':
opts->print_include_names = 1;
break;
case 'D':
if (argv[i][2] != 0)
push_pending (pfile, "-D", argv[i] + 2);
else if (i + 1 == argc)
{
cpp_fatal (pfile, "Macro name missing after -D option");
return argc;
}
else
i++, push_pending (pfile, "-D", argv[i]);
break;
case 'A':
{
char *p;
if (argv[i][2] != 0)
p = argv[i] + 2;
else if (i + 1 == argc)
{
cpp_fatal (pfile, "Assertion missing after -A option");
return argc;
}
else
p = argv[++i];
if (!strcmp (p, "-")) {
struct cpp_pending **ptr;
/* -A- eliminates all predefined macros and assertions.
Let's include also any that were specified earlier
on the command line. That way we can get rid of any
that were passed automatically in from GCC. */
opts->inhibit_predefs = 1;
for (ptr = &opts->pending; *ptr != NULL; )
{
struct cpp_pending *pend = *ptr;
if (pend->cmd && pend->cmd[0] == '-'
&& (pend->cmd[1] == 'D' || pend->cmd[1] == 'A'))
{
*ptr = pend->next;
free (pend);
}
else
ptr = &pend->next;
}
} else {
push_pending (pfile, "-A", p);
}
}
break;
case 'U': /* JF #undef something */
if (argv[i][2] != 0)
push_pending (pfile, "-U", argv[i] + 2);
else if (i + 1 == argc)
{
cpp_fatal (pfile, "Macro name missing after -U option");
return argc;
}
else
push_pending (pfile, "-U", argv[i+1]), i++;
break;
case 'C':
opts->put_out_comments = 1;
break;
case 'E': /* -E comes from cc -E; ignore it. */
break;
case 'P':
opts->no_line_commands = 1;
break;
case '$': /* Don't include $ in identifiers. */
opts->dollars_in_ident = 0;
break;
case 'n':
if (!strcmp (argv[i], "-nostdinc"))
/* -nostdinc causes no default include directories.
You must specify all include-file directories with -I. */
opts->no_standard_includes = 1;
else if (!strcmp (argv[i], "-nostdinc++"))
/* -nostdinc++ causes no default C++-specific include directories. */
opts->no_standard_cplusplus_includes = 1;
#if 0
else if (!strcmp (argv[i], "-noprecomp"))
no_precomp = 1;
#endif
break;
case 'r':
if (!strcmp (argv[i], "-remap"))
opts->remap = 1;
break;
case 'u':
/* Sun compiler passes undocumented switch "-undef".
Let's assume it means to inhibit the predefined symbols. */
opts->inhibit_predefs = 1;
break;
case '\0': /* JF handle '-' as file name meaning stdin or stdout */
if (opts->in_fname == NULL) {
opts->in_fname = "";
break;
} else if (opts->out_fname == NULL) {
opts->out_fname = "";
break;
} /* else fall through into error */
default:
return i;
}
}
return i + 1;
}
/* Handle command-line options in (argc, argv).
Can be called multiple times, to handle multiple sets of options.
Returns if an unrecognized option is seen.
Returns number of strings consumed. */
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);
if (strings_processed == 0)
break;
}
return i;
}
static void
print_help ()
{
cpp_notice ("Usage: %s [switches] input output\n", progname);
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\
-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\
-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\
-pedantic Issue all warnings demanded by strict ANSI C\n\
-traditional Follow K&R pre-processor behaviour\n\
-trigraphs Support ANSI 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\
-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\
-lang-chill Assume that the input sources are in Chill\n\
-std=<std name> Specify the conformance standard; one of:\n\
gnu89, gnu9x, c89, c9x, iso9899:1990,\n\
iso9899:199409, iso9899:199x\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\
-Wno-comment{s} Do not warn about comments\n\
-Wtraditional Warn if a macro argument is/would be turned into\n\
a string if -traditional is specified\n\
-Wno-traditional Do not warn about stringification\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\
-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\
-Wall Enable all preprocessor warnings\n\
-M Generate make dependencies\n\
-MM As -M, but ignore system header files\n\
-MD As -M, but put output in a .d file\n\
-MMD As -MD, but ignore system header files\n\
-MG Treat missing header file as generated files\n\
-g Include #define and #undef directives in the output\n\
-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\
-U<macro> Undefine <macro> \n\
-u or -undef Do not predefine any macros\n\
-v Display the version number\n\
-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\
-ifoutput Describe skipped code blocks in output \n\
-P Do not generate #line directives\n\
-$ Do not allow '$' in identifiers\n\
-remap Remap file names when including files.\n\
-h or --help Display this information\n\
"), stdout);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -637,11 +637,19 @@ struct definition {
} args;
};
extern const unsigned char is_idstart[256];
extern const unsigned char is_idchar[256];
extern const unsigned char is_hor_space[256];
extern const unsigned char is_space[256];
extern const unsigned char trigraph_table[256];
/* These tables are not really `const', but they are only modified at
initialization time, in a separate translation unit from the rest
of the library. We let the rest of the library think they are `const'
to get better code and some additional sanity checks. */
#ifndef FAKE_CONST
#define FAKE_CONST const
#endif
extern FAKE_CONST unsigned char is_idstart[256];
extern FAKE_CONST unsigned char is_idchar[256];
extern FAKE_CONST unsigned char is_hor_space[256];
extern FAKE_CONST unsigned char is_space[256];
extern FAKE_CONST unsigned char trigraph_table[256];
#undef FAKE_CONST
/* Stack of conditionals currently in progress
(including both successful and failing conditionals). */
......@@ -667,8 +675,9 @@ typedef struct if_stack IF_STACK_FRAME;
extern void cpp_buf_line_and_col PARAMS((cpp_buffer *, long *, long *));
extern cpp_buffer* cpp_file_buffer PARAMS((cpp_reader *));
extern void cpp_define PARAMS ((cpp_reader*, unsigned char *));
extern void cpp_define PARAMS ((cpp_reader *, unsigned char *));
extern void cpp_assert PARAMS ((cpp_reader *, unsigned char *));
extern void cpp_undef PARAMS ((cpp_reader *, unsigned char *));
extern void cpp_error PVPROTO ((cpp_reader *, const char *, ...))
ATTRIBUTE_PRINTF_2;
......@@ -705,6 +714,16 @@ extern int scan_decls PARAMS ((cpp_reader *, int, char **));
extern void skip_rest_of_line PARAMS ((cpp_reader *));
extern void cpp_finish PARAMS ((cpp_reader *));
extern void quote_string PARAMS ((cpp_reader *, const char *));
extern void cpp_expand_to_buffer PARAMS ((cpp_reader *, U_CHAR *, int));
extern void cpp_scan_buffer PARAMS ((cpp_reader *));
extern int check_macro_name PARAMS ((cpp_reader *, U_CHAR *, int));
/* Last arg to output_line_command. */
enum file_change_code {same_file, enter_file, leave_file};
extern void output_line_command PARAMS ((cpp_reader *, int,
enum file_change_code));
/* From cpperror.c */
extern void cpp_fatal PVPROTO ((cpp_reader *, const char *, ...))
ATTRIBUTE_PRINTF_2;
......@@ -729,9 +748,6 @@ extern int finclude PROTO ((cpp_reader *, int,
extern void deps_output PROTO ((cpp_reader *, char *, int));
extern struct include_hash *include_hash PROTO ((cpp_reader *, char *, int));
/* cppinit.c */
extern void initialize_char_syntax PROTO ((int));
#ifndef INCLUDE_LEN_FUDGE
#define INCLUDE_LEN_FUDGE 0
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment