X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fmain.c;h=38771daed2b5f0a3da100007a8e3539ddcd74bea;hb=2fe3b329f69ca294a8ad3f1f655df7db33a6eb65;hp=e36d7305107e712e9d8fdfadf65c7f67cdf0f66a;hpb=7d9884b92772d5b4fa0de57de5caca2d9308c16c;p=binutils-gdb.git diff --git a/gdb/main.c b/gdb/main.c index e36d7305107..38771daed2b 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -1,5 +1,6 @@ /* Top level `main' program for GDB, the GNU debugger. - Copyright 1986, 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc. + Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -17,16 +18,18 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -int fclose (); #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 "language.h" +#include "terminal.h" /* For job_control. */ #include "getopt.h" @@ -37,13 +40,16 @@ int fclose (); /* readline defines this. */ #undef savestring -#ifdef USG #include +#ifdef USG +/* What is this for? X_OK? */ #include #endif #include +#ifndef NO_SYS_FILE #include +#endif #include #include #include @@ -56,6 +62,105 @@ int fclose (); int original_stack_limit; #endif +/* Prototypes for local functions */ + +static char * +symbol_completion_function PARAMS ((char *, int)); + +static void +command_loop PARAMS ((void)); + +static void +command_loop_marker PARAMS ((int)); + +static void +print_gdb_version PARAMS ((GDB_FILE *)); + +static void +quit_command PARAMS ((char *, int)); + +static void +init_main PARAMS ((void)); + +static void +init_history PARAMS ((void)); + +static void +init_cmd_lists PARAMS ((void)); + +static void +float_handler PARAMS ((int)); + +static void +source_command PARAMS ((char *, int)); + +static void cd_command PARAMS ((char *, int)); + +static void +print_gnu_advertisement PARAMS ((void)); + +static void +init_signals PARAMS ((void)); + +static void +read_command_file PARAMS ((FILE *)); + +static void +set_verbose PARAMS ((char *, int, struct cmd_list_element *)); + +static void +show_history PARAMS ((char *, int)); + +static void +set_history PARAMS ((char *, int)); + +static void +set_history_size_command PARAMS ((char *, int, struct cmd_list_element *)); + +static void +show_commands PARAMS ((char *, int)); + +static void +echo_command PARAMS ((char *, int)); + +static void +pwd_command PARAMS ((char *, int)); + +static void +show_version PARAMS ((char *, int)); + +static void +document_command PARAMS ((char *, int)); + +static void +define_command PARAMS ((char *, int)); + +static void +validate_comname PARAMS ((char *)); + +static void +help_command PARAMS ((char *, int)); + +static void +show_command PARAMS ((char *, int)); + +static void +info_command PARAMS ((char *, int)); + +static void +complete_command PARAMS ((char *, int)); + +static void +do_nothing PARAMS ((int)); + +static int +quit_cover PARAMS ((char *)); + +static void +disconnect PARAMS ((int)); + +static void +source_cleanup PARAMS ((FILE *)); /* If this definition isn't overridden by the header files, assume that isatty and fileno exist on this system. */ @@ -68,7 +173,8 @@ int original_stack_limit; #ifndef GDBINIT_FILENAME #define GDBINIT_FILENAME ".gdbinit" #endif -char gdbinit[] = GDBINIT_FILENAME; +static char gdbinit[] = GDBINIT_FILENAME; +static int inhibit_gdbinit = 0; #define ALL_CLEANUPS ((struct cleanup *)0) @@ -76,9 +182,13 @@ char gdbinit[] = GDBINIT_FILENAME; extern char *version; -/* Message to be printed before the error message, when an error occurs. */ +/* Canonical host name as a string. */ -extern char *error_pre_print; +extern char *host_name; + +/* Canonical target name as a string. */ + +extern char *target_name; extern char lang_frame_mismatch_warn[]; /* language.c */ @@ -118,7 +228,12 @@ struct cmd_list_element *enablebreaklist; struct cmd_list_element *setlist; +/* Chain containing all defined unset subcommands */ + +struct cmd_list_element *unsetlist; + /* Chain containing all defined show subcommands. */ + struct cmd_list_element *showlist; /* Chain containing all defined \"set history\". */ @@ -126,13 +241,42 @@ struct cmd_list_element *showlist; struct cmd_list_element *sethistlist; /* Chain containing all defined \"show history\". */ + struct cmd_list_element *showhistlist; /* Chain containing all defined \"unset history\". */ struct cmd_list_element *unsethistlist; -/* stdio stream that command input is being read from. */ +/* Chain containing all defined maintenance subcommands. */ + +#if MAINTENANCE_CMDS +struct cmd_list_element *maintenancelist; +#endif + +/* Chain containing all defined "maintenance info" subcommands. */ + +#if MAINTENANCE_CMDS +struct cmd_list_element *maintenanceinfolist; +#endif + +/* Chain containing all defined "maintenance print" subcommands. */ + +#if MAINTENANCE_CMDS +struct cmd_list_element *maintenanceprintlist; +#endif + +struct cmd_list_element *setprintlist; + +struct cmd_list_element *showprintlist; + +struct cmd_list_element *setchecklist; + +struct cmd_list_element *showchecklist; + +/* stdio stream that command input is being read from. Set to stdin normally. + Set by source_command to the file we are sourcing. Set to NULL if we are + executing a user-defined command. */ FILE *instream; @@ -141,49 +285,20 @@ FILE *instream; char *current_directory; /* The directory name is actually stored here (usually). */ -static char dirbuf[MAXPATHLEN]; +static char dirbuf[1024]; /* Function to call before reading a command, if nonzero. The function receives two args: an input stream, and a prompt string. */ -void (*window_hook) (); +void (*window_hook) PARAMS ((FILE *, char *)); + +extern int mapped_symbol_files; +extern int readnow_symbol_files; -extern int frame_file_full_name; int epoch_interface; int xgdb_verbose; -/* The external commands we call... */ -extern void init_source_path (); -extern void directory_command (); -extern void exec_file_command (); -extern void symbol_file_command (); -extern void core_file_command (); -extern void tty_command (); - -extern void help_list (); -extern void initialize_all_files (); -extern void init_malloc (); - -/* Forward declarations for this file */ -void free_command_lines (); -char *gdb_readline (); -char *command_line_input (); -static void initialize_history (); -static void initialize_main (); -static void initialize_cmd_lists (); -static void init_signals (); -static void quit_command (); -void command_loop (); -static void source_command (); -static void print_gdb_version (); -static void print_gnu_advertisement (); -static void float_handler (); -static void cd_command (); -static void read_command_file (); - -char *getenv (); - /* gdb prints this when reading a command interactively */ static char *prompt; @@ -194,55 +309,104 @@ char *line; int linesize = 100; /* Baud rate specified for talking to serial target systems. Default - is left as a zero pointer, so targets can choose their own defaults. */ + is left as -1, so targets can choose their own defaults. */ +/* FIXME: This means that "show remotebaud" and gr_files_info can print -1 + or (unsigned int)-1. This is a Bad User Interface. */ -char *baud_rate; +int baud_rate = -1; + +/* Non-zero tells remote* modules to output debugging info. */ + +int remote_debug = 0; /* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */ #ifndef STOP_SIGNAL #ifdef SIGTSTP #define STOP_SIGNAL SIGTSTP +static void stop_sig PARAMS ((int)); #endif #endif /* Some System V have job control but not sigsetmask(). */ #if !defined (HAVE_SIGSETMASK) -#define HAVE_SIGSETMASK !defined (USG) +#if !defined (USG) +#define HAVE_SIGSETMASK 1 +#else +#define HAVE_SIGSETMASK 0 +#endif #endif #if 0 == (HAVE_SIGSETMASK) #define sigsetmask(n) #endif -/* 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; -void -return_to_top_level () +/* 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 (reason) + enum return_reason reason; { quit_flag = 0; immediate_quit = 0; + + /* Perhaps it would be cleaner to do this via the cleanup chain (not sure + I can think of a reason why that is vital, though). */ bpstat_clear_actions(stop_bpstat); /* Clear queued breakpoint commands */ - clear_momentary_breakpoints (); + disable_current_display (); do_cleanups (ALL_CLEANUPS); - 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. + + Must not be called with immediate_quit in effect (bad things might + happen, say we got a signal in the middle of a memcpy to quit_return). + This is an OK restriction; with very few exceptions immediate_quit can + be replaced by judicious use of QUIT. + + 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) - int (*func) (); - char *args; +catch_errors (func, args, errstring, mask) + int (*func) PARAMS ((char *)); + 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; @@ -250,31 +414,72 @@ catch_errors (func, args, errstring) saved_cleanup_chain = save_cleanups (); saved_error_pre_print = error_pre_print; - bcopy (to_top_level, saved, 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; - bcopy (saved, to_top_level, 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; } /* Handler for SIGHUP. */ static void -disconnect () +disconnect (signo) +int signo; { - kill_inferior_fast (); + catch_errors (quit_cover, NULL, + "Could not kill the program being debugged", RETURN_MASK_ALL); signal (SIGHUP, SIG_DFL); kill (getpid (), SIGHUP); } + +/* Just a little helper function for disconnect(). */ + +static int +quit_cover (s) +char *s; +{ + caution = 0; /* Throw caution to the wind -- we're exiting. + This prevents asking the user dumb questions. */ + quit_command((char *)0, 0); + return 0; +} +/* Line number we are currently in in a file which is being sourced. */ +static int source_line_number; + +/* Name of the file we are sourcing. */ +static char *source_file_name; + +/* Buffer containing the error_pre_print used by the source stuff. + Malloc'd. */ +static char *source_error; +static int source_error_allocated; + +/* Something to glom on to the start of error_pre_print if source_file_name + is set. */ +static char *source_pre_error; + /* Clean up on error during a "source" command (or execution of a user-defined command). */ @@ -305,7 +510,6 @@ main (argc, argv) char **argv; { int count; - static int inhibit_gdbinit = 0; static int quiet = 0; static int batch = 0; @@ -316,24 +520,31 @@ main (argc, argv) char *cdarg = NULL; char *ttyarg = NULL; - /* Pointers to all arguments of +command option. */ + /* These are static so that we can take their address in an initializer. */ + static int print_help; + static int print_version; + + /* Pointers to all arguments of --command option. */ char **cmdarg; /* Allocated size of cmdarg. */ int cmdsize; /* Number of elements of cmdarg used. */ int ncmd; - /* Indices of all arguments of +directory option. */ + /* Indices of all arguments of --directory option. */ char **dirarg; /* Allocated size. */ int dirsize; /* Number of elements used. */ int ndir; + struct stat homebuf, cwdbuf; + char *homedir, *homeinit; + register int i; /* This needs to happen before the first use of malloc. */ - init_malloc (); + init_malloc ((PTR) NULL); #if defined (ALIGN_STACK_ON_STARTUP) i = (int) &count & 0x3; @@ -342,7 +553,7 @@ main (argc, argv) #endif /* If error() is called from initialization code, just exit */ - if (setjmp (to_top_level)) { + if (SET_TOP_LEVEL ()) { exit(1); } @@ -358,7 +569,7 @@ main (argc, argv) line[0] = '\0'; /* Terminate saved (now empty) cmd line */ instream = stdin; - getwd (dirbuf); + getcwd (dirbuf, sizeof (dirbuf)); current_directory = dirbuf; #ifdef SET_STACK_LIMIT_HUGE @@ -377,39 +588,51 @@ main (argc, argv) /* Parse arguments and options. */ { int c; - static int print_help; /* When var field is 0, use flag field to record the equivalent short option (or arbitrary numbers starting at 10 for those with no equivalent). */ static struct option long_options[] = { - {"quiet", 0, &quiet, 1}, - {"nx", 0, &inhibit_gdbinit, 1}, - {"batch", 0, &batch, 1}, - {"epoch", 0, &epoch_interface, 1}, - {"fullname", 0, &frame_file_full_name, 1}, - {"help", 0, &print_help, 1}, - {"se", 1, 0, 10}, - {"symbols", 1, 0, 's'}, - {"s", 1, 0, 's'}, - {"exec", 1, 0, 'e'}, - {"core", 1, 0, 'c'}, - {"c", 1, 0, 'c'}, - {"command", 1, 0, 'x'}, - {"x", 1, 0, 'x'}, - {"directory", 1, 0, 'd'}, - {"cd", 1, 0, 11}, - {"tty", 1, 0, 't'}, - {"b", 1, 0, 'b'}, + {"readnow", no_argument, &readnow_symbol_files, 1}, + {"r", no_argument, &readnow_symbol_files, 1}, + {"mapped", no_argument, &mapped_symbol_files, 1}, + {"m", no_argument, &mapped_symbol_files, 1}, + {"quiet", no_argument, &quiet, 1}, + {"q", no_argument, &quiet, 1}, + {"silent", no_argument, &quiet, 1}, + {"nx", no_argument, &inhibit_gdbinit, 1}, + {"n", no_argument, &inhibit_gdbinit, 1}, + {"batch", no_argument, &batch, 1}, + {"epoch", no_argument, &epoch_interface, 1}, + {"fullname", no_argument, &frame_file_full_name, 1}, + {"f", no_argument, &frame_file_full_name, 1}, + {"help", no_argument, &print_help, 1}, + {"se", required_argument, 0, 10}, + {"symbols", required_argument, 0, 's'}, + {"s", required_argument, 0, 's'}, + {"exec", required_argument, 0, 'e'}, + {"e", required_argument, 0, 'e'}, + {"core", required_argument, 0, 'c'}, + {"c", required_argument, 0, 'c'}, + {"command", required_argument, 0, 'x'}, + {"version", no_argument, &print_version, 1}, + {"x", required_argument, 0, 'x'}, + {"directory", required_argument, 0, 'd'}, + {"cd", required_argument, 0, 11}, + {"tty", required_argument, 0, 't'}, + {"baud", required_argument, 0, 'b'}, + {"b", required_argument, 0, 'b'}, /* Allow machine descriptions to add more options... */ #ifdef ADDITIONAL_OPTIONS ADDITIONAL_OPTIONS #endif - {0, 0, 0, 0}, + {0, no_argument, 0, 0}, }; while (1) { + int option_index; + c = getopt_long_only (argc, argv, "", long_options, &option_index); if (c == EOF) @@ -465,54 +688,35 @@ main (argc, argv) quiet = 1; break; case 'b': - baud_rate = optarg; + { + int i; + char *p; + + i = strtol (optarg, &p, 0); + if (i == 0 && p == optarg) + + /* Don't use *_filtered or warning() (which relies on + current_target) until after initialize_all_files(). */ + + fprintf_unfiltered + (gdb_stderr, + "warning: could not set baud rate to `%s'.\n", optarg); + else + baud_rate = i; + } break; + #ifdef ADDITIONAL_OPTION_CASES ADDITIONAL_OPTION_CASES #endif case '?': - fprintf (stderr, - "Use `%s +help' for a complete list of options.\n", + fprintf_unfiltered (gdb_stderr, + "Use `%s --help' for a complete list of options.\n", argv[0]); exit (1); } - } - if (print_help) - { - fputs ("\ -This is GDB, the GNU debugger. Use the command\n\ - gdb [options] [executable [core-file]]\n\ -to enter the debugger.\n\ -\n\ -Options available are:\n\ - -help Print this message.\n\ - -quiet Do not print version number on startup.\n\ - -fullname Output information used by emacs-GDB interface.\n\ - -epoch Output information used by epoch emacs-GDB interface.\n\ - -batch Exit after processing options.\n\ - -nx Do not read .gdbinit file.\n\ - -tty=TTY Use TTY for input/output by the program being debugged.\n\ - -cd=DIR Change current directory to DIR.\n\ - -directory=DIR Search for source files in DIR.\n\ - -command=FILE Execute GDB commands from FILE.\n\ - -symbols=SYMFILE Read symbols from SYMFILE.\n\ - -exec=EXECFILE Use EXECFILE as the executable.\n\ - -se=FILE Use FILE as symbol file and executable file.\n\ - -core=COREFILE Analyze the core dump COREFILE.\n\ - -b BAUDRATE Set serial port baud rate used for remote debugging\n\ -", stderr); -#ifdef ADDITIONAL_OPTION_HELP - fputs (ADDITIONAL_OPTION_HELP, stderr); -#endif - fputs ("\n\ -For more information, type \"help\" from within GDB, or consult the\n\ -GDB manual (available as on-line info or a printed manual).\n", stderr); - /* Exiting after printing this message seems like - the most useful thing to do. */ - exit (0); - } - + /* OK, that's all the options. The other arguments are filenames. */ count = 0; for (; optind < argc; optind++) @@ -526,7 +730,7 @@ GDB manual (available as on-line info or a printed manual).\n", stderr); corearg = argv[optind]; break; case 3: - fprintf (stderr, + fprintf_unfiltered (gdb_stderr, "Excess command line arguments ignored. (%s%s)\n", argv[optind], (optind == argc - 1) ? "" : " ..."); break; @@ -537,49 +741,142 @@ GDB manual (available as on-line info or a printed manual).\n", stderr); /* 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 (); + /* Do these (and anything which might call wrap_here or *_filtered) + after initialize_all_files. */ + if (print_version) + { + print_gdb_version (gdb_stdout); + wrap_here (""); + printf_filtered ("\n"); + exit (0); + } + + if (print_help) + { + /* --version is intentionally not documented here, because we + are printing the version here, and the help is long enough + already. */ + + print_gdb_version (gdb_stdout); + /* Make sure the output gets printed. */ + wrap_here (""); + printf_filtered ("\n"); + + /* But don't use *_filtered here. We don't want to prompt for continue + no matter how small the screen or how much we're going to print. */ + fputs_unfiltered ("\ +This is the GNU debugger. Usage:\n\ + gdb [options] [executable-file [core-file or process-id]]\n\ +Options:\n\ + --help Print this message.\n\ + --quiet Do not print version number on startup.\n\ + --fullname Output information used by emacs-GDB interface.\n\ + --epoch Output information used by epoch emacs-GDB interface.\n\ + --batch Exit after processing options.\n\ + --nx Do not read .gdbinit file.\n\ + --tty=TTY Use TTY for input/output by the program being debugged.\n\ + --cd=DIR Change current directory to DIR.\n\ + --directory=DIR Search for source files in DIR.\n\ + --command=FILE Execute GDB commands from FILE.\n\ + --symbols=SYMFILE Read symbols from SYMFILE.\n\ + --exec=EXECFILE Use EXECFILE as the executable.\n\ + --se=FILE Use FILE as symbol file and executable file.\n\ + --core=COREFILE Analyze the core dump COREFILE.\n\ + -b BAUDRATE Set serial port baud rate used for remote debugging.\n\ + --mapped Use mapped symbol files if supported on this system.\n\ + --readnow Fully read symbol files on first access.\n\ +", gdb_stdout); +#ifdef ADDITIONAL_OPTION_HELP + fputs_unfiltered (ADDITIONAL_OPTION_HELP, gdb_stdout); +#endif + fputs_unfiltered ("\n\ +For more information, type \"help\" from within GDB, or consult the\n\ +GDB manual (available as on-line info or a printed manual).\n", gdb_stdout); + exit (0); + } + if (!quiet) { /* Print all the junk at the top, with trailing "..." if we are about to read a symbol file (possibly slowly). */ print_gnu_advertisement (); - print_gdb_version (); + print_gdb_version (gdb_stdout); if (symarg) printf_filtered (".."); wrap_here(""); - fflush (stdout); /* Force to screen during slow operations */ + gdb_flush (gdb_stdout); /* Force to screen during slow operations */ } error_pre_print = "\n\n"; + /* We may get more than one warning, don't double space all of them... */ + warning_pre_print = "\nwarning: "; + + /* We need a default language for parsing expressions, so simple things like + "set width 0" won't fail if no language is explicitly set in a config file + or implicitly set by reading an executable during startup. */ + set_language (language_c); + expected_language = current_language; /* don't warn about the change. */ + + /* Read and execute $HOME/.gdbinit file, if it exists. This is done + *before* all the command line arguments are processed; it sets + global parameters, which are independent of what file you are + debugging or what directory you are in. */ + homedir = getenv ("HOME"); + if (homedir) + { + homeinit = (char *) alloca (strlen (getenv ("HOME")) + + strlen (gdbinit) + 10); + strcpy (homeinit, getenv ("HOME")); + strcat (homeinit, "/"); + strcat (homeinit, gdbinit); + if (!inhibit_gdbinit && access (homeinit, R_OK) == 0) + { + if (!SET_TOP_LEVEL ()) + source_command (homeinit, 0); + } + do_cleanups (ALL_CLEANUPS); + /* Do stats; no need to do them elsewhere since we'll only + need them if homedir is set. Make sure that they are + zero in case one of them fails (this guarantees that they + won't match if either exists). */ + + memset (&homebuf, 0, sizeof (struct stat)); + memset (&cwdbuf, 0, sizeof (struct stat)); + + stat (homeinit, &homebuf); + stat (gdbinit, &cwdbuf); /* We'll only need this if + homedir was set. */ + } + /* 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 (dirarg); + free ((PTR)dirarg); do_cleanups (ALL_CLEANUPS); if (execarg != NULL && symarg != NULL - && strcmp (execarg, symarg) == 0) + && STREQ (execarg, symarg)) { /* 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); @@ -588,10 +885,10 @@ GDB manual (available as on-line info or a printed manual).\n", stderr); 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); @@ -602,37 +899,17 @@ GDB manual (available as on-line info or a printed manual).\n", stderr); if (!quiet) printf_filtered ("\n"); error_pre_print = "\n"; - - /* Set the initial language. */ - { - extern enum language deduce_language_from_filename (); - extern struct partial_symtab *find_main_psymtab (); - struct partial_symtab *pst = find_main_psymtab (); - enum language lang = language_unknown; - if (pst == NULL) ; -#if 0 - /* A better solution would set the language when reading the psymtab. - This would win for symbol file formats that encode the langauge, - such as dwarf. But, we don't do that yet. FIXME */ - else if (pst->language != language_unknown) - lang = pst->language; -#endif - else if (pst->filename != NULL) - lang = deduce_language_from_filename (pst->filename); - if (lang == language_unknown) /* Make C the default language */ - lang = language_c; - set_language (lang); - } + 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); @@ -642,64 +919,35 @@ GDB manual (available as on-line info or a printed manual).\n", stderr); /* Error messages should no longer be distinguished with extra output. */ error_pre_print = 0; + warning_pre_print = "warning: "; - { - struct stat homebuf, cwdbuf; - char *homedir, *homeinit; - - /* Read init file, if it exists in home directory */ - homedir = getenv ("HOME"); - if (homedir) + /* Read the .gdbinit file in the current directory, *if* it isn't + the same as the $HOME/.gdbinit file (it should exist, also). */ + + if (!homedir + || memcmp ((char *) &homebuf, (char *) &cwdbuf, sizeof (struct stat))) + if (!inhibit_gdbinit && access (gdbinit, R_OK) == 0) { - homeinit = (char *) alloca (strlen (getenv ("HOME")) + - strlen (gdbinit) + 10); - strcpy (homeinit, getenv ("HOME")); - strcat (homeinit, "/"); - strcat (homeinit, gdbinit); - if (!inhibit_gdbinit && access (homeinit, R_OK) == 0) - if (!setjmp (to_top_level)) - source_command (homeinit, 0); - do_cleanups (ALL_CLEANUPS); - - /* Do stats; no need to do them elsewhere since we'll only - need them if homedir is set. Make sure that they are - zero in case one of them fails (this guarantees that they - won't match if either exists). */ - - bzero (&homebuf, sizeof (struct stat)); - bzero (&cwdbuf, sizeof (struct stat)); - - stat (homeinit, &homebuf); - stat (gdbinit, &cwdbuf); /* We'll only need this if - homedir was set. */ - } - - /* Read the input file in the current directory, *if* it isn't - the same file (it should exist, also). */ - - if (!homedir - || bcmp ((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); - } + } + do_cleanups (ALL_CLEANUPS); for (i = 0; i < ncmd; i++) - if (!setjmp (to_top_level)) - { - if (cmdarg[i][0] == '-' && cmdarg[i][1] == '\0') - read_command_file (stdin); - else - source_command (cmdarg[i], !batch); - do_cleanups (ALL_CLEANUPS); - } - free (cmdarg); + { + if (!SET_TOP_LEVEL ()) + { + if (cmdarg[i][0] == '-' && cmdarg[i][1] == '\0') + read_command_file (stdin); + else + source_command (cmdarg[i], !batch); + do_cleanups (ALL_CLEANUPS); + } + } + free ((PTR)cmdarg); /* Read in the old history after all the command files have been read. */ - initialize_history(); + init_history(); if (batch) { @@ -718,7 +966,7 @@ GDB manual (available as on-line info or a printed manual).\n", stderr); while (1) { - if (!setjmp (to_top_level)) + if (!SET_TOP_LEVEL ()) { do_cleanups (ALL_CLEANUPS); /* Do complete cleanup */ command_loop (); @@ -728,6 +976,34 @@ GDB manual (available as on-line info or a printed manual).\n", stderr); /* No exit -- exit is through quit_command. */ } +void +execute_user_command (c, args) + struct cmd_list_element *c; + char *args; +{ + register struct command_line *cmdlines; + struct cleanup *old_chain; + + if (args) + error ("User-defined commands cannot take arguments."); + + cmdlines = c->user_commands; + if (cmdlines == 0) + /* Null command */ + return; + + /* Set the instream to 0, indicating execution of a + user-defined function. */ + old_chain = make_cleanup (source_cleanup, instream); + instream = (FILE *) 0; + while (cmdlines) + { + execute_command (cmdlines->line, 0); + cmdlines = cmdlines->next; + } + do_cleanups (old_chain); +} + /* Execute the line P as a command. Pass FROM_TTY as second argument to the defining function. */ @@ -737,9 +1013,7 @@ execute_command (p, from_tty) int from_tty; { register struct cmd_list_element *c; - register struct command_line *cmdlines; register enum language flang; - static struct language_defn *saved_language = 0; static int warned = 0; free_all_values (); @@ -756,44 +1030,27 @@ execute_command (p, from_tty) c = lookup_cmd (&p, cmdlist, "", 0, 1); /* Pass null arg rather than an empty one. */ arg = *p ? p : 0; + + /* If this command has been hooked, run the hook first. */ + if (c->hook) + execute_user_command (c->hook, (char *)0); + if (c->class == class_user) - { - struct cleanup *old_chain; - - if (*p) - error ("User-defined commands cannot take arguments."); - cmdlines = c->user_commands; - if (cmdlines == 0) - /* Null command */ - return; - - /* Set the instream to 0, indicating execution of a - user-defined function. */ - old_chain = make_cleanup (source_cleanup, instream); - instream = (FILE *) 0; - while (cmdlines) - { - execute_command (cmdlines->line, 0); - cmdlines = cmdlines->next; - } - do_cleanups (old_chain); - } + 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 == NO_FUNCTION) + else if (c->function.cfunc == NO_FUNCTION) error ("That is not a command, just a help topic."); else - (*c->function) (arg, from_tty & caution); + (*c->function.cfunc) (arg, from_tty & caution); } /* Tell the user if the language has changed (except first time). */ - if (current_language != saved_language) + if (current_language != expected_language) { if (language_mode == language_mode_auto) { - if (saved_language) - language_info (); + language_info (1); /* Print what changed. */ } - saved_language = current_language; warned = 0; } @@ -816,7 +1073,7 @@ execute_command (p, from_tty) } /* ARGSUSED */ -void +static void command_loop_marker (foo) int foo; { @@ -824,7 +1081,7 @@ command_loop_marker (foo) /* Read commands from `instream' and execute them until end of file or error reading instream. */ -void +static void command_loop () { struct cleanup *old_chain; @@ -840,7 +1097,7 @@ command_loop () if (instream == stdin && stdin_is_tty) reinitialize_more_filter (); old_chain = make_cleanup (command_loop_marker, 0); - command = command_line_input (instream == stdin ? prompt : 0, + command = command_line_input (instream == stdin ? prompt : (char *) NULL, instream == stdin); if (command == 0) return; @@ -881,8 +1138,11 @@ gdb_readline (prrompt) if (prrompt) { - printf (prrompt); - fflush (stdout); + /* Don't use a _filtered function here. It causes the assumed + character position to be off, since the newline we read from + the user is not accounted for. */ + fputs_unfiltered (prrompt, gdb_stdout); + gdb_flush (gdb_stdout); } result = (char *) xmalloc (result_size); @@ -895,6 +1155,11 @@ gdb_readline (prrompt) if (c == EOF) { + if (input_index > 0) + /* The last line does not end with a newline. Return it, and + if we are called again fgetc will still return EOF and + we'll return NULL then. */ + break; free (result); return NULL; } @@ -914,9 +1179,6 @@ gdb_readline (prrompt) return result; } -/* Declaration for fancy readline with command line editing. */ -char *readline (); - /* Variables which control command line editing and history substitution. These variables are given default values at the end of this file. */ @@ -926,9 +1188,34 @@ static int write_history_p; static int history_size; static char *history_filename; +/* readline uses the word breaks for two things: + (1) In figuring out where to point the TEXT parameter to the + rl_completion_entry_function. Since we don't use TEXT for much, + it doesn't matter a lot what the word breaks are for this purpose, but + it does affect how much stuff M-? lists. + (2) If one of the matches contains a word break character, readline + will quote it. That's why we switch between + gdb_completer_word_break_characters and + gdb_completer_command_word_break_characters. I'm not sure when + we need this behavior (perhaps for funky characters in C++ symbols?). */ + /* Variables which are necessary for fancy command line editing. */ char *gdb_completer_word_break_characters = - " \t\n!@#$%^&*()-+=|~`}{[]\"';:?/>.<,"; + " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,-"; + +/* When completing on command names, we remove '-' from the list of + word break characters, since we use it in command names. If the + readline library sees one in any of the current completion strings, + it thinks that the string needs to be quoted and automatically supplies + a leading quote. */ +char *gdb_completer_command_word_break_characters = + " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,"; + +/* Characters that can be used to quote completion strings. Note that we + can't include '"' because the gdb C parser treats such quoted sequences + as strings. */ +char *gdb_completer_quote_characters = + "'"; /* Functions that are used as part of the fancy command line editing. */ @@ -936,152 +1223,387 @@ char *gdb_completer_word_break_characters = but don't want to complete on anything else either. */ /* ARGSUSED */ char ** -noop_completer (text) +noop_completer (text, prefix) char *text; + char *prefix; { return NULL; } -/* Generate symbol names one by one for the completer. If STATE is - zero, then we need to initialize, otherwise the initialization has - already taken place. TEXT is what we expect the symbol to start - with. RL_LINE_BUFFER is available to be looked at; it contains the - entire text of the line. RL_POINT is the offset in that line of - the cursor. You should pretend that the line ends at RL_POINT. - The result is NULL if there are no more completions, else a char - string which is a possible completion. */ -char * -symbol_completion_function (text, state) +/* Complete on filenames. */ +char ** +filename_completer (text, word) + char *text; + char *word; +{ + /* 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 *)); + } + if (p == NULL) + { + return_val[return_val_used++] = p; + break; + } + /* Like emacs, don't complete on old versions. Especially useful + in the "source" command. */ + if (p[strlen (p) - 1] == '~') + continue; + + { + char *q; + if (word == text) + /* Return exactly p. */ + return_val[return_val_used++] = p; + else if (word > text) + { + /* Return some portion of p. */ + q = xmalloc (strlen (p) + 5); + strcpy (q, p + (word - text)); + return_val[return_val_used++] = q; + free (p); + } + else + { + /* Return some of TEXT plus p. */ + 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); + } + } + subsequent_name = 1; + } +#if 0 + /* There is no way to do this just long enough to affect quote inserting + without also affecting the next completion. This should be fixed in + readline. FIXME. */ + /* Insure that readline does the right thing + with respect to inserting quotes. */ + rl_completer_word_break_characters = ""; +#endif + return return_val; +} + +/* Here are some useful test cases for completion. FIXME: These should + be put in the test suite. They should be tested with both M-? and TAB. + + "show output-" "radix" + "show output" "-radix" + "p" ambiguous (commands starting with p--path, print, printf, etc.) + "p " ambiguous (all symbols) + "info t foo" no completions + "info t " no completions + "info t" ambiguous ("info target", "info terminal", etc.) + "info ajksdlfk" no completions + "info ajksdlfk " no completions + "info" " " + "info " ambiguous (all info commands) + "p \"a" no completions (string constant) + "p 'a" ambiguous (all symbols starting with a) + "p b-a" ambiguous (all symbols starting with a) + "p b-" ambiguous (all symbols) + "file Make" "file" (word break hard to screw up here) + "file ../gdb.stabs/we" "ird" (needs to not break word at slash) + */ + +/* Generate completions one by one for the completer. Each time we are + called return another potential completion to the caller. The function + is misnamed; it just completes on commands or passes the buck to the + command's completer function; the stuff specific to symbol completion + is in make_symbol_completion_list. + + TEXT is readline's idea of the "word" we are looking at; we don't really + like readline's ideas about word breaking so we ignore it. + + MATCHES is the number of matches that have currently been collected from + calling this completion function. When zero, then we need to initialize, + otherwise the initialization has already taken place and we can just + return the next potential completion string. + + Returns NULL if there are no more completions, else a pointer to a string + which is a possible completion. + + RL_LINE_BUFFER is available to be looked at; it contains the entire text + of the line. RL_POINT is the offset in that line of the cursor. You + should pretend that the line ends at RL_POINT. */ + +static char * +symbol_completion_function (text, matches) char *text; - int state; + int matches; { - static char **list = (char **)NULL; - static int index; - char *output; - extern char *rl_line_buffer; - extern int rl_point; + static char **list = (char **)NULL; /* Cache of completions */ + static int index; /* Next cached completion */ + char *output = NULL; char *tmp_command, *p; + /* Pointer within tmp_command which corresponds to text. */ + char *word; struct cmd_list_element *c, *result_list; - if (!state) + if (matches == 0) { - /* Free the storage used by LIST, but not by the strings inside. This is - because rl_complete_internal () frees the strings. */ + /* The caller is beginning to accumulate a new set of completions, so + we need to find all of them now, and cache them for returning one at + a time on future calls. */ + if (list) - free (list); + { + /* Free the storage used by LIST, but not by the strings inside. + This is because rl_complete_internal () frees the strings. */ + free ((PTR)list); + } list = 0; index = 0; - /* Decide whether to complete on a list of gdb commands or on - symbols. */ + /* Choose the default set of word break characters to break completions. + If we later find out that we are doing completions on command strings + (as opposed to strings supplied by the individual command completer + functions, which can be any string) then we will switch to the + special word break set for command strings, which leaves out the + '-' character used in some commands. */ + + rl_completer_word_break_characters = + gdb_completer_word_break_characters; + + /* Decide whether to complete on a list of gdb commands or on symbols. */ tmp_command = (char *) alloca (rl_point + 1); p = tmp_command; - + strncpy (tmp_command, rl_line_buffer, rl_point); tmp_command[rl_point] = '\0'; + /* Since text always contains some number of characters leading up + to rl_point, we can find the equivalent position in tmp_command + by subtracting that many characters from the end of tmp_command. */ + word = tmp_command + rl_point - strlen (text); if (rl_point == 0) { - /* An empty line we want to consider ambiguous; that is, - it could be any command. */ + /* An empty line we want to consider ambiguous; that is, it + could be any command. */ c = (struct cmd_list_element *) -1; result_list = 0; } else - c = lookup_cmd_1 (&p, cmdlist, &result_list, 1); + { + c = lookup_cmd_1 (&p, cmdlist, &result_list, 1); + } /* Move p up to the next interesting thing. */ while (*p == ' ' || *p == '\t') - p++; + { + p++; + } if (!c) - /* He's typed something unrecognizable. Sigh. */ - list = (char **) 0; + { + /* It is an unrecognized command. So there are no + possible completions. */ + list = NULL; + } else if (c == (struct cmd_list_element *) -1) { - /* If we didn't recognize everything up to the thing that - needs completing, and we don't know what command it is - yet, we are in trouble. Part of the trouble might be - that the list of delimiters used by readline includes - '-', which we use in commands. Check for this. */ - if (p + strlen(text) != tmp_command + rl_point) { - if (tmp_command[rl_point - strlen(text) - 1] == '-') - text = p; - else { - /* This really should not produce an error. Better would - be to pretend to hit RETURN here; this would produce a - response like "Ambiguous command: foo, foobar, etc", - and leave the line available for re-entry with ^P. Instead, - this error blows away the user's typed input without - any way to get it back. */ - error (" Unrecognized command."); + char *q; + + /* lookup_cmd_1 advances p up to the first ambiguous thing, but + doesn't advance over that thing itself. Do so now. */ + q = p; + while (*q && (isalnum (*q) || *q == '-' || *q == '_')) + ++q; + if (q != tmp_command + rl_point) + { + /* There is something beyond the ambiguous + command, so there are no possible completions. For + example, "info t " or "info t foo" does not complete + to anything, because "info t" can be "info target" or + "info terminal". */ + list = NULL; } - } - - /* He's typed something ambiguous. This is easier. */ - if (result_list) - list = complete_on_cmdlist (*result_list->prefixlist, text); else - list = complete_on_cmdlist (cmdlist, text); + { + /* We're trying to complete on the command which was ambiguous. + This we can deal with. */ + if (result_list) + { + list = complete_on_cmdlist (*result_list->prefixlist, p, + word); + } + else + { + list = complete_on_cmdlist (cmdlist, p, word); + } + /* Insure that readline does the right thing with respect to + inserting quotes. */ + rl_completer_word_break_characters = + gdb_completer_command_word_break_characters; + } } else { - /* If we've gotten this far, gdb has recognized a full - command. There are several possibilities: - - 1) We need to complete on the command. - 2) We need to complete on the possibilities coming after - the command. - 2) We need to complete the text of what comes after the - command. */ - - if (!*p && *text) - /* Always (might be longer versions of thie command). */ - list = complete_on_cmdlist (result_list, text); - else if (!*p && !*text) + /* We've recognized a full command. */ + + if (p == tmp_command + rl_point) { - if (c->prefixlist) - list = complete_on_cmdlist (*c->prefixlist, ""); + /* There is no non-whitespace in the line beyond the command. */ + + if (p[-1] == ' ' || p[-1] == '\t') + { + /* The command is followed by whitespace; we need to complete + on whatever comes after command. */ + if (c->prefixlist) + { + /* It is a prefix command; what comes after it is + a subcommand (e.g. "info "). */ + list = complete_on_cmdlist (*c->prefixlist, p, word); + + /* Insure that readline does the right thing + with respect to inserting quotes. */ + rl_completer_word_break_characters = + gdb_completer_command_word_break_characters; + } + else + { + /* It is a normal command; what comes after it is + completed by the command's completer function. */ + list = (*c->completer) (p, word); + } + } else - list = (*c->completer) (""); + { + /* The command is not followed by whitespace; we need to + complete on the command itself. e.g. "p" which is a + command itself but also can complete to "print", "ptype" + etc. */ + char *q; + + /* Find the command we are completing on. */ + 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); + + /* Insure that readline does the right thing + with respect to inserting quotes. */ + rl_completer_word_break_characters = + gdb_completer_command_word_break_characters; + } } else { + /* There is non-whitespace beyond the command. */ + if (c->prefixlist && !c->allow_unknown) { -#if 0 - /* Something like "info adsfkdj". But error() is not - the proper response; just return no completions - instead. */ - *p = '\0'; - error ("\"%s\" command requires a subcommand.", - tmp_command); -#else + /* It is an unrecognized subcommand of a prefix command, + e.g. "info adsfkdj". */ list = NULL; -#endif } else - list = (*c->completer) (text); + { + /* It is a normal command. */ + list = (*c->completer) (p, word); + } } } } - /* If the debugged program wasn't compiled with symbols, or if we're - clearly completing on a command and no command matches, return - NULL. */ - if (!list) - return ((char *)NULL); + /* If we found a list of potential completions during initialization then + dole them out one at a time. The vector of completions is NULL + terminated, so after returning the last one, return NULL (and continue + to do so) each time we are called after that, until a new list is + available. */ + + if (list) + { + output = list[index]; + if (output) + { + index++; + } + } - output = list[index]; - if (output) - index++; +#if 0 + /* Can't do this because readline hasn't yet checked the word breaks + for figuring out whether to insert a quote. */ + if (output == NULL) + /* Make sure the word break characters are set back to normal for the + next time that readline tries to complete something. */ + rl_completer_word_break_characters = + gdb_completer_word_break_characters; +#endif return (output); } + +/* Skip over a possibly quoted word (as defined by the quote characters + and word break characters the completer uses). Returns pointer to the + location after the "word". */ + +char * +skip_quoted (str) + char *str; +{ + char quote_char = '\0'; + char *scan; + + for (scan = str; *scan != '\0'; scan++) + { + if (quote_char != '\0') + { + /* Ignore everything until the matching close quote char */ + if (*scan == quote_char) + { + /* Found matching close quote. */ + scan++; + break; + } + } + else if (strchr (gdb_completer_quote_characters, *scan)) + { + /* Found start of a quoted string. */ + quote_char = *scan; + } + else if (strchr (gdb_completer_word_break_characters, *scan)) + { + break; + } + } + return (scan); +} + #ifdef STOP_SIGNAL static void -stop_sig () +stop_sig (signo) +int signo; { #if STOP_SIGNAL == SIGTSTP signal (SIGTSTP, SIG_DFL); @@ -1091,8 +1613,8 @@ stop_sig () #else signal (STOP_SIGNAL, stop_sig); #endif - printf ("%s", prompt); - fflush (stdout); + printf_unfiltered ("%s", prompt); + gdb_flush (gdb_stdout); /* Forget about any previous command -- null line now will do nothing. */ dont_repeat (); @@ -1101,15 +1623,14 @@ stop_sig () /* Initialize signal handlers. */ static void -do_nothing () +do_nothing (signo) +int signo; { } static void init_signals () { - extern void request_quit (); - signal (SIGINT, request_quit); /* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get @@ -1124,6 +1645,10 @@ init_signals () if (signal (SIGHUP, do_nothing) != SIG_IGN) signal (SIGHUP, disconnect); signal (SIGFPE, float_handler); + +#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) + signal (SIGWINCH, SIGWINCH_HANDLER); +#endif } /* Read one line from the command input stream `instream' @@ -1147,7 +1672,7 @@ command_line_input (prrompt, repeat) int repeat; { static char *linebuffer = 0; - static int linelength = 0; + static unsigned linelength = 0; register char *p; char *p1; char *rl; @@ -1168,17 +1693,29 @@ command_line_input (prrompt, repeat) since it should not wait until the user types a newline. */ immediate_quit++; #ifdef STOP_SIGNAL - signal (STOP_SIGNAL, stop_sig); + if (job_control) + signal (STOP_SIGNAL, stop_sig); #endif while (1) { - /* Reports are that some Sys V's don't flush stdout/err on reads + /* Reports are that some Sys V's don't flush gdb_stdout/err on reads from stdin, when stdin/out are sockets rather than ttys. So we have to do it ourselves, to make emacs-gdb and xxgdb work. On other machines, doing this once per input should be a cheap nop. */ - fflush (stdout); - fflush (stderr); + 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; + } /* Don't use fancy stuff if not talking to stdin. */ if (command_editing_p && instream == stdin @@ -1215,7 +1752,8 @@ command_line_input (prrompt, repeat) } #ifdef STOP_SIGNAL - signal (SIGTSTP, SIG_DFL); + if (job_control) + signal (STOP_SIGNAL, SIG_DFL); #endif immediate_quit--; @@ -1234,7 +1772,7 @@ command_line_input (prrompt, repeat) if (expanded) { /* Print the changes. */ - printf ("%s\n", history_value); + printf_unfiltered ("%s\n", history_value); /* If there was an error, call this function again. */ if (expanded < 0) @@ -1341,7 +1879,7 @@ read_command_lines () while (1) { dont_repeat (); - p = command_line_input (0, instream == stdin); + p = command_line_input ((char *) NULL, instream == stdin); if (p == NULL) /* Treat end of file like "end". */ break; @@ -1396,7 +1934,7 @@ free_command_lines (lptr) { next = l->next; free (l->line); - free (l); + free ((PTR)l); l = next; } } @@ -1406,7 +1944,7 @@ free_command_lines (lptr) void add_info (name, fun, doc) char *name; - void (*fun) (); + void (*fun) PARAMS ((char *, int)); char *doc; { add_cmd (name, no_class, fun, doc, &infolist); @@ -1432,8 +1970,38 @@ info_command (arg, from_tty) char *arg; int from_tty; { - printf ("\"info\" must be followed by the name of an info command.\n"); - help_list (infolist, "info ", -1, stdout); + printf_unfiltered ("\"info\" must be followed by the name of an info command.\n"); + help_list (infolist, "info ", -1, gdb_stdout); +} + +/* The "complete" command is used by Emacs to implement completion. */ + +/* ARGSUSED */ +static void +complete_command (arg, from_tty) + char *arg; + int from_tty; +{ + int i; + char *completion; + + dont_repeat (); + + if (arg == NULL) + { + rl_line_buffer[0] = '\0'; + rl_point = 0; + } + else + { + strcpy (rl_line_buffer, arg); + rl_point = strlen (arg); + } + + for (completion = symbol_completion_function (rl_line_buffer, i = 0); + completion; + completion = symbol_completion_function (rl_line_buffer, ++i)) + printf_unfiltered ("%s\n", completion); } /* The "show" command with no arguments shows all the settings. */ @@ -1453,7 +2021,7 @@ void add_com (name, class, fun, doc) char *name; enum command_class class; - void (*fun) (); + void (*fun) PARAMS ((char *, int)); char *doc; { add_cmd (name, class, fun, doc, &cmdlist); @@ -1484,7 +2052,7 @@ help_command (command, from_tty) char *command; int from_tty; /* Ignored */ { - help_cmd (command, stdout); + help_cmd (command, gdb_stdout); } static void @@ -1499,30 +2067,36 @@ validate_comname (comname) p = comname; while (*p) { - if (!(*p >= 'A' && *p <= 'Z') - && !(*p >= 'a' && *p <= 'z') - && !(*p >= '0' && *p <= '9') - && *p != '-') + if (!isalnum(*p) && *p != '-') error ("Junk in argument list: \"%s\"", p); p++; } } +/* This is just a placeholder in the command data structures. */ +static void +user_defined_command (ignore, from_tty) + char *ignore; + int from_tty; +{ +} + static void define_command (comname, from_tty) char *comname; int from_tty; { register struct command_line *cmds; - register struct cmd_list_element *c, *newc; + register struct cmd_list_element *c, *newc, *hookc = 0; char *tem = comname; - extern void not_just_help_class_command (); +#define HOOK_STRING "hook-" +#define HOOK_LEN 5 validate_comname (comname); /* Look it up, and verify that we got an exact match. */ c = lookup_cmd (&tem, cmdlist, "", -1, 1); - if (c && 0 != strcmp (comname, c->name)) + if (c && !STREQ (comname, c->name)) c = 0; if (c) @@ -1531,27 +2105,61 @@ define_command (comname, from_tty) tem = "Redefine command \"%s\"? "; else tem = "Really redefine built-in command \"%s\"? "; - if (!query (tem, comname)) - error ("Command \"%s\" not redefined.", comname); + if (!query (tem, c->name)) + error ("Command \"%s\" not redefined.", c->name); } + /* If this new command is a hook, then mark the command which it + is hooking. Note that we allow hooking `help' commands, so that + we can hook the `stop' pseudo-command. */ + + if (!strncmp (comname, HOOK_STRING, HOOK_LEN)) + { + /* Look up cmd it hooks, and verify that we got an exact match. */ + tem = comname+HOOK_LEN; + hookc = lookup_cmd (&tem, cmdlist, "", -1, 0); + if (hookc && !STREQ (comname+HOOK_LEN, hookc->name)) + hookc = 0; + if (!hookc) + { + warning ("Your new `%s' command does not hook any existing command.", + comname); + if (!query ("Proceed? ", (char *)0)) + error ("Not confirmed."); + } + } + + comname = savestring (comname, strlen (comname)); + + /* If the rest of the commands will be case insensitive, this one + should behave in the same manner. */ + for (tem = comname; *tem; tem++) + if (isupper(*tem)) *tem = tolower(*tem); + if (from_tty) { - printf ("Type commands for definition of \"%s\".\n\ + printf_unfiltered ("Type commands for definition of \"%s\".\n\ End with a line saying just \"end\".\n", comname); - fflush (stdout); + gdb_flush (gdb_stdout); } - comname = savestring (comname, strlen (comname)); cmds = read_command_lines (); if (c && c->class == class_user) free_command_lines (&c->user_commands); - newc = add_cmd (comname, class_user, not_just_help_class_command, + 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 this new command is a hook, then mark both commands as being + tied. */ + if (hookc) + { + hookc->hook = newc; /* Target gets hooked. */ + newc->hookee = hookc; /* We are marked as hooking target cmd. */ + } } static void @@ -1571,7 +2179,7 @@ document_command (comname, from_tty) error ("Command \"%s\" is built-in.", comname); if (from_tty) - printf ("Type documentation for \"%s\".\n\ + printf_unfiltered ("Type documentation for \"%s\".\n\ End with a line saying just \"end\".\n", comname); doclines = read_command_lines (); @@ -1602,7 +2210,7 @@ End with a line saying just \"end\".\n", comname); static void print_gnu_advertisement() { - printf ("\ + printf_unfiltered ("\ GDB is free software and you are welcome to distribute copies of it\n\ under certain conditions; type \"show copying\" to see the conditions.\n\ There is absolutely no warranty for GDB; type \"show warranty\" for details.\n\ @@ -1610,11 +2218,18 @@ There is absolutely no warranty for GDB; type \"show warranty\" for details.\n\ } static void -print_gdb_version () +print_gdb_version (stream) + GDB_FILE *stream; { - printf_filtered ("\ -GDB %s, Copyright 1991 Free Software Foundation, Inc.", - version); + fprintf_filtered (stream, "\ +GDB %s (%s", version, host_name); + + if (!STREQ (host_name, target_name)) + fprintf_filtered (stream, " --target %s", target_name); + + fprintf_filtered (stream, "), "); + wrap_here(""); + fprintf_filtered (stream, "Copyright 1994 Free Software Foundation, Inc."); } /* ARGSUSED */ @@ -1625,7 +2240,7 @@ show_version (args, from_tty) { immediate_quit++; print_gnu_advertisement (); - print_gdb_version (); + print_gdb_version (gdb_stdout); printf_filtered ("\n"); immediate_quit--; } @@ -1635,8 +2250,8 @@ show_version (args, from_tty) void print_prompt () { - printf ("%s", prompt); - fflush (stdout); + printf_unfiltered ("%s", prompt); + gdb_flush (gdb_stdout); } static void @@ -1646,23 +2261,38 @@ quit_command (args, from_tty) { if (inferior_pid != 0 && target_has_execution) { - if (query ("The program is running. Quit anyway? ")) + if (attach_flag) { - target_kill (args, from_tty); + if (query ("The program is running. Quit anyway (and detach it)? ")) + target_detach (args, from_tty); + else + error ("Not confirmed."); } else - error ("Not confirmed."); + { + if (query ("The program is running. Quit anyway (and kill it)? ")) + target_kill (); + else + error ("Not confirmed."); + } } + /* UDI wants this, to kill the TIP. */ + target_close (1); + /* Save the history information if it is appropriate to do so. */ if (write_history_p && history_filename) write_history (history_filename); + exit (0); } +/* Returns whether GDB is running on a terminal and whether the user + desires that questions be asked of them on that terminal. */ + int input_from_terminal_p () { - return (instream == stdin) & caution; + return gdb_has_a_terminal () && (instream == stdin) & caution; } /* ARGSUSED */ @@ -1672,13 +2302,13 @@ pwd_command (args, from_tty) int from_tty; { if (args) error ("The \"pwd\" command does not take an argument: %s", args); - getwd (dirbuf); + getcwd (dirbuf, sizeof (dirbuf)); - if (strcmp (dirbuf, current_directory)) - printf ("Working directory %s\n (canonically %s).\n", + if (!STREQ (dirbuf, current_directory)) + printf_unfiltered ("Working directory %s\n (canonically %s).\n", current_directory, dirbuf); else - printf ("Working directory %s.\n", current_directory); + printf_unfiltered ("Working directory %s.\n", current_directory); } static void @@ -1687,7 +2317,9 @@ cd_command (dir, from_tty) int from_tty; { int len; - int change; + /* Found something other than leading repetitions of "/..". */ + int found_real_path; + char *p; /* If the new directory is absolute, repeat is a no-op; if relative, repeat might be useful but is more likely to be a mistake. */ @@ -1699,54 +2331,87 @@ cd_command (dir, from_tty) dir = tilde_expand (dir); make_cleanup (free, dir); + if (chdir (dir) < 0) + perror_with_name (dir); + len = strlen (dir); dir = savestring (dir, len - (len > 1 && dir[len-1] == '/')); if (dir[0] == '/') current_directory = dir; else { - current_directory = concat (current_directory, "/", dir, NULL); + if (current_directory[0] == '/' && current_directory[1] == '\0') + current_directory = concat (current_directory, dir, NULL); + else + current_directory = concat (current_directory, "/", dir, NULL); free (dir); } /* Now simplify any occurrences of `.' and `..' in the pathname. */ - change = 1; - while (change) + found_real_path = 0; + for (p = current_directory; *p;) { - char *p; - change = 0; - - for (p = current_directory; *p;) + if (p[0] == '/' && p[1] == '.' && (p[2] == 0 || p[2] == '/')) + strcpy (p, p + 2); + else if (p[0] == '/' && p[1] == '.' && p[2] == '.' + && (p[3] == 0 || p[3] == '/')) { - if (!strncmp (p, "/./", 2) - && (p[2] == 0 || p[2] == '/')) - strcpy (p, p + 2); - else if (!strncmp (p, "/..", 3) - && (p[3] == 0 || p[3] == '/') - && p != current_directory) + if (found_real_path) { + /* Search backwards for the directory just before the "/.." + and obliterate it and the "/..". */ char *q = p; - while (q != current_directory && q[-1] != '/') q--; - if (q != current_directory) + while (q != current_directory && q[-1] != '/') + --q; + + if (q == current_directory) + /* current_directory is + a relative pathname ("can't happen"--leave it alone). */ + ++p; + else { - strcpy (q-1, p+3); - p = q-1; + strcpy (q - 1, p + 3); + p = q - 1; } } - else p++; + else + /* We are dealing with leading repetitions of "/..", for example + "/../..", which is the Mach super-root. */ + p += 3; + } + else + { + found_real_path = 1; + ++p; } } - if (chdir (dir) < 0) - perror_with_name (dir); - 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 (args) + 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; +} + /* ARGSUSED */ static void source_command (args, from_tty) @@ -1754,25 +2419,54 @@ source_command (args, from_tty) int from_tty; { FILE *stream; - struct cleanup *cleanups; + struct cleanup *old_cleanups; char *file = args; + struct source_cleanup_lines_args old_lines; + int needed_length; - if (file == 0) - /* Let source without arguments read .gdbinit. */ - file = gdbinit; + if (file == NULL) + { + error ("source command requires pathname of file to source."); + } file = tilde_expand (file); - make_cleanup (free, file); + old_cleanups = make_cleanup (free, file); - stream = fopen (file, "r"); + stream = fopen (file, FOPEN_RT); if (stream == 0) perror_with_name (file); - cleanups = make_cleanup (fclose, stream); + make_cleanup (fclose, 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); + /* This will get set every time we read a line. So it won't stay "" for + long. */ + 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 (cleanups); + do_cleanups (old_cleanups); } /* ARGSUSED */ @@ -1785,7 +2479,7 @@ echo_command (text, from_tty) register int c; if (text) - while (c = *p++) + while ((c = *p++) != '\0') { if (c == '\\') { @@ -1804,21 +2498,9 @@ echo_command (text, from_tty) /* Force this output to appear now. */ wrap_here (""); - fflush (stdout); + gdb_flush (gdb_stdout); } -/* ARGSUSED */ -static void -dump_me_command (args, from_tty) - char *args; - int from_tty; -{ - if (query ("Should GDB dump core? ")) - { - signal (SIGQUIT, SIG_DFL); - kill (getpid (), SIGQUIT); - } -} /* Functions to manipulate command line editing control variables. */ @@ -1840,23 +2522,7 @@ show_commands (args, from_tty) than the number of the last command). Relative to history_base. */ int hist_len; - struct _hist_entry *history_get(); - extern int history_base; - -#if 0 - /* This is all reported by individual "show" commands. */ - printf_filtered ("Interactive command editing is %s.\n", - command_editing_p ? "on" : "off"); - - printf_filtered ("History expansion of command input is %s.\n", - history_expansion_p ? "on" : "off"); - printf_filtered ("Writing of a history record upon exit is %s.\n", - write_history_p ? "enabled" : "disabled"); - printf_filtered ("The size of the history list (number of stored commands) is %d.\n", - history_size); - printf_filtered ("The name of the history record is \"%s\".\n\n", - history_filename ? history_filename : ""); -#endif /* 0 */ + extern HIST_ENTRY *history_get PARAMS ((int)); /* Print out some of the commands from the command history. */ /* First determine the length of the history list. */ @@ -1879,7 +2545,7 @@ show_commands (args, from_tty) /* "info editing " should print around command number . */ num = (parse_and_eval_address (args) - history_base) - Hist_print / 2; } - /* "info editing" means print the last Hist_print commands. */ + /* "show commands" means print the last Hist_print commands. */ else { num = hist_len - Hist_print; @@ -1897,14 +2563,6 @@ show_commands (args, from_tty) num = 0; } -#if 0 - /* No need for a header now that "info editing" only prints one thing. */ - if (num == hist_len - Hist_print) - printf_filtered ("The list of the last %d commands is:\n\n", Hist_print); - else - printf_filtered ("Some of the stored commands are:\n\n"); -#endif /* 0 */ - for (offset = num; offset < num + Hist_print && offset < hist_len; offset++) { printf_filtered ("%5d %s\n", history_base + offset, @@ -1916,8 +2574,8 @@ show_commands (args, from_tty) num += Hist_print; /* If the user repeats this command with return, it should do what - "info editing +" does. This is unnecessary if arg is null, - because "info editing +" is not useful after "info editing". */ + "show commands +" does. This is unnecessary if arg is null, + because "show commands +" is not useful after "show commands". */ if (from_tty && args) { args[0] = '+'; @@ -1933,10 +2591,15 @@ set_history_size_command (args, from_tty, c) int from_tty; struct cmd_list_element *c; { - if (history_size == UINT_MAX) + if (history_size == INT_MAX) unstifle_history (); - else + else if (history_size >= 0) stifle_history (history_size); + else + { + history_size = INT_MAX; + error ("History size must be non-negative"); + } } /* ARGSUSED */ @@ -1945,8 +2608,8 @@ set_history (args, from_tty) char *args; int from_tty; { - printf ("\"set history\" must be followed by the name of a history subcommand.\n"); - help_list (sethistlist, "set history ", -1, stdout); + printf_unfiltered ("\"set history\" must be followed by the name of a history subcommand.\n"); + help_list (sethistlist, "set history ", -1, gdb_stdout); } /* ARGSUSED */ @@ -1986,10 +2649,12 @@ set_verbose (args, from_tty, c) } static void -float_handler () +float_handler (signo) +int signo; { /* This message is based on ANSI C, section 4.7. Note that integer divide by zero causes this, so "float" is a misnomer. */ + signal (SIGFPE, float_handler); error ("Erroneous arithmetic operation."); } @@ -2002,19 +2667,29 @@ batch_mode () static void -initialize_cmd_lists () +init_cmd_lists () { - cmdlist = (struct cmd_list_element *) 0; - infolist = (struct cmd_list_element *) 0; - enablelist = (struct cmd_list_element *) 0; - disablelist = (struct cmd_list_element *) 0; - deletelist = (struct cmd_list_element *) 0; - enablebreaklist = (struct cmd_list_element *) 0; - setlist = (struct cmd_list_element *) 0; + cmdlist = NULL; + infolist = NULL; + enablelist = NULL; + disablelist = NULL; + deletelist = NULL; + enablebreaklist = NULL; + setlist = NULL; + unsetlist = NULL; showlist = NULL; - sethistlist = (struct cmd_list_element *) 0; + sethistlist = NULL; showhistlist = NULL; - unsethistlist = (struct cmd_list_element *) 0; + unsethistlist = NULL; +#if MAINTENANCE_CMDS + maintenancelist = NULL; + maintenanceinfolist = NULL; + maintenanceprintlist = NULL; +#endif + setprintlist = NULL; + showprintlist = NULL; + setchecklist = NULL; + showchecklist = NULL; } /* Init the history buffer. Note that we are called after the init file(s) @@ -2024,18 +2699,20 @@ initialize_cmd_lists () */ static void -initialize_history() +init_history() { char *tmpenv; - if (tmpenv = getenv ("HISTSIZE")) + tmpenv = getenv ("HISTSIZE"); + if (tmpenv) history_size = atoi (tmpenv); else if (!history_size) history_size = 256; stifle_history (history_size); - if (tmpenv = getenv ("GDBHISTFILE")) + tmpenv = getenv ("GDBHISTFILE"); + if (tmpenv) history_filename = savestring (tmpenv, strlen(tmpenv)); else if (!history_filename) { /* We include the current directory so that if the user changes @@ -2047,7 +2724,7 @@ initialize_history() } static void -initialize_main () +init_main () { struct cmd_list_element *c; @@ -2065,11 +2742,18 @@ initialize_main () /* Setup important stuff for command line editing. */ rl_completion_entry_function = (int (*)()) symbol_completion_function; rl_completer_word_break_characters = gdb_completer_word_break_characters; + rl_completer_quote_characters = gdb_completer_quote_characters; rl_readline_name = "gdb"; /* Define the classes of commands. They will appear in the help list in the reverse of this order. */ + 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\ @@ -2092,10 +2776,11 @@ The commands below can be used to select other frames by number or address.", 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, @@ -2123,17 +2808,18 @@ Use the \"document\" command to give documentation for the new command.\n\ 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."); @@ -2145,17 +2831,15 @@ when gdb is started."); "Set ", &setlist), add_show_from_set (c, &showlist); - c->function = set_verbose; + c->function.sfunc = set_verbose; set_verbose (NULL, 0, c); - add_com ("dump-me", class_obscure, dump_me_command, - "Get fatal error; make debugger dump its core."); - add_show_from_set (add_set_cmd ("editing", class_support, var_boolean, (char *)&command_editing_p, - "Set command line editing.\n\ + "Set editing of command lines as they are typed.\n\ Use \"on\" to enable to enable the editing, and \"off\" to disable it.\n\ -Without an argument, command line editing is enabled.", &setlist), +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_prefix_cmd ("history", class_support, set_history, @@ -2178,11 +2862,11 @@ Use \"on\" to enable 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_uinteger, (char *)&history_size, + 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 = set_history_size_command; + c->function.sfunc = set_history_size_command; add_show_from_set (add_set_cmd ("filename", no_class, var_filename, (char *)&history_filename, @@ -2198,19 +2882,41 @@ ie. the number of previous commands to keep a record of.", &sethistlist); &showlist); add_prefix_cmd ("info", class_info, info_command, - "Generic command for printing status.", + "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 set with \"set\".", + "Generic command for showing things about the debugger.", &showlist, "show ", 0, &cmdlist); /* Another way to get at the same thing. */ add_info ("set", show_command, "Show all GDB settings."); - add_cmd ("commands", no_class, show_commands, "Status of command editor.", + add_cmd ("commands", no_class, show_commands, + "Show the 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, - "Report what version of GDB this is.", &showlist); + "Show what version of GDB this is.", &showlist); + + /* If target is open when baud changes, it doesn't take effect until the + next open (I think, not sure). */ + 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); + + add_show_from_set ( + 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), + &showlist); }