GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
symtab.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2013 John W. Eaton
4 Copyright (C) 2009 VZLU Prague
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
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
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
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if !defined (octave_symtab_h)
25 #define octave_symtab_h 1
26 
27 #include <deque>
28 #include <list>
29 #include <map>
30 #include <set>
31 #include <string>
32 
33 #include "glob-match.h"
34 #include "lo-regexp.h"
35 
36 class tree_argument_list;
38 
39 #include "oct-obj.h"
40 #include "workspace-element.h"
41 #include "oct-refcount.h"
42 #include "ov.h"
43 
44 class
47 {
48 public:
49 
50  typedef int scope_id;
51  typedef size_t context_id;
52 
53  class
55  {
56  protected:
57 
58  typedef std::set<scope_id>::iterator set_iterator;
59  typedef std::set<scope_id>::const_iterator set_const_iterator;
60 
61  // We start with 2 because we allocate 0 for the global symbols
62  // and 1 for the top-level workspace.
63 
64  scope_id_cache (void) : next_available (2), in_use (), free_list () { }
65 
66  public:
67 
68  ~scope_id_cache (void) { }
69 
70  static scope_id alloc (void)
71  {
72  return instance_ok () ? instance->do_alloc () : -1;
73  }
74 
75  static void free (scope_id scope)
76  {
77  if (instance_ok ())
78  return instance->do_free (scope);
79  }
80 
81  static std::list<scope_id> scopes (void)
82  {
83  return instance_ok () ? instance->do_scopes () : std::list<scope_id> ();
84  }
85 
86  static void create_instance (void);
87 
88  static bool instance_ok (void)
89  {
90  bool retval = true;
91 
92  if (! instance)
93  create_instance ();
94 
95  if (! instance)
96  {
97  ::error ("unable to create scope_id_cache object!");
98 
99  retval = false;
100  }
101 
102  return retval;
103  }
104 
105  private:
106 
107  // No copying!
108 
110 
112 
114 
115  static void cleanup_instance (void) { delete instance; instance = 0; }
116 
117  // The next available scope not in the free list.
118  scope_id next_available;
119 
120  // The set of scope IDs that are currently allocated.
121  std::set<scope_id> in_use;
122 
123  // The set of scope IDs that are currently available.
124  std::set<scope_id> free_list;
125 
126  scope_id do_alloc (void)
127  {
128  scope_id retval;
129 
130  set_iterator p = free_list.begin ();
131 
132  if (p != free_list.end ())
133  {
134  retval = *p;
135  free_list.erase (p);
136  }
137  else
138  retval = next_available++;
139 
140  in_use.insert (retval);
141 
142  return retval;
143  }
144 
145  void do_free (scope_id scope)
146  {
147  set_iterator p = in_use.find (scope);
148 
149  if (p != in_use.end ())
150  {
151  in_use.erase (p);
152  free_list.insert (scope);
153  }
154  else
155  error ("free_scope: scope %d not found!", scope);
156  }
157 
158  std::list<scope_id> do_scopes (void) const
159  {
160  std::list<scope_id> retval;
161 
162  for (set_const_iterator p = in_use.begin (); p != in_use.end (); p++)
163  retval.push_back (*p);
164 
165  retval.sort ();
166 
167  return retval;
168  }
169  };
170 
171  class fcn_info;
172 
173  class
175  {
176  public:
177 
178  // generic variable
179  static const unsigned int local = 1;
180 
181  // varargin, argn, .nargin., .nargout.
182  // (FIXME -- is this really used now?)
183  static const unsigned int automatic = 2;
184 
185  // formal parameter
186  static const unsigned int formal = 4;
187 
188  // not listed or cleared (.nargin., .nargout.)
189  static const unsigned int hidden = 8;
190 
191  // inherited from parent scope; not cleared at function exit
192  static const unsigned int inherited = 16;
193 
194  // global (redirects to global scope)
195  static const unsigned int global = 32;
196 
197  // not cleared at function exit
198  static const unsigned int persistent = 64;
199 
200  // this symbol may NOT become a variable.
201  // (symbol added to a static workspace)
202  static const unsigned int added_static = 128;
203 
204  private:
205 
206  class
208  {
209  public:
210 
211  symbol_record_rep (scope_id s, const std::string& nm,
212  const octave_value& v, unsigned int sc)
213  : decl_scope (s), curr_fcn (0), name (nm), value_stack (),
214  storage_class (sc), finfo (), valid (true), count (1)
215  {
216  value_stack.push_back (v);
217  }
218 
219  void assign (const octave_value& value,
220  context_id context = xdefault_context)
221  {
222  varref (context) = value;
223  }
224 
225  void assign (octave_value::assign_op op,
226  const std::string& type,
227  const std::list<octave_value_list>& idx,
228  const octave_value& value,
229  context_id context = xdefault_context)
230  {
231  varref(context).assign (op, type, idx, value);
232  }
233 
234  void assign (octave_value::assign_op op, const octave_value& value,
235  context_id context = xdefault_context)
236  {
237  varref(context).assign (op, value);
238  }
239 
240  void do_non_const_unary_op (octave_value::unary_op op,
241  context_id context = xdefault_context)
242  {
243  varref(context).do_non_const_unary_op (op);
244  }
245 
246  void do_non_const_unary_op (octave_value::unary_op op,
247  const std::string& type,
248  const std::list<octave_value_list>& idx,
249  context_id context = xdefault_context)
250  {
251  varref(context).do_non_const_unary_op (op, type, idx);
252  }
253 
254  octave_value& varref (context_id context = xdefault_context)
255  {
256  // We duplicate global_varref and persistent_varref here to
257  // avoid calling deprecated functions.
258 
259  if (is_global ())
260  {
262  = symbol_table::global_table.find (name);
263 
264  return (p == symbol_table::global_table.end ())
265  ? symbol_table::global_table[name] : p->second;
266  }
267  else if (is_persistent ())
268  {
269  static octave_value foobar;
270 
271  symbol_table *inst
273 
274  return inst ? inst->do_persistent_varref (name) : foobar;
275  }
276  else
277  {
278  if (context == xdefault_context)
279  context = active_context ();
280 
281  context_id n = value_stack.size ();
282  while (n++ <= context)
283  value_stack.push_back (octave_value ());
284 
285  return value_stack[context];
286  }
287  }
288 
289  octave_value varval (context_id context = xdefault_context) const
290  {
291  if (is_global ())
292  return symbol_table::global_varval (name);
293  else if (is_persistent ())
294  return symbol_table::persistent_varval (name);
295  else
296  {
297  if (context == xdefault_context)
298  context = active_context ();
299 
300  if (context < value_stack.size ())
301  return value_stack[context];
302  else
303  return octave_value ();
304  }
305  }
306 
307  void push_context (scope_id s)
308  {
309  if (! (is_persistent () || is_global ())
310  && s == scope ())
311  value_stack.push_back (octave_value ());
312  }
313 
314  // If pop_context returns 0, we are out of values and this element
315  // of the symbol table should be deleted. This can happen for
316  // functions like
317  //
318  // function foo (n)
319  // if (n > 0)
320  // foo (n-1);
321  // else
322  // eval ("x = 1");
323  // endif
324  // endfunction
325  //
326  // Here, X should only exist in the final stack frame.
327 
328  size_t pop_context (scope_id s)
329  {
330  size_t retval = 1;
331 
332  if (! (is_persistent () || is_global ())
333  && s == scope ())
334  {
335  value_stack.pop_back ();
336  retval = value_stack.size ();
337  }
338 
339  return retval;
340  }
341 
342  void clear (void) { clear (scope ()); }
343 
344  void clear (scope_id s)
345  {
346  if (! (is_hidden () || is_inherited ())
347  && s == scope ())
348  {
349  if (is_global ())
350  unmark_global ();
351 
352  if (is_persistent ())
353  {
354  symbol_table::persistent_assign (name, varval ());
355 
356  unmark_persistent ();
357  }
358 
359  assign (octave_value ());
360  }
361  }
362 
363  bool is_defined (context_id context = xdefault_context) const
364  {
365  if (context == xdefault_context)
366  context = active_context ();
367 
368  return varval (context).is_defined ();
369  }
370 
371  bool is_valid (void) const
372  {
373  return valid;
374  }
375 
376  bool is_variable (context_id context) const
377  {
378  if (context == xdefault_context)
379  context = active_context ();
380 
381  return (! is_local () || is_defined (context));
382  }
383 
384  bool is_local (void) const { return storage_class & local; }
385  bool is_automatic (void) const { return storage_class & automatic; }
386  bool is_formal (void) const { return storage_class & formal; }
387  bool is_hidden (void) const { return storage_class & hidden; }
388  bool is_inherited (void) const { return storage_class & inherited; }
389  bool is_global (void) const { return storage_class & global; }
390  bool is_persistent (void) const { return storage_class & persistent; }
391  bool is_added_static (void) const {return storage_class & added_static; }
392 
393  void mark_local (void) { storage_class |= local; }
394  void mark_automatic (void) { storage_class |= automatic; }
395  void mark_formal (void) { storage_class |= formal; }
396  void mark_hidden (void) { storage_class |= hidden; }
397  void mark_inherited (void) { storage_class |= inherited; }
398  void mark_global (void)
399  {
400  if (is_persistent ())
401  error ("can't make persistent variable %s global", name.c_str ());
402  else
403  storage_class |= global;
404  }
405  void mark_persistent (void)
406  {
407  if (is_global ())
408  error ("can't make global variable %s persistent", name.c_str ());
409  else
410  storage_class |= persistent;
411  }
412  void mark_added_static (void) { storage_class |= added_static; }
413 
414  void unmark_local (void) { storage_class &= ~local; }
415  void unmark_automatic (void) { storage_class &= ~automatic; }
416  void unmark_formal (void) { storage_class &= ~formal; }
417  void unmark_hidden (void) { storage_class &= ~hidden; }
418  void unmark_inherited (void) { storage_class &= ~inherited; }
419  void unmark_global (void) { storage_class &= ~global; }
420  void unmark_persistent (void) { storage_class &= ~persistent; }
421  void unmark_added_static (void) { storage_class &= ~added_static; }
422 
423  void init_persistent (void)
424  {
425  if (! is_defined ())
426  {
427  mark_persistent ();
428 
429  assign (symbol_table::persistent_varval (name));
430  }
431  // FIXME: this causes trouble with recursive calls.
432  // else
433  // error ("unable to declare existing variable persistent");
434  }
435 
436  void invalidate (void)
437  {
438  valid = false;
439  }
440 
441  void erase_persistent (void)
442  {
443  unmark_persistent ();
445  }
446 
447  OCTINTERP_API context_id active_context (void) const;
448 
449  scope_id scope (void) const { return decl_scope; }
450 
451  void set_curr_fcn (octave_user_function *fcn)
452  {
453  curr_fcn = fcn;
454  }
455 
456  symbol_record_rep *dup (scope_id new_scope) const
457  {
458  return new symbol_record_rep (new_scope, name, varval (),
459  storage_class);
460  }
461 
462  void dump (std::ostream& os, const std::string& prefix) const;
463 
464  scope_id decl_scope;
465 
467 
468  std::string name;
469 
470  std::deque<octave_value> value_stack;
471 
472  unsigned int storage_class;
473 
475 
476  bool valid;
477 
479 
480  private:
481 
482  // No copying!
483 
485 
486  symbol_record_rep& operator = (const symbol_record_rep&);
487  };
488 
489  public:
490 
491  symbol_record (scope_id s = xcurrent_scope,
492  const std::string& nm = std::string (),
493  const octave_value& v = octave_value (),
494  unsigned int sc = local)
495  : rep (new symbol_record_rep (s, nm, v, sc)) { }
496 
498  : rep (sr.rep)
499  {
500  rep->count++;
501  }
502 
503  symbol_record& operator = (const symbol_record& sr)
504  {
505  if (this != &sr)
506  {
507  if (--rep->count == 0)
508  delete rep;
509 
510  rep = sr.rep;
511  rep->count++;
512  }
513 
514  return *this;
515  }
516 
518  {
519  if (--rep->count == 0)
520  delete rep;
521  }
522 
523  symbol_record dup (scope_id new_scope) const
524  {
525  return symbol_record (rep->dup (new_scope));
526  }
527 
528  const std::string& name (void) const { return rep->name; }
529 
530  void rename (const std::string& new_name) { rep->name = new_name; }
531 
533  find (const octave_value_list& args = octave_value_list ()) const;
534 
535  void assign (const octave_value& value,
536  context_id context = xdefault_context)
537  {
538  rep->assign (value, context);
539  }
540 
541  void assign (octave_value::assign_op op,
542  const std::string& type,
543  const std::list<octave_value_list>& idx,
544  const octave_value& value,
545  context_id context = xdefault_context)
546  {
547  rep->assign (op, type, idx, value, context);
548  }
549 
550  void assign (octave_value::assign_op op, const octave_value& value,
551  context_id context = xdefault_context)
552  {
553  rep->assign (op, value, context);
554  }
555 
556  void do_non_const_unary_op (octave_value::unary_op op)
557  {
558  rep->do_non_const_unary_op (op);
559  }
560 
561  void do_non_const_unary_op (octave_value::unary_op op,
562  const std::string& type,
563  const std::list<octave_value_list>& idx)
564  {
565  rep->do_non_const_unary_op (op, type, idx);
566  }
567 
568  // Delete when deprecated varref functions are removed.
569  octave_value& varref (context_id context = xdefault_context)
570  {
571  return rep->varref (context);
572  }
573 
574  octave_value varval (context_id context = xdefault_context) const
575  {
576  return rep->varval (context);
577  }
578 
579  void push_context (scope_id s) { rep->push_context (s); }
580 
581  size_t pop_context (scope_id s) { return rep->pop_context (s); }
582 
583  void clear (void) { rep->clear (); }
584 
585  void clear (scope_id s) { rep->clear (s); }
586 
587  bool is_defined (context_id context = xdefault_context) const
588  {
589  return rep->is_defined (context);
590  }
591 
592  bool is_undefined (context_id context = xdefault_context) const
593  {
594  return ! rep->is_defined (context);
595  }
596 
597  bool is_valid (void) const
598  {
599  return rep->is_valid ();
600  }
601 
602  bool is_variable (context_id context = xdefault_context) const
603  {
604  return rep->is_variable (context);
605  }
606 
607  bool is_local (void) const { return rep->is_local (); }
608  bool is_automatic (void) const { return rep->is_automatic (); }
609  bool is_formal (void) const { return rep->is_formal (); }
610  bool is_global (void) const { return rep->is_global (); }
611  bool is_hidden (void) const { return rep->is_hidden (); }
612  bool is_inherited (void) const { return rep->is_inherited (); }
613  bool is_persistent (void) const { return rep->is_persistent (); }
614  bool is_added_static (void) const { return rep->is_added_static (); }
615 
616  void mark_local (void) { rep->mark_local (); }
617  void mark_automatic (void) { rep->mark_automatic (); }
618  void mark_formal (void) { rep->mark_formal (); }
619  void mark_hidden (void) { rep->mark_hidden (); }
620  void mark_inherited (void) { rep->mark_inherited (); }
621  void mark_global (void) { rep->mark_global (); }
622  void mark_persistent (void) { rep->mark_persistent (); }
623  void mark_added_static (void) { rep->mark_added_static (); }
624 
625  void unmark_local (void) { rep->unmark_local (); }
626  void unmark_automatic (void) { rep->unmark_automatic (); }
627  void unmark_formal (void) { rep->unmark_formal (); }
628  void unmark_hidden (void) { rep->unmark_hidden (); }
629  void unmark_inherited (void) { rep->unmark_inherited (); }
630  void unmark_global (void) { rep->unmark_global (); }
631  void unmark_persistent (void) { rep->unmark_persistent (); }
632  void unmark_added_static (void) { rep->unmark_added_static (); }
633 
634  void init_persistent (void) { rep->init_persistent (); }
635 
636  void erase_persistent (void) { rep->erase_persistent (); }
637 
638  void invalidate (void) { rep->invalidate (); }
639 
640  context_id active_context (void) const { return rep->active_context (); }
641 
642  scope_id scope (void) const { return rep->scope (); }
643 
644  unsigned int xstorage_class (void) const { return rep->storage_class; }
645 
646  void set_curr_fcn (octave_user_function *fcn) { rep->set_curr_fcn (fcn); }
647 
648  void
649  dump (std::ostream& os, const std::string& prefix = std::string ()) const
650  {
651  rep->dump (os, prefix);
652  }
653 
654  private:
655 
657 
658  symbol_record (symbol_record_rep *new_rep) : rep (new_rep) { }
659  };
660 
661  // Always access a symbol from the current scope.
662  // Useful for scripts, as they may be executed in more than one scope.
663  class
665  {
666  public:
667 
668  symbol_reference (void) : scope (-1) { }
669 
671  scope_id curr_scope = symbol_table::current_scope ())
672  : scope (curr_scope), sym (record)
673  { }
674 
676  : scope (ref.scope), sym (ref.sym)
677  { }
678 
679  symbol_reference& operator = (const symbol_reference& ref)
680  {
681  if (this != &ref)
682  {
683  scope = ref.scope;
684  sym = ref.sym;
685  }
686  return *this;
687  }
688 
689  bool is_black_hole (void) const { return scope < 0; }
690 
691  // The name is the same regardless of scope.
692  const std::string& name (void) const { return sym.name (); }
693 
694  symbol_record *operator-> (void)
695  {
696  update ();
697  return &sym;
698  }
699 
700  symbol_record *operator-> (void) const
701  {
702  update ();
703  return &sym;
704  }
705 
706  // can be used to place symbol_reference in maps, we don't overload < as
707  // it doesn't make any sense for symbol_reference
708  struct comparator
709  {
710  bool operator ()(const symbol_reference& lhs,
711  const symbol_reference& rhs) const
712  {
713  return lhs.name () < rhs.name ();
714  }
715  };
716  private:
717 
718  void update (void) const
719  {
720  scope_id curr_scope = symbol_table::current_scope ();
721 
722  if (scope != curr_scope || ! sym.is_valid ())
723  {
724  scope = curr_scope;
725  sym = symbol_table::insert (sym.name ());
726  }
727  }
728 
729  mutable scope_id scope;
731  };
732 
733  class
734  fcn_info
735  {
736  public:
737 
738  typedef std::map<std::string, std::string> dispatch_map_type;
739 
740  typedef std::map<scope_id, octave_value>::const_iterator
742  typedef std::map<scope_id, octave_value>::iterator scope_val_iterator;
743 
744  typedef std::map<std::string, octave_value>::const_iterator
746  typedef std::map<std::string, octave_value>::iterator str_val_iterator;
747 
748  typedef dispatch_map_type::const_iterator dispatch_map_const_iterator;
749  typedef dispatch_map_type::iterator dispatch_map_iterator;
750 
751  private:
752 
753  class
755  {
756  public:
757 
758  fcn_info_rep (const std::string& nm)
759  : name (nm), subfunctions (), private_functions (),
760  class_constructors (), class_methods (), dispatch_map (),
761  cmdline_function (), autoload_function (), function_on_path (),
762  built_in_function (), count (1) { }
763 
764  octave_value load_private_function (const std::string& dir_name);
765 
766  octave_value load_class_constructor (void);
767 
768  octave_value load_class_method (const std::string& dispatch_type);
769 
770  octave_value find (const octave_value_list& args, bool local_funcs);
771 
772  octave_value builtin_find (void);
773 
774  octave_value find_method (const std::string& dispatch_type);
775 
776  octave_value find_autoload (void);
777 
778  octave_value find_user_function (void);
779 
780  bool is_user_function_defined (void) const
781  {
782  return function_on_path.is_defined ();
783  }
784 
785  octave_value find_function (const octave_value_list& args,
786  bool local_funcs)
787  {
788  return find (args, local_funcs);
789  }
790 
791  void lock_subfunction (scope_id scope)
792  {
793  scope_val_iterator p = subfunctions.find (scope);
794 
795  if (p != subfunctions.end ())
796  p->second.lock ();
797  }
798 
799  void unlock_subfunction (scope_id scope)
800  {
801  scope_val_iterator p = subfunctions.find (scope);
802 
803  if (p != subfunctions.end ())
804  p->second.unlock ();
805  }
806 
807  std::pair<std::string, octave_value>
808  subfunction_defined_in_scope (scope_id scope) const
809  {
810  scope_val_const_iterator p = subfunctions.find (scope);
811 
812  return p == subfunctions.end ()
813  ? std::pair<std::string, octave_value> ()
814  : std::pair<std::string, octave_value> (name, p->second);
815  }
816 
817  void erase_subfunction (scope_id scope)
818  {
819  scope_val_iterator p = subfunctions.find (scope);
820 
821  if (p != subfunctions.end ())
822  subfunctions.erase (p);
823  }
824 
825  void mark_subfunction_in_scope_as_private (scope_id scope,
826  const std::string& class_name);
827 
828  void install_cmdline_function (const octave_value& f)
829  {
830  cmdline_function = f;
831  }
832 
833  void install_subfunction (const octave_value& f, scope_id scope)
834  {
835  subfunctions[scope] = f;
836  }
837 
838  void install_user_function (const octave_value& f)
839  {
840  function_on_path = f;
841  }
842 
843  void install_built_in_function (const octave_value& f)
844  {
845  built_in_function = f;
846  }
847 
848  template <class T>
849  void
850  clear_map (std::map<T, octave_value>& map, bool force = false)
851  {
852  typename std::map<T, octave_value>::iterator p = map.begin ();
853 
854  while (p != map.end ())
855  {
856  if (force || ! p->second.islocked ())
857  map.erase (p++);
858  else
859  p++;
860  }
861  }
862 
863  void clear_autoload_function (bool force = false)
864  {
865  if (force || ! autoload_function.islocked ())
866  autoload_function = octave_value ();
867  }
868 
869  // We also clear command line functions here, as these are both
870  // "user defined"
871  void clear_user_function (bool force = false)
872  {
873  if (force || ! function_on_path.islocked ())
874  function_on_path = octave_value ();
875 
876  if (force || ! cmdline_function.islocked ())
877  cmdline_function = octave_value ();
878  }
879 
880  void clear_mex_function (void)
881  {
882  if (function_on_path.is_mex_function ())
883  clear_user_function ();
884  }
885 
886  void clear (bool force = false)
887  {
888  clear_map (subfunctions, force);
889  clear_map (private_functions, force);
890  clear_map (class_constructors, force);
891  clear_map (class_methods, force);
892 
893  clear_autoload_function (force);
894  clear_user_function (force);
895  }
896 
897  void add_dispatch (const std::string& type, const std::string& fname)
898  {
899  dispatch_map[type] = fname;
900  }
901 
902  void clear_dispatch (const std::string& type)
903  {
904  dispatch_map_iterator p = dispatch_map.find (type);
905 
906  if (p != dispatch_map.end ())
907  dispatch_map.erase (p);
908  }
909 
910  void print_dispatch (std::ostream& os) const;
911 
912  std::string help_for_dispatch (void) const;
913 
914  dispatch_map_type get_dispatch (void) const { return dispatch_map; }
915 
916  void dump (std::ostream& os, const std::string& prefix) const;
917 
918  std::string name;
919 
920  // Scope id to function object.
921  std::map<scope_id, octave_value> subfunctions;
922 
923  // Directory name to function object.
924  std::map<std::string, octave_value> private_functions;
925 
926  // Class name to function object.
927  std::map<std::string, octave_value> class_constructors;
928 
929  // Dispatch type to function object.
930  std::map<std::string, octave_value> class_methods;
931 
932  // Legacy dispatch map (dispatch type name to function name).
933  dispatch_map_type dispatch_map;
934 
936 
938 
940 
942 
944 
945  private:
946 
947  octave_value xfind (const octave_value_list& args, bool local_funcs);
948 
949  octave_value x_builtin_find (void);
950 
951  // No copying!
952 
953  fcn_info_rep (const fcn_info_rep&);
954 
955  fcn_info_rep& operator = (const fcn_info_rep&);
956  };
957 
958  public:
959 
960  fcn_info (const std::string& nm = std::string ())
961  : rep (new fcn_info_rep (nm)) { }
962 
963  fcn_info (const fcn_info& fi) : rep (fi.rep)
964  {
965  rep->count++;
966  }
967 
968  fcn_info& operator = (const fcn_info& fi)
969  {
970  if (this != &fi)
971  {
972  if (--rep->count == 0)
973  delete rep;
974 
975  rep = fi.rep;
976  rep->count++;
977  }
978 
979  return *this;
980  }
981 
982  ~fcn_info (void)
983  {
984  if (--rep->count == 0)
985  delete rep;
986  }
987 
989  bool local_funcs = true)
990  {
991  return rep->find (args, local_funcs);
992  }
993 
994  octave_value builtin_find (void)
995  {
996  return rep->builtin_find ();
997  }
998 
999  octave_value find_method (const std::string& dispatch_type) const
1000  {
1001  return rep->find_method (dispatch_type);
1002  }
1003 
1004  octave_value find_built_in_function (void) const
1005  {
1006  return rep->built_in_function;
1007  }
1008 
1009  octave_value find_cmdline_function (void) const
1010  {
1011  return rep->cmdline_function;
1012  }
1013 
1014  octave_value find_autoload (void)
1015  {
1016  return rep->find_autoload ();
1017  }
1018 
1019  octave_value find_user_function (void)
1020  {
1021  return rep->find_user_function ();
1022  }
1023 
1024  bool is_user_function_defined (void) const
1025  {
1026  return rep->is_user_function_defined ();
1027  }
1028 
1029  octave_value find_function (const octave_value_list& args
1030  = octave_value_list (),
1031  bool local_funcs = true)
1032  {
1033  return rep->find_function (args, local_funcs);
1034  }
1035 
1036  void lock_subfunction (scope_id scope)
1037  {
1038  rep->lock_subfunction (scope);
1039  }
1040 
1041  void unlock_subfunction (scope_id scope)
1042  {
1043  rep->unlock_subfunction (scope);
1044  }
1045 
1046  std::pair<std::string, octave_value>
1047  subfunction_defined_in_scope (scope_id scope = xcurrent_scope) const
1048  {
1049  return rep->subfunction_defined_in_scope (scope);
1050  }
1051 
1052  void erase_subfunction (scope_id scope)
1053  {
1054  rep->erase_subfunction (scope);
1055  }
1056 
1057  void mark_subfunction_in_scope_as_private (scope_id scope,
1058  const std::string& class_name)
1059  {
1060  rep->mark_subfunction_in_scope_as_private (scope, class_name);
1061  }
1062 
1063  void install_cmdline_function (const octave_value& f)
1064  {
1065  rep->install_cmdline_function (f);
1066  }
1067 
1068  void install_subfunction (const octave_value& f, scope_id scope)
1069  {
1070  rep->install_subfunction (f, scope);
1071  }
1072 
1073  void install_user_function (const octave_value& f)
1074  {
1075  rep->install_user_function (f);
1076  }
1077 
1078  void install_built_in_function (const octave_value& f)
1079  {
1080  rep->install_built_in_function (f);
1081  }
1082 
1083  void clear (bool force = false) { rep->clear (force); }
1084 
1085  void clear_user_function (bool force = false)
1086  {
1087  rep->clear_user_function (force);
1088  }
1089 
1090  void clear_autoload_function (bool force = false)
1091  {
1092  rep->clear_autoload_function (force);
1093  }
1094 
1095  void clear_mex_function (void) { rep->clear_mex_function (); }
1096 
1097  void add_dispatch (const std::string& type, const std::string& fname)
1098  {
1099  rep->add_dispatch (type, fname);
1100  }
1101 
1102  void clear_dispatch (const std::string& type)
1103  {
1104  rep->clear_dispatch (type);
1105  }
1106 
1107  void print_dispatch (std::ostream& os) const
1108  {
1109  rep->print_dispatch (os);
1110  }
1111 
1112  std::string help_for_dispatch (void) const
1113  { return rep->help_for_dispatch (); }
1114 
1115  dispatch_map_type get_dispatch (void) const
1116  {
1117  return rep->get_dispatch ();
1118  }
1119 
1120  void
1121  dump (std::ostream& os, const std::string& prefix = std::string ()) const
1122  {
1123  rep->dump (os, prefix);
1124  }
1125 
1126  private:
1127 
1129  };
1130 
1131  static scope_id global_scope (void) { return xglobal_scope; }
1132  static scope_id top_scope (void) { return xtop_scope; }
1133 
1134  static scope_id current_scope (void) { return xcurrent_scope; }
1135 
1136  static context_id current_context (void) { return xcurrent_context; }
1137 
1138  static scope_id alloc_scope (void) { return scope_id_cache::alloc (); }
1139 
1140  static void set_scope (scope_id scope)
1141  {
1142  if (scope == xglobal_scope)
1143  error ("can't set scope to global");
1144  else if (scope != xcurrent_scope)
1145  {
1146  all_instances_iterator p = all_instances.find (scope);
1147 
1148  if (p == all_instances.end ())
1149  {
1150  symbol_table *inst = new symbol_table (scope);
1151 
1152  if (inst)
1153  all_instances[scope] = instance = inst;
1154  }
1155  else
1156  instance = p->second;
1157 
1158  xcurrent_scope = scope;
1159  xcurrent_context = 0;
1160  }
1161  }
1162 
1163  static void set_scope_and_context (scope_id scope, context_id context)
1164  {
1165  if (scope == xglobal_scope)
1166  error ("can't set scope to global");
1167  else
1168  {
1169  if (scope != xcurrent_scope)
1170  {
1171  all_instances_iterator p = all_instances.find (scope);
1172 
1173  if (p == all_instances.end ())
1174  error ("scope not found!");
1175  else
1176  {
1177  instance = p->second;
1178 
1179  xcurrent_scope = scope;
1180 
1181  xcurrent_context = context;
1182  }
1183  }
1184  else
1185  xcurrent_context = context;
1186  }
1187  }
1188 
1189  static void erase_scope (scope_id scope)
1190  {
1191  assert (scope != xglobal_scope);
1192 
1193  erase_subfunctions_in_scope (scope);
1194 
1195  all_instances_iterator p = all_instances.find (scope);
1196 
1197  if (p != all_instances.end ())
1198  {
1199  delete p->second;
1200 
1201  all_instances.erase (p);
1202 
1203  free_scope (scope);
1204  }
1205  }
1206 
1207  static void erase_subfunctions_in_scope (scope_id scope)
1208  {
1209  for (fcn_table_iterator q = fcn_table.begin (); q != fcn_table.end (); q++)
1210  q->second.erase_subfunction (scope);
1211  }
1212 
1213  static void
1214  mark_subfunctions_in_scope_as_private (scope_id scope,
1215  const std::string& class_name)
1216  {
1217  for (fcn_table_iterator q = fcn_table.begin (); q != fcn_table.end (); q++)
1218  q->second.mark_subfunction_in_scope_as_private (scope, class_name);
1219  }
1220 
1221  static scope_id dup_scope (scope_id scope)
1222  {
1223  scope_id retval = -1;
1224 
1225  symbol_table *inst = get_instance (scope);
1226 
1227  if (inst)
1228  {
1229  scope_id new_scope = alloc_scope ();
1230 
1231  symbol_table *new_symbol_table = new symbol_table (scope);
1232 
1233  if (new_symbol_table)
1234  {
1235  all_instances[new_scope] = new_symbol_table;
1236 
1237  inst->do_dup_scope (*new_symbol_table);
1238 
1239  retval = new_scope;
1240  }
1241  }
1242 
1243  return retval;
1244  }
1245 
1246  static std::list<scope_id> scopes (void)
1247  {
1248  return scope_id_cache::scopes ();
1249  }
1250 
1251  static symbol_record
1252  find_symbol (const std::string& name, scope_id scope = xcurrent_scope)
1253  {
1254  symbol_table *inst = get_instance (scope);
1255 
1256  return inst ? inst->do_find_symbol (name) :
1257  symbol_record (scope);
1258  }
1259 
1260  static void
1261  inherit (scope_id scope, scope_id donor_scope, context_id donor_context)
1262  {
1263  symbol_table *inst = get_instance (scope);
1264 
1265  if (inst)
1266  {
1267  symbol_table *donor_symbol_table = get_instance (donor_scope);
1268 
1269  if (donor_symbol_table)
1270  inst->do_inherit (*donor_symbol_table, donor_context);
1271  }
1272  }
1273 
1274  static bool at_top_level (void) { return xcurrent_scope == xtop_scope; }
1275 
1276  // Find a value corresponding to the given name in the table.
1277  static octave_value
1278  find (const std::string& name,
1279  const octave_value_list& args = octave_value_list (),
1280  bool skip_variables = false,
1281  bool local_funcs = true);
1282 
1283  static octave_value builtin_find (const std::string& name);
1284 
1285  // Insert a new name in the table.
1286  static symbol_record& insert (const std::string& name,
1287  scope_id scope = xcurrent_scope)
1288  {
1289  static symbol_record foobar;
1290 
1291  symbol_table *inst = get_instance (scope);
1292 
1293  return inst ? inst->do_insert (name) : foobar;
1294  }
1295 
1296  static void rename (const std::string& old_name,
1297  const std::string& new_name,
1298  scope_id scope = xcurrent_scope)
1299  {
1300  symbol_table *inst = get_instance (scope);
1301 
1302  if (inst)
1303  inst->do_rename (old_name, new_name);
1304  }
1305 
1306  static void assign (const std::string& name,
1307  const octave_value& value = octave_value (),
1308  scope_id scope = xcurrent_scope,
1309  context_id context = xdefault_context,
1310  bool force_add = false)
1311  {
1312  static octave_value foobar;
1313 
1314  symbol_table *inst = get_instance (scope);
1315 
1316  if (inst)
1317  inst->do_assign (name, value, context, force_add);
1318  }
1319 
1320  // Use assign (name, value, scope, context, force_add) instead.
1321  static octave_value&
1322  varref (const std::string& name, scope_id scope = xcurrent_scope,
1323  context_id context = xdefault_context, bool force_add = false)
1325  {
1326  static octave_value foobar;
1327 
1328  symbol_table *inst = get_instance (scope);
1329 
1330  return inst ? inst->do_varref (name, context, force_add) : foobar;
1331  }
1332 
1333  // Convenience function to simplify
1334  // octave_user_function::bind_automatic_vars
1335 
1336  static void force_assign (const std::string& name,
1337  const octave_value& value = octave_value (),
1338  scope_id scope = xcurrent_scope,
1339  context_id context = xdefault_context)
1340  {
1341  assign (name, value, scope, context, true);
1342  }
1343 
1344  // Use force_assign (name, value, scope, context) instead.
1345  static octave_value&
1346  force_varref (const std::string& name, scope_id scope = xcurrent_scope,
1347  context_id context = xdefault_context) GCC_ATTR_DEPRECATED
1348  {
1349  static octave_value foobar;
1350 
1351  symbol_table *inst = get_instance (scope);
1352 
1353  return inst ? inst->do_varref (name, context, true) : foobar;
1354  }
1355 
1356  static octave_value varval (const std::string& name,
1357  scope_id scope = xcurrent_scope,
1358  context_id context = xdefault_context)
1359  {
1360  symbol_table *inst = get_instance (scope);
1361 
1362  return inst ? inst->do_varval (name, context) : octave_value ();
1363  }
1364 
1365  static void
1366  global_assign (const std::string& name,
1367  const octave_value& value = octave_value ())
1368 
1369  {
1370  global_table_iterator p = global_table.find (name);
1371 
1372  if (p == global_table.end ())
1373  global_table[name] = value;
1374  else
1375  p->second = value;
1376  }
1377 
1378  // Use global_assign (name, value) instead.
1379  static octave_value&
1380  global_varref (const std::string& name) GCC_ATTR_DEPRECATED
1381 
1382  {
1383  global_table_iterator p = global_table.find (name);
1384 
1385  return (p == global_table.end ()) ? global_table[name] : p->second;
1386  }
1387 
1388  static octave_value
1389  global_varval (const std::string& name)
1390  {
1391  global_table_const_iterator p = global_table.find (name);
1392 
1393  return (p != global_table.end ()) ? p->second : octave_value ();
1394  }
1395 
1396  static void
1397  top_level_assign (const std::string& name,
1398  const octave_value& value = octave_value ())
1399  {
1400  assign (name, value, top_scope (), 0);
1401  }
1402 
1403  // Use top_level_assign (name, value) instead.
1404  static octave_value&
1405  top_level_varref (const std::string& name) GCC_ATTR_DEPRECATED
1406  {
1407  static octave_value foobar;
1408 
1409  symbol_table *inst = get_instance (top_scope ());
1410 
1411  return inst ? inst->do_varref (name, 0, true) : foobar;
1412  }
1413 
1414  static octave_value
1415  top_level_varval (const std::string& name)
1416  {
1417  return varval (name, top_scope (), 0);
1418  }
1419 
1420  static void
1421  persistent_assign (const std::string& name,
1422  const octave_value& value = octave_value ())
1423  {
1424  symbol_table *inst = get_instance (xcurrent_scope);
1425 
1426  if (inst)
1427  inst->do_persistent_assign (name, value);
1428  }
1429 
1430  // Use persistent_assign (name, value) instead.
1431  static octave_value& persistent_varref (const std::string& name)
1433  {
1434  static octave_value foobar;
1435 
1436  symbol_table *inst = get_instance (xcurrent_scope);
1437 
1438  return inst ? inst->do_persistent_varref (name) : foobar;
1439  }
1440 
1441  static octave_value persistent_varval (const std::string& name)
1442  {
1443  symbol_table *inst = get_instance (xcurrent_scope);
1444 
1445  return inst ? inst->do_persistent_varval (name) : octave_value ();
1446  }
1447 
1448  static void erase_persistent (const std::string& name)
1449  {
1450  symbol_table *inst = get_instance (xcurrent_scope);
1451 
1452  if (inst)
1453  inst->do_erase_persistent (name);
1454  }
1455 
1456  static bool is_variable (const std::string& name)
1457  {
1458  symbol_table *inst = get_instance (xcurrent_scope);
1459 
1460  return inst ? inst->do_is_variable (name) : false;
1461  }
1462 
1463  static bool
1464  is_built_in_function_name (const std::string& name)
1465  {
1466  octave_value val = find_built_in_function (name);
1467 
1468  return val.is_defined ();
1469  }
1470 
1471  static octave_value
1472  find_method (const std::string& name, const std::string& dispatch_type)
1473  {
1474  fcn_table_const_iterator p = fcn_table.find (name);
1475 
1476  if (p != fcn_table.end ())
1477  return p->second.find_method (dispatch_type);
1478  else
1479  {
1480  fcn_info finfo (name);
1481 
1482  octave_value fcn = finfo.find_method (dispatch_type);
1483 
1484  if (fcn.is_defined ())
1485  fcn_table[name] = finfo;
1486 
1487  return fcn;
1488  }
1489  }
1490 
1491  static octave_value
1492  find_built_in_function (const std::string& name)
1493  {
1494  fcn_table_const_iterator p = fcn_table.find (name);
1495 
1496  return (p != fcn_table.end ())
1497  ? p->second.find_built_in_function () : octave_value ();
1498  }
1499 
1500  static octave_value
1501  find_autoload (const std::string& name)
1502  {
1503  fcn_table_iterator p = fcn_table.find (name);
1504 
1505  return (p != fcn_table.end ())
1506  ? p->second.find_autoload () : octave_value ();
1507  }
1508 
1509  static octave_value
1510  find_function (const std::string& name,
1511  const octave_value_list& args = octave_value_list (),
1512  bool local_funcs = true);
1513 
1514  static octave_value find_user_function (const std::string& name)
1515  {
1516  fcn_table_iterator p = fcn_table.find (name);
1517 
1518  return (p != fcn_table.end ())
1519  ? p->second.find_user_function () : octave_value ();
1520  }
1521 
1522  static void install_cmdline_function (const std::string& name,
1523  const octave_value& fcn)
1524  {
1525  fcn_table_iterator p = fcn_table.find (name);
1526 
1527  if (p != fcn_table.end ())
1528  {
1529  fcn_info& finfo = p->second;
1530 
1531  finfo.install_cmdline_function (fcn);
1532  }
1533  else
1534  {
1535  fcn_info finfo (name);
1536 
1537  finfo.install_cmdline_function (fcn);
1538 
1539  fcn_table[name] = finfo;
1540  }
1541  }
1542 
1543  // Install subfunction FCN named NAME. SCOPE is the scope of the
1544  // primary function corresponding to this subfunction.
1545 
1546  static void install_subfunction (const std::string& name,
1547  const octave_value& fcn,
1548  scope_id scope)
1549  {
1550  fcn_table_iterator p = fcn_table.find (name);
1551 
1552  if (p != fcn_table.end ())
1553  {
1554  fcn_info& finfo = p->second;
1555 
1556  finfo.install_subfunction (fcn, scope);
1557  }
1558  else
1559  {
1560  fcn_info finfo (name);
1561 
1562  finfo.install_subfunction (fcn, scope);
1563 
1564  fcn_table[name] = finfo;
1565  }
1566  }
1567 
1568  static void install_nestfunction (const std::string& name,
1569  const octave_value& fcn,
1570  scope_id parent_scope);
1571 
1572  static void update_nest (scope_id scope)
1573  {
1574  symbol_table *inst = get_instance (scope);
1575  if (inst)
1576  inst->do_update_nest ();
1577  }
1578 
1579  static void install_user_function (const std::string& name,
1580  const octave_value& fcn)
1581  {
1582  fcn_table_iterator p = fcn_table.find (name);
1583 
1584  if (p != fcn_table.end ())
1585  {
1586  fcn_info& finfo = p->second;
1587 
1588  finfo.install_user_function (fcn);
1589  }
1590  else
1591  {
1592  fcn_info finfo (name);
1593 
1594  finfo.install_user_function (fcn);
1595 
1596  fcn_table[name] = finfo;
1597  }
1598  }
1599 
1600  static void install_built_in_function (const std::string& name,
1601  const octave_value& fcn)
1602  {
1603  fcn_table_iterator p = fcn_table.find (name);
1604 
1605  if (p != fcn_table.end ())
1606  {
1607  fcn_info& finfo = p->second;
1608 
1609  finfo.install_built_in_function (fcn);
1610  }
1611  else
1612  {
1613  fcn_info finfo (name);
1614 
1615  finfo.install_built_in_function (fcn);
1616 
1617  fcn_table[name] = finfo;
1618  }
1619  }
1620 
1621  static void clear (const std::string& name)
1622  {
1623  clear_variable (name);
1624  }
1625 
1626  static void clear_all (bool force = false)
1627  {
1628  clear_variables ();
1629 
1630  clear_global_pattern ("*");
1631 
1632  clear_functions (force);
1633  }
1634 
1635  static void clear_variables (scope_id scope)
1636  {
1637  symbol_table *inst = get_instance (scope);
1638 
1639  if (inst)
1640  inst->do_clear_variables ();
1641  }
1642 
1643  // This is split for unwind_protect.
1644  static void clear_variables (void)
1645  {
1646  clear_variables (xcurrent_scope);
1647  }
1648 
1649  static void clear_objects (scope_id scope = xcurrent_scope)
1650  {
1651  symbol_table *inst = get_instance (scope);
1652 
1653  if (inst)
1654  inst->do_clear_objects ();
1655  }
1656 
1657  static void clear_functions (bool force = false)
1658  {
1659  for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1660  p->second.clear (force);
1661  }
1662 
1663  static void clear_function (const std::string& name)
1664  {
1665  clear_user_function (name);
1666  }
1667 
1668  static void clear_global (const std::string& name)
1669  {
1670  symbol_table *inst = get_instance (xcurrent_scope);
1671 
1672  if (inst)
1673  inst->do_clear_global (name);
1674  }
1675 
1676  static void clear_variable (const std::string& name)
1677  {
1678  symbol_table *inst = get_instance (xcurrent_scope);
1679 
1680  if (inst)
1681  inst->do_clear_variable (name);
1682  }
1683 
1684  static void clear_symbol (const std::string& name)
1685  {
1686  // FIXME: are we supposed to do both here?
1687 
1688  clear_variable (name);
1689  clear_function (name);
1690  }
1691 
1692  static void clear_function_pattern (const std::string& pat)
1693  {
1694  glob_match pattern (pat);
1695 
1696  for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1697  {
1698  if (pattern.match (p->first))
1699  p->second.clear_user_function ();
1700  }
1701  }
1702 
1703  static void clear_global_pattern (const std::string& pat)
1704  {
1705  symbol_table *inst = get_instance (xcurrent_scope);
1706 
1707  if (inst)
1708  inst->do_clear_global_pattern (pat);
1709  }
1710 
1711  static void clear_variable_pattern (const std::string& pat)
1712  {
1713  symbol_table *inst = get_instance (xcurrent_scope);
1714 
1715  if (inst)
1716  inst->do_clear_variable_pattern (pat);
1717  }
1718 
1719  static void clear_variable_regexp (const std::string& pat)
1720  {
1721  symbol_table *inst = get_instance (xcurrent_scope);
1722 
1723  if (inst)
1724  inst->do_clear_variable_regexp (pat);
1725  }
1726 
1727  static void clear_symbol_pattern (const std::string& pat)
1728  {
1729  // FIXME: are we supposed to do both here?
1730 
1731  clear_variable_pattern (pat);
1732  clear_function_pattern (pat);
1733  }
1734 
1735  static void clear_user_function (const std::string& name)
1736  {
1737  fcn_table_iterator p = fcn_table.find (name);
1738 
1739  if (p != fcn_table.end ())
1740  {
1741  fcn_info& finfo = p->second;
1742 
1743  finfo.clear_user_function ();
1744  }
1745  // FIXME: is this necessary, or even useful?
1746  // else
1747  // error ("clear: no such function '%s'", name.c_str ());
1748  }
1749 
1750  // This clears oct and mex files, incl. autoloads.
1751  static void clear_dld_function (const std::string& name)
1752  {
1753  fcn_table_iterator p = fcn_table.find (name);
1754 
1755  if (p != fcn_table.end ())
1756  {
1757  fcn_info& finfo = p->second;
1758 
1759  finfo.clear_autoload_function ();
1760  finfo.clear_user_function ();
1761  }
1762  }
1763 
1764  static void clear_mex_functions (void)
1765  {
1766  for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
1767  {
1768  fcn_info& finfo = p->second;
1769 
1770  finfo.clear_mex_function ();
1771  }
1772  }
1773 
1774  static bool set_class_relationship (const std::string& sup_class,
1775  const std::string& inf_class);
1776 
1777  static bool is_superiorto (const std::string& a, const std::string& b);
1778 
1779  static void alias_built_in_function (const std::string& alias,
1780  const std::string& name)
1781  {
1782  octave_value fcn = find_built_in_function (name);
1783 
1784  if (fcn.is_defined ())
1785  {
1786  fcn_info finfo (alias);
1787 
1788  finfo.install_built_in_function (fcn);
1789 
1790  fcn_table[alias] = finfo;
1791  }
1792  else
1793  panic ("alias: '%s' is undefined", name.c_str ());
1794  }
1795 
1796  static void add_dispatch (const std::string& name, const std::string& type,
1797  const std::string& fname)
1798  {
1799  fcn_table_iterator p = fcn_table.find (name);
1800 
1801  if (p != fcn_table.end ())
1802  {
1803  fcn_info& finfo = p->second;
1804 
1805  finfo.add_dispatch (type, fname);
1806  }
1807  else
1808  {
1809  fcn_info finfo (name);
1810 
1811  finfo.add_dispatch (type, fname);
1812 
1813  fcn_table[name] = finfo;
1814  }
1815  }
1816 
1817  static void clear_dispatch (const std::string& name, const std::string& type)
1818  {
1819  fcn_table_iterator p = fcn_table.find (name);
1820 
1821  if (p != fcn_table.end ())
1822  {
1823  fcn_info& finfo = p->second;
1824 
1825  finfo.clear_dispatch (type);
1826  }
1827  }
1828 
1829  static void print_dispatch (std::ostream& os, const std::string& name)
1830  {
1831  fcn_table_iterator p = fcn_table.find (name);
1832 
1833  if (p != fcn_table.end ())
1834  {
1835  fcn_info& finfo = p->second;
1836 
1837  finfo.print_dispatch (os);
1838  }
1839  }
1840 
1841  static fcn_info::dispatch_map_type get_dispatch (const std::string& name)
1842  {
1844 
1845  fcn_table_iterator p = fcn_table.find (name);
1846 
1847  if (p != fcn_table.end ())
1848  {
1849  fcn_info& finfo = p->second;
1850 
1851  retval = finfo.get_dispatch ();
1852  }
1853 
1854  return retval;
1855  }
1856 
1857  static std::string help_for_dispatch (const std::string& name)
1858  {
1859  std::string retval;
1860 
1861  fcn_table_iterator p = fcn_table.find (name);
1862 
1863  if (p != fcn_table.end ())
1864  {
1865  fcn_info& finfo = p->second;
1866 
1867  retval = finfo.help_for_dispatch ();
1868  }
1869 
1870  return retval;
1871  }
1872 
1873  static void push_context (void)
1874  {
1875  if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
1876  error ("invalid call to xymtab::push_context");
1877  else
1878  {
1879  symbol_table *inst = get_instance (xcurrent_scope);
1880 
1881  if (inst)
1882  inst->do_push_context ();
1883  }
1884  }
1885 
1886  static void pop_context (void)
1887  {
1888  if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
1889  error ("invalid call to xymtab::pop_context");
1890  else
1891  {
1892  symbol_table *inst = get_instance (xcurrent_scope);
1893 
1894  if (inst)
1895  inst->do_pop_context ();
1896  }
1897  }
1898 
1899  // For unwind_protect.
1900  static void pop_context (void *) { pop_context (); }
1901 
1902  static void mark_automatic (const std::string& name)
1903  {
1904  symbol_table *inst = get_instance (xcurrent_scope);
1905 
1906  if (inst)
1907  inst->do_mark_automatic (name);
1908  }
1909 
1910  static void mark_hidden (const std::string& name)
1911  {
1912  symbol_table *inst = get_instance (xcurrent_scope);
1913 
1914  if (inst)
1915  inst->do_mark_hidden (name);
1916  }
1917 
1918  static void mark_global (const std::string& name)
1919  {
1920  symbol_table *inst = get_instance (xcurrent_scope);
1921 
1922  if (inst)
1923  inst->do_mark_global (name);
1924  }
1925 
1926  // exclude: Storage classes to exclude, you can OR them together
1927  static std::list<symbol_record>
1928  all_variables (scope_id scope = xcurrent_scope,
1929  context_id context = xdefault_context,
1930  bool defined_only = true,
1931  unsigned int exclude = symbol_record::hidden)
1932  {
1933  symbol_table *inst = get_instance (scope);
1934 
1935  return inst
1936  ? inst->do_all_variables (context, defined_only, exclude)
1937  : std::list<symbol_record> ();
1938  }
1939 
1940  static std::list<symbol_record> glob (const std::string& pattern)
1941  {
1942  symbol_table *inst = get_instance (xcurrent_scope);
1943 
1944  return inst ? inst->do_glob (pattern) : std::list<symbol_record> ();
1945  }
1946 
1947  static std::list<symbol_record> regexp (const std::string& pattern)
1948  {
1949  symbol_table *inst = get_instance (xcurrent_scope);
1950 
1951  return inst ? inst->do_regexp (pattern) : std::list<symbol_record> ();
1952  }
1953 
1954  static std::list<symbol_record> glob_variables (const std::string& pattern)
1955  {
1956  symbol_table *inst = get_instance (xcurrent_scope);
1957 
1958  return inst ? inst->do_glob (pattern, true) : std::list<symbol_record> ();
1959  }
1960 
1961  static std::list<symbol_record> regexp_variables (const std::string& pattern)
1962  {
1963  symbol_table *inst = get_instance (xcurrent_scope);
1964 
1965  return inst ? inst->do_regexp (pattern, true) : std::list<symbol_record> ();
1966  }
1967 
1968  static std::list<symbol_record>
1969  glob_global_variables (const std::string& pattern)
1970  {
1971  std::list<symbol_record> retval;
1972 
1973  glob_match pat (pattern);
1974 
1975  for (global_table_const_iterator p = global_table.begin ();
1976  p != global_table.end (); p++)
1977  {
1978  // We generate a list of symbol_record objects so that
1979  // the results from glob_variables and glob_global_variables
1980  // may be handled the same way.
1981 
1982  if (pat.match (p->first))
1983  retval.push_back (symbol_record (xglobal_scope,
1984  p->first, p->second,
1985  symbol_record::global));
1986  }
1987 
1988  return retval;
1989  }
1990 
1991  static std::list<symbol_record>
1992  regexp_global_variables (const std::string& pattern)
1993  {
1994  std::list<symbol_record> retval;
1995 
1996  ::regexp pat (pattern);
1997 
1998  for (global_table_const_iterator p = global_table.begin ();
1999  p != global_table.end (); p++)
2000  {
2001  // We generate a list of symbol_record objects so that
2002  // the results from regexp_variables and regexp_global_variables
2003  // may be handled the same way.
2004 
2005  if (pat.is_match (p->first))
2006  retval.push_back (symbol_record (xglobal_scope,
2007  p->first, p->second,
2008  symbol_record::global));
2009  }
2010 
2011  return retval;
2012  }
2013 
2014  static std::list<symbol_record> glob_variables (const string_vector& patterns)
2015  {
2016  std::list<symbol_record> retval;
2017 
2018  size_t len = patterns.length ();
2019 
2020  for (size_t i = 0; i < len; i++)
2021  {
2022  std::list<symbol_record> tmp = glob_variables (patterns[i]);
2023 
2024  retval.insert (retval.begin (), tmp.begin (), tmp.end ());
2025  }
2026 
2027  return retval;
2028  }
2029 
2030  static std::list<symbol_record> regexp_variables
2031  (const string_vector& patterns)
2032  {
2033  std::list<symbol_record> retval;
2034 
2035  size_t len = patterns.length ();
2036 
2037  for (size_t i = 0; i < len; i++)
2038  {
2039  std::list<symbol_record> tmp = regexp_variables (patterns[i]);
2040 
2041  retval.insert (retval.begin (), tmp.begin (), tmp.end ());
2042  }
2043 
2044  return retval;
2045  }
2046 
2047  static std::list<std::string> user_function_names (void)
2048  {
2049  std::list<std::string> retval;
2050 
2051  for (fcn_table_iterator p = fcn_table.begin ();
2052  p != fcn_table.end (); p++)
2053  {
2054  if (p->second.is_user_function_defined ())
2055  retval.push_back (p->first);
2056  }
2057 
2058  if (! retval.empty ())
2059  retval.sort ();
2060 
2061  return retval;
2062  }
2063 
2064  static std::list<std::string> global_variable_names (void)
2065  {
2066  std::list<std::string> retval;
2067 
2068  for (global_table_const_iterator p = global_table.begin ();
2069  p != global_table.end (); p++)
2070  retval.push_back (p->first);
2071 
2072  retval.sort ();
2073 
2074  return retval;
2075  }
2076 
2077  static std::list<std::string> top_level_variable_names (void)
2078  {
2079  symbol_table *inst = get_instance (xtop_scope);
2080 
2081  return inst ? inst->do_variable_names () : std::list<std::string> ();
2082  }
2083 
2084  static std::list<std::string> variable_names (void)
2085  {
2086  symbol_table *inst = get_instance (xcurrent_scope);
2087 
2088  return inst ? inst->do_variable_names () : std::list<std::string> ();
2089  }
2090 
2091  static std::list<std::string> built_in_function_names (void)
2092  {
2093  std::list<std::string> retval;
2094 
2095  for (fcn_table_const_iterator p = fcn_table.begin ();
2096  p != fcn_table.end (); p++)
2097  {
2098  octave_value fcn = p->second.find_built_in_function ();
2099 
2100  if (fcn.is_defined ())
2101  retval.push_back (p->first);
2102  }
2103 
2104  if (! retval.empty ())
2105  retval.sort ();
2106 
2107  return retval;
2108  }
2109 
2110  static std::list<std::string> cmdline_function_names (void)
2111  {
2112  std::list<std::string> retval;
2113 
2114  for (fcn_table_const_iterator p = fcn_table.begin ();
2115  p != fcn_table.end (); p++)
2116  {
2117  octave_value fcn = p->second.find_cmdline_function ();
2118 
2119  if (fcn.is_defined ())
2120  retval.push_back (p->first);
2121  }
2122 
2123  if (! retval.empty ())
2124  retval.sort ();
2125 
2126  return retval;
2127  }
2128 
2129  static bool is_local_variable (const std::string& name)
2130  {
2131  if (xcurrent_scope == xglobal_scope)
2132  return false;
2133  else
2134  {
2135  symbol_table *inst = get_instance (xcurrent_scope);
2136 
2137  return inst ? inst->do_is_local_variable (name) : false;
2138  }
2139  }
2140 
2141  static bool is_global (const std::string& name)
2142  {
2143  if (xcurrent_scope == xglobal_scope)
2144  return true;
2145  else
2146  {
2147  symbol_table *inst = get_instance (xcurrent_scope);
2148 
2149  return inst ? inst->do_is_global (name) : false;
2150  }
2151  }
2152 
2153  static std::list<workspace_element> workspace_info (void)
2154  {
2155  symbol_table *inst = get_instance (xcurrent_scope);
2156 
2157  return inst
2158  ? inst->do_workspace_info () : std::list<workspace_element> ();
2159  }
2160 
2161  static void dump (std::ostream& os, scope_id scope = xcurrent_scope);
2162 
2163  static void dump_global (std::ostream& os);
2164 
2165  static void dump_functions (std::ostream& os);
2166 
2167  static void cache_name (scope_id scope, const std::string& name)
2168  {
2169  symbol_table *inst = get_instance (scope, false);
2170 
2171  if (inst)
2172  inst->do_cache_name (name);
2173  }
2174 
2175  static void lock_subfunctions (scope_id scope = xcurrent_scope)
2176  {
2177  for (fcn_table_iterator p = fcn_table.begin ();
2178  p != fcn_table.end (); p++)
2179  p->second.lock_subfunction (scope);
2180  }
2181 
2182  static void unlock_subfunctions (scope_id scope = xcurrent_scope)
2183  {
2184  for (fcn_table_iterator p = fcn_table.begin ();
2185  p != fcn_table.end (); p++)
2186  p->second.unlock_subfunction (scope);
2187  }
2188 
2189  static std::map<std::string, octave_value>
2190  subfunctions_defined_in_scope (scope_id scope = xcurrent_scope)
2191  {
2192  std::map<std::string, octave_value> retval;
2193 
2194  for (fcn_table_const_iterator p = fcn_table.begin ();
2195  p != fcn_table.end (); p++)
2196  {
2197  std::pair<std::string, octave_value> tmp
2198  = p->second.subfunction_defined_in_scope (scope);
2199 
2200  std::string nm = tmp.first;
2201 
2202  if (! nm.empty ())
2203  retval[nm] = tmp.second;
2204  }
2205 
2206  return retval;
2207  }
2208 
2209  static void free_scope (scope_id scope)
2210  {
2211  if (scope == xglobal_scope || scope == xtop_scope)
2212  error ("can't free global or top-level scopes!");
2213  else
2215  }
2216 
2217  static void stash_dir_name_for_subfunctions (scope_id scope,
2218  const std::string& dir_name);
2219 
2220  static void add_to_parent_map (const std::string& classname,
2221  const std::list<std::string>& parent_list)
2222  {
2223  parent_map[classname] = parent_list;
2224  }
2225 
2226  static std::list<std::string>
2227  parent_classes (const std::string& dispatch_type)
2228  {
2229  std::list<std::string> retval;
2230 
2231  const_parent_map_iterator it = parent_map.find (dispatch_type);
2232 
2233  if (it != parent_map.end ())
2234  retval = it->second;
2235 
2236  for (std::list<std::string>::const_iterator lit = retval.begin ();
2237  lit != retval.end (); lit++)
2238  {
2239  // Search for parents of parents and append them to the list.
2240 
2241  // FIXME: should we worry about a circular inheritance graph?
2242 
2243  std::list<std::string> parents = parent_classes (*lit);
2244 
2245  if (! parents.empty ())
2246  retval.insert (retval.end (), parents.begin (), parents.end ());
2247  }
2248 
2249  return retval;
2250  }
2251 
2252  static octave_user_function *get_curr_fcn (scope_id scope = xcurrent_scope)
2253  {
2254  symbol_table *inst = get_instance (scope);
2255  return inst->curr_fcn;
2256  }
2257 
2258  static void set_curr_fcn (octave_user_function *curr_fcn,
2259  scope_id scope = xcurrent_scope)
2260  {
2261  assert (scope != xtop_scope && scope != xglobal_scope);
2262  symbol_table *inst = get_instance (scope);
2263  // FIXME: normally, functions should not usurp each other's scope.
2264  // If for any incredible reason this is needed, call
2265  // set_user_function (0, scope) first. This may cause problems with
2266  // nested functions, as the curr_fcn of symbol_records must be updated.
2267  assert (inst->curr_fcn == 0 || curr_fcn == 0);
2268  inst->curr_fcn = curr_fcn;
2269  }
2270 
2271  static void cleanup (void);
2272 
2273 private:
2274 
2275  // No copying!
2276 
2277  symbol_table (const symbol_table&);
2278 
2279  symbol_table& operator = (const symbol_table&);
2280 
2281  typedef std::map<std::string, symbol_record>::const_iterator
2283  typedef std::map<std::string, symbol_record>::iterator
2285 
2286  typedef std::map<std::string, octave_value>::const_iterator
2288  typedef std::map<std::string, octave_value>::iterator
2290 
2291  typedef std::map<std::string, octave_value>::const_iterator
2293  typedef std::map<std::string, octave_value>::iterator
2295 
2296  typedef std::map<scope_id, symbol_table*>::const_iterator
2298  typedef std::map<scope_id, symbol_table*>::iterator
2300 
2301  typedef std::map<std::string, fcn_info>::const_iterator
2303  typedef std::map<std::string, fcn_info>::iterator
2305 
2306  // The scope of this symbol table.
2307  scope_id my_scope;
2308 
2309  // Name for this table (usually the file name of the function
2310  // corresponding to the scope);
2311  std::string table_name;
2312 
2313  // Map from symbol names to symbol info.
2314  std::map<std::string, symbol_record> table;
2315 
2316  // Child nested functions.
2317  std::vector<symbol_table*> nest_children;
2318 
2319  // Parent nested function (may be null).
2321 
2322  // The associated user code (may be null).
2324 
2325  // If true then no variables can be added.
2327 
2328  // Map from names of global variables to values.
2329  static std::map<std::string, octave_value> global_table;
2330 
2331  // Map from names of persistent variables to values.
2332  std::map<std::string, octave_value> persistent_table;
2333 
2334  // Pointer to symbol table for current scope (variables only).
2336 
2337  // Map from scope id to symbol table instances.
2338  static std::map<scope_id, symbol_table*> all_instances;
2339 
2340  // Map from function names to function info (subfunctions, private
2341  // functions, class constructors, class methods, etc.)
2342  static std::map<std::string, fcn_info> fcn_table;
2343 
2344  // Mape from class names to set of classes that have lower
2345  // precedence.
2346  static std::map<std::string, std::set<std::string> > class_precedence_table;
2347 
2348  typedef std::map<std::string, std::set<std::string> >::const_iterator
2350  typedef std::map<std::string, std::set<std::string> >::iterator
2352 
2353  // Map from class names to parent class names.
2354  static std::map<std::string, std::list<std::string> > parent_map;
2355 
2356  typedef std::map<std::string, std::list<std::string> >::const_iterator
2358  typedef std::map<std::string, std::list<std::string> >::iterator
2360 
2361  static const scope_id xglobal_scope;
2362  static const scope_id xtop_scope;
2363 
2364  static scope_id xcurrent_scope;
2365 
2366  static context_id xcurrent_context;
2367 
2368  static const context_id xdefault_context = static_cast<context_id> (-1);
2369 
2370  symbol_table (scope_id scope)
2371  : my_scope (scope), table_name (), table (), nest_children (),
2372  nest_parent (0), curr_fcn (0), static_workspace (false),
2373  persistent_table () { }
2374 
2375  ~symbol_table (void) { }
2376 
2377  static symbol_table *get_instance (scope_id scope, bool create = true)
2378  {
2379  symbol_table *retval = 0;
2380 
2381  bool ok = true;
2382 
2383  if (scope != xglobal_scope)
2384  {
2385  if (scope == xcurrent_scope)
2386  {
2387  if (! instance && create)
2388  {
2389  symbol_table *inst = new symbol_table (scope);
2390 
2391  if (inst)
2392  {
2393  all_instances[scope] = instance = inst;
2394 
2395  if (scope == xtop_scope)
2396  instance->do_cache_name ("top-level");
2397  }
2398  }
2399 
2400  if (! instance)
2401  ok = false;
2402 
2403  retval = instance;
2404  }
2405  else
2406  {
2407  all_instances_iterator p = all_instances.find (scope);
2408 
2409  if (p == all_instances.end ())
2410  {
2411  if (create)
2412  {
2413  retval = new symbol_table (scope);
2414 
2415  if (retval)
2416  all_instances[scope] = retval;
2417  else
2418  ok = false;
2419  }
2420  else
2421  ok = false;
2422  }
2423  else
2424  retval = p->second;
2425  }
2426  }
2427 
2428  if (! ok)
2429  error ("unable to %s symbol_table object for scope %d!",
2430  create ? "create" : "find", scope);
2431 
2432  return retval;
2433  }
2434 
2435  void add_nest_child (symbol_table& st)
2436  {
2437  assert (!st.nest_parent);
2438  nest_children.push_back (&st);
2439  st.nest_parent = this;
2440  }
2441 
2442  void insert_symbol_record (const symbol_record& sr)
2443  {
2444  table[sr.name ()] = sr;
2445  }
2446 
2447  void
2448  do_dup_scope (symbol_table& new_symbol_table) const
2449  {
2450  for (table_const_iterator p = table.begin (); p != table.end (); p++)
2451  new_symbol_table.insert_symbol_record (p->second.dup (new_symbol_table
2452  .my_scope));
2453  }
2454 
2455  symbol_record do_find_symbol (const std::string& name)
2456  {
2457  table_iterator p = table.find (name);
2458 
2459  if (p == table.end ())
2460  return do_insert (name);
2461  else
2462  return p->second;
2463  }
2464 
2465  void do_inherit (symbol_table& donor_table, context_id donor_context)
2466  {
2467  for (table_iterator p = table.begin (); p != table.end (); p++)
2468  {
2469  symbol_record& sr = p->second;
2470 
2471  if (! (sr.is_automatic () || sr.is_formal ()))
2472  {
2473  std::string nm = sr.name ();
2474 
2475  if (nm != "__retval__")
2476  {
2477  octave_value val = donor_table.do_varval (nm, donor_context);
2478 
2479  if (val.is_defined ())
2480  {
2481  sr.assign (val, 0);
2482 
2483  sr.mark_inherited ();
2484  }
2485  }
2486  }
2487  }
2488  }
2489 
2490  static fcn_info *get_fcn_info (const std::string& name)
2491  {
2492  fcn_table_iterator p = fcn_table.find (name);
2493  return p != fcn_table.end () ? &p->second : 0;
2494  }
2495 
2496  octave_value
2497  do_find (const std::string& name, const octave_value_list& args,
2498  bool skip_variables, bool local_funcs);
2499 
2500  octave_value do_builtin_find (const std::string& name);
2501 
2502  symbol_record& do_insert (const std::string& name, bool force_add = false)
2503  {
2504  table_iterator p = table.find (name);
2505 
2506  if (p == table.end ())
2507  {
2508  symbol_record ret (my_scope, name);
2509 
2510  if (nest_parent && nest_parent->look_nonlocal (name, ret))
2511  return table[name] = ret;
2512  else
2513  {
2514  if (static_workspace && ! force_add)
2515  ret.mark_added_static ();
2516 
2517  return table[name] = ret;
2518  }
2519  }
2520  else
2521  return p->second;
2522  }
2523 
2524  void do_rename (const std::string& old_name, const std::string& new_name)
2525  {
2526  table_iterator p = table.find (old_name);
2527 
2528  if (p != table.end ())
2529  {
2530  symbol_record sr = p->second;
2531 
2532  sr.rename (new_name);
2533 
2534  table.erase (p);
2535 
2536  table[new_name] = sr;
2537  }
2538  }
2539 
2540  void do_assign (const std::string& name, const octave_value& value,
2541  context_id context, bool force_add)
2542  {
2543  table_iterator p = table.find (name);
2544 
2545  if (p == table.end ())
2546  {
2547  symbol_record& sr = do_insert (name, force_add);
2548 
2549  sr.assign (value, context);
2550  }
2551  else
2552  p->second.assign (value, context);
2553  }
2554 
2555  // Use do_assign (name, value, context, force_add) instead.
2556  // Delete when deprecated varref functions are removed.
2557  octave_value& do_varref (const std::string& name, context_id context,
2558  bool force_add)
2559  {
2560  table_iterator p = table.find (name);
2561 
2562  if (p == table.end ())
2563  {
2564  symbol_record& sr = do_insert (name, force_add);
2565 
2566  return sr.varref (context);
2567  }
2568  else
2569  return p->second.varref (context);
2570  }
2571 
2572  octave_value do_varval (const std::string& name, context_id context) const
2573  {
2574  table_const_iterator p = table.find (name);
2575 
2576  return (p != table.end ()) ? p->second.varval (context) : octave_value ();
2577  }
2578 
2579  void do_persistent_assign (const std::string& name, const octave_value& value)
2580  {
2581  persistent_table_iterator p = persistent_table.find (name);
2582 
2583  if (p == persistent_table.end ())
2584  persistent_table[name] = value;
2585  else
2586  p->second = value;
2587  }
2588 
2589  // Use do_persistent_assign (name, value) instead.
2590  // Delete when deprecated varref functions are removed.
2591  octave_value& do_persistent_varref (const std::string& name)
2592  {
2593  persistent_table_iterator p = persistent_table.find (name);
2594 
2595  return (p == persistent_table.end ())
2596  ? persistent_table[name] : p->second;
2597  }
2598 
2599  octave_value do_persistent_varval (const std::string& name)
2600  {
2601  persistent_table_const_iterator p = persistent_table.find (name);
2602 
2603  return (p != persistent_table.end ()) ? p->second : octave_value ();
2604  }
2605 
2606  void do_erase_persistent (const std::string& name)
2607  {
2608  persistent_table_iterator p = persistent_table.find (name);
2609 
2610  if (p != persistent_table.end ())
2611  persistent_table.erase (p);
2612  }
2613 
2614  bool do_is_variable (const std::string& name) const
2615  {
2616  bool retval = false;
2617 
2618  table_const_iterator p = table.find (name);
2619 
2620  if (p != table.end ())
2621  {
2622  const symbol_record& sr = p->second;
2623 
2624  retval = sr.is_variable ();
2625  }
2626 
2627  return retval;
2628  }
2629 
2630  void do_push_context (void)
2631  {
2632  for (table_iterator p = table.begin (); p != table.end (); p++)
2633  p->second.push_context (my_scope);
2634  }
2635 
2636  void do_pop_context (void)
2637  {
2638  table_iterator p = table.begin ();
2639 
2640  while (p != table.end ())
2641  {
2642  if (p->second.pop_context (my_scope) == 0)
2643  table.erase (p++);
2644  else
2645  p++;
2646  }
2647  }
2648 
2650  {
2651  for (table_iterator p = table.begin (); p != table.end (); p++)
2652  p->second.clear (my_scope);
2653  }
2654 
2655  void do_clear_objects (void)
2656  {
2657  for (table_iterator p = table.begin (); p != table.end (); p++)
2658  {
2659  symbol_record& sr = p->second;
2660  octave_value val = sr.varval ();
2661  if (val.is_object ())
2662  p->second.clear (my_scope);
2663  }
2664  }
2665 
2666  void do_clear_global (const std::string& name)
2667  {
2668  table_iterator p = table.find (name);
2669 
2670  if (p != table.end ())
2671  {
2672  symbol_record& sr = p->second;
2673 
2674  if (sr.is_global ())
2675  sr.unmark_global ();
2676  }
2677 
2678  global_table_iterator q = global_table.find (name);
2679 
2680  if (q != global_table.end ())
2681  global_table.erase (q);
2682 
2683  }
2684 
2685  void do_clear_variable (const std::string& name)
2686  {
2687  table_iterator p = table.find (name);
2688 
2689  if (p != table.end ())
2690  p->second.clear (my_scope);
2691  }
2692 
2693  void do_clear_global_pattern (const std::string& pat)
2694  {
2695  glob_match pattern (pat);
2696 
2697  for (table_iterator p = table.begin (); p != table.end (); p++)
2698  {
2699  symbol_record& sr = p->second;
2700 
2701  if (sr.is_global () && pattern.match (sr.name ()))
2702  sr.unmark_global ();
2703  }
2704 
2705  global_table_iterator q = global_table.begin ();
2706 
2707  while (q != global_table.end ())
2708  {
2709  if (pattern.match (q->first))
2710  global_table.erase (q++);
2711  else
2712  q++;
2713  }
2714 
2715 
2716  }
2717 
2718  void do_clear_variable_pattern (const std::string& pat)
2719  {
2720  glob_match pattern (pat);
2721 
2722  for (table_iterator p = table.begin (); p != table.end (); p++)
2723  {
2724  symbol_record& sr = p->second;
2725 
2726  if (sr.is_defined () || sr.is_global ())
2727  {
2728  if (pattern.match (sr.name ()))
2729  sr.clear (my_scope);
2730  }
2731  }
2732  }
2733 
2734  void do_clear_variable_regexp (const std::string& pat)
2735  {
2736  ::regexp pattern (pat);
2737 
2738  for (table_iterator p = table.begin (); p != table.end (); p++)
2739  {
2740  symbol_record& sr = p->second;
2741 
2742  if (sr.is_defined () || sr.is_global ())
2743  {
2744  if (pattern.is_match (sr.name ()))
2745  sr.clear (my_scope);
2746  }
2747  }
2748  }
2749 
2750  void do_mark_automatic (const std::string& name)
2751  {
2752  do_insert (name).mark_automatic ();
2753  }
2754 
2755  void do_mark_hidden (const std::string& name)
2756  {
2757  do_insert (name).mark_hidden ();
2758  }
2759 
2760  void do_mark_global (const std::string& name)
2761  {
2762  do_insert (name).mark_global ();
2763  }
2764 
2765  std::list<symbol_record>
2766  do_all_variables (context_id context, bool defined_only,
2767  unsigned int exclude) const
2768  {
2769  std::list<symbol_record> retval;
2770 
2771  for (table_const_iterator p = table.begin (); p != table.end (); p++)
2772  {
2773  const symbol_record& sr = p->second;
2774 
2775  if ((defined_only && ! sr.is_defined (context))
2776  || (sr.xstorage_class () & exclude))
2777  continue;
2778 
2779  retval.push_back (sr);
2780  }
2781 
2782  return retval;
2783  }
2784 
2785  std::list<symbol_record> do_glob (const std::string& pattern,
2786  bool vars_only = false) const
2787  {
2788  std::list<symbol_record> retval;
2789 
2790  glob_match pat (pattern);
2791 
2792  for (table_const_iterator p = table.begin (); p != table.end (); p++)
2793  {
2794  if (pat.match (p->first))
2795  {
2796  const symbol_record& sr = p->second;
2797 
2798  if (vars_only && ! sr.is_variable ())
2799  continue;
2800 
2801  retval.push_back (sr);
2802  }
2803  }
2804 
2805  return retval;
2806  }
2807 
2808  std::list<symbol_record> do_regexp (const std::string& pattern,
2809  bool vars_only = false) const
2810  {
2811  std::list<symbol_record> retval;
2812 
2813  ::regexp pat (pattern);
2814 
2815  for (table_const_iterator p = table.begin (); p != table.end (); p++)
2816  {
2817  if (pat.is_match (p->first))
2818  {
2819  const symbol_record& sr = p->second;
2820 
2821  if (vars_only && ! sr.is_variable ())
2822  continue;
2823 
2824  retval.push_back (sr);
2825  }
2826  }
2827 
2828  return retval;
2829  }
2830 
2831  std::list<std::string> do_variable_names (void)
2832  {
2833  std::list<std::string> retval;
2834 
2835  for (table_const_iterator p = table.begin (); p != table.end (); p++)
2836  {
2837  if (p->second.is_variable ())
2838  retval.push_back (p->first);
2839  }
2840 
2841  retval.sort ();
2842 
2843  return retval;
2844  }
2845 
2846  bool do_is_local_variable (const std::string& name) const
2847  {
2848  table_const_iterator p = table.find (name);
2849 
2850  return (p != table.end ()
2851  && ! p->second.is_global ()
2852  && p->second.is_defined ());
2853  }
2854 
2855  bool do_is_global (const std::string& name) const
2856  {
2857  table_const_iterator p = table.find (name);
2858 
2859  return p != table.end () && p->second.is_global ();
2860  }
2861 
2862  std::list<workspace_element> do_workspace_info (void) const;
2863 
2864  void do_dump (std::ostream& os);
2865 
2866  void do_cache_name (const std::string& name) { table_name = name; }
2867 
2868  void do_update_nest (void);
2869 
2870  bool look_nonlocal (const std::string& name, symbol_record& result)
2871  {
2872  table_iterator p = table.find (name);
2873  if (p == table.end ())
2874  {
2875  if (nest_parent)
2876  return nest_parent->look_nonlocal (name, result);
2877  }
2878  else if (! p->second.is_automatic ())
2879  {
2880  result = p->second;
2881  return true;
2882  }
2883 
2884  return false;
2885  }
2886 };
2887 
2888 extern bool out_of_date_check (octave_value& function,
2889  const std::string& dispatch_type = std::string (),
2890  bool check_relative = true);
2891 
2892 extern OCTINTERP_API std::string
2893 get_dispatch_type (const octave_value_list& args);
2894 extern OCTINTERP_API std::string
2895 get_dispatch_type (const octave_value_list& args, builtin_type_t& builtin_type);
2896 
2897 #endif