aboutsummaryrefslogtreecommitdiff
path: root/gcc/cpphash.c
diff options
context:
space:
mode:
authorZack Weinberg <zack@gcc.gnu.org>2000-04-23 17:03:31 +0000
committerZack Weinberg <zack@gcc.gnu.org>2000-04-23 17:03:31 +0000
commitd9e0bd53b2da36f66fcd18b168b354612ef7f4df (patch)
treedce0dfebe9bc09562c88a4bc2be4eecd8f6147d6 /gcc/cpphash.c
parent3c8c10b8c691cd1f8111f4eaf50ff22beadc0088 (diff)
downloadgcc-d9e0bd53b2da36f66fcd18b168b354612ef7f4df.zip
gcc-d9e0bd53b2da36f66fcd18b168b354612ef7f4df.tar.gz
gcc-d9e0bd53b2da36f66fcd18b168b354612ef7f4df.tar.bz2
cpphash.h (struct definition): Move file, line, col members...
* cpphash.h (struct definition): Move file, line, col members... (struct hashnode): ... here. Also add 'disabled' flag. (enum node_type): Add T_VOID, T_XCONST, T_FMACRO, and T_IDENTITY. Remove T_DISABLED. Update prototypes. * cpphash.c (_cpp_dump_definition): Split out dump_DEFINITION. (collect_expansion): Split into collect_objlike_expansion and collect_funlike_expansion. (_cpp_macroexpand): Split out scan_arguments, stringify, and funlike_macroexpand. (_cpp_compare_defs): Rename compare_defs, make static. (_cpp_make_hashnode): Initialize hp->disabled. (macro_cleanup): Adjust for new token types. Clear m->disabled. (_cpp_create_definition): Move code here to determine what sort of macro it is, and code to check for redefinitions, from do_define. Implement a few simple cases without creating a full DEFINITION. (_cpp_macroexpand, special_symbol, _cpp_dump_definition): Handle the simple cases. (push_macro_expansion): Set buf->has_escapes and hp->disabled here. * cppinit.c (builtin_array): Change MCONST to XCONST everywhere. * cpplex.c (maybe_macroexpand): Handle IDENTITY macros here; fix check for disabled and function-like macros. * cpplib.c (do_define): Move most logic to _cpp_create_definition. (do_undef): Handle new special token types. From-SVN: r33355
Diffstat (limited to 'gcc/cpphash.c')
-rw-r--r--gcc/cpphash.c1226
1 files changed, 719 insertions, 507 deletions
diff --git a/gcc/cpphash.c b/gcc/cpphash.c
index 26d03fe..cc70465 100644
--- a/gcc/cpphash.c
+++ b/gcc/cpphash.c
@@ -34,14 +34,17 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static unsigned int hash_HASHNODE PARAMS ((const void *));
static int eq_HASHNODE PARAMS ((const void *, const void *));
static void del_HASHNODE PARAMS ((void *));
+static void dump_DEFINITION PARAMS ((cpp_reader *, DEFINITION *));
static int dump_hash_helper PARAMS ((void **, void *));
-static void push_macro_expansion PARAMS ((cpp_reader *,
- U_CHAR *, int, HASHNODE *));
+static void push_macro_expansion PARAMS ((cpp_reader *, const U_CHAR *,
+ int, HASHNODE *));
static int unsafe_chars PARAMS ((cpp_reader *, int, int));
static int macro_cleanup PARAMS ((cpp_buffer *, cpp_reader *));
static enum cpp_ttype macarg PARAMS ((cpp_reader *, int));
-static void special_symbol PARAMS ((HASHNODE *, cpp_reader *));
+static void special_symbol PARAMS ((cpp_reader *, HASHNODE *));
+static int compare_defs PARAMS ((cpp_reader *, DEFINITION *,
+ DEFINITION *));
/* Initial hash table size. (It can grow if necessary - see hashtab.c.) */
#define HASHSIZE 500
@@ -72,8 +75,11 @@ struct arglist
};
-static DEFINITION *collect_expansion PARAMS ((cpp_reader *, cpp_toklist *,
- struct arglist *, unsigned int));
+static DEFINITION *
+collect_objlike_expansion PARAMS ((cpp_reader *, cpp_toklist *));
+static DEFINITION *
+collect_funlike_expansion PARAMS ((cpp_reader *, cpp_toklist *,
+ struct arglist *, unsigned int));
static unsigned int collect_params PARAMS ((cpp_reader *, cpp_toklist *,
struct arglist *));
@@ -105,6 +111,12 @@ struct argdata
int stringified_length;
};
+static void scan_arguments PARAMS ((cpp_reader *, DEFINITION *,
+ struct argdata *, const U_CHAR *));
+static void stringify PARAMS ((cpp_reader *, struct argdata *));
+static void funlike_macroexpand PARAMS ((cpp_reader *, HASHNODE *,
+ struct argdata *));
+
/* Calculate hash of a string of length LEN. */
unsigned int
_cpp_calc_hash (str, len)
@@ -174,6 +186,7 @@ _cpp_make_hashnode (name, len, type, hash)
hp->length = len;
hp->name = p;
hp->hash = hash;
+ hp->disabled = 0;
memcpy (p, name, len);
p[len] = 0;
@@ -277,10 +290,13 @@ macro_cleanup (pbuf, pfile)
cpp_buffer *pbuf;
cpp_reader *pfile ATTRIBUTE_UNUSED;
{
- HASHNODE *macro = pbuf->macro;
- if (macro->type == T_DISABLED)
- macro->type = T_MACRO;
- if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
+ HASHNODE *m = pbuf->macro;
+
+ m->disabled = 0;
+ if (m->type == T_FMACRO && pbuf->buf != m->value.defn->expansion)
+ free ((PTR) pbuf->buf);
+ else if (m->type != T_MACRO && m->type != T_FMACRO && m->type != T_CONST
+ && m->type != T_MCONST && m->type != T_XCONST)
free ((PTR) pbuf->buf);
return 0;
}
@@ -398,16 +414,90 @@ trad_stringify (pfile, base, len, argc, argv, pat, endpat, last)
return last;
}
+/* Read a replacement list for an object-like macro, and build the
+ DEFINITION structure. LIST contains the replacement list,
+ beginning at 1. */
+static DEFINITION *
+collect_objlike_expansion (pfile, list)
+ cpp_reader *pfile;
+ cpp_toklist *list;
+{
+ DEFINITION *defn;
+ unsigned int i;
+ unsigned int start;
+ int last_was_paste = 0;
+ U_CHAR *exp;
+ size_t len;
-/* Read a replacement list for a macro, and build the DEFINITION
- structure. LIST contains the replacement list, beginning at
- REPLACEMENT. ARGLIST specifies the formal parameters to look for
- in the text of the definition. If ARGLIST is null, this is an
- object-like macro; if it points to an empty arglist, this is a
- function-like macro with no arguments. */
+ /* We copy the expansion text into the token_buffer, then out to
+ its proper home. */
+ start = CPP_WRITTEN (pfile);
+ CPP_PUTS (pfile, "\r ", 2);
+
+ for (i = 1; i < list->tokens_used; i++)
+ {
+ switch (list->tokens[i].type)
+ {
+ case CPP_POP:
+ case CPP_EOF:
+ cpp_ice (pfile, "EOF in collect_expansion");
+ /* fall through */
+ case CPP_VSPACE:
+ goto done;
+
+ case CPP_PASTE:
+ /* ## is not special if it appears right after another ##;
+ nor is it special if -traditional. */
+ if (last_was_paste || CPP_TRADITIONAL (pfile))
+ break;
+ if (i == 1)
+ cpp_error (pfile, "`##' at start of macro definition");
+
+ last_was_paste = 1;
+ continue;
+
+ default:;
+ }
+
+ if (i > 1 && !last_was_paste && (list->tokens[i].flags & HSPACE_BEFORE))
+ CPP_PUTC (pfile, ' ');
+
+ CPP_PUTS (pfile,
+ list->tokens[i].val.name.offset + list->namebuf,
+ list->tokens[i].val.name.len);
+ last_was_paste = 0;
+ }
+ done:
+
+ if (last_was_paste)
+ cpp_error (pfile, "`##' at end of macro definition");
+
+ CPP_PUTS (pfile, "\r ", 2);
+ len = CPP_WRITTEN (pfile) - start;
+ CPP_SET_WRITTEN (pfile, start);
+
+ exp = (U_CHAR *) xmalloc (len + 1);
+ memcpy (exp, pfile->token_buffer + start, len);
+ exp[len] = '\0';
+
+ defn = (DEFINITION *) xmalloc (sizeof (DEFINITION));
+ defn->length = len;
+ defn->expansion = exp;
+ defn->pattern = 0;
+ defn->rest_args = 0;
+ defn->argnames = 0;
+ defn->nargs = -1;
+
+ return defn;
+}
+
+/* Read a replacement list for a function-like macro, and build the
+ DEFINITION structure. LIST contains the replacement list,
+ beginning at REPLACEMENT. ARGLIST specifies the formal parameters
+ to look for in the text of the definition. */
static DEFINITION *
-collect_expansion (pfile, list, arglist, replacement)
+collect_funlike_expansion (pfile, list, arglist, replacement)
cpp_reader *pfile;
cpp_toklist *list;
struct arglist *arglist;
@@ -424,16 +514,8 @@ collect_expansion (pfile, list, arglist, replacement)
U_CHAR *tok, *exp;
enum { START = 0, NORM, ARG, STRIZE, PASTE } last_token = START;
- if (arglist)
- {
- argv = arglist->argv;
- argc = arglist->argc;
- }
- else
- {
- argv = 0;
- argc = 0;
- }
+ argv = arglist->argv;
+ argc = arglist->argc;
/* We copy the expansion text into the token_buffer, then out to
its proper home. */
@@ -455,12 +537,11 @@ collect_expansion (pfile, list, arglist, replacement)
goto done;
case CPP_HASH:
- /* # is not special in object-like macros. It is special in
- function-like macros with no args. (6.10.3.2 para 1.)
- However, it is not special after PASTE. (Implied by
- 6.10.3.3 para 4.) Nor is it special if -traditional. */
- if (arglist == NULL || last_token == PASTE
- || CPP_TRADITIONAL (pfile))
+ /* # is special in function-like macros with no args.
+ (6.10.3.2 para 1.) However, it is not special after
+ PASTE. (Implied by 6.10.3.3 para 4.) Nor is it special
+ if -traditional. */
+ if (last_token == PASTE || CPP_TRADITIONAL (pfile))
break;
last_token = STRIZE;
continue;
@@ -497,18 +578,20 @@ collect_expansion (pfile, list, arglist, replacement)
{
case CPP_STRING:
case CPP_CHAR:
- if (argc)
+ if (argc == 0)
+ goto norm;
+ if (CPP_TRADITIONAL (pfile))
+ {
+ last = trad_stringify (pfile, tok, len, argc, argv,
+ &pat, &endpat, last);
+ break;
+ }
+ else
{
- if (CPP_TRADITIONAL (pfile))
- {
- last = trad_stringify (pfile, tok, len, argc, argv,
- &pat, &endpat, last);
- break;
- }
if (CPP_WTRADITIONAL (pfile))
warn_trad_stringify (pfile, tok, len, argc, argv);
+ goto norm;
}
- goto norm;
case CPP_NAME:
for (j = 0; j < argc; j++)
@@ -521,9 +604,6 @@ collect_expansion (pfile, list, arglist, replacement)
norm:
if (last_token == STRIZE)
cpp_error (pfile, "# is not followed by a macro argument name");
- if (last_token != PASTE && last_token != START
- && (list->tokens[i].flags & HSPACE_BEFORE))
- CPP_PUTC (pfile, ' ');
CPP_PUTS (pfile, tok, len);
last_token = NORM;
}
@@ -563,19 +643,11 @@ collect_expansion (pfile, list, arglist, replacement)
defn->length = len;
defn->expansion = exp;
defn->pattern = pat;
- defn->rest_args = argv && argv[argc - 1].rest_arg;
- if (arglist)
- {
- defn->nargs = argc;
- defn->argnames = arglist->namebuf;
- if (argv)
- free ((PTR) argv);
- }
- else
- {
- defn->nargs = -1;
- defn->argnames = 0;
- }
+ defn->rest_args = argc && argv[argc - 1].rest_arg;
+ defn->nargs = argc;
+ defn->argnames = arglist->namebuf;
+ if (argv)
+ free ((PTR) argv);
return defn;
}
@@ -745,31 +817,134 @@ collect_params (pfile, list, arglist)
(including formal parameters if present) is in LIST. If FUNLIKE is
true, this is a function-like macro. */
-DEFINITION *
-_cpp_create_definition (pfile, list, funlike)
+int
+_cpp_create_definition (pfile, list, hp)
cpp_reader *pfile;
cpp_toklist *list;
- int funlike;
+ HASHNODE *hp;
{
- struct arglist args;
- DEFINITION *defn;
- int replacement = 1; /* replacement begins at this token */
+ DEFINITION *defn = 0;
+ U_CHAR *cpval = 0;
+ enum node_type ntype;
+ int ok;
+
+ /* Special-case a few simple and common idioms:
+ #define TOKEN // nothing
+ #define TOKEN TOKEN
+ #define TOKEN OTHERTOKEN
+
+ Might also be good to special-case these:
+
+ #define FUNC() // nothing
+ #define FUNC(a, b, ...) // nothing
+ #define FUNC(a, b, c) FUNC(a, b, c)
+ #define FUNC(a, b, c) foobar(a, b, c) */
+
+ if (list->tokens_used == 2)
+ ntype = T_EMPTY; /* Empty definition of object-like macro. */
+ else if (list->tokens_used == 3 && list->tokens[1].type == CPP_NAME)
+ {
+ if (list->tokens[0].val.name.len == list->tokens[1].val.name.len
+ && !strncmp (list->tokens[0].val.name.offset + list->namebuf,
+ list->tokens[1].val.name.offset + list->namebuf,
+ list->tokens[0].val.name.len))
+ ntype = T_IDENTITY;
+ else
+ {
+ ntype = T_MCONST;
+ cpval = xmalloc (list->tokens[1].val.name.len + 1);
+ memcpy (cpval, list->tokens[1].val.name.offset + list->namebuf,
+ list->tokens[1].val.name.len);
+ cpval[list->tokens[1].val.name.len] = '\0';
+ }
+ }
- if (funlike)
+ /* The macro is function-like only if the next character,
+ with no intervening whitespace, is '('. */
+ else if (list->tokens[1].type == CPP_OPEN_PAREN
+ && ! (list->tokens[1].flags & HSPACE_BEFORE))
{
+ struct arglist args;
+ int replacement;
+
replacement = collect_params (pfile, list, &args);
if (replacement == 0)
return 0;
+ defn = collect_funlike_expansion (pfile, list, &args, replacement);
+ if (defn == 0)
+ return 0;
+
+ ntype = T_FMACRO;
}
- defn = collect_expansion (pfile, list, funlike ? &args : 0, replacement);
- if (defn == 0)
- return 0;
+ /* Otherwise it is an object-like macro, and C99 requires
+ whitespace after the name (6.10.3 para 3). */
+ else
+ {
+ if (! (list->tokens[1].flags & CPP_OPEN_PAREN))
+ cpp_pedwarn (pfile,
+ "The C standard requires whitespace after #define %s",
+ hp->name);
- defn->file = CPP_BUFFER (pfile)->nominal_fname;
- defn->line = list->line;
- defn->col = list->tokens[0].col;
- return defn;
+ defn = collect_objlike_expansion (pfile, list);
+ if (defn == 0)
+ return 0;
+
+ ntype = T_MACRO;
+ }
+
+ /* Check for a redefinition, and its legality. Redefining a macro
+ of whatever stripe is ok if the definitions are the same.
+ Redefining a built-in _constant_ (T_CONST or T_XCONST) is ok only
+ with -D. Otherwise a redefinition is not ok. */
+
+ switch (hp->type)
+ {
+ case T_VOID: ok = 1; break;
+ default: ok = 0; break;
+
+ case T_MACRO: case T_FMACRO:
+ ok = (ntype == hp->type && !compare_defs (pfile, defn, hp->value.defn));
+ break;
+ case T_IDENTITY:
+ case T_EMPTY:
+ ok = (ntype == hp->type);
+ break;
+ case T_MCONST:
+ ok = (ntype == hp->type && !strcmp (cpval, hp->value.cpval));
+ break;
+ case T_CONST:
+ case T_XCONST:
+ ok = ! pfile->done_initializing;
+ break;
+ }
+
+ /* Print the warning or error if it's not ok. */
+ if (! ok)
+ {
+ cpp_pedwarn (pfile, "\"%s\" redefined", hp->name);
+ if (pfile->done_initializing)
+ cpp_pedwarn_with_file_and_line (pfile, hp->file, hp->line, hp->col,
+ "this is the location of the previous definition");
+ }
+
+ /* And replace the old definition (if any). */
+
+ if (hp->type == T_MACRO || hp->type == T_FMACRO)
+ _cpp_free_definition (hp->value.defn);
+ else if (hp->type == T_MCONST || hp->type == T_XCONST)
+ free ((PTR) hp->value.cpval);
+
+ if (ntype == T_MACRO || ntype == T_FMACRO)
+ hp->value.defn = defn;
+ else
+ hp->value.cpval = cpval;
+
+ hp->type = ntype;
+ hp->file = CPP_BUFFER (pfile)->nominal_fname;
+ hp->line = list->line;
+ hp->col = list->tokens[0].col;
+ return 1;
}
/*
@@ -874,9 +1049,9 @@ _cpp_quote_string (pfile, src)
#define DSC(str) (const U_CHAR *)str, sizeof str - 1
static void
-special_symbol (hp, pfile)
- HASHNODE *hp;
+special_symbol (pfile, hp)
cpp_reader *pfile;
+ HASHNODE *hp;
{
const char *buf;
cpp_buffer *ip;
@@ -929,6 +1104,7 @@ special_symbol (hp, pfile)
/* else fall through */
case T_CONST:
case T_MCONST:
+ case T_XCONST:
constant:
buf = hp->value.cpval;
if (!buf)
@@ -1005,430 +1181,429 @@ _cpp_macroexpand (pfile, hp)
cpp_reader *pfile;
HASHNODE *hp;
{
- int nargs;
DEFINITION *defn;
- register U_CHAR *xbuf;
- unsigned int start_line, start_column;
- cpp_buffer *ip;
- int xbuf_len;
- struct argdata *args = 0;
- long old_written = CPP_WRITTEN (pfile);
- int rest_args, rest_zero = 0;
- register int i;
+ struct argdata *args;
+ unsigned int old_written;
+ int i;
- ip = cpp_file_buffer (pfile);
- if (ip)
+ /* Object like macro - most common case. */
+ if (hp->type == T_MACRO)
{
- start_line = CPP_BUF_LINE (ip);
- start_column = CPP_BUF_COL (ip);
+ push_macro_expansion (pfile, hp->value.defn->expansion,
+ hp->value.defn->length, hp);
+ return;
+ }
+
+ /* Or might it be a constant string? */
+ if (hp->type == T_MCONST || hp->type == T_CONST || hp->type == T_XCONST)
+ {
+ const U_CHAR *cpval = hp->value.cpval;
+ if (!cpval || *cpval == '\0')
+ cpval = (const U_CHAR *) "\r \r ";
+ push_macro_expansion (pfile, cpval, strlen (cpval), hp);
+ return;
}
- else
- start_line = start_column = 0;
- /* Check for and handle special symbols. */
- if (hp->type != T_MACRO)
+ /* Or a special symbol? */
+ if (hp->type != T_FMACRO)
{
- special_symbol (hp, pfile);
- xbuf_len = CPP_WRITTEN (pfile) - old_written;
- xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
+ U_CHAR *xbuf;
+ unsigned int len, old_written = CPP_WRITTEN (pfile);
+
+ special_symbol (pfile, hp);
+ len = CPP_WRITTEN (pfile) - old_written;
CPP_SET_WRITTEN (pfile, old_written);
- memcpy (xbuf, CPP_PWRITTEN (pfile), xbuf_len + 1);
- push_macro_expansion (pfile, xbuf, xbuf_len, hp);
- CPP_BUFFER (pfile)->has_escapes = 1;
+ xbuf = (U_CHAR *) xmalloc (len + 1);
+ memcpy (xbuf, CPP_PWRITTEN (pfile), len);
+ xbuf[len] = '\0';
+ push_macro_expansion (pfile, xbuf, len, hp);
return;
}
+ /* Okay, it's a full-on function-like macro... */
+ old_written = CPP_WRITTEN (pfile);
defn = hp->value.defn;
- nargs = defn->nargs;
+
+ args = alloca (MAX (defn->nargs, 1) * sizeof (struct argdata));
+ for (i = 0; i < MAX (defn->nargs, 1); i++)
+ {
+ args[i].raw = args[i].expanded = 0;
+ args[i].raw_length = 0;
+ args[i].expand_length = args[i].stringified_length = -1;
+ }
+
pfile->output_escapes++;
+ scan_arguments (pfile, defn, args, hp->name);
- if (nargs >= 0)
+ /* If macro wants zero args, we parsed the arglist for checking only.
+ Read directly from the macro definition. */
+ if (defn->nargs == 0 || defn->pattern == 0)
{
- enum cpp_ttype token;
+ CPP_SET_WRITTEN (pfile, old_written);
+ pfile->output_escapes--;
+ push_macro_expansion (pfile, defn->expansion, defn->length, hp);
+ return;
+ }
- args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
+ funlike_macroexpand (pfile, hp, args);
+ pfile->output_escapes--;
+}
- for (i = 0; i < nargs; i++)
- {
- args[i].raw = args[i].expanded = 0;
- args[i].raw_length = 0;
- args[i].expand_length = args[i].stringified_length = -1;
- }
+static void
+scan_arguments (pfile, defn, args, name)
+ cpp_reader *pfile;
+ DEFINITION *defn;
+ struct argdata *args;
+ const U_CHAR *name;
+{
+ enum cpp_ttype token;
+ unsigned int start_line, start_column;
+ unsigned int nargs = defn->nargs;
+ unsigned int i;
+
+ cpp_buffer *ip = cpp_file_buffer (pfile);
+ if (ip)
+ {
+ start_line = CPP_BUF_LINE (ip);
+ start_column = CPP_BUF_COL (ip);
+ }
+ else
+ start_line = start_column = 0;
- /* Parse all the macro args that are supplied. I counts them.
- The first NARGS args are stored in ARGS.
- The rest are discarded. If rest_args is set then we assume
- macarg absorbed the rest of the args. */
- i = 0;
- rest_args = 0;
-
- /* Skip over the opening parenthesis. */
- CPP_OPTION (pfile, discard_comments)++;
- pfile->no_macro_expand++;
- pfile->no_directives++;
-
- token = cpp_get_non_space_token (pfile);
- if (token != CPP_OPEN_PAREN)
- cpp_ice (pfile, "macroexpand: unexpected token %d (wanted LPAREN)",
- token);
- CPP_ADJUST_WRITTEN (pfile, -1);
-
- token = CPP_EOF;
- do
- {
- if (rest_args)
- continue;
- if (i < nargs || (nargs == 0 && i == 0))
- {
- /* if we are working on last arg which absorbs rest of args... */
- if (i == nargs - 1 && defn->rest_args)
- rest_args = 1;
- args[i].raw = CPP_WRITTEN (pfile);
- token = macarg (pfile, rest_args);
- args[i].raw_length = CPP_WRITTEN (pfile) - args[i].raw;
- }
- else
- token = macarg (pfile, 0);
- if (token == CPP_EOF || token == CPP_POP)
- cpp_error_with_line (pfile, start_line, start_column,
- "unterminated macro call");
- i++;
- }
- while (token == CPP_COMMA);
- CPP_OPTION (pfile, discard_comments)--;
- pfile->no_macro_expand--;
- pfile->no_directives--;
- if (token != CPP_CLOSE_PAREN)
- return;
+ /* Parse all the macro args that are supplied. I counts them. The
+ first NARGS args are stored in ARGS. The rest are discarded. If
+ rest_args is set then we assume macarg absorbed the rest of the
+ args. */
+ i = 0;
- /* foo ( ) is equivalent to foo () unless foo takes exactly one
- argument, in which case the former is allowed and the latter
- is not. XXX C99 is silent on this rule, but it seems
- inconsistent to me. */
- if (i == 1 && nargs != 1)
- {
- register U_CHAR *bp = ARG_BASE + args[0].raw;
- register U_CHAR *lim = bp + args[0].raw_length;
- while (bp != lim && is_space(*bp))
- bp++;
- if (bp == lim)
- i = 0;
- }
+ /* Skip over the opening parenthesis. */
+ CPP_OPTION (pfile, discard_comments)++;
+ pfile->no_macro_expand++;
+ pfile->no_directives++;
- /* Don't output an error message if we have already output one for
- a parse error above. */
- rest_zero = 0;
- if (nargs == 0 && i > 0)
- {
- cpp_error (pfile, "arguments given to macro `%s'", hp->name);
- }
- else if (i < nargs)
- {
- /* traditional C allows foo() if foo wants one argument. */
- if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile))
- ;
- /* the rest args token is allowed to absorb 0 tokens */
- else if (i == nargs - 1 && defn->rest_args)
- rest_zero = 1;
- else if (i == 0)
- cpp_error (pfile, "macro `%s' used without args", hp->name);
- else if (i == 1)
- cpp_error (pfile, "macro `%s' used with just one arg", hp->name);
- else
- cpp_error (pfile, "macro `%s' used with only %d args",
- hp->name, i);
- }
- else if (i > nargs)
+ token = cpp_get_non_space_token (pfile);
+ if (token != CPP_OPEN_PAREN)
+ cpp_ice (pfile, "macroexpand: unexpected token %d (wanted LPAREN)",
+ token);
+ CPP_ADJUST_WRITTEN (pfile, -1);
+
+ token = CPP_EOF;
+ do
+ {
+ if (i < MAX (nargs, 1))
{
- cpp_error (pfile,
- "macro `%s' used with too many (%d) args", hp->name, i);
+ args[i].raw = CPP_WRITTEN (pfile);
+ token = macarg (pfile, (i == nargs - 1 && defn->rest_args));
+ args[i].raw_length = CPP_WRITTEN (pfile) - args[i].raw;
}
+ else
+ token = macarg (pfile, 0);
+ if (token == CPP_EOF || token == CPP_POP)
+ cpp_error_with_line (pfile, start_line, start_column,
+ "unterminated macro call");
+ i++;
}
+ while (token == CPP_COMMA);
+ CPP_OPTION (pfile, discard_comments)--;
+ pfile->no_macro_expand--;
+ pfile->no_directives--;
+ if (token != CPP_CLOSE_PAREN)
+ return;
- /* If macro wants zero args, we parsed the arglist for checking only.
- Read directly from the macro definition. */
- if (nargs <= 0)
+ /* foo ( ) is equivalent to foo () unless foo takes exactly one
+ argument, in which case the former is allowed and the latter
+ is not. XXX C99 is silent on this rule, but it seems
+ inconsistent to me. */
+ if (i == 1 && nargs == 0)
{
- xbuf = defn->expansion;
- xbuf_len = defn->length;
+ register U_CHAR *bp = ARG_BASE + args[0].raw;
+ register U_CHAR *lim = bp + args[0].raw_length;
+ while (bp != lim && is_space(*bp))
+ bp++;
+ if (bp == lim)
+ i = 0;
}
- else
- {
- register U_CHAR *exp = defn->expansion;
- register int offset; /* offset in expansion,
- copied a piece at a time */
- register int totlen; /* total amount of exp buffer filled so far */
- register struct reflist *ap, *last_ap;
+ /* Don't output an error message if we have already output one for
+ a parse error above. */
+ if (nargs == 0 && i > 0)
+ {
+ cpp_error (pfile, "arguments given to macro `%s'", name);
+ }
+ else if (i < nargs)
+ {
+ /* traditional C allows foo() if foo wants one argument. */
+ if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile))
+ ;
+ /* the rest args token is allowed to absorb 0 tokens */
+ else if (i == nargs - 1 && defn->rest_args)
+ ;
+ else if (i == 0)
+ cpp_error (pfile, "macro `%s' used without args", name);
+ else if (i == 1)
+ cpp_error (pfile, "macro `%s' used with just one arg", name);
+ else
+ cpp_error (pfile, "macro `%s' used with only %d args", name, i);
+ }
+ else if (i > nargs)
+ {
+ cpp_error (pfile, "macro `%s' used with too many (%d) args", name, i);
+ }
+}
- /* Macro really takes args. Compute the expansion of this call. */
+static void
+stringify (pfile, arg)
+ cpp_reader *pfile;
+ struct argdata *arg;
+{
+ int arglen = arg->raw_length;
+ int escaped = 0;
+ int in_string = 0;
+ int c;
+ int i;
+ /* Initially need_space is -1. Otherwise, 1 means the previous
+ character was a space, but we suppressed it; 0 means the previous
+ character was a non-space. */
+ int need_space = -1;
+ i = 0;
+ arg->stringified = CPP_WRITTEN (pfile);
+ CPP_PUTC (pfile, '\"'); /* insert beginning quote */
+ for (; i < arglen; i++)
+ {
+ c = (ARG_BASE + arg->raw)[i];
- /* Compute length in characters of the macro's expansion.
- Also count number of times each arg is used. */
- xbuf_len = defn->length;
- for (ap = defn->pattern; ap != NULL; ap = ap->next)
+ if (!in_string)
{
- if (ap->stringify)
+ /* Delete "\r " and "\r-" escapes. */
+ if (c == '\r')
{
- register struct argdata *arg = &args[ap->argno];
- /* Stringify if it hasn't already been */
- if (arg->stringified_length < 0)
- {
- int arglen = arg->raw_length;
- int escaped = 0;
- int in_string = 0;
- int c;
- /* Initially need_space is -1. Otherwise, 1 means the
- previous character was a space, but we suppressed it;
- 0 means the previous character was a non-space. */
- int need_space = -1;
- i = 0;
- arg->stringified = CPP_WRITTEN (pfile);
- CPP_PUTC (pfile, '\"'); /* insert beginning quote */
- for (; i < arglen; i++)
- {
- c = (ARG_BASE + arg->raw)[i];
-
- if (!in_string)
- {
- /* Delete "\r " and "\r-" escapes. */
- if (c == '\r')
- {
- i++;
- continue;
- }
- /* Internal sequences of whitespace are
- replaced by one space except within
- a string or char token. */
- else if (is_space(c))
- {
- if (need_space == 0)
- need_space = 1;
- continue;
- }
- else if (need_space > 0)
- CPP_PUTC (pfile, ' ');
- need_space = 0;
- }
-
- if (escaped)
- escaped = 0;
- else
- {
- if (c == '\\')
- escaped = 1;
- if (in_string)
- {
- if (c == in_string)
- in_string = 0;
- }
- else if (c == '\"' || c == '\'')
- in_string = c;
- }
-
- /* Escape these chars */
- if (c == '\"' || (in_string && c == '\\'))
- CPP_PUTC (pfile, '\\');
- if (ISPRINT (c))
- CPP_PUTC (pfile, c);
- else
- {
- CPP_RESERVE (pfile, 4);
- sprintf ((char *) CPP_PWRITTEN (pfile), "\\%03o",
- (unsigned int) c);
- CPP_ADJUST_WRITTEN (pfile, 4);
- }
- }
- CPP_PUTC (pfile, '\"'); /* insert ending quote */
- arg->stringified_length
- = CPP_WRITTEN (pfile) - arg->stringified;
- }
- xbuf_len += args[ap->argno].stringified_length;
+ i++;
+ continue;
}
- else if (ap->raw_before || ap->raw_after)
- /* Add 4 for two \r-space markers to prevent
- token concatenation. */
- xbuf_len += args[ap->argno].raw_length + 4;
- else
+ /* Internal sequences of whitespace are replaced by one
+ space except within a string or char token. */
+ else if (is_space(c))
{
- /* We have an ordinary (expanded) occurrence of the arg.
- So compute its expansion, if we have not already. */
- if (args[ap->argno].expand_length < 0)
- {
- args[ap->argno].expanded = CPP_WRITTEN (pfile);
- _cpp_expand_to_buffer (pfile,
- ARG_BASE + args[ap->argno].raw,
- args[ap->argno].raw_length);
-
- args[ap->argno].expand_length
- = CPP_WRITTEN (pfile) - args[ap->argno].expanded;
- }
+ if (need_space == 0)
+ need_space = 1;
+ continue;
+ }
+ else if (need_space > 0)
+ CPP_PUTC (pfile, ' ');
+ need_space = 0;
+ }
- /* Add 4 for two \r-space markers to prevent
- token concatenation. */
- xbuf_len += args[ap->argno].expand_length + 4;
+ if (escaped)
+ escaped = 0;
+ else
+ {
+ if (c == '\\')
+ escaped = 1;
+ if (in_string)
+ {
+ if (c == in_string)
+ in_string = 0;
}
+ else if (c == '\"' || c == '\'')
+ in_string = c;
}
- xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
+ /* Escape these chars */
+ if (c == '\"' || (in_string && c == '\\'))
+ CPP_PUTC (pfile, '\\');
+ if (ISPRINT (c))
+ CPP_PUTC (pfile, c);
+ else
+ {
+ CPP_RESERVE (pfile, 4);
+ sprintf ((char *) CPP_PWRITTEN (pfile), "\\%03o", (unsigned int) c);
+ CPP_ADJUST_WRITTEN (pfile, 4);
+ }
+ }
+ CPP_PUTC (pfile, '\"'); /* insert ending quote */
+ arg->stringified_length = CPP_WRITTEN (pfile) - arg->stringified;
+}
- /* Generate in XBUF the complete expansion
- with arguments substituted in.
- TOTLEN is the total size generated so far.
- OFFSET is the index in the definition
- of where we are copying from. */
- offset = totlen = 0;
- for (last_ap = NULL, ap = defn->pattern; ap != NULL;
- last_ap = ap, ap = ap->next)
+static void
+funlike_macroexpand (pfile, hp, args)
+ cpp_reader *pfile;
+ HASHNODE *hp;
+ struct argdata *args;
+{
+ DEFINITION *defn = hp->value.defn;
+ register U_CHAR *xbuf;
+ int xbuf_len;
+ long old_written = CPP_WRITTEN (pfile);
+ U_CHAR *exp = defn->expansion;
+ int offset; /* offset in expansion, copied a piece at a time */
+ int totlen; /* total amount of exp buffer filled so far */
+ struct reflist *ap, *last_ap;
+ int i;
+
+ /* Compute length in characters of the macro's expansion.
+ Also count number of times each arg is used. */
+ xbuf_len = defn->length;
+ for (ap = defn->pattern; ap != NULL; ap = ap->next)
+ {
+ if (ap->stringify)
{
- register struct argdata *arg = &args[ap->argno];
- int count_before = totlen;
-
- /* Add chars to XBUF. */
- i = ap->nchars;
- memcpy (&xbuf[totlen], &exp[offset], i);
- totlen += i;
- offset += i;
-
- /* If followed by an empty rest arg with concatenation,
- delete the last run of nonwhite chars. */
- if (rest_zero && totlen > count_before
- && ((ap->rest_args && ap->raw_before)
- || (last_ap != NULL && last_ap->rest_args
- && last_ap->raw_after)))
+ /* Stringify if it hasn't already been */
+ if (args[ap->argno].stringified_length < 0)
+ stringify (pfile, &args[ap->argno]);
+ xbuf_len += args[ap->argno].stringified_length;
+ }
+ else if (ap->raw_before || ap->raw_after)
+ /* Add 4 for two \r-space markers to prevent
+ token concatenation. */
+ xbuf_len += args[ap->argno].raw_length + 4;
+ else
+ {
+ /* We have an ordinary (expanded) occurrence of the arg.
+ So compute its expansion, if we have not already. */
+ if (args[ap->argno].expand_length < 0)
{
- /* Delete final whitespace. */
- while (totlen > count_before && is_space(xbuf[totlen - 1]))
- totlen--;
+ args[ap->argno].expanded = CPP_WRITTEN (pfile);
+ _cpp_expand_to_buffer (pfile, ARG_BASE + args[ap->argno].raw,
+ args[ap->argno].raw_length);
- /* Delete the nonwhites before them. */
- while (totlen > count_before && !is_space(xbuf[totlen - 1]))
- totlen--;
+ args[ap->argno].expand_length
+ = CPP_WRITTEN (pfile) - args[ap->argno].expanded;
}
- if (ap->stringify != 0)
- {
- memcpy (xbuf + totlen, ARG_BASE + arg->stringified,
- arg->stringified_length);
- totlen += arg->stringified_length;
- }
- else if (ap->raw_before || ap->raw_after)
+ /* Add 4 for two \r-space markers to prevent
+ token concatenation. */
+ xbuf_len += args[ap->argno].expand_length + 4;
+ }
+ }
+
+ xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
+
+ /* Generate in XBUF the complete expansion with arguments
+ substituted in. TOTLEN is the total size generated so far.
+ OFFSET is the index in the definition of where we are copying
+ from. */
+ offset = totlen = 0;
+ for (last_ap = NULL, ap = defn->pattern; ap != NULL;
+ last_ap = ap, ap = ap->next)
+ {
+ register struct argdata *arg = &args[ap->argno];
+ int count_before = totlen;
+
+ /* Add chars to XBUF. */
+ i = ap->nchars;
+ memcpy (&xbuf[totlen], &exp[offset], i);
+ totlen += i;
+ offset += i;
+
+ /* If followed by an empty rest arg with concatenation,
+ delete the last run of nonwhite chars. */
+ if (arg->raw_length == 0 && totlen > count_before
+ && ((ap->rest_args && ap->raw_before)
+ || (last_ap != NULL && last_ap->rest_args
+ && last_ap->raw_after)))
+ {
+ /* Delete final whitespace. */
+ while (totlen > count_before && is_space(xbuf[totlen - 1]))
+ totlen--;
+
+ /* Delete the nonwhites before them. */
+ while (totlen > count_before && !is_space(xbuf[totlen - 1]))
+ totlen--;
+ }
+
+ if (ap->stringify != 0)
+ {
+ memcpy (xbuf + totlen, ARG_BASE + arg->stringified,
+ arg->stringified_length);
+ totlen += arg->stringified_length;
+ }
+ else if (ap->raw_before || ap->raw_after)
+ {
+ U_CHAR *p1 = ARG_BASE + arg->raw;
+ U_CHAR *l1 = p1 + arg->raw_length;
+ if (ap->raw_before)
{
- U_CHAR *p1 = ARG_BASE + arg->raw;
- U_CHAR *l1 = p1 + arg->raw_length;
- if (ap->raw_before)
+ /* Arg is concatenated before: delete leading whitespace,
+ whitespace markers, and no-reexpansion markers. */
+ while (p1 != l1)
{
- /* Arg is concatenated before: delete leading whitespace,
- whitespace markers, and no-reexpansion markers. */
- while (p1 != l1)
- {
- if (is_space(p1[0]))
- p1++;
- else if (p1[0] == '\r')
- p1 += 2;
- else
- break;
- }
+ if (is_space(p1[0]))
+ p1++;
+ else if (p1[0] == '\r')
+ p1 += 2;
+ else
+ break;
}
- if (ap->raw_after)
+ }
+ if (ap->raw_after)
+ {
+ /* Arg is concatenated after: delete trailing whitespace,
+ whitespace markers, and no-reexpansion markers. */
+ while (p1 != l1)
{
- /* Arg is concatenated after: delete trailing whitespace,
- whitespace markers, and no-reexpansion markers. */
- while (p1 != l1)
+ if (is_space(l1[-1]))
+ l1--;
+ else if (l1[-1] == '\r')
+ l1--;
+ else if (l1[-1] == '-')
{
- if (is_space(l1[-1]))
- l1--;
- else if (l1[-1] == '\r')
- l1--;
- else if (l1[-1] == '-')
- {
- if (l1 != p1 + 1 && l1[-2] == '\r')
- l1 -= 2;
- else
- break;
- }
+ if (l1 != p1 + 1 && l1[-2] == '\r')
+ l1 -= 2;
else
break;
}
+ else
+ break;
}
-
- /* Delete any no-reexpansion marker that precedes
- an identifier at the beginning of the argument. */
- if (p1[0] == '\r' && p1[1] == '-')
- p1 += 2;
-
- memcpy (xbuf + totlen, p1, l1 - p1);
- totlen += l1 - p1;
}
- else
- {
- U_CHAR *expanded = ARG_BASE + arg->expanded;
- if (!ap->raw_before && totlen > 0 && arg->expand_length
- && unsafe_chars (pfile, xbuf[totlen - 1], expanded[0]))
- {
- xbuf[totlen++] = '\r';
- xbuf[totlen++] = ' ';
- }
- memcpy (xbuf + totlen, expanded, arg->expand_length);
- totlen += arg->expand_length;
+ /* Delete any no-reexpansion marker that precedes
+ an identifier at the beginning of the argument. */
+ if (p1[0] == '\r' && p1[1] == '-')
+ p1 += 2;
- if (!ap->raw_after && totlen > 0 && offset < defn->length
- && unsafe_chars (pfile, xbuf[totlen - 1], exp[offset]))
- {
- xbuf[totlen++] = '\r';
- xbuf[totlen++] = ' ';
- }
- }
-
- if (totlen > xbuf_len)
+ memcpy (xbuf + totlen, p1, l1 - p1);
+ totlen += l1 - p1;
+ }
+ else
+ {
+ U_CHAR *expanded = ARG_BASE + arg->expanded;
+ if (!ap->raw_before && totlen > 0 && arg->expand_length
+ && unsafe_chars (pfile, xbuf[totlen - 1], expanded[0]))
{
- cpp_ice (pfile, "buffer overrun in macroexpand");
- return;
+ xbuf[totlen++] = '\r';
+ xbuf[totlen++] = ' ';
}
- }
- /* if there is anything left of the definition
- after handling the arg list, copy that in too. */
+ memcpy (xbuf + totlen, expanded, arg->expand_length);
+ totlen += arg->expand_length;
- for (i = offset; i < defn->length; i++)
- {
- /* if we've reached the end of the macro */
- if (exp[i] == ')')
- rest_zero = 0;
- if (!(rest_zero && last_ap != NULL && last_ap->rest_args
- && last_ap->raw_after))
- xbuf[totlen++] = exp[i];
+ if (!ap->raw_after && totlen > 0 && offset < defn->length
+ && unsafe_chars (pfile, xbuf[totlen - 1], exp[offset]))
+ {
+ xbuf[totlen++] = '\r';
+ xbuf[totlen++] = ' ';
+ }
}
-
- xbuf[totlen] = 0;
- xbuf_len = totlen;
-
}
- pfile->output_escapes--;
+ /* if there is anything left of the definition
+ after handling the arg list, copy that in too. */
+ for (i = offset; i < defn->length; i++)
+ xbuf[totlen++] = exp[i];
+ xbuf[totlen] = 0;
+
+ if (totlen > xbuf_len)
+ /* Just die - we've trashed the heap at this point. */
+ abort ();
+
/* Now put the expansion on the input stack
so our caller will commence reading from it. */
- push_macro_expansion (pfile, xbuf, xbuf_len, hp);
- CPP_BUFFER (pfile)->has_escapes = 1;
+ push_macro_expansion (pfile, xbuf, totlen, hp);
/* Pop the space we've used in the token_buffer for argument expansion. */
CPP_SET_WRITTEN (pfile, old_written);
-
- /* In C89, a macro cannot be expanded recursively. Traditional C
- permits it, but any use in an object-like macro must lead to
- infinite recursion, so always follow C89 in object-like macros.
-
- The only example known where this doesn't cause infinite recursion
- in function-like macros is:
- #define foo(x,y) bar(x(y, 0))
- foo(foo, baz)
- which expands to bar(foo(baz, 0)) in C89 and
- bar(bar(baz(0, 0)) in K+R. This looks pathological to me.
- If someone has a real-world example I would love to see it. */
- if (nargs <= 0 || !CPP_TRADITIONAL (pfile))
- hp->type = T_DISABLED;
}
/* Return 1 iff a token ending in C1 followed directly by a token C2
@@ -1501,7 +1676,7 @@ unsafe_chars (pfile, c1, c2)
static void
push_macro_expansion (pfile, xbuf, len, hp)
cpp_reader *pfile;
- register U_CHAR *xbuf;
+ const U_CHAR *xbuf;
int len;
HASHNODE *hp;
{
@@ -1539,12 +1714,33 @@ push_macro_expansion (pfile, xbuf, len, hp)
mbuf->cur += 2;
mbuf->cleanup = macro_cleanup;
mbuf->macro = hp;
+ mbuf->has_escapes = 1;
+
+ /* In C89, a macro cannot be expanded recursively. Traditional C
+ permits it, but any use in an object-like macro must lead to
+ infinite recursion, so always follow C89 in object-like macros.
+ Likewise, in a function-like macro it must cause infinite
+ recursion unless we are actually doing something with the
+ arguments.
+
+ Even that criterion is too weak. The only example known where
+ macro recursion isn't infinite is:
+ #define bar(x,y) foo(x(y, 0))
+ bar(bar, baz)
+ which expands to foo(bar(baz, 0)) in C89 and
+ foo(foo(baz(0, 0)) in K+R. This looks pathological to me.
+ If someone has a real-world example I would love to see it. */
+ if (hp->type != T_FMACRO
+ || hp->value.defn->nargs == 0
+ || hp->value.defn->pattern == 0
+ || !CPP_TRADITIONAL (pfile))
+ hp->disabled = 1;
}
/* Return zero if two DEFINITIONs are isomorphic. */
-int
-_cpp_compare_defs (pfile, d1, d2)
+static int
+compare_defs (pfile, d1, d2)
cpp_reader *pfile;
DEFINITION *d1, *d2;
{
@@ -1590,91 +1786,107 @@ _cpp_compare_defs (pfile, d1, d2)
to be read back in again. */
void
-_cpp_dump_definition (pfile, sym, len, defn)
+_cpp_dump_definition (pfile, hp)
cpp_reader *pfile;
- const U_CHAR *sym;
- long len;
- DEFINITION *defn;
+ HASHNODE *hp;
{
- CPP_RESERVE (pfile, len + sizeof "#define ");
- CPP_PUTS_Q (pfile, "#define ", sizeof "#define " -1);
- CPP_PUTS_Q (pfile, sym, len);
-
- if (defn->nargs == -1)
+ CPP_RESERVE (pfile, hp->length + sizeof "#define ");
+ CPP_PUTS_Q (pfile, "#define ", sizeof "#define " - 1);
+ CPP_PUTS_Q (pfile, hp->name, hp->length);
+
+ if (hp->type == T_EMPTY)
+ /* do nothing */;
+ else if (hp->type == T_FMACRO)
+ dump_DEFINITION (pfile, hp->value.defn);
+ else
{
CPP_PUTC_Q (pfile, ' ');
- /* The first and last two characters of a macro expansion are
- always "\r "; this needs to be trimmed out.
- So we need length-4 chars of space, plus one for the NUL. */
- CPP_RESERVE (pfile, defn->length - 4 + 1);
- CPP_PUTS_Q (pfile, defn->expansion + 2, defn->length - 4);
- }
- else
- {
- struct reflist *r;
- unsigned char **argv = (unsigned char **) alloca (defn->nargs *
- sizeof(char *));
- int *argl = (int *) alloca (defn->nargs * sizeof(int));
- unsigned char *x;
- int i;
-
- /* First extract the argument list. */
- x = defn->argnames;
- for (i = 0; i < defn->nargs; i++)
- {
- argv[i] = x;
- argl[i] = strlen (x);
- x += argl[i] + 1;
- }
-
- /* Now print out the argument list. */
- CPP_PUTC_Q (pfile, '(');
- for (i = 0; i < defn->nargs; i++)
+ if (hp->type == T_IDENTITY)
+ CPP_PUTS (pfile, hp->name, hp->length);
+ else if (hp->type == T_MCONST)
+ CPP_PUTS (pfile, hp->value.cpval, strlen (hp->value.cpval));
+ else if (hp->type == T_MACRO)
{
- CPP_RESERVE (pfile, argl[i] + 2);
- if (!(i == defn->nargs-1 && defn->rest_args
- && !strcmp (argv[i], "__VA_ARGS__")))
- CPP_PUTS_Q (pfile, argv[i], argl[i]);
- if (i < defn->nargs-1)
- CPP_PUTS_Q (pfile, ", ", 2);
+ /* The first and last two characters of a macro expansion are
+ always "\r "; this needs to be trimmed out.
+ So we need length-4 chars of space, plus one for the NUL. */
+ CPP_RESERVE (pfile, hp->value.defn->length - 4 + 1);
+ CPP_PUTS_Q (pfile, hp->value.defn->expansion + 2,
+ hp->value.defn->length - 4);
}
- if (defn->rest_args)
- CPP_PUTS (pfile, "...", 3);
- CPP_PUTS (pfile, ") ", 2);
+ else
+ cpp_ice (pfile, "invalid hash type %d in dump_definition", hp->type);
+ }
+ if (CPP_BUFFER (pfile) == 0 || ! pfile->done_initializing)
+ CPP_PUTC (pfile, '\n');
+}
- /* Now the definition. */
- x = defn->expansion;
- for (r = defn->pattern; r; r = r->next)
- {
- i = r->nchars;
- if (*x == '\r') x += 2, i -= 2;
- /* i chars for macro text, plus the length of the macro
- argument name, plus one for a stringify marker, plus two for
- each concatenation marker. */
- CPP_RESERVE (pfile,
- i + argl[r->argno] + r->stringify
- + (r->raw_before + r->raw_after) * 2);
-
- if (i > 0) CPP_PUTS_Q (pfile, x, i);
- if (r->raw_before)
- CPP_PUTS_Q (pfile, "##", 2);
- if (r->stringify)
- CPP_PUTC_Q (pfile, '#');
- CPP_PUTS_Q (pfile, argv[r->argno], argl[r->argno]);
- if (r->raw_after && !(r->next && r->next->nchars == 0
- && r->next->raw_before))
- CPP_PUTS_Q (pfile, "##", 2);
-
- x += i;
- }
+static void
+dump_DEFINITION (pfile, defn)
+ cpp_reader *pfile;
+ DEFINITION *defn;
+{
+ struct reflist *r;
+ unsigned char **argv = (unsigned char **) alloca (defn->nargs *
+ sizeof(char *));
+ int *argl = (int *) alloca (defn->nargs * sizeof(int));
+ unsigned char *x;
+ int i;
+
+ /* First extract the argument list. */
+ x = defn->argnames;
+ for (i = 0; i < defn->nargs; i++)
+ {
+ argv[i] = x;
+ argl[i] = strlen (x);
+ x += argl[i] + 1;
+ }
+
+ /* Now print out the argument list. */
+ CPP_PUTC_Q (pfile, '(');
+ for (i = 0; i < defn->nargs; i++)
+ {
+ CPP_RESERVE (pfile, argl[i] + 2);
+ if (!(i == defn->nargs-1 && defn->rest_args
+ && !strcmp (argv[i], "__VA_ARGS__")))
+ CPP_PUTS_Q (pfile, argv[i], argl[i]);
+ if (i < defn->nargs-1)
+ CPP_PUTS_Q (pfile, ", ", 2);
+ }
+ if (defn->rest_args)
+ CPP_PUTS (pfile, "...", 3);
+ CPP_PUTS (pfile, ") ", 2);
- i = defn->length - (x - defn->expansion) - 2;
+ /* Now the definition. */
+ x = defn->expansion;
+ for (r = defn->pattern; r; r = r->next)
+ {
+ i = r->nchars;
if (*x == '\r') x += 2, i -= 2;
- if (i > 0) CPP_PUTS (pfile, x, i);
+ /* i chars for macro text, plus the length of the macro
+ argument name, plus one for a stringify marker, plus two for
+ each concatenation marker. */
+ CPP_RESERVE (pfile,
+ i + argl[r->argno] + r->stringify
+ + (r->raw_before + r->raw_after) * 2);
+
+ if (i > 0) CPP_PUTS_Q (pfile, x, i);
+ if (r->raw_before)
+ CPP_PUTS_Q (pfile, "##", 2);
+ if (r->stringify)
+ CPP_PUTC_Q (pfile, '#');
+ CPP_PUTS_Q (pfile, argv[r->argno], argl[r->argno]);
+ if (r->raw_after && !(r->next && r->next->nchars == 0
+ && r->next->raw_before))
+ CPP_PUTS_Q (pfile, "##", 2);
+
+ x += i;
}
- if (CPP_BUFFER (pfile) == 0 || ! pfile->done_initializing)
- CPP_PUTC (pfile, '\n');
+
+ i = defn->length - (x - defn->expansion) - 2;
+ if (*x == '\r') x += 2, i -= 2;
+ if (i > 0) CPP_PUTS (pfile, x, i);
}
/* Dump out the hash table. */
@@ -1687,7 +1899,7 @@ dump_hash_helper (h, p)
cpp_reader *pfile = (cpp_reader *)p;
if (hp->type == T_MACRO)
- _cpp_dump_definition (pfile, hp->name, hp->length, hp->value.defn);
+ _cpp_dump_definition (pfile, hp);
return 1;
}