db_output.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* $OpenBSD: db_output.c,v 1.29 2015/03/14 03:38:46 jsg Exp $ */
  2. /* $NetBSD: db_output.c,v 1.13 1996/04/01 17:27:14 christos Exp $ */
  3. /*
  4. * Mach Operating System
  5. * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
  6. * All Rights Reserved.
  7. *
  8. * Permission to use, copy, modify and distribute this software and its
  9. * documentation is hereby granted, provided that both the copyright
  10. * notice and this permission notice appear in all copies of the
  11. * software, derivative works or modified versions, and any portions
  12. * thereof, and that both notices appear in supporting documentation.
  13. *
  14. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  15. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  16. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  17. *
  18. * Carnegie Mellon requests users of this software to return to
  19. *
  20. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  21. * School of Computer Science
  22. * Carnegie Mellon University
  23. * Pittsburgh PA 15213-3890
  24. *
  25. * any improvements or extensions that they make and grant Carnegie Mellon
  26. * the rights to redistribute these changes.
  27. */
  28. /*
  29. * Printf and character output for debugger.
  30. */
  31. #include <sys/param.h>
  32. #include <sys/stdarg.h>
  33. #include <sys/systm.h>
  34. #include <dev/cons.h>
  35. #include <machine/db_machdep.h>
  36. #include <ddb/db_command.h>
  37. #include <ddb/db_output.h>
  38. #include <ddb/db_interface.h>
  39. #include <ddb/db_sym.h>
  40. #include <ddb/db_var.h>
  41. /*
  42. * Character output - tracks position in line.
  43. * To do this correctly, we should know how wide
  44. * the output device is - then we could zero
  45. * the line position when the output device wraps
  46. * around to the start of the next line.
  47. *
  48. * Instead, we count the number of spaces printed
  49. * since the last printing character so that we
  50. * don't print trailing spaces. This avoids most
  51. * of the wraparounds.
  52. */
  53. #ifndef DB_MAX_LINE
  54. #define DB_MAX_LINE 24 /* maximum line */
  55. #define DB_MAX_WIDTH 80 /* maximum width */
  56. #endif /* DB_MAX_LINE */
  57. #define DB_MIN_MAX_WIDTH 20 /* minimum max width */
  58. #define DB_MIN_MAX_LINE 3 /* minimum max line */
  59. #define CTRL(c) ((c) & 0xff)
  60. int db_output_position = 0; /* output column */
  61. int db_output_line = 0; /* output line number */
  62. int db_last_non_space = 0; /* last non-space character */
  63. int db_tab_stop_width = 8; /* how wide are tab stops? */
  64. #define NEXT_TAB(i) \
  65. ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
  66. int db_max_line = DB_MAX_LINE; /* output max lines */
  67. int db_max_width = DB_MAX_WIDTH; /* output line width */
  68. int db_radix = 16; /* output numbers radix */
  69. static void db_more(void);
  70. /*
  71. * Force pending whitespace.
  72. */
  73. void
  74. db_force_whitespace(void)
  75. {
  76. int last_print, next_tab;
  77. last_print = db_last_non_space;
  78. while (last_print < db_output_position) {
  79. next_tab = NEXT_TAB(last_print);
  80. if (next_tab <= db_output_position) {
  81. while (last_print < next_tab) { /* DON'T send a tab!!! */
  82. cnputc(' ');
  83. last_print++;
  84. }
  85. }
  86. else {
  87. cnputc(' ');
  88. last_print++;
  89. }
  90. }
  91. db_last_non_space = db_output_position;
  92. }
  93. static void
  94. db_more(void)
  95. {
  96. char *p;
  97. int quit_output = 0;
  98. for (p = "--db_more--"; *p; p++)
  99. cnputc(*p);
  100. switch(cngetc()) {
  101. case ' ':
  102. db_output_line = 0;
  103. break;
  104. case 'q':
  105. case CTRL('c'):
  106. db_output_line = 0;
  107. quit_output = 1;
  108. break;
  109. default:
  110. db_output_line--;
  111. break;
  112. }
  113. p = "\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b";
  114. while (*p)
  115. cnputc(*p++);
  116. if (quit_output) {
  117. db_error(0);
  118. /* NOTREACHED */
  119. }
  120. }
  121. /*
  122. * Output character. Buffer whitespace.
  123. */
  124. void
  125. db_putchar(int c)
  126. {
  127. if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1)
  128. db_more();
  129. if (c > ' ' && c <= '~') {
  130. /*
  131. * Printing character.
  132. * If we have spaces to print, print them first.
  133. * Use tabs if possible.
  134. */
  135. db_force_whitespace();
  136. cnputc(c);
  137. db_output_position++;
  138. if (db_max_width >= DB_MIN_MAX_WIDTH
  139. && db_output_position >= db_max_width-1) {
  140. /* auto new line */
  141. cnputc('\n');
  142. db_output_position = 0;
  143. db_last_non_space = 0;
  144. db_output_line++;
  145. }
  146. db_last_non_space = db_output_position;
  147. }
  148. else if (c == '\n') {
  149. /* Return */
  150. cnputc(c);
  151. db_output_position = 0;
  152. db_last_non_space = 0;
  153. db_output_line++;
  154. }
  155. else if (c == '\t') {
  156. /* assume tabs every 8 positions */
  157. db_output_position = NEXT_TAB(db_output_position);
  158. }
  159. else if (c == ' ') {
  160. /* space */
  161. db_output_position++;
  162. }
  163. else if (c == '\007') {
  164. /* bell */
  165. cnputc(c);
  166. }
  167. /* other characters are assumed non-printing */
  168. }
  169. /*
  170. * Return output position
  171. */
  172. int
  173. db_print_position(void)
  174. {
  175. return (db_output_position);
  176. }
  177. /*
  178. * End line if too long.
  179. */
  180. void
  181. db_end_line(int space)
  182. {
  183. if (db_output_position >= db_max_width - space)
  184. db_printf("\n");
  185. }
  186. char *
  187. db_format(char *buf, size_t bufsize, long val, int format, int alt, int width)
  188. {
  189. const char *fmt;
  190. if (format == DB_FORMAT_Z || db_radix == 16)
  191. fmt = alt ? "-%#*lx" : "-%*lx";
  192. else if (db_radix == 8)
  193. fmt = alt ? "-%#*lo" : "-%*lo";
  194. else
  195. fmt = alt ? "-%#*lu" : "-%*lu";
  196. /* The leading '-' is a nasty (and beautiful) idea from NetBSD */
  197. if (val < 0 && format != DB_FORMAT_N)
  198. val = -val;
  199. else
  200. fmt++;
  201. snprintf(buf, bufsize, fmt, width, val);
  202. return (buf);
  203. }
  204. void
  205. db_stack_dump(void)
  206. {
  207. static int intrace;
  208. if (intrace) {
  209. printf("Faulted in traceback, aborting...\n");
  210. return;
  211. }
  212. intrace = 1;
  213. printf("Starting stack trace...\n");
  214. db_stack_trace_print((db_expr_t)__builtin_frame_address(0), TRUE,
  215. 256 /* low limit */, "", printf);
  216. printf("End of stack trace.\n");
  217. intrace = 0;
  218. }