/[m4]/m4/m4/symtab.c
ViewVC logotype

Diff of /m4/m4/symtab.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.7 by gary, Sat Sep 1 16:10:40 2001 UTC revision 1.8 by gary, Sat Sep 1 20:05:27 2001 UTC
# Line 32  Line 32 
32    
33  #include "m4private.h"  #include "m4private.h"
34    
35  /* Initialise the symbol table, by allocating the necessary storage, and  static size_t   m4_symtab_hash          (const void *key);
36     zeroing all the entries.  */  static int      m4_symtab_cmp           (const void *key, const void *try);
37    static void     m4_token_data_delete    (m4_token_data *data);
38    static void     m4_symbol_popdef        (m4_symbol *symbol);
39    static void     m4_symbol_delete        (m4_symbol *symbol);
40    
41    
42  /* Pointer to symbol table.  */  /* Pointer to symbol table.  */
43  m4_symbol **m4_symtab;  m4_hash *m4_symtab = 0;
44    
45    
46    
47  void  void
48  m4_symtab_init (void)  m4_symtab_init (void)
49  {  {
50    int i;    m4_symtab = m4_hash_new (m4_symtab_hash, m4_symtab_cmp);
   m4_symbol **symbol;  
   
   symbol = m4_symtab = XMALLOC (m4_symbol *, hash_table_size);  
   
   for (i = hash_table_size; --i >= 0;)  
     *symbol++ = NULL;  
51  }  }
52    
53  /* Return a hashvalue for a string, from GNU-emacs.  */  /* Return a hashvalue for a string, from GNU-emacs.  */
54  static int  size_t
55  hash (const char *s)  m4_symtab_hash (const void *key)
56  {  {
57    register int val = 0;    int val = 0;
58      const char *ptr = (const char *) key;
59    register const char *ptr = s;    char ch;
   register char ch;  
60    
61    while ((ch = *ptr++) != '\0')    while ((ch = *ptr++) != '\0')
62      {      {
# Line 66  hash (const char *s) Line 65  hash (const char *s)
65        val = ((val << 3) + (val >> 28) + ch);        val = ((val << 3) + (val >> 28) + ch);
66      };      };
67    val = (val < 0) ? -val : val;    val = (val < 0) ? -val : val;
68    return val % hash_table_size;    return val;
69    }
70    
71    int
72    m4_symtab_cmp (const void *key, const void *try)
73    {
74      return (strcmp ((const char *) key, (const char *) try));
75    }
76    
77    
78    
79    void
80    m4_token_data_delete (m4_token_data *data)
81    {
82      assert (data);
83      assert (M4_TOKEN_DATA_NEXT (data) == 0);
84    
85      if (M4_TOKEN_DATA_TYPE (data) == M4_TOKEN_TEXT)
86        XFREE (M4_TOKEN_DATA_TEXT (data));
87    
88      XFREE (data);
89    }
90    
91    void
92    m4_symbol_popdef (m4_symbol *symbol)
93    {
94      m4_token_data *stale;
95    
96      assert (symbol);
97      assert (M4_SYMBOL_DATA_NEXT (symbol));
98    
99      stale                 = M4_SYMBOL_DATA (symbol);
100      M4_SYMBOL_DATA (symbol)       = M4_TOKEN_DATA_NEXT (stale);
101    
102    #ifndef NDEBUG
103      M4_TOKEN_DATA_NEXT (stale) = 0;
104    #endif
105      m4_token_data_delete (stale);
106  }  }
107    
108  /* Free all storage associated with a symbol.  */  /* Free all storage associated with a symbol.  */
109  static void  void
110  free_symbol (m4_symbol *symbol)  m4_symbol_delete (m4_symbol *symbol)
111  {  {
112    if (M4_SYMBOL_NAME (symbol))    assert (symbol);
113      xfree (M4_SYMBOL_NAME (symbol));  
114      while (M4_SYMBOL_DATA_NEXT (symbol))
115        m4_symbol_popdef (symbol);
116    
117      assert (M4_SYMBOL_DATA_NEXT (symbol) == 0);
118    
119    if (M4_SYMBOL_TYPE (symbol) == M4_TOKEN_TEXT)    if (M4_SYMBOL_TYPE (symbol) == M4_TOKEN_TEXT)
120      xfree (M4_SYMBOL_TEXT (symbol));      XFREE (M4_SYMBOL_TEXT (symbol));
121    xfree ((void *) symbol);  
122      XFREE (M4_SYMBOL_DATA (symbol));
123      XFREE (symbol);
124  }  }
125    
126  /* Search in, and manipulation of the symbol table, are all done by  /* Search in, and manipulation of the symbol table, are all done by
# Line 93  free_symbol (m4_symbol *symbol) Line 136  free_symbol (m4_symbol *symbol)
136  m4_symbol *  m4_symbol *
137  m4_lookup_symbol (const char *name, m4_symbol_lookup mode)  m4_lookup_symbol (const char *name, m4_symbol_lookup mode)
138  {  {
139    if (mode != M4_SYMBOL_IGNORE)    if (mode == M4_SYMBOL_IGNORE)
140      {      return 0;
       int cmp = 1;  
       int h = hash (name);  
       m4_symbol *symbol = m4_symtab[h];  
       m4_symbol **spp, *prev;  
   
       for (prev = NULL; symbol != NULL; prev = symbol, symbol = symbol->next)  
         {  
           cmp = strcmp (M4_SYMBOL_NAME (symbol), name);  
           if (cmp >= 0)  
             break;  
         }  
141    
142        /* If just searching, return status of search.  */    {
143        m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name);
144    
145        if (mode == M4_SYMBOL_LOOKUP)      switch (mode)
146          return cmp == 0 ? symbol : NULL;        {
147          case M4_SYMBOL_LOOKUP:
148        /* Symbol not found.  */          /* If just searching, return status of search.  */
149            return psymbol ? *psymbol : 0;
150        spp = (prev != NULL) ?  &prev->next : &m4_symtab[h];  
151          case M4_SYMBOL_INSERT:
152        switch (mode)          /* Return the symbol, if the name was found in the table.
153               Otherwise, just insert the name, and return the new symbol.  */
154            if (psymbol)
155              return *psymbol;
156            /* NOBREAK */
157    
158          case M4_SYMBOL_PUSHDEF:
159            /* Insert a name in the symbol table.  If there is already a symbol
160               with the name, push the new value on top of the value stack for
161               this symbol.  */
162          {          {
163              m4_symbol *symbol             = 0;
164              m4_token_data *value          = XCALLOC (m4_token_data, 1);
165    
166          case M4_SYMBOL_INSERT:            if (psymbol)
   
           /* Return the symbol, if the name was found in the table.  
              Otherwise, just insert the name, and return the new symbol.  */  
   
           if (cmp == 0 && symbol != NULL)  
             return symbol;  
           /* Fall through.  */  
   
         case M4_SYMBOL_PUSHDEF:  
   
           /* Insert a name in the symbol table.  If there is already a symbol  
              with the name, insert this in front of it, and mark the old  
              symbol as "shadowed".  */  
   
           symbol = XMALLOC (m4_symbol, 1);  
           M4_SYMBOL_TYPE (symbol) = M4_TOKEN_VOID;  
           M4_SYMBOL_TRACED (symbol) = M4_SYMBOL_SHADOWED (symbol) = FALSE;  
           M4_SYMBOL_NAME (symbol) = xstrdup (name);  
   
           M4_SYMBOL_NEXT (symbol) = *spp;  
           (*spp) = symbol;  
   
           if (mode == M4_SYMBOL_PUSHDEF && cmp == 0)  
167              {              {
168                M4_SYMBOL_SHADOWED (M4_SYMBOL_NEXT (symbol)) = TRUE;                symbol = *psymbol;
169                M4_SYMBOL_TRACED (symbol) = M4_SYMBOL_TRACED (M4_SYMBOL_NEXT (symbol));                M4_TOKEN_DATA_NEXT (value)= M4_SYMBOL_DATA (symbol);
170              }              }
171            return symbol;            else
172                symbol = XCALLOC (m4_symbol, 1);
         case M4_SYMBOL_DELETE:  
   
           /* Delete all occurences of symbols with NAME.  */  
173    
174            if (cmp != 0 || symbol == NULL)            M4_SYMBOL_DATA (symbol)       = value;
175              return NULL;            M4_SYMBOL_TYPE (symbol)       = M4_TOKEN_VOID;
           do  
             {  
               *spp = M4_SYMBOL_NEXT (symbol);  
               free_symbol (symbol);  
               symbol = *spp;  
             }  
           while (symbol != NULL && strcmp (name, M4_SYMBOL_NAME (symbol)) == 0);  
           return NULL;  
176    
177          case M4_SYMBOL_POPDEF:            if (!psymbol)
178                m4_hash_insert (m4_symtab, xstrdup (name), symbol);
179    
180            /* Delete the first occurence of a symbol with NAME.  */            return symbol;
181            }
182    
183            if (cmp != 0 || symbol == NULL)        case M4_SYMBOL_POPDEF:
184              return NULL;          /* Delete the first occurence of a symbol with NAME.  */
185            if (M4_SYMBOL_NEXT (symbol) != NULL && cmp == 0)          if (psymbol)
186              M4_SYMBOL_SHADOWED (M4_SYMBOL_NEXT (symbol)) = FALSE;            {
187            *spp = M4_SYMBOL_NEXT (symbol);              if (M4_SYMBOL_DATA_NEXT (*psymbol))
188            free_symbol (symbol);                m4_symbol_popdef (*psymbol);
189            return NULL;              else
190                  {
191                    xfree (m4_hash_remove (m4_symtab, name));
192                    m4_symbol_delete (*psymbol);
193                  }
194              }
195            return 0;
196    
197          default:        case M4_SYMBOL_DELETE:
198            /* Delete all occurences of symbols with NAME.  */
199            if (psymbol)
200              {
201                xfree (m4_hash_remove (m4_symtab, name));
202                m4_symbol_delete (*psymbol);
203              }
204            else
205            M4ERROR ((warning_status, 0,            M4ERROR ((warning_status, 0,
206                      _("INTERNAL ERROR: Illegal mode to m4_symbol_lookup ()")));                    _("INTERNAL ERROR: Attempt to delete non-existant symbol")));
207            abort ();          return 0;
208          }  
209      }        default:
210            M4ERROR ((warning_status, 0,
211                      _("INTERNAL ERROR: Illegal mode to m4_symbol_lookup ()")));
212            abort ();
213          }
214      }
215    
216    return NULL;    /*NOTREACHED*/
217      return 0;
218  }  }
219    
220  /* The following function removes from the symbol table, every symbol  /* The following function removes from the symbol table, every symbol
221     that references a function in the given builtin table.  */     that references the given module handle.  */
222  void  void
223  m4_remove_table_reference_symbols (m4_builtin *builtins, m4_macro *macros)  m4_remove_table_reference_symbols (lt_dlhandle handle)
224  {  {
225    /* FIXME:  This can be reimplemented to work much faster now that each    m4_hash_iterator *place = 0;
226       symtab entry carries a reference to its defining module.  */  
227    m4_symbol *symbol;    assert (handle);
   int h;  
228    
229    /* Look in each bucket of the hashtable... */    while ((place = m4_hash_iterator_next (m4_symtab, place)))
   for (h = 0; h < hash_table_size; h++)  
230      {      {
231        m4_symbol *prev = NULL;        m4_symbol *symbol = (m4_symbol *) m4_hash_iterator_value (place);
232        m4_symbol *next = NULL;        m4_token_data *data = M4_SYMBOL_DATA (symbol);
233    
234        /* And each symbol in each hash bucket... */        /* Purge any shadowed references.  */
235        for (symbol = m4_symtab[h]; symbol != NULL; prev = symbol, symbol = next)        while (M4_TOKEN_DATA_NEXT (data))
236          {          {
237            next = M4_SYMBOL_NEXT (symbol);            m4_token_data *next = M4_TOKEN_DATA_NEXT (data);
238    
239            switch (M4_SYMBOL_TYPE (symbol))            if (M4_TOKEN_DATA_HANDLE (next) == handle)
240              {              {
241              case M4_TOKEN_FUNC:                M4_TOKEN_DATA_NEXT (data) = M4_TOKEN_DATA_NEXT (next);
242                /* For symbol functions referencing a function in                m4_token_data_delete (next);
243                   BUILTIN_TABLE.  */              }
244                {            else
245                  const m4_builtin *bp;              data = next;
246                  for (bp = builtins; symbol && bp && bp->name != NULL; ++bp)          }
                   if (M4_SYMBOL_FUNC (symbol) == bp->func)  
                     {  
                       if (prev)  
                         M4_SYMBOL_NEXT (prev) = M4_SYMBOL_NEXT (symbol);  
                       else  
                         m4_symtab[h] = M4_SYMBOL_NEXT (symbol);  
   
                       /* Unshadow any symbol that this one had shadowed. */  
                       if (M4_SYMBOL_NEXT (symbol) != NULL)  
                         M4_SYMBOL_SHADOWED (M4_SYMBOL_NEXT (symbol)) = FALSE;  
   
                       free_symbol (symbol);  
   
                       /* Maintain the loop invariant. */  
                       symbol = prev;  
                     }  
               }  
               break;  
   
             case M4_TOKEN_TEXT:  
               /* For symbol macros referencing a value in  
                  PREDEFINED_TABLE.  */  
               {  
                 const m4_macro *mp;  
                 for (mp = macros; symbol && mp && mp->name; mp++)  
                   if ((strcmp(M4_SYMBOL_NAME (symbol), mp->name) == 0)  
                       && (strcmp (M4_SYMBOL_TEXT (symbol), mp->value) == 0))  
                     {  
                       if (prev)  
                         M4_SYMBOL_NEXT (prev) = M4_SYMBOL_NEXT (symbol);  
                       else  
                         m4_symtab[h] = M4_SYMBOL_NEXT (symbol);  
   
                       /* Unshadow any symbol that this one had shadowed. */  
                       if (M4_SYMBOL_NEXT (symbol) != NULL)  
                         M4_SYMBOL_SHADOWED (M4_SYMBOL_NEXT (symbol)) = FALSE;  
   
                       free_symbol (symbol);  
   
                       /* Maintain the loop invariant. */  
                       symbol = prev;  
                     }  
               }  
               break;  
247    
248              default:        /* Purge live reference.  */
249                /*NOWORK*/        if (M4_SYMBOL_HANDLE (symbol) == handle)
250                break;          {
251              if (M4_SYMBOL_DATA_NEXT (symbol))
252                m4_symbol_popdef (symbol);
253              else
254                {
255                  xfree (m4_hash_remove (m4_symtab, m4_hash_iterator_key (place)));
256                  m4_symbol_delete (symbol);
257              }              }
258          }          }
259      }      }
# Line 273  m4_remove_table_reference_symbols (m4_bu Line 264  m4_remove_table_reference_symbols (m4_bu
264     hack_all_symbols () traverses the symbol table, and calls a specified     hack_all_symbols () traverses the symbol table, and calls a specified
265     function FUNC for each symbol in the table.  FUNC is called with a     function FUNC for each symbol in the table.  FUNC is called with a
266     pointer to the symbol, and the DATA argument.  */     pointer to the symbol, and the DATA argument.  */
267  void  int
268  m4_hack_all_symbols (m4_hack_symbol *func, const char *data)  m4_symtab_apply (m4_symtab_apply_func *func, void *data)
269  {  {
270    int h;    int result = 0;
271    m4_symbol *symbol;    m4_hash_iterator *place = 0;
272    
273    for (h = 0; h < hash_table_size; h++)    assert (func);
274      for (symbol = m4_symtab[h]; symbol != NULL; symbol = M4_SYMBOL_NEXT (symbol))  
275        (*func) (symbol, data);    while ((place = m4_hash_iterator_next (m4_symtab, place)))
276        {
277          const char *name  = (const char *) m4_hash_iterator_key (place);
278          m4_symbol *symbol = (m4_symbol *) m4_hash_iterator_value (place);
279          result = (*func) (name, symbol, data);
280    
281          if (result != 0)
282            break;
283        }
284    
285      return result;
286  }  }
287    
288    
289    
290  #ifdef DEBUG_SYM  #ifdef DEBUG_SYM
291    
292    static int symtab_print_list (const char *name, m4_symbol *symbol, void *ignored);
293    
294  static void  static void
295  symtab_debug (void)  symtab_debug (void)
296  {  {
# Line 295  symtab_debug (void) Line 300  symtab_debug (void)
300    m4_symbol *s;    m4_symbol *s;
301    int delete;    int delete;
302    
303    while ((t = next_token (&td)) != NULL)    while ((t = m4_next_token (&td)) != NULL)
304      {      {
305        if (t != M4_TOKEN_WORD)        if (t != M4_TOKEN_WORD)
306          continue;          continue;
# Line 318  symtab_debug (void) Line 323  symtab_debug (void)
323        else        else
324          (void) m4_lookup_symbol (text, M4_SYMBOL_INSERT);          (void) m4_lookup_symbol (text, M4_SYMBOL_INSERT);
325      }      }
326    m4_hack_all_symbols (symtab_print_list, "foo");    m4_symtab_apply (symtab_print_list, 0);
327  }  }
328    
329  static void  static int
330  symtab_print_list (int i)  symtab_print_list (const char *name, m4_symbol *symbol, void *ignored)
331  {  {
332    m4_symbol *symbol;    printf ("\tname %s, addr %#x, flags: %s\n",
333              name, (unsigned) symbol,
334    printf ("Symbol dump #%d:\n", i);            M4_SYMBOL_TRACED (symbol) ? " traced" : "<none>");
335    for (symbol = m4_symtab[i]; symbol != NULL; symbol = symbol->next)    return 0;
     printf ("\tname %s, addr 0x%x, next 0x%x, flags%s%s\n",  
            M4_SYMBOL_NAME (symbol), symbol, symbol->next,  
            M4_SYMBOL_TRACED (symbol) ? " traced" : "",  
            M4_SYMBOL_SHADOWED (symbol) ? " shadowed" : "");  
336  }  }
337    
338  #endif /* DEBUG_SYM */  #endif /* DEBUG_SYM */

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26