OSDN Git Service

* config/alpha/osf5.h (TARGET_LD_BUGGY_LDGP): New.
[pf3gnuchains/gcc-fork.git] / gcc / cpphash.c
index c25a56b..9e15ab4 100644 (file)
@@ -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);
 }