Mercurial > hg > octave-avbm
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++ *** |