Statistics
| Branch: | Revision:

root / qemu-error.c @ 0167f772

History | View | Annotate | Download (4.3 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
void 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

    
55
static Location std_loc = {
56
    .kind = LOC_NONE
57
};
58
static 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
 */
65
Location *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
 */
79
Location *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
 */
90
Location *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
 */
101
Location *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
 */
111
void 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
 */
122
void 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
 */
130
void 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
 */
140
void 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

    
150
static const char *progname;
151

    
152
/*
153
 * Set the program name for error_print_loc().
154
 */
155
void 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
 */
164
void 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
 */
200
void 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
}