m4-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

FYI: 15-gary-cleanup-from-renaming-token-data-to-symbol.patch


From: Gary V. Vaughan
Subject: FYI: 15-gary-cleanup-from-renaming-token-data-to-symbol.patch
Date: Thu, 20 Sep 2001 04:53:47 +0100
User-agent: Mutt/1.3.22.1i

Index: ChangeLog
from  Gary V. Vaughan  <address@hidden>

        More cleanup.  After the last patch, m4_symbol holds nothing but
        the head of a chain of m4_token_data.  So I have removed the old
        m4_symbol, so that m4_token_data chains are stored directly in the
        value cell of a hash table node.  But there's more... m4_symbol
        was a more natural name for the symbol value cell, and now that it
        is gone I have renamed the former m4_token_data structure to
        m4_symbol.  This change turned out to be a pig to get right, since
        the original code didn't need to modify the value cell itself,
        since changing the chain happened inside the m4_symbol that used
        to be returned -- I had to pass the address of the value cell
        across various function calls, incase the head value changed.  I
        also tightened up the memory management to help me find a nasty
        memory corruption bug that took me all night to track down...

        * m4/m4private.h (struct m4_symbol): Removed.
        (struct m4_token_data): Renamed to `struct m4_symbol'.  Updated
        all references.
        * m4/hash.c (m4_hash_iterator_value): Return the address of the
        value cell.  Updated all callers.
        * m4/symtab.c: Took advantage of the simplification in the data
        structures to rewrite a lot of this file more simply.  There is
        still some room for optimisation here, but we should tackle that
        systematically closer to the release.

        * m4/ltdl.c: Added dmalloc support, and fixed some memory leaks it
        revealed.  This version is ahead of CVS libtool until I get chance
        to flush my changes.
        * m4/module.c (m4_module_remove): New function that holds the core
        of the old m4_module_unload.
        (m4_module_unload): Use it.
        (m4_module_unload_all): When we know the modules will never be
        used again (i.e. on exit), free up as much module memory as
        possible.  There are still some artifacts from resident modules
        living inside ltdl.c, but everything else is freed.
        * m4/debug.c (m4_debug_exit): Free memory allocated in
        m4_debug_init().
        * m4/input.c (m4_input_exit): Ditto wrt m4_input_init().
        * m4/output.c (m4_output_exit): Ditto wrt m4_output_init ().
        * src/stackovf.c (stackovf_exit): Ditto wrt setup_stackovf_trap ().
        * m4/m4module.h: Updated prototypes.
        * m4/hash.c (m4_hash_exit): Free the nodes on the free list.
        * m4/hash.h: Updated prototypes.
        * src/main.c (main): Use all these new functions to clean up as
        much memory as possible before exit.

Index: m4/debug.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/debug.c,v
retrieving revision 1.5
diff -u -p -u -r1.5 debug.c
--- m4/debug.c 2001/08/20 20:25:25 1.5
+++ m4/debug.c 2001/09/20 03:46:05
@@ -44,6 +44,12 @@ m4_debug_init (void)
   obstack_init (&trace);
 }
 
+void
+m4_debug_exit (void)
+{
+  obstack_free (&trace, NULL);
+}
+
 
 
 /* Function to decode the debugging flags OPTS.  Used by main while
@@ -320,7 +326,7 @@ m4_trace_prepre (const char *name, int i
 /* Format the parts of a trace line, that can be made before the macro is
    actually expanded.  Used from expand_macro ().  */
 void
-m4_trace_pre (const char *name, int id, int argc, m4_token_data **argv)
+m4_trace_pre (const char *name, int id, int argc, m4_symbol **argv)
 {
   int i;
   const m4_builtin *bp;
@@ -337,14 +343,14 @@ m4_trace_pre (const char *name, int id, 
          if (i != 1)
            m4_trace_format (", ");
 
-         switch (M4_TOKEN_DATA_TYPE (argv[i]))
+         switch (M4_SYMBOL_TYPE (argv[i]))
            {
            case M4_TOKEN_TEXT:
-             m4_trace_format ("%l%S%r", M4_TOKEN_DATA_TEXT (argv[i]));
+             m4_trace_format ("%l%S%r", M4_SYMBOL_TEXT (argv[i]));
              break;
 
            case M4_TOKEN_FUNC:
-             bp = m4_builtin_find_by_func (NULL, M4_TOKEN_DATA_FUNC(argv[i]));
+             bp = m4_builtin_find_by_func (NULL, M4_SYMBOL_FUNC (argv[i]));
              if (bp == NULL)
                {
                  M4ERROR ((warning_status, 0, _("\
@@ -374,7 +380,7 @@ INTERNAL ERROR: Bad token data type (m4_
 /* Format the final part of a trace line and print it all.  Used from
    expand_macro ().  */
 void
-m4_trace_post (const char *name, int id, int argc, m4_token_data **argv,
+m4_trace_post (const char *name, int id, int argc, m4_symbol **argv,
            const char *expanded)
 {
   if (debug_level & M4_DEBUG_TRACE_CALL)
Index: m4/evalparse.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/evalparse.c,v
retrieving revision 1.5
diff -u -p -u -r1.5 evalparse.c
--- m4/evalparse.c 2001/08/20 19:42:38 1.5
+++ m4/evalparse.c 2001/09/20 03:46:07
@@ -843,8 +843,7 @@ simple_term (eval_token et, number *v1)
 
 void
 m4_do_eval (struct obstack *obs,
-           int argc, m4_token_data **argv,
-           m4_eval_func func)
+           int argc, m4_symbol **argv, m4_eval_func func)
 {
   int radix = 10;
   int min = 1;
Index: m4/hash.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/hash.c,v
retrieving revision 1.2
diff -u -p -u -r1.2 hash.c
--- m4/hash.c 2001/09/08 02:13:17 1.2
+++ m4/hash.c 2001/09/20 03:46:08
@@ -271,8 +271,9 @@ m4_hash_remove (m4_hash *hash, const voi
 
 /* Return the address of the value field of the first node in
    HASH that has a matching KEY.  The address is returned so that
-   an explicit 0 value can be distinguihed from a failed lookup
-   (also 0).  */
+   an explicit 0 value can be distinguished from a failed lookup
+   (also 0).  Fortuitously for M4, this also means that the value
+   field can be changed `in situ' to implement a value stack.  */
 void **
 m4_hash_lookup (m4_hash *hash, const void *key)
 {
@@ -363,6 +364,17 @@ m4_hash_bucket_insert (m4_hash *hash, m4
   while (bucket);
 }
 
+void
+m4_hash_exit (void)
+{
+  while (m4_hash_node_free_list)
+    {
+      m4_hash_node *stale = m4_hash_node_free_list;
+      m4_hash_node_free_list = M4_HASH_NODE_NEXT (stale);
+      xfree (stale);
+    }
+}
+
 
 
 struct m4_hash_iterator
@@ -448,10 +460,10 @@ m4_hash_iterator_key (m4_hash_iterator *
   return M4_HASH_NODE_KEY (M4_ITERATOR_PLACE (place));
 }
 
-void *
+void **
 m4_hash_iterator_value (m4_hash_iterator *place)
 {
   assert (place);
 
-  return M4_HASH_NODE_VAL (M4_ITERATOR_PLACE (place));
+  return &M4_HASH_NODE_VAL (M4_ITERATOR_PLACE (place));
 }
Index: m4/hash.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/hash.h,v
retrieving revision 1.1
diff -u -p -u -r1.1 hash.h
--- m4/hash.h 2001/09/02 09:05:14 1.1
+++ m4/hash.h 2001/09/20 03:46:08
@@ -44,15 +44,15 @@ void                m4_hash_insert  (m4_hash *hash, con
 void *         m4_hash_remove  (m4_hash *hash, const void *key);
 void **                m4_hash_lookup  (m4_hash *hash, const void *key);
 size_t         m4_hash_length  (m4_hash *hash);
+void           m4_hash_exit    (void);
 
-
 
 typedef struct m4_hash_iterator m4_hash_iterator;
 
 m4_hash_iterator *     m4_hash_iterator_next   (const m4_hash *hash,
                                                 m4_hash_iterator *place);
 const void *           m4_hash_iterator_key    (m4_hash_iterator *place);
-void *                 m4_hash_iterator_value  (m4_hash_iterator *place);
+void **                        m4_hash_iterator_value  (m4_hash_iterator 
*place);
 
 END_C_DECLS
 
Index: m4/input.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/input.c,v
retrieving revision 1.10
diff -u -p -u -r1.10 input.c
--- m4/input.c 2001/09/18 01:07:09 1.10
+++ m4/input.c 2001/09/20 03:46:11
@@ -142,7 +142,7 @@ static      int   file_peek                 (void);
 static int   file_read                 (void);
 static void  file_unget                (int ch);
 static void  file_clean                (void);
-static void  init_macro_token          (m4_token_data *td);
+static void  init_macro_token          (m4_symbol *symbol);
 static int   macro_peek                (void);
 static int   macro_read                (void);
 static int   match_input               (const unsigned char *s);
@@ -594,7 +594,7 @@ m4_pop_wrapup (void)
 /* When a MACRO token is seen, next_token () uses init_macro_token
    to retrieve the value of the function pointer.  */
 static void
-init_macro_token (m4_token_data *td)
+init_macro_token (m4_symbol *symbol)
 {
   if (isp->funcs->read_func != macro_read)
     {
@@ -603,10 +603,10 @@ init_macro_token (m4_token_data *td)
       abort ();
     }
 
-  M4_TOKEN_DATA_TYPE (td) = M4_TOKEN_FUNC;
-  M4_TOKEN_DATA_FUNC (td) = isp->u.u_m.func;
-  M4_TOKEN_DATA_HANDLE (td) = isp->u.u_m.handle;
-  M4_TOKEN_TRACED (td) = isp->u.u_m.traced;
+  M4_SYMBOL_TYPE (symbol)   = M4_TOKEN_FUNC;
+  M4_SYMBOL_FUNC (symbol)   = isp->u.u_m.func;
+  M4_SYMBOL_HANDLE (symbol) = isp->u.u_m.handle;
+  M4_SYMBOL_TRACED (symbol) = isp->u.u_m.traced;
 }
 
 
@@ -794,6 +794,18 @@ m4_input_init (void)
 }
 
 void
+m4_input_exit (void)
+{
+  XFREE (lquote.string);
+  XFREE (rquote.string);
+  XFREE (bcomm.string);
+  XFREE (ecomm.string);
+  obstack_free (&wrapup_stack, NULL);
+  obstack_free (&input_stack, NULL);
+  obstack_free (&token_stack, NULL);
+}
+
+void
 m4_syntax_init (void)
 {
   int ch;
@@ -997,7 +1009,7 @@ m4_set_syntax (char key, const unsigned 
    The storage pointed to by the fields in TD is therefore subject to
    change the next time next_token () is called.        */
 m4_token_t
-m4_next_token (m4_token_data *td)
+m4_next_token (m4_symbol *symbol)
 {
   int ch;
   int quote_level;
@@ -1019,10 +1031,10 @@ m4_next_token (m4_token_data *td)
 
     if (ch == CHAR_MACRO)              /* MACRO TOKEN */
       {
-       init_macro_token (td);
+       init_macro_token (symbol);
        (void) next_char ();
 #ifdef DEBUG_INPUT
-       print_token("next_token", M4_TOKEN_MACDEF, td);
+       print_token("next_token", M4_TOKEN_MACDEF, symbol);
 #endif
        return M4_TOKEN_MACDEF;
       }
@@ -1188,8 +1200,8 @@ m4_next_token (m4_token_data *td)
 
   obstack_1grow (&token_stack, '\0');
 
-  M4_TOKEN_DATA_TYPE (td) = M4_TOKEN_TEXT;
-  M4_TOKEN_DATA_TEXT (td) = obstack_finish (&token_stack);
+  M4_SYMBOL_TYPE (symbol) = M4_TOKEN_TEXT;
+  M4_SYMBOL_TEXT (symbol) = obstack_finish (&token_stack);
 
 #ifdef DEBUG_INPUT
   print_token("next_token", type, td);
@@ -1204,29 +1216,29 @@ m4_next_token (m4_token_data *td)
 static void  lex_debug (void);
 
 int
-m4_print_token (const char *s, m4_token_t t, m4_token_data *td)
+m4_print_token (const char *s, m4_token_t t, m4_symbol *symbol)
 {
   fprintf (stderr, "%s: ", s);
   switch (t)
     {                          /* TOKSW */
     case M4_TOKEN_SIMPLE:
-      fprintf (stderr, "char\t\"%s\"\n", M4_TOKEN_DATA_TEXT (td));
+      fprintf (stderr, "char\t\"%s\"\n", M4_SYMBOL_TEXT (symbol));
       break;
 
     case M4_TOKEN_WORD:
-      fprintf (stderr, "word\t\"%s\"\n", M4_TOKEN_DATA_TEXT (td));
+      fprintf (stderr, "word\t\"%s\"\n", M4_SYMBOL_TEXT (symbol));
       break;
 
     case M4_TOKEN_STRING:
-      fprintf (stderr, "string\t\"%s\"\n", M4_TOKEN_DATA_TEXT (td));
+      fprintf (stderr, "string\t\"%s\"\n", M4_SYMBOL_TEXT (symbol));
       break;
 
     case M4_TOKEN_SPACE:
-      fprintf (stderr, "space\t\"%s\"\n", M4_TOKEN_DATA_TEXT (td));
+      fprintf (stderr, "space\t\"%s\"\n", M4_SYMBOL_TEXT (symbol));
       break;
 
     case M4_TOKEN_MACDEF:
-      fprintf (stderr, "macro 0x%x\n", (int)M4_TOKEN_DATA_FUNC (td));
+      fprintf (stderr, "macro 0x%x\n", (int)M4_SYMBOL_FUNC (symbol));
       break;
 
     case M4_TOKEN_EOF:
@@ -1244,9 +1256,9 @@ static void
 lex_debug (void)
 {
   m4_token_t t;
-  m4_token_data td;
+  m4_symbol symbol;
 
-  while ((t = next_token (&td)) != NULL)
-    print_token ("lex", t, &td);
+  while ((t = next_token (&symbol)) != NULL)
+    print_token ("lex", t, &symbol);
 }
 #endif
Index: m4/ltdl.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/ltdl.c,v
retrieving revision 1.9
diff -u -p -u -r1.9 ltdl.c
--- m4/ltdl.c 2001/09/04 00:15:34 1.9
+++ m4/ltdl.c 2001/09/20 03:46:18
@@ -91,6 +91,9 @@ Foundation, Inc., 59 Temple Place, Suite
 
 #include "ltdl.h"
 
+#if WITH_DMALLOC
+#  include <dmalloc.h>
+#endif
 
 
 
@@ -163,6 +166,18 @@ LT_GLOBAL_DATA void   (*lt_dlfree) LT_PA
 
 /* The following macros reduce the amount of typing needed to cast
    assigned memory.  */
+#if WITH_DMALLOC
+
+#define LT_DLMALLOC(tp, n)     ((tp *) xmalloc ((n) * sizeof(tp)))
+#define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
+#define LT_DLFREE(p)                                           \
+       LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
+
+#define LT_EMALLOC(tp, n)      ((tp *) xmalloc ((n) * sizeof(tp)))
+#define LT_EREALLOC(tp, p, n)  ((tp *) xrealloc ((p), (n) * sizeof(tp)))
+
+#else
+
 #define LT_DLMALLOC(tp, n)     ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
 #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
 #define LT_DLFREE(p)                                           \
@@ -171,8 +186,10 @@ LT_GLOBAL_DATA void   (*lt_dlfree) LT_PA
 #define LT_EMALLOC(tp, n)      ((tp *) lt_emalloc ((n) * sizeof(tp)))
 #define LT_EREALLOC(tp, p, n)  ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
 
+#endif
+
 #define LT_DLMEM_REASSIGN(p, q)                        LT_STMT_START { \
-       if ((p) != (q)) { lt_dlfree (p); (p) = (q); (q) = 0; }  \
+       if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }   \
                                                } LT_STMT_END
 
 
@@ -878,10 +895,10 @@ char *
 lt_estrdup (str)
      const char *str;
 {
-  char *dup = strdup (str);
-  if (LT_STRLEN (str) && !dup)
+  char *copy = strdup (str);
+  if (LT_STRLEN (str) && !copy)
     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
-  return dup;
+  return copy;
 }
 
 
@@ -1682,9 +1699,17 @@ static   int     lt_argz_insert        LT_PARAM
 static int     lt_argz_insertinorder LT_PARAMS((char **pargz,
                                                 size_t *pargz_len,
                                                 const char *entry));
+static int     lt_argz_insertdir     LT_PARAMS((char **pargz,
+                                                size_t *pargz_len,
+                                                const char *dirnam,
+                                                struct dirent *dp));
 static int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
                                                 char *before,
                                                 const char *dir));
+static int     list_files_by_dir     LT_PARAMS((const char *dirnam,
+                                                char **pargz,
+                                                size_t *pargz_len));
+static int     file_not_found        LT_PARAMS((void));
 
 static char           *user_search_path= 0;
 static lt_dlloader    *loaders         = 0;
@@ -2892,7 +2917,7 @@ lt_dlopen (filename)
 
 /* If the last error messge store was `FILE_NOT_FOUND', then return
    non-zero.  */
-int
+static int
 file_not_found ()
 {
   const char *error = 0;
@@ -2917,7 +2942,6 @@ lt_dlopenext (filename)
   char *       ext             = 0;
   int          len;
   int          errors          = 0;
-  int          file_found      = 1; /* until proven otherwise */
 
   if (!filename)
     {
@@ -3278,6 +3302,9 @@ lt_dlclose (handle)
 
       errors += handle->loader->module_close (data, handle->module);
       errors += unload_deplibs(handle);
+
+      /* It is up to the callers to free the data itself.  */
+      LT_DLFREE (handle->caller_data);
 
       LT_DLFREE (handle->info.filename);
       LT_DLFREE (handle->info.name);
Index: m4/m4module.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4module.h,v
retrieving revision 1.28
diff -u -p -u -r1.28 m4module.h
--- m4/m4module.h 2001/09/08 02:36:47 1.28
+++ m4/m4module.h 2001/09/20 03:46:20
@@ -32,9 +32,8 @@ BEGIN_C_DECLS
 
 typedef struct m4_symbol m4_symbol;
 typedef struct m4_module_data m4_module_data;
-typedef struct m4_token_data m4_token_data;
 
-typedef void m4_builtin_func (struct obstack *, int, struct m4_token_data **);
+typedef void m4_builtin_func (struct obstack *, int, struct m4_symbol **);
 typedef void *m4_module_func (const char *);
 typedef int m4_symtab_apply_func (const char *name, m4_symbol *symbol, void 
*data);
 
@@ -56,12 +55,13 @@ typedef struct {
 } m4_builtin;
 
 
-extern void        m4_module_init   (void);
-extern lt_dlhandle  m4_module_load   (const char*, struct obstack*);
-extern void        m4_module_unload (const char*, struct obstack*);
-extern lt_dlhandle  m4_module_open   (const char*, struct obstack*);
-extern void        m4_module_close  (lt_dlhandle, struct obstack*);
-extern void        m4_module_close_all (struct obstack*);
+extern void        m4_module_init      (void);
+extern lt_dlhandle  m4_module_load     (const char*, struct obstack*);
+extern void        m4_module_unload    (const char*, struct obstack*);
+extern void        m4_module_unload_all (void);
+extern lt_dlhandle  m4_module_open     (const char*, struct obstack*);
+extern void        m4_module_close     (lt_dlhandle, struct obstack*);
+extern void        m4_module_close_all (struct obstack*);
 
 extern const char  *m4_module_name     (lt_dlhandle);
 extern m4_builtin  *m4_module_builtins (lt_dlhandle);
@@ -94,6 +94,7 @@ extern m4_hash *m4_symtab;
 extern void    m4_symtab_init          (void);
 extern int     m4_symtab_apply         (m4_symtab_apply_func *, void *);
 extern void    m4_symtab_remove_module_references (lt_dlhandle);
+extern void    m4_symtab_exit          (void);
 
 extern m4_symbol *m4_symbol_lookup     (const char *);
 extern m4_symbol *m4_symbol_pushdef    (const char *);
@@ -127,20 +128,20 @@ typedef enum {
 typedef void m4_module_init_func   (lt_dlhandle, struct obstack*);
 typedef void m4_module_finish_func (lt_dlhandle, struct obstack*);
 
-extern m4_token_data_t  m4_token_data_type       (m4_token_data*);
-extern char           *m4_token_data_text        (m4_token_data*);
-extern m4_builtin_func *m4_token_data_func       (m4_token_data*);
+extern m4_token_data_t  m4_symbol_type   (m4_symbol*);
+extern char           *m4_symbol_text    (m4_symbol*);
+extern m4_builtin_func *m4_symbol_func   (m4_symbol*);
 
 
-#define M4ARG(i)       (argc > (i) ? m4_token_data_text (argv[i]) : "")
+#define M4ARG(i)       (argc > (i) ? m4_symbol_text (argv[i]) : "")
 
 #define M4BUILTIN(name)                                        \
   static void CONC(builtin_, name)                             \
-       (struct obstack *, int , m4_token_data **);
+       (struct obstack *, int , m4_symbol **);
 
 #define M4BUILTIN_HANDLER(name)                                \
   static void CONC(builtin_, name) (obs, argc, argv)           \
-       struct obstack *obs; int argc; m4_token_data **argv;
+       struct obstack *obs; int argc; m4_symbol **argv;
 
 #define M4INIT_HANDLER(name)                                   \
   void CONC(name, CONC(_LTX_, m4_init_module))                         \
@@ -192,12 +193,12 @@ m4_string ecomm;
 #define DEF_BCOMM "#"
 #define DEF_ECOMM "\n"
 
-boolean m4_bad_argc (m4_token_data *, int, int, int);
+boolean m4_bad_argc (m4_symbol *, int, int, int);
 const char *m4_skip_space (const char *);
-boolean m4_numeric_arg (m4_token_data *, const char *, int *);
+boolean m4_numeric_arg (m4_symbol *, const char *, int *);
 void m4_shipout_int (struct obstack *, int);
 void m4_shipout_string (struct obstack*, const char*, int, boolean);
-void m4_dump_args (struct obstack *obs, int argc, m4_token_data **argv, const 
char *sep, boolean quoted);
+void m4_dump_args (struct obstack *obs, int argc, m4_symbol **argv, const char 
*sep, boolean quoted);
 
 
 FILE *m4_debug;
@@ -291,14 +292,15 @@ FILE *m4_debug;
   while (0)
 
 void m4_debug_init (void);
+void m4_debug_exit (void);
 int m4_debug_decode (const char *);
 void m4_debug_flush_files (void);
 boolean m4_debug_set_output (const char *);
 void m4_debug_message_prefix (void);
 
 void m4_trace_prepre (const char *, int);
-void m4_trace_pre (const char *, int, int, m4_token_data **);
-void m4_trace_post (const char *, int, int, m4_token_data **,
+void m4_trace_pre (const char *, int, int, m4_symbol **);
+void m4_trace_post (const char *, int, int, m4_symbol **,
                           const char *);
 
 /* Exit code from last "syscmd" command.  */
@@ -307,8 +309,8 @@ int m4_expansion_level;
 
 const char *m4_expand_ranges (const char *s, struct obstack *obs);
 void m4_expand_input (void);
-void m4_call_macro (m4_symbol *, int, m4_token_data **, struct obstack *);
-void m4_process_macro (struct obstack *obs, m4_symbol *symbol, int argc, 
m4_token_data **argv);
+void m4_call_macro (m4_symbol *, int, m4_symbol **, struct obstack *);
+void m4_process_macro (struct obstack *obs, m4_symbol *symbol, int argc, 
m4_symbol **argv);
 
 
 
@@ -375,9 +377,10 @@ int m4_current_line;
 
 extern int     m4_syntax_code  (char ch);
 extern void    m4_input_init   (void);
+extern void    m4_input_exit   (void);
 extern void    m4_syntax_init  (void);
 extern int     m4_peek_input   (void);
-extern m4_token_t m4_next_token (m4_token_data *);
+extern m4_token_t m4_next_token (m4_symbol *);
 extern void    m4_skip_line    (void);
 
 /* push back input */
@@ -399,6 +402,7 @@ int m4_current_diversion;
 int m4_output_current_line;
 
 extern void    m4_output_init  (void);
+extern void    m4_output_exit  (void);
 extern void    m4_shipout_text (struct obstack *, const char *, int);
 extern void    m4_make_diversion (int);
 extern void    m4_insert_diversion (int);
@@ -445,7 +449,7 @@ struct m4_dump_symbol_data
 };
 
 extern int m4_dump_symbol (const char *name, m4_symbol *symbol, void *data);
-extern void m4_dump_symbols (struct m4_dump_symbol_data *data, int argc, 
m4_token_data **argv, boolean complain);
+extern void m4_dump_symbols (struct m4_dump_symbol_data *data, int argc, 
m4_symbol **argv, boolean complain);
 
 
 
@@ -457,7 +461,7 @@ typedef boolean (*m4_eval_func) (struct 
 
 extern boolean m4_evaluate (struct obstack *obs,
                                      const char *, const int radix, int min);
-extern void m4_do_eval (struct obstack *obs, int argc, m4_token_data **argv, 
m4_eval_func func);
+extern void m4_do_eval (struct obstack *obs, int argc, m4_symbol **argv, 
m4_eval_func func);
 
 #define obstack_chunk_alloc    xmalloc
 #define obstack_chunk_free     xfree
Index: m4/m4private.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4private.h,v
retrieving revision 1.9
diff -u -p -u -r1.9 m4private.h
--- m4/m4private.h 2001/09/18 01:07:09 1.9
+++ m4/m4private.h 2001/09/20 03:46:20
@@ -33,8 +33,8 @@ struct m4_module_data {
 };
 
 
-struct m4_token_data {
-  m4_token_data        *       next;
+struct m4_symbol {
+  m4_symbol    *       next;
   m4_token_data_t      type;
   boolean              traced;
   boolean              macro_args;
@@ -46,42 +46,33 @@ struct m4_token_data {
   } u;
 };
 
-#define M4_TOKEN_DATA_NEXT(Td)         ((Td)->next)
-#define M4_TOKEN_DATA_TYPE(Td)         ((Td)->type)
-#define M4_TOKEN_TRACED(Td)            ((Td)->traced)
-#define M4_TOKEN_MACRO_ARGS(Td)                ((Td)->macro_args)
-#define M4_TOKEN_BLIND_NO_ARGS(Td)     ((Td)->blind_no_args)
-#define M4_TOKEN_DATA_HANDLE(Td)       ((Td)->handle)
-#define M4_TOKEN_DATA_TEXT(Td)         ((Td)->u.text)
-#define M4_TOKEN_DATA_FUNC(Td)         ((Td)->u.func)
+#define M4_SYMBOL_NEXT(Symbol)         ((Symbol)->next)
+#define M4_SYMBOL_TYPE(Symbol)         ((Symbol)->type)
+#define M4_SYMBOL_TRACED(Symbol)       ((Symbol)->traced)
+#define M4_SYMBOL_MACRO_ARGS(Symbol)   ((Symbol)->macro_args)
+#define M4_SYMBOL_BLIND_NO_ARGS(Symbol)        ((Symbol)->blind_no_args)
+#define M4_SYMBOL_HANDLE(Symbol)       ((Symbol)->handle)
+#define M4_SYMBOL_TEXT(Symbol)         ((Symbol)->u.text)
+#define M4_SYMBOL_FUNC(Symbol)         ((Symbol)->u.func)
 
 /* Redefine the exported function to this faster
    macro based version for internal use by the m4 code. */
 #undef M4ARG
-#define M4ARG(i)       (argc > (i) ? M4_TOKEN_DATA_TEXT (argv[i]) : "")
+#define M4ARG(i)       (argc > (i) ? M4_SYMBOL_TEXT (argv[i]) : "")
 
-struct m4_symbol
-{
-  m4_token_data *data;
-};
-
-#define M4_SYMBOL_DATA(S)         ((S)->data)
-#define M4_SYMBOL_DATA_NEXT(S)    (M4_TOKEN_DATA_NEXT (M4_SYMBOL_DATA(S)))
-#define M4_SYMBOL_TYPE(S)         (M4_TOKEN_DATA_TYPE (M4_SYMBOL_DATA(S)))
-#define M4_SYMBOL_TRACED(S)       (M4_TOKEN_TRACED (M4_SYMBOL_DATA(S)))
-#define M4_SYMBOL_MACRO_ARGS(S)           (M4_TOKEN_MACRO_ARGS 
(M4_SYMBOL_DATA(S)))
-#define M4_SYMBOL_BLIND_NO_ARGS(S) (M4_TOKEN_BLIND_NO_ARGS (M4_SYMBOL_DATA(S)))
-#define M4_SYMBOL_TEXT(S)         (M4_TOKEN_DATA_TEXT (M4_SYMBOL_DATA(S)))
-#define M4_SYMBOL_FUNC(S)         (M4_TOKEN_DATA_FUNC (M4_SYMBOL_DATA(S)))
-#define M4_SYMBOL_HANDLE(S)       (M4_TOKEN_DATA_HANDLE (M4_SYMBOL_DATA(S)))
 
 
 /* Debugging the memory allocator.  */
 
 #if WITH_DMALLOC
-# define DMALLOC_FUNC_CHECK
-# include <dmalloc.h>
-#endif
+#  define DMALLOC_FUNC_CHECK
+#  include <dmalloc.h>
+
+/* Dmalloc expects us to use a void returning xfree.  */
+#  undef XFREE
+#  define XFREE(p)     if (p) xfree (p)
+
+#endif /* WITH_DMALLOC */
 
 /* Other debug stuff.  */
 
Index: m4/macro.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/macro.c,v
retrieving revision 1.12
diff -u -p -u -r1.12 macro.c
--- m4/macro.c 2001/09/18 01:07:09 1.12
+++ m4/macro.c 2001/09/20 03:46:21
@@ -23,8 +23,8 @@
 #include "m4.h"
 #include "m4private.h"
 
-static void expand_macro (const char *name, m4_symbol *);
-static void expand_token (struct obstack *, m4_token_t, m4_token_data *);
+static void expand_macro (const char *name, m4_symbol *token);
+static void expand_token (struct obstack *, m4_token_t t, m4_symbol *token);
 
 /* Current recursion level in expand_macro ().  */
 int m4_expansion_level = 0;
@@ -37,10 +37,10 @@ void
 m4_expand_input (void)
 {
   m4_token_t t;
-  m4_token_data td;
+  m4_symbol tokenbuf;
 
-  while ((t = m4_next_token (&td)) != M4_TOKEN_EOF)
-    expand_token ((struct obstack *) NULL, t, &td);
+  while ((t = m4_next_token (&tokenbuf)) != M4_TOKEN_EOF)
+    expand_token ((struct obstack *) NULL, t, &tokenbuf);
 }
 
 
@@ -49,10 +49,10 @@ m4_expand_input (void)
    macro definition.  If they have, they are expanded as macros, otherwise
    the text are just copied to the output.  */
 static void
-expand_token (struct obstack *obs, m4_token_t t, m4_token_data *td)
+expand_token (struct obstack *obs, m4_token_t t, m4_symbol *token)
 {
   m4_symbol *symbol;
-  char *text = xstrdup (M4_TOKEN_DATA_TEXT (td));
+  char *text = xstrdup (M4_SYMBOL_TEXT (token));
 
   switch (t)
     {                          /* TOKSW */
@@ -79,8 +79,8 @@ expand_token (struct obstack *obs, m4_to
                && M4_SYMBOL_BLIND_NO_ARGS (symbol)
                && !M4_IS_OPEN(m4_peek_input ())))
          {
-           m4_shipout_text (obs, M4_TOKEN_DATA_TEXT (td),
-                            strlen (M4_TOKEN_DATA_TEXT (td)));
+           m4_shipout_text (obs, M4_SYMBOL_TEXT (token),
+                            strlen (M4_SYMBOL_TEXT (token)));
          }
        else
          expand_macro (p, symbol);
@@ -95,8 +95,9 @@ expand_token (struct obstack *obs, m4_to
 
   XFREE (text);
 }
-
 
+
+
 /* This function parses one argument to a macro call.  It expects the first
    left parenthesis, or the separating comma to have been read by the
    caller.  It skips leading whitespace, and reads and expands tokens,
@@ -105,19 +106,19 @@ expand_token (struct obstack *obs, m4_to
    the last for the active macro call.  The argument are build on the
    obstack OBS, indirectly through expand_token ().     */
 static boolean
-expand_argument (struct obstack *obs, m4_token_data *argp)
+expand_argument (struct obstack *obs, m4_symbol *argp)
 {
   m4_token_t t;
-  m4_token_data td;
+  m4_symbol tokenbuf;
   char *text;
   int paren_level;
 
-  M4_TOKEN_DATA_TYPE (argp) = M4_TOKEN_VOID;
+  M4_SYMBOL_TYPE (argp) = M4_TOKEN_VOID;
 
   /* Skip leading white space.  */
   do
     {
-      t = m4_next_token (&td);
+      t = m4_next_token (&tokenbuf);
     }
   while (t == M4_TOKEN_SPACE);
 
@@ -125,31 +126,30 @@ expand_argument (struct obstack *obs, m4
 
   while (1)
     {
-
       switch (t)
        {                       /* TOKSW */
        case M4_TOKEN_SIMPLE:
-         text = M4_TOKEN_DATA_TEXT (&td);
-         if ((M4_IS_COMMA(*text) || M4_IS_CLOSE(*text)) && paren_level == 0)
+         text = M4_SYMBOL_TEXT (&tokenbuf);
+         if ((M4_IS_COMMA (*text) || M4_IS_CLOSE (*text)) && paren_level == 0)
            {
 
              /* The argument MUST be finished, whether we want it or not.  */
              obstack_1grow (obs, '\0');
              text = obstack_finish (obs);
 
-             if (M4_TOKEN_DATA_TYPE (argp) == M4_TOKEN_VOID)
+             if (M4_SYMBOL_TYPE (argp) == M4_TOKEN_VOID)
                {
-                 M4_TOKEN_DATA_TYPE (argp) = M4_TOKEN_TEXT;
-                 M4_TOKEN_DATA_TEXT (argp) = text;
+                 M4_SYMBOL_TYPE (argp) = M4_TOKEN_TEXT;
+                 M4_SYMBOL_TEXT (argp) = text;
                }
-             return (boolean) (M4_IS_COMMA(*M4_TOKEN_DATA_TEXT (&td)));
+             return (boolean) (M4_IS_COMMA (*M4_SYMBOL_TEXT (&tokenbuf)));
            }
 
          if (M4_IS_OPEN(*text))
            paren_level++;
          else if (M4_IS_CLOSE(*text))
            paren_level--;
-         expand_token (obs, t, &td);
+         expand_token (obs, t, &tokenbuf);
          break;
 
        case M4_TOKEN_EOF:
@@ -160,16 +160,16 @@ expand_argument (struct obstack *obs, m4
        case M4_TOKEN_WORD:
        case M4_TOKEN_SPACE:
        case M4_TOKEN_STRING:
-         expand_token (obs, t, &td);
+         expand_token (obs, t, &tokenbuf);
          break;
 
        case M4_TOKEN_MACDEF:
          if (obstack_object_size (obs) == 0)
            {
-             M4_TOKEN_DATA_TYPE (argp)   = M4_TOKEN_FUNC;
-             M4_TOKEN_DATA_HANDLE (argp) = M4_TOKEN_DATA_HANDLE (&td);
-             M4_TOKEN_DATA_FUNC (argp)   = M4_TOKEN_DATA_FUNC (&td);
-             M4_TOKEN_TRACED (argp)      = M4_TOKEN_TRACED (&td);
+             M4_SYMBOL_TYPE (argp)   = M4_TOKEN_FUNC;
+             M4_SYMBOL_HANDLE (argp) = M4_SYMBOL_HANDLE (&tokenbuf);
+             M4_SYMBOL_FUNC (argp)   = M4_SYMBOL_FUNC (&tokenbuf);
+             M4_SYMBOL_TRACED (argp) = M4_SYMBOL_TRACED (&tokenbuf);
            }
          break;
 
@@ -179,7 +179,7 @@ INTERNAL ERROR: Bad token type in expand
          abort ();
        }
 
-      t = m4_next_token (&td);
+      t = m4_next_token (&tokenbuf);
     }
 }
 
@@ -191,32 +191,32 @@ collect_arguments (const char *name, m4_
                   struct obstack *argptr, struct obstack *arguments)
 {
   int ch;                      /* lookahead for ( */
-  m4_token_data td;
-  m4_token_data *tdp;
+  m4_symbol tokenbuf;
+  m4_symbol *token;
   boolean more_args;
   boolean groks_macro_args = M4_SYMBOL_MACRO_ARGS (symbol);
 
-  M4_TOKEN_DATA_TYPE (&td) = M4_TOKEN_TEXT;
-  M4_TOKEN_DATA_TEXT (&td) = (char *) name;
-  tdp = (m4_token_data *) obstack_copy (arguments, (void *) &td, sizeof (td));
-  obstack_grow (argptr, (void *) &tdp, sizeof (tdp));
+  M4_SYMBOL_TYPE (&tokenbuf) = M4_TOKEN_TEXT;
+  M4_SYMBOL_TEXT (&tokenbuf) = (char *) name;
+  token = (m4_symbol *) obstack_copy (arguments, (void *) &tokenbuf, sizeof 
(tokenbuf));
+  obstack_grow (argptr, (void *) &token, sizeof (token));
 
   ch = m4_peek_input ();
   if (M4_IS_OPEN(ch))
     {
-      m4_next_token (&td);             /* gobble parenthesis */
+      m4_next_token (&tokenbuf);               /* gobble parenthesis */
       do
        {
-         more_args = expand_argument (arguments, &td);
+         more_args = expand_argument (arguments, &tokenbuf);
 
-         if (!groks_macro_args && M4_TOKEN_DATA_TYPE (&td) == M4_TOKEN_FUNC)
+         if (!groks_macro_args && M4_SYMBOL_TYPE (&tokenbuf) == M4_TOKEN_FUNC)
            {
-             M4_TOKEN_DATA_TYPE (&td) = M4_TOKEN_TEXT;
-             M4_TOKEN_DATA_TEXT (&td) = "";
+             M4_SYMBOL_TYPE (&tokenbuf) = M4_TOKEN_TEXT;
+             M4_SYMBOL_TEXT (&tokenbuf) = "";
            }
-         tdp = (m4_token_data *)
-           obstack_copy (arguments, (void *) &td, sizeof (td));
-         obstack_grow (argptr, (void *) &tdp, sizeof (tdp));
+         token = (m4_symbol *)
+           obstack_copy (arguments, (void *) &tokenbuf, sizeof (tokenbuf));
+         obstack_grow (argptr, (void *) &token, sizeof (token));
        }
       while (more_args);
     }
@@ -231,7 +231,7 @@ collect_arguments (const char *name, m4_
    arguments to the call, stored in the ARGV table.  The expansion is
    left on the obstack EXPANSION.  Macro tracing is also handled here.  */
 void
-m4_call_macro (m4_symbol *symbol, int argc, m4_token_data **argv,
+m4_call_macro (m4_symbol *symbol, int argc, m4_symbol **argv,
               struct obstack *expansion)
 {
   switch (M4_SYMBOL_TYPE (symbol))
@@ -263,7 +263,7 @@ expand_macro (const char *name, m4_symbo
 {
   struct obstack arguments;
   struct obstack argptr;
-  m4_token_data **argv;
+  m4_symbol **argv;
   int argc;
   struct obstack *expansion;
   const char *expanded;
@@ -289,8 +289,8 @@ ERROR: Recursion limit of %d exceeded, u
 
   collect_arguments (name, symbol, &argptr, &arguments);
 
-  argc = obstack_object_size (&argptr) / sizeof (m4_token_data *);
-  argv = (m4_token_data **) obstack_finish (&argptr);
+  argc = obstack_object_size (&argptr) / sizeof (m4_symbol *);
+  argv = (m4_symbol **) obstack_finish (&argptr);
 
   if (traced)
     m4_trace_pre (name, my_call_id, argc, argv);
@@ -315,7 +315,7 @@ ERROR: Recursion limit of %d exceeded, u
    as usual.  */
 void
 m4_process_macro (struct obstack *obs, m4_symbol *symbol, int argc,
-                 m4_token_data **argv)
+                 m4_symbol **argv)
 {
   const unsigned char *text;
   int i;
@@ -344,7 +344,7 @@ m4_process_macro (struct obstack *obs, m
              text = endp;
            }
          if (i < argc)
-           m4_shipout_string (obs, M4_TOKEN_DATA_TEXT (argv[i]), 0, FALSE);
+           m4_shipout_string (obs, M4_SYMBOL_TEXT (argv[i]), 0, FALSE);
          break;
 
        case '#':               /* number of arguments */
Index: m4/module.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/module.c,v
retrieving revision 1.11
diff -u -p -u -r1.11 module.c
--- m4/module.c 2001/09/07 23:47:28 1.11
+++ m4/module.c 2001/09/20 03:46:22
@@ -59,14 +59,14 @@
  * names to the expansion text.  Any macros defined in `m4_macro_table'
  * are installed into the M4 symbol table with m4_macro_table_install().
  *
- * Each time a module is loaded, the module function 
+ * Each time a module is loaded, the module function
  * "void m4_init_module (lt_dlhandle handle, struct obstack *obs)" is
  * called, if defined.  Any value stored in OBS by this function becomes
- * the expansion of the macro which called it.  Before M4 exits, all 
+ * the expansion of the macro which called it.  Before M4 exits, all
  * modules are unloaded and the function
  * "void m4_finish_module (lt_dlhandle handle, struct obstack *obs)" is
  * called, if defined.  It is safe to load the same module several times:
- * the init and finish functions will also be called multiple times in 
+ * the init and finish functions will also be called multiple times in
  * this case.
  *
  * To unload a module, use m4_module_unload(). which uses
@@ -83,6 +83,8 @@
 #define M4_FINISH_SYMBOL       "m4_finish_module"
 
 static const char*  m4_module_dlerror  (void);
+static int         m4_module_remove    (lt_dlhandle handle,
+                                        struct obstack *obs);
 
 static lt_dlcaller_id m4_caller_id = 0;
 
@@ -167,7 +169,7 @@ void
 m4_module_init (void)
 {
   int errors = 0;
-  
+
   /* Do this only once!  If we already have a caller_id, then the
      module system has already been initialised.  */
   if (m4_caller_id)
@@ -177,9 +179,11 @@ m4_module_init (void)
       return;
     }
 
+#if !WITH_DMALLOC
   /* initialise libltdl's memory management. */
   lt_dlmalloc = xmalloc;
   lt_dlfree   = (void (*)(void*)) xfree;
+#endif
 
   errors      = lt_dlinit ();
 
@@ -201,7 +205,7 @@ m4_module_init (void)
          ++errors;
        }
     }
-  
+
   if (!errors)
     errors = lt_dlsetsearchpath (MODULE_PATH);
 
@@ -290,7 +294,7 @@ m4_module_open (const char *name, struct
   if (handle)
     {
       const lt_dlinfo  *info   = lt_dlgetinfo (handle);
-      
+
       if (info && (info->ref_count == 1))
        {
          m4_module_data *data  = XMALLOC (m4_module_data, 1);
@@ -304,7 +308,7 @@ m4_module_open (const char *name, struct
          if (stale)
            {
              xfree (stale);
-         
+
              M4ERROR ((warning_status, 0,
                        _("Warning: overiding stale caller data in module 
`%s'"),
                        name));
@@ -323,11 +327,11 @@ void
 m4_module_close (lt_dlhandle handle, struct obstack *obs)
 {
   m4_module_finish_func *finish_func   = 0;
-  const char           *name           = 0;
+  char                 *name           = 0;
   int                   errors         = 0;
-  
+
   assert (handle);
-  name = m4_module_name (handle);
+  name = xstrdup (m4_module_name (handle));
 
   /* Run any finishing function for the opened module. */
   finish_func = (m4_module_finish_func *) lt_dlsym (handle, M4_FINISH_SYMBOL);
@@ -340,21 +344,19 @@ m4_module_close (lt_dlhandle handle, str
       M4_DEBUG_MESSAGE1("module %s: finish hook called", name);
 #endif /* DEBUG_MODULES */
     }
-      
+
   if (!lt_dlisresident (handle))
     {
-      {
-       const lt_dlinfo  *info  = lt_dlgetinfo (handle);
+      const lt_dlinfo  *info   = lt_dlgetinfo (handle);
 
-       /* When we are about to unload the module for the final
-          time, be sure to release any client data memory.  */
-       if (info && (info->ref_count == 1))
-         {
-           m4_module_data *stale
-             = lt_dlcaller_set_data (m4_caller_id, handle, 0);
-           xfree (stale);
-         }
-      }
+      /* When we are about to unload the module for the final
+        time, be sure to release any client data memory.  */
+      if (info && (info->ref_count == 1))
+       {
+         m4_module_data *stale
+           = lt_dlcaller_set_data (m4_caller_id, handle, 0);
+         XFREE (stale);
+       }
 
       errors = lt_dlclose (handle);
       if (!errors)
@@ -364,6 +366,10 @@ m4_module_close (lt_dlhandle handle, str
 #endif /* DEBUG_MODULES */
        }
     }
+#ifdef DEBUG_MODULES
+  else
+    M4_DEBUG_MESSAGE1("module %s: resident module not closed", name);
+#endif /* DEBUG_MODULES */
 
   if (errors)
     {
@@ -371,6 +377,8 @@ m4_module_close (lt_dlhandle handle, str
                _("ERROR: cannot close module `%s': %s"),
                name, m4_module_dlerror ()));
     }
+
+  xfree (name);
 }
 
 void
@@ -384,6 +392,10 @@ m4_module_close_all (struct obstack *obs
         closed, even to find the address of the next handle.  */
       lt_dlhandle pending = handle;
       handle = lt_dlhandle_next (handle);
+#ifdef DEBUG_MODULES
+      M4_DEBUG_MESSAGE1("module %s: attempting module close",
+                       m4_module_name (pending));
+#endif /* DEBUG_MODULES */
       m4_module_close (pending, obs);
     }
 
@@ -438,6 +450,46 @@ m4_module_load (const char *name, struct
   return handle;
 }
 
+int
+m4_module_remove (lt_dlhandle handle, struct obstack *obs)
+{
+  const lt_dlinfo *info                = 0;
+  int             errors       = 0;
+
+  assert (handle);
+
+  info = lt_dlgetinfo (handle);
+
+  /* Only do the actual close when the number of calls to close this
+     module is equal to the number of times it was opened. */
+#ifdef DEBUG_MODULES
+  if (info->ref_count > 1)
+    {
+      M4_DEBUG_MESSAGE2("module %s: now has %d references.",
+                       m4_module_name (handle), info->ref_count -1);
+    }
+#endif /* DEBUG_MODULES */
+
+  if (info->ref_count == 1)
+    {
+      /* Remove the table references only when ref_count is *exactly*
+        equal to 1.  If m4_module_close is called again on a
+        resident module after the references have already been
+        removed, we needn't try to remove them again!  */
+      m4_symtab_remove_module_references (handle);
+
+#ifdef DEBUG_MODULES
+      M4_DEBUG_MESSAGE1("module %s: symbols unloaded",
+                       m4_module_name (handle));
+#endif /* DEBUG_MODULES */
+    }
+
+  if (!errors)
+    m4_module_close (handle, obs);
+
+  return errors;
+}
+
 /* Unload a module.  */
 void
 m4_module_unload (const char *name, struct obstack *obs)
@@ -460,40 +512,51 @@ m4_module_unload (const char *name, stru
       ++errors;
     }
   else
+    errors = m4_module_remove (handle, obs);
+
+  if (errors)
     {
-      const lt_dlinfo *info = lt_dlgetinfo (handle);
+      M4ERROR ((EXIT_FAILURE, 0,
+               _("ERROR: cannot unload module `%s': %s"),
+               name, m4_module_dlerror ()));
+    }
+}
+
+void
+m4_module_unload_all (void)
+{
+  lt_dlhandle  handle  = lt_dlhandle_next (0);
+  int          errors  = 0;
 
-      /* Only do the actual close when the number of calls to close this
-        module is equal to the number of times it was opened. */
-      if (info->ref_count > 1)
+  while (handle && !errors)
+    {
+      lt_dlhandle      pending = handle;
+      const lt_dlinfo *info    = lt_dlgetinfo (pending);
+
+      /* We are *really* shutting down here, so freeing the module
+        data is required.  */
+      if (info)
        {
-#ifdef DEBUG_MODULES
-         M4_DEBUG_MESSAGE2("module %s: now has %d references.",
-                           name, info->ref_count -1);
-#endif /* DEBUG_MODULES */
+         m4_module_data *stale
+           = lt_dlcaller_set_data (m4_caller_id, handle, 0);
+         XFREE (stale);
        }
 
-      if (info->ref_count == 1)
-       {
-         /* Remove the table references only when ref_count is *exactly*
-            equal to 1.  If m4_module_close is called again on a
-            resident module after the references have already been
-            removed, we needn't try to remove them again!  */
-         m4_symtab_remove_module_references (handle);
+      /* If we are about to unload the final reference, move on to the
+        next handle before we unload the current one.  */
+      if (info->ref_count <= 1)
+       handle = lt_dlhandle_next (pending);
 
-#ifdef DEBUG_MODULES
-         M4_DEBUG_MESSAGE1("module %s: symbols unloaded", name);
-#endif /* DEBUG_MODULES */
-       }
+      errors = m4_module_remove (pending, 0);
     }
 
   if (!errors)
-    m4_module_close (handle, obs);
+    errors = lt_dlexit();
 
   if (errors)
     {
       M4ERROR ((EXIT_FAILURE, 0,
-               _("ERROR: cannot unload module `%s': %s"),
-               name, m4_module_dlerror ()));
+               _("ERROR: cannot unload all modules: %s"),
+               m4_module_dlerror ()));
     }
 }
Index: m4/output.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/output.c,v
retrieving revision 1.5
diff -u -p -u -r1.5 output.c
--- m4/output.c 2001/08/20 20:25:25 1.5
+++ m4/output.c 2001/09/20 03:46:23
@@ -105,7 +105,7 @@ int m4_output_current_line;
 void
 m4_output_init (void)
 {
-  diversion_table = (struct diversion *) xmalloc (sizeof (struct diversion));
+  diversion_table = XMALLOC (struct diversion, 1);
   diversions = 1;
   diversion_table[0].file = stdout;
   diversion_table[0].buffer = NULL;
@@ -120,6 +120,14 @@ m4_output_init (void)
   output_unused = 0;
 }
 
+void
+m4_output_exit (void)
+{
+  assert (diversions = 1);
+  XFREE (diversion_table);
+}
+
+
 #ifdef HAVE_MKTEMP
 #ifndef HAVE_MKSTEMP
 
@@ -683,4 +691,3 @@ m4_freeze_diversions (file)
   if (saved_number != last_inserted)
     fprintf (file, "D%d,0\n\n", saved_number);
 }
-
Index: m4/symtab.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/symtab.c,v
retrieving revision 1.21
diff -u -p -u -r1.21 symtab.c
--- m4/symtab.c 2001/09/08 01:56:34 1.21
+++ m4/symtab.c 2001/09/20 03:46:24
@@ -18,6 +18,11 @@
    02111-1307  USA
 */
 
+#include "m4private.h"
+
+#define DEBUG_SYM              /* Define this to see runtime debug info.  */
+#undef DEBUG_SYM
+
 /* This file handles all the low level work around the symbol table.  The
    symbol table is an abstract hash table type implemented in hash.c.  Each
    symbol is represented by `struct m4_symbol', which is stored in the hash
@@ -27,13 +32,13 @@
    simply ordered on the stack by age.  The most recently pushed definition
    will then always be the first found.  */
 
-#include "m4private.h"
-
 static size_t  m4_symtab_hash          (const void *key);
 static int     m4_symtab_cmp           (const void *key, const void *try);
-static void    m4_token_data_delete    (m4_token_data *data);
-static void    m4_symbol_pop           (m4_symbol *symbol);
-static void    m4_symbol_del           (m4_symbol *symbol);
+static void    m4_token_data_delete    (m4_symbol *data);
+static void    m4_symbol_pop           (m4_symbol **psymbol);
+static void    m4_symbol_del           (m4_symbol **psymbol);
+static int     m4_symbol_destroy       (const char *name, m4_symbol *symbol,
+                                        void *data);
 
 
 /* Pointer to symbol table.  */
@@ -47,6 +52,21 @@ m4_symtab_init (void)
   m4_symtab = m4_hash_new (m4_symtab_hash, m4_symtab_cmp);
 }
 
+int
+m4_symbol_destroy (const char *name, m4_symbol *symbol, void *data)
+{
+  m4_symbol_delete (name);
+  return 0;
+}
+
+void
+m4_symtab_exit (void)
+{
+  m4_symtab_apply (m4_symbol_destroy, NULL);
+  m4_hash_delete (m4_symtab);
+  m4_hash_exit ();
+}
+
 /* Return a hashvalue for a string, from GNU-emacs.  */
 size_t
 m4_symtab_hash (const void *key)
@@ -74,50 +94,45 @@ m4_symtab_cmp (const void *key, const vo
 
 
 void
-m4_token_data_delete (m4_token_data *data)
+m4_token_data_delete (m4_symbol *data)
 {
   assert (data);
-  assert (M4_TOKEN_DATA_NEXT (data) == 0);
+  assert (M4_SYMBOL_NEXT (data) == 0);
 
-  if (M4_TOKEN_DATA_TYPE (data) == M4_TOKEN_TEXT)
-    XFREE (M4_TOKEN_DATA_TEXT (data));
+  if (M4_SYMBOL_TYPE (data) == M4_TOKEN_TEXT)
+    XFREE (M4_SYMBOL_TEXT (data));
 
   XFREE (data);
 }
 
+
 void
-m4_symbol_pop (m4_symbol *symbol)
+m4_symbol_pop (m4_symbol **psymbol)
 {
-  m4_token_data *stale;
+  m4_symbol *stale;
 
-  assert (symbol);
-  assert (M4_SYMBOL_DATA_NEXT (symbol));
+  assert (psymbol);
+  assert (*psymbol);
 
-  stale                                = M4_SYMBOL_DATA (symbol);
-  M4_SYMBOL_DATA (symbol)      = M4_TOKEN_DATA_NEXT (stale);
+  stale         = *psymbol;
+  *psymbol = M4_SYMBOL_NEXT (stale);
 
 #ifndef NDEBUG
-  M4_TOKEN_DATA_NEXT (stale) = 0;
+  M4_SYMBOL_NEXT (stale) = 0;
 #endif
   m4_token_data_delete (stale);
 }
 
+
 /* Free all storage associated with a symbol.  */
 void
-m4_symbol_del (m4_symbol *symbol)
+m4_symbol_del (m4_symbol **psymbol)
 {
-  assert (symbol);
-
-  while (M4_SYMBOL_DATA_NEXT (symbol))
-    m4_symbol_pop (symbol);
-
-  assert (M4_SYMBOL_DATA_NEXT (symbol) == 0);
-
-  if (M4_SYMBOL_TYPE (symbol) == M4_TOKEN_TEXT)
-    XFREE (M4_SYMBOL_TEXT (symbol));
+  assert (psymbol);
+  assert (*psymbol);
 
-  XFREE (M4_SYMBOL_DATA (symbol));
-  XFREE (symbol);
+  while (*psymbol)
+    m4_symbol_pop (psymbol);
 }
 
 
@@ -142,21 +157,15 @@ m4_symbol_pushdef (const char *name)
   /* Insert a name in the symbol table.  If there is already a symbol
      with the name, push the new value on top of the value stack for
      this symbol.  */
-  m4_symbol *symbol    = 0;
-  m4_token_data *value = XCALLOC (m4_token_data, 1);
+  m4_symbol *symbol         = XCALLOC (m4_symbol, 1);;
+  M4_SYMBOL_TYPE (symbol)      = M4_TOKEN_VOID;
 
   if (psymbol)
     {
-      symbol = *psymbol;
-      M4_TOKEN_DATA_NEXT (value) = M4_SYMBOL_DATA (symbol);
+      M4_SYMBOL_NEXT (symbol) = *psymbol;
+      *psymbol = symbol;
     }
   else
-    symbol = XCALLOC (m4_symbol, 1);
-
-  M4_SYMBOL_DATA (symbol)      = value;
-  M4_SYMBOL_TYPE (symbol)      = M4_TOKEN_VOID;
-
-  if (!psymbol)
     m4_hash_insert (m4_symtab, xstrdup (name), symbol);
 
   return symbol;
@@ -167,11 +176,11 @@ m4_symbol_pushdef (const char *name)
 m4_symbol *
 m4_symbol_define (const char *name)
 {
-  m4_symbol *res = m4_symbol_lookup (name);
-  if (res)
-    return res;
+  m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name);
+  if (psymbol)
+    return *psymbol;
   else
-    m4_symbol_pushdef (name);
+    return m4_symbol_pushdef (name);
 }
 
 
@@ -183,12 +192,12 @@ m4_symbol_popdef (const char *name)
 
   assert (psymbol);
 
-  if (M4_SYMBOL_DATA_NEXT (*psymbol))
-    m4_symbol_pop (*psymbol);
+  if (M4_SYMBOL_NEXT (*psymbol))
+    m4_symbol_pop (psymbol);
   else
     {
       xfree (m4_hash_remove (m4_symtab, name));
-      m4_symbol_del (*psymbol);
+      m4_symbol_del (psymbol);
     }
 }
 
@@ -200,8 +209,13 @@ m4_symbol_delete (const char *name)
   m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name);
 
   assert (psymbol);
+
+#ifdef DEBUG_SYM
+  M4_DEBUG_MESSAGE1("symbol %s recycled.", name);
+#endif
+
   xfree (m4_hash_remove (m4_symtab, name));
-  m4_symbol_del (*psymbol);
+  m4_symbol_del (psymbol);
 }
 
 
@@ -253,42 +267,43 @@ m4_symtab_remove_module_references (lt_d
 
   assert (handle);
 
+  /* Traverse each symbol name in the hash table.  */
   while ((place = m4_hash_iterator_next (m4_symtab, place)))
     {
-      m4_symbol *symbol = (m4_symbol *) m4_hash_iterator_value (place);
-      m4_token_data *data = M4_SYMBOL_DATA (symbol);
+      m4_symbol **psymbol = (m4_symbol **) m4_hash_iterator_value (place);
+      m4_symbol *current  = *psymbol;
 
-      /* Purge any shadowed references.  */
-      while (M4_TOKEN_DATA_NEXT (data))
+      /* Examine each value in the value stack associated with this
+        symbol name.  */
+      while (M4_SYMBOL_NEXT (current))
        {
-         m4_token_data *next = M4_TOKEN_DATA_NEXT (data);
+         m4_symbol *next = M4_SYMBOL_NEXT (current);
 
-         if (M4_TOKEN_DATA_HANDLE (next) == handle)
+         if (M4_SYMBOL_HANDLE (next) == handle)
            {
-             M4_TOKEN_DATA_NEXT (data) = M4_TOKEN_DATA_NEXT (next);
+             M4_SYMBOL_NEXT (current) = M4_SYMBOL_NEXT (next);
              m4_token_data_delete (next);
            }
          else
-           data = next;
+           current = next;
        }
 
-      /* Purge live reference.  */
-      if (M4_SYMBOL_HANDLE (symbol) == handle)
+      /* Purge live reference.
+         This must be performed after the shadowed values have been weeded
+         so that the symbol key can be removed from the hash table if this
+         last value matches too.  */
+      if (M4_SYMBOL_HANDLE (*psymbol) == handle)
        {
-         if (M4_SYMBOL_DATA_NEXT (symbol))
-           m4_symbol_pop (symbol);
-         else
-           {
-             xfree (m4_hash_remove (m4_symtab, m4_hash_iterator_key (place)));
-             m4_symbol_del (symbol);
-           }
+         if (!M4_SYMBOL_NEXT (*psymbol))
+           xfree (m4_hash_remove (m4_symtab, m4_hash_iterator_key (place)));
+         m4_symbol_pop (psymbol);
        }
     }
 }
 
-/* The following function is used for the cases, where we want to do
+/* The following function is used for the cases where we want to do
    something to each and every symbol in the table.  The function
-   hack_all_symbols () traverses the symbol table, and calls a specified
+   m4_symtab_apply () traverses the symbol table, and calls a specified
    function FUNC for each symbol in the table.  FUNC is called with a
    pointer to the symbol, and the DATA argument.  */
 int
@@ -301,9 +316,9 @@ m4_symtab_apply (m4_symtab_apply_func *f
 
   while ((place = m4_hash_iterator_next (m4_symtab, place)))
     {
-      const char *name = (const char *) m4_hash_iterator_key (place);
-      m4_symbol *symbol = (m4_symbol *) m4_hash_iterator_value (place);
-      result = (*func) (name, symbol, data);
+      const char *name   = (const char *) m4_hash_iterator_key (place);
+      m4_symbol **psymbol = (m4_symbol **) m4_hash_iterator_value (place);
+      result = (*func) (name, *psymbol, data);
 
       if (result != 0)
        break;
@@ -321,17 +336,17 @@ static int symtab_print_list (const char
 static void
 symtab_debug (void)
 {
-  m4_token_data_t t;
-  m4_token_data td;
+  m4_token_t t;
+  m4_symbol tokenbuf;
   const char *text;
   m4_symbol *s;
   int delete;
 
-  while ((t = m4_next_token (&td)) != NULL)
+  while ((t = m4_next_token (&tokenbuf)) != M4_TOKEN_EOF)
     {
       if (t != M4_TOKEN_WORD)
        continue;
-      text = M4_TOKEN_DATA_TEXT (&td);
+      text = M4_SYMBOL_TEXT (&tokenbuf);
       if (*text == '_')
        {
          delete = 1;
Index: m4/utility.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/utility.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 utility.c
--- m4/utility.c 2001/09/08 02:36:47 1.13
+++ m4/utility.c 2001/09/20 03:46:24
@@ -79,21 +79,21 @@ m4_string ecomm;
    internal data structure, so they are safe to export for use in
    external modules.  */
 m4_token_data_t
-m4_token_data_type (m4_token_data *name)
+m4_symbol_type (m4_symbol *name)
 {
-  return M4_TOKEN_DATA_TYPE(name);
+  return M4_SYMBOL_TYPE(name);
 }
 
 char *
-m4_token_data_text (m4_token_data *name)
+m4_symbol_text (m4_symbol *name)
 {
-  return M4_TOKEN_DATA_TEXT(name);
+  return M4_SYMBOL_TEXT(name);
 }
 
 m4_builtin_func *
-m4_token_data_func (m4_token_data *name)
+m4_symbol_func (m4_symbol *name)
 {
-  return M4_TOKEN_DATA_FUNC(name);
+  return M4_SYMBOL_FUNC(name);
 }
 
 
@@ -104,13 +104,13 @@ m4_token_data_func (m4_token_data *name)
    negative if not applicable, MAX is the maximum number, negative if not
    applicable.  */
 boolean
-m4_bad_argc (m4_token_data *name, int argc, int min, int max)
+m4_bad_argc (m4_symbol *name, int argc, int min, int max)
 {
   if (min > 0 && argc < min)
     {
       M4WARN ((warning_status, 0,
               _("Warning: %s: too few arguments"),
-              M4_TOKEN_DATA_TEXT (name)));
+              M4_SYMBOL_TEXT (name)));
       return TRUE;
     }
 
@@ -118,7 +118,7 @@ m4_bad_argc (m4_token_data *name, int ar
     {
       M4WARN ((warning_status, 0,
               _("Warning: %s: too many arguments (ignored)"),
-              M4_TOKEN_DATA_TEXT (name)));
+              M4_SYMBOL_TEXT (name)));
       /* Return FALSE, otherwise it is not exactly `ignored'. */
       return FALSE;
     }
@@ -138,7 +138,7 @@ m4_skip_space (const char *arg)
    VALUEP. If the conversion fails, print error message for macro MACRO.
    Return TRUE iff conversion succeeds.  */
 boolean
-m4_numeric_arg (m4_token_data *macro, const char *arg, int *valuep)
+m4_numeric_arg (m4_symbol *macro, const char *arg, int *valuep)
 {
   char *endp;
 
@@ -147,7 +147,7 @@ m4_numeric_arg (m4_token_data *macro, co
     {
       M4WARN ((warning_status, 0,
               _("Warning: %s: non-numeric argument: %s"),
-              M4_TOKEN_DATA_TEXT (macro), arg));
+              M4_SYMBOL_TEXT (macro), arg));
       return FALSE;
     }
   return TRUE;
@@ -157,7 +157,7 @@ m4_numeric_arg (m4_token_data *macro, co
 /* Print ARGC arguments from the table ARGV to obstack OBS, separated by
    SEP, and quoted by the current quotes, if QUOTED is TRUE.  */
 void
-m4_dump_args (struct obstack *obs, int argc, m4_token_data **argv,
+m4_dump_args (struct obstack *obs, int argc, m4_symbol **argv,
              const char *sep, boolean quoted)
 {
   int i;
@@ -168,7 +168,7 @@ m4_dump_args (struct obstack *obs, int a
       if (i > 1)
        obstack_grow (obs, sep, len);
 
-      m4_shipout_string (obs, M4_TOKEN_DATA_TEXT (argv[i]), 0, quoted);
+      m4_shipout_string (obs, M4_SYMBOL_TEXT (argv[i]), 0, quoted);
     }
 }
 
@@ -243,7 +243,7 @@ m4_dump_symbol (const char *name, m4_sym
    symbols, otherwise, only the specified symbols.  */
 void
 m4_dump_symbols (struct m4_dump_symbol_data *data, int argc,
-                m4_token_data **argv, boolean complain)
+                m4_symbol **argv, boolean complain)
 {
   data->base = (const char **) obstack_base (data->obs);
   data->size = 0;
@@ -259,9 +259,9 @@ m4_dump_symbols (struct m4_dump_symbol_d
 
       for (i = 1; i < argc; i++)
        {
-         symbol = m4_symbol_lookup (M4_TOKEN_DATA_TEXT (argv[i]));
+         symbol = m4_symbol_lookup (M4_SYMBOL_TEXT (argv[i]));
          if (symbol != NULL && M4_SYMBOL_TYPE (symbol) != M4_TOKEN_VOID)
-           m4_dump_symbol (M4_TOKEN_DATA_TEXT (argv[i]), symbol, data);
+           m4_dump_symbol (M4_SYMBOL_TEXT (argv[i]), symbol, data);
          else if (complain)
            M4WARN ((warning_status, 0,
                     _("Warning: %s: undefined name: %s"),
Index: modules/format.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/format.c,v
retrieving revision 1.9
diff -u -p -u -r1.9 format.c
--- modules/format.c 2001/09/05 07:51:59 1.9
+++ modules/format.c 2001/09/20 03:46:30
@@ -24,36 +24,36 @@
 
 #define ARG_INT(argc, argv) \
        ((argc == 0) ? 0 : \
-        (--argc, argv++, atoi (M4_TOKEN_DATA_TEXT (argv[-1]))))
+        (--argc, argv++, atoi (M4_SYMBOL_TEXT (argv[-1]))))
 
 #define ARG_UINT(argc, argv) \
        ((argc == 0) ? 0 : \
-        (--argc, argv++, (unsigned int) atoi (M4_TOKEN_DATA_TEXT (argv[-1]))))
+        (--argc, argv++, (unsigned int) atoi (M4_SYMBOL_TEXT (argv[-1]))))
 
 #define ARG_LONG(argc, argv) \
        ((argc == 0) ? 0 : \
-        (--argc, argv++, atol (M4_TOKEN_DATA_TEXT (argv[-1]))))
+        (--argc, argv++, atol (M4_SYMBOL_TEXT (argv[-1]))))
 
 #define ARG_ULONG(argc, argv) \
        ((argc == 0) ? 0 : \
-        (--argc, argv++, (unsigned long) atol (M4_TOKEN_DATA_TEXT (argv[-1]))))
+        (--argc, argv++, (unsigned long) atol (M4_SYMBOL_TEXT (argv[-1]))))
 
 #define ARG_STR(argc, argv) \
        ((argc == 0) ? "" : \
-        (--argc, argv++, M4_TOKEN_DATA_TEXT (argv[-1])))
+        (--argc, argv++, M4_SYMBOL_TEXT (argv[-1])))
 
 #define ARG_DOUBLE(argc, argv) \
        ((argc == 0) ? 0 : \
-        (--argc, argv++, atof (M4_TOKEN_DATA_TEXT (argv[-1]))))
+        (--argc, argv++, atof (M4_SYMBOL_TEXT (argv[-1]))))
 
 
 /* The main formatting function.  Output is placed on the obstack OBS, the
    first argument in ARGV is the formatting string, and the rest is
    arguments for the string.  */
-void format (struct obstack *obs, int argc, m4_token_data **argv);
+void format (struct obstack *obs, int argc, m4_symbol **argv);
 
 void
-format (struct obstack *obs, int argc, m4_token_data **argv)
+format (struct obstack *obs, int argc, m4_symbol **argv)
 {
   char *fmt;                   /* format control string */
   const char *fstart;          /* beginning of current format spec */
Index: modules/gnu.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/gnu.c,v
retrieving revision 1.9
diff -u -p -u -r1.9 gnu.c
--- modules/gnu.c 2001/09/05 07:28:49 1.9
+++ modules/gnu.c 2001/09/20 03:46:30
@@ -171,8 +171,8 @@ M4BUILTIN_HANDLER (changesyntax)
 
   for (i = 1; i < argc; i++)
     {
-      m4_set_syntax (*M4_TOKEN_DATA_TEXT (argv[i]),
-                    m4_expand_ranges (M4_TOKEN_DATA_TEXT (argv[i])+1, obs));
+      m4_set_syntax (*M4_SYMBOL_TEXT (argv[i]),
+                    m4_expand_ranges (M4_SYMBOL_TEXT (argv[i])+1, obs));
     }
 }
 
@@ -270,8 +270,8 @@ M4BUILTIN_HANDLER (regexp)
   if (m4_bad_argc (argv[0], argc, 3, 4))
     return;
 
-  victim = M4_TOKEN_DATA_TEXT (argv[1]);
-  regexp = M4_TOKEN_DATA_TEXT (argv[2]);
+  victim = M4_SYMBOL_TEXT (argv[1]);
+  regexp = M4_SYMBOL_TEXT (argv[2]);
 
   buf.buffer = NULL;
   buf.allocated = 0;
@@ -301,7 +301,7 @@ M4BUILTIN_HANDLER (regexp)
     m4_shipout_int (obs, startpos);
   else if (startpos >= 0)
     {
-      repl = M4_TOKEN_DATA_TEXT (argv[3]);
+      repl = M4_SYMBOL_TEXT (argv[3]);
       substitute (obs, victim, repl, &regs);
     }
 
@@ -331,7 +331,7 @@ M4BUILTIN_HANDLER (patsubst)
   if (m4_bad_argc (argv[0], argc, 3, 4))
     return;
 
-  regexp = M4_TOKEN_DATA_TEXT (argv[2]);
+  regexp = M4_SYMBOL_TEXT (argv[2]);
 
   buf.buffer = NULL;
   buf.allocated = 0;
@@ -348,7 +348,7 @@ M4BUILTIN_HANDLER (patsubst)
       return;
     }
 
-  victim = M4_TOKEN_DATA_TEXT (argv[1]);
+  victim = M4_SYMBOL_TEXT (argv[1]);
   length = strlen (victim);
 
   offset = 0;
@@ -433,18 +433,18 @@ M4BUILTIN_HANDLER (syncoutput)
   if (m4_bad_argc (argv[0], argc, 2, 2))
     return;
 
-  if (M4_TOKEN_DATA_TYPE (argv[1]) != M4_TOKEN_TEXT)
+  if (M4_SYMBOL_TYPE (argv[1]) != M4_TOKEN_TEXT)
     return;
 
-  if (M4_TOKEN_DATA_TEXT(argv[1])[0] == '0'
-      || M4_TOKEN_DATA_TEXT(argv[1])[0] == 'n'
-      || (M4_TOKEN_DATA_TEXT(argv[1])[0] == 'o'
-         && M4_TOKEN_DATA_TEXT(argv[1])[1] == 'f'))
+  if (M4_SYMBOL_TEXT(argv[1])[0] == '0'
+      || M4_SYMBOL_TEXT(argv[1])[0] == 'n'
+      || (M4_SYMBOL_TEXT(argv[1])[0] == 'o'
+         && M4_SYMBOL_TEXT(argv[1])[1] == 'f'))
     sync_output = 0;
-  else if (M4_TOKEN_DATA_TEXT(argv[1])[0] == '1'
-          || M4_TOKEN_DATA_TEXT(argv[1])[0] == 'y'
-          || (M4_TOKEN_DATA_TEXT(argv[1])[0] == 'o'
-              && M4_TOKEN_DATA_TEXT(argv[1])[1] == 'n'))
+  else if (M4_SYMBOL_TEXT(argv[1])[0] == '1'
+          || M4_SYMBOL_TEXT(argv[1])[0] == 'y'
+          || (M4_SYMBOL_TEXT(argv[1])[0] == 'o'
+              && M4_SYMBOL_TEXT(argv[1])[1] == 'n'))
     sync_output = 1;
 }
 
Index: modules/m4.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/m4.c,v
retrieving revision 1.21
diff -u -p -u -r1.21 m4.c
--- modules/m4.c 2001/09/18 01:07:09 1.21
+++ modules/m4.c 2001/09/20 03:46:31
@@ -131,7 +131,7 @@ M4BUILTIN_HANDLER (define)
   if (m4_bad_argc (argv[0], argc, 2, 3))
     return;
 
-  if (M4_TOKEN_DATA_TYPE (argv[1]) != M4_TOKEN_TEXT)
+  if (M4_SYMBOL_TYPE (argv[1]) != M4_TOKEN_TEXT)
     return;
 
   if (argc == 2)
@@ -140,7 +140,7 @@ M4BUILTIN_HANDLER (define)
       return;
     }
 
-  switch (M4_TOKEN_DATA_TYPE (argv[2]))
+  switch (M4_SYMBOL_TYPE (argv[2]))
     {
     case M4_TOKEN_TEXT:
       m4_macro_define (M4ARG (1), NULL, M4ARG (2));
@@ -148,9 +148,9 @@ M4BUILTIN_HANDLER (define)
 
     case M4_TOKEN_FUNC:
       {
-       lt_dlhandle  handle  = M4_TOKEN_DATA_HANDLE (argv[2]);
-       const m4_builtin  *builtin = 0;
-       m4_symbol *symbol = 0;
+       lt_dlhandle        handle  = M4_SYMBOL_HANDLE (argv[2]);
+       const m4_builtin * builtin = 0;
+       m4_symbol *        symbol  = 0;
 
        /* If we find a TOKEN_FUNC with no defining module, then
           somewhere along the way we have lost the module handle.  */
@@ -160,12 +160,12 @@ M4BUILTIN_HANDLER (define)
           and blind_no_args flags?  May as well carry these around with
           the traced flag, and save a _lot_ of lookup time.  */
        builtin = m4_builtin_find_by_func (m4_module_builtins (handle),
-                                          M4_TOKEN_DATA_FUNC (argv[2]));
+                                          M4_SYMBOL_FUNC (argv[2]));
 
-       symbol = m4_builtin_define (M4ARG (1), handle, builtin);
+       symbol  = m4_builtin_define (M4ARG (1), handle, builtin);
 
        /* Be sure to propogate the flags from the TOKEN_FUNC.  */
-       M4_SYMBOL_TRACED (symbol) = M4_TOKEN_TRACED (argv[2]);
+       M4_SYMBOL_TRACED (symbol) = M4_SYMBOL_TRACED (argv[2]);
       }
       return;
     }
@@ -191,7 +191,7 @@ M4BUILTIN_HANDLER (pushdef)
   if (m4_bad_argc (argv[0], argc, 2, 3))
     return;
 
-  if (M4_TOKEN_DATA_TYPE (argv[1]) != M4_TOKEN_TEXT)
+  if (M4_SYMBOL_TYPE (argv[1]) != M4_TOKEN_TEXT)
     return;
 
   if (argc == 2)
@@ -200,7 +200,7 @@ M4BUILTIN_HANDLER (pushdef)
       return;
     }
 
-  switch (M4_TOKEN_DATA_TYPE (argv[2]))
+  switch (M4_SYMBOL_TYPE (argv[2]))
     {
     case M4_TOKEN_TEXT:
       m4_macro_pushdef (M4ARG (1), NULL, M4ARG (2));
@@ -208,15 +208,15 @@ M4BUILTIN_HANDLER (pushdef)
 
     case M4_TOKEN_FUNC:
       {
-       lt_dlhandle  handle  = M4_TOKEN_DATA_HANDLE (argv[2]);
-       const m4_builtin  *builtin = 0;
+       lt_dlhandle        handle  = M4_SYMBOL_HANDLE (argv[2]);
+       const m4_builtin * builtin = 0;
 
        /* If we find a TOKEN_FUNC with no defining module, then
           somewhere along the way we have lost the module handle.  */
        assert (handle);
 
        builtin = m4_builtin_find_by_func (m4_module_builtins (handle),
-                                          M4_TOKEN_DATA_FUNC (argv[2]));
+                                          M4_SYMBOL_FUNC (argv[2]));
 
        m4_builtin_pushdef (M4ARG (1), handle, builtin);
       }
@@ -524,8 +524,8 @@ M4BUILTIN_HANDLER (changequote)
   if (m4_bad_argc (argv[0], argc, 1, 3))
     return;
 
-  m4_set_quotes ((argc >= 2) ? M4_TOKEN_DATA_TEXT (argv[1]) : NULL,
-            (argc >= 3) ? M4_TOKEN_DATA_TEXT (argv[2]) : NULL);
+  m4_set_quotes ((argc >= 2) ? M4_SYMBOL_TEXT (argv[1]) : NULL,
+            (argc >= 3) ? M4_SYMBOL_TEXT (argv[2]) : NULL);
 }
 
 /* Change the current comment delimiters.  The function set_comment ()
@@ -538,8 +538,8 @@ M4BUILTIN_HANDLER (changecom)
   if (argc == 1)
     m4_set_comment ("", "");   /* disable comments */
   else
-    m4_set_comment (M4_TOKEN_DATA_TEXT (argv[1]),
-                   (argc >= 3) ? M4_TOKEN_DATA_TEXT (argv[2]) : NULL);
+    m4_set_comment (M4_SYMBOL_TEXT (argv[1]),
+                   (argc >= 3) ? M4_SYMBOL_TEXT (argv[2]) : NULL);
 }
 
 
@@ -550,7 +550,7 @@ M4BUILTIN_HANDLER (changecom)
 /* Generic include function.  Include the file given by the first argument,
    if it exists.  Complain about inaccesible files iff SILENT is FALSE.  */
 static void
-include (int argc, m4_token_data **argv, boolean silent)
+include (int argc, m4_symbol **argv, boolean silent)
 {
   FILE *fp;
   char *name = NULL;
Index: src/freeze.c
===================================================================
RCS file: /cvsroot/m4/m4/src/freeze.c,v
retrieving revision 1.16
diff -u -p -u -r1.16 freeze.c
--- src/freeze.c 2001/09/08 01:40:47 1.16
+++ src/freeze.c 2001/09/20 03:46:31
@@ -128,8 +128,8 @@ produce_symbol_dump (FILE *file, m4_hash
 
   while ((place = m4_hash_iterator_next (hash, place)))
     {
-      const char   *symbol_name        = m4_hash_iterator_key (place);
-      m4_symbol           *symbol      = m4_hash_iterator_value (place);
+      const char   *symbol_name        = (const char *)m4_hash_iterator_key 
(place);
+      m4_symbol           *symbol      = *(m4_symbol 
**)m4_hash_iterator_value(place);
       lt_dlhandle   handle     = M4_SYMBOL_HANDLE (symbol);
       const char   *module_name        = handle ? m4_module_name (handle) : 
NULL;
       const m4_builtin *bp;
Index: src/m4.h
===================================================================
RCS file: /cvsroot/m4/m4/src/m4.h,v
retrieving revision 1.8
diff -u -p -u -r1.8 m4.h
--- src/m4.h 2001/08/20 19:42:38 1.8
+++ src/m4.h 2001/09/20 03:46:33
@@ -99,6 +99,7 @@ char *mktemp ();
 #ifdef USE_STACKOVF
 void setup_stackovf_trap (char *const *, char *const *,
                          void (*handler) (void));
+void stackovf_exit (void);
 #endif
 
 
Index: src/main.c
===================================================================
RCS file: /cvsroot/m4/m4/src/main.c,v
retrieving revision 1.24
diff -u -p -u -r1.24 main.c
--- src/main.c 2001/09/08 01:56:34 1.24
+++ src/main.c 2001/09/20 03:46:34
@@ -516,10 +516,21 @@ warranty; not even for MERCHANTABILITY o
       m4_undivert_all ();
     }
 
-  {
-    struct obstack *obs = 0;
-    m4_module_close_all (obs);
-  }
+  m4_module_unload_all ();
+
+  /* The remaining cleanup functions systematically free all of the
+     memory we still have pointers to.  By definition, if there is
+     anything left when we're done: it was caused by a memory leak.
+     Strictly, we don't need to do this, but it makes leak detection
+     a whole lot easier!  */
+  m4_symtab_exit ();
+  m4_output_exit ();
+  m4_input_exit ();
+  m4_debug_exit ();
+
+#ifdef USE_STACKOVF
+  stackovf_exit ();
+#endif
 
   exit (exit_status);
 }
Index: src/stackovf.c
===================================================================
RCS file: /cvsroot/m4/m4/src/stackovf.c,v
retrieving revision 1.6
diff -u -p -u -r1.6 stackovf.c
--- src/stackovf.c 2001/08/20 19:42:38 1.6
+++ src/stackovf.c 2001/09/20 03:46:34
@@ -118,6 +118,7 @@ extern int  sigstack        (struct sigstack *, 
 extern int     sigvec          (int, struct sigvec *, struct sigvec *);
 #endif
 
+static const char *stackbuf;
 static const char *stackbot;
 static const char *stackend;
 static const char *arg0;
@@ -335,12 +336,14 @@ setup_stackovf_trap (char *const *argv, 
   {
     stack_t ss;
 
+    stackbuf = (char *) xmalloc (SIGSTKSZ);
+
     ss.ss_size = SIGSTKSZ;
-    ss.ss_sp = xmalloc (ss.ss_size);
+    ss.ss_sp = (void *) stackbuf;
     ss.ss_flags = 0;
     if (sigaltstack (&ss, (stack_t *) 0) < 0)
       {
-       xfree (ss.ss_sp);
+       xfree (stackbuf);
        error (1, errno, "sigaltstack");
       }
   }
@@ -350,7 +353,7 @@ setup_stackovf_trap (char *const *argv, 
 
   {
     struct sigstack ss;
-    char *stackbuf = xmalloc (2 * SIGSTKSZ);
+    stackbuf = (char *) xmalloc (2 * SIGSTKSZ);
 
     ss.ss_sp = stackbuf + SIGSTKSZ;
     ss.ss_onstack = 0;
@@ -406,6 +409,12 @@ Error - Do not know how to catch signals
 #endif /* HAVE_SIGVEC && defined(SV_ONSTACK) */
 #endif /* HAVE_SIGALTSTACK && defined(SA_ONSTACK) */
 
+}
+
+void
+stackovf_exit (void)
+{
+  XFREE (stackbuf);
 }
 
 #endif /* USE_STACKOVF */

-- 
  ())_. Gary V. Vaughan     gary@(oranda.demon.co.uk|gnu.org)
  ( '/  Research Scientist  http://www.oranda.demon.co.uk       ,_())____
  / )=  GNU Hacker          http://www.gnu.org/software/libtool  \'      `&
`(_~)_  Tech' Author        http://sources.redhat.com/autobook   =`---d__/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]