#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "MacsBug.h"
int ditto = 0;
int unmangle = 0;
int echo_commands = 0;
int wrap_lines = 1;
int show_so_si_src = 1;
int dx_state = 1;
int sidebar_state = 1;
int tab_value = DEFAULT_TAB_VALUE;
int pc_area_lines = DEFAULT_PC_LINES;
int cmd_area_lines = DEFAULT_CMD_LINES;
int max_history = DEFAULT_HISTORY_SIZE;
int hexdump_width = DEFAULT_HEXDUMP_WIDTH;
int hexdump_group = DEFAULT_HEXDUMP_GROUP;
int mb_testing = 0;
static char *ditto_args;
static char *unmangle_args;
static char *echo_args;
static char *wrap_args;
static char *sosi_args;
static char *dx_args;
static char *sidebar_args;
static int new_tab_value = DEFAULT_TAB_VALUE;
static int new_pc_area_lines = DEFAULT_PC_LINES;
static int new_cmd_area_lines = DEFAULT_CMD_LINES;
static int new_max_history = DEFAULT_HISTORY_SIZE;
static int new_hexdump_width = DEFAULT_HEXDUMP_WIDTH;
static int new_hexdump_group = DEFAULT_HEXDUMP_GROUP;
static int new_testing;
static void check_all_sets(char *theSetting, Gdb_Set_Type type, void *value, int show,
int confirm)
{
char *prompt;
if (macsbug_screen && !doing_set_prompt && theSetting && gdb_strcmpl(theSetting, "prompt")) {
if (type == Set_String)
update_macsbug_prompt();
}
}
static void macsbug_set(char *cmd, char **arg, int *value, char *meaning, int confirm,
void (*additional_stuff)(int state, int confirm))
{
int argc, err = 0;
char *argv[4], tmpCmdLine[1024];
static char *options[] = {"ON", "OFF", "NOW", "SHOW", NULL};
gdb_setup_argv(safe_strcpy(tmpCmdLine, *arg), cmd, &argc, argv, 3);
if (argc == 1) {
if (*value) {
*value = 0;
if (additional_stuff)
additional_stuff(0, confirm);
if (confirm)
gdb_printf("%s is disabled\n", meaning);
} else {
*value = 1;
if (additional_stuff)
additional_stuff(1, confirm);
if (confirm)
gdb_printf("%s is enabled\n", meaning);
}
} else if (argc == 2) {
switch (gdb_keyword(argv[1], options)) {
case 0:
if (*value) {
if (confirm)
gdb_printf("%s is still enabled\n", meaning);
} else {
*value = 1;
if (additional_stuff)
additional_stuff(1, confirm);
if (confirm)
gdb_printf("%s is enabled\n", meaning);
}
break;
case 1:
if (*value) {
*value = 0;
if (additional_stuff)
additional_stuff(0, confirm);
if (confirm)
gdb_printf("%s is disabled\n", meaning);
} else if (confirm)
gdb_printf("%s is still disabled\n", meaning);
break;
case 2:
case 3:
if (*value)
gdb_printf("%s is still enabled\n", meaning);
else
gdb_printf("%s is still disabled\n", meaning);
break;
default:
err = 1;
}
} else
err = 1;
gdb_set_int("$__lastcmd__", 40);
if (*value)
if (*arg)
*arg = strcpy((char *)gdb_realloc(*arg, 3), "on");
else
*arg = strcpy((char *)gdb_malloc(3), "on");
else if (*arg)
*arg = strcpy((char *)gdb_realloc(*arg, 4), "off");
else
*arg = strcpy((char *)gdb_malloc(4), "off");
if (err)
gdb_error("\"on\", \"off\", \"now\", or \"show\" expected.");
}
static void set_gdb_demangle(int state, int confirm)
{
if (state) {
gdb_execute_command("set print demangle on");
gdb_execute_command("set print asm-demangle on");
} else {
gdb_execute_command("set print demangle off");
gdb_execute_command("set print asm-demangle off");
}
}
static void mset(char *arg, int from_tty)
{
int argc;
char *set_args, *p, *argv[5], tmpCmdLine[1024];
static char *macsbug_set_keywords[] = {"DITTO", "UNMANGLE", NULL};
gdb_setup_argv(safe_strcpy(tmpCmdLine, arg), "mset", &argc, argv, 4);
if (argc > 1) {
if (argc == 2)
p = "";
else if (argc == 3)
p = argv[2];
else
p = NULL;
if (p) {
if (gdb_strcmpl(argv[1], "ditto")) {
if (ditto_args)
gdb_free(ditto_args);
ditto_args = strcpy((char *)gdb_malloc(strlen(arg)+1), p);
macsbug_set("mset", &ditto_args, &ditto, "Ditto-display in memory dumps", from_tty, NULL);
} else if (gdb_strcmpl(argv[1], "unmangle")) {
if (unmangle_args)
gdb_free(unmangle_args);
unmangle_args = strcpy((char *)gdb_malloc(strlen(arg)+1), p);
macsbug_set("mset", &unmangle_args, &unmangle, "Unmangling of symbols", from_tty, set_gdb_demangle);
} else
gdb_error("usage: MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] (invalid arguments)");
} else
gdb_error("usage: MSET DITTO | UNMANGLE [ON | OFF | NOW | SHOW] (invalid arguments)");
}
gdb_set_int("$__lastcmd__", 40);
}
#define MSET_HELP \
"MSET option [ON|OFF|NOW|SHOW] -- Change the specified gdb MacsBug behavior.\n" \
"On/off options toggle if you don't specify ON or OFF. NOW or SHOW lets you check\n" \
"the setting without disturbing it. The options are:\n" \
"\n" \
" DITTO: When on, DM and DMA show ditto marks (''''''') instead of groups\n" \
" of identical lines.\n" \
"\n" \
" UNMANGLE: When on, C++ symbols appear as in source code, such as \"TFoo::Bar()\".\n"\
" When off, you'll see stuff like \"Bar__4TFooFv\" instead.\n" \
"\n" \
"SHOW is the same as NOW to display the current setting. It was added since gdb\n" \
"uses SHOW to show settings.\n" \
"\n" \
"Macsbug features not supported: The is the MacsBug SET command was changed to\n" \
" MSET since SET conflicts with the SET gdb command.\n" \
"\n" \
" Options AUTOGP, ECHO, MOUSE, MENUBAR, SCROLLPROMPT,\n" \
" SUSPENDPROMPT, and SIMPLIFIED not supported.\n" \
"\n" \
"This command is depricated. Use SET. Type \"help set\" to see a list of all gdb\n" \
"SET options. The MacsBug options all begin with \"mb-\" although it is optional\n" \
"with \"ditto\" and \"unmangle\" for compatibility with MSET."
static void control_breakpoints(int state, int confirm)
{
if (state)
gdb_execute_command("enable breakpoints");
else
gdb_execute_command("disable breakpoints");
}
static void dx(char *arg, int confirm)
{
if (dx_args)
gdb_free(dx_args);
if (arg)
dx_args = strcpy((char *)gdb_malloc(strlen(arg)+1), arg);
else
dx_args = strcpy((char *)gdb_malloc(1), "");
macsbug_set("dx", &dx_args, &dx_state, "Breakpoints", confirm, control_breakpoints);
gdb_set_int("$__lastcmd__", 39);
}
#define DX_HELP \
"DX [ON | OFF | NOW | SHOW] -- Temporarily enable/disable/toggle breakpoints.\n" \
"The setting is toggled when there is no argument.\n" \
"\n" \
"SHOW is the same as NOW to display the current setting. It was added\n" \
"since gdb uses SHOW to show settings."
#define SET_ON_OFF_NOW(funct_name, sw_name, sw_value, help, additional_stuff) \
static void funct_name(char *theSetting, Gdb_Set_Type type, void *value, int show, \
int confirm) \
{ \
macsbug_set("set", &sw_value, &sw_name, help, confirm, additional_stuff); \
}
SET_ON_OFF_NOW(set_ditto, ditto, ditto_args, "Ditto-display in memory dumps", NULL);
SET_ON_OFF_NOW(set_unmangle, unmangle, unmangle_args, "Unmangling of symbols", set_gdb_demangle);
SET_ON_OFF_NOW(set_echo, echo_commands, echo_args, "Echoing command lines to history", NULL);
SET_ON_OFF_NOW(set_wrap, wrap_lines, wrap_args, "Wrapping history lines", NULL);
SET_ON_OFF_NOW(set_so_si_source, show_so_si_src, sosi_args, "Source with SO/SI", NULL);
SET_ON_OFF_NOW(set_dx, dx_state, dx_args, "Breakpoints", control_breakpoints);
SET_ON_OFF_NOW(set_sidebar, sidebar_state, sidebar_args, "Displaying register side-bar", NULL);
#define DITTO_DESCRIPTION "Set ditto marks for DM and DMA repeated lines"
#define UNMANGLE_DESCRIPTION "Set C++ symbol unmangling"
#define ECHO_DESCRIPTION "Set echoing commands to history area"
#define WRAP_DESCRIPTION "Set history area line wrapping"
#define SOSI_DESCRIPTION "Set source display with SO/SI"
#define DX_DESCRIPTION "Set stopping on breakpoints"
#define SIDEBAR_DESCRIPTION "Set displaying register side-bar (for ID, IL, IP, SO, SI)"
static void set_tab(char *theSetting, Gdb_Set_Type type, void *value, int show,
int confirm)
{
if (new_tab_value < 0 | new_tab_value > 20)
gdb_error("invalid tab value (must be 0 to 20)");
else
tab_value = new_tab_value;
}
#define TAB_DESCRIPTION "Set history area source line tab interpretation"
static void set_pc_area(char *theSetting, Gdb_Set_Type type, void *value, int show,
int confirm)
{
if (new_pc_area_lines < MIN_PC_LINES || new_pc_area_lines > MAX_PC_LINES)
gdb_error("screen pc area must be %d to %d lines long", MIN_PC_LINES, MAX_PC_LINES);
else {
pc_area_lines = new_pc_area_lines;
if (macsbug_screen)
refresh(NULL, 0);
}
}
#define PC_AREA_DESCRIPTION "Set number of lines in pc area"
static void set_cmd_area(char *theSetting, Gdb_Set_Type type, void *value, int show,
int confirm)
{
if (new_cmd_area_lines < MIN_PC_LINES || new_cmd_area_lines > MAX_PC_LINES)
gdb_error("screen command linearea must be %d to %d lines long", MIN_CMD_LINES, MAX_CMD_LINES);
else {
cmd_area_lines = new_cmd_area_lines;
if (macsbug_screen)
refresh(NULL, 0);
}
}
#define CMD_AREA_DESCRIPTION "Set number of lines in command line area"
static void set_history_size(char *theSetting, Gdb_Set_Type type, void *value, int show,
int confirm)
{
get_screen_size(&max_rows, &max_cols);
if (new_max_history < max_rows)
gdb_error("the history size cannot be set smaller than the number of lines in the history area");
else {
if (macsbug_screen && new_max_history < max_history)
forget_some_history(new_max_history);
max_history = new_max_history;
}
}
#define HISTORY_DESCRIPTION "Set number of remembered history lines"
static void set_hexdump_width(char *theSetting, Gdb_Set_Type type, void *value, int show,
int confirm)
{
if (new_hexdump_width < 1 || new_hexdump_width >= 1024)
gdb_error("invalid value");
else if (new_hexdump_width % hexdump_group != 0)
gdb_error("hexdump width must be a multiple of the group value");
else
hexdump_width = new_hexdump_width;
}
#define HEXDUMP_WIDTH_DESCRIPTION "Set hexdump number of bytes per line"
static void set_hexdump_group(char *theSetting, Gdb_Set_Type type, void *value, int show,
int confirm)
{
if (new_hexdump_group < 1 || new_hexdump_group >= 1024)
gdb_error("invalid value");
else if (hexdump_width % new_hexdump_group != 0)
gdb_error("hexdump width must be a multiple of the group value");
else
hexdump_group = new_hexdump_group;
}
#define HEXDUMP_GROUP_DESCRIPTION "Set number of bytes grouped together without intervening spaces"
static void set_mb_testing(char *theSetting, Gdb_Set_Type type, void *value, int show,
int confirm)
{
switch (new_testing) {
case 0:
mb_testing = 0;
break;
default:
gdb_error("Invalid value.");
break;
}
}
#define TESTING_DESCRIPTION "Private debugging value";
void init_macsbug_set(void)
{
MACSBUG_COMMAND(dx, DX_HELP);
gdb_define_cmd("mset", mset, Gdb_Support, MSET_HELP);
gdb_define_set_generic(check_all_sets);
gdb_define_set("ditto", set_ditto, Set_String, &ditto_args, 0, DITTO_DESCRIPTION);
gdb_define_set("unmangle", set_unmangle, Set_String, &unmangle_args, 0, UNMANGLE_DESCRIPTION);
gdb_define_set("dx", set_dx, Set_String, &dx_args, 0, DX_DESCRIPTION);
gdb_define_set("mb-ditto", set_ditto, Set_String, &ditto_args, 0, DITTO_DESCRIPTION);
gdb_define_set("mb-unmangle", set_unmangle, Set_String, &unmangle_args, 0, UNMANGLE_DESCRIPTION);
gdb_define_set("mb-echo", set_echo, Set_String, &echo_args, 0, ECHO_DESCRIPTION);
gdb_define_set("mb-wrap", set_wrap, Set_String, &wrap_args, 0, WRAP_DESCRIPTION);
gdb_define_set("mb-so-si-source", set_so_si_source, Set_String, &sosi_args, 0, SOSI_DESCRIPTION);
gdb_define_set("mb-dx", set_dx, Set_String, &dx_args, 0, DX_DESCRIPTION);
gdb_define_set("mb-sidebar", set_sidebar, Set_String, &sidebar_args, 0, SIDEBAR_DESCRIPTION);
gdb_define_set("mb-tab", set_tab, Set_Int, &new_tab_value, 0, TAB_DESCRIPTION);
gdb_define_set("mb-pc-area", set_pc_area, Set_Int, &new_pc_area_lines, 0, PC_AREA_DESCRIPTION);
gdb_define_set("mb-cmd-area", set_cmd_area, Set_Int, &new_cmd_area_lines, 0, CMD_AREA_DESCRIPTION);
gdb_define_set("mb-history", set_history_size, Set_Int, &new_max_history, 0, HISTORY_DESCRIPTION);
gdb_define_set("mb-hexdump-width",set_hexdump_width,Set_Int, &new_hexdump_width, 0, HEXDUMP_WIDTH_DESCRIPTION);
gdb_define_set("mb-hexdump-group",set_hexdump_group,Set_Int, &new_hexdump_group, 0, HEXDUMP_GROUP_DESCRIPTION);
#define INIT_ENABLED_DISABLED(x, y) if (y) \
x = strcpy((char *)gdb_malloc(3), "on"); \
else \
x = strcpy((char *)gdb_malloc(4), "off");
INIT_ENABLED_DISABLED(ditto_args, ditto);
INIT_ENABLED_DISABLED(unmangle_args, unmangle);
INIT_ENABLED_DISABLED(echo_args, echo_commands);
INIT_ENABLED_DISABLED(wrap_args, wrap_lines);
INIT_ENABLED_DISABLED(sosi_args, show_so_si_src);
INIT_ENABLED_DISABLED(dx_args, dx_state);
INIT_ENABLED_DISABLED(sidebar_args, sidebar_state);
}