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