comparison src/symtab.cc @ 3013:66a1cede95e7

[project @ 1997-06-02 19:35:05 by jwe]
author jwe
date Mon, 02 Jun 1997 19:41:17 +0000
parents a3556d2adec9
children dcc6c985d72d
comparison
equal deleted inserted replaced
3012:0ea30e0e86cc 3013:66a1cede95e7
26 26
27 #ifdef HAVE_CONFIG_H 27 #ifdef HAVE_CONFIG_H
28 #include <config.h> 28 #include <config.h>
29 #endif 29 #endif
30 30
31 #include <cassert>
31 #include <cctype> 32 #include <cctype>
33 #include <climits>
34
35 #include <iomanip.h>
32 36
33 #include "glob-match.h" 37 #include "glob-match.h"
34 #include "str-vec.h" 38 #include "str-vec.h"
35 39
36 #include "error.h" 40 #include "error.h"
37 #include "oct-lvalue.h" 41 #include "oct-lvalue.h"
38 #include "ov.h" 42 #include "ov.h"
43 #include "pager.h"
39 #include "symtab.h" 44 #include "symtab.h"
40 #include "utils.h" 45 #include "utils.h"
41 #include "variables.h" 46 #include "variables.h"
42 47
43 // Variables and functions. 48 octave_allocator
44 49 symbol_record::symbol_def::allocator (sizeof (symbol_record::symbol_def));
45 symbol_def::symbol_def (void)
46 {
47 init_state ();
48 }
49
50 symbol_def::symbol_def (const octave_value& val, unsigned int sym_type)
51 {
52 init_state ();
53 definition = val;
54 type = sym_type;
55 }
56
57 void
58 symbol_def::init_state (void)
59 {
60 type = UNKNOWN;
61 eternal = 0;
62 read_only = 0;
63
64 next_elem = 0;
65 count = 0;
66 }
67
68 bool
69 symbol_def::is_variable (void) const
70 {
71 return (type & USER_VARIABLE || type & BUILTIN_VARIABLE);
72 }
73
74 bool
75 symbol_def::is_function (void) const
76 {
77 return (type & USER_FUNCTION || type & BUILTIN_FUNCTION);
78 }
79
80 bool
81 symbol_def::is_user_variable (void) const
82 {
83 return (type & USER_VARIABLE);
84 }
85
86 bool
87 symbol_def::is_text_function (void) const
88 {
89 return (type & TEXT_FUNCTION);
90 }
91
92 bool
93 symbol_def::is_mapper_function (void) const
94 {
95 return (type & MAPPER_FUNCTION);
96 }
97
98 bool
99 symbol_def::is_user_function (void) const
100 {
101 return (type & USER_FUNCTION);
102 }
103
104 bool
105 symbol_def::is_builtin_variable (void) const
106 {
107 return (type & BUILTIN_VARIABLE);
108 }
109
110 bool
111 symbol_def::is_builtin_function (void) const
112 {
113 return (type & BUILTIN_FUNCTION);
114 }
115
116 // XXX FIXME XXX
117 bool
118 symbol_def::is_map_element (const string& /* elts */) const
119 {
120 return false;
121 }
122
123 void
124 symbol_def::define (const octave_value& val, unsigned int sym_type)
125 {
126 definition = val;
127
128 type = sym_type;
129 }
130
131 void
132 symbol_def::protect (void)
133 {
134 read_only = 1;
135 }
136
137 void
138 symbol_def::unprotect (void)
139 {
140 read_only = 0;
141
142 }
143
144 void
145 symbol_def::make_eternal (void)
146 {
147 eternal = 1;
148 }
149
150 octave_value&
151 symbol_def::def (void)
152 {
153 return definition;
154 }
155
156 string
157 symbol_def::help (void) const
158 {
159 return help_string;
160 }
161
162 void
163 symbol_def::document (const string& h)
164 {
165 help_string = h;
166 }
167
168 int
169 maybe_delete (symbol_def *def)
170 {
171 int count = 0;
172 if (def && def->count > 0)
173 {
174 def->count--;
175 count = def->count;
176 if (def->count == 0)
177 delete def;
178 }
179 return count;
180 }
181 50
182 // Individual records in a symbol table. 51 // Individual records in a symbol table.
183 52
184 symbol_record::symbol_record (void) 53 // XXX FIXME XXX -- there are lots of places below where we should
185 { 54 // probably be temporarily ignoring interrupts.
186 init_state ();
187 }
188
189 symbol_record::symbol_record (const string& n, symbol_record *nxt)
190 {
191 init_state ();
192 nm = n;
193 next_elem = nxt;
194 }
195
196 void
197 symbol_record::init_state (void)
198 {
199 formal_param = 0;
200 linked_to_global = 0;
201 tagged_static = 0;
202 sv_fcn = 0;
203 definition = 0;
204 next_elem = 0;
205 }
206
207 string
208 symbol_record::name (void) const
209 {
210 return nm;
211 }
212
213 string
214 symbol_record::help (void) const
215 {
216 string retval;
217 if (definition)
218 retval = definition->help ();
219 return retval;
220 }
221
222 octave_value&
223 symbol_record::def (void)
224 {
225 static octave_value foo;
226
227 return definition ? definition->def () : foo;
228 }
229 55
230 void 56 void
231 symbol_record::rename (const string& new_name) 57 symbol_record::rename (const string& new_name)
232 { 58 {
233 if (! read_only_error ("rename")) 59 if (! read_only_error ("rename"))
234 nm = new_name; 60 nm = new_name;
235 } 61 }
236 62
63 void
64 symbol_record::define (const octave_value& v, unsigned int sym_type)
65 {
66 if (! (is_variable () && read_only_error ("redefine")))
67 {
68 if (is_function ())
69 push_def (new symbol_def ());
70
71 if (definition->type () == symbol_record::BUILTIN_VARIABLE)
72 sym_type = symbol_record::BUILTIN_VARIABLE;
73
74 definition->define (v, sym_type);
75 }
76 }
77
78 void
79 symbol_record::define_builtin_var (const octave_value& v)
80 {
81 define (v, symbol_record::BUILTIN_VARIABLE);
82
83 if (chg_fcn)
84 chg_fcn ();
85 }
86
237 bool 87 bool
238 symbol_record::is_function (void) const 88 symbol_record::define_as_fcn (const octave_value& v)
239 { 89 {
240 return definition ? definition->is_function () : false; 90 bool retval = false;
91
92 if (! (is_variable () || read_only_error ("redefine")))
93 {
94 replace_all_defs (new symbol_def (v, symbol_record::BUILTIN_FUNCTION));
95
96 retval = true;
97 }
98
99 return retval;
241 } 100 }
242 101
243 bool 102 bool
244 symbol_record::is_text_function (void) const 103 symbol_record::define (octave_function *f, unsigned int sym_type)
245 { 104 {
246 return definition ? definition->is_text_function () : false; 105 bool retval = false;
247 } 106
248 107 if (! read_only_error ("redefine"))
249 bool 108 {
250 symbol_record::is_mapper_function (void) const 109 octave_value tmp (f);
251 { 110
252 return definition ? definition->is_mapper_function () : false; 111 replace_all_defs (new symbol_def (tmp, sym_type));
253 } 112
254 113 retval = true;
255 bool 114 }
256 symbol_record::is_user_function (void) const 115
257 { 116 return retval;
258 return definition ? definition->is_user_function () : false; 117 }
259 } 118
260 119 void
261 bool 120 symbol_record::clear (void)
262 symbol_record::is_builtin_function (void) const 121 {
263 { 122 if (linked_to_global)
264 return definition ? definition->is_builtin_function () : false; 123 {
265 } 124 if (--definition->count <= 0)
266 125 delete definition;
267 bool 126
268 symbol_record::is_variable (void) const 127 definition = new symbol_def ();
269 { 128
270 return definition ? definition->is_variable () : false; 129 linked_to_global = 0;
271 } 130 }
272 131 else if (! tagged_static)
273 bool 132 {
274 symbol_record::is_user_variable (void) const 133 remove_top_def ();
275 { 134
276 return definition ? definition->is_user_variable () : false;
277 }
278
279 bool
280 symbol_record::is_builtin_variable (void) const
281 {
282 return definition ? definition->is_builtin_variable () : false;
283 }
284
285 bool
286 symbol_record::is_map_element (const string& elts) const
287 {
288 return definition ? definition->is_map_element (elts) : false;
289 }
290
291 unsigned int
292 symbol_record::type (void) const
293 {
294 return definition ? definition->type : false;
295 }
296
297 bool
298 symbol_record::is_defined (void) const
299 {
300 return (definition != 0);
301 }
302
303 bool
304 symbol_record::is_read_only (void) const
305 {
306 return definition ? definition->read_only : false;
307 }
308
309 bool
310 symbol_record::is_eternal (void) const
311 {
312 return definition ? definition->eternal : false;
313 }
314
315 void
316 symbol_record::protect (void)
317 {
318 if (definition)
319 {
320 definition->protect ();
321
322 if (! is_defined ())
323 warning ("protecting undefined variable `%s'", nm.c_str ());
324 }
325 }
326
327 void
328 symbol_record::unprotect (void)
329 {
330 if (definition)
331 definition->unprotect ();
332 }
333
334 void
335 symbol_record::make_eternal (void)
336 {
337 if (definition)
338 {
339 definition->make_eternal ();
340
341 if (! is_defined ())
342 warning ("giving eternal life to undefined variable `%s'",
343 nm.c_str ());
344 }
345 }
346
347 void
348 symbol_record::set_sv_function (sv_function f)
349 {
350 sv_fcn = f;
351 }
352
353 int
354 symbol_record::define (const octave_value& v, unsigned int sym_type)
355 {
356 int retval = 0;
357
358 if (! (is_variable () && read_only_error ("redefine")))
359 {
360 if (! definition) 135 if (! definition)
361 { 136 definition = new symbol_def ();
362 definition = new symbol_def (); 137 }
363 definition->count = 1; 138 }
364 } 139
365 else if (is_function ()) 140 void
366 { 141 symbol_record::alias (symbol_record *s, bool /* force */)
367 push_def (new symbol_def ()); 142 {
368 definition->count = 1; 143 chg_fcn = s->chg_fcn;
369 } 144
370 145 replace_all_defs (s->definition);
371 if (definition->symbol_type () == symbol_def::BUILTIN_VARIABLE) 146
372 sym_type = symbol_def::BUILTIN_VARIABLE; 147 definition->count++;
373
374 definition->define (v, sym_type);
375 }
376
377 return retval;
378 }
379
380 int
381 symbol_record::define_builtin_var (const octave_value& v)
382 {
383 int retval = define (v, symbol_def::BUILTIN_VARIABLE);
384
385 if (sv_fcn)
386 sv_fcn ();
387
388 return retval;
389 }
390
391 int
392 symbol_record::define_as_fcn (const octave_value& v)
393 {
394 if (is_variable () && read_only_error ("redefine"))
395 return 0;
396
397 if (is_variable ())
398 {
399 symbol_def *old_def = pop_def ();
400 maybe_delete (old_def);
401 }
402
403 if (is_function ())
404 {
405 symbol_def *old_def = pop_def ();
406 maybe_delete (old_def);
407 }
408
409 push_def (new symbol_def (v, symbol_def::BUILTIN_FUNCTION));
410
411 definition->count = 1;
412
413 return 1;
414 }
415
416 int
417 symbol_record::define (octave_function *f, unsigned int sym_type)
418 {
419 if (read_only_error ("redefine"))
420 return 0;
421
422 if (is_variable ())
423 {
424 symbol_def *old_def = pop_def ();
425 maybe_delete (old_def);
426 }
427
428 if (is_function ())
429 {
430 symbol_def *old_def = pop_def ();
431 maybe_delete (old_def);
432 }
433
434 octave_value tmp (f);
435
436 push_def (new symbol_def (tmp, sym_type));
437
438 definition->count = 1;
439
440 return 1;
441 }
442
443 void
444 symbol_record::document (const string& h)
445 {
446 if (definition)
447 {
448 definition->document (h);
449
450 if (! is_defined ())
451 warning ("documenting undefined variable `%s'", nm.c_str ());
452 }
453 }
454
455 int
456 symbol_record::clear (void)
457 {
458 int count = 0;
459 if (linked_to_global)
460 {
461 count = maybe_delete (definition);
462 definition = 0;
463 linked_to_global = 0;
464 }
465 else if (! tagged_static)
466 {
467 symbol_def *old_def = pop_def ();
468 count = maybe_delete (old_def);
469 }
470 return count;
471 }
472
473 void
474 symbol_record::alias (symbol_record *s, bool force)
475 {
476 sv_fcn = s->sv_fcn;
477
478 if (force && ! s->definition)
479 {
480 s->definition = new symbol_def ();
481 definition = s->definition;
482 definition->count = 2; // Yes, this is correct.
483 }
484 else if (s->definition)
485 {
486 definition = s->definition;
487 definition->count++;
488 }
489 } 148 }
490 149
491 void 150 void
492 symbol_record::mark_as_formal_parameter (void) 151 symbol_record::mark_as_formal_parameter (void)
493 { 152 {
494 formal_param = 1; 153 if (is_linked_to_global ())
495 } 154 error ("can't mark global variable `%s' as function parameter",
496 155 nm.c_str ());
497 bool 156 else if (is_static ())
498 symbol_record::is_formal_parameter (void) const 157 error ("can't mark static variable `%s' as function paraemter",
499 { 158 nm.c_str ());
500 return formal_param; 159 else
160 formal_param = 1;
501 } 161 }
502 162
503 void 163 void
504 symbol_record::mark_as_linked_to_global (void) 164 symbol_record::mark_as_linked_to_global (void)
505 { 165 {
509 error ("can't make static variable `%s' global", nm.c_str ()); 169 error ("can't make static variable `%s' global", nm.c_str ());
510 else 170 else
511 linked_to_global = 1; 171 linked_to_global = 1;
512 } 172 }
513 173
514 bool
515 symbol_record::is_linked_to_global (void) const
516 {
517 return linked_to_global;
518 }
519
520 void 174 void
521 symbol_record::mark_as_static (void) 175 symbol_record::mark_as_static (void)
522 { 176 {
523 if (is_linked_to_global ()) 177 if (is_linked_to_global ())
524 error ("can't make global variable `%s' static", nm.c_str ()); 178 error ("can't make global variable `%s' static", nm.c_str ());
527 else 181 else
528 tagged_static = 1; 182 tagged_static = 1;
529 } 183 }
530 184
531 bool 185 bool
532 symbol_record::is_static (void) const 186 symbol_record::hides_fcn (void) const
533 { 187 {
534 return tagged_static; 188 bool retval = false;
189
190 if (is_variable () && is_defined ())
191 {
192 symbol_def *hidden_def = definition->next_elem;
193
194 if (hidden_def && hidden_def->is_builtin_function ())
195 retval = true;
196 }
197
198 return retval;
199 }
200
201 bool
202 symbol_record::hides_builtin (void) const
203 {
204 bool retval = false;
205
206 if (is_variable () && is_defined ())
207 {
208 symbol_def *hidden_def = definition->next_elem;
209
210 if (hidden_def && hidden_def->is_user_function ())
211 retval = true;
212 }
213
214 return retval;
535 } 215 }
536 216
537 octave_value& 217 octave_value&
538 symbol_record::variable_value (void) 218 symbol_record::variable_value (void)
539 { 219 {
558 octave_value tmp; 238 octave_value tmp;
559 define (tmp); 239 define (tmp);
560 } 240 }
561 } 241 }
562 242
563 return octave_lvalue (&(def ()), sv_fcn); 243 return octave_lvalue (&(def ()), chg_fcn);
564 }
565
566 symbol_record *
567 symbol_record::next (void) const
568 {
569 return next_elem;
570 }
571
572 void
573 symbol_record::chain (symbol_record *s)
574 {
575 next_elem = s;
576 } 244 }
577 245
578 void 246 void
579 symbol_record::push_context (void) 247 symbol_record::push_context (void)
580 { 248 {
581 if (! is_static ()) 249 if (! is_static ())
582 { 250 {
583 context.push (definition); 251 context.push (definition);
584 definition = 0; 252
253 definition = new symbol_def ();
585 254
586 global_link_context.push (static_cast<unsigned int> (linked_to_global)); 255 global_link_context.push (static_cast<unsigned int> (linked_to_global));
256
587 linked_to_global = 0; 257 linked_to_global = 0;
588 } 258 }
589 } 259 }
590 260
591 void 261 void
595 // inserted in the symbol table during recursive calls. This can 265 // inserted in the symbol table during recursive calls. This can
596 // happen as a result of calls to eval() and feval(). 266 // happen as a result of calls to eval() and feval().
597 267
598 if (! context.empty ()) 268 if (! context.empty ())
599 { 269 {
270 replace_all_defs (context.pop ());
271
272 linked_to_global = global_link_context.pop ();
273 }
274 }
275
276 void
277 symbol_record::print_symbol_info_line (ostream& os)
278 {
279 os << (is_read_only () ? " r-" : " rw")
280 << (is_eternal () ? "-" : "d")
281 #if 0
282 << (hides_fcn () ? "f" : (hides_builtin () ? "F" : "-"))
283 #endif
284 << " "
285 << setiosflags (ios::left) << setw (24) << type_name () . c_str ();
286
287 os << resetiosflags (ios::left);
288
289 int nr = rows ();
290 int nc = columns ();
291
292 if (nr < 0)
293 os << " -";
294 else
295 os << setiosflags (ios::right) << setw (7) << nr;
296
297 if (nc < 0)
298 os << " -";
299 else
300 os << setiosflags (ios::right) << setw (7) << nc;
301
302 os << resetiosflags (ios::right);
303
304 os << " " << name () << "\n";
305 }
306
307 bool
308 symbol_record::read_only_error (const char *action)
309 {
310 if (is_read_only ())
311 {
600 if (is_variable ()) 312 if (is_variable ())
601 { 313 ::error ("can't %s read-only constant `%s'", action, nm.c_str ());
602 symbol_def *old_def = pop_def ();
603 maybe_delete (old_def);
604 }
605
606 if (is_function ())
607 {
608 symbol_def *old_def = pop_def ();
609 maybe_delete (old_def);
610 }
611
612 definition = context.pop ();
613 linked_to_global = global_link_context.pop ();
614 }
615 }
616
617 int
618 symbol_record::read_only_error (const char *action)
619 {
620 if (is_read_only ())
621 {
622 if (is_variable ())
623 {
624 ::error ("can't %s read-only constant `%s'", action, nm.c_str ());
625 }
626 else if (is_function ()) 314 else if (is_function ())
627 { 315 ::error ("can't %s read-only function `%s'", action, nm.c_str ());
628 ::error ("can't %s read-only function `%s'", action, nm.c_str ());
629 }
630 else 316 else
631 { 317 ::error ("can't %s read-only symbol `%s'", action, nm.c_str ());
632 ::error ("can't %s read-only symbol `%s'", action, nm.c_str ()); 318
633 } 319 return true;
634
635 return 1;
636 } 320 }
637 else 321 else
638 return 0; 322 return false;
639 } 323 }
640 324
641 void 325 void
642 symbol_record::push_def (symbol_def *sd) 326 symbol_record::push_def (symbol_def *sd)
643 { 327 {
644 if (! sd) 328 if (! sd)
645 return; 329 return;
646 330
331 assert (definition == 0 || definition->next_elem == 0);
332
647 sd->next_elem = definition; 333 sd->next_elem = definition;
334
648 definition = sd; 335 definition = sd;
649 } 336 }
650 337
651 symbol_def * 338 void
652 symbol_record::pop_def (void) 339 symbol_record::remove_top_def (void)
653 { 340 {
654 symbol_def *top = definition; 341 symbol_def *top = definition;
655 if (definition) 342
656 definition = definition->next_elem; 343 definition = definition->next_elem;
657 return top; 344
658 } 345 if (--top->count <= 0)
659 346 delete top;
660 // A structure for handling verbose information about a symbol_record. 347 }
661 348
662 symbol_record_info::symbol_record_info (void) 349 void
663 : initialized (0), nr (-1), nc (-1), type (symbol_def::UNKNOWN), 350 symbol_record::replace_all_defs (symbol_def *sd)
664 hides (SR_INFO_NONE), eternal (0), read_only (0), nm (), 351 {
665 const_type () { } 352 while (definition)
666 353 remove_top_def ();
667 symbol_record_info::symbol_record_info (symbol_record& sr) 354
668 : initialized (0), nr (-1), nc (-1), type (sr.type ()), 355 push_def (sd);
669 hides (SR_INFO_NONE), eternal (0), read_only (0), nm (),
670 const_type ()
671 {
672 if (sr.is_variable () && sr.is_defined ())
673 {
674 octave_value tmp = sr.def ();
675
676 const_type = tmp.type_name ();
677
678 nr = tmp.rows ();
679 nc = tmp.columns ();
680
681 symbol_def *sr_def = sr.definition;
682 symbol_def *hidden_def = sr_def->next_elem;
683
684 if (hidden_def)
685 {
686 if (hidden_def->is_user_function ())
687 hides = SR_INFO_USER_FUNCTION;
688 else if (hidden_def->is_builtin_function ())
689 hides = SR_INFO_BUILTIN_FUNCTION;
690 }
691 }
692
693 eternal = sr.is_eternal ();
694 read_only = sr.is_read_only ();
695
696 nm = sr.name ();
697
698 initialized = 1;
699 }
700
701 symbol_record_info::symbol_record_info (const symbol_record_info& s)
702 : initialized (s.initialized), nr (s.nr), nc (s.nc), type (s.type),
703 hides (s.hides), eternal (s.eternal), read_only (s.read_only),
704 nm (s.nm), const_type (s.const_type) { }
705
706 symbol_record_info&
707 symbol_record_info::operator = (const symbol_record_info& s)
708 {
709 if (this != &s)
710 {
711 initialized = s.initialized;
712 nr = s.nr;
713 nc = s.nc;
714 type = s.type;
715 hides = s.hides;
716 eternal = s.eternal;
717 read_only = s.read_only;
718 nm = s.nm;
719 const_type = s.const_type;
720 }
721 return *this;
722 }
723
724 bool
725 symbol_record_info::is_defined (void) const
726 {
727 return initialized;
728 }
729
730 bool
731 symbol_record_info::is_read_only (void) const
732 {
733 return read_only;
734 }
735
736 bool
737 symbol_record_info::is_eternal (void) const
738 {
739 return eternal;
740 }
741
742 bool
743 symbol_record_info::hides_fcn (void) const
744 {
745 return (hides & SR_INFO_USER_FUNCTION);
746 }
747
748 bool
749 symbol_record_info::hides_builtin (void) const
750 {
751 return (hides & SR_INFO_BUILTIN_FUNCTION);
752 }
753
754 string
755 symbol_record_info::type_name (void) const
756 {
757 string retval;
758
759 if (type == symbol_def::USER_FUNCTION)
760 retval = "user function";
761 else if (type & symbol_def::BUILTIN_FUNCTION)
762 {
763 if (type & symbol_def::TEXT_FUNCTION)
764 retval = "text function";
765 else if (type & symbol_def::MAPPER_FUNCTION)
766 retval = "mapper function";
767 else
768 retval = "builtin function";
769 }
770 else
771 retval = const_type;
772
773 return retval;
774 }
775
776 bool
777 symbol_record_info::is_function (void) const
778 {
779 return (type == symbol_def::USER_FUNCTION
780 || type == symbol_def::BUILTIN_FUNCTION
781 || symbol_def::TEXT_FUNCTION
782 || symbol_def::MAPPER_FUNCTION);
783 }
784
785 int
786 symbol_record_info::rows (void) const
787 {
788 return nr;
789 }
790
791 int
792 symbol_record_info::columns (void) const
793 {
794 return nc;
795 }
796
797 string
798 symbol_record_info::name (void) const
799 {
800 return nm;
801 } 356 }
802 357
803 // A symbol table. 358 // A symbol table.
804
805 symbol_table::symbol_table (void)
806 {
807 }
808 359
809 symbol_record * 360 symbol_record *
810 symbol_table::lookup (const string& nm, bool insert, bool warn) 361 symbol_table::lookup (const string& nm, bool insert, bool warn)
811 { 362 {
812 int index = hash (nm) & HASH_MASK; 363 unsigned int index = hash (nm);
813 364
814 symbol_record *ptr = table[index].next (); 365 symbol_record *ptr = table[index].next ();
815 366
816 while (ptr) 367 while (ptr)
817 { 368 {
818 if (ptr->name () == nm) 369 if (ptr->name () == nm)
819 return ptr; 370 return ptr;
371
820 ptr = ptr->next (); 372 ptr = ptr->next ();
821 } 373 }
822 374
823 if (insert) 375 if (insert)
824 { 376 {
825 symbol_record *new_sym; 377 symbol_record *sr = new symbol_record (nm, table[index].next ());
826 new_sym = new symbol_record (nm, table[index].next ()); 378
827 table[index].chain (new_sym); 379 table[index].chain (sr);
828 return new_sym; 380
381 return sr;
829 } 382 }
830 else if (warn) 383 else if (warn)
831 warning ("lookup: symbol`%s' not found", nm.c_str ()); 384 warning ("lookup: symbol`%s' not found", nm.c_str ());
832 385
833 return 0; 386 return 0;
834 } 387 }
835 388
836 void 389 void
837 symbol_table::rename (const string& old_name, const string& new_name) 390 symbol_table::rename (const string& old_name, const string& new_name)
838 { 391 {
839 int index = hash (old_name) & HASH_MASK; 392 unsigned int index = hash (old_name);
840 393
841 symbol_record *prev = &table[index]; 394 symbol_record *prev = &table[index];
842 symbol_record *ptr = prev->next (); 395 symbol_record *ptr = prev->next ();
843 396
844 while (ptr) 397 while (ptr)
849 402
850 if (! error_state) 403 if (! error_state)
851 { 404 {
852 prev->chain (ptr->next ()); 405 prev->chain (ptr->next ());
853 406
854 index = hash (new_name) & HASH_MASK; 407 index = hash (new_name);
855 table[index].chain (ptr); 408 table[index].chain (ptr);
856 409
857 return; 410 return;
858 } 411 }
859 412
869 } 422 }
870 423
871 void 424 void
872 symbol_table::clear (bool clear_user_functions) 425 symbol_table::clear (bool clear_user_functions)
873 { 426 {
874 for (int i = 0; i < HASH_TABLE_SIZE; i++) 427 for (unsigned int i = 0; i < table_size; i++)
875 { 428 {
876 symbol_record *ptr = table[i].next (); 429 symbol_record *ptr = table[i].next ();
877 430
878 while (ptr) 431 while (ptr)
879 { 432 {
886 ptr = ptr->next (); 439 ptr = ptr->next ();
887 } 440 }
888 } 441 }
889 } 442 }
890 443
891 int 444 bool
892 symbol_table::clear (const string& nm, bool clear_user_functions) 445 symbol_table::clear (const string& nm, bool clear_user_functions)
893 { 446 {
894 int index = hash (nm) & HASH_MASK; 447 unsigned int index = hash (nm);
895 448
896 symbol_record *ptr = table[index].next (); 449 symbol_record *ptr = table[index].next ();
897 450
898 while (ptr) 451 while (ptr)
899 { 452 {
900 if (ptr->name () == nm 453 if (ptr->name () == nm
901 && (ptr->is_user_variable () 454 && (ptr->is_user_variable ()
902 || (clear_user_functions && ptr->is_user_function ()))) 455 || (clear_user_functions && ptr->is_user_function ())))
903 { 456 {
904 ptr->clear (); 457 ptr->clear ();
905 return 1; 458 return true;
906 } 459 }
907 ptr = ptr->next (); 460 ptr = ptr->next ();
908 } 461 }
909 462
910 return 0; 463 return false;
911 } 464 }
912 465
913 int 466 int
914 symbol_table::size (void) const 467 symbol_table::size (void) const
915 { 468 {
916 int count = 0; 469 int count = 0;
917 for (int i = 0; i < HASH_TABLE_SIZE; i++) 470
471 for (unsigned int i = 0; i < table_size; i++)
918 { 472 {
919 symbol_record *ptr = table[i].next (); 473 symbol_record *ptr = table[i].next ();
474
920 while (ptr) 475 while (ptr)
921 { 476 {
922 count++; 477 count++;
923 ptr = ptr->next (); 478 ptr = ptr->next ();
924 } 479 }
925 } 480 }
481
926 return count; 482 return count;
927 } 483 }
928 484
929 static inline int 485 static bool
930 pstrcmp (char **a, char **b) 486 matches_patterns (const string& name, const string_vector& pats)
931 { 487 {
932 return strcmp (*a, *b); 488 int npats = pats.length ();
933 } 489
934 490 if (npats == 0)
935 static inline int 491 return true;
936 symbol_record_info_cmp (symbol_record_info *a, symbol_record_info *b) 492
937 { 493 glob_match pattern (pats);
938 return (a->name () == b->name ()); 494
495 return pattern.match (name);
496 }
497
498 Array<symbol_record *>
499 symbol_table::symbol_list (int& count, const string_vector& pats,
500 unsigned int type, unsigned int scope) const
501 {
502 count = 0;
503
504 int n = size ();
505
506 if (n == 0)
507 return 0;
508
509 Array<symbol_record *> symbols (n);
510
511 for (unsigned int i = 0; i < table_size; i++)
512 {
513 symbol_record *ptr = table[i].next ();
514
515 while (ptr)
516 {
517 assert (count < n);
518
519 unsigned int my_scope = ptr->is_linked_to_global () + 1; // Tricky...
520
521 unsigned int my_type = ptr->type ();
522
523 string my_name = ptr->name ();
524
525 if ((type & my_type) && (scope & my_scope)
526 && matches_patterns (my_name, pats))
527 symbols(count++) = ptr;
528
529 ptr = ptr->next ();
530 }
531 }
532
533 symbols.resize (count);
534
535 return symbols;
536 }
537
538 string_vector
539 symbol_table::name_list (int& count, const string_vector& pats, bool sort,
540 unsigned int type, unsigned int scope) const
541 {
542 Array<symbol_record *> symbols
543 = symbol_list (count, pats, type, scope);
544
545 string_vector names;
546
547 int n = symbols.length ();
548
549 if (n > 0)
550 {
551 names.resize (n);
552
553 for (int i = 0; i < n; i++)
554 names[i] = symbols(i)->name ();
555 }
556
557 if (sort)
558 names.qsort ();
559
560 return names;
939 } 561 }
940 562
941 static int 563 static int
942 matches_patterns (const string& name, const string_vector& pats, int npats) 564 maybe_list_cmp_fcn (symbol_record **a_arg, symbol_record **b_arg)
943 { 565 {
944 for (int i = 0; i < npats; i++) 566 string a = (*a_arg)->name ();
945 { 567 string b = (*b_arg)->name ();
946 glob_match pattern (pats[i]); 568
947 if (pattern.match (name)) 569 return a.compare (b);
948 return 1; 570 }
949 } 571
950 572 int
951 return 0; 573 symbol_table::maybe_list (const char *header, const string_vector& argv,
952 } 574 ostream& os, bool show_verbose,
953 575 unsigned type, unsigned scope)
954 // This function should probably share code with symbol_table::list. 576 {
955 // XXX FIXME XXX 577 int count;
956 578
957 symbol_record_info * 579 int status = 0;
958 symbol_table::long_list (int& count, const string_vector& pats, 580
959 int npats, bool sort, unsigned int type, 581 if (show_verbose)
960 unsigned int scope) const 582 {
583 Array<symbol_record *> symbols = symbol_list (count, argv, type, scope);
584
585 int len = symbols.length ();
586
587 if (len > 0 && count > 0)
588 {
589 os << "\n" << header << "\n\n"
590 << "prot type rows cols name\n"
591 << "==== ==== ==== ==== ====\n";
592
593 symbols.qsort (maybe_list_cmp_fcn);
594
595 for (int i = 0; i < len; i++)
596 symbols(i)->print_symbol_info_line (os);
597
598 status = 1;
599 }
600 }
601 else
602 {
603 string_vector symbols = name_list (count, argv, 1, type, scope);
604
605 if (symbols.length () > 0 && count > 0)
606 {
607 os << "\n" << header << "\n\n";
608
609 symbols.list_in_columns (os);
610
611 status = 1;
612 }
613 }
614
615 return status;
616 }
617
618 symbol_record **
619 symbol_table::glob (int& count, const string& pat, unsigned int type,
620 unsigned int scope) const
961 { 621 {
962 count = 0; 622 count = 0;
963 int n = size (); 623 int n = size ();
964 if (n == 0) 624 if (n == 0)
965 return 0; 625 return 0;
966 626
967 symbol_record_info *symbols = new symbol_record_info [n+1]; 627 symbol_record **symbols = new symbol_record * [n+1];
968 for (int i = 0; i < HASH_TABLE_SIZE; i++) 628
629 for (unsigned int i = 0; i < table_size; i++)
969 { 630 {
970 symbol_record *ptr = table[i].next (); 631 symbol_record *ptr = table[i].next ();
971 while (ptr) 632
972 {
973 assert (count < n);
974
975 unsigned int my_scope = ptr->is_linked_to_global () + 1; // Tricky...
976
977 unsigned int my_type = ptr->type ();
978
979 string my_name = ptr->name ();
980
981 if ((type & my_type) && (scope & my_scope)
982 && (npats == 0 || matches_patterns (my_name, pats, npats)))
983 symbols[count++] = symbol_record_info (*ptr);
984
985 ptr = ptr->next ();
986 }
987 }
988 symbols[count] = symbol_record_info ();
989
990 if (sort && symbols)
991 qsort (symbols, count, sizeof (symbol_record_info),
992 symbol_record_info_cmp);
993
994 return symbols;
995 }
996
997 string_vector
998 symbol_table::list (int& count, const string_vector& pats, int npats,
999 bool sort, unsigned int type, unsigned int scope) const
1000 {
1001 count = 0;
1002 int n = size ();
1003 if (n == 0)
1004 return 0;
1005
1006 string_vector symbols (n);
1007
1008 for (int i = 0; i < HASH_TABLE_SIZE; i++)
1009 {
1010 symbol_record *ptr = table[i].next ();
1011 while (ptr)
1012 {
1013 assert (count < n);
1014
1015 unsigned int my_scope = ptr->is_linked_to_global () + 1; // Tricky...
1016
1017 unsigned int my_type = ptr->type ();
1018
1019 string my_name = ptr->name ();
1020
1021 if ((type & my_type) && (scope & my_scope)
1022 && (npats == 0 || matches_patterns (my_name, pats, npats)))
1023 symbols[count++] = ptr->name ();
1024
1025 ptr = ptr->next ();
1026 }
1027 }
1028
1029 symbols.resize (count);
1030
1031 if (sort && ! symbols.empty ())
1032 symbols.qsort ();
1033
1034 return symbols;
1035 }
1036
1037 symbol_record **
1038 symbol_table::glob (int& count, const string& pat, unsigned int type,
1039 unsigned int scope) const
1040 {
1041 count = 0;
1042 int n = size ();
1043 if (n == 0)
1044 return 0;
1045
1046 symbol_record **symbols = new symbol_record * [n+1];
1047 for (int i = 0; i < HASH_TABLE_SIZE; i++)
1048 {
1049 symbol_record *ptr = table[i].next ();
1050 while (ptr) 633 while (ptr)
1051 { 634 {
1052 assert (count < n); 635 assert (count < n);
1053 636
1054 unsigned int my_scope = ptr->is_linked_to_global () + 1; // Tricky... 637 unsigned int my_scope = ptr->is_linked_to_global () + 1; // Tricky...
1072 } 655 }
1073 656
1074 void 657 void
1075 symbol_table::push_context (void) 658 symbol_table::push_context (void)
1076 { 659 {
1077 for (int i = 0; i < HASH_TABLE_SIZE; i++) 660 for (unsigned int i = 0; i < table_size; i++)
1078 { 661 {
1079 symbol_record *ptr = table[i].next (); 662 symbol_record *ptr = table[i].next ();
1080 663
1081 while (ptr) 664 while (ptr)
1082 { 665 {
1087 } 670 }
1088 671
1089 void 672 void
1090 symbol_table::pop_context (void) 673 symbol_table::pop_context (void)
1091 { 674 {
1092 for (int i = 0; i < HASH_TABLE_SIZE; i++) 675 for (unsigned int i = 0; i < table_size; i++)
1093 { 676 {
1094 symbol_record *ptr = table[i].next (); 677 symbol_record *ptr = table[i].next ();
1095 678
1096 while (ptr) 679 while (ptr)
1097 { 680 {
1099 ptr = ptr->next (); 682 ptr = ptr->next ();
1100 } 683 }
1101 } 684 }
1102 } 685 }
1103 686
687 void
688 symbol_table::print_stats (void)
689 {
690 int count = 0;
691 int empty_chains = 0;
692 int max_chain_length = 0;
693 int min_chain_length = INT_MAX;
694
695 for (unsigned int i = 0; i < table_size; i++)
696 {
697 int num_this_chain = 0;
698
699 symbol_record *ptr = table[i].next ();
700
701 if (ptr)
702 octave_stdout << "chain number " << i << ":\n";
703 else
704 {
705 empty_chains++;
706 min_chain_length = 0;
707 }
708
709 while (ptr)
710 {
711 num_this_chain++;
712
713 octave_stdout << " " << ptr->name () << "\n";
714
715 ptr = ptr->next ();
716 }
717
718 count += num_this_chain;
719
720 if (num_this_chain > max_chain_length)
721 max_chain_length = num_this_chain;
722
723 if (num_this_chain < min_chain_length)
724 min_chain_length = num_this_chain;
725
726 if (num_this_chain > 0)
727 octave_stdout << "\n";
728 }
729
730 octave_stdout << "max chain length: " << max_chain_length << "\n";
731 octave_stdout << "min chain length: " << min_chain_length << "\n";
732 octave_stdout << "empty chains: " << empty_chains << "\n";
733 octave_stdout << "total chains: " << table_size << "\n";
734 octave_stdout << "total symbols: " << count << "\n";
735 }
736
1104 // Chris Torek's fave hash function. 737 // Chris Torek's fave hash function.
1105 738
1106 unsigned int 739 unsigned int
1107 symbol_table::hash (const string& str) 740 symbol_table::hash (const string& str)
1108 { 741 {
1109 unsigned int h = 0; 742 unsigned int h = 0;
743
1110 for (unsigned int i = 0; i < str.length (); i++) 744 for (unsigned int i = 0; i < str.length (); i++)
1111 h = h * 33 + str[i]; 745 h = h * 33 + str[i];
1112 return h; 746
1113 } 747 return h & (table_size - 1);
1114
1115 // Return nonzero if S is a valid identifier.
1116
1117 bool
1118 valid_identifier (const char *s)
1119 {
1120 if (! s || ! (isalnum (*s) || *s == '_'))
1121 return false;
1122
1123 while (*++s != '\0')
1124 if (! (isalnum (*s) || *s == '_'))
1125 return false;
1126
1127 return true;
1128 }
1129
1130 bool
1131 valid_identifier (const string& s)
1132 {
1133 return valid_identifier (s.c_str ());
1134 } 748 }
1135 749
1136 /* 750 /*
1137 ;;; Local Variables: *** 751 ;;; Local Variables: ***
1138 ;;; mode: C++ *** 752 ;;; mode: C++ ***