modified: SpatialOmicsCoord.py
[GalaxyCodeBases.git] / c_cpp / etc / calc / symbol.c
blob42669aee2c5bdeb7fadf35ac4afadf12984fb660
1 /*
2 * symbol - global and local symbol routines
4 * Copyright (C) 1999-2007 David I. Bell and Ernest Bowen
6 * Primary author: David I. Bell
8 * Calc is open software; you can redistribute it and/or modify it under
9 * the terms of the version 2.1 of the GNU Lesser General Public License
10 * as published by the Free Software Foundation.
12 * Calc is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
15 * Public License for more details.
17 * A copy of version 2.1 of the GNU Lesser General Public License is
18 * distributed with calc under the filename COPYING-LGPL. You should have
19 * received a copy with calc; if not, write to Free Software Foundation, Inc.
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * @(#) $Revision: 30.2 $
23 * @(#) $Id: symbol.c,v 30.2 2013/08/11 08:41:38 chongo Exp $
24 * @(#) $Source: /usr/local/src/bin/calc/RCS/symbol.c,v $
26 * Under source code control: 1990/02/15 01:48:23
27 * File existed as early as: before 1990
29 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
33 #include <stdio.h>
34 #include "calc.h"
35 #include "token.h"
36 #include "symbol.h"
37 #include "str.h"
38 #include "opcodes.h"
39 #include "func.h"
41 #define HASHSIZE 37 /* size of hash table */
43 E_FUNC FILE *f_open(char *name, char *mode);
45 STATIC int filescope; /* file scope level for static variables */
46 STATIC int funcscope; /* function scope level for static variables */
47 STATIC STRINGHEAD localnames; /* list of local variable names */
48 STATIC STRINGHEAD globalnames; /* list of global variable names */
49 STATIC STRINGHEAD paramnames; /* list of parameter variable names */
50 STATIC GLOBAL *globalhash[HASHSIZE]; /* hash table for globals */
52 S_FUNC void printtype(VALUE *);
53 S_FUNC void unscope(void);
54 S_FUNC void addstatic(GLOBAL *);
55 STATIC long staticcount = 0;
56 STATIC long staticavail = 0;
57 STATIC GLOBAL **statictable;
61 * Hash a symbol name so we can find it in the hash table.
62 * Args are the symbol name and the symbol name size.
64 #define HASHSYM(n, s) ((unsigned)((n)[0]*123 + (n)[s-1]*135 + (s)*157) % \
65 HASHSIZE)
69 * Initialize the global symbol table.
71 void
72 initglobals(void)
74 int i; /* index counter */
76 for (i = 0; i < HASHSIZE; i++)
77 globalhash[i] = NULL;
78 initstr(&globalnames);
79 filescope = SCOPE_STATIC;
80 funcscope = 0;
85 * Define a possibly new global variable which may or may not be static.
86 * If it did not already exist, it is created with a value of zero.
87 * The address of the global symbol structure is returned.
89 * given:
90 * name name of global variable
91 * isstatic TRUE if symbol is static
93 GLOBAL *
94 addglobal(char *name, BOOL isstatic)
96 GLOBAL *sp; /* current symbol pointer */
97 GLOBAL **hp; /* hash table head address */
98 size_t len; /* length of string */
99 int newfilescope; /* file scope being looked for */
100 int newfuncscope; /* function scope being looked for */
102 newfilescope = SCOPE_GLOBAL;
103 newfuncscope = 0;
104 if (isstatic) {
105 newfilescope = filescope;
106 newfuncscope = funcscope;
108 len = strlen(name);
109 if (len <= 0)
110 return NULL;
111 hp = &globalhash[HASHSYM(name, len)];
112 for (sp = *hp; sp; sp = sp->g_next) {
113 if ((sp->g_len == len) && (strcmp(sp->g_name, name) == 0)
114 && (sp->g_filescope == newfilescope)
115 && (sp->g_funcscope == newfuncscope))
116 return sp;
118 sp = (GLOBAL *) malloc(sizeof(GLOBAL));
119 if (sp == NULL)
120 return sp;
121 sp->g_name = addstr(&globalnames, name);
122 sp->g_len = len;
123 sp->g_filescope = newfilescope;
124 sp->g_funcscope = newfuncscope;
125 sp->g_value.v_num = qlink(&_qzero_);
126 sp->g_value.v_type = V_NUM;
127 sp->g_value.v_subtype = V_NOSUBTYPE;
128 sp->g_next = *hp;
129 *hp = sp;
130 return sp;
135 * Look for the highest-scope global variable with a specified name.
136 * Returns the address of the variable or NULL according as the search
137 * succeeds or fails.
139 GLOBAL *
140 findglobal(char *name)
142 GLOBAL *sp; /* current symbol pointer */
143 GLOBAL *bestsp; /* found symbol with highest scope */
144 size_t len; /* length of string */
146 bestsp = NULL;
147 len = strlen(name);
148 for (sp = globalhash[HASHSYM(name, len)]; sp; sp = sp->g_next) {
149 if ((sp->g_len == len) && !strcmp(sp->g_name, name)) {
150 if ((bestsp == NULL) ||
151 (sp->g_filescope > bestsp->g_filescope) ||
152 (sp->g_funcscope > bestsp->g_funcscope))
153 bestsp = sp;
156 return bestsp;
161 * Return the name of a global variable given its address.
163 * given:
164 * sp address of global pointer
166 char *
167 globalname(GLOBAL *sp)
169 if (sp)
170 return sp->g_name;
171 return "";
176 * Show the value of all real-number valued global variables, displaying
177 * only the head and tail of very large numerators and denominators.
178 * Static variables are not included.
180 void
181 showglobals(void)
183 GLOBAL **hp; /* hash table head address */
184 register GLOBAL *sp; /* current global symbol pointer */
185 long count; /* number of global variables shown */
187 count = 0;
188 for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
189 for (sp = *hp; sp; sp = sp->g_next) {
190 if (sp->g_value.v_type != V_NUM)
191 continue;
192 if (count++ == 0) {
193 printf("\nName Digits Value\n");
194 printf( "---- ------ -----\n");
196 printf("%-8s", sp->g_name);
197 if (sp->g_filescope != SCOPE_GLOBAL)
198 printf(" (s)");
199 fitprint(sp->g_value.v_num, 50);
200 printf("\n");
203 if (count == 0) {
204 printf("No real-valued global variables\n");
206 putchar('\n');
210 void
211 showallglobals(void)
213 GLOBAL **hp; /* hash table head address */
214 register GLOBAL *sp; /* current global symbol pointer */
215 long count; /* number of global variables shown */
217 count = 0;
218 for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
219 for (sp = *hp; sp; sp = sp->g_next) {
220 if (count++ == 0) {
221 printf("\nName Level Type\n");
222 printf( "---- ----- -----\n");
224 printf("%-8s%4d ", sp->g_name, sp->g_filescope);
225 printtype(&sp->g_value);
226 printf("\n");
229 if (count > 0)
230 printf("\nNumber: %ld\n", count);
231 else
232 printf("No global variables\n");
235 S_FUNC void
236 printtype(VALUE *vp)
238 int type;
239 char *s;
241 type = vp->v_type;
242 if (type < 0) {
243 printf("Error %d", -type);
244 return;
246 switch (type) {
247 case V_NUM:
248 printf("real = ");
249 fitprint(vp->v_num, 32);
250 return;
251 case V_COM:
252 printf("complex = ");
253 fitprint(vp->v_com->real, 8);
254 if (!vp->v_com->imag->num.sign)
255 printf("+");
256 fitprint(vp->v_com->imag, 8);
257 printf("i");
258 return;
259 case V_STR:
260 printf("string = \"");
261 fitstring(vp->v_str->s_str, vp->v_str->s_len, 50);
262 printf("\"");
263 return;
264 case V_NULL:
265 s = "null";
266 break;
267 case V_MAT:
268 s = "matrix";
269 break;
270 case V_LIST:
271 s = "list";
272 break;
273 case V_ASSOC:
274 s = "association";
275 break;
276 case V_OBJ:
277 printf("%s ", objtypename(
278 vp->v_obj->o_actions->oa_index));
279 s = "object";
280 break;
281 case V_FILE:
282 s = "file id";
283 break;
284 case V_RAND:
285 s = "additive 55 random state";
286 break;
287 case V_RANDOM:
288 s = "Blum random state";
289 break;
290 case V_CONFIG:
291 s = "config state";
292 break;
293 case V_HASH:
294 s = "hash state";
295 break;
296 case V_BLOCK:
297 s = "unnamed block";
298 break;
299 case V_NBLOCK:
300 s = "named block";
301 break;
302 case V_VPTR:
303 s = "value pointer";
304 break;
305 case V_OPTR:
306 s = "octet pointer";
307 break;
308 case V_SPTR:
309 s = "string pointer";
310 break;
311 case V_NPTR:
312 s = "number pointer";
313 break;
314 default:
315 s = "???";
316 break;
318 printf("%s", s);
323 * Write all normal global variables to an output file.
324 * Note: Currently only simple types are saved.
325 * Returns nonzero on error.
328 writeglobals(char *name)
330 FILE *fp;
331 GLOBAL **hp; /* hash table head address */
332 register GLOBAL *sp; /* current global symbol pointer */
333 int savemode; /* saved output mode */
334 E_FUNC void math_setfp(FILE *fp);
336 fp = f_open(name, "w");
337 if (fp == NULL)
338 return 1;
339 math_setfp(fp);
340 for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
341 for (sp = *hp; sp; sp = sp->g_next) {
342 switch (sp->g_value.v_type) {
343 case V_NUM:
344 case V_COM:
345 case V_STR:
346 break;
347 default:
348 continue;
350 math_fmt("%s = ", sp->g_name);
351 savemode = math_setmode(MODE_HEX);
352 printvalue(&sp->g_value, PRINT_UNAMBIG);
353 math_setmode(savemode);
354 math_str(";\n");
357 math_setfp(stdout);
358 if (fclose(fp))
359 return 1;
360 return 0;
364 * Free all non-null global and visible static variables
366 void
367 freeglobals(void)
369 GLOBAL **hp; /* hash table head address */
370 GLOBAL *sp; /* current global symbol pointer */
371 long count; /* number of global variables freed */
374 * We prevent the hp pointer from walking behind globalhash
375 * by stopping one short of the end and running the loop one
376 * more time.
378 * We could stop the loop with just hp >= globalhash, but stopping
379 * short and running the loop one last time manually helps make
380 * code checkers such as insure happy.
382 count = 0;
383 for (hp = &globalhash[HASHSIZE-1]; hp > globalhash; hp--) {
384 for (sp = *hp; sp; sp = sp->g_next) {
385 if (sp->g_value.v_type != V_NULL) {
386 freevalue(&sp->g_value);
387 count++;
391 /* run the loop manually one last time */
392 for (sp = *hp; sp; sp = sp->g_next) {
393 if (sp->g_value.v_type != V_NULL) {
394 freevalue(&sp->g_value);
395 count++;
401 * Free all invisible static variables
403 void
404 freestatics(void)
406 GLOBAL **stp;
407 GLOBAL *sp;
408 long count;
410 stp = statictable;
411 count = staticcount;
412 while (count-- > 0) {
413 sp = *stp++;
414 freevalue(&sp->g_value);
420 * Reset the file and function scope levels back to the original values.
421 * This is called on errors to forget any static variables which were being
422 * defined.
424 void
425 resetscopes(void)
427 filescope = SCOPE_STATIC;
428 funcscope = 0;
429 unscope();
434 * Enter a new file scope level so that newly defined static variables
435 * will have the appropriate scope, and so that previously defined static
436 * variables will temporarily be unaccessible. This should only be called
437 * when the function scope level is zero.
439 void
440 enterfilescope(void)
442 filescope++;
443 funcscope = 0;
448 * Exit from a file scope level. This deletes from the global symbol table
449 * all of the static variables that were defined within this file scope level.
450 * The function scope level is also reset to zero.
452 void
453 exitfilescope(void)
455 if (filescope > SCOPE_STATIC)
456 filescope--;
457 funcscope = 0;
458 unscope();
463 * Enter a new function scope level within the current file scope level.
464 * This allows newly defined static variables to override previously defined
465 * static variables in the same file scope level.
467 void
468 enterfuncscope(void)
470 funcscope++;
475 * Exit from a function scope level. This deletes static symbols which were
476 * defined within the current function scope level, and makes previously
477 * defined symbols with the same name within the same file scope level
478 * accessible again.
480 void
481 exitfuncscope(void)
483 if (funcscope > 0)
484 funcscope--;
485 unscope();
490 * To end the scope of any static variable with identifier id when
491 * id is being declared as global, or when id is declared as static and the
492 * variable is at the same file and function level.
494 void
495 endscope(char *name, BOOL isglobal)
497 GLOBAL *sp;
498 GLOBAL *prevsp;
499 GLOBAL **hp;
500 size_t len;
502 len = strlen(name);
503 prevsp = NULL;
504 hp = &globalhash[HASHSYM(name, len)];
505 for (sp = *hp; sp; sp = sp->g_next) {
506 if (sp->g_len == len && !strcmp(sp->g_name, name) &&
507 sp->g_filescope > SCOPE_GLOBAL) {
508 if (isglobal || (sp->g_filescope == filescope &&
509 sp->g_funcscope == funcscope)) {
510 addstatic(sp);
511 if (prevsp)
512 prevsp->g_next = sp->g_next;
513 else
514 *hp = sp->g_next;
515 continue;
518 prevsp = sp;
523 * To store in a table a static variable whose scope is being ended
525 void
526 addstatic(GLOBAL *sp)
528 GLOBAL **stp;
530 if (staticavail <= 0) {
531 if (staticcount <= 0)
532 stp = (GLOBAL **) malloc(20 * sizeof(GLOBAL *));
533 else
534 stp = (GLOBAL **) realloc(statictable,
535 (20 + staticcount) * sizeof(GLOBAL *));
536 if (stp == NULL) {
537 math_error("Cannot allocate static-variable table");
538 /*NOTREACHED*/
540 statictable = stp;
541 staticavail = 20;
543 statictable[staticcount++] = sp;
544 staticavail--;
548 * To display all static variables whose scope has been ended
550 void
551 showstatics(void)
553 long count;
554 GLOBAL **stp;
555 GLOBAL *sp;
557 for (count = 0, stp = statictable; count < staticcount; count++) {
558 sp = *stp++;
559 if (count == 0) {
560 printf("\nName Scopes Type\n");
561 printf( "---- ------ -----\n");
563 printf("%-8s", sp->g_name);
564 printf("%3d", sp->g_filescope);
565 printf("%3d ", sp->g_funcscope);
566 printtype(&sp->g_value);
567 printf("\n");
569 if (count > 0)
570 printf("\nNumber: %ld\n", count);
571 else
572 printf("No unscoped static variables\n");
576 * Remove all the symbols from the global symbol table which have file or
577 * function scopes larger than the current scope levels. Their memory
578 * remains allocated since their values still actually exist.
580 S_FUNC void
581 unscope(void)
583 GLOBAL **hp; /* hash table head address */
584 register GLOBAL *sp; /* current global symbol pointer */
585 GLOBAL *prevsp; /* previous kept symbol pointer */
588 * We prevent the hp pointer from walking behind globalhash
589 * by stopping one short of the end and running the loop one
590 * more time.
592 * We could stop the loop with just hp >= globalhash, but stopping
593 * short and running the loop one last time manually helps make
594 * code checkers such as insure happy.
596 for (hp = &globalhash[HASHSIZE-1]; hp > globalhash; hp--) {
597 prevsp = NULL;
598 for (sp = *hp; sp; sp = sp->g_next) {
599 if ((sp->g_filescope == SCOPE_GLOBAL) ||
600 (sp->g_filescope < filescope) ||
601 ((sp->g_filescope == filescope) &&
602 (sp->g_funcscope <= funcscope))) {
603 prevsp = sp;
604 continue;
608 * This symbol needs removing.
610 addstatic(sp);
611 if (prevsp)
612 prevsp->g_next = sp->g_next;
613 else
614 *hp = sp->g_next;
617 /* run the loop manually one last time */
618 prevsp = NULL;
619 for (sp = *hp; sp; sp = sp->g_next) {
620 if ((sp->g_filescope == SCOPE_GLOBAL) ||
621 (sp->g_filescope < filescope) ||
622 ((sp->g_filescope == filescope) &&
623 (sp->g_funcscope <= funcscope))) {
624 prevsp = sp;
625 continue;
629 * This symbol needs removing.
631 addstatic(sp);
632 if (prevsp)
633 prevsp->g_next = sp->g_next;
634 else
635 *hp = sp->g_next;
641 * Initialize the local and parameter symbol table information.
643 void
644 initlocals(void)
646 initstr(&localnames);
647 initstr(&paramnames);
648 curfunc->f_localcount = 0;
649 curfunc->f_paramcount = 0;
654 * Add a possibly new local variable definition.
655 * Returns the index of the variable into the local symbol table.
656 * Minus one indicates the symbol could not be added.
658 * given:
659 * name name of local variable
661 long
662 addlocal(char *name)
664 long index; /* current symbol index */
666 index = findstr(&localnames, name);
667 if (index >= 0)
668 return index;
669 index = localnames.h_count;
670 (void) addstr(&localnames, name);
671 curfunc->f_localcount++;
672 return index;
677 * Find a local variable name and return its index.
678 * Returns minus one if the variable name is not defined.
680 * given:
681 * name name of local variable
683 long
684 findlocal(char *name)
686 return findstr(&localnames, name);
691 * Return the name of a local variable.
693 char *
694 localname(long n)
696 return namestr(&localnames, n);
701 * Add a possibly new parameter variable definition.
702 * Returns the index of the variable into the parameter symbol table.
703 * Minus one indicates the symbol could not be added.
705 * given:
706 * name name of parameter variable
708 long
709 addparam(char *name)
711 long index; /* current symbol index */
713 index = findstr(&paramnames, name);
714 if (index >= 0)
715 return index;
716 index = paramnames.h_count;
717 (void) addstr(&paramnames, name);
718 curfunc->f_paramcount++;
719 return index;
724 * Find a parameter variable name and return its index.
725 * Returns minus one if the variable name is not defined.
727 * given:
728 * name name of parameter variable
730 long
731 findparam(char *name)
733 return findstr(&paramnames, name);
738 * Return the name of a parameter variable.
740 char *
741 paramname(long n)
743 return namestr(&paramnames, n);
748 * Return the type of a variable name.
749 * This is either local, parameter, global, static, or undefined.
751 * given:
752 * name variable name to find
755 symboltype(char *name)
757 GLOBAL *sp;
759 if (findparam(name) >= 0)
760 return SYM_PARAM;
761 if (findlocal(name) >= 0)
762 return SYM_LOCAL;
763 sp = findglobal(name);
764 if (sp) {
765 if (sp->g_filescope == SCOPE_GLOBAL)
766 return SYM_GLOBAL;
767 return SYM_STATIC;
769 return SYM_UNDEFINED;
772 /* END CODE */