cpphash.h (struct cpp_reader): Make date and time strings.
* cpphash.h (struct cpp_reader): Make date and time strings. (_cpp_builtin_macro_text, _cpp_copy_replacement_text, _cpp_replacement_text_len): New. * cppinit.c (cpp_create_reader): Update. (init_builtins): Register appropriate builtins for -traditional-cpp. * cppmacro.c (new_number_token): Remove. (_cpp_builtin_macro_text): New. (builtin_macro): Use it. (cpp_macro_definition): Update to handle traditional macros. * cppmain.c (cb_line_change): Don't do column positioning for traditional output. * cpptrad.c (enum ls): Rename ls_fun_macro to ls_fun_open. New state ls_fun_close. (skip_whitespace): Fix. (maybe_start_funlike): Don't set state.parsing_args. (scan_out_logical_line): Remove duplicate error. Use lex_state rather than state.parsing_args. (push_replacement_text): Handle builtins. (_cpp_replacement_text_len, _cpp_copy_replacement_text): New. From-SVN: r54771
This commit is contained in:
parent
9d7b4c5a4f
commit
278c466207
|
@ -1,3 +1,25 @@
|
|||
2002-06-19 Neil Booth <neil@daikokuya.co.uk>
|
||||
|
||||
* cpphash.h (struct cpp_reader): Make date and time strings.
|
||||
(_cpp_builtin_macro_text, _cpp_copy_replacement_text,
|
||||
_cpp_replacement_text_len): New.
|
||||
* cppinit.c (cpp_create_reader): Update.
|
||||
(init_builtins): Register appropriate builtins for -traditional-cpp.
|
||||
* cppmacro.c (new_number_token): Remove.
|
||||
(_cpp_builtin_macro_text): New.
|
||||
(builtin_macro): Use it.
|
||||
(cpp_macro_definition): Update to handle traditional macros.
|
||||
* cppmain.c (cb_line_change): Don't do column positioning for
|
||||
traditional output.
|
||||
* cpptrad.c (enum ls): Rename ls_fun_macro to ls_fun_open. New
|
||||
state ls_fun_close.
|
||||
(skip_whitespace): Fix.
|
||||
(maybe_start_funlike): Don't set state.parsing_args.
|
||||
(scan_out_logical_line): Remove duplicate error. Use lex_state
|
||||
rather than state.parsing_args.
|
||||
(push_replacement_text): Handle builtins.
|
||||
(_cpp_replacement_text_len, _cpp_copy_replacement_text): New.
|
||||
|
||||
2002-06-18 Hans-Peter Nilsson <hp@axis.com>
|
||||
Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
|
|
|
@ -370,9 +370,9 @@ struct cpp_reader
|
|||
for include files. (Altered as we get more of them.) */
|
||||
unsigned int max_include_len;
|
||||
|
||||
/* Date and time tokens. Calculated together if either is requested. */
|
||||
cpp_token date;
|
||||
cpp_token time;
|
||||
/* Date and time text. Calculated together if either is requested. */
|
||||
const uchar *date;
|
||||
const uchar *time;
|
||||
|
||||
/* EOF token, and a token forcing paste avoidance. */
|
||||
cpp_token avoid_paste;
|
||||
|
@ -475,7 +475,8 @@ extern bool _cpp_save_parameter PARAMS ((cpp_reader *, cpp_macro *,
|
|||
extern bool _cpp_arguments_ok PARAMS ((cpp_reader *, cpp_macro *,
|
||||
const cpp_hashnode *,
|
||||
unsigned int));
|
||||
|
||||
extern const uchar *_cpp_builtin_macro_text PARAMS ((cpp_reader *,
|
||||
cpp_hashnode *));
|
||||
/* In cpphash.c */
|
||||
extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *));
|
||||
extern void _cpp_destroy_hashtable PARAMS ((cpp_reader *));
|
||||
|
@ -532,6 +533,8 @@ extern void _cpp_set_trad_context PARAMS ((cpp_reader *));
|
|||
extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *));
|
||||
extern bool _cpp_expansions_different_trad PARAMS ((const cpp_macro *,
|
||||
const cpp_macro *));
|
||||
extern uchar *_cpp_copy_replacement_text PARAMS ((const cpp_macro *, uchar *));
|
||||
extern size_t _cpp_replacement_text_len PARAMS ((const cpp_macro *));
|
||||
|
||||
/* Utility routines and macros. */
|
||||
#define DSC(str) (const uchar *)str, sizeof str - 1
|
||||
|
|
|
@ -512,7 +512,6 @@ cpp_create_reader (lang)
|
|||
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
|
||||
|
||||
/* Set up static tokens. */
|
||||
pfile->date.type = CPP_EOF;
|
||||
pfile->avoid_paste.type = CPP_PADDING;
|
||||
pfile->avoid_paste.val.source = NULL;
|
||||
pfile->eof.type = CPP_EOF;
|
||||
|
@ -640,6 +639,8 @@ static const struct builtin builtin_array[] =
|
|||
B("__BASE_FILE__", BT_BASE_FILE),
|
||||
B("__LINE__", BT_SPECLINE),
|
||||
B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL),
|
||||
/* Keep builtins not used for -traditional-cpp at the end, and
|
||||
update init_builtins() if any more are added. */
|
||||
B("_Pragma", BT_PRAGMA),
|
||||
B("__STDC__", BT_STDC),
|
||||
};
|
||||
|
@ -684,10 +685,12 @@ init_builtins (pfile)
|
|||
cpp_reader *pfile;
|
||||
{
|
||||
const struct builtin *b;
|
||||
size_t n = ARRAY_SIZE (builtin_array);
|
||||
|
||||
for(b = builtin_array;
|
||||
b < (builtin_array + ARRAY_SIZE (builtin_array));
|
||||
b++)
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
n -= 2;
|
||||
|
||||
for(b = builtin_array; b < builtin_array + n; b++)
|
||||
{
|
||||
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
|
||||
hp->type = NT_MACRO;
|
||||
|
|
151
gcc/cppmacro.c
151
gcc/cppmacro.c
|
@ -54,7 +54,6 @@ static const cpp_token *padding_token
|
|||
static void expand_arg PARAMS ((cpp_reader *, macro_arg *));
|
||||
static const cpp_token *new_string_token PARAMS ((cpp_reader *, uchar *,
|
||||
unsigned int));
|
||||
static const cpp_token *new_number_token PARAMS ((cpp_reader *, unsigned int));
|
||||
static const cpp_token *stringify_arg PARAMS ((cpp_reader *, macro_arg *));
|
||||
static void paste_all_tokens PARAMS ((cpp_reader *, const cpp_token *));
|
||||
static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **,
|
||||
|
@ -93,24 +92,6 @@ new_string_token (pfile, text, len)
|
|||
return token;
|
||||
}
|
||||
|
||||
/* Allocates and returns a CPP_NUMBER token evaluating to NUMBER. */
|
||||
static const cpp_token *
|
||||
new_number_token (pfile, number)
|
||||
cpp_reader *pfile;
|
||||
unsigned int number;
|
||||
{
|
||||
cpp_token *token = _cpp_temp_token (pfile);
|
||||
/* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */
|
||||
unsigned char *buf = _cpp_unaligned_alloc (pfile, 21);
|
||||
|
||||
sprintf ((char *) buf, "%u", number);
|
||||
token->type = CPP_NUMBER;
|
||||
token->val.str.text = buf;
|
||||
token->val.str.len = ustrlen (buf);
|
||||
token->flags = 0;
|
||||
return token;
|
||||
}
|
||||
|
||||
static const char * const monthnames[] =
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
|
@ -121,19 +102,20 @@ static const char * const monthnames[] =
|
|||
on the context stack. Also handles _Pragma, for which no new token
|
||||
is created. Returns 1 if it generates a new token context, 0 to
|
||||
return the token to the caller. */
|
||||
static int
|
||||
builtin_macro (pfile, node)
|
||||
const uchar *
|
||||
_cpp_builtin_macro_text (pfile, node)
|
||||
cpp_reader *pfile;
|
||||
cpp_hashnode *node;
|
||||
{
|
||||
const cpp_token *result;
|
||||
const uchar *result = NULL;
|
||||
unsigned int number = 1;
|
||||
|
||||
switch (node->value.builtin)
|
||||
{
|
||||
default:
|
||||
cpp_error (pfile, DL_ICE, "invalid built-in macro \"%s\"",
|
||||
NODE_NAME (node));
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case BT_FILE:
|
||||
case BT_BASE_FILE:
|
||||
|
@ -149,10 +131,12 @@ builtin_macro (pfile, node)
|
|||
|
||||
name = map->to_file;
|
||||
len = strlen (name);
|
||||
buf = _cpp_unaligned_alloc (pfile, len * 4 + 1);
|
||||
len = cpp_quote_string (buf, (const unsigned char *) name, len) - buf;
|
||||
|
||||
result = new_string_token (pfile, buf, len);
|
||||
buf = _cpp_unaligned_alloc (pfile, len * 4 + 3);
|
||||
result = buf;
|
||||
*buf = '"';
|
||||
buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len);
|
||||
*buf++ = '"';
|
||||
*buf = '\0';
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -160,16 +144,18 @@ builtin_macro (pfile, node)
|
|||
/* The line map depth counts the primary source as level 1, but
|
||||
historically __INCLUDE_DEPTH__ has called the primary source
|
||||
level 0. */
|
||||
result = new_number_token (pfile, pfile->line_maps.depth - 1);
|
||||
number = pfile->line_maps.depth - 1;
|
||||
break;
|
||||
|
||||
case BT_SPECLINE:
|
||||
/* If __LINE__ is embedded in a macro, it must expand to the
|
||||
line of the macro's invocation, not its definition.
|
||||
Otherwise things like assert() will not work properly. */
|
||||
result = new_number_token (pfile,
|
||||
SOURCE_LINE (pfile->map,
|
||||
pfile->cur_token[-1].line));
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
number = pfile->line;
|
||||
else
|
||||
number = pfile->cur_token[-1].line;
|
||||
number = SOURCE_LINE (pfile->map, number);
|
||||
break;
|
||||
|
||||
/* __STDC__ has the value 1 under normal circumstances.
|
||||
|
@ -179,23 +165,20 @@ builtin_macro (pfile, node)
|
|||
value 0. */
|
||||
case BT_STDC:
|
||||
{
|
||||
int stdc;
|
||||
enum c_lang lang = CPP_OPTION (pfile, lang);
|
||||
if (CPP_IN_SYSTEM_HEADER (pfile)
|
||||
&& CPP_OPTION (pfile, stdc_0_in_system_headers)
|
||||
&& !(lang == CLK_STDC89 || lang == CLK_STDC94
|
||||
|| lang == CLK_STDC99)) /* || lang == CLK_CXX98 ? */
|
||||
stdc = 0;
|
||||
number = 0;
|
||||
else
|
||||
stdc = 1;
|
||||
|
||||
result = new_number_token (pfile, stdc);
|
||||
number = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case BT_DATE:
|
||||
case BT_TIME:
|
||||
if (pfile->date.type == CPP_EOF)
|
||||
if (pfile->date == NULL)
|
||||
{
|
||||
/* Allocate __DATE__ and __TIME__ strings from permanent
|
||||
storage. We only do this once, and don't generate them
|
||||
|
@ -204,30 +187,46 @@ builtin_macro (pfile, node)
|
|||
time_t tt = time (NULL);
|
||||
struct tm *tb = localtime (&tt);
|
||||
|
||||
pfile->date.val.str.text =
|
||||
_cpp_unaligned_alloc (pfile, sizeof ("Oct 11 1347"));
|
||||
pfile->date.val.str.len = sizeof ("Oct 11 1347") - 1;
|
||||
pfile->date.type = CPP_STRING;
|
||||
pfile->date.flags = 0;
|
||||
sprintf ((char *) pfile->date.val.str.text, "%s %2d %4d",
|
||||
pfile->date = _cpp_unaligned_alloc (pfile,
|
||||
sizeof ("\"Oct 11 1347\""));
|
||||
sprintf ((char *) pfile->date, "\"%s %2d %4d\"",
|
||||
monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900);
|
||||
|
||||
pfile->time.val.str.text =
|
||||
_cpp_unaligned_alloc (pfile, sizeof ("12:34:56"));
|
||||
pfile->time.val.str.len = sizeof ("12:34:56") - 1;
|
||||
pfile->time.type = CPP_STRING;
|
||||
pfile->time.flags = 0;
|
||||
sprintf ((char *) pfile->time.val.str.text, "%02d:%02d:%02d",
|
||||
pfile->time = _cpp_unaligned_alloc (pfile, sizeof ("\"12:34:56\""));
|
||||
sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"",
|
||||
tb->tm_hour, tb->tm_min, tb->tm_sec);
|
||||
}
|
||||
|
||||
if (node->value.builtin == BT_DATE)
|
||||
result = &pfile->date;
|
||||
result = pfile->date;
|
||||
else
|
||||
result = &pfile->time;
|
||||
result = pfile->time;
|
||||
break;
|
||||
}
|
||||
|
||||
case BT_PRAGMA:
|
||||
if (result == NULL)
|
||||
{
|
||||
/* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */
|
||||
result = _cpp_unaligned_alloc (pfile, 21);
|
||||
sprintf ((char *) result, "%u", number);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Convert builtin macros like __FILE__ to a token and push it on the
|
||||
context stack. Also handles _Pragma, for which no new token is
|
||||
created. Returns 1 if it generates a new token context, 0 to
|
||||
return the token to the caller. */
|
||||
static int
|
||||
builtin_macro (pfile, node)
|
||||
cpp_reader *pfile;
|
||||
cpp_hashnode *node;
|
||||
{
|
||||
const uchar *buf;
|
||||
|
||||
if (node->value.builtin == BT_PRAGMA)
|
||||
{
|
||||
/* Don't interpret _Pragma within directives. The standard is
|
||||
not clear on this, but to me this makes most sense. */
|
||||
if (pfile->state.in_directive)
|
||||
|
@ -237,7 +236,24 @@ builtin_macro (pfile, node)
|
|||
return 1;
|
||||
}
|
||||
|
||||
push_token_context (pfile, NULL, result, 1);
|
||||
buf = _cpp_builtin_macro_text (pfile, node);
|
||||
|
||||
cpp_push_buffer (pfile, buf, ustrlen (buf), /* from_stage3 */ true, 1);
|
||||
|
||||
/* Tweak the column number the lexer will report. */
|
||||
pfile->buffer->col_adjust = pfile->cur_token[-1].col - 1;
|
||||
|
||||
/* We don't want a leading # to be interpreted as a directive. */
|
||||
pfile->buffer->saved_flags = 0;
|
||||
|
||||
/* Set pfile->cur_token as required by _cpp_lex_direct. */
|
||||
pfile->cur_token = _cpp_temp_token (pfile);
|
||||
push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
|
||||
if (pfile->buffer->cur != pfile->buffer->rlimit)
|
||||
cpp_error (pfile, DL_ICE, "invalid built-in macro \"%s\"",
|
||||
NODE_NAME (node));
|
||||
_cpp_pop_buffer (pfile);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1598,18 +1614,23 @@ cpp_macro_definition (pfile, node)
|
|||
len += NODE_LEN (macro->params[i]) + 1; /* "," */
|
||||
}
|
||||
|
||||
for (i = 0; i < macro->count; i++)
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
len += _cpp_replacement_text_len (macro);
|
||||
else
|
||||
{
|
||||
cpp_token *token = ¯o->exp.tokens[i];
|
||||
for (i = 0; i < macro->count; i++)
|
||||
{
|
||||
cpp_token *token = ¯o->exp.tokens[i];
|
||||
|
||||
if (token->type == CPP_MACRO_ARG)
|
||||
len += NODE_LEN (macro->params[token->val.arg_no - 1]);
|
||||
else
|
||||
len += cpp_token_len (token); /* Includes room for ' '. */
|
||||
if (token->flags & STRINGIFY_ARG)
|
||||
len++; /* "#" */
|
||||
if (token->flags & PASTE_LEFT)
|
||||
len += 3; /* " ##" */
|
||||
if (token->type == CPP_MACRO_ARG)
|
||||
len += NODE_LEN (macro->params[token->val.arg_no - 1]);
|
||||
else
|
||||
len += cpp_token_len (token); /* Includes room for ' '. */
|
||||
if (token->flags & STRINGIFY_ARG)
|
||||
len++; /* "#" */
|
||||
if (token->flags & PASTE_LEFT)
|
||||
len += 3; /* " ##" */
|
||||
}
|
||||
}
|
||||
|
||||
if (len > pfile->macro_buffer_len)
|
||||
|
@ -1652,8 +1673,10 @@ cpp_macro_definition (pfile, node)
|
|||
definition is the empty string. */
|
||||
*buffer++ = ' ';
|
||||
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
buffer = _cpp_copy_replacement_text (macro, buffer);
|
||||
else if (macro->count)
|
||||
/* Expansion tokens. */
|
||||
if (macro->count)
|
||||
{
|
||||
for (i = 0; i < macro->count; i++)
|
||||
{
|
||||
|
|
|
@ -320,7 +320,6 @@ cb_line_change (pfile, token, parsing_args)
|
|||
return;
|
||||
|
||||
maybe_print_line (print.map, token->line);
|
||||
print.printed = 1;
|
||||
print.prev = 0;
|
||||
print.source = 0;
|
||||
|
||||
|
@ -329,12 +328,16 @@ cb_line_change (pfile, token, parsing_args)
|
|||
will provide a space if PREV_WHITE. Don't bother trying to
|
||||
reconstruct tabs; we can't get it right in general, and nothing
|
||||
ought to care. Some things do care; the fault lies with them. */
|
||||
if (token->col > 2)
|
||||
if (!CPP_OPTION (pfile, traditional))
|
||||
{
|
||||
unsigned int spaces = token->col - 2;
|
||||
print.printed = 1;
|
||||
if (token->col > 2)
|
||||
{
|
||||
unsigned int spaces = token->col - 2;
|
||||
|
||||
while (spaces--)
|
||||
putc (' ', print.outf);
|
||||
while (spaces--)
|
||||
putc (' ', print.outf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
132
gcc/cpptrad.c
132
gcc/cpptrad.c
|
@ -65,7 +65,8 @@ struct fun_macro
|
|||
|
||||
/* Lexing state. It is mostly used to prevent macro expansion. */
|
||||
enum ls {ls_none = 0, /* Normal state. */
|
||||
ls_fun_macro, /* When looking for '('. */
|
||||
ls_fun_open, /* When looking for '('. */
|
||||
ls_fun_close, /* When looking for ')'. */
|
||||
ls_defined, /* After defined. */
|
||||
ls_defined_close, /* Looking for ')' of defined(). */
|
||||
ls_hash, /* After # in preprocessor conditional. */
|
||||
|
@ -262,7 +263,7 @@ skip_whitespace (pfile, cur, skip_comments)
|
|||
if (is_nvspace (c) && c)
|
||||
continue;
|
||||
|
||||
if (!c && cur != RLIMIT (pfile->context))
|
||||
if (!c && cur - 1 != RLIMIT (pfile->context))
|
||||
continue;
|
||||
|
||||
if (*cur == '/' && skip_comments)
|
||||
|
@ -409,8 +410,6 @@ maybe_start_funlike (pfile, node, start, macro)
|
|||
macro->node = node;
|
||||
macro->offset = start - pfile->out.base;
|
||||
macro->argc = 0;
|
||||
|
||||
pfile->state.parsing_args = 1;
|
||||
}
|
||||
|
||||
/* Save the OFFSET of the start of the next argument to MACRO. */
|
||||
|
@ -485,19 +484,17 @@ scan_out_logical_line (pfile, macro)
|
|||
cur--;
|
||||
if (!pfile->buffer->from_stage3)
|
||||
cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
|
||||
if (pfile->state.parsing_args == 2)
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"unterminated argument list invoking macro \"%s\"",
|
||||
NODE_NAME (fmacro.node));
|
||||
pfile->line++;
|
||||
goto done;
|
||||
|
||||
case '\r': case '\n':
|
||||
cur = handle_newline (pfile, cur - 1);
|
||||
if (pfile->state.parsing_args == 2 && !pfile->state.in_directive)
|
||||
if ((lex_state == ls_fun_open || lex_state == ls_fun_close)
|
||||
&& !pfile->state.in_directive)
|
||||
{
|
||||
/* Newlines in arguments become a space. */
|
||||
out[-1] = ' ';
|
||||
if (lex_state == ls_fun_close)
|
||||
out[-1] = ' ';
|
||||
continue;
|
||||
}
|
||||
goto done;
|
||||
|
@ -578,14 +575,17 @@ scan_out_logical_line (pfile, macro)
|
|||
|
||||
if (node->type == NT_MACRO
|
||||
/* Should we expand for ls_answer? */
|
||||
&& lex_state == ls_none
|
||||
&& (lex_state == ls_none || lex_state == ls_fun_open)
|
||||
&& !pfile->state.prevent_expansion
|
||||
&& !recursive_macro (pfile, node))
|
||||
{
|
||||
if (node->value.macro->fun_like)
|
||||
/* Macros invalidate MI optimization. */
|
||||
pfile->mi_valid = false;
|
||||
if (! (node->flags & NODE_BUILTIN)
|
||||
&& node->value.macro->fun_like)
|
||||
{
|
||||
maybe_start_funlike (pfile, node, out_start, &fmacro);
|
||||
lex_state = ls_fun_macro;
|
||||
lex_state = ls_fun_open;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
@ -594,6 +594,7 @@ scan_out_logical_line (pfile, macro)
|
|||
output, and push its replacement text. */
|
||||
pfile->out.cur = out_start;
|
||||
push_replacement_text (pfile, node);
|
||||
lex_state = ls_none;
|
||||
goto new_context;
|
||||
}
|
||||
}
|
||||
|
@ -622,10 +623,9 @@ scan_out_logical_line (pfile, macro)
|
|||
if (quote == 0)
|
||||
{
|
||||
paren_depth++;
|
||||
if (lex_state == ls_fun_macro)
|
||||
if (lex_state == ls_fun_open)
|
||||
{
|
||||
lex_state = ls_none;
|
||||
pfile->state.parsing_args = 2;
|
||||
lex_state = ls_fun_close;
|
||||
paren_depth = 1;
|
||||
out = pfile->out.base + fmacro.offset;
|
||||
fmacro.args[0] = fmacro.offset;
|
||||
|
@ -638,7 +638,7 @@ scan_out_logical_line (pfile, macro)
|
|||
break;
|
||||
|
||||
case ',':
|
||||
if (quote == 0 && pfile->state.parsing_args == 2 && paren_depth == 1)
|
||||
if (quote == 0 && lex_state == ls_fun_close && paren_depth == 1)
|
||||
save_argument (&fmacro, out - pfile->out.base);
|
||||
break;
|
||||
|
||||
|
@ -646,11 +646,11 @@ scan_out_logical_line (pfile, macro)
|
|||
if (quote == 0)
|
||||
{
|
||||
paren_depth--;
|
||||
if (pfile->state.parsing_args == 2 && paren_depth == 0)
|
||||
if (lex_state == ls_fun_close && paren_depth == 0)
|
||||
{
|
||||
cpp_macro *m = fmacro.node->value.macro;
|
||||
|
||||
pfile->state.parsing_args = 0;
|
||||
lex_state = ls_none;
|
||||
save_argument (&fmacro, out - pfile->out.base);
|
||||
|
||||
/* A single zero-length argument is no argument. */
|
||||
|
@ -701,12 +701,9 @@ scan_out_logical_line (pfile, macro)
|
|||
|
||||
/* Some of these transitions of state are syntax errors. The
|
||||
ISO preprocessor will issue errors later. */
|
||||
if (lex_state == ls_fun_macro)
|
||||
{
|
||||
/* Missing '('. */
|
||||
lex_state = ls_none;
|
||||
pfile->state.parsing_args = 0;
|
||||
}
|
||||
if (lex_state == ls_fun_open)
|
||||
/* Missing '('. */
|
||||
lex_state = ls_none;
|
||||
else if (lex_state == ls_hash
|
||||
|| lex_state == ls_predicate
|
||||
|| lex_state == ls_defined)
|
||||
|
@ -722,11 +719,10 @@ scan_out_logical_line (pfile, macro)
|
|||
if (fmacro.buff)
|
||||
_cpp_release_buff (pfile, fmacro.buff);
|
||||
|
||||
if (pfile->state.parsing_args == 2)
|
||||
if (lex_state == ls_fun_close)
|
||||
cpp_error (pfile, DL_ERROR,
|
||||
"unterminated argument list invoking macro \"%s\"",
|
||||
NODE_NAME (fmacro.node));
|
||||
pfile->state.parsing_args = 0;
|
||||
}
|
||||
|
||||
/* Push a context holding the replacement text of the macro NODE on
|
||||
|
@ -737,9 +733,22 @@ push_replacement_text (pfile, node)
|
|||
cpp_reader *pfile;
|
||||
cpp_hashnode *node;
|
||||
{
|
||||
cpp_macro *macro = node->value.macro;
|
||||
size_t len;
|
||||
const uchar *text;
|
||||
|
||||
_cpp_push_text_context (pfile, node, macro->exp.text, macro->count);
|
||||
if (node->flags & NODE_BUILTIN)
|
||||
{
|
||||
text = _cpp_builtin_macro_text (pfile, node);
|
||||
len = ustrlen (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpp_macro *macro = node->value.macro;
|
||||
text = macro->exp.text;
|
||||
len = macro->count;
|
||||
}
|
||||
|
||||
_cpp_push_text_context (pfile, node, text, len);
|
||||
}
|
||||
|
||||
/* Returns TRUE if traditional macro recursion is detected. */
|
||||
|
@ -784,6 +793,71 @@ recursive_macro (pfile, node)
|
|||
return recursing;
|
||||
}
|
||||
|
||||
/* Return the length of the replacement text of a function-like or
|
||||
object-like non-builtin macro. */
|
||||
size_t
|
||||
_cpp_replacement_text_len (macro)
|
||||
const cpp_macro *macro;
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (macro->fun_like)
|
||||
{
|
||||
const uchar *exp;
|
||||
|
||||
for (exp = macro->exp.text;;)
|
||||
{
|
||||
struct block *b = (struct block *) exp;
|
||||
|
||||
len += b->text_len;
|
||||
if (b->arg_index == 0)
|
||||
break;
|
||||
len += NODE_LEN (macro->params[b->arg_index - 1]);
|
||||
exp += BLOCK_LEN (b->text_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
len = macro->count;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Copy the replacement text of MACRO to DEST, which must be of
|
||||
sufficient size. It is not NUL-terminated. The next character is
|
||||
returned. */
|
||||
uchar *
|
||||
_cpp_copy_replacement_text (macro, dest)
|
||||
const cpp_macro *macro;
|
||||
uchar *dest;
|
||||
{
|
||||
if (macro->fun_like)
|
||||
{
|
||||
const uchar *exp;
|
||||
|
||||
for (exp = macro->exp.text;;)
|
||||
{
|
||||
struct block *b = (struct block *) exp;
|
||||
cpp_hashnode *param;
|
||||
|
||||
memcpy (dest, b->text, b->text_len);
|
||||
dest += b->text_len;
|
||||
if (b->arg_index == 0)
|
||||
break;
|
||||
param = macro->params[b->arg_index - 1];
|
||||
memcpy (dest, NODE_NAME (param), NODE_LEN (param));
|
||||
dest += NODE_LEN (param);
|
||||
exp += BLOCK_LEN (b->text_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (dest, macro->exp.text, macro->count);
|
||||
dest += macro->count;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Push a context holding the replacement text of the macro NODE on
|
||||
the context stack. NODE is either object-like, or a function-like
|
||||
macro with no arguments. */
|
||||
|
|
Loading…
Reference in New Issue