Mercurial > hg > octave-avbm
changeset 4009:27e461aed956
[project @ 2002-07-31 09:33:03 by jwe]
author | jwe |
---|---|
date | Wed, 31 Jul 2002 09:33:09 +0000 |
parents | a0e323e959cd |
children | 0a30852e0249 |
files | src/ChangeLog src/defun.cc src/dynamic-ld.cc src/help.cc src/load-save.cc src/parse.y src/pt-decl.cc src/pt-id.cc src/symtab.cc src/symtab.h src/variables.cc src/variables.h |
diffstat | 12 files changed, 888 insertions(+), 342 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,122 @@ +2002-07-31 John W. Eaton <jwe@bevo.che.wisc.edu> + + * symtab.cc (symbol_table::clear (void)): Clear all records. + (symbol_table::clear (const std::string&)): Delete second arg. + Clear any symbol that matches, regardless of type. + + * symtab.h (symbol_table::variable_name_list): New function. + (symbol_table::global_variable_name_list): Likewise. + (symbol_table::user_function_name_list): Likewise. + + * symtab.h, symtab.cc (symbol_table::clear_variables): New function. + (symbol_table::clear_functions): Likewise. + (symbol_table::clear_globals): Likewise. + (symbol_table::clear_variable): New function. + (symbol_table::clear_function): Likewise. + (symbol_table::clear_global): Likewise. + (symbol_table::clear_variable_pattern): New function. + (symbol_table::clear_function_pattern): Likewise. + (symbol_table::clear_global_pattern): Likewise. + + * variables.cc (name_matches_any_pattern): Rename from + var_matches_any_pattern. + (is_local_variable): New static inline function. + (maybe_warn_exclusive): Likewise. + (do_clear_all): Likewise. + (do_clear_functions): Likewise. + (do_clear_globals): Likewise. + (do_clear_variables): Likewise. + (do_clear_function): Likewise. + (do_clear_global): Likewise. + (do_clear_variable): Likewise. + (do_clear_symbol): Likewise. + (do_clear_function_pattern): Likewise. + (do_clear_global_pattern): Likewise. + (do_clear_variable_pattern): Likewise. + (do_clear_symbol_pattern): Likewise. + (do_clear_functions): Likewise. + (do_clear_functions): Likewise. + (do_clear_globals): Likewise. + (do_clear_variables): Likewise. + (do_clear_symbols): Likewise. + (do_matlab_compatible_clear): Likewise. + (CLEAR_OPTION_ERROR): New macro. + (Fclear): Rewrite for Matlab compatibility and to cope with new + symbol table semantics. + +2002-07-30 John W. Eaton <jwe@bevo.che.wisc.edu> + + * symtab.cc (symbol_table::clear): Simply clear everything. + (symbol_table::clear_functions, symbol_table::clear_globals, + symbol_table::clear_all): New functions. + + * symtab.h (symbol_record::symbol_def::next_elem): Delete. + (symbol_record::symbol_def::symbol_def): Delete intializer. + + * symtab.h, symtab.cc (symbol_record::push_def): Delete. + (symbol_record::remove_top_def): Delete. + (symbol_record::replace_all_defs): Delete. + (symbol_record::hides_fcn): Delete. + (symbol_record::hides_builtin): Delete. + + * symtab.h (symbol_table::~symbol_table): Call clear before + deleting the table. + + * variables.cc (initialize_symbol_tables): Create fbi_sym_tab too. + (Fexist): Look in fbi_sym_tab, not global_sym_tab. + + * parse.y (function_symtab): Rename from global_symtab. + Set curr_sym_tab to fbi_sym_tab, not global_sym_tab. + Change all uses of global_symtab to be function_symtab instead. + (frob_function): Rename and look for function name in fbi_sym_tab, + not global_sym_tab. + (parse_fcn_file): Clear function name from fbi_sym_tab, not + global_sym_tab. + + * load-save.cc (save_vars): Look for built-in vars in fbi_sym_tab. + * symtab.cc (symbol_record::link_to_builtin_variable): Likewise. + * variables.cc (is_builtin_variable): Likewise. + (bind_ans): Likewise. + (bind_builtin_constant): Likewise. + (bind_builtin_variable): Likewise. + (builtin_string_variable): Likewise. + (builtin_real_scalar_variable): Likewise. + (builtin_any_variable): Likewise. + (is_text_function_name): Likewise, for functions. + (force_link_to_function): Likewise. + (is_builtin_function_name): Likewise. + (is_mapper_function_name): Likewise. + (is_valid_function): Likewise. + (Fclear): Likewise. + (F__print_symtab_info__): Likewise. + * defun.cc (print_usage): Likewise. + (install_builtin_mapper): Likewise. + (install_builtin_function): Likewise. + (install_dld_function): Likewise. + (Falias): Likewise. + * dynamic-ld.cc (clear_function): Likewise. + * variables.cc (do_who): Likewise, for built-ins and functions. + (link_to_builtin_or_function): Likewise. + * help.cc (LIST_SYMBOLS): Likewise. + (make_name_list): Handle fbi_sym_tab too. + + * variables.cc (fbi_sym_tab): New symbol table. + * variables.h (fbi_sym_tab): Provide decl. + +2002-07-29 John W. Eaton <jwe@bevo.che.wisc.edu> + + * symtab.h (symbol_record::alias): Delete unused arg force. + Change all callers. + + * variables.cc (link_to_global_variable): Give local variable + global value. + + * pt-id.cc (tree_identifier::link_to_global): Warn about global + variables that have been defined before being declared global. + for a global variable to be used before it is declared global. + * pt-decl.cc (tree_global_command::do_init): Handle possible error + from tree_identifier::link_to_global. + 2002-07-25 John W. Eaton <jwe@bevo.che.wisc.edu> * ov.cc (silent_functions, Vsilent_functions): Move here.
--- a/src/defun.cc +++ b/src/defun.cc @@ -43,7 +43,7 @@ void print_usage (const std::string& nm, bool just_usage) { - symbol_record *sym_rec = global_sym_tab->lookup (nm); + symbol_record *sym_rec = fbi_sym_tab->lookup (nm); if (sym_rec) { @@ -83,7 +83,7 @@ void install_builtin_mapper (octave_mapper *mf) { - symbol_record *sym_rec = global_sym_tab->lookup (mf->name (), true); + symbol_record *sym_rec = fbi_sym_tab->lookup (mf->name (), true); unsigned int t = symbol_record::BUILTIN_FUNCTION | symbol_record::MAPPER_FUNCTION; @@ -99,7 +99,7 @@ install_builtin_function (octave_builtin::fcn f, const std::string& name, const std::string& doc, bool is_text_fcn) { - symbol_record *sym_rec = global_sym_tab->lookup (name, true); + symbol_record *sym_rec = fbi_sym_tab->lookup (name, true); unsigned int t = symbol_record::BUILTIN_FUNCTION; @@ -134,7 +134,7 @@ const octave_shlib& shl, const std::string& doc, bool is_text_fcn) { - symbol_record *sym_rec = global_sym_tab->lookup (name, true); + symbol_record *sym_rec = fbi_sym_tab->lookup (name, true); unsigned int t = symbol_record::DLD_FUNCTION; @@ -151,12 +151,12 @@ void alias_builtin (const std::string& alias, const std::string& name) { - symbol_record *sr_name = global_sym_tab->lookup (name); + symbol_record *sr_name = fbi_sym_tab->lookup (name); if (! sr_name) panic ("can't alias to undefined name!"); - symbol_record *sr_alias = global_sym_tab->lookup (alias, true); + symbol_record *sr_alias = fbi_sym_tab->lookup (alias, true); if (sr_alias) sr_alias->alias (sr_name); @@ -187,7 +187,7 @@ if (sr_name && sr_name->is_function ()) { - symbol_record *sr_alias = global_sym_tab->lookup (alias, true); + symbol_record *sr_alias = fbi_sym_tab->lookup (alias, true); if (sr_alias) sr_alias->alias (sr_name);
--- a/src/dynamic-ld.cc +++ b/src/dynamic-ld.cc @@ -203,7 +203,7 @@ if (curr_sym_tab != top_level_sym_tab) top_level_sym_tab->clear (fcn_name); - global_sym_tab->clear (fcn_name); + fbi_sym_tab->clear (fcn_name); } bool
--- a/src/help.cc +++ b/src/help.cc @@ -347,6 +347,9 @@ string_vector key = names (keyword_help ()); int key_len = key.length (); + string_vector fbi = fbi_sym_tab->name_list (); + int fbi_len = fbi.length (); + string_vector glb = global_sym_tab->name_list (); int glb_len = glb.length (); @@ -361,7 +364,7 @@ string_vector ffl = octave_fcn_file_name_cache::list_no_suffix (); int ffl_len = ffl.length (); - int total_len = key_len + glb_len + top_len + lcl_len + ffl_len; + int total_len = key_len + fbi_len + glb_len + top_len + lcl_len + ffl_len; string_vector list (total_len); @@ -372,6 +375,9 @@ for (i = 0; i < key_len; i++) list[j++] = key[i]; + for (i = 0; i < fbi_len; i++) + list[j++] = fbi[i]; + for (i = 0; i < glb_len; i++) list[j++] = glb[i]; @@ -438,7 +444,7 @@ do \ { \ string_vector names \ - = global_sym_tab->name_list (string_vector (), true, type); \ + = fbi_sym_tab->name_list (string_vector (), true, type); \ display_symtab_names (octave_stdout, names, msg); \ } \ while (0)
--- a/src/load-save.cc +++ b/src/load-save.cc @@ -4696,7 +4696,7 @@ if (! error_state && save_builtins) { - vars = global_sym_tab->glob + vars = fbi_sym_tab->glob (pattern, symbol_record::BUILTIN_VARIABLE, SYMTAB_ALL_SCOPES); int count = vars.length ();
--- a/src/parse.y +++ b/src/parse.y @@ -1070,8 +1070,8 @@ } ; -global_symtab : // empty - { curr_sym_tab = global_sym_tab; } +function_symtab : // empty + { curr_sym_tab = fbi_sym_tab; } ; local_symtab : // empty @@ -1187,14 +1187,14 @@ } ; -return_list_end : global_symtab ']' +return_list_end : function_symtab ']' ; // =================== // Function definition // =================== -function_beg : save_symtab FCN stash_comment global_symtab +function_beg : save_symtab FCN stash_comment function_symtab { $$ = $3; } ; @@ -1218,7 +1218,7 @@ } ; -function1 : global_symtab '=' function2 +function1 : function_symtab '=' function2 { $$ = $3; } ; @@ -2478,7 +2478,7 @@ warning ("function name `%s' does not agree with function\ file name `%s'", id_name.c_str (), curr_fcn_file_full_name.c_str ()); - global_sym_tab->rename (id_name, curr_fcn_file_name); + fbi_sym_tab->rename (id_name, curr_fcn_file_name); if (error_state) return 0; @@ -2513,7 +2513,7 @@ top_level_sym_tab->clear (id_name); - symbol_record *sr = global_sym_tab->lookup (id_name); + symbol_record *sr = fbi_sym_tab->lookup (id_name); if (sr) fcn->stash_symtab_ptr (sr); @@ -3224,7 +3224,7 @@ { error ("parse error while reading function file %s", ff.c_str ()); - global_sym_tab->clear (curr_fcn_file_name); + fbi_sym_tab->clear (curr_fcn_file_name); } } else if (exec_script)
--- a/src/pt-decl.cc +++ b/src/pt-decl.cc @@ -102,20 +102,24 @@ { id->link_to_global (); - octave_lvalue ult = id->lvalue (); + if (! error_state) + { + octave_lvalue ult = id->lvalue (); - if (ult.is_undefined ()) - { - tree_expression *expr = elt.expression (); + if (ult.is_undefined ()) + { + tree_expression *expr = elt.expression (); - octave_value init_val; + octave_value init_val; - if (expr) - init_val = expr->rvalue (); - else if (Vinitialize_global_variables) - init_val = builtin_any_variable ("default_global_variable_value"); + if (expr) + init_val = expr->rvalue (); + else if (Vinitialize_global_variables) + init_val + = builtin_any_variable ("default_global_variable_value"); - ult.assign (octave_value::op_asn_eq, init_val); + ult.assign (octave_value::op_asn_eq, init_val); + } } } }
--- a/src/pt-id.cc +++ b/src/pt-id.cc @@ -119,7 +119,15 @@ tree_identifier::link_to_global (void) { if (sym) - link_to_global_variable (sym); + { + if (! sym->is_linked_to_global ()) + { + if (sym->is_defined () && sym->is_variable ()) + warning ("local variable value may have changed to match global"); + + link_to_global_variable (sym); + } + } } void
--- a/src/symtab.cc +++ b/src/symtab.cc @@ -202,19 +202,6 @@ { if (! (is_variable () && read_only_error ("redefine"))) { - if (is_function () || is_constant ()) - { - if (Vvariables_can_hide_functions) - { - push_def (new symbol_def ()); - - if (Vvariables_can_hide_functions < 0) - warning ("variable `%s' hides function", nm.c_str ()); - } - else - error ("variable `%s' hides function", nm.c_str ()); - } - if (definition->type () == symbol_record::BUILTIN_VARIABLE) sym_type = symbol_record::BUILTIN_VARIABLE; @@ -255,7 +242,9 @@ { octave_value tmp (f); - replace_all_defs (new symbol_def (tmp, sym_type)); + delete definition; + + definition = new symbol_def (tmp, sym_type); retval = true; } @@ -266,30 +255,27 @@ void symbol_record::clear (void) { - if (linked_to_global) + if (! tagged_static) { if (--definition->count <= 0) delete definition; definition = new symbol_def (); + } - linked_to_global = 0; - } - else if (! tagged_static) - { - remove_top_def (); - - if (! definition) - definition = new symbol_def (); - } + if (linked_to_global) + linked_to_global = 0; } void -symbol_record::alias (symbol_record *s, bool /* force */) +symbol_record::alias (symbol_record *s) { chg_fcn = s->chg_fcn; - replace_all_defs (s->definition); + if (--definition->count <= 0) + delete definition; + + definition = (s->definition); definition->count++; } @@ -329,38 +315,6 @@ tagged_static = 1; } -bool -symbol_record::hides_fcn (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; -} - -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_builtin_function ()) - retval = true; - } - - return retval; -} - octave_value& symbol_record::variable_value (void) { @@ -372,7 +326,7 @@ inline void symbol_record::link_to_builtin_variable (void) { - symbol_record *tmp_sym = global_sym_tab->lookup (name ()); + symbol_record *tmp_sym = fbi_sym_tab->lookup (name ()); if (tmp_sym && tmp_sym->is_builtin_variable ()) alias (tmp_sym); @@ -437,7 +391,10 @@ if (! context.empty ()) { - replace_all_defs (context.pop ()); + if (--definition->count <= 0) + delete definition; + + definition = context.pop (); linked_to_global = global_link_context.pop (); } @@ -448,9 +405,6 @@ { os << (is_read_only () ? " r-" : " rw") << (is_eternal () ? "-" : "d") -#if 0 - << (hides_fcn () ? "f" : (hides_builtin () ? "F" : "-")) -#endif << " " << std::setiosflags (std::ios::left) << std::setw (24) << type_name () . c_str (); @@ -502,42 +456,6 @@ return false; } -void -symbol_record::push_def (symbol_def *sd) -{ - if (! sd) - return; - - assert (definition == 0 || definition->next_elem == 0); - - sd->next_elem = definition; - - definition = sd; -} - -void -symbol_record::remove_top_def (void) -{ - symbol_def *top = definition; - - definition = definition->next_elem; - - if (--top->count <= 0) - delete top; -} - -void -symbol_record::replace_all_defs (symbol_def *sd) -{ - while (definition) - remove_top_def (); - - if (! sd) - sd = new symbol_def (); - - push_def (sd); -} - // A symbol table. symbol_record * @@ -605,8 +523,46 @@ new_name.c_str ()); } +// XXX FIXME XXX -- it would be nice to eliminate a lot of the +// following duplicate code. + void -symbol_table::clear (bool clear_user_functions) +symbol_table::clear (void) +{ + for (unsigned int i = 0; i < table_size; i++) + { + symbol_record *ptr = table[i].next (); + + while (ptr) + { + ptr->clear (); + + ptr = ptr->next (); + } + } +} + +void +symbol_table::clear_variables (void) +{ + for (unsigned int i = 0; i < table_size; i++) + { + symbol_record *ptr = table[i].next (); + + while (ptr) + { + if (ptr->is_user_variable ()) + ptr->clear (); + + ptr = ptr->next (); + } + } +} + +// Really only clear functions that can be reloaded. + +void +symbol_table::clear_functions (void) { for (unsigned int i = 0; i < table_size; i++) { @@ -614,12 +570,25 @@ while (ptr) { - if (ptr->is_user_variable () - || (clear_user_functions - && (ptr->is_user_function () || ptr->is_dld_function ()))) - { - ptr->clear (); - } + if (ptr->is_user_function () || ptr->is_dld_function ()) + ptr->clear (); + + ptr = ptr->next (); + } + } +} + +void +symbol_table::clear_globals (void) +{ + for (unsigned int i = 0; i < table_size; i++) + { + symbol_record *ptr = table[i].next (); + + while (ptr) + { + if (ptr->is_user_variable () && ptr->is_linked_to_global ()) + ptr->clear (); ptr = ptr->next (); } @@ -627,7 +596,47 @@ } bool -symbol_table::clear (const std::string& nm, bool clear_user_functions) +symbol_table::clear (const std::string& nm) +{ + unsigned int index = hash (nm); + + symbol_record *ptr = table[index].next (); + + while (ptr) + { + if (ptr->name () == nm) + { + ptr->clear (); + return true; + } + ptr = ptr->next (); + } + + return false; +} + +bool +symbol_table::clear_variable (const std::string& nm) +{ + unsigned int index = hash (nm); + + symbol_record *ptr = table[index].next (); + + while (ptr) + { + if (ptr->name () == nm && ptr->is_user_variable ()) + { + ptr->clear (); + return true; + } + ptr = ptr->next (); + } + + return false; +} + +bool +symbol_table::clear_global (const std::string& nm) { unsigned int index = hash (nm); @@ -636,9 +645,31 @@ while (ptr) { if (ptr->name () == nm - && (ptr->is_user_variable () - || (clear_user_functions - && (ptr->is_user_function () || ptr->is_dld_function ())))) + && ptr->is_user_variable () + && ptr->is_linked_to_global ()) + { + ptr->clear (); + return true; + } + ptr = ptr->next (); + } + + return false; +} + +// Really only clear functions that can be reloaded. + +bool +symbol_table::clear_function (const std::string& nm) +{ + unsigned int index = hash (nm); + + symbol_record *ptr = table[index].next (); + + while (ptr) + { + if (ptr->name () == nm + && (ptr->is_user_function () || ptr->is_dld_function ())) { ptr->clear (); return true; @@ -649,6 +680,98 @@ return false; } +bool +symbol_table::clear_variable_pattern (const std::string& pat) +{ + bool retval = false; + + for (unsigned int i = 0; i < table_size; i++) + { + symbol_record *ptr = table[i].next (); + + while (ptr) + { + if (ptr->is_user_variable ()) + { + glob_match pattern (pat); + + if (pattern.match (ptr->name ())) + { + ptr->clear (); + + retval = true; + } + } + + ptr = ptr->next (); + } + } + + return retval; +} + +bool +symbol_table::clear_global_pattern (const std::string& pat) +{ + bool retval = false; + + for (unsigned int i = 0; i < table_size; i++) + { + symbol_record *ptr = table[i].next (); + + while (ptr) + { + if (ptr->is_user_variable () && ptr->is_linked_to_global ()) + { + glob_match pattern (pat); + + if (pattern.match (ptr->name ())) + { + ptr->clear (); + + retval = true; + } + } + + ptr = ptr->next (); + } + } + + return retval; +} + +// Really only clear functions that can be reloaded. + +bool +symbol_table::clear_function_pattern (const std::string& pat) +{ + bool retval = false; + + for (unsigned int i = 0; i < table_size; i++) + { + symbol_record *ptr = table[i].next (); + + while (ptr) + { + if (ptr->is_user_function () || ptr->is_dld_function ()) + { + glob_match pattern (pat); + + if (pattern.match (ptr->name ())) + { + ptr->clear (); + + retval = true; + } + } + + ptr = ptr->next (); + } + } + + return retval; +} + int symbol_table::size (void) const {
--- a/src/symtab.h +++ b/src/symtab.h @@ -79,7 +79,7 @@ symbol_def (const octave_value& val = octave_value (), unsigned int sym_type = 0) : symbol_type (sym_type), eternal (0), read_only (0), help_string (), - definition (val), next_elem (0), count (1) { } + definition (val), count (1) { } ~symbol_def (void) { } @@ -197,11 +197,6 @@ // The value of this definition. See ov.h and related files. octave_value definition; - // Pointer to next definition in chain. This is used so that - // variables can hide function definitions, and so that the function - // definitions can reappear if the variable is cleared. - symbol_def *next_elem; - // Reference count. int count; @@ -303,7 +298,7 @@ void clear (void); - void alias (symbol_record *s, bool force = false); + void alias (symbol_record *s); void mark_as_formal_parameter (void); bool is_formal_parameter (void) const { return formal_param; } @@ -314,9 +309,6 @@ void mark_as_static (void); bool is_static (void) const { return tagged_static; } - bool hides_fcn (void) const; - bool hides_builtin (void) const; - int rows (void) const { return definition->rows (); } int columns (void) const { return definition->columns (); } @@ -366,12 +358,6 @@ bool read_only_error (const char *action); - void push_def (symbol_def *sd); - - void remove_top_def (void); - - void replace_all_defs (symbol_def *sd); - void link_to_builtin_variable (void); // No copying! @@ -407,22 +393,36 @@ symbol_table (unsigned int tab_size = 128) : table_size (tab_size), table (new symbol_record [table_size]) - { - assert ((tab_size % 2) == 0); - } + { + assert ((tab_size % 2) == 0); + } ~symbol_table (void) - { - delete [] table; - } + { + clear (); + delete [] table; + } symbol_record *lookup (const std::string& nm, bool insert = false, bool warn = false); void rename (const std::string& old_name, const std::string& new_name); - void clear (bool clear_user_functions = true); - bool clear (const std::string& nm, bool clear_user_functions = true); + void clear (void); + + void clear_variables (void); + void clear_functions (void); + void clear_globals (void); + + bool clear (const std::string& nm); + + bool clear_variable (const std::string& nm); + bool clear_function (const std::string& nm); + bool clear_global (const std::string& nm); + + bool clear_variable_pattern (const std::string& pat); + bool clear_function_pattern (const std::string& pat); + bool clear_global_pattern (const std::string& pat); int size (void) const; @@ -437,6 +437,28 @@ bool sort = false, unsigned int type = SYMTAB_ALL_TYPES, unsigned int scope = SYMTAB_ALL_SCOPES) const; + string_vector + user_function_name_list (void) const + { + return name_list + (string_vector (), false, + symbol_record::USER_FUNCTION|symbol_record::DLD_FUNCTION, + SYMTAB_ALL_SCOPES); + } + + string_vector + global_variable_name_list (void) const + { + return name_list + (string_vector (), false, SYMTAB_VARIABLES, SYMTAB_GLOBAL_SCOPE); + } + + string_vector + variable_name_list (void) const + { + return name_list + (string_vector (), false, SYMTAB_VARIABLES, SYMTAB_LOCAL_SCOPE); + } int maybe_list (const char *header, const string_vector& argv, std::ostream& os, bool show_verbose,
--- a/src/variables.cc +++ b/src/variables.cc @@ -67,6 +67,9 @@ // Symbol table for global symbols. symbol_table *global_sym_tab = 0; +// Symbol table for functions and built-in symbols. +symbol_table *fbi_sym_tab = 0; + // Initialization. // Create the initial symbol tables and set the current scope at the @@ -75,6 +78,9 @@ void initialize_symbol_tables (void) { + if (! fbi_sym_tab) + fbi_sym_tab = new symbol_table (2048); + if (! global_sym_tab) global_sym_tab = new symbol_table (2048); @@ -91,7 +97,7 @@ bool is_builtin_variable (const std::string& name) { - symbol_record *sr = global_sym_tab->lookup (name); + symbol_record *sr = fbi_sym_tab->lookup (name); return (sr && sr->is_builtin_variable ()); } @@ -100,7 +106,7 @@ bool is_text_function_name (const std::string& s) { - symbol_record *sr = global_sym_tab->lookup (s); + symbol_record *sr = fbi_sym_tab->lookup (s); return (sr && sr->is_text_function ()); } @@ -109,7 +115,7 @@ bool is_builtin_function_name (const std::string& s) { - symbol_record *sr = global_sym_tab->lookup (s); + symbol_record *sr = fbi_sym_tab->lookup (s); return (sr && sr->is_builtin_function ()); } @@ -118,7 +124,7 @@ bool is_mapper_function_name (const std::string& s) { - symbol_record *sr = global_sym_tab->lookup (s); + symbol_record *sr = fbi_sym_tab->lookup (s); return (sr && sr->is_mapper_function ()); } @@ -142,7 +148,7 @@ if (! fcn_name.empty ()) { - sr = global_sym_tab->lookup (fcn_name, true); + sr = fbi_sym_tab->lookup (fcn_name, true); lookup (sr, false); } @@ -372,7 +378,7 @@ @code{file_in_path} and @code{stat} instead.\n\ @end deftypefn") { - octave_value_list retval; + octave_value retval = 0.0; int nargin = args.length (); @@ -401,29 +407,34 @@ symbol_name = name.substr (0, pos); } + // We shouldn't need to look in the global symbol table, since any + // name that is visible in the current scope will be in the local + // symbol table. + symbol_record *sr = curr_sym_tab->lookup (symbol_name); - if (! (sr && (sr->is_defined () - || (curr_sym_tab != top_level_sym_tab)))) - sr = global_sym_tab->lookup (symbol_name); - retval = 0.0; + if (! (sr && sr->is_defined ())) + sr = fbi_sym_tab->lookup (symbol_name); - if (sr && sr->is_variable () && sr->is_defined ()) + if (sr && sr->is_defined ()) { - if (struct_elts.empty () || sr->is_map_element (struct_elts)) - retval = 1.0; - } - else if (sr && sr->is_builtin_function ()) - { - retval = 5.0; - } - else if (sr && sr->is_builtin_constant ()) - { - retval = 6.0; - } - else if (sr && sr->is_user_function ()) - { - retval = 2.0; + if (sr->is_variable ()) + { + if (struct_elts.empty () || sr->is_map_element (struct_elts)) + retval = 1.0; + } + else if (sr->is_builtin_function ()) + { + retval = 5.0; + } + else if (sr->is_builtin_constant ()) + { + retval = 6.0; + } + else if (sr->is_user_function ()) + { + retval = 2.0; + } } else { @@ -589,7 +600,7 @@ std::string builtin_string_variable (const std::string& name) { - symbol_record *sr = global_sym_tab->lookup (name); + symbol_record *sr = fbi_sym_tab->lookup (name); // It is a prorgramming error to look for builtins that aren't. @@ -613,7 +624,7 @@ builtin_real_scalar_variable (const std::string& name, double& d) { int status = 0; - symbol_record *sr = global_sym_tab->lookup (name); + symbol_record *sr = fbi_sym_tab->lookup (name); // It is a prorgramming error to look for builtins that aren't. @@ -635,7 +646,7 @@ octave_value builtin_any_variable (const std::string& name) { - symbol_record *sr = global_sym_tab->lookup (name); + symbol_record *sr = fbi_sym_tab->lookup (name); // It is a prorgramming error to look for builtins that aren't. @@ -663,17 +674,12 @@ symbol_record *gsr = global_sym_tab->lookup (nm, true); - // There must be a better way to do this. XXX FIXME XXX - - if (sr->is_variable ()) - gsr->define (sr->def ()); - // Make sure this symbol is a variable. - if (! gsr->is_variable ()) + if (! gsr->is_user_variable ()) gsr->define (octave_value ()); - sr->alias (gsr, 1); + sr->alias (gsr); } } } @@ -689,7 +695,7 @@ void link_to_builtin_or_function (symbol_record *sr) { - symbol_record *tmp_sym = global_sym_tab->lookup (sr->name ()); + symbol_record *tmp_sym = fbi_sym_tab->lookup (sr->name ()); if (tmp_sym && (tmp_sym->is_builtin_variable () @@ -710,12 +716,12 @@ void force_link_to_function (const std::string& id_name) { - symbol_record *gsr = global_sym_tab->lookup (id_name, true); - if (gsr->is_function ()) + symbol_record *fsr = fbi_sym_tab->lookup (id_name, true); + if (fsr->is_function ()) { curr_sym_tab->clear (id_name); symbol_record *csr = curr_sym_tab->lookup (id_name, true); - csr->alias (gsr); + csr->alias (fsr); } } @@ -825,22 +831,22 @@ if (show_builtins) { - pad_after += global_sym_tab->maybe_list + pad_after += fbi_sym_tab->maybe_list ("*** built-in constants:", pats, octave_stdout, show_verbose, symbol_record::BUILTIN_CONSTANT, SYMTAB_ALL_SCOPES); - pad_after += global_sym_tab->maybe_list + pad_after += fbi_sym_tab->maybe_list ("*** built-in variables:", pats, octave_stdout, show_verbose, symbol_record::BUILTIN_VARIABLE, SYMTAB_ALL_SCOPES); - pad_after += global_sym_tab->maybe_list + pad_after += fbi_sym_tab->maybe_list ("*** built-in functions:", pats, octave_stdout, show_verbose, symbol_record::BUILTIN_FUNCTION, SYMTAB_ALL_SCOPES); } if (show_functions) { - pad_after += global_sym_tab->maybe_list + pad_after += fbi_sym_tab->maybe_list ("*** currently compiled functions:", pats, octave_stdout, show_verbose, symbol_record::USER_FUNCTION, SYMTAB_ALL_SCOPES); @@ -948,7 +954,7 @@ void bind_ans (const octave_value& val, bool print) { - static symbol_record *sr = global_sym_tab->lookup ("ans", true); + static symbol_record *sr = fbi_sym_tab->lookup ("ans", true); if (val.is_defined ()) { @@ -969,7 +975,7 @@ bind_builtin_constant (const std::string& name, const octave_value& val, bool protect, bool eternal, const std::string& help) { - symbol_record *sym_rec = global_sym_tab->lookup (name, true); + symbol_record *sym_rec = fbi_sym_tab->lookup (name, true); sym_rec->unprotect (); std::string tmp_help = help.empty () ? sym_rec->help () : help; @@ -997,7 +1003,7 @@ symbol_record::change_function chg_fcn, const std::string& help) { - symbol_record *sr = global_sym_tab->lookup (varname, true); + symbol_record *sr = fbi_sym_tab->lookup (varname, true); // It is a programming error for a builtin symbol to be missing. // Besides, we just inserted it, so it must be there. @@ -1027,8 +1033,8 @@ // Deleting names from the symbol tables. static inline bool -var_matches_any_pattern (const std::string& nm, - const string_vector& argv, int argc, int idx) +name_matches_any_pattern (const std::string& nm, + const string_vector& argv, int argc, int idx) { bool retval = false; @@ -1051,6 +1057,309 @@ return retval; } +static inline bool +is_local_variable (const std::string& nm) +{ + symbol_record *sr = curr_sym_tab->lookup (nm); + + return (sr && sr->is_variable ()); +} + +static inline void +maybe_warn_exclusive (bool exclusive) +{ + if (exclusive) + warning ("clear: ignoring --exclusive option"); +} + +static inline void +do_clear_all (void) +{ + curr_sym_tab->clear (); + fbi_sym_tab->clear_functions (); + global_sym_tab->clear (); +} + +static inline void +do_clear_functions (void) +{ + curr_sym_tab->clear_functions (); + fbi_sym_tab->clear_functions (); +} + +static inline void +do_clear_globals (void) +{ + curr_sym_tab->clear_globals (); + global_sym_tab->clear (); +} + +static inline void +do_clear_variables (void) +{ + curr_sym_tab->clear (); +} + +static inline bool +do_clear_function (const std::string& nm) +{ + bool b1 = curr_sym_tab->clear_function (nm); + + bool b2 = fbi_sym_tab->clear_function (nm); + + return b1 || b2; +} + +static inline bool +do_clear_global (const std::string& nm) +{ + bool b1 = curr_sym_tab->clear_global (nm); + + bool b2 = global_sym_tab->clear_variable (nm); + + return b1 || b2; +} + +static inline bool +do_clear_variable (const std::string& nm) +{ + return curr_sym_tab->clear_variable (nm); +} + +static inline bool +do_clear_symbol (const std::string& nm) +{ + bool cleared = curr_sym_tab->clear_variable (nm); + + if (! cleared) + cleared = do_clear_function (nm); + + return cleared; +} + +static inline bool +do_clear_function_pattern (const std::string& pat) +{ + bool b1 = curr_sym_tab->clear_function_pattern (pat); + + bool b2 = fbi_sym_tab->clear_function_pattern (pat); + + return b1 || b2; +} + +static inline bool +do_clear_global_pattern (const std::string& pat) +{ + bool b1 = curr_sym_tab->clear_global_pattern (pat); + + bool b2 = global_sym_tab->clear_variable_pattern (pat); + + return b1 || b2; +} + +static inline bool +do_clear_variable_pattern (const std::string& pat) +{ + return curr_sym_tab->clear_variable_pattern (pat); +} + +static inline bool +do_clear_symbol_pattern (const std::string& pat) +{ + // XXX FIXME XXX -- if we have a variable v1 and a function v2 and + // someone says clear v*, we will clear the variable but not the + // function. Is that really what should happen? (I think it is + // what Matlab does.) + + bool cleared = curr_sym_tab->clear_variable_pattern (pat); + + if (! cleared) + cleared = do_clear_function_pattern (pat); + + return cleared; +} + +static inline void +do_clear_functions (const string_vector& argv, int argc, int idx, + bool exclusive = false) +{ + if (idx == argc) + do_clear_functions (); + else + { + if (exclusive) + { + string_vector lfcns = curr_sym_tab->user_function_name_list (); + + int lcount = lfcns.length (); + + for (int i = 0; i < lcount; i++) + { + std::string nm = lfcns[i]; + + if (! name_matches_any_pattern (nm, argv, argc, idx)) + do_clear_function (nm); + } + + string_vector fcns = fbi_sym_tab->user_function_name_list (); + + int fcount = fcns.length (); + + for (int i = 0; i < fcount; i++) + { + std::string nm = fcns[i]; + + if (! name_matches_any_pattern (nm, argv, argc, idx)) + do_clear_function (nm); + } + } + else + { + while (idx < argc) + do_clear_function_pattern (argv[idx++]); + } + } +} + +static inline void +do_clear_globals (const string_vector& argv, int argc, int idx, + bool exclusive = false) +{ + if (idx == argc) + do_clear_globals (); + else + { + if (exclusive) + { + string_vector lvars = curr_sym_tab->global_variable_name_list (); + + int lcount = lvars.length (); + + for (int i = 0; i < lcount; i++) + { + std::string nm = lvars[i]; + + if (! name_matches_any_pattern (nm, argv, argc, idx)) + do_clear_global (nm); + } + + string_vector gvars = global_sym_tab->global_variable_name_list (); + + int gcount = gvars.length (); + + for (int i = 0; i < gcount; i++) + { + std::string nm = gvars[i]; + + if (! name_matches_any_pattern (nm, argv, argc, idx)) + do_clear_global (nm); + } + } + else + { + while (idx < argc) + do_clear_global_pattern (argv[idx++]); + } + } +} + +static inline void +do_clear_variables (const string_vector& argv, int argc, int idx, + bool exclusive = false) +{ + if (idx == argc) + do_clear_variables (); + else + { + if (exclusive) + { + string_vector lvars = curr_sym_tab->variable_name_list (); + + int lcount = lvars.length (); + + for (int i = 0; i < lcount; i++) + { + std::string nm = lvars[i]; + + if (! name_matches_any_pattern (nm, argv, argc, idx)) + do_clear_variable (nm); + } + } + else + { + while (idx < argc) + do_clear_variable_pattern (argv[idx++]); + } + } +} + +static inline void +do_clear_symbols (const string_vector& argv, int argc, int idx, + bool exclusive = false) +{ + if (idx == argc) + do_clear_variables (); + else + { + if (exclusive) + { + // XXX FIXME XXX -- is this really what we want, or do we + // somehow want to only clear the functions that are not + // shadowed by local variables? It seems that would be a + // bit harder to do. + + do_clear_variables (argv, argc, idx, exclusive); + do_clear_functions (argv, argc, idx, exclusive); + } + else + { + while (idx < argc) + do_clear_symbol_pattern (argv[idx++]); + } + } +} + +static void +do_matlab_compatible_clear (const string_vector& argv, int argc, int idx) +{ + // This is supposed to be mostly Matlab compatible. + + for (; idx < argc; idx++) + { + if (argv[idx] == "all" && ! is_local_variable ("all")) + { + do_clear_all (); + } + else if (argv[idx] == "functions" && ! is_local_variable ("functions")) + { + do_clear_functions (argv, argc, ++idx); + } + else if (argv[idx] == "global" && ! is_local_variable ("global")) + { + do_clear_globals (argv, argc, ++idx); + } + else if (argv[idx] == "variables" && ! is_local_variable ("variables")) + { + do_clear_variables (); + } + else + { + do_clear_symbol_pattern (argv[idx]); + } + } +} + +#define CLEAR_OPTION_ERROR(cond) \ + do \ + { \ + if (cond) \ + { \ + print_usage ("clear"); \ + return retval; \ + } \ + } \ + while (0) + DEFUN_TEXT (clear, args, , "-*- texinfo -*-\n\ @deffn {Command} clear [-x] pattern @dots{}\n\ @@ -1101,147 +1410,97 @@ string_vector argv = args.make_argv ("clear"); - if (error_state) - return retval; - - // Always clear the local table, but don't clear currently compiled - // functions unless we are at the top level. (Allowing that to - // happen inside functions would result in pretty odd behavior...) - - bool clear_user_functions = (curr_sym_tab == top_level_sym_tab); - - if (argc == 1) - { - curr_sym_tab->clear (); - global_sym_tab->clear (clear_user_functions); - } - else + if (! error_state) { - int exclusive = 0; - - int idx = 1; - - if (argc > 1) - { - if (argv[idx] == "-x") - { - idx++; - exclusive = 1; - } - } - - string_vector lvars; - string_vector gvars; - string_vector fcns; - - if (argc > 0) + if (argc == 1) { - string_vector tmp; - - lvars = curr_sym_tab->name_list - (tmp, false, SYMTAB_VARIABLES, SYMTAB_LOCAL_SCOPE); - - gvars = curr_sym_tab->name_list - (tmp, false, SYMTAB_VARIABLES, SYMTAB_GLOBAL_SCOPE); - - fcns = global_sym_tab->name_list - (tmp, false, - symbol_record::USER_FUNCTION|symbol_record::DLD_FUNCTION, - SYMTAB_ALL_SCOPES); - } - - // XXX FIXME XXX -- this needs to be optimized to avoid the - // pattern matching code if the string doesn't contain any - // globbing patterns. - - if (exclusive) - { - int lcount = lvars.length (); - - for (int i = 0; i < lcount; i++) - { - std::string nm = lvars[i]; - - if (! var_matches_any_pattern (nm, argv, argc, idx)) - curr_sym_tab->clear (nm); - } - - int gcount = gvars.length (); - - for (int i = 0; i < gcount; i++) - { - std::string nm = gvars[i]; - - if (! var_matches_any_pattern (nm, argv, argc, idx)) - { - int count = curr_sym_tab->clear (nm); - - if (count > 0) - global_sym_tab->clear (nm, clear_user_functions); - } - } - - int fcount = fcns.length (); - - for (int i = 0; i < fcount; i++) - { - std::string nm = fcns[i]; - - if (! var_matches_any_pattern (nm, argv, argc, idx)) - { - curr_sym_tab->clear (nm); - - global_sym_tab->clear (nm, clear_user_functions); - } - } + do_clear_variables (); } else { - for (int k = idx; k < argc; k++) - { - std::string patstr = argv[k]; + int idx = 0; + + bool clear_all = false; + bool clear_functions = false; + bool clear_globals = false; + bool clear_variables = false; + bool exclusive = false; + bool have_dash_option = false; - if (! patstr.empty ()) + while (++idx < argc) + { + if (argv[idx] == "--all" || argv[idx] == "-a") { - glob_match pattern (patstr); + CLEAR_OPTION_ERROR (have_dash_option && ! exclusive); - int lcount = lvars.length (); + have_dash_option = true; + clear_all = true; + } + else if (argv[idx] == "--exclusive" || argv[idx] == "-x") + { + have_dash_option = true; + exclusive = true; + } + else if (argv[idx] == "--functions" || argv[idx] == "-f") + { + CLEAR_OPTION_ERROR (have_dash_option && ! exclusive); - for (int i = 0; i < lcount; i++) - { - std::string nm = lvars[i]; + have_dash_option = true; + clear_functions = true; + } + else if (argv[idx] == "--global" || argv[idx] == "-g") + { + CLEAR_OPTION_ERROR (have_dash_option && ! exclusive); + + have_dash_option = true; + clear_globals = true; + } + else if (argv[idx] == "--variables" || argv[idx] == "-v") + { + CLEAR_OPTION_ERROR (have_dash_option && ! exclusive); - if (pattern.match (nm)) - curr_sym_tab->clear (nm); - } + have_dash_option = true; + clear_variables = true; + } + else + break; + } - int gcount = gvars.length (); - - for (int i = 0; i < gcount; i++) + if (idx < argc) + { + if (! have_dash_option) + { + do_matlab_compatible_clear (argv, argc, idx); + } + else + { + if (clear_all) { - std::string nm = gvars[i]; + maybe_warn_exclusive (exclusive); - if (pattern.match (nm)) - { - int count = curr_sym_tab->clear (nm); - - if (count > 0) - global_sym_tab->clear (nm, clear_user_functions); - } - } + if (++idx < argc) + warning + ("clear: ignoring extra arguments after --all"); - int fcount = fcns.length (); - - for (int i = 0; i < fcount; i++) + curr_sym_tab->clear (); + fbi_sym_tab->clear_functions (); + global_sym_tab->clear (); + } + else if (clear_functions) + { + do_clear_functions (argv, argc, idx, exclusive); + } + else if (clear_globals) { - std::string nm = fcns[i]; - - if (pattern.match (nm)) - { - curr_sym_tab->clear (nm); - - global_sym_tab->clear (nm, clear_user_functions); - } + do_clear_globals (argv, argc, idx, exclusive); + } + else if (clear_variables) + { + do_clear_variables (argv, argc, idx, exclusive); + } + else + { + do_clear_symbols (argv, argc, idx, exclusive); } } } @@ -1265,17 +1524,19 @@ { std::string arg = args(0).string_value (); - if (arg == "global") + if (arg == "fbi") + fbi_sym_tab->print_info (octave_stdout); + else if (arg == "global") global_sym_tab->print_info (octave_stdout); else if (arg == "top-level") top_level_sym_tab->print_info (octave_stdout); else { - symbol_record *gsr = global_sym_tab->lookup (arg, true); + symbol_record *fsr = fbi_sym_tab->lookup (arg, true); - if (gsr && gsr->is_user_function ()) + if (fsr && fsr->is_user_function ()) { - octave_value tmp = gsr->def (); + octave_value tmp = fsr->def (); const octave_value& rep = tmp.get_rep (); const octave_user_function& fcn