[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_output.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /*-
  2  * Mach Operating System
  3  * Copyright (c) 1991,1990 Carnegie Mellon University
  4  * All Rights Reserved.
  5  *
  6  * Permission to use, copy, modify and distribute this software and its
  7  * documentation is hereby granted, provided that both the copyright
  8  * notice and this permission notice appear in all copies of the
  9  * software, derivative works or modified versions, and any portions
 10  * thereof, and that both notices appear in supporting documentation.
 11  *
 12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
 13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 15  *
 16  * Carnegie Mellon requests users of this software to return to
 17  *
 18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 19  *  School of Computer Science
 20  *  Carnegie Mellon University
 21  *  Pittsburgh PA 15213-3890
 22  *
 23  * any improvements or extensions that they make and grant Carnegie the
 24  * rights to redistribute these changes.
 25  */
 26 /*
 27  *      Author: David B. Golub, Carnegie Mellon University
 28  *      Date:   7/90
 29  */
 30 
 31 /*
 32  * Printf and character output for debugger.
 33  */
 34 
 35 #include <sys/cdefs.h>
 36 __FBSDID("$FreeBSD: src/sys/ddb/db_output.c,v 1.40 2008/08/18 16:51:44 attilio Exp $");
 37 
 38 #include "opt_ddb.h"
 39 
 40 #include <sys/param.h>
 41 #include <sys/systm.h>
 42 #include <sys/cons.h>
 43 #include <sys/kdb.h>
 44 #include <sys/kernel.h>
 45 #include <sys/sysctl.h>
 46 
 47 #include <machine/stdarg.h>
 48 
 49 #include <ddb/ddb.h>
 50 #include <ddb/db_output.h>
 51 
 52 struct dbputchar_arg {
 53         size_t  da_nbufr;
 54         size_t  da_remain;
 55         char    *da_pbufr;
 56         char    *da_pnext;
 57 };
 58 
 59 /*
 60  *      Character output - tracks position in line.
 61  *      To do this correctly, we should know how wide
 62  *      the output device is - then we could zero
 63  *      the line position when the output device wraps
 64  *      around to the start of the next line.
 65  *
 66  *      Instead, we count the number of spaces printed
 67  *      since the last printing character so that we
 68  *      don't print trailing spaces.  This avoids most
 69  *      of the wraparounds.
 70  */
 71 static int      db_output_position = 0;         /* output column */
 72 static int      db_last_non_space = 0;          /* last non-space character */
 73 db_expr_t       db_tab_stop_width = 8;          /* how wide are tab stops? */
 74 #define NEXT_TAB(i) \
 75         ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
 76 db_expr_t       db_max_width = 79;              /* output line width */
 77 db_expr_t       db_lines_per_page = 20;         /* lines per page */
 78 volatile int    db_pager_quit;                  /* user requested quit */
 79 static int      db_newlines;                    /* # lines this page */
 80 static int      db_maxlines;                    /* max lines/page when paging */
 81 static int      ddb_use_printf = 0;
 82 SYSCTL_INT(_debug, OID_AUTO, ddb_use_printf, CTLFLAG_RW, &ddb_use_printf, 0,
 83     "use printf for all ddb output");
 84 
 85 static void     db_putc(int c);
 86 static void     db_puts(const char *str);
 87 static void     db_putchar(int c, void *arg);
 88 static void     db_pager(void);
 89 
 90 /*
 91  * Force pending whitespace.
 92  */
 93 void
 94 db_force_whitespace()
 95 {
 96         register int last_print, next_tab;
 97 
 98         last_print = db_last_non_space;
 99         while (last_print < db_output_position) {
100             next_tab = NEXT_TAB(last_print);
101             if (next_tab <= db_output_position) {
102                 while (last_print < next_tab) { /* DON'T send a tab!!! */
103                         cnputc(' ');
104                         db_capture_writech(' ');
105                         last_print++;
106                 }
107             }
108             else {
109                 cnputc(' ');
110                 db_capture_writech(' ');
111                 last_print++;
112             }
113         }
114         db_last_non_space = db_output_position;
115 }
116 
117 /*
118  * Output character.  Buffer whitespace.
119  */
120 static void
121 db_putchar(int c, void *arg)
122 {
123         struct dbputchar_arg *dap = arg;
124 
125         if (dap->da_pbufr == NULL) {
126 
127                  /* No bufferized output is provided. */
128                 db_putc(c);
129         } else {
130 
131                 *dap->da_pnext++ = c;
132                 dap->da_remain--;
133 
134                 /* Leave always the buffer 0 terminated. */
135                 *dap->da_pnext = '\0';
136 
137                 /* Check if the buffer needs to be flushed. */
138                 if (dap->da_remain < 2 || c == '\n') {
139                         db_puts(dap->da_pbufr);
140                         dap->da_pnext = dap->da_pbufr;
141                         dap->da_remain = dap->da_nbufr;
142                         *dap->da_pnext = '\0';
143                 }
144         }
145 }
146 
147 static void
148 db_putc(int c)
149 {
150 
151         /*
152          * If not in the debugger or the user requests it, output data to
153          * both the console and the message buffer.
154          */
155         if (!kdb_active || ddb_use_printf) {
156                 printf("%c", c);
157                 if (!kdb_active)
158                         return;
159                 if (c == '\r' || c == '\n')
160                         db_check_interrupt();
161                 if (c == '\n' && db_maxlines > 0) {
162                         db_newlines++;
163                         if (db_newlines >= db_maxlines)
164                                 db_pager();
165                 }
166                 return;
167         }
168 
169         /* Otherwise, output data directly to the console. */
170         if (c > ' ' && c <= '~') {
171             /*
172              * Printing character.
173              * If we have spaces to print, print them first.
174              * Use tabs if possible.
175              */
176             db_force_whitespace();
177             cnputc(c);
178             db_capture_writech(c);
179             db_output_position++;
180             db_last_non_space = db_output_position;
181         }
182         else if (c == '\n') {
183             /* Newline */
184             cnputc(c);
185             db_capture_writech(c);
186             db_output_position = 0;
187             db_last_non_space = 0;
188             db_check_interrupt();
189             if (db_maxlines > 0) {
190                     db_newlines++;
191                     if (db_newlines >= db_maxlines)
192                             db_pager();
193             }
194         }
195         else if (c == '\r') {
196             /* Return */
197             cnputc(c);
198             db_capture_writech(c);
199             db_output_position = 0;
200             db_last_non_space = 0;
201             db_check_interrupt();
202         }
203         else if (c == '\t') {
204             /* assume tabs every 8 positions */
205             db_output_position = NEXT_TAB(db_output_position);
206         }
207         else if (c == ' ') {
208             /* space */
209             db_output_position++;
210         }
211         else if (c == '\007') {
212             /* bell */
213             cnputc(c);
214             /* No need to beep in a log: db_capture_writech(c); */
215         }
216         /* other characters are assumed non-printing */
217 }
218 
219 static void
220 db_puts(const char *str)
221 {
222         int i;
223 
224         for (i = 0; str[i] != '\0'; i++)
225                 db_putc(str[i]);
226 }
227 
228 /*
229  * Turn on the pager.
230  */
231 void
232 db_enable_pager(void)
233 {
234         if (db_maxlines == 0) {
235                 db_maxlines = db_lines_per_page;
236                 db_newlines = 0;
237                 db_pager_quit = 0;
238         }
239 }
240 
241 /*
242  * Turn off the pager.
243  */
244 void
245 db_disable_pager(void)
246 {
247         db_maxlines = 0;
248 }
249 
250 /*
251  * A simple paging callout function.  It supports several simple more(1)-like
252  * commands as well as a quit command that sets db_pager_quit which db
253  * commands can poll to see if they should terminate early.
254  */
255 void
256 db_pager(void)
257 {
258         int c, done;
259 
260         db_capture_enterpager();
261         db_printf("--More--\r");
262         done = 0;
263         while (!done) {
264                 c = cngetc();
265                 switch (c) {
266                 case 'e':
267                 case 'j':
268                 case '\n':
269                         /* Just one more line. */
270                         db_maxlines = 1;
271                         done++;
272                         break;
273                 case 'd':
274                         /* Half a page. */
275                         db_maxlines = db_lines_per_page / 2;
276                         done++;
277                         break;
278                 case 'f':
279                 case ' ':
280                         /* Another page. */
281                         db_maxlines = db_lines_per_page;
282                         done++;
283                         break;
284                 case 'q':
285                 case 'Q':
286                 case 'x':
287                 case 'X':
288                         /* Quit */
289                         db_maxlines = 0;
290                         db_pager_quit = 1;
291                         done++;
292                         break;
293 #if 0
294                         /* FALLTHROUGH */
295                 default:
296                         cnputc('\007');
297 #endif
298                 }
299         }
300         db_printf("        ");
301         db_force_whitespace();
302         db_printf("\r");
303         db_newlines = 0;
304         db_capture_exitpager();
305 }
306 
307 /*
308  * Return output position
309  */
310 int
311 db_print_position()
312 {
313         return (db_output_position);
314 }
315 
316 /*
317  * Printing
318  */
319 void
320 db_printf(const char *fmt, ...)
321 {
322 #ifdef DDB_BUFR_SIZE
323         char bufr[DDB_BUFR_SIZE];
324 #endif
325         struct dbputchar_arg dca;
326         va_list listp;
327 
328 #ifdef DDB_BUFR_SIZE
329         dca.da_pbufr = bufr;
330         dca.da_pnext = dca.da_pbufr;
331         dca.da_nbufr = sizeof(bufr);
332         dca.da_remain = sizeof(bufr);
333         *dca.da_pnext = '\0';
334 #else
335         dca.da_pbufr = NULL;
336 #endif
337 
338         va_start(listp, fmt);
339         kvprintf (fmt, db_putchar, &dca, db_radix, listp);
340         va_end(listp);
341 
342 #ifdef DDB_BUFR_SIZE
343         if (*dca.da_pbufr != '\0')
344                 db_puts(dca.da_pbufr);
345 #endif
346 }
347 
348 int db_indent;
349 
350 void
351 db_iprintf(const char *fmt,...)
352 {
353 #ifdef DDB_BUFR_SIZE
354         char bufr[DDB_BUFR_SIZE];
355 #endif
356         struct dbputchar_arg dca;
357         register int i;
358         va_list listp;
359 
360         for (i = db_indent; i >= 8; i -= 8)
361                 db_printf("\t");
362         while (--i >= 0)
363                 db_printf(" ");
364 
365 #ifdef DDB_BUFR_SIZE
366         dca.da_pbufr = bufr;
367         dca.da_pnext = dca.da_pbufr;
368         dca.da_nbufr = sizeof(bufr);
369         dca.da_remain = sizeof(bufr);
370         *dca.da_pnext = '\0';
371 #else
372         dca.da_pbufr = NULL;
373 #endif
374 
375         va_start(listp, fmt);
376         kvprintf (fmt, db_putchar, &dca, db_radix, listp);
377         va_end(listp);
378 
379 #ifdef DDB_BUFR_SIZE
380         if (*dca.da_pbufr != '\0')
381                 db_puts(dca.da_pbufr);
382 #endif
383 }
384 
385 /*
386  * End line if too long.
387  */
388 void
389 db_end_line(int field_width)
390 {
391         if (db_output_position + field_width > db_max_width)
392             db_printf("\n");
393 }
394 

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.