Mercurial > octave
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 */ |