summaryrefslogtreecommitdiff
path: root/usage.c
diff options
context:
space:
mode:
Diffstat (limited to 'usage.c')
-rw-r--r--usage.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/usage.c b/usage.c
index 58fb5fff5f..1b206de36d 100644
--- a/usage.c
+++ b/usage.c
@@ -81,6 +81,12 @@ static void error_builtin(const char *err, va_list params)
static void warn_builtin(const char *warn, va_list params)
{
+ /*
+ * We call this trace2 function first and expect it to va_copy 'params'
+ * before using it (because an 'ap' can only be walked once).
+ */
+ trace2_cmd_error_va(warn, params);
+
vreportf("warning: ", warn, params);
}
@@ -108,33 +114,33 @@ static int die_is_recursing_builtin(void)
/* If we are in a dlopen()ed .so write to a global variable would segfault
* (ugh), so keep things static. */
-static NORETURN_PTR void (*usage_routine)(const char *err, va_list params) = usage_builtin;
-static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = die_builtin;
-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 NORETURN_PTR report_fn usage_routine = usage_builtin;
+static NORETURN_PTR report_fn die_routine = die_builtin;
+static report_fn error_routine = error_builtin;
+static report_fn warn_routine = warn_builtin;
static int (*die_is_recursing)(void) = die_is_recursing_builtin;
-void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params))
+void set_die_routine(NORETURN_PTR report_fn routine)
{
die_routine = routine;
}
-void set_error_routine(void (*routine)(const char *err, va_list params))
+void set_error_routine(report_fn routine)
{
error_routine = routine;
}
-void (*get_error_routine(void))(const char *err, va_list params)
+report_fn get_error_routine(void)
{
return error_routine;
}
-void set_warn_routine(void (*routine)(const char *warn, va_list params))
+void set_warn_routine(report_fn routine)
{
warn_routine = routine;
}
-void (*get_warn_routine(void))(const char *warn, va_list params)
+report_fn get_warn_routine(void)
{
return warn_routine;
}
@@ -260,6 +266,10 @@ int BUG_exit_code;
static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params)
{
char prefix[256];
+ va_list params_copy;
+ static int in_bug;
+
+ va_copy(params_copy, params);
/* truncation via snprintf is OK here */
if (file)
@@ -268,6 +278,13 @@ static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_lis
snprintf(prefix, sizeof(prefix), "BUG: ");
vreportf(prefix, fmt, params);
+
+ if (in_bug)
+ abort();
+ in_bug = 1;
+
+ trace2_cmd_error_va(fmt, params_copy);
+
if (BUG_exit_code)
exit(BUG_exit_code);
abort();