cpplib.h (CPP_ASSERTION, [...]): New token types.

* cpplib.h (CPP_ASSERTION, CPP_STRINGIZE, CPP_TOKPASTE): New
	token types.
	(struct cpp_reader): Add parsing_if_directive and
	parsing_define_directive flags.
	(struct cpp_options): Remove output_conditionals flag.
	(check_macro_name): Delete prototype.

	* cpphash.h (struct macrodef): Delete.
	(struct reflist): Separate from struct definition.
	(struct definition): Remove unused fields.  Add column number.
	(create_definition): Returns a DEFINITION *.  Takes a
	cpp_reader * and an int.

	* cpphash.c (SKIP_WHITE_SPACE): Delete.
	(PEEKC): Copy defn from cpplib.c.
	(rest_extension, REST_EXTENSION_LENGTH): Delete.
	(struct arg): New.
	(struct arglist): Simplify.
	(collect_expansion): Rewrite.  Get tokens by calling
	cpp_get_token.  Add more error checking.
	(collect_formal_parameters): New function, broken out of
	create_definition and reworked to use get_directive_token.
	(create_definition): All real work is now in collect_expansion
	and collect_formal_parameters.  do_define handles finding the
	macro name.  Return a DEFINITION, not a MACRODEF.
	(macroexpand): Replace bcopy with memcpy throughout.  Replace
	character-at-a-time copy loop with memcpy and pointer increments.
	(compare-defs): d1->argnames / d2->argnames might be null.

	* cpplib.c (copy_rest_of_line): Delete function.
	(skip_rest_of_line): Do all the work ourselves.
	(skip_string): New function.
	(parse_string): Use skip_string.
	(get_macro_name): New function.
	(check_macro_name): Delete.
	(copy_comment): Use CPP_RESERVE and CPP_PUTC_Q.
	(cpp_skip_hspace): Use CPP_BUMP_LINE.
	(handle_directive): ICE if we're called on a macro buffer.
	(do_define): Determine macro name and type (funlike/objlike)
	here.  Expunge all uses of MACRODEF.
	(cpp_push_buffer): Set line_base to NULL.
	(do_undef, read_line_number): Don't worry about getting a POP token.
	(eval_if_expression): Set/reset parsing_if_directive around
	cpp_parse_expr. Don't clear only_seen_white.
	(skip_if_group): Remove output_conditionals logic.  Use
	skip_rest_of_line.
	(cpp_get_token): Return ASSERTION, STRINGIZE, and TOKPASTE
	tokens under appropriate conditions.
	(cpp_unassert): Call do_unassert not do_assert.  Oops.

	* cppexp.c (parse_defined): New function, break out of
	cpp_lex.
	(cpp_lex): We now get CPP_ASSERTION tokens and can check them
	ourselves, with cpp_defined.
	* cppinit.c (cpp_handle_option, print_help): Delete -ifoutput.

	* gcc.dg/20000209-2.c: Turn off -pedantic-errors.
	* gcc.dg/strpaste-2.c: New.

From-SVN: r32274
This commit is contained in:
Zack Weinberg 2000-03-01 00:57:09 +00:00 committed by Zack Weinberg
parent 38769add25
commit ba412f14ad
9 changed files with 818 additions and 778 deletions

View File

@ -1,3 +1,64 @@
2000-02-29 Zack Weinberg <zack@wolery.cumb.org>
* cpplib.h (CPP_ASSERTION, CPP_STRINGIZE, CPP_TOKPASTE): New
token types.
(struct cpp_reader): Add parsing_if_directive and
parsing_define_directive flags.
(struct cpp_options): Remove output_conditionals flag.
(check_macro_name): Delete prototype.
* cpphash.h (struct macrodef): Delete.
(struct reflist): Separate from struct definition.
(struct definition): Remove unused fields. Add column number.
(create_definition): Returns a DEFINITION *. Takes a
cpp_reader * and an int.
* cpphash.c (SKIP_WHITE_SPACE): Delete.
(PEEKC): Copy defn from cpplib.c.
(rest_extension, REST_EXTENSION_LENGTH): Delete.
(struct arg): New.
(struct arglist): Simplify.
(collect_expansion): Rewrite. Get tokens by calling
cpp_get_token. Add more error checking.
(collect_formal_parameters): New function, broken out of
create_definition and reworked to use get_directive_token.
(create_definition): All real work is now in collect_expansion
and collect_formal_parameters. do_define handles finding the
macro name. Return a DEFINITION, not a MACRODEF.
(macroexpand): Replace bcopy with memcpy throughout. Replace
character-at-a-time copy loop with memcpy and pointer increments.
(compare-defs): d1->argnames / d2->argnames might be null.
* cpplib.c (copy_rest_of_line): Delete function.
(skip_rest_of_line): Do all the work ourselves.
(skip_string): New function.
(parse_string): Use skip_string.
(get_macro_name): New function.
(check_macro_name): Delete.
(copy_comment): Use CPP_RESERVE and CPP_PUTC_Q.
(cpp_skip_hspace): Use CPP_BUMP_LINE.
(handle_directive): ICE if we're called on a macro buffer.
(do_define): Determine macro name and type (funlike/objlike)
here. Expunge all uses of MACRODEF.
(cpp_push_buffer): Set line_base to NULL.
(do_undef, read_line_number): Don't worry about getting a POP token.
(eval_if_expression): Set/reset parsing_if_directive around
cpp_parse_expr. Don't clear only_seen_white.
(skip_if_group): Remove output_conditionals logic. Use
skip_rest_of_line.
(cpp_get_token): Return ASSERTION, STRINGIZE, and TOKPASTE
tokens under appropriate conditions.
(cpp_unassert): Call do_unassert not do_assert. Oops.
* cppexp.c (parse_defined): New function, break out of
cpp_lex.
(cpp_lex): We now get CPP_ASSERTION tokens and can check them
ourselves, with cpp_defined.
* cppinit.c (cpp_handle_option, print_help): Delete -ifoutput.
* gcc.dg/20000209-2.c: Turn off -pedantic-errors.
* gcc.dg/strpaste-2.c: New.
2000-02-29 Mark Mitchell <mark@codesourcery.com>
* fold-const.c (size_binop): Don't asert inputs are the same and

View File

@ -81,6 +81,7 @@ static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int, u
static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int, unsigned HOST_WIDEST_INT));
static struct operation parse_number PARAMS ((cpp_reader *, U_CHAR *, U_CHAR *));
static struct operation parse_charconst PARAMS ((cpp_reader *, U_CHAR *, U_CHAR *));
static struct operation parse_defined PARAMS ((cpp_reader *));
static struct operation cpp_lex PARAMS ((cpp_reader *, int));
extern HOST_WIDEST_INT cpp_parse_expr PARAMS ((cpp_reader *));
static HOST_WIDEST_INT cpp_parse_escape PARAMS ((cpp_reader *, U_CHAR **, HOST_WIDEST_INT));
@ -349,6 +350,53 @@ parse_charconst (pfile, start, end)
return op;
}
static struct operation
parse_defined (pfile)
cpp_reader *pfile;
{
int paren = 0, len;
U_CHAR *tok;
enum cpp_token token;
struct operation op;
long old_written = CPP_WRITTEN (pfile);
op.unsignedp = 0;
op.op = INT;
pfile->no_macro_expand++;
token = get_directive_token (pfile);
if (token == CPP_LPAREN)
{
paren++;
CPP_SET_WRITTEN (pfile, old_written);
token = get_directive_token (pfile);
}
if (token != CPP_NAME)
goto oops;
tok = pfile->token_buffer + old_written;
len = CPP_PWRITTEN (pfile) - tok;
op.value = cpp_defined (pfile, tok, len);
if (paren)
{
if (get_directive_token (pfile) != CPP_RPAREN)
goto oops;
}
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
return op;
oops:
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
cpp_error (pfile, "`defined' without an identifier");
op.op = ERROR;
return op;
}
struct token {
const char *operator;
@ -389,7 +437,7 @@ cpp_lex (pfile, skip_evaluation)
tok_end = CPP_PWRITTEN (pfile);
CPP_SET_WRITTEN (pfile, old_written);
switch (token)
{
{
case CPP_EOF: /* Should not happen ... */
case CPP_VSPACE:
op.op = 0;
@ -407,51 +455,22 @@ cpp_lex (pfile, skip_evaluation)
return parse_charconst (pfile, tok_start, tok_end);
case CPP_NAME:
if (!strcmp (tok_start, "defined"))
return parse_defined (pfile);
op.op = INT;
op.unsignedp = 0;
op.value = 0;
if (strcmp (tok_start, "defined"))
{
if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
cpp_warning (pfile, "`%.*s' is not defined",
(int) (tok_end - tok_start), tok_start);
}
else
{
int paren = 0, len;
U_CHAR *tok;
pfile->no_macro_expand++;
token = get_directive_token (pfile);
if (token == CPP_LPAREN)
{
paren++;
CPP_SET_WRITTEN (pfile, old_written);
token = get_directive_token (pfile);
}
if (token != CPP_NAME)
goto oops;
tok = pfile->token_buffer + old_written;
len = CPP_PWRITTEN (pfile) - tok;
if (cpp_defined (pfile, tok, len))
op.value = 1;
if (paren)
{
if (get_directive_token (pfile) != CPP_RPAREN)
goto oops;
}
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
}
if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
cpp_warning (pfile, "`%.*s' is not defined",
(int) (tok_end - tok_start), tok_start);
return op;
oops:
CPP_SET_WRITTEN (pfile, old_written);
pfile->no_macro_expand--;
cpp_error (pfile, "`defined' without an identifier");
case CPP_ASSERTION:
op.op = INT;
op.unsignedp = 0;
op.value = cpp_defined (pfile, tok_start, tok_end - tok_start);
return op;
case CPP_OTHER:
@ -468,13 +487,6 @@ cpp_lex (pfile, skip_evaluation)
op.op = toktab->token;
return op;
}
else if (tok_start + 1 == tok_end && *tok_start == '#')
{
CPP_FORWARD (CPP_BUFFER (pfile), -1);
op.op = INT;
op.value = cpp_read_check_assertion (pfile);
return op;
}
/* fall through */
default:
op.op = *tok_start;

File diff suppressed because it is too large Load Diff

View File

@ -18,15 +18,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef __GCC_CPPHASH__
#define __GCC_CPPHASH__
/* Structure returned by create_definition */
typedef struct macrodef MACRODEF;
struct macrodef
{
struct definition *defn;
const U_CHAR *symnam;
int symlen;
};
/* Structure allocated for every #define. For a simple replacement
such as
#define foo bar ,
@ -48,30 +39,35 @@ struct macrodef
{ (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
where (x, y) means (nchars, argno). */
struct reflist
{
struct reflist *next;
char stringify; /* nonzero if this arg was preceded by a
# operator. */
char raw_before; /* Nonzero if a ## operator before arg. */
char raw_after; /* Nonzero if a ## operator after arg. */
char rest_args; /* Nonzero if this arg. absorbs the rest */
int nchars; /* Number of literal chars to copy before
this arg occurrence. */
int argno; /* Number of arg to substitute (origin-0) */
};
typedef struct definition DEFINITION;
struct definition {
struct definition
{
int nargs;
int length; /* length of expansion string */
unsigned char *expansion;
U_CHAR *expansion;
int line; /* Line number of definition */
int col;
const char *file; /* File of definition */
char rest_args; /* Nonzero if last arg. absorbs the rest */
struct reflist {
struct reflist *next;
char stringify; /* nonzero if this arg was preceded by a
# operator. */
char raw_before; /* Nonzero if a ## operator before arg. */
char raw_after; /* Nonzero if a ## operator after arg. */
char rest_args; /* Nonzero if this arg. absorbs the rest */
int nchars; /* Number of literal chars to copy before
this arg occurrence. */
int argno; /* Number of arg to substitute (origin-0) */
} *pattern;
/* Names of macro args, concatenated in reverse order
with comma-space between them.
The only use of this is that we warn on redefinition
if this differs between the old and new definitions. */
unsigned char *argnames;
struct reflist *pattern;
/* Names of macro args, concatenated in order with commas between
them. The only use of this is that we warn on redefinition if
this differs between the old and new definitions. */
U_CHAR *argnames;
};
/* different kinds of things that can appear in the value field
@ -102,8 +98,7 @@ extern HASHNODE *cpp_lookup PARAMS ((cpp_reader *, const U_CHAR *, int));
extern void free_definition PARAMS ((DEFINITION *));
extern void delete_macro PARAMS ((HASHNODE *));
extern MACRODEF create_definition PARAMS ((U_CHAR *, U_CHAR *,
cpp_reader *));
extern DEFINITION *create_definition PARAMS ((cpp_reader *, int));
extern int compare_defs PARAMS ((cpp_reader *, DEFINITION *,
DEFINITION *));
extern void macroexpand PARAMS ((cpp_reader *, HASHNODE *));

View File

@ -1256,9 +1256,6 @@ cpp_handle_option (pfile, argc, argv)
opts->include_prefix_len = strlen (argv[i]);
}
}
else if (!strcmp (argv[i], "-ifoutput"))
opts->output_conditionals = 1;
break;
case 'o':
@ -1736,7 +1733,6 @@ Switches:\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\

View File

@ -46,7 +46,8 @@ extern HOST_WIDEST_INT cpp_parse_expr PARAMS ((cpp_reader *));
/* `struct directive' defines one #-directive, including how to handle it. */
struct directive {
struct directive
{
int length; /* Length of name */
int (*func) /* Function to handle directive */
PARAMS ((cpp_reader *, const struct directive *));
@ -93,7 +94,7 @@ static enum cpp_token null_underflow PARAMS ((cpp_reader *));
static int null_cleanup PARAMS ((cpp_buffer *, cpp_reader *));
static int skip_comment PARAMS ((cpp_reader *, int));
static int copy_comment PARAMS ((cpp_reader *, int));
static void copy_rest_of_line PARAMS ((cpp_reader *));
static void skip_string PARAMS ((cpp_reader *, int));
static void skip_rest_of_line PARAMS ((cpp_reader *));
static void cpp_skip_hspace PARAMS ((cpp_reader *));
static int handle_directive PARAMS ((cpp_reader *));
@ -108,6 +109,7 @@ static void skip_block_comment PARAMS ((cpp_reader *));
static void skip_line_comment PARAMS ((cpp_reader *));
static void parse_set_mark PARAMS ((cpp_reader *));
static void parse_goto_mark PARAMS ((cpp_reader *));
static int get_macro_name PARAMS ((cpp_reader *));
/* Here is the actual list of #-directives.
This table is ordered by frequency of occurrence; the numbers
@ -410,10 +412,13 @@ copy_comment (pfile, m)
if (skip_comment (pfile, m) == m)
return m;
CPP_PUTC (pfile, m);
for (limit = CPP_BUFFER (pfile)->cur; start <= limit; start++)
limit = CPP_BUFFER (pfile)->cur;
CPP_RESERVE (pfile, limit - start + 2);
CPP_PUTC_Q (pfile, m);
for (; start <= limit; start++)
if (*start != '\r')
CPP_PUTC (pfile, *start);
CPP_PUTC_Q (pfile, *start);
return ' ';
}
@ -447,7 +452,7 @@ cpp_skip_hspace (pfile)
break;
}
else
CPP_BUFFER (pfile)->lineno++;
CPP_BUMP_LINE (pfile);
}
else if (c == '/' || c == '-')
{
@ -461,11 +466,10 @@ cpp_skip_hspace (pfile)
FORWARD(-1);
}
/* Read the rest of the current line.
The line is appended to PFILE's output buffer. */
/* Read and discard the rest of the current line. */
static void
copy_rest_of_line (pfile)
skip_rest_of_line (pfile)
cpp_reader *pfile;
{
for (;;)
@ -476,32 +480,21 @@ copy_rest_of_line (pfile)
case '\n':
FORWARD(-1);
case EOF:
CPP_NUL_TERMINATE (pfile);
return;
case '\r':
if (CPP_BUFFER (pfile)->has_escapes)
break;
else
{
CPP_BUFFER (pfile)->lineno++;
continue;
}
if (! CPP_BUFFER (pfile)->has_escapes)
CPP_BUMP_LINE (pfile);
break;
case '\'':
case '\"':
parse_string (pfile, c);
continue;
skip_string (pfile, c);
break;
case '/':
if (PEEKC() == '*')
{
if (CPP_TRADITIONAL (pfile))
CPP_PUTS (pfile, "/**/", 4);
skip_block_comment (pfile);
continue;
}
/* else fall through */
case '-':
c = skip_comment (pfile, c);
skip_comment (pfile, c);
break;
case '\f':
@ -512,23 +505,9 @@ copy_rest_of_line (pfile)
break;
}
CPP_PUTC (pfile, c);
}
}
/* FIXME: It is almost definitely a performance win to make this do
the scan itself. >75% of calls to copy_r_o_l are from here or
skip_if_group, which means the common case is to copy stuff into the
token_buffer only to discard it. */
static void
skip_rest_of_line (pfile)
cpp_reader *pfile;
{
long old = CPP_WRITTEN (pfile);
copy_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, old);
}
/* Handle a possible # directive.
'#' has already been read. */
@ -542,6 +521,12 @@ handle_directive (pfile)
U_CHAR *ident;
long old_written = CPP_WRITTEN (pfile);
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
{
cpp_ice (pfile, "handle_directive called on macro buffer");
return 0;
}
cpp_skip_hspace (pfile);
c = PEEKC ();
@ -629,71 +614,88 @@ pass_thru_directive (buf, len, pfile, keyword)
CPP_PUTS_Q (pfile, buf, len);
}
/* Check a purported macro name SYMNAME, and yield its length. */
/* Subroutine of do_define: determine the name of the macro to be
defined. */
int
check_macro_name (pfile, symname)
static int
get_macro_name (pfile)
cpp_reader *pfile;
const U_CHAR *symname;
{
const U_CHAR *p;
int sym_length;
long here, len;
for (p = symname; is_idchar(*p); p++)
;
sym_length = p - symname;
if (sym_length == 0
|| (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
cpp_error (pfile, "invalid macro name");
else if (!is_idstart(*symname)
|| (! strncmp (symname, "defined", 7) && sym_length == 7)) {
U_CHAR *msg; /* what pain... */
msg = (U_CHAR *) alloca (sym_length + 1);
bcopy (symname, msg, sym_length);
msg[sym_length] = 0;
cpp_error (pfile, "invalid macro name `%s'", msg);
}
return sym_length;
here = CPP_WRITTEN (pfile);
pfile->no_macro_expand++;
if (get_directive_token (pfile) != CPP_NAME)
{
cpp_error (pfile, "`#define' must be followed by an identifier");
goto invalid;
}
len = CPP_WRITTEN (pfile) - here;
if (len == 7 && !strncmp (pfile->token_buffer + here, "defined", 7))
{
cpp_error (pfile, "`defined' is not a legal macro name");
goto invalid;
}
pfile->no_macro_expand--;
return len;
invalid:
skip_rest_of_line (pfile);
pfile->no_macro_expand--;
return 0;
}
/* Process a #define command.
KEYWORD is the keyword-table entry for #define,
or NULL for a "predefined" macro,
or the keyword-table entry for #pragma in the case of a #pragma poison. */
or NULL for a "predefined" macro. */
static int
do_define (pfile, keyword)
cpp_reader *pfile;
const struct directive *keyword;
{
MACRODEF mdef;
HASHNODE *hp;
DEFINITION *def;
long here;
U_CHAR *macro, *buf, *end;
int len, c;
int funlike = 0;
U_CHAR *sym;
here = CPP_WRITTEN (pfile);
copy_rest_of_line (pfile);
/* Copy out the line so we can pop the token buffer. */
buf = pfile->token_buffer + here;
end = CPP_PWRITTEN (pfile);
macro = (U_CHAR *) alloca (end - buf + 1);
memcpy (macro, buf, end - buf + 1);
end = macro + (end - buf);
CPP_SET_WRITTEN (pfile, here);
mdef = create_definition (macro, end, pfile);
if (mdef.defn == 0)
len = get_macro_name (pfile);
if (len == 0)
return 0;
if ((hp = cpp_lookup (pfile, mdef.symnam, mdef.symlen)) != NULL)
/* Copy out the name so we can pop the token buffer. */
len = CPP_WRITTEN (pfile) - here;
sym = (U_CHAR *) alloca (len + 1);
memcpy (sym, pfile->token_buffer + here, len);
sym[len] = '\0';
CPP_SET_WRITTEN (pfile, here);
/* If the next character, with no intervening whitespace, is '(',
then this is a function-like macro. */
c = PEEKC ();
if (c == '(')
funlike = 1;
else if (c != '\n' && !is_hspace (c))
/* Otherwise, C99 requires white space after the name. We treat it
as an object-like macro if this happens, with a warning. */
cpp_pedwarn (pfile, "missing white space after `#define %.*s'", len, sym);
def = create_definition (pfile, funlike);
if (def == 0)
return 0;
if ((hp = cpp_lookup (pfile, sym, len)) != NULL)
{
int ok;
/* Redefining a macro is ok if the definitions are the same. */
if (hp->type == T_MACRO)
ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
ok = ! compare_defs (pfile, def, hp->value.defn);
/* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST || hp->type == T_STDC)
ok = ! CPP_OPTIONS (pfile)->done_initializing;
@ -704,14 +706,15 @@ do_define (pfile, keyword)
if (! ok)
{
if (hp->type == T_POISON)
cpp_error (pfile, "redefining poisoned `%.*s'",
mdef.symlen, mdef.symnam);
cpp_error (pfile, "redefining poisoned `%.*s'", len, sym);
else
cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam);
cpp_pedwarn (pfile, "`%.*s' redefined", len, sym);
if (hp->type == T_MACRO && CPP_OPTIONS (pfile)->done_initializing)
cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file,
hp->value.defn->line, -1,
{
DEFINITION *d = hp->value.defn;
cpp_pedwarn_with_file_and_line (pfile, d->file, d->line, d->col,
"this is the location of the previous definition");
}
}
if (hp->type != T_POISON)
{
@ -719,19 +722,19 @@ do_define (pfile, keyword)
if (hp->type == T_MACRO)
free_definition (hp->value.defn);
hp->type = T_MACRO;
hp->value.defn = mdef.defn;
hp->value.defn = def;
}
}
else
cpp_install (pfile, mdef.symnam, mdef.symlen, T_MACRO, (char *)mdef.defn);
cpp_install (pfile, sym, len, T_MACRO, (char *) def);
if (keyword != NULL && keyword->type == T_DEFINE)
{
if (CPP_OPTIONS (pfile)->debug_output
|| CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
dump_definition (pfile, mdef.symnam, mdef.symlen, mdef.defn);
dump_definition (pfile, sym, len, def);
else if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
pass_thru_directive (mdef.symnam, mdef.symlen, pfile, keyword);
pass_thru_directive (sym, len, pfile, keyword);
}
return 0;
@ -766,6 +769,7 @@ cpp_push_buffer (pfile, buffer, length)
new->alimit = new->rlimit = buffer + length;
new->prev = buf;
new->mark = -1;
new->line_base = NULL;
CPP_BUFFER (pfile) = new;
return new;
@ -1309,7 +1313,7 @@ read_line_number (pfile, num)
}
else
{
if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
if (token != CPP_VSPACE && token != CPP_EOF)
cpp_error (pfile, "invalid format `#line' command");
return 0;
}
@ -1467,15 +1471,14 @@ do_undef (pfile, keyword)
len = limit - buf;
name = (U_CHAR *) alloca (len + 1);
memcpy (name, buf, len);
name[limit - buf] = '\0';
name[len] = '\0';
token = get_directive_token (pfile);
if (token != CPP_VSPACE && token != CPP_POP)
if (token != CPP_VSPACE)
{
cpp_pedwarn (pfile, "junk on line after #undef");
skip_rest_of_line (pfile);
}
CPP_SET_WRITTEN (pfile, here);
while ((hp = cpp_lookup (pfile, name, len)) != NULL)
@ -1950,11 +1953,9 @@ eval_if_expression (pfile)
HOST_WIDEST_INT value;
long old_written = CPP_WRITTEN (pfile);
/* Work around bug in cpp_get_token where it may mistake an
assertion for a directive. */
pfile->only_seen_white = 0;
pfile->parsing_if_directive++;
value = cpp_parse_expr (pfile);
pfile->parsing_if_directive--;
skip_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, old_written); /* Pop */
@ -2148,13 +2149,6 @@ skip_if_group (pfile)
U_CHAR *beg_of_line;
long old_written;
if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTS (pfile, "#failed\n", 8);
pfile->lineno++;
output_line_command (pfile, same_file);
}
old_written = CPP_WRITTEN (pfile);
for (;;)
@ -2166,8 +2160,6 @@ skip_if_group (pfile)
c = GETC();
if (c == '\n')
{
if (CPP_OPTIONS (pfile)->output_conditionals)
CPP_PUTC (pfile, c);
CPP_BUMP_LINE (pfile);
continue;
}
@ -2180,41 +2172,19 @@ skip_if_group (pfile)
return; /* Caller will issue error. */
FORWARD(-1);
if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTS (pfile, beg_of_line, CPP_BUFFER (pfile)->cur - beg_of_line);
copy_rest_of_line (pfile);
}
else
{
copy_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, old_written); /* discard it */
}
skip_rest_of_line (pfile);
c = GETC();
if (c == EOF)
return; /* Caller will issue error. */
else
{
/* \n */
if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTC (pfile, c);
pfile->lineno++;
}
CPP_BUMP_LINE (pfile);
}
CPP_BUMP_LINE (pfile);
}
/* Back up to the beginning of this line. Caller will process the
directive. */
CPP_BUFFER (pfile)->cur = beg_of_line;
pfile->only_seen_white = 1;
if (CPP_OPTIONS (pfile)->output_conditionals)
{
CPP_PUTS (pfile, "#endfailed\n", 11);
pfile->lineno++;
}
}
/*
@ -2443,6 +2413,27 @@ cpp_get_token (pfile)
}
case '#':
if (pfile->parsing_if_directive)
{
cpp_skip_hspace (pfile);
parse_assertion (pfile);
return CPP_ASSERTION;
}
if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile))
{
CPP_RESERVE (pfile, 3);
CPP_PUTC_Q (pfile, '#');
CPP_NUL_TERMINATE_Q (pfile);
if (PEEKC () != '#')
return CPP_STRINGIZE;
FORWARD (1);
CPP_PUTC_Q (pfile, '#');
CPP_NUL_TERMINATE_Q (pfile);
return CPP_TOKPASTE;
}
if (!pfile->only_seen_white)
goto randomchar;
/* -traditional directives are recognized only with the # in
@ -2886,35 +2877,24 @@ parse_name (pfile, c)
return;
}
/* Parse a string starting with C. A single quoted string is treated
like a double -- some programs (e.g., troff) are perverse this way.
(However, a single quoted string is not allowed to extend over
multiple lines.) */
/* Parse and skip over a string starting with C. A single quoted
string is treated like a double -- some programs (e.g., troff) are
perverse this way. (However, a single quoted string is not allowed
to extend over multiple lines.) */
static void
parse_string (pfile, c)
skip_string (pfile, c)
cpp_reader *pfile;
int c;
{
long start_line, start_column;
cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
CPP_PUTC (pfile, c);
while (1)
{
int cc = GETC();
if (cc == EOF)
switch (cc)
{
if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
{
/* try harder: this string crosses a macro expansion
boundary. This can happen naturally if -traditional.
Otherwise, only -D can make a macro with an unmatched
quote. */
cpp_pop_buffer (pfile);
continue;
}
case EOF:
cpp_error_with_line (pfile, start_line, start_column,
"unterminated string or character constant");
if (pfile->multiline_string_line != start_line
@ -2923,22 +2903,20 @@ parse_string (pfile, c)
pfile->multiline_string_line, -1,
"possible real start of unterminated constant");
pfile->multiline_string_line = 0;
break;
}
CPP_PUTC (pfile, cc);
switch (cc)
{
return;
case '\n':
CPP_BUMP_LINE (pfile);
pfile->lineno++;
/* In Fortran and assembly language, silently terminate
strings of either variety at end of line. This is a
kludge around not knowing where comments are in these
languages. */
if (CPP_OPTIONS (pfile)->lang_fortran
|| CPP_OPTIONS (pfile)->lang_asm)
return;
{
FORWARD(-1);
return;
}
/* Character constants may not extend over multiple lines.
In Standard C, neither may strings. We accept multiline
strings as an extension. */
@ -2946,6 +2924,7 @@ parse_string (pfile, c)
{
cpp_error_with_line (pfile, start_line, start_column,
"unterminated character constant");
FORWARD(-1);
return;
}
if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0)
@ -2956,7 +2935,6 @@ parse_string (pfile, c)
break;
case '\r':
CPP_ADJUST_WRITTEN (pfile, -1);
if (CPP_BUFFER (pfile)->has_escapes)
{
cpp_ice (pfile, "\\r escape inside string constant");
@ -2968,9 +2946,7 @@ parse_string (pfile, c)
break;
case '\\':
cc = GETC();
if (cc != EOF)
CPP_PUTC (pfile, cc);
FORWARD(1);
break;
case '\"':
@ -2982,6 +2958,26 @@ parse_string (pfile, c)
}
}
/* Parse a string and copy it to the output. */
static void
parse_string (pfile, c)
cpp_reader *pfile;
int c;
{
U_CHAR *start = CPP_BUFFER (pfile)->cur; /* XXX Layering violation */
U_CHAR *limit;
skip_string (pfile, c);
limit = CPP_BUFFER (pfile)->cur;
CPP_RESERVE (pfile, limit - start + 2);
CPP_PUTC_Q (pfile, c);
for (; start < limit; start++)
if (*start != '\r')
CPP_PUTC_Q (pfile, *start);
}
/* Read an assertion into the token buffer, converting to
canonical form: `#predicate(a n swe r)' The next non-whitespace
character to read should be the first letter of the predicate.
@ -3199,33 +3195,11 @@ cpp_unassert (pfile, str)
{
if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
{
do_assert (pfile, NULL);
do_unassert (pfile, NULL);
cpp_pop_buffer (pfile);
}
}
int
cpp_read_check_assertion (pfile)
cpp_reader *pfile;
{
U_CHAR *name;
int result;
long written = CPP_WRITTEN (pfile);
FORWARD (1); /* Skip '#' */
cpp_skip_hspace (pfile);
if (! parse_assertion (pfile))
result = 0;
else
{
name = pfile->token_buffer + written;
result = cpp_defined (pfile, name, CPP_PWRITTEN (pfile) - name);
}
CPP_SET_WRITTEN (pfile, written);
return result;
}
/* Remember the current position of PFILE so it may be returned to
after looking ahead a bit.

View File

@ -47,14 +47,17 @@ enum cpp_token {
CPP_STRING,
CPP_WSTRING,
CPP_DIRECTIVE,
CPP_LPAREN, /* "(" */
CPP_RPAREN, /* ")" */
CPP_LBRACE, /* "{" */
CPP_RBRACE, /* "}" */
CPP_COMMA, /* "," */
CPP_SEMICOLON,/* ";" */
CPP_3DOTS, /* "..." */
CPP_POP /* We're about to pop the buffer stack. */
CPP_ASSERTION, /* #machine(a29k) */
CPP_STRINGIZE, /* stringize macro argument */
CPP_TOKPASTE, /* paste macro arg with next/prev token */
CPP_LPAREN, /* "(" */
CPP_RPAREN, /* ")" */
CPP_LBRACE, /* "{" */
CPP_RBRACE, /* "}" */
CPP_COMMA, /* "," */
CPP_SEMICOLON, /* ";" */
CPP_3DOTS, /* "..." */
CPP_POP /* We're about to pop the buffer stack. */
};
typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader *));
@ -193,7 +196,6 @@ struct cpp_reader
/* If non-zero, directives cause a hard error. Used when parsing
macro arguments. */
char no_directives;
/* Print column number in error messages. */
@ -205,6 +207,12 @@ struct cpp_reader
/* If true, character between '<' and '>' are a single (string) token. */
char parsing_include_directive;
/* If true, # introduces an assertion (see do_assert) */
char parsing_if_directive;
/* If true, # and ## are the STRINGIZE and TOKPASTE operators */
char parsing_define_directive;
/* True if escape sequences (as described for has_escapes in
parse_buffer) should be emitted. */
char output_escapes;
@ -217,7 +225,7 @@ struct cpp_reader
/* Nonzero means this file was included with a -imacros or -include
command line and should not be recorded as an include file. */
int no_record_file;
char no_record_file;
long lineno;
@ -427,11 +435,6 @@ struct cpp_options {
char no_line_commands;
/* Nonzero means output the text in failing conditionals,
inside #failed ... #endfailed. */
char output_conditionals;
/* Nonzero means -I- has been seen,
so don't look for #include "foo" the source-file directory. */
char ignore_srcdir;
@ -689,14 +692,12 @@ extern int cpp_defined PARAMS ((cpp_reader *, const U_CHAR *, int));
extern void cpp_reader_init PARAMS ((cpp_reader *));
extern void cpp_options_init PARAMS ((cpp_options *));
extern int cpp_start_read PARAMS ((cpp_reader *, char *));
extern int cpp_read_check_assertion 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 *, const U_CHAR *,
int));
extern void cpp_scan_buffer PARAMS ((cpp_reader *));
extern int check_macro_name PARAMS ((cpp_reader *, const U_CHAR *));
/* Last arg to output_line_command. */
enum file_change_code {same_file, rename_file, enter_file, leave_file};

View File

@ -1,5 +1,7 @@
/* { dg-do compile } */
/* Distilled from glibc sources. Tests preprocessor corner cases. */
/* { dg-options "-Wall" } */
/* Distilled from glibc sources. Tests preprocessor corner cases.
Since it uses rest args, we must turn off -pedantic-errors. */
#define NO_PAREN(rest...) rest
#define DEFINE_CATEGORY(category, items) \

View File

@ -0,0 +1,23 @@
/* { dg-do run } */
/* Test for odd corner cases in stringizing/pasting.
Taken more or less verbatim from C99 section 6.10.3.3. */
#include <stdlib.h>
#include <string.h>
#define hash_hash # ## #
#define mkstr(a) # a
#define in_between(a) mkstr(a)
#define join(c, d) in_between(c hash_hash d)
const char p[] = join(x, y);
const char q[] = "x ## y";
int
main (void)
{
if (strcmp (p, q))
abort ();
return 0;
}