summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>2002-06-07 06:26:32 +0000
committerneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>2002-06-07 06:26:32 +0000
commit198b48a003250a3678f6fa816a016a196e81e6bb (patch)
tree6aed42053a56ed0593bc263de6125d7efc67c493 /gcc
parentb177c3c29498a92c2ec45ef0f4daaeba896c20ba (diff)
downloadgcc-198b48a003250a3678f6fa816a016a196e81e6bb.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54331 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/cpphash.h19
-rw-r--r--gcc/cpplex.c15
-rw-r--r--gcc/cppmacro.c10
-rw-r--r--gcc/cpptrad.c239
5 files changed, 246 insertions, 53 deletions
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 <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
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 *) &macro->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;
}