The following commit has been merged in the master branch:
commit bf1455085899a5203373eff34741cd7ea3d64774
Author: Guillem Jover <guil...@debian.org>
Date:   Sat Oct 16 19:04:13 2010 +0200

    libdpkg: Add error context function handler support
    
    This allows the code to use a function instead of a jump buffer to
    handle the errors, which happen to be possible for the general case,
    when it does not need to continue processing in an upper stack frame.
    Thus reducing the preceived complexity of simple code, and avoids
    exposing setjmp machinery to the casual user.

diff --git a/lib/dpkg/ehandle.c b/lib/dpkg/ehandle.c
index b630bf5..9e15161 100644
--- a/lib/dpkg/ehandle.c
+++ b/lib/dpkg/ehandle.c
@@ -62,7 +62,17 @@ struct cleanup_entry {
 
 struct error_context {
   struct error_context *next;
-  jmp_buf *jump;
+
+  enum {
+    handler_type_func,
+    handler_type_jump,
+  } handler_type;
+
+  union {
+    error_handler *func;
+    jmp_buf *jump;
+  } handler;
+
   struct cleanup_entry *cleanups;
   void (*printerror)(const char *emsg, const char *contextstring);
   const char *contextstring;
@@ -103,8 +113,13 @@ run_error_handler(void)
     fprintf(stderr, _("%s: outside error context, aborting:\n %s\n"),
             thisname, errmsg);
     exit(2);
+  } else if (econtext->handler_type == handler_type_func) {
+    econtext->handler.func();
+    internerr("error handler returned unexpectedly!");
+  } else if (econtext->handler_type == handler_type_jump) {
+    longjmp(*econtext->handler.jump, 1);
   } else {
-    longjmp(*econtext->jump, 1);
+    internerr("unknown error handler type %d!", econtext->handler_type);
   }
 }
 
@@ -131,15 +146,41 @@ set_error_printer(struct error_context *ec, error_printer 
*printerror,
   ec->contextstring = contextstring;
 }
 
+static void
+set_func_handler(struct error_context *ec, error_handler *func)
+{
+  ec->handler_type = handler_type_func;
+  ec->handler.func = func;
+}
+
+static void
+set_jump_handler(struct error_context *ec, jmp_buf *jump)
+{
+  ec->handler_type = handler_type_jump;
+  ec->handler.jump = jump;
+}
+
+void
+push_error_context_func(error_handler *func, error_printer *printerror,
+                        const char *contextstring)
+{
+  struct error_context *ec;
+
+  ec = error_context_new();
+  set_error_printer(ec, printerror, contextstring);
+  set_func_handler(ec, func);
+  onerr_abort = 0;
+}
+
 void
-push_error_handler(jmp_buf *jump, error_printer *printerror,
-                   const char *contextstring)
+push_error_context_jump(jmp_buf *jump, error_printer *printerror,
+                        const char *contextstring)
 {
   struct error_context *ec;
 
   ec = error_context_new();
   set_error_printer(ec, printerror, contextstring);
-  ec->jump = jump;
+  set_jump_handler(ec, jump);
   onerr_abort = 0;
 }
 
@@ -177,10 +218,10 @@ run_cleanups(struct error_context *econ, int flagsetin)
         if (setjmp(recurse_jump)) {
           run_cleanups(&recurserr, ehflag_bombout | ehflag_recursiveerror);
         } else {
-          recurserr.jump = &recurse_jump;
           recurserr.cleanups= NULL;
           recurserr.next= NULL;
           set_error_printer(&recurserr, print_cleanup_error, NULL);
+          set_jump_handler(&recurserr, &recurse_jump);
           econtext= &recurserr;
           cep->calls[i].call(cep->argc,cep->argv);
         }
diff --git a/lib/dpkg/ehandle.h b/lib/dpkg/ehandle.h
index d86ccaf..1b72700 100644
--- a/lib/dpkg/ehandle.h
+++ b/lib/dpkg/ehandle.h
@@ -40,13 +40,18 @@ enum {
        ehflag_recursiveerror = 04
 };
 
+typedef void error_handler(void);
 typedef void error_printer(const char *emsg, const char *contextstring);
 
 void print_fatal_error(const char *emsg, const char *contextstring);
 void catch_fatal_error(void);
 
-void push_error_handler(jmp_buf *jbufp, error_printer *printerror,
-                        const char *contextstring);
+#define push_error_handler push_error_context_jump
+
+void push_error_context_jump(jmp_buf *jbufp, error_printer *printerror,
+                             const char *contextstring);
+void push_error_context_func(error_handler *func, error_printer *printerror,
+                             const char *contextstring);
 void error_unwind(int flagset);
 void set_error_display(error_printer *printerror, const char *contextstring);
 
diff --git a/lib/dpkg/libdpkg.Versions b/lib/dpkg/libdpkg.Versions
index 1e9a25d..0850328 100644
--- a/lib/dpkg/libdpkg.Versions
+++ b/lib/dpkg/libdpkg.Versions
@@ -9,10 +9,11 @@ local:
 
 LIBDPKG_PRIVATE {
        # Error handling
+       push_error_context_jump;
+       push_error_context_func;
        set_error_display;
        print_fatal_error;
        catch_fatal_error;
-       push_error_handler;
        push_checkpoint;
        push_cleanup;
        pop_cleanup;

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to debian-dpkg-cvs-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to