qemu/util/qemu-error.c
<<
>>
Prefs
   1/*
   2 * Error reporting
   3 *
   4 * Copyright (C) 2010 Red Hat Inc.
   5 *
   6 * Authors:
   7 *  Markus Armbruster <armbru@redhat.com>,
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10 * See the COPYING file in the top-level directory.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "monitor/monitor.h"
  15#include "qemu/error-report.h"
  16
  17/*
  18 * Print to current monitor if we have one, else to stderr.
  19 * TODO should return int, so callers can calculate width, but that
  20 * requires surgery to monitor_vprintf().  Left for another day.
  21 */
  22void error_vprintf(const char *fmt, va_list ap)
  23{
  24    if (cur_mon && !monitor_cur_is_qmp()) {
  25        monitor_vprintf(cur_mon, fmt, ap);
  26    } else {
  27        vfprintf(stderr, fmt, ap);
  28    }
  29}
  30
  31/*
  32 * Print to current monitor if we have one, else to stderr.
  33 * TODO just like error_vprintf()
  34 */
  35void error_printf(const char *fmt, ...)
  36{
  37    va_list ap;
  38
  39    va_start(ap, fmt);
  40    error_vprintf(fmt, ap);
  41    va_end(ap);
  42}
  43
  44void error_printf_unless_qmp(const char *fmt, ...)
  45{
  46    va_list ap;
  47
  48    if (!monitor_cur_is_qmp()) {
  49        va_start(ap, fmt);
  50        error_vprintf(fmt, ap);
  51        va_end(ap);
  52    }
  53}
  54
  55static Location std_loc = {
  56    .kind = LOC_NONE
  57};
  58static Location *cur_loc = &std_loc;
  59
  60/*
  61 * Push location saved in LOC onto the location stack, return it.
  62 * The top of that stack is the current location.
  63 * Needs a matching loc_pop().
  64 */
  65Location *loc_push_restore(Location *loc)
  66{
  67    assert(!loc->prev);
  68    loc->prev = cur_loc;
  69    cur_loc = loc;
  70    return loc;
  71}
  72
  73/*
  74 * Initialize *LOC to "nowhere", push it onto the location stack.
  75 * The top of that stack is the current location.
  76 * Needs a matching loc_pop().
  77 * Return LOC.
  78 */
  79Location *loc_push_none(Location *loc)
  80{
  81    loc->kind = LOC_NONE;
  82    loc->prev = NULL;
  83    return loc_push_restore(loc);
  84}
  85
  86/*
  87 * Pop the location stack.
  88 * LOC must be the current location, i.e. the top of the stack.
  89 */
  90Location *loc_pop(Location *loc)
  91{
  92    assert(cur_loc == loc && loc->prev);
  93    cur_loc = loc->prev;
  94    loc->prev = NULL;
  95    return loc;
  96}
  97
  98/*
  99 * Save the current location in LOC, return LOC.
 100 */
 101Location *loc_save(Location *loc)
 102{
 103    *loc = *cur_loc;
 104    loc->prev = NULL;
 105    return loc;
 106}
 107
 108/*
 109 * Change the current location to the one saved in LOC.
 110 */
 111void loc_restore(Location *loc)
 112{
 113    Location *prev = cur_loc->prev;
 114    assert(!loc->prev);
 115    *cur_loc = *loc;
 116    cur_loc->prev = prev;
 117}
 118
 119/*
 120 * Change the current location to "nowhere in particular".
 121 */
 122void loc_set_none(void)
 123{
 124    cur_loc->kind = LOC_NONE;
 125}
 126
 127/*
 128 * Change the current location to argument ARGV[IDX..IDX+CNT-1].
 129 */
 130void loc_set_cmdline(char **argv, int idx, int cnt)
 131{
 132    cur_loc->kind = LOC_CMDLINE;
 133    cur_loc->num = cnt;
 134    cur_loc->ptr = argv + idx;
 135}
 136
 137/*
 138 * Change the current location to file FNAME, line LNO.
 139 */
 140void loc_set_file(const char *fname, int lno)
 141{
 142    assert (fname || cur_loc->kind == LOC_FILE);
 143    cur_loc->kind = LOC_FILE;
 144    cur_loc->num = lno;
 145    if (fname) {
 146        cur_loc->ptr = fname;
 147    }
 148}
 149
 150static const char *progname;
 151
 152/*
 153 * Set the program name for error_print_loc().
 154 */
 155void error_set_progname(const char *argv0)
 156{
 157    const char *p = strrchr(argv0, '/');
 158    progname = p ? p + 1 : argv0;
 159}
 160
 161const char *error_get_progname(void)
 162{
 163    return progname;
 164}
 165
 166/*
 167 * Print current location to current monitor if we have one, else to stderr.
 168 */
 169static void error_print_loc(void)
 170{
 171    const char *sep = "";
 172    int i;
 173    const char *const *argp;
 174
 175    if (!cur_mon && progname) {
 176        fprintf(stderr, "%s:", progname);
 177        sep = " ";
 178    }
 179    switch (cur_loc->kind) {
 180    case LOC_CMDLINE:
 181        argp = cur_loc->ptr;
 182        for (i = 0; i < cur_loc->num; i++) {
 183            error_printf("%s%s", sep, argp[i]);
 184            sep = " ";
 185        }
 186        error_printf(": ");
 187        break;
 188    case LOC_FILE:
 189        error_printf("%s:", (const char *)cur_loc->ptr);
 190        if (cur_loc->num) {
 191            error_printf("%d:", cur_loc->num);
 192        }
 193        error_printf(" ");
 194        break;
 195    default:
 196        error_printf("%s", sep);
 197    }
 198}
 199
 200bool enable_timestamp_msg;
 201/*
 202 * Print an error message to current monitor if we have one, else to stderr.
 203 * Format arguments like vsprintf().  The resulting message should be
 204 * a single phrase, with no newline or trailing punctuation.
 205 * Prepend the current location and append a newline.
 206 * It's wrong to call this in a QMP monitor.  Use error_setg() there.
 207 */
 208void error_vreport(const char *fmt, va_list ap)
 209{
 210    GTimeVal tv;
 211    gchar *timestr;
 212
 213    if (enable_timestamp_msg && !cur_mon) {
 214        g_get_current_time(&tv);
 215        timestr = g_time_val_to_iso8601(&tv);
 216        error_printf("%s ", timestr);
 217        g_free(timestr);
 218    }
 219
 220    error_print_loc();
 221    error_vprintf(fmt, ap);
 222    error_printf("\n");
 223}
 224
 225/*
 226 * Print an error message to current monitor if we have one, else to stderr.
 227 * Format arguments like sprintf().  The resulting message should be a
 228 * single phrase, with no newline or trailing punctuation.
 229 * Prepend the current location and append a newline.
 230 * It's wrong to call this in a QMP monitor.  Use error_setg() there.
 231 */
 232void error_report(const char *fmt, ...)
 233{
 234    va_list ap;
 235
 236    va_start(ap, fmt);
 237    error_vreport(fmt, ap);
 238    va_end(ap);
 239}
 240