diff options
-rw-r--r-- | include/qapi/error.h | 31 | ||||
-rw-r--r-- | util/error.c | 33 |
2 files changed, 62 insertions, 2 deletions
diff --git a/include/qapi/error.h b/include/qapi/error.h index b18a608..45d6c72 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -31,6 +31,9 @@ * error_report_err(err); * This frees the error object. * + * Report an error to stderr with additional text prepended: + * error_reportf_err(err, "Could not frobnicate '%s': ", name); + * * Report an error somewhere else: * const char *msg = error_get_pretty(err); * do with msg what needs to be done... @@ -48,6 +51,10 @@ * error_propagate(errp, err); * where Error **errp is a parameter, by convention the last one. * + * Pass an existing error to the caller with the message modified: + * error_propagate(errp, err); + * error_prepend(errp, "Could not frobnicate '%s': ", name); + * * Create a new error and pass it to the caller: * error_setg(errp, "situation normal, all fouled up"); * @@ -108,9 +115,10 @@ #ifndef ERROR_H #define ERROR_H +#include <stdarg.h> +#include <stdbool.h> #include "qemu/compiler.h" #include "qapi-types.h" -#include <stdbool.h> /* * Opaque error object. @@ -208,7 +216,20 @@ void error_setg_win32_internal(Error **errp, */ void error_propagate(Error **dst_errp, Error *local_err); -/** +/* + * Prepend some text to @errp's human-readable error message. + * The text is made by formatting @fmt, @ap like vprintf(). + */ +void error_vprepend(Error **errp, const char *fmt, va_list ap); + +/* + * Prepend some text to @errp's human-readable error message. + * The text is made by formatting @fmt, ... like printf(). + */ +void error_prepend(Error **errp, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + +/* * Append a printf-style human-readable explanation to an existing error. * @errp may be NULL, but not &error_fatal or &error_abort. * Trivially the case if you call it only after error_setg() or @@ -251,6 +272,12 @@ void error_free_or_abort(Error **errp); void error_report_err(Error *err); /* + * Convenience function to error_prepend(), error_report() and free @err. + */ +void error_reportf_err(Error *err, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + +/* * Just like error_setg(), except you get to specify the error class. * Note: use of error classes other than ERROR_CLASS_GENERIC_ERROR is * strongly discouraged. diff --git a/util/error.c b/util/error.c index ebfb74b..57303fd 100644 --- a/util/error.c +++ b/util/error.c @@ -122,6 +122,29 @@ void error_setg_file_open_internal(Error **errp, "Could not open '%s'", filename); } +void error_vprepend(Error **errp, const char *fmt, va_list ap) +{ + GString *newmsg; + + if (!errp) { + return; + } + + newmsg = g_string_new(NULL); + g_string_vprintf(newmsg, fmt, ap); + g_string_append(newmsg, (*errp)->msg); + (*errp)->msg = g_string_free(newmsg, 0); +} + +void error_prepend(Error **errp, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_vprepend(errp, fmt, ap); + va_end(ap); +} + void error_append_hint(Error **errp, const char *fmt, ...) { va_list ap; @@ -209,6 +232,16 @@ void error_report_err(Error *err) error_free(err); } +void error_reportf_err(Error *err, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_vprepend(&err, fmt, ap); + va_end(ap); + error_report_err(err); +} + void error_free(Error *err) { if (err) { |