2
0

qemu-error.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. #include <stdio.h>
  13. #include "monitor.h"
  14. /*
  15. * Print to current monitor if we have one, else to stderr.
  16. * TODO should return int, so callers can calculate width, but that
  17. * requires surgery to monitor_vprintf(). Left for another day.
  18. */
  19. void error_vprintf(const char *fmt, va_list ap)
  20. {
  21. if (cur_mon) {
  22. monitor_vprintf(cur_mon, fmt, ap);
  23. } else {
  24. vfprintf(stderr, fmt, ap);
  25. }
  26. }
  27. /*
  28. * Print to current monitor if we have one, else to stderr.
  29. * TODO just like error_vprintf()
  30. */
  31. void error_printf(const char *fmt, ...)
  32. {
  33. va_list ap;
  34. va_start(ap, fmt);
  35. error_vprintf(fmt, ap);
  36. va_end(ap);
  37. }
  38. void error_printf_unless_qmp(const char *fmt, ...)
  39. {
  40. va_list ap;
  41. if (!monitor_cur_is_qmp()) {
  42. va_start(ap, fmt);
  43. error_vprintf(fmt, ap);
  44. va_end(ap);
  45. }
  46. }
  47. static Location std_loc = {
  48. .kind = LOC_NONE
  49. };
  50. static Location *cur_loc = &std_loc;
  51. /*
  52. * Push location saved in LOC onto the location stack, return it.
  53. * The top of that stack is the current location.
  54. * Needs a matching loc_pop().
  55. */
  56. Location *loc_push_restore(Location *loc)
  57. {
  58. assert(!loc->prev);
  59. loc->prev = cur_loc;
  60. cur_loc = loc;
  61. return loc;
  62. }
  63. /*
  64. * Initialize *LOC to "nowhere", push it onto the location stack.
  65. * The top of that stack is the current location.
  66. * Needs a matching loc_pop().
  67. * Return LOC.
  68. */
  69. Location *loc_push_none(Location *loc)
  70. {
  71. loc->kind = LOC_NONE;
  72. loc->prev = NULL;
  73. return loc_push_restore(loc);
  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. * Save the current location in LOC, return LOC.
  88. */
  89. Location *loc_save(Location *loc)
  90. {
  91. *loc = *cur_loc;
  92. loc->prev = NULL;
  93. return loc;
  94. }
  95. /*
  96. * Change the current location to the one saved in LOC.
  97. */
  98. void loc_restore(Location *loc)
  99. {
  100. Location *prev = cur_loc->prev;
  101. assert(!loc->prev);
  102. *cur_loc = *loc;
  103. cur_loc->prev = prev;
  104. }
  105. /*
  106. * Change the current location to "nowhere in particular".
  107. */
  108. void loc_set_none(void)
  109. {
  110. cur_loc->kind = LOC_NONE;
  111. }
  112. /*
  113. * Change the current location to argument ARGV[IDX..IDX+CNT-1].
  114. */
  115. void loc_set_cmdline(char **argv, int idx, int cnt)
  116. {
  117. cur_loc->kind = LOC_CMDLINE;
  118. cur_loc->num = cnt;
  119. cur_loc->ptr = argv + idx;
  120. }
  121. /*
  122. * Change the current location to file FNAME, line LNO.
  123. */
  124. void loc_set_file(const char *fname, int lno)
  125. {
  126. assert (fname || cur_loc->kind == LOC_FILE);
  127. cur_loc->kind = LOC_FILE;
  128. cur_loc->num = lno;
  129. if (fname) {
  130. cur_loc->ptr = fname;
  131. }
  132. }
  133. static const char *progname;
  134. /*
  135. * Set the program name for error_print_loc().
  136. */
  137. void error_set_progname(const char *argv0)
  138. {
  139. const char *p = strrchr(argv0, '/');
  140. progname = p ? p + 1 : argv0;
  141. }
  142. const char *error_get_progname(void)
  143. {
  144. return progname;
  145. }
  146. /*
  147. * Print current location to current monitor if we have one, else to stderr.
  148. */
  149. void error_print_loc(void)
  150. {
  151. const char *sep = "";
  152. int i;
  153. const char *const *argp;
  154. if (!cur_mon && progname) {
  155. fprintf(stderr, "%s:", progname);
  156. sep = " ";
  157. }
  158. switch (cur_loc->kind) {
  159. case LOC_CMDLINE:
  160. argp = cur_loc->ptr;
  161. for (i = 0; i < cur_loc->num; i++) {
  162. error_printf("%s%s", sep, argp[i]);
  163. sep = " ";
  164. }
  165. error_printf(": ");
  166. break;
  167. case LOC_FILE:
  168. error_printf("%s:", (const char *)cur_loc->ptr);
  169. if (cur_loc->num) {
  170. error_printf("%d:", cur_loc->num);
  171. }
  172. error_printf(" ");
  173. break;
  174. default:
  175. error_printf("%s", sep);
  176. }
  177. }
  178. /*
  179. * Print an error message to current monitor if we have one, else to stderr.
  180. * Format arguments like sprintf(). The result should not contain
  181. * newlines.
  182. * Prepend the current location and append a newline.
  183. * It's wrong to call this in a QMP monitor. Use qerror_report() there.
  184. */
  185. void error_report(const char *fmt, ...)
  186. {
  187. va_list ap;
  188. error_print_loc();
  189. va_start(ap, fmt);
  190. error_vprintf(fmt, ap);
  191. va_end(ap);
  192. error_printf("\n");
  193. }