Mercurial > hg > octave-nkf
annotate src/variables.cc @ 11821:018dff0b30d2 release-3-0-x
avoid problematic subfunction call in an anonymous function
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 20 Aug 2008 11:01:24 -0400 |
parents | 72830070a17b |
children | eff8ac793dbf |
rev | line source |
---|---|
1 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, |
11740 | 4 2003, 2004, 2005, 2006, 2007, 2008 John W. Eaton |
1 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
1 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
1 | 21 |
22 */ | |
23 | |
240 | 24 #ifdef HAVE_CONFIG_H |
1192 | 25 #include <config.h> |
1 | 26 #endif |
27 | |
1468 | 28 #include <cstdio> |
1343 | 29 #include <cstring> |
605 | 30 |
4207 | 31 #include <set> |
1728 | 32 #include <string> |
33 | |
2926 | 34 #include "file-stat.h" |
35 #include "oct-env.h" | |
4604 | 36 #include "file-ops.h" |
2926 | 37 #include "glob-match.h" |
1755 | 38 #include "str-vec.h" |
39 | |
2492 | 40 #include <defaults.h> |
4435 | 41 #include "Cell.h" |
1352 | 42 #include "defun.h" |
43 #include "dirfns.h" | |
44 #include "error.h" | |
2205 | 45 #include "gripes.h" |
1352 | 46 #include "help.h" |
3165 | 47 #include "input.h" |
1352 | 48 #include "lex.h" |
5832 | 49 #include "load-path.h" |
2926 | 50 #include "oct-map.h" |
51 #include "oct-obj.h" | |
52 #include "ov.h" | |
3933 | 53 #include "ov-usr-fcn.h" |
605 | 54 #include "pager.h" |
1352 | 55 #include "parse.h" |
2926 | 56 #include "symtab.h" |
2205 | 57 #include "toplev.h" |
1352 | 58 #include "unwind-prot.h" |
1 | 59 #include "utils.h" |
1352 | 60 #include "variables.h" |
2205 | 61 |
62 // Should Octave always check to see if function files have changed | |
63 // since they were last compiled? | |
5794 | 64 static int Vignore_function_time_stamp = 1; |
2205 | 65 |
1 | 66 // Symbol table for symbols at the top level. |
581 | 67 symbol_table *top_level_sym_tab = 0; |
1 | 68 |
69 // Symbol table for the current scope. | |
581 | 70 symbol_table *curr_sym_tab = 0; |
1 | 71 |
4245 | 72 // Symbol table for the current caller scope. |
73 symbol_table *curr_caller_sym_tab = 0; | |
74 | |
1 | 75 // Symbol table for global symbols. |
581 | 76 symbol_table *global_sym_tab = 0; |
1 | 77 |
4009 | 78 // Symbol table for functions and built-in symbols. |
79 symbol_table *fbi_sym_tab = 0; | |
80 | |
4700 | 81 bool |
4208 | 82 at_top_level (void) |
83 { | |
84 return (curr_sym_tab == top_level_sym_tab); | |
85 } | |
86 | |
593 | 87 // Initialization. |
88 | |
89 // Create the initial symbol tables and set the current scope at the | |
90 // top level. | |
91 | |
195 | 92 void |
93 initialize_symbol_tables (void) | |
94 { | |
4009 | 95 if (! fbi_sym_tab) |
4238 | 96 fbi_sym_tab = new symbol_table (2048, "FBI"); |
4009 | 97 |
581 | 98 if (! global_sym_tab) |
4238 | 99 global_sym_tab = new symbol_table (2048, "GLOBAL"); |
195 | 100 |
581 | 101 if (! top_level_sym_tab) |
4238 | 102 top_level_sym_tab = new symbol_table (4096, "TOP"); |
195 | 103 |
4245 | 104 curr_caller_sym_tab = curr_sym_tab = top_level_sym_tab; |
195 | 105 } |
106 | |
6068 | 107 void |
6072 | 108 clear_mex_functions (void) |
6068 | 109 { |
6072 | 110 fbi_sym_tab->clear_mex_functions (); |
6068 | 111 } |
112 | |
593 | 113 // Attributes of variables and functions. |
114 | |
4208 | 115 // Is this a command-style function? |
593 | 116 |
4208 | 117 static std::set <std::string> command_set; |
4207 | 118 |
119 static inline bool | |
4208 | 120 is_marked_as_command (const std::string& s) |
4207 | 121 { |
4208 | 122 return command_set.find (s) != command_set.end (); |
4207 | 123 } |
124 | |
125 static inline void | |
4208 | 126 mark_as_command (const std::string& s) |
4207 | 127 { |
4208 | 128 command_set.insert (s); |
4207 | 129 } |
130 | |
131 static inline void | |
4208 | 132 unmark_command (const std::string& s) |
4207 | 133 { |
4208 | 134 command_set.erase (s); |
4207 | 135 |
136 symbol_record *sr = fbi_sym_tab->lookup (s); | |
137 | |
138 if (sr) | |
4208 | 139 sr->unmark_command (); |
4207 | 140 } |
141 | |
4208 | 142 DEFCMD (mark_as_command, args, , |
4207 | 143 "-*- texinfo -*-\n\ |
4208 | 144 @deftypefn {Built-in Function} {} mark_as_command (@var{name})\n\ |
145 Enter @var{name} into the list of commands.\n\ | |
5642 | 146 @seealso{unmark_command, iscommand}\n\ |
147 @end deftypefn") | |
4207 | 148 { |
149 octave_value_list retval; | |
150 | |
4208 | 151 if (at_top_level ()) |
152 { | |
153 int nargin = args.length (); | |
4207 | 154 |
4208 | 155 if (nargin > 0) |
156 { | |
157 int argc = nargin + 1; | |
4207 | 158 |
4208 | 159 string_vector argv = args.make_argv ("mark_as_command"); |
4207 | 160 |
4208 | 161 if (! error_state) |
162 { | |
163 for (int i = 1; i < argc; i++) | |
164 mark_as_command (argv[i]); | |
165 } | |
4207 | 166 } |
4208 | 167 else |
5823 | 168 print_usage (); |
4207 | 169 } |
170 else | |
4208 | 171 warning ("mark_as_command: invalid use inside function body"); |
4207 | 172 |
173 return retval; | |
174 } | |
175 | |
4208 | 176 DEFCMD (unmark_command, args, , |
4207 | 177 "-*- texinfo -*-\n\ |
5102 | 178 @deftypefn {Built-in Function} {} unmark_command (@var{name})\n\ |
4208 | 179 Remove @var{name} from the list of commands.\n\ |
5642 | 180 @seealso{mark_as_command, iscommand}\n\ |
181 @end deftypefn") | |
4207 | 182 { |
183 octave_value_list retval; | |
184 | |
4208 | 185 if (at_top_level ()) |
186 { | |
187 int nargin = args.length (); | |
4207 | 188 |
4208 | 189 if (nargin > 0) |
190 { | |
191 int argc = nargin + 1; | |
4207 | 192 |
4208 | 193 string_vector argv = args.make_argv ("unmark_command"); |
4207 | 194 |
4208 | 195 if (! error_state) |
196 { | |
197 for (int i = 1; i < argc; i++) | |
198 unmark_command (argv[i]); | |
199 } | |
4207 | 200 } |
4208 | 201 else |
5823 | 202 print_usage (); |
4207 | 203 } |
204 else | |
4208 | 205 warning ("mark_as_command: invalid use inside function body"); |
4207 | 206 |
207 return retval; | |
208 } | |
209 | |
1827 | 210 bool |
4208 | 211 is_command_name (const std::string& s) |
593 | 212 { |
4207 | 213 bool retval = false; |
214 | |
4009 | 215 symbol_record *sr = fbi_sym_tab->lookup (s); |
4207 | 216 |
217 if (sr) | |
218 { | |
4208 | 219 if (sr->is_command ()) |
4207 | 220 retval = true; |
4208 | 221 else if (is_marked_as_command (s)) |
4207 | 222 { |
4208 | 223 sr->mark_as_command (); |
4207 | 224 retval = true; |
225 } | |
226 } | |
227 else | |
4208 | 228 retval = is_marked_as_command (s); |
4207 | 229 |
230 return retval; | |
593 | 231 } |
232 | |
5102 | 233 DEFCMD (iscommand, args, , |
234 "-*- texinfo -*-\n\ | |
235 @deftypefn {Built-in Function} {} iscommand (@var{name})\n\ | |
236 Return true if @var{name} is a command style function. If @var{name}\n\ | |
237 is omitted, return a list of identifiers which are marked as commands with\n\ | |
6637 | 238 @code{mark_as_command}.\n\ |
5642 | 239 @seealso{mark_as_command, unmark_command}\n\ |
240 @end deftypefn") | |
5102 | 241 { |
242 octave_value retval; | |
243 | |
244 int nargin = args.length (); | |
245 | |
246 if (nargin == 0) | |
247 { | |
248 string_vector lst (command_set.size ()); | |
249 | |
250 int i = 0; | |
251 for (std::set<std::string>::const_iterator p = command_set.begin (); | |
252 p != command_set.end (); p++) | |
253 lst[i++] = *p; | |
254 | |
255 retval = Cell (lst.qsort ()); | |
256 } | |
257 else if (nargin == 1) | |
258 { | |
259 string_vector argv = args.make_argv ("iscommand"); | |
260 | |
261 if (! error_state) | |
262 { | |
263 std::string s = argv[1]; | |
264 retval = is_command_name(s); | |
265 } | |
266 } | |
267 else | |
5823 | 268 print_usage (); |
5102 | 269 |
270 return retval; | |
271 } | |
272 | |
273 // Is this a raw input command? | |
274 | |
275 static std::set <std::string> rawcommand_set; | |
276 | |
5685 | 277 bool |
5102 | 278 is_marked_as_rawcommand (const std::string& s) |
279 { | |
280 return rawcommand_set.find (s) != rawcommand_set.end (); | |
281 } | |
282 | |
5685 | 283 void |
5102 | 284 mark_as_rawcommand (const std::string& s) |
285 { | |
286 command_set.insert (s); | |
287 rawcommand_set.insert (s); | |
288 } | |
289 | |
5685 | 290 void |
5102 | 291 unmark_rawcommand (const std::string& s) |
292 { | |
293 rawcommand_set.erase (s); | |
294 | |
295 symbol_record *sr = fbi_sym_tab->lookup (s); | |
296 | |
297 if (sr) | |
298 sr->unmark_rawcommand (); | |
299 } | |
300 | |
301 DEFCMD (mark_as_rawcommand, args, , | |
302 "-*- texinfo -*-\n\ | |
303 @deftypefn {Built-in Function} {} mark_as_rawcommand (@var{name})\n\ | |
304 Enter @var{name} into the list of raw input commands and to the list of\n\ | |
305 command style functions.\n\ | |
306 Raw input commands are like normal command style functions, but they\n\ | |
307 receive their input unprocessed (ie. strings still contain the quotes\n\ | |
308 and escapes they had when input). However, comments and continuations\n\ | |
309 are handled as usual, you cannot pass a token starting with a comment\n\ | |
310 character ('#' or '%') to your function, and the last token cannot be\n\ | |
311 a continuation token ('\\' or '...').\n\ | |
5642 | 312 @seealso{unmark_rawcommand, israwcommand, iscommand, mark_as_command}\n\ |
313 @end deftypefn") | |
5102 | 314 { |
315 octave_value_list retval; | |
316 | |
317 if (at_top_level ()) | |
318 { | |
319 int nargin = args.length (); | |
320 | |
321 if (nargin > 0) | |
322 { | |
323 int argc = nargin + 1; | |
324 | |
325 string_vector argv = args.make_argv ("mark_as_rawcommand"); | |
326 | |
327 if (! error_state) | |
328 { | |
329 for (int i = 1; i < argc; i++) | |
330 mark_as_rawcommand (argv[i]); | |
331 } | |
332 } | |
333 else | |
5823 | 334 print_usage (); |
5102 | 335 } |
336 else | |
337 warning ("mark_as_rawcommand: invalid use inside function body"); | |
338 | |
339 return retval; | |
340 } | |
341 | |
342 DEFCMD (unmark_rawcommand, args, , | |
343 "-*- texinfo -*-\n\ | |
344 @deftypefn {Built-in Function} {} unmark_rawcommand (@var{name})\n\ | |
345 Remove @var{name} from the list of raw input commands.\n\ | |
346 Note that this does not remove @var{name} from the list of command style\n\ | |
347 functions.\n\ | |
5642 | 348 @seealso{mark_as_rawcommand, israwcommand, iscommand, unmark_command}\n\ |
349 @end deftypefn") | |
5102 | 350 { |
351 octave_value_list retval; | |
352 | |
353 if (at_top_level ()) | |
354 { | |
355 int nargin = args.length (); | |
356 | |
357 if (nargin > 0) | |
358 { | |
359 int argc = nargin + 1; | |
360 | |
361 string_vector argv = args.make_argv ("unmark_rawcommand"); | |
362 | |
363 if (! error_state) | |
364 { | |
365 for (int i = 1; i < argc; i++) | |
366 unmark_rawcommand (argv[i]); | |
367 } | |
368 } | |
369 else | |
5823 | 370 print_usage (); |
5102 | 371 } |
372 else | |
373 warning ("unmark_rawcommand: invalid use inside function body"); | |
374 | |
375 return retval; | |
376 } | |
377 | |
378 bool | |
379 is_rawcommand_name (const std::string& s) | |
380 { | |
381 bool retval = false; | |
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 } | |
400 | |
401 DEFCMD (israwcommand, args, , | |
402 "-*- texinfo -*-\n\ | |
403 @deftypefn {Built-in Function} {} israwcommand (@var{name})\n\ | |
404 Return true if @var{name} is a raw input command function.\n\ | |
405 If @var{name} is omitted, return a list of identifiers which are marked as\n\ | |
406 raw input commands with mark_as_rawcommand.\n\ | |
5642 | 407 @seealso{mark_as_rawcommand, unmark_rawcommand}\n\ |
408 @end deftypefn") | |
5102 | 409 { |
410 octave_value retval; | |
411 | |
412 int nargin = args.length (); | |
413 | |
414 if (nargin == 0) | |
415 { | |
416 string_vector lst (rawcommand_set.size()); | |
417 | |
418 int i = 0; | |
419 for (std::set<std::string>::const_iterator p = rawcommand_set.begin (); | |
420 p != rawcommand_set.end (); | |
421 p++) | |
422 lst[i++] = *p; | |
423 | |
424 retval = Cell (lst.qsort ()); | |
425 } | |
426 else if (nargin == 1) | |
427 { | |
428 string_vector argv = args.make_argv ("israwcommand"); | |
429 | |
430 if (! error_state) | |
431 { | |
432 std::string s = argv[1]; | |
433 retval = is_rawcommand_name(s); | |
434 } | |
435 } | |
436 else | |
5823 | 437 print_usage (); |
5102 | 438 |
439 return retval; | |
440 } | |
441 | |
3355 | 442 // Is this a built-in function? |
2294 | 443 |
444 bool | |
3523 | 445 is_builtin_function_name (const std::string& s) |
2294 | 446 { |
4009 | 447 symbol_record *sr = fbi_sym_tab->lookup (s); |
2294 | 448 return (sr && sr->is_builtin_function ()); |
449 } | |
450 | |
451 // Is this a mapper function? | |
452 | |
453 bool | |
3523 | 454 is_mapper_function_name (const std::string& s) |
2294 | 455 { |
4009 | 456 symbol_record *sr = fbi_sym_tab->lookup (s); |
2294 | 457 return (sr && sr->is_mapper_function ()); |
458 } | |
459 | |
593 | 460 // Is this function globally in this scope? |
461 | |
1827 | 462 bool |
3523 | 463 is_globally_visible (const std::string& name) |
593 | 464 { |
2856 | 465 symbol_record *sr = curr_sym_tab->lookup (name); |
593 | 466 return (sr && sr->is_linked_to_global ()); |
467 } | |
468 | |
2086 | 469 // Is this octave_value a valid function? |
593 | 470 |
2975 | 471 octave_function * |
4345 | 472 is_valid_function (const std::string& fcn_name, |
473 const std::string& warn_for, bool warn) | |
593 | 474 { |
2975 | 475 octave_function *ans = 0; |
593 | 476 |
477 symbol_record *sr = 0; | |
1755 | 478 |
479 if (! fcn_name.empty ()) | |
3618 | 480 { |
4009 | 481 sr = fbi_sym_tab->lookup (fcn_name, true); |
3618 | 482 |
483 lookup (sr, false); | |
484 } | |
593 | 485 |
486 if (sr) | |
2975 | 487 { |
488 octave_value tmp = sr->def (); | |
489 ans = tmp.function_value (true); | |
490 } | |
593 | 491 |
492 if (! sr || ! ans || ! sr->is_function ()) | |
493 { | |
494 if (warn) | |
495 error ("%s: the symbol `%s' is not valid as a function", | |
1755 | 496 warn_for.c_str (), fcn_name.c_str ()); |
593 | 497 ans = 0; |
498 } | |
499 | |
500 return ans; | |
501 } | |
502 | |
2975 | 503 octave_function * |
4345 | 504 is_valid_function (const octave_value& arg, |
505 const std::string& warn_for, bool warn) | |
3178 | 506 { |
507 octave_function *ans = 0; | |
508 | |
3523 | 509 std::string fcn_name; |
3178 | 510 |
511 if (arg.is_string ()) | |
4700 | 512 { |
513 fcn_name = arg.string_value (); | |
3178 | 514 |
4700 | 515 if (! error_state) |
516 ans = is_valid_function (fcn_name, warn_for, warn); | |
517 else if (warn) | |
518 error ("%s: expecting function name as argument", warn_for.c_str ()); | |
519 } | |
3178 | 520 else if (warn) |
521 error ("%s: expecting function name as argument", warn_for.c_str ()); | |
522 | |
523 return ans; | |
524 } | |
525 | |
526 octave_function * | |
3523 | 527 extract_function (const octave_value& arg, const std::string& warn_for, |
528 const std::string& fname, const std::string& header, | |
529 const std::string& trailer) | |
2796 | 530 { |
2975 | 531 octave_function *retval = 0; |
2796 | 532 |
533 retval = is_valid_function (arg, warn_for, 0); | |
534 | |
535 if (! retval) | |
536 { | |
3523 | 537 std::string s = arg.string_value (); |
2796 | 538 |
3523 | 539 std::string cmd = header; |
2796 | 540 cmd.append (s); |
541 cmd.append (trailer); | |
542 | |
543 if (! error_state) | |
544 { | |
545 int parse_status; | |
546 | |
2898 | 547 eval_string (cmd, true, parse_status); |
2796 | 548 |
549 if (parse_status == 0) | |
550 { | |
551 retval = is_valid_function (fname, warn_for, 0); | |
552 | |
553 if (! retval) | |
554 { | |
555 error ("%s: `%s' is not valid as a function", | |
556 warn_for.c_str (), fname.c_str ()); | |
557 return retval; | |
558 } | |
559 } | |
560 else | |
561 error ("%s: `%s' is not valid as a function", | |
562 warn_for.c_str (), fname.c_str ()); | |
563 } | |
564 else | |
565 error ("%s: expecting first argument to be a string", | |
566 warn_for.c_str ()); | |
567 } | |
568 | |
569 return retval; | |
570 } | |
571 | |
2921 | 572 string_vector |
3523 | 573 get_struct_elts (const std::string& text) |
2921 | 574 { |
575 int n = 1; | |
576 | |
577 size_t pos = 0; | |
578 | |
579 size_t len = text.length (); | |
580 | |
581 while ((pos = text.find ('.', pos)) != NPOS) | |
582 { | |
583 if (++pos == len) | |
584 break; | |
585 | |
586 n++; | |
587 } | |
588 | |
589 string_vector retval (n); | |
590 | |
591 pos = 0; | |
592 | |
593 for (int i = 0; i < n; i++) | |
594 { | |
4587 | 595 len = text.find ('.', pos); |
2921 | 596 |
597 if (len != NPOS) | |
598 len -= pos; | |
599 | |
600 retval[i] = text.substr (pos, len); | |
601 | |
602 if (len != NPOS) | |
603 pos += len + 1; | |
604 } | |
605 | |
606 return retval; | |
607 } | |
608 | |
4179 | 609 static inline bool |
610 is_variable (const std::string& name) | |
611 { | |
612 bool retval = false; | |
613 | |
614 if (! name.empty ()) | |
615 { | |
616 symbol_record *sr = curr_sym_tab->lookup (name); | |
617 | |
618 if (! sr) | |
619 sr = fbi_sym_tab->lookup (name); | |
620 | |
621 retval = (sr && sr->is_variable ()); | |
622 } | |
623 | |
624 return retval; | |
625 } | |
626 | |
2921 | 627 string_vector |
3933 | 628 generate_struct_completions (const std::string& text, |
629 std::string& prefix, std::string& hint) | |
2921 | 630 { |
631 string_vector names; | |
632 | |
633 size_t pos = text.rfind ('.'); | |
634 | |
3933 | 635 if (pos != NPOS) |
2921 | 636 { |
637 if (pos == text.length ()) | |
638 hint = ""; | |
639 else | |
640 hint = text.substr (pos+1); | |
641 | |
642 prefix = text.substr (0, pos); | |
643 | |
4179 | 644 std::string base_name = prefix; |
645 | |
646 pos = base_name.find_first_of ("{(."); | |
2921 | 647 |
4179 | 648 if (pos != NPOS) |
649 base_name = base_name.substr (0, pos); | |
4143 | 650 |
4179 | 651 if (is_variable (base_name)) |
652 { | |
653 int parse_status; | |
654 | |
655 unwind_protect::begin_frame ("generate_struct_completions"); | |
3935 | 656 |
4452 | 657 unwind_protect_int (error_state); |
658 unwind_protect_int (warning_state); | |
659 | |
4179 | 660 unwind_protect_bool (discard_error_messages); |
4452 | 661 unwind_protect_bool (discard_warning_messages); |
3935 | 662 |
4179 | 663 discard_error_messages = true; |
4452 | 664 discard_warning_messages = true; |
2921 | 665 |
4179 | 666 octave_value tmp = eval_string (prefix, true, parse_status); |
667 | |
668 unwind_protect::run_frame ("generate_struct_completions"); | |
3935 | 669 |
4179 | 670 if (tmp.is_defined () && tmp.is_map ()) |
671 names = tmp.map_keys (); | |
672 } | |
673 } | |
2921 | 674 |
675 return names; | |
676 } | |
677 | |
5775 | 678 // FIXME -- this will have to be much smarter to work |
4179 | 679 // "correctly". |
680 | |
2921 | 681 bool |
3523 | 682 looks_like_struct (const std::string& text) |
2921 | 683 { |
4604 | 684 bool retval = (! text.empty () |
685 && text != "." | |
686 && text.find_first_of (file_ops::dir_sep_chars) == NPOS | |
687 && text.find ("..") == NPOS | |
688 && text.rfind ('.') != NPOS); | |
3968 | 689 |
4179 | 690 #if 0 |
3968 | 691 symbol_record *sr = curr_sym_tab->lookup (text); |
2963 | 692 |
3968 | 693 if (sr && ! sr->is_function ()) |
694 { | |
695 int parse_status; | |
2921 | 696 |
4143 | 697 unwind_protect::begin_frame ("looks_like_struct"); |
698 | |
699 unwind_protect_bool (discard_error_messages); | |
700 unwind_protect_int (error_state); | |
701 | |
702 discard_error_messages = true; | |
703 | |
3968 | 704 octave_value tmp = eval_string (text, true, parse_status); |
705 | |
4143 | 706 unwind_protect::run_frame ("looks_like_struct"); |
707 | |
3968 | 708 retval = (tmp.is_defined () && tmp.is_map ()); |
709 } | |
4179 | 710 #endif |
3968 | 711 |
712 return retval; | |
2921 | 713 } |
2796 | 714 |
5930 | 715 static octave_value |
716 do_isglobal (const octave_value_list& args) | |
593 | 717 { |
4233 | 718 octave_value retval = false; |
593 | 719 |
712 | 720 int nargin = args.length (); |
721 | |
722 if (nargin != 1) | |
593 | 723 { |
5823 | 724 print_usage (); |
593 | 725 return retval; |
726 } | |
727 | |
3523 | 728 std::string name = args(0).string_value (); |
593 | 729 |
636 | 730 if (error_state) |
731 { | |
4028 | 732 error ("isglobal: expecting std::string argument"); |
636 | 733 return retval; |
734 } | |
735 | |
2856 | 736 symbol_record *sr = curr_sym_tab->lookup (name); |
593 | 737 |
4233 | 738 retval = (sr && sr->is_linked_to_global ()); |
593 | 739 |
740 return retval; | |
741 } | |
742 | |
5930 | 743 DEFUN (isglobal, args, , |
744 "-*- texinfo -*-\n\ | |
745 @deftypefn {Built-in Function} {} isglobal (@var{name})\n\ | |
746 Return 1 if @var{name} is globally visible. Otherwise, return 0. For\n\ | |
747 example,\n\ | |
748 \n\ | |
749 @example\n\ | |
750 @group\n\ | |
751 global x\n\ | |
752 isglobal (\"x\")\n\ | |
753 @result{} 1\n\ | |
754 @end group\n\ | |
755 @end example\n\ | |
756 @end deftypefn") | |
757 { | |
758 return do_isglobal (args); | |
759 } | |
760 | |
761 DEFUN (is_global, args, , | |
762 "-*- texinfo -*-\n\ | |
763 @deftypefn {Built-in Function} {} isglobal (@var{name})\n\ | |
764 This function has been deprecated. Use isglobal instead.\n\ | |
765 @end deftypefn") | |
766 { | |
767 return do_isglobal (args); | |
768 } | |
769 | |
4016 | 770 int |
771 symbol_exist (const std::string& name, const std::string& type) | |
593 | 772 { |
4016 | 773 int retval = 0; |
636 | 774 |
3523 | 775 std::string struct_elts; |
776 std::string symbol_name = name; | |
1755 | 777 |
778 size_t pos = name.find ('.'); | |
779 | |
2790 | 780 if (pos != NPOS && pos > 0) |
1277 | 781 { |
1755 | 782 struct_elts = name.substr (pos+1); |
2790 | 783 symbol_name = name.substr (0, pos); |
1277 | 784 } |
785 | |
4009 | 786 // 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 | |
788 // symbol table. | |
789 | |
2856 | 790 symbol_record *sr = curr_sym_tab->lookup (symbol_name); |
593 | 791 |
4009 | 792 if (! (sr && sr->is_defined ())) |
793 sr = fbi_sym_tab->lookup (symbol_name); | |
593 | 794 |
4009 | 795 if (sr && sr->is_defined ()) |
1277 | 796 { |
4357 | 797 bool not_a_struct = struct_elts.empty (); |
798 bool var_ok = not_a_struct || sr->is_map_element (struct_elts); | |
799 | |
4016 | 800 if (! retval |
4357 | 801 && var_ok |
4016 | 802 && (type == "any" || type == "var") |
4357 | 803 && sr->is_user_variable ()) |
4009 | 804 { |
4016 | 805 retval = 1; |
4009 | 806 } |
4016 | 807 |
808 if (! retval | |
809 && (type == "any" || type == "builtin")) | |
4009 | 810 { |
4357 | 811 if (not_a_struct && sr->is_builtin_function ()) |
4016 | 812 { |
813 retval = 5; | |
814 } | |
4009 | 815 } |
4016 | 816 |
817 if (! retval | |
4357 | 818 && not_a_struct |
4016 | 819 && (type == "any" || type == "file") |
820 && (sr->is_user_function () || sr->is_dld_function ())) | |
4009 | 821 { |
4261 | 822 octave_value t = sr->def (); |
4016 | 823 octave_function *f = t.function_value (true); |
824 std::string s = f ? f->fcn_file_name () : std::string (); | |
825 | |
4438 | 826 retval = s.empty () ? 103 : (sr->is_user_function () ? 2 : 3); |
4009 | 827 } |
1421 | 828 } |
4016 | 829 |
5140 | 830 if (! (type == "var" || type == "builtin")) |
593 | 831 { |
5140 | 832 if (! retval) |
593 | 833 { |
5484 | 834 std::string file_name = lookup_autoload (name); |
835 | |
836 if (file_name.empty ()) | |
5832 | 837 file_name = load_path::find_fcn (name); |
5140 | 838 |
839 size_t len = file_name.length (); | |
840 | |
5832 | 841 if (len > 0) |
4437 | 842 { |
5140 | 843 if (type == "any" || type == "file") |
844 { | |
5864 | 845 if (len > 4 && (file_name.substr (len-4) == ".oct" |
846 || file_name.substr (len-4) == ".mex")) | |
5140 | 847 retval = 3; |
848 else | |
849 retval = 2; | |
850 } | |
4437 | 851 } |
593 | 852 } |
5140 | 853 |
854 if (! retval) | |
593 | 855 { |
5140 | 856 std::string file_name = file_in_path (name, ""); |
857 | |
858 if (file_name.empty ()) | |
859 file_name = name; | |
860 | |
861 file_stat fs (file_name); | |
862 | |
863 if (fs) | |
1421 | 864 { |
5140 | 865 if ((type == "any" || type == "file") |
866 && fs.is_reg ()) | |
867 { | |
868 retval = 2; | |
869 } | |
870 else if ((type == "any" || type == "dir") | |
871 && fs.is_dir ()) | |
872 { | |
873 retval = 7; | |
874 } | |
1421 | 875 } |
593 | 876 } |
877 } | |
878 | |
879 return retval; | |
880 } | |
881 | |
4962 | 882 #define GET_IDX(LEN) \ |
883 static_cast<int> ((LEN-1) * static_cast<double> (rand ()) / RAND_MAX) | |
884 | |
4954 | 885 std::string |
886 unique_symbol_name (const std::string& basename) | |
887 { | |
4962 | 888 static const std::string alpha |
889 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
890 | |
891 static size_t len = alpha.length (); | |
892 | |
893 std::string nm = basename + alpha[GET_IDX (len)]; | |
894 | |
895 size_t pos = nm.length (); | |
896 | |
897 if (nm.substr (0, 2) == "__") | |
898 nm.append ("__"); | |
899 | |
900 while (symbol_exist (nm, "any")) | |
901 nm.insert (pos++, 1, alpha[GET_IDX (len)]); | |
902 | |
903 return nm; | |
4954 | 904 } |
905 | |
4016 | 906 DEFUN (exist, args, , |
907 "-*- texinfo -*-\n\ | |
908 @deftypefn {Built-in Function} {} exist (@var{name}, @var{type})\n\ | |
11711
7a4efac7e476
variables.cc (exist): Clarify help.
Ben Abbott <bpabbott@mac.com>
parents:
11630
diff
changeset
|
909 Return 1 if the name exists as a variable, 2 if the name is an\n\ |
7a4efac7e476
variables.cc (exist): Clarify help.
Ben Abbott <bpabbott@mac.com>
parents:
11630
diff
changeset
|
910 absolute file name, an ordinary file in Octave's @code{path}, or (after\n\ |
7a4efac7e476
variables.cc (exist): Clarify help.
Ben Abbott <bpabbott@mac.com>
parents:
11630
diff
changeset
|
911 appending @samp{.m}) a function file in Octave's @code{path}, 3 if the\n\ |
5864 | 912 name is a @samp{.oct} or @samp{.mex} file in Octave's @code{path},\n\ |
913 5 if the name is a built-in function, 7 if the name is a directory, or 103\n\ | |
4016 | 914 if the name is a function not associated with a file (entered on\n\ |
915 the command line).\n\ | |
916 \n\ | |
917 Otherwise, return 0.\n\ | |
918 \n\ | |
919 This function also returns 2 if a regular file called @var{name}\n\ | |
5814 | 920 exists in Octave's search path. If you want information about\n\ |
4016 | 921 other types of files, you should use some combination of the functions\n\ |
922 @code{file_in_path} and @code{stat} instead.\n\ | |
923 \n\ | |
924 If the optional argument @var{type} is supplied, check only for\n\ | |
925 symbols of the specified type. Valid types are\n\ | |
926 \n\ | |
927 @table @samp\n\ | |
928 @item \"var\"\n\ | |
929 Check only for variables.\n\ | |
930 @item \"builtin\"\n\ | |
931 Check only for built-in functions.\n\ | |
932 @item \"file\"\n\ | |
933 Check only for files.\n\ | |
934 @item \"dir\"\n\ | |
935 Check only for directories.\n\ | |
936 @end table\n\ | |
937 @end deftypefn") | |
938 { | |
4233 | 939 octave_value retval = false; |
4016 | 940 |
941 int nargin = args.length (); | |
942 | |
943 if (nargin == 1 || nargin == 2) | |
944 { | |
945 std::string name = args(0).string_value (); | |
946 | |
947 if (! error_state) | |
948 { | |
949 std::string type | |
950 = (nargin == 2) ? args(1).string_value () : std::string ("any"); | |
951 | |
952 if (! error_state) | |
4233 | 953 retval = symbol_exist (name, type); |
4016 | 954 else |
955 error ("exist: expecting second argument to be a string"); | |
956 } | |
957 else | |
958 error ("exist: expecting first argument to be a string"); | |
959 } | |
960 else | |
5823 | 961 print_usage (); |
4016 | 962 |
963 return retval; | |
964 } | |
965 | |
5663 | 966 bool |
5397 | 967 fcn_out_of_date (octave_function *fcn, const std::string& ff, time_t tp) |
5312 | 968 { |
969 bool retval = false; | |
970 | |
5397 | 971 fcn->mark_fcn_file_up_to_date (octave_time ()); |
972 | |
973 if (! (Vignore_function_time_stamp == 2 | |
974 || (Vignore_function_time_stamp && fcn->is_system_fcn_file ()))) | |
5312 | 975 { |
5397 | 976 file_stat fs (ff); |
977 | |
978 if (fs && fs.is_newer (tp)) | |
979 retval = true; | |
5312 | 980 } |
981 | |
982 return retval; | |
983 } | |
984 | |
5397 | 985 // Is there a corresponding function file that is newer than the |
986 // symbol definition? | |
987 | |
5312 | 988 static bool |
1 | 989 symbol_out_of_date (symbol_record *sr) |
990 { | |
2926 | 991 bool retval = false; |
195 | 992 |
5397 | 993 if (sr) |
1 | 994 { |
2975 | 995 octave_value ans = sr->def (); |
996 | |
5397 | 997 octave_function *fcn = ans.function_value (true); |
998 | |
6325 | 999 if (fcn) |
5397 | 1000 { |
1001 std::string ff = fcn->fcn_file_name (); | |
1002 | |
1003 if (! ff.empty ()) | |
1004 { | |
6323 | 1005 octave_time tc = fcn->time_checked (); |
1006 | |
1007 bool relative = fcn->is_relative (); | |
1008 | |
1009 if (tc < Vlast_prompt_time | |
1010 || (relative && tc < Vlast_chdir_time)) | |
5397 | 1011 { |
7065 | 1012 octave_time ottp = fcn->time_parsed (); |
1013 time_t tp = ottp.unix_time (); | |
5397 | 1014 |
6346 | 1015 std::string nm = fcn->is_nested_function () |
1016 ? fcn->parent_fcn_name () : fcn->name (); | |
5397 | 1017 |
5775 | 1018 // FIXME -- the following code is repeated |
5534 | 1019 // in load_fcn_from_file in parse.y. |
1020 | |
1021 int nm_len = nm.length (); | |
1022 | |
1023 std::string file; | |
1024 | |
1025 if (octave_env::absolute_pathname (nm) | |
5864 | 1026 && ((nm_len > 4 && (nm.substr (nm_len-4) == ".oct" |
1027 || nm.substr (nm_len-4) == ".mex")) | |
5534 | 1028 || (nm_len > 2 && nm.substr (nm_len-4) == ".m"))) |
1029 { | |
1030 file = nm; | |
1031 } | |
1032 else | |
1033 { | |
1034 file = lookup_autoload (nm); | |
1035 | |
1036 if (file.empty ()) | |
6323 | 1037 file = load_path::find_fcn (nm); |
1038 | |
1039 file = octave_env::make_absolute (file, octave_env::getcwd ()); | |
5534 | 1040 } |
5397 | 1041 |
6613 | 1042 if (file.empty ()) |
6323 | 1043 { |
6613 | 1044 // Can't see this function now, so we should |
1045 // clear it. | |
6323 | 1046 |
1047 sr->clear (); | |
1048 | |
1049 retval = true; | |
1050 } | |
1051 else if (same_file (file, ff)) | |
5397 | 1052 { |
1053 retval = fcn_out_of_date (fcn, ff, tp); | |
1054 } | |
1055 else | |
1056 { | |
6323 | 1057 // Check the full function name. Maybe we already |
5397 | 1058 // parsed it. |
1059 | |
1060 symbol_record *full_sr = fbi_sym_tab->lookup (file); | |
1061 | |
1062 if (full_sr) | |
1063 { | |
1064 octave_value v = full_sr->def (); | |
1065 | |
1066 if (v.is_function ()) | |
1067 { | |
1068 // OK, swap the aliases around. | |
1069 | |
5775 | 1070 // FIXME -- this is a bit |
5397 | 1071 // tricky, so maybe some refactoring is |
1072 // in order here too... | |
1073 | |
1074 symbol_record *short_sr = fbi_sym_tab->lookup (nm); | |
1075 | |
1076 if (short_sr) | |
1077 short_sr->alias (full_sr); | |
1078 | |
1079 // Make local symbol table entry point | |
1080 // to correct global function too. | |
1081 | |
1082 sr->alias (full_sr); | |
1083 | |
1084 fcn = v.function_value (); | |
1085 | |
1086 retval = fcn_out_of_date (fcn, file, tp); | |
1087 } | |
1088 else | |
1089 retval = true; | |
1090 } | |
1091 else | |
1092 retval = true; | |
1093 } | |
1094 } | |
1095 } | |
1096 } | |
1 | 1097 } |
2926 | 1098 |
1099 return retval; | |
1 | 1100 } |
1101 | |
1827 | 1102 bool |
2856 | 1103 lookup (symbol_record *sym_rec, bool exec_script) |
581 | 1104 { |
1827 | 1105 bool script_executed = false; |
581 | 1106 |
1107 if (! sym_rec->is_linked_to_global ()) | |
1108 { | |
1109 if (sym_rec->is_defined ()) | |
1110 { | |
1111 if (sym_rec->is_function () && symbol_out_of_date (sym_rec)) | |
1271 | 1112 script_executed = load_fcn_from_file (sym_rec, exec_script); |
581 | 1113 } |
1114 else if (! sym_rec->is_formal_parameter ()) | |
1115 { | |
1116 link_to_builtin_or_function (sym_rec); | |
1271 | 1117 |
581 | 1118 if (! sym_rec->is_defined ()) |
1271 | 1119 script_executed = load_fcn_from_file (sym_rec, exec_script); |
581 | 1120 else if (sym_rec->is_function () && symbol_out_of_date (sym_rec)) |
1271 | 1121 script_executed = load_fcn_from_file (sym_rec, exec_script); |
581 | 1122 } |
1123 } | |
1124 | |
1271 | 1125 return script_executed; |
581 | 1126 } |
1127 | |
1128 // Get the symbol record for the given name that is visible in the | |
1129 // current scope. Reread any function definitions that appear to be | |
1130 // out of date. If a function is available in a file but is not | |
1131 // currently loaded, this will load it and insert the name in the | |
1132 // current symbol table. | |
1133 | |
1134 symbol_record * | |
3523 | 1135 lookup_by_name (const std::string& nm, bool exec_script) |
581 | 1136 { |
2856 | 1137 symbol_record *sym_rec = curr_sym_tab->lookup (nm, true); |
581 | 1138 |
1139 lookup (sym_rec, exec_script); | |
1140 | |
1141 return sym_rec; | |
1142 } | |
1143 | |
4930 | 1144 octave_value |
6323 | 1145 lookup_function (const std::string& nm, const std::string& parent) |
4342 | 1146 { |
4930 | 1147 octave_value retval; |
4342 | 1148 |
1149 symbol_record *sr = 0; | |
1150 | |
6323 | 1151 if (! parent.empty ()) |
1152 sr = fbi_sym_tab->lookup (parent + ":" + nm); | |
1153 | |
4342 | 1154 if (! sr || ! sr->is_function ()) |
1155 { | |
6351 | 1156 if (curr_parent_function) |
1157 sr = fbi_sym_tab->lookup (curr_parent_function->name () + ":" + nm); | |
1158 | |
1159 if (! sr || ! sr->is_function ()) | |
1160 sr = fbi_sym_tab->lookup (nm, true); | |
4342 | 1161 |
1162 if (sr && ! sr->is_function ()) | |
1163 load_fcn_from_file (sr, false); | |
1164 } | |
1165 | |
1166 if (sr) | |
1167 { | |
1168 octave_value v = sr->def (); | |
1169 | |
1170 if (v.is_function ()) | |
4930 | 1171 retval = v; |
4342 | 1172 } |
1173 | |
1174 return retval; | |
1175 } | |
1176 | |
4930 | 1177 octave_value |
4700 | 1178 lookup_user_function (const std::string& nm) |
1179 { | |
4930 | 1180 octave_value retval; |
4700 | 1181 |
1182 symbol_record *sr = 0; | |
1183 | |
1184 if (curr_parent_function) | |
1185 { | |
4748 | 1186 std::string parent = curr_parent_function->name (); |
4700 | 1187 |
1188 sr = fbi_sym_tab->lookup (parent + ":" + nm); | |
1189 } | |
1190 | |
1191 if (! sr || ! sr->is_user_function ()) | |
1192 { | |
1193 sr = fbi_sym_tab->lookup (nm, true); | |
1194 | |
1195 if (sr && ! sr->is_user_function ()) | |
1196 load_fcn_from_file (sr, false); | |
1197 } | |
1198 | |
1199 if (sr) | |
4930 | 1200 retval = sr->def (); |
4700 | 1201 |
1202 return retval; | |
1203 } | |
1204 | |
2849 | 1205 octave_value |
4988 | 1206 lookup_function_handle (const std::string& nm) |
1207 { | |
1208 octave_value retval; | |
1209 | |
1210 symbol_record *sr = curr_sym_tab->lookup (nm, true); | |
1211 | |
1212 if (sr && sr->def ().is_function_handle ()) | |
1213 retval = sr->def (); | |
1214 | |
1215 return retval; | |
1216 } | |
1217 | |
1218 octave_value | |
5027 | 1219 get_global_value (const std::string& nm, bool silent) |
2849 | 1220 { |
1221 octave_value retval; | |
1222 | |
1223 symbol_record *sr = global_sym_tab->lookup (nm); | |
1224 | |
1225 if (sr) | |
1226 { | |
2975 | 1227 octave_value sr_def = sr->def (); |
2849 | 1228 |
5027 | 1229 if (sr_def.is_defined ()) |
1230 retval = sr_def; | |
1231 else if (! silent) | |
2849 | 1232 error ("get_global_by_name: undefined symbol `%s'", nm.c_str ()); |
1233 } | |
5027 | 1234 else if (! silent) |
2849 | 1235 error ("get_global_by_name: unknown symbol `%s'", nm.c_str ()); |
1236 | |
1237 return retval; | |
1238 } | |
1239 | |
1240 void | |
3523 | 1241 set_global_value (const std::string& nm, const octave_value& val) |
2849 | 1242 { |
2856 | 1243 symbol_record *sr = global_sym_tab->lookup (nm, true); |
2849 | 1244 |
1245 if (sr) | |
1246 sr->define (val); | |
1247 else | |
1248 panic_impossible (); | |
1249 } | |
1250 | |
593 | 1251 // Variable values. |
195 | 1252 |
5791 | 1253 octave_value |
1254 set_internal_variable (bool& var, const octave_value_list& args, | |
5794 | 1255 int nargout, const char *nm) |
5791 | 1256 { |
5794 | 1257 octave_value retval; |
1258 | |
5800 | 1259 int nargin = args.length (); |
1260 | |
1261 if (nargout > 0 || nargin == 0) | |
5794 | 1262 retval = var; |
5791 | 1263 |
1264 if (nargin == 1) | |
1265 { | |
1266 bool bval = args(0).bool_value (); | |
1267 | |
1268 if (! error_state) | |
1269 var = bval; | |
1270 else | |
1271 error ("%s: expecting arg to be a logical value", nm); | |
1272 } | |
1273 else if (nargin > 1) | |
5823 | 1274 print_usage (); |
5791 | 1275 |
1276 return retval; | |
1277 } | |
1278 | |
1279 octave_value | |
5794 | 1280 set_internal_variable (char& var, const octave_value_list& args, |
1281 int nargout, const char *nm) | |
5791 | 1282 { |
5794 | 1283 octave_value retval; |
1284 | |
5800 | 1285 int nargin = args.length (); |
1286 | |
1287 if (nargout > 0 || nargin == 0) | |
5794 | 1288 retval = var; |
5791 | 1289 |
1290 if (nargin == 1) | |
1291 { | |
1292 std::string sval = args(0).string_value (); | |
1293 | |
1294 if (! error_state) | |
5794 | 1295 { |
1296 switch (sval.length ()) | |
1297 { | |
1298 case 1: | |
1299 var = sval[0]; | |
1300 break; | |
1301 | |
1302 case 0: | |
1303 var = '\0'; | |
1304 break; | |
1305 | |
1306 default: | |
1307 error ("%s: argument must be a single character", nm); | |
1308 break; | |
1309 } | |
1310 } | |
1311 else | |
1312 error ("%s: argument must be a single character", nm); | |
1313 } | |
1314 else if (nargin > 1) | |
5823 | 1315 print_usage (); |
5794 | 1316 |
1317 return retval; | |
1318 } | |
1319 | |
1320 octave_value | |
1321 set_internal_variable (int& var, const octave_value_list& args, | |
1322 int nargout, const char *nm, | |
1323 int minval, int maxval) | |
1324 { | |
1325 octave_value retval; | |
1326 | |
5800 | 1327 int nargin = args.length (); |
1328 | |
1329 if (nargout > 0 || nargin == 0) | |
5794 | 1330 retval = var; |
1331 | |
1332 if (nargin == 1) | |
1333 { | |
1334 int ival = args(0).int_value (); | |
1335 | |
1336 if (! error_state) | |
1337 { | |
1338 if (ival < minval) | |
1339 error ("%s: expecting arg to be greater than %d", minval); | |
1340 else if (ival > maxval) | |
1341 error ("%s: expecting arg to be less than or equal to %d", maxval); | |
1342 else | |
1343 var = ival; | |
1344 } | |
1345 else | |
1346 error ("%s: expecting arg to be an integer value", nm); | |
1347 } | |
1348 else if (nargin > 1) | |
5823 | 1349 print_usage (); |
5794 | 1350 |
1351 return retval; | |
1352 } | |
1353 | |
1354 octave_value | |
1355 set_internal_variable (double& var, const octave_value_list& args, | |
1356 int nargout, const char *nm, | |
1357 double minval, double maxval) | |
1358 { | |
1359 octave_value retval; | |
1360 | |
5800 | 1361 int nargin = args.length (); |
1362 | |
1363 if (nargout > 0 || nargin == 0) | |
5794 | 1364 retval = var; |
1365 | |
1366 if (nargin == 1) | |
1367 { | |
1368 double dval = args(0).scalar_value (); | |
1369 | |
1370 if (! error_state) | |
1371 { | |
1372 if (dval < minval) | |
1373 error ("%s: expecting arg to be greater than %g", minval); | |
1374 else if (dval > maxval) | |
1375 error ("%s: expecting arg to be less than or equal to %g", maxval); | |
1376 else | |
1377 var = dval; | |
1378 } | |
1379 else | |
1380 error ("%s: expecting arg to be a scalar value", nm); | |
1381 } | |
1382 else if (nargin > 1) | |
5823 | 1383 print_usage (); |
5794 | 1384 |
1385 return retval; | |
1386 } | |
1387 | |
1388 octave_value | |
1389 set_internal_variable (std::string& var, const octave_value_list& args, | |
1390 int nargout, const char *nm, bool empty_ok) | |
1391 { | |
1392 octave_value retval; | |
1393 | |
5800 | 1394 int nargin = args.length (); |
1395 | |
1396 if (nargout > 0 || nargin == 0) | |
5794 | 1397 retval = var; |
1398 | |
1399 if (nargin == 1) | |
1400 { | |
1401 std::string sval = args(0).string_value (); | |
1402 | |
1403 if (! error_state) | |
1404 { | |
1405 if (empty_ok || ! sval.empty ()) | |
1406 var = sval; | |
1407 else | |
1408 error ("%s: value must not be empty", nm); | |
1409 } | |
5791 | 1410 else |
1411 error ("%s: expecting arg to be a character string", nm); | |
1412 } | |
1413 else if (nargin > 1) | |
5823 | 1414 print_usage (); |
1 | 1415 |
1416 return retval; | |
1417 } | |
1418 | |
593 | 1419 // Global stuff and links to builtin variables and functions. |
1420 | |
581 | 1421 // Make the definition of the symbol record sr be the same as the |
1422 // definition of the global variable of the same name, creating it if | |
1418 | 1423 // it doesn't already exist. |
581 | 1424 |
195 | 1425 void |
1426 link_to_global_variable (symbol_record *sr) | |
1427 { | |
2975 | 1428 if (! sr->is_linked_to_global ()) |
195 | 1429 { |
2975 | 1430 sr->mark_as_linked_to_global (); |
195 | 1431 |
2975 | 1432 if (! error_state) |
1433 { | |
3523 | 1434 std::string nm = sr->name (); |
2846 | 1435 |
2975 | 1436 symbol_record *gsr = global_sym_tab->lookup (nm, true); |
1437 | |
1438 // Make sure this symbol is a variable. | |
2900 | 1439 |
4009 | 1440 if (! gsr->is_user_variable ()) |
2975 | 1441 gsr->define (octave_value ()); |
2900 | 1442 |
4009 | 1443 sr->alias (gsr); |
2975 | 1444 } |
195 | 1445 } |
1446 } | |
1447 | |
581 | 1448 // Make the definition of the symbol record sr be the same as the |
1449 // definition of the builtin variable of the same name. | |
1450 | |
1451 // Make the definition of the symbol record sr be the same as the | |
5794 | 1452 // definition of the builtin function, or user function of the same |
1453 // name, provided that the name has not been used as a formal parameter. | |
581 | 1454 |
195 | 1455 void |
1456 link_to_builtin_or_function (symbol_record *sr) | |
1457 { | |
4238 | 1458 std::string nm = sr->name (); |
1459 | |
1460 symbol_record *tmp_sym = 0; | |
1461 | |
6323 | 1462 octave_function *fcn = octave_call_stack::current (); |
1463 | |
1464 std::string parent = fcn ? fcn->parent_fcn_name () : std::string (); | |
1465 | |
1466 if (! parent.empty ()) | |
1467 tmp_sym = fbi_sym_tab->lookup (parent + ":" + nm); | |
1468 | |
1469 if (! tmp_sym && curr_parent_function) | |
1470 tmp_sym = fbi_sym_tab->lookup (curr_parent_function->name () + ":" + nm); | |
4238 | 1471 |
1472 if (! tmp_sym) | |
1473 tmp_sym = fbi_sym_tab->lookup (nm); | |
195 | 1474 |
529 | 1475 if (tmp_sym |
5794 | 1476 && tmp_sym->is_function () |
529 | 1477 && ! tmp_sym->is_formal_parameter ()) |
1478 sr->alias (tmp_sym); | |
195 | 1479 } |
1480 | |
581 | 1481 // Force a link to a function in the current symbol table. This is |
1482 // used just after defining a function to avoid different behavior | |
1483 // depending on whether or not the function has been evaluated after | |
1484 // being defined. | |
1485 // | |
1486 // Return without doing anything if there isn't a function with the | |
1487 // given name defined in the global symbol table. | |
1488 | |
195 | 1489 void |
3523 | 1490 force_link_to_function (const std::string& id_name) |
195 | 1491 { |
4009 | 1492 symbol_record *fsr = fbi_sym_tab->lookup (id_name, true); |
1493 if (fsr->is_function ()) | |
195 | 1494 { |
1495 curr_sym_tab->clear (id_name); | |
2856 | 1496 symbol_record *csr = curr_sym_tab->lookup (id_name, true); |
4009 | 1497 csr->alias (fsr); |
195 | 1498 } |
1499 } | |
1500 | |
2294 | 1501 DEFUN (document, args, , |
3361 | 1502 "-*- texinfo -*-\n\ |
1503 @deftypefn {Built-in Function} {} document (@var{symbol}, @var{text})\n\ | |
1504 Set the documentation string for @var{symbol} to @var{text}.\n\ | |
1505 @end deftypefn") | |
593 | 1506 { |
2294 | 1507 octave_value retval; |
1755 | 1508 |
2294 | 1509 int nargin = args.length (); |
1755 | 1510 |
2294 | 1511 if (nargin == 2) |
593 | 1512 { |
3523 | 1513 std::string name = args(0).string_value (); |
593 | 1514 |
2294 | 1515 if (! error_state) |
593 | 1516 { |
3523 | 1517 std::string help = args(1).string_value (); |
593 | 1518 |
2294 | 1519 if (! error_state) |
1520 { | |
5794 | 1521 if (is_command_name (name) |
2294 | 1522 || is_mapper_function_name (name) |
1523 || is_builtin_function_name (name)) | |
5794 | 1524 error ("document: can't redefine help for built-in functions"); |
2294 | 1525 else |
1526 { | |
2856 | 1527 symbol_record *sym_rec = curr_sym_tab->lookup (name); |
2294 | 1528 |
1529 if (sym_rec) | |
1530 sym_rec->document (help); | |
1531 else | |
1532 error ("document: no such symbol `%s'", name.c_str ()); | |
1533 } | |
1534 } | |
593 | 1535 } |
1536 } | |
1537 else | |
5823 | 1538 print_usage (); |
593 | 1539 |
1540 return retval; | |
1541 } | |
1542 | |
5775 | 1543 // FIXME -- this function is duplicated in symtab.cc with the |
5659 | 1544 // name maybe_list_cmp_fcn. |
1545 | |
1546 static int | |
1547 symbol_record_name_compare (const void *a_arg, const void *b_arg) | |
1548 { | |
5929 | 1549 const symbol_record *a = *(static_cast<symbol_record *const*> (a_arg)); |
1550 const symbol_record *b = *(static_cast<symbol_record *const*> (b_arg)); | |
5659 | 1551 |
1552 std::string a_nm = a->name (); | |
1553 std::string b_nm = b->name (); | |
1554 | |
1555 return a_nm.compare (b_nm); | |
1556 } | |
1557 | |
4435 | 1558 static octave_value |
1559 do_who (int argc, const string_vector& argv, int return_list) | |
529 | 1560 { |
4435 | 1561 octave_value retval; |
529 | 1562 |
2856 | 1563 bool show_builtins = false; |
3248 | 1564 bool show_functions = false; |
1565 bool show_variables = false; | |
2856 | 1566 bool show_verbose = false; |
529 | 1567 |
3523 | 1568 std::string my_name = argv[0]; |
584 | 1569 |
1857 | 1570 int i; |
1571 for (i = 1; i < argc; i++) | |
529 | 1572 { |
1755 | 1573 if (argv[i] == "-all" || argv[i] == "-a") |
529 | 1574 { |
2856 | 1575 show_builtins = true; |
1576 show_functions = true; | |
1577 show_variables = true; | |
529 | 1578 } |
1755 | 1579 else if (argv[i] == "-builtins" || argv[i] == "-b") |
2856 | 1580 show_builtins = true; |
1755 | 1581 else if (argv[i] == "-functions" || argv[i] == "-f") |
2856 | 1582 show_functions = true; |
1755 | 1583 else if (argv[i] == "-long" || argv[i] == "-l") |
2856 | 1584 show_verbose = true; |
1755 | 1585 else if (argv[i] == "-variables" || argv[i] == "-v") |
2856 | 1586 show_variables = true; |
1755 | 1587 else if (argv[i][0] == '-') |
1588 warning ("%s: unrecognized option `%s'", my_name.c_str (), | |
1589 argv[i].c_str ()); | |
529 | 1590 else |
867 | 1591 break; |
529 | 1592 } |
1593 | |
3248 | 1594 // If no options were specified to select the type of symbol to |
1595 // display, then set defaults. | |
1596 | |
1597 if (! (show_builtins || show_functions || show_variables)) | |
1598 { | |
4208 | 1599 show_functions = at_top_level (); |
3248 | 1600 show_variables = true; |
1601 } | |
1602 | |
1857 | 1603 int npats = argc - i; |
1604 string_vector pats (npats); | |
1605 for (int j = 0; j < npats; j++) | |
1606 pats[j] = argv[i+j]; | |
1607 | |
1271 | 1608 // If the user specified -l and nothing else, show variables. If |
1609 // evaluating this at the top level, also show functions. | |
529 | 1610 |
1611 if (show_verbose && ! (show_builtins || show_functions || show_variables)) | |
1612 { | |
4208 | 1613 show_functions = at_top_level (); |
529 | 1614 show_variables = 1; |
1615 } | |
1616 | |
4435 | 1617 if (return_list) |
529 | 1618 { |
5775 | 1619 // FIXME -- maybe symbol_list should return a std::list |
5659 | 1620 // object instead of an Array. |
1621 | |
1622 dim_vector dv (0, 0); | |
1623 | |
1624 Array<symbol_record *> s3 (dv); | |
1625 Array<symbol_record *> s4 (dv); | |
1626 Array<symbol_record *> s5 (dv); | |
1627 Array<symbol_record *> s6 (dv); | |
1628 Array<symbol_record *> s7 (dv); | |
5864 | 1629 Array<symbol_record *> s8 (dv); |
4435 | 1630 |
1631 if (show_builtins) | |
1632 { | |
5659 | 1633 s3 = fbi_sym_tab->symbol_list (pats, symbol_record::BUILTIN_FUNCTION, |
1634 SYMTAB_ALL_SCOPES); | |
4435 | 1635 } |
1636 | |
1637 if (show_functions) | |
1638 { | |
5659 | 1639 s4 = fbi_sym_tab->symbol_list (pats, symbol_record::DLD_FUNCTION, |
1640 SYMTAB_ALL_SCOPES); | |
1641 | |
1642 s5 = fbi_sym_tab->symbol_list (pats, symbol_record::USER_FUNCTION, | |
1643 SYMTAB_ALL_SCOPES); | |
5864 | 1644 |
1645 s6 = fbi_sym_tab->symbol_list (pats, symbol_record::MEX_FUNCTION, | |
1646 SYMTAB_ALL_SCOPES); | |
4435 | 1647 } |
1648 | |
1649 if (show_variables) | |
1650 { | |
5864 | 1651 s7 = curr_sym_tab->symbol_list (pats, symbol_record::USER_VARIABLE, |
5659 | 1652 SYMTAB_LOCAL_SCOPE); |
1653 | |
5864 | 1654 s8 = curr_sym_tab->symbol_list (pats, symbol_record::USER_VARIABLE, |
5659 | 1655 SYMTAB_GLOBAL_SCOPE); |
4435 | 1656 } |
1657 | |
5659 | 1658 octave_idx_type s3_len = s3.length (); |
1659 octave_idx_type s4_len = s4.length (); | |
1660 octave_idx_type s5_len = s5.length (); | |
1661 octave_idx_type s6_len = s6.length (); | |
1662 octave_idx_type s7_len = s7.length (); | |
5864 | 1663 octave_idx_type s8_len = s8.length (); |
1664 | |
1665 octave_idx_type symbols_len | |
1666 = s3_len + s4_len + s5_len + s6_len + s7_len + s8_len; | |
5659 | 1667 |
1668 Array<symbol_record *> symbols (dim_vector (symbols_len, 1)); | |
1669 | |
1670 octave_idx_type k = 0; | |
1671 | |
1672 symbols.insert (s3, k, 0); | |
1673 k += s3_len; | |
1674 symbols.insert (s4, k, 0); | |
1675 k += s4_len; | |
1676 symbols.insert (s5, k, 0); | |
1677 k += s5_len; | |
1678 symbols.insert (s6, k, 0); | |
1679 k += s6_len; | |
1680 symbols.insert (s7, k, 0); | |
5864 | 1681 k += s7_len; |
1682 symbols.insert (s8, k, 0); | |
5659 | 1683 |
1684 symbols.qsort (symbol_record_name_compare); | |
1685 | |
4435 | 1686 if (show_verbose) |
1687 { | |
5659 | 1688 Array<octave_value> name_info (symbols_len, 1); |
1689 Array<octave_value> size_info (symbols_len, 1); | |
1690 Array<octave_value> bytes_info (symbols_len, 1); | |
1691 Array<octave_value> class_info (symbols_len, 1); | |
1692 Array<octave_value> global_info (symbols_len, 1); | |
1693 Array<octave_value> sparse_info (symbols_len, 1); | |
1694 Array<octave_value> complex_info (symbols_len, 1); | |
1695 Array<octave_value> nesting_info (symbols_len, 1); | |
1696 | |
1697 for (octave_idx_type j = 0; j < symbols_len; j++) | |
1698 { | |
1699 symbol_record *sr = symbols(j); | |
1700 | |
1701 Octave_map ni; | |
1702 | |
1703 std::string caller_function_name; | |
5743 | 1704 |
1705 octave_function *caller = octave_call_stack::caller (); | |
1706 if (caller) | |
1707 caller_function_name = caller->name (); | |
5659 | 1708 |
1709 ni.assign ("function", caller_function_name); | |
1710 ni.assign ("level", 1); | |
1711 | |
1712 name_info(j) = sr->name (); | |
1713 size_info(j) = sr->size (); | |
1714 bytes_info(j) = sr->byte_size (); | |
1715 class_info(j) = sr->class_name (); | |
1716 global_info(j) = sr->is_linked_to_global (); | |
1717 sparse_info(j) = sr->is_sparse_type (); | |
1718 complex_info(j) = sr->is_complex_type (); | |
1719 nesting_info(j) = ni; | |
1720 } | |
1721 | |
1722 Octave_map info; | |
1723 | |
1724 info.assign ("name", name_info); | |
1725 info.assign ("size", size_info); | |
1726 info.assign ("bytes", bytes_info); | |
1727 info.assign ("class", class_info); | |
1728 info.assign ("global", global_info); | |
1729 info.assign ("sparse", sparse_info); | |
1730 info.assign ("complex", complex_info); | |
1731 info.assign ("nesting", nesting_info); | |
1732 | |
1733 retval = info; | |
4435 | 1734 } |
1735 else | |
5659 | 1736 { |
1737 string_vector names; | |
1738 | |
1739 if (symbols_len > 0) | |
1740 { | |
1741 names.resize (symbols_len); | |
1742 | |
1743 for (octave_idx_type j = 0; j < symbols_len; j++) | |
1744 names[j] = symbols(j)->name (); | |
1745 } | |
1746 | |
1747 retval = Cell (names); | |
1748 } | |
529 | 1749 } |
4435 | 1750 else |
529 | 1751 { |
4435 | 1752 int pad_after = 0; |
1753 | |
1754 if (show_builtins) | |
1755 { | |
1756 pad_after += fbi_sym_tab->maybe_list | |
1757 ("*** built-in functions:", pats, octave_stdout, | |
1758 show_verbose, symbol_record::BUILTIN_FUNCTION, SYMTAB_ALL_SCOPES); | |
1759 } | |
529 | 1760 |
4435 | 1761 if (show_functions) |
1762 { | |
1763 pad_after += fbi_sym_tab->maybe_list | |
1764 ("*** dynamically linked functions:", pats, | |
1765 octave_stdout, show_verbose, symbol_record::DLD_FUNCTION, | |
1766 SYMTAB_ALL_SCOPES); | |
1767 | |
1768 pad_after += fbi_sym_tab->maybe_list | |
1769 ("*** currently compiled functions:", pats, | |
1770 octave_stdout, show_verbose, symbol_record::USER_FUNCTION, | |
1771 SYMTAB_ALL_SCOPES); | |
5864 | 1772 |
1773 pad_after += fbi_sym_tab->maybe_list | |
1774 ("*** mex functions:", pats, | |
1775 octave_stdout, show_verbose, symbol_record::MEX_FUNCTION, | |
1776 SYMTAB_ALL_SCOPES); | |
4435 | 1777 } |
1778 | |
1779 if (show_variables) | |
1780 { | |
1781 pad_after += curr_sym_tab->maybe_list | |
1782 ("*** local user variables:", pats, octave_stdout, | |
1783 show_verbose, symbol_record::USER_VARIABLE, SYMTAB_LOCAL_SCOPE); | |
1784 | |
1785 pad_after += curr_sym_tab->maybe_list | |
1786 ("*** globally visible user variables:", pats, | |
1787 octave_stdout, show_verbose, symbol_record::USER_VARIABLE, | |
1788 SYMTAB_GLOBAL_SCOPE); | |
1789 } | |
1790 | |
1791 if (pad_after) | |
1792 octave_stdout << "\n"; | |
529 | 1793 } |
1794 | |
581 | 1795 return retval; |
1796 } | |
1797 | |
4435 | 1798 DEFCMD (who, args, nargout, |
3361 | 1799 "-*- texinfo -*-\n\ |
1800 @deffn {Command} who options pattern @dots{}\n\ | |
1801 @deffnx {Command} whos options pattern @dots{}\n\ | |
1802 List currently defined symbols matching the given patterns. The\n\ | |
1803 following are valid options. They may be shortened to one character but\n\ | |
1804 may not be combined.\n\ | |
1805 \n\ | |
1806 @table @code\n\ | |
1807 @item -all\n\ | |
1808 List all currently defined symbols.\n\ | |
1809 \n\ | |
1810 @item -builtins\n\ | |
5794 | 1811 List built-in functions. This includes all currently\n\ |
3361 | 1812 compiled function files, but does not include all function files that\n\ |
5814 | 1813 are in the search path.\n\ |
581 | 1814 \n\ |
3361 | 1815 @item -functions\n\ |
1816 List user-defined functions.\n\ | |
1817 \n\ | |
1818 @item -long\n\ | |
1819 Print a long listing including the type and dimensions of any symbols.\n\ | |
1820 The symbols in the first column of output indicate whether it is\n\ | |
1821 possible to redefine the symbol, and whether it is possible for it to be\n\ | |
1822 cleared.\n\ | |
1823 \n\ | |
1824 @item -variables\n\ | |
1825 List user-defined variables.\n\ | |
1826 @end table\n\ | |
1827 \n\ | |
1828 Valid patterns are the same as described for the @code{clear} command\n\ | |
1829 above. If no patterns are supplied, all symbols from the given category\n\ | |
1830 are listed. By default, only user defined functions and variables\n\ | |
1831 visible in the local scope are displayed.\n\ | |
1832 \n\ | |
1833 The command @kbd{whos} is equivalent to @kbd{who -long}.\n\ | |
1834 @end deffn") | |
581 | 1835 { |
4435 | 1836 octave_value retval; |
581 | 1837 |
4435 | 1838 if (nargout < 2) |
1839 { | |
1840 int argc = args.length () + 1; | |
1841 | |
1842 string_vector argv = args.make_argv ("who"); | |
1755 | 1843 |
4435 | 1844 if (error_state) |
1845 return retval; | |
1755 | 1846 |
4435 | 1847 retval = do_who (argc, argv, nargout == 1); |
1848 } | |
1849 else | |
5823 | 1850 print_usage (); |
581 | 1851 |
529 | 1852 return retval; |
1853 } | |
1854 | |
4435 | 1855 DEFCMD (whos, args, nargout, |
3458 | 1856 "-*- texinfo -*-\n\ |
1857 @deffn {Command} whos options pattern @dots{}\n\ | |
1858 See who.\n\ | |
1859 @end deffn") | |
581 | 1860 { |
4435 | 1861 octave_value retval; |
712 | 1862 |
4435 | 1863 if (nargout < 2) |
1864 { | |
1865 int nargin = args.length (); | |
1866 | |
1867 octave_value_list tmp_args; | |
1868 | |
1869 for (int i = nargin; i > 0; i--) | |
1870 tmp_args(i) = args(i-1); | |
581 | 1871 |
4435 | 1872 tmp_args(0) = "-long"; |
1755 | 1873 |
4435 | 1874 int argc = tmp_args.length () + 1; |
1875 | |
1876 string_vector argv = tmp_args.make_argv ("whos"); | |
581 | 1877 |
4435 | 1878 if (error_state) |
1879 return retval; | |
581 | 1880 |
4435 | 1881 retval = do_who (argc, argv, nargout == 1); |
1882 } | |
1883 else | |
5823 | 1884 print_usage (); |
581 | 1885 |
1886 return retval; | |
1887 } | |
1888 | |
593 | 1889 // Defining variables. |
1890 | |
1162 | 1891 void |
2856 | 1892 bind_ans (const octave_value& val, bool print) |
1162 | 1893 { |
5794 | 1894 symbol_record *sr = curr_sym_tab->lookup ("ans", true); |
1162 | 1895 |
2978 | 1896 if (val.is_defined ()) |
1897 { | |
1898 sr->define (val); | |
1162 | 1899 |
2978 | 1900 if (print) |
1901 val.print_with_name (octave_stdout, "ans"); | |
1902 } | |
1162 | 1903 } |
1904 | |
593 | 1905 void |
5794 | 1906 bind_internal_variable (const std::string& fname, const octave_value& val) |
593 | 1907 { |
5794 | 1908 octave_value_list args; |
1909 | |
1910 args(0) = val; | |
1911 | |
1912 feval (fname, args, 0); | |
529 | 1913 } |
1914 | |
4319 | 1915 void |
1916 mlock (const std::string& nm) | |
1917 { | |
1918 symbol_record *sr = fbi_sym_tab->lookup (nm, true); | |
1919 | |
1920 if (sr) | |
1921 sr->mark_as_static (); | |
1922 } | |
1923 | |
1924 void | |
1925 munlock (const std::string& nm) | |
1926 { | |
1927 symbol_record *sr = fbi_sym_tab->lookup (nm); | |
1928 | |
1929 if (sr && sr->is_static ()) | |
1930 sr->unmark_static (); | |
1931 else | |
1932 error ("munlock: %s is not locked", nm.c_str ()); | |
1933 } | |
1934 | |
1935 bool | |
1936 mislocked (const std::string& nm) | |
1937 { | |
1938 symbol_record *sr = fbi_sym_tab->lookup (nm); | |
1939 | |
1940 return (sr && sr->is_static ()); | |
1941 } | |
1942 | |
1943 DEFCMD (mlock, args, , | |
1944 "-*- texinfo -*-\n\ | |
4526 | 1945 @deftypefn {Built-in Function} {} mlock (@var{name})\n\ |
4319 | 1946 Lock the named function into memory. If no function is named\n\ |
1947 then lock in the current function.\n\ | |
5642 | 1948 @seealso{munlock, mislocked, persistent}\n\ |
1949 @end deftypefn") | |
4319 | 1950 { |
1951 octave_value_list retval; | |
1952 | |
1953 if (args.length () == 1) | |
1954 { | |
1955 std::string name = args(0).string_value (); | |
1956 | |
1957 if (! error_state) | |
1958 mlock (name); | |
1959 else | |
1960 error ("mlock: expecting argument to be a function name"); | |
1961 } | |
1962 else if (args.length () == 0) | |
1963 { | |
5744 | 1964 octave_user_function *fcn = octave_call_stack::caller_user_function (); |
5743 | 1965 |
1966 if (fcn) | |
1967 mlock (fcn->name ()); | |
4319 | 1968 else |
1969 error ("mlock: invalid use outside a function"); | |
1970 } | |
1971 else | |
5823 | 1972 print_usage (); |
4319 | 1973 |
1974 return retval; | |
1975 } | |
1976 | |
1977 DEFCMD (munlock, args, , | |
1978 "-*- texinfo -*-\n\ | |
1979 @deftypefn {Built-in Function} {} munlock (@var{fcn})\n\ | |
1980 Unlock the named function. If no function is named\n\ | |
1981 then unlock the current function.\n\ | |
5642 | 1982 @seealso{mlock, mislocked, persistent}\n\ |
1983 @end deftypefn") | |
4319 | 1984 { |
1985 octave_value_list retval; | |
1986 | |
1987 if (args.length() == 1) | |
1988 { | |
1989 std::string name = args(0).string_value (); | |
1990 | |
1991 if (! error_state) | |
1992 munlock (name); | |
1993 else | |
1994 error ("munlock: expecting argument to be a function name"); | |
1995 } | |
1996 else if (args.length () == 0) | |
1997 { | |
5744 | 1998 octave_user_function *fcn = octave_call_stack::caller_user_function (); |
5743 | 1999 |
2000 if (fcn) | |
6819 | 2001 munlock (fcn->name ()); |
4319 | 2002 else |
2003 error ("munlock: invalid use outside a function"); | |
2004 } | |
2005 else | |
5823 | 2006 print_usage (); |
4319 | 2007 |
2008 return retval; | |
2009 } | |
2010 | |
2011 | |
2012 DEFCMD (mislocked, args, , | |
2013 "-*- texinfo -*-\n\ | |
2014 @deftypefn {Built-in Function} {} mislocked (@var{fcn})\n\ | |
2015 Return true if the named function is locked. If no function is named\n\ | |
2016 then return true if the current function is locked.\n\ | |
5642 | 2017 @seealso{mlock, munlock, persistent}\n\ |
2018 @end deftypefn") | |
4319 | 2019 { |
2020 octave_value retval; | |
2021 | |
2022 if (args.length() == 1) | |
2023 { | |
2024 std::string name = args(0).string_value (); | |
2025 | |
2026 if (! error_state) | |
2027 retval = mislocked (name); | |
2028 else | |
2029 error ("mislocked: expecting argument to be a function name"); | |
2030 } | |
2031 else if (args.length () == 0) | |
2032 { | |
5744 | 2033 octave_user_function *fcn = octave_call_stack::caller_user_function (); |
5743 | 2034 |
2035 if (fcn) | |
2036 retval = mislocked (fcn->name ()); | |
4319 | 2037 else |
2038 error ("mislocked: invalid use outside a function"); | |
2039 } | |
2040 else | |
5823 | 2041 print_usage (); |
4319 | 2042 |
2043 return retval; | |
2044 } | |
2045 | |
593 | 2046 // Deleting names from the symbol tables. |
2047 | |
3681 | 2048 static inline bool |
4009 | 2049 name_matches_any_pattern (const std::string& nm, |
2050 const string_vector& argv, int argc, int idx) | |
3681 | 2051 { |
2052 bool retval = false; | |
2053 | |
2054 for (int k = idx; k < argc; k++) | |
2055 { | |
2056 std::string patstr = argv[k]; | |
2057 | |
2058 if (! patstr.empty ()) | |
2059 { | |
2060 glob_match pattern (patstr); | |
2061 | |
2062 if (pattern.match (nm)) | |
2063 { | |
2064 retval = true; | |
2065 break; | |
2066 } | |
2067 } | |
2068 } | |
2069 | |
2070 return retval; | |
2071 } | |
2072 | |
4009 | 2073 static inline bool |
2074 is_local_variable (const std::string& nm) | |
2075 { | |
2076 symbol_record *sr = curr_sym_tab->lookup (nm); | |
2077 | |
2078 return (sr && sr->is_variable ()); | |
2079 } | |
2080 | |
2081 static inline void | |
2082 maybe_warn_exclusive (bool exclusive) | |
2083 { | |
2084 if (exclusive) | |
2085 warning ("clear: ignoring --exclusive option"); | |
2086 } | |
2087 | |
2088 static inline void | |
2089 do_clear_all (void) | |
2090 { | |
2091 curr_sym_tab->clear (); | |
2092 fbi_sym_tab->clear_functions (); | |
2093 global_sym_tab->clear (); | |
2094 } | |
2095 | |
2096 static inline void | |
2097 do_clear_functions (void) | |
2098 { | |
2099 curr_sym_tab->clear_functions (); | |
2100 fbi_sym_tab->clear_functions (); | |
2101 } | |
2102 | |
2103 static inline void | |
2104 do_clear_globals (void) | |
2105 { | |
2106 curr_sym_tab->clear_globals (); | |
2107 global_sym_tab->clear (); | |
2108 } | |
2109 | |
2110 static inline void | |
2111 do_clear_variables (void) | |
2112 { | |
2113 curr_sym_tab->clear (); | |
2114 } | |
2115 | |
2116 static inline bool | |
2117 do_clear_function (const std::string& nm) | |
2118 { | |
2119 bool b1 = curr_sym_tab->clear_function (nm); | |
2120 | |
2121 bool b2 = fbi_sym_tab->clear_function (nm); | |
2122 | |
2123 return b1 || b2; | |
2124 } | |
2125 | |
2126 static inline bool | |
2127 do_clear_global (const std::string& nm) | |
2128 { | |
2129 bool b1 = curr_sym_tab->clear_global (nm); | |
2130 | |
2131 bool b2 = global_sym_tab->clear_variable (nm); | |
2132 | |
2133 return b1 || b2; | |
2134 } | |
2135 | |
2136 static inline bool | |
2137 do_clear_variable (const std::string& nm) | |
2138 { | |
2139 return curr_sym_tab->clear_variable (nm); | |
2140 } | |
2141 | |
2142 static inline bool | |
2143 do_clear_symbol (const std::string& nm) | |
2144 { | |
2145 bool cleared = curr_sym_tab->clear_variable (nm); | |
2146 | |
2147 if (! cleared) | |
2148 cleared = do_clear_function (nm); | |
2149 | |
2150 return cleared; | |
2151 } | |
2152 | |
2153 static inline bool | |
2154 do_clear_function_pattern (const std::string& pat) | |
2155 { | |
2156 bool b1 = curr_sym_tab->clear_function_pattern (pat); | |
2157 | |
2158 bool b2 = fbi_sym_tab->clear_function_pattern (pat); | |
2159 | |
2160 return b1 || b2; | |
2161 } | |
2162 | |
2163 static inline bool | |
2164 do_clear_global_pattern (const std::string& pat) | |
2165 { | |
2166 bool b1 = curr_sym_tab->clear_global_pattern (pat); | |
2167 | |
2168 bool b2 = global_sym_tab->clear_variable_pattern (pat); | |
2169 | |
2170 return b1 || b2; | |
2171 } | |
2172 | |
2173 static inline bool | |
2174 do_clear_variable_pattern (const std::string& pat) | |
2175 { | |
2176 return curr_sym_tab->clear_variable_pattern (pat); | |
2177 } | |
2178 | |
2179 static inline bool | |
2180 do_clear_symbol_pattern (const std::string& pat) | |
2181 { | |
5775 | 2182 // FIXME -- if we have a variable v1 and a function v2 and |
4009 | 2183 // someone says clear v*, we will clear the variable but not the |
2184 // function. Is that really what should happen? (I think it is | |
2185 // what Matlab does.) | |
2186 | |
2187 bool cleared = curr_sym_tab->clear_variable_pattern (pat); | |
2188 | |
2189 if (! cleared) | |
2190 cleared = do_clear_function_pattern (pat); | |
2191 | |
2192 return cleared; | |
2193 } | |
2194 | |
2195 static inline void | |
2196 do_clear_functions (const string_vector& argv, int argc, int idx, | |
2197 bool exclusive = false) | |
2198 { | |
2199 if (idx == argc) | |
2200 do_clear_functions (); | |
2201 else | |
2202 { | |
2203 if (exclusive) | |
2204 { | |
2205 string_vector lfcns = curr_sym_tab->user_function_name_list (); | |
2206 | |
2207 int lcount = lfcns.length (); | |
2208 | |
2209 for (int i = 0; i < lcount; i++) | |
2210 { | |
2211 std::string nm = lfcns[i]; | |
2212 | |
2213 if (! name_matches_any_pattern (nm, argv, argc, idx)) | |
2214 do_clear_function (nm); | |
2215 } | |
2216 | |
2217 string_vector fcns = fbi_sym_tab->user_function_name_list (); | |
2218 | |
2219 int fcount = fcns.length (); | |
2220 | |
2221 for (int i = 0; i < fcount; i++) | |
2222 { | |
2223 std::string nm = fcns[i]; | |
2224 | |
2225 if (! name_matches_any_pattern (nm, argv, argc, idx)) | |
2226 do_clear_function (nm); | |
2227 } | |
2228 } | |
2229 else | |
2230 { | |
2231 while (idx < argc) | |
2232 do_clear_function_pattern (argv[idx++]); | |
2233 } | |
2234 } | |
2235 } | |
2236 | |
2237 static inline void | |
2238 do_clear_globals (const string_vector& argv, int argc, int idx, | |
2239 bool exclusive = false) | |
2240 { | |
2241 if (idx == argc) | |
2242 do_clear_globals (); | |
2243 else | |
2244 { | |
2245 if (exclusive) | |
2246 { | |
2247 string_vector lvars = curr_sym_tab->global_variable_name_list (); | |
2248 | |
2249 int lcount = lvars.length (); | |
2250 | |
2251 for (int i = 0; i < lcount; i++) | |
2252 { | |
2253 std::string nm = lvars[i]; | |
2254 | |
2255 if (! name_matches_any_pattern (nm, argv, argc, idx)) | |
2256 do_clear_global (nm); | |
2257 } | |
2258 | |
2259 string_vector gvars = global_sym_tab->global_variable_name_list (); | |
2260 | |
2261 int gcount = gvars.length (); | |
2262 | |
2263 for (int i = 0; i < gcount; i++) | |
2264 { | |
2265 std::string nm = gvars[i]; | |
2266 | |
2267 if (! name_matches_any_pattern (nm, argv, argc, idx)) | |
2268 do_clear_global (nm); | |
2269 } | |
2270 } | |
2271 else | |
2272 { | |
2273 while (idx < argc) | |
2274 do_clear_global_pattern (argv[idx++]); | |
2275 } | |
2276 } | |
2277 } | |
2278 | |
2279 static inline void | |
2280 do_clear_variables (const string_vector& argv, int argc, int idx, | |
2281 bool exclusive = false) | |
2282 { | |
2283 if (idx == argc) | |
2284 do_clear_variables (); | |
2285 else | |
2286 { | |
2287 if (exclusive) | |
2288 { | |
2289 string_vector lvars = curr_sym_tab->variable_name_list (); | |
2290 | |
2291 int lcount = lvars.length (); | |
2292 | |
2293 for (int i = 0; i < lcount; i++) | |
2294 { | |
2295 std::string nm = lvars[i]; | |
2296 | |
2297 if (! name_matches_any_pattern (nm, argv, argc, idx)) | |
2298 do_clear_variable (nm); | |
2299 } | |
2300 } | |
2301 else | |
2302 { | |
2303 while (idx < argc) | |
2304 do_clear_variable_pattern (argv[idx++]); | |
2305 } | |
2306 } | |
2307 } | |
2308 | |
2309 static inline void | |
2310 do_clear_symbols (const string_vector& argv, int argc, int idx, | |
2311 bool exclusive = false) | |
2312 { | |
2313 if (idx == argc) | |
2314 do_clear_variables (); | |
2315 else | |
2316 { | |
2317 if (exclusive) | |
2318 { | |
5775 | 2319 // FIXME -- is this really what we want, or do we |
4009 | 2320 // somehow want to only clear the functions that are not |
2321 // shadowed by local variables? It seems that would be a | |
2322 // bit harder to do. | |
2323 | |
2324 do_clear_variables (argv, argc, idx, exclusive); | |
2325 do_clear_functions (argv, argc, idx, exclusive); | |
2326 } | |
2327 else | |
2328 { | |
2329 while (idx < argc) | |
2330 do_clear_symbol_pattern (argv[idx++]); | |
2331 } | |
2332 } | |
2333 } | |
2334 | |
2335 static void | |
2336 do_matlab_compatible_clear (const string_vector& argv, int argc, int idx) | |
2337 { | |
2338 // This is supposed to be mostly Matlab compatible. | |
2339 | |
2340 for (; idx < argc; idx++) | |
2341 { | |
2342 if (argv[idx] == "all" && ! is_local_variable ("all")) | |
2343 { | |
2344 do_clear_all (); | |
2345 } | |
2346 else if (argv[idx] == "functions" && ! is_local_variable ("functions")) | |
2347 { | |
2348 do_clear_functions (argv, argc, ++idx); | |
2349 } | |
2350 else if (argv[idx] == "global" && ! is_local_variable ("global")) | |
2351 { | |
2352 do_clear_globals (argv, argc, ++idx); | |
2353 } | |
2354 else if (argv[idx] == "variables" && ! is_local_variable ("variables")) | |
2355 { | |
2356 do_clear_variables (); | |
2357 } | |
2358 else | |
2359 { | |
2360 do_clear_symbol_pattern (argv[idx]); | |
2361 } | |
2362 } | |
2363 } | |
2364 | |
2365 #define CLEAR_OPTION_ERROR(cond) \ | |
2366 do \ | |
2367 { \ | |
2368 if (cond) \ | |
2369 { \ | |
5823 | 2370 print_usage (); \ |
4009 | 2371 return retval; \ |
2372 } \ | |
2373 } \ | |
2374 while (0) | |
2375 | |
4954 | 2376 bool |
2377 clear_function (const std::string& nm) | |
2378 { | |
2379 return do_clear_function (nm); | |
2380 } | |
2381 | |
4988 | 2382 bool |
2383 clear_variable (const std::string& nm) | |
2384 { | |
2385 return do_clear_variable (nm); | |
2386 } | |
2387 | |
2388 bool | |
2389 clear_symbol (const std::string& nm) | |
2390 { | |
2391 return do_clear_symbol (nm); | |
2392 } | |
2393 | |
4208 | 2394 DEFCMD (clear, args, , |
3361 | 2395 "-*- texinfo -*-\n\ |
11630 | 2396 @deffn {Command} clear [options] pattern @dots{}\n\ |
3361 | 2397 Delete the names matching the given patterns from the symbol table. The\n\ |
2398 pattern may contain the following special characters:\n\ | |
4016 | 2399 \n\ |
3361 | 2400 @table @code\n\ |
2401 @item ?\n\ | |
2402 Match any single character.\n\ | |
668 | 2403 \n\ |
3361 | 2404 @item *\n\ |
2405 Match zero or more characters.\n\ | |
2406 \n\ | |
2407 @item [ @var{list} ]\n\ | |
2408 Match the list of characters specified by @var{list}. If the first\n\ | |
2409 character is @code{!} or @code{^}, match all characters except those\n\ | |
2410 specified by @var{list}. For example, the pattern @samp{[a-zA-Z]} will\n\ | |
2411 match all lower and upper case alphabetic characters.\n\ | |
2412 @end table\n\ | |
2413 \n\ | |
2414 For example, the command\n\ | |
593 | 2415 \n\ |
3361 | 2416 @example\n\ |
2417 clear foo b*r\n\ | |
2418 @end example\n\ | |
2419 \n\ | |
2420 @noindent\n\ | |
2421 clears the name @code{foo} and all names that begin with the letter\n\ | |
2422 @code{b} and end with the letter @code{r}.\n\ | |
668 | 2423 \n\ |
3361 | 2424 If @code{clear} is called without any arguments, all user-defined\n\ |
2425 variables (local and global) are cleared from the symbol table. If\n\ | |
2426 @code{clear} is called with at least one argument, only the visible\n\ | |
2427 names matching the arguments are cleared. For example, suppose you have\n\ | |
2428 defined a function @code{foo}, and then hidden it by performing the\n\ | |
2429 assignment @code{foo = 2}. Executing the command @kbd{clear foo} once\n\ | |
2430 will clear the variable definition and restore the definition of\n\ | |
2431 @code{foo} as a function. Executing @kbd{clear foo} a second time will\n\ | |
2432 clear the function definition.\n\ | |
2433 \n\ | |
11630 | 2434 The following options are available in both long and short form\n\ |
2435 @table @code\n\ | |
2436 @item -all, -a\n\ | |
2437 Clears all local and global user-defined variables and all functions\n\ | |
2438 from the symbol table.\n\ | |
2439 \n\ | |
2440 @item -exclusive, -x\n\ | |
2441 Clears the variables that don't match the following pattern.\n\ | |
2442 \n\ | |
2443 @item -functions, -f\n\ | |
2444 Clears the function names and the built-in symbols names.\n\ | |
2445 @item -global, -g\n\ | |
2446 Clears the global symbol names.\n\ | |
2447 @item -variables, -v\n\ | |
2448 Clears the local variable names.\n\ | |
2449 @end table\n\ | |
2450 With the execption of @code{exclusive}, all long options can be used \n\ | |
2451 without the dash as well.\n\ | |
3361 | 2452 @end deffn") |
529 | 2453 { |
2086 | 2454 octave_value_list retval; |
593 | 2455 |
1755 | 2456 int argc = args.length () + 1; |
593 | 2457 |
1968 | 2458 string_vector argv = args.make_argv ("clear"); |
1755 | 2459 |
4009 | 2460 if (! error_state) |
529 | 2461 { |
4009 | 2462 if (argc == 1) |
593 | 2463 { |
4009 | 2464 do_clear_variables (); |
3681 | 2465 } |
2466 else | |
2467 { | |
4009 | 2468 int idx = 0; |
2469 | |
2470 bool clear_all = false; | |
2471 bool clear_functions = false; | |
2472 bool clear_globals = false; | |
2473 bool clear_variables = false; | |
2474 bool exclusive = false; | |
2475 bool have_dash_option = false; | |
3681 | 2476 |
4009 | 2477 while (++idx < argc) |
2478 { | |
4010 | 2479 if (argv[idx] == "-all" || argv[idx] == "-a") |
593 | 2480 { |
4009 | 2481 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive); |
3681 | 2482 |
4009 | 2483 have_dash_option = true; |
2484 clear_all = true; | |
2485 } | |
4010 | 2486 else if (argv[idx] == "-exclusive" || argv[idx] == "-x") |
4009 | 2487 { |
2488 have_dash_option = true; | |
2489 exclusive = true; | |
2490 } | |
4010 | 2491 else if (argv[idx] == "-functions" || argv[idx] == "-f") |
4009 | 2492 { |
2493 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive); | |
3681 | 2494 |
4009 | 2495 have_dash_option = true; |
2496 clear_functions = true; | |
2497 } | |
4010 | 2498 else if (argv[idx] == "-global" || argv[idx] == "-g") |
4009 | 2499 { |
2500 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive); | |
2501 | |
2502 have_dash_option = true; | |
2503 clear_globals = true; | |
2504 } | |
4010 | 2505 else if (argv[idx] == "-variables" || argv[idx] == "-v") |
4009 | 2506 { |
2507 CLEAR_OPTION_ERROR (have_dash_option && ! exclusive); | |
3681 | 2508 |
4009 | 2509 have_dash_option = true; |
2510 clear_variables = true; | |
2511 } | |
2512 else | |
2513 break; | |
2514 } | |
3681 | 2515 |
4224 | 2516 if (idx <= argc) |
4009 | 2517 { |
2518 if (! have_dash_option) | |
2519 { | |
2520 do_matlab_compatible_clear (argv, argc, idx); | |
2521 } | |
2522 else | |
2523 { | |
2524 if (clear_all) | |
3681 | 2525 { |
4009 | 2526 maybe_warn_exclusive (exclusive); |
3681 | 2527 |
4009 | 2528 if (++idx < argc) |
2529 warning | |
4010 | 2530 ("clear: ignoring extra arguments after -all"); |
3681 | 2531 |
4009 | 2532 curr_sym_tab->clear (); |
2533 fbi_sym_tab->clear_functions (); | |
2534 global_sym_tab->clear (); | |
2535 } | |
2536 else if (clear_functions) | |
2537 { | |
2538 do_clear_functions (argv, argc, idx, exclusive); | |
2539 } | |
2540 else if (clear_globals) | |
593 | 2541 { |
4009 | 2542 do_clear_globals (argv, argc, idx, exclusive); |
2543 } | |
2544 else if (clear_variables) | |
2545 { | |
2546 do_clear_variables (argv, argc, idx, exclusive); | |
2547 } | |
2548 else | |
2549 { | |
2550 do_clear_symbols (argv, argc, idx, exclusive); | |
593 | 2551 } |
2552 } | |
2553 } | |
2554 } | |
2555 } | |
2556 | |
2557 return retval; | |
529 | 2558 } |
2559 | |
3933 | 2560 DEFUN (__print_symtab_info__, args, , |
3446 | 2561 "-*- texinfo -*-\n\ |
3933 | 2562 @deftypefn {Built-in Function} {} __print_symtab_info__ ()\n\ |
6945 | 2563 Undocumented internal function.\n\ |
3446 | 2564 @end deftypefn") |
3005 | 2565 { |
2566 octave_value_list retval; | |
2567 | |
2568 int nargin = args.length (); | |
2569 | |
2570 if (nargin == 1) | |
2571 { | |
3523 | 2572 std::string arg = args(0).string_value (); |
3005 | 2573 |
4009 | 2574 if (arg == "fbi") |
2575 fbi_sym_tab->print_info (octave_stdout); | |
2576 else if (arg == "global") | |
3933 | 2577 global_sym_tab->print_info (octave_stdout); |
2578 else if (arg == "top-level") | |
2579 top_level_sym_tab->print_info (octave_stdout); | |
3005 | 2580 else |
3933 | 2581 { |
4009 | 2582 symbol_record *fsr = fbi_sym_tab->lookup (arg, true); |
3933 | 2583 |
4009 | 2584 if (fsr && fsr->is_user_function ()) |
3933 | 2585 { |
4009 | 2586 octave_value tmp = fsr->def (); |
5759 | 2587 const octave_base_value& rep = tmp.get_rep (); |
3933 | 2588 |
2589 const octave_user_function& fcn | |
5759 | 2590 = dynamic_cast<const octave_user_function&> (rep); |
3933 | 2591 |
2592 fcn.print_symtab_info (octave_stdout); | |
2593 } | |
2594 else | |
2595 error ("no user-defined function named %s", arg.c_str ()); | |
2596 } | |
3005 | 2597 } |
2598 else if (nargin == 0) | |
3933 | 2599 curr_sym_tab->print_info (octave_stdout); |
3005 | 2600 else |
5823 | 2601 print_usage (); |
3005 | 2602 |
2603 return retval; | |
2604 } | |
2605 | |
3933 | 2606 DEFUN (__print_symbol_info__, args, , |
3446 | 2607 "-*- texinfo -*-\n\ |
2608 @deftypefn {Built-in Function} {} __dump_symbol_info__ (@var{name})\n\ | |
6945 | 2609 Undocumented internal function.\n\ |
3446 | 2610 @end deftypefn") |
3239 | 2611 { |
2612 octave_value_list retval; | |
2613 | |
2614 int nargin = args.length (); | |
2615 | |
2616 if (nargin == 1) | |
2617 { | |
3523 | 2618 std::string symbol_name = args(0).string_value (); |
3239 | 2619 |
2620 if (! error_state) | |
2621 { | |
2622 symbol_record *sr = curr_sym_tab->lookup (symbol_name); | |
2623 | |
2624 if (sr) | |
3933 | 2625 sr->print_info (octave_stdout); |
3239 | 2626 else |
3933 | 2627 error ("__print_symbol_info__: symbol %s not found", |
3239 | 2628 symbol_name.c_str ()); |
2629 } | |
2630 else | |
5823 | 2631 print_usage (); |
3239 | 2632 } |
2633 else | |
5823 | 2634 print_usage (); |
3239 | 2635 |
2636 return retval; | |
2637 } | |
2638 | |
5794 | 2639 DEFUN (ignore_function_time_stamp, args, nargout, |
3372 | 2640 "-*- texinfo -*-\n\ |
5794 | 2641 @deftypefn {Built-in Function} {@var{val} =} ignore_function_time_stamp ()\n\ |
2642 @deftypefnx {Built-in Function} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})\n\ | |
2643 Query or set the internal variable that controls whether Octave checks\n\ | |
2644 the time stamp on files each time it looks up functions defined in\n\ | |
2645 function files. If the internal variable is set to @code{\"system\"},\n\ | |
2646 Octave will not automatically recompile function files in subdirectories of\n\ | |
3371 | 2647 @file{@var{octave-home}/lib/@var{version}} if they have changed since\n\ |
2648 they were last compiled, but will recompile other function files in the\n\ | |
5814 | 2649 search path if they change. If set to @code{\"all\"}, Octave will not\n\ |
3371 | 2650 recompile any function files unless their definitions are removed with\n\ |
5794 | 2651 @code{clear}. If set to \"none\", Octave will always check time stamps\n\ |
2652 on files to determine whether functions defined in function files\n\ | |
7001 | 2653 need to be recompiled.\n\ |
5794 | 2654 @end deftypefn") |
2655 { | |
2656 octave_value retval; | |
2657 | |
2658 if (nargout > 0) | |
2659 { | |
2660 switch (Vignore_function_time_stamp) | |
2661 { | |
2662 case 1: | |
2663 retval = "system"; | |
2664 break; | |
2665 | |
2666 case 2: | |
2667 retval = "all"; | |
2668 break; | |
2669 | |
2670 default: | |
2671 retval = "none"; | |
2672 break; | |
2673 } | |
2674 } | |
2675 | |
2676 int nargin = args.length (); | |
2677 | |
2678 if (nargin == 1) | |
2679 { | |
2680 std::string sval = args(0).string_value (); | |
2681 | |
2682 if (! error_state) | |
2683 { | |
2684 if (sval == "all") | |
2685 Vignore_function_time_stamp = 2; | |
2686 else if (sval == "system") | |
2687 Vignore_function_time_stamp = 1; | |
2688 else if (sval == "none") | |
2689 Vignore_function_time_stamp = 0; | |
2690 else | |
2691 error ("ignore_function_time_stamp: expecting argument to be \"all\", \"system\", or \"none\""); | |
2692 } | |
2693 else | |
2694 error ("ignore_function_time_stamp: expecting argument to be character string"); | |
2695 } | |
2696 else if (nargin > 1) | |
5823 | 2697 print_usage (); |
5794 | 2698 |
2699 return retval; | |
3016 | 2700 } |
2701 | |
1 | 2702 /* |
2703 ;;; Local Variables: *** | |
2704 ;;; mode: C++ *** | |
2705 ;;; End: *** | |
2706 */ |