quit_command PARAMS ((char *, int));
static void
-initialize_main PARAMS ((void));
+init_main PARAMS ((void));
static void
-initialize_history PARAMS ((void));
+init_history PARAMS ((void));
static void
-initialize_cmd_lists PARAMS ((void));
+init_cmd_lists PARAMS ((void));
static void
float_handler PARAMS ((int));
#define sigsetmask(n)
#endif
\f
-/* This is how `error' returns to command level. */
+/* Where to go for return_to_top_level (RETURN_ERROR). */
+static jmp_buf error_return;
+/* Where to go for return_to_top_level (RETURN_QUIT). */
+static jmp_buf quit_return;
-jmp_buf to_top_level;
+/* Temporary variable for SET_TOP_LEVEL. */
+static int top_level_val;
+
+/* Do a setjmp on error_return and quit_return. catch_errors is
+ generally a cleaner way to do this, but main() would look pretty
+ ugly if it had to use catch_errors each time. */
+
+#define SET_TOP_LEVEL() \
+ (((top_level_val = setjmp (error_return)) \
+ ? (PTR) 0 : (PTR) memcpy (quit_return, error_return, sizeof (jmp_buf))) \
+ , top_level_val)
+
+/* Return for reason REASON. This generally gets back to the command
+ loop, but can be caught via catch_errors. */
NORETURN void
-return_to_top_level ()
+return_to_top_level (reason)
+ enum return_reason reason;
{
quit_flag = 0;
immediate_quit = 0;
bpstat_clear_actions(stop_bpstat); /* Clear queued breakpoint commands */
disable_current_display ();
do_cleanups (ALL_CLEANUPS);
- (NORETURN void) longjmp (to_top_level, 1);
+ (NORETURN void) longjmp
+ (reason == RETURN_ERROR ? error_return : quit_return, 1);
}
-/* Call FUNC with arg ARGS, catching any errors.
- If there is no error, return the value returned by FUNC.
- If there is an error, print ERRSTRING, print the specific error message,
- then return zero. */
+/* Call FUNC with arg ARGS, catching any errors. If there is no
+ error, return the value returned by FUNC. If there is an error,
+ print ERRSTRING, print the specific error message, then return
+ zero.
+
+ MASK specifies what to catch; it is normally set to
+ RETURN_MASK_ALL, if for no other reason than that the code which
+ calls catch_errors might not be set up to deal with a quit which
+ isn't caught. But if the code can deal with it, it generally
+ should be RETURN_MASK_ERROR, unless for some reason it is more
+ useful to abort only the portion of the operation inside the
+ catch_errors. Note that quit should return to the command line
+ fairly quickly, even if some further processing is being done. */
int
-catch_errors (func, args, errstring)
+catch_errors (func, args, errstring, mask)
int (*func) PARAMS ((char *));
- char *args;
+ PTR args;
char *errstring;
+ return_mask mask;
{
- jmp_buf saved;
+ jmp_buf saved_error;
+ jmp_buf saved_quit;
+ jmp_buf tmp_jmp;
int val;
struct cleanup *saved_cleanup_chain;
char *saved_error_pre_print;
saved_cleanup_chain = save_cleanups ();
saved_error_pre_print = error_pre_print;
- memcpy ((char *)saved, (char *)to_top_level, sizeof (jmp_buf));
+ if (mask & RETURN_MASK_ERROR)
+ memcpy ((char *)saved_error, (char *)error_return, sizeof (jmp_buf));
+ if (mask & RETURN_MASK_QUIT)
+ memcpy (saved_quit, quit_return, sizeof (jmp_buf));
error_pre_print = errstring;
- if (setjmp (to_top_level) == 0)
- val = (*func) (args);
+ if (setjmp (tmp_jmp) == 0)
+ {
+ if (mask & RETURN_MASK_ERROR)
+ memcpy (error_return, tmp_jmp, sizeof (jmp_buf));
+ if (mask & RETURN_MASK_QUIT)
+ memcpy (quit_return, tmp_jmp, sizeof (jmp_buf));
+ val = (*func) (args);
+ }
else
val = 0;
restore_cleanups (saved_cleanup_chain);
error_pre_print = saved_error_pre_print;
- memcpy ((char *)to_top_level, (char *)saved, sizeof (jmp_buf));
+ if (mask & RETURN_MASK_ERROR)
+ memcpy (error_return, saved_error, sizeof (jmp_buf));
+ if (mask & RETURN_MASK_QUIT)
+ memcpy (quit_return, saved_quit, sizeof (jmp_buf));
return val;
}
int signo;
{
catch_errors (quit_cover, NULL,
- "Could not kill the program being debugged");
+ "Could not kill the program being debugged", RETURN_MASK_ALL);
signal (SIGHUP, SIG_DFL);
kill (getpid (), SIGHUP);
}
#endif
/* If error() is called from initialization code, just exit */
- if (setjmp (to_top_level)) {
+ if (SET_TOP_LEVEL ()) {
exit(1);
}
/* Run the init function of each source file */
- initialize_cmd_lists (); /* This needs to be done first */
+ init_cmd_lists (); /* This needs to be done first */
initialize_all_files ();
- initialize_main (); /* But that omits this file! Do it now */
+ init_main (); /* But that omits this file! Do it now */
init_signals ();
if (!quiet)
strcat (homeinit, gdbinit);
if (!inhibit_gdbinit && access (homeinit, R_OK) == 0)
{
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
source_command (homeinit, 0);
}
do_cleanups (ALL_CLEANUPS);
/* Now perform all the actions indicated by the arguments. */
if (cdarg != NULL)
{
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
{
cd_command (cdarg, 0);
init_source_path ();
do_cleanups (ALL_CLEANUPS);
for (i = 0; i < ndir; i++)
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
directory_command (dirarg[i], 0);
free ((PTR)dirarg);
do_cleanups (ALL_CLEANUPS);
{
/* The exec file and the symbol-file are the same. If we can't open
it, better only print one error message. */
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
{
exec_file_command (execarg, !batch);
symbol_file_command (symarg, 0);
else
{
if (execarg != NULL)
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
exec_file_command (execarg, !batch);
if (symarg != NULL)
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
symbol_file_command (symarg, 0);
}
do_cleanups (ALL_CLEANUPS);
warning_pre_print = "\nwarning: ";
if (corearg != NULL)
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
core_file_command (corearg, !batch);
- else if (isdigit (corearg[0]) && !setjmp (to_top_level))
+ else if (isdigit (corearg[0]) && !SET_TOP_LEVEL ())
attach_command (corearg, !batch);
do_cleanups (ALL_CLEANUPS);
if (ttyarg != NULL)
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
tty_command (ttyarg, !batch);
do_cleanups (ALL_CLEANUPS);
|| memcmp ((char *) &homebuf, (char *) &cwdbuf, sizeof (struct stat)))
if (!inhibit_gdbinit && access (gdbinit, R_OK) == 0)
{
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
source_command (gdbinit, 0);
}
do_cleanups (ALL_CLEANUPS);
for (i = 0; i < ncmd; i++)
{
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
{
if (cmdarg[i][0] == '-' && cmdarg[i][1] == '\0')
read_command_file (stdin);
free ((PTR)cmdarg);
/* Read in the old history after all the command files have been read. */
- initialize_history();
+ init_history();
if (batch)
{
while (1)
{
- if (!setjmp (to_top_level))
+ if (!SET_TOP_LEVEL ())
{
do_cleanups (ALL_CLEANUPS); /* Do complete cleanup */
command_loop ();
return NULL;
}
+/* Complete on filenames. */
+/* FIXME: This would be a lot more useful if the word breaks got set
+ to not include '/'. Probably best to make it up to each completer
+ to do its own word breaking. */
+char **
+filename_completer (text)
+ char *text;
+{
+ /* From readline. */
+ extern char *filename_completion_function ();
+ int subsequent_name;
+ char **return_val;
+ int return_val_used;
+ int return_val_alloced;
+
+ return_val_used = 0;
+ /* Small for testing. */
+ 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 *));
+ }
+ /* The string itself has already been stored in newly malloc'd space
+ for us by filename_completion_function. */
+ return_val[return_val_used++] = p;
+ if (p == NULL)
+ break;
+ subsequent_name = 1;
+ }
+ return return_val;
+}
+
/* Generate symbol names one by one for the completer. Each time we are
called return another potential completion to the caller.
special word break set for command strings, which leaves out the
'-' character used in some commands. */
+ /* FIXME: Using rl_completer_word_break_characters is the wrong
+ approach, because "show foo-bar<TAB>" won't know to use the
+ new set until too late. Better approach is to do the word breaking
+ ourself. */
+
rl_completer_word_break_characters =
gdb_completer_word_break_characters;
\f
static void
-initialize_cmd_lists ()
+init_cmd_lists ()
{
cmdlist = NULL;
infolist = NULL;
*/
static void
-initialize_history()
+init_history()
{
char *tmpenv;
}
static void
-initialize_main ()
+init_main ()
{
struct cmd_list_element *c;
add_com ("pwd", class_files, pwd_command,
"Print working directory. This is used for your program as well.");
- add_com ("cd", class_files, cd_command,
+ 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.");
+until the next time it is started.", &cmdlist);
+ c->completer = filename_completer;
add_show_from_set
(add_set_cmd ("prompt", class_support, var_string, (char *)&prompt,
Commands defined in this way do not take arguments.");
#ifdef __STDC__
- add_com ("source", class_support, source_command,
+ 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.");
+when gdb is started.", &cmdlist);
#else
/* Punt file name, we can't help it easily. */
- add_com ("source", class_support, source_command,
+ 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.");
+when gdb is started.", &cmdlist);
#endif
+ c->completer = filename_completer;
add_com ("quit", class_support, quit_command, "Exit gdb.");
add_com ("help", class_support, help_command, "Print list of commands.");