Statistics
| Branch: | Revision:

root / qemu-error.c @ a74cdab4

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

    
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
 */
21
void 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
 */
34
void 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

    
43
void 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

    
54
static Location std_loc = {
55
    .kind = LOC_NONE
56
};
57
static 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
 */
64
Location *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
 */
78
Location *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
 */
89
Location *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
 */
100
Location *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
 */
110
void 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
 */
121
void 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
 */
129
void 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
 */
139
void 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

    
149
static const char *progname;
150

    
151
/*
152
 * Set the program name for error_print_loc().
153
 */
154
void error_set_progname(const char *argv0)
155
{
156
    const char *p = strrchr(argv0, '/');
157
    progname = p ? p + 1 : argv0;
158
}
159

    
160
/*
161
 * Print current location to current monitor if we have one, else to stderr.
162
 */
163
void error_print_loc(void)
164
{
165
    const char *sep = "";
166
    int i;
167
    const char *const *argp;
168

    
169
    if (!cur_mon && progname) {
170
        fprintf(stderr, "%s:", progname);
171
        sep = " ";
172
    }
173
    switch (cur_loc->kind) {
174
    case LOC_CMDLINE:
175
        argp = cur_loc->ptr;
176
        for (i = 0; i < cur_loc->num; i++) {
177
            error_printf("%s%s", sep, argp[i]);
178
            sep = " ";
179
        }
180
        error_printf(": ");
181
        break;
182
    case LOC_FILE:
183
        error_printf("%s:", (const char *)cur_loc->ptr);
184
        if (cur_loc->num) {
185
            error_printf("%d:", cur_loc->num);
186
        }
187
        error_printf(" ");
188
        break;
189
    default:
190
        error_printf("%s", sep);
191
    }
192
}
193

    
194
/*
195
 * Print an error message to current monitor if we have one, else to stderr.
196
 * Prepend the current location and append a newline.
197
 * It's wrong to call this in a QMP monitor.  Use qerror_report() there.
198
 */
199
void error_report(const char *fmt, ...)
200
{
201
    va_list ap;
202

    
203
    error_print_loc();
204
    va_start(ap, fmt);
205
    error_vprintf(fmt, ap);
206
    va_end(ap);
207
    error_printf("\n");
208
}