Skip to content
Snippets Groups Projects
Commit 827b0813 authored by Markus Armbruster's avatar Markus Armbruster
Browse files

error: Infrastructure to track locations for error reporting

New struct Location holds a location.  So far, the only location is
LOC_NONE, so this doesn't do anything useful yet.

Passing the current location all over the place would be too
cumbersome.  Hide it away in static cur_loc instead, and provide
accessors.  Print it in error_report().

Store it in QError, and print it in qerror_print().

Store it in QemuOpt, for use by qemu_opts_foreach().  This makes
error_report() do the right thing when it runs within
qemu_opts_foreach().

We may still have to store it in other data structures holding user
input for better error messages.  Left for another day.
parent ab5b027e
No related branches found
No related tags found
No related merge requests found
......@@ -41,15 +41,98 @@ void error_printf(const char *fmt, ...)
va_end(ap);
}
static Location std_loc = {
.kind = LOC_NONE
};
static Location *cur_loc = &std_loc;
/*
* Push location saved in LOC onto the location stack, return it.
* The top of that stack is the current location.
* Needs a matching loc_pop().
*/
Location *loc_push_restore(Location *loc)
{
assert(!loc->prev);
loc->prev = cur_loc;
cur_loc = loc;
return loc;
}
/*
* Initialize *LOC to "nowhere", push it onto the location stack.
* The top of that stack is the current location.
* Needs a matching loc_pop().
* Return LOC.
*/
Location *loc_push_none(Location *loc)
{
loc->kind = LOC_NONE;
loc->prev = NULL;
return loc_push_restore(loc);
}
/*
* Pop the location stack.
* LOC must be the current location, i.e. the top of the stack.
*/
Location *loc_pop(Location *loc)
{
assert(cur_loc == loc && loc->prev);
cur_loc = loc->prev;
loc->prev = NULL;
return loc;
}
/*
* Save the current location in LOC, return LOC.
*/
Location *loc_save(Location *loc)
{
*loc = *cur_loc;
loc->prev = NULL;
return loc;
}
/*
* Change the current location to the one saved in LOC.
*/
void loc_restore(Location *loc)
{
Location *prev = cur_loc->prev;
assert(!loc->prev);
*cur_loc = *loc;
cur_loc->prev = prev;
}
/*
* Change the current location to "nowhere in particular".
*/
void loc_set_none(void)
{
cur_loc->kind = LOC_NONE;
}
/*
* Print current location to current monitor if we have one, else to stderr.
*/
void error_print_loc(void)
{
switch (cur_loc->kind) {
default: ;
}
}
/*
* Print an error message to current monitor if we have one, else to stderr.
* Appends a newline to the message.
* Prepend the current location and append a newline.
* It's wrong to call this in a QMP monitor. Use qerror_report() there.
*/
void error_report(const char *fmt, ...)
{
va_list ap;
error_print_loc();
va_start(ap, fmt);
error_vprintf(fmt, ap);
va_end(ap);
......
......@@ -13,8 +13,24 @@
#ifndef QEMU_ERROR_H
#define QEMU_ERROR_H
typedef struct Location {
/* all members are private to qemu-error.c */
enum { LOC_NONE } kind;
int num;
const void *ptr;
struct Location *prev;
} Location;
Location *loc_push_restore(Location *loc);
Location *loc_push_none(Location *loc);
Location *loc_pop(Location *loc);
Location *loc_save(Location *loc);
void loc_restore(Location *loc);
void loc_set_none(void);
void error_vprintf(const char *fmt, va_list ap);
void error_printf(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
void error_print_loc(void);
void error_report(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
void qerror_report_internal(const char *file, int linenr, const char *func,
const char *fmt, ...)
......
......@@ -27,6 +27,7 @@
#include <string.h>
#include "qemu-common.h"
#include "qemu-error.h"
#include "qemu-option.h"
/*
......@@ -483,6 +484,7 @@ struct QemuOpt {
struct QemuOpts {
char *id;
QemuOptsList *list;
Location loc;
QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
QTAILQ_ENTRY(QemuOpts) next;
};
......@@ -653,6 +655,7 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exist
opts->id = qemu_strdup(id);
}
opts->list = list;
loc_save(&opts->loc);
QTAILQ_INIT(&opts->head);
QTAILQ_INSERT_TAIL(&list->head, opts, next);
return opts;
......@@ -810,13 +813,17 @@ int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
int abort_on_failure)
{
Location loc;
QemuOpts *opts;
int rc = 0;
loc_push_none(&loc);
QTAILQ_FOREACH(opts, &list->head, next) {
loc_restore(&opts->loc);
rc |= func(opts, opaque);
if (abort_on_failure && rc != 0)
break;
}
loc_pop(&loc);
return rc;
}
......@@ -104,6 +104,30 @@ int64_t qemu_get_clock(QEMUClock *clock)
return (tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000)) / 1000000;
}
Location *loc_push_restore(Location *loc)
{
return loc;
}
Location *loc_push_none(Location *loc)
{
return loc;
}
Location *loc_pop(Location *loc)
{
return loc;
}
Location *loc_save(Location *loc)
{
return loc;
}
void loc_restore(Location *loc)
{
}
void error_report(const char *fmt, ...)
{
va_list args;
......
......@@ -224,6 +224,7 @@ QError *qerror_from_info(const char *file, int linenr, const char *func,
QError *qerr;
qerr = qerror_new();
loc_save(&qerr->loc);
qerr->linenr = linenr;
qerr->file = file;
qerr->func = func;
......@@ -321,10 +322,12 @@ QString *qerror_human(const QError *qerror)
* it uses error_report() for this, so that the output is routed to the right
* place (ie. stderr or Monitor's device).
*/
void qerror_print(const QError *qerror)
void qerror_print(QError *qerror)
{
QString *qstring = qerror_human(qerror);
loc_push_restore(&qerror->loc);
error_report("%s", qstring_get_str(qstring));
loc_pop(&qerror->loc);
QDECREF(qstring);
}
......
......@@ -14,6 +14,7 @@
#include "qdict.h"
#include "qstring.h"
#include "qemu-error.h"
#include <stdarg.h>
typedef struct QErrorStringTable {
......@@ -24,6 +25,7 @@ typedef struct QErrorStringTable {
typedef struct QError {
QObject_HEAD;
QDict *error;
Location loc;
int linenr;
const char *file;
const char *func;
......@@ -34,7 +36,7 @@ QError *qerror_new(void);
QError *qerror_from_info(const char *file, int linenr, const char *func,
const char *fmt, va_list *va);
QString *qerror_human(const QError *qerror);
void qerror_print(const QError *qerror);
void qerror_print(QError *qerror);
QError *qobject_to_qerror(const QObject *obj);
/*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment