Mercurial > octave-nkf
diff src/variables.cc @ 529:7ea224e713cd
[project @ 1994-07-20 18:54:27 by jwe]
author | jwe |
---|---|
date | Wed, 20 Jul 1994 19:19:08 +0000 |
parents | 0f388340e607 |
children | 682393bf54f7 |
line wrap: on
line diff
--- a/src/variables.cc Wed Jul 20 18:53:50 1994 +0000 +++ b/src/variables.cc Wed Jul 20 19:19:08 1994 +0000 @@ -30,21 +30,37 @@ #include <unistd.h> #endif #include <ctype.h> +#include <float.h> +#include <string.h> +#include <fstream.h> #include <iostream.h> #include <strstream.h> #include "statdefs.h" #include "tree-const.h" #include "variables.h" +#include "mappers.h" #include "user-prefs.h" +#include "version.h" #include "symtab.h" -#include "builtins.h" -#include "g-builtins.h" -#include "t-builtins.h" +#include "defaults.h" +#include "dirfns.h" +#include "pager.h" +#include "sysdep.h" +#include "octave.h" +#include "oct-obj.h" #include "error.h" #include "utils.h" #include "tree.h" #include "help.h" +#include "defun.h" + +extern "C" +{ +#include <readline/tilde.h> + +#include "fnmatch.h" +} // Symbol table for symbols at the top level. symbol_table *top_level_sym_tab; @@ -77,14 +93,13 @@ if (ignore == 2) return 0; - if (sr != (symbol_record *) NULL) + if (sr) { tree_fvc *ans = sr->def (); - if (ans != (tree_fvc *) NULL) + if (ans) { char *ff = ans->fcn_file_name (); - if (! (ff == (char *) NULL - || (ignore && ans->is_system_fcn_file ()))) + if (ff && ! (ignore && ans->is_system_fcn_file ())) { time_t tp = ans->time_parsed (); char *fname = fcn_file_in_path (ff); @@ -108,19 +123,15 @@ else { symbol_record *sym_rec = curr_sym_tab->lookup (name, 0); - if (sym_rec == (symbol_record *) NULL) - { - error ("document: no such symbol `%s'", name); - } + if (sym_rec) + sym_rec->document (help); else - { - sym_rec->document (help); - } + error ("document: no such symbol `%s'", name); } } void -install_builtin_mapper_function (builtin_mapper_functions *mf) +install_builtin_mapper (builtin_mapper_function *mf) { symbol_record *sym_rec = global_sym_tab->lookup (mf->name, 1); sym_rec->unprotect (); @@ -143,56 +154,43 @@ } void -install_builtin_text_function (builtin_text_functions *tf) +install_builtin_function (builtin_function *f) { - symbol_record *sym_rec = global_sym_tab->lookup (tf->name, 1); + symbol_record *sym_rec = global_sym_tab->lookup (f->name, 1); sym_rec->unprotect (); - tree_builtin *def = new tree_builtin (tf->nargin_max, 1, - tf->text_fcn, tf->name); - - sym_rec->define (def); - - sym_rec->document (tf->help_string); - sym_rec->make_eternal (); - sym_rec->protect (); - -} + tree_builtin *def = new tree_builtin (f->nargin_max, f->nargout_max, + f->fcn, f->name); -void -install_builtin_general_function (builtin_general_functions *gf) -{ - symbol_record *sym_rec = global_sym_tab->lookup (gf->name, 1); - sym_rec->unprotect (); + sym_rec->define (def, f->is_text_fcn); - tree_builtin *def = new tree_builtin (gf->nargin_max, - gf->nargout_max, - gf->general_fcn, gf->name); - - sym_rec->define (def); - - sym_rec->document (gf->help_string); + sym_rec->document (f->help_string); sym_rec->make_eternal (); sym_rec->protect (); } void -install_builtin_variable (builtin_string_variables *sv) +install_builtin_variable (builtin_variable *v) { - tree_constant *val = new tree_constant (sv->value); - - bind_builtin_variable (sv->name, val, 0, 1, sv->sv_function, - sv->help_string); + if (v->install_as_function) + install_builtin_variable_as_function (v->name, v->value, v->protect, + v->eternal, v->help_string); + else + bind_builtin_variable (v->name, v->value, v->protect, v->eternal, + v->sv_function, v->help_string); } void install_builtin_variable_as_function (const char *name, tree_constant *val, - int protect = 0, int eternal = 0) + int protect, int eternal, + const char *help) { symbol_record *sym_rec = global_sym_tab->lookup (name, 1); sym_rec->unprotect (); - char *tmp_help = sym_rec->help (); + const char *tmp_help = help; + if (! help) + tmp_help = sym_rec->help (); sym_rec->define_as_fcn (val); @@ -230,16 +228,15 @@ */ void bind_builtin_variable (const char *varname, tree_constant *val, - int protect = 0, int eternal = 0, - sv_Function sv_fcn = (sv_Function) 0, - const char *help = (char *) 0) + int protect, int eternal, sv_Function sv_fcn, + const char *help) { symbol_record *sr = global_sym_tab->lookup (varname, 1, 0); // It is a programming error for a builtin symbol to be missing. // Besides, we just inserted it, so it must be there. - assert (sr != (symbol_record *) NULL); + assert (sr); sr->unprotect (); @@ -264,7 +261,7 @@ /* * Look for the given name in the global symbol table. If it refers - * to a string, return a new copy. If not, return NULL. + * to a string, return a new copy. If not, return 0; */ char * builtin_string_variable (const char *name) @@ -273,20 +270,20 @@ // It is a prorgramming error to look for builtins that aren't. - assert (sr != (symbol_record *) NULL); + assert (sr); - char *retval = (char *) NULL; + char *retval = 0; tree_fvc *defn = sr->def (); - if (defn != (tree_fvc *) NULL) + if (defn) { tree_constant val = defn->eval (0); if (! error_state && val.is_string_type ()) { char *s = val.string_value (); - if (s != (char *) NULL) + if (s) retval = strsave (s); } } @@ -307,11 +304,11 @@ // It is a prorgramming error to look for builtins that aren't. - assert (sr != (symbol_record *) NULL); + assert (sr); tree_fvc *defn = sr->def (); - if (defn != (tree_fvc *) NULL) + if (defn) { tree_constant val = defn->eval (0); @@ -351,22 +348,20 @@ { // Would be nice not to have this cast. XXX FIXME XXX tree_constant *tmp = (tree_constant *) sr->def (); - if (tmp == NULL_TREE_CONST) + if (tmp) + tmp = new tree_constant (*tmp); + else tmp = new tree_constant (); - else - tmp = new tree_constant (*tmp); gsr->define (tmp); } else - { - sr->clear (); - } + sr->clear (); // If the global symbol is currently defined as a function, we need to // hide it with a variable. if (gsr->is_function ()) - gsr->define (NULL_TREE_CONST); + gsr->define ((tree_constant *) 0); sr->alias (gsr, 1); sr->mark_as_linked_to_global (); @@ -381,13 +376,8 @@ { symbol_record *tmp_sym = global_sym_tab->lookup (sr->name (), 0, 0); - if (tmp_sym != (symbol_record *) NULL) - { - if (tmp_sym->is_builtin_variable ()) - { - sr->alias (tmp_sym); - } - } + if (tmp_sym && tmp_sym->is_builtin_variable ()) + sr->alias (tmp_sym); } /* @@ -401,14 +391,10 @@ { symbol_record *tmp_sym = global_sym_tab->lookup (sr->name (), 0, 0); - if (tmp_sym != (symbol_record *) NULL) - { - if ((tmp_sym->is_builtin_variable () || tmp_sym->is_function ()) - && ! tmp_sym->is_formal_parameter ()) - { - sr->alias (tmp_sym); - } - } + if (tmp_sym + && (tmp_sym->is_builtin_variable () || tmp_sym->is_function ()) + && ! tmp_sym->is_formal_parameter ()) + sr->alias (tmp_sym); } /* @@ -432,15 +418,27 @@ } } -/* - * Return 1 if the argument names a globally visible variable. - * Otherwise, return 0. - */ -int -is_globally_visible (const char *name) +DEFUN ("is_global", Fis_global, Sis_global, 2, 1, + "is_global (X): return 1 if the string X names a global variable\n\ +otherwise, return 0.") { + Octave_object retval (0.0); + + int nargin = args.length (); + + if (nargin != 2 || ! args(1).is_string_type ()) + { + print_usage ("is_global"); + return retval; + } + + char *name = args(1).string_value (); + symbol_record *sr = curr_sym_tab->lookup (name, 0, 0); - return (sr != (symbol_record *) NULL && sr->is_linked_to_global ()); + + retval = (double) (sr && sr->is_linked_to_global ()); + + return retval; } /* @@ -457,7 +455,7 @@ { ostrstream buf; - char *retval = (char *) NULL; + char *retval = 0; char c; while (is.get (c)) @@ -576,7 +574,7 @@ int valid_identifier (char *s) { - if (s == (char *) NULL || ! (isalnum (*s) || *s == '_')) + if (! s || ! (isalnum (*s) || *s == '_')) return 0; while (*++s != '\0') @@ -586,36 +584,51 @@ return 1; } -/* - * See if the identifier is in scope. - */ -int -identifier_exists (char *name) +DEFUN ("exist", Fexist, Sexist, 2, 1, + "exist (NAME): check if variable or file exists\n\ +\n\ +return 0 if NAME is undefined, 1 if it is a variable, or 2 if it is\n\ +a function.") { + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2 || ! args(1).is_string_type ()) + { + print_usage ("exist"); + return retval; + } + + char *name = args(1).string_value (); + symbol_record *sr = curr_sym_tab->lookup (name, 0, 0); - if (sr == (symbol_record *) NULL) + if (! sr) sr = global_sym_tab->lookup (name, 0, 0); - if (sr != (symbol_record *) NULL && sr->is_variable () && sr->is_defined ()) - return 1; - else if (sr != (symbol_record *) NULL && sr->is_function ()) - return 2; + retval = 0.0; + + if (sr && sr->is_variable () && sr->is_defined ()) + retval = 1.0; + else if (sr && sr->is_function ()) + retval = 2.0; else { char *path = fcn_file_in_path (name); - if (path != (char *) NULL) + if (path) { delete [] path; - return 2; + retval = 2.0; } else { struct stat buf; if (stat (name, &buf) == 0 && S_ISREG (buf.st_mode)) - return 2; + retval = 2.0; } } - return 0; + + return retval; } /* @@ -625,16 +638,16 @@ is_builtin_variable (const char *name) { symbol_record *sr = global_sym_tab->lookup (name, 0, 0); - return (sr != (symbol_record *) NULL && sr->is_builtin_variable ()); + return (sr && sr->is_builtin_variable ()); } /* * Is this tree_constant a valid function? */ tree_fvc * -is_valid_function (tree_constant& arg, char *warn_for, int warn = 0) +is_valid_function (const tree_constant& arg, char *warn_for, int warn) { - tree_fvc *ans = (tree_fvc *) NULL; + tree_fvc *ans = 0; if (! arg.is_string_type ()) { @@ -646,25 +659,25 @@ char *fcn_name = arg.string_value (); symbol_record *sr = global_sym_tab->lookup (fcn_name, 0, 0); - if (sr == (symbol_record *) NULL) + if (sr && symbol_out_of_date (sr)) + { + tree_identifier tmp (sr); + tmp.parse_fcn_file (0); + } + else { sr = global_sym_tab->lookup (fcn_name, 1, 0); tree_identifier tmp (sr); tmp.parse_fcn_file (0); } - else if (symbol_out_of_date (sr)) - { - tree_identifier tmp (sr); - tmp.parse_fcn_file (0); - } ans = sr->def (); - if (ans == (tree_fvc *) NULL || ! sr->is_function ()) + if (! ans || ! sr->is_function ()) { if (warn) error ("%s: the symbol `%s' is not valid as a function", warn_for, fcn_name); - ans = (tree_fvc *) NULL; + ans = 0; } return ans; @@ -675,7 +688,7 @@ */ int takes_correct_nargs (tree_fvc *fcn, int expected_nargin, char *warn_for, - int warn = 0) + int warn) { int nargin = fcn->max_expected_args () - 1; int e_nargin = expected_nargin - 1; @@ -683,7 +696,7 @@ { if (warn) error ("%s: expecting function to take %d argument%c", - warn_for, e_nargin, s_plural (e_nargin)); + warn_for, e_nargin, (e_nargin == 1 ? "" : "s")); return 0; } return 1; @@ -700,11 +713,11 @@ int lcl_len = 0; int ffl_len = 0; - char **key = (char **) NULL; - char **glb = (char **) NULL; - char **top = (char **) NULL; - char **lcl = (char **) NULL; - char **ffl = (char **) NULL; + char **key = 0; + char **glb = 0; + char **top = 0; + char **lcl = 0; + char **ffl = 0; // Each of these functions returns a new vector of pointers to new // strings. @@ -741,7 +754,7 @@ for (i = 0; i < ffl_len; i++) list[j++] = ffl[i]; - list[j] = (char *) NULL; + list[j] = 0; delete [] key; delete [] glb; @@ -752,6 +765,1224 @@ return list; } +int +is_text_function_name (const char *s) +{ + symbol_record *sr = global_sym_tab->lookup (s); + return (sr && sr->is_text_function ()); +} + +/* + * Help stuff. + */ +help_list * +builtin_mapper_functions_help (void) +{ +#if 0 + int count = 0; + builtin_mapper_functions *mfptr; + + mfptr = mapper_functions; + while (mfptr->name) + { + count++; + mfptr++; + } + + if (count == 0) + return 0; + + help_list *hl = new help_list [count+1]; + + int i = 0; + mfptr = mapper_functions; + while (mfptr->name) + { + hl[i].name = mfptr->name; + hl[i].help = mfptr->help_string; + i++; + mfptr++; + } + + hl[count].name = 0; + hl[count].help = 0; + + return hl; +#endif + + return 0; +} + +help_list * +builtin_general_functions_help (void) +{ +#if 0 + int count = 0; + builtin_general_functions *gfptr; + + gfptr = general_functions; + while (gfptr->name) + { + count++; + gfptr++; + } + + if (count == 0) + return 0; + + help_list *hl = new help_list [count+1]; + + int i = 0; + gfptr = general_functions; + while (gfptr->name) + { + hl[i].name = gfptr->name; + hl[i].help = gfptr->help_string; + i++; + gfptr++; + } + + hl[count].name = 0; + hl[count].help = 0; + + return hl; +#endif + + return 0; +} + +help_list * +builtin_text_functions_help (void) +{ +#if 0 + int count = 0; + builtin_text_functions *tfptr; + + tfptr = text_functions; + while (tfptr->name) + { + count++; + tfptr++; + } + + if (count == 0) + return 0; + + help_list *hl = new help_list [count+1]; + + int i = 0; + tfptr = text_functions; + while (tfptr->name) + { + hl[i].name = tfptr->name; + hl[i].help = tfptr->help_string; + i++; + tfptr++; + } + + hl[count].name = 0; + hl[count].help = 0; + + return hl; +#endif + + return 0; +} + +help_list * +builtin_variables_help (void) +{ +#if 0 + int count = 0; + + builtin_string_variables *svptr; + + svptr = string_variables; + while (svptr->name) + { + count++; + svptr++; + } + + if (count == 0) + return 0; + + help_list *hl = new help_list [count+1]; + + int i = 0; + svptr = string_variables; + while (svptr->name) + { + hl[i].name = svptr->name; + hl[i].help = svptr->help_string; + i++; + svptr++; + } + + hl[count].name = 0; + hl[count].help = 0; + + return hl; +#endif + + return 0; +} + +int +help_from_list (ostrstream& output_buf, const help_list *list, + const char *string, int usage) +{ + char *name; + while ((name = list->name) != 0) + { + if (strcmp (name, string) == 0) + { + if (usage) + output_buf << "\nusage: "; + else + { + output_buf << "\n*** " << string << ":\n\n"; + } + + output_buf << list->help << "\n"; + + return 1; + } + list++; + } + return 0; +} + +void +additional_help_message (ostrstream& output_buf) +{ + output_buf + << "\n" + << "Additional help for builtin functions, operators, and variables\n" + << "is available in the on-line version of the manual.\n" + << "\n" + << "Use the command `help -i <topic>' to search the manual index.\n"; +} + +void +print_usage (const char *string, int just_usage) +{ + ostrstream output_buf; + + help_list *gf_help_list = builtin_general_functions_help (); + help_list *tf_help_list = builtin_text_functions_help (); + help_list *mf_help_list = builtin_mapper_functions_help (); + + if (help_from_list (output_buf, gf_help_list, string, 1) + || help_from_list (output_buf, tf_help_list, string, 1) + || help_from_list (output_buf, mf_help_list, string, 1)) + { + if (! just_usage) + additional_help_message (output_buf); + output_buf << ends; + maybe_page_output (output_buf); + } +} + +void +install_builtin_variables (void) +{ +// XXX FIXME XX -- these should probably be moved to where they +// logically belong instead of being all grouped here. + + DEFVAR ("EDITOR", SBV_EDITOR, editor, 0, 0, 1, sv_editor, + "name of the editor to be invoked by the edit_history command"); + + DEFVAR ("I", SBV_I, Complex (0.0, 1.0), 0, 1, 1, 0, + "sqrt (-1)"); + + DEFVAR ("Inf", SBV_Inf, octave_Inf, 0, 1, 1, 0, + "infinity"); + + DEFVAR ("INFO_FILE", SBV_INFO_FILE, info_file, 0, 0, 1, sv_info_file, + "name of the Octave info file"); + + DEFVAR ("J", SBV_J, Complex (0.0, 1.0), 0, 1, 1, 0, + "sqrt (-1)"); + + #if defined (HAVE_ISNAN) + DEFVAR ("NaN", SBV_NaN, octave_NaN, 0, 1, 1, 0, + "not a number"); + #endif + + DEFVAR ("LOADPATH", SBV_LOADPATH, load_path, 0, 0, 1, sv_loadpath, + "colon separated list of directories to search for scripts"); + + DEFVAR ("PAGER", SBV_PAGER, default_pager (), 0, 0, 1, sv_pager_binary, + "path to pager binary"); + + DEFVAR ("PS1", SBV_PS1, "\\s:\\#> ", 0, 0, 1, sv_ps1, + "primary prompt string"); + + DEFVAR ("PS2", SBV_PS2, "> ", 0, 0, 1, sv_ps2, + "secondary prompt string"); + + DEFVAR ("PWD", SBV_PWD, get_working_directory ("initialize_globals"), + 0, 1, 1, sv_pwd, + "current working directory"); + + DEFVAR ("SEEK_SET", SBV_SEEK_SET, 0.0, 0, 1, 1, 0, + "used with fseek to position file relative to the beginning"); + + DEFVAR ("SEEK_CUR", SBV_SEEK_CUR, 1.0, 0, 1, 1, 0, + "used with fseek to position file relative to the current position"); + + DEFVAR ("SEEK_END", SBV_SEEK_END, 2.0, 0, 1, 1, 0, + "used with fseek to position file relative to the end"); + + DEFVAR ("ans", SBV_ans, , 0, 0, 1, 0, + ""); + + DEFVAR ("commas_in_literal_matrix", SBV_commas_in_literal_matrix, "", + 0, 0, 1, commas_in_literal_matrix, + "control auto-insertion of commas in literal matrices"); + + DEFVAR ("do_fortran_indexing", SBV_do_fortran_indexing, "false", 0, 0, + 1, do_fortran_indexing, + "allow single indices for matrices"); + + DEFVAR ("empty_list_elements_ok", SBV_empty_list_elements_ok, "warn", + 0, 0, 1, empty_list_elements_ok, + "ignore the empty element in expressions like `a = [[], 1]'"); + + DEFVAR ("eps", SBV_eps, DBL_EPSILON, 0, 1, 1, 0, + "machine precision"); + + DEFVAR ("gnuplot_binary", SBV_gnuplot_binary, "gnuplot", 0, 0, 1, + sv_gnuplot_binary, + "path to gnuplot binary"); + + DEFVAR ("i", SBV_i, Complex (0.0, 1.0), 1, 1, 1, 0, + "sqrt (-1)"); + + DEFVAR ("ignore_function_time_stamp", SBV_ignore_function_time_stamp, + "system", 0, 0, 1, + ignore_function_time_stamp, + "don't check to see if function files have changed since they were\n\ + last compiled. Possible values are \"system\" and \"all\""); + + DEFVAR ("implicit_str_to_num_ok", SBV_implicit_str_to_num_ok, "false", + 0, 0, 1, implicit_str_to_num_ok, + "allow implicit string to number conversion"); + + DEFVAR ("inf", SBV_inf, octave_Inf, 0, 1, 1, 0, + "infinity"); + + DEFVAR ("j", SBV_j, Complex (0.0, 1.0), 1, 1, 1, 0, + "sqrt (-1)"); + + #if defined (HAVE_ISNAN) + DEFVAR ("nan", SBV_nan, octave_NaN, 0, 1, 1, 0, + "not a number"); + #endif + + DEFVAR ("ok_to_lose_imaginary_part", SBV_ok_to_lose_imaginary_part, + "warn", 0, 0, 1, ok_to_lose_imaginary_part, + "silently convert from complex to real by dropping imaginary part"); + + DEFVAR ("output_max_field_width", SBV_output_max_field_width, 10.0, 0, + 0, 1, set_output_max_field_width, + "maximum width of an output field for numeric output"); + + DEFVAR ("output_precision", SBV_output_precision, 5.0, 0, 0, 1, + set_output_precision, + "number of significant figures to display for numeric output"); + + DEFVAR ("page_screen_output", SBV_page_screen_output, "true", 0, 0, 1, + page_screen_output, + "if possible, send output intended for the screen through the pager"); + + DEFVAR ("pi", SBV_pi, 4.0 * atan (1.0), 0, 1, 1, 0, + "ratio of the circumference of a circle to its diameter"); + + DEFVAR ("prefer_column_vectors", SBV_prefer_column_vectors, "true", 0, + 0, 1, prefer_column_vectors, + "prefer column/row vectors"); + + DEFVAR ("prefer_zero_one_indexing", SBV_prefer_zero_one_indexing, + "false", 0, 0, 1, prefer_zero_one_indexing, + "when there is a conflict, prefer zero-one style indexing"); + + DEFVAR ("print_answer_id_name", SBV_print_answer_id_name, "true", 0, + 0, 1, print_answer_id_name, + "set output style to print `var_name = ...'"); + + DEFVAR ("print_empty_dimensions", SBV_print_empty_dimensions, "true", + 0, 0, 1, print_empty_dimensions, + "also print dimensions of empty matrices"); + + DEFVAR ("propagate_empty_matrices", SBV_propagate_empty_matrices, + "true", 0, 0, 1, propagate_empty_matrices, + "operations on empty matrices return an empty matrix, not an error"); + + DEFVAR ("resize_on_range_error", SBV_resize_on_range_error, "true", 0, + 0, 1, resize_on_range_error, + "enlarge matrices on assignment"); + + DEFVAR ("return_last_computed_value", SBV_return_last_computed_value, + "false", 0, 0, 1, + return_last_computed_value, + "if a function does not return any values explicitly, return the\n\ + last computed value"); + + DEFVAR ("save_precision", SBV_save_precision, 17.0, 0, 0, 1, + set_save_precision, + "number of significant figures kept by the ASCII save command"); + + DEFVAR ("silent_functions", SBV_silent_functions, "false", 0, 0, 1, + silent_functions, + "suppress printing results in called functions"); + + DEFVAR ("split_long_rows", SBV_split_long_rows, "true", 0, 0, 1, + split_long_rows, + "split long matrix rows instead of wrapping"); + + DEFVAR ("stdin", SBV_stdin, 0.0, 0, 1, 1, 0, + "file number of the standard input stream"); + + DEFVAR ("stdout", SBV_stdout, 1.0, 0, 1, 1, 0, + "file number of the standard output stream"); + + DEFVAR ("stderr", SBV_stderr, 2.0, 0, 1, 1, 0, + "file number of the standard error stream"); + + DEFVAR ("treat_neg_dim_as_zero", SBV_treat_neg_dim_as_zero, "false", + 0, 0, 1, treat_neg_dim_as_zero, + "convert negative dimensions to zero"); + + DEFVAR ("warn_assign_as_truth_value", SBV_warn_assign_as_truth_value, + "true", 0, 0, 1, + warn_assign_as_truth_value, + "produce warning for assignments used as truth values"); + + DEFVAR ("warn_comma_in_global_decl", SBV_warn_comma_in_global_decl, + "true", 0, 0, 1, warn_comma_in_global_decl, + "produce warning for commas in global declarations"); + + DEFVAR ("warn_divide_by_zero", SBV_warn_divide_by_zero, "true", 0, 0, + 1, warn_divide_by_zero, + "on IEEE machines, allow divide by zero errors to be suppressed"); +} + +/* + * List variable names. + */ +static void +print_symbol_info_line (ostrstream& output_buf, const symbol_record_info& s) +{ + output_buf << (s.is_read_only () ? " -" : " w"); + output_buf << (s.is_eternal () ? "- " : "d "); +#if 0 + output_buf << (s.hides_fcn () ? "f" : (s.hides_builtin () ? "F" : "-")); +#endif + output_buf.form (" %-16s", s.type_as_string ()); + if (s.is_function ()) + output_buf << " - -"; + else + { + output_buf.form ("%7d", s.rows ()); + output_buf.form ("%7d", s.columns ()); + } + output_buf << " " << s.name () << "\n"; +} + +static void +print_long_listing (ostrstream& output_buf, symbol_record_info *s) +{ + if (! s) + return; + + symbol_record_info *ptr = s; + while (ptr->is_defined ()) + { + print_symbol_info_line (output_buf, *ptr); + ptr++; + } +} + +static int +maybe_list (const char *header, ostrstream& output_buf, + int show_verbose, symbol_table *sym_tab, unsigned type, + unsigned scope) +{ + int count; + int status = 0; + if (show_verbose) + { + symbol_record_info *symbols; + symbols = sym_tab->long_list (count, 1, type, scope); + if (symbols && count > 0) + { + output_buf << "\n" << header << "\n\n" + << "prot type rows cols name\n" + << "==== ==== ==== ==== ====\n"; + + print_long_listing (output_buf, symbols); + status = 1; + } + delete [] symbols; + } + else + { + char **symbols = sym_tab->list (count, 1, type, scope); + if (symbols && count > 0) + { + output_buf << "\n" << header << "\n\n"; + list_in_columns (output_buf, symbols); + status = 1; + } + delete [] symbols; + } + return status; +} + +DEFUN_TEXT ("clear", Fclear, Sclear, -1, 1, + "clear [name ...]\n\ +\n\ +clear symbol(s) matching a list of globbing patterns\n\ +if no arguments are given, clear all user-defined variables and functions") +{ + Octave_object retval; + + DEFINE_ARGV("clear"); + +// 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...) + + int 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 + { + int lcount; + char **lvars = curr_sym_tab->list (lcount, 0, + symbol_def::USER_VARIABLE, + SYMTAB_LOCAL_SCOPE); + int gcount; + char **gvars = curr_sym_tab->list (gcount, 0, + symbol_def::USER_VARIABLE, + SYMTAB_GLOBAL_SCOPE); + int fcount; + char **fcns = curr_sym_tab->list (fcount, 0, + symbol_def::USER_FUNCTION, + SYMTAB_ALL_SCOPES); + + while (--argc > 0) + { + argv++; + if (*argv) + { + int i; + for (i = 0; i < lcount; i++) + { + if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0) + curr_sym_tab->clear (lvars[i]); + } + + int count; + for (i = 0; i < gcount; i++) + { + if (fnmatch (*argv, gvars[i], __FNM_FLAGS) == 0) + { + count = curr_sym_tab->clear (gvars[i]); + if (count > 0) + global_sym_tab->clear (gvars[i], clear_user_functions); + } + } + + for (i = 0; i < fcount; i++) + { + if (fnmatch (*argv, fcns[i], __FNM_FLAGS) == 0) + { + count = curr_sym_tab->clear (fcns[i]); + if (count > 0) + global_sym_tab->clear (fcns[i], clear_user_functions); + } + } + } + } + + delete [] lvars; + delete [] gvars; + delete [] fcns; + + } + + DELETE_ARGV; + + return retval; +} + +DEFUN_TEXT ("document", Fdocument, Sdocument, -1, 1, + "document symbol string ...\n\ +\n\ +Associate a cryptic message with a variable name.") +{ + Octave_object retval; + + DEFINE_ARGV("document"); + + if (argc == 3) + document_symbol (argv[1], argv[2]); + else + print_usage ("document"); + + DELETE_ARGV; + + return retval; +} + +static int +load_variable (char *nm, int force, istream& is) +{ +// Is there already a symbol by this name? If so, what is it? + + symbol_record *lsr = curr_sym_tab->lookup (nm, 0, 0); + + int is_undefined = 1; + int is_variable = 0; + int is_function = 0; + int is_global = 0; + + if (lsr) + { + is_undefined = ! lsr->is_defined (); + is_variable = lsr->is_variable (); + is_function = lsr->is_function (); + is_global = lsr->is_linked_to_global (); + } + +// Try to read data for this name. + + tree_constant tc; + int global = tc.load (is); + + if (tc.const_type () == tree_constant_rep::unknown_constant) + { + error ("load: unable to load variable `%s'", nm); + return 0; + } + + symbol_record *sr = 0; + + if (global) + { + if (is_global || is_undefined) + { + if (force || is_undefined) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: global variable name `%s' exists.", nm); + warning ("use `load -force' to overwrite"); + } + } + else if (is_function) + { + if (force) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: `%s' is currently a function in this scope", nm); + warning ("`load -force' will load variable and hide function"); + } + } + else if (is_variable) + { + if (force) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: local variable name `%s' exists.", nm); + warning ("use `load -force' to overwrite"); + } + } + else + panic_impossible (); + } + else + { + if (is_global) + { + if (force || is_undefined) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: global variable name `%s' exists.", nm); + warning ("use `load -force' to overwrite"); + } + } + else if (is_function) + { + if (force) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + link_to_global_variable (lsr); + sr = lsr; + } + else + { + warning ("load: `%s' is currently a function in this scope", nm); + warning ("`load -force' will load variable and hide function"); + } + } + else if (is_variable || is_undefined) + { + if (force || is_undefined) + { + lsr = curr_sym_tab->lookup (nm, 1, 0); + sr = lsr; + } + else + { + warning ("load: local variable name `%s' exists.", nm); + warning ("use `load -force' to overwrite"); + } + } + else + panic_impossible (); + } + + if (sr) + { + tree_constant *tmp_tc = new tree_constant (tc); + sr->define (tmp_tc); + return 1; + } + else + error ("load: unable to load variable `%s'", nm); + + return 0; +} + +DEFUN_TEXT ("load", Fload, Sload, -1, 1, + "load [-force] file\n +\n\ +load variables from a file") +{ + Octave_object retval; + + DEFINE_ARGV("load"); + + argc--; + argv++; + + int force = 0; + if (argc > 0 && strcmp (*argv, "-force") == 0) + { + force++; + argc--; + argv++; + } + + if (argc < 1) + { + error ("load: you must specify a single file to read"); + DELETE_ARGV; + return retval; + } + + static istream stream; + static ifstream file; + if (strcmp (*argv, "-") == 0) + { + stream = cin; + } + else + { + char *fname = tilde_expand (*argv); + file.open (fname); + if (! file) + { + error ("load: couldn't open input file `%s'", *argv); + DELETE_ARGV; + return retval; + } + stream = file; + } + + int count = 0; + char *nm = 0; + for (;;) + { +// Read name for this entry or break on EOF. + delete [] nm; + nm = extract_keyword (stream, "name"); + if (nm) + count++; + else + { + if (count == 0) + { + error ("load: no name keywords found in file `%s'", *argv); + error ("Are you sure this is an octave data file?"); + } + break; + } + + if (! *nm) + continue; + + if (! valid_identifier (nm)) + { + warning ("load: skipping bogus identifier `%s'"); + continue; + } + + load_variable (nm, force, stream); + + if (error_state) + { + error ("reading file %s", *argv); + break; + } + } + + if (file); + file.close (); + + DELETE_ARGV; + + return retval; +} + +/* + * Return nonzero if PATTERN has any special globbing chars in it. + */ +static int +glob_pattern_p (char *pattern) +{ + char *p = pattern; + char c; + int open = 0; + + while ((c = *p++) != '\0') + { + switch (c) + { + case '?': + case '*': + return 1; + + case '[': // Only accept an open brace if there is a close + open++; // brace to match it. Bracket expressions must be + continue; // complete, according to Posix.2 + + case ']': + if (open) + return 1; + continue; + + case '\\': + if (*p++ == '\0') + return 0; + + default: + continue; + } + } + + return 0; +} + +DEFUN_TEXT ("save", Fsave, Ssave, -1, 1, + "save file [var ...]\n\ +\n\ +save variables in a file") +{ + Octave_object retval; + +#if 0 + DEFINE_ARGV("save"); + + if (argc < 2) + { + print_usage ("save"); + DELETE_ARGV; + return retval; + } + + argc--; + argv++; + + static ostream stream; + static ofstream file; + if (strcmp (*argv, "-") == 0) + { +// XXX FIXME XXX -- should things intended for the screen end up in a +// tree_constant (string)? + stream = cout; + } + else if (argc == 1 && glob_pattern_p (*argv)) // Guard against things + { // like `save a*', + print_usage ("save"); // which are probably + DELETE_ARGV; // mistakes... + return retval; + } + else + { + char *fname = tilde_expand (*argv); + file.open (fname); + if (! file) + { + error ("save: couldn't open output file `%s'", *argv); + DELETE_ARGV; + return retval; + } + stream = file; + + } + + int prec = user_pref.save_precision; + + if (argc == 1) + { + int count; + char **vars = curr_sym_tab->list (count, 0, + symbol_def::USER_VARIABLE, + SYMTAB_ALL_SCOPES); + + for (int i = 0; i < count; i++) + curr_sym_tab->save (stream, vars[i], + is_globally_visible (vars[i]), prec); + + delete [] vars; + } + else + { + while (--argc > 0) + { + argv++; + + int count; + char **lvars = curr_sym_tab->list (count, 0, + symbol_def::USER_VARIABLE); + + int saved_or_error = 0; + int i; + for (i = 0; i < count; i++) + { + if (fnmatch (*argv, lvars[i], __FNM_FLAGS) == 0 + && curr_sym_tab->save (stream, lvars[i], + is_globally_visible (lvars[i]), + prec) != 0) + saved_or_error++; + } + + char **bvars = global_sym_tab->list (count, 0, + symbol_def::BUILTIN_VARIABLE); + + for (i = 0; i < count; i++) + { + if (fnmatch (*argv, bvars[i], __FNM_FLAGS) == 0 + && global_sym_tab->save (stream, bvars[i], 0, prec) != 0) + saved_or_error++; + } + + delete [] lvars; + delete [] bvars; + + if (! saved_or_error) + warning ("save: no such variable `%s'", *argv); + } + } + + if (file); + file.close (); + + DELETE_ARGV; +#endif + + return retval; +} + +DEFUN_TEXT ("who", Fwho, Swho, -1, 1, + "who [-all] [-builtins] [-functions] [-long] [-variables]\n\ +\n\ +List currently defined symbol(s). Options may be shortened to one\n\ +character, but may not be combined.") +{ + Octave_object retval; + + DEFINE_ARGV("who"); + + int show_builtins = 0; + int show_functions = (curr_sym_tab == top_level_sym_tab); + int show_variables = 1; + int show_verbose = 0; + + if (argc > 1) + { + show_functions = 0; + show_variables = 0; + } + + for (int i = 1; i < argc; i++) + { + argv++; + if (strcmp (*argv, "-all") == 0 || strcmp (*argv, "-a") == 0) + { + show_builtins++; + show_functions++; + show_variables++; + } + else if (strcmp (*argv, "-builtins") == 0 + || strcmp (*argv, "-b") == 0) + show_builtins++; + else if (strcmp (*argv, "-functions") == 0 + || strcmp (*argv, "-f") == 0) + show_functions++; + else if (strcmp (*argv, "-long") == 0 + || strcmp (*argv, "-l") == 0) + show_verbose++; + else if (strcmp (*argv, "-variables") == 0 + || strcmp (*argv, "-v") == 0) + show_variables++; + else + warning ("who: unrecognized option `%s'", *argv); + } + +// If the user specified -l and nothing else, show variables. If +// evaluating this at the top level, also show functions. + + if (show_verbose && ! (show_builtins || show_functions || show_variables)) + { + show_functions = (curr_sym_tab == top_level_sym_tab); + show_variables = 1; + } + + ostrstream output_buf; + int pad_after = 0; + + if (show_builtins) + { + pad_after += maybe_list ("*** built-in variables:", + output_buf, show_verbose, global_sym_tab, + symbol_def::BUILTIN_VARIABLE, + SYMTAB_ALL_SCOPES); + + pad_after += maybe_list ("*** built-in functions:", + output_buf, show_verbose, global_sym_tab, + symbol_def::BUILTIN_FUNCTION, + SYMTAB_ALL_SCOPES); + } + + if (show_functions) + { + pad_after += maybe_list ("*** currently compiled functions:", + output_buf, show_verbose, global_sym_tab, + symbol_def::USER_FUNCTION, + SYMTAB_ALL_SCOPES); + } + + if (show_variables) + { + pad_after += maybe_list ("*** local user variables:", + output_buf, show_verbose, curr_sym_tab, + symbol_def::USER_VARIABLE, + SYMTAB_LOCAL_SCOPE); + + pad_after += maybe_list ("*** globally visible user variables:", + output_buf, show_verbose, curr_sym_tab, + symbol_def::USER_VARIABLE, + SYMTAB_GLOBAL_SCOPE); + } + + if (pad_after) + output_buf << "\n"; + + output_buf << ends; + maybe_page_output (output_buf); + + DELETE_ARGV; + + return retval; +} + +// XXX FIXME XXX -- should these really be here? + +char * +octave_home (void) +{ +#ifdef RUN_IN_PLACE + static char *home = OCTAVE_HOME; + return home; +#else + static char *home = 0; + delete [] home; + char *oh = getenv ("OCTAVE_HOME"); + if (oh) + home = strsave (oh); + else + home = strsave (OCTAVE_HOME); + return home; +#endif +} + +char * +octave_lib_dir (void) +{ +#ifdef RUN_IN_PLACE + static char *ol = OCTAVE_LIB_DIR; + return ol; +#else + static char *ol = 0; + delete [] ol; + char *oh = octave_home (); + char *tmp = strconcat (oh, "/lib/octave/"); + ol = strconcat (tmp, version_string); + delete [] tmp; + return ol; +#endif +} + +char * +octave_info_dir (void) +{ +#ifdef RUN_IN_PLACE + static char *oi = OCTAVE_INFO_DIR; + return oi; +#else + static char *oi = 0; + delete [] oi; + char *oh = octave_home (); + oi = strconcat (oh, "/info/"); + return oi; +#endif +} + +/* + * Handle OCTAVE_PATH from the environment like TeX handles TEXINPUTS. + * If the path starts with `:', prepend the standard path. If it ends + * with `:' append the standard path. If it begins and ends with + * `:', do both (which is useless, but the luser asked for it...). + * + * This function may eventually be called more than once, so be + * careful not to create memory leaks. + */ +char * +default_path (void) +{ + static char *pathstring = 0; + delete [] pathstring; + + static char *std_path = 0; + delete [] std_path; + + char *libdir = octave_lib_dir (); + + std_path = strconcat (".:", libdir); + + char *oct_path = getenv ("OCTAVE_PATH"); + + if (oct_path) + { + pathstring = strsave (oct_path); + + if (pathstring[0] == ':') + { + char *tmp = pathstring; + pathstring = strconcat (std_path, pathstring); + delete [] tmp; + } + + int tmp_len = strlen (pathstring); + if (pathstring[tmp_len-1] == ':') + { + char *tmp = pathstring; + pathstring = strconcat (pathstring, std_path); + delete [] tmp; + } + } + else + pathstring = strsave (std_path); + + return pathstring; +} + +char * +default_info_file (void) +{ + static char *info_file_string = 0; + delete [] info_file_string; + char *oct_info_file = getenv ("OCTAVE_INFO_FILE"); + if (oct_info_file) + info_file_string = strsave (oct_info_file); + else + { + char *infodir = octave_info_dir (); + info_file_string = strconcat (infodir, "/octave.info"); + } + return info_file_string; +} + +char * +default_editor (void) +{ + static char *editor_string = 0; + delete [] editor_string; + char *env_editor = getenv ("EDITOR"); + if (env_editor && *env_editor) + editor_string = strsave (env_editor); + else + editor_string = strsave ("vi"); + return editor_string; +} + +char * +get_site_defaults (void) +{ + static char *sd = 0; + delete [] sd; + char *libdir = octave_lib_dir (); + sd = strconcat (libdir, "/octaverc"); + return sd; +} + +char * +default_pager (void) +{ + static char *pager_binary = 0; + delete [] pager_binary; + char *pgr = getenv ("PAGER"); + if (pgr) + pager_binary = strsave (pgr); + else +#ifdef DEFAULT_PAGER + pager_binary = strsave (DEFAULT_PAGER); +#else + pager_binary = strsave (""); +#endif + + return pager_binary; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***