-/* Part of CPP library. (Macro handling.)
+/* Hash tables for the CPP library.
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
1999, 2000 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
#include "system.h"
#include "cpplib.h"
#include "cpphash.h"
-#include "hashtab.h"
-#undef abort
-static unsigned int hash_HASHNODE PARAMS ((const void *));
-static int eq_HASHNODE PARAMS ((const void *, const void *));
-static void del_HASHNODE PARAMS ((void *));
-static int dump_hash_helper PARAMS ((void **, void *));
+static cpp_hashnode *alloc_node PARAMS ((hash_table *));
-static int comp_def_part PARAMS ((int, U_CHAR *, int, U_CHAR *,
- int, int));
-static void push_macro_expansion PARAMS ((cpp_reader *,
- 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_token macarg PARAMS ((cpp_reader *, int));
-static struct tm *timestamp PARAMS ((cpp_reader *));
-static void special_symbol PARAMS ((HASHNODE *, cpp_reader *));
+/* Return an identifier node for hashtable.c. Used by cpplib except
+ when integrated with the C front ends. */
-/* Initial hash table size. (It can grow if necessary - see hashtab.c.) */
-#define HASHSIZE 500
-
-/* The arglist structure is built by create_definition to tell
- collect_expansion where the argument names begin. That
- is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
- would contain pointers to the strings x, y, and z.
- collect_expansion would then build a DEFINITION node,
- with reflist nodes pointing to the places x, y, and z had
- appeared. So the arglist is just convenience data passed
- between these two routines. It is not kept around after
- the current #define has been processed and entered into the
- hash table. */
-
-struct arg
-{
- U_CHAR *name;
- int len;
- char rest_arg;
-};
-
-struct arglist
-{
- U_CHAR *namebuf;
- struct arg *argv;
- int argc;
-};
-
-
-static DEFINITION *collect_expansion PARAMS ((cpp_reader *, struct arglist *));
-static struct arglist *collect_formal_parameters PARAMS ((cpp_reader *));
-
-/* This structure represents one parsed argument in a macro call.
- `raw' points to the argument text as written (`raw_length' is its length).
- `expanded' points to the argument's macro-expansion
- (its length is `expand_length').
- `stringified_length' is the length the argument would have
- if stringified. */
-
-/* raw and expanded are relative to ARG_BASE */
-#define ARG_BASE ((pfile)->token_buffer)
-
-struct argdata
-{
- /* Strings relative to pfile->token_buffer */
- long raw, expanded, stringified;
- int raw_length, expand_length;
- int stringified_length;
-};
-
-/* Calculate hash of a string of length LEN. */
-unsigned int
-_cpp_calc_hash (str, len)
- const U_CHAR *str;
- size_t len;
-{
- size_t n = len;
- unsigned int r = 0;
-
- do
- r = r * 67 + (*str++ - 113);
- while (--n);
- return r + len;
-}
-
-/* Calculate hash of a HASHNODE structure. */
-static unsigned int
-hash_HASHNODE (x)
- const void *x;
-{
- const HASHNODE *h = (const HASHNODE *)x;
- return h->hash;
-}
-
-/* Compare two HASHNODE structures. */
-static int
-eq_HASHNODE (x, y)
- const void *x;
- const void *y;
+static cpp_hashnode *
+alloc_node (table)
+ hash_table *table;
{
- const HASHNODE *a = (const HASHNODE *)x;
- const HASHNODE *b = (const HASHNODE *)y;
-
- return (a->length == b->length
- && !strncmp (a->name, b->name, a->length));
-}
-
-/* Destroy a HASHNODE. */
-static void
-del_HASHNODE (x)
- void *x;
-{
- HASHNODE *h = (HASHNODE *)x;
+ cpp_hashnode *node;
- if (h->type == T_MACRO)
- _cpp_free_definition (h->value.defn);
- free ((void *) h->name);
- free (h);
-}
-
-/* Allocate and initialize a HASHNODE structure.
- Caller must fill in the value field. */
-
-HASHNODE *
-_cpp_make_hashnode (name, len, type, hash)
- const U_CHAR *name;
- size_t len;
- enum node_type type;
- unsigned long hash;
-{
- HASHNODE *hp = (HASHNODE *) xmalloc (sizeof (HASHNODE));
- U_CHAR *p = xmalloc (len + 1);
-
- hp->type = type;
- hp->length = len;
- hp->name = p;
- hp->hash = hash;
-
- memcpy (p, name, len);
- p[len] = 0;
-
- return hp;
-}
-
-/* Find the hash node for name "name", which ends at the first
- non-identifier char.
-
- If LEN is >= 0, it is the length of the name.
- Otherwise, compute the length now. */
-
-HASHNODE *
-_cpp_lookup (pfile, name, len)
- cpp_reader *pfile;
- const U_CHAR *name;
- int len;
-{
- const U_CHAR *bp;
- HASHNODE dummy;
-
- if (len < 0)
- {
- for (bp = name; is_idchar (*bp); bp++);
- len = bp - name;
- }
-
- dummy.name = name;
- dummy.length = len;
- dummy.hash = _cpp_calc_hash (name, len);
-
- return (HASHNODE *) htab_find_with_hash (pfile->hashtab,
- (void *)&dummy, dummy.hash);
-}
-
-/* Find the hashtable slot for name "name". Used to insert or delete. */
-HASHNODE **
-_cpp_lookup_slot (pfile, name, len, insert, hash)
- cpp_reader *pfile;
- const U_CHAR *name;
- int len;
- int insert;
- unsigned long *hash;
-{
- const U_CHAR *bp;
- HASHNODE dummy;
- HASHNODE **slot;
-
- if (len < 0)
- {
- for (bp = name; is_idchar (*bp); bp++);
- len = bp - name;
- }
-
- dummy.name = name;
- dummy.length = len;
- dummy.hash = _cpp_calc_hash (name, len);
-
- slot = (HASHNODE **) htab_find_slot_with_hash (pfile->hashtab,
- (void *)&dummy,
- dummy.hash, insert);
- if (insert)
- *hash = dummy.hash;
- return slot;
-}
-
-/* Init the hash table. In here so it can see the hash and eq functions. */
-void
-_cpp_init_macro_hash (pfile)
- cpp_reader *pfile;
-{
- pfile->hashtab = htab_create (HASHSIZE, hash_HASHNODE,
- eq_HASHNODE, del_HASHNODE);
+ node = (cpp_hashnode *) obstack_alloc (&table->pfile->hash_ob,
+ sizeof (cpp_hashnode));
+ memset ((PTR) node, 0, sizeof (cpp_hashnode));
+ return node;
}
-/* Free a DEFINITION structure. Used by delete_macro, and by
- do_define when redefining macros. */
+/* Set up the identifier hash table. Use TABLE if non-null, otherwise
+ create our own. */
void
-_cpp_free_definition (d)
- DEFINITION *d;
-{
- struct reflist *ap, *nextap;
-
- for (ap = d->pattern; ap != NULL; ap = nextap)
- {
- nextap = ap->next;
- free (ap);
- }
- if (d->argnames)
- free (d->argnames);
- free (d);
-}
-
-static int
-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)
- free ((PTR) pbuf->buf);
- return 0;
-}
-
-/* Read a replacement list for a macro, and build the DEFINITION
- structure. 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.
-
- A good half of this is devoted to supporting -traditional.
- Kill me now. */
-
-static DEFINITION *
-collect_expansion (pfile, arglist)
- cpp_reader *pfile;
- struct arglist *arglist;
-{
- DEFINITION *defn;
- struct reflist *pat = 0, *endpat = 0;
- enum cpp_token token;
- long start, here, last;
- int i;
- int argc;
- size_t len;
- struct arg *argv;
- 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;
- }
-
- last = start = CPP_WRITTEN (pfile);
- last -= 2; /* two extra chars for the leading escape */
- for (;;)
- {
- /* Macro expansion is off, so we are guaranteed not to see POP
- or EOF. */
- here = CPP_WRITTEN (pfile);
- token = _cpp_get_define_token (pfile);
- tok = pfile->token_buffer + here;
- switch (token)
- {
- case CPP_POP:
- case CPP_EOF:
- cpp_ice (pfile, "EOF in collect_expansion");
- /* fall through */
- case CPP_VSPACE:
- goto done;
-
- case CPP_HSPACE:
- if (last_token == STRIZE || last_token == PASTE
- || last_token == START)
- CPP_SET_WRITTEN (pfile, here);
- break;
-
- case CPP_STRINGIZE:
- /* # is not special in object-like macros. It is special in
- function-like macros with no args. (6.10.3.2 para 1.) */
- if (arglist == NULL)
- goto norm;
- /* # is not special immediately after PASTE.
- (Implied by 6.10.3.3 para 4.) */
- if (last_token == PASTE)
- goto norm;
- last_token = STRIZE;
- CPP_SET_WRITTEN (pfile, here); /* delete from replacement text */
- break;
-
- case CPP_TOKPASTE:
- /* If the last token was an argument, discard this token and
- any hspace between it and the argument's position. Then
- mark the arg raw_after. */
- if (last_token == ARG)
- {
- endpat->raw_after = 1;
- last_token = PASTE;
- CPP_SET_WRITTEN (pfile, last);
- break;
- }
- else if (last_token == PASTE)
- /* ## ## - the second ## is ordinary. */
- goto norm;
- else if (last_token == START)
- cpp_error (pfile, "`##' at start of macro definition");
-
- /* Discard the token and any hspace before it. */
- while (is_hspace (pfile->token_buffer[here-1]))
- here--;
- CPP_SET_WRITTEN (pfile, here);
-
- if (last_token == STRIZE)
- /* Oops - that wasn't a stringify operator. */
- CPP_PUTC (pfile, '#');
- last_token = PASTE;
- break;
-
- case CPP_COMMENT:
- /* We must be in -traditional mode. Pretend this was a
- token paste, but only if there was no leading or
- trailing space and it's in the middle of the line.
- _cpp_lex_token won't return a COMMENT if there was trailing
- space. */
- CPP_SET_WRITTEN (pfile, here);
- if (last_token == START)
- break;
- if (is_hspace (pfile->token_buffer[here-1]))
- break;
- if (last_token == ARG)
- endpat->raw_after = 1;
- last_token = PASTE;
- break;
-
- case CPP_STRING:
- case CPP_CHAR:
- if (last_token == STRIZE)
- cpp_error (pfile, "`#' is not followed by a macro argument name");
-
- if (CPP_TRADITIONAL (pfile) || CPP_WTRADITIONAL (pfile))
- goto maybe_trad_stringify;
- else
- goto norm;
-
- case CPP_NAME:
- for (i = 0; i < argc; i++)
- if (!strncmp (tok, argv[i].name, argv[i].len)
- && ! is_idchar (tok[argv[i].len]))
- goto addref;
-
- /* fall through */
- default:
- norm:
- if (last_token == STRIZE)
- cpp_error (pfile, "`#' is not followed by a macro argument name");
- last_token = NORM;
- break;
- }
- continue;
-
- addref:
- {
- struct reflist *tpat;
-
- /* Make a pat node for this arg and add it to the pat list */
- tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
- tpat->next = NULL;
- tpat->raw_before = (last_token == PASTE);
- tpat->raw_after = 0;
- tpat->stringify = (last_token == STRIZE);
- tpat->rest_args = argv[i].rest_arg;
- tpat->argno = i;
- tpat->nchars = here - last;
-
- if (endpat == NULL)
- pat = tpat;
- else
- endpat->next = tpat;
- endpat = tpat;
- last = here;
- }
- CPP_SET_WRITTEN (pfile, here); /* discard arg name */
- last_token = ARG;
- continue;
-
- maybe_trad_stringify:
- last_token = NORM;
- {
- U_CHAR *base, *p, *limit;
- struct reflist *tpat;
-
- base = p = pfile->token_buffer + here;
- limit = CPP_PWRITTEN (pfile);
-
- while (++p < limit)
- {
- if (is_idstart (*p))
- continue;
- for (i = 0; i < argc; i++)
- if (!strncmp (tok, argv[i].name, argv[i].len)
- && ! is_idchar (tok[argv[i].len]))
- goto mts_addref;
- continue;
-
- mts_addref:
- if (!CPP_TRADITIONAL (pfile))
- {
- /* Must have got here because of -Wtraditional. */
- cpp_warning (pfile,
- "macro argument `%.*s' would be stringified with -traditional",
- (int) argv[i].len, argv[i].name);
- continue;
- }
- if (CPP_WTRADITIONAL (pfile))
- cpp_warning (pfile, "macro argument `%.*s' is stringified",
- (int) argv[i].len, argv[i].name);
-
- /* Remove the argument from the string. */
- memmove (p, p + argv[i].len, limit - (p + argv[i].len));
- limit -= argv[i].len;
-
- /* Make a pat node for this arg and add it to the pat list */
- tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
- tpat->next = NULL;
-
- /* Don't attempt to paste this with anything. */
- tpat->raw_before = 0;
- tpat->raw_after = 0;
- tpat->stringify = 1;
- tpat->rest_args = argv[i].rest_arg;
- tpat->argno = i;
- tpat->nchars = (p - base) + here - last;
-
- if (endpat == NULL)
- pat = tpat;
- else
- endpat->next = tpat;
- endpat = tpat;
- last = (p - base) + here;
- }
- CPP_ADJUST_WRITTEN (pfile, CPP_PWRITTEN (pfile) - limit);
- }
- }
- done:
-
- if (last_token == STRIZE)
- cpp_error (pfile, "`#' is not followed by a macro argument name");
- else if (last_token == PASTE)
- cpp_error (pfile, "`##' at end of macro definition");
-
- if (last_token == START)
- {
- /* Empty macro definition. */
- exp = (U_CHAR *) xstrdup ("\r \r ");
- len = 1;
- }
- else
- {
- /* Trim trailing white space from definition. */
- here = CPP_WRITTEN (pfile);
- while (here > last && is_hspace (pfile->token_buffer [here-1]))
- here--;
- CPP_SET_WRITTEN (pfile, here);
- CPP_NUL_TERMINATE (pfile);
- len = CPP_WRITTEN (pfile) - start + 1;
- /* space for no-concat markers at either end */
- exp = (U_CHAR *) xmalloc (len + 4);
- exp[0] = '\r';
- exp[1] = ' ';
- exp[len + 1] = '\r';
- exp[len + 2] = ' ';
- exp[len + 3] = '\0';
- memcpy (&exp[2], pfile->token_buffer + start, len - 1);
- }
-
- CPP_SET_WRITTEN (pfile, start);
-
- defn = (DEFINITION *) xmalloc (sizeof (DEFINITION));
- defn->length = len + 3;
- defn->expansion = exp;
- defn->pattern = pat;
- defn->rest_args = 0;
- if (arglist)
- {
- defn->nargs = argc;
- defn->argnames = arglist->namebuf;
- if (argv)
- {
- defn->rest_args = argv[argc - 1].rest_arg;
- free (argv);
- }
- free (arglist);
- }
- else
- {
- defn->nargs = -1;
- defn->argnames = 0;
- defn->rest_args = 0;
- }
- return defn;
-}
-
-static struct arglist *
-collect_formal_parameters (pfile)
- cpp_reader *pfile;
-{
- struct arglist *result = 0;
- struct arg *argv = 0;
- U_CHAR *namebuf = (U_CHAR *) xstrdup ("");
-
- U_CHAR *name, *tok;
- size_t argslen = 1;
- int len;
- int argc = 0;
- int i;
- enum cpp_token token;
- long old_written;
-
- old_written = CPP_WRITTEN (pfile);
- token = _cpp_get_directive_token (pfile);
- if (token != CPP_LPAREN)
- {
- cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters",
- token, CPP_LPAREN);
- goto invalid;
- }
-
- argv = (struct arg *) xmalloc (sizeof (struct arg));
- argv[argc].len = 0;
- argv[argc].rest_arg = 0;
- for (;;)
- {
- CPP_SET_WRITTEN (pfile, old_written);
- token = _cpp_get_directive_token (pfile);
- switch (token)
- {
- case CPP_NAME:
- tok = pfile->token_buffer + old_written;
- len = CPP_PWRITTEN (pfile) - tok;
- if (namebuf
- && (name = (U_CHAR *) strstr (namebuf, tok))
- && name[len] == ','
- && (name == namebuf || name[-1] == ','))
- {
- cpp_error (pfile, "duplicate macro argument name `%s'", tok);
- continue;
- }
- if (CPP_PEDANTIC (pfile) && CPP_OPTION (pfile, c99)
- && len == sizeof "__VA_ARGS__" - 1
- && !strncmp (tok, "__VA_ARGS__", len))
- cpp_pedwarn (pfile,
- "C99 does not permit use of `__VA_ARGS__' as a macro argument name");
- namebuf = (U_CHAR *) xrealloc (namebuf, argslen + len + 1);
- name = &namebuf[argslen - 1];
- argslen += len + 1;
-
- memcpy (name, tok, len);
- name[len] = ',';
- name[len+1] = '\0';
- argv[argc].len = len;
- argv[argc].rest_arg = 0;
- break;
-
- case CPP_COMMA:
- argc++;
- argv = (struct arg *) xrealloc (argv, (argc + 1)*sizeof(struct arg));
- argv[argc].len = 0;
- break;
-
- case CPP_RPAREN:
- goto done;
-
- case CPP_3DOTS:
- goto rest_arg;
-
- case CPP_VSPACE:
- cpp_error (pfile, "missing right paren in macro argument list");
- goto invalid;
-
- default:
- cpp_error (pfile, "syntax error in #define");
- goto invalid;
- }
- }
-
- rest_arg:
- /* There are two possible styles for a vararg macro:
- the C99 way: #define foo(a, ...) a, __VA_ARGS__
- the gnu way: #define foo(a, b...) a, b
- The C99 way can be considered a special case of the gnu way.
- There are also some constraints to worry about, but we'll handle
- those elsewhere. */
- if (argv[argc].len == 0)
- {
- if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99))
- cpp_pedwarn (pfile, "C89 does not permit varargs macros");
-
- len = sizeof "__VA_ARGS__" - 1;
- namebuf = (U_CHAR *) xrealloc (namebuf, argslen + len + 1);
- name = &namebuf[argslen - 1];
- argslen += len;
- memcpy (name, "__VA_ARGS__", len);
- argv[argc].len = len;
- }
- else
- if (CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "ISO C does not permit named varargs macros");
-
- argv[argc].rest_arg = 1;
-
- token = _cpp_get_directive_token (pfile);
- if (token != CPP_RPAREN)
- {
- cpp_error (pfile, "another parameter follows `...'");
- goto invalid;
- }
-
- done:
- /* Go through argv and fix up the pointers. */
- len = 0;
- for (i = 0; i <= argc; i++)
- {
- argv[i].name = namebuf + len;
- len += argv[i].len + 1;
- namebuf[len - 1] = '\0';
- }
-
- CPP_SET_WRITTEN (pfile, old_written);
-
- result = (struct arglist *) xmalloc (sizeof (struct arglist));
- if (namebuf[0] != '\0')
- {
- result->namebuf = namebuf;
- result->argc = argc + 1;
- result->argv = argv;
- }
- else
- {
- free (namebuf);
- result->namebuf = 0;
- result->argc = 0;
- result->argv = 0;
- }
-
- return result;
-
- invalid:
- if (argv)
- free (argv);
- if (namebuf)
- free (namebuf);
- return 0;
-}
-
-/* Create a DEFINITION node for a macro. The reader's point is just
- after the macro name. If FUNLIKE is true, this is a function-like
- macro. */
-
-DEFINITION *
-_cpp_create_definition (pfile, funlike)
- cpp_reader *pfile;
- int funlike;
-{
- struct arglist *args = 0;
- long line, col;
- const char *file;
- DEFINITION *defn;
-
- cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
- file = CPP_BUFFER (pfile)->nominal_fname;
-
- if (funlike)
- {
- args = collect_formal_parameters (pfile);
- if (args == 0)
- return 0;
- }
-
- defn = collect_expansion (pfile, args);
- if (defn == 0)
- return 0;
-
- defn->line = line;
- defn->file = file;
- defn->col = col;
- return defn;
-}
-
-/*
- * Parse a macro argument and append the info on PFILE's token_buffer.
- * REST_ARGS means to absorb the rest of the args.
- * Return nonzero to indicate a syntax error.
- */
-
-static enum cpp_token
-macarg (pfile, rest_args)
+_cpp_init_hashtable (pfile, table)
cpp_reader *pfile;
- int rest_args;
+ hash_table *table;
{
- int paren = 0;
- enum cpp_token token;
-
- /* Try to parse as much of the argument as exists at this
- input stack level. */
- for (;;)
+ if (table == NULL)
{
- token = cpp_get_token (pfile);
- switch (token)
- {
- case CPP_EOF:
- return token;
- case CPP_POP:
- /* If we've hit end of file, it's an error (reported by caller).
- Ditto if it's the end of cpp_expand_to_buffer text.
- If we've hit end of macro, just continue. */
- if (!CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
- return token;
- break;
- case CPP_LPAREN:
- paren++;
- break;
- case CPP_RPAREN:
- if (--paren < 0)
- goto found;
- break;
- case CPP_COMMA:
- /* if we've returned to lowest level and
- we aren't absorbing all args */
- if (paren == 0 && rest_args == 0)
- goto found;
- break;
- found:
- /* Remove ',' or ')' from argument buffer. */
- CPP_ADJUST_WRITTEN (pfile, -1);
- return token;
- default:;
- }
+ pfile->our_hashtable = 1;
+ table = ht_create (13); /* 8K (=2^13) entries. */
+ table->alloc_node = (hashnode (*) PARAMS ((hash_table *))) alloc_node;
+ gcc_obstack_init (&pfile->hash_ob);
}
-}
-\f
-static struct tm *
-timestamp (pfile)
- cpp_reader *pfile;
-{
- if (!pfile->timebuf)
- {
- time_t t = time ((time_t *) 0);
- pfile->timebuf = localtime (&t);
- }
- return pfile->timebuf;
+ table->pfile = pfile;
+ pfile->hash_table = table;
}
-static const char * const monthnames[] =
-{
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-};
-
-/* Place into PFILE a quoted string representing the string SRC.
- Caller must reserve enough space in pfile->token_buffer. */
+/* Tear down the identifier hash table. */
void
-_cpp_quote_string (pfile, src)
- cpp_reader *pfile;
- const char *src;
-{
- U_CHAR c;
-
- CPP_PUTC_Q (pfile, '\"');
- for (;;)
- switch ((c = *src++))
- {
- default:
- if (ISPRINT (c))
- CPP_PUTC_Q (pfile, c);
- else
- {
- sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c);
- CPP_ADJUST_WRITTEN (pfile, 4);
- }
- break;
-
- case '\"':
- case '\\':
- CPP_PUTC_Q (pfile, '\\');
- CPP_PUTC_Q (pfile, c);
- break;
-
- case '\0':
- CPP_PUTC_Q (pfile, '\"');
- CPP_NUL_TERMINATE_Q (pfile);
- return;
- }
-}
-
-/*
- * expand things like __FILE__. Place the expansion into the output
- * buffer *without* rescanning.
- */
-
-static void
-special_symbol (hp, pfile)
- HASHNODE *hp;
+_cpp_destroy_hashtable (pfile)
cpp_reader *pfile;
{
- const char *buf;
- int len;
- cpp_buffer *ip;
-
- switch (hp->type)
+ if (pfile->our_hashtable)
{
- case T_FILE:
- case T_BASE_FILE:
- {
- ip = cpp_file_buffer (pfile);
- if (hp->type == T_BASE_FILE)
- {
- while (CPP_PREV_BUFFER (ip) != NULL)
- ip = CPP_PREV_BUFFER (ip);
- }
-
- buf = ip->nominal_fname;
-
- if (!buf)
- buf = "";
- CPP_RESERVE (pfile, 3 + 4 * strlen (buf));
- _cpp_quote_string (pfile, buf);
- return;
- }
-
- case T_INCLUDE_LEVEL:
- {
- int true_indepth = 1;
- ip = cpp_file_buffer (pfile);
- while ((ip = CPP_PREV_BUFFER (ip)) != NULL)
- true_indepth++;
-
- CPP_RESERVE (pfile, 10);
- sprintf (CPP_PWRITTEN (pfile), "%d", true_indepth);
- CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
- return;
- }
-
- case T_VERSION:
- len = strlen (hp->value.cpval);
- CPP_RESERVE (pfile, 3 + len);
- CPP_PUTC_Q (pfile, '"');
- CPP_PUTS_Q (pfile, hp->value.cpval, len);
- CPP_PUTC_Q (pfile, '"');
- CPP_NUL_TERMINATE_Q (pfile);
- return;
-
- case T_CONST:
- buf = hp->value.cpval;
- if (!buf)
- return;
- if (*buf == '\0')
- buf = "\r ";
-
- len = strlen (buf);
- CPP_RESERVE (pfile, len + 1);
- CPP_PUTS_Q (pfile, buf, len);
- CPP_NUL_TERMINATE_Q (pfile);
- return;
-
- case T_STDC:
- CPP_RESERVE (pfile, 2);
-#ifdef STDC_0_IN_SYSTEM_HEADERS
- ip = cpp_file_buffer (pfile);
- if (ip->system_header_p
- && !cpp_defined (pfile, (const U_CHAR *) "__STRICT_ANSI__", 15))
- CPP_PUTC_Q (pfile, '0');
- else
-#endif
- CPP_PUTC_Q (pfile, '1');
- CPP_NUL_TERMINATE_Q (pfile);
- return;
-
- case T_SPECLINE:
- {
- long line;
- cpp_buf_line_and_col (cpp_file_buffer (pfile), &line, NULL);
-
- CPP_RESERVE (pfile, 10);
- sprintf (CPP_PWRITTEN (pfile), "%ld", line);
- CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
- return;
- }
-
- case T_DATE:
- case T_TIME:
- {
- struct tm *timebuf;
-
- CPP_RESERVE (pfile, 20);
- timebuf = timestamp (pfile);
- if (hp->type == T_DATE)
- sprintf (CPP_PWRITTEN (pfile), "\"%s %2d %4d\"",
- monthnames[timebuf->tm_mon],
- timebuf->tm_mday, timebuf->tm_year + 1900);
- else
- sprintf (CPP_PWRITTEN (pfile), "\"%02d:%02d:%02d\"",
- timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
-
- CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
- return;
- }
-
- case T_POISON:
- cpp_error (pfile, "attempt to use poisoned `%s'.", hp->name);
- CPP_RESERVE (pfile, 1);
- CPP_PUTC_Q (pfile, '0');
- CPP_NUL_TERMINATE_Q (pfile);
- break;
-
- default:
- cpp_ice (pfile, "invalid special hash type");
- return;
+ free (pfile->hash_table);
+ obstack_free (&pfile->hash_ob, 0);
}
}
-/* Expand a macro call.
- HP points to the symbol that is the macro being called.
- Put the result of expansion onto the input stack
- so that subsequent input by our caller will use it.
-
- If macro wants arguments, caller has already verified that
- an argument list follows; arguments come from the input stack. */
+/* Returns the hash entry for the STR of length LEN, creating one
+ if necessary. */
-void
-_cpp_macroexpand (pfile, hp)
+cpp_hashnode *
+cpp_lookup (pfile, str, len)
cpp_reader *pfile;
- HASHNODE *hp;
+ const unsigned char *str;
+ unsigned int len;
{
- int nargs;
- DEFINITION *defn;
- register U_CHAR *xbuf;
- long start_line, start_column;
- int xbuf_len;
- struct argdata *args = 0;
- long old_written = CPP_WRITTEN (pfile);
- int rest_args, rest_zero = 0;
- register int i;
-
- cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
-
- /* Check for and handle special symbols. */
- if (hp->type != T_MACRO)
- {
- special_symbol (hp, pfile);
- xbuf_len = CPP_WRITTEN (pfile) - old_written;
- xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
- 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;
- return;
- }
-
- defn = hp->value.defn;
- nargs = defn->nargs;
- pfile->output_escapes++;
-
- if (nargs >= 0)
- {
- enum cpp_token token;
-
- args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
-
- 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;
- }
-
- /* 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)++;
- CPP_OPTION (pfile, no_line_commands)++;
- pfile->no_macro_expand++;
- pfile->no_directives++;
-
- token = cpp_get_non_space_token (pfile);
- if (token != CPP_LPAREN)
- 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)--;
- CPP_OPTION (pfile, no_line_commands)--;
- pfile->no_macro_expand--;
- pfile->no_directives--;
- if (token != CPP_RPAREN)
- return;
-
- /* If we got one arg but it was just whitespace, call that 0 args. */
- if (i == 1)
- {
- register U_CHAR *bp = ARG_BASE + args[0].raw;
- register U_CHAR *lim = bp + args[0].raw_length;
- /* cpp.texi says for foo ( ) we provide one argument.
- However, if foo wants just 0 arguments, treat this as 0. */
- if (nargs == 0)
- while (bp != lim && is_space(*bp))
- bp++;
- if (bp == lim)
- i = 0;
- }
-
- /* 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)
- {
- cpp_error (pfile,
- "macro `%s' used with too many (%d) args", hp->name, i);
- }
- }
-
- /* If macro wants zero args, we parsed the arglist for checking only.
- Read directly from the macro definition. */
- if (nargs <= 0)
- {
- xbuf = defn->expansion;
- xbuf_len = defn->length;
- }
- 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;
-
- /* Macro really takes args. Compute the expansion of this call. */
-
- /* 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];
- /* 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);
- if (!CPP_TRADITIONAL (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);
- }
- }
- if (!CPP_TRADITIONAL (pfile))
- CPP_PUTC (pfile, '\"'); /* insert ending quote */
- arg->stringified_length
- = CPP_WRITTEN (pfile) - arg->stringified;
- }
- xbuf_len += args[ap->argno].stringified_length;
- }
- else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
- /* 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)
- {
- 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;
- }
-
- /* 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 (rest_zero && 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 || CPP_TRADITIONAL (pfile))
- {
- 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)
- {
- if (is_space(p1[0]))
- p1++;
- else if (p1[0] == '\r')
- p1 += 2;
- else
- break;
- }
- }
- if (ap->raw_after)
- {
- /* 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 (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
- && !CPP_TRADITIONAL (pfile)
- && unsafe_chars (pfile, xbuf[totlen - 1], expanded[0]))
- {
- xbuf[totlen++] = '\r';
- xbuf[totlen++] = ' ';
- }
-
- memcpy (xbuf + totlen, expanded, arg->expand_length);
- totlen += arg->expand_length;
-
- if (!ap->raw_after && totlen > 0 && offset < defn->length
- && !CPP_TRADITIONAL (pfile)
- && unsafe_chars (pfile, xbuf[totlen - 1], exp[offset]))
- {
- xbuf[totlen++] = '\r';
- xbuf[totlen++] = ' ';
- }
- }
-
- if (totlen > xbuf_len)
- {
- cpp_ice (pfile, "buffer overrun in macroexpand");
- return;
- }
- }
-
- /* if there is anything left of the definition
- after handling the arg list, copy that in too. */
-
- 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];
- }
-
- xbuf[totlen] = 0;
- xbuf_len = totlen;
-
- }
-
- pfile->output_escapes--;
-
- /* 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;
-
- /* Pop the space we've used in the token_buffer for argument expansion. */
- CPP_SET_WRITTEN (pfile, old_written);
-
- /* Recursive macro use sometimes works traditionally.
- #define foo(x,y) bar (x (y,0), y)
- foo (foo, baz) */
-
- if (!CPP_TRADITIONAL (pfile))
- hp->type = T_DISABLED;
-}
-
-/* Return 1 iff a token ending in C1 followed directly by a token C2
- could cause mis-tokenization. */
-
-static int
-unsafe_chars (pfile, c1, c2)
- cpp_reader *pfile;
- int c1, c2;
-{
- switch (c1)
- {
- case EOF:
- /* We don't know what the previous character was. We do know
- that it can't have been an idchar (or else it would have been
- pasted with the idchars of the macro name), and there are a
- number of second characters for which it doesn't matter what
- the first was. */
- if (is_idchar (c2) || c2 == '\'' || c2 == '\"'
- || c2 == '(' || c2 == '[' || c2 == '{'
- || c2 == ')' || c2 == ']' || c2 == '}')
- return 0;
- return 1;
-
- case '+': case '-':
- if (c2 == c1 || c2 == '=')
- return 1;
- goto letter;
-
- case 'e': case 'E': case 'p': case 'P':
- if (c2 == '-' || c2 == '+')
- return 1; /* could extend a pre-processing number */
- goto letter;
-
- case '$':
- if (CPP_OPTION (pfile, dollars_in_ident))
- goto letter;
- return 0;
-
- case 'L':
- if (c2 == '\'' || c2 == '\"')
- return 1; /* Could turn into L"xxx" or L'xxx'. */
- goto letter;
-
- case '.': case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7': case '8': case '9':
- case '_': case 'a': case 'b': case 'c': case 'd': case 'f':
- case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'n': case 'o': case 'q': case 'r': case 's':
- case 't': case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z': case 'A': case 'B': case 'C': case 'D': case 'F':
- case 'G': case 'H': case 'I': case 'J': case 'K': case 'M':
- case 'N': case 'O': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
- letter:
- /* We're in the middle of either a name or a pre-processing number. */
- return (is_idchar(c2) || c2 == '.');
-
- case '<': case '>': case '!': case '%': case '#': case ':':
- case '^': case '&': case '|': case '*': case '/': case '=':
- return (c2 == c1 || c2 == '=');
- }
- return 0;
+ /* ht_lookup cannot return NULL. */
+ return CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_ALLOC));
}
-static void
-push_macro_expansion (pfile, xbuf, len, hp)
- cpp_reader *pfile;
- register U_CHAR *xbuf;
- int len;
- HASHNODE *hp;
-{
- cpp_buffer *mbuf;
- int advance_cur = 0;
-
- /* The first chars of the expansion should be a "\r " added by
- collect_expansion. This is to prevent accidental token-pasting
- between the text preceding the macro invocation, and the macro
- expansion text.
-
- We would like to avoid adding unneeded spaces (for the sake of
- tools that use cpp, such as imake). In some common cases we can
- tell that it is safe to omit the space. */
-
- if (xbuf[0] == '\r' && xbuf[1] == ' '
- && !unsafe_chars (pfile, EOF, xbuf[2]))
- advance_cur = 1;
-
- /* Likewise, avoid the extra space at the end of the macro expansion
- if this is safe. We can do a better job here since we can know
- what the next char will be. */
- if (len >= 3
- && xbuf[len-2] == '\r'
- && xbuf[len-1] == ' ')
- {
- int c = CPP_BUF_PEEK (CPP_BUFFER (pfile));
- if (c == EOF || !unsafe_chars (pfile, xbuf[len-3], c))
- len -= 2;
- }
-
- mbuf = cpp_push_buffer (pfile, xbuf, len);
- if (mbuf == NULL)
- return;
- if (advance_cur)
- mbuf->cur += 2;
- mbuf->cleanup = macro_cleanup;
- mbuf->macro = hp;
-}
-
-/* Return zero if two DEFINITIONs are isomorphic. */
+/* Determine whether the str STR, of length LEN, is a defined macro. */
int
-_cpp_compare_defs (pfile, d1, d2)
+cpp_defined (pfile, str, len)
cpp_reader *pfile;
- DEFINITION *d1, *d2;
-{
- struct reflist *a1, *a2;
- U_CHAR *p1 = d1->expansion;
- U_CHAR *p2 = d2->expansion;
- int first = 1;
-
- if (d1->nargs != d2->nargs)
- return 1;
- if (CPP_PEDANTIC (pfile)
- && d1->argnames && d2->argnames)
- {
- U_CHAR *arg1 = d1->argnames;
- U_CHAR *arg2 = d2->argnames;
- size_t len;
- int i = d1->nargs;
- while (i--)
- {
- len = strlen (arg1) + 1;
- if (strcmp (arg1, arg2))
- return 1;
- arg1 += len;
- arg2 += len;
- }
- }
- for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
- a1 = a1->next, a2 = a2->next)
- {
- if (!((a1->nchars == a2->nchars && !strncmp (p1, p2, a1->nchars))
- || !comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
- || a1->argno != a2->argno
- || a1->stringify != a2->stringify
- || a1->raw_before != a2->raw_before
- || a1->raw_after != a2->raw_after)
- return 1;
- first = 0;
- p1 += a1->nchars;
- p2 += a2->nchars;
- }
- if (a1 != a2)
- return 1;
-
- return comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
- p2, d2->length - (p2 - d2->expansion), 1);
-}
-
-/* Return 1 if two parts of two macro definitions are effectively different.
- One of the parts starts at BEG1 and has LEN1 chars;
- the other has LEN2 chars at BEG2.
- Any sequence of whitespace matches any other sequence of whitespace.
- FIRST means these parts are the first of a macro definition;
- so ignore leading whitespace entirely.
- LAST means these parts are the last of a macro definition;
- so ignore trailing whitespace entirely. */
-
-static int
-comp_def_part (first, beg1, len1, beg2, len2, last)
- int first;
- U_CHAR *beg1, *beg2;
- int len1, len2;
- int last;
-{
- register U_CHAR *end1 = beg1 + len1;
- register U_CHAR *end2 = beg2 + len2;
- if (first)
- {
- while (beg1 != end1 && is_space(*beg1))
- beg1++;
- while (beg2 != end2 && is_space(*beg2))
- beg2++;
- }
- if (last)
- {
- while (beg1 != end1 && is_space(end1[-1]))
- end1--;
- while (beg2 != end2 && is_space(end2[-1]))
- end2--;
- }
- while (beg1 != end1 && beg2 != end2)
- {
- if (is_space(*beg1) && is_space(*beg2))
- {
- while (beg1 != end1 && is_space(*beg1))
- beg1++;
- while (beg2 != end2 && is_space(*beg2))
- beg2++;
- }
- else if (*beg1 == *beg2)
- {
- beg1++;
- beg2++;
- }
- else
- break;
- }
- return (beg1 != end1) || (beg2 != end2);
-}
-
-/* Dump the definition of macro MACRO on stdout. The format is suitable
- to be read back in again. */
-
-void
-_cpp_dump_definition (pfile, sym, len, defn)
- cpp_reader *pfile;
- const U_CHAR *sym;
- long len;
- DEFINITION *defn;
+ const unsigned char *str;
+ int len;
{
- if (pfile->lineno == 0)
- _cpp_output_line_command (pfile, same_file);
-
- 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_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;
+ cpp_hashnode *node;
- /* 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);
+ node = CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_NO_INSERT));
- /* 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;
- }
-
- i = defn->length - (x - defn->expansion) - 2;
- if (*x == '\r') x += 2, i -= 2;
- if (i > 0) CPP_PUTS (pfile, x, i);
- }
- if (pfile->lineno == 0)
- CPP_PUTC (pfile, '\n');
- CPP_NUL_TERMINATE (pfile);
+ /* If it's of type NT_MACRO, it cannot be poisoned. */
+ return node && node->type == NT_MACRO;
}
-/* Dump out the hash table. */
-static int
-dump_hash_helper (h, p)
- void **h;
- void *p;
-{
- HASHNODE *hp = (HASHNODE *)*h;
- cpp_reader *pfile = (cpp_reader *)p;
-
- if (hp->type == T_MACRO)
- {
- _cpp_dump_definition (pfile, hp->name, hp->length, hp->value.defn);
- CPP_PUTC (pfile, '\n');
- }
- return 1;
-}
+/* For all nodes in the hashtable, callback CB with parameters PFILE,
+ the node, and V. */
void
-_cpp_dump_macro_hash (pfile)
+cpp_forall_identifiers (pfile, cb, v)
cpp_reader *pfile;
+ cpp_cb cb;
+ PTR v;
{
- htab_traverse (pfile->hashtab, dump_hash_helper, pfile);
+ /* We don't need a proxy since the hash table's identifier comes
+ first in cpp_hashnode. */
+ ht_forall (pfile->hash_table, (ht_cb) cb, v);
}