#include <mach/boolean.h>
#include <kern/misc_protos.h>
#include <stdarg.h>
#include <machine/db_machdep.h>
#include <ddb/db_command.h>
#include <ddb/db_lex.h>
#include <ddb/db_input.h>
#include <ddb/db_output.h>
#include <ddb/db_task_thread.h>
#ifndef DB_MAX_LINE
#define DB_MAX_LINE 43
#define DB_MAX_WIDTH 132
#endif
#define DB_MIN_MAX_WIDTH 20
#define DB_MIN_MAX_LINE 3
#define CTRL(c) ((c) & 0xff)
int db_output_position = 0;
int db_output_line = 0;
int db_last_non_space = 0;
int db_last_gen_return = 0;
int db_auto_wrap = 1;
int db_tab_stop_width = 8;
#define NEXT_TAB(i) \
((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
int db_max_line = DB_MAX_LINE;
int db_max_width = DB_MAX_WIDTH;
static void db_more(void);
void db_advance_output_position(int new_output_position,
int blank);
void
db_force_whitespace(void)
{
register int last_print, next_tab;
last_print = db_last_non_space;
while (last_print < db_output_position) {
next_tab = NEXT_TAB(last_print);
if (next_tab <= db_output_position) {
cnputc('\t');
last_print = next_tab;
}
else {
cnputc(' ');
last_print++;
}
}
db_last_non_space = db_output_position;
}
void
db_reset_more()
{
db_output_line = 0;
}
static void
db_more(void)
{
const char *p;
boolean_t quit_output = FALSE;
for (p = "--db_more--"; *p; p++)
cnputc(*p);
switch(cngetc()) {
case ' ':
db_output_line = 0;
break;
case 'q':
case CTRL('c'):
db_output_line = 0;
quit_output = TRUE;
break;
default:
db_output_line--;
break;
}
p = "\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b";
while (*p)
cnputc(*p++);
if (quit_output) {
db_error((char *) 0);
}
}
void
db_advance_output_position(int new_output_position,
int blank)
{
if (db_max_width >= DB_MIN_MAX_WIDTH
&& new_output_position >= db_max_width) {
if (!db_auto_wrap || blank)
cnputc('\n');
db_output_position = 0;
db_last_non_space = 0;
db_last_gen_return = 1;
db_output_line++;
} else {
db_output_position = new_output_position;
}
}
boolean_t
db_reserve_output_position(int increment)
{
if (db_max_width >= DB_MIN_MAX_WIDTH
&& db_output_position + increment >= db_max_width) {
if (!db_auto_wrap || db_last_non_space != db_output_position)
cnputc('\n');
db_output_position = 0;
db_last_non_space = 0;
db_last_gen_return = 1;
db_output_line++;
return TRUE;
}
return FALSE;
}
void
db_putchar(char c)
{
if (db_max_line >= DB_MIN_MAX_LINE && db_output_line >= db_max_line-1)
db_more();
if (c > ' ' && c <= '~') {
db_force_whitespace();
cnputc(c);
db_last_gen_return = 0;
db_advance_output_position(db_output_position+1, 0);
db_last_non_space = db_output_position;
}
else if (c == '\n') {
if (db_last_gen_return) {
db_last_gen_return = 0;
} else {
cnputc(c);
db_output_position = 0;
db_last_non_space = 0;
db_output_line++;
db_check_interrupt();
}
}
else if (c == '\t') {
db_advance_output_position(NEXT_TAB(db_output_position), 1);
}
else if (c == ' ') {
db_advance_output_position(db_output_position+1, 1);
}
else if (c == '\007') {
cnputc(c);
}
}
int
db_print_position(void)
{
return (db_output_position);
}
void
db_end_line(void)
{
if (db_output_position >= db_max_width-1) {
if (!db_auto_wrap)
cnputc('\n');
db_output_position = 0;
db_last_non_space = 0;
db_last_gen_return = 1;
db_output_line++;
}
}
void
db_printf(const char *fmt, ...)
{
va_list listp;
va_start(listp, fmt);
_doprnt(fmt, &listp, db_putchar, (int)db_radix);
va_end(listp);
}
void
kdbprintf(const char *fmt, ...)
{
va_list listp;
va_start(listp, fmt);
_doprnt(fmt, &listp, db_putchar, (int)db_radix);
va_end(listp);
}
int db_indent = 0;
void
iprintf(const char *fmt, ...)
{
va_list listp;
register int i;
for (i = db_indent; i > 0; ){
if (i >= 8) {
kdbprintf("\t");
i -= 8;
}
else {
kdbprintf(" ");
i--;
}
}
va_start(listp, fmt);
_doprnt(fmt, &listp, db_putchar, (int)db_radix);
va_end(listp);
}
void
db_output_prompt(void)
{
db_printf("db%s", (db_default_act) ? "t": "");
db_printf("{%d}", cpu_number());
db_printf("> ");
}