X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;ds=sidebyside;f=gcc%2Fcpphash.c;h=9e15ab48f03080192cdaa1f46ee21cfd74d384e9;hb=665617504a0de369ff5c0fd45add7a09e021f462;hp=c25a56bcabfd3e4ef8d3a4c8d810fdcc63bf30f6;hpb=76faa4c0ab5258727ab045e4ea37a00351f0bebd;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cpphash.c b/gcc/cpphash.c index c25a56bcabf..9e15ab48f03 100644 --- a/gcc/cpphash.c +++ b/gcc/cpphash.c @@ -1,4 +1,4 @@ -/* 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. @@ -27,662 +27,96 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "system.h" #include "cpplib.h" #include "cpphash.h" -#include "hashtab.h" -#include "obstack.h" -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free +static cpp_hashnode *alloc_node PARAMS ((hash_table *)); -/* This is the second argument to eq_HASHNODE. */ -struct hashdummy -{ - const U_CHAR *name; - unsigned short length; -}; - -/* Initial hash table size. (It can grow if necessary - see hashtab.c.) */ -#define HASHSIZE 500 - -static unsigned int hash_HASHNODE PARAMS ((const void *)); -static int eq_HASHNODE PARAMS ((const void *, const void *)); -static int dump_hash_helper PARAMS ((void **, void *)); - -static void dump_funlike_macro PARAMS ((cpp_reader *, cpp_hashnode *)); - -static const cpp_token *count_params PARAMS ((cpp_reader *, - const cpp_token *, - cpp_toklist *)); -static int is__va_args__ PARAMS ((cpp_reader *, const cpp_token *)); -static cpp_toklist *parse_define PARAMS((cpp_reader *)); -static int check_macro_redefinition PARAMS((cpp_reader *, cpp_hashnode *hp, - const cpp_toklist *)); -static int save_expansion PARAMS((cpp_reader *, cpp_toklist *, - const cpp_token *, const cpp_token *)); -static unsigned int find_param PARAMS ((const cpp_token *, - const cpp_token *)); +/* Return an identifier node for hashtable.c. Used by cpplib except + when integrated with the C front ends. */ -/* Calculate hash of a string of length LEN. */ -unsigned int -_cpp_calc_hash (str, len) - const U_CHAR *str; - size_t len; +static cpp_hashnode * +alloc_node (table) + hash_table *table; { - size_t n = len; - unsigned int r = 0; - - do - r = r * 67 + (*str++ - 113); - while (--n); - return r + len; + cpp_hashnode *node; + + node = (cpp_hashnode *) obstack_alloc (&table->pfile->hash_ob, + sizeof (cpp_hashnode)); + memset ((PTR) node, 0, sizeof (cpp_hashnode)); + return node; } -/* Calculate hash of a cpp_hashnode structure. */ -static unsigned int -hash_HASHNODE (x) - const void *x; -{ - const cpp_hashnode *h = (const cpp_hashnode *)x; - return h->hash; -} +/* Set up the identifier hash table. Use TABLE if non-null, otherwise + create our own. */ -/* Compare a cpp_hashnode structure (already in the table) with a - hashdummy structure (not yet in the table). This relies on the - rule that the existing entry is the first argument, the potential - entry the second. It also relies on the comparison function never - being called except as a direct consequence of a call to - htab_find(_slot)_with_hash. */ -static int -eq_HASHNODE (x, y) - const void *x; - const void *y; -{ - const cpp_hashnode *a = (const cpp_hashnode *)x; - const struct hashdummy *b = (const struct hashdummy *)y; - - return (a->length == b->length - && !ustrncmp (a->name, b->name, a->length)); -} - -/* Find the hash node for name "name", of length LEN. */ - -cpp_hashnode * -cpp_lookup (pfile, name, len) - cpp_reader *pfile; - const U_CHAR *name; - int len; -{ - struct hashdummy dummy; - cpp_hashnode *new, **slot; - unsigned int hash; - U_CHAR *p; - - dummy.name = name; - dummy.length = len; - hash = _cpp_calc_hash (name, len); - - slot = (cpp_hashnode **) - htab_find_slot_with_hash (pfile->hashtab, (void *)&dummy, hash, INSERT); - if (*slot) - return *slot; - - /* Create a new hash node. */ - p = obstack_alloc (pfile->hash_ob, sizeof (cpp_hashnode) + len); - new = (cpp_hashnode *)p; - p += offsetof (cpp_hashnode, name); - - new->type = T_VOID; - new->length = len; - new->hash = hash; - new->fe_value = 0; - new->value.expansion = NULL; - - memcpy (p, name, len); - p[len] = 0; - - *slot = new; - return new; -} - -/* Set up and tear down internal structures for macro expansion. */ void -_cpp_init_macros (pfile) +_cpp_init_hashtable (pfile, table) cpp_reader *pfile; + hash_table *table; { - pfile->hashtab = htab_create (HASHSIZE, hash_HASHNODE, - eq_HASHNODE, (htab_del) _cpp_free_definition); - pfile->hash_ob = xnew (struct obstack); - obstack_init (pfile->hash_ob); -} + if (table == NULL) + { + 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); + } -void -_cpp_cleanup_macros (pfile) - cpp_reader *pfile; -{ - htab_delete (pfile->hashtab); - obstack_free (pfile->hash_ob, 0); - free (pfile->hash_ob); + table->pfile = pfile; + pfile->hash_table = table; } -/* Free the definition of macro H. */ +/* Tear down the identifier hash table. */ void -_cpp_free_definition (h) - cpp_hashnode *h; -{ - if (h->type == T_MACRO) - _cpp_free_toklist (h->value.expansion); - h->value.expansion = NULL; -} - -/* Scans for a given token, returning the parameter number if found, - or 0 if not found. Scans from FIRST to TOKEN - 1 or the first - CPP_CLOSE_PAREN for TOKEN. */ -static unsigned int -find_param (first, token) - const cpp_token *first, *token; -{ - unsigned int param = 0; - - for (; first < token && first->type != CPP_CLOSE_PAREN; first++) - if (first->type == CPP_NAME) - { - param++; - if (first->val.node == token->val.node) - return param; - } - - return 0; -} - -/* Constraint 6.10.3.5: __VA_ARGS__ should only appear in the - replacement list of a variable-arguments macro. TOKEN is assumed - to be of type CPP_NAME. */ -static int -is__va_args__ (pfile, token) +_cpp_destroy_hashtable (pfile) cpp_reader *pfile; - const cpp_token *token; { - if (!CPP_PEDANTIC (pfile) - || token->val.node != pfile->spec_nodes->n__VA_ARGS__) - return 0; - - cpp_pedwarn_with_line (pfile, token->line, token->col, - "\"%s\" is only valid in the replacement list of a function-like macro", - token->val.node->name); - return 1; -} - -/* Counts the parameters to a function like macro, and saves their - spellings if necessary. Returns the token that we stopped scanning - at; if it's type isn't CPP_CLOSE_PAREN there was an error, which - has been reported. */ -static const cpp_token * -count_params (pfile, first, list) - cpp_reader *pfile; - const cpp_token *first; - cpp_toklist *list; -{ - unsigned int params_len = 0, prev_ident = 0; - const cpp_token *token, *temp; - - list->paramc = 0; - for (token = first;; token++) + if (pfile->our_hashtable) { - switch (token->type) - { - case CPP_EOF: - missing_paren: - cpp_error_with_line (pfile, token->line, token->col, - "missing ')' in macro parameter list"); - goto out; - - case CPP_COMMENT: - continue; /* Ignore -C comments. */ - - case CPP_NAME: - if (prev_ident) - { - cpp_error_with_line (pfile, token->line, token->col, - "macro parameters must be comma-separated"); - goto out; - } - - /* Constraint 6.10.3.5 */ - if (is__va_args__ (pfile, token)) - goto out; - - params_len += token->val.node->length + 1; - prev_ident = 1; - list->paramc++; - - /* Constraint 6.10.3.6 - duplicate parameter names. */ - if (find_param (first, token)) - { - cpp_error_with_line (pfile, token->line, token->col, - "duplicate macro parameter \"%s\"", - token->val.node->name); - goto out; - } - break; - - default: - cpp_error_with_line (pfile, token->line, token->col, - "illegal token in macro parameter list"); - goto out; - - case CPP_CLOSE_PAREN: - if (prev_ident || list->paramc == 0) - goto scanned; - - /* Fall through to pick up the error. */ - case CPP_COMMA: - if (!prev_ident) - { - cpp_error_with_line (pfile, token->line, token->col, - "parameter name expected"); - if (token->type == CPP_CLOSE_PAREN) - token--; /* Return the ',' not ')'. */ - goto out; - } - prev_ident = 0; - break; - - case CPP_ELLIPSIS: - /* Convert ISO-style var_args to named varargs by changing - the ellipsis into an identifier with name __VA_ARGS__. - This simplifies other handling. */ - if (!prev_ident) - { - cpp_token *tok = (cpp_token *) token; - - tok->type = CPP_NAME; - tok->val.node = pfile->spec_nodes->n__VA_ARGS__; - list->paramc++; - params_len += tok->val.node->length + 1; - - if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99)) - cpp_pedwarn (pfile, - "C89 does not permit anon varargs macros"); - } - else - { - list->flags |= GNU_REST_ARGS; - if (CPP_PEDANTIC (pfile)) - cpp_pedwarn (pfile, - "ISO C does not permit named varargs parameters"); - } - - list->flags |= VAR_ARGS; - token++; - if (token->type == CPP_CLOSE_PAREN) - goto scanned; - goto missing_paren; - } - } - - scanned: - /* Store the null-terminated parameter spellings of a function, to - provide pedantic warnings to satisfy 6.10.3.2, or for use when - dumping macro definitions. */ - if (list->paramc > 0 && pfile->save_parameter_spellings) - { - U_CHAR *buf; - - _cpp_reserve_name_space (list, params_len); - list->params_len = list->name_used = params_len; - buf = list->namebuf; - for (temp = first; temp <= token; temp++) - if (temp->type == CPP_NAME) - { - /* copy null too */ - memcpy (buf, temp->val.node->name, temp->val.node->length + 1); - buf += temp->val.node->length + 1; - } + free (pfile->hash_table); + obstack_free (&pfile->hash_ob, 0); } - - out: - return token; } -/* Parses a #define directive. Returns null pointer on error. */ -static cpp_toklist * -parse_define (pfile) - cpp_reader *pfile; -{ - const cpp_token *token, *first_param; - cpp_toklist *list; - int prev_white = 0; - - /* The first token after the macro's name. */ - token = cpp_get_token (pfile); - - /* Constraint 6.10.3.5 */ - if (is__va_args__ (pfile, token - 1)) - return 0; +/* Returns the hash entry for the STR of length LEN, creating one + if necessary. */ - while (token->type == CPP_COMMENT) - token++, prev_white = 1; - - /* Allocate the expansion's list. It will go in the hash table. */ - list = (cpp_toklist *) xmalloc (sizeof (cpp_toklist)); - _cpp_init_toklist (list, 0); - first_param = token + 1; - list->paramc = -1; /* Object-like macro. */ - - if (!prev_white && !(token->flags & PREV_WHITE)) - { - if (token->type == CPP_OPEN_PAREN) - { - token = count_params (pfile, first_param, list); - if (token->type != CPP_CLOSE_PAREN) - goto error; - token++; - } - else if (token->type != CPP_EOF) - cpp_pedwarn (pfile, - "ISO C requires whitespace after the macro name"); - } - - if (save_expansion (pfile, list, token, first_param)) - { - error: - _cpp_free_toklist (list); - list = 0; - } - - return list; -} - -static int -check_macro_redefinition (pfile, hp, list2) +cpp_hashnode * +cpp_lookup (pfile, str, len) cpp_reader *pfile; - cpp_hashnode *hp; - const cpp_toklist *list2; + const unsigned char *str; + unsigned int len; { - const cpp_toklist *list1; - - if (hp->type != T_MACRO) - return ! pfile->done_initializing; - - /* Clear the whitespace and BOL flags of the first tokens. They get - altered during macro expansion, but is not significant here. */ - list1 = hp->value.expansion; - list1->tokens[0].flags &= ~(PREV_WHITE|BOL); - list2->tokens[0].flags &= ~(PREV_WHITE|BOL); - - if (!_cpp_equiv_toklists (list1, list2)) - return 0; - - if (CPP_OPTION (pfile, pedantic) - && list1->paramc > 0 - && (list1->params_len != list2->params_len - || memcmp (list1->namebuf, list2->namebuf, list1->params_len))) - return 0; - - return 1; + /* ht_lookup cannot return NULL. */ + return CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_ALLOC)); } -/* Copy the tokens of the expansion. Change the type of macro - arguments from CPP_NAME to CPP_MACRO_ARG. Remove #'s that - represent stringification, flagging the CPP_MACRO_ARG it operates - on STRINGIFY. Remove ##'s, flagging the token on its immediate - left PASTE_LEFT. Returns non-zero on error. */ -static int -save_expansion (pfile, list, first, first_param) - cpp_reader *pfile; - cpp_toklist *list; - const cpp_token *first; - const cpp_token *first_param; -{ - const cpp_token *token; - cpp_token *dest; - unsigned int len, ntokens; - unsigned char *buf; - - /* Count tokens in expansion. We drop paste tokens, and stringize - tokens, so don't count them. */ - ntokens = len = 0; - for (token = first; token->type != CPP_EOF; token++) - { - const char *msg; - - if (token->type == CPP_PASTE) - { - /* Token-paste ##, but is a normal token if traditional. */ - if (! CPP_TRADITIONAL (pfile)) - { - msg = "\"##\" cannot appear at either end of a macro expansion"; - /* Constraint 6.10.3.3.1 */ - if (token == first || token[1].type == CPP_EOF) - goto error; - continue; - } - } - else if (token->type == CPP_HASH) - { - /* Stringifying #, but is a normal character if traditional, - or in object-like macros. Constraint 6.10.3.2.1. */ - if (list->paramc >= 0 && ! CPP_TRADITIONAL (pfile)) - { - if (token[1].type == CPP_NAME - && find_param (first_param, token + 1)) - continue; - if (! CPP_OPTION (pfile, lang_asm)) - { - msg = "'#' is not followed by a macro parameter"; - error: - cpp_error_with_line (pfile, token->line, token->col, msg); - return 1; - } - } - } - else if (token->type == CPP_NAME) - { - /* Constraint 6.10.3.5 */ - if (!(list->flags & VAR_ARGS) && is__va_args__ (pfile, token)) - return 1; - } - ntokens++; - if (token_spellings[token->type].type == SPELL_STRING) - len += token->val.str.len; - } - - /* Allocate space to hold the tokens. Empty expansions are stored - as a single placemarker token. */ - if (ntokens == 0) - ntokens++; - _cpp_expand_token_space (list, ntokens); - if (len > 0) - _cpp_expand_name_space (list, len); - - dest = list->tokens; - buf = list->namebuf + list->name_used; - for (token = first; token->type != CPP_EOF; token++) - { - unsigned int param_no; - - switch (token->type) - { - case CPP_NAME: - if (list->paramc == -1) - break; - - /* Check if the name is a macro parameter. */ - param_no = find_param (first_param, token); - if (param_no == 0) - break; - dest->val.aux = param_no - 1; - - dest->type = CPP_MACRO_ARG; - if (token[-1].type == CPP_HASH && ! CPP_TRADITIONAL (pfile)) - dest->flags = token[-1].flags | STRINGIFY_ARG; - else - dest->flags = token->flags; /* Particularly PREV_WHITE. */ - dest++; - continue; - - case CPP_PASTE: - if (! CPP_TRADITIONAL (pfile)) - { - dest[-1].flags |= PASTE_LEFT; - continue; - } - break; - - case CPP_HASH: - /* Stringifying #. Constraint 6.10.3.2.1 */ - if (list->paramc >= 0 && ! CPP_TRADITIONAL (pfile) - && token[1].type == CPP_NAME - && find_param (first_param, token + 1)) - continue; - break; - - default: - break; - } - - /* Copy the token. */ - *dest = *token; - if (token_spellings[token->type].type == SPELL_STRING) - { - memcpy (buf, token->val.str.text, token->val.str.len); - dest->val.str.text = buf; - buf += dest->val.str.len; - } - dest++; - } - - if (dest == list->tokens) - { - dest->type = CPP_PLACEMARKER; - dest->flags = 0; - } - - list->tokens_used = ntokens; - list->line = pfile->token_list.line; - list->file = pfile->token_list.file; - list->name_used = len; - - return 0; -} +/* Determine whether the str STR, of length LEN, is a defined macro. */ int -_cpp_create_definition (pfile, hp) - cpp_reader *pfile; - cpp_hashnode *hp; -{ - cpp_toklist *list; - - list = parse_define (pfile); - if (!list) - return 0; - - /* Check for a redefinition. Redefinition of a macro is allowed if - and only if the old and new definitions are the same. - (6.10.3 paragraph 2). */ - - if (hp->type != T_VOID) - { - if (!check_macro_redefinition (pfile, hp, list)) - { - cpp_pedwarn (pfile, "\"%s\" redefined", hp->name); - if (pfile->done_initializing && hp->type == T_MACRO) - cpp_pedwarn_with_file_and_line (pfile, - hp->value.expansion->file, - hp->value.expansion->line, 1, - "this is the location of the previous definition"); - } - _cpp_free_definition (hp); - } - - /* Enter definition in hash table. */ - hp->type = T_MACRO; - hp->value.expansion = list; - - return 1; -} - -/* Dump the definition of macro MACRO on stdout. The format is suitable - to be read back in again. */ - -void -_cpp_dump_definition (pfile, hp) - cpp_reader *pfile; - cpp_hashnode *hp; -{ - 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_MACRO) - { - if (hp->value.expansion->paramc >= 0) - dump_funlike_macro (pfile, hp); - else - { - const cpp_toklist *list = hp->value.expansion; - list->tokens[0].flags &= ~BOL; - list->tokens[0].flags |= PREV_WHITE; - _cpp_dump_list (pfile, list, list->tokens, 1); - } - } - 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'); -} - -static void -dump_funlike_macro (pfile, node) +cpp_defined (pfile, str, len) cpp_reader *pfile; - cpp_hashnode *node; + const unsigned char *str; + int len; { - int i = 0; - const cpp_toklist * list = node->value.expansion; - const U_CHAR *param; + cpp_hashnode *node; - param = list->namebuf; - CPP_PUTC_Q (pfile, '('); - for (i = 0; i++ < list->paramc;) - { - unsigned int len; + node = CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_NO_INSERT)); - len = ustrlen (param); - CPP_PUTS (pfile, param, len); - if (i < list->paramc) - CPP_PUTS(pfile, ", ", 2); - else if (list->flags & VAR_ARGS) - { - if (!ustrcmp (param, U"__VA_ARGS__")) - pfile->limit -= sizeof (U"__VA_ARGS__") - 1; - CPP_PUTS_Q (pfile, "...", 3); - } - param += len + 1; - } - CPP_PUTC (pfile, ')'); - list->tokens[0].flags &= ~BOL; - list->tokens[0].flags |= PREV_WHITE; - _cpp_dump_list (pfile, list, list->tokens, 1); + /* 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; -{ - cpp_hashnode *hp = (cpp_hashnode *)*h; - cpp_reader *pfile = (cpp_reader *)p; - - if (hp->type == T_MACRO) - _cpp_dump_definition (pfile, hp); - 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); }