Mercurial > hg > octave-avbm
diff src/symtab.cc @ 3013:66a1cede95e7
[project @ 1997-06-02 19:35:05 by jwe]
author | jwe |
---|---|
date | Mon, 02 Jun 1997 19:41:17 +0000 |
parents | a3556d2adec9 |
children | dcc6c985d72d |
line wrap: on
line diff
--- a/src/symtab.cc +++ b/src/symtab.cc @@ -28,7 +28,11 @@ #include <config.h> #endif +#include <cassert> #include <cctype> +#include <climits> + +#include <iomanip.h> #include "glob-match.h" #include "str-vec.h" @@ -36,196 +40,18 @@ #include "error.h" #include "oct-lvalue.h" #include "ov.h" +#include "pager.h" #include "symtab.h" #include "utils.h" #include "variables.h" -// Variables and functions. - -symbol_def::symbol_def (void) -{ - init_state (); -} - -symbol_def::symbol_def (const octave_value& val, unsigned int sym_type) -{ - init_state (); - definition = val; - type = sym_type; -} - -void -symbol_def::init_state (void) -{ - type = UNKNOWN; - eternal = 0; - read_only = 0; - - next_elem = 0; - count = 0; -} - -bool -symbol_def::is_variable (void) const -{ - return (type & USER_VARIABLE || type & BUILTIN_VARIABLE); -} - -bool -symbol_def::is_function (void) const -{ - return (type & USER_FUNCTION || type & BUILTIN_FUNCTION); -} - -bool -symbol_def::is_user_variable (void) const -{ - return (type & USER_VARIABLE); -} - -bool -symbol_def::is_text_function (void) const -{ - return (type & TEXT_FUNCTION); -} - -bool -symbol_def::is_mapper_function (void) const -{ - return (type & MAPPER_FUNCTION); -} - -bool -symbol_def::is_user_function (void) const -{ - return (type & USER_FUNCTION); -} - -bool -symbol_def::is_builtin_variable (void) const -{ - return (type & BUILTIN_VARIABLE); -} - -bool -symbol_def::is_builtin_function (void) const -{ - return (type & BUILTIN_FUNCTION); -} - -// XXX FIXME XXX -bool -symbol_def::is_map_element (const string& /* elts */) const -{ - return false; -} - -void -symbol_def::define (const octave_value& val, unsigned int sym_type) -{ - definition = val; - - type = sym_type; -} - -void -symbol_def::protect (void) -{ - read_only = 1; -} - -void -symbol_def::unprotect (void) -{ - read_only = 0; - -} - -void -symbol_def::make_eternal (void) -{ - eternal = 1; -} - -octave_value& -symbol_def::def (void) -{ - return definition; -} - -string -symbol_def::help (void) const -{ - return help_string; -} - -void -symbol_def::document (const string& h) -{ - help_string = h; -} - -int -maybe_delete (symbol_def *def) -{ - int count = 0; - if (def && def->count > 0) - { - def->count--; - count = def->count; - if (def->count == 0) - delete def; - } - return count; -} +octave_allocator +symbol_record::symbol_def::allocator (sizeof (symbol_record::symbol_def)); // Individual records in a symbol table. -symbol_record::symbol_record (void) -{ - init_state (); -} - -symbol_record::symbol_record (const string& n, symbol_record *nxt) -{ - init_state (); - nm = n; - next_elem = nxt; -} - -void -symbol_record::init_state (void) -{ - formal_param = 0; - linked_to_global = 0; - tagged_static = 0; - sv_fcn = 0; - definition = 0; - next_elem = 0; -} - -string -symbol_record::name (void) const -{ - return nm; -} - -string -symbol_record::help (void) const -{ - string retval; - if (definition) - retval = definition->help (); - return retval; -} - -octave_value& -symbol_record::def (void) -{ - static octave_value foo; - - return definition ? definition->def () : foo; -} +// XXX FIXME XXX -- there are lots of places below where we should +// probably be temporarily ignoring interrupts. void symbol_record::rename (const string& new_name) @@ -234,270 +60,104 @@ nm = new_name; } -bool -symbol_record::is_function (void) const -{ - return definition ? definition->is_function () : false; -} - -bool -symbol_record::is_text_function (void) const -{ - return definition ? definition->is_text_function () : false; -} - -bool -symbol_record::is_mapper_function (void) const -{ - return definition ? definition->is_mapper_function () : false; -} - -bool -symbol_record::is_user_function (void) const +void +symbol_record::define (const octave_value& v, unsigned int sym_type) { - return definition ? definition->is_user_function () : false; -} - -bool -symbol_record::is_builtin_function (void) const -{ - return definition ? definition->is_builtin_function () : false; -} - -bool -symbol_record::is_variable (void) const -{ - return definition ? definition->is_variable () : false; -} - -bool -symbol_record::is_user_variable (void) const -{ - return definition ? definition->is_user_variable () : false; -} + if (! (is_variable () && read_only_error ("redefine"))) + { + if (is_function ()) + push_def (new symbol_def ()); -bool -symbol_record::is_builtin_variable (void) const -{ - return definition ? definition->is_builtin_variable () : false; -} - -bool -symbol_record::is_map_element (const string& elts) const -{ - return definition ? definition->is_map_element (elts) : false; -} - -unsigned int -symbol_record::type (void) const -{ - return definition ? definition->type : false; -} + if (definition->type () == symbol_record::BUILTIN_VARIABLE) + sym_type = symbol_record::BUILTIN_VARIABLE; -bool -symbol_record::is_defined (void) const -{ - return (definition != 0); -} - -bool -symbol_record::is_read_only (void) const -{ - return definition ? definition->read_only : false; -} - -bool -symbol_record::is_eternal (void) const -{ - return definition ? definition->eternal : false; -} - -void -symbol_record::protect (void) -{ - if (definition) - { - definition->protect (); - - if (! is_defined ()) - warning ("protecting undefined variable `%s'", nm.c_str ()); + definition->define (v, sym_type); } } void -symbol_record::unprotect (void) -{ - if (definition) - definition->unprotect (); -} - -void -symbol_record::make_eternal (void) +symbol_record::define_builtin_var (const octave_value& v) { - if (definition) - { - definition->make_eternal (); + define (v, symbol_record::BUILTIN_VARIABLE); - if (! is_defined ()) - warning ("giving eternal life to undefined variable `%s'", - nm.c_str ()); - } + if (chg_fcn) + chg_fcn (); } -void -symbol_record::set_sv_function (sv_function f) +bool +symbol_record::define_as_fcn (const octave_value& v) { - sv_fcn = f; -} + bool retval = false; -int -symbol_record::define (const octave_value& v, unsigned int sym_type) -{ - int retval = 0; - - if (! (is_variable () && read_only_error ("redefine"))) + if (! (is_variable () || read_only_error ("redefine"))) { - if (! definition) - { - definition = new symbol_def (); - definition->count = 1; - } - else if (is_function ()) - { - push_def (new symbol_def ()); - definition->count = 1; - } + replace_all_defs (new symbol_def (v, symbol_record::BUILTIN_FUNCTION)); - if (definition->symbol_type () == symbol_def::BUILTIN_VARIABLE) - sym_type = symbol_def::BUILTIN_VARIABLE; - - definition->define (v, sym_type); + retval = true; } return retval; } -int -symbol_record::define_builtin_var (const octave_value& v) +bool +symbol_record::define (octave_function *f, unsigned int sym_type) { - int retval = define (v, symbol_def::BUILTIN_VARIABLE); + bool retval = false; - if (sv_fcn) - sv_fcn (); + if (! read_only_error ("redefine")) + { + octave_value tmp (f); + + replace_all_defs (new symbol_def (tmp, sym_type)); + + retval = true; + } return retval; } -int -symbol_record::define_as_fcn (const octave_value& v) -{ - if (is_variable () && read_only_error ("redefine")) - return 0; - - if (is_variable ()) - { - symbol_def *old_def = pop_def (); - maybe_delete (old_def); - } - - if (is_function ()) - { - symbol_def *old_def = pop_def (); - maybe_delete (old_def); - } - - push_def (new symbol_def (v, symbol_def::BUILTIN_FUNCTION)); - - definition->count = 1; - - return 1; -} - -int -symbol_record::define (octave_function *f, unsigned int sym_type) -{ - if (read_only_error ("redefine")) - return 0; - - if (is_variable ()) - { - symbol_def *old_def = pop_def (); - maybe_delete (old_def); - } - - if (is_function ()) - { - symbol_def *old_def = pop_def (); - maybe_delete (old_def); - } - - octave_value tmp (f); - - push_def (new symbol_def (tmp, sym_type)); - - definition->count = 1; - - return 1; -} - void -symbol_record::document (const string& h) -{ - if (definition) - { - definition->document (h); - - if (! is_defined ()) - warning ("documenting undefined variable `%s'", nm.c_str ()); - } -} - -int symbol_record::clear (void) { - int count = 0; if (linked_to_global) { - count = maybe_delete (definition); - definition = 0; + if (--definition->count <= 0) + delete definition; + + definition = new symbol_def (); + linked_to_global = 0; } else if (! tagged_static) { - symbol_def *old_def = pop_def (); - count = maybe_delete (old_def); + remove_top_def (); + + if (! definition) + definition = new symbol_def (); } - return count; } void -symbol_record::alias (symbol_record *s, bool force) +symbol_record::alias (symbol_record *s, bool /* force */) { - sv_fcn = s->sv_fcn; + chg_fcn = s->chg_fcn; - if (force && ! s->definition) - { - s->definition = new symbol_def (); - definition = s->definition; - definition->count = 2; // Yes, this is correct. - } - else if (s->definition) - { - definition = s->definition; - definition->count++; - } + replace_all_defs (s->definition); + + definition->count++; } void symbol_record::mark_as_formal_parameter (void) { - formal_param = 1; -} - -bool -symbol_record::is_formal_parameter (void) const -{ - return formal_param; + if (is_linked_to_global ()) + error ("can't mark global variable `%s' as function parameter", + nm.c_str ()); + else if (is_static ()) + error ("can't mark static variable `%s' as function paraemter", + nm.c_str ()); + else + formal_param = 1; } void @@ -511,12 +171,6 @@ linked_to_global = 1; } -bool -symbol_record::is_linked_to_global (void) const -{ - return linked_to_global; -} - void symbol_record::mark_as_static (void) { @@ -529,9 +183,35 @@ } bool -symbol_record::is_static (void) const +symbol_record::hides_fcn (void) const { - return tagged_static; + bool retval = false; + + if (is_variable () && is_defined ()) + { + symbol_def *hidden_def = definition->next_elem; + + if (hidden_def && hidden_def->is_builtin_function ()) + retval = true; + } + + return retval; +} + +bool +symbol_record::hides_builtin (void) const +{ + bool retval = false; + + if (is_variable () && is_defined ()) + { + symbol_def *hidden_def = definition->next_elem; + + if (hidden_def && hidden_def->is_user_function ()) + retval = true; + } + + return retval; } octave_value& @@ -560,19 +240,7 @@ } } - return octave_lvalue (&(def ()), sv_fcn); -} - -symbol_record * -symbol_record::next (void) const -{ - return next_elem; -} - -void -symbol_record::chain (symbol_record *s) -{ - next_elem = s; + return octave_lvalue (&(def ()), chg_fcn); } void @@ -581,9 +249,11 @@ if (! is_static ()) { context.push (definition); - definition = 0; + + definition = new symbol_def (); global_link_context.push (static_cast<unsigned int> (linked_to_global)); + linked_to_global = 0; } } @@ -597,45 +267,59 @@ if (! context.empty ()) { - if (is_variable ()) - { - symbol_def *old_def = pop_def (); - maybe_delete (old_def); - } + replace_all_defs (context.pop ()); - if (is_function ()) - { - symbol_def *old_def = pop_def (); - maybe_delete (old_def); - } - - definition = context.pop (); linked_to_global = global_link_context.pop (); } } -int +void +symbol_record::print_symbol_info_line (ostream& os) +{ + os << (is_read_only () ? " r-" : " rw") + << (is_eternal () ? "-" : "d") +#if 0 + << (hides_fcn () ? "f" : (hides_builtin () ? "F" : "-")) +#endif + << " " + << setiosflags (ios::left) << setw (24) << type_name () . c_str (); + + os << resetiosflags (ios::left); + + int nr = rows (); + int nc = columns (); + + if (nr < 0) + os << " -"; + else + os << setiosflags (ios::right) << setw (7) << nr; + + if (nc < 0) + os << " -"; + else + os << setiosflags (ios::right) << setw (7) << nc; + + os << resetiosflags (ios::right); + + os << " " << name () << "\n"; +} + +bool symbol_record::read_only_error (const char *action) { if (is_read_only ()) { if (is_variable ()) - { - ::error ("can't %s read-only constant `%s'", action, nm.c_str ()); - } + ::error ("can't %s read-only constant `%s'", action, nm.c_str ()); else if (is_function ()) - { - ::error ("can't %s read-only function `%s'", action, nm.c_str ()); - } + ::error ("can't %s read-only function `%s'", action, nm.c_str ()); else - { - ::error ("can't %s read-only symbol `%s'", action, nm.c_str ()); - } + ::error ("can't %s read-only symbol `%s'", action, nm.c_str ()); - return 1; + return true; } else - return 0; + return false; } void @@ -644,172 +328,39 @@ if (! sd) return; + assert (definition == 0 || definition->next_elem == 0); + sd->next_elem = definition; + definition = sd; } -symbol_def * -symbol_record::pop_def (void) +void +symbol_record::remove_top_def (void) { symbol_def *top = definition; - if (definition) - definition = definition->next_elem; - return top; -} -// A structure for handling verbose information about a symbol_record. - -symbol_record_info::symbol_record_info (void) - : initialized (0), nr (-1), nc (-1), type (symbol_def::UNKNOWN), - hides (SR_INFO_NONE), eternal (0), read_only (0), nm (), - const_type () { } - -symbol_record_info::symbol_record_info (symbol_record& sr) - : initialized (0), nr (-1), nc (-1), type (sr.type ()), - hides (SR_INFO_NONE), eternal (0), read_only (0), nm (), - const_type () -{ - if (sr.is_variable () && sr.is_defined ()) - { - octave_value tmp = sr.def (); - - const_type = tmp.type_name (); - - nr = tmp.rows (); - nc = tmp.columns (); - - symbol_def *sr_def = sr.definition; - symbol_def *hidden_def = sr_def->next_elem; + definition = definition->next_elem; - if (hidden_def) - { - if (hidden_def->is_user_function ()) - hides = SR_INFO_USER_FUNCTION; - else if (hidden_def->is_builtin_function ()) - hides = SR_INFO_BUILTIN_FUNCTION; - } - } - - eternal = sr.is_eternal (); - read_only = sr.is_read_only (); - - nm = sr.name (); - - initialized = 1; -} - -symbol_record_info::symbol_record_info (const symbol_record_info& s) - : initialized (s.initialized), nr (s.nr), nc (s.nc), type (s.type), - hides (s.hides), eternal (s.eternal), read_only (s.read_only), - nm (s.nm), const_type (s.const_type) { } - -symbol_record_info& -symbol_record_info::operator = (const symbol_record_info& s) -{ - if (this != &s) - { - initialized = s.initialized; - nr = s.nr; - nc = s.nc; - type = s.type; - hides = s.hides; - eternal = s.eternal; - read_only = s.read_only; - nm = s.nm; - const_type = s.const_type; - } - return *this; + if (--top->count <= 0) + delete top; } -bool -symbol_record_info::is_defined (void) const -{ - return initialized; -} - -bool -symbol_record_info::is_read_only (void) const -{ - return read_only; -} - -bool -symbol_record_info::is_eternal (void) const +void +symbol_record::replace_all_defs (symbol_def *sd) { - return eternal; -} - -bool -symbol_record_info::hides_fcn (void) const -{ - return (hides & SR_INFO_USER_FUNCTION); -} - -bool -symbol_record_info::hides_builtin (void) const -{ - return (hides & SR_INFO_BUILTIN_FUNCTION); -} - -string -symbol_record_info::type_name (void) const -{ - string retval; + while (definition) + remove_top_def (); - if (type == symbol_def::USER_FUNCTION) - retval = "user function"; - else if (type & symbol_def::BUILTIN_FUNCTION) - { - if (type & symbol_def::TEXT_FUNCTION) - retval = "text function"; - else if (type & symbol_def::MAPPER_FUNCTION) - retval = "mapper function"; - else - retval = "builtin function"; - } - else - retval = const_type; - - return retval; -} - -bool -symbol_record_info::is_function (void) const -{ - return (type == symbol_def::USER_FUNCTION - || type == symbol_def::BUILTIN_FUNCTION - || symbol_def::TEXT_FUNCTION - || symbol_def::MAPPER_FUNCTION); -} - -int -symbol_record_info::rows (void) const -{ - return nr; -} - -int -symbol_record_info::columns (void) const -{ - return nc; -} - -string -symbol_record_info::name (void) const -{ - return nm; + push_def (sd); } // A symbol table. -symbol_table::symbol_table (void) -{ -} - symbol_record * symbol_table::lookup (const string& nm, bool insert, bool warn) { - int index = hash (nm) & HASH_MASK; + unsigned int index = hash (nm); symbol_record *ptr = table[index].next (); @@ -817,15 +368,17 @@ { if (ptr->name () == nm) return ptr; + ptr = ptr->next (); } if (insert) { - symbol_record *new_sym; - new_sym = new symbol_record (nm, table[index].next ()); - table[index].chain (new_sym); - return new_sym; + symbol_record *sr = new symbol_record (nm, table[index].next ()); + + table[index].chain (sr); + + return sr; } else if (warn) warning ("lookup: symbol`%s' not found", nm.c_str ()); @@ -836,7 +389,7 @@ void symbol_table::rename (const string& old_name, const string& new_name) { - int index = hash (old_name) & HASH_MASK; + unsigned int index = hash (old_name); symbol_record *prev = &table[index]; symbol_record *ptr = prev->next (); @@ -851,7 +404,7 @@ { prev->chain (ptr->next ()); - index = hash (new_name) & HASH_MASK; + index = hash (new_name); table[index].chain (ptr); return; @@ -871,7 +424,7 @@ void symbol_table::clear (bool clear_user_functions) { - for (int i = 0; i < HASH_TABLE_SIZE; i++) + for (unsigned int i = 0; i < table_size; i++) { symbol_record *ptr = table[i].next (); @@ -888,10 +441,10 @@ } } -int +bool symbol_table::clear (const string& nm, bool clear_user_functions) { - int index = hash (nm) & HASH_MASK; + unsigned int index = hash (nm); symbol_record *ptr = table[index].next (); @@ -902,72 +455,63 @@ || (clear_user_functions && ptr->is_user_function ()))) { ptr->clear (); - return 1; + return true; } ptr = ptr->next (); } - return 0; + return false; } int symbol_table::size (void) const { int count = 0; - for (int i = 0; i < HASH_TABLE_SIZE; i++) + + for (unsigned int i = 0; i < table_size; i++) { symbol_record *ptr = table[i].next (); + while (ptr) { count++; ptr = ptr->next (); } } + return count; } -static inline int -pstrcmp (char **a, char **b) +static bool +matches_patterns (const string& name, const string_vector& pats) { - return strcmp (*a, *b); -} + int npats = pats.length (); -static inline int -symbol_record_info_cmp (symbol_record_info *a, symbol_record_info *b) -{ - return (a->name () == b->name ()); + if (npats == 0) + return true; + + glob_match pattern (pats); + + return pattern.match (name); } -static int -matches_patterns (const string& name, const string_vector& pats, int npats) -{ - for (int i = 0; i < npats; i++) - { - glob_match pattern (pats[i]); - if (pattern.match (name)) - return 1; - } - - return 0; -} - -// This function should probably share code with symbol_table::list. -// XXX FIXME XXX - -symbol_record_info * -symbol_table::long_list (int& count, const string_vector& pats, - int npats, bool sort, unsigned int type, - unsigned int scope) const +Array<symbol_record *> +symbol_table::symbol_list (int& count, const string_vector& pats, + unsigned int type, unsigned int scope) const { count = 0; + int n = size (); + if (n == 0) return 0; - symbol_record_info *symbols = new symbol_record_info [n+1]; - for (int i = 0; i < HASH_TABLE_SIZE; i++) + Array<symbol_record *> symbols (n); + + for (unsigned int i = 0; i < table_size; i++) { symbol_record *ptr = table[i].next (); + while (ptr) { assert (count < n); @@ -979,48 +523,8 @@ string my_name = ptr->name (); if ((type & my_type) && (scope & my_scope) - && (npats == 0 || matches_patterns (my_name, pats, npats))) - symbols[count++] = symbol_record_info (*ptr); - - ptr = ptr->next (); - } - } - symbols[count] = symbol_record_info (); - - if (sort && symbols) - qsort (symbols, count, sizeof (symbol_record_info), - symbol_record_info_cmp); - - return symbols; -} - -string_vector -symbol_table::list (int& count, const string_vector& pats, int npats, - bool sort, unsigned int type, unsigned int scope) const -{ - count = 0; - int n = size (); - if (n == 0) - return 0; - - string_vector symbols (n); - - for (int i = 0; i < HASH_TABLE_SIZE; i++) - { - symbol_record *ptr = table[i].next (); - while (ptr) - { - assert (count < n); - - unsigned int my_scope = ptr->is_linked_to_global () + 1; // Tricky... - - unsigned int my_type = ptr->type (); - - string my_name = ptr->name (); - - if ((type & my_type) && (scope & my_scope) - && (npats == 0 || matches_patterns (my_name, pats, npats))) - symbols[count++] = ptr->name (); + && matches_patterns (my_name, pats)) + symbols(count++) = ptr; ptr = ptr->next (); } @@ -1028,10 +532,87 @@ symbols.resize (count); - if (sort && ! symbols.empty ()) - symbols.qsort (); + return symbols; +} + +string_vector +symbol_table::name_list (int& count, const string_vector& pats, bool sort, + unsigned int type, unsigned int scope) const +{ + Array<symbol_record *> symbols + = symbol_list (count, pats, type, scope); + + string_vector names; + + int n = symbols.length (); + + if (n > 0) + { + names.resize (n); + + for (int i = 0; i < n; i++) + names[i] = symbols(i)->name (); + } + + if (sort) + names.qsort (); + + return names; +} + +static int +maybe_list_cmp_fcn (symbol_record **a_arg, symbol_record **b_arg) +{ + string a = (*a_arg)->name (); + string b = (*b_arg)->name (); + + return a.compare (b); +} - return symbols; +int +symbol_table::maybe_list (const char *header, const string_vector& argv, + ostream& os, bool show_verbose, + unsigned type, unsigned scope) +{ + int count; + + int status = 0; + + if (show_verbose) + { + Array<symbol_record *> symbols = symbol_list (count, argv, type, scope); + + int len = symbols.length (); + + if (len > 0 && count > 0) + { + os << "\n" << header << "\n\n" + << "prot type rows cols name\n" + << "==== ==== ==== ==== ====\n"; + + symbols.qsort (maybe_list_cmp_fcn); + + for (int i = 0; i < len; i++) + symbols(i)->print_symbol_info_line (os); + + status = 1; + } + } + else + { + string_vector symbols = name_list (count, argv, 1, type, scope); + + if (symbols.length () > 0 && count > 0) + { + os << "\n" << header << "\n\n"; + + symbols.list_in_columns (os); + + status = 1; + } + } + + return status; } symbol_record ** @@ -1044,9 +625,11 @@ return 0; symbol_record **symbols = new symbol_record * [n+1]; - for (int i = 0; i < HASH_TABLE_SIZE; i++) + + for (unsigned int i = 0; i < table_size; i++) { symbol_record *ptr = table[i].next (); + while (ptr) { assert (count < n); @@ -1074,7 +657,7 @@ void symbol_table::push_context (void) { - for (int i = 0; i < HASH_TABLE_SIZE; i++) + for (unsigned int i = 0; i < table_size; i++) { symbol_record *ptr = table[i].next (); @@ -1089,7 +672,7 @@ void symbol_table::pop_context (void) { - for (int i = 0; i < HASH_TABLE_SIZE; i++) + for (unsigned int i = 0; i < table_size; i++) { symbol_record *ptr = table[i].next (); @@ -1101,36 +684,67 @@ } } +void +symbol_table::print_stats (void) +{ + int count = 0; + int empty_chains = 0; + int max_chain_length = 0; + int min_chain_length = INT_MAX; + + for (unsigned int i = 0; i < table_size; i++) + { + int num_this_chain = 0; + + symbol_record *ptr = table[i].next (); + + if (ptr) + octave_stdout << "chain number " << i << ":\n"; + else + { + empty_chains++; + min_chain_length = 0; + } + + while (ptr) + { + num_this_chain++; + + octave_stdout << " " << ptr->name () << "\n"; + + ptr = ptr->next (); + } + + count += num_this_chain; + + if (num_this_chain > max_chain_length) + max_chain_length = num_this_chain; + + if (num_this_chain < min_chain_length) + min_chain_length = num_this_chain; + + if (num_this_chain > 0) + octave_stdout << "\n"; + } + + octave_stdout << "max chain length: " << max_chain_length << "\n"; + octave_stdout << "min chain length: " << min_chain_length << "\n"; + octave_stdout << "empty chains: " << empty_chains << "\n"; + octave_stdout << "total chains: " << table_size << "\n"; + octave_stdout << "total symbols: " << count << "\n"; +} + // Chris Torek's fave hash function. unsigned int symbol_table::hash (const string& str) { unsigned int h = 0; + for (unsigned int i = 0; i < str.length (); i++) h = h * 33 + str[i]; - return h; -} -// Return nonzero if S is a valid identifier. - -bool -valid_identifier (const char *s) -{ - if (! s || ! (isalnum (*s) || *s == '_')) - return false; - - while (*++s != '\0') - if (! (isalnum (*s) || *s == '_')) - return false; - - return true; -} - -bool -valid_identifier (const string& s) -{ - return valid_identifier (s.c_str ()); + return h & (table_size - 1); } /*