Statistics
| Branch: | Revision:

root / qemu-error.c @ 65abca0a

History | View | Annotate | Download (3.5 kB)

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
 */
22
void 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
 */
35
void 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

    
44
static Location std_loc = {
45
    .kind = LOC_NONE
46
};
47
static Location *cur_loc = &std_loc;
48

    
49
/*
50
 * Push location saved in LOC onto the location stack, return it.
51
 * The top of that stack is the current location.
52
 * Needs a matching loc_pop().
53
 */
54
Location *loc_push_restore(Location *loc)
55
{
56
    assert(!loc->prev);
57
    loc->prev = cur_loc;
58
    cur_loc = loc;
59
    return loc;
60
}
61

    
62
/*
63
 * Initialize *LOC to "nowhere", push it onto the location stack.
64
 * The top of that stack is the current location.
65
 * Needs a matching loc_pop().
66
 * Return LOC.
67
 */
68
Location *loc_push_none(Location *loc)
69
{
70
    loc->kind = LOC_NONE;
71
    loc->prev = NULL;
72
    return loc_push_restore(loc);
73
}
74

    
75
/*
76
 * Pop the location stack.
77
 * LOC must be the current location, i.e. the top of the stack.
78
 */
79
Location *loc_pop(Location *loc)
80
{
81
    assert(cur_loc == loc && loc->prev);
82
    cur_loc = loc->prev;
83
    loc->prev = NULL;
84
    return loc;
85
}
86

    
87
/*
88
 * Save the current location in LOC, return LOC.
89
 */
90
Location *loc_save(Location *loc)
91
{
92
    *loc = *cur_loc;
93
    loc->prev = NULL;
94
    return loc;
95
}
96

    
97
/*
98
 * Change the current location to the one saved in LOC.
99
 */
100
void loc_restore(Location *loc)
101
{
102
    Location *prev = cur_loc->prev;
103
    assert(!loc->prev);
104
    *cur_loc = *loc;
105
    cur_loc->prev = prev;
106
}
107

    
108
/*
109
 * Change the current location to "nowhere in particular".
110
 */
111
void loc_set_none(void)
112
{
113
    cur_loc->kind = LOC_NONE;
114
}
115

    
116
static const char *progname;
117

    
118
/*
119
 * Set the program name for error_print_loc().
120
 */
121
void error_set_progname(const char *argv0)
122
{
123
    const char *p = strrchr(argv0, '/');
124
    progname = p ? p + 1 : argv0;
125
}
126

    
127
/*
128
 * Print current location to current monitor if we have one, else to stderr.
129
 */
130
void error_print_loc(void)
131
{
132
    const char *sep = "";
133

    
134
    if (!cur_mon) {
135
        fprintf(stderr, "%s:", progname);
136
        sep = " ";
137
    }
138
    switch (cur_loc->kind) {
139
    default:
140
        error_printf(sep);
141
    }
142
}
143

    
144
/*
145
 * Print an error message to current monitor if we have one, else to stderr.
146
 * Prepend the current location and append a newline.
147
 * It's wrong to call this in a QMP monitor.  Use qerror_report() there.
148
 */
149
void error_report(const char *fmt, ...)
150
{
151
    va_list ap;
152

    
153
    error_print_loc();
154
    va_start(ap, fmt);
155
    error_vprintf(fmt, ap);
156
    va_end(ap);
157
    error_printf("\n");
158
}
159

    
160
void qerror_report_internal(const char *file, int linenr, const char *func,
161
                            const char *fmt, ...)
162
{
163
    va_list va;
164
    QError *qerror;
165

    
166
    va_start(va, fmt);
167
    qerror = qerror_from_info(file, linenr, func, fmt, &va);
168
    va_end(va);
169

    
170
    if (cur_mon) {
171
        monitor_set_error(cur_mon, qerror);
172
    } else {
173
        qerror_print(qerror);
174
        QDECREF(qerror);
175
    }
176
}