home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / calc / part04 / symbol.c < prev   
C/C++ Source or Header  |  1992-05-09  |  7KB  |  356 lines

  1. /*
  2.  * Copyright (c) 1992 David I. Bell
  3.  * Permission is granted to use, distribute, or modify this source,
  4.  * provided that this copyright notice remains intact.
  5.  *
  6.  * Global and local symbol routines.
  7.  */
  8.  
  9. #include "calc.h"
  10. #include "token.h"
  11. #include "symbol.h"
  12. #include "string.h"
  13. #include "opcodes.h"
  14. #include "func.h"
  15.  
  16. #define HASHSIZE    37    /* size of hash table */
  17.  
  18.  
  19. static STRINGHEAD localnames;    /* list of local variable names */
  20. static STRINGHEAD globalnames;    /* list of global variable names */
  21. static STRINGHEAD paramnames;    /* list of parameter variable names */
  22. static GLOBAL *globalhash[HASHSIZE];    /* hash table for globals */
  23.  
  24. static void fitprint();
  25.  
  26.  
  27. /*
  28.  * Hash a symbol name so we can find it in the hash table.
  29.  * Args are the symbol name and the symbol name size.
  30.  */
  31. #define HASH(n, s) ((unsigned)((n)[0]*123 + (n)[s-1]*135 + (s)*157) % HASHSIZE)
  32.  
  33.  
  34. /*
  35.  * Initialize the global symbol table.
  36.  */
  37. void
  38. initglobals()
  39. {
  40.     int i;        /* index counter */
  41.  
  42.     for (i = 0; i < HASHSIZE; i++)
  43.         globalhash[i] = NULL;
  44.     initstr(&globalnames);
  45. }
  46.  
  47.  
  48. /*
  49.  * Define a possibly new global variable.
  50.  * If it did not already exist, it is created with an undefined value.
  51.  * The address of the global symbol structure is returned.
  52.  */
  53. GLOBAL *
  54. addglobal(name)
  55.     char *name;        /* name of global variable */
  56. {
  57.     GLOBAL *sp;        /* current symbol pointer */
  58.     GLOBAL **hp;        /* hash table head address */
  59.     long len;        /* length of string */
  60.  
  61.     len = strlen(name);
  62.     if (len <= 0)
  63.         return NULL;
  64.     hp = &globalhash[HASH(name, len)];
  65.     for (sp = *hp; sp; sp = sp->g_next) {
  66.         if ((sp->g_len == len) && (strcmp(sp->g_name, name) == 0))
  67.             return sp;
  68.     }
  69.     sp = (GLOBAL *) malloc(sizeof(GLOBAL));
  70.     if (sp == NULL)
  71.         return sp;
  72.     sp->g_name = addstr(&globalnames, name);
  73.     sp->g_len = len;
  74.     sp->g_value.v_type = V_NULL;
  75.     sp->g_next = *hp;
  76.     *hp = sp;
  77.     return sp;
  78. }
  79.  
  80.  
  81. /*
  82.  * Look up the name of a global variable and return its address.
  83.  * Returns NULL if the symbol was not found.
  84.  */
  85. GLOBAL *
  86. findglobal(name)
  87.     char *name;        /* name of global variable */
  88. {
  89.     GLOBAL *sp;        /* current symbol pointer */
  90.     long len;        /* length of string */
  91.  
  92.     len = strlen(name);
  93.     sp = globalhash[HASH(name, len)];
  94.     while (sp) {
  95.         if ((sp->g_len == len) && (strcmp(sp->g_name, name) == 0))
  96.             return sp;
  97.         sp = sp->g_next;
  98.     }
  99.     return sp;
  100. }
  101.  
  102.  
  103. /*
  104.  * Return the name of a global variable given its address.
  105.  */
  106. char *
  107. globalname(sp)
  108.     GLOBAL *sp;        /* address of global pointer */
  109. {
  110.     if (sp)
  111.         return sp->g_name;
  112.     return "";
  113. }
  114.  
  115.  
  116. /*
  117.  * Show the value of all global variables, typing only the head and
  118.  * tail of very large numbers.
  119.  */
  120. void
  121. showglobals()
  122. {
  123.     GLOBAL **hp;            /* hash table head address */
  124.     register GLOBAL *sp;        /* current global symbol pointer */
  125.     long count;            /* number of global variables shown */
  126.     NUMBER *num, *den;
  127.     long digits;
  128.  
  129.     count = 0;
  130.     for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
  131.         for (sp = *hp; sp; sp = sp->g_next) {
  132.             if (sp->g_value.v_type != V_NUM)
  133.                 continue;
  134.             if (count++ == 0) {
  135.                 printf("\nName    Digits  Value\n");
  136.                 printf(  "----    ------  -----\n");
  137.             }
  138.             printf("%-8s ", sp->g_name);
  139.             num = qnum(sp->g_value.v_num);
  140.             digits = qdigits(num);
  141.             printf("%-7ld ", digits);
  142.             fitprint(num, digits, 60L);
  143.             qfree(num);
  144.             if (!qisint(sp->g_value.v_num)) {
  145.                 den = qden(sp->g_value.v_num);
  146.                 digits = qdigits(den);
  147.                 printf("\n    %-6ld /", digits);
  148.                 fitprint(den, digits, 60L);
  149.                 qfree(den);
  150.             }
  151.             printf("\n");
  152.         }
  153.     }
  154.     printf(count ? "\n" : "No global variables defined.\n");
  155. }
  156.  
  157.  
  158. /*
  159.  * Print an integer which is guaranteed to fit in the specified number
  160.  * of columns, using imbedded '...' characters if it is too large.
  161.  */
  162. static void
  163. fitprint(num, digits, width)
  164.     NUMBER *num;        /* number to print */
  165.     long digits, width;
  166. {
  167.     long show, used;
  168.     NUMBER *p, *t, *div, *val;
  169.  
  170.     if (digits <= width) {
  171.         qprintf("%r", num);
  172.         return;
  173.     }
  174.     show = (width / 2) - 2;
  175.     t = itoq(10L);
  176.     p = itoq((long) (digits - show));
  177.     div = qpowi(t, p);
  178.     val = qquo(num, div);
  179.     qprintf("%r...", val);
  180.     qfree(p);
  181.     qfree(div);
  182.     qfree(val);
  183.     p = itoq(show);
  184.     div = qpowi(t, p);
  185.     val = qmod(num, div);
  186.     used = qdigits(val);
  187.     while (used++ < show) printf("0");
  188.     qprintf("%r", val);
  189.     qfree(p);
  190.     qfree(div);
  191.     qfree(val);
  192.     qfree(t);
  193. }
  194.  
  195.  
  196. /*
  197.  * Write all normal global variables to an output file.
  198.  * Note: Currently only simple types are saved.
  199.  * Returns nonzero on error.
  200.  */
  201. writeglobals(name)
  202.     char *name;
  203. {
  204.     FILE *fp;
  205.     GLOBAL **hp;            /* hash table head address */
  206.     register GLOBAL *sp;        /* current global symbol pointer */
  207.     int savemode;            /* saved output mode */
  208.  
  209.     fp = f_open(name, "w");
  210.     if (fp == NULL)
  211.         return 1;
  212.     setfp(fp);
  213.     for (hp = &globalhash[HASHSIZE-1]; hp >= globalhash; hp--) {
  214.         for (sp = *hp; sp; sp = sp->g_next) {
  215.             switch (sp->g_value.v_type) {
  216.                 case V_NUM:
  217.                 case V_COM:
  218.                 case V_STR:
  219.                     break;
  220.                 default:
  221.                     continue;
  222.             }
  223.             math_fmt("%s = ", sp->g_name);
  224.             savemode = _outmode_;
  225.             _outmode_ = MODE_HEX;
  226.             printvalue(&sp->g_value, PRINT_UNAMBIG);
  227.             _outmode_ = savemode;
  228.             math_str(";\n");
  229.         }
  230.     }
  231.     setfp(stdout);
  232.     if (fclose(fp))
  233.         return 1;
  234.     return 0;
  235. }
  236.  
  237.  
  238. /*
  239.  * Initialize the local and parameter symbol table information.
  240.  */
  241. void
  242. initlocals()
  243. {
  244.     initstr(&localnames);
  245.     initstr(¶mnames);
  246.     curfunc->f_localcount = 0;
  247.     curfunc->f_paramcount = 0;
  248. }
  249.  
  250.  
  251. /*
  252.  * Add a possibly new local variable definition.
  253.  * Returns the index of the variable into the local symbol table.
  254.  * Minus one indicates the symbol could not be added.
  255.  */
  256. long
  257. addlocal(name)
  258.     char *name;        /* name of local variable */
  259. {
  260.     long index;        /* current symbol index */
  261.  
  262.     index = findstr(&localnames, name);
  263.     if (index >= 0)
  264.         return index;
  265.     index = localnames.h_count;
  266.     (void) addstr(&localnames, name);
  267.     curfunc->f_localcount++;
  268.     return index;
  269. }
  270.  
  271.  
  272. /*
  273.  * Find a local variable name and return its index.
  274.  * Returns minus one if the variable name is not defined.
  275.  */
  276. long
  277. findlocal(name)
  278.     char *name;        /* name of local variable */
  279. {
  280.     return findstr(&localnames, name);
  281. }
  282.  
  283.  
  284. /*
  285.  * Return the name of a local variable.
  286.  */
  287. char *
  288. localname(n)
  289.     long n;
  290. {
  291.     return namestr(&localnames, n);
  292. }
  293.  
  294.  
  295. /*
  296.  * Add a possibly new parameter variable definition.
  297.  * Returns the index of the variable into the parameter symbol table.
  298.  * Minus one indicates the symbol could not be added.
  299.  */
  300. long
  301. addparam(name)
  302.     char *name;        /* name of parameter variable */
  303. {
  304.     long index;        /* current symbol index */
  305.  
  306.     index = findstr(¶mnames, name);
  307.     if (index >= 0)
  308.         return index;
  309.     index = paramnames.h_count;
  310.     (void) addstr(¶mnames, name);
  311.     curfunc->f_paramcount++;
  312.     return index;
  313. }
  314.  
  315.  
  316. /*
  317.  * Find a parameter variable name and return its index.
  318.  * Returns minus one if the variable name is not defined.
  319.  */
  320. long
  321. findparam(name)
  322.     char *name;        /* name of parameter variable */
  323. {
  324.     return findstr(¶mnames, name);
  325. }
  326.  
  327.  
  328. /*
  329.  * Return the name of a parameter variable.
  330.  */
  331. char *
  332. paramname(n)
  333.     long n;
  334. {
  335.     return namestr(¶mnames, n);
  336. }
  337.  
  338.  
  339. /*
  340.  * Return the type of a variable name.
  341.  * This is either local, parameter, global, or undefined.
  342.  */
  343. symboltype(name)
  344.     char *name;        /* variable name to find */
  345. {
  346.     if (findlocal(name) >= 0)
  347.         return SYM_LOCAL;
  348.     if (findparam(name) >= 0)
  349.         return SYM_PARAM;
  350.     if (findglobal(name))
  351.         return SYM_GLOBAL;
  352.     return SYM_UNDEFINED;
  353. }
  354.  
  355. /* END CODE */
  356.