-/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2003, 2004, 2006, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*/
\f
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "libguile/validate.h"
#include "libguile/symbols.h"
+#include "libguile/private-options.h"
+
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
}
static SCM
-scm_i_mem2symbol (SCM str)
+lookup_interned_symbol (SCM name, unsigned long raw_hash)
+{
+ /* Try to find the symbol in the symbols table */
+ SCM result = SCM_BOOL_F;
+ SCM bucket, elt, previous_elt;
+ size_t len;
+ unsigned long hash = raw_hash % SCM_HASHTABLE_N_BUCKETS (symbols);
+
+ len = scm_i_string_length (name);
+ bucket = SCM_HASHTABLE_BUCKET (symbols, hash);
+
+ for (elt = bucket, previous_elt = SCM_BOOL_F;
+ !scm_is_null (elt);
+ previous_elt = elt, elt = SCM_CDR (elt))
+ {
+ SCM pair, sym;
+
+ pair = SCM_CAR (elt);
+ if (!scm_is_pair (pair))
+ abort ();
+
+ if (SCM_WEAK_PAIR_CAR_DELETED_P (pair))
+ {
+ /* PAIR is a weak pair whose key got nullified: remove it from
+ BUCKET. */
+ /* FIXME: Since this is done lazily, i.e., only when a new symbol
+ is to be inserted in a bucket containing deleted symbols, the
+ number of items in the hash table may remain erroneous for some
+ time, thus precluding proper rehashing. */
+ if (previous_elt != SCM_BOOL_F)
+ SCM_SETCDR (previous_elt, SCM_CDR (elt));
+ else
+ bucket = SCM_CDR (elt);
+
+ SCM_HASHTABLE_DECREMENT (symbols);
+ continue;
+ }
+
+ sym = SCM_CAR (pair);
+
+ if (scm_i_symbol_hash (sym) == raw_hash
+ && scm_i_symbol_length (sym) == len)
+ {
+ size_t i = len;
+
+ /* Slightly faster path for comparing narrow to narrow. */
+ if (scm_i_is_narrow_string (name) && scm_i_is_narrow_symbol (sym))
+ {
+ const char *chrs = scm_i_symbol_chars (sym);
+ const char *str = scm_i_string_chars (name);
+
+ while (i != 0)
+ {
+ --i;
+ if (str[i] != chrs[i])
+ goto next_symbol;
+ }
+ }
+ else
+ {
+ /* Somewhat slower path for comparing narrow to wide or
+ wide to wide. */
+ while (i != 0)
+ {
+ --i;
+ if (scm_i_string_ref (name, i) != scm_i_symbol_ref (sym, i))
+ goto next_symbol;
+ }
+ }
+
+ /* We found it. */
+ result = sym;
+ break;
+ }
+ next_symbol:
+ ;
+ }
+
+ if (SCM_HASHTABLE_N_ITEMS (symbols) < SCM_HASHTABLE_LOWER (symbols))
+ /* We removed many symbols in this pass so trigger a rehashing. */
+ scm_i_rehash (symbols, scm_i_hash_symbol, 0, "lookup_interned_symbol");
+
+ return result;
+}
+
+/* Intern SYMBOL, an uninterned symbol. */
+static void
+intern_symbol (SCM symbol)
+{
+ SCM slot, cell;
+ unsigned long hash;
+
+ hash = scm_i_symbol_hash (symbol) % SCM_HASHTABLE_N_BUCKETS (symbols);
+ slot = SCM_HASHTABLE_BUCKET (symbols, hash);
+ cell = scm_cons (symbol, SCM_UNDEFINED);
+
+ SCM_SET_HASHTABLE_BUCKET (symbols, hash, scm_cons (cell, slot));
+ SCM_HASHTABLE_INCREMENT (symbols);
+
+ if (SCM_HASHTABLE_N_ITEMS (symbols) > SCM_HASHTABLE_UPPER (symbols))
+ scm_i_rehash (symbols, scm_i_hash_symbol, 0, "intern_symbol");
+}
+
+static SCM
+scm_i_str2symbol (SCM str)
{
- const char *name = scm_i_string_chars (str);
- size_t len = scm_i_string_length (str);
-
- size_t raw_hash = scm_string_hash ((const unsigned char *) name, len);
- size_t hash = raw_hash % SCM_HASHTABLE_N_BUCKETS (symbols);
-
- {
- /* Try to find the symbol in the symbols table */
-
- SCM l;
-
- for (l = SCM_HASHTABLE_BUCKET (symbols, hash);
- !scm_is_null (l);
- l = SCM_CDR (l))
- {
- SCM sym = SCM_CAAR (l);
- if (scm_i_symbol_hash (sym) == raw_hash
- && scm_i_symbol_length (sym) == len)
- {
- const char *chrs = scm_i_symbol_chars (sym);
- size_t i = len;
-
- while (i != 0)
- {
- --i;
- if (name[i] != chrs[i])
- goto next_symbol;
- }
-
- return sym;
- }
- next_symbol:
- ;
- }
- }
-
- {
- /* The symbol was not found - create it. */
- SCM symbol = scm_i_make_symbol (str, 0, raw_hash,
- scm_cons (SCM_BOOL_F, SCM_EOL));
-
- SCM slot = SCM_HASHTABLE_BUCKET (symbols, hash);
- SCM cell = scm_cons (symbol, SCM_UNDEFINED);
- SCM_SET_HASHTABLE_BUCKET (symbols, hash, scm_cons (cell, slot));
- SCM_HASHTABLE_INCREMENT (symbols);
- if (SCM_HASHTABLE_N_ITEMS (symbols) > SCM_HASHTABLE_UPPER (symbols))
- scm_i_rehash (symbols, scm_i_hash_symbol, 0, "scm_mem2symbol");
-
- return symbol;
- }
+ SCM symbol;
+ size_t raw_hash = scm_i_string_hash (str);
+
+ symbol = lookup_interned_symbol (str, raw_hash);
+ if (scm_is_false (symbol))
+ {
+ /* The symbol was not found, create it. */
+ symbol = scm_i_make_symbol (str, 0, raw_hash,
+ scm_cons (SCM_BOOL_F, SCM_EOL));
+ intern_symbol (symbol);
+ }
+
+ return symbol;
}
+
static SCM
-scm_i_mem2uninterned_symbol (SCM str)
+scm_i_str2uninterned_symbol (SCM str)
{
- const char *name = scm_i_string_chars (str);
- size_t len = scm_i_string_length (str);
- size_t raw_hash = scm_string_hash ((const unsigned char *) name, len);
+ size_t raw_hash = scm_i_string_hash (str);
return scm_i_make_symbol (str, SCM_I_F_SYMBOL_UNINTERNED,
raw_hash, scm_cons (SCM_BOOL_F, SCM_EOL));
#define FUNC_NAME s_scm_make_symbol
{
SCM_VALIDATE_STRING (1, name);
- return scm_i_mem2uninterned_symbol (name);
+ return scm_i_str2uninterned_symbol (name);
}
#undef FUNC_NAME
#define FUNC_NAME s_scm_string_to_symbol
{
SCM_VALIDATE_STRING (1, string);
- return scm_i_mem2symbol (string);
+ return scm_i_str2symbol (string);
}
#undef FUNC_NAME
prefix = scm_from_locale_string (" g");
/* mutex in case another thread looks and incs at the exact same moment */
- scm_pthread_mutex_lock (&scm_i_misc_mutex);
+ scm_i_scm_pthread_mutex_lock (&scm_i_misc_mutex);
n = gensym_counter++;
- pthread_mutex_unlock (&scm_i_misc_mutex);
+ scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
n_digits = scm_iint2str (n, 10, buf);
suffix = scm_from_locale_stringn (buf, n_digits);
SCM
scm_from_locale_symbol (const char *sym)
{
- return scm_string_to_symbol (scm_from_locale_string (sym));
+ return scm_from_locale_symboln (sym, -1);
}
SCM
scm_from_locale_symboln (const char *sym, size_t len)
{
- return scm_string_to_symbol (scm_from_locale_stringn (sym, len));
+ SCM str = scm_from_locale_stringn (sym, len);
+ return scm_i_str2symbol (str);
+}
+
+SCM
+scm_take_locale_symboln (char *sym, size_t len)
+{
+ SCM str;
+
+ str = scm_take_locale_stringn (sym, len);
+ return scm_i_str2symbol (str);
+}
+
+SCM
+scm_take_locale_symbol (char *sym)
+{
+ return scm_take_locale_symboln (sym, (size_t)-1);
}
void
scm_symbols_prehistory ()
{
symbols = scm_make_weak_key_hash_table (scm_from_int (2139));
- scm_permanent_object (symbols);
}