commit-mailutils
[Top][All Lists]
Advanced

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

[SCM] GNU Mailutils branch, master, updated. release-3.1.1-17-g622bc77


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-3.1.1-17-g622bc77
Date: Tue, 27 Dec 2016 15:46:59 +0000 (UTC)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=622bc770d5f8d7500fa409993c8fef8de5736962

The branch, master has been updated
       via  622bc770d5f8d7500fa409993c8fef8de5736962 (commit)
      from  8c834b60399ac1ef71569a4cedee25bd30b8d07c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 622bc770d5f8d7500fa409993c8fef8de5736962
Author: Sergey Poznyakoff <address@hidden>
Date:   Tue Dec 27 12:39:26 2016 +0200

    Revise associative array API
    
    * configure.ac (VI_REVISION): Increase.
    * include/mailutils/assoc.h (mu_assoc_create): Change prototype.
    (mu_assoc_ref,mu_assoc_ref_install)
    (mu_assoc_remove_ref): Remove.
    (mu_assoc_get): New proto.
    (mu_assoc_lookup,mu_assoc_lookup_ref): New proto.
    (mu_assoc_install_ref): New proto.
    (mu_assoc_set_free): Remove.
    (mu_assoc_set_destroy_item): Set proto.
    * include/mailutils/types.hin (mu_deallocator_t): New typedef.
    * include/mailutils/list.h (mu_list_destroy_item_t): Change definition.
    * libmailutils/base/assoc.c: Rewrite.  Link all entries in
    a doubly-linked list to preserve natural ordering during iterations.
    * libmailutils/base/mutil.c (mutil_parse_field_map): Update calls
    to assoc API.
    * libmailutils/cfg/driver.c (alloc_section_tab)
    (mu_create_canned_section,mu_create_canned_param)
    (mu_get_canned_container,parse_mapping)
    (mu_cfg_field_map): Likewise.
    * libmailutils/mime/mimehdr.c (_mu_mime_param_free): Free the pointer
    itself.
    (flush_param,mu_mime_param_assoc_create)
    (mu_mime_param_assoc_add)
    (_mime_header_parse)
    (mu_mimehdr_aget_decoded_param): Update calls to assoc API.
    (mu_mime_param_free): New function.
    * libmailutils/property/assocprop.c: Likewise.
    * libmu_sieve/environment.c: Likewise.
    * libmu_sieve/variables.c: Likewise.
    * libproto/imap/id.c: Likewise.
    * mail/alias.c: Likewise.
    * mail/testsuite/mail/alias.exp: Update ordering of expected output.
    * mu/imap.c (com_id): Update.
    
    * include/mailutils/mime.h (mu_rfc2047_decode_param): Change prototype.
    * libmailutils/base/rfc2047.c (mu_rfc2047_decode_param): Allocate
    returned value, instead of filling an already allocated structure.
    * libproto/imap/fetch.c: Reflect changes.

-----------------------------------------------------------------------

Summary of changes:
 configure.ac                      |    2 +-
 include/mailutils/assoc.h         |   17 +-
 include/mailutils/list.h          |    2 +-
 include/mailutils/mime.h          |    3 +-
 include/mailutils/types.hin       |    4 +
 libmailutils/base/assoc.c         |  393 ++++++++++++++++++++++++-------------
 libmailutils/base/mutil.c         |   13 +-
 libmailutils/base/rfc2047.c       |   15 +-
 libmailutils/cfg/driver.c         |   22 +--
 libmailutils/mime/mimehdr.c       |  187 ++++++++----------
 libmailutils/property/assocprop.c |   44 ++---
 libmu_sieve/environment.c         |    8 +-
 libmu_sieve/variables.c           |   32 +--
 libproto/imap/fetch.c             |   16 +-
 libproto/imap/id.c                |   17 +-
 mail/alias.c                      |   61 +++---
 mail/testsuite/mail/alias.exp     |   12 +-
 mu/imap.c                         |   12 +-
 18 files changed, 466 insertions(+), 394 deletions(-)

diff --git a/configure.ac b/configure.ac
index c7ce55a..39b8e88 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,7 +32,7 @@ AB_INIT
 
 dnl Library versioning
 AC_SUBST(VI_CURRENT,  5)
-AC_SUBST(VI_REVISION, 1)
+AC_SUBST(VI_REVISION, 2)
 AC_SUBST(VI_AGE,      0)
 
 dnl Library paths
diff --git a/include/mailutils/assoc.h b/include/mailutils/assoc.h
index 0d9df0d..dbf77f4 100644
--- a/include/mailutils/assoc.h
+++ b/include/mailutils/assoc.h
@@ -28,18 +28,19 @@ extern "C" {
 #define MU_ASSOC_COPY_KEY 0x01
 #define MU_ASSOC_ICASE    0x02
   
-typedef void (*mu_assoc_free_fn) (void *data);
-  
-int mu_assoc_create (mu_assoc_t *passoc, size_t elsize, int flags);
+int mu_assoc_create (mu_assoc_t *passoc, int flags);
 void mu_assoc_destroy (mu_assoc_t *passoc);
-void mu_assoc_clear (mu_assoc_t assoc);  
-void *mu_assoc_ref (mu_assoc_t assoc, const char *name);
+void mu_assoc_clear (mu_assoc_t assoc);
+int mu_assoc_lookup (mu_assoc_t assoc, const char *name, void *dataptr);
+void *mu_assoc_get (mu_assoc_t assoc, const char *name);
 int mu_assoc_install (mu_assoc_t assoc, const char *name, void *value);
-int mu_assoc_ref_install (mu_assoc_t assoc, const char *name, void **pval);
+
+int mu_assoc_lookup_ref (mu_assoc_t assoc, const char *name, void *dataptr);
+int mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval);
+  
 int mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator);
-int mu_assoc_remove_ref (mu_assoc_t assoc, void *data);
 int mu_assoc_remove (mu_assoc_t assoc, const char *name);  
-int mu_assoc_set_free (mu_assoc_t assoc, mu_assoc_free_fn fn);
+int mu_assoc_set_destroy_item (mu_assoc_t assoc, mu_deallocator_t fn);
 int mu_assoc_count (mu_assoc_t assoc, size_t *pcount);
 
 #ifdef __cplusplus
diff --git a/include/mailutils/list.h b/include/mailutils/list.h
index 50d1947..33720ac 100644
--- a/include/mailutils/list.h
+++ b/include/mailutils/list.h
@@ -59,7 +59,7 @@ int mu_list_get_comparator (mu_list_t _list, 
mu_list_comparator_t *_pcmp);
 
   /* The destroy function is responsible for deallocating a list element.
      By default, it is not set. */
-typedef void (*mu_list_destroy_item_t) (void *);
+typedef mu_deallocator_t mu_list_destroy_item_t;
 
   /* An often used destroy function.  It simply calls free(3) over the
      _item. */
diff --git a/include/mailutils/mime.h b/include/mailutils/mime.h
index 6065a49..6799e43 100644
--- a/include/mailutils/mime.h
+++ b/include/mailutils/mime.h
@@ -57,7 +57,8 @@ int mu_rfc2047_decode   (const char *tocode, const char 
*fromstr,
 int mu_rfc2047_encode   (const char *charset, const char *encoding, 
                         const char *text, char **result);
 int mu_rfc2047_decode_param (const char *tocode, const char *input,
-                            struct mu_mime_param *param);
+                            struct mu_mime_param **param);
+void mu_mime_param_free (struct mu_mime_param *p);
 
 int mu_base64_encode    (const unsigned char *input, size_t input_len,
                         unsigned char **output, size_t * output_len);
diff --git a/include/mailutils/types.hin b/include/mailutils/types.hin
index 045c140..0981bf8 100644
--- a/include/mailutils/types.hin
+++ b/include/mailutils/types.hin
@@ -129,6 +129,10 @@ typedef struct _mu_dbm_file *mu_dbm_file_t;
 typedef struct _mu_imapio *mu_imapio_t;
 typedef struct _mu_msgset *mu_msgset_t;
 
+/* Pointer to a function responsible for freeing the memory resources
+   allocated for its argument. */
+typedef void (*mu_deallocator_t) (void *);
+  
 typedef void (*mu_onexit_t) (void*);
 typedef unsigned int mu_debug_handle_t;
 typedef unsigned int mu_debug_level_t;
diff --git a/libmailutils/base/assoc.c b/libmailutils/base/assoc.c
index 6a8263b..bae361c 100644
--- a/libmailutils/base/assoc.c
+++ b/libmailutils/base/assoc.c
@@ -46,41 +46,52 @@ static unsigned int max_rehash = sizeof (hash_size) / 
sizeof (hash_size[0]);
 struct _mu_assoc_elem
 {
   char *name;
-  char data[1];
+  struct _mu_assoc_elem *next, *prev;
+  char *data;
 };
 
 struct _mu_assoc
 {
   int flags;
   unsigned int hash_num;  /* Index to hash_size table */
-  size_t elsize;          /* Size of an element */
-  void *tab;
-  mu_assoc_free_fn free;
+  struct _mu_assoc_elem **tab;
+  struct _mu_assoc_elem *head, *tail;
+  mu_deallocator_t free;
   mu_iterator_t itr;
 };
-
-struct _mu_assoc_elem_align
+
+static void
+assoc_elem_unlink (mu_assoc_t assoc, int idx)
 {
-  char c;
-  struct _mu_assoc_elem x;
-};
+  struct _mu_assoc_elem *p;
 
-#define __ASSOC_ELEM_ALIGNMENT (mu_offsetof(struct _mu_assoc_elem_align, x))
-
-#define __ASSOC_ELEM_SIZE(a) \
-   ((a)->elsize + mu_offsetof(struct _mu_assoc_elem, data))
-#define __ASSOC_ALIGN(a, b) (((a) + (b) - 1) & ~((b) - 1))
-#define ASSOC_ELEM_SIZE(a) \
-   __ASSOC_ALIGN(__ASSOC_ELEM_SIZE(a),__ASSOC_ELEM_ALIGNMENT)
+  p = assoc->tab[idx]->prev;
+  if (p)
+    p->next = assoc->tab[idx]->next;
+  else
+    assoc->head = assoc->tab[idx]->next;
 
-#define __ASSOC_ELEM(a,p,n) \
- ((struct _mu_assoc_elem*) ((char*) (p) + ASSOC_ELEM_SIZE (a) * n))
+  p = assoc->tab[idx]->next;
+  if (p)
+    p->prev = assoc->tab[idx]->prev;
+  else
+    assoc->tail = assoc->tab[idx]->prev;
 
-#define ASSOC_ELEM(a,n) __ASSOC_ELEM(a,(a)->tab,n)
+  assoc->tab[idx]->prev = assoc->tab[idx]->next = NULL;
+}
 
-#define ASSOC_ELEM_INDEX(a,e) \
- (((char*)(e) - (char*)(a)->tab) / ASSOC_ELEM_SIZE (a))
+static void
+assoc_elem_link (mu_assoc_t assoc, int idx)
+{
+  assoc->tab[idx]->next = NULL;
+  assoc->tab[idx]->prev = assoc->tail;
 
+  if (assoc->tail)
+    assoc->tail->next = assoc->tab[idx];
+  else
+    assoc->head = assoc->tab[idx];
+  assoc->tail = assoc->tab[idx];
+}
 
 static unsigned
 hash (const char *name, unsigned long hash_num)
@@ -95,39 +106,38 @@ hash (const char *name, unsigned long hash_num)
   return i % hash_size[hash_num];
 };
 
-static int
-assoc_lookup_or_install (struct _mu_assoc_elem **elp,
-                        mu_assoc_t assoc, const char *name, int *install);
+static int assoc_find_slot (mu_assoc_t assoc, const char *name,
+                           int *install, unsigned *slot);
 
 static int
 assoc_rehash (mu_assoc_t assoc)
 {
-  void *old_tab = assoc->tab;
-  void *new_tab;
+  struct _mu_assoc_elem **old_tab = assoc->tab;
+  struct _mu_assoc_elem **new_tab;
   unsigned int i;
   unsigned int hash_num = assoc->hash_num + 1;
   
   if (hash_num >= max_rehash)
-      return MU_ERR_BUFSPACE;
+    return MU_ERR_BUFSPACE;
 
-  new_tab = calloc (hash_size[hash_num], ASSOC_ELEM_SIZE (assoc));
+  new_tab = calloc (hash_size[hash_num], sizeof (new_tab[0]));
+  if (!new_tab)
+    return errno;
   assoc->tab = new_tab;
   if (old_tab)
     {
       assoc->hash_num = hash_num;
       for (i = 0; i < hash_size[hash_num-1]; i++)
        {
-         struct _mu_assoc_elem *elt = __ASSOC_ELEM (assoc, old_tab, i);
-         if (elt->name)
+         if (old_tab[i])
            {
              int tmp;
-             struct _mu_assoc_elem *newp;
-             
-             int rc = assoc_lookup_or_install (&newp, assoc, elt->name, &tmp);
+             unsigned slot;
+             int rc = assoc_find_slot (assoc, old_tab[i]->name,
+                                       &tmp, &slot);
              if (rc)
                return rc;
-             newp->name = elt->name;
-             memcpy(newp->data, elt->data, assoc->elsize);
+             assoc->tab[slot] = old_tab[i];
            }
        }
       free (old_tab);
@@ -136,45 +146,47 @@ assoc_rehash (mu_assoc_t assoc)
 }
 
 static void
-assoc_free_elem (mu_assoc_t assoc, struct _mu_assoc_elem *elem)
+assoc_free_elem (mu_assoc_t assoc, unsigned idx)
 {
-  if (assoc->free)
-    assoc->free (elem->data);
-  if (!(assoc->flags & MU_ASSOC_COPY_KEY))
-    free (elem->name);
+  if (assoc->tab[idx])
+    {
+      assoc_elem_unlink (assoc, idx);
+      if (assoc->free)
+       assoc->free (assoc->tab[idx]->data);
+      if (!(assoc->flags & MU_ASSOC_COPY_KEY))
+       free (assoc->tab[idx]->name);
+      assoc->tab[idx] = NULL;
+    }
 }
 
 static int
-assoc_remove (mu_assoc_t assoc, struct _mu_assoc_elem *elem)
+assoc_remove (mu_assoc_t assoc, unsigned idx)
 {
   unsigned int i, j, r;
 
-  if (!(ASSOC_ELEM (assoc, 0) <= elem
-       && elem < ASSOC_ELEM (assoc, hash_size[assoc->hash_num])))
+  if (!(idx < hash_size[assoc->hash_num]))
     return EINVAL;
 
-  assoc_free_elem (assoc, elem);
+  mu_iterator_delitem (assoc->itr, assoc->tab[idx]);
+  assoc_free_elem (assoc, idx);
   
-  for (i = ASSOC_ELEM_INDEX (assoc, elem);;)
+  for (i = idx;;)
     {
-      struct _mu_assoc_elem *p = ASSOC_ELEM (assoc, i);
-      p->name = NULL;
+      assoc->tab[i] = NULL;
       j = i;
 
       do
        {
          if (++i >= hash_size[assoc->hash_num])
            i = 0;
-         p = ASSOC_ELEM (assoc, i);
-         if (!p->name)
+         if (!assoc->tab[i])
            return 0;
-         r = hash (p->name, assoc->hash_num);
+         r = hash (assoc->tab[i]->name, assoc->hash_num);
        }
       while ((j < r && r <= i) || (i < j && j < r) || (r <= i && i < j));
 
       if (j != i)
-       memcpy (ASSOC_ELEM (assoc, j), ASSOC_ELEM (assoc, i),
-               assoc->elsize);
+       assoc->tab[j] = assoc->tab[i];
     }
   return 0;
 }
@@ -183,8 +195,8 @@ assoc_remove (mu_assoc_t assoc, struct _mu_assoc_elem *elem)
                              mu_c_strcasecmp(a,b) : strcmp(a,b))
 
 static int
-assoc_lookup_or_install (struct _mu_assoc_elem **elp,
-                        mu_assoc_t assoc, const char *name, int *install)
+assoc_find_slot (mu_assoc_t assoc, const char *name,
+                int *install, unsigned *slot)
 {
   int rc;
   unsigned i, pos;
@@ -204,13 +216,13 @@ assoc_lookup_or_install (struct _mu_assoc_elem **elp,
 
   pos = hash (name, assoc->hash_num);
 
-  for (i = pos; (elem = ASSOC_ELEM (assoc, i))->name;)
+  for (i = pos; (elem = assoc->tab[i]);)
     {
       if (name_cmp (assoc, elem->name, name) == 0)
        {
          if (install)
            *install = 0;
-         *elp = elem;
+         *slot = i;
          return 0;
        }
       
@@ -223,35 +235,26 @@ assoc_lookup_or_install (struct _mu_assoc_elem **elp,
   if (!install)
     return MU_ERR_NOENT;
   
-  if (elem->name == NULL)
+  if (!elem)
     {
+      *slot = i;
       *install = 1;
-      if (assoc->flags & MU_ASSOC_COPY_KEY)
-       elem->name = (char *) name;
-      else
-       {
-         elem->name = strdup (name);
-         if (!elem->name)
-           return ENOMEM;
-       }
-      *elp = elem;
       return 0; 
     }
 
   if ((rc = assoc_rehash (assoc)) != 0)
     return rc;
 
-  return assoc_lookup_or_install (elp, assoc, name, install);
+  return assoc_find_slot (assoc, name, install, slot);
 }
 
 int
-mu_assoc_create (mu_assoc_t *passoc, size_t elsize, int flags)
+mu_assoc_create (mu_assoc_t *passoc, int flags)
 {
   mu_assoc_t assoc = calloc (1, sizeof (*assoc));
   if (!assoc)
     return ENOMEM;
   assoc->flags = flags;
-  assoc->elsize = elsize;
   *passoc = assoc;
   return 0;
 }
@@ -266,14 +269,7 @@ mu_assoc_clear (mu_assoc_t assoc)
 
   hs = hash_size[assoc->hash_num];
   for (i = 0; i < hs; i++)
-    {
-      struct _mu_assoc_elem *elem = ASSOC_ELEM (assoc, i);
-      if (elem->name)
-       {
-         assoc_free_elem (assoc, elem);
-         elem->name = NULL;
-       }
-    }
+    assoc_free_elem (assoc, i);
 }
 
 void
@@ -290,7 +286,7 @@ mu_assoc_destroy (mu_assoc_t *passoc)
 }
 
 int
-mu_assoc_set_free (mu_assoc_t assoc, mu_assoc_free_fn fn)
+mu_assoc_set_destroy_item (mu_assoc_t assoc, mu_deallocator_t fn)
 {
   if (!assoc)
     return EINVAL;
@@ -298,18 +294,37 @@ mu_assoc_set_free (mu_assoc_t assoc, mu_assoc_free_fn fn)
   return 0;
 }
 
-void *
-mu_assoc_ref (mu_assoc_t assoc, const char *name)
+int
+mu_assoc_lookup (mu_assoc_t assoc, const char *name, void *dataptr)
 {
   int rc;
-  static struct _mu_assoc_elem *elp;
+  unsigned idx;
+  
+  if (!assoc || !name)
+    return EINVAL;
 
+  rc = assoc_find_slot (assoc, name, NULL, &idx);
+  if (rc == 0)
+    {
+      if (dataptr)
+       *(void**)dataptr = assoc->tab[idx]->data;
+    }
+  return rc;
+}
+
+
+void *
+mu_assoc_get (mu_assoc_t assoc, const char *name)
+{
+  int rc;
+  unsigned idx;
+  
   if (!assoc || !name)
     return NULL;
-  
-  rc = assoc_lookup_or_install (&elp, assoc, name, NULL);
+
+  rc = assoc_find_slot (assoc, name, NULL, &idx);
   if (rc == 0)
-    return elp->data;
+    return assoc->tab[idx]->data;
   return NULL;
 }
 
@@ -318,34 +333,98 @@ mu_assoc_install (mu_assoc_t assoc, const char *name, 
void *value)
 {
   int rc;
   int inst;
-  static struct _mu_assoc_elem *elp;
-
+  unsigned idx;
+  struct _mu_assoc_elem *elem;
+  
   if (!assoc || !name)
     return EINVAL;
 
-  rc = assoc_lookup_or_install (&elp, assoc, name, &inst);
+  rc = assoc_find_slot (assoc, name, &inst, &idx);
   if (rc)
     return rc;
   if (!inst)
     return MU_ERR_EXISTS;
-  memcpy (elp->data, value, assoc->elsize);
+
+  elem = malloc (sizeof *elem);
+  if (!elem)
+    return errno;
+      
+  if (assoc->flags & MU_ASSOC_COPY_KEY)
+    elem->name = (char *) name;
+  else
+    {
+      elem->name = strdup (name);
+      if (!elem->name)
+       {
+         int rc = errno;
+         free (elem);
+         return rc;
+       }
+    }
+  elem->data = value;
+  assoc->tab[idx] = elem;
+  assoc_elem_link (assoc, idx);
   return 0;
 }
+
+int
+mu_assoc_lookup_ref (mu_assoc_t assoc, const char *name, void *dataptr)
+{
+  int rc;
+  unsigned idx;
+  
+  if (!assoc || !name)
+    return EINVAL;
+
+  rc = assoc_find_slot (assoc, name, NULL, &idx);
+  if (rc == 0)
+    {
+      if (dataptr)
+       *(void**)dataptr = &assoc->tab[idx]->data;
+    }
+  return rc;
+}
 
 int
-mu_assoc_ref_install (mu_assoc_t assoc, const char *name, void **pval)
+mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval)
 {
   int rc;
   int inst;
-  static struct _mu_assoc_elem *elp;
+  unsigned idx;
 
   if (!assoc || !name)
     return EINVAL;
-
-  rc = assoc_lookup_or_install (&elp, assoc, name, &inst);
+  
+  rc = assoc_find_slot (assoc, name, &inst, &idx);
   if (rc)
     return rc;
-  *pval = elp->data;
+
+  if (inst)
+    {
+      struct _mu_assoc_elem *elem;
+      
+      elem = malloc (sizeof *elem);
+      if (!elem)
+       return errno;
+      
+      if (assoc->flags & MU_ASSOC_COPY_KEY)
+       elem->name = (char *) name;
+      else
+       {
+         elem->name = strdup (name);
+         if (!elem->name)
+           {
+             int rc = errno;
+             free (elem);
+             return rc;
+           }
+       }
+      elem->data = NULL;
+      assoc->tab[idx] = elem;
+      assoc_elem_link (assoc, idx);
+    }
+  
+  *(void**)pval = &assoc->tab[idx]->data;
   return inst ? 0 : MU_ERR_EXISTS;
 }  
 
@@ -353,71 +432,109 @@ int
 mu_assoc_remove (mu_assoc_t assoc, const char *name)
 {
   int rc;
-  static struct _mu_assoc_elem *elem;
+  unsigned idx;
 
   if (!assoc || !name)
     return EINVAL;
-  rc = assoc_lookup_or_install (&elem, assoc, name, NULL);
+  rc = assoc_find_slot (assoc, name, NULL, &idx);
   if (rc)
     return rc;
-  return assoc_remove (assoc, elem);
+  return assoc_remove (assoc, idx);
 }
-
-#define OFFSET(s,f) (size_t)(&((s*)0)->f)
-
-int
-mu_assoc_remove_ref (mu_assoc_t assoc, void *data)
-{
-  struct _mu_assoc_elem *elem;
-
-  elem = (struct _mu_assoc_elem *) ((char*)data -
-                                   OFFSET(struct _mu_assoc_elem, data));
-  return assoc_remove (assoc, elem);
-}
-
 
 /* Iterator interface */
 
 struct assoc_iterator
 {
   mu_assoc_t assoc;
-  unsigned start;
-  unsigned index;
+  struct _mu_assoc_elem *elem;
+  int backwards; /* true if iterating backwards */
 };
 
 static int
-first (void *owner)
+itrctl (void *owner, enum mu_itrctl_req req, void *arg)
 {
   struct assoc_iterator *itr = owner;
   mu_assoc_t assoc = itr->assoc;
-  unsigned hash_max = hash_size[assoc->hash_num];
-  unsigned i;
 
-  if (assoc->tab)
+  switch (req)
     {
-      for (i = 0; i < hash_max; i++)
-        if ((ASSOC_ELEM (assoc, i))->name)
-         break;
+    case mu_itrctl_tell:
+      /* Return current position in the object */
+      {
+       size_t n = 0;
+       struct _mu_assoc_elem *elem;
+
+       for (elem = itr->elem; elem; elem = elem->prev)
+         n++;
+       *(size_t*)arg = n;
+      }
+      break;
+
+    case mu_itrctl_delete:
+    case mu_itrctl_delete_nd:
+      /* Delete current element */
+      if (itr->elem)
+       {
+         unsigned i;
+
+         for (i = 0; i < hash_size[assoc->hash_num]; i++)
+           {
+             if (assoc->tab[i] == itr->elem)
+               {
+                 if (req == mu_itrctl_delete_nd)
+                   assoc->tab[i]->data = NULL;
+                 assoc_remove (assoc, i);
+                 return 0;
+               }
+           }
+       }
+      return MU_ERR_NOENT;
+
+    case mu_itrctl_replace:
+    case mu_itrctl_replace_nd:
+      /* Replace current element */
+      if (itr->elem == NULL)
+       return MU_ERR_NOENT;
+      if (req == mu_itrctl_replace && assoc->free)
+       assoc->free (itr->elem->data);
+      itr->elem->data = arg;
+      break;
+      
+    case mu_itrctl_qry_direction:
+      if (!arg)
+       return EINVAL;
+      else
+       *(int*)arg = itr->backwards;
+      break;
+
+    case mu_itrctl_set_direction:
+      if (!arg)
+       return EINVAL;
+      else
+       itr->backwards = !!*(int*)arg;
+      break;
+      
+    default:
+      return ENOSYS;
     }
-  else
-    i = hash_max;
-  itr->index = i;
   return 0;
 }
 
 static int
-next (void *owner)
+first (void *owner)
 {
   struct assoc_iterator *itr = owner;
   mu_assoc_t assoc = itr->assoc;
-  unsigned hash_max = hash_size[assoc->hash_num];
-  unsigned i;
-  
-  for (i = itr->index + 1; i < hash_max; i++)
-    if ((ASSOC_ELEM (assoc, i))->name)
-      break;
+  itr->elem = itr->backwards ? assoc->tail : assoc->head;
+  return 0;
+}
 
-  itr->index = i;
+static int
+next (void *owner)
+{
+  struct assoc_iterator *itr = owner;
+  itr->elem = itr->backwards ? itr->elem->prev : itr->elem->next;
   return 0;
 }
 
@@ -425,14 +542,12 @@ static int
 getitem (void *owner, void **pret, const void **pkey)
 {
   struct assoc_iterator *itr = owner;
-  struct _mu_assoc_elem *elem;
 
-  if (itr->index >= hash_size[itr->assoc->hash_num])
+  if (!itr->elem)
     return EINVAL;
-  elem = ASSOC_ELEM (itr->assoc, itr->index);
-  *pret = elem->data;
+  *pret = itr->elem->data;
   if (pkey)
-    *pkey = elem->name;
+    *pkey = itr->elem->name;
   return 0;
 }
 
@@ -440,7 +555,7 @@ static int
 finished_p (void *owner)
 {
   struct assoc_iterator *itr = owner;
-  return itr->index >= hash_size[itr->assoc->hash_num];
+  return itr->elem == NULL;
 }
 
 static int
@@ -456,10 +571,7 @@ static int
 delitem (void *owner, void *item)
 {
   struct assoc_iterator *itr = owner;
-  mu_assoc_t assoc = itr->assoc;
-  struct _mu_assoc_elem *elem = ASSOC_ELEM (assoc, itr->index);
-  
-  return elem == item ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING;
+  return itr->elem == item ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING;
 }
 
 static int
@@ -486,7 +598,7 @@ mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t 
*piterator)
   if (!itr)
     return ENOMEM;
   itr->assoc = assoc;
-  itr->index = 0;
+  itr->elem = NULL;
 
   status = mu_iterator_create (&iterator, itr);
   if (status)
@@ -502,6 +614,7 @@ mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t 
*piterator)
   mu_iterator_set_delitem (iterator, delitem);
   mu_iterator_set_destroy (iterator, destroy);
   mu_iterator_set_dup (iterator, assoc_data_dup);
+  mu_iterator_set_itrctl (iterator, itrctl);
   
   mu_iterator_attach (&assoc->itr, iterator);
 
diff --git a/libmailutils/base/mutil.c b/libmailutils/base/mutil.c
index be5821a..8796b66 100644
--- a/libmailutils/base/mutil.c
+++ b/libmailutils/base/mutil.c
@@ -29,6 +29,7 @@
 #include <mailutils/errno.h>
 #include <mailutils/nls.h>
 #include <mailutils/assoc.h>
+#include <mailutils/list.h>
 #include <mailutils/stream.h>
 #include <mailutils/sql.h>
 
@@ -56,12 +57,6 @@ mu_mh_delim (const char *str)
   return str[0] == '\n';
 }
 
-static void
-assoc_str_free (void *data)
-{
-  free (data);
-}
-
 int
 mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab, int *perr)
 {
@@ -91,10 +86,10 @@ mutil_parse_field_map (const char *map, mu_assoc_t 
*passoc_tab, int *perr)
        }
       if (!assoc_tab)
        {
-         rc = mu_assoc_create (&assoc_tab, sizeof(char*), 0);
+         rc = mu_assoc_create (&assoc_tab, 0);
          if (rc)
            break;
-         mu_assoc_set_free (assoc_tab, assoc_str_free);
+         mu_assoc_set_destroy_item (assoc_tab, mu_list_free_item);
          *passoc_tab = assoc_tab;
        }
       *p++ = 0;
@@ -104,7 +99,7 @@ mutil_parse_field_map (const char *map, mu_assoc_t 
*passoc_tab, int *perr)
          rc = errno;
          break;
        }
-      rc = mu_assoc_install (assoc_tab, tok, &pptr);
+      rc = mu_assoc_install (assoc_tab, tok, pptr);
       if (rc)
        {
          free (p);
diff --git a/libmailutils/base/rfc2047.c b/libmailutils/base/rfc2047.c
index b25e654..02560f8 100644
--- a/libmailutils/base/rfc2047.c
+++ b/libmailutils/base/rfc2047.c
@@ -234,18 +234,23 @@ _rfc2047_decode_param (const char *tocode, const char 
*input,
 
 int
 mu_rfc2047_decode_param (const char *tocode, const char *input,
-                        struct mu_mime_param *param)
+                        struct mu_mime_param **param_ptr)
 {
   int rc;
-  struct mu_mime_param tmp;
+  struct mu_mime_param *p;
 
   if (!input)
     return EINVAL;
-  if (!param)
+  if (!param_ptr)
     return MU_ERR_OUT_PTR_NULL;
-  rc = _rfc2047_decode_param (tocode, input, &tmp);
+  p = malloc (sizeof (*p));
+  if (!p)
+    return errno;
+  rc = _rfc2047_decode_param (tocode, input, p);
   if (rc == 0)
-    *param = tmp;
+    *param_ptr = p;
+  else
+    mu_mime_param_free (p);
   return rc;
 }
 
diff --git a/libmailutils/cfg/driver.c b/libmailutils/cfg/driver.c
index 4f0e875..1c897af 100644
--- a/libmailutils/cfg/driver.c
+++ b/libmailutils/cfg/driver.c
@@ -46,8 +46,7 @@ static void
 alloc_section_tab ()
 {
   if (!section_tab)
-    mu_assoc_create (&section_tab, sizeof (struct mu_cfg_cont **),
-                    MU_ASSOC_COPY_KEY);
+    mu_assoc_create (&section_tab, MU_ASSOC_COPY_KEY);
 }
 
 int
@@ -56,7 +55,7 @@ mu_create_canned_section (char *name, struct mu_cfg_section 
**psection)
   int rc;
   struct mu_cfg_cont **pcont;
   alloc_section_tab ();
-  rc = mu_assoc_ref_install (section_tab, name, (void **)&pcont);
+  rc = mu_assoc_install_ref (section_tab, name, &pcont);
   if (rc == 0)
     {
       mu_config_create_container (pcont, mu_cfg_cont_section);
@@ -74,7 +73,7 @@ mu_create_canned_param (char *name, struct mu_cfg_param 
**pparam)
   int rc;
   struct mu_cfg_cont **pcont;
   alloc_section_tab ();
-  rc = mu_assoc_ref_install (section_tab, name, (void **)&pcont);
+  rc = mu_assoc_install_ref (section_tab, name, &pcont);
   if (rc == 0)
     {
       mu_config_create_container (pcont, mu_cfg_cont_param);
@@ -89,8 +88,7 @@ mu_create_canned_param (char *name, struct mu_cfg_param 
**pparam)
 struct mu_cfg_cont *
 mu_get_canned_container (const char *name)
 {
-  struct mu_cfg_cont **pcont = mu_assoc_ref (section_tab, name);
-  return pcont ? *pcont : NULL;
+  return mu_assoc_get (section_tab, name);
 }
 
 
@@ -615,19 +613,13 @@ parse_mapping (void *item, void *data)
   val = mu_strdup (str + len + 1);
   if (!val)
     return ENOMEM;
-  clos->err = mu_assoc_install (clos->assoc, key, &val);
+  clos->err = mu_assoc_install (clos->assoc, key, val);
   free (key);
   if (clos->err)
     return 1;
   return 0;
 }
 
-static void
-assoc_str_free (void *data)
-{
-  free (data);
-}
-
 int
 mu_cfg_field_map (struct mu_config_value const *val, mu_assoc_t *passoc,
                  char **err_term)
@@ -636,10 +628,10 @@ mu_cfg_field_map (struct mu_config_value const *val, 
mu_assoc_t *passoc,
   struct mapping_closure clos;
   mu_list_t list = NULL;
   
-  rc = mu_assoc_create (&clos.assoc, sizeof(char*), 0);
+  rc = mu_assoc_create (&clos.assoc, 0);
   if (rc)
     return rc;
-  mu_assoc_set_free (clos.assoc, assoc_str_free);
+  mu_assoc_set_destroy_item (clos.assoc, mu_list_free_item);
   clos.err_term = NULL;
   
   switch (val->type)
diff --git a/libmailutils/mime/mimehdr.c b/libmailutils/mime/mimehdr.c
index 73accf7..c015b6a 100644
--- a/libmailutils/mime/mimehdr.c
+++ b/libmailutils/mime/mimehdr.c
@@ -45,12 +45,13 @@
                                      info */
 
 /* Free members of struct mu_mime_param, but do not free it itself. */
-static void
-_mu_mime_param_free (struct mu_mime_param *p)
+void
+mu_mime_param_free (struct mu_mime_param *p)
 {
   free (p->lang);
   free (p->cset);
   free (p->value);
+  free (p);
 }
 
 /* Treat ITEM as a pointer to struct mu_mime_param and reclaim all
@@ -60,7 +61,7 @@ _mu_mime_param_free (struct mu_mime_param *p)
 static void
 _mu_mime_param_free_item (void *item)
 {
-  _mu_mime_param_free (item);
+  mu_mime_param_free (item);
 }
 
 /* Recode a string between two charsets.
@@ -153,31 +154,38 @@ flush_param (struct param_continuation *cont, mu_assoc_t 
assoc, int subset,
             const char *outcharset)
 {
   int rc;
-  struct mu_mime_param param, *param_slot = NULL;
+  struct mu_mime_param *param, **param_slot;
   mu_off_t size;
   
   if (subset)
     {
-      param_slot = mu_assoc_ref (assoc, cont->param_name);
-      if (!param_slot)
+      rc = mu_assoc_lookup_ref (assoc, cont->param_name, &param_slot);
+      if (rc)
        return 0;
     }
   
+  param = calloc (1, sizeof *param);
+  if (!param)
+    return errno;
+  
   if (cont->param_lang)
     {
-      param.lang = strdup (cont->param_lang);
-      if (!param.lang)
-       return ENOMEM;
+      param->lang = strdup (cont->param_lang);
+      if (!param->lang)
+       {
+         mu_mime_param_free (param);
+         return ENOMEM;
+       }
     }
   else
-    param.lang = NULL;
+    param->lang = NULL;
 
   if (outcharset || cont->param_cset)
     {
-      param.cset = strdup (outcharset ? outcharset : cont->param_cset);
-      if (!param.cset)
+      param->cset = strdup (outcharset ? outcharset : cont->param_cset);
+      if (!param->cset)
        {
-         free (param.lang);
+         mu_mime_param_free (param);
          return ENOMEM;
        }
     }
@@ -185,23 +193,25 @@ flush_param (struct param_continuation *cont, mu_assoc_t 
assoc, int subset,
   rc = mu_stream_size (cont->param_value, &size);
   if (rc == 0)
     {
-      param.value = malloc (size + 1);
-      if (!param.value)
-       rc = ENOMEM;
+      param->value = malloc (size + 1);
+      if (!param->value)
+       {
+         mu_mime_param_free (param);
+         rc = ENOMEM;
+       }
     }
 
   if (rc == 0)
     {
       rc = mu_stream_seek (cont->param_value, 0, MU_SEEK_SET, NULL);
       if (rc == 0)
-       rc = mu_stream_read (cont->param_value, param.value, size, NULL);
-      param.value[size] = 0;
+       rc = mu_stream_read (cont->param_value, param->value, size, NULL);
+      param->value[size] = 0;
     }
   
   if (rc)
     {
-      free (param.lang);
-      free (param.cset);
+      mu_mime_param_free (param);
       return rc;
     }
 
@@ -209,26 +219,25 @@ flush_param (struct param_continuation *cont, mu_assoc_t 
assoc, int subset,
       mu_c_strcasecmp (cont->param_cset, outcharset))
     {
       char *tmp;
-      rc = _recode_string (param.value, cont->param_cset, outcharset, &tmp);
-      free (param.value);
+      rc = _recode_string (param->value, cont->param_cset, outcharset, &tmp);
+      free (param->value);
       if (rc)
        {
-         free (param.lang);
-         free (param.cset);
+         mu_mime_param_free (param);
          return rc;
        }
-      param.value = tmp;
+      param->value = tmp;
     }
        
-  if (param_slot)
+  if (subset)
     {
       *param_slot = param;
     }
   else
     {
-      rc = mu_assoc_install (assoc, cont->param_name, &param);
+      rc = mu_assoc_install (assoc, cont->param_name, param);
       if (rc)
-       _mu_mime_param_free (&param);
+       mu_mime_param_free (param);
     }
   
   return rc;
@@ -239,10 +248,9 @@ int
 mu_mime_param_assoc_create (mu_assoc_t *paramtab)
 {
   mu_assoc_t assoc;
-  int rc = mu_assoc_create (&assoc, sizeof (struct mu_mime_param),
-                           MU_ASSOC_ICASE);
+  int rc = mu_assoc_create (&assoc, MU_ASSOC_ICASE);
   if (rc == 0)
-    mu_assoc_set_free (assoc, _mu_mime_param_free_item);
+    mu_assoc_set_destroy_item (assoc, _mu_mime_param_free_item);
   *paramtab = assoc;
   return rc;
 }
@@ -251,20 +259,7 @@ mu_mime_param_assoc_create (mu_assoc_t *paramtab)
 int
 mu_mime_param_assoc_add (mu_assoc_t assoc, const char *name)
 {
-  struct mu_mime_param param;
-
-  memset (&param, 0, sizeof param);
-  return mu_assoc_install (assoc, name, &param);
-}
-
-/* See FIXME near the end of _mime_header_parse, below. */
-static int
-_remove_entry (void *item, void *data)
-{
-  struct mu_mime_param *p = item;
-  mu_assoc_t assoc = data;
-  mu_assoc_remove_ref (assoc, p);
-  return 0;
+  return mu_assoc_install (assoc, name, NULL);
 }
 
 /* A working horse of this module.  Parses input string, which should
@@ -331,7 +326,7 @@ _mime_header_parse (const char *text, char **pvalue,
       char *p;
       char *decoded;
       int flags = 0;
-      struct mu_mime_param param;
+      struct mu_mime_param *param;
 
       key = ws.ws_wordv[i];
       if (key[0] == ';')
@@ -484,19 +479,20 @@ _mime_header_parse (const char *text, char **pvalue,
        }
       else
        {
+         struct mu_mime_param *param;
          rc = mu_rfc2047_decode_param (outcharset, val, &param);
          if (rc)
            return rc;
-         cset = csetp = param.cset;
-         lang = langp = param.lang;
-         decoded = param.value;
+         cset = csetp = param->cset;
+         lang = langp = param->lang;
+         decoded = param->value;
+         free (param);
        }
       val = decoded;
       
       if (flags & MU_MIMEHDR_MULTILINE)
        {
-         rc = mu_stream_write (cont.param_value, val, strlen (val),
-                               NULL);
+         rc = mu_stream_write (cont.param_value, val, strlen (val), NULL);
          free (decoded);
          free (csetp);
          free (langp);
@@ -505,25 +501,30 @@ _mime_header_parse (const char *text, char **pvalue,
          continue;
        }
 
-      memset (&param, 0, sizeof (param));
-      if (lang)
+      param = calloc (1, sizeof (*param));
+      if (!param)
+       rc = ENOMEM;
+      else
        {
-         param.lang = strdup (lang);
-         if (!param.lang)
-           rc = ENOMEM;
-         else
+         if (lang)
            {
-             param.cset = strdup (cset);
-             if (!param.cset)
+             param->lang = strdup (lang);
+             if (!param->lang)
+               rc = ENOMEM;
+             else
                {
-                 free (param.lang);
-                 rc = ENOMEM;
+                 param->cset = strdup (cset);
+                 if (!param->cset)
+                   {
+                     free (param->lang);
+                     rc = ENOMEM;
+                   }
                }
            }
+         
+         free (csetp);
+         free (langp);
        }
-
-      free (csetp);
-      free (langp);
       
       if (rc)
        {
@@ -531,27 +532,29 @@ _mime_header_parse (const char *text, char **pvalue,
          break;
        }
       
-      param.value = strdup (val);
+      param->value = strdup (val);
       free (decoded);
-      if (!param.value)
+      if (!param->value)
        {
-         _mu_mime_param_free (&param);
+         mu_mime_param_free (param);
          rc = ENOMEM;
          break;
        }
 
       if (subset)
        {
-         struct mu_mime_param *p = mu_assoc_ref (assoc, key);
-         if (p)
+         struct mu_mime_param **p;
+         if (mu_assoc_lookup_ref (assoc, key, &p) == 0)
            *p = param;
+         else
+           mu_mime_param_free (param);
        }
       else
        {
-         rc = mu_assoc_install (assoc, key, &param);
+         rc = mu_assoc_install (assoc, key, param);
          if (rc)
            {
-             _mu_mime_param_free (&param);
+             mu_mime_param_free (param);
              break;
            }
        }
@@ -574,12 +577,7 @@ _mime_header_parse (const char *text, char **pvalue,
 
   if (subset)
     {
-      /* Eliminate empty elements.
-        
-        FIXME: What I wanted to do initially is commented out, because
-        unfortunately iterator_ctl is not defined for assoc tables...
-      */
-#if 0
+      /* Eliminate empty elements. */
       mu_iterator_t itr;
 
       rc = mu_assoc_get_iterator (assoc, &itr);
@@ -592,38 +590,11 @@ _mime_header_parse (const char *text, char **pvalue,
              struct mu_mime_param *p;
              
              mu_iterator_current_kv (itr, (const void **)&name, (void**)&p);
-             if (!p->value)
+             if (!p)
                mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
            }
          mu_iterator_destroy (&itr);
        }
-#else
-  /* ... Instead, the following kludgy approach is taken: */
-      mu_iterator_t itr;
-      mu_list_t elist;
-
-      rc = mu_list_create (&elist);
-      if (rc)
-       return rc;
-      rc = mu_assoc_get_iterator (assoc, &itr);
-      if (rc == 0)
-       {
-         for (mu_iterator_first (itr); rc == 0 && !mu_iterator_is_done (itr);
-              mu_iterator_next (itr))
-           {
-             const char *name;
-             struct mu_mime_param *p;
-             
-             mu_iterator_current_kv (itr, (const void **)&name, (void**)&p);
-             if (!p->value)
-               rc = mu_list_append (elist, p);
-           }
-         mu_iterator_destroy (&itr);
-       }
-      if (rc == 0)
-       mu_list_foreach (elist, _remove_entry, assoc);
-      mu_list_destroy (&elist);
-#endif
     }
   
   return rc;
@@ -782,7 +753,7 @@ mu_mimehdr_aget_decoded_param (const char *str, const char 
*name,
          rc = mu_mime_header_parse_subset (str, charset, NULL, assoc);
          if (rc == 0)
            {
-             struct mu_mime_param *param = mu_assoc_ref (assoc, name);
+             struct mu_mime_param *param = mu_assoc_get (assoc, name);
              if (!param)
                rc = MU_ERR_NOENT;
              else
@@ -852,7 +823,7 @@ _get_attachment_name (mu_message_t msg, const char *charset,
            {
              struct mu_mime_param *param;
              if (mu_c_strcasecmp (disp, "attachment") == 0 &&
-                 (param = mu_assoc_ref (assoc, "filename")))
+                 (param = mu_assoc_get (assoc, "filename")))
                {
                  *pbuf = param->value;
                  if (psz)
@@ -893,7 +864,7 @@ _get_attachment_name (mu_message_t msg, const char *charset,
          if (ret == 0)
            {
              struct mu_mime_param *param;
-             if ((param = mu_assoc_ref (assoc, "name")))
+             if ((param = mu_assoc_get (assoc, "name")))
                {
                  *pbuf = param->value;
                  if (psz)
diff --git a/libmailutils/property/assocprop.c 
b/libmailutils/property/assocprop.c
index 19a419e..1f688f3 100644
--- a/libmailutils/property/assocprop.c
+++ b/libmailutils/property/assocprop.c
@@ -25,13 +25,9 @@
 #include <mailutils/assoc.h>
 #include <mailutils/stream.h>
 #include <mailutils/iterator.h>
+#include <mailutils/list.h>
 #include <stdlib.h>
 
-struct property_item
-{
-  char *value;
-};
-
 static void
 _assoc_prop_done (struct _mu_property *prop)
 {
@@ -46,13 +42,13 @@ _assoc_prop_getval (struct _mu_property *prop,
                    const char *key, const char **pval)
 {
   mu_assoc_t assoc = prop->_prop_data;
-  struct property_item *item;
+  char *item;
 
-  item = mu_assoc_ref (assoc, key);
+  item = mu_assoc_get (assoc, key);
   if (item == NULL)
     return MU_ERR_NOENT;
   if (pval)
-    *pval = item->value;
+    *pval = item;
   return 0;
 
 }
@@ -62,14 +58,14 @@ _assoc_prop_setval (struct _mu_property *prop, const char 
*key,
                       const char *val, int overwrite)
 {
   mu_assoc_t assoc = prop->_prop_data;
-  struct property_item *item;
+  char **item;
   int rc;
 
-  rc = mu_assoc_ref_install (assoc, key, (void **)&item);
+  rc = mu_assoc_install_ref (assoc, key, &item);
   if (rc == 0)
     {
-      item->value = strdup (val);
-      if (!item->value)
+      *item = strdup (val);
+      if (!*item)
        {
          mu_assoc_remove (assoc, key);
          return ENOMEM;
@@ -80,8 +76,8 @@ _assoc_prop_setval (struct _mu_property *prop, const char 
*key,
       char *newval = strdup (val);
       if (!newval)
        return ENOMEM;
-      free (item->value);
-      item->value = newval;
+      free (*item);
+      *item = newval;
     }
   else
     return rc;
@@ -105,13 +101,6 @@ _assoc_prop_clear (struct _mu_property *prop)
 }
 
 
-static void *
-_assoc_prop_dataptr (void *in)
-{
-  struct property_item *item = in;
-  return item->value;
-}
-
 static int
 _assoc_prop_getitr (struct _mu_property *prop, mu_iterator_t *pitr)
 {
@@ -121,20 +110,11 @@ _assoc_prop_getitr (struct _mu_property *prop, 
mu_iterator_t *pitr)
   rc = mu_assoc_get_iterator ((mu_assoc_t)prop->_prop_data, &itr);
   if (rc)
     return rc;
-  mu_iterator_set_dataptr (itr, _assoc_prop_dataptr);
   *pitr = itr;
   return 0;
 }
 
 
-static void
-prop_free_value (void *data)
-{
-  struct property_item *item = data;
-  free (item->value);
-}
-
-
 static int
 _assoc_prop_fill (struct _mu_property *prop)
 {
@@ -201,10 +181,10 @@ mu_assoc_property_init (struct _mu_property *prop)
   mu_assoc_t assoc;
   int rc;
   
-  rc = mu_assoc_create (&assoc, sizeof (struct property_item), 0);
+  rc = mu_assoc_create (&assoc, 0);
   if (rc)
     return rc;
-  mu_assoc_set_free (assoc, prop_free_value);
+  mu_assoc_set_destroy_item (assoc, mu_list_free_item);
   prop->_prop_data = assoc;
 
   prop->_prop_done = _assoc_prop_done;
diff --git a/libmu_sieve/environment.c b/libmu_sieve/environment.c
index 9de4862..bc6e6cb 100644
--- a/libmu_sieve/environment.c
+++ b/libmu_sieve/environment.c
@@ -179,10 +179,10 @@ mu_sieve_get_environ (mu_sieve_machine_t mach, char const 
*name, char **retval)
   if (!mach->exenv)
     return MU_ERR_NOENT;
 
-  p = mu_assoc_ref (mach->exenv, name);
+  p = mu_assoc_get (mach->exenv, name);
   if (p)
     {
-      *retval = strdup (*(char**)p);
+      *retval = strdup (p);
       if (!*retval)
        return errno;
     }
@@ -204,11 +204,11 @@ mu_sieve_set_environ (mu_sieve_machine_t mach, char const 
*name,
       
       if (!mach->exenv)
        {
-          int rc = mu_assoc_create (&mach->exenv, sizeof (char *), 0);
+          int rc = mu_assoc_create (&mach->exenv, 0);
          if (rc)
            return rc;
        }
-      rc = mu_assoc_ref_install (mach->exenv, name, (void **) &pptr);
+      rc = mu_assoc_install_ref (mach->exenv, name, &pptr);
       if (rc == 0 || rc == MU_ERR_EXISTS)
        {
          char *copy = strdup (value);
diff --git a/libmu_sieve/variables.c b/libmu_sieve/variables.c
index 6f58e54..da87904 100644
--- a/libmu_sieve/variables.c
+++ b/libmu_sieve/variables.c
@@ -166,7 +166,7 @@ sieve_action_set (mu_sieve_machine_t mach)
   size_t i;
   char *name;
   char *value;
-  struct sieve_variable *vptr;
+  struct sieve_variable *var, **vptr;
   int rc;
   
   mu_sieve_get_arg (mach, 0, SVT_STRING, &name);
@@ -181,21 +181,29 @@ sieve_action_set (mu_sieve_machine_t mach)
       value = str;
     }
 
-  rc = mu_assoc_ref_install (mach->vartab, name, (void **)&vptr);
+  rc = mu_assoc_install_ref (mach->vartab, name, &vptr);
   switch (rc)
     {
     case 0:
+      var = malloc (sizeof (*var));
+      if (!var)
+       {
+         mu_sieve_error (mach, "%s", mu_strerror (errno));
+         mu_sieve_abort (mach);
+       }
+      *vptr = var;
       break;
 
     case MU_ERR_EXISTS:
-      mu_sieve_free (mach, vptr->value);
+      var = *vptr;
+      mu_sieve_free (mach, var->value);
       break;
 
     default:
       mu_sieve_error (mach, "mu_assoc_ref_install: %s", mu_strerror (rc));
       mu_sieve_abort (mach);
     }
-  vptr->value = value;
+  var->value = value;
   return 0;
 }  
 
@@ -354,7 +362,7 @@ mu_i_sv_expand_variables (char const *input, size_t len,
       memcpy (name, input, len);
       name[len] = 0;
 
-      var = mu_assoc_ref (mach->vartab, name);
+      var = mu_assoc_get (mach->vartab, name);
 
       free (name);
       
@@ -383,11 +391,10 @@ mu_sieve_require_variables (mu_sieve_machine_t mach)
   if (mach->vartab)
     return 0;
 
-  rc = mu_assoc_create (&mach->vartab, sizeof (struct sieve_variable),
-                       MU_ASSOC_ICASE);
+  rc = mu_assoc_create (&mach->vartab, MU_ASSOC_ICASE);
   if (rc)
     mu_sieve_error (mach, "mu_assoc_create: %s", mu_strerror (rc));
-
+  mu_assoc_set_destroy_item (mach->vartab, mu_list_free_item);
   if (rc == 0)
     {
       mu_sieve_register_action (mach, "set", sieve_action_set, 
@@ -418,11 +425,14 @@ mu_i_sv_copy_variables (mu_sieve_machine_t child, 
mu_sieve_machine_t parent)
     {
       const char *name;
       struct sieve_variable const *val;
-      struct sieve_variable newval;
+      struct sieve_variable *newval;
 
       mu_iterator_current_kv (itr, (const void **)&name, (void**)&val);
-      newval.value = mu_sieve_strdup (child, val->value);
-      mu_assoc_install (child->vartab, name, &newval);
+      newval = malloc (sizeof (*newval));
+      if (!newval)
+       mu_sieve_abort (child);
+      newval->value = mu_sieve_strdup (child, val->value);
+      mu_assoc_install (child->vartab, name, newval);
     }
 
   mu_iterator_destroy (&itr);    
diff --git a/libproto/imap/fetch.c b/libproto/imap/fetch.c
index cac7947..ad9e08e 100644
--- a/libproto/imap/fetch.c
+++ b/libproto/imap/fetch.c
@@ -362,7 +362,7 @@ static int
 _map_body_param (void **itmv, size_t itmc, void *call_data)
 {
   mu_assoc_t assoc = call_data;
-  struct mu_mime_param param;
+  struct mu_mime_param *param;
   struct imap_list_element *key, *val;
   int rc;
 
@@ -377,12 +377,18 @@ _map_body_param (void **itmv, size_t itmc, void 
*call_data)
   rc = mu_rfc2047_decode_param ("UTF-8", val->v.string, &param);
   if (rc)
     {
-      param.lang = param.cset = NULL;
-      param.value = strdup (val->v.string);
-      if (!param.value)
+      param = malloc (sizeof (*param));
+      if (!param)
        return ENOMEM;
+      param->lang = param->cset = NULL;
+      param->value = strdup (val->v.string);
+      if (!param->value)
+       {
+         free (param);
+         return ENOMEM;
+       }
     }
-  return mu_assoc_install (assoc, key->v.string, &param);
+  return mu_assoc_install (assoc, key->v.string, param);
 }
 
 static int
diff --git a/libproto/imap/id.c b/libproto/imap/id.c
index 893ccf9..b7e5d81 100644
--- a/libproto/imap/id.c
+++ b/libproto/imap/id.c
@@ -27,22 +27,19 @@
 #include <mailutils/imap.h>
 #include <mailutils/sys/imap.h>
 
-void
-_id_free (void *data)
-{
-  char *s = *(char**)data;
-  free (s);
-}
-
 static int
 _id_mapper (void **itmv, size_t itmc, void *call_data)
 {
   int rc;
+  char *copy;
   mu_assoc_t assoc = call_data;
   struct imap_list_element *key = itmv[0], *val = itmv[1];
   if (key->type != imap_eltype_string || val->type != imap_eltype_string)
     return MU_ERR_FAILURE;
-  rc = mu_assoc_install (assoc, key->v.string, &val->v.string);
+  copy = strdup (val->v.string);
+  if (!copy)
+    return errno;
+  rc = mu_assoc_install (assoc, key->v.string, copy);
   if (rc == 0)
     val->v.string = NULL;
   return rc;
@@ -52,10 +49,10 @@ static mu_assoc_t
 create_id_assoc (void)
 {
   mu_assoc_t assoc;
-  int rc = mu_assoc_create (&assoc, sizeof (char**), MU_ASSOC_ICASE);
+  int rc = mu_assoc_create (&assoc, MU_ASSOC_ICASE);
   if (rc)
     return NULL;
-  mu_assoc_set_free (assoc, _id_free);
+  mu_assoc_set_destroy_item (assoc, mu_list_free_item);
   return assoc;
 }
 
diff --git a/mail/alias.c b/mail/alias.c
index 2891ae2..673e45c 100644
--- a/mail/alias.c
+++ b/mail/alias.c
@@ -17,34 +17,27 @@
 
 #include "mail.h"
 
-typedef struct _alias *alias_t;
-
-struct _alias
-{
-  mu_list_t list;
-};
-
 static mu_assoc_t aliases;
 
 static void
 alias_free (void *data)
 {
-  alias_t al = data;
-  util_slist_destroy (&al->list);
+  mu_list_t al = data;
+  util_slist_destroy (&al);
 }
 
 static void
-alias_print_group (const char *name, alias_t al)
+alias_print_group (const char *name, mu_list_t al)
 {
   mu_printf ("%s    ", name);
-  util_slist_print (al->list, 0);
+  util_slist_print (al, 0);
   mu_printf ("\n");
 }
 
-static alias_t
+static mu_list_t
 alias_lookup (const char *name)
 {
-  return mu_assoc_ref (aliases, name);
+  return mu_assoc_get (aliases, name);
 }
 
 static void
@@ -62,7 +55,7 @@ alias_print (char *name)
           mu_iterator_next (itr))
        {
          const char *name;
-         alias_t al;
+         mu_list_t al;
          if (mu_iterator_current_kv (itr, (const void **)&name, (void**)&al))
            continue;
          alias_print_group (name, al);
@@ -70,7 +63,7 @@ alias_print (char *name)
     }
   else
     {
-      alias_t al;
+      mu_list_t al;
 
       al = alias_lookup (name);
       if (!al)
@@ -83,21 +76,25 @@ alias_print (char *name)
 }
 
 static int
-alias_create (const char *name, alias_t *al)
+alias_create (const char *name, mu_list_t *al)
 {
   int rc;
-
+  mu_list_t l;
+  
   if (!aliases)
     {
-      mu_assoc_create (&aliases, sizeof (struct _alias), 0);
-      mu_assoc_set_free (aliases, alias_free);
+      mu_assoc_create (&aliases, 0);
+      mu_assoc_set_destroy_item (aliases, alias_free);
+    }
+  if (mu_assoc_lookup_ref (aliases, name, al))
+    {
+      rc = mu_list_create (&l);
+      if (rc)
+       return rc;
+      mu_assoc_install (aliases, name, l);
+      *al = l;
+      return 0;
     }
-  
-  rc = mu_assoc_ref_install (aliases, name, (void**) al);
-  if (rc == MU_ERR_EXISTS)
-    return 0;
-  if (rc == 0)
-    return mu_list_create (&(*al)->list);
   return 1;
 }
 
@@ -111,7 +108,7 @@ alias_destroy (const char *name)
 static void
 recursive_alias_expand (const char *name, mu_list_t exlist, mu_list_t origlist)
 { 
-  alias_t al;
+  mu_list_t al;
   mu_iterator_t itr;
   
   if ((al = alias_lookup (name)) == NULL)
@@ -121,7 +118,7 @@ recursive_alias_expand (const char *name, mu_list_t exlist, 
mu_list_t origlist)
       return;
     }
   
-  mu_list_get_iterator (al->list, &itr);
+  mu_list_get_iterator (al, &itr);
   for (mu_iterator_first (itr);
        !mu_iterator_is_done (itr);
        mu_iterator_next (itr))
@@ -148,7 +145,7 @@ string_comp (const void *item, const void *value)
 char *
 alias_expand (const char *name)
 {
-  alias_t al;
+  mu_list_t al;
   mu_list_t list;
   
   if (mailvar_get (NULL, "recursivealiases", mailvar_type_boolean, 0) == 0)
@@ -180,7 +177,7 @@ alias_expand (const char *name)
   
   if ((al = alias_lookup (name)) == NULL)
     return NULL;
-  return util_slist_to_string (al->list, ",");
+  return util_slist_to_string (al, ",");
 }
 
 
@@ -198,7 +195,7 @@ alias_iterate_next (alias_iterator_t atr)
   while (!mu_iterator_is_done (atr->itr))
     {
       const char *name;
-      alias_t al;
+      mu_list_t al;
 
       if (mu_iterator_current_kv (atr->itr, (const void **)&name, (void**)&al))
        continue;
@@ -259,7 +256,7 @@ mail_alias (int argc, char **argv)
     alias_print (argv[1]);
   else
     {
-      alias_t al;
+      mu_list_t al;
 
       if (alias_create (argv[1], &al))
        return 1;
@@ -267,7 +264,7 @@ mail_alias (int argc, char **argv)
       argc--;
       argv++;
       while (--argc)
-       util_slist_add (&al->list, *++argv);
+       util_slist_add (&al, *++argv);
     }
   return 0;
 }
diff --git a/mail/testsuite/mail/alias.exp b/mail/testsuite/mail/alias.exp
index 4fb102e..9d27f14 100644
--- a/mail/testsuite/mail/alias.exp
+++ b/mail/testsuite/mail/alias.exp
@@ -24,13 +24,13 @@ mail_test -message "alias staff" "alias" \
 
 mail_command "alias teeparty alice march.hare hatter" 
 mail_test -message "alias teeparty" "alias" \
-       "teeparty    alice march.hare hatter"\
-       "staff    alice tweedledum tweedledee"
+       "staff    alice tweedledum tweedledee" \
+       "teeparty    alice march.hare hatter"
 
 mail_command "alias messengers haigha hatta" 
 mail_test -message "alias messengers" "alias" \
-       "teeparty    alice march.hare hatter"\
-       "staff    alice tweedledum tweedledee"\
+       "staff    alice tweedledum tweedledee" \
+       "teeparty    alice march.hare hatter" \
        "messengers    haigha hatta"
 
 mail_command "unalias teeparty"
@@ -46,9 +46,9 @@ mail_test -message "alias teeparty output" \
 
 mail_command "alias pretenders lion unicorn"
 mail_test -message "alias pretenders" "alias"\
-"pretenders    lion unicorn "\
 "staff    alice tweedledum tweedledee"\
-"messengers    haigha hatta"
+"messengers    haigha hatta"\
+"pretenders    lion unicorn"
 
 mail_stop
 
diff --git a/mu/imap.c b/mu/imap.c
index cc5da3f..822a33a 100644
--- a/mu/imap.c
+++ b/mu/imap.c
@@ -755,10 +755,10 @@ com_id (int argc, char **argv)
     {
       if (test)
        {
-         void *res = mu_assoc_ref (assoc, test);
-         if (res)
+         char *val = mu_assoc_get (assoc, test);
+         if (val)
            {
-             mu_printf ("%s: %s\n", test, *(char **)res);
+             mu_printf ("%s: %s\n", test, val);
            }
          else
            mu_printf (_("%s is not set\n"), test);
@@ -772,10 +772,10 @@ com_id (int argc, char **argv)
               !mu_iterator_is_done (itr); mu_iterator_next (itr))
            {
              char *key;
-             void *val;
+             char *val;
 
-             mu_iterator_current_kv (itr, (const void**)&key, &val);
-             mu_printf ("ID: %s %s\n", key, *(char**)val);
+             mu_iterator_current_kv (itr, (const void**)&key, (void**)&val);
+             mu_printf ("ID: %s %s\n", key, val);
            }
          mu_iterator_destroy (&itr);
        }


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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