#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include "MacsBug.h"
int macsbug_screen = 0;
GDB_FILE *macsbug_screen_stdout = NULL;
GDB_FILE *macsbug_screen_stderr = NULL;
int max_rows, max_cols;
int continued_len = 0;
int continued_count = 0;
char *continued_line_starts[MAX_CMD_LINES];
int continued_segment_len[MAX_CMD_LINES];
char continued_line[1024];
int doing_set_prompt = 0;
int scroll_mode = 1;
int need_CurApName = 1;
FILE *log_stream = NULL;
char *log_filename = NULL;
Special_Refresh_States immediate_flush;
#define SCREEN_RESET() write_line(RESET)
#define SCREEN_CLEAR_LINE() write_line(CLEAR_LINE)
#define SCREEN_GOTO(row, col) write_line(GOTO, row, col)
static char prompt[300];
static int prompt_start = 0;
static unsigned long previous_pc = 0;
static int first_sidebar = 1;
static int prev_running = 1;
typedef struct History {
struct History *next, *prev;
unsigned short flags;
#define ERR_LINE 0x0001
#define PARTIAL_LINE1 0x0002
#define PARTIAL_LINE2 0x0004
char line[1];
} History;
static History *history;
static History *history_tail;
static int history_cnt = 0;
static History *screen_top;
static History *screen_bottom;
static short history_top;
static short history_left;
static short history_bottom;
static short history_right;
static short history_lines;
static short history_wrap;
static short pc_top;
static short pc_left;
static short pc_bottom;
static short pc_right;
static short pc_lines;
static short cmd_top;
static short cmd_left;
static short cmd_bottom;
static short cmd_right;
static short cmd_lines;
static short side_bar_top;
static short side_bar_left;
static short side_bar_bottom;
static short side_bar_right;
static short vertical_divider;
static short pc_top_divider;
static short pc_bottom_divider;
static GDB_HOOK *hook_stop = NULL;
static unsigned long prev_pc;
static unsigned long prev_lr;
static unsigned long prev_ctr;
static unsigned long prev_msr;
static unsigned long prev_cr;
static unsigned long prev_xer;
static unsigned long prev_mq;
static unsigned long prev_gpr[32];
static unsigned long *prev_stack = NULL;
static char *prev_stack_color = NULL;
static int prev_stack_cnt = 0;
#define BUFFER_OUTPUT 1
#if BUFFER_OUTPUT
static char output_buffer[BUFSIZE+1];
static char *bp = output_buffer;
static int buf_row = 0;
#define END_OF_LINE ++buf_row
#define FLUSH_BUFFER flush_buffer()
#else
#define END_OF_LINE
#define FLUSH_BUFFER screen_fflush(stdout, HISTORY_AREA)
#endif
static void word_completion_cursor_control(int save_cursor)
{
if (save_cursor)
fputs(SAVE_CURSOR, stderr);
else {
screen_refresh(0);
fprintf(stderr, GOTO CLEAR_LINE, cmd_bottom, cmd_left);
fputs(RESTORE_CURSOR, stderr);
}
}
static void word_completion_query(GDB_FILE *stream, char *query, ...)
{
va_list ap;
#if 0
va_start(ap, query);
gdb_vfprintf(stream, query, ap);
va_end(ap);
gdb_fflush(stream);
screen_refresh(0);
#else
fprintf(stderr, GOTO COLOR_BOLD, cmd_bottom, cmd_left);
va_start(ap, query);
vfprintf(stderr, query, ap);
va_end(ap);
fprintf(stderr, COLOR_OFF);
#endif
}
void get_screen_size(int *max_rows, int *max_cols)
{
struct winsize size;
if (!isatty(STDOUT_FILENO))
*max_rows = *max_cols = 0;
else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&size) < 0)
gdb_error("Can't get window size");
else {
*max_rows = size.ws_row;
*max_cols = size.ws_col;
}
}
void position_cursor_for_shell_input(void)
{
struct winsize size;
static void flush_buffer(void);
if (macsbug_screen) {
flush_buffer();
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&size) >= 0)
screen_fprintf(stderr, NO_AREA, GOTO "\n", size.ws_row, size.ws_col);
}
}
#if BUFFER_OUTPUT
static void flush_buffer(void)
{
if (bp > output_buffer) {
*bp = '\0';
#if 0
{
int k58 = 0, nl = 0;
char *bp1;
for (bp1 = output_buffer; *bp1; ++bp1)
if (*bp1 == 58)
k58 = 1;
else if (*bp1 == '\n')
nl = 1;
if (k58)
bp += sprintf(bp, "еее 58 еее");
if (nl)
bp += sprintf(bp, "еее nl еее");
}
#endif
screen_fputs(output_buffer, stdout, HISTORY_AREA);
screen_fflush(stdout, HISTORY_AREA);
}
bp = output_buffer;
buf_row = 0;
}
#endif
static int write_line(char *fmt, ...)
{
int len, turn_off;
va_list ap;
char c, *p, line[1024];
va_start(ap, fmt);
len = vsprintf(line, fmt, ap);
va_end(ap);
if (len > history_wrap) {
len = turn_off = 0;
p = line - 1;
while ((c = *++p) != '\0') {
if (c != ESC) {
if (++len > history_wrap)
break;
} else {
turn_off = 0;
if (*++p == '[') {
while ((c=*++p) && !isalpha(c));
if (!c || !*++p)
break;
turn_off = 1;
--p;
}
}
}
if (turn_off) {
strcpy(p, COLOR_OFF);
p += strlen(COLOR_OFF);
}
*p = '\0';
len = p - line;
}
#if BUFFER_OUTPUT
if (bp + len >= output_buffer + BUFSIZE)
FLUSH_BUFFER;
memcpy(bp, line, len);
bp += len;
#else
screen_fputs(line, stdout, HISTORY_AREA);
#endif
return (len);
}
static void su(char *arg, int from_tty)
{
int i, n;
History *h1;
char negated_arg[25];
static void sd(char *arg, int from_tty);
if (!macsbug_screen)
return;
if (arg && *arg) {
n = gdb_get_int(arg);
if (n == 0)
return;
if (n < 0) {
sprintf(negated_arg, "%d", -n);
sd(negated_arg, from_tty);
return;
}
} else
n = 1;
get_screen_size(&max_rows, &max_cols);
if (history_cnt > history_lines) {
if (screen_top && screen_bottom && screen_top->prev && screen_bottom->prev) {
while (n--) {
if (screen_top->prev == NULL || screen_bottom->prev == NULL)
break;
screen_top = screen_top->prev;
screen_bottom = screen_bottom->prev;
}
for (i = 1, h1 = screen_top; h1 && i <= history_lines; ++i, h1 = h1->next) {
SCREEN_GOTO(i, history_left);
if (h1->flags & ERR_LINE)
write_line(COLOR_RED "%s" COLOR_OFF, h1->line);
else
write_line("%s", h1->line);
SCREEN_CLEAR_LINE();
END_OF_LINE;
}
FLUSH_BUFFER;
}
}
}
#define SU_HELP \
"SU [n] -- Scroll MacsBug history up n (or 1) line(s)." \
"Same as SCROLL up [n]."
static void sd(char *arg, int from_tty)
{
int i, n;
History *h1;
char negated_arg[25];
if (!macsbug_screen)
return;
if (arg && *arg) {
n = gdb_get_int(arg);
if (n == 0)
return;
if (n < 0) {
sprintf(negated_arg, "%d", -n);
su(negated_arg, from_tty);
return;
}
} else
n = 1;
get_screen_size(&max_rows, &max_cols);
if (history_cnt > history_lines) {
if (screen_top && screen_bottom && screen_top->next && screen_bottom->next) {
while (n--) {
if (screen_top->next == NULL || screen_bottom->next == NULL)
break;
screen_top = screen_top->next;
screen_bottom = screen_bottom->next;
}
for (i = 1, h1 = screen_top; h1 && i <= history_lines; ++i, h1 = h1->next) {
SCREEN_GOTO(i, history_left);
if (h1->flags & ERR_LINE)
write_line(COLOR_RED "%s" COLOR_OFF, h1->line);
else
write_line("%s", h1->line);
SCREEN_CLEAR_LINE();
END_OF_LINE;
}
FLUSH_BUFFER;
}
}
}
#define SD_HELP \
"SD [n] -- Scroll MacsBug history down n (or 1) line(s)." \
"Same as SCROLL down [n]."
static void scroll(char *arg, int from_tty)
{
int argc;
char *argv[5], tmpCmdLine[1024];
gdb_setup_argv(safe_strcpy(tmpCmdLine, arg), "scroll", &argc, argv, 4);
if (argc < 2)
gdb_error("scroll up | down expected");
if (argc > 3)
gdb_error("Too many scroll arguments");
if (gdb_strcmpl(argv[1], "up"))
su((argc == 3) ? argv[2] : NULL, 0);
else if (gdb_strcmpl(argv[1], "down"))
sd((argc == 3) ? argv[2] : NULL, 0);
else if (gdb_strcmpl(argv[1], "fast")) {
if (macsbug_screen && scroll_mode == 0) {
scroll_mode = 1;
refresh(NULL, 0);
} else
scroll_mode = 1;
} else if (gdb_strcmpl(argv[1], "slow")) {
if (macsbug_screen && scroll_mode == 1) {
scroll_mode = 0;
refresh(NULL, 0);
} else
scroll_mode = 0;
} else
gdb_error("scroll up | down expected");
}
#define SCROLL_HELP \
"SCROLL up [n] | down [n] -- Scroll MacsBug history up or down n (or 1) line(s)."
static void pgu(char *arg, int from_tty)
{
char lines[25];
sprintf(lines, "%ld", ((arg && *arg) ? gdb_get_int(arg) : 1) * history_lines);
su(lines, from_tty);
}
#define PGU_HELP \
"PGU [n] -- Page MacsBug history up n (or 1) page(s).\n" \
"Same as PAGE up [n]."
static void pgd(char *arg, int from_tty)
{
char lines[25];
sprintf(lines, "%ld", ((arg && *arg) ? gdb_get_int(arg) : 1) * history_lines);
sd(lines, from_tty);
}
#define PGD_HELP \
"PGD [n] -- Page MacsBug history down n (or 1) page(s).\n" \
"Same as PAGE down [n]."
static void page(char *arg, int from_tty)
{
int argc;
char *argv[5], tmpCmdLine[1024];
gdb_setup_argv(safe_strcpy(tmpCmdLine, arg), "scroll", &argc, argv, 4);
if (argc < 2)
gdb_error("page up | down expected");
if (argc > 3)
gdb_error("Too many page arguments");
if (gdb_strcmpl(argv[1], "up"))
pgu((argc == 3) ? argv[2] : NULL, from_tty);
else if (gdb_strcmpl(argv[1], "down"))
pgd((argc == 3) ? argv[2] : NULL, from_tty);
else
gdb_error("page up | down expected");
}
#define PAGE_HELP \
"PAGE up [n] | down [n] -- Page MacsBug history up or down n (or 1) page(s)."
static void which_log(char *arg, int from_tty)
{
if (log_stream)
if (macsbug_screen)
gdb_printf("Logging to %s\n", log_filename);
else
gdb_printf("Will be logging to %s when MacsBug screen is turned on\n", log_filename);
else
gdb_printf("No log file is open\n");
}
static void log(char *arg, int from_tty)
{
int hopt, argc;
History *h;
FILE *f;
char *filename, *argv[5], tmpCmdLine[1024];
gdb_set_int("$__lastcmd__", 43);
gdb_setup_argv(safe_strcpy(tmpCmdLine, arg), "log", &argc, argv, 4);
if (argc > 3)
gdb_error("LOG [-h] [pathname | ?] -- wrong number of arguments");
if (argc == 1) {
if (log_stream == NULL)
gdb_error("Log is already closed");
else {
fclose(log_stream);
gdb_printf("Closing log\n");
log_stream = NULL;
}
return;
}
if (argc == 3) {
if (*argv[1] != '-' || !gdb_strcmpl(argv[1], "-h"))
gdb_error("Invalid log parameters");
hopt = 1;
filename = argv[2];
} else if (*argv[1] == '?') {
which_log(NULL, 0);
return;
} else if (*argv[1] != '-') {
hopt = 0;
filename = argv[1];
} else
gdb_error("Invalid log parameters");
if (log_stream)
gdb_error("Log file already open");
log_filename = gdb_realloc(log_filename, strlen(filename) + 1);
filename = gdb_tilde_expand(strcpy(log_filename, filename));
f = fopen(filename, "a");
gdb_free(filename);
if (!f)
gdb_error("Cannot open log file: %s", strerror(errno));
if (macsbug_screen)
gdb_printf("Logging to %s\n", log_filename);
else
gdb_printf("Will log to %s when MacsBug screen is turned on\n", log_filename);
log_stream = f;
if (hopt)
for (h = history; h; h = h->next)
fprintf(log_stream, "%s\n", h->line);
}
#define LOG_HELP \
"LOG [-h] [filename] -- Log all MacsBug output to a file.\n" \
"LOG without parameters turns logging off. LOG with only a filename creates the\n" \
"log file with that filename. LOG -h saves the scrollback history to the bottom\n" \
"of the current screen to the log file. LOG? reveals what log file is open."
static char *write_to_history_area(FILE *f, char *line, void *data)
{
int i, len, wrap, write_col, err = (f == stderr), partial_line;
History *h, *h1;
char *src, *dst, detabbed_line[1024];
if (!line) {
FLUSH_BUFFER;
if (immediate_flush != NORMAL_REFRESH) {
screen_refresh(0);
if (immediate_flush == QUERY_REFRESH1)
immediate_flush = QUERY_REFRESH2;
}
return (NULL);
}
len = strlen(line);
if (len == 0)
return (NULL);
if (line[len-1] == '\n') {
line[--len] = '\0';
partial_line = 0;
} else
partial_line = 1;
if (history_tail && (history_tail->flags & (PARTIAL_LINE1|PARTIAL_LINE2))) {
wrap = history_wrap - strlen(history_tail->line);
} else
wrap = history_wrap;
if (history_tail && (history_tail->flags & (PARTIAL_LINE1|PARTIAL_LINE2)))
i = strlen(history_tail->line);
else
i = 1;
src = line;
dst = detabbed_line;
while (*src)
if (*src == '\t') {
do {
*dst++ = ' ';
++i;
} while ((i % tab_value) != 1);
++src;
} else {
*dst++ = *src++;
++i;
}
*dst = '\0';
line = detabbed_line;
get_screen_size(&max_rows, &max_cols);
if (len > wrap) {
if (!wrap_lines)
line[wrap] = '\0';
else
do {
char c1 = line[wrap];
char c2 = line[wrap+1];
line[wrap] = '\n';
line[wrap+1] = '\0';
write_to_history_area(f, line, data);
line[wrap] = c1;
line[wrap+1] = c2;
len -= wrap;
line += wrap;
} while (len > history_wrap);
}
if (log_stream)
fprintf(log_stream, "%s\n", line);
if (history_tail && (history_tail->flags & (PARTIAL_LINE1|PARTIAL_LINE2))) {
write_col = strlen(history_tail->line);
if (len > 0) {
h = (History *)gdb_malloc(sizeof(History) + write_col + len);
*h = *history_tail;
strcpy(h->line, history_tail->line);
strcpy(h->line+write_col, line);
if (history_tail->prev)
history_tail->prev->next = h;
if (history_tail == history)
history = h;
if (screen_top == history_tail)
screen_top = h;
if (screen_bottom == history_tail)
screen_bottom = h;
gdb_free(history_tail);
history_tail = h;
}
history_tail->flags &= ~PARTIAL_LINE1;
history_tail->flags |= PARTIAL_LINE2;
partial_line = partial_line ? 2 : 3;
write_col += history_left;
} else
write_col = history_left;
if (!partial_line || !history_tail || !(history_tail->flags & PARTIAL_LINE2)) {
if (screen_bottom) {
history_tail = screen_bottom;
h1 = screen_bottom->next;
screen_bottom->next = NULL;
while (h1) {
h = h1->next;
gdb_free(h1);
h1 = h;
--history_cnt;
}
}
if (history_cnt) {
if (history_cnt < history_lines)
i = history_lines - history_cnt;
else {
screen_top = screen_top->next;
i = 1;
}
for (h1 = screen_top; h1; ++i, h1 = h1->next) {
if (h1->flags & ERR_LINE)
write_line(GOTO COLOR_RED "%s" COLOR_OFF CLEAR_LINE, i, history_left, h1->line);
else
write_line(GOTO "%s" CLEAR_LINE, i, history_left, h1->line);
END_OF_LINE;
}
}
if (history_cnt >= max_history) {
h = history;
history = history->next;
history->prev = NULL;
gdb_free(h);
} else
++history_cnt;
}
if (partial_line < 2) {
h = (History *)gdb_malloc(sizeof(History) + strlen(line));
h->next = NULL;
h->prev = history_tail;
h->flags = err ? ERR_LINE : 0;
if (partial_line)
h->flags |= PARTIAL_LINE1;
strcpy(h->line, line);
if (history_cnt == 1)
history = screen_top = h;
else
history_tail->next = h;
history_tail = screen_bottom = h;
} else if (history_tail && partial_line == 3)
history_tail->flags &= ~(PARTIAL_LINE1|PARTIAL_LINE2);
SCREEN_GOTO(history_bottom, write_col);
if (err) {
write_line(COLOR_RED "%s" COLOR_OFF, line);
if (write_col == history_left)
SCREEN_CLEAR_LINE();
FLUSH_BUFFER;
screen_refresh(0);
} else {
write_line("%s", line);
if (write_col == history_left)
SCREEN_CLEAR_LINE();
}
END_OF_LINE;
if (immediate_flush != NORMAL_REFRESH) {
FLUSH_BUFFER;
screen_refresh(0);
}
return (NULL);
}
void rewrite_bottom_line(char *line, int err)
{
if (macsbug_screen && history_tail) {
if (err) {
write_line(GOTO COLOR_RED "%s" COLOR_OFF, history_bottom, history_left, history_tail->line);
history_tail->flags |= ERR_LINE;
} else {
write_line(GOTO "%s", history_bottom, history_left, history_tail->line);
history_tail->flags &= ~ERR_LINE;
}
END_OF_LINE;
}
}
typedef struct {
short row, col;
int remaining;
} Disasm_pc_data;
static char *disasm_pc_area_output(FILE *f, char *line, void *data)
{
Disasm_pc_data *pc_data = (Disasm_pc_data *)data;
if (line && pc_data->remaining-- >= 0) {
screen_fprintf(stdout, PC_AREA, GOTO CLEAR_LINE "%s", pc_data->row, pc_data->col, line);
pc_data->row++;
}
return (NULL);
}
void display_pc_area(void)
{
int row;
unsigned long addr, limit;
DisasmData disasm_info;
Disasm_pc_data pc_data;
GDB_FILE *redirect_stdout;
unsigned long current_pc;
char line[1024];
get_screen_size(&max_rows, &max_cols);
memset(line, '_', max_cols - pc_left);
line[max_cols - pc_left] = '\0';
screen_fprintf(stderr, PC_AREA, GOTO "%s", pc_top_divider, pc_left, line);
screen_fprintf(stderr, PC_AREA, GOTO "%s", pc_bottom_divider, pc_left, line);
if (!gdb_target_running()) {
for (row = pc_top; row <= pc_bottom; ++row) {
screen_fprintf(stdout, PC_AREA, GOTO, row, pc_left);
if (row == pc_top)
screen_fprintf(stdout, PC_AREA, COLOR_RED "Not Running " COLOR_OFF CLEAR_LINE);
else
screen_fprintf(stdout, PC_AREA, CLEAR_LINE);
}
previous_pc = 0;
screen_fflush(stdout, PC_AREA);
return;
}
current_pc = gdb_get_int("$pc");
if (previous_pc == current_pc)
return;
previous_pc = current_pc;
disasm_info.pc = gdb_get_int("$pc");
disasm_info.max_width = max_cols - pc_left;
disasm_info.flags = (ALWAYS_SHOW_NAME|FLAG_PC);
disasm_info.stream = gdb_open_output(stdout, disasm_pc_area_output, &pc_data);
pc_data.row = pc_top;
pc_data.col = pc_left;
pc_data.remaining = pc_lines;
redirect_stdout = gdb_open_output(stdout, format_disasm_line, &disasm_info);
gdb_redirect_output(redirect_stdout);
addr = disasm_info.pc;
limit = addr + 4 * pc_lines;
while (addr < limit && pc_data.remaining >= 0) {
disasm_info.addr = addr;
gdb_execute_command("x/i 0x%lX", addr);
addr += 4;
disasm_info.flags &= ~ALWAYS_SHOW_NAME;
}
gdb_close_output(disasm_info.stream);
gdb_close_output(redirect_stdout);
if (disasm_info.flags & (BRANCH_TAKEN|BRANCH_NOT_TAKEN)) {
screen_fprintf(stderr, PC_AREA, GOTO CLEAR_LINE, pc_top, max_cols - 19);
if (disasm_info.flags & BRANCH_TAKEN)
screen_fprintf(stdout, PC_AREA, COLOR_BLUE " (Will branch) " COLOR_OFF);
else if (disasm_info.flags & BRANCH_NOT_TAKEN)
screen_fprintf(stdout, PC_AREA, COLOR_BLUE " (Will not branch) " COLOR_OFF);
}
screen_fflush(stdout, PC_AREA);
}
#define NSArgv_Use_Redirect 0
#if NSArgv_Use_Redirect
static char *check_for_NSArgv(FILE *f, char *line, void *data)
{
char *p;
if (line)
if (f == stderr)
*(char *)data = '\0';
else {
p = strrchr(line, '/');
p = (p == NULL) ? line : p + 1;
strcpy((char *)data, p);
}
return (NULL);
}
#endif
static char *get_CurApName(char *curApName)
{
GDB_FILE *redirect_stdout, *redirect_stderr;
if (gdb_target_running()) {
#if NSArgv_Use_Redirect
redirect_stdout = gdb_open_output(stdout, check_for_NSArgv, curApName);
redirect_stderr = gdb_open_output(stderr, check_for_NSArgv, curApName);
gdb_redirect_output(redirect_stdout);
gdb_redirect_output(redirect_stderr);
gdb_execute_command("printf \"%%s\", ((char **)NXArgv)[0]");
gdb_close_output(redirect_stderr);
gdb_close_output(redirect_stdout);
#else
if (!gdb_eval_silent("$__CurApName__=((char **)NXArgv)[0]")) {
char *p, *q, pathname[MAXPATHLEN+1];
p = strrchr(q = gdb_get_string("$__CurApName__", pathname, MAXPATHLEN), '/');
strcpy(curApName, p ? p + 1 : q);
}
#endif
} else
*curApName = '\0';
return (curApName);
}
void save_stack(int max_rows)
{
int i;
prev_stack_cnt = max_rows - MIN_SIDEBAR;
i = prev_stack_cnt * sizeof(unsigned long);
if (i <= 0) {
if (prev_stack) {
gdb_free(prev_stack);
prev_stack = NULL;
gdb_free(prev_stack_color);
prev_stack_color = NULL;
}
} else if (prev_stack == NULL)
prev_stack = (unsigned long *)gdb_malloc(i);
else
prev_stack = (unsigned long *)gdb_realloc(prev_stack, i);
if (prev_stack)
gdb_read_memory(prev_stack, "$sp", i);
}
static void save_all_regs(void)
{
int i;
char r[6];
prev_pc = gdb_get_int("$pc");
prev_lr = gdb_get_int("$lr");
prev_ctr = gdb_get_int("$ctr");
prev_msr = gdb_get_int("$ps");
prev_cr = gdb_get_int("$cr");
prev_xer = gdb_get_int("$xer");
prev_mq = gdb_get_int("$mq");
for (i = 0; i < 32; ++i) {
sprintf(r, "$r%d", i);
prev_gpr[i] = gdb_get_int(r);
}
save_stack(max_rows);
}
void __display_side_bar(char *arg, int from_tty)
{
int i, row, col, reg, saved_regs, lastcmd, left_col, bottom,
cur_app_name, force_all_updates, changed, stack_rows;
unsigned long pc, lr, ctr, msr, cr, xer, mq, gpr[32], *stack;
char *bar_left, *bar_right, r[6], centered_name[13];
static char prev_sp_color, prev_pc_color, prev_lr_color, prev_ctr_color,
prev_msr_color, prev_cr_color, prev_xer_color, prev_mq_color,
prev_gpr_color[32];
static char curApName[MAXPATHLEN+1] = {0};
static char prev_curApName[MAXPATHLEN+1] = {0};
#if 0
#define BAR COLOR_BOLD "|" COLOR_OFF
#else
#define BAR COLOR_OFF "|"
#endif
if (!isatty(STDOUT_FILENO))
return;
get_screen_size(&max_rows, &max_cols);
screen_fprintf(stdout, SIDE_BAR, SAVE_CURSOR);
if (need_CurApName) {
need_CurApName= 0;
get_CurApName(curApName);
}
if (!arg || !*arg || gdb_strcmpl(arg, "left")) {
if (!arg || !*arg) {
force_all_updates = 0;
if (!macsbug_screen)
first_sidebar = 1;
} else
force_all_updates = 1;
left_col = side_bar_left;
bar_left = "";
bar_right = BAR;
} else if (gdb_strcmpl(arg, "right")) {
force_all_updates = 1;
left_col = max_cols - 12;
bar_left = BAR;
bar_right = "";
} else
gdb_error("__display_side_bar [left | right] expected, got \"%s\"", arg);
bottom = max_rows;
if (!gdb_have_registers() || !gdb_target_running()) {
if (prev_running == 1) {
prev_running = 0;
for (row = 1; row <= bottom; ++row) {
screen_fprintf(stdout, SIDE_BAR, GOTO, row, left_col);
if (row == 1)
screen_fprintf(stdout, SIDE_BAR, "%s" COLOR_RED "Not Running " "%s", bar_left, bar_right);
else
screen_fprintf(stdout, SIDE_BAR, "%s" " " "%s", bar_left, bar_right);
}
}
screen_fprintf(stdout, SIDE_BAR, RESTORE_CURSOR);
screen_fflush(stdout, SIDE_BAR);
first_sidebar = 1;
return;
}
prev_running = 1;
if (first_sidebar)
save_all_regs();
if (force_all_updates)
first_sidebar = force_all_updates;
pc = gdb_get_int("$pc");
lr = gdb_get_int("$lr");
ctr = gdb_get_int("$ctr");
msr = gdb_get_int("$ps");
cr = gdb_get_int("$cr");
xer = gdb_get_int("$xer");
mq = gdb_get_int("$mq");
for (i = 0; i < 32; ++i) {
sprintf(r, "$r%d", i);
gpr[i] = gdb_get_int(r);
}
row = 1;
stack_rows = max_rows - MIN_SIDEBAR;
if (stack_rows != prev_stack_cnt)
gdb_internal_error("Window size inconsistency dealing with number of stack entries");
if (stack_rows > 0) {
stack = (unsigned long *)gdb_malloc(stack_rows * sizeof(unsigned long));
gdb_read_memory(stack, "$sp", stack_rows * sizeof(unsigned long));
if (first_sidebar) {
prev_stack_color = (char *)gdb_malloc(stack_rows);
memset(prev_stack_color, 0, stack_rows);
}
} else {
stack = NULL;
if (prev_stack_color) {
gdb_free(prev_stack_color);
prev_stack_color = NULL;
}
}
if (first_sidebar)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " SP " "%s", row, left_col, bar_left, bar_right);
++row;
changed = (prev_gpr[1] != gpr[1]);
if (first_sidebar || changed || changed != prev_sp_color)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " " "%s" "%.8lX" " " "%s", row, left_col,
bar_left, COLOR_CHANGE(prev_sp_color = changed),
gpr[1], bar_right);
++row;
for (i = 0; i < stack_rows; ++i) {
changed = (prev_stack[i] != stack[i]);
if (first_sidebar || changed || changed != prev_stack_color[i])
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "%.3lX %s%.8lX" "%s", row, left_col,
bar_left, (gpr[1] + 4*i) & 0xFFF,
COLOR_CHANGE(prev_stack_color[i] = changed), stack[i],
bar_right);
++row;
}
if (stack)
gdb_free(stack);
if (first_sidebar)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " " "%s", row, left_col, bar_left, bar_right);
++row;
if (first_sidebar || (*curApName && strcmp(curApName, prev_curApName) != 0)) {
strcpy(prev_curApName, curApName);
if (*curApName) {
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " CurApName " "%s", row++, left_col, bar_left, bar_right);
if ((i = strlen(curApName)) > 12) {
char c1 = curApName[11];
char c2 = curApName[12];
curApName[11] = '╔';
curApName[12] = '\0';
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "%s" "%s", row++, left_col, bar_left, curApName, bar_right);
curApName[11] = c1;
curApName[12] = c2;
} else if (i == 12)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "%s" "%s", row++, left_col, bar_left, curApName, bar_right);
else {
memset(centered_name, ' ', 12);
centered_name[12] = '\0';
memcpy(¢ered_name[(12 - i)/2], curApName, i);
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "%s" "%s", row++, left_col, bar_left, centered_name, bar_right);
}
} else {
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " " "%s", row++, left_col, bar_left, bar_right);
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " " "%s", row++, left_col, bar_left, bar_right);
}
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " " "%s", row++, left_col, bar_left, bar_right);
} else
row += 3;
changed = (prev_lr != lr);
if (first_sidebar || changed || changed != prev_lr_color)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "LR " "%s" "%.8X" "%s", row, left_col,
bar_left, COLOR_CHANGE(prev_lr_color = changed), lr, bar_right);
++row;
changed = (prev_cr != cr);
if (first_sidebar || changed || changed != prev_cr_color) {
prev_cr_color = changed;
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "CR ", row, left_col, bar_left);
for (i = 28; i >= 0; i -= 4)
screen_fprintf(stdout, SIDE_BAR, "%s" "%.1X", COLOR_CHANGE((prev_cr>>i&15) != (cr>>i&15)), (cr>>i&15));
if (*bar_right)
screen_fprintf(stdout, SIDE_BAR, "%s", bar_right);
}
++row;
if (first_sidebar)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " " "%s", row, left_col, bar_left, bar_right);
++row;
changed = (prev_ctr != ctr);
if (first_sidebar || changed || changed != prev_ctr_color)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "CTR " "%s" "%.8X" "%s", row, left_col, bar_left,
COLOR_CHANGE(prev_ctr_color = changed), ctr, bar_right);
++row;
#if 0
changed = (prev_msr != msr);
if (first_sidebar || changed || changed != prev_msr_color)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "MSR " "%s" "%.8X" "%s", row, left_col, bar_left,
COLOR_CHANGE(prev_msr_color = changed), msr, bar_right);
++row;
changed = (prev_mq != mq);
if (first_sidebar || changed || changed != prev_mq_color)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "MQ " "%s" "%.8X" "%s", row, left_col, bar_left,
COLOR_CHANGE(prev_mq_color = changed), mq , bar_right);
++row;
#endif
changed = (prev_xer != xer);
if (first_sidebar || changed || changed != prev_xer_color) {
prev_xer_color = changed;
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" "XER ", row, left_col, bar_left);
screen_fprintf(stdout, SIDE_BAR, "%s" "%.1X" COLOR_OFF, COLOR_CHANGE((prev_xer>>28&0xF) != (xer>>28&0xF)), xer>>28&0xF);
screen_fprintf(stdout, SIDE_BAR, "%.3X", (xer>>16&0xFFF));
screen_fprintf(stdout, SIDE_BAR, "%s" "%.2X", COLOR_CHANGE((prev_xer>>8&0xFF) != (xer>>8&0xFF)), xer>>8&0xFF);
screen_fprintf(stdout, SIDE_BAR, "%s" "%.2X", COLOR_CHANGE((prev_xer&0xFF) != (xer&0xFF)), xer&0xFF);
if (*bar_right)
screen_fputs(bar_right, stdout, SIDE_BAR);
}
++row;
if (first_sidebar)
screen_fprintf(stdout, SIDE_BAR, GOTO "%s" " " "%s", row, left_col, bar_left, bar_right);
++row;
for (reg = 0; reg < 32; ++reg) {
changed = (prev_gpr[reg] != gpr[reg]);
if (first_sidebar || changed || changed != prev_gpr_color[reg]) {
screen_fprintf(stdout, SIDE_BAR, GOTO "%s", row, left_col, bar_left);
if (reg == 1)
screen_fprintf(stdout, SIDE_BAR, "SP ");
else
screen_fprintf(stdout, SIDE_BAR, "R%-2d ", reg);
screen_fprintf(stdout, SIDE_BAR, "%s" "%.8X" "%s",
COLOR_CHANGE(prev_gpr_color[reg] = changed),
gpr[reg], bar_right);
}
++row;
}
screen_fprintf(stdout, SIDE_BAR, COLOR_OFF);
screen_fprintf(stdout, SIDE_BAR, RESTORE_CURSOR);
screen_fflush(stdout, SIDE_BAR);
if (!first_sidebar || force_all_updates) {
save_all_regs();
if (force_all_updates)
first_sidebar = 0;
} else
first_sidebar = 0;
}
#define __DISPLAY_SIDE_BAR_HELP \
"__DISPLAY_SIDE_BAR [left | right] -- display registers vertically.\n" \
"Used to display the machine registers in a side bar vertically on the right\n" \
"(\"right\") or left (\"left\") side of the screen. The default is the same as\n" \
"specifying \"left\".\n" \
"\n" \
"This command is called as \"__DISPLAY_SIDE_BAR right\" when __DISASM is used\n" \
"and the MacsBug screen is off or as \"__DISPLAY_SIDE_BAR\" (implied \"left\")\n" \
"when the MacsBug screen is on. Obviously you shouldn't use \"left\" when the\n" \
"MacsBug screen is off since the last line will be clobbered by gdb's prompt.\n" \
"It should Also be obvious that it shouldn't be explicitly called at all when\n" \
"the MacsBug scren is on.\n" \
" \n" \
"Note, for each call to __DISPLAY_SIDE_BAR, the registers that changed since\n" \
"the last call will be shown in red. Also displayed is the targer program name\n" \
"being debugged (if available) and the top few entries of the stack."
void init_sidebar_and_pc_areas(void)
{
previous_pc = 0;
prev_running = 1;
first_sidebar = 1;
if (prev_stack) {
gdb_free(prev_stack);
prev_stack = NULL;
}
if (prev_stack_color) {
gdb_free(prev_stack_color);
prev_stack_color = NULL;
}
prev_stack_cnt = 0;
}
static void define_macsbug_screen_positions(short pc_area_lines, short cmd_area_lines)
{
get_screen_size(&max_rows, &max_cols);
side_bar_top = 1;
side_bar_bottom = max_rows;
side_bar_left = 1;
side_bar_right = 12;
cmd_top = max_rows-cmd_area_lines;
cmd_bottom = max_rows;
cmd_left = side_bar_right + 2;
cmd_right = max_cols;
pc_bottom = cmd_top - 2;
pc_top = pc_bottom-pc_area_lines;
pc_left = side_bar_right + 2;
pc_right = max_cols;
history_top = 1;
history_bottom = pc_top - 2;
history_left = side_bar_right + 2;
history_right = max_cols;
vertical_divider = side_bar_right + 1;
pc_top_divider = pc_top - 1;
pc_bottom_divider = pc_bottom + 1;
pc_lines = pc_area_lines;
cmd_lines = cmd_area_lines;
history_lines = history_bottom - history_top + 1;
history_wrap = max_cols - history_left;
#if 0
gdb_printf("--------------------------------\n");
gdb_printf("side_bar_top = %d\n", side_bar_top);
gdb_printf("side_bar_bottom = %d\n", side_bar_bottom);
gdb_printf("side_bar_left = %d\n", side_bar_left);
gdb_printf("side_bar_right = %d\n\n", side_bar_right);
gdb_printf("cmd_top = %d\n", cmd_top);
gdb_printf("cmd_bottom = %d\n", cmd_bottom);
gdb_printf("cmd_left = %d\n", cmd_left);
gdb_printf("cmd_right = %d\n\n", cmd_right);
gdb_printf("pc_bottom = %d\n", pc_bottom);
gdb_printf("pc_top = %d\n", pc_top);
gdb_printf("pc_left = %d\n", pc_left);
gdb_printf("pc_right = %d\n\n", pc_right);
gdb_printf("history_top = %d\n", history_top);
gdb_printf("history_bottom = %d\n", history_bottom);
gdb_printf("history_left = %d\n", history_left);
gdb_printf("history_right = %d\n\n", history_right);
gdb_printf("vertical_divider = %d\n", vertical_divider);
gdb_printf("pc_top_divider = %d\n", pc_top_divider);
gdb_printf("pc_bottom_divider = %d\n\n", pc_bottom_divider);
gdb_printf("pc_lines = %d\n", pc_lines);
gdb_printf("cmd_lines = %d\n", cmd_lines);
gdb_printf("history_lines = %d\n", history_lines);
gdb_printf("history_wrap = %d\n", history_wrap);
#endif
}
void refresh(char *arg, int from_tty)
{
int argc, pc_lines, cmd_lines, i, old_prompt_start;
History *h;
char *argv[5], set_prompt_cmd[1024], old_prompt[1024], tmpCmdLine[1024];;
if (!macsbug_screen)
return;
if (arg && *arg) {
gdb_setup_argv(safe_strcpy(tmpCmdLine, arg), "refresh", &argc, argv, 4);
if (argc > 3)
gdb_error("refresh called with wrong number of arguments.");
pc_lines = gdb_get_int(argv[1]);
if (pc_lines < MIN_PC_LINES || pc_lines > MAX_PC_LINES)
gdb_error("screen pc area must be %d to %d lines long",
MIN_PC_LINES, MAX_PC_LINES);
if (argc == 3) {
cmd_lines = gdb_get_int(argv[2]);
if (cmd_lines < MIN_CMD_LINES || cmd_lines > MAX_CMD_LINES)
gdb_error("screen command line area must be %d to %d lines long",
MIN_CMD_LINES, MAX_CMD_LINES);
} else
cmd_lines = cmd_area_lines;
} else {
pc_lines = pc_area_lines;
cmd_lines = cmd_area_lines;
}
define_macsbug_screen_positions(pc_lines, cmd_lines);
screen_fprintf(stderr, NO_AREA, RESET);
screen_init(history_top, history_left, history_bottom, history_right);
init_sidebar_and_pc_areas();
#if BUFFER_OUTPUT
bp = output_buffer;
buf_row = 0;
#endif
__display_side_bar(NULL, 0);
display_pc_area();
if (history_cnt) {
for (i = history_lines, h = screen_bottom; i > 0 && h; h = h->prev, --i) {
if (h->flags & ERR_LINE)
write_line(GOTO COLOR_RED "%s" COLOR_OFF, i, history_left, h->line);
else
write_line(GOTO "%s", i, history_left, h->line);
END_OF_LINE;
}
screen_top = h ? h->next : history;
FLUSH_BUFFER;
}
gdb_fflush(gdb_current_stdout);
gdb_fflush(gdb_current_stderr);
screen_refresh(1);
old_prompt_start = prompt_start;
prompt_start = sprintf(prompt, GOTO CLEAR_LINE, cmd_top, cmd_left);
if (old_prompt_start) {
gdb_get_prompt(old_prompt);
strcpy(prompt + prompt_start, old_prompt + old_prompt_start);
} else {
char *p1 = prompt + prompt_start;
char *p2 = strstr(gdb_get_prompt(p1), CLEAR_LINE);
if (p2)
strcpy(p1, p2 + strlen(CLEAR_LINE));
}
sprintf(set_prompt_cmd, "set prompt %s", prompt);
doing_set_prompt = 1;
gdb_execute_command(set_prompt_cmd);
doing_set_prompt = 0;
}
#define REFRESH_HELP \
"REFRESH -- Refresh MascBug screen."
void force_pc_area_update(void)
{
previous_pc = 0;
}
void update_macsbug_prompt(void)
{
char *p, set_prompt_cmd[1024], prompt[1024];
if (!doing_set_prompt && macsbug_screen) {
prompt_start = sprintf(prompt, GOTO CLEAR_LINE, cmd_top, cmd_left);
gdb_get_prompt(prompt + prompt_start);
sprintf(set_prompt_cmd, "set prompt %s", prompt);
doing_set_prompt = 1;
gdb_execute_command(set_prompt_cmd);
doing_set_prompt = 0;
}
}
void forget_some_history(int n)
{
History *h;
if (history_cnt > n) {
while (history && n--) {
h = history->next;
gdb_free(history);
history = h;
--history_cnt;
}
history->prev = NULL;
}
}
static void stop_hook(char *arg, int from_tty)
{
gdb_execute_hook(hook_stop);
Update_PC_and_SideBare_Areas();
}
static int line_prefix_cp = 0;
static int xseen = 0;
static int filter_keyboard_characters(int c)
{
char ch = c;
static char line_prefix[5];
static char esc_up_arrow[5] = {ESC, ESC, '[', 'A', '\0'};
static char esc_down_arrow[5] = {ESC, ESC, '[', 'B', '\0'};
#if 0
if (c == '\n' || c == '\r')
line_prefix_cp = 0;
else if (line_prefix_cp < 4) {
line_prefix[line_prefix_cp++] = c;
if (line_prefix_cp == 4) {
if (strcmp(line_prefix, esc_up_arrow) == 0) {
gdb_fprintf(gdb_current_stderr, "еее esc up еее\n");
c = 0;
} else if (strcmp(line_prefix, esc_down_arrow) == 0) {
gdb_fprintf(gdb_current_stderr, "еее esc down еее\n");
c = 0;
} else if (c == ESC)
c = 0;
}
}
#endif
xseen = 1;
return (c);
}
void my_prompt_position_function(int continued)
{
int len, i, j;
char line[1024];
static int used_cmd_lines = 0;
static int starts_top = 0;
if (gdb_interactive() && macsbug_screen)
if (continued == 0) {
immediate_flush = NORMAL_REFRESH;
gdb_fflush(gdb_current_stdout);
gdb_fflush(gdb_current_stderr);
screen_refresh(0);
Update_PC_and_SideBare_Areas();
while (used_cmd_lines)
screen_fprintf(stderr, CMD_AREA, GOTO CLEAR_LINE, cmd_top+used_cmd_lines--, cmd_left);
starts_top = 0;
screen_fprintf(stderr, CMD_AREA, GOTO CLEAR_LINE, cmd_top, cmd_left);
} else if (continued < cmd_lines) {
screen_fprintf(stderr, CMD_AREA, GOTO, cmd_top + continued, cmd_left);
used_cmd_lines = continued;
} else {
for (i = ++starts_top, j = 0; i < continued_count; ++i, ++j) {
len = continued_segment_len[i];
memmove(line, continued_line_starts[i], len);
line[len++] = '\\';
line[len] = '\0';
screen_fprintf(stderr, CMD_AREA, GOTO CLEAR_LINE "%s", cmd_top+j, cmd_left, line);
}
screen_fprintf(stderr, CMD_AREA, GOTO CLEAR_LINE, cmd_top + cmd_lines - 1, cmd_left);
}
gdb_define_raw_input_handler(my_raw_input_handler);
}
void my_raw_input_handler(char *theRawLine)
{
char *p1, *p2, c;
int len;
if (theRawLine) {
p1 = theRawLine;
while (*p1 == ' ' || *p1 == '\t')
++p1;
for (p2 = p1; *p2 && (*p2 != ' ' && *p2 != '\t'); p2++) ;
len = p2 - p1;
c = *p2;
*p2 = '\0';
if (gdb_strcmpl(p1, "end")) {
if (control_level > 0)
--control_level;
if (control_level <= 0) {
gdb_define_raw_input_handler(NULL);
gdb_control_prompt_position(my_prompt_position_function);
reading_raw = 0;
}
}
*p2 = c;
if (control_level <= 0)
gdb_fprintf(gdb_current_stdout, "%s\n", theRawLine);
else
gdb_fprintf(gdb_current_stdout, "%*c%s\n", control_level, ' ', theRawLine);
gdb_fflush(gdb_current_stdout);
*p2 = '\0';
if (gdb_strcmpl(p1, "if") || gdb_strcmpl(p1, "while")) {
gdb_define_raw_input_handler(my_raw_input_handler);
gdb_control_prompt_position(my_prompt_position_function);
++control_level;
}
*p2 = c;
}
}
static int doing_query(const char *prompt, int *result)
{
if (immediate_flush == NORMAL_REFRESH)
immediate_flush = QUERY_REFRESH1;
return (1);
}
static int end_of_query(int result)
{
screen_refresh(0);
immediate_flush = NORMAL_REFRESH;
return (result);
}
void macsbug_on(int resume)
{
get_screen_size(&max_rows, &max_cols);
if (!isatty(STDOUT_FILENO))
gdb_error("MacsBug screen cannot be used in this environment.");
if (max_rows < MIN_SCREEN_ROWS || max_cols < MIN_SCREEN_COLS)
gdb_error(COLOR_RED "\nTerminal window too small (must be at least %ld rows and %ld columns)." COLOR_OFF "\n",
MIN_SCREEN_ROWS, MIN_SCREEN_COLS);
macsbug_screen_stdout = gdb_open_output(stdout, write_to_history_area, NULL);
macsbug_screen_stderr = gdb_open_output(stderr, write_to_history_area, NULL);
gdb_special_events(Gdb_Word_Completion_Cursor, (Gdb_Callback)word_completion_cursor_control);
gdb_special_events(Gdb_Word_Completion_Query, (Gdb_Callback)word_completion_query);
gdb_special_events(Gdb_Before_Query, (Gdb_Callback)doing_query);
gdb_special_events(Gdb_After_Query, (Gdb_Callback)end_of_query);
gdb_redirect_output(macsbug_screen_stderr);
gdb_redirect_output(macsbug_screen_stdout);
gdb_define_raw_input_handler(NULL);
gdb_control_prompt_position(my_prompt_position_function);
gdb_set_int("$macsbug_screen", macsbug_screen = 1);
reading_raw = 0;
if (!resume) {
history_cnt = 0;
history = history_tail = NULL;
screen_top = screen_bottom = NULL;
wrap_lines = 1;
}
prompt_start = 0;
refresh(NULL, 0);
screen_fprintf(stderr, CMD_AREA, GOTO CLEAR_LINE, cmd_top, cmd_left);
}
void macsbug_off(int suspend)
{
History *h;
char set_prompt_cmd[1024];
if (!macsbug_screen)
return;
gdb_close_output(macsbug_screen_stdout);
gdb_close_output(macsbug_screen_stderr);
gdb_special_events(Gdb_Word_Completion_Cursor, NULL);
gdb_special_events(Gdb_Word_Completion_Query, NULL);
gdb_special_events(Gdb_Before_Query, NULL);
gdb_special_events(Gdb_After_Query, NULL);
gdb_define_raw_input_handler(NULL);
gdb_control_prompt_position(NULL);
macsbug_screen_stdout = macsbug_screen_stderr = NULL;
get_screen_size(&max_rows, &max_cols);
if (!suspend) {
while (history) {
h = history->next;
gdb_free(history);
history = h;
}
history_cnt = 0;
history = history_tail = NULL;
screen_top = screen_bottom = NULL;
screen_close();
}
position_cursor_for_shell_input();
gdb_set_int("$macsbug_screen", macsbug_screen = 0);
gdb_get_prompt(prompt);
sprintf(set_prompt_cmd, "set prompt %s", prompt + prompt_start);
doing_set_prompt = 1;
gdb_execute_command(set_prompt_cmd);
doing_set_prompt = 0;
prompt_start = 0;
}
static void mb(char *arg, int from_tty)
{
if (arg && *arg) {
if (gdb_strcmpl(arg, "on")) {
if (!macsbug_screen_stdout)
macsbug_on(0);
} else if (gdb_strcmpl(arg, "off")) {
if (macsbug_screen_stdout)
macsbug_off(0);
} else
gdb_error("macsbug [on | off] expected, got \"%s\"", arg);
} else if (macsbug_screen_stdout)
macsbug_off(0);
else
macsbug_on(0);
}
#define MB_HELP \
"MB [on | off] -- Turn MacsBug display screen on or off or toggle it.\n" \
"Specifying \"on\" turns on the display if not already on.\n" \
"Specifying \"off\" turns off the display if not already off.\n" \
"The default is to toggle the display.\n" \
"\n" \
"Type \"help screen\" command to get a list of all MacsBug screen\n" \
"commands."
void init_macsbug_display(void)
{
MACSBUG_SCREEN_COMMAND(mb, MB_HELP);
MACSBUG_SCREEN_COMMAND(refresh, REFRESH_HELP);
MACSBUG_SCREEN_COMMAND(scroll, SCROLL_HELP);
MACSBUG_SCREEN_COMMAND(su, SU_HELP);
MACSBUG_SCREEN_COMMAND(sd, SD_HELP);
MACSBUG_SCREEN_COMMAND(page, PAGE_HELP);
MACSBUG_SCREEN_COMMAND(pgu, PGU_HELP);
MACSBUG_SCREEN_COMMAND(pgd, PGD_HELP);
MACSBUG_SCREEN_COMMAND(log, LOG_HELP);
MACSBUG_USEFUL_COMMAND(__display_side_bar, __DISPLAY_SIDE_BAR_HELP);
gdb_define_cmd("log?", which_log, macsbug_internal_class, "");
COMMAND_ALIAS(page, pg);
COMMAND_ALIAS(su, scu);
COMMAND_ALIAS(sd, scd);
}