/* Top level stuff for GDB, the GNU debugger.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
Free Software Foundation, Inc.
This file is part of GDB.
static void stop_sig PARAMS ((int));
#endif
-static void disconnect PARAMS ((int));
-
static char * line_completion_function PARAMS ((char *, int, char *, int));
static char * readline_line_completion_function PARAMS ((char *, int));
static void set_verbose PARAMS ((char *, int, struct cmd_list_element *));
-#ifdef TARGET_BYTE_ORDER_SELECTABLE
-
static void set_endian PARAMS ((char *, int));
static void set_endian_big PARAMS ((char *, int));
static void show_endian PARAMS ((char *, int));
-#endif
+static void set_architecture PARAMS ((char *, int));
+
+static void show_architecture PARAMS ((char *, int));
+
+static void info_architecture PARAMS ((char *, int));
static void show_history PARAMS ((char *, int));
static void do_nothing PARAMS ((int));
+#ifdef SIGHUP
static int quit_cover PARAMS ((char *));
static void disconnect PARAMS ((int));
+#endif
static void source_cleanup PARAMS ((FILE *));
struct cmd_list_element *showlist;
-#ifdef TARGET_BYTE_ORDER_SELECTABLE
/* Chain containing the \"set endian\" commands. */
struct cmd_list_element *endianlist;
-#endif
/* Chain containing all defined \"set history\". */
/* Called after most modules have been initialized, but before taking users
command file. */
-void (*init_ui_hook) PARAMS ((void));
+void (*init_ui_hook) PARAMS ((char *argv0));
+#ifdef __CYGWIN32__
+void (*ui_loop_hook) PARAMS ((int));
+#endif
/* Called instead of command_loop at top level. Can be invoked via
return_to_top_level. */
int (*query_hook) PARAMS ((const char *, va_list));
+/* Replaces most of warning. */
+
+void (*warning_hook) PARAMS ((const char *, va_list));
+
/* Called from gdb_flush to flush output. */
void (*flush_hook) PARAMS ((FILE *stream));
void (*registers_changed_hook) PARAMS ((void));
+/* tell the GUI someone changed the PC */
+void (*pc_changed_hook) PARAMS ((void));
+
/* Called when going to wait for the target. Usually allows the GUI to run
while waiting for target events. */
void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
int from_tty));
+/* Called when the current thread changes. Argument is thread id. */
+
+void (*context_hook) PARAMS ((int id));
/* Takes control from error (). Typically used to prevent longjmps out of the
middle of the GUI. Usually used in conjunction with a catch routine. */
\f
/* Where to go for return_to_top_level (RETURN_ERROR). */
-jmp_buf error_return;
+SIGJMP_BUF error_return;
/* Where to go for return_to_top_level (RETURN_QUIT). */
-jmp_buf quit_return;
+SIGJMP_BUF quit_return;
/* Return for reason REASON. This generally gets back to the command
loop, but can be caught via catch_errors. */
break;
}
- (NORETURN void) longjmp
+ (NORETURN void) SIGLONGJMP
(reason == RETURN_ERROR ? error_return : quit_return, 1);
}
char *errstring;
return_mask mask;
{
- jmp_buf saved_error;
- jmp_buf saved_quit;
- jmp_buf tmp_jmp;
+ SIGJMP_BUF saved_error;
+ SIGJMP_BUF saved_quit;
+ SIGJMP_BUF tmp_jmp;
int val;
struct cleanup *saved_cleanup_chain;
char *saved_error_pre_print;
if (mask & RETURN_MASK_ERROR)
{
- memcpy ((char *)saved_error, (char *)error_return, sizeof (jmp_buf));
+ memcpy ((char *)saved_error, (char *)error_return, sizeof (SIGJMP_BUF));
error_pre_print = errstring;
}
if (mask & RETURN_MASK_QUIT)
{
- memcpy (saved_quit, quit_return, sizeof (jmp_buf));
+ memcpy (saved_quit, quit_return, sizeof (SIGJMP_BUF));
quit_pre_print = errstring;
}
- if (setjmp (tmp_jmp) == 0)
+ if (SIGSETJMP (tmp_jmp) == 0)
{
if (mask & RETURN_MASK_ERROR)
- memcpy (error_return, tmp_jmp, sizeof (jmp_buf));
+ memcpy (error_return, tmp_jmp, sizeof (SIGJMP_BUF));
if (mask & RETURN_MASK_QUIT)
- memcpy (quit_return, tmp_jmp, sizeof (jmp_buf));
+ memcpy (quit_return, tmp_jmp, sizeof (SIGJMP_BUF));
val = (*func) (args);
}
else
if (mask & RETURN_MASK_ERROR)
{
- memcpy (error_return, saved_error, sizeof (jmp_buf));
+ memcpy (error_return, saved_error, sizeof (SIGJMP_BUF));
error_pre_print = saved_error_pre_print;
}
if (mask & RETURN_MASK_QUIT)
{
- memcpy (quit_return, saved_quit, sizeof (jmp_buf));
+ memcpy (quit_return, saved_quit, sizeof (SIGJMP_BUF));
quit_pre_print = saved_quit_pre_print;
}
return val;
/* Handler for SIGHUP. */
-#ifndef _WIN32
+#ifdef SIGHUP
static void
disconnect (signo)
int signo;
signal (SIGHUP, SIG_DFL);
kill (getpid (), SIGHUP);
}
-#endif
/* Just a little helper function for disconnect(). */
quit_command((char *)0, 0);
return 0;
}
+#endif /* defined SIGHUP */
\f
/* Line number we are currently in in a file which is being sourced. */
static int source_line_number;
void (*pre_init_ui_hook) PARAMS ((void));
void
-gdb_init ()
+gdb_init (argv0)
+ char *argv0;
{
if (pre_init_ui_hook)
pre_init_ui_hook ();
expected_language = current_language; /* don't warn about the change. */
if (init_ui_hook)
- init_ui_hook ();
+ init_ui_hook (argv0);
}
/* Allocate, initialize a new command line structure for one of the
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;
/* Keep iterating so long as the expression is true. */
while (loop == 1)
{
+ int cond_result;
+
QUIT;
/* Evaluate the expression. */
+ val_mark = value_mark ();
val = evaluate_expression (expr);
+ cond_result = value_true (val);
+ value_free_to_mark (val_mark);
/* If the value is false, then break out of the loop. */
- if (!value_true (val))
+ if (!cond_result)
break;
/* Execute the body of the while statement. */
ret = simple_control;
/* Evaluate the conditional. */
+ val_mark = value_mark ();
val = evaluate_expression (expr);
/* Choose which arm to take commands from based on the value of the
current = *cmd->body_list;
else if (cmd->body_count == 2)
current = *(cmd->body_list + 1);
+ value_free_to_mark (val_mark);
/* Execute commands in the given arm. */
while (current)
while (*p)
{
char *start_arg;
+ int squote = 0;
+ int dquote = 0;
+ int bsquote = 0;
if (arg_count >= MAXUSERARGS)
{
user_args->a[arg_count].arg = p;
/* Get to the end of this argument. */
- while (*p && *p != ' ' && *p != '\t')
- 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++;
free_all_values ();
+ /* Force cleanup of any alloca areas if using C alloca instead of
+ a builtin alloca. */
+ alloca (0);
+
/* This can happen when command_line_input hits end of file. */
if (p == NULL)
return;
do_nothing (signo)
int signo;
{
+ /* Under System V the default disposition of a signal is reinstated after
+ the signal is caught and delivered to an application process. On such
+ systems one must restore the replacement signal handler if one wishes
+ to continue handling the signal in one's program. On BSD systems this
+ is not needed but it is harmless, and it simplifies the code to just do
+ it unconditionally. */
+ signal (signo, do_nothing);
}
static void
might be in memory, shared between the two). Since we establish
a handler for SIGQUIT, when we call exec it will set the signal
to SIG_DFL for us. */
-#ifndef _WIN32
signal (SIGQUIT, do_nothing);
+#ifdef SIGHUP
if (signal (SIGHUP, do_nothing) != SIG_IGN)
signal (SIGHUP, disconnect);
#endif
/* Second line is a copyright notice. */
- fprintf_filtered (stream, "Copyright 1996 Free Software Foundation, Inc.\n");
+ fprintf_filtered (stream, "Copyright 1998 Free Software Foundation, Inc.\n");
/* Following the copyright is a brief statement that the program is
free software, that users are free to copy and change it on
printf_unfiltered ("%s", prompt);
gdb_flush (gdb_stdout);
}
+
+/* This replaces the above for the frontends: it returns a pointer
+ to the prompt. */
+char *
+get_prompt ()
+{
+ return prompt;
+}
\f
+/* If necessary, make the user confirm that we should quit. Return
+ non-zero if we should quit, zero if we shouldn't. */
+
+int
+quit_confirm ()
+{
+ if (inferior_pid != 0 && target_has_execution)
+ {
+ char *s;
+
+ /* This is something of a hack. But there's no reliable way to
+ see if a GUI is running. The `use_windows' variable doesn't
+ cut it. */
+ 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;
+}
+
+/* Quit without asking for confirmation. */
+
void
-quit_command (args, from_tty)
+quit_force (args, from_tty)
char *args;
int from_tty;
{
if (inferior_pid != 0 && target_has_execution)
{
if (attach_flag)
- {
- if (query ("The program is running. Quit anyway (and detach it)? "))
- target_detach (args, from_tty);
- else
- error ("Not confirmed.");
- }
+ target_detach (args, from_tty);
else
- {
- if (query ("The program is running. Quit anyway (and kill it)? "))
- target_kill ();
- else
- error ("Not confirmed.");
- }
+ target_kill ();
}
+
/* UDI wants this, to kill the TIP. */
target_close (1);
if (write_history_p && history_filename)
write_history (history_filename);
+ do_final_cleanups(ALL_CLEANUPS); /* Do any final cleanups before exiting */
+
exit (exit_code);
}
+/* Handle the quit command. */
+
+void
+quit_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (! quit_confirm ())
+ error ("Not confirmed.");
+ quit_force (args, from_tty);
+}
+
/* Returns whether GDB is running on a terminal and whether the user
desires that questions be asked of them on that terminal. */
necessarily reading from stdin. */
}
\f
-#ifdef TARGET_BYTE_ORDER_SELECTABLE
-
/* Functions to manipulate the endianness of the target. */
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
#ifndef TARGET_BYTE_ORDER_DEFAULT
#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN
#endif
-
int target_byte_order = TARGET_BYTE_ORDER_DEFAULT;
-
-static int target_byte_order_auto = 1;
+int target_byte_order_auto = 1;
+#else
+static int target_byte_order_auto = 0;
+#endif
/* Called if the user enters ``set endian'' without an argument. */
static void
char *args;
int from_tty;
{
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
target_byte_order = BIG_ENDIAN;
target_byte_order_auto = 0;
+#else
+ printf_unfiltered ("Byte order is not selectable.");
+ show_endian (args, from_tty);
+#endif
}
/* Called by ``set endian little''. */
char *args;
int from_tty;
{
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
target_byte_order = LITTLE_ENDIAN;
target_byte_order_auto = 0;
+#else
+ printf_unfiltered ("Byte order is not selectable.");
+ show_endian (args, from_tty);
+#endif
}
/* Called by ``set endian auto''. */
char *args;
int from_tty;
{
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
target_byte_order_auto = 1;
+#else
+ printf_unfiltered ("Byte order is not selectable.");
+ show_endian (args, from_tty);
+#endif
}
/* Called by ``show endian''. */
printf_unfiltered ((char *) msg, TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
}
-#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
-
/* Set the endianness from a BFD. */
void
set_endian_from_file (abfd)
#endif /* ! defined (TARGET_BYTE_ORDER_SELECTABLE) */
}
\f
+/* Functions to manipulate the architecture of the target */
+
+int target_architecture_auto = 1;
+extern const bfd_arch_info_type bfd_default_arch_struct;
+const bfd_arch_info_type *target_architecture = &bfd_default_arch_struct;
+int (*target_architecture_hook) PARAMS ((const bfd_arch_info_type *ap));
+
+static void
+set_arch (arch)
+ const bfd_arch_info_type *arch;
+{
+ /* FIXME: Is it compatible with gdb? */
+ /* Check with the target on the setting */
+ if (target_architecture_hook != NULL
+ && !target_architecture_hook (arch))
+ printf_unfiltered ("Target does not support `%s' architecture.\n",
+ arch->printable_name);
+ else
+ {
+ target_architecture_auto = 0;
+ target_architecture = arch;
+ }
+}
+
+
+/* Called if the user enters ``set architecture'' with or without an
+ argument. */
+static void
+set_architecture (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args == NULL)
+ {
+ printf_unfiltered ("\"set architecture\" must be followed by \"auto\" or an architecture name.\n");
+ }
+ else if (strcmp (args, "auto") == 0)
+ {
+ target_architecture_auto = 1;
+ }
+ else
+ {
+ const bfd_arch_info_type *arch = bfd_scan_arch (args);
+ if (arch != NULL)
+ set_arch (arch);
+ else
+ printf_unfiltered ("Architecture `%s' not reconized.\n", args);
+ }
+}
+
+/* Called if the user enters ``show architecture'' without an argument. */
+static void
+show_architecture (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ const char *arch;
+ arch = target_architecture->printable_name;
+ if (target_architecture_auto)
+ printf_filtered ("The target architecture is set automatically (currently %s)\n", arch);
+ else
+ printf_filtered ("The target architecture is assumed to be %s\n", arch);
+}
+
+/* Called if the user enters ``info architecture'' without an argument. */
+static void
+info_architecture (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ enum bfd_architecture a;
+ printf_filtered ("Available architectures are:\n");
+ for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
+ {
+ const bfd_arch_info_type *ap = bfd_lookup_arch (a, 0);
+ if (ap != NULL)
+ {
+ do
+ {
+ printf_filtered (" %s", ap->printable_name);
+ ap = ap->next;
+ }
+ while (ap != NULL);
+ printf_filtered ("\n");
+ }
+ }
+}
+
+/* Set the architecture from arch/machine */
+void
+set_architecture_from_arch_mach (arch, mach)
+ enum bfd_architecture arch;
+ unsigned long mach;
+{
+ const bfd_arch_info_type *wanted = bfd_lookup_arch (arch, mach);
+ if (wanted != NULL)
+ set_arch (wanted);
+ else
+ fatal ("hardwired architecture/machine not reconized");
+}
+
+
+/* Set the architecture from a BFD */
+void
+set_architecture_from_file (abfd)
+ bfd *abfd;
+{
+ const bfd_arch_info_type *wanted = bfd_get_arch_info (abfd);
+ if (target_architecture_auto)
+ {
+ if (target_architecture_hook != NULL
+ && !target_architecture_hook (wanted))
+ warning ("Target may not support %s architecture",
+ wanted->printable_name);
+ target_architecture = wanted;
+ }
+ else if (wanted != target_architecture)
+ {
+ warning ("%s architecture file may be incompatible with %s target.",
+ wanted->printable_name,
+ target_architecture->printable_name);
+ }
+}
+\f
/* Functions to manipulate command line editing control variables. */
/* Number of commands to print in each call to show_commands. */
setlist = NULL;
unsetlist = NULL;
showlist = NULL;
-#ifdef TARGET_BYTE_ORDER_SELECTABLE
endianlist = NULL;
-#endif
sethistlist = NULL;
showhistlist = NULL;
unsethistlist = NULL;
{
struct cmd_list_element *c;
-#ifdef TARGET_BYTE_ORDER_SELECTABLE
-
add_prefix_cmd ("endian", class_support, set_endian,
"Set endianness of target.",
&endianlist, "set endian ", 0, &setlist);
add_cmd ("endian", class_support, show_endian,
"Show endianness of target.", &showlist);
-#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
+ add_cmd ("architecture", class_support, set_architecture,
+ "Set architecture of target.", &setlist);
+ add_alias_cmd ("processor", "architecture", class_support, 1, &setlist);
+ add_cmd ("architecture", class_support, show_architecture,
+ "Show architecture of target.", &showlist);
+ add_cmd ("architecture", class_support, info_architecture,
+ "List supported target architectures", &infolist);
+
#ifdef DEFAULT_PROMPT
prompt = savestring (DEFAULT_PROMPT, strlen(DEFAULT_PROMPT));
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 to enable the editing, and \"off\" to disable it.\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);
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 to enable the saving, and \"off\" to disable it.\n\
+Use \"on\" to enable the saving, and \"off\" to disable it.\n\
Without an argument, saving is enabled.", &sethistlist),
&showhistlist);
This value is used to set the time limit for gdb to wait for a response\n\
from he target.", &setlist),
&showlist);
+
+ 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);
}