?? symbol.c
字號:
/* * symbol - global and local symbol routines * * Copyright (C) 1999-2006 David I. Bell and Ernest Bowen * * Primary author: David I. Bell * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General * Public License for more details. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL. You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * @(#) $Revision: 29.6 $ * @(#) $Id: symbol.c,v 29.6 2006/06/20 10:28:06 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/symbol.c,v $ * * Under source code control: 1990/02/15 01:48:23 * File existed as early as: before 1990 * * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ */#include <stdio.h>#include "calc.h"#include "token.h"#include "symbol.h"#include "string.h"#include "opcodes.h"#include "func.h"#define HASHSIZE 37 /* size of hash table */extern FILE *f_open(char *name, char *mode);static int filescope; /* file scope level for static variables */static int funcscope; /* function scope level for static variables */static STRINGHEAD localnames; /* list of local variable names */static STRINGHEAD globalnames; /* list of global variable names */static STRINGHEAD paramnames; /* list of parameter variable names */static GLOBAL *globalhash[HASHSIZE]; /* hash table for globals */static void printtype(VALUE *);static void unscope(void);static void addstatic(GLOBAL *);static long staticcount = 0;static long staticavail = 0;static GLOBAL **statictable;/* * Hash a symbol name so we can find it in the hash table. * Args are the symbol name and the symbol name size. */#define HASHSYM(n, s) ((unsigned)((n)[0]*123 + (n)[s-1]*135 + (s)*157) % HASHSIZE)/* * Initialize the global symbol table. */voidinitglobals(void){ int i; /* index counter */ for (i = 0; i < HASHSIZE; i++) globalhash[i] = NULL; initstr(&globalnames); filescope = SCOPE_STATIC; funcscope = 0;}/* * Define a possibly new global variable which may or may not be static. * If it did not already exist, it is created with a value of zero. * The address of the global symbol structure is returned. * * given: * name name of global variable * isstatic TRUE if symbol is static */GLOBAL *addglobal(char *name, BOOL isstatic){ GLOBAL *sp; /* current symbol pointer */ GLOBAL **hp; /* hash table head address */ size_t len; /* length of string */ int newfilescope; /* file scope being looked for */ int newfuncscope; /* function scope being looked for */ newfilescope = SCOPE_GLOBAL; newfuncscope = 0; if (isstatic) { newfilescope = filescope; newfuncscope = funcscope; } len = strlen(name); if (len <= 0) return NULL; hp = &globalhash[HASHSYM(name, len)]; for (sp = *hp; sp; sp = sp->g_next) { if ((sp->g_len == len) && (strcmp(sp->g_name, name) == 0) && (sp->g_filescope == newfilescope) && (sp->g_funcscope == newfuncscope)) return sp; } sp = (GLOBAL *) malloc(sizeof(GLOBAL)); if (sp == NULL) return sp; sp->g_name = addstr(&globalnames, name); sp->g_len = len; sp->g_filescope = newfilescope; sp->g_funcscope = newfuncscope; sp->g_value.v_num = qlink(&_qzero_); sp->g_value.v_type = V_NUM; sp->g_value.v_subtype = V_NOSUBTYPE; sp->g_next = *hp; *hp = sp; return sp;}/* * Look for the highest-scope global variable with a specified name. * Returns the address of the variable or NULL according as the search * succeeds or fails. */GLOBAL *findglobal(char *name){ GLOBAL *sp; /* current symbol pointer */ GLOBAL *bestsp; /* found symbol with highest scope */ size_t len; /* length of string */ bestsp = NULL; len = strlen(name); for (sp = globalhash[HASHSYM(name, len)]; sp; sp = sp->g_next) { if ((sp->g_len == len) && !strcmp(sp->g_name, name)) { if ((bestsp == NULL) || (sp->g_filescope > bestsp->g_filescope) || (sp->g_funcscope > bestsp->g_funcscope)) bestsp = sp; } } return bestsp;}/* * Return the name of a global variable given its address. * * given: * sp address of global pointer */char *globalname(GLOBAL *sp){ if (sp) return sp->g_name; return "";}/* * Show the value of all real-number valued global variables, displaying * only the head and tail of very large numerators and denominators. * Static variables are not included. */voidshowglobals(void){ GLOBAL **hp; /* hash table head address */ register GLOBAL *sp; /* current global symbol pointer */ long count; /* number of global variables shown */ count = 0; for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) { for (sp = *hp; sp; sp = sp->g_next) { if (sp->g_value.v_type != V_NUM) continue; if (count++ == 0) { printf("\nName Digits Value\n"); printf( "---- ------ -----\n"); } printf("%-8s", sp->g_name); if (sp->g_filescope != SCOPE_GLOBAL) printf(" (s)"); fitprint(sp->g_value.v_num, 50); printf("\n"); } } if (count == 0) { printf("No real-valued global variables\n"); } putchar('\n');}voidshowallglobals(void){ GLOBAL **hp; /* hash table head address */ register GLOBAL *sp; /* current global symbol pointer */ long count; /* number of global variables shown */ count = 0; for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) { for (sp = *hp; sp; sp = sp->g_next) { if (count++ == 0) { printf("\nName Level Type\n"); printf( "---- ----- -----\n"); } printf("%-8s%4d ", sp->g_name, sp->g_filescope); printtype(&sp->g_value); printf("\n"); } } if (count > 0) printf("\nNumber: %ld\n", count); else printf("No global variables\n");}static voidprinttype(VALUE *vp){ int type; char *s; type = vp->v_type; if (type < 0) { printf("Error %d", -type); return; } switch (type) { case V_NUM: printf("real = "); fitprint(vp->v_num, 32); return; case V_COM: printf("complex = "); fitprint(vp->v_com->real, 8); if (!vp->v_com->imag->num.sign) printf("+"); fitprint(vp->v_com->imag, 8); printf("i"); return; case V_STR: printf("string = \""); fitstring(vp->v_str->s_str, vp->v_str->s_len, 50); printf("\""); return; case V_NULL: s = "null"; break; case V_MAT: s = "matrix"; break; case V_LIST: s = "list"; break; case V_ASSOC: s = "association"; break; case V_OBJ: printf("%s ", objtypename( vp->v_obj->o_actions->oa_index)); s = "object"; break; case V_FILE: s = "file id"; break; case V_RAND: s = "additive 55 random state"; break; case V_RANDOM: s = "Blum random state"; break; case V_CONFIG: s = "config state"; break; case V_HASH: s = "hash state"; break; case V_BLOCK: s = "unnamed block"; break; case V_NBLOCK: s = "named block"; break; case V_VPTR: s = "value pointer"; break; case V_OPTR: s = "octet pointer"; break; case V_SPTR: s = "string pointer"; break; case V_NPTR: s = "number pointer"; break; default: s = "???"; break; } printf("%s", s);}/* * Write all normal global variables to an output file. * Note: Currently only simple types are saved. * Returns nonzero on error. */intwriteglobals(char *name){ FILE *fp; GLOBAL **hp; /* hash table head address */ register GLOBAL *sp; /* current global symbol pointer */ int savemode; /* saved output mode */ extern void math_setfp(FILE *fp); fp = f_open(name, "w"); if (fp == NULL) return 1; math_setfp(fp); for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) { for (sp = *hp; sp; sp = sp->g_next) { switch (sp->g_value.v_type) { case V_NUM: case V_COM: case V_STR: break; default: continue; } math_fmt("%s = ", sp->g_name); savemode = math_setmode(MODE_HEX); printvalue(&sp->g_value, PRINT_UNAMBIG); math_setmode(savemode); math_str(";\n"); } } math_setfp(stdout); if (fclose(fp)) return 1; return 0;}/* * Free all non-null global and visible static variables */voidfreeglobals(void){ GLOBAL **hp; /* hash table head address */ GLOBAL *sp; /* current global symbol pointer */ long count; /* number of global variables freed */ /* * We prevent the hp pointer from walking behind globalhash * by stopping one short of the end and running the loop one * more time. * * We could stop the loop with just hp >= globalhash, but stopping * short and running the loop one last time manually helps make * code checkers such as insure happy. */ count = 0; for (hp = &globalhash[HASHSIZE-1]; hp > globalhash; hp--) { for (sp = *hp; sp; sp = sp->g_next) { if (sp->g_value.v_type != V_NULL) { freevalue(&sp->g_value); count++;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -