comparison src/variables.cc @ 7336:745a8299c2b5

[project @ 2007-12-28 20:56:55 by jwe]
author jwe
date Fri, 28 Dec 2007 20:56:58 +0000
parents 97db94ae2cf0
children 0fa079d04772
comparison
equal deleted inserted replaced
7335:58f5fab3ebe5 7336:745a8299c2b5
26 #endif 26 #endif
27 27
28 #include <cstdio> 28 #include <cstdio>
29 #include <cstring> 29 #include <cstring>
30 30
31 #include <iomanip>
31 #include <set> 32 #include <set>
32 #include <string> 33 #include <string>
33 34
34 #include "file-stat.h" 35 #include "file-stat.h"
35 #include "oct-env.h" 36 #include "oct-env.h"
61 62
62 // Should Octave always check to see if function files have changed 63 // Should Octave always check to see if function files have changed
63 // since they were last compiled? 64 // since they were last compiled?
64 static int Vignore_function_time_stamp = 1; 65 static int Vignore_function_time_stamp = 1;
65 66
66 // Symbol table for symbols at the top level. 67 // Defines layout for the whos/who -long command
67 symbol_table *top_level_sym_tab = 0; 68 static std::string Vwhos_line_format
68 69 = " %a:4; %ln:6; %cs:16:6:8:1; %rb:12; %lc:-1;\n";
69 // Symbol table for the current scope.
70 symbol_table *curr_sym_tab = 0;
71
72 // Symbol table for the current caller scope.
73 symbol_table *curr_caller_sym_tab = 0;
74
75 // Symbol table for global symbols.
76 symbol_table *global_sym_tab = 0;
77
78 // Symbol table for functions and built-in symbols.
79 symbol_table *fbi_sym_tab = 0;
80
81 bool
82 at_top_level (void)
83 {
84 return (curr_sym_tab == top_level_sym_tab);
85 }
86
87 // Initialization.
88
89 // Create the initial symbol tables and set the current scope at the
90 // top level.
91
92 void
93 initialize_symbol_tables (void)
94 {
95 if (! fbi_sym_tab)
96 fbi_sym_tab = new symbol_table (2048, "FBI");
97
98 if (! global_sym_tab)
99 global_sym_tab = new symbol_table (2048, "GLOBAL");
100
101 if (! top_level_sym_tab)
102 top_level_sym_tab = new symbol_table (4096, "TOP");
103
104 curr_caller_sym_tab = curr_sym_tab = top_level_sym_tab;
105 }
106 70
107 void 71 void
108 clear_mex_functions (void) 72 clear_mex_functions (void)
109 { 73 {
110 fbi_sym_tab->clear_mex_functions (); 74 symbol_table::clear_mex_functions ();
75 }
76
77 void
78 clear_function (const std::string& nm)
79 {
80 symbol_table::clear_function (nm);
81 }
82
83 void
84 clear_variable (const std::string& nm)
85 {
86 symbol_table::clear_variable (nm);
87 }
88
89 void
90 clear_symbol (const std::string& nm)
91 {
92 symbol_table::clear_symbol (nm);
111 } 93 }
112 94
113 // Attributes of variables and functions. 95 // Attributes of variables and functions.
114 96
115 // Is this a command-style function? 97 // Is this a command-style function?
116 98
117 static std::set <std::string> command_set; 99 static std::set <std::string> command_set;
118 100
119 static inline bool 101 void
120 is_marked_as_command (const std::string& s)
121 {
122 return command_set.find (s) != command_set.end ();
123 }
124
125 static inline void
126 mark_as_command (const std::string& s) 102 mark_as_command (const std::string& s)
127 { 103 {
128 command_set.insert (s); 104 command_set.insert (s);
129 } 105 }
130 106
131 static inline void 107 static inline void
132 unmark_command (const std::string& s) 108 unmark_command (const std::string& s)
133 { 109 {
134 command_set.erase (s); 110 command_set.erase (s);
135
136 symbol_record *sr = fbi_sym_tab->lookup (s);
137
138 if (sr)
139 sr->unmark_command ();
140 } 111 }
141 112
142 DEFCMD (mark_as_command, args, , 113 DEFCMD (mark_as_command, args, ,
143 "-*- texinfo -*-\n\ 114 "-*- texinfo -*-\n\
144 @deftypefn {Built-in Function} {} mark_as_command (@var{name})\n\ 115 @deftypefn {Built-in Function} {} mark_as_command (@var{name})\n\
146 @seealso{unmark_command, iscommand}\n\ 117 @seealso{unmark_command, iscommand}\n\
147 @end deftypefn") 118 @end deftypefn")
148 { 119 {
149 octave_value_list retval; 120 octave_value_list retval;
150 121
151 if (at_top_level ()) 122 if (symbol_table::at_top_level ())
152 { 123 {
153 int nargin = args.length (); 124 int nargin = args.length ();
154 125
155 if (nargin > 0) 126 if (nargin > 0)
156 { 127 {
180 @seealso{mark_as_command, iscommand}\n\ 151 @seealso{mark_as_command, iscommand}\n\
181 @end deftypefn") 152 @end deftypefn")
182 { 153 {
183 octave_value_list retval; 154 octave_value_list retval;
184 155
185 if (at_top_level ()) 156 if (symbol_table::at_top_level ())
186 { 157 {
187 int nargin = args.length (); 158 int nargin = args.length ();
188 159
189 if (nargin > 0) 160 if (nargin > 0)
190 { 161 {
208 } 179 }
209 180
210 bool 181 bool
211 is_command_name (const std::string& s) 182 is_command_name (const std::string& s)
212 { 183 {
213 bool retval = false; 184 return command_set.find (s) != command_set.end ();
214 185 }
215 symbol_record *sr = fbi_sym_tab->lookup (s); 186
216
217 if (sr)
218 {
219 if (sr->is_command ())
220 retval = true;
221 else if (is_marked_as_command (s))
222 {
223 sr->mark_as_command ();
224 retval = true;
225 }
226 }
227 else
228 retval = is_marked_as_command (s);
229
230 return retval;
231 }
232 187
233 DEFCMD (iscommand, args, , 188 DEFCMD (iscommand, args, ,
234 "-*- texinfo -*-\n\ 189 "-*- texinfo -*-\n\
235 @deftypefn {Built-in Function} {} iscommand (@var{name})\n\ 190 @deftypefn {Built-in Function} {} iscommand (@var{name})\n\
236 Return true if @var{name} is a command style function. If @var{name}\n\ 191 Return true if @var{name} is a command style function. If @var{name}\n\
272 227
273 // Is this a raw input command? 228 // Is this a raw input command?
274 229
275 static std::set <std::string> rawcommand_set; 230 static std::set <std::string> rawcommand_set;
276 231
277 bool
278 is_marked_as_rawcommand (const std::string& s)
279 {
280 return rawcommand_set.find (s) != rawcommand_set.end ();
281 }
282
283 void 232 void
284 mark_as_rawcommand (const std::string& s) 233 mark_as_rawcommand (const std::string& s)
285 { 234 {
286 command_set.insert (s); 235 command_set.insert (s);
287 rawcommand_set.insert (s); 236 rawcommand_set.insert (s);
289 238
290 void 239 void
291 unmark_rawcommand (const std::string& s) 240 unmark_rawcommand (const std::string& s)
292 { 241 {
293 rawcommand_set.erase (s); 242 rawcommand_set.erase (s);
294
295 symbol_record *sr = fbi_sym_tab->lookup (s);
296
297 if (sr)
298 sr->unmark_rawcommand ();
299 } 243 }
300 244
301 DEFCMD (mark_as_rawcommand, args, , 245 DEFCMD (mark_as_rawcommand, args, ,
302 "-*- texinfo -*-\n\ 246 "-*- texinfo -*-\n\
303 @deftypefn {Built-in Function} {} mark_as_rawcommand (@var{name})\n\ 247 @deftypefn {Built-in Function} {} mark_as_rawcommand (@var{name})\n\
312 @seealso{unmark_rawcommand, israwcommand, iscommand, mark_as_command}\n\ 256 @seealso{unmark_rawcommand, israwcommand, iscommand, mark_as_command}\n\
313 @end deftypefn") 257 @end deftypefn")
314 { 258 {
315 octave_value_list retval; 259 octave_value_list retval;
316 260
317 if (at_top_level ()) 261 if (symbol_table::at_top_level ())
318 { 262 {
319 int nargin = args.length (); 263 int nargin = args.length ();
320 264
321 if (nargin > 0) 265 if (nargin > 0)
322 { 266 {
348 @seealso{mark_as_rawcommand, israwcommand, iscommand, unmark_command}\n\ 292 @seealso{mark_as_rawcommand, israwcommand, iscommand, unmark_command}\n\
349 @end deftypefn") 293 @end deftypefn")
350 { 294 {
351 octave_value_list retval; 295 octave_value_list retval;
352 296
353 if (at_top_level ()) 297 if (symbol_table::at_top_level ())
354 { 298 {
355 int nargin = args.length (); 299 int nargin = args.length ();
356 300
357 if (nargin > 0) 301 if (nargin > 0)
358 { 302 {
376 } 320 }
377 321
378 bool 322 bool
379 is_rawcommand_name (const std::string& s) 323 is_rawcommand_name (const std::string& s)
380 { 324 {
381 bool retval = false; 325 return rawcommand_set.find (s) != rawcommand_set.end ();
382
383 symbol_record *sr = fbi_sym_tab->lookup (s);
384
385 if (sr)
386 {
387 if (sr->is_rawcommand ())
388 retval = true;
389 else if (is_marked_as_rawcommand (s))
390 {
391 sr->mark_as_rawcommand ();
392 retval = true;
393 }
394 }
395 else
396 retval = is_marked_as_rawcommand (s);
397
398 return retval;
399 } 326 }
400 327
401 DEFCMD (israwcommand, args, , 328 DEFCMD (israwcommand, args, ,
402 "-*- texinfo -*-\n\ 329 "-*- texinfo -*-\n\
403 @deftypefn {Built-in Function} {} israwcommand (@var{name})\n\ 330 @deftypefn {Built-in Function} {} israwcommand (@var{name})\n\
437 print_usage (); 364 print_usage ();
438 365
439 return retval; 366 return retval;
440 } 367 }
441 368
442 // Is this a built-in function?
443
444 bool
445 is_builtin_function_name (const std::string& s)
446 {
447 symbol_record *sr = fbi_sym_tab->lookup (s);
448 return (sr && sr->is_builtin_function ());
449 }
450
451 // Is this a mapper function?
452
453 bool
454 is_mapper_function_name (const std::string& s)
455 {
456 symbol_record *sr = fbi_sym_tab->lookup (s);
457 return (sr && sr->is_mapper_function ());
458 }
459
460 // Is this function globally in this scope?
461
462 bool
463 is_globally_visible (const std::string& name)
464 {
465 symbol_record *sr = curr_sym_tab->lookup (name);
466 return (sr && sr->is_linked_to_global ());
467 }
468
469 // Is this octave_value a valid function? 369 // Is this octave_value a valid function?
470 370
471 octave_function * 371 octave_function *
472 is_valid_function (const std::string& fcn_name, 372 is_valid_function (const std::string& fcn_name,
473 const std::string& warn_for, bool warn) 373 const std::string& warn_for, bool warn)
474 { 374 {
475 octave_function *ans = 0; 375 octave_function *ans = 0;
476 376
477 symbol_record *sr = 0;
478
479 if (! fcn_name.empty ()) 377 if (! fcn_name.empty ())
480 { 378 {
481 sr = fbi_sym_tab->lookup (fcn_name, true); 379 octave_value val = symbol_table::find_function (fcn_name);
482 380
483 lookup (sr, false); 381 if (val.is_defined ())
484 } 382 ans = val.function_value (true);
485 383 }
486 if (sr) 384
487 { 385 if (! ans && warn)
488 octave_value tmp = sr->def (); 386 error ("%s: the symbol `%s' is not valid as a function",
489 ans = tmp.function_value (true); 387 warn_for.c_str (), fcn_name.c_str ());
490 }
491
492 if (! sr || ! ans || ! sr->is_function ())
493 {
494 if (warn)
495 error ("%s: the symbol `%s' is not valid as a function",
496 warn_for.c_str (), fcn_name.c_str ());
497 ans = 0;
498 }
499 388
500 return ans; 389 return ans;
501 } 390 }
502 391
503 octave_function * 392 octave_function *
611 { 500 {
612 bool retval = false; 501 bool retval = false;
613 502
614 if (! name.empty ()) 503 if (! name.empty ())
615 { 504 {
616 symbol_record *sr = curr_sym_tab->lookup (name); 505 octave_value val = symbol_table::varval (name);
617 506
618 if (! sr) 507 retval = val.is_defined ();
619 sr = fbi_sym_tab->lookup (name);
620
621 retval = (sr && sr->is_variable ());
622 } 508 }
623 509
624 return retval; 510 return retval;
625 } 511 }
626 512
731 { 617 {
732 error ("isglobal: expecting std::string argument"); 618 error ("isglobal: expecting std::string argument");
733 return retval; 619 return retval;
734 } 620 }
735 621
736 symbol_record *sr = curr_sym_tab->lookup (name); 622 return symbol_table::is_global (name);
737
738 retval = (sr && sr->is_linked_to_global ());
739
740 return retval;
741 } 623 }
742 624
743 DEFUN (isglobal, args, , 625 DEFUN (isglobal, args, ,
744 "-*- texinfo -*-\n\ 626 "-*- texinfo -*-\n\
745 @deftypefn {Built-in Function} {} isglobal (@var{name})\n\ 627 @deftypefn {Built-in Function} {} isglobal (@var{name})\n\
785 667
786 // We shouldn't need to look in the global symbol table, since any 668 // We shouldn't need to look in the global symbol table, since any
787 // name that is visible in the current scope will be in the local 669 // name that is visible in the current scope will be in the local
788 // symbol table. 670 // symbol table.
789 671
790 symbol_record *sr = curr_sym_tab->lookup (symbol_name); 672 octave_value_list evaluated_args;
791 673 bool args_evaluated;
792 if (! (sr && sr->is_defined ())) 674
793 sr = fbi_sym_tab->lookup (symbol_name); 675 octave_value val = symbol_table::find (symbol_name, 0, string_vector (),
794 676 evaluated_args, args_evaluated);
795 if (sr && sr->is_defined ()) 677
678 if (val.is_defined ())
796 { 679 {
797 bool not_a_struct = struct_elts.empty (); 680 bool not_a_struct = struct_elts.empty ();
798 bool var_ok = not_a_struct || sr->is_map_element (struct_elts); 681 bool var_ok = not_a_struct /* || val.is_map_element (struct_elts) */;
799 682
800 if (! retval 683 if (! retval
801 && var_ok 684 && var_ok
802 && (type == "any" || type == "var") 685 && (type == "any" || type == "var")
803 && sr->is_user_variable ()) 686 && val.is_constant ())
804 { 687 {
805 retval = 1; 688 retval = 1;
806 } 689 }
807 690
808 if (! retval 691 if (! retval
809 && (type == "any" || type == "builtin")) 692 && (type == "any" || type == "builtin"))
810 { 693 {
811 if (not_a_struct && sr->is_builtin_function ()) 694 if (not_a_struct && val.is_builtin_function ())
812 { 695 {
813 retval = 5; 696 retval = 5;
814 } 697 }
815 } 698 }
816 699
817 if (! retval 700 if (! retval
818 && not_a_struct 701 && not_a_struct
819 && (type == "any" || type == "file") 702 && (type == "any" || type == "file")
820 && (sr->is_user_function () || sr->is_dld_function ())) 703 && (val.is_user_function () || val.is_dld_function ()))
821 { 704 {
822 octave_value t = sr->def (); 705 octave_function *f = val.function_value (true);
823 octave_function *f = t.function_value (true);
824 std::string s = f ? f->fcn_file_name () : std::string (); 706 std::string s = f ? f->fcn_file_name () : std::string ();
825 707
826 retval = s.empty () ? 103 : (sr->is_user_function () ? 2 : 3); 708 retval = s.empty () ? 103 : (val.is_user_function () ? 2 : 3);
827 } 709 }
828 } 710 }
829 711
830 if (! (type == "var" || type == "builtin")) 712 if (! (type == "var" || type == "builtin"))
831 { 713 {
960 print_usage (); 842 print_usage ();
961 843
962 return retval; 844 return retval;
963 } 845 }
964 846
965 bool
966 fcn_out_of_date (octave_function *fcn, const std::string& ff, time_t tp)
967 {
968 bool retval = false;
969
970 fcn->mark_fcn_file_up_to_date (octave_time ());
971
972 if (! (Vignore_function_time_stamp == 2
973 || (Vignore_function_time_stamp && fcn->is_system_fcn_file ())))
974 {
975 file_stat fs (ff);
976
977 if (fs && fs.is_newer (tp))
978 retval = true;
979 }
980
981 return retval;
982 }
983
984 // Is there a corresponding function file that is newer than the
985 // symbol definition?
986
987 static bool
988 symbol_out_of_date (symbol_record *sr)
989 {
990 bool retval = false;
991
992 if (sr)
993 {
994 octave_value ans = sr->def ();
995
996 octave_function *fcn = ans.function_value (true);
997
998 if (fcn)
999 {
1000 std::string ff = fcn->fcn_file_name ();
1001
1002 if (! ff.empty ())
1003 {
1004 octave_time tc = fcn->time_checked ();
1005
1006 bool relative = fcn->is_relative ();
1007
1008 if (tc < Vlast_prompt_time
1009 || (relative && tc < Vlast_chdir_time))
1010 {
1011 octave_time ottp = fcn->time_parsed ();
1012 time_t tp = ottp.unix_time ();
1013
1014 std::string nm = fcn->is_nested_function ()
1015 ? fcn->parent_fcn_name () : fcn->name ();
1016
1017 // FIXME -- the following code is repeated
1018 // in load_fcn_from_file in parse.y.
1019
1020 int nm_len = nm.length ();
1021
1022 std::string file;
1023
1024 if (octave_env::absolute_pathname (nm)
1025 && ((nm_len > 4 && (nm.substr (nm_len-4) == ".oct"
1026 || nm.substr (nm_len-4) == ".mex"))
1027 || (nm_len > 2 && nm.substr (nm_len-4) == ".m")))
1028 {
1029 file = nm;
1030 }
1031 else
1032 {
1033 file = lookup_autoload (nm);
1034
1035 if (file.empty ())
1036 file = load_path::find_fcn (nm);
1037
1038 file = octave_env::make_absolute (file, octave_env::getcwd ());
1039 }
1040
1041 if (file.empty ())
1042 {
1043 // Can't see this function now, so we should
1044 // clear it.
1045
1046 sr->clear ();
1047
1048 retval = true;
1049 }
1050 else if (same_file (file, ff))
1051 {
1052 retval = fcn_out_of_date (fcn, ff, tp);
1053 }
1054 else
1055 {
1056 // Check the full function name. Maybe we already
1057 // parsed it.
1058
1059 symbol_record *full_sr = fbi_sym_tab->lookup (file);
1060
1061 if (full_sr)
1062 {
1063 octave_value v = full_sr->def ();
1064
1065 if (v.is_function ())
1066 {
1067 // OK, swap the aliases around.
1068
1069 // FIXME -- this is a bit
1070 // tricky, so maybe some refactoring is
1071 // in order here too...
1072
1073 symbol_record *short_sr = fbi_sym_tab->lookup (nm);
1074
1075 if (short_sr)
1076 short_sr->alias (full_sr);
1077
1078 // Make local symbol table entry point
1079 // to correct global function too.
1080
1081 sr->alias (full_sr);
1082
1083 fcn = v.function_value ();
1084
1085 retval = fcn_out_of_date (fcn, file, tp);
1086 }
1087 else
1088 retval = true;
1089 }
1090 else
1091 retval = true;
1092 }
1093 }
1094 }
1095 }
1096 }
1097
1098 return retval;
1099 }
1100
1101 bool
1102 lookup (symbol_record *sym_rec, bool exec_script)
1103 {
1104 bool script_executed = false;
1105
1106 if (! sym_rec->is_linked_to_global ())
1107 {
1108 if (sym_rec->is_defined ())
1109 {
1110 if (sym_rec->is_function () && symbol_out_of_date (sym_rec))
1111 script_executed = load_fcn_from_file (sym_rec, exec_script);
1112 }
1113 else if (! sym_rec->is_formal_parameter ())
1114 {
1115 link_to_builtin_or_function (sym_rec);
1116
1117 if (! sym_rec->is_defined ())
1118 script_executed = load_fcn_from_file (sym_rec, exec_script);
1119 else if (sym_rec->is_function () && symbol_out_of_date (sym_rec))
1120 script_executed = load_fcn_from_file (sym_rec, exec_script);
1121 }
1122 }
1123
1124 return script_executed;
1125 }
1126
1127 // Get the symbol record for the given name that is visible in the
1128 // current scope. Reread any function definitions that appear to be
1129 // out of date. If a function is available in a file but is not
1130 // currently loaded, this will load it and insert the name in the
1131 // current symbol table.
1132
1133 symbol_record *
1134 lookup_by_name (const std::string& nm, bool exec_script)
1135 {
1136 symbol_record *sym_rec = curr_sym_tab->lookup (nm, true);
1137
1138 lookup (sym_rec, exec_script);
1139
1140 return sym_rec;
1141 }
1142
1143 octave_value
1144 lookup_function (const std::string& nm, const std::string& parent)
1145 {
1146 octave_value retval;
1147
1148 symbol_record *sr = 0;
1149
1150 if (! parent.empty ())
1151 sr = fbi_sym_tab->lookup (parent + ":" + nm);
1152
1153 if (! sr || ! sr->is_function ())
1154 {
1155 if (curr_parent_function)
1156 sr = fbi_sym_tab->lookup (curr_parent_function->name () + ":" + nm);
1157
1158 if (! sr || ! sr->is_function ())
1159 sr = fbi_sym_tab->lookup (nm, true);
1160
1161 if (sr && ! sr->is_function ())
1162 load_fcn_from_file (sr, false);
1163 }
1164
1165 if (sr)
1166 {
1167 octave_value v = sr->def ();
1168
1169 if (v.is_function ())
1170 retval = v;
1171 }
1172
1173 return retval;
1174 }
1175
1176 octave_value
1177 lookup_user_function (const std::string& nm)
1178 {
1179 octave_value retval;
1180
1181 symbol_record *sr = 0;
1182
1183 if (curr_parent_function)
1184 {
1185 std::string parent = curr_parent_function->name ();
1186
1187 sr = fbi_sym_tab->lookup (parent + ":" + nm);
1188 }
1189
1190 if (! sr || ! sr->is_user_function ())
1191 {
1192 sr = fbi_sym_tab->lookup (nm, true);
1193
1194 if (sr && ! sr->is_user_function ())
1195 load_fcn_from_file (sr, false);
1196 }
1197
1198 if (sr)
1199 retval = sr->def ();
1200
1201 return retval;
1202 }
1203
1204 octave_value 847 octave_value
1205 lookup_function_handle (const std::string& nm) 848 lookup_function_handle (const std::string& nm)
1206 { 849 {
1207 octave_value retval; 850 octave_value val = symbol_table::varval (nm);
1208 851
1209 symbol_record *sr = curr_sym_tab->lookup (nm, true); 852 return val.is_function_handle () ? val : octave_value ();
1210
1211 if (sr && sr->def ().is_function_handle ())
1212 retval = sr->def ();
1213
1214 return retval;
1215 } 853 }
1216 854
1217 octave_value 855 octave_value
1218 get_global_value (const std::string& nm, bool silent) 856 get_global_value (const std::string& nm, bool silent)
1219 { 857 {
1220 octave_value retval; 858 octave_value val = symbol_table::varval (nm, symbol_table::global_scope ());
1221 859
1222 symbol_record *sr = global_sym_tab->lookup (nm); 860 if (val.is_undefined () && ! silent)
1223 861 error ("get_global_by_name: undefined symbol `%s'", nm.c_str ());
1224 if (sr) 862
1225 { 863 return val;
1226 octave_value sr_def = sr->def ();
1227
1228 if (sr_def.is_defined ())
1229 retval = sr_def;
1230 else if (! silent)
1231 error ("get_global_by_name: undefined symbol `%s'", nm.c_str ());
1232 }
1233 else if (! silent)
1234 error ("get_global_by_name: unknown symbol `%s'", nm.c_str ());
1235
1236 return retval;
1237 } 864 }
1238 865
1239 void 866 void
1240 set_global_value (const std::string& nm, const octave_value& val) 867 set_global_value (const std::string& nm, const octave_value& val)
1241 { 868 {
1242 symbol_record *sr = global_sym_tab->lookup (nm, true); 869 symbol_table::varref (nm, symbol_table::global_scope ()) = val;
1243
1244 if (sr)
1245 sr->define (val);
1246 else
1247 panic_impossible ();
1248 } 870 }
1249 871
1250 // Variable values. 872 // Variable values.
1251 873
1252 octave_value 874 octave_value
1413 print_usage (); 1035 print_usage ();
1414 1036
1415 return retval; 1037 return retval;
1416 } 1038 }
1417 1039
1418 // Global stuff and links to builtin variables and functions. 1040 struct
1419 1041 symbol_record_name_compare
1420 // Make the definition of the symbol record sr be the same as the 1042 {
1421 // definition of the global variable of the same name, creating it if 1043 bool operator () (const symbol_table::symbol_record& a,
1422 // it doesn't already exist. 1044 const symbol_table::symbol_record& b)
1045 {
1046 std::string a_nm = a.name ();
1047 std::string b_nm = b.name ();
1048
1049 return a_nm.compare (b_nm);
1050 }
1051 };
1052
1053 struct
1054 whos_parameter
1055 {
1056 char command;
1057 char modifier;
1058 int parameter_length;
1059 int first_parameter_length;
1060 int dimensions;
1061 int balance;
1062 std::string text;
1063 std::string line;
1064 };
1065
1066 static void
1067 print_descriptor (std::ostream& os, std::list<whos_parameter> params)
1068 {
1069 // This method prints a line of information on a given symbol
1070 std::list<whos_parameter>::iterator i = params.begin ();
1071 std::ostringstream param_buf;
1072
1073 while (i != params.end ())
1074 {
1075 whos_parameter param = *i;
1076
1077 if (param.command != '\0')
1078 {
1079 // Do the actual printing
1080 switch (param.modifier)
1081 {
1082 case 'l':
1083 os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
1084 param_buf << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
1085 break;
1086
1087 case 'r':
1088 os << std::setiosflags (std::ios::right) << std::setw (param.parameter_length);
1089 param_buf << std::setiosflags (std::ios::right) << std::setw (param.parameter_length);
1090 break;
1091
1092 case 'c':
1093 if (param.command != 's')
1094 {
1095 os << std::setiosflags (std::ios::left)
1096 << std::setw (param.parameter_length);
1097 param_buf << std::setiosflags (std::ios::left)
1098 << std::setw (param.parameter_length);
1099 }
1100 break;
1101
1102 default:
1103 os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
1104 param_buf << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
1105 }
1106
1107 if (param.command == 's' && param.modifier == 'c')
1108 {
1109 int a, b;
1110
1111 if (param.modifier == 'c')
1112 {
1113 a = param.first_parameter_length - param.balance;
1114 a = (a < 0 ? 0 : a);
1115 b = param.parameter_length - a - param.text . length ();
1116 b = (b < 0 ? 0 : b);
1117 os << std::setiosflags (std::ios::left) << std::setw (a)
1118 << "" << std::resetiosflags (std::ios::left) << param.text
1119 << std::setiosflags (std::ios::left)
1120 << std::setw (b) << ""
1121 << std::resetiosflags (std::ios::left);
1122 param_buf << std::setiosflags (std::ios::left) << std::setw (a)
1123 << "" << std::resetiosflags (std::ios::left) << param.line
1124 << std::setiosflags (std::ios::left)
1125 << std::setw (b) << ""
1126 << std::resetiosflags (std::ios::left);
1127 }
1128 }
1129 else
1130 {
1131 os << param.text;
1132 param_buf << param.line;
1133 }
1134 os << std::resetiosflags (std::ios::left)
1135 << std::resetiosflags (std::ios::right);
1136 param_buf << std::resetiosflags (std::ios::left)
1137 << std::resetiosflags (std::ios::right);
1138 i++;
1139 }
1140 else
1141 {
1142 os << param.text;
1143 param_buf << param.line;
1144 i++;
1145 }
1146 }
1147
1148 os << param_buf.str ();
1149 }
1150
1151 // Calculate how much space needs to be reserved for the first part of
1152 // the dimensions string. For example,
1153 //
1154 // mat is a 12x3 matrix
1155 // ^^ => 2 columns
1156
1157 static int
1158 dimensions_string_req_first_space (const dim_vector& dims, int print_dims)
1159 {
1160 int first_param_space = 0;
1161
1162 // Calculating dimensions.
1163
1164 std::string dim_str = "";
1165 std::stringstream ss;
1166 long dim = dims.length ();
1167
1168 first_param_space = (first_param_space >= 1 ? first_param_space : 1);
1169
1170 // Preparing dimension string.
1171
1172 if ((dim <= print_dims || print_dims < 0) && print_dims != 0)
1173 {
1174 // Dimensions string must be printed like this: 2x3x4x2.
1175
1176 if (dim == 0 || dim == 1)
1177 first_param_space = 1; // First parameter is 1.
1178 else
1179 {
1180 ss << dims (0);
1181
1182 dim_str = ss.str ();
1183 first_param_space = dim_str.length ();
1184 }
1185 }
1186 else
1187 {
1188 // Printing dimension string as: a-D.
1189
1190 ss << dim;
1191
1192 dim_str = ss.str ();
1193 first_param_space = dim_str.length ();
1194 }
1195
1196 return first_param_space;
1197 }
1198
1199 // Make the dimensions-string. For example: mat is a 2x3 matrix.
1200 // ^^^
1201 //
1202 // FIXME -- why not just use the dim_vector::str () method?
1203
1204 std::string
1205 make_dimensions_string (const dim_vector& dims, int print_dims)
1206 {
1207 // Calculating dimensions.
1208
1209 std::string dim_str = "";
1210 std::stringstream ss;
1211 long dim = dims.length ();
1212
1213 // Preparing dimension string.
1214
1215 if ((dim <= print_dims || print_dims < 0) && print_dims != 0)
1216 {
1217 // Only printing the dimension string as: axbxc...
1218
1219 if (dim == 0)
1220 ss << "1x1";
1221 else
1222 {
1223 for (int i = 0; i < dim; i++)
1224 {
1225 if (i == 0)
1226 {
1227 if (dim == 1)
1228 {
1229 // Looks like this is not going to happen in
1230 // Octave, but ...
1231
1232 ss << "1x" << dims (i);
1233 }
1234 else
1235 ss << dims (i);
1236 }
1237 else if (i < dim && dim != 1)
1238 ss << "x" << dims (i);
1239 }
1240 }
1241 }
1242 else
1243 {
1244 // Printing dimension string as: a-D.
1245
1246 ss << dim << "-D";
1247 }
1248
1249 dim_str = ss.str ();
1250
1251 return dim_str;
1252 }
1253
1254 // Calculate how much space needs to be reserved for the
1255 // dimensions string. For example,
1256 //
1257 // mat is a 12x3 matrix
1258 // ^^^^ => 4 columns
1259 //
1260 // FIXME -- why not just use the dim_vector::str () method?
1261
1262 static int
1263 dimensions_string_req_total_space (const dim_vector& dims, int print_dims)
1264 {
1265 std::string dim_str = "";
1266 std::stringstream ss;
1267
1268 ss << make_dimensions_string (dims, print_dims);
1269 dim_str = ss.str ();
1270
1271 return dim_str.length ();
1272 }
1273
1274 static std::list<whos_parameter>
1275 parse_whos_line_format (const std::list<symbol_table::symbol_record>& symbols)
1276 {
1277 // This method parses the string whos_line_format, and returns
1278 // a parameter list, containing all information needed to print
1279 // the given attributtes of the symbols
1280 int idx;
1281 size_t format_len = Vwhos_line_format.length ();
1282 char garbage;
1283 std::list<whos_parameter> params;
1284
1285 size_t bytes1;
1286 int elements1;
1287
1288 std::string param_string = "abcenst";
1289 Array<int> param_length (dim_vector (param_string.length (), 1));
1290 Array<std::string> param_names (dim_vector (param_string.length (), 1));
1291 size_t pos_a, pos_b, pos_c, pos_e, pos_n, pos_s, pos_t;
1292
1293 pos_a = param_string.find ('a'); // Attributes
1294 pos_b = param_string.find ('b'); // Bytes
1295 pos_c = param_string.find ('c'); // Class
1296 pos_e = param_string.find ('e'); // Elements
1297 pos_n = param_string.find ('n'); // Name
1298 pos_s = param_string.find ('s'); // Size
1299 pos_t = param_string.find ('t'); // Type
1300
1301 param_names(pos_a) = "Attr";
1302 param_names(pos_b) = "Bytes";
1303 param_names(pos_c) = "Class";
1304 param_names(pos_e) = "Elements";
1305 param_names(pos_n) = "Name";
1306 param_names(pos_s) = "Size";
1307 param_names(pos_t) = "Type";
1308
1309 for (size_t i = 0; i < param_string.length (); i++)
1310 param_length(i) = param_names(i) . length ();
1311
1312 // Calculating necessary spacing for name column,
1313 // bytes column, elements column and class column
1314
1315 for (std::list<symbol_table::symbol_record>::const_iterator p = symbols.begin ();
1316 p != symbols.end (); p++)
1317 {
1318 std::stringstream ss1, ss2;
1319 std::string str;
1320
1321 str = p->name ();
1322 param_length(pos_n) = ((str.length ()
1323 > static_cast<size_t> (param_length(pos_n)))
1324 ? str.length () : param_length(pos_n));
1325
1326 octave_value val = p->varval ();
1327
1328 str = val.type_name ();
1329 param_length(pos_t) = ((str.length ()
1330 > static_cast<size_t> (param_length(pos_t)))
1331 ? str.length () : param_length(pos_t));
1332
1333 elements1 = val.capacity ();
1334 ss1 << elements1;
1335 str = ss1.str ();
1336 param_length(pos_e) = ((str.length ()
1337 > static_cast<size_t> (param_length(pos_e)))
1338 ? str.length () : param_length(pos_e));
1339
1340 bytes1 = val.byte_size ();
1341 ss2 << bytes1;
1342 str = ss2.str ();
1343 param_length(pos_b) = ((str.length ()
1344 > static_cast<size_t> (param_length(pos_b)))
1345 ? str.length () : param_length (pos_b));
1346 }
1347
1348 idx = 0;
1349 while (static_cast<size_t> (idx) < format_len)
1350 {
1351 whos_parameter param;
1352 param.command = '\0';
1353
1354 if (Vwhos_line_format[idx] == '%')
1355 {
1356 bool error_encountered = false;
1357 param.modifier = 'r';
1358 param.parameter_length = 0;
1359 param.dimensions = 8;
1360
1361 int a = 0, b = -1, c = 8, balance = 1;
1362 unsigned int items;
1363 size_t pos;
1364 std::string cmd;
1365
1366 // Parse one command from whos_line_format
1367 cmd = Vwhos_line_format.substr (idx, Vwhos_line_format.length ());
1368 pos = cmd.find (';');
1369 if (pos != NPOS)
1370 cmd = cmd.substr (0, pos+1);
1371 else
1372 error ("parameter without ; in whos_line_format");
1373
1374 idx += cmd.length ();
1375
1376 // FIXME -- use iostream functions instead of sscanf!
1377
1378 if (cmd.find_first_of ("crl") != 1)
1379 items = sscanf (cmd.c_str (), "%c%c:%d:%d:%d:%d;",
1380 &garbage, &param.command, &a, &b, &c, &balance);
1381 else
1382 items = sscanf (cmd.c_str (), "%c%c%c:%d:%d:%d:%d;",
1383 &garbage, &param.modifier, &param.command,
1384 &a, &b, &c, &balance) - 1;
1385
1386 if (items < 2)
1387 {
1388 error ("whos_line_format: parameter structure without command in whos_line_format");
1389 error_encountered = true;
1390 }
1391
1392 // Insert data into parameter
1393 param.first_parameter_length = 0;
1394 pos = param_string.find (param.command);
1395 if (pos != NPOS)
1396 {
1397 param.parameter_length = param_length(pos);
1398 param.text = param_names(pos);
1399 param.line.assign (param_names(pos).length (), '=');
1400
1401 param.parameter_length = (a > param.parameter_length
1402 ? a : param.parameter_length);
1403 if (param.command == 's' && param.modifier == 'c' && b > 0)
1404 param.first_parameter_length = b;
1405 }
1406 else
1407 {
1408 error ("whos_line_format: '%c' is not a command",
1409 param.command);
1410 error_encountered = true;
1411 }
1412
1413 if (param.command == 's')
1414 {
1415 // Have to calculate space needed for printing matrix dimensions
1416 // Space needed for Size column is hard to determine in prior,
1417 // because it depends on dimensions to be shown. That is why it is
1418 // recalculated for each Size-command
1419 int first, rest = 0, total;
1420 param.dimensions = c;
1421 first = param.first_parameter_length;
1422 total = param.parameter_length;
1423
1424 for (std::list<symbol_table::symbol_record>::const_iterator p = symbols.begin ();
1425 p != symbols.end (); p++)
1426 {
1427 octave_value val = p->varval ();
1428 dim_vector dims = val.dims ();
1429 int first1 = dimensions_string_req_first_space (dims, param.dimensions);
1430 int total1 = dimensions_string_req_total_space (dims, param.dimensions);
1431 int rest1 = total1 - first1;
1432 rest = (rest1 > rest ? rest1 : rest);
1433 first = (first1 > first ? first1 : first);
1434 total = (total1 > total ? total1 : total);
1435 }
1436
1437 if (param.modifier == 'c')
1438 {
1439 if (first < balance)
1440 first += balance - first;
1441 if (rest + balance < param.parameter_length)
1442 rest += param.parameter_length - rest - balance;
1443
1444 param.parameter_length = first + rest;
1445 param.first_parameter_length = first;
1446 param.balance = balance;
1447 }
1448 else
1449 {
1450 param.parameter_length = total;
1451 param.first_parameter_length = 0;
1452 }
1453 }
1454 else if (param.modifier == 'c')
1455 {
1456 error ("whos_line_format: modifier 'c' not available for command '%c'",
1457 param.command);
1458 error_encountered = true;
1459 }
1460
1461 // What happens if whos_line_format contains negative numbers
1462 // at param_length positions?
1463 param.balance = (b < 0 ? 0 : param.balance);
1464 param.first_parameter_length = (b < 0 ? 0 :
1465 param.first_parameter_length);
1466 param.parameter_length = (a < 0
1467 ? 0
1468 : (param.parameter_length
1469 < param_length(pos_s)
1470 ? param_length(pos_s)
1471 : param.parameter_length));
1472
1473 // Parameter will not be pushed into parameter list if ...
1474 if (! error_encountered)
1475 params.push_back (param);
1476 }
1477 else
1478 {
1479 // Text string, to be printed as it is ...
1480 std::string text;
1481 size_t pos;
1482 text = Vwhos_line_format.substr (idx, Vwhos_line_format.length ());
1483 pos = text.find ('%');
1484 if (pos != NPOS)
1485 text = text.substr (0, pos);
1486
1487 // Push parameter into list ...
1488 idx += text.length ();
1489 param.text=text;
1490 param.line.assign (text.length(), ' ');
1491 params.push_back (param);
1492 }
1493 }
1494
1495 return params;
1496 }
1423 1497
1424 void 1498 void
1425 link_to_global_variable (symbol_record *sr) 1499 print_symbol_info_line (std::ostream& os,
1426 { 1500 const symbol_table::symbol_record& sr,
1427 if (! sr->is_linked_to_global ()) 1501 std::list<whos_parameter>& params)
1428 { 1502 {
1429 sr->mark_as_linked_to_global (); 1503 octave_value val = sr.varval ();
1430 1504 dim_vector dims = val.dims ();
1431 if (! error_state) 1505
1432 { 1506 std::list<whos_parameter>::iterator i = params.begin ();
1433 std::string nm = sr->name (); 1507
1434 1508 while (i != params.end ())
1435 symbol_record *gsr = global_sym_tab->lookup (nm, true); 1509 {
1436 1510 whos_parameter param = *i;
1437 // Make sure this symbol is a variable. 1511
1438 1512 if (param.command != '\0')
1439 if (! gsr->is_user_variable ()) 1513 {
1440 gsr->define (octave_value ()); 1514 // Do the actual printing.
1441 1515
1442 sr->alias (gsr); 1516 switch (param.modifier)
1443 } 1517 {
1444 } 1518 case 'l':
1445 } 1519 os << std::setiosflags (std::ios::left)
1446 1520 << std::setw (param.parameter_length);
1447 // Make the definition of the symbol record sr be the same as the 1521 break;
1448 // definition of the builtin variable of the same name. 1522
1449 1523 case 'r':
1450 // Make the definition of the symbol record sr be the same as the 1524 os << std::setiosflags (std::ios::right)
1451 // definition of the builtin function, or user function of the same 1525 << std::setw (param.parameter_length);
1452 // name, provided that the name has not been used as a formal parameter. 1526 break;
1453 1527
1454 void 1528 case 'c':
1455 link_to_builtin_or_function (symbol_record *sr) 1529 if (param.command == 's')
1456 { 1530 {
1457 std::string nm = sr->name (); 1531 int front = param.first_parameter_length
1458 1532 - dimensions_string_req_first_space (dims, param.dimensions);
1459 symbol_record *tmp_sym = 0; 1533 int back = param.parameter_length
1460 1534 - dimensions_string_req_total_space (dims, param.dimensions)
1461 octave_function *fcn = octave_call_stack::current (); 1535 - front;
1462 1536 front = (front > 0) ? front : 0;
1463 std::string parent = fcn ? fcn->parent_fcn_name () : std::string (); 1537 back = (back > 0) ? back : 0;
1464 1538
1465 if (! parent.empty ()) 1539 os << std::setiosflags (std::ios::left)
1466 tmp_sym = fbi_sym_tab->lookup (parent + ":" + nm); 1540 << std::setw (front)
1467 1541 << ""
1468 if (! tmp_sym && curr_parent_function) 1542 << std::resetiosflags (std::ios::left)
1469 tmp_sym = fbi_sym_tab->lookup (curr_parent_function->name () + ":" + nm); 1543 << make_dimensions_string (dims, param.dimensions)
1470 1544 << std::setiosflags (std::ios::left)
1471 if (! tmp_sym) 1545 << std::setw (back)
1472 tmp_sym = fbi_sym_tab->lookup (nm); 1546 << ""
1473 1547 << std::resetiosflags (std::ios::left);
1474 if (tmp_sym 1548 }
1475 && tmp_sym->is_function () 1549 else
1476 && ! tmp_sym->is_formal_parameter ()) 1550 {
1477 sr->alias (tmp_sym); 1551 os << std::setiosflags (std::ios::left)
1478 } 1552 << std::setw (param.parameter_length);
1479 1553 }
1480 // Force a link to a function in the current symbol table. This is 1554 break;
1481 // used just after defining a function to avoid different behavior 1555
1482 // depending on whether or not the function has been evaluated after 1556 default:
1483 // being defined. 1557 error ("whos_line_format: modifier `%c' unknown",
1484 // 1558 param.modifier);
1485 // Return without doing anything if there isn't a function with the 1559
1486 // given name defined in the global symbol table. 1560 os << std::setiosflags (std::ios::right)
1487 1561 << std::setw (param.parameter_length);
1488 void 1562 }
1489 force_link_to_function (const std::string& id_name) 1563
1490 { 1564 switch (param.command)
1491 symbol_record *fsr = fbi_sym_tab->lookup (id_name, true); 1565 {
1492 if (fsr->is_function ()) 1566 case 'a':
1493 { 1567 {
1494 curr_sym_tab->clear (id_name); 1568 char tmp[5];
1495 symbol_record *csr = curr_sym_tab->lookup (id_name, true); 1569
1496 csr->alias (fsr); 1570 tmp[0] = (sr.is_automatic () ? 'a' : ' ');
1497 } 1571 tmp[1] = (sr.is_formal () ? 'f' : ' ');
1498 } 1572 tmp[2] = (sr.is_global () ? 'g' : ' ');
1499 1573 tmp[3] = (sr.is_persistent () ? 'p' : ' ');
1500 DEFUN (document, args, , 1574 tmp[4] = 0;
1501 "-*- texinfo -*-\n\ 1575
1502 @deftypefn {Built-in Function} {} document (@var{symbol}, @var{text})\n\ 1576 os << tmp;
1503 Set the documentation string for @var{symbol} to @var{text}.\n\ 1577 }
1504 @end deftypefn") 1578 break;
1579
1580 case 'b':
1581 os << val.byte_size ();
1582 break;
1583
1584 case 'c':
1585 os << val.class_name ();
1586 break;
1587
1588 case 'e':
1589 os << val.capacity ();
1590 break;
1591
1592 case 'n':
1593 os << sr.name ();
1594 break;
1595
1596 case 's':
1597 if (param.modifier != 'c')
1598 os << make_dimensions_string (dims, param.dimensions);
1599 break;
1600
1601 case 't':
1602 os << val.type_name ();
1603 break;
1604
1605 default:
1606 error ("whos_line_format: command `%c' unknown", param.command);
1607 }
1608
1609 os << std::resetiosflags (std::ios::left)
1610 << std::resetiosflags (std::ios::right);
1611 i++;
1612 }
1613 else
1614 {
1615 os << param.text;
1616 i++;
1617 }
1618 }
1619 }
1620
1621 static octave_value
1622 do_who (int argc, const string_vector& argv, bool return_list,
1623 bool verbose = false)
1505 { 1624 {
1506 octave_value retval; 1625 octave_value retval;
1507 1626
1508 int nargin = args.length ();
1509
1510 if (nargin == 2)
1511 {
1512 std::string name = args(0).string_value ();
1513
1514 if (! error_state)
1515 {
1516 std::string help = args(1).string_value ();
1517
1518 if (! error_state)
1519 {
1520 if (is_command_name (name)
1521 || is_mapper_function_name (name)
1522 || is_builtin_function_name (name))
1523 error ("document: can't redefine help for built-in functions");
1524 else
1525 {
1526 symbol_record *sym_rec = curr_sym_tab->lookup (name);
1527
1528 if (sym_rec)
1529 sym_rec->document (help);
1530 else
1531 error ("document: no such symbol `%s'", name.c_str ());
1532 }
1533 }
1534 }
1535 }
1536 else
1537 print_usage ();
1538
1539 return retval;
1540 }
1541
1542 // FIXME -- this function is duplicated in symtab.cc with the
1543 // name maybe_list_cmp_fcn.
1544
1545 static int
1546 symbol_record_name_compare (const void *a_arg, const void *b_arg)
1547 {
1548 const symbol_record *a = *(static_cast<symbol_record *const*> (a_arg));
1549 const symbol_record *b = *(static_cast<symbol_record *const*> (b_arg));
1550
1551 std::string a_nm = a->name ();
1552 std::string b_nm = b->name ();
1553
1554 return a_nm.compare (b_nm);
1555 }
1556
1557 static octave_value
1558 do_who (int argc, const string_vector& argv, int return_list)
1559 {
1560 octave_value retval;
1561
1562 bool show_builtins = false;
1563 bool show_functions = false;
1564 bool show_variables = false;
1565 bool show_verbose = false;
1566
1567 std::string my_name = argv[0]; 1627 std::string my_name = argv[0];
1628
1629 bool global_only = false;
1568 1630
1569 int i; 1631 int i;
1570 for (i = 1; i < argc; i++) 1632 for (i = 1; i < argc; i++)
1571 { 1633 {
1572 if (argv[i] == "-all" || argv[i] == "-a") 1634 if (argv[i] == "-regexp" || argv[i] == "-file")
1573 { 1635 {
1574 show_builtins = true; 1636 error ("%s: `%s' option not implemented", my_name.c_str (),
1575 show_functions = true; 1637 argv[i].c_str ());
1576 show_variables = true; 1638
1577 } 1639 return retval;
1578 else if (argv[i] == "-builtins" || argv[i] == "-b") 1640 }
1579 show_builtins = true; 1641 else if (argv[i] == "global")
1580 else if (argv[i] == "-functions" || argv[i] == "-f") 1642 global_only = true;
1581 show_functions = true;
1582 else if (argv[i] == "-long" || argv[i] == "-l")
1583 show_verbose = true;
1584 else if (argv[i] == "-variables" || argv[i] == "-v")
1585 show_variables = true;
1586 else if (argv[i][0] == '-') 1643 else if (argv[i][0] == '-')
1587 warning ("%s: unrecognized option `%s'", my_name.c_str (), 1644 warning ("%s: unrecognized option `%s'", my_name.c_str (),
1588 argv[i].c_str ()); 1645 argv[i].c_str ());
1589 else 1646 else
1590 break; 1647 break;
1591 } 1648 }
1592 1649
1593 // If no options were specified to select the type of symbol to
1594 // display, then set defaults.
1595
1596 if (! (show_builtins || show_functions || show_variables))
1597 {
1598 show_functions = at_top_level ();
1599 show_variables = true;
1600 }
1601
1602 int npats = argc - i; 1650 int npats = argc - i;
1603 string_vector pats (npats); 1651 string_vector pats (npats > 0 ? npats : 1);
1604 for (int j = 0; j < npats; j++) 1652 if (npats > 0)
1605 pats[j] = argv[i+j]; 1653 {
1606 1654 for (int j = 0; j < npats; j++)
1607 // If the user specified -l and nothing else, show variables. If 1655 pats[j] = argv[i+j];
1608 // evaluating this at the top level, also show functions. 1656 }
1609 1657 else
1610 if (show_verbose && ! (show_builtins || show_functions || show_variables)) 1658 pats[0] = "*";
1611 { 1659
1612 show_functions = at_top_level (); 1660 symbol_table::scope_id scope = global_only
1613 show_variables = 1; 1661 ? symbol_table::global_scope () : symbol_table::current_scope ();
1614 } 1662
1663 std::list<symbol_table::symbol_record> symbols
1664 = symbol_table::glob_variables (pats, scope);
1665
1666 size_t symbols_len = symbols.size ();
1615 1667
1616 if (return_list) 1668 if (return_list)
1617 { 1669 {
1618 // FIXME -- maybe symbol_list should return a std::list 1670 if (verbose)
1619 // object instead of an Array.
1620
1621 dim_vector dv (0, 0);
1622
1623 Array<symbol_record *> s3 (dv);
1624 Array<symbol_record *> s4 (dv);
1625 Array<symbol_record *> s5 (dv);
1626 Array<symbol_record *> s6 (dv);
1627 Array<symbol_record *> s7 (dv);
1628 Array<symbol_record *> s8 (dv);
1629
1630 if (show_builtins)
1631 {
1632 s3 = fbi_sym_tab->symbol_list (pats, symbol_record::BUILTIN_FUNCTION,
1633 SYMTAB_ALL_SCOPES);
1634 }
1635
1636 if (show_functions)
1637 {
1638 s4 = fbi_sym_tab->symbol_list (pats, symbol_record::DLD_FUNCTION,
1639 SYMTAB_ALL_SCOPES);
1640
1641 s5 = fbi_sym_tab->symbol_list (pats, symbol_record::USER_FUNCTION,
1642 SYMTAB_ALL_SCOPES);
1643
1644 s6 = fbi_sym_tab->symbol_list (pats, symbol_record::MEX_FUNCTION,
1645 SYMTAB_ALL_SCOPES);
1646 }
1647
1648 if (show_variables)
1649 {
1650 s7 = curr_sym_tab->symbol_list (pats, symbol_record::USER_VARIABLE,
1651 SYMTAB_LOCAL_SCOPE);
1652
1653 s8 = curr_sym_tab->symbol_list (pats, symbol_record::USER_VARIABLE,
1654 SYMTAB_GLOBAL_SCOPE);
1655 }
1656
1657 octave_idx_type s3_len = s3.length ();
1658 octave_idx_type s4_len = s4.length ();
1659 octave_idx_type s5_len = s5.length ();
1660 octave_idx_type s6_len = s6.length ();
1661 octave_idx_type s7_len = s7.length ();
1662 octave_idx_type s8_len = s8.length ();
1663
1664 octave_idx_type symbols_len
1665 = s3_len + s4_len + s5_len + s6_len + s7_len + s8_len;
1666
1667 Array<symbol_record *> symbols (dim_vector (symbols_len, 1));
1668
1669 octave_idx_type k = 0;
1670
1671 symbols.insert (s3, k, 0);
1672 k += s3_len;
1673 symbols.insert (s4, k, 0);
1674 k += s4_len;
1675 symbols.insert (s5, k, 0);
1676 k += s5_len;
1677 symbols.insert (s6, k, 0);
1678 k += s6_len;
1679 symbols.insert (s7, k, 0);
1680 k += s7_len;
1681 symbols.insert (s8, k, 0);
1682
1683 symbols.qsort (symbol_record_name_compare);
1684
1685 if (show_verbose)
1686 { 1671 {
1687 Array<octave_value> name_info (symbols_len, 1); 1672 Array<octave_value> name_info (symbols_len, 1);
1688 Array<octave_value> size_info (symbols_len, 1); 1673 Array<octave_value> size_info (symbols_len, 1);
1689 Array<octave_value> bytes_info (symbols_len, 1); 1674 Array<octave_value> bytes_info (symbols_len, 1);
1690 Array<octave_value> class_info (symbols_len, 1); 1675 Array<octave_value> class_info (symbols_len, 1);
1691 Array<octave_value> global_info (symbols_len, 1); 1676 Array<octave_value> global_info (symbols_len, 1);
1692 Array<octave_value> sparse_info (symbols_len, 1); 1677 Array<octave_value> sparse_info (symbols_len, 1);
1693 Array<octave_value> complex_info (symbols_len, 1); 1678 Array<octave_value> complex_info (symbols_len, 1);
1694 Array<octave_value> nesting_info (symbols_len, 1); 1679 Array<octave_value> nesting_info (symbols_len, 1);
1695 1680
1696 for (octave_idx_type j = 0; j < symbols_len; j++) 1681 std::list<symbol_table::symbol_record>::const_iterator p
1697 { 1682 = symbols.begin ();
1698 symbol_record *sr = symbols(j); 1683
1684 for (size_t j = 0; j < symbols_len; j++)
1685 {
1686 const symbol_table::symbol_record& sr = *p++;
1699 1687
1700 Octave_map ni; 1688 Octave_map ni;
1701 1689
1702 std::string caller_function_name; 1690 std::string caller_function_name;
1703 1691
1706 caller_function_name = caller->name (); 1694 caller_function_name = caller->name ();
1707 1695
1708 ni.assign ("function", caller_function_name); 1696 ni.assign ("function", caller_function_name);
1709 ni.assign ("level", 1); 1697 ni.assign ("level", 1);
1710 1698
1711 name_info(j) = sr->name (); 1699 name_info(j) = sr.name ();
1712 size_info(j) = sr->size (); 1700 global_info(j) = sr.is_global ();
1713 bytes_info(j) = sr->byte_size (); 1701
1714 class_info(j) = sr->class_name (); 1702 octave_value val = sr.varval ();
1715 global_info(j) = sr->is_linked_to_global (); 1703
1716 sparse_info(j) = sr->is_sparse_type (); 1704 size_info(j) = val.size ();
1717 complex_info(j) = sr->is_complex_type (); 1705 bytes_info(j) = val.byte_size ();
1706 class_info(j) = val.class_name ();
1707 sparse_info(j) = val.is_sparse_type ();
1708 complex_info(j) = val.is_complex_type ();
1718 nesting_info(j) = ni; 1709 nesting_info(j) = ni;
1719 } 1710 }
1720 1711
1721 Octave_map info; 1712 Octave_map info;
1722 1713
1737 1728
1738 if (symbols_len > 0) 1729 if (symbols_len > 0)
1739 { 1730 {
1740 names.resize (symbols_len); 1731 names.resize (symbols_len);
1741 1732
1742 for (octave_idx_type j = 0; j < symbols_len; j++) 1733 std::list<symbol_table::symbol_record>::const_iterator p
1743 names[j] = symbols(j)->name (); 1734 = symbols.begin ();
1735
1736 for (size_t j = 0; j < symbols_len; j++)
1737 {
1738 names[j] = p->name ();
1739 p++;
1740 }
1744 } 1741 }
1745 1742
1746 retval = Cell (names); 1743 retval = Cell (names);
1747 } 1744 }
1748 } 1745 }
1749 else 1746 else if (symbols_len > 0)
1750 { 1747 {
1751 int pad_after = 0; 1748 if (global_only)
1752 1749 octave_stdout << "Global variables:\n\n";
1753 if (show_builtins) 1750 else
1754 { 1751 octave_stdout << "Variables in the current scope:\n\n";
1755 pad_after += fbi_sym_tab->maybe_list 1752
1756 ("*** built-in functions:", pats, octave_stdout, 1753 if (verbose)
1757 show_verbose, symbol_record::BUILTIN_FUNCTION, SYMTAB_ALL_SCOPES); 1754 {
1758 } 1755 size_t bytes = 0;
1759 1756 size_t elements = 0;
1760 if (show_functions) 1757
1761 { 1758 std::list<whos_parameter> params;
1762 pad_after += fbi_sym_tab->maybe_list 1759
1763 ("*** dynamically linked functions:", pats, 1760 params = parse_whos_line_format (symbols);
1764 octave_stdout, show_verbose, symbol_record::DLD_FUNCTION, 1761
1765 SYMTAB_ALL_SCOPES); 1762 print_descriptor (octave_stdout, params);
1766 1763
1767 pad_after += fbi_sym_tab->maybe_list 1764 octave_stdout << "\n";
1768 ("*** currently compiled functions:", pats, 1765
1769 octave_stdout, show_verbose, symbol_record::USER_FUNCTION, 1766 for (std::list<symbol_table::symbol_record>::const_iterator p = symbols.begin ();
1770 SYMTAB_ALL_SCOPES); 1767 p != symbols.end (); p++)
1771 1768 {
1772 pad_after += fbi_sym_tab->maybe_list 1769 print_symbol_info_line (octave_stdout, *p, params);
1773 ("*** mex functions:", pats, 1770 octave_value val = p->varval ();
1774 octave_stdout, show_verbose, symbol_record::MEX_FUNCTION, 1771 elements += val.capacity ();
1775 SYMTAB_ALL_SCOPES); 1772 bytes += val.byte_size ();
1776 } 1773 }
1777 1774
1778 if (show_variables) 1775 octave_stdout << "\nTotal is " << elements
1779 { 1776 << (elements == 1 ? " element" : " elements")
1780 pad_after += curr_sym_tab->maybe_list 1777 << " using " << bytes
1781 ("*** local user variables:", pats, octave_stdout, 1778 << (bytes == 1 ? " byte" : " bytes") << "\n";
1782 show_verbose, symbol_record::USER_VARIABLE, SYMTAB_LOCAL_SCOPE); 1779 }
1783 1780 else
1784 pad_after += curr_sym_tab->maybe_list 1781 {
1785 ("*** globally visible user variables:", pats, 1782 string_vector names (symbols_len);
1786 octave_stdout, show_verbose, symbol_record::USER_VARIABLE, 1783
1787 SYMTAB_GLOBAL_SCOPE); 1784 std::list<symbol_table::symbol_record>::const_iterator p
1788 } 1785 = symbols.begin ();
1789 1786
1790 if (pad_after) 1787 for (size_t j = 0; j < symbols_len; j++)
1791 octave_stdout << "\n"; 1788 {
1789 names[j] = p->name ();
1790 p++;
1791 }
1792
1793 names.list_in_columns (octave_stdout);
1794 }
1795
1796 octave_stdout << "\n";
1792 } 1797 }
1793 1798
1794 return retval; 1799 return retval;
1795 } 1800 }
1796 1801
1838 { 1843 {
1839 int argc = args.length () + 1; 1844 int argc = args.length () + 1;
1840 1845
1841 string_vector argv = args.make_argv ("who"); 1846 string_vector argv = args.make_argv ("who");
1842 1847
1843 if (error_state) 1848 if (! error_state)
1844 return retval; 1849 retval = do_who (argc, argv, nargout == 1);
1845
1846 retval = do_who (argc, argv, nargout == 1);
1847 } 1850 }
1848 else 1851 else
1849 print_usage (); 1852 print_usage ();
1850 1853
1851 return retval; 1854 return retval;
1859 { 1862 {
1860 octave_value retval; 1863 octave_value retval;
1861 1864
1862 if (nargout < 2) 1865 if (nargout < 2)
1863 { 1866 {
1864 int nargin = args.length (); 1867 int argc = args.length () + 1;
1865 1868
1866 octave_value_list tmp_args; 1869 string_vector argv = args.make_argv ("whos");
1867 1870
1868 for (int i = nargin; i > 0; i--) 1871 if (! error_state)
1869 tmp_args(i) = args(i-1); 1872 retval = do_who (argc, argv, nargout == 1, true);
1870
1871 tmp_args(0) = "-long";
1872
1873 int argc = tmp_args.length () + 1;
1874
1875 string_vector argv = tmp_args.make_argv ("whos");
1876
1877 if (error_state)
1878 return retval;
1879
1880 retval = do_who (argc, argv, nargout == 1);
1881 } 1873 }
1882 else 1874 else
1883 print_usage (); 1875 print_usage ();
1884 1876
1885 return retval; 1877 return retval;
1888 // Defining variables. 1880 // Defining variables.
1889 1881
1890 void 1882 void
1891 bind_ans (const octave_value& val, bool print) 1883 bind_ans (const octave_value& val, bool print)
1892 { 1884 {
1893 symbol_record *sr = curr_sym_tab->lookup ("ans", true); 1885 static std::string ans = "ans";
1894 1886
1895 if (val.is_defined ()) 1887 if (val.is_defined ())
1896 { 1888 {
1897 sr->define (val); 1889 symbol_table::varref (ans) = val;
1898 1890
1899 if (print) 1891 if (print)
1900 val.print_with_name (octave_stdout, "ans"); 1892 val.print_with_name (octave_stdout, ans);
1901 } 1893 }
1902 } 1894 }
1903 1895
1904 void 1896 void
1905 bind_internal_variable (const std::string& fname, const octave_value& val) 1897 bind_internal_variable (const std::string& fname, const octave_value& val)
1910 1902
1911 feval (fname, args, 0); 1903 feval (fname, args, 0);
1912 } 1904 }
1913 1905
1914 void 1906 void
1915 mlock (const std::string& nm) 1907 mlock (void)
1916 { 1908 {
1917 symbol_record *sr = fbi_sym_tab->lookup (nm, true); 1909 octave_function *fcn = octave_call_stack::caller ();
1918 1910
1919 if (sr) 1911 if (fcn)
1920 sr->mark_as_static (); 1912 fcn->lock ();
1913 else
1914 error ("mlock: invalid use outside a function");
1921 } 1915 }
1922 1916
1923 void 1917 void
1924 munlock (const std::string& nm) 1918 munlock (const std::string& nm)
1925 { 1919 {
1926 symbol_record *sr = fbi_sym_tab->lookup (nm); 1920 octave_value val = symbol_table::find_function (nm);
1927 1921
1928 if (sr && sr->is_static ()) 1922 if (val.is_defined ())
1929 sr->unmark_static (); 1923 {
1930 else 1924 octave_function *fcn = val.function_value ();
1931 error ("munlock: %s is not locked", nm.c_str ()); 1925
1926 if (fcn)
1927 fcn->unlock ();
1928 }
1932 } 1929 }
1933 1930
1934 bool 1931 bool
1935 mislocked (const std::string& nm) 1932 mislocked (const std::string& nm)
1936 { 1933 {
1937 symbol_record *sr = fbi_sym_tab->lookup (nm); 1934 bool retval = false;
1938 1935
1939 return (sr && sr->is_static ()); 1936 octave_value val = symbol_table::find_function (nm);
1937
1938 if (val.is_defined ())
1939 {
1940 octave_function *fcn = val.function_value ();
1941
1942 if (fcn)
1943 retval = fcn->islocked ();
1944 }
1945
1946 return retval;
1940 } 1947 }
1941 1948
1942 DEFCMD (mlock, args, , 1949 DEFCMD (mlock, args, ,
1943 "-*- texinfo -*-\n\ 1950 "-*- texinfo -*-\n\
1944 @deftypefn {Built-in Function} {} mlock (@var{name})\n\ 1951 @deftypefn {Built-in Function} {} mlock (@var{name})\n\
1945 Lock the named function into memory. If no function is named\n\ 1952 Lock the current function into memory so that it can't be cleared.\n\
1946 then lock in the current function.\n\
1947 @seealso{munlock, mislocked, persistent}\n\ 1953 @seealso{munlock, mislocked, persistent}\n\
1948 @end deftypefn") 1954 @end deftypefn")
1949 { 1955 {
1950 octave_value_list retval; 1956 octave_value_list retval;
1951 1957
1952 if (args.length () == 1) 1958 if (args.length () == 0)
1953 { 1959 mlock ();
1954 std::string name = args(0).string_value ();
1955
1956 if (! error_state)
1957 mlock (name);
1958 else
1959 error ("mlock: expecting argument to be a function name");
1960 }
1961 else if (args.length () == 0)
1962 {
1963 octave_user_function *fcn = octave_call_stack::caller_user_function ();
1964
1965 if (fcn)
1966 mlock (fcn->name ());
1967 else
1968 error ("mlock: invalid use outside a function");
1969 }
1970 else 1960 else
1971 print_usage (); 1961 print_usage ();
1972 1962
1973 return retval; 1963 return retval;
1974 } 1964 }
1992 else 1982 else
1993 error ("munlock: expecting argument to be a function name"); 1983 error ("munlock: expecting argument to be a function name");
1994 } 1984 }
1995 else if (args.length () == 0) 1985 else if (args.length () == 0)
1996 { 1986 {
1997 octave_user_function *fcn = octave_call_stack::caller_user_function (); 1987 octave_function *fcn = octave_call_stack::caller ();
1998 1988
1999 if (fcn) 1989 if (fcn)
2000 munlock (fcn->name ()); 1990 fcn->unlock ();
2001 else 1991 else
2002 error ("munlock: invalid use outside a function"); 1992 error ("munlock: invalid use outside a function");
2003 } 1993 }
2004 else 1994 else
2005 print_usage (); 1995 print_usage ();
2027 else 2017 else
2028 error ("mislocked: expecting argument to be a function name"); 2018 error ("mislocked: expecting argument to be a function name");
2029 } 2019 }
2030 else if (args.length () == 0) 2020 else if (args.length () == 0)
2031 { 2021 {
2032 octave_user_function *fcn = octave_call_stack::caller_user_function (); 2022 octave_function *fcn = octave_call_stack::caller ();
2033 2023
2034 if (fcn) 2024 if (fcn)
2035 retval = mislocked (fcn->name ()); 2025 retval = fcn->islocked ();
2036 else 2026 else
2037 error ("mislocked: invalid use outside a function"); 2027 error ("mislocked: invalid use outside a function");
2038 } 2028 }
2039 else 2029 else
2040 print_usage (); 2030 print_usage ();
2067 } 2057 }
2068 2058
2069 return retval; 2059 return retval;
2070 } 2060 }
2071 2061
2072 static inline bool
2073 is_local_variable (const std::string& nm)
2074 {
2075 symbol_record *sr = curr_sym_tab->lookup (nm);
2076
2077 return (sr && sr->is_variable ());
2078 }
2079
2080 static inline void 2062 static inline void
2081 maybe_warn_exclusive (bool exclusive) 2063 maybe_warn_exclusive (bool exclusive)
2082 { 2064 {
2083 if (exclusive) 2065 if (exclusive)
2084 warning ("clear: ignoring --exclusive option"); 2066 warning ("clear: ignoring --exclusive option");
2085 } 2067 }
2086 2068
2087 static inline void 2069 static void
2088 do_clear_all (void)
2089 {
2090 curr_sym_tab->clear ();
2091 fbi_sym_tab->clear_functions ();
2092 global_sym_tab->clear ();
2093 }
2094
2095 static inline void
2096 do_clear_functions (void)
2097 {
2098 curr_sym_tab->clear_functions ();
2099 fbi_sym_tab->clear_functions ();
2100 }
2101
2102 static inline void
2103 do_clear_globals (void)
2104 {
2105 curr_sym_tab->clear_globals ();
2106 global_sym_tab->clear ();
2107 }
2108
2109 static inline void
2110 do_clear_variables (void)
2111 {
2112 curr_sym_tab->clear ();
2113 }
2114
2115 static inline bool
2116 do_clear_function (const std::string& nm)
2117 {
2118 bool b1 = curr_sym_tab->clear_function (nm);
2119
2120 bool b2 = fbi_sym_tab->clear_function (nm);
2121
2122 return b1 || b2;
2123 }
2124
2125 static inline bool
2126 do_clear_global (const std::string& nm)
2127 {
2128 bool b1 = curr_sym_tab->clear_global (nm);
2129
2130 bool b2 = global_sym_tab->clear_variable (nm);
2131
2132 return b1 || b2;
2133 }
2134
2135 static inline bool
2136 do_clear_variable (const std::string& nm)
2137 {
2138 return curr_sym_tab->clear_variable (nm);
2139 }
2140
2141 static inline bool
2142 do_clear_symbol (const std::string& nm)
2143 {
2144 bool cleared = curr_sym_tab->clear_variable (nm);
2145
2146 if (! cleared)
2147 cleared = do_clear_function (nm);
2148
2149 return cleared;
2150 }
2151
2152 static inline bool
2153 do_clear_function_pattern (const std::string& pat)
2154 {
2155 bool b1 = curr_sym_tab->clear_function_pattern (pat);
2156
2157 bool b2 = fbi_sym_tab->clear_function_pattern (pat);
2158
2159 return b1 || b2;
2160 }
2161
2162 static inline bool
2163 do_clear_global_pattern (const std::string& pat)
2164 {
2165 bool b1 = curr_sym_tab->clear_global_pattern (pat);
2166
2167 bool b2 = global_sym_tab->clear_variable_pattern (pat);
2168
2169 return b1 || b2;
2170 }
2171
2172 static inline bool
2173 do_clear_variable_pattern (const std::string& pat)
2174 {
2175 return curr_sym_tab->clear_variable_pattern (pat);
2176 }
2177
2178 static inline bool
2179 do_clear_symbol_pattern (const std::string& pat)
2180 {
2181 // FIXME -- if we have a variable v1 and a function v2 and
2182 // someone says clear v*, we will clear the variable but not the
2183 // function. Is that really what should happen? (I think it is
2184 // what Matlab does.)
2185
2186 bool cleared = curr_sym_tab->clear_variable_pattern (pat);
2187
2188 if (! cleared)
2189 cleared = do_clear_function_pattern (pat);
2190
2191 return cleared;
2192 }
2193
2194 static inline void
2195 do_clear_functions (const string_vector& argv, int argc, int idx, 2070 do_clear_functions (const string_vector& argv, int argc, int idx,
2196 bool exclusive = false) 2071 bool exclusive = false)
2197 { 2072 {
2198 if (idx == argc) 2073 if (idx == argc)
2199 do_clear_functions (); 2074 symbol_table::clear_functions ();
2200 else 2075 else
2201 { 2076 {
2202 if (exclusive) 2077 if (exclusive)
2203 { 2078 {
2204 string_vector lfcns = curr_sym_tab->user_function_name_list (); 2079 string_vector fcns = symbol_table::user_function_names ();
2205 2080
2206 int lcount = lfcns.length (); 2081 int fcount = fcns.length ();
2207 2082
2208 for (int i = 0; i < lcount; i++) 2083 for (int i = 0; i < fcount; i++)
2209 { 2084 {
2210 std::string nm = lfcns[i]; 2085 std::string nm = fcns[i];
2211 2086
2212 if (! name_matches_any_pattern (nm, argv, argc, idx)) 2087 if (! name_matches_any_pattern (nm, argv, argc, idx))
2213 do_clear_function (nm); 2088 symbol_table::clear_function (nm);
2214 }
2215
2216 string_vector fcns = fbi_sym_tab->user_function_name_list ();
2217
2218 int fcount = fcns.length ();
2219
2220 for (int i = 0; i < fcount; i++)
2221 {
2222 std::string nm = fcns[i];
2223
2224 if (! name_matches_any_pattern (nm, argv, argc, idx))
2225 do_clear_function (nm);
2226 } 2089 }
2227 } 2090 }
2228 else 2091 else
2229 { 2092 {
2230 while (idx < argc) 2093 while (idx < argc)
2231 do_clear_function_pattern (argv[idx++]); 2094 symbol_table::clear_function_pattern (argv[idx++]);
2232 } 2095 }
2233 } 2096 }
2234 } 2097 }
2235 2098
2236 static inline void 2099 static void
2237 do_clear_globals (const string_vector& argv, int argc, int idx, 2100 do_clear_globals (const string_vector& argv, int argc, int idx,
2238 bool exclusive = false) 2101 bool exclusive = false)
2239 { 2102 {
2240 if (idx == argc) 2103 if (idx == argc)
2241 do_clear_globals (); 2104 symbol_table::clear_variables(symbol_table::global_scope ());
2242 else 2105 else
2243 { 2106 {
2244 if (exclusive) 2107 if (exclusive)
2245 { 2108 {
2246 string_vector lvars = curr_sym_tab->global_variable_name_list (); 2109 string_vector gvars
2247 2110 = symbol_table::variable_names (symbol_table::global_scope ());
2248 int lcount = lvars.length (); 2111
2249 2112 int gcount = gvars.length ();
2250 for (int i = 0; i < lcount; i++) 2113
2251 { 2114 for (int i = 0; i < gcount; i++)
2252 std::string nm = lvars[i]; 2115 {
2116 std::string nm = gvars[i];
2253 2117
2254 if (! name_matches_any_pattern (nm, argv, argc, idx)) 2118 if (! name_matches_any_pattern (nm, argv, argc, idx))
2255 do_clear_global (nm); 2119 symbol_table::clear_global (nm);
2256 }
2257
2258 string_vector gvars = global_sym_tab->global_variable_name_list ();
2259
2260 int gcount = gvars.length ();
2261
2262 for (int i = 0; i < gcount; i++)
2263 {
2264 std::string nm = gvars[i];
2265
2266 if (! name_matches_any_pattern (nm, argv, argc, idx))
2267 do_clear_global (nm);
2268 } 2120 }
2269 } 2121 }
2270 else 2122 else
2271 { 2123 {
2272 while (idx < argc) 2124 while (idx < argc)
2273 do_clear_global_pattern (argv[idx++]); 2125 symbol_table::clear_global_pattern (argv[idx++]);
2274 } 2126 }
2275 } 2127 }
2276 } 2128 }
2277 2129
2278 static inline void 2130 static void
2279 do_clear_variables (const string_vector& argv, int argc, int idx, 2131 do_clear_variables (const string_vector& argv, int argc, int idx,
2280 bool exclusive = false) 2132 bool exclusive = false)
2281 { 2133 {
2282 if (idx == argc) 2134 if (idx == argc)
2283 do_clear_variables (); 2135 symbol_table::clear_variables ();
2284 else 2136 else
2285 { 2137 {
2286 if (exclusive) 2138 if (exclusive)
2287 { 2139 {
2288 string_vector lvars = curr_sym_tab->variable_name_list (); 2140 string_vector lvars = symbol_table::variable_names ();
2289 2141
2290 int lcount = lvars.length (); 2142 int lcount = lvars.length ();
2291 2143
2292 for (int i = 0; i < lcount; i++) 2144 for (int i = 0; i < lcount; i++)
2293 { 2145 {
2294 std::string nm = lvars[i]; 2146 std::string nm = lvars[i];
2295 2147
2296 if (! name_matches_any_pattern (nm, argv, argc, idx)) 2148 if (! name_matches_any_pattern (nm, argv, argc, idx))
2297 do_clear_variable (nm); 2149 symbol_table::clear_variable (nm);
2298 } 2150 }
2299 } 2151 }
2300 else 2152 else
2301 { 2153 {
2302 while (idx < argc) 2154 while (idx < argc)
2303 do_clear_variable_pattern (argv[idx++]); 2155 symbol_table::clear_variable_pattern (argv[idx++]);
2304 } 2156 }
2305 } 2157 }
2306 } 2158 }
2307 2159
2308 static inline void 2160 static void
2309 do_clear_symbols (const string_vector& argv, int argc, int idx, 2161 do_clear_symbols (const string_vector& argv, int argc, int idx,
2310 bool exclusive = false) 2162 bool exclusive = false)
2311 { 2163 {
2312 if (idx == argc) 2164 if (idx == argc)
2313 do_clear_variables (); 2165 symbol_table::clear_variables ();
2314 else 2166 else
2315 { 2167 {
2316 if (exclusive) 2168 if (exclusive)
2317 { 2169 {
2318 // FIXME -- is this really what we want, or do we 2170 // FIXME -- is this really what we want, or do we
2324 do_clear_functions (argv, argc, idx, exclusive); 2176 do_clear_functions (argv, argc, idx, exclusive);
2325 } 2177 }
2326 else 2178 else
2327 { 2179 {
2328 while (idx < argc) 2180 while (idx < argc)
2329 do_clear_symbol_pattern (argv[idx++]); 2181 symbol_table::clear_symbol_pattern (argv[idx++]);
2330 } 2182 }
2331 } 2183 }
2332 } 2184 }
2333 2185
2334 static void 2186 static void
2336 { 2188 {
2337 // This is supposed to be mostly Matlab compatible. 2189 // This is supposed to be mostly Matlab compatible.
2338 2190
2339 for (; idx < argc; idx++) 2191 for (; idx < argc; idx++)
2340 { 2192 {
2341 if (argv[idx] == "all" && ! is_local_variable ("all")) 2193 if (argv[idx] == "all"
2342 { 2194 && ! symbol_table::is_local_variable ("all"))
2343 do_clear_all (); 2195 {
2344 } 2196 symbol_table::clear_all ();
2345 else if (argv[idx] == "functions" && ! is_local_variable ("functions")) 2197 }
2198 else if (argv[idx] == "functions"
2199 && ! symbol_table::is_local_variable ("functions"))
2346 { 2200 {
2347 do_clear_functions (argv, argc, ++idx); 2201 do_clear_functions (argv, argc, ++idx);
2348 } 2202 }
2349 else if (argv[idx] == "global" && ! is_local_variable ("global")) 2203 else if (argv[idx] == "global"
2204 && ! symbol_table::is_local_variable ("global"))
2350 { 2205 {
2351 do_clear_globals (argv, argc, ++idx); 2206 do_clear_globals (argv, argc, ++idx);
2352 } 2207 }
2353 else if (argv[idx] == "variables" && ! is_local_variable ("variables")) 2208 else if (argv[idx] == "variables"
2354 { 2209 && ! symbol_table::is_local_variable ("variables"))
2355 do_clear_variables (); 2210 {
2356 } 2211 symbol_table::clear_variables ();
2357 else 2212 }
2358 { 2213 else
2359 do_clear_symbol_pattern (argv[idx]); 2214 {
2215 symbol_table::clear_symbol_pattern (argv[idx]);
2360 } 2216 }
2361 } 2217 }
2362 } 2218 }
2363 2219
2364 #define CLEAR_OPTION_ERROR(cond) \ 2220 #define CLEAR_OPTION_ERROR(cond) \
2370 return retval; \ 2226 return retval; \
2371 } \ 2227 } \
2372 } \ 2228 } \
2373 while (0) 2229 while (0)
2374 2230
2375 bool
2376 clear_function (const std::string& nm)
2377 {
2378 return do_clear_function (nm);
2379 }
2380
2381 bool
2382 clear_variable (const std::string& nm)
2383 {
2384 return do_clear_variable (nm);
2385 }
2386
2387 bool
2388 clear_symbol (const std::string& nm)
2389 {
2390 return do_clear_symbol (nm);
2391 }
2392
2393 DEFCMD (clear, args, , 2231 DEFCMD (clear, args, ,
2394 "-*- texinfo -*-\n\ 2232 "-*- texinfo -*-\n\
2395 @deffn {Command} clear [-x] pattern @dots{}\n\ 2233 @deffn {Command} clear [-x] pattern @dots{}\n\
2396 Delete the names matching the given patterns from the symbol table. The\n\ 2234 Delete the names matching the given patterns from the symbol table. The\n\
2397 pattern may contain the following special characters:\n\ 2235 pattern may contain the following special characters:\n\
2441 2279
2442 if (! error_state) 2280 if (! error_state)
2443 { 2281 {
2444 if (argc == 1) 2282 if (argc == 1)
2445 { 2283 {
2446 do_clear_variables (); 2284 symbol_table::clear_variables ();
2447 } 2285 }
2448 else 2286 else
2449 { 2287 {
2450 int idx = 0; 2288 int idx = 0;
2451 2289
2509 2347
2510 if (++idx < argc) 2348 if (++idx < argc)
2511 warning 2349 warning
2512 ("clear: ignoring extra arguments after -all"); 2350 ("clear: ignoring extra arguments after -all");
2513 2351
2514 curr_sym_tab->clear (); 2352 symbol_table::clear_all ();
2515 fbi_sym_tab->clear_functions ();
2516 global_sym_tab->clear ();
2517 } 2353 }
2518 else if (clear_functions) 2354 else if (clear_functions)
2519 { 2355 {
2520 do_clear_functions (argv, argc, idx, exclusive); 2356 do_clear_functions (argv, argc, idx, exclusive);
2521 } 2357 }
2545 Undocumented internal function.\n\ 2381 Undocumented internal function.\n\
2546 @end deftypefn") 2382 @end deftypefn")
2547 { 2383 {
2548 octave_value_list retval; 2384 octave_value_list retval;
2549 2385
2550 int nargin = args.length (); 2386 // FIXME -- what should this function do now? Print a summary for
2551 2387 // each scope? Print the entire symbol table? Accept a scope
2552 if (nargin == 1) 2388 // argument?
2553 {
2554 std::string arg = args(0).string_value ();
2555
2556 if (arg == "fbi")
2557 fbi_sym_tab->print_info (octave_stdout);
2558 else if (arg == "global")
2559 global_sym_tab->print_info (octave_stdout);
2560 else if (arg == "top-level")
2561 top_level_sym_tab->print_info (octave_stdout);
2562 else
2563 {
2564 symbol_record *fsr = fbi_sym_tab->lookup (arg, true);
2565
2566 if (fsr && fsr->is_user_function ())
2567 {
2568 octave_value tmp = fsr->def ();
2569 const octave_base_value& rep = tmp.get_rep ();
2570
2571 const octave_user_function& fcn
2572 = dynamic_cast<const octave_user_function&> (rep);
2573
2574 fcn.print_symtab_info (octave_stdout);
2575 }
2576 else
2577 error ("no user-defined function named %s", arg.c_str ());
2578 }
2579 }
2580 else if (nargin == 0)
2581 curr_sym_tab->print_info (octave_stdout);
2582 else
2583 print_usage ();
2584 2389
2585 return retval; 2390 return retval;
2586 } 2391 }
2587 2392
2588 DEFUN (__print_symbol_info__, args, , 2393 DEFUN (__print_symbol_info__, args, ,
2591 Undocumented internal function.\n\ 2396 Undocumented internal function.\n\
2592 @end deftypefn") 2397 @end deftypefn")
2593 { 2398 {
2594 octave_value_list retval; 2399 octave_value_list retval;
2595 2400
2596 int nargin = args.length (); 2401 // FIXME -- what should this function do now?
2597 2402
2598 if (nargin == 1) 2403 return retval;
2599 { 2404 }
2600 std::string symbol_name = args(0).string_value (); 2405
2601 2406 DEFUN (whos_line_format, args, nargout,
2602 if (! error_state) 2407 "-*- texinfo -*-\n\
2603 { 2408 @deftypefn {Built-in Function} {@var{val} =} whos_line_format ()\n\
2604 symbol_record *sr = curr_sym_tab->lookup (symbol_name); 2409 @deftypefnx {Built-in Function} {@var{old_val} =} whos_line_format (@var{new_val})\n\
2605 2410 Query or set the format string used by the @code{whos}.\n\
2606 if (sr) 2411 \n\
2607 sr->print_info (octave_stdout); 2412 The following escape sequences may be used in the format:\n\
2608 else 2413 @table @code\n\
2609 error ("__print_symbol_info__: symbol %s not found", 2414 @item %a\n\
2610 symbol_name.c_str ()); 2415 Prints attributes of variables (g=global, p=persistent,\n\
2611 } 2416 f=formal parameter, a=automatic variable).\n\
2612 else 2417 @item %b\n\
2613 print_usage (); 2418 Prints number of bytes occupied by variables.\n\
2614 } 2419 @item %c\n\
2615 else 2420 Prints class names of variables.\n\
2616 print_usage (); 2421 @item %e\n\
2617 2422 Prints elements held by variables.\n\
2618 return retval; 2423 @item %n\n\
2619 } 2424 Prints variable names.\n\
2620 2425 @item %s\n\
2621 DEFUN (ignore_function_time_stamp, args, nargout, 2426 Prints dimensions of variables.\n\
2622 "-*- texinfo -*-\n\ 2427 @item %t\n\
2623 @deftypefn {Built-in Function} {@var{val} =} ignore_function_time_stamp ()\n\ 2428 Prints type names of variables.\n\
2624 @deftypefnx {Built-in Function} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})\n\ 2429 @end table\n\
2625 Query or set the internal variable that controls whether Octave checks\n\ 2430 \n\
2626 the time stamp on files each time it looks up functions defined in\n\ 2431 Every command may also have a modifier:\n\
2627 function files. If the internal variable is set to @code{\"system\"},\n\ 2432 @table @code\n\
2628 Octave will not automatically recompile function files in subdirectories of\n\ 2433 @item l\n\
2629 @file{@var{octave-home}/lib/@var{version}} if they have changed since\n\ 2434 Left alignment.\n\
2630 they were last compiled, but will recompile other function files in the\n\ 2435 @item r\n\
2631 search path if they change. If set to @code{\"all\"}, Octave will not\n\ 2436 Right alignment (this is the default).\n\
2632 recompile any function files unless their definitions are removed with\n\ 2437 @item c\n\
2633 @code{clear}. If set to \"none\", Octave will always check time stamps\n\ 2438 Centered (may only be applied to command %s).\n\
2634 on files to determine whether functions defined in function files\n\ 2439 @end table\n\
2635 need to be recompiled.\n\ 2440 \n\
2441 A command is composed like this:\n\
2442 \n\
2443 @example\n\
2444 %[modifier]<command>[:size_of_parameter[:center-specific[\n\
2445 :print_dims[:balance]]]];\n\
2446 @end example\n\
2447 \n\
2448 Command and modifier is already explained. Size_of_parameter\n\
2449 tells how many columns the parameter will need for printing.\n\
2450 print_dims tells how many dimensions to print. If number of\n\
2451 dimensions exceeds print_dims, dimensions will be printed like\n\
2452 x-D.\n\
2453 center-specific and print_dims may only be applied to command\n\
2454 %s. A negative value for print_dims will cause Octave to print all\n\
2455 dimensions whatsoever.\n\
2456 balance specifies the offset for printing of the dimensions string.\n\
2457 \n\
2458 The default format is \" %a:4; %ln:6; %cs:16:6:8:1; %rb:12; %lc:-1;\\n\".\n\
2636 @end deftypefn") 2459 @end deftypefn")
2637 { 2460 {
2638 octave_value retval; 2461 return SET_INTERNAL_VARIABLE (whos_line_format);
2639
2640 if (nargout > 0)
2641 {
2642 switch (Vignore_function_time_stamp)
2643 {
2644 case 1:
2645 retval = "system";
2646 break;
2647
2648 case 2:
2649 retval = "all";
2650 break;
2651
2652 default:
2653 retval = "none";
2654 break;
2655 }
2656 }
2657
2658 int nargin = args.length ();
2659
2660 if (nargin == 1)
2661 {
2662 std::string sval = args(0).string_value ();
2663
2664 if (! error_state)
2665 {
2666 if (sval == "all")
2667 Vignore_function_time_stamp = 2;
2668 else if (sval == "system")
2669 Vignore_function_time_stamp = 1;
2670 else if (sval == "none")
2671 Vignore_function_time_stamp = 0;
2672 else
2673 error ("ignore_function_time_stamp: expecting argument to be \"all\", \"system\", or \"none\"");
2674 }
2675 else
2676 error ("ignore_function_time_stamp: expecting argument to be character string");
2677 }
2678 else if (nargin > 1)
2679 print_usage ();
2680
2681 return retval;
2682 } 2462 }
2683 2463
2684 /* 2464 /*
2685 ;;; Local Variables: *** 2465 ;;; Local Variables: ***
2686 ;;; mode: C++ *** 2466 ;;; mode: C++ ***