/[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.37 by gary, Tue Jun 17 15:17:45 2003 UTC revision 1.38 by gary, Wed Jun 18 16:21:54 2003 UTC
# Line 28  Line 28 
28     symbol is represented by `struct m4_symbol', which is stored in the hash     symbol is represented by `struct m4_symbol', which is stored in the hash
29     table keyed by the symbol name.  As a special case, to facilitate the     table keyed by the symbol name.  As a special case, to facilitate the
30     "pushdef" and "popdef" builtins, the value stored against each key is a     "pushdef" and "popdef" builtins, the value stored against each key is a
31     stack of `struct m4_token'. All the value entries for a symbol name are     stack of `struct m4_symbol_value'. All the value entries for a symbol name are
32     simply ordered on the stack by age.  The most recently pushed definition     simply ordered on the stack by age.  The most recently pushed definition
33     will then always be the first found.     will then always be the first found.
34    
# Line 43  Line 43 
43     value stacks) are invisible to the users of this module.  */     value stacks) are invisible to the users of this module.  */
44    
45  #define M4_SYMTAB_DEFAULT_SIZE          2047  #define M4_SYMTAB_DEFAULT_SIZE          2047
 #define M4_ARG_SIGNATURE_DEFAULT_SIZE   7  
46    
47  static m4_symbol *symtab_fetch          (m4_symtab*, const char *);  static m4_symbol *symtab_fetch          (m4_symtab*, const char *);
48  static void       symbol_popval         (m4_symbol *symbol);  static void       symbol_popval         (m4_symbol *symbol);
49  static int        symbol_destroy        (m4_hash *hash, const void *name,  static void *     symbol_destroy        (m4_hash *hash, const void *name,
50                                           void *symbol, void *ignored);                                           void *symbol, void *ignored);
51  static int        arg_destroy           (m4_hash *hash, const void *name,  static void *     arg_destroy           (m4_hash *hash, const void *name,
52                                           void *arg, void *ignored);                                           void *arg, void *ignored);
53  static m4_hash *  arg_signature_parse   (const char *name, const char *param);  static void *     arg_copy              (m4_hash *src, const void *name,
54                                             void *arg, m4_hash *dest);
55    
56    
57  /* -- SYMBOL TABLE MANAGEMENT --  /* -- SYMBOL TABLE MANAGEMENT --
# Line 108  m4__symtab_remove_module_references (m4_ Line 107  m4__symtab_remove_module_references (m4_
107    assert (handle);    assert (handle);
108    
109     /* Traverse each symbol name in the hash table.  */     /* Traverse each symbol name in the hash table.  */
110    while ((place = m4_hash_iterator_next (symtab, place)))    while ((place = m4_get_hash_iterator_next (symtab, place)))
111      {      {
112        m4_symbol *symbol = (m4_symbol *) m4_hash_iterator_value (place);        m4_symbol *symbol = (m4_symbol *) m4_get_hash_iterator_value (place);
113        m4_token  *data   = SYMBOL_TOKEN (symbol);        m4_symbol_value  *data   = SYMBOL_VALUE (symbol);
114    
115        /* For symbols that have token data... */        /* For symbols that have token data... */
116        if (data)        if (data)
117          {          {
118            /* Purge any shadowed references.  */            /* Purge any shadowed references.  */
119            while (TOKEN_NEXT (data))            while (VALUE_NEXT (data))
120              {              {
121                m4_token *next = TOKEN_NEXT (data);                m4_symbol_value *next = VALUE_NEXT (data);
122    
123                if (TOKEN_HANDLE (next) == handle)                if (VALUE_HANDLE (next) == handle)
124                  {                  {
125                    TOKEN_NEXT (data) = TOKEN_NEXT (next);                    VALUE_NEXT (data) = VALUE_NEXT (next);
126    
127                    if (TOKEN_TYPE (next) == M4_TOKEN_TEXT)                    if (VALUE_TYPE (next) == M4_SYMBOL_TEXT)
128                      XFREE (TOKEN_TEXT (next));                      XFREE (VALUE_TEXT (next));
129                    XFREE (next);                    XFREE (next);
130                  }                  }
131                else                else
# Line 135  m4__symtab_remove_module_references (m4_ Line 134  m4__symtab_remove_module_references (m4_
134    
135            /* Purge the live reference if necessary.  */            /* Purge the live reference if necessary.  */
136            if (SYMBOL_HANDLE (symbol) == handle)            if (SYMBOL_HANDLE (symbol) == handle)
137              m4_symbol_popdef (symtab, m4_hash_iterator_key (place));              m4_symbol_popdef (symtab, m4_get_hash_iterator_key (place));
138          }          }
139      }      }
140  }  }
141    
142    
143  /* This callback is used exclusively by m4__symtab_exit(), to cleanup  /* This callback is used exclusively by m4_symtab_delete(), to cleanup
144     the memory used by the symbol table.  As such, the trace bit is reset     the memory used by the symbol table.  As such, the trace bit is reset
145     on every symbol so that m4_symbol_popdef() doesn't try to preserve     on every symbol so that m4_symbol_popdef() doesn't try to preserve
146     the table entry.  */     the table entry.  */
147  static int  static void *
148  symbol_destroy (m4_hash *hash, const void *name, void *symbol, void *ignored)  symbol_destroy (m4_hash *hash, const void *name, void *symbol, void *ignored)
149  {  {
150    char *key = xstrdup ((char *) name);    char *key = xstrdup ((char *) name);
# Line 157  symbol_destroy (m4_hash *hash, const voi Line 156  symbol_destroy (m4_hash *hash, const voi
156    
157    XFREE (key);    XFREE (key);
158    
159    return 0;    return NULL;
160  }  }
161    
162    
# Line 176  m4_symbol_lookup (m4_symtab *symtab, con Line 175  m4_symbol_lookup (m4_symtab *symtab, con
175    
176    /* If just searching, return status of search -- if only an empty    /* If just searching, return status of search -- if only an empty
177       struct is returned, that is treated as a failed lookup.  */       struct is returned, that is treated as a failed lookup.  */
178    return (psymbol && SYMBOL_TOKEN (*psymbol)) ? *psymbol : 0;    return (psymbol && SYMBOL_VALUE (*psymbol)) ? *psymbol : 0;
179  }  }
180    
181    
# Line 184  m4_symbol_lookup (m4_symtab *symtab, con Line 183  m4_symbol_lookup (m4_symtab *symtab, con
183     associated with NAME, push the new VALUE on top of the value stack     associated with NAME, push the new VALUE on top of the value stack
184     for this symbol.  Otherwise create a new association.  */     for this symbol.  Otherwise create a new association.  */
185  m4_symbol *  m4_symbol *
186  m4_symbol_pushdef (m4_symtab *symtab, const char *name, m4_token *value)  m4_symbol_pushdef (m4_symtab *symtab, const char *name, m4_symbol_value *value)
187  {  {
188    m4_symbol *symbol;    m4_symbol *symbol;
189    
# Line 193  m4_symbol_pushdef (m4_symtab *symtab, co Line 192  m4_symbol_pushdef (m4_symtab *symtab, co
192    assert (value);    assert (value);
193    
194    symbol                = symtab_fetch (symtab, name);    symbol                = symtab_fetch (symtab, name);
195    TOKEN_NEXT (value)    = SYMBOL_TOKEN (symbol);    VALUE_NEXT (value)    = SYMBOL_VALUE (symbol);
196    SYMBOL_TOKEN (symbol) = value;    SYMBOL_VALUE (symbol) = value;
197    
198    assert (SYMBOL_TOKEN (symbol));    assert (SYMBOL_VALUE (symbol));
199    
200    return symbol;    return symbol;
201  }  }
# Line 204  m4_symbol_pushdef (m4_symtab *symtab, co Line 203  m4_symbol_pushdef (m4_symtab *symtab, co
203  /* Return the symbol associated with NAME in the symbol table, creating  /* Return the symbol associated with NAME in the symbol table, creating
204     a new symbol if necessary.  In either case set the symbol's VALUE.  */     a new symbol if necessary.  In either case set the symbol's VALUE.  */
205  m4_symbol *  m4_symbol *
206  m4_symbol_define (m4_symtab *symtab, const char *name, m4_token *value)  m4_symbol_define (m4_symtab *symtab, const char *name, m4_symbol_value *value)
207  {  {
208    m4_symbol *symbol;    m4_symbol *symbol;
209    
# Line 213  m4_symbol_define (m4_symtab *symtab, con Line 212  m4_symbol_define (m4_symtab *symtab, con
212    assert (value);    assert (value);
213    
214    symbol = symtab_fetch (symtab, name);    symbol = symtab_fetch (symtab, name);
215    if (SYMBOL_TOKEN (symbol))    if (SYMBOL_VALUE (symbol))
216      symbol_popval (symbol);      symbol_popval (symbol);
217    
218    TOKEN_NEXT (value)    = SYMBOL_TOKEN (symbol);    VALUE_NEXT (value)    = SYMBOL_VALUE (symbol);
219    SYMBOL_TOKEN (symbol) = value;    SYMBOL_VALUE (symbol) = value;
220    
221    assert (SYMBOL_TOKEN (symbol));    assert (SYMBOL_VALUE (symbol));
222    
223    return symbol;    return symbol;
224  }  }
# Line 253  m4_symbol_popdef (m4_symtab *symtab, con Line 252  m4_symbol_popdef (m4_symtab *symtab, con
252    
253    /* Only remove the hash table entry if the last value in the    /* Only remove the hash table entry if the last value in the
254       symbol value stack was successfully removed.  */       symbol value stack was successfully removed.  */
255    if (!SYMBOL_TOKEN (*psymbol))    if (!SYMBOL_VALUE (*psymbol))
256      if (no_gnu_extensions || !SYMBOL_TRACED (*psymbol))      if (no_gnu_extensions || !SYMBOL_TRACED (*psymbol))
257        {        {
258          XFREE (*psymbol);          XFREE (*psymbol);
# Line 265  m4_symbol_popdef (m4_symtab *symtab, con Line 264  m4_symbol_popdef (m4_symtab *symtab, con
264  static void  static void
265  symbol_popval (m4_symbol *symbol)  symbol_popval (m4_symbol *symbol)
266  {  {
267    m4_token  *stale;    m4_symbol_value  *stale;
268    
269    assert (symbol);    assert (symbol);
270    
271    stale = SYMBOL_TOKEN (symbol);    stale = SYMBOL_VALUE (symbol);
272    
273    if (stale)    if (stale)
274      {      {
275        SYMBOL_TOKEN (symbol) = TOKEN_NEXT (stale);        SYMBOL_VALUE (symbol) = VALUE_NEXT (stale);
276    
277        if (TOKEN_ARG_SIGNATURE (stale))        if (VALUE_ARG_SIGNATURE (stale))
278          {          {
279            m4_hash_apply (TOKEN_ARG_SIGNATURE (stale), arg_destroy, NULL);            m4_hash_apply (VALUE_ARG_SIGNATURE (stale), arg_destroy, NULL);
280            m4_hash_delete (TOKEN_ARG_SIGNATURE (stale));            m4_hash_delete (VALUE_ARG_SIGNATURE (stale));
281          }          }
282        if (TOKEN_TYPE (stale) == M4_TOKEN_TEXT)        if (VALUE_TYPE (stale) == M4_SYMBOL_TEXT)
283          XFREE (TOKEN_TEXT (stale));          XFREE (VALUE_TEXT (stale));
284        XFREE (stale);        XFREE (stale);
285      }      }
286  }  }
287    
288  /* Callback used by m4_symbol_popdef () to release the memory used  /* Callback used by m4_symbol_popdef () to release the memory used
289     by values in the arg_signature hash.  */     by values in the arg_signature hash.  */
290  static int  static void *
291  arg_destroy (m4_hash *hash, const void *name, void *arg, void *ignored)  arg_destroy (m4_hash *hash, const void *name, void *arg, void *ignored)
292  {  {
293    struct m4_token_arg *token_arg = (struct m4_token_arg *) arg;    struct m4_symbol_arg *token_arg = (struct m4_symbol_arg *) arg;
294    
295    assert (name);    assert (name);
296    assert (hash);    assert (hash);
297    
298    if (TOKEN_ARG_DEFAULT (token_arg))    if (SYMBOL_ARG_DEFAULT (token_arg))
299      XFREE (TOKEN_ARG_DEFAULT (token_arg));      XFREE (SYMBOL_ARG_DEFAULT (token_arg));
300    xfree (token_arg);    xfree (token_arg);
301    xfree (m4_hash_remove (hash, (const char *) name));    xfree (m4_hash_remove (hash, (const char *) name));
302    
303    return 0;    return NULL;
 }  
   
 #if 0  
 m4_symbol *  
 m4_symbol_push_token (m4_symtab *symtab, const char *name, m4_token *token)  
 {  
   m4_token *next;  
   
   assert (symtab);  
   assert (name);  
   assert (token);  
   
   /* If it's a function, it must have come from a module.  */  
   assert ((TOKEN_TYPE (token) != M4_TOKEN_FUNC) || TOKEN_HANDLE (token));  
   
 #if M4PARAMS  
   const char *openp  = NULL;  
   const char *params = NULL;  
   
   if (!no_gnu_extensions)  
     {  
       /* If name contains an open paren, then parse before that paren  
          as the actual name, and the rest as a formal parameter list.  */  
       size_t len = 0;  
       for (openp = name; *openp && !M4_IS_OPEN (*openp); ++openp)  
         ++len;  
   
       if (*openp)  
         {  
           name   = xstrzdup (name, len);  
           params = 1+ openp;  
         }  
     }  
   
   if (params)  
     {  
       /* Make a hash table to map formal parameter names to  
          argv offsets, and store that in the symbol's token.  */  
       TOKEN_ARG_SIGNATURE (token) = arg_signature_parse (name, params);  
     }  
 #endif  
   
   SYMBOL_TOKEN (symbol) = token;  
   
 #if M4PARAMS  
   /* If we split name on open paren, free the copied substring.  */  
   if (params)  
     xfree ((char *) name);  
 #endif  
   
   return symbol;  
304  }  }
 #endif  
305    
306  void  void
307  m4_token_copy (m4_token *dest, m4_token *src)  m4_symbol_value_copy (m4_symbol_value *dest, m4_symbol_value *src)
308  {  {
309    m4_token *next;    m4_symbol_value *next;
310    
311    assert (dest);    assert (dest);
312    assert (src);    assert (src);
313    
314    if (TOKEN_TYPE (dest) == M4_TOKEN_TEXT)    if (VALUE_TYPE (dest) == M4_SYMBOL_TEXT)
315      xfree (TOKEN_TEXT (dest));      xfree (VALUE_TEXT (dest));
316    
317  #if M4PARAMS    if (VALUE_ARG_SIGNATURE (dest))
   if (TOKEN_ARG_SIGNATURE (dest))  
318      {      {
319        m4_hash_apply (TOKEN_ARG_SIGNATURE (dest), arg_destroy, NULL);        m4_hash_apply (VALUE_ARG_SIGNATURE (dest), arg_destroy, NULL);
320        m4_hash_delete (TOKEN_ARG_SIGNATURE (dest));        m4_hash_delete (VALUE_ARG_SIGNATURE (dest));
321      }      }
 #endif  
322    
323    /* Copy the token contents over, being careful to preserve    /* Copy the token contents over, being careful to preserve
324       the next pointer.  */       the next pointer.  */
325    next = TOKEN_NEXT (dest);    next = VALUE_NEXT (dest);
326    bcopy (src, dest, sizeof (m4_token));    bcopy (src, dest, sizeof (m4_symbol_value));
327    TOKEN_NEXT (dest) = next;    VALUE_NEXT (dest) = next;
328    
329    /* Caller is supposed to free text token strings, so we have to    /* Caller is supposed to free text token strings, so we have to
330       copy the string not just its address in that case.  */       copy the string not just its address in that case.  */
331    if (TOKEN_TYPE (src) == M4_TOKEN_TEXT)    if (VALUE_TYPE (src) == M4_SYMBOL_TEXT)
332      TOKEN_TEXT (dest) = xstrdup (TOKEN_TEXT (src));      VALUE_TEXT (dest) = xstrdup (VALUE_TEXT (src));
333    
334  #if M4PARAMS    if (VALUE_ARG_SIGNATURE (src))
335    if (TOKEN_ARG_SIGNATURE (src))      VALUE_ARG_SIGNATURE (dest) = m4_hash_dup (VALUE_ARG_SIGNATURE (src),
336      TOKEN_ARG_SIGNATURE (dest) = m4_hash_dup (TOKEN_ARG_SIGNATURE (token));                                                arg_copy);
 #endif  
337  }  }
338    
339  #if M4PARAMS  static void *
340  static m4_hash *  arg_copy (m4_hash *src, const void *name, void *arg, m4_hash *dest)
 arg_signature_parse (const char *name, const char *params)  
341  {  {
342    m4_hash *arg_signature;    m4_hash_insert ((m4_hash *) dest, name, arg);
343    const char *commap;    return NULL;
   int offset;  
   
   assert (params);  
   
   arg_signature = m4_hash_new (M4_ARG_SIGNATURE_DEFAULT_SIZE,  
                         m4_hash_string_hash, m4_hash_string_cmp);  
   
   for (offset = 1; *params && !M4_IS_CLOSE (*params); ++offset)  
     {  
       size_t len = 0;  
   
       /* Skip leading whitespace.  */  
       while (M4_IS_SPACE (*params))  
         ++params;  
   
       for (commap = params; *commap && M4_IS_IDENT (*commap); ++commap)  
         ++len;  
   
       /* Skip trailing whitespace.  */  
       while (M4_IS_SPACE (*commap))  
         ++commap;  
   
       if (!M4_IS_COMMA (*commap) && !M4_IS_CLOSE (*commap))  
         M4ERROR ((EXIT_FAILURE, 0,  
                   _("Error: %s: syntax error in parameter list at char `%c'"),  
                   name, *commap));  
   
       /* Skip parameter delimiter.  */  
       if (M4_IS_COMMA (*commap))  
         ++commap;  
   
       if (len)  
         {  
           struct m4_token_arg *arg = XCALLOC (struct m4_token_arg, 1);  
   
           TOKEN_ARG_INDEX (arg) = offset;  
   
           m4_hash_insert (arg_signature, xstrzdup (params, len), arg);  
   
           params = commap;  
         }  
     }  
   
   if (!M4_IS_CLOSE (*commap))  
     M4WARN ((warning_status, 0,  
              _("Warning: %s: unterminated parameter list"), name));  
   
   return arg_signature;  
344  }  }
 #endif  
   
345    
346    
347  #ifdef DEBUG_SYM  #ifdef DEBUG_SYM
# Line 463  symtab_dump (m4_symtab *symtab) Line 356  symtab_dump (m4_symtab *symtab)
356  {  {
357    m4_hash_iterator *place = 0;    m4_hash_iterator *place = 0;
358    
359    while ((place = m4_hash_iterator_next ((m4_hash *) symtab, place)))    while ((place = m4_get_hash_iterator_next ((m4_hash *) symtab, place)))
360      {      {
361        const char   *symbol_name = (const char *) m4_hash_iterator_key (place);        const char   *symbol_name = (const char *) m4_get_hash_iterator_key (place);
362        m4_symbol    *symbol      = m4_hash_iterator_value (place);        m4_symbol    *symbol      = m4_get_hash_iterator_value (place);
363        m4_token     *token       = SYMBOL_TOKEN (symbol);        m4_symbol_value *token    = SYMBOL_VALUE (symbol);
364        int           flags       = token ? SYMBOL_FLAGS (symbol) : 0;        int           flags       = token ? SYMBOL_FLAGS (symbol) : 0;
365        lt_dlhandle   handle      = token ? SYMBOL_HANDLE (symbol) : 0;        lt_dlhandle   handle      = token ? SYMBOL_HANDLE (symbol) : 0;
366        const char   *module_name = handle ? m4_get_module_name (handle) : "NONE";        const char   *module_name = handle ? m4_get_module_name (handle) : "NONE";
# Line 482  symtab_dump (m4_symtab *symtab) Line 375  symtab_dump (m4_symtab *symtab)
375        else        else
376          switch (SYMBOL_TYPE (symbol))          switch (SYMBOL_TYPE (symbol))
377            {            {
378            case M4_TOKEN_TEXT:            case M4_SYMBOL_TEXT:
379              fputs (SYMBOL_TEXT (symbol), stderr);              fputs (SYMBOL_TEXT (symbol), stderr);
380              break;              break;
381    
382            case M4_TOKEN_FUNC:            case M4_SYMBOL_FUNC:
383              bp = m4_builtin_find_by_func (m4_get_module_builtin_table (handle),              bp = m4_builtin_find_by_func (m4_get_module_builtin_table (handle),
384                                          SYMBOL_FUNC (symbol));                                          SYMBOL_FUNC (symbol));
385              fprintf (stderr, "<%s>",              fprintf (stderr, "<%s>",
386                       bp ? bp->name : "!ERROR!");                       bp ? bp->name : "!ERROR!");
387              break;              break;
388            case M4_TOKEN_VOID:            case M4_SYMBOL_VOID:
389              fputs ("<!VOID!>", stderr);              fputs ("<!VOID!>", stderr);
390              break;              break;
391          }          }
392        fputc ('\n', stderr);        fputc ('\n', stderr);
393      }      }
394  }  }
   
 static void  
 symtab_debug (m4_symtab *symtab)  
 {  
   m4__token_type type;  
   m4_token token;  
   const char *text;  
   m4_symbol *symbol;  
   int delete;  
   
   while ((type = m4_next_token (&token)) != M4_TOKEN_EOF)  
     {  
       if (type != M4_TOKEN_WORD)  
         continue;  
       text = TOKEN_TEXT (&token);  
       if (*text == '_')  
         {  
           delete = 1;  
           text++;  
         }  
       else  
         delete = 0;  
   
       symbol = m4_symbol_lookup (symtab, text);  
   
       if (symbol == NULL)  
         printf (_("Name `%s' is unknown\n"), text);  
   
       if (delete)  
         m4_symbol_delete (symtab, text);  
       else  
         symtab_fetch (symtab, text);  
     }  
   m4_symtab_apply (symtab, symtab_print_list, NULL);  
 }  
   
 static int  
 symtab_print_list (m4_hash *hash, const void *name, void *symbol,  
                    void *ignored)  
 {  
   printf ("\tname %s, addr %#x, flags: %d %s\n",  
           (char *) name, (unsigned) symbol,  
           SYMBOL_FLAGS ((m4_symbol *) symbol),  
           SYMBOL_TRACED ((m4_symbol *) symbol) ? " traced" : "<none>");  
   return 0;  
 }  
   
395  #endif /* DEBUG_SYM */  #endif /* DEBUG_SYM */
396    
397  /* Define these functions at the end, so that calls in the file use the  /* Define these functions at the end, so that calls in the file use the
398     faster macro version from m4module.h.  */     faster macro version from m4module.h.  */
399  #undef m4_symtab_apply  #undef m4_symtab_apply
400  int  void *
401  m4_symtab_apply (m4_symtab *symtab, m4_symtab_apply_func *func, void *userdata)  m4_symtab_apply (m4_symtab *symtab, m4_symtab_apply_func *func, void *userdata)
402  {  {
403    return m4_hash_apply ((m4_hash *) symtab, (m4_hash_apply_func *) func,    return m4_hash_apply ((m4_hash *) symtab, (m4_hash_apply_func *) func,

Legend:
Removed from v.1.37  
changed lines
  Added in v.1.38

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