#include "defs.h"
#include "gdbcmd.h"
#include "call-cmds.h"
#include "cli/cli-cmds.h"
#include "cli/cli-script.h"
#include "cli/cli-setshow.h"
#include "symtab.h"
#include "inferior.h"
#include <signal.h>
#include "target.h"
#include "breakpoint.h"
#include "gdbtypes.h"
#include "expression.h"
#include "value.h"
#include "language.h"
#include "terminal.h"
#include "annotate.h"
#include "completer.h"
#include "top.h"
#include "version.h"
#include "serial.h"
#include "doublest.h"
#include "gdb_assert.h"
#include "interpreter.h"
#include <readline/readline.h>
#include <readline/history.h>
#undef savestring
#include <sys/types.h>
#include <setjmp.h>
#include "event-top.h"
#include "gdb_string.h"
#include "gdb_stat.h"
#include <ctype.h>
#include "ui-out.h"
#include "cli-out.h"
#ifndef DEFAULT_PROMPT
#define DEFAULT_PROMPT "(gdb) "
#endif
#ifndef GDBINIT_FILENAME
#define GDBINIT_FILENAME ".gdbinit"
#endif
#ifndef GDBINIT_GLOBAL
#define GDBINIT_GLOBAL "/etc/gdb.conf"
#endif
char gdbinit[] = GDBINIT_FILENAME;
char gdbinit_global[] = GDBINIT_GLOBAL;
int inhibit_gdbinit = 0;
int use_windows = 1;
extern char lang_frame_mismatch_warn[];
int caution = 1;
FILE *instream;
char *current_directory;
char gdb_dirbuf[1024];
void (*window_hook) (FILE *, char *);
int epoch_interface;
int xgdb_verbose;
static char *gdb_prompt_string;
char *line;
int linesize = 100;
int server_command;
int baud_rate = -1;
int remote_timeout = 2;
int remote_debug = 0;
int target_executing = 0;
static int control_level;
#ifndef STOP_SIGNAL
#ifdef SIGTSTP
#define STOP_SIGNAL SIGTSTP
static void stop_sig (int);
#endif
#endif
void (*init_ui_hook) (char *argv0);
int (*ui_loop_hook) (int);
void (*command_loop_hook) (void);
void (*print_frame_info_listing_hook) (struct symtab * s, int line,
int stopline, int noerror);
void (*print_frame_more_info_hook) (struct ui_out *uiout,
struct symtab_and_line *sal,
struct frame_info *fi);
int (*query_hook) (const char *, va_list);
void (*warning_hook) (const char *, va_list);
void (*readline_begin_hook) (char *, ...);
char *(*readline_hook) (char *);
void (*readline_end_hook) (void);
void (*create_breakpoint_hook) (struct breakpoint * bpt);
void (*delete_breakpoint_hook) (struct breakpoint * bpt);
void (*modify_breakpoint_hook) (struct breakpoint * bpt);
void (*attach_hook) (void);
void (*detach_hook) (void);
void (*interactive_hook) (void);
void (*registers_changed_hook) (void);
void (*register_changed_hook) (int regno);
void (*memory_changed_hook) (CORE_ADDR addr, int len);
ptid_t (*target_wait_hook) (ptid_t ptid,
struct target_waitstatus * status,
gdb_client_data client_data);
void (*call_command_hook) (struct cmd_list_element * c, char *cmd,
int from_tty);
void (*set_hook) PARAMS ((struct cmd_list_element *c));
void (*print_source_lines_hook) PARAMS ((struct symtab * s,
int line, int stopline));
void (*set_hook) (struct cmd_list_element * c);
void (*state_change_hook) PARAMS ((Debugger_state new_state));
void (*frame_changed_hook) PARAMS ((int new_frame_number));
void (*stack_changed_hook) PARAMS ((void));
char *(*command_line_input_hook) PARAMS ((char *, int, char *));
void (*context_hook) (int id);
NORETURN void (*error_hook) (void) ATTR_NORETURN;
void (*stepping_command_hook) (void);
void (*continue_command_hook) (void);
int (*run_command_hook) (void);
#if defined(HAVE_SIGSETJMP)
#define SIGJMP_BUF sigjmp_buf
#define SIGSETJMP(buf) sigsetjmp((buf), 1)
#define SIGLONGJMP(buf,val) siglongjmp((buf), (val))
#else
#define SIGJMP_BUF jmp_buf
#define SIGSETJMP(buf) setjmp(buf)
#define SIGLONGJMP(buf,val) longjmp((buf), (val))
#endif
SIGJMP_BUF *catch_return;
NORETURN void
return_to_top_level (enum return_reason reason)
{
quit_flag = 0;
immediate_quit = 0;
bpstat_clear_actions (stop_bpstat);
disable_current_display ();
do_cleanups (ALL_CLEANUPS);
if (event_loop_p && target_can_async_p () && !target_executing)
do_exec_cleanups (ALL_CLEANUPS);
if (event_loop_p && sync_execution)
do_exec_error_cleanups (ALL_CLEANUPS);
if (annotation_level > 1)
switch (reason)
{
case RETURN_QUIT:
annotate_quit ();
break;
case RETURN_ERROR:
annotate_error ();
break;
}
(NORETURN void) SIGLONGJMP (*catch_return, (int) reason);
}
static void
catcher (catch_exceptions_ftype *func,
struct ui_out *func_uiout,
void *func_args,
int *func_val,
enum return_reason *func_caught,
char *errstring,
return_mask mask)
{
SIGJMP_BUF *saved_catch;
SIGJMP_BUF catch;
struct cleanup *saved_cleanup_chain;
char *saved_error_pre_print;
char *saved_quit_pre_print;
struct ui_out *saved_uiout;
int caught;
int val;
saved_error_pre_print = error_pre_print;
saved_quit_pre_print = quit_pre_print;
if (mask & RETURN_MASK_ERROR)
error_pre_print = errstring;
if (mask & RETURN_MASK_QUIT)
quit_pre_print = errstring;
saved_uiout = uiout;
uiout = func_uiout;
saved_cleanup_chain = save_cleanups ();
saved_catch = catch_return;
catch_return = &catch;
caught = SIGSETJMP (catch);
if (!caught)
val = (*func) (func_uiout, func_args);
else
val = 0;
catch_return = saved_catch;
restore_cleanups (saved_cleanup_chain);
if (uiout != func_uiout)
saved_uiout = uiout;
else
uiout = saved_uiout;
if (mask & RETURN_MASK_QUIT)
quit_pre_print = saved_quit_pre_print;
if (mask & RETURN_MASK_ERROR)
error_pre_print = saved_error_pre_print;
if (!caught || (mask & RETURN_MASK (caught)))
{
*func_val = val;
*func_caught = caught;
return;
}
return_to_top_level (caught);
}
int
catch_exceptions (struct ui_out *uiout,
catch_exceptions_ftype *func,
void *func_args,
char *errstring,
return_mask mask)
{
int val;
enum return_reason caught;
catcher (func, uiout, func_args, &val, &caught, errstring, mask);
gdb_assert (val >= 0);
gdb_assert (caught <= 0);
if (caught < 0)
return caught;
return val;
}
struct catch_errors_args
{
catch_errors_ftype *func;
void *func_args;
};
int
do_catch_errors (struct ui_out *uiout, void *data)
{
struct catch_errors_args *args = data;
return args->func (args->func_args);
}
int
catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
return_mask mask)
{
int val;
enum return_reason caught;
struct catch_errors_args args;
args.func = func;
args.func_args = func_args;
catcher (do_catch_errors, uiout, &args, &val, &caught, errstring, mask);
if (caught != 0)
return 0;
return val;
}
struct captured_command_args
{
catch_command_errors_ftype *command;
char *arg;
int from_tty;
};
static int
do_captured_command (void *data)
{
struct captured_command_args *context = data;
context->command (context->arg, context->from_tty);
do_cleanups (ALL_CLEANUPS);
return 1;
}
int
catch_command_errors (catch_command_errors_ftype * command,
char *arg, int from_tty, return_mask mask)
{
struct captured_command_args args;
args.command = command;
args.arg = arg;
args.from_tty = from_tty;
return catch_errors (do_captured_command, &args, "", mask);
}
#ifdef SIGHUP
int
quit_cover (void *s)
{
caution = 0;
quit_command ((char *) 0, 0);
return 0;
}
static void
disconnect (int signo)
{
catch_errors (quit_cover, NULL,
"Could not kill the program being debugged", RETURN_MASK_ALL);
signal (SIGHUP, SIG_DFL);
kill (getpid (), SIGHUP);
}
#endif
int source_line_number;
char *source_file_name;
char *source_error;
static int source_error_allocated;
char *source_pre_error;
void
do_restore_instream_cleanup (void *stream)
{
instream = stream;
}
void
read_command_file (FILE *stream)
{
struct cleanup *cleanups;
cleanups = make_cleanup (do_restore_instream_cleanup, instream);
instream = stream;
if (target_can_async_p ())
{
gdb_set_async_override (1);
make_cleanup (gdb_set_async_override, 0);
}
command_loop ();
do_cleanups (cleanups);
}
void (*pre_init_ui_hook) (void);
#ifdef __MSDOS__
void
do_chdir_cleanup (void *old_dir)
{
chdir (old_dir);
xfree (old_dir);
}
#endif
void
execute_command (char *p, int from_tty)
{
register struct cmd_list_element *c;
register enum language flang;
static int warned = 0;
char *line;
free_all_values ();
alloca (0);
if (p == NULL)
return;
serial_log_command (p);
while (*p == ' ' || *p == '\t')
p++;
if (*p)
{
char *arg;
line = p;
c = lookup_cmd (&p, cmdlist, "", 0, 1);
if (event_loop_p && target_can_async_p () && target_executing)
if (!strcmp (c->name, "help")
&& !strcmp (c->name, "pwd")
&& !strcmp (c->name, "show")
&& !strcmp (c->name, "stop"))
error ("Cannot execute this command while the target is running.");
arg = *p ? p : 0;
if (arg
&& c->type != set_cmd
&& !is_complete_command (c->function.cfunc))
{
p = arg + strlen (arg) - 1;
while (p >= arg && (*p == ' ' || *p == '\t'))
p--;
*(p + 1) = '\0';
}
if ((c->hook_pre) && (!c->hook_in))
{
c->hook_in = 1;
execute_user_command (c->hook_pre, (char *) 0);
c->hook_in = 0;
}
if (c->flags & DEPRECATED_WARN_USER)
deprecated_cmd_warning (&line);
if (c->class == class_user)
execute_user_command (c, arg);
else if (c->type == set_cmd || c->type == show_cmd)
do_setshow_command (arg, from_tty & caution, c);
else if (c->function.cfunc == NO_FUNCTION)
error ("That is not a command, just a help topic.");
else if (call_command_hook)
call_command_hook (c, arg, from_tty & caution);
else
(*c->function.cfunc) (arg, from_tty & caution);
if ((c->hook_post) && (!c->hook_in))
{
c->hook_in = 1;
execute_user_command (c->hook_post, (char *) 0);
c->hook_in = 0;
}
}
if (current_language != expected_language)
{
if (language_mode == language_mode_auto)
{
language_info (1);
}
warned = 0;
}
if (target_has_stack)
{
flang = get_frame_language ();
if (!warned
&& flang != language_unknown
&& flang != current_language->la_language)
{
printf_filtered ("%s\n", lang_frame_mismatch_warn);
warned = 1;
}
}
}
void
command_loop (void)
{
struct cleanup *old_chain;
char *command;
int stdin_is_tty = ISATTY (stdin);
long time_at_cmd_start;
#ifdef HAVE_SBRK
long space_at_cmd_start = 0;
#endif
extern int display_time;
extern int display_space;
while (instream && !feof (instream))
{
if (window_hook && instream == stdin)
(*window_hook) (instream, get_prompt ());
quit_flag = 0;
if (instream == stdin && stdin_is_tty)
reinitialize_more_filter ();
old_chain = make_cleanup (null_cleanup, 0);
command = command_line_input (instream == stdin ?
get_prompt () : (char *) NULL,
instream == stdin, "prompt");
if (command == 0)
return;
time_at_cmd_start = get_run_time ();
if (display_space)
{
#ifdef HAVE_SBRK
extern char **environ;
char *lim = (char *) sbrk (0);
space_at_cmd_start = (long) (lim - (char *) &environ);
#endif
}
execute_command (command, instream == stdin);
bpstat_do_actions (&stop_bpstat);
do_cleanups (old_chain);
if (display_time)
{
long cmd_time = get_run_time () - time_at_cmd_start;
printf_unfiltered ("Command execution time: %ld.%06ld\n",
cmd_time / 1000000, cmd_time % 1000000);
}
if (display_space)
{
#ifdef HAVE_SBRK
extern char **environ;
char *lim = (char *) sbrk (0);
long space_now = lim - (char *) &environ;
long space_diff = space_now - space_at_cmd_start;
printf_unfiltered ("Space used: %ld (%c%ld for this command)\n",
space_now,
(space_diff >= 0 ? '+' : '-'),
space_diff);
#endif
}
}
}
void
simplified_command_loop (char *(*read_input_func) (char *),
void (*execute_command_func) (char *, int))
{
struct cleanup *old_chain;
char *command;
int stdin_is_tty = ISATTY (stdin);
while (instream && !feof (instream))
{
quit_flag = 0;
if (instream == stdin && stdin_is_tty)
reinitialize_more_filter ();
old_chain = make_cleanup (null_cleanup, 0);
command = (*read_input_func) (instream == stdin ?
get_prompt () : (char *) NULL);
if (command == 0)
return;
(*execute_command_func) (command, instream == stdin);
bpstat_do_actions (&stop_bpstat);
do_cleanups (old_chain);
}
}
void
dont_repeat (void)
{
if (server_command)
return;
if (instream == stdin)
*line = 0;
}
char *
gdb_readline (char *prompt_arg)
{
int c;
char *result;
int input_index = 0;
int result_size = 80;
if (prompt_arg)
{
fputs_unfiltered (prompt_arg, gdb_stdout);
gdb_flush (gdb_stdout);
}
result = (char *) xmalloc (result_size);
while (1)
{
c = fgetc (instream ? instream : stdin);
if (c == EOF)
{
if (input_index > 0)
break;
xfree (result);
return NULL;
}
if (c == '\n')
#ifndef CRLF_SOURCE_FILES
break;
#else
{
if (input_index > 0 && result[input_index - 1] == '\r')
input_index--;
break;
}
#endif
result[input_index++] = c;
while (input_index >= result_size)
{
result_size *= 2;
result = (char *) xrealloc (result, result_size);
}
}
result[input_index++] = '\0';
return result;
}
static int command_editing_p;
int history_expansion_p;
static int write_history_p;
static int history_size;
static char *history_filename;
#ifdef STOP_SIGNAL
static void
stop_sig (int signo)
{
#if STOP_SIGNAL == SIGTSTP
signal (SIGTSTP, SIG_DFL);
#if HAVE_SIGPROCMASK
{
sigset_t zero;
sigemptyset (&zero);
sigprocmask (SIG_SETMASK, &zero, 0);
}
#elif HAVE_SIGSETMASK
sigsetmask (0);
#endif
kill (getpid (), SIGTSTP);
signal (SIGTSTP, stop_sig);
#else
signal (STOP_SIGNAL, stop_sig);
#endif
printf_unfiltered ("%s", get_prompt ());
gdb_flush (gdb_stdout);
dont_repeat ();
}
#endif
static void
float_handler (int signo)
{
signal (SIGFPE, float_handler);
error ("Erroneous arithmetic operation.");
}
static void
do_nothing (int signo)
{
signal (signo, do_nothing);
}
static void
init_signals (void)
{
signal (SIGINT, request_quit);
#ifdef SIGTRAP
signal (SIGTRAP, SIG_DFL);
#endif
#ifdef SIGQUIT
signal (SIGQUIT, do_nothing);
#endif
#ifdef SIGHUP
if (signal (SIGHUP, do_nothing) != SIG_IGN)
signal (SIGHUP, disconnect);
#endif
signal (SIGFPE, float_handler);
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
signal (SIGWINCH, SIGWINCH_HANDLER);
#endif
}
static int operate_saved_history = -1;
void
gdb_rl_operate_and_get_next_completion ()
{
int delta = where_history () - operate_saved_history;
rl_get_previous_history (delta, 0);
operate_saved_history = -1;
rl_redisplay ();
after_char_processing_hook = NULL;
rl_pre_input_hook = NULL;
}
static int
gdb_rl_operate_and_get_next (int count, int key)
{
if (event_loop_p)
{
after_char_processing_hook = gdb_rl_operate_and_get_next_completion;
}
else
{
rl_pre_input_hook = (Function *) gdb_rl_operate_and_get_next_completion;
}
operate_saved_history = where_history () + 1;
return rl_newline (1, key);
}
char *
command_line_input (char *prompt_arg, int repeat, char *annotation_suffix)
{
static char *linebuffer = 0;
static unsigned linelength = 0;
register char *p;
char *p1;
char *rl;
char *local_prompt = prompt_arg;
char *nline;
char got_eof = 0;
if (annotation_suffix == NULL)
annotation_suffix = "";
if (command_line_input_hook && (instream == stdin))
{
char *ret_val;
ret_val = command_line_input_hook (prompt_arg, repeat, annotation_suffix);
return ret_val;
}
if (annotation_level > 1 && instream == stdin)
{
local_prompt = alloca ((prompt_arg == NULL ? 0 : strlen (prompt_arg))
+ strlen (annotation_suffix) + 40);
if (prompt_arg == NULL)
local_prompt[0] = '\0';
else
strcpy (local_prompt, prompt_arg);
strcat (local_prompt, "\n\032\032");
strcat (local_prompt, annotation_suffix);
strcat (local_prompt, "\n");
}
if (linebuffer == 0)
{
linelength = 80;
linebuffer = (char *) xmalloc (linelength);
}
p = linebuffer;
immediate_quit++;
#ifdef STOP_SIGNAL
if (job_control)
{
if (event_loop_p)
signal (STOP_SIGNAL, handle_stop_sig);
else
signal (STOP_SIGNAL, stop_sig);
}
#endif
while (1)
{
wrap_here ("");
gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr);
if (source_file_name != NULL)
{
++source_line_number;
sprintf (source_error,
"%s%s:%d: Error in sourced command file:\n",
source_pre_error,
source_file_name,
source_line_number);
error_pre_print = source_error;
}
if (annotation_level > 1 && instream == stdin)
{
printf_unfiltered ("\n\032\032pre-");
printf_unfiltered (annotation_suffix);
printf_unfiltered ("\n");
}
if (readline_hook && instream == NULL)
{
rl = (*readline_hook) (local_prompt);
}
else if (command_editing_p && instream == stdin && ISATTY (instream))
{
rl = readline (local_prompt);
}
else
{
rl = gdb_readline (local_prompt);
}
if (annotation_level > 1 && instream == stdin)
{
printf_unfiltered ("\n\032\032post-");
printf_unfiltered (annotation_suffix);
printf_unfiltered ("\n");
}
if (!rl || rl == (char *) EOF)
{
got_eof = 1;
break;
}
if (strlen (rl) + 1 + (p - linebuffer) > linelength)
{
linelength = strlen (rl) + 1 + (p - linebuffer);
nline = (char *) xrealloc (linebuffer, linelength);
p += nline - linebuffer;
linebuffer = nline;
}
p1 = rl;
while (*p1)
*p++ = *p1++;
xfree (rl);
if (p == linebuffer || *(p - 1) != '\\')
break;
p--;
local_prompt = (char *) 0;
}
#ifdef STOP_SIGNAL
if (job_control)
signal (STOP_SIGNAL, SIG_DFL);
#endif
immediate_quit--;
if (got_eof)
return NULL;
#define SERVER_COMMAND_LENGTH 7
server_command =
(p - linebuffer > SERVER_COMMAND_LENGTH)
&& STREQN (linebuffer, "server ", SERVER_COMMAND_LENGTH);
if (server_command)
{
*p = '\0';
return linebuffer + SERVER_COMMAND_LENGTH;
}
if (history_expansion_p && instream == stdin
&& ISATTY (instream))
{
char *history_value;
int expanded;
*p = '\0';
expanded = history_expand (linebuffer, &history_value);
if (expanded)
{
printf_unfiltered ("%s\n", history_value);
if (expanded < 0)
{
xfree (history_value);
return command_line_input (prompt_arg, repeat, annotation_suffix);
}
if (strlen (history_value) > linelength)
{
linelength = strlen (history_value) + 1;
linebuffer = (char *) xrealloc (linebuffer, linelength);
}
strcpy (linebuffer, history_value);
p = linebuffer + strlen (linebuffer);
xfree (history_value);
}
}
if (repeat && p == linebuffer)
return line;
for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++);
if (repeat && !*p1)
return line;
*p = 0;
if (instream == stdin
&& ISATTY (stdin) && *linebuffer)
add_history (linebuffer);
if (*p1 == '#')
*p1 = '\0';
if (repeat)
{
if (linelength > linesize)
{
line = xrealloc (line, linelength);
linesize = linelength;
}
strcpy (line, linebuffer);
return line;
}
return linebuffer;
}
void
print_gdb_version (struct ui_file *stream)
{
fprintf_filtered (stream, "GNU gdb %s (%s)\n", version, build_date);
fprintf_filtered (stream, "Copyright 2002 Free Software Foundation, Inc.\n");
fprintf_filtered (stream, "\
GDB is free software, covered by the GNU General Public License, and you are\n\
welcome to change it and/or distribute copies of it under certain conditions.\n\
Type \"show copying\" to see the conditions.\n\
There is absolutely no warranty for GDB. Type \"show warranty\" for details.\n");
fprintf_filtered (stream, "This GDB was configured as \"");
if (!STREQ (host_name, target_name))
{
fprintf_filtered (stream, "--host=%s --target=%s", host_name, target_name);
}
else
{
fprintf_filtered (stream, "%s", host_name);
}
fprintf_filtered (stream, "\".");
}
#define MAX_PROMPT_SIZE 256
static int gdb_prompt_escape;
static int
get_prompt_1 (void *data)
{
char *formatted_prompt = data;
char *local_prompt;
if (event_loop_p)
local_prompt = PROMPT (0);
else
local_prompt = gdb_prompt_string;
if (gdb_prompt_escape == 0)
{
return 0;
}
else
{
char fmt[40], *promptp, *outp, *tmp;
struct value *arg_val;
DOUBLEST doubleval;
LONGEST longval;
CORE_ADDR addrval;
int i, len;
struct type *arg_type, *elt_type;
promptp = local_prompt;
outp = formatted_prompt;
while (*promptp != '\0')
{
int available = MAX_PROMPT_SIZE - (outp - formatted_prompt) - 1;
if (*promptp != gdb_prompt_escape)
{
if (available >= 1)
*outp++ = *promptp++;
}
else
{
fmt[0] = '\0';
if (promptp[1] == gdb_prompt_escape)
{
promptp += 2;
}
else
{
i = 0;
do
{
fmt[i++] = *promptp++;
}
while (i < sizeof (fmt) - 1 &&
*promptp != gdb_prompt_escape &&
*promptp != '\0');
if (*promptp != gdb_prompt_escape)
error ("Syntax error at prompt position %d",
promptp - local_prompt);
else
{
promptp++;
fmt[i++] = '\0';
}
}
arg_val = parse_to_comma_and_eval (&promptp);
if (*promptp == ',')
promptp++;
arg_type = check_typedef (VALUE_TYPE (arg_val));
switch (TYPE_CODE (arg_type))
{
case TYPE_CODE_ARRAY:
elt_type = check_typedef (TYPE_TARGET_TYPE (arg_type));
if (TYPE_LENGTH (arg_type) > 0 &&
TYPE_LENGTH (elt_type) == 1 &&
TYPE_CODE (elt_type) == TYPE_CODE_INT)
{
int len = TYPE_LENGTH (arg_type);
if (VALUE_LAZY (arg_val))
value_fetch_lazy (arg_val);
tmp = VALUE_CONTENTS (arg_val);
if (len > available)
len = available;
if (fmt[0] != 0)
sprintf (outp, fmt, tmp);
else
strncpy (outp, tmp, len);
outp[len] = '\0';
}
break;
case TYPE_CODE_PTR:
elt_type = check_typedef (TYPE_TARGET_TYPE (arg_type));
addrval = value_as_address (arg_val);
if (TYPE_LENGTH (elt_type) == 1 &&
TYPE_CODE (elt_type) == TYPE_CODE_INT &&
addrval != 0)
{
char *default_fmt = "%s";
char *tmp;
int err = 0;
i = target_read_string (addrval,
&tmp,
available,
&err);
if (err)
error ("%s on target_read", safe_strerror (err));
tmp[i] = '\0';
sprintf (outp, fmt[0] == 0 ? default_fmt : fmt,
tmp);
xfree (tmp);
}
else
{
char *default_fmt = "0x%x";
if (available >= 16 )
sprintf (outp, fmt[0] == 0 ? default_fmt : fmt,
(long) addrval);
}
break;
case TYPE_CODE_FLT:
{
char *default_fmt = "%g";
doubleval = value_as_double (arg_val);
if (available >= 16 )
sprintf (outp, fmt[0] == 0 ? default_fmt : fmt,
(double) doubleval);
break;
}
case TYPE_CODE_INT:
{
char *default_fmt = "%d";
longval = value_as_long (arg_val);
if (available >= 16 )
sprintf (outp, fmt[0] == 0 ? default_fmt : fmt,
(long) longval);
break;
}
case TYPE_CODE_BOOL:
{
longval = value_as_long (arg_val);
if (available >= 8 )
{
if (longval)
strcpy (outp, "<true>");
else
strcpy (outp, "<false>");
}
break;
}
case TYPE_CODE_ENUM:
{
longval = value_as_long (arg_val);
len = TYPE_NFIELDS (arg_type);
for (i = 0; i < len; i++)
if (TYPE_FIELD_BITPOS (arg_type, i) == longval)
break;
if (i < len)
{
char *name = TYPE_FIELD_NAME (arg_type, i);
strncpy (outp, name, available);
outp[available] = '\0';
}
else
{
if (available >= 16 )
sprintf (outp, "%ld", (long) longval);
}
break;
}
case TYPE_CODE_VOID:
*outp = '\0';
break;
default:
error ("bad data type at prompt position %d",
promptp - local_prompt);
break;
}
outp += strlen (outp);
}
}
*outp++ = '\0';
return 1;
}
}
char *
get_prompt (void)
{
static char buf[MAX_PROMPT_SIZE];
if (catch_errors (get_prompt_1, buf, "bad formatted prompt: ",
RETURN_MASK_ALL))
{
return &buf[0];
}
else
{
if (event_loop_p)
return PROMPT (0);
else
return gdb_prompt_string;
}
}
void
set_prompt (char *s)
{
if (event_loop_p)
PROMPT (0) = savestring (s, strlen (s));
else
gdb_prompt_string = savestring (s, strlen (s));
}
int
quit_confirm (void)
{
if (! ptid_equal (inferior_ptid, null_ptid) && target_has_execution)
{
char *s;
if (init_ui_hook)
s = "A debugging session is active.\nDo you still want to close the debugger?";
else if (attach_flag)
s = "The program is running. Quit anyway (and detach it)? ";
else
s = "The program is running. Exit anyway? ";
if (!query (s))
return 0;
}
return 1;
}
void
quit_force (char *args, int from_tty)
{
int exit_code = 0;
if (args)
{
struct value *val = parse_and_eval (args);
exit_code = (int) value_as_long (val);
}
if (! ptid_equal (inferior_ptid, null_ptid) && target_has_execution)
{
if (attach_flag)
target_detach (args, from_tty);
else
target_kill ();
}
target_close (1);
if (write_history_p && history_filename)
write_history (history_filename);
if (state_change_hook)
state_change_hook (STATE_NOT_ACTIVE);
do_final_cleanups (ALL_CLEANUPS);
exit (exit_code);
}
int
input_from_terminal_p (void)
{
return gdb_has_a_terminal () && (instream == stdin) & caution;
}
static void
dont_repeat_command (char *ignored, int from_tty)
{
*line = 0;
}
#define Hist_print 10
void
show_commands (char *args, int from_tty)
{
int offset;
static int num = 0;
int hist_len;
hist_len = history_size;
for (offset = 0; offset < history_size; offset++)
{
if (!history_get (history_base + offset))
{
hist_len = offset;
break;
}
}
if (args)
{
if (args[0] == '+' && args[1] == '\0')
;
else
num = (parse_and_eval_long (args) - history_base) - Hist_print / 2;
}
else
{
num = hist_len - Hist_print;
}
if (num < 0)
num = 0;
if (hist_len - num < Hist_print)
{
num = hist_len - Hist_print;
if (num < 0)
num = 0;
}
for (offset = num; offset < num + Hist_print && offset < hist_len; offset++)
{
printf_filtered ("%5d %s\n", history_base + offset,
(history_get (history_base + offset))->line);
}
num += Hist_print;
if (from_tty && args)
{
args[0] = '+';
args[1] = '\0';
}
}
static void
set_history_size_command (char *args, int from_tty, struct cmd_list_element *c)
{
if (history_size == INT_MAX)
unstifle_history ();
else if (history_size >= 0)
stifle_history (history_size);
else
{
history_size = INT_MAX;
error ("History size must be non-negative");
}
}
void
set_history (char *args, int from_tty)
{
printf_unfiltered ("\"set history\" must be followed by the name of a history subcommand.\n");
help_list (sethistlist, "set history ", -1, gdb_stdout);
}
void
show_history (char *args, int from_tty)
{
cmd_show_list (showhistlist, from_tty, "");
}
int info_verbose = 0;
void
set_verbose (char *args, int from_tty, struct cmd_list_element *c)
{
char *cmdname = "verbose";
struct cmd_list_element *showcmd;
showcmd = lookup_cmd_1 (&cmdname, showlist, NULL, 1);
if (info_verbose)
{
c->doc = "Set verbose printing of informational messages.";
showcmd->doc = "Show verbose printing of informational messages.";
}
else
{
c->doc = "Set verbosity.";
showcmd->doc = "Show verbosity.";
}
}
void
init_history (void)
{
char *tmpenv;
int ret;
tmpenv = getenv ("HISTSIZE");
if (tmpenv)
history_size = atoi (tmpenv);
else if (!history_size)
history_size = 256;
stifle_history (history_size);
tmpenv = getenv ("GDBHISTFILE");
if (tmpenv)
history_filename = savestring (tmpenv, strlen (tmpenv));
else if (!history_filename)
{
#ifdef __MSDOS__
history_filename = concat (current_directory, "/_gdb_history", NULL);
#else
history_filename = concat (current_directory, "/.gdb_history", NULL);
#endif
}
ret = read_history (history_filename);
if ((ret != 0) && (ret != ENOENT))
warning ("unable to read history from \"%s\": %s", history_filename, strerror (ret));
}
static void
init_main (void)
{
struct cmd_list_element *c;
if (!event_loop_p)
{
gdb_prompt_string = savestring (DEFAULT_PROMPT, strlen (DEFAULT_PROMPT));
}
else
{
the_prompts.top = 0;
PREFIX (0) = "";
PROMPT (0) = savestring (DEFAULT_PROMPT, strlen (DEFAULT_PROMPT));
SUFFIX (0) = "";
async_annotation_suffix = "prompt";
new_async_prompt = savestring (PROMPT (0), strlen (PROMPT (0)));
if (annotation_level > 1)
set_async_annotation_level (NULL, 0, NULL);
}
gdb_prompt_escape = 0;
command_editing_p = 1;
history_expansion_p = 0;
write_history_p = 0;
rl_completion_entry_function = (int (*)()) readline_line_completion_function;
rl_completer_word_break_characters =
get_gdb_completer_word_break_characters ();
rl_completer_quote_characters = get_gdb_completer_quote_characters ();
rl_readline_name = "gdb";
rl_add_defun ("operate-and-get-next", gdb_rl_operate_and_get_next, 15);
if (!event_loop_p)
{
add_show_from_set
(add_set_cmd ("prompt", class_support, var_string,
(char *) &gdb_prompt_string, "Set gdb's prompt",
&setlist),
&showlist);
}
else
{
c = add_set_cmd ("prompt", class_support, var_string,
(char *) &new_async_prompt, "Set gdb's prompt",
&setlist);
add_show_from_set (c, &showlist);
c->function.sfunc = set_async_prompt;
}
add_show_from_set
(add_set_cmd ("prompt-escape-char", class_support, var_zinteger,
(char *) &gdb_prompt_escape,
"Set escape character for formatting of gdb's prompt",
&setlist),
&showlist);
add_com ("dont-repeat", class_support, dont_repeat_command, "Don't repeat this command.\n\
Primarily used inside of user-defined commands that should not be repeated when\n\
hitting return.");
if (!event_loop_p)
{
add_show_from_set
(add_set_cmd ("editing", class_support, var_boolean, (char *) &command_editing_p,
"Set editing of command lines as they are typed.\n\
Use \"on\" to enable the editing, and \"off\" to disable it.\n\
Without an argument, command line editing is enabled. To edit, use\n\
EMACS-like or VI-like commands like control-P or ESC.", &setlist),
&showlist);
}
else
{
c = add_set_cmd ("editing", class_support, var_boolean, (char *) &async_command_editing_p,
"Set editing of command lines as they are typed.\n\
Use \"on\" to enable the editing, and \"off\" to disable it.\n\
Without an argument, command line editing is enabled. To edit, use\n\
EMACS-like or VI-like commands like control-P or ESC.", &setlist);
add_show_from_set (c, &showlist);
c->function.sfunc = set_async_editing_command;
}
add_show_from_set
(add_set_cmd ("save", no_class, var_boolean, (char *) &write_history_p,
"Set saving of the history record on exit.\n\
Use \"on\" to enable the saving, and \"off\" to disable it.\n\
Without an argument, saving is enabled.", &sethistlist),
&showhistlist);
c = add_set_cmd ("size", no_class, var_integer, (char *) &history_size,
"Set the size of the command history, \n\
ie. the number of previous commands to keep a record of.", &sethistlist);
add_show_from_set (c, &showhistlist);
c->function.sfunc = set_history_size_command;
c = add_set_cmd ("filename", no_class, var_filename,
(char *) &history_filename,
"Set the filename in which to record the command history\n\
(the list of previous commands of which a record is kept).", &sethistlist);
c->completer = filename_completer;
c->completer_word_break_characters =
gdb_completer_filename_word_break_characters;
add_show_from_set (c, &showhistlist);
add_show_from_set
(add_set_cmd ("confirm", class_support, var_boolean,
(char *) &caution,
"Set whether to confirm potentially dangerous operations.",
&setlist),
&showlist);
if (!event_loop_p)
{
c = add_set_cmd ("annotate", class_obscure, var_zinteger,
(char *) &annotation_level, "Set annotation_level.\n\
0 == normal; 1 == fullname (for use when running under emacs)\n\
2 == output annotated suitably for use by programs that control GDB.",
&setlist);
c = add_show_from_set (c, &showlist);
}
else
{
c = add_set_cmd ("annotate", class_obscure, var_zinteger,
(char *) &annotation_level, "Set annotation_level.\n\
0 == normal; 1 == fullname (for use when running under emacs)\n\
2 == output annotated suitably for use by programs that control GDB.",
&setlist);
add_show_from_set (c, &showlist);
c->function.sfunc = set_async_annotation_level;
}
if (event_loop_p)
{
add_show_from_set
(add_set_cmd ("exec-done-display", class_support, var_boolean, (char *) &exec_done_display_p,
"Set notification of completion for asynchronous execution commands.\n\
Use \"on\" to enable the notification, and \"off\" to disable it.", &setlist),
&showlist);
}
}
void
gdb_init (char *argv0)
{
if (pre_init_ui_hook)
pre_init_ui_hook ();
getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
current_directory = gdb_dirbuf;
#ifdef __MSDOS__
make_final_cleanup (do_chdir_cleanup, xstrdup (current_directory));
#endif
init_cmd_lists ();
initialize_targets ();
initialize_utils ();
initialize_all_files ();
initialize_current_architecture ();
init_cli_cmds();
init_main ();
if (event_loop_p)
async_init_signals ();
else
init_signals ();
set_language (language_c);
expected_language = current_language;
if (!init_ui_hook)
{
struct gdb_interpreter *interp;
if (interpreter_p == NULL)
interpreter_p = strsave ("console");
interp = gdb_lookup_interpreter (interpreter_p);
if (interp == NULL)
{
fprintf_unfiltered (gdb_stderr, "Interpreter `%s' unrecognized.\n",
interpreter_p);
exit (1);
}
if (!gdb_set_interpreter (interp))
{
fprintf_unfiltered (gdb_stderr, "Interpreter `%s' failed to initialize.\n",
interpreter_p);
exit (1);
}
}
if (init_ui_hook)
init_ui_hook (argv0);
}