home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 355_02 / slk2.exe / SPP / ST.C < prev    next >
C/C++ Source or Header  |  1991-06-09  |  6KB  |  269 lines

  1. /*
  2.     Sherlock preprocessor --  symbol table routines.
  3.  
  4.     Block-structured version.
  5.  
  6.     source:  st.c
  7.     started: November 4, 1985
  8.     version: December 4, 1987;
  9.         February 10, 1989  put better tracing in st_lookup.
  10.         April 16, 1990:    fix bugs in st_enter and st_init.
  11.  
  12.  
  13.     PUBLIC DOMAIN SOFTWARE
  14.  
  15.     Sherlock, including the SPP, SDEL and SDIF programs, was placed in
  16.     the public domain on June 15, 1991, by its author,
  17.  
  18.         Edward K. Ream
  19.         166 North Prospect Ave.
  20.         Madison, WI 53705.
  21.         (608) 257-0802
  22.  
  23.     Sherlock may be used for any commercial or non-commercial purpose.
  24.  
  25.  
  26.     DISCLAIMER OF WARRANTIES
  27.  
  28.     Edward K. Ream (Ream) specifically disclaims all warranties,
  29.     expressed or implied, with respect to this computer software,
  30.     including but not limited to implied warranties of merchantability
  31.     and fitness for a particular purpose.  In no event shall Ream be
  32.     liable for any loss of profit or any commercial damage, including
  33.     but not limited to special, incidental consequential or other damages.
  34. */
  35.  
  36. #include "spp.h"
  37.  
  38. /* Define static routines. */
  39. static int st_hash(char *s);
  40.  
  41. /*
  42.     Define the format of symbol table nodes.
  43. */
  44. #define ST_PRIME 101
  45. typedef struct st_node symtab;
  46.  
  47. static struct st_node {
  48.     symtab *  st_next;
  49.     symtab *  st_back;
  50.     symtab *  st_lnext;
  51.     int      st_leveln;
  52.     char *      st_name;
  53.     en_tokens st_type;    /* type for printf    */
  54.     bool      st_tdflag;    /* typedef flag        */
  55. };
  56. static symtab    st_ht [ST_PRIME];    /* The hash table. */
  57.  
  58. /*
  59.     Define the list of symbol tables.
  60. */
  61. typedef struct level_node level;
  62. static struct level_node {
  63.     level  * lev_next;
  64.     symtab * lev_lnext;
  65.     int     lev_leveln;
  66. };
  67. static level level_head = {NULL, NULL, 0};  /* Head of the list of tables. */
  68.  
  69. static int cur_level = 0;
  70.  
  71. /* ========== Debugging routines ========== */
  72.  
  73. /*
  74.     Dump all symbols of both symbol tables.
  75. */
  76. #ifdef BUG
  77. void
  78. st_dump()
  79. {
  80.     TICK("st_dump");
  81.  
  82. }
  83. #endif /* BUG */
  84.  
  85. /*
  86.     Enter a new level of the symbol table.
  87. */
  88. void
  89. st_begin(void)
  90. {
  91.     level * lp;
  92.  
  93.     TRACEP("st_begin", printf("cur_level = %d\n", cur_level+1));
  94.     cur_level++;
  95.  
  96.     lp = m_alloc(sizeof(level));
  97.     lp -> lev_next        = level_head . lev_next;
  98.     level_head . lev_next    = lp;
  99.     lp -> lev_lnext        = NULL;
  100.     lp -> lev_leveln    = cur_level;
  101. }
  102.  
  103. /*
  104.     Exit a level of the symbol table.
  105. */
  106. void
  107. st_end(void)
  108. {
  109.     symtab * sp, * next, * back;
  110.     level * lp;
  111.  
  112.     TICK("st_end");
  113.  
  114.     if (cur_level <= 0) {
  115.         syserr("st_end: cur_level <= 0");
  116.     }
  117.  
  118.     lp = level_head . lev_next;
  119.  
  120.     if (lp == NULL) {
  121.         syserr("st_end: NULL level node");
  122.     }
  123.     
  124.     /* Unlink and deallocate all st_nodes at this level. */
  125.     for (sp = lp -> lev_lnext; sp; sp = next) {
  126.  
  127.         /* Unlink the node from the bucket list. */
  128.         back        = sp -> st_back;
  129.         next        = sp -> st_next;
  130.         back -> st_next    = next;
  131.         if (next) {
  132.             next -> st_back = back;
  133.         }
  134.  
  135.         /* Deallocate the st_node. */
  136.         m_free(sp);
  137.     }
  138.  
  139.     /* Unlink the level node. */
  140.     level_head . lev_next = lp -> lev_next;
  141.     m_free(lp);
  142.     cur_level--;
  143. }
  144.  
  145.  
  146. /*
  147.     Place a symbol at the start of the hash list.
  148.     This will insure that any new definition hides previous defs.
  149. */
  150. void
  151. st_enter (char *symbol, en_tokens type, bool td_flag)
  152. {
  153.     register symtab * p;
  154.     register level * lp;
  155.     int hash;
  156.  
  157.     TRACEP("st_enter", printf("(%s, %s, %d)\n",
  158.         symbol, pr_op(type), td_flag));
  159.  
  160.     if (symbol == NULL) {
  161.         error("st_enter: internal: NULL symbol");
  162.         symbol = "";
  163.         return;
  164.     }
  165.  
  166.     /* Dynamically allocate space for node. */
  167.     p = m_alloc(sizeof(symtab));
  168.     
  169.     /* Hang node from hash table. */
  170.     hash = st_hash(symbol);
  171.     p -> st_next        = st_ht [hash] . st_next;
  172.     p -> st_back        = &st_ht [hash];
  173.     st_ht [hash] . st_next    = p;
  174.  
  175.     /* Link the node to the level list. */
  176.     lp        = level_head . lev_next;
  177.     p -> st_lnext    = lp -> lev_lnext;
  178.     lp -> lev_lnext    = p;
  179.     p -> st_leveln    = cur_level;
  180.     
  181.     /* Fill in the name and type. */
  182.     p -> st_type    = type;
  183.     p -> st_name    = str_alloc(symbol);
  184.     p -> st_tdflag  = td_flag;
  185. }
  186.  
  187. /*
  188.     Compute the hash function for a local symbol.
  189. */
  190. static int
  191. st_hash (sym)
  192. register char * sym;
  193. {
  194.     register int hash;
  195.  
  196.     TRACEP("st_hash", printf("(%s)\n", sym));
  197.  
  198.     for (hash = 0; *sym; ) {
  199.         hash *= 3;
  200.         hash += (int) *sym++;
  201.         hash %= ST_PRIME;
  202.     }
  203.  
  204.     TRACEPN("st_hash", printf("returns: %d\n", hash));
  205.     return hash;
  206. }
  207.  
  208. /*
  209.     Initialize the symbol tables for the very first time.
  210. */
  211. void
  212. st_init(void)
  213. {
  214.     int i;
  215.     register symtab *p;
  216.  
  217.     TICK("st_init");
  218.  
  219.     /* Initialize the hash table. */
  220.     for(i = 0; i < ST_PRIME; i++) {
  221.         p = & st_ht [i];
  222.         p -> st_next    = NULL;
  223.         p -> st_back    = NULL;
  224.         p -> st_lnext    = NULL;
  225.         p -> st_leveln    = 0;
  226.         p -> st_name    = "<header>";
  227.     }
  228.  
  229.     /* bug fix: 4/16/90 
  230.         Required so st_enter doesn't dereference a NULL pointer.
  231.     */
  232.     st_begin();
  233. }
  234.  
  235. /*
  236.     Look up a symbol in the local symbol table.
  237.     Return a type token.
  238. */
  239. bool
  240. st_lookup (register char * symbol, en_tokens * type, bool * td_flag)
  241. {
  242.     register symtab * sp;
  243.     int hash;
  244.  
  245.     TRACEP("st_lookup", printf("(%s)\n", symbol));
  246.  
  247.     /* Search down the list of st_nodes. */
  248.     hash = st_hash(symbol);
  249.     for (sp = st_ht [hash] . st_next; sp; sp = sp -> st_next) {
  250.  
  251.         TRACEN("v", printf("compare with <%s>\n", sp -> st_name));
  252.  
  253.         if(str_eq(symbol, sp -> st_name)) {
  254.  
  255.             TRACEPN("st_lookup",
  256.                 printf("sets *type = %s, ",
  257.                     pr_op(sp -> st_type));
  258.                 printf("*td_flag = %d\n", sp -> st_tdflag));
  259.  
  260.             *type    = sp -> st_type;
  261.             *td_flag = sp -> st_tdflag;
  262.             return TRUE;
  263.         }
  264.     }
  265.  
  266.     TRACEPN("st_lookup", printf("not found\n"));
  267.     return FALSE;
  268. }
  269.