From: Neil Booth Date: Fri, 7 Jun 2002 06:26:32 +0000 (+0000) Subject: cpptrad.c (struct block, [...]): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c70f6ed31478e27420d2038d09f3a343422db22f;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e1829472672..239331c174d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2002-06-07 Neil Booth + + * 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 * config/mmix/mmix.c: Remove extra broken prototype for diff --git a/gcc/cpphash.h b/gcc/cpphash.h index e508b80ddcf..38ba244769a 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -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 diff --git a/gcc/cpplex.c b/gcc/cpplex.c index 2baa3e00a02..0dd9d22ec65 100644 --- a/gcc/cpplex.c +++ b/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); diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index 0b1f0ffc9fe..5e954d457e0 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -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, diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c index 63972487333..3886b4522c7 100644 --- a/gcc/cpptrad.c +++ b/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; - - 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); - } + if (quote == 0 || macro) + { + cpp_hashnode *node; + + 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; }