Commit ba412f14 by Zack Weinberg Committed by Zack Weinberg

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
parent 38769add
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
......
......@@ -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;
......
......@@ -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 *));
......
......@@ -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\
......
......@@ -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};
......
/* { 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) \
......
/* { 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;
}
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