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> 2000-07-03 Zack Weinberg <zack@wolery.cumb.org>
* cppspec.c (lang_specific_driver): Use double quotes in error * cppspec.c (lang_specific_driver): Use double quotes in error

View file

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

View file

@ -394,74 +394,22 @@ parse_assertion (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
struct operation op; struct operation op;
struct answer *answer;
cpp_hashnode *hp; 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; 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 struct token
@ -480,8 +428,6 @@ static const struct token tokentab2[] =
{"!=", NOTEQUAL}, {"!=", NOTEQUAL},
{"<=", LEQ}, {"<=", LEQ},
{">=", GEQ}, {">=", GEQ},
{"++", ERROR},
{"--", ERROR},
{NULL, ERROR} {NULL, ERROR}
}; };
@ -496,16 +442,20 @@ lex (pfile, skip_evaluation)
enum cpp_ttype token; enum cpp_ttype token;
struct operation op; struct operation op;
U_CHAR *tok_start, *tok_end; 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); token = _cpp_get_directive_token (pfile);
tok_start = pfile->token_buffer + old_written; tok_start = pfile->token_buffer + old_written;
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_PLACEMARKER:
CPP_SET_WRITTEN (pfile, old_written);
goto retry;
case CPP_EOF: /* Should not happen ... */ case CPP_EOF: /* Should not happen ... */
case CPP_VSPACE: case CPP_VSPACE:
op.op = 0; op.op = 0;
@ -524,6 +474,7 @@ 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:
/* FIXME: could this not overflow the tok_start buffer? */
if (!ustrncmp (tok_start, U"defined", 7)) if (!ustrncmp (tok_start, U"defined", 7))
return parse_defined (pfile); return parse_defined (pfile);
@ -539,7 +490,16 @@ lex (pfile, skip_evaluation)
case CPP_HASH: case CPP_HASH:
return parse_assertion (pfile); 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. */ /* See if it is a special token of length 2. */
if (tok_start + 2 == tok_end) if (tok_start + 2 == tok_end)
{ {
@ -553,8 +513,6 @@ lex (pfile, skip_evaluation)
op.op = toktab->token; op.op = toktab->token;
return op; return op;
} }
/* fall through */
default:
op.op = *tok_start; op.op = *tok_start;
return op; return op;
} }
@ -612,7 +570,7 @@ parse_escape (pfile, string_ptr, result_mask)
case 'e': case 'e':
case 'E': case 'E':
if (CPP_PEDANTIC (pfile)) 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; return TARGET_ESC;
case 'f': case 'f':
return TARGET_FF; return TARGET_FF;
@ -844,9 +802,7 @@ _cpp_parse_expr (pfile)
char buff[5]; char buff[5];
/* Save parser state and set it to something sane. */ /* Save parser state and set it to something sane. */
int save_only_seen_white = pfile->only_seen_white;
int save_skipping = pfile->skipping; int save_skipping = pfile->skipping;
pfile->only_seen_white = 0;
pfile->skipping = 0; pfile->skipping = 0;
/* We've finished when we try to reduce this. */ /* We've finished when we try to reduce this. */
@ -875,7 +831,8 @@ _cpp_parse_expr (pfile)
case ERROR: case ERROR:
goto syntax_error; goto syntax_error;
default: default:
SYNTAX_ERROR ("invalid character in #if"); SYNTAX_ERROR2 ("invalid character '%s' in #if",
op_to_str (op.op, buff));
push_immediate: push_immediate:
case INT: case INT:
@ -1168,7 +1125,6 @@ _cpp_parse_expr (pfile)
if (stack != init_stack) if (stack != init_stack)
free (stack); free (stack);
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
pfile->only_seen_white = save_only_seen_white;
pfile->skipping = save_skipping; pfile->skipping = save_skipping;
return result; return result;
} }

View file

@ -180,7 +180,7 @@ open_include_file (pfile, filename)
#ifdef EACCES #ifdef EACCES
if (errno == 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); filename);
} }
#endif #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)) #define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth))
void 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; cpp_reader *pfile;
U_CHAR *f; const U_CHAR *f;
unsigned int len; unsigned int len;
int no_reinclude; int no_reinclude;
struct file_name_list *search_start; struct file_name_list *search_start;
int angle_brackets;
{ {
struct include_file *inc; struct include_file *inc;
char *fname = (char *)f; char *fname;
int angle_brackets = fname[0] == '<';
if (!search_start) if (!search_start)
{ {
@ -387,9 +387,8 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start)
return; return;
} }
/* Remove quote marks. */ fname = alloca (len + 1);
fname++; memcpy (fname, f, len);
len -= 2;
fname[len] = '\0'; fname[len] = '\0';
inc = find_include_file (pfile, fname, search_start); 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. */ if F cannot be located or dated, 1, if it is newer and 0 if older. */
int int
_cpp_compare_file_date (pfile, f, len, search_start) _cpp_compare_file_date (pfile, f, len, angle_brackets)
cpp_reader *pfile; cpp_reader *pfile;
U_CHAR *f; const U_CHAR *f;
unsigned int len; unsigned int len;
struct file_name_list *search_start; int angle_brackets;
{ {
char *fname = (char *)f; char *fname;
int angle_brackets = fname[0] == '<'; struct file_name_list *search_start;
struct include_file *inc; 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);
if (angle_brackets) else if (CPP_OPTION (pfile, ignore_srcdir))
search_start = CPP_OPTION (pfile, bracket_include); search_start = CPP_OPTION (pfile, quote_include);
else if (CPP_OPTION (pfile, ignore_srcdir)) else
search_start = CPP_OPTION (pfile, quote_include); search_start = CPP_BUFFER (pfile)->actual_dir;
else
search_start = CPP_BUFFER (pfile)->actual_dir;
}
/* Remove quote marks. */ fname = alloca (len + 1);
fname++; memcpy (fname, f, len);
len -= 2;
fname[len] = '\0'; fname[len] = '\0';
inc = find_include_file (pfile, fname, search_start); inc = find_include_file (pfile, fname, search_start);
if (!inc) if (!inc)
@ -534,6 +528,12 @@ cpp_read_file (pfile, fname)
f = open_include_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); return read_include_file (pfile, f);
} }
@ -550,12 +550,17 @@ read_include_file (pfile, inc)
cpp_buffer *fp; cpp_buffer *fp;
int fd = inc->fd; 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); fp = cpp_push_buffer (pfile, NULL, 0);
if (fp == 0) if (fp == 0)
goto push_fail; goto push_fail;
if (fstat (fd, &st) < 0) if (fd < 0 || fstat (fd, &st) < 0)
goto perror_fail; goto perror_fail;
inc->date = st.st_mtime; inc->date = st.st_mtime;
@ -622,9 +627,6 @@ read_include_file (pfile, inc)
if (length == 0) if (length == 0)
inc->cmacro = NEVER_REREAD; inc->cmacro = NEVER_REREAD;
else
/* Temporary - I hope. */
length = _cpp_prescan (pfile, fp, length);
fp->rlimit = fp->buf + length; fp->rlimit = fp->buf + length;
fp->cur = fp->buf; fp->cur = fp->buf;
@ -637,13 +639,13 @@ read_include_file (pfile, inc)
fp->actual_dir = actual_directory (pfile, inc->name); fp->actual_dir = actual_directory (pfile, inc->name);
pfile->input_stack_listing_current = 0; pfile->input_stack_listing_current = 0;
pfile->only_seen_white = 2;
return 1; return 1;
perror_fail: perror_fail:
cpp_error_from_errno (pfile, inc->name); cpp_error_from_errno (pfile, inc->name);
/* Do not try to read this file again. */ /* Do not try to read this file again. */
close (fd); if (fd != -1)
close (fd);
inc->fd = -1; inc->fd = -1;
inc->cmacro = NEVER_REREAD; inc->cmacro = NEVER_REREAD;
fail: 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; typedef unsigned char U_CHAR;
#define U (const U_CHAR *) /* Intended use: U"string" */ #define U (const U_CHAR *) /* Intended use: U"string" */
/* Structure used for assertion predicates. */ /* Order here matters. Those beyond SPELL_NONE store their spelling
struct predicate in the token list, and it's length in the token->val.name.len. */
enum spell_type
{ {
struct predicate *next; SPELL_OPERATOR = 0,
struct cpp_toklist answer; 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. */ /* List of directories to look for include files in. */
@ -105,12 +154,6 @@ extern unsigned char _cpp_IStable[256];
/* Macros. */ /* 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. */ /* Make sure PFILE->token_buffer has space for at least N more characters. */
#define CPP_RESERVE(PFILE, N) \ #define CPP_RESERVE(PFILE, N) \
(CPP_WRITTEN (PFILE) + (size_t)(N) > (PFILE)->token_buffer_size \ (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. */ /* 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)) #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) #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_PRINT_DEPS(PFILE) CPP_OPTION (PFILE, print_deps)
#define CPP_TRADITIONAL(PFILE) CPP_OPTION (PFILE, traditional) #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) \ #define CPP_PEDANTIC(PF) \
(CPP_OPTION (PF, pedantic) && !CPP_IN_SYSTEM_HEADER (PF)) (CPP_OPTION (PF, pedantic) && !CPP_IN_SYSTEM_HEADER (PF))
#define CPP_WTRADITIONAL(PF) \ #define CPP_WTRADITIONAL(PF) \
(CPP_OPTION (PF, warn_traditional) && !CPP_IN_SYSTEM_HEADER (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. */ /* Flags for _cpp_init_toklist. */
#define DUMMY_TOKEN 0 #define DUMMY_TOKEN 0
#define NO_DUMMY_TOKEN 1 #define NO_DUMMY_TOKEN 1
@ -181,22 +186,19 @@ extern unsigned char _cpp_IStable[256];
/* In cpphash.c */ /* In cpphash.c */
extern unsigned int _cpp_calc_hash PARAMS ((const U_CHAR *, size_t)); extern unsigned int _cpp_calc_hash PARAMS ((const U_CHAR *, size_t));
extern void _cpp_free_definition PARAMS ((cpp_hashnode *)); extern void _cpp_free_definition PARAMS ((cpp_hashnode *));
extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_toklist *, extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *));
cpp_hashnode *));
extern void _cpp_dump_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_init_macro_hash PARAMS ((cpp_reader *));
extern void _cpp_dump_macro_hash PARAMS ((cpp_reader *)); extern void _cpp_dump_macro_hash PARAMS ((cpp_reader *));
/* In cppfiles.c */ /* In cppfiles.c */
extern void _cpp_simplify_pathname PARAMS ((char *)); 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, unsigned int, int,
struct file_name_list *)); struct file_name_list *,
extern int _cpp_compare_file_date PARAMS ((cpp_reader *, U_CHAR *, int));
unsigned int, extern int _cpp_compare_file_date PARAMS ((cpp_reader *, const U_CHAR *,
struct file_name_list *)); unsigned int, int));
extern void _cpp_init_include_table PARAMS ((cpp_reader *)); extern void _cpp_init_include_table PARAMS ((cpp_reader *));
extern const char *_cpp_fake_include PARAMS ((cpp_reader *, const char *)); 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 *)); extern int _cpp_parse_expr PARAMS ((cpp_reader *));
/* In cpplex.c */ /* 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_rest_of_line PARAMS ((cpp_reader *));
extern void _cpp_skip_hspace PARAMS ((cpp_reader *)); extern void _cpp_free_temp_tokens 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_init_input_buffer PARAMS ((cpp_reader *)); extern void _cpp_init_input_buffer PARAMS ((cpp_reader *));
extern void _cpp_grow_token_buffer PARAMS ((cpp_reader *, long)); extern void _cpp_grow_token_buffer PARAMS ((cpp_reader *, long));
extern enum cpp_ttype _cpp_get_directive_token extern enum cpp_ttype _cpp_get_directive_token
PARAMS ((cpp_reader *)); 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_init_toklist PARAMS ((cpp_toklist *, int));
extern void _cpp_clear_toklist PARAMS ((cpp_toklist *)); extern void _cpp_clear_toklist PARAMS ((cpp_toklist *));
extern void _cpp_free_toklist PARAMS ((cpp_toklist *)); extern void _cpp_free_toklist PARAMS ((const 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 int _cpp_equiv_tokens PARAMS ((const cpp_token *, extern int _cpp_equiv_tokens PARAMS ((const cpp_token *,
const cpp_token *)); const cpp_token *));
extern int _cpp_equiv_toklists PARAMS ((const cpp_toklist *, extern int _cpp_equiv_toklists PARAMS ((const cpp_toklist *,
const cpp_toklist *)); const cpp_toklist *));
extern void _cpp_expand_token_space PARAMS ((cpp_toklist *, unsigned int)); 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 */ /* 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_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. */ /* Utility routines and macros. */
#define xnew(T) (T *) xmalloc (sizeof(T)) #define xnew(T) (T *) xmalloc (sizeof(T))

View file

@ -215,8 +215,6 @@ static void append_include_chain PARAMS ((cpp_reader *,
char *, int, int)); char *, int, int));
static void merge_include_chains PARAMS ((cpp_reader *)); 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_dependency_output PARAMS ((cpp_reader *));
static void initialize_standard_includes PARAMS ((cpp_reader *)); static void initialize_standard_includes PARAMS ((cpp_reader *));
static void new_pending_directive PARAMS ((struct cpp_pending *, 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) if (errno != ENOENT)
cpp_notice_from_errno (pfile, dir); cpp_notice_from_errno (pfile, dir);
else if (CPP_OPTION (pfile, verbose)) else if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring nonexistent directory `%s'\n"), dir); fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"), dir);
return; return;
} }
@ -442,7 +440,7 @@ merge_include_chains (pfile)
&& cur->dev == other->dev) && cur->dev == other->dev)
{ {
if (CPP_OPTION (pfile, verbose)) if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory `%s'\n"), fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
cur->name); cur->name);
prev->next = cur->next; prev->next = cur->next;
@ -462,7 +460,7 @@ merge_include_chains (pfile)
&& cur->dev == other->dev) && cur->dev == other->dev)
{ {
if (CPP_OPTION (pfile, verbose)) if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory `%s'\n"), fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
cur->name); cur->name);
prev->next = cur->next; prev->next = cur->next;
@ -481,7 +479,7 @@ merge_include_chains (pfile)
if (quote == qtail) if (quote == qtail)
{ {
if (CPP_OPTION (pfile, verbose)) if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory `%s'\n"), fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
quote->name); quote->name);
free (quote->name); free (quote->name);
@ -495,7 +493,7 @@ merge_include_chains (pfile)
cur = cur->next; cur = cur->next;
cur->next = brack; cur->next = brack;
if (CPP_OPTION (pfile, verbose)) if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring duplicate directory `%s'\n"), fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"),
qtail->name); qtail->name);
free (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. */ /* Initialize a cpp_reader structure. */
void void
cpp_reader_init (pfile) cpp_reader_init (pfile)
@ -545,6 +525,7 @@ cpp_reader_init (pfile)
CPP_OPTION (pfile, dollars_in_ident) = 1; CPP_OPTION (pfile, dollars_in_ident) = 1;
CPP_OPTION (pfile, cplusplus_comments) = 1; CPP_OPTION (pfile, cplusplus_comments) = 1;
CPP_OPTION (pfile, warn_import) = 1; CPP_OPTION (pfile, warn_import) = 1;
CPP_OPTION (pfile, warn_paste) = 1;
CPP_OPTION (pfile, discard_comments) = 1; CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, show_column) = 1; CPP_OPTION (pfile, show_column) = 1;
CPP_OPTION (pfile, tabstop) = 8; CPP_OPTION (pfile, tabstop) = 8;
@ -596,25 +577,19 @@ cpp_cleanup (pfile)
pfile->token_buffer = NULL; pfile->token_buffer = NULL;
} }
if (pfile->input_buffer)
{
free (pfile->input_buffer);
pfile->input_buffer = NULL;
pfile->input_buffer_len = 0;
}
if (pfile->deps) if (pfile->deps)
deps_free (pfile->deps); deps_free (pfile->deps);
htab_delete (pfile->hashtab); htab_delete (pfile->hashtab);
splay_tree_delete (pfile->all_include_files); 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 /* 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 be entered in the macro hash table under the name NAME, with value
VALUE (if any). FLAGS tweaks the behavior a little: VALUE (if any). Two values are not compile time constants, so we tag
DUMP write debug info for this macro them in the FLAGS field instead:
VERS value is the global version_string, quoted VERS value is the global version_string, quoted
ULP value is the global user_label_prefix ULP value is the global user_label_prefix
*/ */
@ -622,18 +597,17 @@ cpp_cleanup (pfile)
struct builtin struct builtin
{ {
const U_CHAR *name; const U_CHAR *name;
const U_CHAR *value; const char *value;
unsigned short type; unsigned short type;
unsigned short flags; unsigned short flags;
unsigned int len; unsigned int len;
}; };
#define DUMP 0x01 #define VERS 0x01
#define VERS 0x02 #define ULP 0x02
#define ULP 0x04
#define B(n, t) { U n, 0, t, 0, sizeof n - 1 } #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 C(n, v) { U n, v, T_MACRO, 0, sizeof n - 1 }
#define X(n, v, t, f) { U n, U v, t, DUMP|f, sizeof n - 1 } #define X(n, f) { U n, 0, T_MACRO, f, sizeof n - 1 }
static const struct builtin builtin_array[] = static const struct builtin builtin_array[] =
{ {
B("__TIME__", T_TIME), B("__TIME__", T_TIME),
@ -642,10 +616,10 @@ static const struct builtin builtin_array[] =
B("__BASE_FILE__", T_BASE_FILE), B("__BASE_FILE__", T_BASE_FILE),
B("__LINE__", T_SPECLINE), B("__LINE__", T_SPECLINE),
B("__INCLUDE_LEVEL__", T_INCLUDE_LEVEL), B("__INCLUDE_LEVEL__", T_INCLUDE_LEVEL),
B("__STDC__", T_STDC),
X("__VERSION__", 0, T_XCONST, VERS), X("__VERSION__", VERS),
X("__USER_LABEL_PREFIX__", 0, T_CONST, ULP), X("__USER_LABEL_PREFIX__", ULP),
X("__STDC__", "1", T_STDC, 0),
C("__REGISTER_PREFIX__", REGISTER_PREFIX), C("__REGISTER_PREFIX__", REGISTER_PREFIX),
C("__HAVE_BUILTIN_SETJMP__", "1"), C("__HAVE_BUILTIN_SETJMP__", "1"),
#ifndef NO_BUILTIN_SIZE_TYPE #ifndef NO_BUILTIN_SIZE_TYPE
@ -671,35 +645,47 @@ initialize_builtins (pfile)
cpp_reader *pfile; cpp_reader *pfile;
{ {
const struct builtin *b; const struct builtin *b;
const U_CHAR *val;
cpp_hashnode *hp;
for(b = builtin_array; b < builtin_array_end; b++) for(b = builtin_array; b < builtin_array_end; b++)
{ {
if (b->type == T_STDC && CPP_TRADITIONAL (pfile)) if (b->type == T_MACRO)
continue;
if (b->flags & ULP)
val = (const U_CHAR *) user_label_prefix;
else if (b->flags & VERS)
{ {
val = (const U_CHAR *) xmalloc (strlen (version_string) + 3); const char *val;
sprintf ((char *)val, "\"%s\"", version_string); 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 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 = cpp_lookup (pfile, b->name, b->len);
hp->value.cpval = val; hp->type = b->type;
hp->type = b->type; }
if ((b->flags & DUMP) && CPP_OPTION (pfile, debug_output))
dump_special_to_buffer (pfile, b->name, b->len);
} }
} }
#undef DUMP
#undef STDC
#undef VERS #undef VERS
#undef ULP #undef ULP
#undef builtin_array_end
/* Another subroutine of cpp_start_read. This one sets up to do /* Another subroutine of cpp_start_read. This one sets up to do
dependency-file output. */ dependency-file output. */
@ -889,6 +875,13 @@ cpp_start_read (pfile, print, fname)
if (CPP_OPTION (pfile, cplusplus)) if (CPP_OPTION (pfile, cplusplus))
CPP_OPTION (pfile, warn_traditional) = 0; 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. */ /* Set this if it hasn't been set already. */
if (user_label_prefix == NULL) if (user_label_prefix == NULL)
user_label_prefix = USER_LABEL_PREFIX; user_label_prefix = USER_LABEL_PREFIX;
@ -898,6 +891,16 @@ cpp_start_read (pfile, print, fname)
if (CPP_OPTION (pfile, preprocessed)) if (CPP_OPTION (pfile, preprocessed))
pfile->no_macro_expand++; 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 /* Set up the IStable. This doesn't do anything if we were compiled
with a compiler that supports C99 designated initializers. */ with a compiler that supports C99 designated initializers. */
init_IStable (); init_IStable ();
@ -946,13 +949,12 @@ cpp_start_read (pfile, print, fname)
as line 0. */ as line 0. */
CPP_BUFFER (pfile)->lineno = 0; CPP_BUFFER (pfile)->lineno = 0;
if (print) if (print)
{ {
print->lineno = 0;
print->last_fname = CPP_BUFFER (pfile)->nominal_fname; print->last_fname = CPP_BUFFER (pfile)->nominal_fname;
print->last_id = pfile->include_depth; print->last_id = pfile->include_depth;
print->written = CPP_WRITTEN (pfile); print->written = CPP_WRITTEN (pfile);
print->lineno = 0;
} }
/* Install __LINE__, etc. */ /* Install __LINE__, etc. */
@ -968,10 +970,13 @@ cpp_start_read (pfile, print, fname)
p = q; p = q;
} }
pfile->done_initializing = 1; 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; CPP_BUFFER (pfile)->lineno = 1;
if (print && ! CPP_OPTION (pfile, no_output)) 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 /* The -imacros files can be scanned now, but the -include files
have to be pushed onto the include stack and processed later, 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) if (cpp_read_file (pfile, p->arg)
&& print && ! CPP_OPTION (pfile, no_output)) && print && ! CPP_OPTION (pfile, no_output))
cpp_output_tokens (pfile, print); cpp_output_tokens (pfile, print, 1); /* record entry to file */
q = p->next; q = p->next;
free (p); free (p);
p = q; p = q;
@ -1073,7 +1078,7 @@ cpp_finish (pfile, print)
/* Flush any pending output. */ /* Flush any pending output. */
if (print) if (print)
{ {
cpp_output_tokens (pfile, print); cpp_output_tokens (pfile, print, print->lineno);
if (ferror (print->outf) || fclose (print->outf)) if (ferror (print->outf) || fclose (print->outf))
cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname)); 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; CPP_OPTION (pfile, warn_undef) = 1;
else if (!strcmp (argv[i], "-Wimport")) else if (!strcmp (argv[i], "-Wimport"))
CPP_OPTION (pfile, warn_import) = 1; CPP_OPTION (pfile, warn_import) = 1;
else if (!strcmp (argv[i], "-Wpaste"))
CPP_OPTION (pfile, warn_paste) = 1;
else if (!strcmp (argv[i], "-Werror")) else if (!strcmp (argv[i], "-Werror"))
CPP_OPTION (pfile, warnings_are_errors) = 1; CPP_OPTION (pfile, warnings_are_errors) = 1;
else if (!strcmp (argv[i], "-Wno-traditional")) else if (!strcmp (argv[i], "-Wno-traditional"))
@ -1767,6 +1774,8 @@ handle_option (pfile, argc, argv)
CPP_OPTION (pfile, warn_undef) = 0; CPP_OPTION (pfile, warn_undef) = 0;
else if (!strcmp (argv[i], "-Wno-import")) else if (!strcmp (argv[i], "-Wno-import"))
CPP_OPTION (pfile, warn_import) = 0; 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")) else if (!strcmp (argv[i], "-Wno-error"))
CPP_OPTION (pfile, warnings_are_errors) = 0; CPP_OPTION (pfile, warnings_are_errors) = 0;
break; break;
@ -1836,10 +1845,10 @@ Switches:\n\
(dirs specified with -isystem will still be used)\n\ (dirs specified with -isystem will still be used)\n\
-nostdinc++ Do not search system include directories for C++\n\ -nostdinc++ Do not search system include directories for C++\n\
-o <file> Put output into <file>\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\ -pedantic-errors Issue -pedantic warnings as errors instead\n\
-traditional Follow K&R pre-processor behaviour\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-c Assume that the input sources are in C\n\
-lang-c89 Assume that the input sources are in C89\n\ -lang-c89 Assume that the input sources are in C89\n\
-lang-c++ Assume that the input sources are in C++\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_DOT_STAR, ".*") \
T(CPP_MIN, "<?") /* extension */ \ T(CPP_MIN, "<?") /* extension */ \
T(CPP_MAX, ">?") \ 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_NAME, 0) /* word */ \
I(CPP_INT, 0) /* 23 */ \ I(CPP_INT, 0) /* 23 */ \
@ -121,15 +122,11 @@ typedef struct cpp_hashnode cpp_hashnode;
\ \
I(CPP_COMMENT, 0) /* Only if output comments. */ \ I(CPP_COMMENT, 0) /* Only if output comments. */ \
N(CPP_MACRO_ARG, 0) /* Macro argument. */ \ N(CPP_MACRO_ARG, 0) /* Macro argument. */ \
N(CPP_SUBLIST, 0) /* Sublist. */ \
N(CPP_EOF, 0) /* End of file. */ \ 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. */ \ /* Obsolete - will be removed when no code uses them still. */ \
T(CPP_VSPACE, "\n") /* End of line. */ \ 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. */
#define T(e, s) e, #define T(e, s) e,
#define I(e, s) e, #define I(e, s) e,
@ -154,49 +151,42 @@ struct cpp_name
const unsigned char *text; 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. */ /* Flags for the cpp_token structure. */
#define PREV_WHITESPACE 1 /* If whitespace before this token. */ #define PREV_WHITE (1 << 0) /* If whitespace before this token. */
#define BOL 2 /* Beginning of line. */ #define BOL (1 << 1) /* Beginning of logical line. */
#define DIGRAPH 4 /* If it was a digraph. */ #define DIGRAPH (1 << 2) /* If it was a digraph. */
#define UNSIGNED_INT 8 /* If int preprocessing token unsigned. */ #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 /* 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 struct cpp_token
{ {
unsigned short col; /* starting column of this token */ unsigned int line; /* starting line number of this token */
ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* node type */ unsigned short col; /* starting column of this token */
unsigned char flags; /* flags - see above */ ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */
unsigned int aux; /* CPP_OTHER character. Hash of a unsigned char flags; /* flags - see above */
NAME, or something - see uses
in the code */
union 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; } val;
}; };
/* General flags. */ /* cpp_toklist flags. */
#define LIST_OFFSET (1 << 0) #define LIST_OFFSET (1 << 0)
#define VAR_ARGS (1 << 1)
#define BEG_OF_FILE (1 << 2)
/* Directive flags. */ struct directive; /* These are deliberately incomplete. */
#define SYNTAX_INCLUDE (1 << 8) struct answer;
struct macro_args;
typedef int (*directive_handler) PARAMS ((cpp_reader *)); struct cpp_context;
struct cpp_toklist struct cpp_toklist
{ {
@ -208,11 +198,15 @@ struct cpp_toklist
unsigned int name_used; /* _bytes_ used */ unsigned int name_used; /* _bytes_ used */
unsigned int name_cap; /* _bytes_ allocated */ 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 */ unsigned int line; /* starting line number */
/* The handler to call after lexing the rest of this line. unsigned short params_len; /* length of macro parameter names. */
-1 for none */
short dirno; short int paramc; /* no. of macro params (-1 = obj-like). */
/* Per-list flags, see above */ /* Per-list flags, see above */
unsigned short flags; unsigned short flags;
@ -224,12 +218,12 @@ struct cpp_buffer
const unsigned char *rlimit; /* end of valid data */ const unsigned char *rlimit; /* end of valid data */
const unsigned char *buf; /* entire buffer */ const unsigned char *buf; /* entire buffer */
const unsigned char *line_base; /* start of current line */ const unsigned char *line_base; /* start of current line */
const unsigned char *mark; /* Saved position for lengthy backtrack. */
struct cpp_buffer *prev; struct cpp_buffer *prev;
/* Filename specified with #line command. */ /* Filename specified with #line command. */
const char *nominal_fname; const char *nominal_fname;
/* Actual directory of this file, used only for "" includes */ /* Actual directory of this file, used only for "" includes */
struct file_name_list *actual_dir; struct file_name_list *actual_dir;
@ -237,10 +231,6 @@ struct cpp_buffer
to record control macros. */ to record control macros. */
struct include_file *inc; 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. /* Value of if_stack at start of this file.
Used to prohibit unmatched #endif (etc) in an include file. */ Used to prohibit unmatched #endif (etc) in an include file. */
struct if_stack *if_stack; struct if_stack *if_stack;
@ -248,29 +238,13 @@ struct cpp_buffer
/* Line number at line_base (above). */ /* Line number at line_base (above). */
unsigned int lineno; 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. /* True if we have already warned about C++ comments in this file.
The warning happens only for C89 extended mode with -pedantic on, The warning happens only for C89 extended mode with -pedantic on,
or for -Wtraditional, and only once per file (otherwise it would or for -Wtraditional, and only once per file (otherwise it would
be far too noisy). */ be far too noisy). */
char warned_cplusplus_comments; char warned_cplusplus_comments;
/* In a file buffer, true if this buffer's data is mmapped /* 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. */
char mapped; char mapped;
}; };
@ -354,7 +328,7 @@ struct cpp_options
/* Nonzero means don't copy comments into the output file. */ /* Nonzero means don't copy comments into the output file. */
unsigned char discard_comments; unsigned char discard_comments;
/* Nonzero means process the ANSI trigraph sequences. */ /* Nonzero means process the ISO trigraph sequences. */
unsigned char trigraphs; unsigned char trigraphs;
/* Nonzero means print the names of included files rather than the /* 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. */ with the # indented from the beginning of the line. */
unsigned char warn_traditional; 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. */ /* Nonzero means turn warnings into errors. */
unsigned char warnings_are_errors; unsigned char warnings_are_errors;
@ -417,7 +395,7 @@ struct cpp_options
/* Zero means dollar signs are punctuation. */ /* Zero means dollar signs are punctuation. */
unsigned char dollars_in_ident; 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; unsigned char traditional;
/* Nonzero means warn if undefined identifiers are evaluated in an #if. */ /* Nonzero means warn if undefined identifiers are evaluated in an #if. */
@ -460,19 +438,18 @@ struct cpp_options
unsigned char show_column; unsigned char show_column;
}; };
/* A cpp_reader encapsulates the "state" of a pre-processor run. /* A cpp_reader encapsulates the "state" of a pre-processor run.
Applying cpp_get_token repeatedly yields a stream of pre-processor Applying cpp_get_token repeatedly yields a stream of pre-processor
tokens. Usually, there is only one cpp_reader object active. */ tokens. Usually, there is only one cpp_reader object active. */
struct cpp_reader struct cpp_reader
{ {
/* HACK FIXME. Maybe make into cpp_printer printer later. */
cpp_printer *printer;
/* Top of buffer stack. */ /* Top of buffer stack. */
cpp_buffer *buffer; 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. */ /* A buffer used for both for cpp_get_token's output, and also internally. */
unsigned char *token_buffer; unsigned char *token_buffer;
/* Allocated size of token_buffer. CPP_RESERVE allocates space. */ /* Allocated size of token_buffer. CPP_RESERVE allocates space. */
@ -483,8 +460,9 @@ struct cpp_reader
/* Error counter for exit code */ /* Error counter for exit code */
unsigned int errors; 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_line;
unsigned int multiline_string_column;
/* Current depth in #include directives that use <...>. */ /* Current depth in #include directives that use <...>. */
unsigned int system_include_depth; unsigned int system_include_depth;
@ -509,19 +487,46 @@ struct cpp_reader
for include files. (Altered as we get more of them.) */ for include files. (Altered as we get more of them.) */
unsigned int max_include_len; 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; const cpp_hashnode *potential_control_macro;
/* Token column position adjustment owing to tabs in whitespace. */ /* Token column position adjustment owing to tabs in whitespace. */
unsigned int col_adjust; 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. */ /* Buffer of -M output. */
struct deps *deps; 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. */ /* User visible options. */
struct cpp_options opts; struct cpp_options opts;
@ -532,31 +537,24 @@ struct cpp_reader
/* If non-zero, macros are not expanded. */ /* If non-zero, macros are not expanded. */
unsigned char no_macro_expand; 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. */ /* We're printed a warning recommending against using #import. */
unsigned char import_warning; 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 /* True after cpp_start_read completes. Used to inhibit some
warnings while parsing the command line. */ warnings while parsing the command line. */
unsigned char done_initializing; unsigned char done_initializing;
/* True if we are skipping a failed conditional group. */ /* True if we are skipping a failed conditional group. */
unsigned char skipping; 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 /* struct cpp_printer encapsulates state used to convert the stream of
@ -611,13 +609,8 @@ enum node_type
T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */ T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
T_TIME, /* `__TIME__' */ T_TIME, /* `__TIME__' */
T_STDC, /* `__STDC__' */ 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_POISON, /* poisoned identifier */
T_MACRO, /* object-like macro */ T_MACRO, /* a macro, either object-like or function-like */
T_FMACRO, /* function-like macro */
T_IDENTITY, /* macro defined to itself */
T_EMPTY, /* macro defined to nothing */
T_ASSERTION /* predicate for #assert */ T_ASSERTION /* predicate for #assert */
}; };
@ -634,11 +627,10 @@ struct cpp_hashnode
ENUM_BITFIELD(node_type) type : 8; /* node type */ ENUM_BITFIELD(node_type) type : 8; /* node type */
char disabled; /* macro turned off for rescan? */ char disabled; /* macro turned off for rescan? */
union { union
const unsigned char *cpval; /* some predefined macros */ {
const struct object_defn *odefn; /* #define foo bar */ const cpp_toklist *expansion; /* a macro's replacement list. */
const struct funct_defn *fdefn; /* #define foo(x) bar(x) */ struct answer *answers; /* answers to an assertion. */
struct predicate *pred; /* #assert */
} value; } value;
union tree_node *fe_value; /* front end value */ union tree_node *fe_value; /* front end value */
@ -646,23 +638,17 @@ struct cpp_hashnode
const unsigned char name[1]; /* name[length] */ 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 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 void cpp_reader_init PARAMS ((cpp_reader *));
extern cpp_printer *cpp_printer_init PARAMS ((cpp_reader *, cpp_printer *)); extern cpp_printer *cpp_printer_init PARAMS ((cpp_reader *, cpp_printer *));
extern int cpp_start_read PARAMS ((cpp_reader *, cpp_printer *, const char *)); 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_tokens PARAMS ((cpp_reader *, cpp_printer *,
extern void cpp_output_list PARAMS ((cpp_reader *, cpp_printer *, unsigned int));
const cpp_toklist *));
extern void cpp_finish PARAMS ((cpp_reader *, cpp_printer *)); extern void cpp_finish PARAMS ((cpp_reader *, cpp_printer *));
extern void cpp_cleanup PARAMS ((cpp_reader *)); 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_define PARAMS ((cpp_reader *, const char *));
extern void cpp_assert PARAMS ((cpp_reader *, const char *)); extern void cpp_assert PARAMS ((cpp_reader *, const char *));
extern void cpp_undef 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); print = cpp_printer_init (pfile, &parse_out);
if (! print) if (! print)
return (FATAL_EXIT_CODE); return (FATAL_EXIT_CODE);
pfile->printer = print;
if (! cpp_start_read (pfile, print, CPP_OPTION (pfile, in_fname))) if (! cpp_start_read (pfile, print, CPP_OPTION (pfile, in_fname)))
return (FATAL_EXIT_CODE); return (FATAL_EXIT_CODE);

View file

@ -432,8 +432,6 @@ write_lbrac ()
struct partial_proto struct partial_proto
{ {
struct partial_proto *next; struct partial_proto *next;
char *fname; /* name of function */
char *rtype; /* return type */
struct fn_decl *fn; struct fn_decl *fn;
int line_seen; int line_seen;
}; };
@ -497,15 +495,13 @@ recognized_macro (fname)
} }
void void
recognized_extern (name, name_length, type, type_length) recognized_extern (name)
const char *name; const cpp_token *name;
const char *type ATTRIBUTE_UNUSED;
int name_length, type_length ATTRIBUTE_UNUSED;
{ {
switch (special_file_handling) switch (special_file_handling)
{ {
case errno_h: 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--; seen_errno = 1, required_other--;
break; 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 /* Called by scan_decls if it saw a function definition for a function
named FNAME, with return type RTYPE, and argument list ARGS, named FNAME, in source file FILE_SEEN on line LINE_SEEN. KIND is
in source file FILE_SEEN on line LINE_SEEN. 'I' for an inline function; 'F' if a normal function declaration
KIND is 'I' for an inline function; preceded by 'extern "C"' (or nested inside 'extern "C"' braces); or
'F' if a normal function declaration preceded by 'extern "C"'
(or nested inside 'extern "C"' braces); or
'f' for other function declarations. */ 'f' for other function declarations. */
void void
recognized_function (fname, fname_length, recognized_function (fname, kind, have_arg_list, file_seen)
kind, rtype, rtype_length, const cpp_token *fname;
have_arg_list, file_seen, line_seen)
const char *fname;
int fname_length;
int kind; /* One of 'f' 'F' or 'I' */ int kind; /* One of 'f' 'F' or 'I' */
const char *rtype;
int rtype_length;
int have_arg_list; int have_arg_list;
const char *file_seen; const char *file_seen;
int line_seen;
{ {
struct partial_proto *partial; struct partial_proto *partial;
int i; int i;
@ -543,7 +531,8 @@ recognized_function (fname, fname_length,
missing_extern_C_count++; missing_extern_C_count++;
#endif #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. */ /* Remove the function from the list of required function. */
if (fn) if (fn)
@ -577,12 +566,7 @@ recognized_function (fname, fname_length,
partial_count++; partial_count++;
partial = (struct partial_proto *) partial = (struct partial_proto *)
obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto)); obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto));
partial->fname = obstack_alloc (&scan_file_obstack, fname_length + 1); partial->line_seen = fname->line;
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->fn = fn; partial->fn = fn;
fn->partial = partial; fn->partial = partial;
partial->next = partial_proto_list; partial->next = partial_proto_list;
@ -590,7 +574,7 @@ recognized_function (fname, fname_length,
if (verbose) if (verbose)
{ {
fprintf (stderr, "(%s: %s non-prototype function declaration.)\n", 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++) for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
check_macro_names (&scan_in, cur_symbols->names); 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. /* Traditionally, getc and putc are defined in terms of _filbuf and _flsbuf.
If so, those functions are also required. */ If so, those functions are also required. */
if (special_file_handling == stdio_h if (special_file_handling == stdio_h
&& (fn = lookup_std_proto ("_filbuf", 7)) != NULL) && (fn = lookup_std_proto ("_filbuf", 7)) != NULL)
{ {
static const unsigned char getchar_call[] = "getchar();"; static const unsigned char getchar_call[] = "getchar();";
int old_written = CPP_WRITTEN (&scan_in);
int seen_filbuf = 0; int seen_filbuf = 0;
cpp_buffer *buf = CPP_BUFFER (&scan_in); cpp_buffer *buf = CPP_BUFFER (&scan_in);
if (cpp_push_buffer (&scan_in, getchar_call, 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();". */ /* Scan the macro expansion of "getchar();". */
for (;;) for (;;)
{ {
enum cpp_ttype token = cpp_get_token (&scan_in); const cpp_token *t = cpp_get_token (&scan_in);
int length = CPP_WRITTEN (&scan_in) - old_written;
unsigned char *id = scan_in.token_buffer + old_written; if (t->type == CPP_EOF)
{
CPP_SET_WRITTEN (&scan_in, old_written); cpp_pop_buffer (&scan_in);
if (token == CPP_EOF && CPP_BUFFER (&scan_in) == buf) if (CPP_BUFFER (&scan_in) == buf)
break; break;
if (token == CPP_NAME && cpp_idcmp (id, length, "_filbuf") == 0) }
else if (t->type == CPP_NAME && cpp_idcmp (t->val.name.text,
t->val.name.len,
"_filbuf") == 0)
seen_filbuf++; seen_filbuf++;
} }
if (seen_filbuf) if (seen_filbuf)
@ -1030,8 +1010,6 @@ check_protection (ifndef_line, endif_line)
} }
else if (!strcmp (buf.base, "define")) else if (!strcmp (buf.base, "define"))
{ {
if (if_nesting != 1)
goto skip_to_eol;
c = inf_skip_spaces (c); c = inf_skip_spaces (c);
c = inf_scan_ident (&buf, c); c = inf_scan_ident (&buf, c);
if (buf.base[0] > 0 && strcmp (buf.base, protect_name) == 0) 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; int nesting = 1;
for (;;) for (;;)
{ {
enum cpp_ttype token = cpp_get_token (pfile); enum cpp_ttype token = cpp_get_token (pfile)->type;
if (token == CPP_EOF) if (token == CPP_EOF)
break; break;
if (token == CPP_OPEN_BRACE) if (token == CPP_OPEN_BRACE)
@ -84,24 +84,17 @@ scan_decls (pfile, argc, argv)
char **argv ATTRIBUTE_UNUSED; char **argv ATTRIBUTE_UNUSED;
{ {
int saw_extern, saw_inline; int saw_extern, saw_inline;
int start_written; const cpp_token *prev_id;
/* If declarator_start is non-zero, it marks the start of the current const cpp_token *token;
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;
new_statement: new_statement:
CPP_SET_WRITTEN (pfile, 0);
start_written = 0;
token = cpp_get_token (pfile); token = cpp_get_token (pfile);
handle_statement: handle_statement:
current_extern_C = 0; current_extern_C = 0;
saw_extern = 0; saw_extern = 0;
saw_inline = 0; saw_inline = 0;
if (token == CPP_OPEN_BRACE) if (token->type == CPP_OPEN_BRACE)
{ {
/* Pop an 'extern "C"' nesting level, if appropriate. */ /* Pop an 'extern "C"' nesting level, if appropriate. */
if (extern_C_braces_length if (extern_C_braces_length
@ -110,120 +103,112 @@ scan_decls (pfile, argc, argv)
brace_nesting--; brace_nesting--;
goto new_statement; goto new_statement;
} }
if (token == CPP_OPEN_BRACE) if (token->type == CPP_OPEN_BRACE)
{ {
brace_nesting++; brace_nesting++;
goto new_statement; goto new_statement;
} }
if (token == CPP_EOF) if (token->type == CPP_EOF)
{ {
cpp_pop_buffer (pfile);
if (CPP_BUFFER (pfile) == NULL) if (CPP_BUFFER (pfile) == NULL)
return 0; return 0;
else
goto new_statement; goto new_statement;
} }
if (token == CPP_SEMICOLON) if (token->type == CPP_SEMICOLON)
goto new_statement; goto new_statement;
if (token != CPP_NAME) if (token->type != CPP_NAME)
goto new_statement; goto new_statement;
prev_id_start = 0; prev_id = 0;
declarator_start = 0;
for (;;) 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: case CPP_OPEN_PAREN:
/* Looks like this is the start of a formal parameter list. */ /* Looks like this is the start of a formal parameter list. */
if (prev_id_start) if (prev_id)
{ {
int nesting = 1; int nesting = 1;
int have_arg_list = 0; int have_arg_list = 0;
cpp_buffer *fbuf = cpp_file_buffer (pfile);
unsigned int func_lineno = CPP_BUF_LINE (fbuf);
for (;;) for (;;)
{ {
token = cpp_get_token (pfile); token = cpp_get_token (pfile);
if (token == CPP_OPEN_PAREN) if (token->type == CPP_OPEN_PAREN)
nesting++; nesting++;
else if (token == CPP_CLOSE_PAREN) else if (token->type == CPP_CLOSE_PAREN)
{ {
nesting--; nesting--;
if (nesting == 0) if (nesting == 0)
break; break;
} }
else if (token == CPP_EOF) else if (token->type == CPP_EOF)
break; break;
else if (token == CPP_NAME || token == CPP_ELLIPSIS) else if (token->type == CPP_NAME
|| token->type == CPP_ELLIPSIS)
have_arg_list = 1; have_arg_list = 1;
} }
recognized_function (pfile->token_buffer + prev_id_start, recognized_function (prev_id,
prev_id_end - prev_id_start,
(saw_inline ? 'I' (saw_inline ? 'I'
: in_extern_C_brace || current_extern_C : in_extern_C_brace || current_extern_C
? 'F' : 'f'), ? 'F' : 'f'), have_arg_list,
pfile->token_buffer, prev_id_start, CPP_BUFFER (pfile)->nominal_fname);
have_arg_list, token = cpp_get_token (pfile);
fbuf->nominal_fname, func_lineno); if (token->type == CPP_OPEN_BRACE)
token = cpp_get_non_space_token (pfile);
if (token == CPP_OPEN_BRACE)
{ {
/* skip body of (normally) inline function */ /* skip body of (normally) inline function */
skip_to_closing_brace (pfile); skip_to_closing_brace (pfile);
goto new_statement; goto new_statement;
} }
goto maybe_handle_comma; if (token->type == CPP_SEMICOLON)
goto new_statement;
} }
break; 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: case CPP_NAME:
/* "inline" and "extern" are recognized but skipped */ /* "inline" and "extern" are recognized but skipped */
if (!cpp_idcmp (pfile->token_buffer, if (!cpp_idcmp (token->val.name.text, token->val.name.len, "inline"))
CPP_WRITTEN (pfile), "inline"))
{ {
saw_inline = 1; saw_inline = 1;
CPP_SET_WRITTEN (pfile, start_written);
} }
else if (!cpp_idcmp (pfile->token_buffer, else if (!cpp_idcmp (token->val.name.text,
CPP_WRITTEN (pfile), "extern")) token->val.name.len, "extern"))
{ {
saw_extern = 1; saw_extern = 1;
CPP_SET_WRITTEN (pfile, start_written); token = cpp_get_token (pfile);
token = cpp_get_non_space_token (pfile); if (token->type == CPP_STRING
if (token == CPP_STRING && !cpp_idcmp (token->val.name.text,
&& strcmp (pfile->token_buffer, "\"C\"") == 0) token->val.name.len, "C"))
{ {
CPP_SET_WRITTEN (pfile, start_written);
current_extern_C = 1; current_extern_C = 1;
token = cpp_get_non_space_token (pfile); token = cpp_get_token (pfile);
if (token == CPP_OPEN_BRACE) if (token->type == CPP_OPEN_BRACE)
{ {
brace_nesting++; brace_nesting++;
extern_C_braces[extern_C_braces_length++] extern_C_braces[extern_C_braces_length++]
@ -236,29 +221,9 @@ scan_decls (pfile, argc, argv)
break; break;
} }
/* This may be the name of a variable or function. */ /* This may be the name of a variable or function. */
prev_id_start = start_written; prev_id = token;
prev_id_end = CPP_WRITTEN (pfile);
break; 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); token = cpp_get_token (pfile);
} }
} }

View file

@ -50,6 +50,8 @@ struct fn_decl
struct partial_proto *partial; struct partial_proto *partial;
}; };
struct cpp_token;
extern int lineno; extern int lineno;
extern void sstring_append _PARAMS((sstring *, sstring *)); extern void sstring_append _PARAMS((sstring *, sstring *));
extern void make_sstring_space _PARAMS((sstring *, int)); 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 scan_string _PARAMS((FILE *, sstring *, int));
extern int read_upto _PARAMS((FILE *, sstring *, int)); extern int read_upto _PARAMS((FILE *, sstring *, int));
extern unsigned long hash _PARAMS((const char *)); 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_function _PARAMS((const struct cpp_token *, int, int,
extern void recognized_extern _PARAMS((const char *, int, const char *, int)); const char *));
extern void recognized_extern _PARAMS((const struct cpp_token *));
extern unsigned int hashstr _PARAMS((const char *, unsigned int)); extern unsigned int hashstr _PARAMS((const char *, unsigned int));
struct cpp_reader; 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> 2000-07-03 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/20000703-1.c: New test. * gcc.c-torture/execute/20000703-1.c: New test.

View file

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

View file

@ -14,7 +14,7 @@
int int
main(void) 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) */ char *y = "0-0"; /* should be the expansion of SP1(0,MZ) */
if(strcmp(x, y)) if(strcmp(x, y))

View file

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

View file

@ -7,6 +7,7 @@
#define xstr(x) #x #define xstr(x) #x
const char a[] = str(symbol_version(getrlimit, GLIBC_2.0)); 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 b[] = str(getrlimit@GLIBC_2.0);
const char c[] = "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;
}