cpplib.h (TTYPE_TABLE): Rearrange to use only two per-entry macros, not five.

* cpplib.h (TTYPE_TABLE): Rearrange to use only two per-entry
          macros, not five.

	* cpphash.h (TOKEN_NAME): New macro.
	(_cpp_spell_operator): Deleted.
	(token_spellings): Now _cpp_token_spellings.

	* cppexp.c: Use TOKEN_NAME or TYPE_NAME, not _cpp_spell_operator.
	* cpplex.c: Use OP and TK macros when expanding the
	TTYPE_TABLE.  Eliminate token_names.  For non-OPERATOR tokens,
	store the stringification of the enumeration name (CPP_CHAR,
	etc.) in the name slot of token_spellings.
	Use TOKEN_NAME and/or TOKEN_SPELL, do not reference
	token_spellings directly.
	* cpplib.c: Use TOKEN_SPELL.

	* cpplex.c (_cpp_push_token): If the token being pushed back
	is the previous token in this context, just subtract one from
	context->posn.
	* cppmacro.c (save_expansion): Clear aux field when storing a
	placemarker.

	* gcc.dg/cpp/paste5.c: New test.
	* gcc.dg/cpp/vararg1.c: New test.

From-SVN: r35124
This commit is contained in:
Zack Weinberg 2000-07-18 23:25:06 +00:00 committed by Zack Weinberg
parent d0089985e7
commit 96be699833
10 changed files with 197 additions and 142 deletions

View File

@ -1,3 +1,27 @@
2000-07-18 Zack Weinberg <zack@wolery.cumb.org>
* cpplib.h (TTYPE_TABLE): Rearrange to use only two per-entry
macros, not five.
* cpphash.h (TOKEN_NAME): New macro.
(_cpp_spell_operator): Deleted.
(token_spellings): Now _cpp_token_spellings.
* cppexp.c: Use TOKEN_NAME or TYPE_NAME, not _cpp_spell_operator.
* cpplex.c: Use OP and TK macros when expanding the
TTYPE_TABLE. Eliminate token_names. For non-OPERATOR tokens,
store the stringification of the enumeration name (CPP_CHAR,
etc.) in the name slot of token_spellings.
Use TOKEN_NAME and/or TOKEN_SPELL, do not reference
token_spellings directly.
* cpplib.c: Use TOKEN_SPELL.
* cpplex.c (_cpp_push_token): If the token being pushed back
is the previous token in this context, just subtract one from
context->posn.
* cppmacro.c (save_expansion): Clear aux field when storing a
placemarker.
2000-07-18 Jakub Jelinek <jakub@redhat.com>
* cpplex.c (cpp_scan_buffer): Output line command even at the stop

View File

@ -397,7 +397,6 @@ lex (pfile, skip_evaluation)
switch (tok->type)
{
case CPP_PLACEMARKER:
/* XXX These shouldn't be visible outside cpplex.c. */
goto retry;
case CPP_INT:
@ -443,8 +442,7 @@ lex (pfile, skip_evaluation)
return op;
}
SYNTAX_ERROR2("'%s' is not valid in #if expressions",
_cpp_spell_operator (tok->type));
SYNTAX_ERROR2("'%s' is not valid in #if expressions", TOKEN_NAME (tok));
}
syntax_error:
@ -718,6 +716,8 @@ op_to_prio[] =
/* Parse and evaluate a C expression, reading from PFILE.
Returns the truth value of the expression. */
#define TYPE_NAME(t) _cpp_token_spellings[t].name
int
_cpp_parse_expr (pfile)
cpp_reader *pfile;
@ -804,7 +804,7 @@ _cpp_parse_expr (pfile)
SYNTAX_ERROR ("void expression between '(' and ')'");
else
SYNTAX_ERROR2 ("operator '%s' has no right operand",
_cpp_spell_operator (top->op));
TYPE_NAME (top->op));
}
unsigned2 = top->unsignedp, v2 = top->value;
@ -815,8 +815,7 @@ _cpp_parse_expr (pfile)
switch (top[1].op)
{
default:
cpp_ice (pfile, "impossible operator type %s",
_cpp_spell_operator (op.op));
cpp_ice (pfile, "impossible operator type %s", TYPE_NAME (op.op));
goto syntax_error;
case CPP_NOT: UNARY(!); break;
@ -969,13 +968,13 @@ _cpp_parse_expr (pfile)
{
if (top->flags & HAVE_VALUE)
SYNTAX_ERROR2 ("missing binary operator before '%s'",
_cpp_spell_operator (op.op));
TYPE_NAME (op.op));
}
else
{
if (!(top->flags & HAVE_VALUE))
SYNTAX_ERROR2 ("operator '%s' has no left operand",
_cpp_spell_operator (op.op));
TYPE_NAME (op.op));
}
/* Check for and handle stack overflow. */

View File

@ -38,12 +38,13 @@ enum spell_type
struct token_spelling
{
ENUM_BITFIELD(spell_type) type : CHAR_BIT;
const U_CHAR *spelling;
enum spell_type category;
const U_CHAR *name;
};
extern const struct token_spelling token_spellings[];
#define TOKEN_SPELL(token) (token_spellings[(token)->type].type)
extern const struct token_spelling _cpp_token_spellings[];
#define TOKEN_SPELL(token) (_cpp_token_spellings[(token)->type].category)
#define TOKEN_NAME(token) (_cpp_token_spellings[(token)->type].name)
/* Chained list of answers to an assertion. */
struct answer
@ -267,7 +268,6 @@ extern const cpp_token *_cpp_get_token PARAMS ((cpp_reader *));
extern const cpp_token *_cpp_get_raw_token PARAMS ((cpp_reader *));
extern void _cpp_push_token PARAMS ((cpp_reader *, const cpp_token*));
extern const cpp_token *_cpp_glue_header_name PARAMS ((cpp_reader *));
extern const U_CHAR *_cpp_spell_operator PARAMS ((enum cpp_ttype));
/* In cpplib.c */
extern const struct directive *_cpp_check_directive

View File

@ -209,35 +209,14 @@ static void process_directive PARAMS ((cpp_reader *, const cpp_token *));
if ((f) & BOL) {(d)->col = (s)->col; (d)->line = (s)->line;} \
} while (0)
#define T(e, s) {SPELL_OPERATOR, (const U_CHAR *) s},
#define I(e, s) {SPELL_IDENT, s},
#define S(e, s) {SPELL_STRING, s},
#define C(e, s) {SPELL_CHAR, s},
#define N(e, s) {SPELL_NONE, s},
#define OP(e, s) { SPELL_OPERATOR, U s },
#define TK(e, s) { s, U STRINGX (e) },
const struct token_spelling
token_spellings [N_TTYPES + 1] = {TTYPE_TABLE {0, 0} };
_cpp_token_spellings [N_TTYPES] = {TTYPE_TABLE };
#undef T
#undef I
#undef S
#undef C
#undef N
/* For debugging: the internal names of the tokens. */
#define T(e, s) U STRINGX(e),
#define I(e, s) U STRINGX(e),
#define S(e, s) U STRINGX(e),
#define C(e, s) U STRINGX(e),
#define N(e, s) U STRINGX(e),
const U_CHAR *const token_names[N_TTYPES] = { TTYPE_TABLE };
#undef T
#undef I
#undef S
#undef C
#undef N
#undef OP
#undef TK
/* The following table is used by trigraph_ok/trigraph_replace. If we
have designated initializers, it can be constant data; otherwise,
@ -579,7 +558,7 @@ _cpp_expand_name_space (list, len)
unsigned int i;
for (i = 0; i < list->tokens_used; i++)
if (token_spellings[list->tokens[i].type].type == SPELL_STRING)
if (TOKEN_SPELL (&list->tokens[i]) == SPELL_STRING)
list->tokens[i].val.str.text += (list->namebuf - old_namebuf);
}
}
@ -684,7 +663,7 @@ _cpp_equiv_tokens (a, b)
const cpp_token *a, *b;
{
if (a->type == b->type && a->flags == b->flags)
switch (token_spellings[a->type].type)
switch (TOKEN_SPELL (a))
{
default: /* Keep compiler happy. */
case SPELL_OPERATOR:
@ -1966,7 +1945,7 @@ spell_token (pfile, token, buffer)
const cpp_token *token;
unsigned char *buffer;
{
switch (token_spellings[token->type].type)
switch (TOKEN_SPELL (token))
{
case SPELL_OPERATOR:
{
@ -1976,7 +1955,7 @@ spell_token (pfile, token, buffer)
if (token->flags & DIGRAPH)
spelling = digraph_spellings[token->type - CPP_FIRST_DIGRAPH];
else
spelling = token_spellings[token->type].spelling;
spelling = TOKEN_NAME (token);
while ((c = *spelling++) != '\0')
*buffer++ = c;
@ -2013,26 +1992,13 @@ spell_token (pfile, token, buffer)
break;
case SPELL_NONE:
cpp_ice (pfile, "Unspellable token %s", token_names[token->type]);
cpp_ice (pfile, "Unspellable token %s", TOKEN_NAME (token));
break;
}
return buffer;
}
/* Return the spelling of a token known to be an operator.
Does not distinguish digraphs from their counterparts. */
const unsigned char *
_cpp_spell_operator (type)
enum cpp_ttype type;
{
if (token_spellings[type].type == SPELL_OPERATOR)
return token_spellings[type].spelling;
else
return token_names[type];
}
/* Macro expansion algorithm.
Macro expansion is implemented by a single-pass algorithm; there are
@ -2554,7 +2520,7 @@ release_temp_tokens (pfile)
{
cpp_token *token = pfile->temp_tokens[--pfile->temp_used];
if (token_spellings[token->type].type == SPELL_STRING)
if (TOKEN_SPELL (token) == SPELL_STRING)
{
free ((char *) token->val.str.text);
token->val.str.text = 0;
@ -2595,7 +2561,7 @@ duplicate_token (pfile, token)
cpp_token *result = get_temp_token (pfile);
*result = *token;
if (token_spellings[token->type].type == SPELL_STRING)
if (TOKEN_SPELL (token) == SPELL_STRING)
{
U_CHAR *buff = (U_CHAR *) xmalloc (token->val.str.len);
memcpy (buff, token->val.str.text, token->val.str.len);
@ -2837,6 +2803,9 @@ stringify_arg (pfile, token)
unsigned char *buf;
unsigned int len = TOKEN_LEN (token);
if (token->type == CPP_PLACEMARKER)
continue;
escape = (token->type == CPP_STRING || token->type == CPP_WSTRING
|| token->type == CPP_CHAR || token->type == CPP_WCHAR);
if (escape)
@ -3008,6 +2977,22 @@ _cpp_push_token (pfile, token)
const cpp_token *token;
{
cpp_context *context = CURRENT_CONTEXT (pfile);
if (context->posn > 0)
{
const cpp_token *prev;
if (IS_ARG_CONTEXT (context))
prev = context->u.arg[context->posn - 1];
else
prev = &context->u.list->tokens[context->posn - 1];
if (prev == token)
{
context->posn--;
return;
}
}
if (context->pushed_token)
cpp_ice (pfile, "two tokens pushed in a row");
if (token->type != CPP_EOF)
@ -3031,8 +3016,7 @@ process_directive (pfile, token)
if (token[1].type == CPP_NAME)
_cpp_get_raw_token (pfile);
else if (token[1].type != CPP_NUMBER)
cpp_ice (pfile, "directive begins with %s?!",
token_names[token[1].type]);
cpp_ice (pfile, "directive begins with %s?!", TOKEN_NAME (token));
/* Flush pending tokens at this point, in case the directive produces
output. XXX Directive output won't be visible to a direct caller of
@ -3491,7 +3475,7 @@ _cpp_dump_list (pfile, list, token, flush)
CPP_PUTC (pfile, '#');
dump_param_spelling (pfile, list, token->val.aux);
}
else
else if (token->type != CPP_PLACEMARKER)
output_token (pfile, token, prev);
if (token->flags & PASTE_LEFT)
CPP_PUTS (pfile, " ##", 3);

View File

@ -1252,7 +1252,7 @@ _cpp_parse_assertion (pfile, answerp)
dest = &list->tokens[list->tokens_used++];
*dest = *token;
if (token_spellings[token->type].type == SPELL_STRING)
if (TOKEN_SPELL (token) == SPELL_STRING)
{
_cpp_expand_name_space (list, token->val.str.len);
dest->val.str.text = list->namebuf + list->name_used;

View File

@ -50,96 +50,92 @@ typedef struct cpp_hashnode cpp_hashnode;
#define CPP_FIRST_DIGRAPH CPP_HASH
#define TTYPE_TABLE \
T(CPP_EQ = 0, "=") \
T(CPP_NOT, "!") \
T(CPP_GREATER, ">") /* compare */ \
T(CPP_LESS, "<") \
T(CPP_PLUS, "+") /* math */ \
T(CPP_MINUS, "-") \
T(CPP_MULT, "*") \
T(CPP_DIV, "/") \
T(CPP_MOD, "%") \
T(CPP_AND, "&") /* bit ops */ \
T(CPP_OR, "|") \
T(CPP_XOR, "^") \
T(CPP_RSHIFT, ">>") \
T(CPP_LSHIFT, "<<") \
OP(CPP_EQ = 0, "=") \
OP(CPP_NOT, "!") \
OP(CPP_GREATER, ">") /* compare */ \
OP(CPP_LESS, "<") \
OP(CPP_PLUS, "+") /* math */ \
OP(CPP_MINUS, "-") \
OP(CPP_MULT, "*") \
OP(CPP_DIV, "/") \
OP(CPP_MOD, "%") \
OP(CPP_AND, "&") /* bit ops */ \
OP(CPP_OR, "|") \
OP(CPP_XOR, "^") \
OP(CPP_RSHIFT, ">>") \
OP(CPP_LSHIFT, "<<") \
\
T(CPP_COMPL, "~") \
T(CPP_AND_AND, "&&") /* logical */ \
T(CPP_OR_OR, "||") \
T(CPP_QUERY, "?") \
T(CPP_COLON, ":") \
T(CPP_COMMA, ",") /* grouping */ \
T(CPP_OPEN_PAREN, "(") \
T(CPP_CLOSE_PAREN, ")") \
T(CPP_EQ_EQ, "==") /* compare */ \
T(CPP_NOT_EQ, "!=") \
T(CPP_GREATER_EQ, ">=") \
T(CPP_LESS_EQ, "<=") \
OP(CPP_COMPL, "~") \
OP(CPP_AND_AND, "&&") /* logical */ \
OP(CPP_OR_OR, "||") \
OP(CPP_QUERY, "?") \
OP(CPP_COLON, ":") \
OP(CPP_COMMA, ",") /* grouping */ \
OP(CPP_OPEN_PAREN, "(") \
OP(CPP_CLOSE_PAREN, ")") \
OP(CPP_EQ_EQ, "==") /* compare */ \
OP(CPP_NOT_EQ, "!=") \
OP(CPP_GREATER_EQ, ">=") \
OP(CPP_LESS_EQ, "<=") \
\
T(CPP_PLUS_EQ, "+=") /* math */ \
T(CPP_MINUS_EQ, "-=") \
T(CPP_MULT_EQ, "*=") \
T(CPP_DIV_EQ, "/=") \
T(CPP_MOD_EQ, "%=") \
T(CPP_AND_EQ, "&=") /* bit ops */ \
T(CPP_OR_EQ, "|=") \
T(CPP_XOR_EQ, "^=") \
T(CPP_RSHIFT_EQ, ">>=") \
T(CPP_LSHIFT_EQ, "<<=") \
OP(CPP_PLUS_EQ, "+=") /* math */ \
OP(CPP_MINUS_EQ, "-=") \
OP(CPP_MULT_EQ, "*=") \
OP(CPP_DIV_EQ, "/=") \
OP(CPP_MOD_EQ, "%=") \
OP(CPP_AND_EQ, "&=") /* bit ops */ \
OP(CPP_OR_EQ, "|=") \
OP(CPP_XOR_EQ, "^=") \
OP(CPP_RSHIFT_EQ, ">>=") \
OP(CPP_LSHIFT_EQ, "<<=") \
/* Digraphs together, beginning with CPP_FIRST_DIGRAPH. */ \
T(CPP_HASH, "#") /* digraphs */ \
T(CPP_PASTE, "##") \
T(CPP_OPEN_SQUARE, "[") \
T(CPP_CLOSE_SQUARE, "]") \
T(CPP_OPEN_BRACE, "{") \
T(CPP_CLOSE_BRACE, "}") \
/* The remainder of the punctuation. Order is not significant. */ \
T(CPP_SEMICOLON, ";") /* structure */ \
T(CPP_ELLIPSIS, "...") \
T(CPP_BACKSLASH, "\\") \
T(CPP_PLUS_PLUS, "++") /* increment */ \
T(CPP_MINUS_MINUS, "--") \
T(CPP_DEREF, "->") /* accessors */ \
T(CPP_DOT, ".") \
T(CPP_SCOPE, "::") \
T(CPP_DEREF_STAR, "->*") \
T(CPP_DOT_STAR, ".*") \
T(CPP_MIN, "<?") /* extension */ \
T(CPP_MAX, ">?") \
T(CPP_PLACEMARKER, "") /* Placemarker token. */ \
C(CPP_OTHER, 0) /* stray punctuation */ \
OP(CPP_HASH, "#") /* digraphs */ \
OP(CPP_PASTE, "##") \
OP(CPP_OPEN_SQUARE, "[") \
OP(CPP_CLOSE_SQUARE, "]") \
OP(CPP_OPEN_BRACE, "{") \
OP(CPP_CLOSE_BRACE, "}") \
/* The remainder of the punctuation. Order is not significant. */ \
OP(CPP_SEMICOLON, ";") /* structure */ \
OP(CPP_ELLIPSIS, "...") \
OP(CPP_BACKSLASH, "\\") \
OP(CPP_PLUS_PLUS, "++") /* increment */ \
OP(CPP_MINUS_MINUS, "--") \
OP(CPP_DEREF, "->") /* accessors */ \
OP(CPP_DOT, ".") \
OP(CPP_SCOPE, "::") \
OP(CPP_DEREF_STAR, "->*") \
OP(CPP_DOT_STAR, ".*") \
OP(CPP_MIN, "<?") /* extension */ \
OP(CPP_MAX, ">?") \
\
I(CPP_NAME, 0) /* word */ \
S(CPP_INT, 0) /* 23 */ \
S(CPP_FLOAT, 0) /* 3.14159 */ \
S(CPP_NUMBER, 0) /* 34_be+ta */ \
S(CPP_CHAR, 0) /* 'char' */ \
S(CPP_WCHAR, 0) /* L'char' */ \
S(CPP_STRING, 0) /* "string" */ \
S(CPP_WSTRING, 0) /* L"string" */ \
TK(CPP_NAME, SPELL_IDENT) /* word */ \
TK(CPP_INT, SPELL_STRING) /* 23 */ \
TK(CPP_FLOAT, SPELL_STRING) /* 3.14159 */ \
TK(CPP_NUMBER, SPELL_STRING) /* 34_be+ta */ \
\
S(CPP_COMMENT, 0) /* Only if output comments. */ \
N(CPP_MACRO_ARG, 0) /* Macro argument. */ \
N(CPP_EOF, 0) /* End of file. */ \
S(CPP_HEADER_NAME, 0) /* <stdio.h> in #include */
TK(CPP_CHAR, SPELL_STRING) /* 'char' */ \
TK(CPP_WCHAR, SPELL_STRING) /* L'char' */ \
TK(CPP_OTHER, SPELL_CHAR) /* stray punctuation */ \
\
TK(CPP_STRING, SPELL_STRING) /* "string" */ \
TK(CPP_WSTRING, SPELL_STRING) /* L"string" */ \
TK(CPP_HEADER_NAME, SPELL_STRING) /* <stdio.h> in #include */ \
\
TK(CPP_COMMENT, SPELL_STRING) /* Only if output comments. */ \
TK(CPP_MACRO_ARG, SPELL_NONE) /* Macro argument. */ \
TK(CPP_PLACEMARKER, SPELL_NONE) /* Placemarker token. */ \
TK(CPP_EOF, SPELL_NONE) /* End of file. */
#define T(e, s) e,
#define I(e, s) e,
#define S(e, s) e,
#define C(e, s) e,
#define N(e, s) e,
#define OP(e, s) e,
#define TK(e, s) e,
enum cpp_ttype
{
TTYPE_TABLE
N_TTYPES
};
#undef T
#undef I
#undef S
#undef C
#undef N
#undef OP
#undef TK
/* Payload of a NUMBER, FLOAT, STRING, or COMMENT token. */
struct cpp_string

View File

@ -495,6 +495,7 @@ save_expansion (pfile, info)
{
dest->type = CPP_PLACEMARKER;
dest->flags = 0;
dest->val.aux = 0;
}
return list;

View File

@ -1,3 +1,11 @@
2000-07-18 Zack Weinberg <zack@wolery.cumb.org>
* cpplex.c (_cpp_push_token): If the token being pushed back
is the previous token in this context, just subtract one from
context->posn.
* cppmacro.c (save_expansion): Clear aux field when storing a
placemarker.
2000-07-18 Alexandre Oliva <aoliva@redhat.com>
* gcc.dg/noncompile/redecl-1.c: New test.

View File

@ -0,0 +1,24 @@
/* Regression test for bug in convoluted situation involving token paste
plus function-like macros used outside function context. It may be
easier to understand if you mentally replace 'struct' with 'A'
throughout this file; 'struct' is used only to get the code to compile
when preprocessed correctly.
The original problem was seen in the Linux kernel and reported by
Jakub Jelinek <jakub@redhat.com>; this test is synthetic. */
/* { dg-do compile } */
#define glue(a,b) a##b
#define struct(x) B(x)
#define E(x) struct x
#define FG (22)
extern void B(int);
void foo(void)
{
E(glue(F,*)) dummy; /* { dg-warning "valid preprocessing token" } */
E(glue(F,G)) ;
}

View File

@ -0,0 +1,19 @@
/* Test for changed behavior of the GNU varargs extension.
##args, where args is a rest argument which received zero tokens,
used to delete the previous sequence of nonwhitespace characters.
Now it deletes the previous token. */
/* { dg-do run } */
/* { dg-options -w } */
#include <string.h>
#define S(str, args...) " " str "\n", ##args
int
main()
{
const char *s = S("foo");
return strchr (s, '\n') == NULL;
}