-/* Top level for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
+/* Top level `main' program for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
-int fclose ();
#include "defs.h"
#include "gdbcmd.h"
-#include "param.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 "getopt.h"
#endif
#include <string.h>
+#ifndef NO_SYS_FILE
#include <sys/file.h>
+#endif
#include <setjmp.h>
#include <sys/param.h>
#include <sys/stat.h>
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 ((void));
+
+static void
+quit_command PARAMS ((char *, int));
+
+static void
+initialize_main PARAMS ((void));
+
+static void
+initialize_history PARAMS ((void));
+
+static void
+initialize_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
+dump_me_command 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
+do_nothing PARAMS ((int));
+
+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. */
extern char lang_frame_mismatch_warn[]; /* language.c */
+/* Whether GDB's stdin is on a terminal. */
+
+extern int gdb_has_a_terminal; /* inflow.c */
+
/* Flag for whether we want all the "from_tty" gubbish printed. */
int caution = 1; /* Default is yes, sigh. */
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 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_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;
#ifndef STOP_SIGNAL
#ifdef SIGTSTP
#define STOP_SIGNAL SIGTSTP
+static void stop_sig PARAMS ((int));
#endif
#endif
#define HAVE_SIGSETMASK !defined (USG)
#endif
-#if !HAVE_SIGSETMASK
+#if 0 == (HAVE_SIGSETMASK)
#define sigsetmask(n)
#endif
\f
jmp_buf to_top_level;
-void
+NORETURN void
return_to_top_level ()
{
quit_flag = 0;
immediate_quit = 0;
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 (to_top_level, 1);
}
/* Call FUNC with arg ARGS, catching any errors.
int
catch_errors (func, args, errstring)
- int (*func) ();
+ int (*func) PARAMS ((char *));
char *args;
char *errstring;
{
/* Handler for SIGHUP. */
static void
-disconnect ()
+disconnect (signo)
+int signo;
{
kill_inferior_fast ();
signal (SIGHUP, SIG_DFL);
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
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'},
+ {"quiet", no_argument, &quiet, 1},
+ {"q", 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'},
+ {"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)
/* After the symbol file has been read, print a newline to get us
beyond the copyright line... But errors should still set off
the error message with a (single) blank line. */
- printf_filtered ("\n");
+ if (!quiet)
+ printf_filtered ("\n");
error_pre_print = "\n";
+ /* Set the initial language. */
+ {
+ 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);
+ }
+
if (corearg != NULL)
if (!setjmp (to_top_level))
core_file_command (corearg, !batch);
}
free (cmdarg);
+ /* Read in the old history after all the command files have been read. */
+ initialize_history();
+
if (batch)
{
/* We have hit the end of the batch file. */
register struct cmd_list_element *c;
register struct command_line *cmdlines;
register enum language flang;
- static enum language current = language_unknown;
+ static const struct language_defn *saved_language = 0;
static int warned = 0;
free_all_values ();
}
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 */
- if (working_lang != current)
+ /* Tell the user if the language has changed (except first time). */
+ if (current_language != saved_language)
{
if (language_mode == language_mode_auto) {
- if (current != language_unknown)
- language_info ();
+ if (saved_language)
+ language_info (1); /* Print what changed. */
}
- current = working_lang;
+ saved_language = current_language;
warned = 0;
}
/* Warn the user if the working language does not match the
language of the current frame. Only warn the user if we are
actually running the program, i.e. there is a stack. */
+ /* FIXME: This should be cacheing the frame and only running when
+ the frame changes. */
if (target_has_stack)
{
- flang = get_frame_language();
- if(!warned && flang != language_unknown && flang != working_lang)
+ flang = get_frame_language ();
+ if (!warned
+ && flang != language_unknown
+ && flang != current_language->la_language)
{
printf_filtered ("%s\n", lang_frame_mismatch_warn);
warned = 1;
}
/* ARGSUSED */
-void
+static void
command_loop_marker (foo)
int 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;
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;
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. */
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 *
+
+static char *
symbol_completion_function (text, state)
char *text;
int state;
\f
#ifdef STOP_SIGNAL
static void
-stop_sig ()
+stop_sig (signo)
+int signo;
{
#if STOP_SIGNAL == SIGTSTP
signal (SIGTSTP, SIG_DFL);
/* 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
int repeat;
{
static char *linebuffer = 0;
- static int linelength = 0;
+ static unsigned linelength = 0;
register char *p;
char *p1;
char *rl;
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;
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);
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);
register struct command_line *cmds;
register struct cmd_list_element *c, *newc;
char *tem = comname;
- extern void not_just_help_class_command ();
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))
+ c = 0;
+
if (c)
{
if (c->class == class_user || c->class == class_alias)
{
printf ("\
GDB is free software and you are welcome to distribute copies of it\n\
- under certain conditions; type \"info copying\" to see the conditions.\n\
-There is absolutely no warranty for GDB; type \"info warranty\" for details.\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\
");
}
print_gdb_version ()
{
printf_filtered ("\
-GDB %s, Copyright 1991 Free Software Foundation, Inc.",
+GDB %s, Copyright 1992 Free Software Foundation, Inc.",
version);
}
{
if (query ("The program is running. Quit anyway? "))
{
- target_kill (args, from_tty);
+ target_kill ();
}
else
error ("Not confirmed.");
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;
}
\f
/* ARGSUSED */
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",
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);
+ current_directory = concat (current_directory, "/", dir, NULL);
free (dir);
}
}
}
- if (chdir (dir) < 0)
- perror_with_name (dir);
-
forget_cached_source_info ();
if (from_tty)
c = parse_escape (&p);
if (c >= 0)
- fputc (c, stdout);
+ printf_filtered ("%c", c);
}
else
- fputc (c, stdout);
+ printf_filtered ("%c", c);
}
+
+ /* Force this output to appear now. */
+ wrap_here ("");
fflush (stdout);
}
than the number of the last command). Relative to history_base. */
int hist_len;
- struct _hist_entry *history_get();
+ extern struct _hist_entry *history_get PARAMS ((int));
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 */
-
/* Print out some of the commands from the command history. */
/* First determine the length of the history list. */
hist_len = history_size;
/* "info editing <exp>" should print around command number <exp>. */
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;
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,
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] = '+';
}
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. */
unsethistlist = (struct cmd_list_element *) 0;
}
+/* Init the history buffer. Note that we are called after the init file(s)
+ * have been read so that the user can change the history file via his
+ * .gdbinit file (for instance). The GDBHISTFILE environment variable
+ * overrides all of this.
+ */
+
static void
-initialize_main ()
+initialize_history()
{
- struct cmd_list_element *c;
-
char *tmpenv;
-
-#ifdef DEFAULT_PROMPT
- prompt = savestring (DEFAULT_PROMPT, strlen(DEFAULT_PROMPT));
-#else
- prompt = savestring ("(gdb) ", 6);
-#endif
- /* Set the important stuff up for command editing. */
- command_editing_p = 1;
- history_expansion_p = 0;
- write_history_p = 0;
-
if (tmpenv = getenv ("HISTSIZE"))
history_size = atoi (tmpenv);
- else
+ else if (!history_size)
history_size = 256;
stifle_history (history_size);
if (tmpenv = getenv ("GDBHISTFILE"))
history_filename = savestring (tmpenv, strlen(tmpenv));
- else
+ else if (!history_filename) {
/* We include the current directory so that if the user changes
directories the file written will be the same as the one
that was read. */
- history_filename = concat (current_directory, "/.gdb_history", "");
-
+ history_filename = concat (current_directory, "/.gdb_history", NULL);
+ }
read_history (history_filename);
+}
+static void
+initialize_main ()
+{
+ struct cmd_list_element *c;
+
+#ifdef DEFAULT_PROMPT
+ prompt = savestring (DEFAULT_PROMPT, strlen(DEFAULT_PROMPT));
+#else
+ prompt = savestring ("(gdb) ", 6);
+#endif
+
+ /* Set the important stuff up for command editing. */
+ command_editing_p = 1;
+ history_expansion_p = 0;
+ write_history_p = 0;
+
/* 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;
"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,
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,
"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,
&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_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);
}