}
/* In macro.c */
+extern cpp_macro *_cpp_new_macro (cpp_reader *, cpp_macro_kind);
extern void _cpp_free_definition (cpp_hashnode *);
extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *);
extern void _cpp_pop_context (cpp_reader *);
const unsigned char *, size_t);
extern bool _cpp_save_parameter (cpp_reader *, unsigned, cpp_hashnode *,
cpp_hashnode *);
+extern void _cpp_unsave_parameters (cpp_reader *, unsigned);
extern bool _cpp_arguments_ok (cpp_reader *, cpp_macro *, const cpp_hashnode *,
unsigned int);
extern const unsigned char *_cpp_builtin_macro_text (cpp_reader *,
extern void _cpp_overlay_buffer (cpp_reader *pfile, const unsigned char *,
size_t);
extern void _cpp_remove_overlay (cpp_reader *);
-extern bool _cpp_create_trad_definition (cpp_reader *, cpp_macro *);
+extern cpp_macro *_cpp_create_trad_definition (cpp_reader *);
extern bool _cpp_expansions_different_trad (const cpp_macro *,
const cpp_macro *);
extern unsigned char *_cpp_copy_replacement_text (const cpp_macro *,
macro_arg *, source_location);
static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *,
_cpp_buff **, unsigned *);
-static bool create_iso_definition (cpp_reader *, cpp_macro *);
+static cpp_macro *create_iso_definition (cpp_reader *);
/* #define directive parsing and handling. */
static cpp_token *lex_expansion_token (cpp_reader *, cpp_macro *);
static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *,
const cpp_macro *);
-static bool parse_params (cpp_reader *, cpp_macro *);
+static bool parse_params (cpp_reader *, unsigned *, bool *);
static void check_trad_stringification (cpp_reader *, const cpp_macro *,
const cpp_string *);
static bool reached_end_of_context (cpp_context *);
return true;
}
-/* Check the syntax of the parameters in a MACRO definition. Returns
+/* Restore the parameters to their previous state. */
+
+void
+_cpp_unsave_parameters (cpp_reader *pfile, unsigned n)
+{
+ /* Clear the fast argument lookup indices. */
+ while (n--)
+ {
+ struct macro_arg_saved_data *save =
+ &((struct macro_arg_saved_data *) pfile->macro_buffer)[n];
+
+ struct cpp_hashnode *node = save->canonical_node;
+ node->flags &= ~ NODE_MACRO_ARG;
+ node->value = save->value;
+ }
+}
+
+/* Check the syntax of the parameters in a MACRO definition. Return
+ number of parameters, or -1 on failure
false if an error occurs. */
+
static bool
-parse_params (cpp_reader *pfile, cpp_macro *macro)
+parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr)
{
unsigned int prev_ident = 0;
unsigned nparms = 0;
continue;
case CPP_ELLIPSIS:
- macro->variadic = 1;
+ *varadic_ptr = true;
if (!prev_ident)
{
_cpp_save_parameter (pfile, nparms,
}
out:
- macro->paramc = nparms;
+ *n_ptr = nparms;
+
return ok;
}
return token;
}
-static bool
-create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
+static cpp_macro *
+create_iso_definition (cpp_reader *pfile)
{
+ cpp_macro *macro = _cpp_new_macro (pfile, cmk_macro);
cpp_token *token;
const cpp_token *ctoken;
bool following_paste_op = false;
const char *paste_op_error_msg =
N_("'##' cannot appear at either end of a macro expansion");
unsigned int num_extra_tokens = 0;
+ unsigned nparms = 0;
+ bool ok = false;
/* Get the first token of the expansion (or the '(' of a
function-like macro). */
if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
{
- bool ok = parse_params (pfile, macro);
+ bool varadic = false;
+ if (!parse_params (pfile, &nparms, &varadic))
+ goto out;
+
macro->parm.params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
- if (!ok)
- return false;
+ macro->variadic = varadic;
+ macro->paramc = nparms;
/* Success. Commit or allocate the parameter array. */
if (pfile->hash_table->alloc_subobject)
*token = *ctoken;
}
- /* The argument doesn't matter here. */
- vaopt_state vaopt_tracker (pfile, macro->variadic, true);
-
- for (;;)
+ for (vaopt_state vaopt_tracker (pfile, macro->variadic, true);;)
{
/* Check the stringifying # constraint 6.10.3.2.1 of
function-like macros when lexing the subsequent token. */
{
cpp_error (pfile, CPP_DL_ERROR,
"'#' is not followed by a macro parameter");
- return false;
+ goto out;
}
}
if (following_paste_op)
{
cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
- return false;
+ goto out;
}
+ if (!vaopt_tracker.completed ())
+ goto out;
break;
}
if (macro->count == 1)
{
cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
- return false;
+ goto out;
}
if (token[-1].flags & PASTE_LEFT)
}
if (vaopt_tracker.update (token) == vaopt_state::ERROR)
- return false;
+ goto out;
following_paste_op = (token->type == CPP_PASTE);
token = lex_expansion_token (pfile, macro);
}
- if (!vaopt_tracker.completed ())
- return false;
+ ok = true;
macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff);
macro->kind = cmk_macro;
}
else
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->exp.tokens[macro->count];
+ out:
+ pfile->state.va_args_ok = 0;
+ _cpp_unsave_parameters (pfile, nparms);
- return true;
+ return ok ? macro : NULL;
}
-/* Parse a macro and save its expansion. Returns nonzero on success. */
-bool
-_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
+cpp_macro *
+_cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind)
{
cpp_macro *macro;
- unsigned int i;
- bool ok;
if (pfile->hash_table->alloc_subobject)
macro = (cpp_macro *) pfile->hash_table->alloc_subobject
/* To suppress some diagnostics. */
macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0;
- if (CPP_OPTION (pfile, traditional))
- ok = _cpp_create_trad_definition (pfile, macro);
- else
- {
- ok = create_iso_definition (pfile, macro);
-
- /* We set the type for SEEN_EOL() in directives.c.
+ macro->kind = kind;
- Longer term we should lex the whole line before coming here,
- and just copy the expansion. */
+ return macro;
+}
- /* Stop the lexer accepting __VA_ARGS__. */
- pfile->state.va_args_ok = 0;
- }
+/* Parse a macro and save its expansion. Returns nonzero on success. */
+bool
+_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
+{
+ cpp_macro *macro;
- /* Clear the fast argument lookup indices. */
- for (i = macro->paramc; i-- > 0; )
- {
- struct macro_arg_saved_data *save =
- &((struct macro_arg_saved_data *) pfile->macro_buffer)[i];
- struct cpp_hashnode *node = save->canonical_node;
- node->flags &= ~ NODE_MACRO_ARG;
- node->value = save->value;
- }
+ if (CPP_OPTION (pfile, traditional))
+ macro = _cpp_create_trad_definition (pfile);
+ else
+ macro = create_iso_definition (pfile);
- if (!ok)
- return ok;
+ if (!macro)
+ return false;
if (node->type == NT_MACRO)
{
conditional flag */
node->flags &= ~NODE_CONDITIONAL;
- return ok;
+ return true;
}
/* Warn if a token in STRING matches one of a function-like MACRO's
static const uchar *copy_comment (cpp_reader *, const uchar *, int);
static void check_output_buffer (cpp_reader *, size_t);
static void push_replacement_text (cpp_reader *, cpp_hashnode *);
-static bool scan_parameters (cpp_reader *, cpp_macro *);
+static bool scan_parameters (cpp_reader *, unsigned *);
static bool recursive_macro (cpp_reader *, cpp_hashnode *);
static void save_replacement_text (cpp_reader *, cpp_macro *, unsigned int);
static void maybe_start_funlike (cpp_reader *, cpp_hashnode *, const uchar *,
duplicate parameter). On success, CUR (pfile->context) is just
past the closing parenthesis. */
static bool
-scan_parameters (cpp_reader *pfile, cpp_macro *macro)
+scan_parameters (cpp_reader *pfile, unsigned *n_ptr)
{
const uchar *cur = CUR (pfile->context) + 1;
bool ok;
break;
}
- macro->paramc = nparms;
+ *n_ptr = nparms;
if (!ok)
cpp_error (pfile, CPP_DL_ERROR, "syntax error in macro parameter list");
/* Analyze and save the replacement text of a macro. Returns true on
success. */
-bool
-_cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
+cpp_macro *
+_cpp_create_trad_definition (cpp_reader *pfile)
{
+ cpp_macro *macro = _cpp_new_macro (pfile, cmk_traditional);
const uchar *cur;
uchar *limit;
cpp_context *context = pfile->context;
+ unsigned nparms = 0;
/* The context has not been set up for command line defines, and CUR
has not been updated for the macro name for in-file defines. */
/* Is this a function-like macro? */
if (* CUR (context) == '(')
{
- bool ok = scan_parameters (pfile, macro);
-
- /* Remember the params so we can clear NODE_MACRO_ARG flags. */
- macro->parm.params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
-
- /* Setting macro to NULL indicates an error occurred, and
- prevents unnecessary work in _cpp_scan_out_logical_line. */
- if (!ok)
- macro = NULL;
- else
+ if (scan_parameters (pfile, &nparms))
{
+ macro->paramc = nparms;
+ macro->parm.params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
BUFF_FRONT (pfile->a_buff)
= (uchar *) ¯o->parm.params[macro->paramc];
macro->fun_like = 1;
}
+ else
+ macro = NULL;
}
/* Skip leading whitespace in the replacement text. */
_cpp_scan_out_logical_line (pfile, macro, false);
pfile->state.prevent_expansion--;
- if (!macro)
- return false;
+ _cpp_unsave_parameters (pfile, nparms);
- /* Skip trailing white space. */
- cur = pfile->out.base;
- limit = pfile->out.cur;
- while (limit > cur && is_space (limit[-1]))
- limit--;
- pfile->out.cur = limit;
- save_replacement_text (pfile, macro, 0);
+ if (macro)
+ {
+ /* Skip trailing white space. */
+ cur = pfile->out.base;
+ limit = pfile->out.cur;
+ while (limit > cur && is_space (limit[-1]))
+ limit--;
+ pfile->out.cur = limit;
+ save_replacement_text (pfile, macro, 0);
+ }
- return true;
+ return macro;
}
/* Copy SRC of length LEN to DEST, but convert all contiguous