mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-07 14:57:21 +08:00
cpptrad.c (struct block, [...]): New.
* cpptrad.c (struct block, BLOCK_HEADER_LEN, BLOCK_LEN, scan_parameters, save_replacement_text, replacement_length): New. (scan_out_logical_line): Take a macro and save parameters if non-NULL. (_cpp_logical_line_trad): Update. (_cpp_create_trad_definition): Update to handle function-like macros. * cpplex.c (new_buff): Update. (struct dummy, DEFAULT_ALIGNMENT, CPP_ALIGN): Move... * cpphash.h: ...here. (CPP_ALIGN2, _cpp_save_parameter): New. * cppmacro.c (save_parameter): Rename, export. (parse_params): Update. From-SVN: r54331
This commit is contained in:
parent
aec2ac46a7
commit
c70f6ed314
@ -1,3 +1,19 @@
|
||||
2002-06-07 Neil Booth <neil@daikokuya.demon.co.uk>
|
||||
|
||||
* cpptrad.c (struct block, BLOCK_HEADER_LEN, BLOCK_LEN,
|
||||
scan_parameters, save_replacement_text, replacement_length): New.
|
||||
(scan_out_logical_line): Take a macro and save parameters if
|
||||
non-NULL.
|
||||
(_cpp_logical_line_trad): Update.
|
||||
(_cpp_create_trad_definition): Update to handle function-like
|
||||
macros.
|
||||
* cpplex.c (new_buff): Update.
|
||||
(struct dummy, DEFAULT_ALIGNMENT, CPP_ALIGN): Move...
|
||||
* cpphash.h: ...here.
|
||||
(CPP_ALIGN2, _cpp_save_parameter): New.
|
||||
* cppmacro.c (save_parameter): Rename, export.
|
||||
(parse_params): Update.
|
||||
|
||||
2002-06-07 Andreas Jaeger <aj@suse.de>
|
||||
|
||||
* config/mmix/mmix.c: Remove extra broken prototype for
|
||||
|
@ -50,6 +50,21 @@ typedef unsigned char uchar;
|
||||
efficiency, and partly to limit runaway recursion. */
|
||||
#define CPP_STACK_MAX 200
|
||||
|
||||
/* Host alignment handling. */
|
||||
struct dummy
|
||||
{
|
||||
char c;
|
||||
union
|
||||
{
|
||||
double d;
|
||||
int *p;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define DEFAULT_ALIGNMENT offsetof (struct dummy, u)
|
||||
#define CPP_ALIGN2(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
|
||||
#define CPP_ALIGN(size) CPP_ALIGN2 (size, DEFAULT_ALIGNMENT)
|
||||
|
||||
/* Each macro definition is recorded in a cpp_macro structure.
|
||||
Variadic macros cannot occur with traditional cpp. */
|
||||
struct cpp_macro
|
||||
@ -428,7 +443,8 @@ extern bool _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *));
|
||||
extern void _cpp_pop_context PARAMS ((cpp_reader *));
|
||||
extern void _cpp_push_text_context PARAMS ((cpp_reader *, cpp_hashnode *,
|
||||
const uchar *, const uchar*));
|
||||
extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *));
|
||||
extern bool _cpp_save_parameter PARAMS ((cpp_reader *, cpp_macro *,
|
||||
cpp_hashnode *));
|
||||
|
||||
/* In cpphash.c */
|
||||
extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *));
|
||||
@ -483,6 +499,7 @@ extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *,
|
||||
size_t));
|
||||
extern cpp_hashnode *_cpp_lex_identifier_trad PARAMS ((cpp_reader *));
|
||||
extern void _cpp_set_trad_context PARAMS ((cpp_reader *));
|
||||
extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *));
|
||||
|
||||
/* Utility routines and macros. */
|
||||
#define DSC(str) (const uchar *)str, sizeof str - 1
|
||||
|
15
gcc/cpplex.c
15
gcc/cpplex.c
@ -2011,19 +2011,6 @@ cpp_interpret_charconst (pfile, token, pchars_seen, unsignedp)
|
||||
#error BUFF_SIZE_UPPER_BOUND must be at least as large as MIN_BUFF_SIZE!
|
||||
#endif
|
||||
|
||||
struct dummy
|
||||
{
|
||||
char c;
|
||||
union
|
||||
{
|
||||
double d;
|
||||
int *p;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define DEFAULT_ALIGNMENT (offsetof (struct dummy, u))
|
||||
#define CPP_ALIGN(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
/* Create a new allocation buffer. Place the control block at the end
|
||||
of the buffer, so that buffer overflows will cause immediate chaos. */
|
||||
static _cpp_buff *
|
||||
@ -2035,7 +2022,7 @@ new_buff (len)
|
||||
|
||||
if (len < MIN_BUFF_SIZE)
|
||||
len = MIN_BUFF_SIZE;
|
||||
len = CPP_ALIGN (len, DEFAULT_ALIGNMENT);
|
||||
len = CPP_ALIGN (len);
|
||||
|
||||
base = xmalloc (len + sizeof (_cpp_buff));
|
||||
result = (_cpp_buff *) (base + len);
|
||||
|
@ -70,7 +70,6 @@ static cpp_token *alloc_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
|
||||
static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
|
||||
static bool warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *,
|
||||
const cpp_macro *));
|
||||
static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *));
|
||||
static int parse_params PARAMS ((cpp_reader *, cpp_macro *));
|
||||
static void check_trad_stringification PARAMS ((cpp_reader *,
|
||||
const cpp_macro *,
|
||||
@ -1197,8 +1196,8 @@ _cpp_free_definition (h)
|
||||
|
||||
/* Save parameter NODE to the parameter list of macro MACRO. Returns
|
||||
zero on success, non-zero if the parameter is a duplicate. */
|
||||
static int
|
||||
save_parameter (pfile, macro, node)
|
||||
bool
|
||||
_cpp_save_parameter (pfile, macro, node)
|
||||
cpp_reader *pfile;
|
||||
cpp_macro *macro;
|
||||
cpp_hashnode *node;
|
||||
@ -1255,7 +1254,7 @@ parse_params (pfile, macro)
|
||||
}
|
||||
prev_ident = 1;
|
||||
|
||||
if (save_parameter (pfile, macro, token->val.node))
|
||||
if (_cpp_save_parameter (pfile, macro, token->val.node))
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
@ -1277,7 +1276,8 @@ parse_params (pfile, macro)
|
||||
macro->variadic = 1;
|
||||
if (!prev_ident)
|
||||
{
|
||||
save_parameter (pfile, macro, pfile->spec_nodes.n__VA_ARGS__);
|
||||
_cpp_save_parameter (pfile, macro,
|
||||
pfile->spec_nodes.n__VA_ARGS__);
|
||||
pfile->state.va_args_ok = 1;
|
||||
if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, pedantic))
|
||||
cpp_error (pfile, DL_PEDWARN,
|
||||
|
237
gcc/cpptrad.c
237
gcc/cpptrad.c
@ -21,6 +21,29 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#include "cpplib.h"
|
||||
#include "cpphash.h"
|
||||
|
||||
/* The replacement text of a function-like macro is stored as a
|
||||
contiguous sequence of aligned blocks. Each block represents the
|
||||
portion of text from the start of the previous block (or the start
|
||||
of the macro replacement text in the case of the first block) to
|
||||
the next parameter, or the end of the replacement list if there
|
||||
are none left.
|
||||
|
||||
Each block consists of an unsigned int, which is the length of text
|
||||
contained in the third part, an unsigned short, which is the
|
||||
one-based index of the argument that immediately follows that text,
|
||||
and the text itself. The final block in the macro expansion is
|
||||
recognizable as it has an argument index of zero. */
|
||||
|
||||
struct block
|
||||
{
|
||||
unsigned int text_len;
|
||||
unsigned short arg_index;
|
||||
uchar text[1];
|
||||
};
|
||||
|
||||
#define BLOCK_HEADER_LEN offsetof (struct block, text)
|
||||
#define BLOCK_LEN(TEXT_LEN) CPP_ALIGN (BLOCK_HEADER_LEN + TEXT_LEN)
|
||||
|
||||
/* Lexing TODO: Handle -C, maybe -CC, and space in escaped newlines.
|
||||
Stop cpplex.c from recognizing comments and directives during its
|
||||
lexing pass. Get rid of line_base usage - seems pointless? Do we
|
||||
@ -32,10 +55,14 @@ static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *,
|
||||
static const uchar *skip_whitespace PARAMS ((cpp_reader *, const uchar *));
|
||||
static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *));
|
||||
static const uchar *skip_comment PARAMS ((cpp_reader *, const uchar *));
|
||||
static void scan_out_logical_line PARAMS ((cpp_reader *pfile));
|
||||
static void scan_out_logical_line PARAMS ((cpp_reader *pfile, cpp_macro *));
|
||||
static void check_output_buffer PARAMS ((cpp_reader *, size_t));
|
||||
static void restore_buff PARAMS ((cpp_reader *));
|
||||
static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
|
||||
static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *));
|
||||
static void save_replacement_text PARAMS ((cpp_reader *, cpp_macro *,
|
||||
unsigned int));
|
||||
static unsigned int replacement_length PARAMS ((cpp_macro *));
|
||||
|
||||
/* Ensures we have N bytes' space in the output buffer, and
|
||||
reallocates it if not. */
|
||||
@ -272,7 +299,7 @@ _cpp_read_logical_line_trad (pfile)
|
||||
CUR (pfile->context) = buffer->cur;
|
||||
RLIMIT (pfile->context) = buffer->rlimit;
|
||||
pfile->trad_out_cur = pfile->trad_out_base;
|
||||
scan_out_logical_line (pfile);
|
||||
scan_out_logical_line (pfile, NULL);
|
||||
buffer->cur = CUR (pfile->context);
|
||||
|
||||
pfile->trad_line = pfile->line;
|
||||
@ -284,10 +311,15 @@ _cpp_read_logical_line_trad (pfile)
|
||||
|
||||
/* Copies the next logical line in the current buffer to the output
|
||||
buffer. The output is guaranteed to terminate with a NUL
|
||||
character. */
|
||||
character.
|
||||
|
||||
If MACRO is non-NULL, then we are scanning the replacement list of
|
||||
MACRO, and we call save_replacement_text every time we meet an
|
||||
argument. */
|
||||
static void
|
||||
scan_out_logical_line (pfile)
|
||||
scan_out_logical_line (pfile, macro)
|
||||
cpp_reader *pfile;
|
||||
cpp_macro *macro;
|
||||
{
|
||||
cpp_context *context;
|
||||
const uchar *cur;
|
||||
@ -379,21 +411,30 @@ scan_out_logical_line (pfile)
|
||||
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
||||
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
||||
case 'Y': case 'Z':
|
||||
{
|
||||
cpp_hashnode *node;
|
||||
if (quote == 0 || macro)
|
||||
{
|
||||
cpp_hashnode *node;
|
||||
|
||||
pfile->trad_out_cur = --out;
|
||||
node = lex_identifier (pfile, cur - 1);
|
||||
if (node->type == NT_MACRO)
|
||||
{
|
||||
/* Remove the macro name from the output. */
|
||||
pfile->trad_out_cur = out;
|
||||
push_replacement_text (pfile, node);
|
||||
goto new_context;
|
||||
}
|
||||
out = pfile->trad_out_cur;
|
||||
cur = CUR (context);
|
||||
}
|
||||
pfile->trad_out_cur = --out;
|
||||
node = lex_identifier (pfile, cur - 1);
|
||||
|
||||
if (node->type == NT_MACRO && !pfile->state.prevent_expansion)
|
||||
{
|
||||
/* Remove the macro name from the output. */
|
||||
pfile->trad_out_cur = out;
|
||||
push_replacement_text (pfile, node);
|
||||
goto new_context;
|
||||
}
|
||||
else if (macro && node->arg_index)
|
||||
{
|
||||
/* Remove the macro name from the output. */
|
||||
pfile->trad_out_cur = out;
|
||||
save_replacement_text (pfile, macro, node->arg_index);
|
||||
}
|
||||
|
||||
out = pfile->trad_out_cur;
|
||||
cur = CUR (context);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -417,36 +458,168 @@ push_replacement_text (pfile, node)
|
||||
macro->exp.text + macro->count);
|
||||
}
|
||||
|
||||
/* Analyze and save the replacement text of a macro. */
|
||||
/* Read and record the parameters, if any, of a function-like macro
|
||||
definition. Destroys pfile->trad_out_cur.
|
||||
|
||||
Returns true on success, false on failure (syntax error or a
|
||||
duplicate parameter). On success, CUR (pfile->context) is just
|
||||
past the closing parenthesis. */
|
||||
static bool
|
||||
scan_parameters (pfile, macro)
|
||||
cpp_reader *pfile;
|
||||
cpp_macro *macro;
|
||||
{
|
||||
const uchar *cur = CUR (pfile->context) + 1;
|
||||
bool ok;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
cur = skip_whitespace (pfile, cur);
|
||||
|
||||
if (ISIDST (*cur))
|
||||
{
|
||||
ok = false;
|
||||
if (_cpp_save_parameter (pfile, macro, lex_identifier (pfile, cur)))
|
||||
break;
|
||||
cur = skip_whitespace (pfile, CUR (pfile->context));
|
||||
if (*cur == ',')
|
||||
{
|
||||
cur++;
|
||||
continue;
|
||||
}
|
||||
ok = (*cur == ')');
|
||||
break;
|
||||
}
|
||||
|
||||
ok = (*cur == ')' && macro->paramc == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
CUR (pfile->context) = cur + (*cur == ')');
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Calculate the length of the replacement text of MACRO. */
|
||||
static unsigned int
|
||||
replacement_length (macro)
|
||||
cpp_macro *macro;
|
||||
{
|
||||
unsigned int result = 0;
|
||||
const uchar *exp = macro->exp.text;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
struct block *block = (struct block *) exp;
|
||||
|
||||
result += block->text_len;
|
||||
if (block->arg_index == 0)
|
||||
return result;
|
||||
exp += BLOCK_LEN (block->text_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the text from pfile->trad_out_base to pfile->trad_out_cur as
|
||||
the replacement text for the current macro, followed by argument
|
||||
ARG_INDEX, with zero indicating the end of the replacement
|
||||
text. */
|
||||
static void
|
||||
save_replacement_text (pfile, macro, arg_index)
|
||||
cpp_reader *pfile;
|
||||
cpp_macro *macro;
|
||||
unsigned int arg_index;
|
||||
{
|
||||
size_t len = pfile->trad_out_cur - pfile->trad_out_base;
|
||||
uchar *exp;
|
||||
|
||||
if (macro->paramc == 0)
|
||||
{
|
||||
/* Object-like and function-like macros without parameters
|
||||
simply store their NUL-terminated replacement text. */
|
||||
exp = _cpp_unaligned_alloc (pfile, len + 1);
|
||||
memcpy (exp, pfile->trad_out_base, len);
|
||||
exp[len] = '\0';
|
||||
macro->exp.text = exp;
|
||||
macro->count = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Store the text's length (unsigned int), the argument index
|
||||
(unsigned short, base 1) and then the text. */
|
||||
size_t blen = BLOCK_LEN (len);
|
||||
struct block *block;
|
||||
|
||||
if (macro->count + blen > BUFF_ROOM (pfile->a_buff))
|
||||
_cpp_extend_buff (pfile, &pfile->a_buff, macro->count + blen);
|
||||
|
||||
exp = BUFF_FRONT (pfile->a_buff);
|
||||
block = (struct block *) (exp + macro->count);
|
||||
macro->exp.text = exp;
|
||||
|
||||
/* Write out the block information. */
|
||||
block->text_len = len;
|
||||
block->arg_index = arg_index;
|
||||
memcpy (block->text, pfile->trad_out_base, len);
|
||||
|
||||
/* Lex the rest into the start of the output buffer. */
|
||||
pfile->trad_out_cur = pfile->trad_out_base;
|
||||
|
||||
/* If this is the end of the macro, count up the bytes of text
|
||||
in the replacement list, excluding the parameter names, and
|
||||
save this in macro->count, else store the total bytes in the
|
||||
replacement text so far (including block headers). */
|
||||
if (arg_index == 0)
|
||||
macro->count = replacement_length (macro);
|
||||
else
|
||||
macro->count += blen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Analyze and save the replacement text of a macro. Returns true on
|
||||
success. */
|
||||
bool
|
||||
_cpp_create_trad_definition (pfile, macro)
|
||||
cpp_reader *pfile;
|
||||
cpp_macro *macro;
|
||||
{
|
||||
const uchar *cur, *limit;
|
||||
uchar *exp;
|
||||
size_t len;
|
||||
const uchar *cur;
|
||||
uchar *limit;
|
||||
|
||||
/* Skip leading whitespace now. */
|
||||
CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
|
||||
|
||||
/* Is this a function-like macro? */
|
||||
if (* CUR (pfile->context) == '(')
|
||||
{
|
||||
/* Setting macro to NULL indicates an error occurred. */
|
||||
if (!scan_parameters (pfile, macro))
|
||||
macro = NULL;
|
||||
else
|
||||
{
|
||||
/* Success. Commit the parameter array. */
|
||||
macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
|
||||
BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc];
|
||||
macro->fun_like = 1;
|
||||
}
|
||||
|
||||
CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
|
||||
}
|
||||
|
||||
pfile->trad_out_cur = pfile->trad_out_base;
|
||||
scan_out_logical_line (pfile);
|
||||
pfile->state.prevent_expansion++;
|
||||
scan_out_logical_line (pfile, macro);
|
||||
pfile->state.prevent_expansion--;
|
||||
|
||||
if (!macro)
|
||||
return false;
|
||||
|
||||
/* Skip trailing white space. */
|
||||
cur = pfile->trad_out_base;
|
||||
limit = pfile->trad_out_cur;
|
||||
while (limit > cur && is_space (limit[-1]))
|
||||
limit--;
|
||||
|
||||
len = (size_t) (limit - cur);
|
||||
exp = _cpp_unaligned_alloc (pfile, len + 1);
|
||||
memcpy (exp, cur, len);
|
||||
exp[len] = '\0';
|
||||
|
||||
macro->exp.text = exp;
|
||||
/* Include NUL. */
|
||||
macro->count = len;
|
||||
pfile->trad_out_cur = limit;
|
||||
save_replacement_text (pfile, macro, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user