Let error routine be a stack of error functions so that callers can
temporarily override the error_routine and then pop their modification
off the stack. This enables customizing error for a small code segment.

Signed-off-by: Jacob Keller <jacob.e.kel...@intel.com>
This is a modification of Peff's original idea for handling multiple error
routines. I simplified it by not having the collect and other routines. I only
modify set_error_routine to be a "push" operation, with pop_error_routine being
its opposite. I don't let pop_error_routine remove all the error routines,
instead only doing one with an assert check that we never call it too many 

This enables temporarily modifying the error routine and then popping back to
the previous value.

 git-compat-util.h |  1 +
 usage.c           | 29 ++++++++++++++++++++++++++---
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/git-compat-util.h b/git-compat-util.h
index 9de318071083..6d0416c90ad8 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -344,6 +344,7 @@ static inline int const_error(void)
 extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, 
va_list params));
 extern void set_error_routine(void (*routine)(const char *err, va_list 
+extern void pop_error_routine(void);
 extern void set_die_is_recursing_routine(int (*routine)(void));
 extern int starts_with(const char *str, const char *prefix);
diff --git a/usage.c b/usage.c
index ed146453cabe..fd9126a7ca0b 100644
--- a/usage.c
+++ b/usage.c
@@ -57,18 +57,41 @@ static int die_is_recursing_builtin(void)
  * (ugh), so keep things static. */
 static NORETURN_PTR void (*usage_routine)(const char *err, va_list params) = 
 static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = 
-static void (*error_routine)(const char *err, va_list params) = error_builtin;
 static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
 static int (*die_is_recursing)(void) = die_is_recursing_builtin;
+struct error_func_list {
+       void (*func)(const char *, va_list);
+       struct error_func_list *next;
+static struct error_func_list default_error_func = { error_builtin };
+static struct error_func_list *error_funcs = &default_error_func;
 void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list 
        die_routine = routine;
+/* push error routine onto the error function stack */
 void set_error_routine(void (*routine)(const char *err, va_list params))
-       error_routine = routine;
+       struct error_func_list *efl = xmalloc(sizeof(*efl));
+       efl->func = routine;
+       efl->next = error_funcs;
+       error_funcs = efl;
+/* pop a single error routine off of the error function stack, thus reverting
+ * to previous error. Should always be paired with a set_error_routine */
+void pop_error_routine(void)
+       assert(error_funcs != &default_error_func);
+       struct error_func_list *efl = error_funcs;
+       if (efl->next) {
+               error_funcs = efl->next;
+               free(efl);
+       }
 void set_die_is_recursing_routine(int (*routine)(void))
@@ -144,7 +167,7 @@ int error(const char *err, ...)
        va_list params;
        va_start(params, err);
-       error_routine(err, params);
+       error_funcs->func(err, params);
        return -1;

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to