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.0-24-ge2bd3a0


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-3.0-24-ge2bd3a0
Date: Sun, 4 Dec 2016 11:46:28 +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=e2bd3a059eb8268d156baf59e41909cae1e28297

The branch, master has been updated
       via  e2bd3a059eb8268d156baf59e41909cae1e28297 (commit)
      from  fdf02db320d6bd88920cdcd15db3c45f71d2fb74 (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 e2bd3a059eb8268d156baf59e41909cae1e28297
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Dec 4 11:23:43 2016 +0200

    sieve: redo symbol registry support.
    
    The purpose is to simplify the machine structure and to ensure its
    clones are completely independent of the master instance.
    
    * include/mailutils/sieve.h (mu_sieve_command): New struct.
    (mu_sieve_record): New enum
    (mu_sieve_registry_t): Generalize for storing various types of objects.
    (mu_sieve_test_lookup,mu_sieve_action_lookup)
    (mu_sieve_require_action,mu_sieve_require_test)
    (mu_sieve_require_comparator): Remove.
    (mu_sieve_register_test_ext,mu_sieve_register_test)
    (mu_sieve_register_action_ext,mu_sieve_register_action)
    (mu_sieve_register_comparator)
    (mu_sieve_load_ext): Change return type.
    (mu_sieve_registry_require,mu_sieve_unload_ext): New functions.
    (mu_sieve_machine_inherit): Rename to mu_sieve_machine_clone.
    * libmu_sieve/sieve-priv.h (mu_sieve_machine): Remove source_list,
    test_list, action_list, and comp_list.  Add a single registry list
    instead.
    Add space for file and command (action and test) names: idspace,
    idcount, idmax.
    Remove unused field "stack";
    (mu_i_sv_lex_finish): Change prototype.
    (_mu_i_sv_instr_push,_mu_i_sv_instr_pop): Remove protos.
    (mu_i_sv_id_canon,mu_i_sv_id_num)
    (mu_i_sv_id_str,mu_i_sv_free_idspace): New protos.
    * libmu_sieve/register.c: Rename to registry.c
    * libmu_sieve/registry.c (mu_sieve_test_lookup)
    (mu_sieve_action_lookup): Remove.
    (mu_sieve_require_test,mu_sieve_require_action): Remove.
    (mu_sieve_registry_require): New function.
    (mu_sieve_registry_add,mu_sieve_registry_lookup): New functions.
    * libmu_sieve/Makefile.am: Update.
    * libmu_sieve/comparator.c: Rewrite using new registry functions.
    * libmu_sieve/load.c (mu_sieve_load_ext): Return module handle.
    (mu_sieve_unload_ext): New function.
    * libmu_sieve/mem.c (mu_sieve_free): Gracefully handle NULL argument.
    (mu_i_sv_id_canon,mu_i_sv_id_num,mu_i_sv_id_str): New functions.
    * libmu_sieve/prog.c (mu_i_sv_locus): Store index of the file name in
    the id space, instead of pointer to the name itself.
    
    * libmu_sieve/require.c (mu_sieve_require): Rewrite.
    * libmu_sieve/runtime.c (_mu_i_sv_instr_source): Expect ID index
    as argument.
    (_mu_i_sv_instr_push)
    (_mu_i_sv_instr_pop): Remove unused instructions.
    
    * libmu_sieve/sieve.l (file_names): Remove.  Use mu_sieve_machine
    idspace instead.
    * libmu_sieve/sieve.y (mu_sieve_machine_clone)
    (mu_sieve_machine_dup): Rewrite.
    (mu_sieve_machine_destroy): Free idspace and registry
    
    * examples/numaddr.c: Reflect changes.
    * libmu_sieve/extensions/editheader.c: Likewise.
    * libmu_sieve/extensions/list.c: Likewise.
    * libmu_sieve/extensions/moderator.c: Likewise.
    * libmu_sieve/extensions/pipe.c: Likewise.
    * libmu_sieve/extensions/spamd.c: Likewise.
    * libmu_sieve/extensions/timestamp.c: Likewise.
    * libmu_sieve/extensions/vacation.c: Likewise.

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

Summary of changes:
 examples/numaddr.c                  |    5 +-
 include/mailutils/sieve.h           |  103 +++++++++++--------
 libmu_sieve/Makefile.am             |    2 +-
 libmu_sieve/comparator.c            |   80 +++------------
 libmu_sieve/extensions/editheader.c |   25 ++---
 libmu_sieve/extensions/list.c       |    5 +-
 libmu_sieve/extensions/moderator.c  |   11 +-
 libmu_sieve/extensions/pipe.c       |   12 +--
 libmu_sieve/extensions/spamd.c      |    5 +-
 libmu_sieve/extensions/timestamp.c  |    5 +-
 libmu_sieve/extensions/vacation.c   |    5 +-
 libmu_sieve/load.c                  |   38 +++----
 libmu_sieve/mem.c                   |   65 ++++++++++++
 libmu_sieve/prog.c                  |   22 ++--
 libmu_sieve/register.c              |  171 -------------------------------
 libmu_sieve/registry.c              |  177 ++++++++++++++++++++++++++++++++
 libmu_sieve/require.c               |   44 +++-----
 libmu_sieve/runtime.c               |   36 +------
 libmu_sieve/sieve-priv.h            |   22 ++--
 libmu_sieve/sieve.l                 |   32 +-----
 libmu_sieve/sieve.y                 |  190 +++++++++++++++++++++++++----------
 libmu_sieve/tests.c                 |   10 +-
 22 files changed, 553 insertions(+), 512 deletions(-)
 delete mode 100644 libmu_sieve/register.c
 create mode 100644 libmu_sieve/registry.c

diff --git a/examples/numaddr.c b/examples/numaddr.c
index 584d2b9..dd43293 100644
--- a/examples/numaddr.c
+++ b/examples/numaddr.c
@@ -131,6 +131,7 @@ static mu_sieve_tag_group_t numaddr_tag_groups[] = {
 int
 SIEVE_EXPORT(numaddr,init) (mu_sieve_machine_t mach)
 {
-  return mu_sieve_register_test (mach, "numaddr", numaddr_test,
-                              numaddr_req_args, numaddr_tag_groups, 1);
+  mu_sieve_register_test (mach, "numaddr", numaddr_test,
+                         numaddr_req_args, numaddr_tag_groups, 1);
+  return 0;
 }
diff --git a/include/mailutils/sieve.h b/include/mailutils/sieve.h
index 42836f0..6316332 100644
--- a/include/mailutils/sieve.h
+++ b/include/mailutils/sieve.h
@@ -100,17 +100,13 @@ typedef struct
   mu_sieve_tag_checker_t checker;
 } mu_sieve_tag_group_t;
 
-typedef struct
+struct mu_sieve_command          /* test or action */
 {
-  const char *name;
-  int required;
   mu_sieve_handler_t handler;
   mu_sieve_data_type *req_args;
   mu_sieve_data_type *opt_args;
   mu_sieve_tag_group_t *tags;
-} mu_sieve_register_t;
-
-#define MU_SIEVE_CHARSET "UTF-8"
+};
 
 #define MU_SIEVE_MATCH_IS        1
 #define MU_SIEVE_MATCH_CONTAINS  2
@@ -119,6 +115,28 @@ typedef struct
 #define MU_SIEVE_MATCH_EQ        5
 #define MU_SIEVE_MATCH_LAST      6
 
+enum mu_sieve_record
+  {
+    mu_sieve_record_action,
+    mu_sieve_record_test,
+    mu_sieve_record_comparator
+  };
+  
+typedef struct
+{
+  const char *name;
+  int required;
+  void *handle;
+  enum mu_sieve_record type;
+  union
+  {
+    struct mu_sieve_command command;
+    mu_sieve_comparator_t comp[MU_SIEVE_MATCH_LAST];
+  } v;
+} mu_sieve_registry_t;
+
+#define MU_SIEVE_CHARSET "UTF-8"
+
 extern mu_debug_handle_t mu_sieve_debug_handle;
 extern mu_list_t mu_sieve_include_path;
 extern mu_list_t mu_sieve_library_path;
@@ -143,41 +161,46 @@ size_t mu_sieve_value_create (mu_sieve_machine_t mach,
                              mu_sieve_data_type type, void *data);
 
 /* Symbol space functions */
-mu_sieve_register_t *mu_sieve_test_lookup (mu_sieve_machine_t mach,
-                                          const char *name);
-mu_sieve_register_t *mu_sieve_action_lookup (mu_sieve_machine_t mach,
-                                            const char *name);
-int mu_sieve_register_test_ext (mu_sieve_machine_t mach,
-                               const char *name, mu_sieve_handler_t handler,
-                               mu_sieve_data_type *req_args,
-                               mu_sieve_data_type *opt_args,
-                               mu_sieve_tag_group_t *tags, int required);
-int mu_sieve_register_test (mu_sieve_machine_t mach,
-                           const char *name, mu_sieve_handler_t handler,
-                           mu_sieve_data_type *arg_types,
-                           mu_sieve_tag_group_t *tags, int required);
-
-int mu_sieve_register_action_ext (mu_sieve_machine_t mach,
-                                 const char *name, mu_sieve_handler_t handler,
-                                 mu_sieve_data_type *req_args,
-                                 mu_sieve_data_type *opt_args,
-                                 mu_sieve_tag_group_t *tags, int required);
-int mu_sieve_register_action (mu_sieve_machine_t mach,
-                             const char *name, mu_sieve_handler_t handler,
-                             mu_sieve_data_type *arg_types,
-                             mu_sieve_tag_group_t *tags, int required);
-int mu_sieve_register_comparator (mu_sieve_machine_t mach, const char *name,
-                                 int required, mu_sieve_comparator_t is,
-                                 mu_sieve_comparator_t contains,
-                                 mu_sieve_comparator_t matches,
-                                 mu_sieve_comparator_t regex,
-                                 mu_sieve_comparator_t eq);
-int mu_sieve_require_action (mu_sieve_machine_t mach, const char *name);
-int mu_sieve_require_test (mu_sieve_machine_t mach, const char *name);
-int mu_sieve_require_comparator (mu_sieve_machine_t mach, const char *name);
+mu_sieve_registry_t *mu_sieve_registry_add (mu_sieve_machine_t mach,
+                                           const char *name);
+mu_sieve_registry_t *mu_sieve_registry_lookup (mu_sieve_machine_t mach,
+                                              const char *name,
+                                              enum mu_sieve_record type);
+int mu_sieve_registry_require (mu_sieve_machine_t mach, const char *name,
+                              enum mu_sieve_record type);
+
+void mu_sieve_register_test_ext (mu_sieve_machine_t mach,
+                                const char *name, mu_sieve_handler_t handler,
+                                mu_sieve_data_type *req_args,
+                                mu_sieve_data_type *opt_args,
+                                mu_sieve_tag_group_t *tags, int required);
+void mu_sieve_register_test (mu_sieve_machine_t mach,
+                            const char *name, mu_sieve_handler_t handler,
+                            mu_sieve_data_type *arg_types,
+                            mu_sieve_tag_group_t *tags, int required);
+
+void mu_sieve_register_action_ext (mu_sieve_machine_t mach,
+                                  const char *name, mu_sieve_handler_t handler,
+                                  mu_sieve_data_type *req_args,
+                                  mu_sieve_data_type *opt_args,
+                                  mu_sieve_tag_group_t *tags, int required);
+void mu_sieve_register_action (mu_sieve_machine_t mach,
+                              const char *name, mu_sieve_handler_t handler,
+                              mu_sieve_data_type *arg_types,
+                              mu_sieve_tag_group_t *tags, int required);
+  
+void mu_sieve_register_comparator (mu_sieve_machine_t mach, const char *name,
+                                  int required, mu_sieve_comparator_t is,
+                                  mu_sieve_comparator_t contains,
+                                  mu_sieve_comparator_t matches,
+                                  mu_sieve_comparator_t regex,
+                                  mu_sieve_comparator_t eq);
+
 int mu_sieve_require_relational (mu_sieve_machine_t mach, const char *name);
 
-int mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name);
+void *mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name);
+void mu_sieve_unload_ext (void *handle);
+  
 int mu_sieve_match_part_checker (mu_sieve_machine_t mach);
 
 mu_sieve_comparator_t mu_sieve_comparator_lookup (mu_sieve_machine_t mach,
@@ -229,7 +252,7 @@ int mu_sieve_vlist_compare (mu_sieve_machine_t mach,
 int mu_sieve_machine_create (mu_sieve_machine_t *mach);
 int mu_sieve_machine_dup (mu_sieve_machine_t const in,
                          mu_sieve_machine_t *out);
-int mu_sieve_machine_inherit (mu_sieve_machine_t const in,
+int mu_sieve_machine_clone (mu_sieve_machine_t const in,
                              mu_sieve_machine_t *out);
 void mu_sieve_machine_destroy (mu_sieve_machine_t *pmach);
 void mu_sieve_machine_add_destructor (mu_sieve_machine_t mach,
diff --git a/libmu_sieve/Makefile.am b/libmu_sieve/Makefile.am
index b9f3a0a..d0a77a9 100644
--- a/libmu_sieve/Makefile.am
+++ b/libmu_sieve/Makefile.am
@@ -34,7 +34,7 @@ libmu_sieve_la_SOURCES = \
  load.c\
  mem.c\
  prog.c\
- register.c\
+ registry.c\
  relational.c\
  require.c\
  runtime.c\
diff --git a/libmu_sieve/comparator.c b/libmu_sieve/comparator.c
index 44dd05b..591b4d4 100644
--- a/libmu_sieve/comparator.c
+++ b/libmu_sieve/comparator.c
@@ -30,13 +30,7 @@
 #include <mailutils/cctype.h>
 #include <mailutils/cstr.h>
 
-typedef struct {
-  const char *name;
-  int required;
-  mu_sieve_comparator_t comp[MU_SIEVE_MATCH_LAST];
-} sieve_comparator_record_t;
-
-int
+void
 mu_sieve_register_comparator (mu_sieve_machine_t mach,
                              const char *name,
                              int required,
@@ -46,70 +40,26 @@ mu_sieve_register_comparator (mu_sieve_machine_t mach,
                              mu_sieve_comparator_t regex,
                              mu_sieve_comparator_t eq)
 {
-  sieve_comparator_record_t *rp;
-
-  if (!mach->comp_list)
-    {
-      int rc = mu_list_create (&mach->comp_list);
-      if (rc)
-       return rc;
-    }
-
-  rp = mu_sieve_malloc (mach, sizeof (*rp));
-  rp->required = required;
-  rp->name = name;
-  rp->comp[MU_SIEVE_MATCH_IS] = is;       
-  rp->comp[MU_SIEVE_MATCH_CONTAINS] = contains; 
-  rp->comp[MU_SIEVE_MATCH_MATCHES] = matches;  
-  rp->comp[MU_SIEVE_MATCH_REGEX] = regex;    
-  rp->comp[MU_SIEVE_MATCH_EQ] = eq;    
-
-  return mu_list_append (mach->comp_list, rp);
-}
-
-sieve_comparator_record_t *
-_lookup (mu_list_t list, const char *name)
-{
-  mu_iterator_t itr;
-  sieve_comparator_record_t *reg;
-
-  if (!list || mu_list_get_iterator (list, &itr))
-    return NULL;
-
-  for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next 
(itr))
-    {
-      mu_iterator_current (itr, (void **)&reg);
-      if (strcmp (reg->name, name) == 0)
-       break;
-      else
-       reg = NULL;
-    }
-  mu_iterator_destroy (&itr);
-  return reg;
-}
-    
-int
-mu_sieve_require_comparator (mu_sieve_machine_t mach, const char *name)
-{
-  sieve_comparator_record_t *reg = _lookup (mach->comp_list, name);
-  if (!reg)
-    {
-      if (!(mu_sieve_load_ext (mach, name) == 0
-           && (reg = _lookup (mach->comp_list, name)) != NULL))
-       return 1;
-    }
-
-  reg->required = 1;
-  return 0;
+  mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name);
+
+  reg->type = mu_sieve_record_comparator;
+  reg->required = required;
+  reg->name = name;
+  reg->v.comp[MU_SIEVE_MATCH_IS] = is;       
+  reg->v.comp[MU_SIEVE_MATCH_CONTAINS] = contains; 
+  reg->v.comp[MU_SIEVE_MATCH_MATCHES] = matches;  
+  reg->v.comp[MU_SIEVE_MATCH_REGEX] = regex;    
+  reg->v.comp[MU_SIEVE_MATCH_EQ] = eq;    
 }
 
 mu_sieve_comparator_t 
 mu_sieve_comparator_lookup (mu_sieve_machine_t mach, const char *name, 
                             int matchtype)
 {
-  sieve_comparator_record_t *reg = _lookup (mach->comp_list, name);
-  if (reg && reg->comp[matchtype])
-    return reg->comp[matchtype];
+  mu_sieve_registry_t *reg =
+    mu_sieve_registry_lookup (mach, name, mu_sieve_record_comparator);
+  if (reg && reg->v.comp[matchtype])
+    return reg->v.comp[matchtype];
   return NULL;
 }
 
diff --git a/libmu_sieve/extensions/editheader.c 
b/libmu_sieve/extensions/editheader.c
index 3ef017f..dfb51ac 100644
--- a/libmu_sieve/extensions/editheader.c
+++ b/libmu_sieve/extensions/editheader.c
@@ -272,22 +272,13 @@ static mu_sieve_data_type deleteheader_args[] = {
 int
 SIEVE_EXPORT (editheader, init) (mu_sieve_machine_t mach)
 {
-  int rc;
-
   /* This dummy record is required by libmu_sieve  */
-  rc = mu_sieve_register_action (mach, "editheader", NULL, NULL, NULL, 1);
-  if (rc)
-    return rc;
-  rc = mu_sieve_register_action (mach, "addheader", sieve_addheader,
-                                addheader_args, addheader_tag_groups, 1);
-  if (rc)
-    return rc;
-  rc = mu_sieve_register_action_ext (mach, "deleteheader", sieve_deleteheader,
-                                    deleteheader_args, deleteheader_args,
-                                    deleteheader_tag_groups,
-                                    1);
-  if (rc)
-    return rc;
-
-  return rc;
+  mu_sieve_register_action (mach, "editheader", NULL, NULL, NULL, 1);
+  mu_sieve_register_action (mach, "addheader", sieve_addheader,
+                           addheader_args, addheader_tag_groups, 1);
+  mu_sieve_register_action_ext (mach, "deleteheader", sieve_deleteheader,
+                               deleteheader_args, deleteheader_args,
+                               deleteheader_tag_groups,
+                               1);
+  return 0;
 }
diff --git a/libmu_sieve/extensions/list.c b/libmu_sieve/extensions/list.c
index 3a64e0a..e31e763 100644
--- a/libmu_sieve/extensions/list.c
+++ b/libmu_sieve/extensions/list.c
@@ -203,8 +203,9 @@ static mu_sieve_tag_group_t list_tag_groups[] = {
 int
 SIEVE_EXPORT(list,init) (mu_sieve_machine_t mach)
 {
-  return mu_sieve_register_test (mach, "list", list_test,
-                              list_req_args, list_tag_groups, 1);
+  mu_sieve_register_test (mach, "list", list_test,
+                         list_req_args, list_tag_groups, 1);
+  return 0;
 }
 
 /* End of list.c */
diff --git a/libmu_sieve/extensions/moderator.c 
b/libmu_sieve/extensions/moderator.c
index 249611c..f2ccd82 100644
--- a/libmu_sieve/extensions/moderator.c
+++ b/libmu_sieve/extensions/moderator.c
@@ -84,7 +84,7 @@ moderator_filter_message (mu_sieve_machine_t mach,
   
   if (mu_sieve_get_tag (mach, "source", SVT_STRING, &arg))
     {
-      rc = mu_sieve_machine_inherit (mach, &newmach);
+      rc = mu_sieve_machine_clone (mach, &newmach);
       if (rc)
        {
          mu_sieve_error (mach, _("cannot initialize sieve machine: %s"),
@@ -105,7 +105,7 @@ moderator_filter_message (mu_sieve_machine_t mach,
     {
       struct mu_locus locus;
       
-      rc = mu_sieve_machine_inherit (mach, &newmach);
+      rc = mu_sieve_machine_clone (mach, &newmach);
       if (rc)
        {
          mu_sieve_error (mach, _("cannot initialize sieve machine: %s"),
@@ -363,8 +363,9 @@ static mu_sieve_tag_group_t moderator_tag_groups[] = {
 int
 SIEVE_EXPORT(moderator,init) (mu_sieve_machine_t mach)
 {
-  return mu_sieve_register_action (mach, "moderator", moderator_action,
-                                  moderator_req_args,
-                                  moderator_tag_groups, 1);
+  mu_sieve_register_action (mach, "moderator", moderator_action,
+                           moderator_req_args,
+                           moderator_tag_groups, 1);
+  return 0;
 }
    
diff --git a/libmu_sieve/extensions/pipe.c b/libmu_sieve/extensions/pipe.c
index 3aedf16..5ba6c13 100644
--- a/libmu_sieve/extensions/pipe.c
+++ b/libmu_sieve/extensions/pipe.c
@@ -275,11 +275,9 @@ static mu_sieve_data_type pipe_args[] = {
 int
 SIEVE_EXPORT (pipe, init) (mu_sieve_machine_t mach)
 {
-  int rc;
-  rc = mu_sieve_register_action (mach, "pipe", sieve_action_pipe,
-                                pipe_args, pipe_action_tag_groups, 1);
-  if (rc)
-    return rc;
-  return mu_sieve_register_test (mach, "pipe", sieve_test_pipe,
-                                pipe_args, pipe_test_tag_groups, 1);
+  mu_sieve_register_action (mach, "pipe", sieve_action_pipe,
+                           pipe_args, pipe_action_tag_groups, 1);
+  mu_sieve_register_test (mach, "pipe", sieve_test_pipe,
+                         pipe_args, pipe_test_tag_groups, 1);
+  return 0;
 }
diff --git a/libmu_sieve/extensions/spamd.c b/libmu_sieve/extensions/spamd.c
index 692f49a..2ea2efd 100644
--- a/libmu_sieve/extensions/spamd.c
+++ b/libmu_sieve/extensions/spamd.c
@@ -544,7 +544,8 @@ static mu_sieve_tag_group_t spamd_tag_groups[] = {
 int
 SIEVE_EXPORT(spamd,init) (mu_sieve_machine_t mach)
 {
-  return mu_sieve_register_test (mach, "spamd", spamd_test,
-                              spamd_req_args, spamd_tag_groups, 1);
+  mu_sieve_register_test (mach, "spamd", spamd_test,
+                         spamd_req_args, spamd_tag_groups, 1);
+  return 0;
 }
    
diff --git a/libmu_sieve/extensions/timestamp.c 
b/libmu_sieve/extensions/timestamp.c
index e96f4dd..5adf4de 100644
--- a/libmu_sieve/extensions/timestamp.c
+++ b/libmu_sieve/extensions/timestamp.c
@@ -123,6 +123,7 @@ static mu_sieve_tag_group_t timestamp_tag_groups[] = {
 int
 SIEVE_EXPORT(timestamp,init) (mu_sieve_machine_t mach)
 {
-  return mu_sieve_register_test (mach, "timestamp", timestamp_test,
-                              timestamp_req_args, timestamp_tag_groups, 1);
+  mu_sieve_register_test (mach, "timestamp", timestamp_test,
+                         timestamp_req_args, timestamp_tag_groups, 1);
+  return 0;
 }
diff --git a/libmu_sieve/extensions/vacation.c 
b/libmu_sieve/extensions/vacation.c
index fa19c87..ecff938 100644
--- a/libmu_sieve/extensions/vacation.c
+++ b/libmu_sieve/extensions/vacation.c
@@ -868,6 +868,7 @@ static mu_sieve_data_type vacation_args[] = {
 
 int SIEVE_EXPORT (vacation, init) (mu_sieve_machine_t mach)
 {
-  return mu_sieve_register_action (mach, "vacation", sieve_action_vacation,
-                               vacation_args, vacation_tag_groups, 1);
+  mu_sieve_register_action (mach, "vacation", sieve_action_vacation,
+                           vacation_args, vacation_tag_groups, 1);
+  return 0;
 }
diff --git a/libmu_sieve/load.c b/libmu_sieve/load.c
index c164c27..deddcd2 100644
--- a/libmu_sieve/load.c
+++ b/libmu_sieve/load.c
@@ -31,16 +31,6 @@
 
 typedef int (*sieve_module_init_t) (mu_sieve_machine_t mach);
 
-#if 0
-/* FIXME: See comment below */ 
-static void
-_free_loaded_module (void *data)
-{
-  lt_dlclose ((lt_dlhandle)data);
-  lt_dlexit ();
-}
-#endif
-
 static int _add_load_dir (void *, void *);
 
 static int
@@ -61,8 +51,7 @@ sieve_init_load_path ()
     }
   return 0;
 }
-  
-     
+
 static lt_dlhandle
 load_module (mu_sieve_machine_t mach, const char *name)
 {
@@ -74,18 +63,12 @@ load_module (mu_sieve_machine_t mach, const char *name)
   handle = lt_dlopenext (name);
   if (handle)
     {
-      sieve_module_init_t init = (sieve_module_init_t)
-                                       lt_dlsym (handle, "init");
+      sieve_module_init_t init;
+      
+      init  = (sieve_module_init_t) lt_dlsym (handle, "init");
       if (init)
        {
          init (mach);
-         /* FIXME: We used to have this:
-              mu_sieve_machine_add_destructor (mach, _free_loaded_module,
-                                               handle);
-             However, unloading modules can lead to random segfaults in
-            case they allocated any global-access data (e.g. mach->msg).
-            In particular, this was the case with extensions/pipe.c. 
-         */
          return handle;
        }
       else
@@ -114,7 +97,7 @@ fix_module_name (char *name)
     }
 }
 
-int
+void *
 mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name)
 {
   lt_dlhandle handle;
@@ -122,11 +105,18 @@ mu_sieve_load_ext (mu_sieve_machine_t mach, const char 
*name)
 
   modname = strdup (name);
   if (!modname)
-    return 1;
+    return NULL;
   fix_module_name (modname);
   handle = load_module (mach, modname);
   free (modname);
-  return handle == NULL;
+  return handle;
+}
+
+void
+mu_sieve_unload_ext (void *data)
+{
+  if (data)
+    lt_dlclose ((lt_dlhandle)data);
 }
 
 static int
diff --git a/libmu_sieve/mem.c b/libmu_sieve/mem.c
index 3c39a3d..565ba32 100644
--- a/libmu_sieve/mem.c
+++ b/libmu_sieve/mem.c
@@ -83,6 +83,9 @@ mu_sieve_free (mu_sieve_machine_t mach, void *ptr)
   int rc;
   struct memory_cell mcell;
 
+  if (!ptr)
+    return;
+  
   mcell.ptr = ptr;
   rc = mu_list_remove (mach->memory_pool, &mcell);
   if (rc)
@@ -228,3 +231,65 @@ mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, 
size_t *pnmemb,
   *pptr = ptr;
   *pnmemb = nmemb;
 }
+
+char *
+mu_i_sv_id_canon (mu_sieve_machine_t mach, char const *name)
+{
+  size_t i;
+  char *p;
+  
+  if (!name)
+    return NULL;
+  
+  for (i = 0; i < mach->idcount; i++)
+    {
+      if (strcmp (mach->idspace[i], name) == 0)
+       return mach->idspace[i];
+    }
+
+  if (mach->idcount == mach->idmax)
+    {
+      mu_i_sv_2nrealloc (mach, 
+                        (void **) &mach->idspace,
+                        &mach->idmax,
+                        sizeof mach->idspace[0]);
+    }
+
+  p = mu_sieve_strdup (mach, name);
+  mach->idspace[mach->idcount++] = p;
+
+  return p;
+}
+ 
+size_t
+mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name)
+{
+  size_t i;
+
+  for (i = 0; i < mach->idcount; i++)
+    {
+      if (mach->idspace[i] == name || strcmp (mach->idspace[i], name) == 0)
+       return i;
+    }
+  abort ();
+}
+
+char *
+mu_i_sv_id_str (mu_sieve_machine_t mach, size_t n)
+{
+  if (n >= mach->idcount)
+    abort ();
+  return mach->idspace[n];
+}
+
+void
+mu_i_sv_free_idspace (mu_sieve_machine_t mach)
+{
+  size_t i;
+
+  for (i = 0; i < mach->idcount; i++)
+    mu_sieve_free (mach, mach->idspace[i]);
+  mach->idcount = 0;
+}
+
+      
diff --git a/libmu_sieve/prog.c b/libmu_sieve/prog.c
index 17b6587..6ab9609 100644
--- a/libmu_sieve/prog.c
+++ b/libmu_sieve/prog.c
@@ -52,7 +52,7 @@ mu_i_sv_locus (struct mu_sieve_machine *mach, struct 
mu_locus_range *lr)
   if (!file_eq (mach->locus.mu_file, lr->beg.mu_file))
     {
       mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_source);
-      mu_i_sv_code (mach, (sieve_op_t) lr->beg.mu_file);
+      mu_i_sv_code (mach, (sieve_op_t) mu_i_sv_id_num (mach, lr->beg.mu_file));
     }
   if (mach->locus.mu_line != lr->beg.mu_line)
     {
@@ -133,8 +133,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
                      struct mu_sieve_node *node)
 {
   size_t i;
-  mu_sieve_register_t *reg = node->v.command.reg;
-
+  mu_sieve_registry_t *reg = node->v.command.reg;
+  
   mu_sieve_value_t *start = mach->valspace + node->v.command.argstart;
   
   mu_list_t chk_list = NULL;
@@ -142,8 +142,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
   int opt_args = 0;
   int rc, err = 0;
   static mu_sieve_data_type empty[] = { SVT_VOID };
+
+  if (!reg)
+    return;
   
-  exp_arg = reg->req_args ? reg->req_args : empty;
+  exp_arg = reg->v.command.req_args ? reg->v.command.req_args : empty;
 
   /* Pass 1: consolidation */
   for (i = 0; i < node->v.command.argcount; i++)
@@ -153,7 +156,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
       if (val->type == SVT_TAG)
        {
          mu_sieve_tag_checker_t cf;
-         mu_sieve_tag_def_t *tag = find_tag (reg->tags, val->v.string, &cf);
+         mu_sieve_tag_def_t *tag = find_tag (reg->v.command.tags,
+                                             val->v.string, &cf);
              
          if (!tag)
            {
@@ -228,9 +232,9 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
        {
          if (*exp_arg == SVT_VOID)
            {
-             if (reg->opt_args)
+             if (reg->v.command.opt_args)
                {
-                 exp_arg = reg->opt_args;
+                 exp_arg = reg->v.command.opt_args;
                  opt_args = 1;
                }
              else
@@ -252,7 +256,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
                {
                  mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, 
                                    _("type mismatch in argument %lu to `%s'"),
-                                   (unsigned long) (exp_arg - reg->req_args + 
1),
+                                   (unsigned long) (exp_arg - 
reg->v.command.req_args + 1),
                                    reg->name);
                  mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, 
                                    _("expected %s but passed %s"),
@@ -316,7 +320,7 @@ static void
 sv_code_command (struct mu_sieve_machine *mach,
                 struct mu_sieve_node *node)
 {
-  mu_i_sv_code (mach, (sieve_op_t) node->v.command.reg->handler);
+  mu_i_sv_code (mach, (sieve_op_t) node->v.command.reg->v.command.handler);
   mu_i_sv_code (mach, (sieve_op_t) node->v.command.argstart);
   mu_i_sv_code (mach, (sieve_op_t) node->v.command.argcount);
   mu_i_sv_code (mach, (sieve_op_t) node->v.command.tagcount);
diff --git a/libmu_sieve/register.c b/libmu_sieve/register.c
deleted file mode 100644
index acd3876..0000000
--- a/libmu_sieve/register.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999-2002, 2004-2005, 2007-2008, 2010-2012, 2014-2016
-   Free Software Foundation, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 3 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General
-   Public License along with this library.  If not, see
-   <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif  
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>  
-#include <string.h>  
-#include <sieve-priv.h>
-
-static mu_sieve_register_t *
-reg_lookup (mu_list_t list, const char *name)
-{
-  mu_iterator_t itr;
-  mu_sieve_register_t *reg;
-
-  if (!list || mu_list_get_iterator (list, &itr))
-    return NULL;
-
-  for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next 
(itr))
-    {
-      mu_iterator_current (itr, (void **)&reg);
-      if (strcmp (reg->name, name) == 0)
-       break;
-      else
-       reg = NULL;
-    }
-  mu_iterator_destroy (&itr);
-  return reg;
-}
-
-mu_sieve_register_t *
-mu_sieve_test_lookup (mu_sieve_machine_t mach, const char *name)
-{
-  mu_sieve_register_t *reg = reg_lookup (mach->test_list, name);
-  return (reg && reg->handler) ? reg : NULL;
-}
-
-mu_sieve_register_t *
-mu_sieve_action_lookup (mu_sieve_machine_t mach, const char *name)
-{
-  mu_sieve_register_t *reg = reg_lookup (mach->action_list, name);
-  return (reg && reg->handler) ? reg : NULL;
-}
-
-static int
-reg_require (mu_sieve_machine_t mach, mu_list_t list, const char *name)
-{
-  mu_sieve_register_t *reg = reg_lookup (list, name);
-  if (!reg)
-    {
-      if (!(mu_sieve_load_ext (mach, name) == 0
-           && (reg = reg_lookup (list, name)) != NULL))
-       return 1;
-    }
-  reg->required = 1;
-  return 0;
-}
-
-int
-mu_sieve_require_action (mu_sieve_machine_t mach, const char *name)
-{
-  return reg_require (mach, mach->action_list, name);
-}
-
-int
-mu_sieve_require_test (mu_sieve_machine_t mach, const char *name)
-{
-  return reg_require (mach, mach->test_list, name);
-}
-
-
-static int
-sieve_register (mu_sieve_machine_t mach,
-               mu_list_t *list,
-               const char *name, mu_sieve_handler_t handler,
-               mu_sieve_data_type *req_arg_types,
-               mu_sieve_data_type *opt_arg_types,
-               mu_sieve_tag_group_t *tags, int required)
-{
-  mu_sieve_register_t *reg = mu_sieve_malloc (mach, sizeof (*reg));
-
-  if (!reg)
-    return ENOMEM;
-  reg->name = name;
-  reg->handler = handler;
-
-  reg->req_args = req_arg_types;
-  reg->opt_args = opt_arg_types;
-  reg->tags = tags;
-  reg->required = required;
-  
-  if (!*list)
-    {
-      int rc = mu_list_create (list);
-      if (rc)
-       {
-         free (reg);
-         return rc;
-       }
-    }
-  
-  return mu_list_append (*list, reg);
-}
-
-
-int
-mu_sieve_register_test_ext (mu_sieve_machine_t mach,
-                           const char *name, mu_sieve_handler_t handler,
-                           mu_sieve_data_type *req_args,
-                           mu_sieve_data_type *opt_args,
-                           mu_sieve_tag_group_t *tags, int required)
-{
-  return sieve_register (mach,
-                        &mach->test_list, name, handler,
-                        req_args, opt_args, tags, required);
-}
-
-int
-mu_sieve_register_test (mu_sieve_machine_t mach,
-                       const char *name, mu_sieve_handler_t handler,
-                       mu_sieve_data_type *arg_types,
-                       mu_sieve_tag_group_t *tags, int required)
-{
-  return mu_sieve_register_test_ext (mach, name, handler,
-                                    arg_types, NULL,
-                                    tags,
-                                    required);
-}
-
-int
-mu_sieve_register_action_ext (mu_sieve_machine_t mach,
-                             const char *name, mu_sieve_handler_t handler,
-                             mu_sieve_data_type *req_args,
-                             mu_sieve_data_type *opt_args,
-                             mu_sieve_tag_group_t *tags, int required)
-{
-  return sieve_register (mach,
-                        &mach->action_list, name, handler,
-                        req_args, opt_args, tags, required);
-}
-
-int
-mu_sieve_register_action (mu_sieve_machine_t mach,
-                         const char *name, mu_sieve_handler_t handler,
-                         mu_sieve_data_type *arg_types,
-                         mu_sieve_tag_group_t *tags, int required)
-{
-  return mu_sieve_register_action_ext (mach, name, handler,
-                                      arg_types, NULL,
-                                      tags,
-                                      required);
-}
diff --git a/libmu_sieve/registry.c b/libmu_sieve/registry.c
new file mode 100644
index 0000000..a5cbdfc
--- /dev/null
+++ b/libmu_sieve/registry.c
@@ -0,0 +1,177 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999-2002, 2004-2005, 2007-2008, 2010-2012, 2014-2016
+   Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General
+   Public License along with this library.  If not, see
+   <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif  
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>  
+#include <string.h>  
+#include <sieve-priv.h>
+
+int
+mu_sieve_registry_require (mu_sieve_machine_t mach, const char *name,
+                          enum mu_sieve_record type)
+{
+  mu_sieve_registry_t *reg;
+
+  reg = mu_sieve_registry_lookup (mach, name, type);
+  if (!reg)
+    {
+      void *handle = mu_sieve_load_ext (mach, name);
+      if (!handle)
+       return 1;
+      reg = mu_sieve_registry_lookup (mach, name, type);
+      if (!reg)
+       return 1;
+      reg->handle = handle;
+    }
+
+  reg->required = 1;
+  return 0;
+}
+
+
+static void
+regunload (void *data)
+{
+  mu_sieve_registry_t *reg = data;
+  mu_sieve_unload_ext (reg->handle);
+}
+
+static int
+regcmp (void const *a, void const *b)
+{
+  mu_sieve_registry_t const *rega = a;
+  mu_sieve_registry_t const *regb = b;
+  if (rega->type != regb->type)
+    return rega->type - regb->type;
+  return strcmp (rega->name, regb->name);
+}
+
+mu_sieve_registry_t *
+mu_sieve_registry_add (mu_sieve_machine_t mach, const char *name)
+{
+  mu_sieve_registry_t *reg;
+  int rc;
+  
+  if (!mach->registry)
+    {
+      rc = mu_list_create (&mach->registry);
+      if (rc)
+       {
+         mu_sieve_error (mach, "mu_list_create: %s", mu_strerror (rc));
+         mu_sieve_abort (mach);
+       }
+      mu_list_set_destroy_item (mach->registry, regunload);
+      mu_list_set_comparator (mach->registry, regcmp);
+    }
+  reg = mu_sieve_malloc (mach, sizeof (*reg));
+  reg->name = name;
+  reg->handle = NULL;
+  reg->required = 0;
+  memset (&reg->v, 0, sizeof reg->v);
+  rc = mu_list_append (mach->registry, reg);
+  if (rc)
+    {
+      mu_sieve_error (mach, "mu_list_append: %s", mu_strerror (rc));
+      mu_sieve_abort (mach);
+    }
+  return reg;
+}
+
+mu_sieve_registry_t *
+mu_sieve_registry_lookup (mu_sieve_machine_t mach, const char *name,
+                         enum mu_sieve_record type)
+{
+  mu_sieve_registry_t key, *reg;
+  int rc;
+  
+  key.name = name;
+  key.type = type;
+
+  rc = mu_list_locate (mach->registry, &key, (void**) &reg);
+  if (rc == MU_ERR_NOENT)
+    return NULL;
+  else if (rc)
+    {
+      mu_sieve_error (mach, _("registry lookup failed: %s"), mu_strerror (rc));
+      mu_sieve_abort (mach);
+    }
+  return reg;
+}
+
+void
+mu_sieve_register_test_ext (mu_sieve_machine_t mach,
+                           const char *name, mu_sieve_handler_t handler,
+                           mu_sieve_data_type *req_args,
+                           mu_sieve_data_type *opt_args,
+                           mu_sieve_tag_group_t *tags, int required)
+{
+  mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name);
+
+  reg->type = mu_sieve_record_test;
+  reg->required = required;
+  reg->v.command.handler = handler;
+  reg->v.command.req_args = req_args;
+  reg->v.command.opt_args = opt_args;
+  reg->v.command.tags = tags;
+}
+
+void
+mu_sieve_register_test (mu_sieve_machine_t mach,
+                       const char *name, mu_sieve_handler_t handler,
+                       mu_sieve_data_type *arg_types,
+                       mu_sieve_tag_group_t *tags, int required)
+{
+  return mu_sieve_register_test_ext (mach, name, handler,
+                                    arg_types, NULL,
+                                    tags,
+                                    required);
+}
+
+void
+mu_sieve_register_action_ext (mu_sieve_machine_t mach,
+                             const char *name, mu_sieve_handler_t handler,
+                             mu_sieve_data_type *req_args,
+                             mu_sieve_data_type *opt_args,
+                             mu_sieve_tag_group_t *tags, int required)
+{
+  mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name);
+
+  reg->type = mu_sieve_record_action;
+  reg->required = required;
+  reg->v.command.handler = handler;
+  reg->v.command.req_args = req_args;
+  reg->v.command.opt_args = opt_args;
+  reg->v.command.tags = tags;
+}
+
+void
+mu_sieve_register_action (mu_sieve_machine_t mach,
+                         const char *name, mu_sieve_handler_t handler,
+                         mu_sieve_data_type *arg_types,
+                         mu_sieve_tag_group_t *tags, int required)
+{
+  return mu_sieve_register_action_ext (mach, name, handler,
+                                      arg_types, NULL,
+                                      tags,
+                                      required);
+}
diff --git a/libmu_sieve/require.c b/libmu_sieve/require.c
index a04d654..372bd07 100644
--- a/libmu_sieve/require.c
+++ b/libmu_sieve/require.c
@@ -35,42 +35,26 @@ mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t 
list)
     {
       struct mu_sieve_string *str = mu_sieve_string_raw (mach, list, i);
       char *name = str->orig;
-      int (*reqfn) (mu_sieve_machine_t mach, const char *name) = NULL;
-      const char *text = NULL;
+      int rc;
       
-      if (strncmp (name, "comparator-", 11) == 0)
-       {
-         name += 11;
-         reqfn = mu_sieve_require_comparator;
-         text = _("required comparator");
-       }
-      else if (strncmp (name, "test-", 5)  == 0) /* GNU extension */
-       {
-         name += 5;
-         reqfn = mu_sieve_require_test;
-         text = _("required test");
-       }
-      else if (strcmp (name, "relational") == 0) /* RFC 3431 */
-       {
-         reqfn = mu_sieve_require_relational;
-         text = "";
-       }
+      if (strcmp (name, "relational") == 0) /* RFC 3431 */
+       rc = mu_sieve_require_relational (mach, name);
       else if (strcmp (name, "encoded-character") == 0) /* RFC 5228, 2.4.2.4 */
-       {
-         reqfn = mu_sieve_require_encoded_character;
-         text = "";
-       }
+       rc = mu_sieve_require_encoded_character (mach, name);
+      else if (strncmp (name, "comparator-", 11) == 0)
+       rc = mu_sieve_registry_require (mach, name + 11,
+                                       mu_sieve_record_comparator);
+      else if (strncmp (name, "test-", 5)  == 0) /* GNU extension */
+       rc = mu_sieve_registry_require (mach, name + 5,
+                                       mu_sieve_record_test);
       else
-       {
-         reqfn = mu_sieve_require_action;
-         text = _("required action");
-       }
+       rc = mu_sieve_registry_require (mach, name, mu_sieve_record_action);
 
-      if (reqfn (mach, name))
+      if (rc)
        {
          mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
-                           _("source for the %s %s is not available"),
-                           text, name);
+                           _("can't require %s is not available"),
+                           name);
          mu_i_sv_error (mach);
        }
     }
diff --git a/libmu_sieve/runtime.c b/libmu_sieve/runtime.c
index fea9bf8..8317f81 100644
--- a/libmu_sieve/runtime.c
+++ b/libmu_sieve/runtime.c
@@ -34,7 +34,7 @@
 void
 _mu_i_sv_instr_source (mu_sieve_machine_t mach)
 {
-  mach->locus.mu_file = (char*) SIEVE_RT_ARG (mach, 0, string);
+  mach->locus.mu_file = mu_i_sv_id_str (mach, SIEVE_RT_ARG (mach, 0, pc));
   mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
                    MU_IOCTL_LOGSTREAM_SET_LOCUS,
                   &mach->locus);
@@ -98,38 +98,6 @@ _mu_i_sv_instr_test (mu_sieve_machine_t mach)
 }
 
 void
-_mu_i_sv_instr_push (mu_sieve_machine_t mach)
-{
-  if (INSTR_DEBUG (mach))
-    mu_i_sv_debug (mach, mach->pc - 1, "PUSH");
-  if (INSTR_DISASS (mach))
-    return;
-  
-  if (!mach->stack && mu_list_create (&mach->stack))
-    {
-      mu_sieve_error (mach, _("cannot create stack"));
-      mu_sieve_abort (mach);
-    }
-  mu_list_push (mach->stack, (void*) mach->reg);
-}
-
-void
-_mu_i_sv_instr_pop (mu_sieve_machine_t mach)
-{
-  if (INSTR_DEBUG (mach))
-    mu_i_sv_debug (mach, mach->pc - 1, "POP");
-  if (INSTR_DISASS (mach))
-    return;
-
-  if (!mach->stack || mu_list_is_empty (mach->stack))
-    {
-      mu_sieve_error (mach, _("stack underflow"));
-      mu_sieve_abort (mach);
-    }
-  mu_list_pop (mach->stack, (void **)&mach->reg);
-}
-
-void
 _mu_i_sv_instr_not (mu_sieve_machine_t mach)
 {
   if (INSTR_DEBUG (mach))
@@ -207,7 +175,7 @@ mu_sieve_get_data (mu_sieve_machine_t mach)
 int
 mu_sieve_get_locus (mu_sieve_machine_t mach, struct mu_locus *loc)
 {
-  if (mach->source_list)
+  if (mach->locus.mu_file)
     {
       *loc = mach->locus;
       return 0;
diff --git a/libmu_sieve/sieve-priv.h b/libmu_sieve/sieve-priv.h
index c1ebb15..a960b89 100644
--- a/libmu_sieve/sieve-priv.h
+++ b/libmu_sieve/sieve-priv.h
@@ -68,11 +68,12 @@ struct mu_sieve_machine
 
   /* Symbol space: */
   mu_opool_t string_pool;    /* String constants */
-  mu_list_t source_list;     /* Source names (for diagnostics) */
-  mu_list_t test_list;       /* Tests */
-  mu_list_t action_list;     /* Actions */
-  mu_list_t comp_list;       /* Comparators */
+  mu_list_t registry;        /* Tests, Actions, Comparators */
 
+  char **idspace;            /* Source and identifier names */
+  size_t idcount;
+  size_t idmax;
+  
   mu_sieve_string_t *stringspace;
   size_t stringcount;
   size_t stringmax;
@@ -88,7 +89,6 @@ struct mu_sieve_machine
   enum mu_sieve_state state; /* Machine state */
   size_t pc;                 /* Current program counter */
   long reg;                  /* Numeric register */
-  mu_list_t stack;           /* Runtime stack */
 
   /* Call environment */
   const char *identifier;    /* Name of action or test being executed */
@@ -152,7 +152,7 @@ struct mu_sieve_node
     } cond;
     struct
     {
-      mu_sieve_register_t *reg;
+      mu_sieve_registry_t *reg;
       size_t argstart;
       size_t argcount;
       size_t tagcount;
@@ -167,7 +167,7 @@ int mu_sieve_yylex (void);
 int mu_i_sv_lex_begin (const char *name);
 int mu_i_sv_lex_begin_string (const char *buf, int bufsize,
                              const char *fname, int line);
-void mu_i_sv_lex_finish (struct mu_sieve_machine *mach);
+void mu_i_sv_lex_finish (void);
 
 extern mu_sieve_machine_t mu_sieve_machine;
 
@@ -182,8 +182,6 @@ void mu_i_sv_code_test (struct mu_sieve_machine *mach,
 /* Opcodes */
 void _mu_i_sv_instr_action (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_test (mu_sieve_machine_t mach);
-void _mu_i_sv_instr_push (mu_sieve_machine_t mach);
-void _mu_i_sv_instr_pop (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_not (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_branch (mu_sieve_machine_t mach);
 void _mu_i_sv_instr_brz (mu_sieve_machine_t mach);
@@ -230,3 +228,9 @@ void mu_i_sv_lint_command (struct mu_sieve_machine *mach,
 
 size_t  mu_i_sv_string_create (mu_sieve_machine_t mach, char *str);
 
+char *mu_i_sv_id_canon (mu_sieve_machine_t mach, char const *name);
+size_t mu_i_sv_id_num (mu_sieve_machine_t mach, char const *name);
+char *mu_i_sv_id_str (mu_sieve_machine_t mach, size_t n);
+void mu_i_sv_free_idspace (mu_sieve_machine_t mach);
+
+
diff --git a/libmu_sieve/sieve.l b/libmu_sieve/sieve.l
index 9f684e3..8f51b4c 100644
--- a/libmu_sieve/sieve.l
+++ b/libmu_sieve/sieve.l
@@ -56,7 +56,6 @@ static int isemptystr (char *text);
 static ino_t sieve_source_inode;
 struct mu_locus mu_sieve_locus;
 static int newline;
-static mu_list_t file_names;
 
 static mu_stream_t input_stream;
  
@@ -90,35 +89,10 @@ fillbuf (char *buf, size_t max_size)
         yy_switch_to_buffer (s); \
 } while (0)
 
-static int
-file_name_cmp (const void *a, const void *b)  
-{
-  return strcmp (a, b);
-}
-
 static void
 init_locus (char const *name, ino_t ino)
 {
-  mu_sieve_locus.mu_file = NULL;
-  if (name)
-    {
-      if (!file_names)
-       {
-         mu_list_create (&file_names);
-         mu_list_set_comparator (file_names, file_name_cmp);
-         mu_list_set_destroy_item (file_names, mu_list_free_item);
-       }
-      else
-       {
-         mu_list_locate (file_names, (void*) name,
-                         (void**) &mu_sieve_locus.mu_file);
-       }
-      if (!mu_sieve_locus.mu_file)
-       {
-         mu_sieve_locus.mu_file = strdup (name);//FIXME: Error checking
-         mu_list_append (file_names, mu_sieve_locus.mu_file);
-       }
-    }
+  mu_sieve_locus.mu_file = mu_i_sv_id_canon (mu_sieve_machine, name);
   mu_sieve_locus.mu_line = 1;
   mu_sieve_locus.mu_col = 0;
   newline = 0;
@@ -496,12 +470,10 @@ mu_i_sv_lex_begin_string (const char *buf, int bufsize,
 }
 
 void
-mu_i_sv_lex_finish (struct mu_sieve_machine *mach)
+mu_i_sv_lex_finish (void)
 {
   while (pop_source () == 0)
     ;
-  mach->source_list = file_names;
-  file_names = NULL;
 }
   
 static int
diff --git a/libmu_sieve/sieve.y b/libmu_sieve/sieve.y
index 9bb0ebd..46a8fba 100644
--- a/libmu_sieve/sieve.y
+++ b/libmu_sieve/sieve.y
@@ -245,10 +245,11 @@ cond         : test
 
 test         : command
                {
-                mu_sieve_register_t *reg;
+                mu_sieve_registry_t *reg;
 
                 mu_sieve_machine->locus = @1.beg;
-                reg = mu_sieve_test_lookup (mu_sieve_machine, $1.ident);
+                reg = mu_sieve_registry_lookup (mu_sieve_machine, $1.ident,
+                                                mu_sieve_record_test);
                 if (!reg)
                   {
                     mu_diag_at_locus (MU_LOG_ERROR, &@1.beg,
@@ -292,10 +293,11 @@ command      : IDENT maybe_arglist
 
 action       : command
                {
-                mu_sieve_register_t *reg;
+                mu_sieve_registry_t *reg;
 
                 mu_sieve_machine->locus = @1.beg;
-                reg = mu_sieve_action_lookup (mu_sieve_machine, $1.ident);
+                reg = mu_sieve_registry_lookup (mu_sieve_machine, $1.ident,
+                                                mu_sieve_record_action);
                 
                 if (!reg)
                   {
@@ -999,8 +1001,6 @@ mu_sieve_machine_create (mu_sieve_machine_t *pmach)
       return rc;
     }
   
-  mach->source_list = NULL;
-
   mach->data = NULL;
 
   mu_sieve_set_diag_stream (mach, mu_strerr);
@@ -1053,10 +1053,8 @@ mu_sieve_machine_reset (mu_sieve_machine_t mach)
   mu_list_clear (mach->memory_pool);
   mu_list_clear (mach->destr_list);
   mu_opool_free (mach->string_pool, NULL);
-  mu_list_clear (mach->source_list);
-  mu_list_clear (mach->test_list);
-  mu_list_clear (mach->action_list);
-  mu_list_clear (mach->comp_list);
+  mu_i_sv_free_idspace (mach);
+  mu_list_clear (mach->registry);
 
   mach->stringspace = NULL;
   mach->stringcount = 0;
@@ -1074,22 +1072,19 @@ mu_sieve_machine_reset (mu_sieve_machine_t mach)
   return 0;
 }
 
-int
-mu_sieve_machine_inherit (mu_sieve_machine_t const parent,
-                         mu_sieve_machine_t *pmach)
+static int
+regdup (void *item, void *data)
 {
-  mu_sieve_machine_t child;
-  int rc;
-  
-  if (!parent || parent->state == mu_sieve_state_error)
-    return EINVAL;
-  
-  rc = mu_sieve_machine_create (&child);
-  if (rc)
-    return rc;
+  mu_sieve_registry_t *reg = item;
+  mu_sieve_machine_t mach = data;
 
-  child->dry_run     = parent->dry_run;
+  mu_sieve_registry_require (mach, reg->name, reg->type);
+  return 0;
+}
 
+static void
+copy_stream_state (mu_sieve_machine_t child, mu_sieve_machine_t parent)
+{
   child->state_flags = parent->state_flags;
   child->err_mode    = parent->err_mode;
   child->err_locus   = parent->err_locus;
@@ -1105,13 +1100,97 @@ mu_sieve_machine_inherit (mu_sieve_machine_t const 
parent,
   mu_stream_ref (child->errstream);
   child->dbgstream = parent->dbgstream;
   mu_stream_ref (child->dbgstream);
+}
+
+int
+mu_sieve_machine_clone (mu_sieve_machine_t const parent,
+                       mu_sieve_machine_t *pmach)
+{
+  size_t i;
+  mu_sieve_machine_t child;
+  int rc;
+  
+  if (!parent || parent->state == mu_sieve_state_error)
+    return EINVAL;
   
-  child->data = parent->data;
-  child->logger = parent->logger;
-  child->daemon_email = parent->daemon_email;
+  rc = mu_sieve_machine_create (&child);
+  if (rc)
+    return rc;
 
-  *pmach = child;
-  return 0;
+  rc = setjmp (child->errbuf);
+
+  if (rc == 0)
+    {
+      child->state = mu_sieve_state_init;
+      mu_i_sv_register_standard_actions (child);
+      mu_i_sv_register_standard_tests (child);
+      mu_i_sv_register_standard_comparators (child);
+
+      /* Load necessary modules */
+      mu_list_foreach (parent->registry, regdup, child);
+  
+      /* Copy identifiers */
+      child->idspace = mu_sieve_calloc (child, parent->idcount,
+                                       sizeof (child->idspace[0]));
+      child->idcount = child->idmax = parent->idcount;
+      for (i = 0; i < child->idcount; i++)
+       child->idspace[i] = mu_sieve_strdup (parent, parent->idspace[i]);
+      
+      /* Copy string constants */
+      child->stringspace = mu_sieve_calloc (child, parent->stringcount,
+                                           sizeof (child->stringspace[0]));
+      child->stringcount = child->stringmax = parent->stringcount;
+      for (i = 0; i < parent->stringcount; i++)
+       {
+         memset (&child->stringspace[i], 0, sizeof (child->stringspace[0]));
+         child->stringspace[i].orig =
+           mu_sieve_strdup (parent, parent->stringspace[i].orig);
+       }
+
+      /* Copy value space */
+      child->valspace = mu_sieve_calloc (parent, parent->valcount,
+                                        sizeof child->valspace[0]);
+      child->valcount = child->valmax = parent->valcount;
+      for (i = 0; i < child->valcount; i++)
+       {
+         child->valspace[i].type = parent->valspace[i].type;
+         child->valspace[i].tag =
+           mu_sieve_strdup (parent, parent->valspace[i].tag);
+         switch (child->valspace[i].type)
+           {
+           case SVT_TAG:
+             child->valspace[i].v.string =
+               mu_sieve_strdup (parent, parent->valspace[i].v.string);
+             break;
+             
+           default:
+             child->valspace[i].v = parent->valspace[i].v;
+           }
+       }
+      
+      /* Copy progspace */
+      child->progsize = parent->progsize;
+      child->prog = mu_sieve_calloc (child, parent->progsize,
+                                    sizeof child->prog[0]);
+      memcpy (child->prog, parent->prog,
+             parent->progsize * sizeof (child->prog[0]));
+      
+      /* Copy user-defined settings */
+      
+      child->dry_run     = parent->dry_run;
+      
+      copy_stream_state (child, parent);
+      
+      child->data = parent->data;
+      child->logger = parent->logger;
+      child->daemon_email = parent->daemon_email;
+      
+      *pmach = child;
+    }
+  else
+    mu_sieve_machine_destroy (&child);
+  
+  return rc;
 }
 
 int
@@ -1133,9 +1212,7 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, 
mu_sieve_machine_t *out)
       return rc;
     }
   mach->destr_list = NULL;
-  mach->test_list = NULL;
-  mach->action_list = NULL;
-  mach->comp_list = NULL;
+  mach->registry = NULL;
 
   mach->progsize = in->progsize;
   mach->prog = in->prog;
@@ -1150,30 +1227,34 @@ mu_sieve_machine_dup (mu_sieve_machine_t const in, 
mu_sieve_machine_t *out)
     default:
       mach->state = in->state;
     }
-  
-  mach->pc = 0;
-  mach->reg = 0;
-  mach->stack = NULL;
 
-  mach->dry_run = in->dry_run;
+  rc = setjmp (mach->errbuf);
 
-  mach->state_flags = in->state_flags;
-  mach->err_mode    = in->err_mode;
-  mach->err_locus   = in->err_locus;
-  mach->dbg_mode    = in->dbg_mode;
-  mach->dbg_locus   = in->dbg_locus;  
+  if (rc == 0)
+    {
+      mach->pc = 0;
+      mach->reg = 0;
 
-  mach->errstream = in->errstream;
-  mu_stream_ref (mach->errstream);
-  mach->dbgstream = in->dbgstream;
-  mu_stream_ref (mach->dbgstream);
+      mach->dry_run = in->dry_run;
+      
+      mach->state_flags = in->state_flags;
+      mach->err_mode    = in->err_mode;
+      mach->err_locus   = in->err_locus;
+      mach->dbg_mode    = in->dbg_mode;
+      mach->dbg_locus   = in->dbg_locus;  
+      
+      copy_stream_state (mach, in);
   
-  mach->data = in->data;
-  mach->logger = in->logger;
-  mach->daemon_email = in->daemon_email;
+      mach->data = in->data;
+      mach->logger = in->logger;
+      mach->daemon_email = in->daemon_email;
 
-  *out = mach;
-  return 0;
+      *out = mach;
+    }
+  else
+    mu_sieve_machine_destroy (&mach);
+  
+  return rc;
 }
 
 void
@@ -1334,14 +1415,13 @@ mu_sieve_machine_destroy (mu_sieve_machine_t *pmach)
   mu_sieve_machine_t mach = *pmach;
 
   mu_i_sv_free_stringspace (mach);
+  mu_sieve_free (mach, mach->stringspace);
   mu_stream_destroy (&mach->errstream);
   mu_stream_destroy (&mach->dbgstream);
   mu_mailer_destroy (&mach->mailer);
   mu_list_destroy (&mach->destr_list);
-  mu_list_destroy (&mach->action_list);
-  mu_list_destroy (&mach->test_list);
-  mu_list_destroy (&mach->comp_list);
-  mu_list_destroy (&mach->source_list);
+  mu_list_destroy (&mach->registry);
+  mu_sieve_free (mach, mach->idspace);
   mu_opool_destroy (&mach->string_pool);
   mu_list_destroy (&mach->memory_pool);
   free (mach);
@@ -1397,7 +1477,7 @@ sieve_parse (void)
   yydebug = mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE3);
 
   rc = yyparse ();
-  mu_i_sv_lex_finish (mu_sieve_machine);
+  mu_i_sv_lex_finish ();
   if (rc)
     mu_i_sv_error (mu_sieve_machine);
   if (mu_sieve_machine->state == mu_sieve_state_init)
diff --git a/libmu_sieve/tests.c b/libmu_sieve/tests.c
index 10c4825..647484b 100644
--- a/libmu_sieve/tests.c
+++ b/libmu_sieve/tests.c
@@ -378,13 +378,13 @@ mu_i_sv_register_standard_tests (mu_sieve_machine_t mach)
 {
   /* true and false are built-ins */
   mu_sieve_register_test (mach, "address", sieve_test_address,
-                      address_req_args, address_tag_groups, 1);
+                         address_req_args, address_tag_groups, 1);
   mu_sieve_register_test (mach, "size", sieve_test_size,
-                      size_req_args, size_tag_groups, 1);
+                         size_req_args, size_tag_groups, 1);
   mu_sieve_register_test (mach, "envelope", sieve_test_envelope,
-                      address_req_args, envelope_tag_groups, 1);
+                         address_req_args, envelope_tag_groups, 1);
   mu_sieve_register_test (mach, "exists", sieve_test_exists,
-                      exists_req_args, NULL, 1);
+                         exists_req_args, NULL, 1);
   mu_sieve_register_test (mach, "header", sieve_test_header,
-                      address_req_args, header_tag_groups, 1);
+                         address_req_args, header_tag_groups, 1);
 }


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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