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> 2000-02-29 Mark Mitchell <mark@codesourcery.com>
* fold-const.c (size_binop): Don't asert inputs are the same and * 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 ...@@ -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 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_number PARAMS ((cpp_reader *, U_CHAR *, U_CHAR *));
static struct operation parse_charconst 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)); static struct operation cpp_lex PARAMS ((cpp_reader *, int));
extern HOST_WIDEST_INT cpp_parse_expr PARAMS ((cpp_reader *)); 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)); static HOST_WIDEST_INT cpp_parse_escape PARAMS ((cpp_reader *, U_CHAR **, HOST_WIDEST_INT));
...@@ -349,6 +350,53 @@ parse_charconst (pfile, start, end) ...@@ -349,6 +350,53 @@ parse_charconst (pfile, start, end)
return op; 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 { struct token {
const char *operator; const char *operator;
...@@ -389,7 +437,7 @@ cpp_lex (pfile, skip_evaluation) ...@@ -389,7 +437,7 @@ cpp_lex (pfile, skip_evaluation)
tok_end = CPP_PWRITTEN (pfile); tok_end = CPP_PWRITTEN (pfile);
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
switch (token) switch (token)
{ {
case CPP_EOF: /* Should not happen ... */ case CPP_EOF: /* Should not happen ... */
case CPP_VSPACE: case CPP_VSPACE:
op.op = 0; op.op = 0;
...@@ -407,51 +455,22 @@ cpp_lex (pfile, skip_evaluation) ...@@ -407,51 +455,22 @@ cpp_lex (pfile, skip_evaluation)
return parse_charconst (pfile, tok_start, tok_end); return parse_charconst (pfile, tok_start, tok_end);
case CPP_NAME: case CPP_NAME:
if (!strcmp (tok_start, "defined"))
return parse_defined (pfile);
op.op = INT; op.op = INT;
op.unsignedp = 0; op.unsignedp = 0;
op.value = 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) if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
goto oops; cpp_warning (pfile, "`%.*s' is not defined",
(int) (tok_end - tok_start), tok_start);
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--;
}
return op; return op;
oops: case CPP_ASSERTION:
CPP_SET_WRITTEN (pfile, old_written); op.op = INT;
pfile->no_macro_expand--; op.unsignedp = 0;
cpp_error (pfile, "`defined' without an identifier"); op.value = cpp_defined (pfile, tok_start, tok_end - tok_start);
return op; return op;
case CPP_OTHER: case CPP_OTHER:
...@@ -468,13 +487,6 @@ cpp_lex (pfile, skip_evaluation) ...@@ -468,13 +487,6 @@ cpp_lex (pfile, skip_evaluation)
op.op = toktab->token; op.op = toktab->token;
return op; 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 */ /* fall through */
default: default:
op.op = *tok_start; op.op = *tok_start;
......
...@@ -18,15 +18,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ...@@ -18,15 +18,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef __GCC_CPPHASH__ #ifndef __GCC_CPPHASH__
#define __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 /* Structure allocated for every #define. For a simple replacement
such as such as
#define foo bar , #define foo bar ,
...@@ -48,30 +39,35 @@ struct macrodef ...@@ -48,30 +39,35 @@ struct macrodef
{ (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL } { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
where (x, y) means (nchars, argno). */ 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; typedef struct definition DEFINITION;
struct definition { struct definition
{
int nargs; int nargs;
int length; /* length of expansion string */ int length; /* length of expansion string */
unsigned char *expansion; U_CHAR *expansion;
int line; /* Line number of definition */ int line; /* Line number of definition */
int col;
const char *file; /* File of definition */ const char *file; /* File of definition */
char rest_args; /* Nonzero if last arg. absorbs the rest */ char rest_args; /* Nonzero if last arg. absorbs the rest */
struct reflist { struct reflist *pattern;
struct reflist *next;
char stringify; /* nonzero if this arg was preceded by a /* Names of macro args, concatenated in order with commas between
# operator. */ them. The only use of this is that we warn on redefinition if
char raw_before; /* Nonzero if a ## operator before arg. */ this differs between the old and new definitions. */
char raw_after; /* Nonzero if a ## operator after arg. */ U_CHAR *argnames;
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;
}; };
/* different kinds of things that can appear in the value field /* 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)); ...@@ -102,8 +98,7 @@ extern HASHNODE *cpp_lookup PARAMS ((cpp_reader *, const U_CHAR *, int));
extern void free_definition PARAMS ((DEFINITION *)); extern void free_definition PARAMS ((DEFINITION *));
extern void delete_macro PARAMS ((HASHNODE *)); extern void delete_macro PARAMS ((HASHNODE *));
extern MACRODEF create_definition PARAMS ((U_CHAR *, U_CHAR *, extern DEFINITION *create_definition PARAMS ((cpp_reader *, int));
cpp_reader *));
extern int compare_defs PARAMS ((cpp_reader *, DEFINITION *, extern int compare_defs PARAMS ((cpp_reader *, DEFINITION *,
DEFINITION *)); DEFINITION *));
extern void macroexpand PARAMS ((cpp_reader *, HASHNODE *)); extern void macroexpand PARAMS ((cpp_reader *, HASHNODE *));
......
...@@ -1256,9 +1256,6 @@ cpp_handle_option (pfile, argc, argv) ...@@ -1256,9 +1256,6 @@ cpp_handle_option (pfile, argc, argv)
opts->include_prefix_len = strlen (argv[i]); opts->include_prefix_len = strlen (argv[i]);
} }
} }
else if (!strcmp (argv[i], "-ifoutput"))
opts->output_conditionals = 1;
break; break;
case 'o': case 'o':
...@@ -1736,7 +1733,6 @@ Switches:\n\ ...@@ -1736,7 +1733,6 @@ Switches:\n\
-dD Preserve macro definitions in output\n\ -dD Preserve macro definitions in output\n\
-dN As -dD except that only the names are preserved\n\ -dN As -dD except that only the names are preserved\n\
-dI Include #include directives in the output\n\ -dI Include #include directives in the output\n\
-ifoutput Describe skipped code blocks in output \n\
-P Do not generate #line directives\n\ -P Do not generate #line directives\n\
-$ Do not allow '$' in identifiers\n\ -$ Do not allow '$' in identifiers\n\
-remap Remap file names when including files.\n\ -remap Remap file names when including files.\n\
......
...@@ -47,14 +47,17 @@ enum cpp_token { ...@@ -47,14 +47,17 @@ enum cpp_token {
CPP_STRING, CPP_STRING,
CPP_WSTRING, CPP_WSTRING,
CPP_DIRECTIVE, CPP_DIRECTIVE,
CPP_LPAREN, /* "(" */ CPP_ASSERTION, /* #machine(a29k) */
CPP_RPAREN, /* ")" */ CPP_STRINGIZE, /* stringize macro argument */
CPP_LBRACE, /* "{" */ CPP_TOKPASTE, /* paste macro arg with next/prev token */
CPP_RBRACE, /* "}" */ CPP_LPAREN, /* "(" */
CPP_COMMA, /* "," */ CPP_RPAREN, /* ")" */
CPP_SEMICOLON,/* ";" */ CPP_LBRACE, /* "{" */
CPP_3DOTS, /* "..." */ CPP_RBRACE, /* "}" */
CPP_POP /* We're about to pop the buffer stack. */ 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 *)); typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader *));
...@@ -193,7 +196,6 @@ struct cpp_reader ...@@ -193,7 +196,6 @@ struct cpp_reader
/* If non-zero, directives cause a hard error. Used when parsing /* If non-zero, directives cause a hard error. Used when parsing
macro arguments. */ macro arguments. */
char no_directives; char no_directives;
/* Print column number in error messages. */ /* Print column number in error messages. */
...@@ -205,6 +207,12 @@ struct cpp_reader ...@@ -205,6 +207,12 @@ struct cpp_reader
/* If true, character between '<' and '>' are a single (string) token. */ /* If true, character between '<' and '>' are a single (string) token. */
char parsing_include_directive; 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 /* True if escape sequences (as described for has_escapes in
parse_buffer) should be emitted. */ parse_buffer) should be emitted. */
char output_escapes; char output_escapes;
...@@ -217,7 +225,7 @@ struct cpp_reader ...@@ -217,7 +225,7 @@ struct cpp_reader
/* Nonzero means this file was included with a -imacros or -include /* Nonzero means this file was included with a -imacros or -include
command line and should not be recorded as an include file. */ command line and should not be recorded as an include file. */
int no_record_file; char no_record_file;
long lineno; long lineno;
...@@ -427,11 +435,6 @@ struct cpp_options { ...@@ -427,11 +435,6 @@ struct cpp_options {
char no_line_commands; char no_line_commands;
/* Nonzero means output the text in failing conditionals,
inside #failed ... #endfailed. */
char output_conditionals;
/* Nonzero means -I- has been seen, /* Nonzero means -I- has been seen,
so don't look for #include "foo" the source-file directory. */ so don't look for #include "foo" the source-file directory. */
char ignore_srcdir; char ignore_srcdir;
...@@ -689,14 +692,12 @@ extern int cpp_defined PARAMS ((cpp_reader *, const U_CHAR *, int)); ...@@ -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_reader_init PARAMS ((cpp_reader *));
extern void cpp_options_init PARAMS ((cpp_options *)); extern void cpp_options_init PARAMS ((cpp_options *));
extern int cpp_start_read PARAMS ((cpp_reader *, char *)); 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 cpp_finish PARAMS ((cpp_reader *));
extern void quote_string PARAMS ((cpp_reader *, const char *)); extern void quote_string PARAMS ((cpp_reader *, const char *));
extern void cpp_expand_to_buffer PARAMS ((cpp_reader *, const U_CHAR *, extern void cpp_expand_to_buffer PARAMS ((cpp_reader *, const U_CHAR *,
int)); int));
extern void cpp_scan_buffer PARAMS ((cpp_reader *)); 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. */ /* Last arg to output_line_command. */
enum file_change_code {same_file, rename_file, enter_file, leave_file}; enum file_change_code {same_file, rename_file, enter_file, leave_file};
......
/* { dg-do compile } */ /* { 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 NO_PAREN(rest...) rest
#define DEFINE_CATEGORY(category, items) \ #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