4 * Copyright (C) 2010 Red Hat Inc.
7 * Markus Armbruster <armbru@redhat.com>,
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.
13 #include "qemu/osdep.h"
14 #include "monitor/monitor.h"
15 #include "qemu/error-report.h"
18 * @report_type is the type of message: error, warning or
27 /* Prepend timestamp to messages */
28 bool error_with_timestamp
;
29 bool error_with_guestname
;
30 const char *error_guest_name
;
32 int error_printf(const char *fmt
, ...)
38 ret
= error_vprintf(fmt
, ap
);
43 int error_printf_unless_qmp(const char *fmt
, ...)
49 ret
= error_vprintf_unless_qmp(fmt
, ap
);
54 static Location std_loc
= {
57 static Location
*cur_loc
= &std_loc
;
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().
64 Location
*loc_push_restore(Location
*loc
)
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().
78 Location
*loc_push_none(Location
*loc
)
82 return loc_push_restore(loc
);
86 * Pop the location stack.
87 * LOC must be the current location, i.e. the top of the stack.
89 Location
*loc_pop(Location
*loc
)
91 assert(cur_loc
== loc
&& loc
->prev
);
98 * Save the current location in LOC, return LOC.
100 Location
*loc_save(Location
*loc
)
108 * Change the current location to the one saved in LOC.
110 void loc_restore(Location
*loc
)
112 Location
*prev
= cur_loc
->prev
;
115 cur_loc
->prev
= prev
;
119 * Change the current location to "nowhere in particular".
121 void loc_set_none(void)
123 cur_loc
->kind
= LOC_NONE
;
127 * Change the current location to argument ARGV[IDX..IDX+CNT-1].
129 void loc_set_cmdline(char **argv
, int idx
, int cnt
)
131 cur_loc
->kind
= LOC_CMDLINE
;
133 cur_loc
->ptr
= argv
+ idx
;
137 * Change the current location to file FNAME, line LNO.
139 void loc_set_file(const char *fname
, int lno
)
141 assert (fname
|| cur_loc
->kind
== LOC_FILE
);
142 cur_loc
->kind
= LOC_FILE
;
145 cur_loc
->ptr
= fname
;
149 static const char *progname
;
152 * Set the program name for error_print_loc().
154 static void error_set_progname(const char *argv0
)
156 const char *p
= strrchr(argv0
, '/');
157 progname
= p
? p
+ 1 : argv0
;
160 const char *error_get_progname(void)
166 * Print current location to current monitor if we have one, else to stderr.
168 static void print_loc(void)
170 const char *sep
= "";
172 const char *const *argp
;
174 if (!cur_mon
&& progname
) {
175 fprintf(stderr
, "%s:", progname
);
178 switch (cur_loc
->kind
) {
181 for (i
= 0; i
< cur_loc
->num
; i
++) {
182 error_printf("%s%s", sep
, argp
[i
]);
188 error_printf("%s:", (const char *)cur_loc
->ptr
);
190 error_printf("%d:", cur_loc
->num
);
195 error_printf("%s", sep
);
200 * Print a message to current monitor if we have one, else to stderr.
201 * @report_type is the type of message: error, warning or informational.
202 * Format arguments like vsprintf(). The resulting message should be
203 * a single phrase, with no newline or trailing punctuation.
204 * Prepend the current location and append a newline.
206 static void vreport(report_type type
, const char *fmt
, va_list ap
)
211 if (error_with_timestamp
&& !cur_mon
) {
212 g_get_current_time(&tv
);
213 timestr
= g_time_val_to_iso8601(&tv
);
214 error_printf("%s ", timestr
);
218 /* Only prepend guest name if -msg guest-name and -name guest=... are set */
219 if (error_with_guestname
&& error_guest_name
&& !cur_mon
) {
220 error_printf("%s ", error_guest_name
);
226 case REPORT_TYPE_ERROR
:
228 case REPORT_TYPE_WARNING
:
229 error_printf("warning: ");
231 case REPORT_TYPE_INFO
:
232 error_printf("info: ");
236 error_vprintf(fmt
, ap
);
241 * Print an error message to current monitor if we have one, else to stderr.
242 * Format arguments like vsprintf(). The resulting message should be
243 * a single phrase, with no newline or trailing punctuation.
244 * Prepend the current location and append a newline.
245 * It's wrong to call this in a QMP monitor. Use error_setg() there.
247 void error_vreport(const char *fmt
, va_list ap
)
249 vreport(REPORT_TYPE_ERROR
, fmt
, ap
);
253 * Print a warning message to current monitor if we have one, else to stderr.
254 * Format arguments like vsprintf(). The resulting message should be
255 * a single phrase, with no newline or trailing punctuation.
256 * Prepend the current location and append a newline.
258 void warn_vreport(const char *fmt
, va_list ap
)
260 vreport(REPORT_TYPE_WARNING
, fmt
, ap
);
264 * Print an information message to current monitor if we have one, else to
266 * Format arguments like vsprintf(). The resulting message should be
267 * a single phrase, with no newline or trailing punctuation.
268 * Prepend the current location and append a newline.
270 void info_vreport(const char *fmt
, va_list ap
)
272 vreport(REPORT_TYPE_INFO
, fmt
, ap
);
276 * Print an error message to current monitor if we have one, else to stderr.
277 * Format arguments like sprintf(). The resulting message should be
278 * a single phrase, with no newline or trailing punctuation.
279 * Prepend the current location and append a newline.
280 * It's wrong to call this in a QMP monitor. Use error_setg() there.
282 void error_report(const char *fmt
, ...)
287 vreport(REPORT_TYPE_ERROR
, fmt
, ap
);
292 * Print a warning message to current monitor if we have one, else to stderr.
293 * Format arguments like sprintf(). The resulting message should be a
294 * single phrase, with no newline or trailing punctuation.
295 * Prepend the current location and append a newline.
297 void warn_report(const char *fmt
, ...)
302 vreport(REPORT_TYPE_WARNING
, fmt
, ap
);
307 * Print an information message to current monitor if we have one, else to
309 * Format arguments like sprintf(). The resulting message should be a
310 * single phrase, with no newline or trailing punctuation.
311 * Prepend the current location and append a newline.
313 void info_report(const char *fmt
, ...)
318 vreport(REPORT_TYPE_INFO
, fmt
, ap
);
323 * Like error_report(), except print just once.
324 * If *printed is false, print the message, and flip *printed to true.
325 * Return whether the message was printed.
327 bool error_report_once_cond(bool *printed
, const char *fmt
, ...)
337 vreport(REPORT_TYPE_ERROR
, fmt
, ap
);
343 * Like warn_report(), except print just once.
344 * If *printed is false, print the message, and flip *printed to true.
345 * Return whether the message was printed.
347 bool warn_report_once_cond(bool *printed
, const char *fmt
, ...)
357 vreport(REPORT_TYPE_WARNING
, fmt
, ap
);
362 static char *qemu_glog_domains
;
364 static void qemu_log_func(const gchar
*log_domain
,
365 GLogLevelFlags log_level
,
366 const gchar
*message
,
369 switch (log_level
& G_LOG_LEVEL_MASK
) {
370 case G_LOG_LEVEL_DEBUG
:
371 case G_LOG_LEVEL_INFO
:
373 * Use same G_MESSAGES_DEBUG logic as glib to enable/disable debug
376 if (qemu_glog_domains
== NULL
) {
379 if (strcmp(qemu_glog_domains
, "all") != 0 &&
380 (log_domain
== NULL
|| !strstr(qemu_glog_domains
, log_domain
))) {
384 case G_LOG_LEVEL_MESSAGE
:
385 info_report("%s%s%s",
386 log_domain
?: "", log_domain
? ": " : "", message
);
389 case G_LOG_LEVEL_WARNING
:
390 warn_report("%s%s%s",
391 log_domain
?: "", log_domain
? ": " : "", message
);
393 case G_LOG_LEVEL_CRITICAL
:
394 case G_LOG_LEVEL_ERROR
:
395 error_report("%s%s%s",
396 log_domain
?: "", log_domain
? ": " : "", message
);
401 void error_init(const char *argv0
)
403 /* Set the program name for error_print_loc(). */
404 error_set_progname(argv0
);
407 * This sets up glib logging so libraries using it also print their logs
408 * through error_report(), warn_report(), info_report().
410 g_log_set_default_handler(qemu_log_func
, NULL
);
411 g_warn_if_fail(qemu_glog_domains
== NULL
);
412 qemu_glog_domains
= g_strdup(g_getenv("G_MESSAGES_DEBUG"));