00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <cstdio>
00029 #include <cstring>
00030
00031 #include <iomanip>
00032 #include <set>
00033 #include <string>
00034
00035 #include "file-stat.h"
00036 #include "oct-env.h"
00037 #include "file-ops.h"
00038 #include "glob-match.h"
00039 #include "regexp.h"
00040 #include "str-vec.h"
00041
00042 #include <defaults.h>
00043 #include "Cell.h"
00044 #include "defun.h"
00045 #include "dirfns.h"
00046 #include "error.h"
00047 #include "gripes.h"
00048 #include "help.h"
00049 #include "input.h"
00050 #include "lex.h"
00051 #include "load-path.h"
00052 #include "oct-map.h"
00053 #include "oct-obj.h"
00054 #include "ov.h"
00055 #include "ov-class.h"
00056 #include "ov-usr-fcn.h"
00057 #include "pager.h"
00058 #include "parse.h"
00059 #include "symtab.h"
00060 #include "toplev.h"
00061 #include "unwind-prot.h"
00062 #include "utils.h"
00063 #include "variables.h"
00064
00065
00066 static std::string Vwhos_line_format
00067 = " %a:4; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;\n";
00068
00069 void
00070 clear_mex_functions (void)
00071 {
00072 symbol_table::clear_mex_functions ();
00073 }
00074
00075 void
00076 clear_function (const std::string& nm)
00077 {
00078 symbol_table::clear_function (nm);
00079 }
00080
00081 void
00082 clear_variable (const std::string& nm)
00083 {
00084 symbol_table::clear_variable (nm);
00085 }
00086
00087 void
00088 clear_symbol (const std::string& nm)
00089 {
00090 symbol_table::clear_symbol (nm);
00091 }
00092
00093
00094
00095
00096
00097 octave_function *
00098 is_valid_function (const std::string& fcn_name,
00099 const std::string& warn_for, bool warn)
00100 {
00101 octave_function *ans = 0;
00102
00103 if (! fcn_name.empty ())
00104 {
00105 octave_value val = symbol_table::find_function (fcn_name);
00106
00107 if (val.is_defined ())
00108 ans = val.function_value (true);
00109 }
00110
00111 if (! ans && warn)
00112 error ("%s: the symbol '%s' is not valid as a function",
00113 warn_for.c_str (), fcn_name.c_str ());
00114
00115 return ans;
00116 }
00117
00118 octave_function *
00119 is_valid_function (const octave_value& arg,
00120 const std::string& warn_for, bool warn)
00121 {
00122 octave_function *ans = 0;
00123
00124 std::string fcn_name;
00125
00126 if (arg.is_string ())
00127 {
00128 fcn_name = arg.string_value ();
00129
00130 if (! error_state)
00131 ans = is_valid_function (fcn_name, warn_for, warn);
00132 else if (warn)
00133 error ("%s: expecting function name as argument", warn_for.c_str ());
00134 }
00135 else if (warn)
00136 error ("%s: expecting function name as argument", warn_for.c_str ());
00137
00138 return ans;
00139 }
00140
00141 octave_function *
00142 extract_function (const octave_value& arg, const std::string& warn_for,
00143 const std::string& fname, const std::string& header,
00144 const std::string& trailer)
00145 {
00146 octave_function *retval = 0;
00147
00148 retval = is_valid_function (arg, warn_for, 0);
00149
00150 if (! retval)
00151 {
00152 std::string s = arg.string_value ();
00153
00154 std::string cmd = header;
00155 cmd.append (s);
00156 cmd.append (trailer);
00157
00158 if (! error_state)
00159 {
00160 int parse_status;
00161
00162 eval_string (cmd, true, parse_status, 0);
00163
00164 if (parse_status == 0)
00165 {
00166 retval = is_valid_function (fname, warn_for, 0);
00167
00168 if (! retval)
00169 {
00170 error ("%s: '%s' is not valid as a function",
00171 warn_for.c_str (), fname.c_str ());
00172 return retval;
00173 }
00174
00175 warning ("%s: passing function body as a string is obsolete; please use anonymous functions",
00176 warn_for.c_str ());
00177 }
00178 else
00179 error ("%s: '%s' is not valid as a function",
00180 warn_for.c_str (), fname.c_str ());
00181 }
00182 else
00183 error ("%s: expecting first argument to be a string",
00184 warn_for.c_str ());
00185 }
00186
00187 return retval;
00188 }
00189
00190 string_vector
00191 get_struct_elts (const std::string& text)
00192 {
00193 int n = 1;
00194
00195 size_t pos = 0;
00196
00197 size_t len = text.length ();
00198
00199 while ((pos = text.find ('.', pos)) != std::string::npos)
00200 {
00201 if (++pos == len)
00202 break;
00203
00204 n++;
00205 }
00206
00207 string_vector retval (n);
00208
00209 pos = 0;
00210
00211 for (int i = 0; i < n; i++)
00212 {
00213 len = text.find ('.', pos);
00214
00215 if (len != std::string::npos)
00216 len -= pos;
00217
00218 retval[i] = text.substr (pos, len);
00219
00220 if (len != std::string::npos)
00221 pos += len + 1;
00222 }
00223
00224 return retval;
00225 }
00226
00227 static inline bool
00228 is_variable (const std::string& name)
00229 {
00230 bool retval = false;
00231
00232 if (! name.empty ())
00233 {
00234 octave_value val = symbol_table::varval (name);
00235
00236 retval = val.is_defined ();
00237 }
00238
00239 return retval;
00240 }
00241
00242 string_vector
00243 generate_struct_completions (const std::string& text,
00244 std::string& prefix, std::string& hint)
00245 {
00246 string_vector names;
00247
00248 size_t pos = text.rfind ('.');
00249
00250 if (pos != std::string::npos)
00251 {
00252 if (pos == text.length ())
00253 hint = "";
00254 else
00255 hint = text.substr (pos+1);
00256
00257 prefix = text.substr (0, pos);
00258
00259 std::string base_name = prefix;
00260
00261 pos = base_name.find_first_of ("{(.");
00262
00263 if (pos != std::string::npos)
00264 base_name = base_name.substr (0, pos);
00265
00266 if (is_variable (base_name))
00267 {
00268 int parse_status;
00269
00270 unwind_protect frame;
00271
00272 frame.protect_var (error_state);
00273 frame.protect_var (warning_state);
00274
00275 frame.protect_var (discard_error_messages);
00276 frame.protect_var (discard_warning_messages);
00277
00278 discard_error_messages = true;
00279 discard_warning_messages = true;
00280
00281 octave_value tmp = eval_string (prefix, true, parse_status);
00282
00283 frame.run ();
00284
00285 if (tmp.is_defined () && tmp.is_map ())
00286 names = tmp.map_keys ();
00287 }
00288 }
00289
00290 return names;
00291 }
00292
00293
00294
00295
00296 bool
00297 looks_like_struct (const std::string& text)
00298 {
00299 bool retval = (! text.empty ()
00300 && text != "."
00301 && text.find_first_of (file_ops::dir_sep_chars ()) == std::string::npos
00302 && text.find ("..") == std::string::npos
00303 && text.rfind ('.') != std::string::npos);
00304
00305 #if 0
00306 symbol_record *sr = curr_sym_tab->lookup (text);
00307
00308 if (sr && ! sr->is_function ())
00309 {
00310 int parse_status;
00311
00312 unwind_protect frame;
00313
00314 frame.protect_var (discard_error_messages);
00315 frame.protect_var (error_state);
00316
00317 discard_error_messages = true;
00318
00319 octave_value tmp = eval_string (text, true, parse_status);
00320
00321 frame.run ();
00322
00323 retval = (tmp.is_defined () && tmp.is_map ());
00324 }
00325 #endif
00326
00327 return retval;
00328 }
00329
00330 static octave_value
00331 do_isglobal (const octave_value_list& args)
00332 {
00333 octave_value retval = false;
00334
00335 int nargin = args.length ();
00336
00337 if (nargin != 1)
00338 {
00339 print_usage ();
00340 return retval;
00341 }
00342
00343 std::string name = args(0).string_value ();
00344
00345 if (error_state)
00346 {
00347 error ("isglobal: NAME must be a string");
00348 return retval;
00349 }
00350
00351 return symbol_table::is_global (name);
00352 }
00353
00354 DEFUN (isglobal, args, ,
00355 "-*- texinfo -*-\n\
00356 @deftypefn {Built-in Function} {} isglobal (@var{name})\n\
00357 Return true if @var{name} is a globally visible variable.\n\
00358 For example:\n\
00359 \n\
00360 @example\n\
00361 @group\n\
00362 global x\n\
00363 isglobal (\"x\")\n\
00364 @result{} 1\n\
00365 @end group\n\
00366 @end example\n\
00367 @seealso{isvarname, exist}\n\
00368 @end deftypefn")
00369 {
00370 return do_isglobal (args);
00371 }
00372
00373 static octave_value
00374 safe_symbol_lookup (const std::string& symbol_name)
00375 {
00376 octave_value retval;
00377
00378 unwind_protect frame;
00379 interpreter_try (frame);
00380
00381 retval = symbol_table::find (symbol_name);
00382
00383 error_state = 0;
00384
00385 return retval;
00386 }
00387
00388 int
00389 symbol_exist (const std::string& name, const std::string& type)
00390 {
00391 int retval = 0;
00392
00393 std::string struct_elts;
00394 std::string symbol_name = name;
00395
00396 size_t pos = name.find ('.');
00397
00398 if (pos != std::string::npos && pos > 0)
00399 {
00400 struct_elts = name.substr (pos+1);
00401 symbol_name = name.substr (0, pos);
00402 }
00403
00404
00405
00406
00407
00408 octave_value val = safe_symbol_lookup (symbol_name);
00409
00410 if (val.is_defined ())
00411 {
00412 bool not_a_struct = struct_elts.empty ();
00413 bool var_ok = not_a_struct ;
00414
00415 if (! retval
00416 && var_ok
00417 && (type == "any" || type == "var")
00418 && (val.is_constant () || val.is_object ()
00419 || val.is_function_handle ()
00420 || val.is_anonymous_function ()
00421 || val.is_inline_function ()))
00422 {
00423 retval = 1;
00424 }
00425
00426 if (! retval
00427 && (type == "any" || type == "builtin"))
00428 {
00429 if (not_a_struct && val.is_builtin_function ())
00430 {
00431 retval = 5;
00432 }
00433 }
00434
00435 if (! retval
00436 && not_a_struct
00437 && (type == "any" || type == "file")
00438 && (val.is_user_function () || val.is_dld_function ()))
00439 {
00440 octave_function *f = val.function_value (true);
00441 std::string s = f ? f->fcn_file_name () : std::string ();
00442
00443 retval = s.empty () ? 103 : (val.is_user_function () ? 2 : 3);
00444 }
00445 }
00446
00447 if (! (type == "var" || type == "builtin"))
00448 {
00449 if (! retval)
00450 {
00451 std::string file_name = lookup_autoload (name);
00452
00453 if (file_name.empty ())
00454 file_name = load_path::find_fcn (name);
00455
00456 size_t len = file_name.length ();
00457
00458 if (len > 0)
00459 {
00460 if (type == "any" || type == "file")
00461 {
00462 if (len > 4 && (file_name.substr (len-4) == ".oct"
00463 || file_name.substr (len-4) == ".mex"))
00464 retval = 3;
00465 else
00466 retval = 2;
00467 }
00468 }
00469 }
00470
00471 if (! retval)
00472 {
00473 std::string file_name = file_in_path (name, "");
00474
00475 if (file_name.empty ())
00476 file_name = name;
00477
00478 file_stat fs (file_name);
00479
00480 if (fs)
00481 {
00482 if (type == "any" || type == "file")
00483 retval = fs.is_dir () ? 7 : 2;
00484 else if (type == "dir" && fs.is_dir ())
00485 retval = 7;
00486 }
00487 }
00488 }
00489
00490 return retval;
00491 }
00492
00493 #define GET_IDX(LEN) \
00494 static_cast<int> ((LEN-1) * static_cast<double> (rand ()) / RAND_MAX)
00495
00496 std::string
00497 unique_symbol_name (const std::string& basename)
00498 {
00499 static const std::string alpha
00500 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
00501
00502 static size_t len = alpha.length ();
00503
00504 std::string nm = basename + alpha[GET_IDX (len)];
00505
00506 size_t pos = nm.length ();
00507
00508 if (nm.substr (0, 2) == "__")
00509 nm.append ("__");
00510
00511 while (symbol_exist (nm, "any"))
00512 nm.insert (pos++, 1, alpha[GET_IDX (len)]);
00513
00514 return nm;
00515 }
00516
00517 DEFUN (exist, args, ,
00518 "-*- texinfo -*-\n\
00519 @deftypefn {Built-in Function} {} exist (@var{name}, @var{type})\n\
00520 Return 1 if the name exists as a variable, 2 if the name is an\n\
00521 absolute file name, an ordinary file in Octave's @code{path}, or (after\n\
00522 appending @samp{.m}) a function file in Octave's @code{path}, 3 if the\n\
00523 name is a @samp{.oct} or @samp{.mex} file in Octave's @code{path},\n\
00524 5 if the name is a built-in function, 7 if the name is a directory, or 103\n\
00525 if the name is a function not associated with a file (entered on\n\
00526 the command line).\n\
00527 \n\
00528 Otherwise, return 0.\n\
00529 \n\
00530 This function also returns 2 if a regular file called @var{name}\n\
00531 exists in Octave's search path. If you want information about\n\
00532 other types of files, you should use some combination of the functions\n\
00533 @code{file_in_path} and @code{stat} instead.\n\
00534 \n\
00535 If the optional argument @var{type} is supplied, check only for\n\
00536 symbols of the specified type. Valid types are\n\
00537 \n\
00538 @table @asis\n\
00539 @item \"var\"\n\
00540 Check only for variables.\n\
00541 \n\
00542 @item \"builtin\"\n\
00543 Check only for built-in functions.\n\
00544 \n\
00545 @item \"file\"\n\
00546 Check only for files.\n\
00547 \n\
00548 @item \"dir\"\n\
00549 Check only for directories.\n\
00550 @end table\n\
00551 @seealso{file_in_loadpath}\n\
00552 @end deftypefn")
00553 {
00554 octave_value retval = false;
00555
00556 int nargin = args.length ();
00557
00558 if (nargin == 1 || nargin == 2)
00559 {
00560 std::string name = args(0).string_value ();
00561
00562 if (! error_state)
00563 {
00564 std::string type
00565 = (nargin == 2) ? args(1).string_value () : std::string ("any");
00566
00567 if (! error_state)
00568 retval = symbol_exist (name, type);
00569 else
00570 error ("exist: TYPE must be a string");
00571 }
00572 else
00573 error ("exist: NAME must be a string");
00574 }
00575 else
00576 print_usage ();
00577
00578 return retval;
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 octave_value
00597 lookup_function_handle (const std::string& nm)
00598 {
00599 octave_value val = symbol_table::varval (nm);
00600
00601 return val.is_function_handle () ? val : octave_value ();
00602 }
00603
00604 octave_value
00605 get_global_value (const std::string& nm, bool silent)
00606 {
00607 octave_value val = symbol_table::global_varval (nm);
00608
00609 if (val.is_undefined () && ! silent)
00610 error ("get_global_value: undefined symbol '%s'", nm.c_str ());
00611
00612 return val;
00613 }
00614
00615 void
00616 set_global_value (const std::string& nm, const octave_value& val)
00617 {
00618 symbol_table::global_varref (nm) = val;
00619 }
00620
00621 octave_value
00622 get_top_level_value (const std::string& nm, bool silent)
00623 {
00624 octave_value val = symbol_table::top_level_varval (nm);
00625
00626 if (val.is_undefined () && ! silent)
00627 error ("get_top_level_value: undefined symbol '%s'", nm.c_str ());
00628
00629 return val;
00630 }
00631
00632 void
00633 set_top_level_value (const std::string& nm, const octave_value& val)
00634 {
00635 symbol_table::top_level_varref (nm) = val;
00636 }
00637
00638
00639
00640 static bool
00641 wants_local_change (const octave_value_list& args, int& nargin)
00642 {
00643 bool retval = false;
00644
00645 if (nargin == 2)
00646 {
00647 if (args(1).is_string () && args(1).string_value () == "local")
00648 {
00649 nargin = 1;
00650 retval = true;
00651 }
00652 else
00653 {
00654 error_with_cfn ("expecting second argument to be \"local\"");
00655 nargin = 0;
00656 }
00657 }
00658
00659 return retval;
00660 }
00661
00662 template <class T>
00663 bool try_local_protect (T& var)
00664 {
00665 octave_user_code *curr_usr_code = octave_call_stack::caller_user_code ();
00666 octave_user_function *curr_usr_fcn = 0;
00667 if (curr_usr_code && curr_usr_code->is_user_function ())
00668 curr_usr_fcn = dynamic_cast<octave_user_function *> (curr_usr_code);
00669
00670 if (curr_usr_fcn && curr_usr_fcn->local_protect (var))
00671 return true;
00672 else
00673 return false;
00674 }
00675
00676 octave_value
00677 set_internal_variable (bool& var, const octave_value_list& args,
00678 int nargout, const char *nm)
00679 {
00680 octave_value retval;
00681
00682 int nargin = args.length ();
00683
00684 if (nargout > 0 || nargin == 0)
00685 retval = var;
00686
00687 if (wants_local_change (args, nargin))
00688 {
00689 if (! try_local_protect (var))
00690 warning ("\"local\" has no effect outside a function");
00691 }
00692
00693 if (nargin == 1)
00694 {
00695 bool bval = args(0).bool_value ();
00696
00697 if (! error_state)
00698 var = bval;
00699 else
00700 error ("%s: expecting arg to be a logical value", nm);
00701 }
00702 else if (nargin > 1)
00703 print_usage ();
00704
00705 return retval;
00706 }
00707
00708 octave_value
00709 set_internal_variable (char& var, const octave_value_list& args,
00710 int nargout, const char *nm)
00711 {
00712 octave_value retval;
00713
00714 int nargin = args.length ();
00715
00716 if (nargout > 0 || nargin == 0)
00717 retval = var;
00718
00719 if (wants_local_change (args, nargin))
00720 {
00721 if (! try_local_protect (var))
00722 warning ("\"local\" has no effect outside a function");
00723 }
00724
00725 if (nargin == 1)
00726 {
00727 std::string sval = args(0).string_value ();
00728
00729 if (! error_state)
00730 {
00731 switch (sval.length ())
00732 {
00733 case 1:
00734 var = sval[0];
00735 break;
00736
00737 case 0:
00738 var = '\0';
00739 break;
00740
00741 default:
00742 error ("%s: argument must be a single character", nm);
00743 break;
00744 }
00745 }
00746 else
00747 error ("%s: argument must be a single character", nm);
00748 }
00749 else if (nargin > 1)
00750 print_usage ();
00751
00752 return retval;
00753 }
00754
00755 octave_value
00756 set_internal_variable (int& var, const octave_value_list& args,
00757 int nargout, const char *nm,
00758 int minval, int maxval)
00759 {
00760 octave_value retval;
00761
00762 int nargin = args.length ();
00763
00764 if (nargout > 0 || nargin == 0)
00765 retval = var;
00766
00767 if (wants_local_change (args, nargin))
00768 {
00769 if (! try_local_protect (var))
00770 warning ("\"local\" has no effect outside a function");
00771 }
00772
00773 if (nargin == 1)
00774 {
00775 int ival = args(0).int_value ();
00776
00777 if (! error_state)
00778 {
00779 if (ival < minval)
00780 error ("%s: expecting arg to be greater than %d", nm, minval);
00781 else if (ival > maxval)
00782 error ("%s: expecting arg to be less than or equal to %d",
00783 nm, maxval);
00784 else
00785 var = ival;
00786 }
00787 else
00788 error ("%s: expecting arg to be an integer value", nm);
00789 }
00790 else if (nargin > 1)
00791 print_usage ();
00792
00793 return retval;
00794 }
00795
00796 octave_value
00797 set_internal_variable (double& var, const octave_value_list& args,
00798 int nargout, const char *nm,
00799 double minval, double maxval)
00800 {
00801 octave_value retval;
00802
00803 int nargin = args.length ();
00804
00805 if (nargout > 0 || nargin == 0)
00806 retval = var;
00807
00808 if (wants_local_change (args, nargin))
00809 {
00810 if (! try_local_protect (var))
00811 warning ("\"local\" has no effect outside a function");
00812 }
00813
00814 if (nargin == 1)
00815 {
00816 double dval = args(0).scalar_value ();
00817
00818 if (! error_state)
00819 {
00820 if (dval < minval)
00821 error ("%s: expecting arg to be greater than %g", minval);
00822 else if (dval > maxval)
00823 error ("%s: expecting arg to be less than or equal to %g", maxval);
00824 else
00825 var = dval;
00826 }
00827 else
00828 error ("%s: expecting arg to be a scalar value", nm);
00829 }
00830 else if (nargin > 1)
00831 print_usage ();
00832
00833 return retval;
00834 }
00835
00836 octave_value
00837 set_internal_variable (std::string& var, const octave_value_list& args,
00838 int nargout, const char *nm, bool empty_ok)
00839 {
00840 octave_value retval;
00841
00842 int nargin = args.length ();
00843
00844 if (nargout > 0 || nargin == 0)
00845 retval = var;
00846
00847 if (wants_local_change (args, nargin))
00848 {
00849 if (! try_local_protect (var))
00850 warning ("\"local\" has no effect outside a function");
00851 }
00852
00853 if (nargin == 1)
00854 {
00855 std::string sval = args(0).string_value ();
00856
00857 if (! error_state)
00858 {
00859 if (empty_ok || ! sval.empty ())
00860 var = sval;
00861 else
00862 error ("%s: value must not be empty", nm);
00863 }
00864 else
00865 error ("%s: expecting arg to be a character string", nm);
00866 }
00867 else if (nargin > 1)
00868 print_usage ();
00869
00870 return retval;
00871 }
00872
00873 octave_value
00874 set_internal_variable (int& var, const octave_value_list& args,
00875 int nargout, const char *nm, const char **choices)
00876 {
00877 octave_value retval;
00878 int nchoices = 0;
00879 while (choices[nchoices] != 0)
00880 nchoices++;
00881
00882 int nargin = args.length ();
00883 assert (var < nchoices);
00884
00885 if (nargout > 0 || nargin == 0)
00886 retval = choices[var];
00887
00888 if (wants_local_change (args, nargin))
00889 {
00890 if (! try_local_protect (var))
00891 warning ("\"local\" has no effect outside a function");
00892 }
00893
00894 if (nargin == 1)
00895 {
00896 std::string sval = args(0).string_value ();
00897
00898 if (! error_state)
00899 {
00900 int i = 0;
00901 for (; i < nchoices; i++)
00902 {
00903 if (sval == choices[i])
00904 {
00905 var = i;
00906 break;
00907 }
00908 }
00909 if (i == nchoices)
00910 error ("%s: value not allowed (\"%s\")", nm, sval.c_str ());
00911 }
00912 else
00913 error ("%s: expecting arg to be a character string", nm);
00914 }
00915 else if (nargin > 1)
00916 print_usage ();
00917
00918 return retval;
00919 }
00920
00921 struct
00922 whos_parameter
00923 {
00924 char command;
00925 char modifier;
00926 int parameter_length;
00927 int first_parameter_length;
00928 int balance;
00929 std::string text;
00930 std::string line;
00931 };
00932
00933 static void
00934 print_descriptor (std::ostream& os, std::list<whos_parameter> params)
00935 {
00936
00937 std::list<whos_parameter>::iterator i = params.begin ();
00938 std::ostringstream param_buf;
00939
00940 while (i != params.end ())
00941 {
00942 whos_parameter param = *i;
00943
00944 if (param.command != '\0')
00945 {
00946
00947 switch (param.modifier)
00948 {
00949 case 'l':
00950 os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
00951 param_buf << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
00952 break;
00953
00954 case 'r':
00955 os << std::setiosflags (std::ios::right) << std::setw (param.parameter_length);
00956 param_buf << std::setiosflags (std::ios::right) << std::setw (param.parameter_length);
00957 break;
00958
00959 case 'c':
00960 if (param.command != 's')
00961 {
00962 os << std::setiosflags (std::ios::left)
00963 << std::setw (param.parameter_length);
00964 param_buf << std::setiosflags (std::ios::left)
00965 << std::setw (param.parameter_length);
00966 }
00967 break;
00968
00969 default:
00970 os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
00971 param_buf << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
00972 }
00973
00974 if (param.command == 's' && param.modifier == 'c')
00975 {
00976 int a, b;
00977
00978 if (param.modifier == 'c')
00979 {
00980 a = param.first_parameter_length - param.balance;
00981 a = (a < 0 ? 0 : a);
00982 b = param.parameter_length - a - param.text . length ();
00983 b = (b < 0 ? 0 : b);
00984 os << std::setiosflags (std::ios::left) << std::setw (a)
00985 << "" << std::resetiosflags (std::ios::left) << param.text
00986 << std::setiosflags (std::ios::left)
00987 << std::setw (b) << ""
00988 << std::resetiosflags (std::ios::left);
00989 param_buf << std::setiosflags (std::ios::left) << std::setw (a)
00990 << "" << std::resetiosflags (std::ios::left) << param.line
00991 << std::setiosflags (std::ios::left)
00992 << std::setw (b) << ""
00993 << std::resetiosflags (std::ios::left);
00994 }
00995 }
00996 else
00997 {
00998 os << param.text;
00999 param_buf << param.line;
01000 }
01001 os << std::resetiosflags (std::ios::left)
01002 << std::resetiosflags (std::ios::right);
01003 param_buf << std::resetiosflags (std::ios::left)
01004 << std::resetiosflags (std::ios::right);
01005 i++;
01006 }
01007 else
01008 {
01009 os << param.text;
01010 param_buf << param.line;
01011 i++;
01012 }
01013 }
01014
01015 os << param_buf.str ();
01016 }
01017
01018
01019
01020
01021
01022
01023 std::string
01024 get_dims_str (const octave_value& val)
01025 {
01026 octave_value tmp = val;
01027
01028 Matrix sz = tmp.size ();
01029
01030 dim_vector dv = dim_vector::alloc (sz.numel ());
01031
01032 for (octave_idx_type i = 0; i < dv.length (); i++)
01033 dv(i) = sz(i);
01034
01035 return dv.str ();
01036 }
01037
01038 class
01039 symbol_info_list
01040 {
01041 private:
01042 struct symbol_info
01043 {
01044 symbol_info (const symbol_table::symbol_record& sr,
01045 const std::string& expr_str = std::string (),
01046 const octave_value& expr_val = octave_value ())
01047 : name (expr_str.empty () ? sr.name () : expr_str),
01048 varval (expr_val.is_undefined () ? sr.varval () : expr_val),
01049 is_automatic (sr.is_automatic ()),
01050 is_complex (varval.is_complex_type ()),
01051 is_formal (sr.is_formal ()),
01052 is_global (sr.is_global ()),
01053 is_persistent (sr.is_persistent ())
01054 { }
01055
01056 void display_line (std::ostream& os,
01057 const std::list<whos_parameter>& params) const
01058 {
01059 std::string dims_str = get_dims_str (varval);
01060
01061 std::list<whos_parameter>::const_iterator i = params.begin ();
01062
01063 while (i != params.end ())
01064 {
01065 whos_parameter param = *i;
01066
01067 if (param.command != '\0')
01068 {
01069
01070
01071 switch (param.modifier)
01072 {
01073 case 'l':
01074 os << std::setiosflags (std::ios::left)
01075 << std::setw (param.parameter_length);
01076 break;
01077
01078 case 'r':
01079 os << std::setiosflags (std::ios::right)
01080 << std::setw (param.parameter_length);
01081 break;
01082
01083 case 'c':
01084 if (param.command == 's')
01085 {
01086 int front = param.first_parameter_length
01087 - dims_str.find ('x');
01088 int back = param.parameter_length
01089 - dims_str.length ()
01090 - front;
01091 front = (front > 0) ? front : 0;
01092 back = (back > 0) ? back : 0;
01093
01094 os << std::setiosflags (std::ios::left)
01095 << std::setw (front)
01096 << ""
01097 << std::resetiosflags (std::ios::left)
01098 << dims_str
01099 << std::setiosflags (std::ios::left)
01100 << std::setw (back)
01101 << ""
01102 << std::resetiosflags (std::ios::left);
01103 }
01104 else
01105 {
01106 os << std::setiosflags (std::ios::left)
01107 << std::setw (param.parameter_length);
01108 }
01109 break;
01110
01111 default:
01112 error ("whos_line_format: modifier '%c' unknown",
01113 param.modifier);
01114
01115 os << std::setiosflags (std::ios::right)
01116 << std::setw (param.parameter_length);
01117 }
01118
01119 switch (param.command)
01120 {
01121 case 'a':
01122 {
01123 char tmp[6];
01124
01125 tmp[0] = (is_automatic ? 'a' : ' ');
01126 tmp[1] = (is_complex ? 'c' : ' ');
01127 tmp[2] = (is_formal ? 'f' : ' ');
01128 tmp[3] = (is_global ? 'g' : ' ');
01129 tmp[4] = (is_persistent ? 'p' : ' ');
01130 tmp[5] = 0;
01131
01132 os << tmp;
01133 }
01134 break;
01135
01136 case 'b':
01137 os << varval.byte_size ();
01138 break;
01139
01140 case 'c':
01141 os << varval.class_name ();
01142 break;
01143
01144 case 'e':
01145 os << varval.capacity ();
01146 break;
01147
01148 case 'n':
01149 os << name;
01150 break;
01151
01152 case 's':
01153 if (param.modifier != 'c')
01154 os << dims_str;
01155 break;
01156
01157 case 't':
01158 os << varval.type_name ();
01159 break;
01160
01161 default:
01162 error ("whos_line_format: command '%c' unknown",
01163 param.command);
01164 }
01165
01166 os << std::resetiosflags (std::ios::left)
01167 << std::resetiosflags (std::ios::right);
01168 i++;
01169 }
01170 else
01171 {
01172 os << param.text;
01173 i++;
01174 }
01175 }
01176 }
01177
01178 std::string name;
01179 octave_value varval;
01180 bool is_automatic;
01181 bool is_complex;
01182 bool is_formal;
01183 bool is_global;
01184 bool is_persistent;
01185 };
01186
01187 public:
01188 symbol_info_list (void) : lst () { }
01189
01190 symbol_info_list (const symbol_info_list& sil) : lst (sil.lst) { }
01191
01192 symbol_info_list& operator = (const symbol_info_list& sil)
01193 {
01194 if (this != &sil)
01195 lst = sil.lst;
01196
01197 return *this;
01198 }
01199
01200 ~symbol_info_list (void) { }
01201
01202 void append (const symbol_table::symbol_record& sr)
01203 {
01204 lst.push_back (symbol_info (sr));
01205 }
01206
01207 void append (const symbol_table::symbol_record& sr,
01208 const std::string& expr_str,
01209 const octave_value& expr_val)
01210 {
01211 lst.push_back (symbol_info (sr, expr_str, expr_val));
01212 }
01213
01214 size_t size (void) const { return lst.size (); }
01215
01216 bool empty (void) const { return lst.empty (); }
01217
01218 octave_map
01219 map_value (const std::string& caller_function_name, int nesting_level) const
01220 {
01221 size_t len = lst.size ();
01222
01223 Cell name_info (len, 1);
01224 Cell size_info (len, 1);
01225 Cell bytes_info (len, 1);
01226 Cell class_info (len, 1);
01227 Cell global_info (len, 1);
01228 Cell sparse_info (len, 1);
01229 Cell complex_info (len, 1);
01230 Cell nesting_info (len, 1);
01231 Cell persistent_info (len, 1);
01232
01233 std::list<symbol_info>::const_iterator p = lst.begin ();
01234
01235 for (size_t j = 0; j < len; j++)
01236 {
01237 const symbol_info& si = *p++;
01238
01239 octave_scalar_map ni;
01240
01241 ni.assign ("function", caller_function_name);
01242 ni.assign ("level", nesting_level);
01243
01244 name_info(j) = si.name;
01245 global_info(j) = si.is_global;
01246 persistent_info(j) = si.is_persistent;
01247
01248 octave_value val = si.varval;
01249
01250 size_info(j) = val.size ();
01251 bytes_info(j) = val.byte_size ();
01252 class_info(j) = val.class_name ();
01253 sparse_info(j) = val.is_sparse_type ();
01254 complex_info(j) = val.is_complex_type ();
01255 nesting_info(j) = ni;
01256 }
01257
01258 octave_map info;
01259
01260 info.assign ("name", name_info);
01261 info.assign ("size", size_info);
01262 info.assign ("bytes", bytes_info);
01263 info.assign ("class", class_info);
01264 info.assign ("global", global_info);
01265 info.assign ("sparse", sparse_info);
01266 info.assign ("complex", complex_info);
01267 info.assign ("nesting", nesting_info);
01268 info.assign ("persistent", persistent_info);
01269
01270 return info;
01271 }
01272
01273 void display (std::ostream& os)
01274 {
01275 if (! lst.empty ())
01276 {
01277 size_t bytes = 0;
01278 size_t elements = 0;
01279
01280 std::list<whos_parameter> params = parse_whos_line_format ();
01281
01282 print_descriptor (os, params);
01283
01284 octave_stdout << "\n";
01285
01286 for (std::list<symbol_info>::const_iterator p = lst.begin ();
01287 p != lst.end (); p++)
01288 {
01289 p->display_line (os, params);
01290
01291 octave_value val = p->varval;
01292
01293 elements += val.capacity ();
01294 bytes += val.byte_size ();
01295 }
01296
01297 os << "\nTotal is " << elements
01298 << (elements == 1 ? " element" : " elements")
01299 << " using " << bytes << (bytes == 1 ? " byte" : " bytes")
01300 << "\n";
01301 }
01302 }
01303
01304
01305
01306
01307 std::list<whos_parameter> parse_whos_line_format (void)
01308 {
01309 int idx;
01310 size_t format_len = Vwhos_line_format.length ();
01311 char garbage;
01312 std::list<whos_parameter> params;
01313
01314 size_t bytes1;
01315 int elements1;
01316
01317 std::string param_string = "abcenst";
01318 Array<int> param_length (dim_vector (param_string.length (), 1));
01319 Array<std::string> param_names (dim_vector (param_string.length (), 1));
01320 size_t pos_a, pos_b, pos_c, pos_e, pos_n, pos_s, pos_t;
01321
01322 pos_a = param_string.find ('a');
01323 pos_b = param_string.find ('b');
01324 pos_c = param_string.find ('c');
01325 pos_e = param_string.find ('e');
01326 pos_n = param_string.find ('n');
01327 pos_s = param_string.find ('s');
01328 pos_t = param_string.find ('t');
01329
01330 param_names(pos_a) = "Attr";
01331 param_names(pos_b) = "Bytes";
01332 param_names(pos_c) = "Class";
01333 param_names(pos_e) = "Elements";
01334 param_names(pos_n) = "Name";
01335 param_names(pos_s) = "Size";
01336 param_names(pos_t) = "Type";
01337
01338 for (size_t i = 0; i < param_string.length (); i++)
01339 param_length(i) = param_names(i) . length ();
01340
01341
01342 param_length(pos_a) = 5;
01343
01344
01345
01346
01347 for (std::list<symbol_info>::const_iterator p = lst.begin ();
01348 p != lst.end (); p++)
01349 {
01350 std::stringstream ss1, ss2;
01351 std::string str;
01352
01353 str = p->name;
01354 param_length(pos_n) = ((str.length ()
01355 > static_cast<size_t> (param_length(pos_n)))
01356 ? str.length () : param_length(pos_n));
01357
01358 octave_value val = p->varval;
01359
01360 str = val.type_name ();
01361 param_length(pos_t) = ((str.length ()
01362 > static_cast<size_t> (param_length(pos_t)))
01363 ? str.length () : param_length(pos_t));
01364
01365 elements1 = val.capacity ();
01366 ss1 << elements1;
01367 str = ss1.str ();
01368 param_length(pos_e) = ((str.length ()
01369 > static_cast<size_t> (param_length(pos_e)))
01370 ? str.length () : param_length(pos_e));
01371
01372 bytes1 = val.byte_size ();
01373 ss2 << bytes1;
01374 str = ss2.str ();
01375 param_length(pos_b) = ((str.length ()
01376 > static_cast<size_t> (param_length(pos_b)))
01377 ? str.length () : param_length (pos_b));
01378 }
01379
01380 idx = 0;
01381 while (static_cast<size_t> (idx) < format_len)
01382 {
01383 whos_parameter param;
01384 param.command = '\0';
01385
01386 if (Vwhos_line_format[idx] == '%')
01387 {
01388 bool error_encountered = false;
01389 param.modifier = 'r';
01390 param.parameter_length = 0;
01391
01392 int a = 0, b = -1, balance = 1;
01393 unsigned int items;
01394 size_t pos;
01395 std::string cmd;
01396
01397
01398 cmd = Vwhos_line_format.substr (idx, Vwhos_line_format.length ());
01399 pos = cmd.find (';');
01400 if (pos != std::string::npos)
01401 cmd = cmd.substr (0, pos+1);
01402 else
01403 error ("parameter without ; in whos_line_format");
01404
01405 idx += cmd.length ();
01406
01407
01408
01409 if (cmd.find_first_of ("crl") != 1)
01410 items = sscanf (cmd.c_str (), "%c%c:%d:%d:%d;",
01411 &garbage, ¶m.command, &a, &b, &balance);
01412 else
01413 items = sscanf (cmd.c_str (), "%c%c%c:%d:%d:%d;",
01414 &garbage, ¶m.modifier, ¶m.command,
01415 &a, &b, &balance) - 1;
01416
01417 if (items < 2)
01418 {
01419 error ("whos_line_format: parameter structure without command in whos_line_format");
01420 error_encountered = true;
01421 }
01422
01423
01424 param.first_parameter_length = 0;
01425 pos = param_string.find (param.command);
01426 if (pos != std::string::npos)
01427 {
01428 param.parameter_length = param_length(pos);
01429 param.text = param_names(pos);
01430 param.line.assign (param_names(pos).length (), '=');
01431
01432 param.parameter_length = (a > param.parameter_length
01433 ? a : param.parameter_length);
01434 if (param.command == 's' && param.modifier == 'c' && b > 0)
01435 param.first_parameter_length = b;
01436 }
01437 else
01438 {
01439 error ("whos_line_format: '%c' is not a command",
01440 param.command);
01441 error_encountered = true;
01442 }
01443
01444 if (param.command == 's')
01445 {
01446
01447
01448
01449
01450
01451
01452 int rest = 0;
01453 int first = param.first_parameter_length;
01454 int total = param.parameter_length;
01455
01456 for (std::list<symbol_info>::const_iterator p = lst.begin ();
01457 p != lst.end (); p++)
01458 {
01459 octave_value val = p->varval;
01460 std::string dims_str = get_dims_str (val);
01461 int first1 = dims_str.find ('x');
01462 int total1 = dims_str.length ();
01463 int rest1 = total1 - first1;
01464 rest = (rest1 > rest ? rest1 : rest);
01465 first = (first1 > first ? first1 : first);
01466 total = (total1 > total ? total1 : total);
01467 }
01468
01469 if (param.modifier == 'c')
01470 {
01471 if (first < balance)
01472 first += balance - first;
01473 if (rest + balance < param.parameter_length)
01474 rest += param.parameter_length - rest - balance;
01475
01476 param.parameter_length = first + rest;
01477 param.first_parameter_length = first;
01478 param.balance = balance;
01479 }
01480 else
01481 {
01482 param.parameter_length = total;
01483 param.first_parameter_length = 0;
01484 }
01485 }
01486 else if (param.modifier == 'c')
01487 {
01488 error ("whos_line_format: modifier 'c' not available for command '%c'",
01489 param.command);
01490 error_encountered = true;
01491 }
01492
01493
01494
01495 param.balance = (b < 0 ? 0 : param.balance);
01496 param.first_parameter_length = (b < 0 ? 0 :
01497 param.first_parameter_length);
01498 param.parameter_length = (a < 0
01499 ? 0
01500 : (param.parameter_length
01501 < param_length(pos_s)
01502 ? param_length(pos_s)
01503 : param.parameter_length));
01504
01505
01506 if (! error_encountered)
01507 params.push_back (param);
01508 }
01509 else
01510 {
01511
01512 std::string text;
01513 size_t pos;
01514 text = Vwhos_line_format.substr (idx, Vwhos_line_format.length ());
01515 pos = text.find ('%');
01516 if (pos != std::string::npos)
01517 text = text.substr (0, pos);
01518
01519
01520 idx += text.length ();
01521 param.text=text;
01522 param.line.assign (text.length(), ' ');
01523 params.push_back (param);
01524 }
01525 }
01526
01527 return params;
01528 }
01529
01530 private:
01531 std::list<symbol_info> lst;
01532
01533 };
01534
01535 static octave_value
01536 do_who (int argc, const string_vector& argv, bool return_list,
01537 bool verbose = false, std::string msg = std::string ())
01538 {
01539 octave_value retval;
01540
01541 std::string my_name = argv[0];
01542
01543 bool global_only = false;
01544 bool have_regexp = false;
01545
01546 int i;
01547 for (i = 1; i < argc; i++)
01548 {
01549 if (argv[i] == "-file")
01550 {
01551
01552
01553
01554
01555
01556
01557 if (i == argc - 1)
01558 error ("whos: -file argument must be followed by a file name");
01559 else
01560 {
01561 std::string nm = argv [i + 1];
01562
01563 unwind_protect frame;
01564
01565
01566
01567 symbol_table::scope_id tmp_scope = symbol_table::alloc_scope ();
01568 frame.add_fcn (symbol_table::erase_scope, tmp_scope);
01569
01570 symbol_table::set_scope (tmp_scope);
01571
01572 octave_call_stack::push (tmp_scope, 0);
01573 frame.add_fcn (octave_call_stack::pop);
01574
01575 frame.add_fcn (symbol_table::clear_variables);
01576
01577 feval ("load", octave_value (nm), 0);
01578
01579 if (! error_state)
01580 {
01581 std::string newmsg = std::string ("Variables in the file ") +
01582 nm + ":\n\n";
01583
01584 retval = do_who (i, argv, return_list, verbose, newmsg);
01585 }
01586 }
01587
01588 return retval;
01589 }
01590 else if (argv[i] == "-regexp")
01591 have_regexp = true;
01592 else if (argv[i] == "global")
01593 global_only = true;
01594 else if (argv[i][0] == '-')
01595 warning ("%s: unrecognized option '%s'", my_name.c_str (),
01596 argv[i].c_str ());
01597 else
01598 break;
01599 }
01600
01601 int npats = argc - i;
01602 string_vector pats;
01603 if (npats > 0)
01604 {
01605 pats.resize (npats);
01606 for (int j = 0; j < npats; j++)
01607 pats[j] = argv[i+j];
01608 }
01609 else
01610 {
01611 pats.resize (++npats);
01612 pats[0] = "*";
01613 }
01614
01615 symbol_info_list symbol_stats;
01616 std::list<std::string> symbol_names;
01617
01618 for (int j = 0; j < npats; j++)
01619 {
01620 std::string pat = pats[j];
01621
01622 if (have_regexp)
01623 {
01624 std::list<symbol_table::symbol_record> tmp = global_only
01625 ? symbol_table::regexp_global_variables (pat)
01626 : symbol_table::regexp_variables (pat);
01627
01628 for (std::list<symbol_table::symbol_record>::const_iterator p = tmp.begin ();
01629 p != tmp.end (); p++)
01630 {
01631 if (p->is_variable ())
01632 {
01633 if (verbose)
01634 symbol_stats.append (*p);
01635 else
01636 symbol_names.push_back (p->name ());
01637 }
01638 }
01639 }
01640 else
01641 {
01642 size_t pos = pat.find_first_of (".({");
01643
01644 if (pos != std::string::npos && pos > 0)
01645 {
01646 if (verbose)
01647 {
01648
01649
01650
01651
01652
01653
01654
01655 std::string base_name = pat.substr (0, pos);
01656
01657 if (symbol_table::is_variable (base_name))
01658 {
01659 symbol_table::symbol_record sr
01660 = symbol_table::find_symbol (base_name);
01661
01662 if (! global_only || sr.is_global ())
01663 {
01664 int parse_status;
01665
01666 octave_value expr_val
01667 = eval_string (pat, true, parse_status);
01668
01669 if (! error_state)
01670 symbol_stats.append (sr, pat, expr_val);
01671 else
01672 return retval;
01673 }
01674 }
01675 }
01676 }
01677 else
01678 {
01679 std::list<symbol_table::symbol_record> tmp = global_only
01680 ? symbol_table::glob_global_variables (pat)
01681 : symbol_table::glob_variables (pat);
01682
01683 for (std::list<symbol_table::symbol_record>::const_iterator p = tmp.begin ();
01684 p != tmp.end (); p++)
01685 {
01686 if (p->is_variable ())
01687 {
01688 if (verbose)
01689 symbol_stats.append (*p);
01690 else
01691 symbol_names.push_back (p->name ());
01692 }
01693 }
01694 }
01695 }
01696 }
01697
01698 if (return_list)
01699 {
01700 if (verbose)
01701 {
01702 std::string caller_function_name;
01703 octave_function *caller = octave_call_stack::caller ();
01704 if (caller)
01705 caller_function_name = caller->name ();
01706
01707 retval = symbol_stats.map_value (caller_function_name, 1);
01708 }
01709 else
01710 retval = Cell (string_vector (symbol_names));
01711 }
01712 else if (! (symbol_stats.empty () && symbol_names.empty ()))
01713 {
01714 if (msg.length () == 0)
01715 if (global_only)
01716 octave_stdout << "Global variables:\n\n";
01717 else
01718 octave_stdout << "Variables in the current scope:\n\n";
01719 else
01720 octave_stdout << msg;
01721
01722 if (verbose)
01723 symbol_stats.display (octave_stdout);
01724 else
01725 {
01726 string_vector names (symbol_names);
01727
01728 names.list_in_columns (octave_stdout);
01729 }
01730
01731 octave_stdout << "\n";
01732 }
01733
01734 return retval;
01735 }
01736
01737 DEFUN (who, args, nargout,
01738 "-*- texinfo -*-\n\
01739 @deftypefn {Command} {} who\n\
01740 @deftypefnx {Command} {} who pattern @dots{}\n\
01741 @deftypefnx {Command} {} who option pattern @dots{}\n\
01742 @deftypefnx {Command} {C =} who (\"pattern\", @dots{})\n\
01743 List currently defined variables matching the given patterns. Valid\n\
01744 pattern syntax is the same as described for the @code{clear} command.\n\
01745 If no patterns are supplied, all variables are listed.\n\
01746 By default, only variables visible in the local scope are displayed.\n\
01747 \n\
01748 The following are valid options but may not be combined.\n\
01749 \n\
01750 @table @code\n\
01751 @item global\n\
01752 List variables in the global scope rather than the current scope.\n\
01753 \n\
01754 @item -regexp\n\
01755 The patterns are considered to be regular expressions when matching the\n\
01756 variables to display. The same pattern syntax accepted by\n\
01757 the @code{regexp} function is used.\n\
01758 \n\
01759 @item -file\n\
01760 The next argument is treated as a filename. All variables found within the\n\
01761 specified file are listed. No patterns are accepted when reading variables\n\
01762 from a file.\n\
01763 @end table\n\
01764 \n\
01765 If called as a function, return a cell array of defined variable names\n\
01766 matching the given patterns.\n\
01767 @seealso{whos, isglobal, isvarname, exist, regexp}\n\
01768 @end deftypefn")
01769 {
01770 octave_value retval;
01771
01772 if (nargout < 2)
01773 {
01774 int argc = args.length () + 1;
01775
01776 string_vector argv = args.make_argv ("who");
01777
01778 if (! error_state)
01779 retval = do_who (argc, argv, nargout == 1);
01780 }
01781 else
01782 print_usage ();
01783
01784 return retval;
01785 }
01786
01787 DEFUN (whos, args, nargout,
01788 "-*- texinfo -*-\n\
01789 @deftypefn {Command} {} whos\n\
01790 @deftypefnx {Command} {} whos pattern @dots{}\n\
01791 @deftypefnx {Command} {} whos option pattern @dots{}\n\
01792 @deftypefnx {Command} {S =} whos (\"pattern\", @dots{})\n\
01793 Provide detailed information on currently defined variables matching the\n\
01794 given patterns. Options and pattern syntax are the same as for the\n\
01795 @code{who} command. Extended information about each variable is\n\
01796 summarized in a table with the following default entries.\n\
01797 \n\
01798 @table @asis\n\
01799 @item Attr\n\
01800 Attributes of the listed variable. Possible attributes are:\n\
01801 @table @asis\n\
01802 @item blank\n\
01803 Variable in local scope\n\
01804 \n\
01805 @item @code{a}\n\
01806 Automatic variable. An automatic variable is one created by the\n\
01807 interpreter, for example @code{argn}.\n\
01808 \n\
01809 @item @code{c}\n\
01810 Variable of complex type.\n\
01811 \n\
01812 @item @code{f}\n\
01813 Formal parameter (function argument).\n\
01814 \n\
01815 @item @code{g}\n\
01816 Variable with global scope.\n\
01817 \n\
01818 @item @code{p}\n\
01819 Persistent variable.\n\
01820 @end table\n\
01821 \n\
01822 @item Name\n\
01823 The name of the variable.\n\
01824 \n\
01825 @item Size\n\
01826 The logical size of the variable. A scalar is 1x1, a vector is\n\
01827 @nospell{1xN} or @nospell{Nx1}, a 2-D matrix is @nospell{MxN}.\n\
01828 \n\
01829 @item Bytes\n\
01830 The amount of memory currently used to store the variable.\n\
01831 \n\
01832 @item Class\n\
01833 The class of the variable. Examples include double, single, char, uint16,\n\
01834 cell, and struct.\n\
01835 @end table\n\
01836 \n\
01837 The table can be customized to display more or less information through\n\
01838 the function @code{whos_line_format}.\n\
01839 \n\
01840 If @code{whos} is called as a function, return a struct array of defined\n\
01841 variable names matching the given patterns. Fields in the structure\n\
01842 describing each variable are: name, size, bytes, class, global, sparse,\n\
01843 complex, nesting, persistent.\n\
01844 @seealso{who, whos_line_format}\n\
01845 @end deftypefn")
01846 {
01847 octave_value retval;
01848
01849 if (nargout < 2)
01850 {
01851 int argc = args.length () + 1;
01852
01853 string_vector argv = args.make_argv ("whos");
01854
01855 if (! error_state)
01856 retval = do_who (argc, argv, nargout == 1, true);
01857 }
01858 else
01859 print_usage ();
01860
01861 return retval;
01862 }
01863
01864
01865
01866 void
01867 bind_ans (const octave_value& val, bool print)
01868 {
01869 static std::string ans = "ans";
01870
01871 if (val.is_defined ())
01872 {
01873 if (val.is_cs_list ())
01874 {
01875 octave_value_list lst = val.list_value ();
01876
01877 for (octave_idx_type i = 0; i < lst.length (); i++)
01878 bind_ans (lst(i), print);
01879 }
01880 else
01881 {
01882 symbol_table::varref (ans) = val;
01883
01884 if (print)
01885 val.print_with_name (octave_stdout, ans);
01886 }
01887 }
01888 }
01889
01890 void
01891 bind_internal_variable (const std::string& fname, const octave_value& val)
01892 {
01893 octave_value_list args;
01894
01895 args(0) = val;
01896
01897 feval (fname, args, 0);
01898 }
01899
01900 void
01901 mlock (void)
01902 {
01903 octave_function *fcn = octave_call_stack::current ();
01904
01905 if (fcn)
01906 fcn->lock ();
01907 else
01908 error ("mlock: invalid use outside a function");
01909 }
01910
01911 void
01912 munlock (const std::string& nm)
01913 {
01914 octave_value val = symbol_table::find_function (nm);
01915
01916 if (val.is_defined ())
01917 {
01918 octave_function *fcn = val.function_value ();
01919
01920 if (fcn)
01921 fcn->unlock ();
01922 }
01923 }
01924
01925 bool
01926 mislocked (const std::string& nm)
01927 {
01928 bool retval = false;
01929
01930 octave_value val = symbol_table::find_function (nm);
01931
01932 if (val.is_defined ())
01933 {
01934 octave_function *fcn = val.function_value ();
01935
01936 if (fcn)
01937 retval = fcn->islocked ();
01938 }
01939
01940 return retval;
01941 }
01942
01943 DEFUN (mlock, args, ,
01944 "-*- texinfo -*-\n\
01945 @deftypefn {Built-in Function} {} mlock ()\n\
01946 Lock the current function into memory so that it can't be cleared.\n\
01947 @seealso{munlock, mislocked, persistent}\n\
01948 @end deftypefn")
01949 {
01950 octave_value_list retval;
01951
01952 if (args.length () == 0)
01953 {
01954 octave_function *fcn = octave_call_stack::caller ();
01955
01956 if (fcn)
01957 fcn->lock ();
01958 else
01959 error ("mlock: invalid use outside a function");
01960 }
01961 else
01962 print_usage ();
01963
01964 return retval;
01965 }
01966
01967 DEFUN (munlock, args, ,
01968 "-*- texinfo -*-\n\
01969 @deftypefn {Built-in Function} {} munlock ()\n\
01970 @deftypefnx {Built-in Function} {} munlock (@var{fcn})\n\
01971 Unlock the named function @var{fcn}. If no function is named\n\
01972 then unlock the current function.\n\
01973 @seealso{mlock, mislocked, persistent}\n\
01974 @end deftypefn")
01975 {
01976 octave_value_list retval;
01977
01978 if (args.length() == 1)
01979 {
01980 std::string name = args(0).string_value ();
01981
01982 if (! error_state)
01983 munlock (name);
01984 else
01985 error ("munlock: FCN must be a string");
01986 }
01987 else if (args.length () == 0)
01988 {
01989 octave_function *fcn = octave_call_stack::caller ();
01990
01991 if (fcn)
01992 fcn->unlock ();
01993 else
01994 error ("munlock: invalid use outside a function");
01995 }
01996 else
01997 print_usage ();
01998
01999 return retval;
02000 }
02001
02002
02003 DEFUN (mislocked, args, ,
02004 "-*- texinfo -*-\n\
02005 @deftypefn {Built-in Function} {} mislocked ()\n\
02006 @deftypefnx {Built-in Function} {} mislocked (@var{fcn})\n\
02007 Return true if the named function @var{fcn} is locked. If no function is\n\
02008 named then return true if the current function is locked.\n\
02009 @seealso{mlock, munlock, persistent}\n\
02010 @end deftypefn")
02011 {
02012 octave_value retval;
02013
02014 if (args.length() == 1)
02015 {
02016 std::string name = args(0).string_value ();
02017
02018 if (! error_state)
02019 retval = mislocked (name);
02020 else
02021 error ("mislocked: FCN must be a string");
02022 }
02023 else if (args.length () == 0)
02024 {
02025 octave_function *fcn = octave_call_stack::caller ();
02026
02027 if (fcn)
02028 retval = fcn->islocked ();
02029 else
02030 error ("mislocked: invalid use outside a function");
02031 }
02032 else
02033 print_usage ();
02034
02035 return retval;
02036 }
02037
02038
02039
02040 static inline bool
02041 name_matches_any_pattern (const std::string& nm, const string_vector& argv,
02042 int argc, int idx, bool have_regexp = false)
02043 {
02044 bool retval = false;
02045
02046 for (int k = idx; k < argc; k++)
02047 {
02048 std::string patstr = argv[k];
02049 if (! patstr.empty ())
02050 {
02051 if (have_regexp)
02052 {
02053 if (is_regexp_match (patstr, nm))
02054 {
02055 retval = true;
02056 break;
02057 }
02058 }
02059 else
02060 {
02061 glob_match pattern (patstr);
02062
02063 if (pattern.match (nm))
02064 {
02065 retval = true;
02066 break;
02067 }
02068 }
02069 }
02070 }
02071
02072 return retval;
02073 }
02074
02075 static inline void
02076 maybe_warn_exclusive (bool exclusive)
02077 {
02078 if (exclusive)
02079 warning ("clear: ignoring --exclusive option");
02080 }
02081
02082 static void
02083 do_clear_functions (const string_vector& argv, int argc, int idx,
02084 bool exclusive = false)
02085 {
02086 if (idx == argc)
02087 symbol_table::clear_functions ();
02088 else
02089 {
02090 if (exclusive)
02091 {
02092 string_vector fcns = symbol_table::user_function_names ();
02093
02094 int fcount = fcns.length ();
02095
02096 for (int i = 0; i < fcount; i++)
02097 {
02098 std::string nm = fcns[i];
02099
02100 if (! name_matches_any_pattern (nm, argv, argc, idx))
02101 symbol_table::clear_function (nm);
02102 }
02103 }
02104 else
02105 {
02106 while (idx < argc)
02107 symbol_table::clear_function_pattern (argv[idx++]);
02108 }
02109 }
02110 }
02111
02112 static void
02113 do_clear_globals (const string_vector& argv, int argc, int idx,
02114 bool exclusive = false)
02115 {
02116 if (idx == argc)
02117 {
02118 string_vector gvars = symbol_table::global_variable_names ();
02119
02120 int gcount = gvars.length ();
02121
02122 for (int i = 0; i < gcount; i++)
02123 symbol_table::clear_global (gvars[i]);
02124 }
02125 else
02126 {
02127 if (exclusive)
02128 {
02129 string_vector gvars = symbol_table::global_variable_names ();
02130
02131 int gcount = gvars.length ();
02132
02133 for (int i = 0; i < gcount; i++)
02134 {
02135 std::string nm = gvars[i];
02136
02137 if (! name_matches_any_pattern (nm, argv, argc, idx))
02138 symbol_table::clear_global (nm);
02139 }
02140 }
02141 else
02142 {
02143 while (idx < argc)
02144 symbol_table::clear_global_pattern (argv[idx++]);
02145 }
02146 }
02147 }
02148
02149 static void
02150 do_clear_variables (const string_vector& argv, int argc, int idx,
02151 bool exclusive = false, bool have_regexp = false)
02152 {
02153 if (idx == argc)
02154 symbol_table::clear_variables ();
02155 else
02156 {
02157 if (exclusive)
02158 {
02159 string_vector lvars = symbol_table::variable_names ();
02160
02161 int lcount = lvars.length ();
02162
02163 for (int i = 0; i < lcount; i++)
02164 {
02165 std::string nm = lvars[i];
02166
02167 if (! name_matches_any_pattern (nm, argv, argc, idx, have_regexp))
02168 symbol_table::clear_variable (nm);
02169 }
02170 }
02171 else
02172 {
02173 if (have_regexp)
02174 while (idx < argc)
02175 symbol_table::clear_variable_regexp (argv[idx++]);
02176 else
02177 while (idx < argc)
02178 symbol_table::clear_variable_pattern (argv[idx++]);
02179 }
02180 }
02181 }
02182
02183 static void
02184 do_clear_symbols (const string_vector& argv, int argc, int idx,
02185 bool exclusive = false)
02186 {
02187 if (idx == argc)
02188 symbol_table::clear_variables ();
02189 else
02190 {
02191 if (exclusive)
02192 {
02193
02194
02195
02196
02197
02198 do_clear_variables (argv, argc, idx, exclusive);
02199 do_clear_functions (argv, argc, idx, exclusive);
02200 }
02201 else
02202 {
02203 while (idx < argc)
02204 symbol_table::clear_symbol_pattern (argv[idx++]);
02205 }
02206 }
02207 }
02208
02209 static void
02210 do_matlab_compatible_clear (const string_vector& argv, int argc, int idx)
02211 {
02212
02213
02214 for (; idx < argc; idx++)
02215 {
02216 if (argv[idx] == "all"
02217 && ! symbol_table::is_local_variable ("all"))
02218 {
02219 symbol_table::clear_all ();
02220 }
02221 else if (argv[idx] == "functions"
02222 && ! symbol_table::is_local_variable ("functions"))
02223 {
02224 do_clear_functions (argv, argc, ++idx);
02225 }
02226 else if (argv[idx] == "global"
02227 && ! symbol_table::is_local_variable ("global"))
02228 {
02229 do_clear_globals (argv, argc, ++idx);
02230 }
02231 else if (argv[idx] == "variables"
02232 && ! symbol_table::is_local_variable ("variables"))
02233 {
02234 symbol_table::clear_variables ();
02235 }
02236 else if (argv[idx] == "classes"
02237 && ! symbol_table::is_local_variable ("classes"))
02238 {
02239 symbol_table::clear_objects ();
02240 octave_class::clear_exemplar_map ();
02241 }
02242 else
02243 {
02244 symbol_table::clear_symbol_pattern (argv[idx]);
02245 }
02246 }
02247 }
02248
02249 #define CLEAR_OPTION_ERROR(cond) \
02250 do \
02251 { \
02252 if (cond) \
02253 { \
02254 print_usage (); \
02255 return retval; \
02256 } \
02257 } \
02258 while (0)
02259
02260 DEFUN (clear, args, ,
02261 "-*- texinfo -*-\n\
02262 @deftypefn {Command} {} clear [options] pattern @dots{}\n\
02263 Delete the names matching the given patterns from the symbol table. The\n\
02264 pattern may contain the following special characters:\n\
02265 \n\
02266 @table @code\n\
02267 @item ?\n\
02268 Match any single character.\n\
02269 \n\
02270 @item *\n\
02271 Match zero or more characters.\n\
02272 \n\
02273 @item [ @var{list} ]\n\
02274 Match the list of characters specified by @var{list}. If the first\n\
02275 character is @code{!} or @code{^}, match all characters except those\n\
02276 specified by @var{list}. For example, the pattern @samp{[a-zA-Z]} will\n\
02277 match all lowercase and uppercase alphabetic characters.\n\
02278 @end table\n\
02279 \n\
02280 For example, the command\n\
02281 \n\
02282 @example\n\
02283 clear foo b*r\n\
02284 @end example\n\
02285 \n\
02286 @noindent\n\
02287 clears the name @code{foo} and all names that begin with the letter\n\
02288 @code{b} and end with the letter @code{r}.\n\
02289 \n\
02290 If @code{clear} is called without any arguments, all user-defined\n\
02291 variables (local and global) are cleared from the symbol table. If\n\
02292 @code{clear} is called with at least one argument, only the visible\n\
02293 names matching the arguments are cleared. For example, suppose you have\n\
02294 defined a function @code{foo}, and then hidden it by performing the\n\
02295 assignment @code{foo = 2}. Executing the command @kbd{clear foo} once\n\
02296 will clear the variable definition and restore the definition of\n\
02297 @code{foo} as a function. Executing @kbd{clear foo} a second time will\n\
02298 clear the function definition.\n\
02299 \n\
02300 The following options are available in both long and short form\n\
02301 @table @code\n\
02302 @item -all, -a\n\
02303 Clears all local and global user-defined variables and all functions\n\
02304 from the symbol table.\n\
02305 \n\
02306 @item -exclusive, -x\n\
02307 Clears the variables that don't match the following pattern.\n\
02308 \n\
02309 @item -functions, -f\n\
02310 Clears the function names and the built-in symbols names.\n\
02311 \n\
02312 @item -global, -g\n\
02313 Clears the global symbol names.\n\
02314 \n\
02315 @item -variables, -v\n\
02316 Clears the local variable names.\n\
02317 \n\
02318 @item -classes, -c\n\
02319 Clears the class structure table and clears all objects.\n\
02320 \n\
02321 @item -regexp, -r\n\
02322 The arguments are treated as regular expressions as any variables that\n\
02323 match will be cleared.\n\
02324 @end table\n\
02325 With the exception of @code{exclusive}, all long options can be used\n\
02326 without the dash as well.\n\
02327 @end deftypefn")
02328 {
02329 octave_value_list retval;
02330
02331 int argc = args.length () + 1;
02332
02333 string_vector argv = args.make_argv ("clear");
02334
02335 if (! error_state)
02336 {
02337 if (argc == 1)
02338 {
02339 do_clear_globals (argv, argc, 1);
02340 do_clear_variables (argv, argc, 1);
02341 }
02342 else
02343 {
02344 int idx = 0;
02345
02346 bool clear_all = false;
02347 bool clear_functions = false;
02348 bool clear_globals = false;
02349 bool clear_variables = false;
02350 bool clear_objects = false;
02351 bool exclusive = false;
02352 bool have_regexp = false;
02353 bool have_dash_option = false;
02354
02355 while (++idx < argc)
02356 {
02357 if (argv[idx] == "-all" || argv[idx] == "-a")
02358 {
02359 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
02360
02361 have_dash_option = true;
02362 clear_all = true;
02363 }
02364 else if (argv[idx] == "-exclusive" || argv[idx] == "-x")
02365 {
02366 have_dash_option = true;
02367 exclusive = true;
02368 }
02369 else if (argv[idx] == "-functions" || argv[idx] == "-f")
02370 {
02371 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
02372
02373 have_dash_option = true;
02374 clear_functions = true;
02375 }
02376 else if (argv[idx] == "-global" || argv[idx] == "-g")
02377 {
02378 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
02379
02380 have_dash_option = true;
02381 clear_globals = true;
02382 }
02383 else if (argv[idx] == "-variables" || argv[idx] == "-v")
02384 {
02385 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
02386
02387 have_dash_option = true;
02388 clear_variables = true;
02389 }
02390 else if (argv[idx] == "-classes" || argv[idx] == "-c")
02391 {
02392 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
02393
02394 have_dash_option = true;
02395 clear_objects = true;
02396 }
02397 else if (argv[idx] == "-regexp" || argv[idx] == "-r")
02398 {
02399 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
02400
02401 have_dash_option = true;
02402 have_regexp = true;
02403 }
02404 else
02405 break;
02406 }
02407
02408 if (idx <= argc)
02409 {
02410 if (! have_dash_option)
02411 {
02412 do_matlab_compatible_clear (argv, argc, idx);
02413 }
02414 else
02415 {
02416 if (clear_all)
02417 {
02418 maybe_warn_exclusive (exclusive);
02419
02420 if (++idx < argc)
02421 warning
02422 ("clear: ignoring extra arguments after -all");
02423
02424 symbol_table::clear_all ();
02425 }
02426 else if (have_regexp)
02427 {
02428 do_clear_variables (argv, argc, idx, exclusive, true);
02429 }
02430 else if (clear_functions)
02431 {
02432 do_clear_functions (argv, argc, idx, exclusive);
02433 }
02434 else if (clear_globals)
02435 {
02436 do_clear_globals (argv, argc, idx, exclusive);
02437 }
02438 else if (clear_variables)
02439 {
02440 do_clear_variables (argv, argc, idx, exclusive);
02441 }
02442 else if (clear_objects)
02443 {
02444 symbol_table::clear_objects ();
02445 octave_class::clear_exemplar_map ();
02446 }
02447 else
02448 {
02449 do_clear_symbols (argv, argc, idx, exclusive);
02450 }
02451 }
02452 }
02453 }
02454 }
02455
02456 return retval;
02457 }
02458
02459 DEFUN (whos_line_format, args, nargout,
02460 "-*- texinfo -*-\n\
02461 @deftypefn {Built-in Function} {@var{val} =} whos_line_format ()\n\
02462 @deftypefnx {Built-in Function} {@var{old_val} =} whos_line_format (@var{new_val})\n\
02463 @deftypefnx {Built-in Function} {} whos_line_format (@var{new_val}, \"local\")\n\
02464 Query or set the format string used by the command @code{whos}.\n\
02465 \n\
02466 A full format string is:\n\
02467 @c Set example in small font to prevent overfull line\n\
02468 \n\
02469 @smallexample\n\
02470 %[modifier]<command>[:width[:left-min[:balance]]];\n\
02471 @end smallexample\n\
02472 \n\
02473 The following command sequences are available:\n\
02474 \n\
02475 @table @code\n\
02476 @item %a\n\
02477 Prints attributes of variables (g=global, p=persistent,\n\
02478 f=formal parameter, a=automatic variable).\n\
02479 \n\
02480 @item %b\n\
02481 Prints number of bytes occupied by variables.\n\
02482 \n\
02483 @item %c\n\
02484 Prints class names of variables.\n\
02485 \n\
02486 @item %e\n\
02487 Prints elements held by variables.\n\
02488 \n\
02489 @item %n\n\
02490 Prints variable names.\n\
02491 \n\
02492 @item %s\n\
02493 Prints dimensions of variables.\n\
02494 \n\
02495 @item %t\n\
02496 Prints type names of variables.\n\
02497 @end table\n\
02498 \n\
02499 Every command may also have an alignment modifier:\n\
02500 \n\
02501 @table @code\n\
02502 @item l\n\
02503 Left alignment.\n\
02504 \n\
02505 @item r\n\
02506 Right alignment (default).\n\
02507 \n\
02508 @item c\n\
02509 Column-aligned (only applicable to command %s).\n\
02510 @end table\n\
02511 \n\
02512 The @code{width} parameter is a positive integer specifying the minimum\n\
02513 number of columns used for printing. No maximum is needed as the field will\n\
02514 auto-expand as required.\n\
02515 \n\
02516 The parameters @code{left-min} and @code{balance} are only available when the\n\
02517 column-aligned modifier is used with the command @samp{%s}.\n\
02518 @code{balance} specifies the column number within the field width which will\n\
02519 be aligned between entries. Numbering starts from 0 which indicates the\n\
02520 leftmost column. @code{left-min} specifies the minimum field width to the\n\
02521 left of the specified balance column.\n\
02522 \n\
02523 The default format is\n\
02524 @code{\" %a:4; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;\\n\"}.\n\
02525 \n\
02526 When called from inside a function with the \"local\" option, the variable is\n\
02527 changed locally for the function and any subroutines it calls. The original\n\
02528 variable value is restored when exiting the function.\n\
02529 @seealso{whos}\n\
02530 @end deftypefn")
02531 {
02532 return SET_INTERNAL_VARIABLE (whos_line_format);
02533 }
02534
02535 static std::string Vmissing_function_hook = "unimplemented";
02536
02537 DEFUN (missing_function_hook, args, nargout,
02538 "-*- texinfo -*-\n\
02539 @deftypefn {Built-in Function} {@var{val} =} missing_function_hook ()\n\
02540 @deftypefnx {Built-in Function} {@var{old_val} =} missing_function_hook (@var{new_val})\n\
02541 @deftypefnx {Built-in Function} {} missing_function_hook (@var{new_val}, \"local\")\n\
02542 Query or set the internal variable that specifies the function to call when\n\
02543 an unknown identifier is requested.\n\
02544 \n\
02545 When called from inside a function with the \"local\" option, the variable is\n\
02546 changed locally for the function and any subroutines it calls. The original\n\
02547 variable value is restored when exiting the function.\n\
02548 @end deftypefn")
02549 {
02550 return SET_INTERNAL_VARIABLE (missing_function_hook);
02551 }
02552
02553 void maybe_missing_function_hook (const std::string& name)
02554 {
02555
02556 if (buffer_error_messages == 0 && ! Vmissing_function_hook.empty ())
02557 {
02558
02559 unwind_protect frame;
02560 frame.protect_var (Vmissing_function_hook);
02561
02562
02563 const std::string func_name = Vmissing_function_hook;
02564 Vmissing_function_hook.clear ();
02565
02566
02567 feval (func_name, octave_value (name));
02568 }
02569 }
02570
02571 DEFUN (__varval__, args, ,
02572 "-*- texinfo -*-\n\
02573 @deftypefn {Built-in Function} {} __varval__ (@var{name})\n\
02574 Undocumented internal function.\n\
02575 @end deftypefn")
02576 {
02577 octave_value retval;
02578
02579 if (args.length () == 1)
02580 {
02581 std::string name = args(0).string_value ();
02582
02583 if (! error_state)
02584 retval = symbol_table::varval (args(0).string_value ());
02585 else
02586 error ("__varval__: expecting argument to be variable name");
02587 }
02588 else
02589 print_usage ();
02590
02591 return retval;
02592 }