1/* 2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31/* 32 * Mach Operating System 33 * Copyright (c) 1991,1990 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56/* 57 */ 58/* 59 * Author: David B. Golub, Carnegie Mellon University 60 * Date: 7/90 61 */ 62 63/* 64 * Printf and character output for debugger. 65 */ 66 67#include <mach/boolean.h> 68#include <kern/misc_protos.h> 69#include <stdarg.h> 70#include <machine/db_machdep.h> 71#include <ddb/db_command.h> 72#include <ddb/db_lex.h> 73#include <ddb/db_input.h> 74#include <ddb/db_output.h> 75#include <ddb/db_task_thread.h> 76 77/* 78 * Character output - tracks position in line. 79 * To do this correctly, we should know how wide 80 * the output device is - then we could zero 81 * the line position when the output device wraps 82 * around to the start of the next line. 83 * 84 * Instead, we count the number of spaces printed 85 * since the last printing character so that we 86 * don't print trailing spaces. This avoids most 87 * of the wraparounds. 88 */ 89 90#ifndef DB_MAX_LINE 91#define DB_MAX_LINE 43 /* maximum line */ 92#define DB_MAX_WIDTH 132 /* maximum width */ 93#endif /* DB_MAX_LINE */ 94 95#define DB_MIN_MAX_WIDTH 20 /* minimum max width */ 96#define DB_MIN_MAX_LINE 3 /* minimum max line */ 97#define CTRL(c) ((c) & 0xff) 98 99int db_output_position = 0; /* output column */ 100int db_output_line = 0; /* output line number */ 101int db_last_non_space = 0; /* last non-space character */ 102int db_last_gen_return = 0; /* last character generated return */ 103int db_auto_wrap = 1; /* auto wrap at end of line ? */ 104int db_tab_stop_width = 8; /* how wide are tab stops? */ 105#define NEXT_TAB(i) \ 106 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 107int db_max_line = DB_MAX_LINE; /* output max lines */ 108int db_max_width = DB_MAX_WIDTH; /* output line width */ 109 110 111/* Prototypes for functions local to this file. XXX -- should be static! 112 */ 113static void db_more(void); 114void db_advance_output_position(int new_output_position, 115 int blank); 116 117 118/* 119 * Force pending whitespace. 120 */ 121void 122db_force_whitespace(void) 123{ 124 register int last_print, next_tab; 125 126 last_print = db_last_non_space; 127 while (last_print < db_output_position) { 128 next_tab = NEXT_TAB(last_print); 129 if (next_tab <= db_output_position) { 130 cnputc('\t'); 131 last_print = next_tab; 132 } 133 else { 134 cnputc(' '); 135 last_print++; 136 } 137 } 138 db_last_non_space = db_output_position; 139} 140 141void 142db_reset_more() 143{ 144 db_output_line = 0; 145} 146 147static void 148db_more(void) 149{ 150 const char *p; 151 boolean_t quit_output = FALSE; 152 153 for (p = "--db_more--"; *p; p++) 154 cnputc(*p); 155 switch(cngetc()) { 156 case ' ': 157 db_output_line = 0; 158 break; 159 case 'q': 160 case CTRL('c'): 161 db_output_line = 0; 162 quit_output = TRUE; 163 break; 164 default: 165 db_output_line--; 166 break; 167 } 168 p = "\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"; 169 while (*p) 170 cnputc(*p++); 171 if (quit_output) { 172 db_error((char *) 0); 173 /* NOTREACHED */ 174 } 175} 176 177void 178db_advance_output_position(int new_output_position, 179 int blank) 180{ 181 if (db_max_width >= DB_MIN_MAX_WIDTH 182 && new_output_position >= db_max_width) { 183 /* auto new line */ 184 if (!db_auto_wrap || blank) 185 cnputc('\n'); 186 db_output_position = 0; 187 db_last_non_space = 0; 188 db_last_gen_return = 1; 189 db_output_line++; 190 } else { 191 db_output_position = new_output_position; 192 } 193} 194 195boolean_t 196db_reserve_output_position(int increment) 197{ 198 if (db_max_width >= DB_MIN_MAX_WIDTH 199 && db_output_position + increment >= db_max_width) { 200 /* auto new line */ 201 if (!db_auto_wrap || db_last_non_space != db_output_position) 202 cnputc('\n'); 203 db_output_position = 0; 204 db_last_non_space = 0; 205 db_last_gen_return = 1; 206 db_output_line++; 207 return TRUE; 208 } 209 return FALSE; 210} 211 212/* 213 * Output character. Buffer whitespace. 214 */ 215void 216db_putchar(char c) 217{ 218 if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1) 219 db_more(); 220 if (c > ' ' && c <= '~') { 221 /* 222 * Printing character. 223 * If we have spaces to print, print them first. 224 * Use tabs if possible. 225 */ 226 db_force_whitespace(); 227 cnputc(c); 228 db_last_gen_return = 0; 229 db_advance_output_position(db_output_position+1, 0); 230 db_last_non_space = db_output_position; 231 } 232 else if (c == '\n') { 233 /* Return */ 234 if (db_last_gen_return) { 235 db_last_gen_return = 0; 236 } else { 237 cnputc(c); 238 db_output_position = 0; 239 db_last_non_space = 0; 240 db_output_line++; 241 db_check_interrupt(); 242 } 243 } 244 else if (c == '\t') { 245 /* assume tabs every 8 positions */ 246 db_advance_output_position(NEXT_TAB(db_output_position), 1); 247 } 248 else if (c == ' ') { 249 /* space */ 250 db_advance_output_position(db_output_position+1, 1); 251 } 252 else if (c == '\007') { 253 /* bell */ 254 cnputc(c); 255 } 256 /* other characters are assumed non-printing */ 257} 258 259/* 260 * Return output position 261 */ 262int 263db_print_position(void) 264{ 265 return (db_output_position); 266} 267 268/* 269 * End line if too long. 270 */ 271void 272db_end_line(void) 273{ 274 if (db_output_position >= db_max_width-1) { 275 /* auto new line */ 276 if (!db_auto_wrap) 277 cnputc('\n'); 278 db_output_position = 0; 279 db_last_non_space = 0; 280 db_last_gen_return = 1; 281 db_output_line++; 282 } 283} 284 285/* 286 * Printing 287 */ 288 289void 290db_printf(const char *fmt, ...) 291{ 292 va_list listp; 293 294 va_start(listp, fmt); 295 _doprnt(fmt, &listp, db_putchar, db_radix); 296 va_end(listp); 297} 298 299/* alternate name */ 300 301void 302kdbprintf(const char *fmt, ...) 303{ 304 va_list listp; 305 306 va_start(listp, fmt); 307 _doprnt(fmt, &listp, db_putchar, db_radix); 308 va_end(listp); 309} 310 311int db_indent = 0; 312 313/* 314 * Printing (to console) with indentation. 315 */ 316void 317iprintf(const char *fmt, ...) 318{ 319 va_list listp; 320 register int i; 321 322 for (i = db_indent; i > 0; ){ 323 if (i >= 8) { 324 kdbprintf("\t"); 325 i -= 8; 326 } 327 else { 328 kdbprintf(" "); 329 i--; 330 } 331 } 332 333 va_start(listp, fmt); 334 _doprnt(fmt, &listp, db_putchar, db_radix); 335 va_end(listp); 336} 337 338void 339db_output_prompt(void) 340{ 341 db_printf("db%s", (db_default_act) ? "t": ""); 342 db_printf("{%d}", cpu_number()); 343 db_printf("> "); 344} 345 346