comparison src/symtab.cc @ 1:78fd87e624cb

[project @ 1993-08-08 01:13:40 by jwe] Initial revision
author jwe
date Sun, 08 Aug 1993 01:13:40 +0000
parents
children e4acc68c9c60
comparison
equal deleted inserted replaced
0:22412e3a4641 1:78fd87e624cb
1 // Symbol table classes. -*- C++ -*-
2 /*
3
4 Copyright (C) 1992, 1993 John W. Eaton
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 2, or (at your option) any
11 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, write to the Free
20 Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23
24 #ifdef __GNUG__
25 #pragma implementation
26 #endif
27
28 // Don't even think about moving the tree.h include to symtab.h...
29
30 #include "symtab.h"
31 #include "error.h"
32 #include "variables.h"
33 #include "utils.h"
34 #include "tree.h"
35 #include "tree-const.h"
36
37 /*
38 * Variables and functions.
39 */
40 symbol_def::symbol_def (void)
41 {
42 help_string = (char *) NULL;
43 type = unknown_type;
44 lifespan = temporary;
45 sym_class = read_write;
46 definition = (tree *) NULL;
47 }
48
49 symbol_def::symbol_def (tree_constant *t)
50 {
51 help_string = (char *) NULL;
52 type = variable;
53 lifespan = temporary;
54 sym_class = read_write;
55 definition = t;
56 }
57
58 symbol_def::symbol_def (tree_builtin *t)
59 {
60 help_string = (char *) NULL;
61 type = builtin_function;
62 lifespan = temporary;
63 sym_class = read_write;
64 definition = t;
65 }
66
67 symbol_def::symbol_def (tree_function *t)
68 {
69 help_string = (char *) NULL;
70 type = user_function;
71 lifespan = temporary;
72 sym_class = read_write;
73 definition = t;
74 }
75
76 symbol_def::~symbol_def (void)
77 {
78 delete [] help_string;
79 delete definition;
80 }
81
82 void
83 symbol_def::define (tree_constant *t)
84 {
85 definition = t;
86 type = variable;
87 }
88
89 void
90 symbol_def::define (tree_builtin *t)
91 {
92 definition = t;
93 type = builtin_function;
94 }
95
96 void
97 symbol_def::define (tree_function *t)
98 {
99 definition = t;
100 type = user_function;
101 }
102
103 tree *
104 symbol_def::def (void)
105 {
106 return definition;
107 }
108
109 char *
110 symbol_def::help (void)
111 {
112 return help_string;
113 }
114
115 void
116 symbol_def::document (char *h)
117 {
118 delete [] help_string;
119 help_string = strsave (h);
120 }
121
122 int
123 symbol_def::save (ostream& os, int mark_as_global)
124 {
125 return definition->save (os, mark_as_global);
126 }
127
128 /*
129 * Individual records in a symbol table.
130 */
131 symbol_record::symbol_record (void)
132 {
133 nm = (char *) NULL;
134 formal_param = 0;
135 var = (symbol_def *) NULL;
136 fcn = (symbol_def *) NULL;
137 sv_fcn = (sv_Function) NULL;
138 next_elem = (symbol_record *) NULL;
139 }
140
141 symbol_record::symbol_record (char *n)
142 {
143 nm = strsave (n);
144 formal_param = 0;
145 var = (symbol_def *) NULL;
146 fcn = (symbol_def *) NULL;
147 sv_fcn = (sv_Function) NULL;
148 next_elem = (symbol_record *) NULL;
149 }
150
151 symbol_record::symbol_record (char *n, symbol_record *nxt)
152 {
153 nm = strsave (n);
154 formal_param = 0;
155 var = (symbol_def *) NULL;
156 fcn = (symbol_def *) NULL;
157 sv_fcn = (sv_Function) NULL;
158 next_elem = nxt;
159 }
160
161 symbol_record::~symbol_record (void)
162 {
163 delete [] nm;
164
165 if (var != (symbol_def *) NULL && --var->count <= 0)
166 delete var;
167
168 if (fcn != (symbol_def *) NULL && --fcn->count <= 0)
169 delete fcn;
170 }
171
172 char *
173 symbol_record::name (void)
174 {
175 return nm;
176 }
177
178 char *
179 symbol_record::help (void)
180 {
181 if (var != (symbol_def *) NULL)
182 return var->help ();
183 else if (fcn != (symbol_def *) NULL)
184 return fcn->help ();
185 else
186 return (char *) NULL;
187 }
188
189 tree *
190 symbol_record::def (void)
191 {
192 if (var != (symbol_def *) NULL)
193 return var->def ();
194 else if (fcn != (symbol_def *) NULL)
195 return fcn->def ();
196 else
197 return (tree *) NULL;
198 }
199
200 int
201 symbol_record::is_function (void)
202 {
203 return (var == (symbol_def *) NULL && fcn != (symbol_def *) NULL);
204 }
205
206 int
207 symbol_record::is_variable (void)
208 {
209 return (var != (symbol_def *) NULL);
210 }
211
212 int
213 symbol_record::is_defined (void)
214 {
215 return (var != (symbol_def *) NULL || fcn != (symbol_def *) NULL);
216 }
217
218 void
219 symbol_record::set_sv_function (sv_Function f)
220 {
221 sv_fcn = f;
222 }
223
224 int
225 symbol_record::var_read_only (void)
226 {
227 if (var != (symbol_def *) NULL
228 && var->sym_class == symbol_def::read_only)
229 {
230 error ("can't assign to read only symbol `%s'", nm);
231 return 1;
232 }
233 else
234 return 0;
235 }
236
237 int
238 symbol_record::read_only (void)
239 {
240 if ((var != (symbol_def *) NULL
241 && var->sym_class == symbol_def::read_only)
242 || (fcn != (symbol_def *) NULL
243 && fcn->sym_class == symbol_def::read_only))
244 {
245 error ("can't assign to read only symbol `%s'", nm);
246 return 1;
247 }
248 else
249 return 0;
250 }
251
252 int
253 symbol_record::define (tree_constant *t)
254 {
255 if (var_read_only ())
256 return 0;
257
258 tree_constant *saved_def = NULL_TREE_CONST;
259
260 if (var != (symbol_def *) NULL)
261 {
262 saved_def = (tree_constant *) var->def (); // XXX FIXME XXX
263 var->define (t);
264 }
265 else
266 {
267 var = new symbol_def (t);
268 var->count = 1;
269 }
270
271 if (sv_fcn != (sv_Function) NULL && sv_fcn () < 0)
272 {
273 var->define (saved_def);
274 delete t;
275 return 0;
276 }
277
278 delete saved_def;
279
280 return 1;
281 }
282
283 int
284 symbol_record::define (tree_builtin *t)
285 {
286 if (read_only ())
287 return 0;
288
289 if (var != (symbol_def *) NULL)
290 {
291 if (--var->count <= 0)
292 delete var;
293 var = (symbol_def *) NULL;
294 }
295
296 if (fcn != (symbol_def *) NULL)
297 fcn->define (t);
298 else
299 {
300 fcn = new symbol_def (t);
301 fcn->count = 1;
302 }
303
304 return 1;
305 }
306
307 int
308 symbol_record::define (tree_function *t)
309 {
310 if (read_only ())
311 return 0;
312
313 if (var != (symbol_def *) NULL)
314 {
315 if (--var->count <= 0)
316 delete var;
317 var = (symbol_def *) NULL;
318 }
319
320 if (fcn != (symbol_def *) NULL)
321 fcn->define (t);
322 else
323 {
324 fcn = new symbol_def (t);
325 fcn->count = 1;
326 }
327
328 return 1;
329 }
330
331 int
332 symbol_record::define_as_fcn (tree_constant *t)
333 {
334 if (read_only ())
335 return 0;
336
337 if (var != (symbol_def *) NULL)
338 {
339 if (--var->count <= 0)
340 delete var;
341 var = (symbol_def *) NULL;
342 }
343
344 if (fcn != (symbol_def *) NULL)
345 fcn->define (t);
346 else
347 {
348 fcn = new symbol_def (t);
349 fcn->count = 1;
350 }
351
352 return 1;
353 }
354
355 void
356 symbol_record::document (char *h)
357 {
358 if (var != (symbol_def *) NULL)
359 var->document (h);
360 else if (fcn != (symbol_def *) NULL)
361 fcn->document (h);
362 else
363 warning ("couldn't document undefined variable `%s'", nm);
364 }
365
366 void
367 symbol_record::protect (void)
368 {
369 if (var != (symbol_def *) NULL)
370 var->sym_class = symbol_def::read_only;
371 else if (fcn != (symbol_def *) NULL)
372 fcn->sym_class = symbol_def::read_only;
373 else
374 warning ("couldn't protect undefined variable `%s'", nm);
375 }
376
377 void
378 symbol_record::unprotect (void)
379 {
380 if (var != (symbol_def *) NULL)
381 var->sym_class = symbol_def::read_write;
382 else if (fcn != (symbol_def *) NULL)
383 fcn->sym_class = symbol_def::read_write;
384 }
385
386 void
387 symbol_record::make_eternal (void)
388 {
389 if (var != (symbol_def *) NULL)
390 var->lifespan = symbol_def::eternal;
391 else if (fcn != (symbol_def *) NULL)
392 fcn->lifespan = symbol_def::eternal;
393 else
394 warning ("couldn't give eternal life to the variable `%s'", nm);
395 }
396
397 int
398 symbol_record::save (ostream& os, int mark_as_global = 0)
399 {
400 int status = 0;
401
402 if (var != (symbol_def *) NULL && var->def () != (tree *) NULL)
403 {
404 // For now, eternal implies builtin.
405 if (var->lifespan != symbol_def::eternal)
406 {
407 // Should we also save the help string? Maybe someday.
408 os << "# name: " << nm << "\n";
409 status = var->save (os, mark_as_global);
410 }
411 }
412 else if (fcn != (symbol_def *) NULL)
413 message ("save", "sorry, can't save functions yet");
414 else
415 message ("save", "can't save undefined symbols!");
416
417 return status;
418 }
419
420 void
421 symbol_record::clear_visible (void)
422 {
423 if (var != (symbol_def *) NULL && var->lifespan != symbol_def::eternal)
424 {
425 if (--var->count <= 0)
426 delete var;
427 var = (symbol_def *) NULL;
428 }
429 else if (fcn != (symbol_def *) NULL && fcn->lifespan != symbol_def::eternal)
430 {
431 if (--fcn->count <= 0)
432 delete fcn;
433 fcn = (symbol_def *) NULL;
434 }
435 }
436
437 void
438 symbol_record::clear_all (void)
439 {
440 if (var != (symbol_def *) NULL && var->lifespan != symbol_def::eternal)
441 {
442 if (--var->count <= 0)
443 delete var;
444 var = (symbol_def *) NULL;
445 }
446
447 if (fcn != (symbol_def *) NULL && fcn->lifespan != symbol_def::eternal)
448 {
449 if (--fcn->count <= 0)
450 delete fcn;
451 fcn = (symbol_def *) NULL;
452 }
453 }
454
455 void
456 symbol_record::undefine (void)
457 {
458 if (var != (symbol_def *) NULL)
459 {
460 if (--var->count <= 0)
461 delete var;
462 var = (symbol_def *) NULL;
463 }
464
465 if (fcn != (symbol_def *) NULL)
466 {
467 if (--fcn->count <= 0)
468 delete fcn;
469 fcn = (symbol_def *) NULL;
470 }
471 }
472
473 void
474 symbol_record::mark_as_formal_parameter (void)
475 {
476 formal_param = 1;
477 }
478
479 int
480 symbol_record::is_formal_parameter (void)
481 {
482 return formal_param;
483 }
484
485 void
486 symbol_record::alias (symbol_record *s, int force = 0)
487 {
488 sv_fcn = s->sv_fcn; // Maybe this should go in the var symbol_def?
489
490 formal_param = s->formal_param; // Hmm.
491
492 if (force && s->var == (symbol_def *) NULL
493 && s->fcn == (symbol_def *) NULL)
494 {
495 s->var = new symbol_def ();
496 var = s->var;
497 var->count = 2; // Yes, this is correct.
498 return;
499 }
500
501 if (s->var != (symbol_def *) NULL)
502 {
503 var = s->var;
504 var->count++;
505 }
506 else if (s->fcn != (symbol_def *) NULL)
507 {
508 fcn = s->fcn;
509 fcn->count++;
510 }
511 }
512
513 symbol_record *
514 symbol_record::next (void)
515 {
516 return next_elem;
517 }
518
519 /*
520 * A symbol table.
521 */
522
523 symbol_table::symbol_table (void)
524 {
525 }
526
527 symbol_record *
528 symbol_table::lookup (char *nm, int insert = 0, int warn = 0)
529 {
530 int index = hash (nm) & HASH_MASK;
531
532 symbol_record *ptr = table[index].next ();
533
534 while (ptr != (symbol_record *) NULL)
535 {
536 if (strcmp (ptr->name (), nm) == 0)
537 return ptr;
538 ptr = ptr->next ();
539 }
540
541 if (insert)
542 {
543 symbol_record *new_sym;
544 new_sym = new symbol_record (nm, table[index].next ());
545 table[index].next_elem = new_sym;
546 return new_sym;
547 }
548 else if (warn)
549 message ("lookup", "symbol`%s' not found", nm);
550
551 return (symbol_record *) NULL;
552 }
553
554 void
555 symbol_table::clear (void)
556 {
557 for (int i = 0; i < HASH_TABLE_SIZE; i++)
558 {
559 symbol_record *prev = &table[i];
560 symbol_record *curr = prev->next ();
561
562 while (curr != (symbol_record *) NULL)
563 {
564 curr->clear_all ();
565
566 // This record might have been read only. If so, we shouldn't delete
567 // it from the table.
568 if (curr->is_defined ())
569 {
570 prev = curr;
571 curr = curr->next ();
572 }
573 else
574 {
575 prev->next_elem = curr->next ();
576 symbol_record *tmp = curr;
577 curr = curr->next ();
578 delete tmp;
579 }
580 }
581 }
582 }
583
584 int
585 symbol_table::clear (char *nm)
586 {
587 int index = hash (nm) & HASH_MASK;
588
589 symbol_record *prev = &table[index];
590 symbol_record *curr = prev->next ();
591
592 while (curr != (symbol_record *) NULL)
593 {
594 if (strcmp (curr->name (), nm) == 0)
595 {
596 curr->clear_visible ();
597
598 if (! curr->is_defined ())
599 {
600 prev->next_elem = curr->next ();
601 symbol_record *tmp = curr;
602 curr = curr->next ();
603 delete tmp;
604 }
605
606 return 1;
607 }
608 prev = curr;
609 curr = curr->next ();
610 }
611
612 return 0;
613 }
614
615 void
616 symbol_table::undefine (void)
617 {
618 for (int i = 0; i < HASH_TABLE_SIZE; i++)
619 {
620 symbol_record *ptr = table[i].next ();
621
622 while (ptr != (symbol_record *) NULL)
623 {
624 ptr->undefine ();
625 ptr = ptr->next ();
626 }
627 }
628 }
629
630 // Ugh.
631
632 void
633 symbol_table::bind_globals (void)
634 {
635 assert (this != global_sym_tab);
636
637 for (int i = 0; i < HASH_TABLE_SIZE; i++)
638 {
639 symbol_record *ptr = table[i].next ();
640
641 while (ptr != (symbol_record *) NULL && ! ptr->formal_param)
642 {
643 char *nm = ptr->name ();
644 symbol_record *sr = global_sym_tab->lookup (nm, 0, 0);
645 if (sr != (symbol_record *) NULL)
646 ptr->alias (sr, 1);
647 ptr = ptr->next ();
648 }
649 }
650 }
651
652 int
653 symbol_table::save (ostream& os, int mark_as_global = 0)
654 {
655 int status = 0;
656 for (char **names = sorted_var_list (); *names != (char *) NULL; names++)
657 {
658 if (save (os, *names, mark_as_global))
659 status++;
660 }
661 return status;
662 }
663
664 int
665 symbol_table::save (ostream& os, char *name, int mark_as_global = 0)
666 {
667 int status = 0;
668 symbol_record *sr = lookup (name, 0, 0);
669 if (sr != (symbol_record *) NULL)
670 status = sr->save (os, mark_as_global);
671 return status;
672 }
673
674 int
675 symbol_table::size (void)
676 {
677 int count = 0;
678 for (int i = 0; i < HASH_TABLE_SIZE; i++)
679 {
680 symbol_record *ptr = table[i].next ();
681 while (ptr != (symbol_record *) NULL)
682 {
683 count++;
684 ptr = ptr->next ();
685 }
686 }
687 return count;
688 }
689
690 char **
691 symbol_table::list (void)
692 {
693 int count;
694 return list (count);
695 }
696
697 char **
698 symbol_table::var_list (void)
699 {
700 int count;
701 return var_list (count);
702 }
703
704 char **
705 symbol_table::fcn_list (void)
706 {
707 int count;
708 return fcn_list (count);
709 }
710
711 char **
712 symbol_table::list (int& count)
713 {
714 int n = size ();
715 if (n == 0)
716 return (char **) NULL;
717
718 char **symbols = new char * [n+1];
719 count = 0;
720 for (int i = 0; i < HASH_TABLE_SIZE; i++)
721 {
722 symbol_record *ptr = table[i].next ();
723 while (ptr != (symbol_record *) NULL)
724 {
725 assert (count < n);
726 symbols[count++] = strsave (ptr->name ());
727 ptr = ptr->next ();
728 }
729 }
730 symbols[count] = (char *) NULL;
731 return symbols;
732 }
733
734 char **
735 symbol_table::var_list (int& count)
736 {
737 int n = size ();
738 if (n == 0)
739 return (char **) NULL;
740
741 char **symbols = new char * [n+1];
742 count = 0;
743 for (int i = 0; i < HASH_TABLE_SIZE; i++)
744 {
745 symbol_record *ptr = table[i].next ();
746 while (ptr != (symbol_record *) NULL)
747 {
748 assert (count < n);
749 if (ptr->is_variable ())
750 symbols[count++] = strsave (ptr->name ());
751 ptr = ptr->next ();
752 }
753 }
754 symbols[count] = (char *) NULL;
755 return symbols;
756 }
757
758 char **
759 symbol_table::fcn_list (int& count)
760 {
761 int n = size ();
762 if (n == 0)
763 return (char **) NULL;
764
765 char **symbols = new char * [n+1];
766 count = 0;
767 for (int i = 0; i < HASH_TABLE_SIZE; i++)
768 {
769 symbol_record *ptr = table[i].next ();
770 while (ptr != (symbol_record *) NULL)
771 {
772 assert (count < n);
773 if (ptr->is_function ())
774 symbols[count++] = strsave (ptr->name ());
775 ptr = ptr->next ();
776 }
777 }
778 symbols[count] = (char *) NULL;
779 return symbols;
780 }
781
782 static inline int
783 pstrcmp (char **a, char **b)
784 {
785 return strcmp (*a, *b);
786 }
787
788 char **
789 symbol_table::sorted_list (void)
790 {
791 int count = 0;
792 return sorted_list (count);
793 }
794
795 char **
796 symbol_table::sorted_var_list (void)
797 {
798 int count = 0;
799 return sorted_var_list (count);
800 }
801
802 char **
803 symbol_table::sorted_fcn_list (void)
804 {
805 int count = 0;
806 return sorted_fcn_list (count);
807 }
808
809 char **
810 symbol_table::sorted_list (int& count)
811 {
812 char **symbols = list (count);
813 if (symbols != (char **) NULL)
814 qsort ((void **) symbols, count, sizeof (char *),
815 (int (*)(void*, void*)) pstrcmp);
816 return symbols;
817 }
818
819 char **
820 symbol_table::sorted_var_list (int& count)
821 {
822 char **symbols = var_list (count);
823 if (symbols != (char **) NULL)
824 qsort ((void **) symbols, count, sizeof (char *),
825 (int (*)(void*, void*)) pstrcmp);
826 return symbols;
827 }
828
829 char **
830 symbol_table::sorted_fcn_list (int& count)
831 {
832 char **symbols = fcn_list (count);
833 if (symbols != (char **) NULL)
834 qsort ((void **) symbols, count, sizeof (char *),
835 (int (*)(void*, void*)) pstrcmp);
836 return symbols;
837 }
838
839 // Chris Torek's fave hash function.
840
841 unsigned int
842 symbol_table::hash (const char *str)
843 {
844 unsigned h = 0;
845 while (*str)
846 h = h * 33 + *str++;
847 return h;
848 }
849
850 /*
851 ;;; Local Variables: ***
852 ;;; mode: C++ ***
853 ;;; page-delimiter: "^/\\*" ***
854 ;;; End: ***
855 */