#include "defs.h"
#include "gdbcmd.h"
#include "call-cmds.h"
#include "symtab.h"
#include "inferior.h"
#include "signals.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 "top.h"
#include "version.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>
#ifdef UI_OUT
#include "ui-out.h"
#include "cli-out.h"
#endif
static void dont_repeat_command (char *, int);
static void source_cleanup_lines (PTR);
static void user_defined_command (char *, int);
static void init_signals (void);
#ifdef STOP_SIGNAL
static void stop_sig (int);
#endif
static char *line_completion_function (char *, int, char *, int);
static char *readline_line_completion_function (char *, int);
static void while_command (char *, int);
static void if_command (char *, int);
static struct command_line *build_command_line (enum command_control_type,
char *);
static struct command_line *get_command_line (enum command_control_type,
char *);
static void realloc_body_list (struct command_line *, int);
static enum misc_command_type read_next_line (struct command_line **);
static enum command_control_type
recurse_read_control_structure (struct command_line *);
static struct cleanup *setup_user_args (char *);
static char *locate_arg (char *);
static char *insert_args (char *);
static void arg_cleanup (void *);
static void init_main (void);
static void init_cmd_lists (void);
static void float_handler (int);
static void init_signals (void);
static void set_verbose (char *, int, struct cmd_list_element *);
static void show_history (char *, int);
static void set_history (char *, int);
static void set_history_size_command (char *, int, struct cmd_list_element *);
static void show_commands (char *, int);
static void echo_command (char *, int);
static void pwd_command (char *, int);
static void show_version (char *, int);
static void document_command (char *, int);
static void define_command (char *, int);
static void validate_comname (char *);
static void help_command (char *, int);
static void show_command (char *, int);
static void info_command (char *, int);
static void complete_command (char *, int);
static void do_nothing (int);
static void show_debug (char *, int);
static void set_debug (char *, int);
#ifdef SIGHUP
int quit_cover (PTR);
static void disconnect (int);
#endif
static void do_restore_instream_cleanup (void *stream);
static struct cleanup *make_cleanup_free_command_lines (struct command_line **);
#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;
struct cmd_list_element *cmdlist;
struct cmd_list_element *infolist;
struct cmd_list_element *enablelist;
struct cmd_list_element *disablelist;
struct cmd_list_element *togglelist;
struct cmd_list_element *stoplist;
struct cmd_list_element *deletelist;
struct cmd_list_element *enablebreaklist;
struct cmd_list_element *setlist;
struct cmd_list_element *unsetlist;
struct cmd_list_element *showlist;
struct cmd_list_element *sethistlist;
struct cmd_list_element *showhistlist;
struct cmd_list_element *unsethistlist;
struct cmd_list_element *maintenancelist;
struct cmd_list_element *maintenanceinfolist;
struct cmd_list_element *maintenanceprintlist;
struct cmd_list_element *setprintlist;
struct cmd_list_element *showprintlist;
struct cmd_list_element *setdebuglist;
struct cmd_list_element *showdebuglist;
struct cmd_list_element *setchecklist;
struct cmd_list_element *showchecklist;
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;
extern char *get_prompt (void);
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;
#define MAXUSERARGS 10
struct user_args
{
struct user_args *next;
struct
{
char *arg;
int len;
}
a[MAXUSERARGS];
int count;
}
*user_args;
#ifndef STOP_SIGNAL
#ifdef SIGTSTP
#define STOP_SIGNAL SIGTSTP
static void stop_sig (int);
#endif
#endif
#if !defined (HAVE_SIGSETMASK)
#if !defined (USG)
#define HAVE_SIGSETMASK 1
#else
#define HAVE_SIGSETMASK 0
#endif
#endif
#if 0 == (HAVE_SIGSETMASK)
#define sigsetmask(n)
#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);
int (*target_wait_hook) (int pid, struct target_waitstatus * status);
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 (*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;
#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);
}
int
catch_errors (catch_errors_ftype *func, PTR args, char *errstring,
return_mask mask)
{
SIGJMP_BUF *saved_catch;
SIGJMP_BUF catch;
int val;
struct cleanup *saved_cleanup_chain;
char *saved_error_pre_print;
char *saved_quit_pre_print;
int caught;
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_cleanup_chain = save_cleanups ();
saved_catch = catch_return;
catch_return = &catch;
caught = SIGSETJMP (catch);
if (!caught)
val = (*func) (args);
catch_return = saved_catch;
restore_cleanups (saved_cleanup_chain);
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)
return val;
if (!(mask & RETURN_MASK (caught)))
return_to_top_level (caught);
return 0;
}
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
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);
}
int
quit_cover (PTR s)
{
caution = 0;
quit_command ((char *) 0, 0);
return 0;
}
#endif
int source_line_number;
char *source_file_name;
char *source_error;
static int source_error_allocated;
char *source_pre_error;
static 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;
command_loop ();
do_cleanups (cleanups);
}
extern void init_proc (void);
void (*pre_init_ui_hook) (void);
#ifdef __MSDOS__
void
do_chdir_cleanup (void *old_dir)
{
chdir (old_dir);
free (old_dir);
}
#endif
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_main ();
if (event_loop_p)
async_init_signals ();
else
init_signals ();
set_language (language_c);
expected_language = current_language;
#ifdef UI_OUT
{
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);
}
}
#endif
if (init_ui_hook)
init_ui_hook (argv0);
}
static struct command_line *
build_command_line (enum command_control_type type, char *args)
{
struct command_line *cmd;
if (args == NULL)
error ("if/while commands require arguments.\n");
cmd = (struct command_line *) xmalloc (sizeof (struct command_line));
cmd->next = NULL;
cmd->control_type = type;
cmd->body_count = 1;
cmd->body_list
= (struct command_line **) xmalloc (sizeof (struct command_line *)
* cmd->body_count);
memset (cmd->body_list, 0, sizeof (struct command_line *) * cmd->body_count);
cmd->line = savestring (args, strlen (args));
return cmd;
}
static struct command_line *
get_command_line (enum command_control_type type, char *arg)
{
struct command_line *cmd;
struct cleanup *old_chain = NULL;
cmd = build_command_line (type, arg);
old_chain = make_cleanup_free_command_lines (&cmd);
if (recurse_read_control_structure (cmd) == invalid_control)
{
warning ("error reading in control structure\n");
do_cleanups (old_chain);
return NULL;
}
discard_cleanups (old_chain);
return cmd;
}
void
print_command_lines (struct ui_out *uiout, struct command_line *cmd,
unsigned int depth)
{
struct command_line *list;
list = cmd;
while (list)
{
if (depth)
ui_out_spaces (uiout, 2 * depth);
if (list->control_type == simple_control)
{
ui_out_field_string (uiout, NULL, list->line);
ui_out_text (uiout, "\n");
list = list->next;
continue;
}
if (list->control_type == continue_control)
{
ui_out_field_string (uiout, NULL, "loop_continue");
ui_out_text (uiout, "\n");
list = list->next;
continue;
}
if (list->control_type == break_control)
{
ui_out_field_string (uiout, NULL, "loop_break");
ui_out_text (uiout, "\n");
list = list->next;
continue;
}
if (list->control_type == while_control)
{
ui_out_text (uiout, "while ");
ui_out_field_fmt (uiout, NULL, "while %s", list->line);
ui_out_text (uiout, "\n");
print_command_lines (uiout, *list->body_list, depth + 1);
ui_out_field_string (uiout, NULL, "end");
if (depth)
ui_out_spaces (uiout, 2 * depth);
ui_out_text (uiout, "end\n");
list = list->next;
continue;
}
if (list->control_type == if_control)
{
ui_out_text (uiout, "if ");
ui_out_field_fmt (uiout, NULL, "if %s", list->line);
ui_out_text (uiout, "\n");
print_command_lines (uiout, list->body_list[0], depth + 1);
if (list->body_count == 2)
{
if (depth)
ui_out_spaces (uiout, 2 * depth);
ui_out_field_string (uiout, NULL, "else");
ui_out_text (uiout, "else\n");
print_command_lines (uiout, list->body_list[1], depth + 1);
}
ui_out_field_string (uiout, NULL, "end");
if (depth)
ui_out_spaces (uiout, 2 * depth);
ui_out_text (uiout, "end\n");
list = list->next;
continue;
}
list = list->next;
}
}
void
print_command_line (struct command_line *cmd, unsigned int depth,
struct ui_file *stream)
{
unsigned int i;
if (depth)
{
for (i = 0; i < depth; i++)
fputs_filtered (" ", stream);
}
if (cmd->control_type == simple_control)
{
fputs_filtered (cmd->line, stream);
fputs_filtered ("\n", stream);
return;
}
if (cmd->control_type == continue_control)
{
fputs_filtered ("loop_continue\n", stream);
return;
}
if (cmd->control_type == break_control)
{
fputs_filtered ("loop_break\n", stream);
return;
}
if (cmd->control_type == while_control)
{
struct command_line *list;
fputs_filtered ("while ", stream);
fputs_filtered (cmd->line, stream);
fputs_filtered ("\n", stream);
list = *cmd->body_list;
while (list)
{
print_command_line (list, depth + 1, stream);
list = list->next;
}
}
if (cmd->control_type == if_control)
{
fputs_filtered ("if ", stream);
fputs_filtered (cmd->line, stream);
fputs_filtered ("\n", stream);
print_command_line (cmd->body_list[0], depth + 1, stream);
if (cmd->body_count == 2)
{
if (depth)
{
for (i = 0; i < depth; i++)
fputs_filtered (" ", stream);
}
fputs_filtered ("else\n", stream);
print_command_line (cmd->body_list[1], depth + 1, stream);
}
if (depth)
{
for (i = 0; i < depth; i++)
fputs_filtered (" ", stream);
}
fputs_filtered ("end\n", stream);
}
}
enum command_control_type
execute_control_command (struct command_line *cmd)
{
struct expression *expr;
struct command_line *current;
struct cleanup *old_chain = 0;
value_ptr val;
value_ptr val_mark;
int loop;
enum command_control_type ret;
char *new_line;
switch (cmd->control_type)
{
case simple_control:
new_line = insert_args (cmd->line);
if (!new_line)
return invalid_control;
old_chain = make_cleanup (free_current_contents, &new_line);
execute_command (new_line, 0);
ret = cmd->control_type;
break;
case continue_control:
case break_control:
ret = cmd->control_type;
break;
case while_control:
{
new_line = insert_args (cmd->line);
if (!new_line)
return invalid_control;
old_chain = make_cleanup (free_current_contents, &new_line);
expr = parse_expression (new_line);
make_cleanup (free_current_contents, &expr);
ret = simple_control;
loop = 1;
while (loop == 1)
{
int cond_result;
QUIT;
val_mark = value_mark ();
val = evaluate_expression (expr);
cond_result = value_true (val);
value_free_to_mark (val_mark);
if (!cond_result)
break;
current = *cmd->body_list;
while (current)
{
ret = execute_control_command (current);
if (ret == invalid_control || ret == break_control)
{
loop = 0;
break;
}
if (ret == continue_control)
break;
current = current->next;
}
}
if (ret == break_control)
ret = simple_control;
break;
}
case if_control:
{
new_line = insert_args (cmd->line);
if (!new_line)
return invalid_control;
old_chain = make_cleanup (free_current_contents, &new_line);
expr = parse_expression (new_line);
make_cleanup (free_current_contents, &expr);
current = NULL;
ret = simple_control;
val_mark = value_mark ();
val = evaluate_expression (expr);
if (value_true (val))
current = *cmd->body_list;
else if (cmd->body_count == 2)
current = *(cmd->body_list + 1);
value_free_to_mark (val_mark);
while (current)
{
ret = execute_control_command (current);
if (ret != simple_control)
break;
current = current->next;
}
break;
}
default:
warning ("Invalid control type in command structure.");
return invalid_control;
}
if (old_chain)
do_cleanups (old_chain);
return ret;
}
static void
while_command (char *arg, int from_tty)
{
struct command_line *command = NULL;
control_level = 1;
command = get_command_line (while_control, arg);
if (command == NULL)
return;
execute_control_command (command);
free_command_lines (&command);
}
static void
if_command (char *arg, int from_tty)
{
struct command_line *command = NULL;
control_level = 1;
command = get_command_line (if_control, arg);
if (command == NULL)
return;
execute_control_command (command);
free_command_lines (&command);
}
static void
arg_cleanup (void *ignore)
{
struct user_args *oargs = user_args;
if (!user_args)
internal_error ("Internal error, arg_cleanup called with no user args.\n");
user_args = user_args->next;
free (oargs);
}
static struct cleanup *
setup_user_args (char *p)
{
struct user_args *args;
struct cleanup *old_chain;
unsigned int arg_count = 0;
args = (struct user_args *) xmalloc (sizeof (struct user_args));
memset (args, 0, sizeof (struct user_args));
args->next = user_args;
user_args = args;
old_chain = make_cleanup (arg_cleanup, 0);
if (p == NULL)
return old_chain;
while (*p)
{
char *start_arg;
int squote = 0;
int dquote = 0;
int bsquote = 0;
if (arg_count >= MAXUSERARGS)
{
error ("user defined function may only have %d arguments.\n",
MAXUSERARGS);
return old_chain;
}
while (*p == ' ' || *p == '\t')
p++;
start_arg = p;
user_args->a[arg_count].arg = p;
while (*p)
{
if (((*p == ' ' || *p == '\t')) && !squote && !dquote && !bsquote)
break;
else
{
if (bsquote)
bsquote = 0;
else if (*p == '\\')
bsquote = 1;
else if (squote)
{
if (*p == '\'')
squote = 0;
}
else if (dquote)
{
if (*p == '"')
dquote = 0;
}
else
{
if (*p == '\'')
squote = 1;
else if (*p == '"')
dquote = 1;
}
p++;
}
}
user_args->a[arg_count].len = p - start_arg;
arg_count++;
user_args->count++;
}
return old_chain;
}
static char *
locate_arg (char *p)
{
while ((p = strchr (p, '$')))
{
if (strncmp (p, "$arg", 4) == 0 && (p[4] == 'c' || isdigit (p[4])))
return p;
p++;
}
return NULL;
}
static char *
insert_args (char *line)
{
char *p, *save_line, *new_line;
unsigned len, i;
save_line = line;
len = 0;
while ((p = locate_arg (line)))
{
len += p - line;
if (p[4] == 'c')
{
if (user_args->count > 9)
len += 2;
else
len += 1;
}
else
{
i = p[4] - '0';
if (i >= user_args->count)
{
error ("Missing argument %d in user function.\n", i);
return NULL;
}
len += user_args->a[i].len;
}
line = p + 5;
}
len += strlen (line);
new_line = (char *) xmalloc (len + 1);
if (new_line == NULL)
return NULL;
line = save_line;
save_line = new_line;
while ((p = locate_arg (line)))
{
int i, len;
memcpy (new_line, line, p - line);
new_line += p - line;
if (p[4] == 'c')
{
if (user_args->count > 9)
*(new_line++) = '0' + (user_args->count / 10);
*(new_line++) = '0' + (user_args->count % 10);
}
else
{
i = p[4] - '0';
len = user_args->a[i].len;
if (len)
{
memcpy (new_line, user_args->a[i].arg, len);
new_line += len;
}
}
line = p + 5;
}
strcpy (new_line, line);
return save_line;
}
void
execute_user_command (struct cmd_list_element *c, char *args)
{
register struct command_line *cmdlines;
struct cleanup *old_chain;
enum command_control_type ret;
int saved_async;
old_chain = setup_user_args (args);
cmdlines = c->user_commands;
if (cmdlines == 0)
return;
old_chain = make_cleanup (do_restore_instream_cleanup, instream);
instream = (FILE *) 0;
if (target_can_async_p ())
{
gdb_set_async_override (1);
make_cleanup (gdb_set_async_override, 0);
}
while (cmdlines)
{
ret = execute_control_command (cmdlines);
if (ret != simple_control && ret != break_control)
{
warning ("Error in control structure.\n");
break;
}
cmdlines = cmdlines->next;
}
do_cleanups (old_chain);
}
void
execute_command (char *p, int from_tty)
{
register struct cmd_list_element *c;
register enum language flang;
static int warned = 0;
char *line;
extern void serial_log_command (const char *);
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 && c->function.cfunc != complete_command)
{
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 defined(TUI)
extern int insert_mode;
#endif
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);
#if defined(TUI)
insert_mode = 0;
#endif
command = command_line_input (instream == stdin ?
get_prompt () : (char *) NULL,
instream == stdin, "prompt");
#if defined(TUI)
insert_mode = 0;
#endif
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);
#ifdef MPW
fputs_unfiltered ("\n", gdb_stdout);
#endif
gdb_flush (gdb_stdout);
}
result = (char *) xmalloc (result_size);
while (1)
{
c = fgetc (instream ? instream : stdin);
if (c == EOF)
{
if (input_index > 0)
break;
free (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;
char *gdb_completer_word_break_characters =
" \t\n!@#$%^&*()+=|~`}{[]\"';:?>.<,-";
char *gdb_completer_command_word_break_characters =
" \t\n!@#$%^&*()+=|~`}{[]\"';:?>.<,";
char *gdb_completer_filename_word_break_characters =
" ";
char *gdb_completer_file_name_break_characters = " \t\n*|\"';:?/><";
char *gdb_completer_quote_characters =
"'";
char **
noop_completer (char *text, char *prefix)
{
return NULL;
}
char **
filename_completer (char *text, char *word)
{
extern char *filename_completion_function (char *, int);
int subsequent_name;
char **return_val;
int return_val_used;
int return_val_alloced;
return_val_used = 0;
return_val_alloced = 1;
return_val = (char **) xmalloc (return_val_alloced * sizeof (char *));
subsequent_name = 0;
while (1)
{
char *p;
p = filename_completion_function (text, subsequent_name);
if (return_val_used >= return_val_alloced)
{
return_val_alloced *= 2;
return_val =
(char **) xrealloc (return_val,
return_val_alloced * sizeof (char *));
}
if (p == NULL)
{
return_val[return_val_used++] = p;
break;
}
subsequent_name = 1;
if (p[strlen (p) - 1] == '~')
continue;
{
char *q;
if (word == text)
return_val[return_val_used++] = p;
else if (word > text)
{
q = xmalloc (strlen (p) + 5);
strcpy (q, p + (word - text));
return_val[return_val_used++] = q;
free (p);
}
else
{
q = xmalloc (strlen (p) + (text - word) + 5);
strncpy (q, word, text - word);
q[text - word] = '\0';
strcat (q, p);
return_val[return_val_used++] = q;
free (p);
}
}
}
#if 0
rl_completer_word_break_characters = "";
#endif
return return_val;
}
static char *
line_completion_function (char *text, int matches, char *line_buffer, int point)
{
static char **list = (char **) NULL;
static int index;
char *output = NULL;
char *tmp_command, *p;
char *word;
struct cmd_list_element *c, *result_list;
if (matches == 0)
{
if (list)
{
free ((PTR) list);
}
list = 0;
index = 0;
rl_completer_word_break_characters =
gdb_completer_word_break_characters;
rl_completer_quote_characters =
gdb_completer_quote_characters;
tmp_command = (char *) alloca (point + 1);
p = tmp_command;
strncpy (tmp_command, line_buffer, point);
tmp_command[point] = '\0';
word = tmp_command + point - strlen (text);
if (point == 0)
{
c = (struct cmd_list_element *) -1;
result_list = 0;
}
else
{
c = lookup_cmd_1 (&p, cmdlist, &result_list, 1);
}
while (*p == ' ' || *p == '\t')
{
p++;
}
if (!c)
{
list = NULL;
}
else if (c == (struct cmd_list_element *) -1)
{
char *q;
q = p;
while (*q && (isalnum (*q) || *q == '-' || *q == '_'))
++q;
if (q != tmp_command + point)
{
list = NULL;
}
else
{
if (result_list)
{
list = complete_on_cmdlist (*result_list->prefixlist, p,
word);
}
else
{
list = complete_on_cmdlist (cmdlist, p, word);
}
rl_completer_word_break_characters =
gdb_completer_command_word_break_characters;
rl_completer_quote_characters =
gdb_completer_quote_characters;
}
}
else
{
if (p == tmp_command + point)
{
if (p[-1] == ' ' || p[-1] == '\t')
{
if (c->prefixlist)
{
list = complete_on_cmdlist (*c->prefixlist, p, word);
rl_completer_word_break_characters =
gdb_completer_command_word_break_characters;
rl_completer_quote_characters =
gdb_completer_quote_characters;
}
else if (c->enums)
{
list = complete_on_enum (c->enums, p, word);
rl_completer_word_break_characters =
gdb_completer_command_word_break_characters;
rl_completer_quote_characters =
gdb_completer_quote_characters;
}
else
{
rl_completer_word_break_characters =
c->completer_word_break_characters;
rl_completer_quote_characters =
c->completer_quote_characters;
list = (*c->completer) (p, word);
if (c->completer == filename_completer)
rl_completer_word_break_characters =
gdb_completer_file_name_break_characters;
}
}
else
{
char *q;
q = p;
while (q > tmp_command)
{
if (isalnum (q[-1]) || q[-1] == '-' || q[-1] == '_')
--q;
else
break;
}
list = complete_on_cmdlist (result_list, q, word);
rl_completer_word_break_characters =
gdb_completer_command_word_break_characters;
rl_completer_quote_characters =
gdb_completer_quote_characters;
}
}
else
{
if (c->prefixlist && !c->allow_unknown)
{
list = NULL;
}
else if (c->enums)
{
list = complete_on_enum (c->enums, p, word);
}
else
{
rl_completer_word_break_characters =
c->completer_word_break_characters;
rl_completer_quote_characters =
c->completer_quote_characters;
list = (*c->completer) (p, word);
if (c->completer == filename_completer)
rl_completer_word_break_characters =
gdb_completer_file_name_break_characters;
}
}
}
}
if (list)
{
output = list[index];
if (output)
{
index++;
}
}
#if 0
if (output == NULL)
rl_completer_word_break_characters =
gdb_completer_word_break_characters;
#endif
return (output);
}
static char *
readline_line_completion_function (char *text, int matches)
{
return line_completion_function (text, matches, rl_line_buffer, rl_point);
}
char *
skip_quoted (char *str, char *breakchars)
{
char quote_char = '\0';
char *scan;
for (scan = str; *scan != '\0'; scan++)
{
if (quote_char != '\0')
{
if (*scan == quote_char)
{
scan++;
break;
}
}
else if (strchr (gdb_completer_quote_characters, *scan))
{
quote_char = *scan;
}
else if (strchr (breakchars, *scan))
{
break;
}
}
return (scan);
}
#ifdef STOP_SIGNAL
static void
stop_sig (int signo)
{
#if STOP_SIGNAL == SIGTSTP
signal (SIGTSTP, SIG_DFL);
sigsetmask (0);
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
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
}
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++;
free (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)
{
free (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);
free (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;
}
static void
realloc_body_list (struct command_line *command, int new_length)
{
int n;
struct command_line **body_list;
n = command->body_count;
if (new_length <= n)
return;
body_list = (struct command_line **)
xmalloc (sizeof (struct command_line *) * new_length);
memcpy (body_list, command->body_list, sizeof (struct command_line *) * n);
free (command->body_list);
command->body_list = body_list;
command->body_count = new_length;
}
static enum misc_command_type
read_next_line (struct command_line **command)
{
char *p, *p1, *prompt_ptr, control_prompt[256];
int i = 0;
if (control_level >= 254)
error ("Control nesting too deep!\n");
if (instream == stdin || (instream == 0 && readline_hook != NULL))
{
for (i = 0; i < control_level; i++)
control_prompt[i] = ' ';
control_prompt[i] = '>';
control_prompt[i + 1] = '\0';
prompt_ptr = (char *) &control_prompt[0];
}
else
prompt_ptr = NULL;
p = command_line_input (prompt_ptr, instream == stdin, "commands");
if (p == NULL)
return end_command;
while (*p == ' ' || *p == '\t')
p++;
p1 = p + strlen (p);
while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t'))
p1--;
if (p1 == p || p[0] == '#')
return nop_command;
if (p1 - p == 3 && !strncmp (p, "end", 3))
return end_command;
if (p1 - p == 4 && !strncmp (p, "else", 4))
return else_command;
if (p1 - p > 5 && !strncmp (p, "while", 5))
*command = build_command_line (while_control, p + 6);
else if (p1 - p > 2 && !strncmp (p, "if", 2))
*command = build_command_line (if_control, p + 3);
else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
xmalloc (sizeof (struct command_line));
(*command)->next = NULL;
(*command)->line = NULL;
(*command)->control_type = break_control;
(*command)->body_count = 0;
(*command)->body_list = NULL;
}
else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13))
{
*command = (struct command_line *)
xmalloc (sizeof (struct command_line));
(*command)->next = NULL;
(*command)->line = NULL;
(*command)->control_type = continue_control;
(*command)->body_count = 0;
(*command)->body_list = NULL;
}
else
{
*command = (struct command_line *)
xmalloc (sizeof (struct command_line));
(*command)->next = NULL;
(*command)->line = savestring (p, p1 - p);
(*command)->control_type = simple_control;
(*command)->body_count = 0;
(*command)->body_list = NULL;
}
return ok_command;
}
static enum command_control_type
recurse_read_control_structure (struct command_line *current_cmd)
{
int current_body, i;
enum misc_command_type val;
enum command_control_type ret;
struct command_line **body_ptr, *child_tail, *next;
child_tail = NULL;
current_body = 1;
if (current_cmd->control_type == simple_control)
{
error ("Recursed on a simple control type\n");
return invalid_control;
}
if (current_body > current_cmd->body_count)
{
error ("Allocated body is smaller than this command type needs\n");
return invalid_control;
}
while (1)
{
dont_repeat ();
next = NULL;
val = read_next_line (&next);
if (val == nop_command)
continue;
if (val == end_command)
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control)
{
ret = simple_control;
break;
}
else
{
ret = invalid_control;
break;
}
}
if (val == else_command)
{
if (current_cmd->control_type == if_control
&& current_body == 1)
{
realloc_body_list (current_cmd, 2);
current_body = 2;
child_tail = NULL;
continue;
}
else
{
ret = invalid_control;
break;
}
}
if (child_tail)
{
child_tail->next = next;
}
else
{
body_ptr = current_cmd->body_list;
for (i = 1; i < current_body; i++)
body_ptr++;
*body_ptr = next;
}
child_tail = next;
if (next->control_type == while_control
|| next->control_type == if_control)
{
control_level++;
ret = recurse_read_control_structure (next);
control_level--;
if (ret != simple_control)
break;
}
}
dont_repeat ();
return ret;
}
#define END_MESSAGE "End with a line saying just \"end\"."
struct command_line *
read_command_lines (char *prompt_arg, int from_tty)
{
struct command_line *head, *tail, *next;
struct cleanup *old_chain;
enum command_control_type ret;
enum misc_command_type val;
control_level = 0;
if (readline_begin_hook)
{
(*readline_begin_hook) ("%s %s\n", prompt_arg, END_MESSAGE);
}
else if (from_tty && input_from_terminal_p ())
{
printf_unfiltered ("%s\n%s\n", prompt_arg, END_MESSAGE);
gdb_flush (gdb_stdout);
}
head = tail = NULL;
old_chain = NULL;
while (1)
{
val = read_next_line (&next);
if (val == nop_command)
continue;
if (val == end_command)
{
ret = simple_control;
break;
}
if (val != ok_command)
{
ret = invalid_control;
break;
}
if (next->control_type == while_control
|| next->control_type == if_control)
{
control_level++;
ret = recurse_read_control_structure (next);
control_level--;
if (ret == invalid_control)
break;
}
if (tail)
{
tail->next = next;
}
else
{
head = next;
old_chain = make_cleanup_free_command_lines (&head);
}
tail = next;
}
dont_repeat ();
if (head)
{
if (ret != invalid_control)
{
discard_cleanups (old_chain);
}
else
do_cleanups (old_chain);
}
if (readline_end_hook)
{
(*readline_end_hook) ();
}
return (head);
}
void
free_command_lines (struct command_line **lptr)
{
register struct command_line *l = *lptr;
register struct command_line *next;
struct command_line **blist;
int i;
while (l)
{
if (l->body_count > 0)
{
blist = l->body_list;
for (i = 0; i < l->body_count; i++, blist++)
free_command_lines (blist);
}
next = l->next;
free (l->line);
free ((PTR) l);
l = next;
}
}
static void
do_free_command_lines_cleanup (void *arg)
{
free_command_lines (arg);
}
static struct cleanup *
make_cleanup_free_command_lines (struct command_line **arg)
{
return make_cleanup (do_free_command_lines_cleanup, arg);
}
struct cmd_list_element *
add_info (char *name, void (*fun) (char *, int), char *doc)
{
return add_cmd (name, no_class, fun, doc, &infolist);
}
struct cmd_list_element *
add_info_alias (char *name, char *oldname, int abbrev_flag)
{
return add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist);
}
static void
info_command (char *arg, int from_tty)
{
printf_unfiltered ("\"info\" must be followed by the name of an info command.\n");
help_list (infolist, "info ", -1, gdb_stdout);
}
static void
complete_command (char *arg, int from_tty)
{
int i;
int argpoint;
char *completion;
dont_repeat ();
if (arg == NULL)
arg = "";
argpoint = strlen (arg);
for (completion = line_completion_function (arg, i = 0, arg, argpoint);
completion;
completion = line_completion_function (arg, ++i, arg, argpoint))
{
printf_unfiltered ("%s\n", completion);
free (completion);
}
}
static void
show_command (char *arg, int from_tty)
{
cmd_show_list (showlist, from_tty, "");
}
struct cmd_list_element *
add_com (char *name, enum command_class class, void (*fun) (char *, int),
char *doc)
{
return add_cmd (name, class, fun, doc, &cmdlist);
}
struct cmd_list_element *
add_com_alias (char *name, char *oldname, enum command_class class,
int abbrev_flag)
{
return add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist);
}
void
error_no_arg (char *why)
{
error ("Argument required (%s).", why);
}
static void
help_command (char *command, int from_tty)
{
help_cmd (command, gdb_stdout);
}
static void
validate_comname (char *comname)
{
register char *p;
if (comname == 0)
error_no_arg ("name of command to define");
p = comname;
while (*p)
{
if (!isalnum (*p) && *p != '-' && *p != '_')
error ("Junk in argument list: \"%s\"", p);
p++;
}
}
static void
user_defined_command (char *ignore, int from_tty)
{
}
static void
define_command (char *comname, int from_tty)
{
#define MAX_TMPBUF 128
enum cmd_hook_type
{
CMD_NO_HOOK = 0,
CMD_PRE_HOOK,
CMD_POST_HOOK
};
register struct command_line *cmds;
register struct cmd_list_element *c, *newc, *oldc, *hookc = 0;
char *tem = comname;
char *tem2;
char tmpbuf[MAX_TMPBUF];
int hook_type = CMD_NO_HOOK;
int hook_name_size = 0;
#define HOOK_STRING "hook-"
#define HOOK_LEN 5
#define HOOK_POST_STRING "hookpost-"
#define HOOK_POST_LEN 9
validate_comname (comname);
c = lookup_cmd (&tem, cmdlist, "", -1, 1);
if (c && !STREQ (comname, c->name))
c = 0;
if (c)
{
if (c->class == class_user || c->class == class_alias)
tem = "Redefine command \"%s\"? ";
else
tem = "Really redefine built-in command \"%s\"? ";
if (!query (tem, c->name))
error ("Command \"%s\" not redefined.", c->name);
}
if (!strncmp (comname, HOOK_STRING, HOOK_LEN))
{
hook_type = CMD_PRE_HOOK;
hook_name_size = HOOK_LEN;
}
else if (!strncmp (comname, HOOK_POST_STRING, HOOK_POST_LEN))
{
hook_type = CMD_POST_HOOK;
hook_name_size = HOOK_POST_LEN;
}
if (hook_type != CMD_NO_HOOK)
{
tem = comname + hook_name_size;
hookc = lookup_cmd (&tem, cmdlist, "", -1, 0);
if (hookc && !STREQ (comname + hook_name_size, hookc->name))
hookc = 0;
if (!hookc)
{
warning ("Your new `%s' command does not hook any existing command.",
comname);
if (!query ("Proceed? "))
error ("Not confirmed.");
}
}
comname = savestring (comname, strlen (comname));
for (tem = comname; *tem; tem++)
if (isupper (*tem))
*tem = tolower (*tem);
sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname);
cmds = read_command_lines (tmpbuf, from_tty);
if (c && c->class == class_user)
free_command_lines (&c->user_commands);
newc = add_cmd (comname, class_user, user_defined_command,
(c && c->class == class_user)
? c->doc : savestring ("User-defined.", 13), &cmdlist);
newc->user_commands = cmds;
if (hookc)
{
switch (hook_type)
{
case CMD_PRE_HOOK:
hookc->hook_pre = newc;
newc->hookee_pre = hookc;
break;
case CMD_POST_HOOK:
hookc->hook_pre = newc;
newc->hookee_pre = hookc;
break;
default:
}
}
}
static void
document_command (char *comname, int from_tty)
{
struct command_line *doclines;
register struct cmd_list_element *c;
char *tem = comname;
char tmpbuf[128];
validate_comname (comname);
c = lookup_cmd (&tem, cmdlist, "", 0, 1);
if (c->class != class_user)
error ("Command \"%s\" is built-in.", comname);
sprintf (tmpbuf, "Type documentation for \"%s\".", comname);
doclines = read_command_lines (tmpbuf, from_tty);
if (c->doc)
free (c->doc);
{
register struct command_line *cl1;
register int len = 0;
for (cl1 = doclines; cl1; cl1 = cl1->next)
len += strlen (cl1->line) + 1;
c->doc = (char *) xmalloc (len + 1);
*c->doc = 0;
for (cl1 = doclines; cl1; cl1 = cl1->next)
{
strcat (c->doc, cl1->line);
if (cl1->next)
strcat (c->doc, "\n");
}
}
free_command_lines (&doclines);
}
void
print_gdb_version (struct ui_file *stream)
{
#ifdef UI_OUT
fprintf_filtered (stream, "GNU gdb %s (%s) (UI_OUT)\n", version, build_date);
#else
fprintf_filtered (stream, "GNU gdb %s (%s)\n", version, build_date);
#endif
fprintf_filtered (stream, "Copyright 2000 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, "\".");
}
static void
show_version (char *args, int from_tty)
{
immediate_quit++;
print_gdb_version (gdb_stdout);
printf_filtered ("\n");
immediate_quit--;
}
#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;
value_ptr 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_pointer (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);
free (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 (inferior_pid != 0 && 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)
{
value_ptr val = parse_and_eval (args);
exit_code = (int) value_as_long (val);
}
if (inferior_pid != 0 && 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);
#if defined(TUI)
if (tui_version)
tuiCleanUp ();
#endif
exit (exit_code);
}
void
quit_command (char *args, int from_tty)
{
if (!quit_confirm ())
error ("Not confirmed.");
quit_force (args, from_tty);
}
int
input_from_terminal_p (void)
{
return gdb_has_a_terminal () && (instream == stdin) & caution;
}
static void
pwd_command (char *args, int from_tty)
{
if (args)
error ("The \"pwd\" command does not take an argument: %s", args);
getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
if (!STREQ (gdb_dirbuf, current_directory))
printf_unfiltered ("Working directory %s\n (canonically %s).\n",
current_directory, gdb_dirbuf);
else
printf_unfiltered ("Working directory %s.\n", current_directory);
}
void
cd_command (char *dir, int from_tty)
{
int len;
int found_real_path;
char *p;
dont_repeat ();
if (dir == 0)
error_no_arg ("new working directory");
dir = tilde_expand (dir);
make_cleanup (free, dir);
if (chdir (dir) < 0)
perror_with_name (dir);
#if defined(_WIN32) || defined(__MSDOS__)
dir = getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
#endif
len = strlen (dir);
if (SLASH_P (dir[len - 1]))
{
if (!(len == 1)
#if defined(_WIN32) || defined(__MSDOS__)
&& !(!SLASH_P (*dir) && ROOTED_P (dir) && len <= 3)
#endif
)
len--;
}
dir = savestring (dir, len);
if (ROOTED_P (dir))
current_directory = dir;
else
{
if (SLASH_P (current_directory[strlen (current_directory) - 1]))
current_directory = concat (current_directory, dir, NULL);
else
current_directory = concat (current_directory, SLASH_STRING, dir, NULL);
free (dir);
}
found_real_path = 0;
for (p = current_directory; *p;)
{
if (SLASH_P (p[0]) && p[1] == '.' && (p[2] == 0 || SLASH_P (p[2])))
strcpy (p, p + 2);
else if (SLASH_P (p[0]) && p[1] == '.' && p[2] == '.'
&& (p[3] == 0 || SLASH_P (p[3])))
{
if (found_real_path)
{
char *q = p;
while (q != current_directory && !SLASH_P (q[-1]))
--q;
if (q == current_directory)
++p;
else
{
strcpy (q - 1, p + 3);
p = q - 1;
}
}
else
p += 3;
}
else
{
found_real_path = 1;
++p;
}
}
forget_cached_source_info ();
if (from_tty)
pwd_command ((char *) 0, 1);
}
struct source_cleanup_lines_args
{
int old_line;
char *old_file;
char *old_pre_error;
char *old_error_pre_print;
};
static void
source_cleanup_lines (PTR args)
{
struct source_cleanup_lines_args *p =
(struct source_cleanup_lines_args *) args;
source_line_number = p->old_line;
source_file_name = p->old_file;
source_pre_error = p->old_pre_error;
error_pre_print = p->old_error_pre_print;
}
static void
do_fclose_cleanup (void *stream)
{
fclose (stream);
}
void
source_command (char *args, int from_tty)
{
FILE *stream;
struct cleanup *old_cleanups;
char *file = args;
struct source_cleanup_lines_args old_lines;
int needed_length;
if (file == NULL)
{
error ("source command requires pathname of file to source.");
}
file = tilde_expand (file);
old_cleanups = make_cleanup (free, file);
stream = fopen (file, FOPEN_RT);
if (!stream)
{
if (from_tty)
perror_with_name (file);
else
return;
}
make_cleanup (do_fclose_cleanup, stream);
old_lines.old_line = source_line_number;
old_lines.old_file = source_file_name;
old_lines.old_pre_error = source_pre_error;
old_lines.old_error_pre_print = error_pre_print;
make_cleanup (source_cleanup_lines, &old_lines);
source_line_number = 0;
source_file_name = file;
source_pre_error = error_pre_print == NULL ? "" : error_pre_print;
source_pre_error = savestring (source_pre_error, strlen (source_pre_error));
make_cleanup (free, source_pre_error);
error_pre_print = "";
needed_length = strlen (source_file_name) + strlen (source_pre_error) + 80;
if (source_error_allocated < needed_length)
{
source_error_allocated *= 2;
if (source_error_allocated < needed_length)
source_error_allocated = needed_length;
if (source_error == NULL)
source_error = xmalloc (source_error_allocated);
else
source_error = xrealloc (source_error, source_error_allocated);
}
read_command_file (stream);
do_cleanups (old_cleanups);
}
static void
echo_command (char *text, int from_tty)
{
char *p = text;
register int c;
if (text)
while ((c = *p++) != '\0')
{
if (c == '\\')
{
if (*p == 0)
return;
c = parse_escape (&p);
if (c >= 0)
printf_filtered ("%c", c);
}
else
printf_filtered ("%c", c);
}
wrap_here ("");
gdb_flush (gdb_stdout);
}
static void
dont_repeat_command (char *ignored, int from_tty)
{
*line = 0;
}
#define Hist_print 10
static void
show_commands (char *args, int from_tty)
{
int offset;
static int num = 0;
int hist_len;
extern HIST_ENTRY *history_get (int);
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_address (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");
}
}
static 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);
}
static void
show_history (char *args, int from_tty)
{
cmd_show_list (showhistlist, from_tty, "");
}
int info_verbose = 0;
static 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.";
}
}
static void
float_handler (int signo)
{
signal (SIGFPE, float_handler);
error ("Erroneous arithmetic operation.");
}
static void
set_debug (char *arg, int from_tty)
{
printf_unfiltered ("\"set debug\" must be followed by the name of a print subcommand.\n");
help_list (setdebuglist, "set debug ", -1, gdb_stdout);
}
static void
show_debug (char *args, int from_tty)
{
cmd_show_list (showdebuglist, from_tty, "");
}
static void
init_cmd_lists (void)
{
cmdlist = NULL;
infolist = NULL;
enablelist = NULL;
disablelist = NULL;
togglelist = NULL;
stoplist = NULL;
deletelist = NULL;
enablebreaklist = NULL;
setlist = NULL;
unsetlist = NULL;
showlist = NULL;
sethistlist = NULL;
showhistlist = NULL;
unsethistlist = NULL;
maintenancelist = NULL;
maintenanceinfolist = NULL;
maintenanceprintlist = NULL;
setprintlist = NULL;
showprintlist = NULL;
setchecklist = NULL;
showchecklist = NULL;
}
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)
{
if (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)));
}
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 = gdb_completer_word_break_characters;
rl_completer_quote_characters = gdb_completer_quote_characters;
rl_readline_name = "gdb";
add_cmd ("internals", class_maintenance, NO_FUNCTION,
"Maintenance commands.\n\
Some gdb commands are provided just for use by gdb maintainers.\n\
These commands are subject to frequent change, and may not be as\n\
well documented as user commands.",
&cmdlist);
add_cmd ("obscure", class_obscure, NO_FUNCTION, "Obscure features.", &cmdlist);
add_cmd ("aliases", class_alias, NO_FUNCTION, "Aliases of other commands.", &cmdlist);
add_cmd ("user-defined", class_user, NO_FUNCTION, "User-defined commands.\n\
The commands in this class are those defined by the user.\n\
Use the \"define\" command to define a command.", &cmdlist);
add_cmd ("support", class_support, NO_FUNCTION, "Support facilities.", &cmdlist);
if (!dbx_commands)
add_cmd ("status", class_info, NO_FUNCTION, "Status inquiries.", &cmdlist);
add_cmd ("files", class_files, NO_FUNCTION, "Specifying and examining files.", &cmdlist);
add_cmd ("breakpoints", class_breakpoint, NO_FUNCTION, "Making program stop at certain points.", &cmdlist);
add_cmd ("data", class_vars, NO_FUNCTION, "Examining data.", &cmdlist);
add_cmd ("stack", class_stack, NO_FUNCTION, "Examining the stack.\n\
The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\
counting from zero for the innermost (currently executing) frame.\n\n\
At any time gdb identifies one frame as the \"selected\" frame.\n\
Variable lookups are done with respect to the selected frame.\n\
When the program being debugged stops, gdb selects the innermost frame.\n\
The commands below can be used to select other frames by number or address.",
&cmdlist);
add_cmd ("running", class_run, NO_FUNCTION, "Running the program.", &cmdlist);
add_com ("pwd", class_files, pwd_command,
"Print working directory. This is used for your program as well.");
c = add_cmd ("cd", class_files, cd_command,
"Set working directory to DIR for debugger and program being debugged.\n\
The change does not take effect for the program being debugged\n\
until the next time it is started.", &cmdlist);
c->completer = filename_completer;
c->completer_word_break_characters =
gdb_completer_filename_word_break_characters;
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 ("echo", class_support, echo_command,
"Print a constant string. Give string as argument.\n\
C escape sequences may be used in the argument.\n\
No newline is added at the end of the argument;\n\
use \"\\n\" if you want a newline to be printed.\n\
Since leading and trailing whitespace are ignored in command arguments,\n\
if you want to print some you must use \"\\\" before leading whitespace\n\
to be printed or after trailing whitespace.");
add_com ("document", class_support, document_command,
"Document a user-defined command.\n\
Give command name as argument. Give documentation on following lines.\n\
End with a line of just \"end\".");
add_com ("define", class_support, define_command,
"Define a new command name. Command name is argument.\n\
Definition appears on following lines, one command per line.\n\
End with a line of just \"end\".\n\
Use the \"document\" command to give documentation for the new command.\n\
Commands defined in this way may have up to ten arguments.");
#ifdef __STDC__
c = add_cmd ("source", class_support, source_command,
"Read commands from a file named FILE.\n\
Note that the file \"" GDBINIT_FILENAME "\" is read automatically in this way\n\
when gdb is started.", &cmdlist);
#else
c = add_cmd ("source", class_support, source_command,
"Read commands from a file named FILE.\n\
Note that the file \".gdbinit\" is read automatically in this way\n\
when gdb is started.", &cmdlist);
#endif
c->completer = filename_completer;
c->completer_word_break_characters =
gdb_completer_filename_word_break_characters;
add_com ("quit", class_support, quit_command, "Exit gdb.");
add_com ("help", class_support, help_command, "Print list of commands.");
add_com_alias ("q", "quit", class_support, 1);
add_com_alias ("h", "help", class_support, 1);
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.");
c = add_set_cmd ("verbose", class_support, var_boolean, (char *) &info_verbose,
"Set ",
&setlist),
add_show_from_set (c, &showlist);
c->function.sfunc = set_verbose;
set_verbose (NULL, 0, c);
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_prefix_cmd ("history", class_support, set_history,
"Generic command for setting command history parameters.",
&sethistlist, "set history ", 0, &setlist);
add_prefix_cmd ("history", class_support, show_history,
"Generic command for showing command history parameters.",
&showhistlist, "show history ", 0, &showlist);
add_show_from_set
(add_set_cmd ("expansion", no_class, var_boolean, (char *) &history_expansion_p,
"Set history expansion on command input.\n\
Without an argument, history expansion is enabled.", &sethistlist),
&showhistlist);
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;
add_show_from_set
(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),
&showhistlist);
add_show_from_set
(add_set_cmd ("confirm", class_support, var_boolean,
(char *) &caution,
"Set whether to confirm potentially dangerous operations.",
&setlist),
&showlist);
add_prefix_cmd ("info", class_info, info_command,
"Generic command for showing things about the program being debugged.",
&infolist, "info ", 0, &cmdlist);
add_com_alias ("i", "info", class_info, 1);
add_com ("complete", class_obscure, complete_command,
"List the completions for the rest of the line as a command.");
add_prefix_cmd ("show", class_info, show_command,
"Generic command for showing things about the debugger.",
&showlist, "show ", 0, &cmdlist);
add_info ("set", show_command, "Show all GDB settings.");
add_cmd ("commands", no_class, show_commands,
"Show the history of commands you typed.\n\
You can supply a command number to start with, or a `+' to start after\n\
the previous command number shown.",
&showlist);
add_cmd ("version", no_class, show_version,
"Show what version of GDB this is.", &showlist);
add_com ("while", class_support, while_command,
"Execute nested commands WHILE the conditional expression is non zero.\n\
The conditional expression must follow the word `while' and must in turn be\n\
followed by a new line. The nested commands must be entered one per line,\n\
and should be terminated by the word `end'.");
add_com ("if", class_support, if_command,
"Execute nested commands once IF the conditional expression is non zero.\n\
The conditional expression must follow the word `if' and must in turn be\n\
followed by a new line. The nested commands must be entered one per line,\n\
and should be terminated by the word 'else' or `end'. If an else clause\n\
is used, the same rules apply to its nested commands as to the first ones.");
add_show_from_set (add_set_cmd ("remotebaud", no_class,
var_zinteger, (char *) &baud_rate,
"Set baud rate for remote serial I/O.\n\
This value is used to set the speed of the serial port when debugging\n\
using remote targets.", &setlist),
&showlist);
c = add_set_cmd ("remotedebug", no_class, var_zinteger,
(char *) &remote_debug,
"Set debugging of remote protocol.\n\
When enabled, each packet sent or received with the remote target\n\
is displayed.", &setlist);
deprecate_cmd (c, "set debug remote");
deprecate_cmd (add_show_from_set (c, &showlist), "show debug remote");
add_show_from_set (add_set_cmd ("remote", no_class, var_zinteger,
(char *) &remote_debug,
"Set debugging of remote protocol.\n\
When enabled, each packet sent or received with the remote target\n\
is displayed.", &setdebuglist),
&showdebuglist);
add_show_from_set (
add_set_cmd ("remotetimeout", no_class, var_integer, (char *) &remote_timeout,
"Set timeout limit to wait for target to respond.\n\
This value is used to set the time limit for gdb to wait for a response\n\
from the target.", &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);
}
add_prefix_cmd ("debug", no_class, set_debug,
"Generic command for setting gdb debugging flags",
&setdebuglist, "set debug ", 0, &setlist);
add_prefix_cmd ("debug", no_class, show_debug,
"Generic command for showing gdb debugging flags",
&showdebuglist, "show debug ", 0, &showlist);
}