qemu/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.h"
  15#include "sysemu.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) {
  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
 161/*
 162 * Print current location to current monitor if we have one, else to stderr.
 163 */
 164void error_print_loc(void)
 165{
 166    const char *sep = "";
 167    int i;
 168    const char *const *argp;
 169
 170    if (!cur_mon && progname) {
 171        fprintf(stderr, "%s:", progname);
 172        sep = " ";
 173    }
 174    switch (cur_loc->kind) {
 175    case LOC_CMDLINE:
 176        argp = cur_loc->ptr;
 177        for (i = 0; i < cur_loc->num; i++) {
 178            error_printf("%s%s", sep, argp[i]);
 179            sep = " ";
 180        }
 181        error_printf(": ");
 182        break;
 183    case LOC_FILE:
 184        error_printf("%s:", (const char *)cur_loc->ptr);
 185        if (cur_loc->num) {
 186            error_printf("%d:", cur_loc->num);
 187        }
 188        error_printf(" ");
 189        break;
 190    default:
 191        error_printf("%s", sep);
 192    }
 193}
 194
 195/*
 196 * Print an error message to current monitor if we have one, else to stderr.
 197 * Prepend the current location and append a newline.
 198 * It's wrong to call this in a QMP monitor.  Use qerror_report() there.
 199 */
 200void error_report(const char *fmt, ...)
 201{
 202    va_list ap;
 203
 204    error_print_loc();
 205    va_start(ap, fmt);
 206    error_vprintf(fmt, ap);
 207    va_end(ap);
 208    error_printf("\n");
 209}
 210