Commit 1ce676a0 by Neil Booth Committed by Neil Booth

cpphash.h (_cpp_push_text_context): Update.

	* cpphash.h (_cpp_push_text_context): Update.
	(_cpp_arguments_ok): New.
	* cppmacro.c (_cpp_arguments_ok): New, split out from...
	(collect_args): ...here.
	(_cpp_push_text_context): Change inputs.
	* cpptrad.c (struct fun_macro, maybe_start_funlike, save_argument,
	replace_args_and_push): New.
	(lex_identifier, _cpp_lex_identifier_trad, scan_parameters):
	Don't use IS macros directly.
	(scan_out_logical_line): Handle function-like macro argument
	collection.
	(push_replacement_text): Update.
	(replacement_length): Remove.
	(_cpp_create_trad_definition): Don't skip whitespace before
	checking for '('.

From-SVN: r54412
parent 25f2e176
2002-06-09 Neil Booth <neil@daikokuya.demon.co.uk>
* cpphash.h (_cpp_push_text_context): Update.
(_cpp_arguments_ok): New.
* cppmacro.c (_cpp_arguments_ok): New, split out from...
(collect_args): ...here.
(_cpp_push_text_context): Change inputs.
* cpptrad.c (struct fun_macro, maybe_start_funlike, save_argument,
replace_args_and_push): New.
(lex_identifier, _cpp_lex_identifier_trad, scan_parameters):
Don't use IS macros directly.
(scan_out_logical_line): Handle function-like macro argument
collection.
(push_replacement_text): Update.
(replacement_length): Remove.
(_cpp_create_trad_definition): Don't skip whitespace before
checking for '('.
2002-06-09 Marek Michalkiewicz <marekm@amelek.gda.pl> 2002-06-09 Marek Michalkiewicz <marekm@amelek.gda.pl>
* config/avr/avr.c (avr_mcu_types): Update for new devices. * config/avr/avr.c (avr_mcu_types): Update for new devices.
......
...@@ -438,9 +438,12 @@ extern void _cpp_free_definition PARAMS ((cpp_hashnode *)); ...@@ -438,9 +438,12 @@ extern void _cpp_free_definition PARAMS ((cpp_hashnode *));
extern bool _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *)); extern bool _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *));
extern void _cpp_pop_context PARAMS ((cpp_reader *)); extern void _cpp_pop_context PARAMS ((cpp_reader *));
extern void _cpp_push_text_context PARAMS ((cpp_reader *, cpp_hashnode *, extern void _cpp_push_text_context PARAMS ((cpp_reader *, cpp_hashnode *,
const uchar *, const uchar*)); const uchar *, size_t));
extern bool _cpp_save_parameter PARAMS ((cpp_reader *, cpp_macro *, extern bool _cpp_save_parameter PARAMS ((cpp_reader *, cpp_macro *,
cpp_hashnode *)); cpp_hashnode *));
extern bool _cpp_arguments_ok PARAMS ((cpp_reader *, cpp_macro *,
const cpp_hashnode *,
unsigned int));
/* In cpphash.c */ /* In cpphash.c */
extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *)); extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *));
......
...@@ -451,6 +451,52 @@ paste_all_tokens (pfile, lhs) ...@@ -451,6 +451,52 @@ paste_all_tokens (pfile, lhs)
push_token_context (pfile, NULL, lhs, 1); push_token_context (pfile, NULL, lhs, 1);
} }
/* Returns TRUE if the number of arguments ARGC supplied in an
invocation of the MACRO referenced by NODE is valid. An empty
invocation to a macro with no parameters should pass ARGC as zero.
Note that MACRO cannot necessarily be deduced from NODE, in case
NODE was redefined whilst collecting arguments. */
bool
_cpp_arguments_ok (pfile, macro, node, argc)
cpp_reader *pfile;
cpp_macro *macro;
const cpp_hashnode *node;
unsigned int argc;
{
if (argc == macro->paramc)
return true;
if (argc < macro->paramc)
{
/* As an extension, a rest argument is allowed to not appear in
the invocation at all.
e.g. #define debug(format, args...) something
debug("string");
This is exactly the same as if there had been an empty rest
argument - debug("string", ). */
if (argc + 1 == macro->paramc && macro->variadic)
{
if (CPP_PEDANTIC (pfile) && ! macro->syshdr)
cpp_error (pfile, DL_PEDWARN,
"ISO C99 requires rest arguments to be used");
return true;
}
cpp_error (pfile, DL_ERROR,
"macro \"%s\" requires %u arguments, but only %u given",
NODE_NAME (node), macro->paramc, argc);
}
else
cpp_error (pfile, DL_ERROR,
"macro \"%s\" passed %u arguments, but takes just %u",
NODE_NAME (node), argc, macro->paramc);
return false;
}
/* Reads and returns the arguments to a function-like macro /* Reads and returns the arguments to a function-like macro
invocation. Assumes the opening parenthesis has been processed. invocation. Assumes the opening parenthesis has been processed.
If there is an error, emits an appropriate diagnostic and returns If there is an error, emits an appropriate diagnostic and returns
...@@ -466,7 +512,6 @@ collect_args (pfile, node) ...@@ -466,7 +512,6 @@ collect_args (pfile, node)
macro_arg *args, *arg; macro_arg *args, *arg;
const cpp_token *token; const cpp_token *token;
unsigned int argc; unsigned int argc;
bool error = false;
macro = node->value.macro; macro = node->value.macro;
if (macro->paramc) if (macro->paramc)
...@@ -561,47 +606,17 @@ collect_args (pfile, node) ...@@ -561,47 +606,17 @@ collect_args (pfile, node)
cpp_error (pfile, DL_ERROR, cpp_error (pfile, DL_ERROR,
"unterminated argument list invoking macro \"%s\"", "unterminated argument list invoking macro \"%s\"",
NODE_NAME (node)); NODE_NAME (node));
error = true;
}
else if (argc < macro->paramc)
{
/* As an extension, a rest argument is allowed to not appear in
the invocation at all.
e.g. #define debug(format, args...) something
debug("string");
This is exactly the same as if there had been an empty rest
argument - debug("string", ). */
if (argc + 1 == macro->paramc && macro->variadic)
{
if (CPP_PEDANTIC (pfile) && ! macro->syshdr)
cpp_error (pfile, DL_PEDWARN,
"ISO C99 requires rest arguments to be used");
}
else
{
cpp_error (pfile, DL_ERROR,
"macro \"%s\" requires %u arguments, but only %u given",
NODE_NAME (node), macro->paramc, argc);
error = true;
}
} }
else if (argc > macro->paramc) else
{ {
/* Empty argument to a macro taking no arguments is OK. */ /* A single empty argument is counted as no argument. */
if (argc != 1 || arg->count) if (argc == 1 && macro->paramc == 0 && args[0].count == 0)
{ argc = 0;
cpp_error (pfile, DL_ERROR, if (_cpp_arguments_ok (pfile, macro, node, argc))
"macro \"%s\" passed %u arguments, but takes just %u", return base_buff;
NODE_NAME (node), argc, macro->paramc);
error = true;
}
} }
if (!error) /* An error occurred. */
return base_buff;
_cpp_release_buff (pfile, base_buff); _cpp_release_buff (pfile, base_buff);
return NULL; return NULL;
} }
...@@ -919,10 +934,11 @@ push_token_context (pfile, macro, first, count) ...@@ -919,10 +934,11 @@ push_token_context (pfile, macro, first, count)
/* Push a traditional macro's replacement text. */ /* Push a traditional macro's replacement text. */
void void
_cpp_push_text_context (pfile, macro, start, end) _cpp_push_text_context (pfile, macro, start, len)
cpp_reader *pfile; cpp_reader *pfile;
cpp_hashnode *macro; cpp_hashnode *macro;
const uchar *start, *end; const uchar *start;
size_t len;
{ {
cpp_context *context = next_context (pfile); cpp_context *context = next_context (pfile);
...@@ -930,7 +946,7 @@ _cpp_push_text_context (pfile, macro, start, end) ...@@ -930,7 +946,7 @@ _cpp_push_text_context (pfile, macro, start, end)
context->macro = macro; context->macro = macro;
context->buff = NULL; context->buff = NULL;
CUR (context) = start; CUR (context) = start;
RLIMIT (context) = end; RLIMIT (context) = start + len;
} }
/* Expand an argument ARG before replacing parameters in a /* Expand an argument ARG before replacing parameters in a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment