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