top level:

2000-07-03  Zack Weinberg  <zack@wolery.cumb.org>

	* fix-header.c (struct partial_proto): Remove unnecessary fields.
	(recognized_extern, recognized_function, read_scan_file):
	Update for new scheme.
	(check_protection): It's still a multiple include guard even
	if it doesn't always trigger.
	* scan-decls.c (skip_to_closing_brace, scan_decls): Update for
	new scheme.
	* scan.h: Declare struct cpp_token.  Update prototypes.

2000-07-03  Neil Booth  <neilb@earthling.net>
	    Zack Weinberg  <zack@wolery.cumb.org>

	Complete overhaul of the lexer and macro expander.

	* cpphash.c (object_defn, funct_defn, push_macro_expansion,
	arg, arglist, argdata, reflist, collect_objlike_expansion,
	collect_funlike_expansion, collect_params,
	warn_trad_stringify, trad_stringify, duplicate_arg_p, add_pat,
	unsafe_chars, macarg, compare_defs, special_symbol,
	scan_arguments, stringify, funlike_macroexpand,
	_cpp_quote_string, monthnames): Delete.
	(cpp_lookup, _cpp_free_definition, dump_funlike_macro,
	_cpp_create_definition, _cpp_dump_definition,
	dump_hash_helper): Adjust.
	(find_param, count_params, parse_define, var_args_str,
	check_macro_redefinition, save_expansion): New.

	* cpplex.c (skip_block_comment, skip_line_comment, parse_name,
        parse_string, output_line_command, trigraph_replace,
        lex_line, cpp_push_buffer, cpp_pop_buffer, cpp_output_tokens,
        cpp_scan_buffer_nooutput, cpp_scan_buffer, cpp_free_toklist,
        cpp_idcmp, _cpp_get_directive_token, _cpp_init_input_buffer,
	_cpp_skip_rest_of_line): Modify.

        (maybe_macroexpand, skip_comment, copy_comment, skip_string,
	find_position, null_warning, bump_column, expand_name_space,
	pedantic_whitespace, _cpp_output_list, _cpp_slice_toklist,
	_cpp_squeeze_toklist, _cpp_scan_until, _cpp_skip_hspace,
	_cpp_parse_name, _cpp_lex_token, cpp_get_non_space_token,
	_cpp_prescan): Delete.

	(dump_param_spelling, process_directive, lex_next,
        is_macro_disabled, stringify_arg, expand_context_stack,
        output_token, make_string_token, alloc_number_token,
        special_symbol, duplicate_token, maybe_paste_with_next,
        can_paste, prevent_macro_expansion, restore_macro_expansion,
        get_temp_token, release_temp_tokens, quote_string,
        token_names, token_spellings, _cpp_expand_name_space,
        _cpp_glue_header_name, _cpp_reserve_name_space,
        digraph_spellings, trigraph_ok, skip_whitespace, save_comment,
        placemarker_token, eof_token, cpp_context, macro_args,
        get_raw_token, parse_arg, parse_args, save_token,
        push_arg_context, push_macro_context, pop_context,
        do_pop_context, free_macro_args, _cpp_get_line,
        _cpp_run_directive): New.

	* cpplib.c (validate_else, parse_include, push_conditional,
	pass_thru_directive, read_line_number, parse_ifdef,
	detect_if_not_defined, _cpp_check_directive, do_define,
	do_undef, do_include, do_import, do_include_next, do_error,
	do_warning, do_ident, do_pragma, pragma_dispatch, gcc_pragmas,
	top_pragmas, do_pragma_gcc, do_pragma_implementation,
	do_pragma_poison, do_pragma_system_header,
	do_pragma_dependency, do_sccs, do_ifdef, do_ifndef, do_else,
	dl_elif, do_endif, _cpp_unwind_if_stack, do_assert,
	do_unassert, cpp_define, cpp_undef, cpp_assert, cpp_unassert,
	cpp_defined): Update for new scheme.
	(strtoul_for_line, get_define_node, dump_macro_name,
	_cpp_check_linemarker, _cpp_parse_assertion): New.
	(_cpp_handle_directive, do_pragma_default): Delete.

	* cpphash.h (struct predicate): Now struct answer.
	(enum spell_type, struct token_spelling, struct directive,
	directive_handler): New.
	Update prototypes.  Remove unused macros.
	* cpplib.h: Update prototypes.  Remove unused macros,
	structure definitions, and fields.

	* cpperror.c (print_containing_files, v_message): Adjust.
	* cppexp.c (parse_assertion, lex, parse_escape,
	_cpp_parse_expr): Adjust.
	* cppfiles.c (open_include_file, _cpp_execute_include,
	_cpp_compare_file_date, cpp_read_file, read_include_file):
	Adjust.
	* cppinit.c (dump_special_to_buffer): Delete.
	(append_include_chain, merge_include_chains, cpp_reader_init,
	cpp_cleanup, initialize_builtins, builtin_array, cpp_start_read,
	cpp_finish, handle_option, print_help): Adjust.
	* cppmain.c (main): Adjust.

testsuite:
2000-07-03  Zack Weinberg  <zack@wolery.cumb.org>

	* testsuite/gcc.dg/cpp/19951025-1.c: Adjust regexps.
	* testsuite/gcc.dg/cpp/19990703-1.c: Likewise.
	* testsuite/gcc.dg/cpp/20000625-1.c: Likewise.
	* testsuite/gcc.dg/cpp/20000625-2.c: Likewise.

	* testsuite/gcc.dg/cpp/macro1.c,
	testsuite/gcc.dg/cpp/paste1.c, testsuite/gcc.dg/cpp/paste2.c,
	testsuite/gcc.dg/cpp/paste3.c, testsuite/gcc.dg/cpp/paste4.c,
	testsuite/gcc.dg/cpp/strify1.c,
	testsuite/gcc.dg/cpp/strify2.c: New tests.

From-SVN: r34859
This commit is contained in:
Zack Weinberg 2000-07-04 01:58:21 +00:00
parent 4f647814ce
commit 041c31944c
26 changed files with 3856 additions and 5027 deletions

View file

@ -1,3 +1,95 @@
2000-07-03 Zack Weinberg <zack@wolery.cumb.org>
* fix-header.c (struct partial_proto): Remove unnecessary fields.
(recognized_extern, recognized_function, read_scan_file):
Update for new scheme.
(check_protection): It's still a multiple include guard even
if it doesn't always trigger.
* scan-decls.c (skip_to_closing_brace, scan_decls): Update for
new scheme.
* scan.h: Declare struct cpp_token. Update prototypes.
2000-07-03 Neil Booth <neilb@earthling.net>
Zack Weinberg <zack@wolery.cumb.org>
Complete overhaul of the lexer and macro expander.
* cpphash.c (object_defn, funct_defn, push_macro_expansion,
arg, arglist, argdata, reflist, collect_objlike_expansion,
collect_funlike_expansion, collect_params,
warn_trad_stringify, trad_stringify, duplicate_arg_p, add_pat,
unsafe_chars, macarg, compare_defs, special_symbol,
scan_arguments, stringify, funlike_macroexpand,
_cpp_quote_string, monthnames): Delete.
(cpp_lookup, _cpp_free_definition, dump_funlike_macro,
_cpp_create_definition, _cpp_dump_definition,
dump_hash_helper): Adjust.
(find_param, count_params, parse_define, var_args_str,
check_macro_redefinition, save_expansion): New.
* cpplex.c (skip_block_comment, skip_line_comment, parse_name,
parse_string, output_line_command, trigraph_replace,
lex_line, cpp_push_buffer, cpp_pop_buffer, cpp_output_tokens,
cpp_scan_buffer_nooutput, cpp_scan_buffer, cpp_free_toklist,
cpp_idcmp, _cpp_get_directive_token, _cpp_init_input_buffer,
_cpp_skip_rest_of_line): Modify.
(maybe_macroexpand, skip_comment, copy_comment, skip_string,
find_position, null_warning, bump_column, expand_name_space,
pedantic_whitespace, _cpp_output_list, _cpp_slice_toklist,
_cpp_squeeze_toklist, _cpp_scan_until, _cpp_skip_hspace,
_cpp_parse_name, _cpp_lex_token, cpp_get_non_space_token,
_cpp_prescan): Delete.
(dump_param_spelling, process_directive, lex_next,
is_macro_disabled, stringify_arg, expand_context_stack,
output_token, make_string_token, alloc_number_token,
special_symbol, duplicate_token, maybe_paste_with_next,
can_paste, prevent_macro_expansion, restore_macro_expansion,
get_temp_token, release_temp_tokens, quote_string,
token_names, token_spellings, _cpp_expand_name_space,
_cpp_glue_header_name, _cpp_reserve_name_space,
digraph_spellings, trigraph_ok, skip_whitespace, save_comment,
placemarker_token, eof_token, cpp_context, macro_args,
get_raw_token, parse_arg, parse_args, save_token,
push_arg_context, push_macro_context, pop_context,
do_pop_context, free_macro_args, _cpp_get_line,
_cpp_run_directive): New.
* cpplib.c (validate_else, parse_include, push_conditional,
pass_thru_directive, read_line_number, parse_ifdef,
detect_if_not_defined, _cpp_check_directive, do_define,
do_undef, do_include, do_import, do_include_next, do_error,
do_warning, do_ident, do_pragma, pragma_dispatch, gcc_pragmas,
top_pragmas, do_pragma_gcc, do_pragma_implementation,
do_pragma_poison, do_pragma_system_header,
do_pragma_dependency, do_sccs, do_ifdef, do_ifndef, do_else,
dl_elif, do_endif, _cpp_unwind_if_stack, do_assert,
do_unassert, cpp_define, cpp_undef, cpp_assert, cpp_unassert,
cpp_defined): Update for new scheme.
(strtoul_for_line, get_define_node, dump_macro_name,
_cpp_check_linemarker, _cpp_parse_assertion): New.
(_cpp_handle_directive, do_pragma_default): Delete.
* cpphash.h (struct predicate): Now struct answer.
(enum spell_type, struct token_spelling, struct directive,
directive_handler): New.
Update prototypes. Remove unused macros.
* cpplib.h: Update prototypes. Remove unused macros,
structure definitions, and fields.
* cpperror.c (print_containing_files, v_message): Adjust.
* cppexp.c (parse_assertion, lex, parse_escape,
_cpp_parse_expr): Adjust.
* cppfiles.c (open_include_file, _cpp_execute_include,
_cpp_compare_file_date, cpp_read_file, read_include_file):
Adjust.
* cppinit.c (dump_special_to_buffer): Delete.
(append_include_chain, merge_include_chains, cpp_reader_init,
cpp_cleanup, initialize_builtins, builtin_array, cpp_start_read,
cpp_finish, handle_option, print_help): Adjust.
* cppmain.c (main): Adjust.
2000-07-03 Zack Weinberg <zack@wolery.cumb.org>
* cppspec.c (lang_specific_driver): Use double quotes in error

View file

@ -58,23 +58,27 @@ print_containing_files (pfile, ip)
if (first)
{
first = 0;
/* N.B. The current line in each outer source file is one
greater than the line of the #include, so we must
subtract one to correct for that. */
fprintf (stderr, _("In file included from %s:%u"),
ip->nominal_fname, CPP_BUF_LINE (ip));
ip->nominal_fname, CPP_BUF_LINE (ip) - 1);
}
else
/* Translators note: this message is used in conjunction
with "In file included from %s:%ld" and some other
tricks. We want something like this:
In file included from sys/select.h:123,
from sys/types.h:234,
from userfile.c:31:
bits/select.h:45: <error message here>
| In file included from sys/select.h:123,
| from sys/types.h:234,
| from userfile.c:31:
| bits/select.h:45: <error message here>
with all the "from"s lined up.
The trailing comma is at the beginning of this message,
and the trailing colon is not translated. */
fprintf (stderr, _(",\n from %s:%u"),
ip->nominal_fname, CPP_BUF_LINE (ip));
ip->nominal_fname, CPP_BUF_LINE (ip) - 1);
}
if (first == 0)
fputs (":\n", stderr);
@ -111,17 +115,14 @@ v_message (pfile, is_error, file, line, col, msg, ap)
const char *msg;
va_list ap;
{
cpp_buffer *ip = cpp_file_buffer (pfile);
cpp_buffer *ip = CPP_BUFFER (pfile);
if (ip)
{
if (file == NULL)
file = ip->nominal_fname;
if (line == 0)
{
line = CPP_BUF_LINE (ip);
col = CPP_BUF_COL (ip);
}
line = _cpp_get_line (pfile, &col);
print_containing_files (pfile, ip);
print_file_and_line (file, line,
CPP_OPTION (pfile, show_column) ? col : 0);
@ -132,8 +133,12 @@ v_message (pfile, is_error, file, line, col, msg, ap)
switch (is_error)
{
case 0:
fprintf (stderr, _("warning: "));
break;
if (! CPP_OPTION (pfile, warnings_are_errors))
{
fprintf (stderr, _("warning: "));
break;
}
/* else fall through */
case 1:
if (pfile->errors < CPP_FATAL_LIMIT)
pfile->errors++;

View file

@ -394,74 +394,22 @@ parse_assertion (pfile)
cpp_reader *pfile;
{
struct operation op;
struct answer *answer;
cpp_hashnode *hp;
struct predicate *pred;
cpp_toklist query;
enum cpp_ttype type;
U_CHAR *tok;
size_t len;
unsigned int old_written;
int specific = 0;
old_written = CPP_WRITTEN (pfile);
CPP_PUTC (pfile, '#');
pfile->no_macro_expand++;
type = _cpp_get_directive_token (pfile);
if (type == CPP_VSPACE)
SYNTAX_ERROR ("assertion without predicate");
else if (type != CPP_NAME)
SYNTAX_ERROR ("assertion predicate is not an identifier");
tok = pfile->token_buffer + old_written;
len = CPP_WRITTEN (pfile) - old_written;
hp = cpp_lookup (pfile, tok, len);
/* Look ahead for an open paren. */
_cpp_skip_hspace (pfile);
if (CPP_BUF_PEEK (CPP_BUFFER (pfile)) == '(')
{
if (_cpp_get_directive_token (pfile) != CPP_OPEN_PAREN)
CPP_ICE ("impossible token, expecting ( in parse_assertion");
_cpp_init_toklist (&query, NO_DUMMY_TOKEN);
specific = 1;
if (_cpp_scan_until (pfile, &query, CPP_CLOSE_PAREN) != CPP_CLOSE_PAREN)
SYNTAX_ERROR ("missing close paren on assertion answer");
if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
CPP_ICE ("impossible token, expecting ) in parse_assertion");
}
/* If we get here, the syntax is valid. */
op.op = INT;
op.value = 0;
/* Has this predicate been asserted at all? */
if (hp->type == T_ASSERTION)
{
if (specific)
{
for (pred = hp->value.pred; pred; pred = pred->next)
if (_cpp_equiv_toklists (&query, &pred->answer))
{
op.value = 1;
break;
}
_cpp_free_toklist (&query);
}
else
op.value = 1;
}
out:
pfile->no_macro_expand--;
CPP_SET_WRITTEN (pfile, old_written);
return op;
syntax_error:
if (specific)
_cpp_free_toklist (&query);
op.op = ERROR;
goto out;
hp = _cpp_parse_assertion (pfile, &answer);
if (hp)
{
/* If we get here, the syntax is valid. */
op.op = INT;
op.value = (hp->type == T_ASSERTION &&
(answer == 0 || *find_answer (hp, &answer->list) != 0));
if (answer)
FREE_ANSWER (answer);
}
return op;
}
struct token
@ -480,8 +428,6 @@ static const struct token tokentab2[] =
{"!=", NOTEQUAL},
{"<=", LEQ},
{">=", GEQ},
{"++", ERROR},
{"--", ERROR},
{NULL, ERROR}
};
@ -496,16 +442,20 @@ lex (pfile, skip_evaluation)
enum cpp_ttype token;
struct operation op;
U_CHAR *tok_start, *tok_end;
long old_written;
long old_written = CPP_WRITTEN (pfile);
old_written = CPP_WRITTEN (pfile);
retry:
token = _cpp_get_directive_token (pfile);
tok_start = pfile->token_buffer + old_written;
tok_end = CPP_PWRITTEN (pfile);
CPP_SET_WRITTEN (pfile, old_written);
switch (token)
{
case CPP_PLACEMARKER:
CPP_SET_WRITTEN (pfile, old_written);
goto retry;
case CPP_EOF: /* Should not happen ... */
case CPP_VSPACE:
op.op = 0;
@ -524,6 +474,7 @@ lex (pfile, skip_evaluation)
return parse_charconst (pfile, tok_start, tok_end);
case CPP_NAME:
/* FIXME: could this not overflow the tok_start buffer? */
if (!ustrncmp (tok_start, U"defined", 7))
return parse_defined (pfile);
@ -539,7 +490,16 @@ lex (pfile, skip_evaluation)
case CPP_HASH:
return parse_assertion (pfile);
case CPP_OTHER:
case CPP_AND_AND: op.op = ANDAND; return op;
case CPP_OR_OR: op.op = OROR; return op;
case CPP_LSHIFT: op.op = LSH; return op;
case CPP_RSHIFT: op.op = RSH; return op;
case CPP_EQ_EQ: op.op = EQUAL; return op;
case CPP_NOT_EQ: op.op = NOTEQUAL; return op;
case CPP_LESS_EQ: op.op = LEQ; return op;
case CPP_GREATER_EQ:op.op = GEQ; return op;
default:
/* See if it is a special token of length 2. */
if (tok_start + 2 == tok_end)
{
@ -553,8 +513,6 @@ lex (pfile, skip_evaluation)
op.op = toktab->token;
return op;
}
/* fall through */
default:
op.op = *tok_start;
return op;
}
@ -612,7 +570,7 @@ parse_escape (pfile, string_ptr, result_mask)
case 'e':
case 'E':
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "non-ANSI-standard escape sequence, '\\%c'", c);
cpp_pedwarn (pfile, "non-ISO-standard escape sequence, '\\%c'", c);
return TARGET_ESC;
case 'f':
return TARGET_FF;
@ -844,9 +802,7 @@ _cpp_parse_expr (pfile)
char buff[5];
/* Save parser state and set it to something sane. */
int save_only_seen_white = pfile->only_seen_white;
int save_skipping = pfile->skipping;
pfile->only_seen_white = 0;
pfile->skipping = 0;
/* We've finished when we try to reduce this. */
@ -875,7 +831,8 @@ _cpp_parse_expr (pfile)
case ERROR:
goto syntax_error;
default:
SYNTAX_ERROR ("invalid character in #if");
SYNTAX_ERROR2 ("invalid character '%s' in #if",
op_to_str (op.op, buff));
push_immediate:
case INT:
@ -1168,7 +1125,6 @@ _cpp_parse_expr (pfile)
if (stack != init_stack)
free (stack);
CPP_SET_WRITTEN (pfile, old_written);
pfile->only_seen_white = save_only_seen_white;
pfile->skipping = save_skipping;
return result;
}

View file

@ -180,7 +180,7 @@ open_include_file (pfile, filename)
#ifdef EACCES
if (errno == EACCES)
{
cpp_error (pfile, "included file `%s' exists but is not readable",
cpp_error (pfile, "included file \"%s\" exists but is not readable",
filename);
}
#endif
@ -360,16 +360,16 @@ cpp_make_system_header (pfile, pbuf, flag)
#define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth))
void
_cpp_execute_include (pfile, f, len, no_reinclude, search_start)
_cpp_execute_include (pfile, f, len, no_reinclude, search_start, angle_brackets)
cpp_reader *pfile;
U_CHAR *f;
const U_CHAR *f;
unsigned int len;
int no_reinclude;
struct file_name_list *search_start;
int angle_brackets;
{
struct include_file *inc;
char *fname = (char *)f;
int angle_brackets = fname[0] == '<';
char *fname;
if (!search_start)
{
@ -387,9 +387,8 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
return;
}
/* Remove quote marks. */
fname++;
len -= 2;
fname = alloca (len + 1);
memcpy (fname, f, len);
fname[len] = '\0';
inc = find_include_file (pfile, fname, search_start);
@ -470,32 +469,27 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
if F cannot be located or dated, 1, if it is newer and 0 if older. */
int
_cpp_compare_file_date (pfile, f, len, search_start)
_cpp_compare_file_date (pfile, f, len, angle_brackets)
cpp_reader *pfile;
U_CHAR *f;
const U_CHAR *f;
unsigned int len;
struct file_name_list *search_start;
int angle_brackets;
{
char *fname = (char *)f;
int angle_brackets = fname[0] == '<';
char *fname;
struct file_name_list *search_start;
struct include_file *inc;
struct include_file *current_include = cpp_file_buffer (pfile)->inc;
struct include_file *current_include = CPP_BUFFER (pfile)->inc;
if (!search_start)
{
if (angle_brackets)
search_start = CPP_OPTION (pfile, bracket_include);
else if (CPP_OPTION (pfile, ignore_srcdir))
search_start = CPP_OPTION (pfile, quote_include);
else
search_start = CPP_BUFFER (pfile)->actual_dir;
}
if (angle_brackets)
search_start = CPP_OPTION (pfile, bracket_include);
else if (CPP_OPTION (pfile, ignore_srcdir))
search_start = CPP_OPTION (pfile, quote_include);
else
search_start = CPP_BUFFER (pfile)->actual_dir;
/* Remove quote marks. */
fname++;
len -= 2;
fname = alloca (len + 1);
memcpy (fname, f, len);
fname[len] = '\0';
inc = find_include_file (pfile, fname, search_start);
if (!inc)
@ -534,6 +528,12 @@ cpp_read_file (pfile, fname)
f = open_include_file (pfile, fname);
if (f == NULL)
{
cpp_error_from_errno (pfile, fname);
return 0;
}
return read_include_file (pfile, f);
}
@ -550,12 +550,17 @@ read_include_file (pfile, inc)
cpp_buffer *fp;
int fd = inc->fd;
/* Ensures we dump our current line before entering an include file. */
if (CPP_BUFFER (pfile) && pfile->printer)
cpp_output_tokens (pfile, pfile->printer,
CPP_BUF_LINE (CPP_BUFFER (pfile)));
fp = cpp_push_buffer (pfile, NULL, 0);
if (fp == 0)
goto push_fail;
if (fstat (fd, &st) < 0)
if (fd < 0 || fstat (fd, &st) < 0)
goto perror_fail;
inc->date = st.st_mtime;
@ -622,9 +627,6 @@ read_include_file (pfile, inc)
if (length == 0)
inc->cmacro = NEVER_REREAD;
else
/* Temporary - I hope. */
length = _cpp_prescan (pfile, fp, length);
fp->rlimit = fp->buf + length;
fp->cur = fp->buf;
@ -637,13 +639,13 @@ read_include_file (pfile, inc)
fp->actual_dir = actual_directory (pfile, inc->name);
pfile->input_stack_listing_current = 0;
pfile->only_seen_white = 2;
return 1;
perror_fail:
cpp_error_from_errno (pfile, inc->name);
/* Do not try to read this file again. */
close (fd);
if (fd != -1)
close (fd);
inc->fd = -1;
inc->cmacro = NEVER_REREAD;
fail:

File diff suppressed because it is too large Load diff

View file

@ -25,11 +25,60 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
typedef unsigned char U_CHAR;
#define U (const U_CHAR *) /* Intended use: U"string" */
/* Structure used for assertion predicates. */
struct predicate
/* Order here matters. Those beyond SPELL_NONE store their spelling
in the token list, and it's length in the token->val.name.len. */
enum spell_type
{
struct predicate *next;
struct cpp_toklist answer;
SPELL_OPERATOR = 0,
SPELL_CHAR,
SPELL_NONE,
SPELL_IDENT,
SPELL_STRING
};
struct token_spelling
{
ENUM_BITFIELD(spell_type) type : CHAR_BIT;
const U_CHAR *spelling;
};
extern const struct token_spelling token_spellings[];
/* Chained list of answers to an assertion. */
struct answer
{
struct answer *next;
cpp_toklist list;
};
#define FREE_ANSWER(answer) do {_cpp_free_toklist (&answer->list); \
free (answer); } while (0)
/* Values for the origin field of struct directive. KANDR directives
come from traditional (K&R) C. STDC89 directives come from the
1989 C standard. EXTENSION directives are extensions. */
#define KANDR 0
#define STDC89 1
#define EXTENSION 2
/* Values for the flags field of struct directive. COND indicates a
conditional. EXPAND means that macros are to be expanded on the
directive line. INCL means to treat "..." and <...> as
q-char-sequence and h-char-sequence respectively. COMMENTS means
preserve comments in the directive if -C. */
#define COND (1 << 0)
#define EXPAND (1 << 1)
#define INCL (1 << 2)
#define COMMENTS (1 << 3)
/* Defines one #-directive, including how to handle it. */
typedef int (*directive_handler) PARAMS ((cpp_reader *));
struct directive
{
directive_handler handler; /* Function to handle directive. */
const U_CHAR *name; /* Name of directive. */
unsigned short length; /* Length of name. */
unsigned char origin; /* Origin of directive. */
unsigned char flags; /* Flags describing this directive. */
};
/* List of directories to look for include files in. */
@ -105,12 +154,6 @@ extern unsigned char _cpp_IStable[256];
/* Macros. */
/* One character lookahead in the input buffer. Note that if this
returns EOF, it does *not* necessarily mean the file's end has been
reached. */
#define CPP_BUF_PEEK(BUFFER) \
((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur : EOF)
/* Make sure PFILE->token_buffer has space for at least N more characters. */
#define CPP_RESERVE(PFILE, N) \
(CPP_WRITTEN (PFILE) + (size_t)(N) > (PFILE)->token_buffer_size \
@ -127,53 +170,15 @@ extern unsigned char _cpp_IStable[256];
/* Append character CH to PFILE's output buffer. Make space if need be. */
#define CPP_PUTC(PFILE, CH) (CPP_RESERVE (PFILE, 1), CPP_PUTC_Q (PFILE, CH))
/* Advance the current line by one. */
#define CPP_BUMP_BUFFER_LINE(PBUF) ((PBUF)->lineno++,\
(PBUF)->line_base = (PBUF)->cur)
#define CPP_BUMP_LINE(PFILE) CPP_BUMP_BUFFER_LINE(CPP_BUFFER(PFILE))
#define CPP_BUMP_BUFFER_LINE_CUR(PBUF, CUR) ((PBUF)->lineno++,\
(PBUF)->line_base = CUR)
#define CPP_BUMP_LINE_CUR(PFILE, CUR) \
CPP_BUMP_BUFFER_LINE_CUR(CPP_BUFFER(PFILE), CUR)
#define CPP_PREV_BUFFER(BUFFER) ((BUFFER)->prev)
/* Are we in column 1 right now? Used mainly for -traditional handling
of directives. */
#define CPP_IN_COLUMN_1(PFILE) \
(CPP_BUFFER (PFILE)->cur - CPP_BUFFER (PFILE)->line_base == 1)
#define CPP_PRINT_DEPS(PFILE) CPP_OPTION (PFILE, print_deps)
#define CPP_TRADITIONAL(PFILE) CPP_OPTION (PFILE, traditional)
#define CPP_IN_SYSTEM_HEADER(PFILE) (cpp_file_buffer (PFILE)->inc->sysp)
#define CPP_IN_SYSTEM_HEADER(PFILE) (CPP_BUFFER (PFILE)->inc->sysp)
#define CPP_PEDANTIC(PF) \
(CPP_OPTION (PF, pedantic) && !CPP_IN_SYSTEM_HEADER (PF))
#define CPP_WTRADITIONAL(PF) \
(CPP_OPTION (PF, warn_traditional) && !CPP_IN_SYSTEM_HEADER (PF))
/* CPP_IS_MACRO_BUFFER is true if the buffer contains macro expansion.
(Note that it is false while we're expanding macro *arguments*.) */
#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->macro != NULL)
/* Remember the current position of PFILE so it may be returned to
after looking ahead a bit.
Note that when you set a mark, you _must_ return to that mark. You
may not forget about it and continue parsing. You may not pop a
buffer with an active mark. You may not call CPP_BUMP_LINE while a
mark is active. */
#define CPP_SET_BUF_MARK(IP) ((IP)->mark = (IP)->cur)
#define CPP_GOTO_BUF_MARK(IP) ((IP)->cur = (IP)->mark, (IP)->mark = 0)
#define CPP_SET_MARK(PFILE) CPP_SET_BUF_MARK(CPP_BUFFER(PFILE))
#define CPP_GOTO_MARK(PFILE) CPP_GOTO_BUF_MARK(CPP_BUFFER(PFILE))
/* ACTIVE_MARK_P is true if there's a live mark in the buffer. */
#define ACTIVE_MARK_P(PFILE) (CPP_BUFFER (PFILE)->mark != 0)
/* Are mark and point adjacent characters? Used mostly to deal with
the somewhat annoying semantic of #define. */
#define ADJACENT_TO_MARK(PFILE) \
(CPP_BUFFER(PFILE)->cur - CPP_BUFFER(PFILE)->mark == 1)
/* Flags for _cpp_init_toklist. */
#define DUMMY_TOKEN 0
#define NO_DUMMY_TOKEN 1
@ -181,22 +186,19 @@ extern unsigned char _cpp_IStable[256];
/* In cpphash.c */
extern unsigned int _cpp_calc_hash PARAMS ((const U_CHAR *, size_t));
extern void _cpp_free_definition PARAMS ((cpp_hashnode *));
extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_toklist *,
cpp_hashnode *));
extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *));
extern void _cpp_dump_definition PARAMS ((cpp_reader *, cpp_hashnode *));
extern void _cpp_quote_string PARAMS ((cpp_reader *, const U_CHAR *));
extern void _cpp_macroexpand PARAMS ((cpp_reader *, cpp_hashnode *));
extern void _cpp_init_macro_hash PARAMS ((cpp_reader *));
extern void _cpp_dump_macro_hash PARAMS ((cpp_reader *));
/* In cppfiles.c */
extern void _cpp_simplify_pathname PARAMS ((char *));
extern void _cpp_execute_include PARAMS ((cpp_reader *, U_CHAR *,
extern void _cpp_execute_include PARAMS ((cpp_reader *, const U_CHAR *,
unsigned int, int,
struct file_name_list *));
extern int _cpp_compare_file_date PARAMS ((cpp_reader *, U_CHAR *,
unsigned int,
struct file_name_list *));
struct file_name_list *,
int));
extern int _cpp_compare_file_date PARAMS ((cpp_reader *, const U_CHAR *,
unsigned int, int));
extern void _cpp_init_include_table PARAMS ((cpp_reader *));
extern const char *_cpp_fake_include PARAMS ((cpp_reader *, const char *));
@ -204,40 +206,46 @@ extern const char *_cpp_fake_include PARAMS ((cpp_reader *, const char *));
extern int _cpp_parse_expr PARAMS ((cpp_reader *));
/* In cpplex.c */
extern void _cpp_parse_name PARAMS ((cpp_reader *, int));
extern void _cpp_skip_rest_of_line PARAMS ((cpp_reader *));
extern void _cpp_skip_hspace PARAMS ((cpp_reader *));
extern void _cpp_expand_to_buffer PARAMS ((cpp_reader *,
const unsigned char *, int));
extern int _cpp_parse_assertion PARAMS ((cpp_reader *));
extern enum cpp_ttype _cpp_lex_token PARAMS ((cpp_reader *));
extern ssize_t _cpp_prescan PARAMS ((cpp_reader *, cpp_buffer *,
ssize_t));
extern void _cpp_free_temp_tokens PARAMS ((cpp_reader *));
extern void _cpp_init_input_buffer PARAMS ((cpp_reader *));
extern void _cpp_grow_token_buffer PARAMS ((cpp_reader *, long));
extern enum cpp_ttype _cpp_get_directive_token
PARAMS ((cpp_reader *));
extern enum cpp_ttype _cpp_get_define_token
PARAMS ((cpp_reader *));
extern enum cpp_ttype _cpp_scan_until PARAMS ((cpp_reader *, cpp_toklist *,
enum cpp_ttype));
extern void _cpp_init_toklist PARAMS ((cpp_toklist *, int));
extern void _cpp_clear_toklist PARAMS ((cpp_toklist *));
extern void _cpp_free_toklist PARAMS ((cpp_toklist *));
extern void _cpp_slice_toklist PARAMS ((cpp_toklist *,
const cpp_token *,
const cpp_token *));
extern void _cpp_squeeze_toklist PARAMS ((cpp_toklist *));
extern void _cpp_free_toklist PARAMS ((const cpp_toklist *));
extern int _cpp_equiv_tokens PARAMS ((const cpp_token *,
const cpp_token *));
extern int _cpp_equiv_toklists PARAMS ((const cpp_toklist *,
const cpp_toklist *));
extern void _cpp_expand_token_space PARAMS ((cpp_toklist *, unsigned int));
extern void _cpp_reserve_name_space PARAMS ((cpp_toklist *, unsigned int));
extern void _cpp_expand_name_space PARAMS ((cpp_toklist *, unsigned int));
extern void _cpp_dump_list PARAMS ((cpp_reader *,
const cpp_toklist *,
const cpp_token *, int));
extern int _cpp_equiv_tokens PARAMS ((const cpp_token *,
const cpp_token *));
extern void _cpp_run_directive PARAMS ((cpp_reader *,
const struct directive *,
const char *, size_t));
extern unsigned int _cpp_get_line PARAMS ((cpp_reader *,
unsigned int *));
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 *));
/* In cpplib.c */
extern int _cpp_handle_directive PARAMS ((cpp_reader *));
extern const struct directive *_cpp_check_directive
PARAMS ((cpp_reader *, const cpp_token *, int));
extern const struct directive *_cpp_check_linemarker
PARAMS ((cpp_reader *, const cpp_token *, int));
extern void _cpp_unwind_if_stack PARAMS ((cpp_reader *, cpp_buffer *));
extern void _cpp_check_directive PARAMS ((cpp_toklist *, cpp_token *));
extern cpp_hashnode * _cpp_parse_assertion PARAMS ((cpp_reader *,
struct answer **));
extern struct answer** find_answer PARAMS ((cpp_hashnode *,
const cpp_toklist *));
/* Utility routines and macros. */
#define xnew(T) (T *) xmalloc (sizeof(T))

View file

@ -215,8 +215,6 @@ static void append_include_chain PARAMS ((cpp_reader *,
char *, int, int));
static void merge_include_chains PARAMS ((cpp_reader *));
static void dump_special_to_buffer PARAMS ((cpp_reader *, const U_CHAR *,
size_t));
static void initialize_dependency_output PARAMS ((cpp_reader *));
static void initialize_standard_includes PARAMS ((cpp_reader *));
static void new_pending_directive PARAMS ((struct cpp_pending *,
@ -345,7 +343,7 @@ append_include_chain (pfile, pend, dir, path, cxx_aware)
if (errno != ENOENT)
cpp_notice_from_errno (pfile, dir);
else if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring nonexistent directory `%s'\n"), dir);
fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"), dir);
return;
}
@ -442,7 +440,7 @@ merge_include_chains (pfile)
&& cur->dev == other->dev)
{
if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory `%s'\n"),
fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
cur->name);
prev->next = cur->next;
@ -462,7 +460,7 @@ merge_include_chains (pfile)
&& cur->dev == other->dev)
{
if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory `%s'\n"),
fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
cur->name);
prev->next = cur->next;
@ -481,7 +479,7 @@ merge_include_chains (pfile)
if (quote == qtail)
{
if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory `%s'\n"),
fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
quote->name);
free (quote->name);
@ -495,7 +493,7 @@ merge_include_chains (pfile)
cur = cur->next;
cur->next = brack;
if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory `%s'\n"),
fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
qtail->name);
free (qtail->name);
@ -513,24 +511,6 @@ merge_include_chains (pfile)
}
/* 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, macro_len)
cpp_reader *pfile;
const U_CHAR *macro_name;
size_t macro_len;
{
static const char define_directive[] = "#define ";
CPP_RESERVE (pfile, sizeof(define_directive) + macro_len);
CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
CPP_PUTS_Q (pfile, macro_name, macro_len);
CPP_PUTC_Q (pfile, ' ');
_cpp_expand_to_buffer (pfile, macro_name, macro_len);
CPP_PUTC (pfile, '\n');
}
/* Initialize a cpp_reader structure. */
void
cpp_reader_init (pfile)
@ -545,6 +525,7 @@ cpp_reader_init (pfile)
CPP_OPTION (pfile, dollars_in_ident) = 1;
CPP_OPTION (pfile, cplusplus_comments) = 1;
CPP_OPTION (pfile, warn_import) = 1;
CPP_OPTION (pfile, warn_paste) = 1;
CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, show_column) = 1;
CPP_OPTION (pfile, tabstop) = 8;
@ -596,25 +577,19 @@ cpp_cleanup (pfile)
pfile->token_buffer = NULL;
}
if (pfile->input_buffer)
{
free (pfile->input_buffer);
pfile->input_buffer = NULL;
pfile->input_buffer_len = 0;
}
if (pfile->deps)
deps_free (pfile->deps);
htab_delete (pfile->hashtab);
splay_tree_delete (pfile->all_include_files);
_cpp_free_temp_tokens (pfile);
}
/* This structure defines one built-in macro. A node of type TYPE will
be entered in the macro hash table under the name NAME, with value
VALUE (if any). FLAGS tweaks the behavior a little:
DUMP write debug info for this macro
VALUE (if any). Two values are not compile time constants, so we tag
them in the FLAGS field instead:
VERS value is the global version_string, quoted
ULP value is the global user_label_prefix
*/
@ -622,18 +597,17 @@ cpp_cleanup (pfile)
struct builtin
{
const U_CHAR *name;
const U_CHAR *value;
const char *value;
unsigned short type;
unsigned short flags;
unsigned int len;
};
#define DUMP 0x01
#define VERS 0x02
#define ULP 0x04
#define VERS 0x01
#define ULP 0x02
#define B(n, t) { U n, 0, t, 0, sizeof n - 1 }
#define C(n, v) { U n, U v, T_CONST, DUMP, sizeof n - 1 }
#define X(n, v, t, f) { U n, U v, t, DUMP|f, sizeof n - 1 }
#define B(n, t) { U n, 0, t, 0, sizeof n - 1 }
#define C(n, v) { U n, v, T_MACRO, 0, sizeof n - 1 }
#define X(n, f) { U n, 0, T_MACRO, f, sizeof n - 1 }
static const struct builtin builtin_array[] =
{
B("__TIME__", T_TIME),
@ -642,10 +616,10 @@ static const struct builtin builtin_array[] =
B("__BASE_FILE__", T_BASE_FILE),
B("__LINE__", T_SPECLINE),
B("__INCLUDE_LEVEL__", T_INCLUDE_LEVEL),
B("__STDC__", T_STDC),
X("__VERSION__", 0, T_XCONST, VERS),
X("__USER_LABEL_PREFIX__", 0, T_CONST, ULP),
X("__STDC__", "1", T_STDC, 0),
X("__VERSION__", VERS),
X("__USER_LABEL_PREFIX__", ULP),
C("__REGISTER_PREFIX__", REGISTER_PREFIX),
C("__HAVE_BUILTIN_SETJMP__", "1"),
#ifndef NO_BUILTIN_SIZE_TYPE
@ -671,35 +645,47 @@ initialize_builtins (pfile)
cpp_reader *pfile;
{
const struct builtin *b;
const U_CHAR *val;
cpp_hashnode *hp;
for(b = builtin_array; b < builtin_array_end; b++)
{
if (b->type == T_STDC && CPP_TRADITIONAL (pfile))
continue;
if (b->flags & ULP)
val = (const U_CHAR *) user_label_prefix;
else if (b->flags & VERS)
if (b->type == T_MACRO)
{
val = (const U_CHAR *) xmalloc (strlen (version_string) + 3);
sprintf ((char *)val, "\"%s\"", version_string);
const char *val;
char *str;
if (b->flags & VERS)
{
/* Allocate enough space for 'name="value"\0'. */
str = xmalloc (b->len + strlen (version_string) + 4);
sprintf (str, "%s=\"%s\"", b->name, version_string);
}
else
{
if (b->flags & ULP)
val = user_label_prefix;
else
val = b->value;
/* Allocate enough space for "name=value\0". */
str = xmalloc (b->len + strlen (val) + 2);
sprintf(str, "%s=%s", b->name, val);
}
cpp_define (pfile, str);
}
else
val = b->value;
{
cpp_hashnode *hp;
if (b->type == T_STDC && CPP_TRADITIONAL (pfile))
continue;
hp = cpp_lookup (pfile, b->name, b->len);
hp->value.cpval = val;
hp->type = b->type;
if ((b->flags & DUMP) && CPP_OPTION (pfile, debug_output))
dump_special_to_buffer (pfile, b->name, b->len);
hp = cpp_lookup (pfile, b->name, b->len);
hp->type = b->type;
}
}
}
#undef DUMP
#undef STDC
#undef VERS
#undef ULP
#undef builtin_array_end
/* Another subroutine of cpp_start_read. This one sets up to do
dependency-file output. */
@ -889,6 +875,13 @@ cpp_start_read (pfile, print, fname)
if (CPP_OPTION (pfile, cplusplus))
CPP_OPTION (pfile, warn_traditional) = 0;
/* Do not warn about illegal token pasting if -traditional,
-lang-fortran, or -lang-asm. */
if (CPP_OPTION (pfile, traditional)
|| CPP_OPTION (pfile, lang_fortran)
|| CPP_OPTION (pfile, lang_asm))
CPP_OPTION (pfile, warn_paste) = 0;
/* Set this if it hasn't been set already. */
if (user_label_prefix == NULL)
user_label_prefix = USER_LABEL_PREFIX;
@ -898,6 +891,16 @@ cpp_start_read (pfile, print, fname)
if (CPP_OPTION (pfile, preprocessed))
pfile->no_macro_expand++;
/* Figure out if we need to save function macro parameter spellings.
We don't use CPP_PEDANTIC() here because that depends on whether
or not the current file is a system header, and there is no
current file yet. */
pfile->save_parameter_spellings =
CPP_OPTION (pfile, pedantic)
|| CPP_OPTION (pfile, debug_output)
|| CPP_OPTION (pfile, dump_macros) == dump_definitions
|| CPP_OPTION (pfile, dump_macros) == dump_only;
/* Set up the IStable. This doesn't do anything if we were compiled
with a compiler that supports C99 designated initializers. */
init_IStable ();
@ -946,13 +949,12 @@ cpp_start_read (pfile, print, fname)
as line 0. */
CPP_BUFFER (pfile)->lineno = 0;
if (print)
{
print->lineno = 0;
print->last_fname = CPP_BUFFER (pfile)->nominal_fname;
print->last_id = pfile->include_depth;
print->written = CPP_WRITTEN (pfile);
print->lineno = 0;
}
/* Install __LINE__, etc. */
@ -968,10 +970,13 @@ cpp_start_read (pfile, print, fname)
p = q;
}
pfile->done_initializing = 1;
pfile->only_seen_white = 2;
/* Now flush any output recorded during initialization, and advance
to line 1 of the main input file. */
CPP_BUFFER (pfile)->lineno = 1;
if (print && ! CPP_OPTION (pfile, no_output))
cpp_output_tokens (pfile, print);
cpp_output_tokens (pfile, print, 1);
/* The -imacros files can be scanned now, but the -include files
have to be pushed onto the include stack and processed later,
@ -992,7 +997,7 @@ cpp_start_read (pfile, print, fname)
{
if (cpp_read_file (pfile, p->arg)
&& print && ! CPP_OPTION (pfile, no_output))
cpp_output_tokens (pfile, print);
cpp_output_tokens (pfile, print, 1); /* record entry to file */
q = p->next;
free (p);
p = q;
@ -1073,7 +1078,7 @@ cpp_finish (pfile, print)
/* Flush any pending output. */
if (print)
{
cpp_output_tokens (pfile, print);
cpp_output_tokens (pfile, print, print->lineno);
if (ferror (print->outf) || fclose (print->outf))
cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname));
}
@ -1753,6 +1758,8 @@ handle_option (pfile, argc, argv)
CPP_OPTION (pfile, warn_undef) = 1;
else if (!strcmp (argv[i], "-Wimport"))
CPP_OPTION (pfile, warn_import) = 1;
else if (!strcmp (argv[i], "-Wpaste"))
CPP_OPTION (pfile, warn_paste) = 1;
else if (!strcmp (argv[i], "-Werror"))
CPP_OPTION (pfile, warnings_are_errors) = 1;
else if (!strcmp (argv[i], "-Wno-traditional"))
@ -1767,6 +1774,8 @@ handle_option (pfile, argc, argv)
CPP_OPTION (pfile, warn_undef) = 0;
else if (!strcmp (argv[i], "-Wno-import"))
CPP_OPTION (pfile, warn_import) = 0;
else if (!strcmp (argv[i], "-Wno-paste"))
CPP_OPTION (pfile, warn_paste) = 0;
else if (!strcmp (argv[i], "-Wno-error"))
CPP_OPTION (pfile, warnings_are_errors) = 0;
break;
@ -1836,10 +1845,10 @@ Switches:\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\
-pedantic Issue all warnings demanded by strict ISO C\n\
-pedantic-errors Issue -pedantic warnings as errors instead\n\
-traditional Follow K&R pre-processor behaviour\n\
-trigraphs Support ANSI C trigraphs\n\
-trigraphs Support ISO 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\

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -108,7 +108,8 @@ typedef struct cpp_hashnode cpp_hashnode;
T(CPP_DOT_STAR, ".*") \
T(CPP_MIN, "<?") /* extension */ \
T(CPP_MAX, ">?") \
C(CPP_OTHER, 0) /* stray punctuation */ \
T(CPP_PLACEMARKER, "") /* Placemarker token. */ \
C(CPP_OTHER, 0) /* stray punctuation */ \
\
I(CPP_NAME, 0) /* word */ \
I(CPP_INT, 0) /* 23 */ \
@ -121,15 +122,11 @@ typedef struct cpp_hashnode cpp_hashnode;
\
I(CPP_COMMENT, 0) /* Only if output comments. */ \
N(CPP_MACRO_ARG, 0) /* Macro argument. */ \
N(CPP_SUBLIST, 0) /* Sublist. */ \
N(CPP_EOF, 0) /* End of file. */ \
N(CPP_HEADER_NAME, 0) /* <stdio.h> in #include */ \
I(CPP_HEADER_NAME, 0) /* <stdio.h> in #include */ \
\
/* Obsolete - will be removed when no code uses them still. */ \
T(CPP_VSPACE, "\n") /* End of line. */ \
N(CPP_HSPACE, 0) /* Horizontal white space. */ \
N(CPP_DIRECTIVE, 0) /* #define and the like */ \
N(CPP_MACRO, 0) /* Like a NAME, but expanded. */
T(CPP_VSPACE, "\n") /* End of line. */
#define T(e, s) e,
#define I(e, s) e,
@ -154,49 +151,42 @@ struct cpp_name
const unsigned char *text;
};
/* Accessor macros for token lists - all expect you have a
list and an index. */
#define TOK_TYPE(l_, i_) ((l_)->tokens[i_].type)
#define TOK_FLAGS(l_, i_) ((l_)->tokens[i_].flags)
#define TOK_AUX(l_, i_) ((l_)->tokens[i_].aux)
#define TOK_COL(l_, i_) ((l_)->tokens[i_].col)
#define TOK_INT(l_, i_) ((l_)->tokens[i_].val.integer)
#define TOK_NAME(l_, i_) ((l_)->tokens[i_].val.name.text)
#define TOK_LEN(l_, i_) ((l_)->tokens[i_].val.name.len)
#define TOK_PREV_WHITE(l_, i_) (TOK_FLAGS(l_, i_) & PREV_WHITESPACE)
/* Flags for the cpp_token structure. */
#define PREV_WHITESPACE 1 /* If whitespace before this token. */
#define BOL 2 /* Beginning of line. */
#define DIGRAPH 4 /* If it was a digraph. */
#define UNSIGNED_INT 8 /* If int preprocessing token unsigned. */
#define PREV_WHITE (1 << 0) /* If whitespace before this token. */
#define BOL (1 << 1) /* Beginning of logical line. */
#define DIGRAPH (1 << 2) /* If it was a digraph. */
#define STRINGIFY_ARG (1 << 3) /* If macro argument to be stringified. */
#define PASTE_LEFT (1 << 4) /* If on LHS of a ## operator. */
#define PASTED (1 << 5) /* The result of a ## operator. */
#define GNU_VARARGS (1 << 6) /* GNU ## kludge. */
/* A preprocessing token. This has been carefully packed and should
occupy 16 bytes on both 32- and 64-bit hosts. */
occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */
struct cpp_token
{
unsigned short col; /* starting column of this token */
ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* node type */
unsigned char flags; /* flags - see above */
unsigned int aux; /* CPP_OTHER character. Hash of a
NAME, or something - see uses
in the code */
unsigned int line; /* starting line number of this token */
unsigned short col; /* starting column of this token */
ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */
unsigned char flags; /* flags - see above */
union
{
struct cpp_name name; /* a string */
HOST_WIDEST_INT integer; /* an integer */
HOST_WIDEST_INT integer; /* an integer */
struct cpp_name name; /* a string */
unsigned int aux; /* argument no. for a CPP_MACRO_ARG, or
character represented by CPP_OTHER. */
} val;
};
/* General flags. */
#define LIST_OFFSET (1 << 0)
/* cpp_toklist flags. */
#define LIST_OFFSET (1 << 0)
#define VAR_ARGS (1 << 1)
#define BEG_OF_FILE (1 << 2)
/* Directive flags. */
#define SYNTAX_INCLUDE (1 << 8)
typedef int (*directive_handler) PARAMS ((cpp_reader *));
struct directive; /* These are deliberately incomplete. */
struct answer;
struct macro_args;
struct cpp_context;
struct cpp_toklist
{
@ -208,11 +198,15 @@ struct cpp_toklist
unsigned int name_used; /* _bytes_ used */
unsigned int name_cap; /* _bytes_ allocated */
/* If the list represents a directive, this points to it. */
const struct directive *directive;
const char *file; /* in file name */
unsigned int line; /* starting line number */
/* The handler to call after lexing the rest of this line.
-1 for none */
short dirno;
unsigned short params_len; /* length of macro parameter names. */
short int paramc; /* no. of macro params (-1 = obj-like). */
/* Per-list flags, see above */
unsigned short flags;
@ -224,12 +218,12 @@ struct cpp_buffer
const unsigned char *rlimit; /* end of valid data */
const unsigned char *buf; /* entire buffer */
const unsigned char *line_base; /* start of current line */
const unsigned char *mark; /* Saved position for lengthy backtrack. */
struct cpp_buffer *prev;
/* Filename specified with #line command. */
const char *nominal_fname;
/* Actual directory of this file, used only for "" includes */
struct file_name_list *actual_dir;
@ -237,10 +231,6 @@ struct cpp_buffer
to record control macros. */
struct include_file *inc;
/* If the buffer is the expansion of a macro, this points to the
macro's hash table entry. */
struct cpp_hashnode *macro;
/* Value of if_stack at start of this file.
Used to prohibit unmatched #endif (etc) in an include file. */
struct if_stack *if_stack;
@ -248,29 +238,13 @@ struct cpp_buffer
/* Line number at line_base (above). */
unsigned int lineno;
/* True if buffer contains escape sequences.
Currently there are two kinds:
"\r-" means following identifier should not be macro-expanded.
"\r " means a token-separator. This turns into " " in final output
if not stringizing and needed to separate tokens; otherwise nothing.
Any other two-character sequence beginning with \r is an error.
If this is NOT set, then \r is a one-character escape meaning backslash
newline. This is guaranteed not to occur in the middle of a token.
The two interpretations of \r do not conflict, because the two-character
escapes are used only in macro buffers, and backslash-newline is removed
from macro expansion text in collect_expansion and/or macarg. */
char has_escapes;
/* True if we have already warned about C++ comments in this file.
The warning happens only for C89 extended mode with -pedantic on,
or for -Wtraditional, and only once per file (otherwise it would
be far too noisy). */
char warned_cplusplus_comments;
/* In a file buffer, true if this buffer's data is mmapped
(currently never the case). In a macro buffer, true if this
buffer's data must be freed. */
/* True if this buffer's data is mmapped. */
char mapped;
};
@ -354,7 +328,7 @@ struct cpp_options
/* Nonzero means don't copy comments into the output file. */
unsigned char discard_comments;
/* Nonzero means process the ANSI trigraph sequences. */
/* Nonzero means process the ISO trigraph sequences. */
unsigned char trigraphs;
/* Nonzero means print the names of included files rather than the
@ -396,6 +370,10 @@ struct cpp_options
with the # indented from the beginning of the line. */
unsigned char warn_traditional;
/* Nonzero means warn if ## is applied to two tokens that cannot be
pasted together. */
unsigned char warn_paste;
/* Nonzero means turn warnings into errors. */
unsigned char warnings_are_errors;
@ -417,7 +395,7 @@ struct cpp_options
/* Zero means dollar signs are punctuation. */
unsigned char dollars_in_ident;
/* Nonzero means try to imitate old fashioned non-ANSI preprocessor. */
/* Nonzero means try to imitate old fashioned non-ISO preprocessor. */
unsigned char traditional;
/* Nonzero means warn if undefined identifiers are evaluated in an #if. */
@ -460,19 +438,18 @@ struct cpp_options
unsigned char show_column;
};
/* A cpp_reader encapsulates the "state" of a pre-processor run.
Applying cpp_get_token repeatedly yields a stream of pre-processor
tokens. Usually, there is only one cpp_reader object active. */
struct cpp_reader
{
/* HACK FIXME. Maybe make into cpp_printer printer later. */
cpp_printer *printer;
/* Top of buffer stack. */
cpp_buffer *buffer;
/* Token list used by get_directive_token. */
cpp_toklist directbuf;
/* A buffer used for both for cpp_get_token's output, and also internally. */
unsigned char *token_buffer;
/* Allocated size of token_buffer. CPP_RESERVE allocates space. */
@ -483,8 +460,9 @@ struct cpp_reader
/* Error counter for exit code */
unsigned int errors;
/* Line where a newline was first seen in a string constant. */
/* Line and column where a newline was first seen in a string constant. */
unsigned int multiline_string_line;
unsigned int multiline_string_column;
/* Current depth in #include directives that use <...>. */
unsigned int system_include_depth;
@ -509,19 +487,46 @@ struct cpp_reader
for include files. (Altered as we get more of them.) */
unsigned int max_include_len;
/* Potential controlling macro for the current buffer. This is only
live between the #endif and the end of file, and there can only
be one at a time, so it is per-reader not per-buffer. */
const cpp_hashnode *potential_control_macro;
/* Token column position adjustment owing to tabs in whitespace. */
unsigned int col_adjust;
/* Token list used to store logical lines with new lexer. */
cpp_toklist token_list;
/* Temporary token store. */
cpp_token **temp_tokens;
unsigned int temp_cap;
unsigned int temp_alloced;
unsigned int temp_used;
/* Date and time tokens. Calculated together if either is requested. */
cpp_token *date;
cpp_token *time;
/* The # of a the current directive. It may not be first in line if
we append, and finding it is tedious. */
const cpp_token *first_directive_token;
/* Context stack. Used for macro expansion and for determining
which macros are disabled. */
unsigned int context_cap;
unsigned int cur_context;
unsigned int no_expand_level;
unsigned int paste_level;
struct cpp_context *contexts;
/* Current arguments when scanning arguments. Used for pointer
fix-up. */
struct macro_args *args;
/* Buffer of -M output. */
struct deps *deps;
/* A buffer used only by read_and_prescan (in cppfiles.c), which is
allocated once per cpp_reader object to keep it off the stack. */
unsigned char *input_buffer;
size_t input_buffer_len;
/* User visible options. */
struct cpp_options opts;
@ -532,31 +537,24 @@ struct cpp_reader
/* If non-zero, macros are not expanded. */
unsigned char no_macro_expand;
/* If non-zero, directives cause a hard error. Used when parsing
macro arguments. */
unsigned char no_directives;
/* We're printed a warning recommending against using #import. */
unsigned char import_warning;
/* If true, characters between '<' and '>' are a single (string) token. */
unsigned char parsing_include_directive;
/* True if escape sequences (as described for has_escapes in
parse_buffer) should be emitted. */
unsigned char output_escapes;
/* 0: Have seen non-white-space on this line.
1: Only seen white space so far on this line.
2: Only seen white space so far in this file. */
unsigned char only_seen_white;
/* True after cpp_start_read completes. Used to inhibit some
warnings while parsing the command line. */
unsigned char done_initializing;
/* True if we are skipping a failed conditional group. */
unsigned char skipping;
/* Do we need to save paramter spellings. */
unsigned char save_parameter_spellings;
/* If we're in lex_line. */
unsigned char in_lex_line;
/* True if output_line_command needs to output a newline. */
unsigned char need_newline;
};
/* struct cpp_printer encapsulates state used to convert the stream of
@ -611,13 +609,8 @@ enum node_type
T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
T_TIME, /* `__TIME__' */
T_STDC, /* `__STDC__' */
T_CONST, /* Constant string, used by `__SIZE_TYPE__' etc */
T_XCONST, /* Ditto, but the string is malloced memory */
T_POISON, /* poisoned identifier */
T_MACRO, /* object-like macro */
T_FMACRO, /* function-like macro */
T_IDENTITY, /* macro defined to itself */
T_EMPTY, /* macro defined to nothing */
T_MACRO, /* a macro, either object-like or function-like */
T_ASSERTION /* predicate for #assert */
};
@ -634,11 +627,10 @@ struct cpp_hashnode
ENUM_BITFIELD(node_type) type : 8; /* node type */
char disabled; /* macro turned off for rescan? */
union {
const unsigned char *cpval; /* some predefined macros */
const struct object_defn *odefn; /* #define foo bar */
const struct funct_defn *fdefn; /* #define foo(x) bar(x) */
struct predicate *pred; /* #assert */
union
{
const cpp_toklist *expansion; /* a macro's replacement list. */
struct answer *answers; /* answers to an assertion. */
} value;
union tree_node *fe_value; /* front end value */
@ -646,23 +638,17 @@ struct cpp_hashnode
const unsigned char name[1]; /* name[length] */
};
extern void _cpp_lex_file PARAMS((cpp_reader *));
extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
extern enum cpp_ttype cpp_get_token PARAMS ((cpp_reader *));
extern enum cpp_ttype cpp_get_non_space_token PARAMS ((cpp_reader *));
extern void cpp_reader_init PARAMS ((cpp_reader *));
extern cpp_printer *cpp_printer_init PARAMS ((cpp_reader *, cpp_printer *));
extern int cpp_start_read PARAMS ((cpp_reader *, cpp_printer *, const char *));
extern void cpp_output_tokens PARAMS ((cpp_reader *, cpp_printer *));
extern void cpp_output_list PARAMS ((cpp_reader *, cpp_printer *,
const cpp_toklist *));
extern void cpp_output_tokens PARAMS ((cpp_reader *, cpp_printer *,
unsigned int));
extern void cpp_finish PARAMS ((cpp_reader *, cpp_printer *));
extern void cpp_cleanup PARAMS ((cpp_reader *));
extern cpp_buffer *cpp_file_buffer PARAMS((cpp_reader *));
extern const cpp_token *cpp_get_token PARAMS ((cpp_reader *));
extern void cpp_define PARAMS ((cpp_reader *, const char *));
extern void cpp_assert PARAMS ((cpp_reader *, const char *));
extern void cpp_undef PARAMS ((cpp_reader *, const char *));

View file

@ -68,6 +68,7 @@ main (argc, argv)
print = cpp_printer_init (pfile, &parse_out);
if (! print)
return (FATAL_EXIT_CODE);
pfile->printer = print;
if (! cpp_start_read (pfile, print, CPP_OPTION (pfile, in_fname)))
return (FATAL_EXIT_CODE);

View file

@ -432,8 +432,6 @@ write_lbrac ()
struct partial_proto
{
struct partial_proto *next;
char *fname; /* name of function */
char *rtype; /* return type */
struct fn_decl *fn;
int line_seen;
};
@ -497,15 +495,13 @@ recognized_macro (fname)
}
void
recognized_extern (name, name_length, type, type_length)
const char *name;
const char *type ATTRIBUTE_UNUSED;
int name_length, type_length ATTRIBUTE_UNUSED;
recognized_extern (name)
const cpp_token *name;
{
switch (special_file_handling)
{
case errno_h:
if (name_length == 5 && strncmp (name, "errno", 5) == 0 && !seen_errno)
if (!cpp_idcmp (name->val.name.text, name->val.name.len, "errno"))
seen_errno = 1, required_other--;
break;
@ -515,25 +511,17 @@ recognized_extern (name, name_length, type, type_length)
}
/* Called by scan_decls if it saw a function definition for a function
named FNAME, with return type RTYPE, and argument list ARGS,
in source file FILE_SEEN on line LINE_SEEN.
KIND is 'I' for an inline function;
'F' if a normal function declaration preceded by 'extern "C"'
(or nested inside 'extern "C"' braces); or
named FNAME, in source file FILE_SEEN on line LINE_SEEN. KIND is
'I' for an inline function; 'F' if a normal function declaration
preceded by 'extern "C"' (or nested inside 'extern "C"' braces); or
'f' for other function declarations. */
void
recognized_function (fname, fname_length,
kind, rtype, rtype_length,
have_arg_list, file_seen, line_seen)
const char *fname;
int fname_length;
recognized_function (fname, kind, have_arg_list, file_seen)
const cpp_token *fname;
int kind; /* One of 'f' 'F' or 'I' */
const char *rtype;
int rtype_length;
int have_arg_list;
const char *file_seen;
int line_seen;
{
struct partial_proto *partial;
int i;
@ -543,7 +531,8 @@ recognized_function (fname, fname_length,
missing_extern_C_count++;
#endif
fn = lookup_std_proto (fname, fname_length);
fn = lookup_std_proto ((const char *)fname->val.name.text,
fname->val.name.len);
/* Remove the function from the list of required function. */
if (fn)
@ -577,12 +566,7 @@ recognized_function (fname, fname_length,
partial_count++;
partial = (struct partial_proto *)
obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto));
partial->fname = obstack_alloc (&scan_file_obstack, fname_length + 1);
bcopy (fname, partial->fname, fname_length);
partial->fname[fname_length] = 0;
partial->rtype = obstack_alloc (&scan_file_obstack, rtype_length + 1);
sprintf (partial->rtype, "%.*s", rtype_length, rtype);
partial->line_seen = line_seen;
partial->line_seen = fname->line;
partial->fn = fn;
fn->partial = partial;
partial->next = partial_proto_list;
@ -590,7 +574,7 @@ recognized_function (fname, fname_length,
if (verbose)
{
fprintf (stderr, "(%s: %s non-prototype function declaration.)\n",
inc_filename, partial->fname);
inc_filename, fn->fname);
}
}
@ -646,19 +630,12 @@ read_scan_file (in_fname, argc, argv)
for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
check_macro_names (&scan_in, cur_symbols->names);
if (verbose && (scan_in.errors + warnings) > 0)
fprintf (stderr, "(%s: %d errors and %d warnings from cpp)\n",
inc_filename, scan_in.errors, warnings);
if (scan_in.errors)
exit (SUCCESS_EXIT_CODE);
/* Traditionally, getc and putc are defined in terms of _filbuf and _flsbuf.
If so, those functions are also required. */
if (special_file_handling == stdio_h
&& (fn = lookup_std_proto ("_filbuf", 7)) != NULL)
{
static const unsigned char getchar_call[] = "getchar();";
int old_written = CPP_WRITTEN (&scan_in);
int seen_filbuf = 0;
cpp_buffer *buf = CPP_BUFFER (&scan_in);
if (cpp_push_buffer (&scan_in, getchar_call,
@ -668,14 +645,17 @@ read_scan_file (in_fname, argc, argv)
/* Scan the macro expansion of "getchar();". */
for (;;)
{
enum cpp_ttype token = cpp_get_token (&scan_in);
int length = CPP_WRITTEN (&scan_in) - old_written;
unsigned char *id = scan_in.token_buffer + old_written;
CPP_SET_WRITTEN (&scan_in, old_written);
if (token == CPP_EOF && CPP_BUFFER (&scan_in) == buf)
break;
if (token == CPP_NAME && cpp_idcmp (id, length, "_filbuf") == 0)
const cpp_token *t = cpp_get_token (&scan_in);
if (t->type == CPP_EOF)
{
cpp_pop_buffer (&scan_in);
if (CPP_BUFFER (&scan_in) == buf)
break;
}
else if (t->type == CPP_NAME && cpp_idcmp (t->val.name.text,
t->val.name.len,
"_filbuf") == 0)
seen_filbuf++;
}
if (seen_filbuf)
@ -1030,8 +1010,6 @@ check_protection (ifndef_line, endif_line)
}
else if (!strcmp (buf.base, "define"))
{
if (if_nesting != 1)
goto skip_to_eol;
c = inf_skip_spaces (c);
c = inf_scan_ident (&buf, c);
if (buf.base[0] > 0 && strcmp (buf.base, protect_name) == 0)

View file

@ -45,7 +45,7 @@ skip_to_closing_brace (pfile)
int nesting = 1;
for (;;)
{
enum cpp_ttype token = cpp_get_token (pfile);
enum cpp_ttype token = cpp_get_token (pfile)->type;
if (token == CPP_EOF)
break;
if (token == CPP_OPEN_BRACE)
@ -84,24 +84,17 @@ scan_decls (pfile, argc, argv)
char **argv ATTRIBUTE_UNUSED;
{
int saw_extern, saw_inline;
int start_written;
/* If declarator_start is non-zero, it marks the start of the current
declarator. If it is zero, we are either still parsing the
decl-specs, or prev_id_start marks the start of the declarator. */
int declarator_start;
int prev_id_start, prev_id_end = 0;
enum cpp_ttype token;
const cpp_token *prev_id;
const cpp_token *token;
new_statement:
CPP_SET_WRITTEN (pfile, 0);
start_written = 0;
token = cpp_get_token (pfile);
handle_statement:
current_extern_C = 0;
saw_extern = 0;
saw_inline = 0;
if (token == CPP_OPEN_BRACE)
if (token->type == CPP_OPEN_BRACE)
{
/* Pop an 'extern "C"' nesting level, if appropriate. */
if (extern_C_braces_length
@ -110,120 +103,112 @@ scan_decls (pfile, argc, argv)
brace_nesting--;
goto new_statement;
}
if (token == CPP_OPEN_BRACE)
if (token->type == CPP_OPEN_BRACE)
{
brace_nesting++;
goto new_statement;
}
if (token == CPP_EOF)
if (token->type == CPP_EOF)
{
cpp_pop_buffer (pfile);
if (CPP_BUFFER (pfile) == NULL)
return 0;
else
goto new_statement;
goto new_statement;
}
if (token == CPP_SEMICOLON)
if (token->type == CPP_SEMICOLON)
goto new_statement;
if (token != CPP_NAME)
if (token->type != CPP_NAME)
goto new_statement;
prev_id_start = 0;
declarator_start = 0;
prev_id = 0;
for (;;)
{
switch (token)
switch (token->type)
{
default:
goto handle_statement;
case CPP_MULT:
case CPP_AND:
case CPP_PLACEMARKER:
/* skip */
break;
case CPP_COMMA:
case CPP_SEMICOLON:
if (prev_id && saw_extern)
{
recognized_extern (prev_id);
}
if (token->type == CPP_COMMA)
break;
/* ... fall through ... */
case CPP_OPEN_BRACE: case CPP_CLOSE_BRACE:
goto new_statement;
case CPP_EOF:
cpp_pop_buffer (pfile);
if (CPP_BUFFER (pfile) == NULL)
return 0;
break;
case CPP_OPEN_PAREN:
/* Looks like this is the start of a formal parameter list. */
if (prev_id_start)
if (prev_id)
{
int nesting = 1;
int have_arg_list = 0;
cpp_buffer *fbuf = cpp_file_buffer (pfile);
unsigned int func_lineno = CPP_BUF_LINE (fbuf);
for (;;)
{
token = cpp_get_token (pfile);
if (token == CPP_OPEN_PAREN)
if (token->type == CPP_OPEN_PAREN)
nesting++;
else if (token == CPP_CLOSE_PAREN)
else if (token->type == CPP_CLOSE_PAREN)
{
nesting--;
if (nesting == 0)
break;
}
else if (token == CPP_EOF)
else if (token->type == CPP_EOF)
break;
else if (token == CPP_NAME || token == CPP_ELLIPSIS)
else if (token->type == CPP_NAME
|| token->type == CPP_ELLIPSIS)
have_arg_list = 1;
}
recognized_function (pfile->token_buffer + prev_id_start,
prev_id_end - prev_id_start,
recognized_function (prev_id,
(saw_inline ? 'I'
: in_extern_C_brace || current_extern_C
? 'F' : 'f'),
pfile->token_buffer, prev_id_start,
have_arg_list,
fbuf->nominal_fname, func_lineno);
token = cpp_get_non_space_token (pfile);
if (token == CPP_OPEN_BRACE)
? 'F' : 'f'), have_arg_list,
CPP_BUFFER (pfile)->nominal_fname);
token = cpp_get_token (pfile);
if (token->type == CPP_OPEN_BRACE)
{
/* skip body of (normally) inline function */
skip_to_closing_brace (pfile);
goto new_statement;
}
goto maybe_handle_comma;
if (token->type == CPP_SEMICOLON)
goto new_statement;
}
break;
case CPP_OTHER:
if (CPP_WRITTEN (pfile) == (size_t) start_written + 1
&& (CPP_PWRITTEN (pfile)[-1] == '*'
|| CPP_PWRITTEN (pfile)[-1] == '&'))
declarator_start = start_written;
else
goto handle_statement;
break;
case CPP_COMMA:
case CPP_SEMICOLON:
if (prev_id_start && saw_extern)
{
recognized_extern (pfile->token_buffer + prev_id_start,
prev_id_end - prev_id_start,
pfile->token_buffer,
prev_id_start);
}
/* ... fall through ... */
maybe_handle_comma:
if (token != CPP_COMMA)
goto new_statement;
/* Handle multiple declarators in a single declaration,
as in: extern char *strcpy (), *strcat (), ... ; */
if (declarator_start == 0)
declarator_start = prev_id_start;
CPP_SET_WRITTEN (pfile, declarator_start);
break;
case CPP_NAME:
/* "inline" and "extern" are recognized but skipped */
if (!cpp_idcmp (pfile->token_buffer,
CPP_WRITTEN (pfile), "inline"))
if (!cpp_idcmp (token->val.name.text, token->val.name.len, "inline"))
{
saw_inline = 1;
CPP_SET_WRITTEN (pfile, start_written);
}
else if (!cpp_idcmp (pfile->token_buffer,
CPP_WRITTEN (pfile), "extern"))
else if (!cpp_idcmp (token->val.name.text,
token->val.name.len, "extern"))
{
saw_extern = 1;
CPP_SET_WRITTEN (pfile, start_written);
token = cpp_get_non_space_token (pfile);
if (token == CPP_STRING
&& strcmp (pfile->token_buffer, "\"C\"") == 0)
token = cpp_get_token (pfile);
if (token->type == CPP_STRING
&& !cpp_idcmp (token->val.name.text,
token->val.name.len, "C"))
{
CPP_SET_WRITTEN (pfile, start_written);
current_extern_C = 1;
token = cpp_get_non_space_token (pfile);
if (token == CPP_OPEN_BRACE)
token = cpp_get_token (pfile);
if (token->type == CPP_OPEN_BRACE)
{
brace_nesting++;
extern_C_braces[extern_C_braces_length++]
@ -236,29 +221,9 @@ scan_decls (pfile, argc, argv)
break;
}
/* This may be the name of a variable or function. */
prev_id_start = start_written;
prev_id_end = CPP_WRITTEN (pfile);
prev_id = token;
break;
case CPP_OPEN_BRACE: case CPP_CLOSE_BRACE: case CPP_DIRECTIVE:
goto new_statement; /* handle_statement? */
case CPP_EOF:
if (CPP_BUFFER (pfile) == NULL)
return 0;
/* else fall through */
case CPP_HSPACE: case CPP_VSPACE: case CPP_COMMENT:
/* Skip initial white space. */
if (start_written == 0)
CPP_SET_WRITTEN (pfile, 0);
break;
default:
prev_id_start = 0;
}
start_written = CPP_WRITTEN (pfile);
token = cpp_get_token (pfile);
}
}

View file

@ -50,6 +50,8 @@ struct fn_decl
struct partial_proto *partial;
};
struct cpp_token;
extern int lineno;
extern void sstring_append _PARAMS((sstring *, sstring *));
extern void make_sstring_space _PARAMS((sstring *, int));
@ -58,8 +60,9 @@ extern int scan_ident _PARAMS((FILE *, sstring *, int));
extern int scan_string _PARAMS((FILE *, sstring *, int));
extern int read_upto _PARAMS((FILE *, sstring *, int));
extern unsigned long hash _PARAMS((const char *));
extern void recognized_function _PARAMS((const char *, int, int, const char *, int, int, const char *, int));
extern void recognized_extern _PARAMS((const char *, int, const char *, int));
extern void recognized_function _PARAMS((const struct cpp_token *, int, int,
const char *));
extern void recognized_extern _PARAMS((const struct cpp_token *));
extern unsigned int hashstr _PARAMS((const char *, unsigned int));
struct cpp_reader;

View file

@ -1,3 +1,16 @@
2000-07-03 Zack Weinberg <zack@wolery.cumb.org>
* testsuite/gcc.dg/cpp/19951025-1.c: Adjust regexps.
* testsuite/gcc.dg/cpp/19990703-1.c: Likewise.
* testsuite/gcc.dg/cpp/20000625-1.c: Likewise.
* testsuite/gcc.dg/cpp/20000625-2.c: Likewise.
* testsuite/gcc.dg/cpp/macro1.c,
testsuite/gcc.dg/cpp/paste1.c, testsuite/gcc.dg/cpp/paste2.c,
testsuite/gcc.dg/cpp/paste3.c, testsuite/gcc.dg/cpp/paste4.c,
testsuite/gcc.dg/cpp/strify1.c,
testsuite/gcc.dg/cpp/strify2.c: New tests.
2000-07-03 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/20000703-1.c: New test.

View file

@ -1,4 +1,4 @@
/* { dg-do preprocess } */
/* { dg-error "include expects" "" { target *-*-* } 4 } */
/* { dg-warning "no newline" "" { target *-*-* } 5 } */
/* { dg-error "newline at end" "" { target *-*-* } 4 } */
#include /\

View file

@ -14,7 +14,7 @@
int
main(void)
{
char *x = SP1(0,MZ);
char *x = SP1(0,MZ); /* { dg-warning "valid preprocessing token" "" } */
char *y = "0-0"; /* should be the expansion of SP1(0,MZ) */
if(strcmp(x, y))

View file

@ -11,6 +11,6 @@ main(void)
{
goto socket;
ENTRY(socket)
ENTRY(socket) /* { dg-warning "valid preprocessing token" "" } */
return 0;
}

View file

@ -7,6 +7,7 @@
#define xstr(x) #x
const char a[] = str(symbol_version(getrlimit, GLIBC_2.0));
/* { dg-warning "valid preprocessing token" "" { target *-*-* } 9 } */
const char b[] = str(getrlimit@GLIBC_2.0);
const char c[] = "getrlimit@GLIBC_2.0";

View file

@ -0,0 +1,72 @@
/* Copyright (C) 2000 Free Software Foundation, Inc. */
/* { dg-do run } */
/* Tests various macros are correctly expanded. */
extern int puts (const char *);
extern void abort (void);
#define err(str) do { puts(str); abort(); } while (0)
#define j(x, y) x + y
#define k(x, y) j(x + 2, y +
int q(int x) {return x + 40;}
int B(int x) {return x + 20;}
int foo(int x) {return x + 10;}
int bar(int x, int y) {return x + y;}
int baz(int x, int y) {return x + y;}
int toupper(int x) {return x + 32;}
int main (int argc, char *argv[])
{
#define q(x) x
if (q(q)(2) != 42)
err ("q");
#define A(x) B(x)
if (A(A(2)) != 42)
err ("A");
#define E(x) A x
#define F (22)
if (E(F) != 42)
err ("E(F)");
#define COMMA ,
#define NASTY(a) j(a 37)
if (NASTY (5 COMMA) != 42)
err ("NASTY");
#define bar(x, y) foo(x(y, 0))
#define apply(x, y) foo(x(y, 22))
#define bam bar
if (bar(bar, 32) != 42) /* foo(bar(32, 0)). */
err ("bar bar");
if (bar(bam, 32) != 42) /* Same. */
err ("bar bam");
if (apply(bar, baz) != 42) /* foo(foo(baz(22, 0))). */
err ("apply bar baz");
#define __tobody(c, f) f (c)
#define toupper(c) __tobody (c, toupper)
if (toupper (10) != 42) /* toupper (10). */
err ("toupper");
/* This looks like it has too many ')', but it hasn't. */
if (k(1, 4) 35) != 42)
err ("k");
/*#define B(x) Z B(x)
#define XEXP(RTX, N) RTX->fld[N].rtx
#define PATTERN(INSN) XEXP(INSN, 3)
#define COST(X) XEXP (XEXP (x, 0), 0)
#define M(a) OK M (a)
#define stpcpy(a) M(a)
#define C(x) A(x)
XEXP (PATTERN (insn), i);
XEXP (XEXP (insn, 3), i);
COST (b)*/
return 0;
}

View file

@ -0,0 +1,10 @@
/* Copyright (C) 2000 Free Software Foundation, Inc. */
/* { dg-do preprocess } */
/* Test operator ## semantics. */
#define bad1 ## owt /* { dg-error "cannot" "## at objlike start" } */
#define bad2 owt ## /* { dg-error "cannot" "## at objlike end" } */
#define bad3(x) ## x /* { dg-error "cannot" "## at funlike start" } */
#define bad4(x) x ## /* { dg-error "cannot" "## at funlike end" } */

View file

@ -0,0 +1,115 @@
/* Copyright (C) 2000 Free Software Foundation, Inc. */
/* { dg-do run } */
/* { dg-options "-std=c99 -pedantic-errors" } */
/* Test ## behaviour and corner cases thoroughly. The macro expander
failed many of these during development. */
#include <string.h>
#ifndef __WCHAR_TYPE__
#define __WCHAR_TYPE__ int
#endif
typedef __WCHAR_TYPE__ wchar_t;
extern int puts (const char *);
extern void abort (void);
#define err(str) do { puts(str); abort(); } while (0)
#define EMPTY
#define str(x) #x
#define xstr(x) str(x)
#define glue(x, y) x ## y
#define xglue(x, y) glue (x, y)
#define glue3(x, y, z) x ## y ## z
#define glue_var(x, ...) x ## __VA_ARGS__
#define __muldi3 __NDW(mul, 3 = 50)
#define __NDW(a,b) __ ## a ## di ## b
#define m3 NDW()
#define NDW(x) m3 ## x = 50
#define five 5
#define fifty int fif ## ty
/* Defines a function called glue, returning what it is passed. */
int glue (glue,) (int x)
{
return x;
}
int main ()
{
/* m3 and __muldi3 would sometimes cause an infinite loop. Ensure
we only expand fifty once. */
fifty = 50, m3, __muldi3;
/* General glue and macro expanding test. */
int five0 = xglue (glue (fi, ve), 0);
/* Tests only first and last tokens are pasted, and pasting to form
the != operator. Should expand to: if (five0 != 50). */
if (glue3 (fi, ve0 !,= glue (EMPTY 5, 0)))
err ("five0 != 50");
/* Test varags pasting, and pasting to form the >> operator. */
if (glue_var(50 >, > 1 != 25))
err ("Operator >> pasting");
/* The LHS should not attempt to expand twice, and thus becomes a
call to the function glue, but the RHS should fully expand. */
if (glue (gl, ue) (12) != glue (xgl, ue) (1, 2))
err ("Recursive macros");
/* Test placemarker pasting. The glued lines should all appear
neatly in the same column and below each other, though we don't
test that here. */
{
int glue3(a, b, ) = 1, glue3(a,,) = 1;
glue3(a, , b)++;
glue3(, a, b)++;
glue3(,a,)++;
glue3(,,a)++;
if (a != 3 || ab != 3 glue3(,,))
err ("Placemarker pasting");
}
/* Test that macros in arguments are not expanded. */
{
int glue (EMPTY,1) = 123, glue (T, EMPTY) = 123;
if (EMPTY1 != 123 || TEMPTY != 123)
err ("Pasted arguments macro expanding");
}
/* Test various paste combinations. */
{
const wchar_t* wc_array = glue(L, "wide string");
wchar_t wc = glue(L, 'w');
const char * hh = xstr(xglue(glue(%, :), glue(%, :)));
int array glue (<, :) 1 glue (:, >) = glue(<, %) 1 glue(%, >);
int x = 4;
if (array[0] != 1)
err ("Digraph pasting");
x glue (>>, =) 1; /* 2 */
x glue (<<, =) 1; /* 4 */
x glue (*, =) 2; /* 8 */
x glue (+, =) 100; /* 108 */
x glue (-, =) 50; /* 58 */
x glue (/, =) 2; /* 29 */
x glue (%, =) 20; /* 9 */
x glue (&, =) 254; /* 8 */
x glue (|, =) 16; /* 24 */
x glue (^, =) 18; /* 10 */
if (x != 10 || 0 glue (>, =) 1 glue (|, |) 1 glue (<, =) 0)
err ("Various operator pasting");
if (strcmp (hh, "%:%:"))
err ("Pasted digraph spelling");
if ((glue (., 0) glue (=, =) .0) + (glue3 (1.0e, +, 1) == 10.0) != 2)
err ("Pasted numbers");
}
return 0;
}

View file

@ -0,0 +1,14 @@
/* Copyright (C) 2000 Free Software Foundation, Inc. */
/* { dg-do compile } */
#define plus +
void foo()
{
int a, b = 1;
/* The correct "a = 1 + ++b" will compile.
The incorrect "a = 1 +++b" won't. */
a = 1 plus++b;
}

View file

@ -0,0 +1,14 @@
/* Copyright (C) 2000 Free Software Foundation, Inc. */
/* { dg-do compile } */
/* Since 1.0e and + form the pasted token, 1 is a separate token and
so should be output with a preceding space. The old preprocessor
gets this wrong. */
#define glue(x, y) x ## y
int main ()
{
double d = glue (1.0e, +1); /* { dg-error "floating const|parse error" } */
return 0;
}

View file

@ -0,0 +1,10 @@
/* Copyright (C) 2000 Free Software Foundation, Inc. */
/* { dg-do preprocess } */
/* Test operator # semantics. */
#define OK1 # /* No problem. */
#define OK2(x) x#x /* No problem. */
#define bad1(x) # /* { dg-error "followed by a macro parameter" "#1" } */
#define bad2(x) #y /* { dg-error "followed by a macro parameter" "#2" } */

View file

@ -0,0 +1,45 @@
/* Copyright (C) 2000 Free Software Foundation, Inc. */
/* { dg-do run } */
/* { dg-options "-std=c99 -pedantic-errors" } */
/* Tests a whole bunch of things are correctly stringified. */
extern int strcmp (const char *, const char *);
extern int puts (const char *);
extern void abort (void);
#define err(str) do { puts(str); abort(); } while (0)
#define str(x) #x
#define xstr(x) str(x)
#define strvar(...) #__VA_ARGS__
int main (int argc, char *argv[])
{
str (\); /* { dg-warning "valid string" "str(\)" } */
str (\\\); /* { dg-warning "valid string" "str(\\\)" } */
/* This also serves as a useful test of the value of __INCLUDE_LEVEL. */
if (strcmp (xstr (__INCLUDE_LEVEL__), "0"))
err ("macro expansion");
if (strcmp(str (__INCLUDE_LEVEL__), "__INCLUDE_LEVEL__"))
err ("macro name");
if (strcmp(str ("s\n"), "\"s\\n\""))
err ("quoted string");
if (strcmp (str (a b), "a \200 b"))
err ("unprintable char");
if (strcmp (str ( a b@ c ), "a b@ c"))
err ("internal whitespace");
if (strcmp (str(a \n), "a \n"))
err ("backslash token");
if (strcmp (strvar (foo, bar), "foo, bar"))
err ("variable arguments");
return 0;
}