X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ftop.c;h=40955abe63d3a4e362cbdb40d210a13b2540ce9a;hb=96baa820df8126165bd3c4a33c561556b21203af;hp=766b240dfde014f5f6f867ce75c385819df26441;hpb=7aaec27bc740ff6c5a1377744ec0faac6edca74a;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/top.c b/gdb/top.c index 766b240dfd..40955abe63 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1,22 +1,23 @@ /* Top level stuff for GDB, the GNU debugger. - Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995 + Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. -This file is part of GDB. + This file is part of GDB. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ #include "defs.h" #include "gdbcmd.h" @@ -30,14 +31,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "expression.h" #include "value.h" #include "language.h" -#include "terminal.h" /* For job_control. */ +#include "terminal.h" /* For job_control. */ #include "annotate.h" -#include #include "top.h" /* readline include files */ -#include "readline.h" -#include "history.h" +#include +#include /* readline defines this. */ #undef savestring @@ -47,35 +47,43 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #endif +#include "event-loop.h" #include "gdb_string.h" -#ifndef NO_SYS_FILE -#include -#endif -#include #include "gdb_stat.h" #include -extern void initialize_targets PARAMS ((void)); +/* Prototypes for local functions */ -extern void initialize_utils PARAMS ((void)); +static void dont_repeat_command PARAMS ((char *, int)); -/* Prototypes for local functions */ +static void source_cleanup_lines PARAMS ((PTR)); -static char * line_completion_function PARAMS ((char *, int, char *, int)); +static void user_defined_command PARAMS ((char *, int)); -static char * readline_line_completion_function PARAMS ((char *, int)); +static void init_signals PARAMS ((void)); -static void command_loop_marker PARAMS ((int)); +#ifdef STOP_SIGNAL +static void stop_sig PARAMS ((int)); +#endif + +static char *line_completion_function PARAMS ((char *, int, char *, int)); + +static char *readline_line_completion_function PARAMS ((char *, int)); + +/* NOTE 1999-04-29: this function will be static again, after we make the + event loop be the default command loop for gdb, and we merge + event-top.c into this file, top.c */ +/* static */ void command_loop_marker PARAMS ((int)); static void while_command PARAMS ((char *, int)); static void if_command PARAMS ((char *, int)); static struct command_line * -build_command_line PARAMS ((enum command_control_type, char *)); + build_command_line PARAMS ((enum command_control_type, char *)); static struct command_line * -get_command_line PARAMS ((enum command_control_type, char *)); + get_command_line PARAMS ((enum command_control_type, char *)); static void realloc_body_list PARAMS ((struct command_line *, int)); @@ -84,11 +92,11 @@ static enum misc_command_type read_next_line PARAMS ((struct command_line **)); static enum command_control_type recurse_read_control_structure PARAMS ((struct command_line *)); -static struct cleanup * setup_user_args PARAMS ((char *)); +static struct cleanup *setup_user_args PARAMS ((char *)); -static char * locate_arg PARAMS ((char *)); +static char *locate_arg PARAMS ((char *)); -static char * insert_args PARAMS ((char *)); +static char *insert_args PARAMS ((char *)); static void arg_cleanup PARAMS ((void)); @@ -102,20 +110,6 @@ static void init_signals PARAMS ((void)); static void set_verbose PARAMS ((char *, int, struct cmd_list_element *)); -#ifdef TARGET_BYTE_ORDER_SELECTABLE - -static void set_endian PARAMS ((char *, int)); - -static void set_endian_big PARAMS ((char *, int)); - -static void set_endian_little PARAMS ((char *, int)); - -static void set_endian_auto PARAMS ((char *, int)); - -static void show_endian PARAMS ((char *, int)); - -#endif - static void show_history PARAMS ((char *, int)); static void set_history PARAMS ((char *, int)); @@ -147,9 +141,14 @@ static void complete_command PARAMS ((char *, int)); static void do_nothing PARAMS ((int)); -static int quit_cover PARAMS ((char *)); +#ifdef SIGHUP +/* NOTE 1999-04-29: This function will be static again, once we modify + gdb to use the event loop as the default command loop and we merge + event-top.c into this file, top.c */ +/* static */ int quit_cover PARAMS ((PTR)); static void disconnect PARAMS ((int)); +#endif static void source_cleanup PARAMS ((FILE *)); @@ -189,7 +188,7 @@ extern char lang_frame_mismatch_warn[]; /* language.c */ /* Flag for whether we want all the "from_tty" gubbish printed. */ -int caution = 1; /* Default is yes, sigh. */ +int caution = 1; /* Default is yes, sigh. */ /* Define all cmd_list_elements. */ @@ -209,6 +208,14 @@ struct cmd_list_element *enablelist; struct cmd_list_element *disablelist; +/* Chain containing all defined toggle subcommands. */ + +struct cmd_list_element *togglelist; + +/* Chain containing all defined stop subcommands. */ + +struct cmd_list_element *stoplist; + /* Chain containing all defined delete subcommands. */ struct cmd_list_element *deletelist; @@ -229,12 +236,6 @@ struct cmd_list_element *unsetlist; struct cmd_list_element *showlist; -#ifdef TARGET_BYTE_ORDER_SELECTABLE -/* Chain containing the \"set endian\" commands. */ - -struct cmd_list_element *endianlist; -#endif - /* Chain containing all defined \"set history\". */ struct cmd_list_element *sethistlist; @@ -249,21 +250,15 @@ struct cmd_list_element *unsethistlist; /* 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; @@ -275,7 +270,7 @@ 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. */ + executing a user-defined command or interacting via a GUI. */ FILE *instream; @@ -296,7 +291,8 @@ int epoch_interface; int xgdb_verbose; /* gdb prints this when reading a command interactively */ -static char *prompt; +static char *gdb_prompt_string; /* the global prompt string */ +extern char *get_prompt PARAMS ((void)); /* access function for prompt string */ /* Buffer used for reading command lines, and the size allocated for it so far. */ @@ -319,25 +315,37 @@ int server_command; int baud_rate = -1; +/* Timeout limit for response from target. */ + +int remote_timeout = 20; /* Set default to 20 */ + /* Non-zero tells remote* modules to output debugging info. */ int remote_debug = 0; +/* Non-zero means the target is running. Note: this is different from + saying that there is an active target and we are stopped at a + breakpoint, for instance. This is a real indicator whether the + target is off and running, which gdb is doing something else. */ +int target_executing = 0; + /* Level of control structure. */ static int control_level; /* Structure for arguments to user defined functions. */ #define MAXUSERARGS 10 struct user_args -{ - struct user_args *next; - struct - { - char *arg; - int len; - } a[MAXUSERARGS]; - int count; -} *user_args; + { + struct user_args *next; + struct + { + char *arg; + int len; + } + a[MAXUSERARGS]; + int count; + } + *user_args; /* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */ @@ -366,7 +374,13 @@ static void stop_sig PARAMS ((int)); /* Called after most modules have been initialized, but before taking users command file. */ -void (*init_ui_hook) PARAMS ((void)); +void (*init_ui_hook) PARAMS ((char *argv0)); + +/* This hook is called from within gdb's many mini-event loops which could + steal control from a real user interface's event loop. It returns + non-zero if the user is requesting a detach, zero otherwise. */ + +int (*ui_loop_hook) PARAMS ((int)); /* Called instead of command_loop at top level. Can be invoked via return_to_top_level. */ @@ -376,31 +390,45 @@ void (*command_loop_hook) PARAMS ((void)); /* Called instead of fputs for all output. */ -void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, FILE *stream)); - -/* Called when the target says something to the host, which may - want to appear in a different window. */ - -void (*target_output_hook) PARAMS ((unsigned char *)); +void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, GDB_FILE * stream)); /* Called from print_frame_info to list the line we stopped in. */ -void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, int line, +void (*print_frame_info_listing_hook) PARAMS ((struct symtab * s, int line, int stopline, int noerror)); /* Replaces most of query. */ -int (*query_hook) PARAMS (()); +int (*query_hook) PARAMS ((const char *, va_list)); + +/* Replaces most of warning. */ + +void (*warning_hook) PARAMS ((const char *, va_list)); /* Called from gdb_flush to flush output. */ -void (*flush_hook) PARAMS ((FILE *stream)); +void (*flush_hook) PARAMS ((GDB_FILE * stream)); + +/* These three functions support getting lines of text from the user. They + are used in sequence. First readline_begin_hook is called with a text + string that might be (for example) a message for the user to type in a + sequence of commands to be executed at a breakpoint. If this function + calls back to a GUI, it might take this opportunity to pop up a text + interaction window with this message. Next, readline_hook is called + with a prompt that is emitted prior to collecting the user input. + It can be called multiple times. Finally, readline_end_hook is called + to notify the GUI that we are done with the interaction window and it + can close it. */ + +void (*readline_begin_hook) PARAMS ((char *,...)); +char *(*readline_hook) PARAMS ((char *)); +void (*readline_end_hook) PARAMS ((void)); /* Called as appropriate to notify the interface of the specified breakpoint conditions. */ -void (*create_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); -void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); -void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); +void (*create_breakpoint_hook) PARAMS ((struct breakpoint * bpt)); +void (*delete_breakpoint_hook) PARAMS ((struct breakpoint * bpt)); +void (*modify_breakpoint_hook) PARAMS ((struct breakpoint * bpt)); /* Called during long calculations to allow GUI to repair window damage, and to check for stop buttons, etc... */ @@ -412,34 +440,54 @@ void (*interactive_hook) PARAMS ((void)); void (*registers_changed_hook) PARAMS ((void)); +/* Tell the GUI someone changed the register REGNO. -1 means + that the caller does not know which register changed or + that several registers have changed (see value_assign). */ +void (*register_changed_hook) PARAMS ((int regno)); + +/* Tell the GUI that the disassembly flavor has changed */ +void (*disassembly_flavor_hook) PARAMS((char *args, int from_tty)); + +/* Tell the GUI someone changed LEN bytes of memory at ADDR */ +void (*memory_changed_hook) PARAMS ((CORE_ADDR addr, int len)); + /* Called when going to wait for the target. Usually allows the GUI to run while waiting for target events. */ -int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status)); +int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus * status)); /* Used by UI as a wrapper around command execution. May do various things like enabling/disabling buttons, etc... */ -void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd, +void (*call_command_hook) PARAMS ((struct cmd_list_element * c, char *cmd, int from_tty)); +/* Called after a `set' command has finished. Is only run if the + `set' command succeeded. */ + +void (*set_hook) PARAMS ((struct cmd_list_element *c)); + +/* Called when the current thread changes. Argument is thread id. */ + +void (*context_hook) PARAMS ((int id)); /* Takes control from error (). Typically used to prevent longjmps out of the middle of the GUI. Usually used in conjunction with a catch routine. */ -NORETURN void (*error_hook) PARAMS (()) ATTR_NORETURN; - +NORETURN void (*error_hook) +PARAMS ((void)) ATTR_NORETURN; + /* Where to go for return_to_top_level (RETURN_ERROR). */ -jmp_buf error_return; + SIGJMP_BUF error_return; /* Where to go for return_to_top_level (RETURN_QUIT). */ -jmp_buf quit_return; + SIGJMP_BUF quit_return; /* Return for reason REASON. This generally gets back to the command loop, but can be caught via catch_errors. */ -NORETURN void -return_to_top_level (reason) + NORETURN void + return_to_top_level (reason) enum return_reason reason; { quit_flag = 0; @@ -447,10 +495,12 @@ return_to_top_level (reason) /* 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 */ + bpstat_clear_actions (stop_bpstat); /* Clear queued breakpoint commands */ disable_current_display (); do_cleanups (ALL_CLEANUPS); + if (async_p && target_has_async) + do_exec_cleanups (ALL_CLEANUPS); if (annotation_level > 1) switch (reason) @@ -463,7 +513,7 @@ return_to_top_level (reason) break; } - (NORETURN void) longjmp + (NORETURN void) SIGLONGJMP (reason == RETURN_ERROR ? error_return : quit_return, 1); } @@ -488,14 +538,14 @@ return_to_top_level (reason) int catch_errors (func, args, errstring, mask) - int (*func) PARAMS ((char *)); + catch_errors_ftype *func; PTR args; char *errstring; return_mask mask; { - jmp_buf saved_error; - jmp_buf saved_quit; - jmp_buf tmp_jmp; + SIGJMP_BUF saved_error; + SIGJMP_BUF saved_quit; + SIGJMP_BUF tmp_jmp; int val; struct cleanup *saved_cleanup_chain; char *saved_error_pre_print; @@ -507,21 +557,21 @@ catch_errors (func, args, errstring, mask) if (mask & RETURN_MASK_ERROR) { - memcpy ((char *)saved_error, (char *)error_return, sizeof (jmp_buf)); + memcpy ((char *) saved_error, (char *) error_return, sizeof (SIGJMP_BUF)); error_pre_print = errstring; } if (mask & RETURN_MASK_QUIT) { - memcpy (saved_quit, quit_return, sizeof (jmp_buf)); + memcpy (saved_quit, quit_return, sizeof (SIGJMP_BUF)); quit_pre_print = errstring; } - if (setjmp (tmp_jmp) == 0) + if (SIGSETJMP (tmp_jmp) == 0) { if (mask & RETURN_MASK_ERROR) - memcpy (error_return, tmp_jmp, sizeof (jmp_buf)); + memcpy (error_return, tmp_jmp, sizeof (SIGJMP_BUF)); if (mask & RETURN_MASK_QUIT) - memcpy (quit_return, tmp_jmp, sizeof (jmp_buf)); + memcpy (quit_return, tmp_jmp, sizeof (SIGJMP_BUF)); val = (*func) (args); } else @@ -531,12 +581,12 @@ catch_errors (func, args, errstring, mask) if (mask & RETURN_MASK_ERROR) { - memcpy (error_return, saved_error, sizeof (jmp_buf)); + memcpy (error_return, saved_error, sizeof (SIGJMP_BUF)); error_pre_print = saved_error_pre_print; } if (mask & RETURN_MASK_QUIT) { - memcpy (quit_return, saved_quit, sizeof (jmp_buf)); + memcpy (quit_return, saved_quit, sizeof (SIGJMP_BUF)); quit_pre_print = saved_quit_pre_print; } return val; @@ -544,42 +594,59 @@ catch_errors (func, args, errstring, mask) /* Handler for SIGHUP. */ +#ifdef SIGHUP static void disconnect (signo) -int signo; + int signo; { catch_errors (quit_cover, NULL, - "Could not kill the program being debugged", RETURN_MASK_ALL); + "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 +/* NOTE 1999-04-29: This function will be static again, once we modify + gdb to use the event loop as the default command loop and we merge + event-top.c into this file, top.c */ +/* static */ int quit_cover (s) -char *s; + PTR s; { - caution = 0; /* Throw caution to the wind -- we're exiting. - This prevents asking the user dumb questions. */ - quit_command((char *)0, 0); + caution = 0; /* Throw caution to the wind -- we're exiting. + This prevents asking the user dumb questions. */ + quit_command ((char *) 0, 0); return 0; } +#endif /* defined SIGHUP */ /* Line number we are currently in in a file which is being sourced. */ -static int source_line_number; +/* NOTE 1999-04-29: This variable will be static again, once we modify + gdb to use the event loop as the default command loop and we merge + event-top.c into this file, top.c */ +/* static */ int source_line_number; /* Name of the file we are sourcing. */ -static char *source_file_name; +/* NOTE 1999-04-29: This variable will be static again, once we modify + gdb to use the event loop as the default command loop and we merge + event-top.c into this file, top.c */ +/* static */ char *source_file_name; /* Buffer containing the error_pre_print used by the source stuff. Malloc'd. */ -static char *source_error; +/* NOTE 1999-04-29: This variable will be static again, once we modify + gdb to use the event loop as the default command loop and we merge + event-top.c into this file, top.c */ +/* 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; +/* NOTE 1999-04-29: This variable will be static again, once we modify + gdb to use the event loop as the default command loop and we merge + event-top.c into this file, top.c */ +/* static */ char *source_pre_error; /* Clean up on error during a "source" command (or execution of a user-defined command). */ @@ -599,18 +666,19 @@ read_command_file (stream) { struct cleanup *cleanups; - cleanups = make_cleanup (source_cleanup, instream); + cleanups = make_cleanup ((make_cleanup_func) source_cleanup, instream); instream = stream; command_loop (); do_cleanups (cleanups); } -extern void init_proc (); +extern void init_proc PARAMS ((void)); void (*pre_init_ui_hook) PARAMS ((void)); void -gdb_init () +gdb_init (argv0) + char *argv0; { if (pre_init_ui_hook) pre_init_ui_hook (); @@ -620,23 +688,37 @@ gdb_init () getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)); current_directory = gdb_dirbuf; - init_cmd_lists (); /* This needs to be done first */ - initialize_targets (); /* Setup target_terminal macros for utils.c */ - initialize_utils (); /* Make errors and warnings possible */ - initialize_all_files (); - init_main (); /* But that omits this file! Do it now */ - init_signals (); +#ifdef __MSDOS__ + /* Make sure we return to the original directory upon exit, come + what may, since the OS doesn't do that for us. */ + make_final_cleanup ((make_cleanup_func) chdir, strsave (current_directory)); +#endif - init_proc (); + init_cmd_lists (); /* This needs to be done first */ + initialize_targets (); /* Setup target_terminal macros for utils.c */ + initialize_utils (); /* Make errors and warnings possible */ + initialize_all_files (); + init_main (); /* But that omits this file! Do it now */ + + /* The signal handling mechanism is different depending whether or + not the async version is run. NOTE: in the future we plan to make + the event loop be the default engine of gdb, and this difference + will disappear. */ + if (async_p) + async_init_signals (); + else + init_signals (); /* 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. */ + expected_language = current_language; /* don't warn about the change. */ + /* All the interpreters should have had a look at things by now. + Initialize the selected interpreter. */ if (init_ui_hook) - init_ui_hook (); + init_ui_hook (argv0); } /* Allocate, initialize a new command line structure for one of the @@ -649,14 +731,17 @@ build_command_line (type, args) { struct command_line *cmd; - cmd = (struct command_line *)xmalloc (sizeof (struct command_line)); + if (args == NULL) + error ("if/while commands require arguments.\n"); + + cmd = (struct command_line *) xmalloc (sizeof (struct command_line)); cmd->next = NULL; cmd->control_type = type; cmd->body_count = 1; cmd->body_list - = (struct command_line **)xmalloc (sizeof (struct command_line *) - * cmd->body_count); + = (struct command_line **) xmalloc (sizeof (struct command_line *) + * cmd->body_count); memset (cmd->body_list, 0, sizeof (struct command_line *) * cmd->body_count); cmd->line = savestring (args, strlen (args)); return cmd; @@ -676,7 +761,7 @@ get_command_line (type, arg) /* Allocate and build a new command line structure. */ cmd = build_command_line (type, arg); - old_chain = make_cleanup (free_command_lines, &cmd); + old_chain = make_cleanup ((make_cleanup_func) free_command_lines, &cmd); /* Read in the body of this command. */ if (recurse_read_control_structure (cmd) == invalid_control) @@ -692,23 +777,24 @@ get_command_line (type, arg) /* Recursively print a command (including full control structures). */ void -print_command_line (cmd, depth) +print_command_line (cmd, depth, stream) struct command_line *cmd; unsigned int depth; + GDB_FILE *stream; { unsigned int i; if (depth) { for (i = 0; i < depth; i++) - fputs_filtered (" ", gdb_stdout); + fputs_filtered (" ", stream); } /* A simple command, print it and return. */ if (cmd->control_type == simple_control) { - fputs_filtered (cmd->line, gdb_stdout); - fputs_filtered ("\n", gdb_stdout); + fputs_filtered (cmd->line, stream); + fputs_filtered ("\n", stream); return; } @@ -716,14 +802,14 @@ print_command_line (cmd, depth) and return. */ if (cmd->control_type == continue_control) { - fputs_filtered ("loop_continue\n", gdb_stdout); + fputs_filtered ("loop_continue\n", stream); return; } /* loop_break to break out of a while loop, print it and return. */ if (cmd->control_type == break_control) { - fputs_filtered ("loop_break\n", gdb_stdout); + fputs_filtered ("loop_break\n", stream); return; } @@ -731,13 +817,13 @@ print_command_line (cmd, depth) if (cmd->control_type == while_control) { struct command_line *list; - fputs_filtered ("while ", gdb_stdout); - fputs_filtered (cmd->line, gdb_stdout); - fputs_filtered ("\n", gdb_stdout); + fputs_filtered ("while ", stream); + fputs_filtered (cmd->line, stream); + fputs_filtered ("\n", stream); list = *cmd->body_list; while (list) { - print_command_line (list, depth + 1); + print_command_line (list, depth + 1, stream); list = list->next; } } @@ -745,29 +831,29 @@ print_command_line (cmd, depth) /* An if command. Recursively print both arms before returning. */ if (cmd->control_type == if_control) { - fputs_filtered ("if ", gdb_stdout); - fputs_filtered (cmd->line, gdb_stdout); - fputs_filtered ("\n", gdb_stdout); + fputs_filtered ("if ", stream); + fputs_filtered (cmd->line, stream); + fputs_filtered ("\n", stream); /* The true arm. */ - print_command_line (cmd->body_list[0], depth + 1); + print_command_line (cmd->body_list[0], depth + 1, stream); /* Show the false arm if it exists. */ if (cmd->body_count == 2) - { - if (depth) - { - for (i = 0; i < depth; i++) - fputs_filtered (" ", gdb_stdout); - } - fputs_filtered ("else\n", gdb_stdout); - print_command_line (cmd->body_list[1], depth + 1); - } + { + if (depth) + { + for (i = 0; i < depth; i++) + fputs_filtered (" ", stream); + } + fputs_filtered ("else\n", stream); + print_command_line (cmd->body_list[1], depth + 1, stream); + } if (depth) { for (i = 0; i < depth; i++) - fputs_filtered (" ", gdb_stdout); + fputs_filtered (" ", stream); } - fputs_filtered ("end\n", gdb_stdout); + fputs_filtered ("end\n", stream); } } @@ -781,6 +867,7 @@ execute_control_command (cmd) struct command_line *current; struct cleanup *old_chain = 0; value_ptr val; + value_ptr val_mark; int loop; enum command_control_type ret; char *new_line; @@ -792,7 +879,8 @@ execute_control_command (cmd) new_line = insert_args (cmd->line); if (!new_line) return invalid_control; - old_chain = make_cleanup (free_current_contents, &new_line); + old_chain = make_cleanup ((make_cleanup_func) free_current_contents, + &new_line); execute_command (new_line, 0); ret = cmd->control_type; break; @@ -800,7 +888,7 @@ execute_control_command (cmd) case continue_control: case break_control: /* Return for "continue", and "break" so we can either - continue the loop at the top, or break out. */ + continue the loop at the top, or break out. */ ret = cmd->control_type; break; @@ -810,21 +898,29 @@ execute_control_command (cmd) new_line = insert_args (cmd->line); if (!new_line) return invalid_control; - old_chain = make_cleanup (free_current_contents, &new_line); + old_chain = make_cleanup ((make_cleanup_func) free_current_contents, + &new_line); expr = parse_expression (new_line); - make_cleanup (free_current_contents, &expr); - + make_cleanup ((make_cleanup_func) free_current_contents, &expr); + ret = simple_control; - loop = true; + loop = 1; /* Keep iterating so long as the expression is true. */ - while (loop == true) + while (loop == 1) { + int cond_result; + + QUIT; + /* Evaluate the expression. */ + val_mark = value_mark (); val = evaluate_expression (expr); + cond_result = value_true (val); + value_free_to_mark (val_mark); /* If the value is false, then break out of the loop. */ - if (!value_true (val)) + if (!cond_result) break; /* Execute the body of the while statement. */ @@ -837,7 +933,7 @@ execute_control_command (cmd) looping. */ if (ret == invalid_control || ret == break_control) { - loop = false; + loop = 0; break; } @@ -845,9 +941,9 @@ execute_control_command (cmd) at this point. */ if (ret == continue_control) break; - + /* Get the next statement. */ - current = current->next; + current = current->next; } } @@ -863,15 +959,17 @@ execute_control_command (cmd) new_line = insert_args (cmd->line); if (!new_line) return invalid_control; - old_chain = make_cleanup (free_current_contents, &new_line); + old_chain = make_cleanup ((make_cleanup_func) free_current_contents, + &new_line); /* Parse the conditional for the if statement. */ expr = parse_expression (new_line); - make_cleanup (free_current_contents, &expr); + make_cleanup ((make_cleanup_func) free_current_contents, &expr); current = NULL; ret = simple_control; /* Evaluate the conditional. */ + val_mark = value_mark (); val = evaluate_expression (expr); /* Choose which arm to take commands from based on the value of the @@ -880,6 +978,7 @@ execute_control_command (cmd) current = *cmd->body_list; else if (cmd->body_count == 2) current = *(cmd->body_list + 1); + value_free_to_mark (val_mark); /* Execute commands in the given arm. */ while (current) @@ -954,7 +1053,7 @@ arg_cleanup () { struct user_args *oargs = user_args; if (!user_args) - fatal ("Internal error, arg_cleanup called with no user args.\n"); + internal_error ("Internal error, arg_cleanup called with no user args.\n"); user_args = user_args->next; free (oargs); @@ -971,13 +1070,13 @@ setup_user_args (p) struct cleanup *old_chain; unsigned int arg_count = 0; - args = (struct user_args *)xmalloc (sizeof (struct user_args)); + args = (struct user_args *) xmalloc (sizeof (struct user_args)); memset (args, 0, sizeof (struct user_args)); args->next = user_args; user_args = args; - old_chain = make_cleanup (arg_cleanup, 0); + old_chain = make_cleanup ((make_cleanup_func) arg_cleanup, 0); if (p == NULL) return old_chain; @@ -985,6 +1084,9 @@ setup_user_args (p) while (*p) { char *start_arg; + int squote = 0; + int dquote = 0; + int bsquote = 0; if (arg_count >= MAXUSERARGS) { @@ -1002,8 +1104,36 @@ setup_user_args (p) user_args->a[arg_count].arg = p; /* Get to the end of this argument. */ - while (*p && *p != ' ' && *p != '\t') - p++; + while (*p) + { + if (((*p == ' ' || *p == '\t')) && !squote && !dquote && !bsquote) + break; + else + { + if (bsquote) + bsquote = 0; + else if (*p == '\\') + bsquote = 1; + else if (squote) + { + if (*p == '\'') + squote = 0; + } + else if (dquote) + { + if (*p == '"') + dquote = 0; + } + else + { + if (*p == '\'') + squote = 1; + else if (*p == '"') + dquote = 1; + } + p++; + } + } user_args->a[arg_count].len = p - start_arg; arg_count++; @@ -1045,7 +1175,7 @@ insert_args (line) { len += p - line; i = p[4] - '0'; - + if (i >= user_args->count) { error ("Missing argument %d in user function.\n", i); @@ -1059,7 +1189,7 @@ insert_args (line) len += strlen (line); /* Allocate space for the new line and fill it in. */ - new_line = (char *)xmalloc (len + 1); + new_line = (char *) xmalloc (len + 1); if (new_line == NULL) return NULL; @@ -1110,7 +1240,7 @@ execute_user_command (c, args) /* Set the instream to 0, indicating execution of a user-defined function. */ - old_chain = make_cleanup (source_cleanup, instream); + old_chain = make_cleanup ((make_cleanup_func) source_cleanup, instream); instream = (FILE *) 0; while (cmdlines) { @@ -1136,25 +1266,53 @@ execute_command (p, from_tty) register struct cmd_list_element *c; register enum language flang; static int warned = 0; + /* FIXME: These should really be in an appropriate header file */ + extern void serial_log_command PARAMS ((const char *)); free_all_values (); + /* Force cleanup of any alloca areas if using C alloca instead of + a builtin alloca. */ + alloca (0); + /* This can happen when command_line_input hits end of file. */ if (p == NULL) - return; + return; - while (*p == ' ' || *p == '\t') p++; + serial_log_command (p); + + while (*p == ' ' || *p == '\t') + p++; if (*p) { char *arg; c = lookup_cmd (&p, cmdlist, "", 0, 1); + + /* If the target is running, we allow only a limited set of + commands. */ + if (async_p && target_has_async && target_executing) + if (!strcmp (c->name, "help") + && !strcmp (c->name, "pwd") + && !strcmp (c->name, "show") + && !strcmp (c->name, "stop")) + error ("Cannot execute this command while the target is running."); + /* Pass null arg rather than an empty one. */ arg = *p ? p : 0; + /* Clear off trailing whitespace, except for set and complete command. */ + if (arg && c->type != set_cmd && c->function.cfunc != complete_command) + { + p = arg + strlen (arg) - 1; + while (p >= arg && (*p == ' ' || *p == '\t')) + p--; + *(p + 1) = '\0'; + } + /* If this command has been hooked, run the hook first. */ if (c->hook) - execute_user_command (c->hook, (char *)0); + execute_user_command (c->hook, (char *) 0); if (c->class == class_user) execute_user_command (c, arg); @@ -1166,16 +1324,17 @@ execute_command (p, from_tty) call_command_hook (c, arg, from_tty & caution); else (*c->function.cfunc) (arg, from_tty & caution); - } + } /* Tell the user if the language has changed (except first time). */ if (current_language != expected_language) - { - if (language_mode == language_mode_auto) { - language_info (1); /* Print what changed. */ + { + if (language_mode == language_mode_auto) + { + language_info (1); /* Print what changed. */ + } + warned = 0; } - 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 @@ -1197,7 +1356,10 @@ execute_command (p, from_tty) } /* ARGSUSED */ -static void +/* NOTE 1999-04-29: This function will be static again, once we modify + gdb to use the event loop as the default command loop and we merge + event-top.c into this file, top.c */ +/* static */ void command_loop_marker (foo) int foo; { @@ -1213,21 +1375,41 @@ command_loop () char *command; int stdin_is_tty = ISATTY (stdin); long time_at_cmd_start; - long space_at_cmd_start; +#ifdef HAVE_SBRK + long space_at_cmd_start = 0; +#endif extern int display_time; extern int display_space; - while (!feof (instream)) + while (instream && !feof (instream)) { +#if defined(TUI) + extern int insert_mode; +#endif if (window_hook && instream == stdin) - (*window_hook) (instream, prompt); + (*window_hook) (instream, get_prompt ()); quit_flag = 0; if (instream == stdin && stdin_is_tty) reinitialize_more_filter (); - old_chain = make_cleanup (command_loop_marker, 0); - command = command_line_input (instream == stdin ? prompt : (char *) NULL, + old_chain = make_cleanup ((make_cleanup_func) command_loop_marker, 0); + +#if defined(TUI) + /* A bit of paranoia: I want to make sure the "insert_mode" global + * is clear except when it is being used for command-line editing + * (see tuiIO.c, utils.c); otherwise normal output will + * get messed up in the TUI. So clear it before/after + * the command-line-input call. - RT + */ + insert_mode = 0; +#endif + /* Get a command-line. This calls the readline package. */ + command = command_line_input (instream == stdin ? + get_prompt () : (char *) NULL, instream == stdin, "prompt"); +#if defined(TUI) + insert_mode = 0; +#endif if (command == 0) return; @@ -1235,10 +1417,12 @@ command_loop () if (display_space) { +#ifdef HAVE_SBRK extern char **environ; char *lim = (char *) sbrk (0); space_at_cmd_start = (long) (lim - (char *) &environ); +#endif } execute_command (command, instream == stdin); @@ -1256,6 +1440,7 @@ command_loop () if (display_space) { +#ifdef HAVE_SBRK extern char **environ; char *lim = (char *) sbrk (0); long space_now = lim - (char *) &environ; @@ -1265,9 +1450,11 @@ command_loop () space_now, (space_diff >= 0 ? '+' : '-'), space_diff); +#endif } } } + /* Commands call this if they do not want to be repeated by null lines. */ @@ -1286,29 +1473,29 @@ dont_repeat () /* Read a line from the stream "instream" without command line editing. - It prints PRROMPT once at the start. + It prints PROMPT_ARG once at the start. Action is compatible with "readline", e.g. space for the result is malloc'd and should be freed by the caller. A NULL return means end of file. */ char * -gdb_readline (prrompt) - char *prrompt; +gdb_readline (prompt_arg) + char *prompt_arg; { int c; char *result; int input_index = 0; int result_size = 80; - if (prrompt) + if (prompt_arg) { /* 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); + character position to be off, since the newline we read from + the user is not accounted for. */ + fputs_unfiltered (prompt_arg, gdb_stdout); #ifdef MPW /* Move to a new line so the entered line doesn't have a prompt - on the front of it. */ + on the front of it. */ fputs_unfiltered ("\n", gdb_stdout); #endif /* MPW */ gdb_flush (gdb_stdout); @@ -1319,7 +1506,7 @@ gdb_readline (prrompt) while (1) { /* Read from stdin if we are executing a user defined command. - This is the right thing for prompt_for_continue, at least. */ + This is the right thing for prompt_for_continue, at least. */ c = fgetc (instream ? instream : stdin); if (c == EOF) @@ -1334,7 +1521,15 @@ gdb_readline (prrompt) } if (c == '\n') +#ifndef CRLF_SOURCE_FILES break; +#else + { + if (input_index > 0 && result[input_index - 1] == '\r') + input_index--; + break; + } +#endif result[input_index++] = c; while (input_index >= result_size) @@ -1352,7 +1547,10 @@ gdb_readline (prrompt) substitution. These variables are given default values at the end of this file. */ static int command_editing_p; -static int history_expansion_p; +/* NOTE 1999-04-29: This variable will be static again, once we modify + gdb to use the event loop as the default command loop and we merge + event-top.c into this file, top.c */ +/* static */ int history_expansion_p; static int write_history_p; static int history_size; static char *history_filename; @@ -1370,7 +1568,7 @@ static char *history_filename; /* 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 @@ -1378,13 +1576,13 @@ char *gdb_completer_word_break_characters = it thinks that the string needs to be quoted and automatically supplies a leading quote. */ char *gdb_completer_command_word_break_characters = - " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,"; +" \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. */ @@ -1406,7 +1604,7 @@ filename_completer (text, word) char *word; { /* From readline. */ - extern char *filename_completion_function (); + extern char *filename_completion_function PARAMS ((char *, int)); int subsequent_name; char **return_val; int return_val_used; @@ -1435,7 +1633,7 @@ filename_completer (text, word) break; } /* Like emacs, don't complete on old versions. Especially useful - in the "source" command. */ + in the "source" command. */ if (p[strlen (p) - 1] == '~') continue; @@ -1496,7 +1694,7 @@ filename_completer (text, word) "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. @@ -1526,8 +1724,8 @@ line_completion_function (text, matches, line_buffer, point) char *line_buffer; int point; { - static char **list = (char **)NULL; /* Cache of completions */ - static int index; /* Next cached completion */ + 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. */ @@ -1537,27 +1735,27 @@ line_completion_function (text, matches, line_buffer, point) if (matches == 0) { /* 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. */ + we need to find all of them now, and cache them for returning one at + a time on future calls. */ if (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); + free ((PTR) list); } list = 0; index = 0; /* 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. */ + 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; + gdb_completer_word_break_characters; /* Decide whether to complete on a list of gdb commands or on symbols. */ tmp_command = (char *) alloca (point + 1); @@ -1566,8 +1764,8 @@ line_completion_function (text, matches, line_buffer, point) strncpy (tmp_command, line_buffer, point); tmp_command[point] = '\0'; /* Since text always contains some number of characters leading up - to point, we can find the equivalent position in tmp_command - by subtracting that many characters from the end of tmp_command. */ + to point, we can find the equivalent position in tmp_command + by subtracting that many characters from the end of tmp_command. */ word = tmp_command + point - strlen (text); if (point == 0) @@ -1606,16 +1804,16 @@ line_completion_function (text, matches, line_buffer, point) if (q != tmp_command + 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". */ + 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; } else { /* We're trying to complete on the command which was ambiguous. - This we can deal with. */ + This we can deal with. */ if (result_list) { list = complete_on_cmdlist (*result_list->prefixlist, p, @@ -1626,7 +1824,7 @@ line_completion_function (text, matches, line_buffer, point) list = complete_on_cmdlist (cmdlist, p, word); } /* Insure that readline does the right thing with respect to - inserting quotes. */ + inserting quotes. */ rl_completer_word_break_characters = gdb_completer_command_word_break_characters; } @@ -1646,11 +1844,11 @@ line_completion_function (text, matches, line_buffer, point) if (c->prefixlist) { /* It is a prefix command; what comes after it is - a subcommand (e.g. "info "). */ + 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. */ + with respect to inserting quotes. */ rl_completer_word_break_characters = gdb_completer_command_word_break_characters; } @@ -1663,7 +1861,7 @@ line_completion_function (text, matches, line_buffer, point) else { /* It is a normal command; what comes after it is - completed by the command's completer function. */ + completed by the command's completer function. */ list = (*c->completer) (p, word); } } @@ -1789,12 +1987,12 @@ skip_quoted (str) } return (scan); } - + #ifdef STOP_SIGNAL static void stop_sig (signo) -int signo; + int signo; { #if STOP_SIGNAL == SIGTSTP signal (SIGTSTP, SIG_DFL); @@ -1804,7 +2002,7 @@ int signo; #else signal (STOP_SIGNAL, stop_sig); #endif - printf_unfiltered ("%s", prompt); + printf_unfiltered ("%s", get_prompt ()); gdb_flush (gdb_stdout); /* Forget about any previous command -- null line now will do nothing. */ @@ -1815,8 +2013,15 @@ int signo; /* Initialize signal handlers. */ static void do_nothing (signo) -int signo; + int signo; { + /* Under System V the default disposition of a signal is reinstated after + the signal is caught and delivered to an application process. On such + systems one must restore the replacement signal handler if one wishes + to continue handling the signal in one's program. On BSD systems this + is not needed but it is harmless, and it simplifies the code to just do + it unconditionally. */ + signal (signo, do_nothing); } static void @@ -1824,6 +2029,12 @@ init_signals () { signal (SIGINT, request_quit); + /* If SIGTRAP was set to SIG_IGN, then the SIG_IGN will get passed + to the inferior and breakpoints will be ignored. */ +#ifdef SIGTRAP + signal (SIGTRAP, SIG_DFL); +#endif + /* If we initialize SIGQUIT to SIG_IGN, then the SIG_IGN will get passed to the inferior, which we don't want. It would be possible to do a "signal (SIGQUIT, SIG_DFL)" after we fork, but @@ -1833,8 +2044,10 @@ init_signals () a handler for SIGQUIT, when we call exec it will set the signal to SIG_DFL for us. */ signal (SIGQUIT, do_nothing); +#ifdef SIGHUP if (signal (SIGHUP, do_nothing) != SIG_IGN) signal (SIGHUP, disconnect); +#endif signal (SIGFPE, float_handler); #if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) @@ -1858,8 +2071,8 @@ init_signals () simple input as the user has requested. */ char * -command_line_input (prrompt, repeat, annotation_suffix) - char *prrompt; +command_line_input (prompt_arg, repeat, annotation_suffix) + char *prompt_arg; int repeat; char *annotation_suffix; { @@ -1868,8 +2081,7 @@ command_line_input (prrompt, repeat, annotation_suffix) register char *p; char *p1; char *rl; - char *local_prompt = prrompt; - register int c; + char *local_prompt = prompt_arg; char *nline; char got_eof = 0; @@ -1879,12 +2091,12 @@ command_line_input (prrompt, repeat, annotation_suffix) if (annotation_level > 1 && instream == stdin) { - local_prompt = alloca ((prrompt == NULL ? 0 : strlen (prrompt)) + local_prompt = alloca ((prompt_arg == NULL ? 0 : strlen (prompt_arg)) + strlen (annotation_suffix) + 40); - if (prrompt == NULL) + if (prompt_arg == NULL) local_prompt[0] = '\0'; else - strcpy (local_prompt, prrompt); + strcpy (local_prompt, prompt_arg); strcat (local_prompt, "\n\032\032"); strcat (local_prompt, annotation_suffix); strcat (local_prompt, "\n"); @@ -1903,13 +2115,18 @@ command_line_input (prrompt, repeat, annotation_suffix) immediate_quit++; #ifdef STOP_SIGNAL if (job_control) - signal (STOP_SIGNAL, stop_sig); + { + if (async_p) + signal (STOP_SIGNAL, handle_stop_sig); + else + signal (STOP_SIGNAL, stop_sig); + } #endif while (1) { /* Make sure that all output has been output. Some machines may let - you get away with leaving out some of the gdb_flush, but not all. */ + you get away with leaving out some of the gdb_flush, but not all. */ wrap_here (""); gdb_flush (gdb_stdout); gdb_flush (gdb_stderr); @@ -1933,11 +2150,18 @@ command_line_input (prrompt, repeat, annotation_suffix) } /* Don't use fancy stuff if not talking to stdin. */ - if (command_editing_p && instream == stdin - && ISATTY (instream)) - rl = readline (local_prompt); + if (readline_hook && instream == NULL) + { + rl = (*readline_hook) (local_prompt); + } + else if (command_editing_p && instream == stdin && ISATTY (instream)) + { + rl = readline (local_prompt); + } else - rl = gdb_readline (local_prompt); + { + rl = gdb_readline (local_prompt); + } if (annotation_level > 1 && instream == stdin) { @@ -1951,9 +2175,9 @@ command_line_input (prrompt, repeat, annotation_suffix) got_eof = 1; break; } - if (strlen(rl) + 1 + (p - linebuffer) > linelength) + if (strlen (rl) + 1 + (p - linebuffer) > linelength) { - linelength = strlen(rl) + 1 + (p - linebuffer); + linelength = strlen (rl) + 1 + (p - linebuffer); nline = (char *) xrealloc (linebuffer, linelength); p += nline - linebuffer; linebuffer = nline; @@ -1964,14 +2188,14 @@ command_line_input (prrompt, repeat, annotation_suffix) while (*p1) *p++ = *p1++; - free (rl); /* Allocated in readline. */ + free (rl); /* Allocated in readline. */ if (p == linebuffer || *(p - 1) != '\\') break; p--; /* Put on top of '\'. */ local_prompt = (char *) 0; - } + } #ifdef STOP_SIGNAL if (job_control) @@ -1985,12 +2209,12 @@ command_line_input (prrompt, repeat, annotation_suffix) #define SERVER_COMMAND_LENGTH 7 server_command = (p - linebuffer > SERVER_COMMAND_LENGTH) - && STREQN (linebuffer, "server ", SERVER_COMMAND_LENGTH); + && STREQN (linebuffer, "server ", SERVER_COMMAND_LENGTH); if (server_command) { /* Note that we don't set `line'. Between this and the check in - dont_repeat, this insures that repeating will still do the - right thing. */ + dont_repeat, this insures that repeating will still do the + right thing. */ *p = '\0'; return linebuffer + SERVER_COMMAND_LENGTH; } @@ -2013,7 +2237,7 @@ command_line_input (prrompt, repeat, annotation_suffix) if (expanded < 0) { free (history_value); - return command_line_input (prrompt, repeat, annotation_suffix); + return command_line_input (prompt_arg, repeat, annotation_suffix); } if (strlen (history_value) > linelength) { @@ -2021,7 +2245,7 @@ command_line_input (prrompt, repeat, annotation_suffix) linebuffer = (char *) xrealloc (linebuffer, linelength); } strcpy (linebuffer, history_value); - p = linebuffer + strlen(linebuffer); + p = linebuffer + strlen (linebuffer); free (history_value); } } @@ -2029,16 +2253,11 @@ command_line_input (prrompt, repeat, annotation_suffix) /* If we just got an empty line, and that is supposed to repeat the previous command, return the value in the global buffer. */ - if (repeat) - { - if (p == linebuffer) - return line; - p1 = linebuffer; - while (*p1 == ' ' || *p1 == '\t') - p1++; - if (!*p1) - return line; - } + if (repeat && p == linebuffer) + return line; + for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++); + if (repeat && !*p1) + return line; *p = 0; @@ -2053,36 +2272,8 @@ command_line_input (prrompt, repeat, annotation_suffix) out the command and then later fetch it from the value history and remove the '#'. The kill ring is probably better, but some people are in the habit of commenting things out. */ - p1 = linebuffer; - while ((c = *p1++) != '\0') - { - if (c == '"') - while ((c = *p1++) != '"') - { - /* Make sure an escaped '"' doesn't make us think the string - is ended. */ - if (c == '\\') - parse_escape (&p1); - if (c == '\0') - break; - } - else if (c == '\'') - while ((c = *p1++) != '\'') - { - /* Make sure an escaped '\'' doesn't make us think the string - is ended. */ - if (c == '\\') - parse_escape (&p1); - if (c == '\0') - break; - } - else if (c == '#') - { - /* Found a comment. */ - p1[-1] = '\0'; - break; - } - } + if (*p1 == '#') + *p1 = '\0'; /* Found a comment. */ /* Save into global buffer if appropriate. */ if (repeat) @@ -2142,13 +2333,13 @@ read_next_line (command) error ("Control nesting too deep!\n"); /* Set a prompt based on the nesting of the control commands. */ - if (instream == stdin) + if (instream == stdin || (instream == 0 && readline_hook != NULL)) { for (i = 0; i < control_level; i++) control_prompt[i] = ' '; control_prompt[i] = '>'; - control_prompt[i+1] = '\0'; - prompt_ptr = (char *)&control_prompt[0]; + control_prompt[i + 1] = '\0'; + prompt_ptr = (char *) &control_prompt[0]; } else prompt_ptr = NULL; @@ -2172,7 +2363,7 @@ read_next_line (command) executed. */ if (p1 == p || p[0] == '#') return nop_command; - + /* Is this the end of a simple, while, or if control structure? */ if (p1 - p == 3 && !strncmp (p, "end", 3)) return end_command; @@ -2187,7 +2378,7 @@ read_next_line (command) *command = build_command_line (while_control, p + 6); else if (p1 - p > 2 && !strncmp (p, "if", 2)) *command = build_command_line (if_control, p + 3); - else if (p1 - p == 5 && !strncmp (p, "loop_break", 5)) + else if (p1 - p == 10 && !strncmp (p, "loop_break", 10)) { *command = (struct command_line *) xmalloc (sizeof (struct command_line)); @@ -2197,7 +2388,7 @@ read_next_line (command) (*command)->body_count = 0; (*command)->body_list = NULL; } - else if (p1 - p == 8 && !strncmp (p, "loop_continue", 8)) + else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13)) { *command = (struct command_line *) xmalloc (sizeof (struct command_line)); @@ -2217,14 +2408,14 @@ read_next_line (command) (*command)->control_type = simple_control; (*command)->body_count = 0; (*command)->body_list = NULL; - } + } /* Nothing special. */ return ok_command; } /* Recursively read in the control structures and create a command_line - tructure from them. + structure from them. The parent_control parameter is the control structure in which the following commands are nested. */ @@ -2237,9 +2428,7 @@ recurse_read_control_structure (current_cmd) enum misc_command_type val; enum command_control_type ret; struct command_line **body_ptr, *child_tail, *next; - struct cleanup *old_chains, *tmp_chains; - old_chains = NULL; child_tail = NULL; current_body = 1; @@ -2283,7 +2472,7 @@ recurse_read_control_structure (current_cmd) break; } } - + /* Not the end of a control structure. */ if (val == else_command) { @@ -2308,25 +2497,18 @@ recurse_read_control_structure (current_cmd) } else { - /* We have just read the first line of the child's control - structure. From now on, arrange to throw away the line - we have if we quit or get an error. */ body_ptr = current_cmd->body_list; for (i = 1; i < current_body; i++) body_ptr++; *body_ptr = next; - tmp_chains = make_cleanup (free_command_lines, body_ptr); - - if (!old_chains) - old_chains = tmp_chains; } child_tail = next; /* If the latest line is another control structure, then recurse - on it. */ + on it. */ if (next->control_type == while_control || next->control_type == if_control) { @@ -2340,27 +2522,39 @@ recurse_read_control_structure (current_cmd) } dont_repeat (); - if (ret == invalid_control && old_chains) - do_cleanups (old_chains); - else if (old_chains) - discard_cleanups (old_chains); return ret; } +/* Read lines from the input stream and accumulate them in a chain of + struct command_line's, which is then returned. For input from a + terminal, the special command "end" is used to mark the end of the + input, and is not included in the returned chain of commands. */ -/* Read lines from the input stream - and accumulate them in a chain of struct command_line's - which is then returned. */ +#define END_MESSAGE "End with a line saying just \"end\"." struct command_line * -read_command_lines () +read_command_lines (prompt_arg, from_tty) + char *prompt_arg; + int from_tty; { struct command_line *head, *tail, *next; struct cleanup *old_chain; enum command_control_type ret; enum misc_command_type val; + control_level = 0; + if (readline_begin_hook) + { + /* Note - intentional to merge messages with no newline */ + (*readline_begin_hook) ("%s %s\n", prompt_arg, END_MESSAGE); + } + else if (from_tty && input_from_terminal_p ()) + { + printf_unfiltered ("%s\n%s\n", prompt_arg, END_MESSAGE); + gdb_flush (gdb_stdout); + } + head = tail = NULL; old_chain = NULL; @@ -2394,7 +2588,7 @@ read_command_lines () if (ret == invalid_control) break; } - + if (tail) { tail->next = next; @@ -2402,7 +2596,8 @@ read_command_lines () else { head = next; - old_chain = make_cleanup (free_command_lines, &head); + old_chain = make_cleanup ((make_cleanup_func) free_command_lines, + &head); } tail = next; } @@ -2414,20 +2609,23 @@ read_command_lines () if (ret != invalid_control) { discard_cleanups (old_chain); - return head; } else do_cleanups (old_chain); } - return NULL; + if (readline_end_hook) + { + (*readline_end_hook) (); + } + return (head); } /* Free a chain of struct command_line's. */ void free_command_lines (lptr) - struct command_line **lptr; + struct command_line **lptr; { register struct command_line *l = *lptr; register struct command_line *next; @@ -2444,7 +2642,7 @@ free_command_lines (lptr) } next = l->next; free (l->line); - free ((PTR)l); + free ((PTR) l); l = next; } } @@ -2557,7 +2755,7 @@ error_no_arg (why) static void help_command (command, from_tty) char *command; - int from_tty; /* Ignored */ + int from_tty; /* Ignored */ { help_cmd (command, gdb_stdout); } @@ -2574,7 +2772,7 @@ validate_comname (comname) p = comname; while (*p) { - if (!isalnum(*p) && *p != '-') + if (!isalnum (*p) && *p != '-' && *p != '_') error ("Junk in argument list: \"%s\"", p); p++; } @@ -2596,6 +2794,7 @@ define_command (comname, from_tty) register struct command_line *cmds; register struct cmd_list_element *c, *newc, *hookc = 0; char *tem = comname; + char tmpbuf[128]; #define HOOK_STRING "hook-" #define HOOK_LEN 5 @@ -2623,9 +2822,9 @@ define_command (comname, from_tty) if (!strncmp (comname, HOOK_STRING, HOOK_LEN)) { /* Look up cmd it hooks, and verify that we got an exact match. */ - tem = comname+HOOK_LEN; + tem = comname + HOOK_LEN; hookc = lookup_cmd (&tem, cmdlist, "", -1, 0); - if (hookc && !STREQ (comname+HOOK_LEN, hookc->name)) + if (hookc && !STREQ (comname + HOOK_LEN, hookc->name)) hookc = 0; if (!hookc) { @@ -2641,24 +2840,18 @@ define_command (comname, from_tty) /* 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 (isupper (*tem)) + *tem = tolower (*tem); - if (from_tty) - { - printf_unfiltered ("Type commands for definition of \"%s\".\n\ -End with a line saying just \"end\".\n", comname); - gdb_flush (gdb_stdout); - } - - control_level = 0; - cmds = read_command_lines (); + sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname); + cmds = read_command_lines (tmpbuf, from_tty); if (c && c->class == class_user) free_command_lines (&c->user_commands); newc = add_cmd (comname, class_user, user_defined_command, - (c && c->class == class_user) - ? c->doc : savestring ("User-defined.", 13), &cmdlist); + (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 @@ -2678,6 +2871,7 @@ document_command (comname, from_tty) struct command_line *doclines; register struct cmd_list_element *c; char *tem = comname; + char tmpbuf[128]; validate_comname (comname); @@ -2686,13 +2880,11 @@ document_command (comname, from_tty) if (c->class != class_user) error ("Command \"%s\" is built-in.", comname); - if (from_tty) - printf_unfiltered ("Type documentation for \"%s\".\n\ -End with a line saying just \"end\".\n", comname); - - doclines = read_command_lines (); + sprintf (tmpbuf, "Type documentation for \"%s\".", comname); + doclines = read_command_lines (tmpbuf, from_tty); - if (c->doc) free (c->doc); + if (c->doc) + free (c->doc); { register struct command_line *cl1; @@ -2715,29 +2907,44 @@ End with a line saying just \"end\".\n", comname); free_command_lines (&doclines); } -void -print_gnu_advertisement () -{ - 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\ -"); -} - +/* Print the GDB banner. */ void print_gdb_version (stream) - GDB_FILE *stream; + GDB_FILE *stream; { + /* From GNU coding standards, first line is meant to be easy for a + program to parse, and is just canonical program name and version + number, which starts after last space. */ + + fprintf_filtered (stream, "GNU gdb %s\n", version); + + /* Second line is a copyright notice. */ + + fprintf_filtered (stream, "Copyright 1998 Free Software Foundation, Inc.\n"); + + /* Following the copyright is a brief statement that the program is + free software, that users are free to copy and change it on + certain conditions, that it is covered by the GNU GPL, and that + there is no warranty. */ + fprintf_filtered (stream, "\ -GDB %s (%s", version, host_name); +GDB is free software, covered by the GNU General Public License, and you are\n\ +welcome to change it and/or distribute copies of it under certain conditions.\n\ +Type \"show copying\" to see the conditions.\n\ +There is absolutely no warranty for GDB. Type \"show warranty\" for details.\n"); - if (!STREQ (host_name, target_name)) - fprintf_filtered (stream, " --target %s", target_name); + /* After the required info we print the configuration information. */ - fprintf_filtered (stream, "), "); - wrap_here(""); - fprintf_filtered (stream, "Copyright 1995 Free Software Foundation, Inc."); + fprintf_filtered (stream, "This GDB was configured as \""); + if (!STREQ (host_name, target_name)) + { + fprintf_filtered (stream, "--host=%s --target=%s", host_name, target_name); + } + else + { + fprintf_filtered (stream, "%s", host_name); + } + fprintf_filtered (stream, "\"."); } /* ARGSUSED */ @@ -2747,24 +2954,323 @@ show_version (args, from_tty) int from_tty; { immediate_quit++; - print_gnu_advertisement (); print_gdb_version (gdb_stdout); printf_filtered ("\n"); immediate_quit--; } -/* xgdb calls this to reprint the usual GDB prompt. Obsolete now that xgdb - is obsolete. */ +/* get_prompt: access method for the GDB prompt string. */ + +#define MAX_PROMPT_SIZE 256 + +/* + * int get_prompt_1 (char * buf); + * + * Work-horse for get_prompt (called via catch_errors). + * Argument is buffer to hold the formatted prompt. + * + * Returns: 1 for success (use formatted prompt) + * 0 for failure (use gdb_prompt_string). + */ + +static int gdb_prompt_escape; + +static int +get_prompt_1 (formatted_prompt) + char *formatted_prompt; +{ + char *local_prompt; + + if (async_p) + local_prompt = PROMPT (0); + else + local_prompt = gdb_prompt_string; + + + if (gdb_prompt_escape == 0) + { + return 0; /* do no formatting */ + } + else + /* formatted prompt */ + { + char fmt[40], *promptp, *outp, *tmp; + value_ptr arg_val; + DOUBLEST doubleval; + LONGEST longval; + CORE_ADDR addrval; + + int i, len; + struct type *arg_type, *elt_type; + + promptp = local_prompt; + outp = formatted_prompt; + + while (*promptp != '\0') + { + int available = MAX_PROMPT_SIZE - (outp - formatted_prompt) - 1; + + if (*promptp != gdb_prompt_escape) + { + if (available >= 1) /* overflow protect */ + *outp++ = *promptp++; + } + else + { + /* GDB prompt string contains escape char. Parse for arg. + Two consecutive escape chars followed by arg followed by + a comma means to insert the arg using a default format. + Otherwise a printf format string may be included between + the two escape chars. eg: + %%foo, insert foo using default format + %2.2f%foo, insert foo using "%2.2f" format + A mismatch between the format string and the data type + of "foo" is an error (which we don't know how to protect + against). */ + + fmt[0] = '\0'; /* assume null format string */ + if (promptp[1] == gdb_prompt_escape) /* double esc char */ + { + promptp += 2; /* skip past two escape chars. */ + } + else + { + /* extract format string from between two esc chars */ + i = 0; + do + { + fmt[i++] = *promptp++; /* copy format string */ + } + while (i < sizeof (fmt) - 1 && + *promptp != gdb_prompt_escape && + *promptp != '\0'); + + if (*promptp != gdb_prompt_escape) + error ("Syntax error at prompt position %d", + promptp - local_prompt); + else + { + promptp++; /* skip second escape char */ + fmt[i++] = '\0'; /* terminate the format string */ + } + } + + arg_val = parse_to_comma_and_eval (&promptp); + if (*promptp == ',') + promptp++; /* skip past the comma */ + arg_type = check_typedef (VALUE_TYPE (arg_val)); + switch (TYPE_CODE (arg_type)) + { + case TYPE_CODE_ARRAY: + elt_type = check_typedef (TYPE_TARGET_TYPE (arg_type)); + if (TYPE_LENGTH (arg_type) > 0 && + TYPE_LENGTH (elt_type) == 1 && + TYPE_CODE (elt_type) == TYPE_CODE_INT) + { + int len = TYPE_LENGTH (arg_type); + + if (VALUE_LAZY (arg_val)) + value_fetch_lazy (arg_val); + tmp = VALUE_CONTENTS (arg_val); + + if (len > available) + len = available; /* overflow protect */ + + /* FIXME: how to protect GDB from crashing + from bad user-supplied format string? */ + if (fmt[0] != 0) + sprintf (outp, fmt, tmp); + else + strncpy (outp, tmp, len); + outp[len] = '\0'; + } + break; + case TYPE_CODE_PTR: + elt_type = check_typedef (TYPE_TARGET_TYPE (arg_type)); + addrval = value_as_pointer (arg_val); + + if (TYPE_LENGTH (elt_type) == 1 && + TYPE_CODE (elt_type) == TYPE_CODE_INT && + addrval != 0) + { + /* display it as a string */ + char *default_fmt = "%s"; + char *tmp; + int err = 0; + + /* Limiting the number of bytes that the following call + will read protects us from sprintf overflow later. */ + i = target_read_string (addrval, /* src */ + &tmp, /* dest */ + available, /* len */ + &err); + if (err) /* read failed */ + error ("%s on target_read", safe_strerror (err)); + + tmp[i] = '\0'; /* force-terminate string */ + /* FIXME: how to protect GDB from crashing + from bad user-supplied format string? */ + sprintf (outp, fmt[0] == 0 ? default_fmt : fmt, + tmp); + free (tmp); + } + else + { + /* display it as a pointer */ + char *default_fmt = "0x%x"; + + /* FIXME: how to protect GDB from crashing + from bad user-supplied format string? */ + if (available >= 16 /*? */ ) /* overflow protect */ + sprintf (outp, fmt[0] == 0 ? default_fmt : fmt, + (long) addrval); + } + break; + case TYPE_CODE_FLT: + { + char *default_fmt = "%g"; + + doubleval = value_as_double (arg_val); + /* FIXME: how to protect GDB from crashing + from bad user-supplied format string? */ + if (available >= 16 /*? */ ) /* overflow protect */ + sprintf (outp, fmt[0] == 0 ? default_fmt : fmt, + (double) doubleval); + break; + } + case TYPE_CODE_INT: + { + char *default_fmt = "%d"; + + longval = value_as_long (arg_val); + /* FIXME: how to protect GDB from crashing + from bad user-supplied format string? */ + if (available >= 16 /*? */ ) /* overflow protect */ + sprintf (outp, fmt[0] == 0 ? default_fmt : fmt, + (long) longval); + break; + } + case TYPE_CODE_BOOL: + { + /* no default format for bool */ + longval = value_as_long (arg_val); + if (available >= 8 /*? */ ) /* overflow protect */ + { + if (longval) + strcpy (outp, ""); + else + strcpy (outp, ""); + } + break; + } + case TYPE_CODE_ENUM: + { + /* no default format for enum */ + longval = value_as_long (arg_val); + len = TYPE_NFIELDS (arg_type); + /* find enum name if possible */ + for (i = 0; i < len; i++) + if (TYPE_FIELD_BITPOS (arg_type, i) == longval) + break; /* match -- end loop */ + + if (i < len) /* enum name found */ + { + char *name = TYPE_FIELD_NAME (arg_type, i); + + strncpy (outp, name, available); + /* in casel available < strlen (name), */ + outp[available] = '\0'; + } + else + { + if (available >= 16 /*? */ ) /* overflow protect */ + sprintf (outp, "%d", (long) longval); + } + break; + } + case TYPE_CODE_VOID: + *outp = '\0'; + break; /* void type -- no output */ + default: + error ("bad data type at prompt position %d", + promptp - local_prompt); + break; + } + outp += strlen (outp); + } + } + *outp++ = '\0'; /* terminate prompt string */ + return 1; + } +} + +char * +get_prompt () +{ + static char buf[MAX_PROMPT_SIZE]; + + if (catch_errors (get_prompt_1, buf, "bad formatted prompt: ", + RETURN_MASK_ALL)) + { + return &buf[0]; /* successful formatted prompt */ + } + else + { + /* Prompt could not be formatted. */ + if (async_p) + return PROMPT (0); + else + return gdb_prompt_string; + } +} void -print_prompt () +set_prompt (s) + char *s; { - printf_unfiltered ("%s", prompt); - gdb_flush (gdb_stdout); +/* ??rehrauer: I don't know why this fails, since it looks as though + assignments to prompt are wrapped in calls to savestring... + if (prompt != NULL) + free (prompt); + */ + if (async_p) + PROMPT (0) = savestring (s, strlen (s)); + else + gdb_prompt_string = savestring (s, strlen (s)); } + +/* If necessary, make the user confirm that we should quit. Return + non-zero if we should quit, zero if we shouldn't. */ + +int +quit_confirm () +{ + if (inferior_pid != 0 && target_has_execution) + { + char *s; + + /* This is something of a hack. But there's no reliable way to + see if a GUI is running. The `use_windows' variable doesn't + cut it. */ + if (init_ui_hook) + s = "A debugging session is active.\nDo you still want to close the debugger?"; + else if (attach_flag) + s = "The program is running. Quit anyway (and detach it)? "; + else + s = "The program is running. Exit anyway? "; + + if (!query (s)) + return 0; + } + + return 1; +} + +/* Quit without asking for confirmation. */ + void -quit_command (args, from_tty) +quit_force (args, from_tty) char *args; int from_tty; { @@ -2782,20 +3288,11 @@ quit_command (args, from_tty) if (inferior_pid != 0 && target_has_execution) { if (attach_flag) - { - if (query ("The program is running. Quit anyway (and detach it)? ")) - target_detach (args, from_tty); - else - error ("Not confirmed."); - } + target_detach (args, from_tty); else - { - if (query ("The program is running. Quit anyway (and kill it)? ")) - target_kill (); - else - error ("Not confirmed."); - } + target_kill (); } + /* UDI wants this, to kill the TIP. */ target_close (1); @@ -2803,9 +3300,33 @@ quit_command (args, from_tty) if (write_history_p && history_filename) write_history (history_filename); + do_final_cleanups (ALL_CLEANUPS); /* Do any final cleanups before exiting */ + +#if defined(TUI) + /* tuiDo((TuiOpaqueFuncPtr)tuiCleanUp); */ + /* The above does not need to be inside a tuiDo(), since + * it is not manipulating the curses screen, but rather, + * it is tearing it down. + */ + if (tui_version) + tuiCleanUp (); +#endif + exit (exit_code); } +/* Handle the quit command. */ + +void +quit_command (args, from_tty) + char *args; + int from_tty; +{ + if (!quit_confirm ()) + error ("Not confirmed."); + quit_force (args, from_tty); +} + /* Returns whether GDB is running on a terminal and whether the user desires that questions be asked of them on that terminal. */ @@ -2821,12 +3342,13 @@ pwd_command (args, from_tty) char *args; int from_tty; { - if (args) error ("The \"pwd\" command does not take an argument: %s", args); + if (args) + error ("The \"pwd\" command does not take an argument: %s", args); getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)); if (!STREQ (gdb_dirbuf, current_directory)) printf_unfiltered ("Working directory %s\n (canonically %s).\n", - current_directory, gdb_dirbuf); + current_directory, gdb_dirbuf); else printf_unfiltered ("Working directory %s.\n", current_directory); } @@ -2854,13 +3376,32 @@ cd_command (dir, from_tty) if (chdir (dir) < 0) perror_with_name (dir); +#if defined(_WIN32) || defined(__MSDOS__) + /* There's too much mess with DOSish names like "d:", "d:.", + "d:./foo" etc. Instead of having lots of special #ifdef'ed code, + simply get the canonicalized name of the current directory. */ + dir = getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)); +#endif + len = strlen (dir); - dir = savestring (dir, len - (len > 1 && SLASH_P(dir[len-1]))); - if (ROOTED_P(dir)) + if (SLASH_P (dir[len-1])) + { + /* Remove the trailing slash unless this is a root directory + (including a drive letter on non-Unix systems). */ + if (!(len == 1) /* "/" */ +#if defined(_WIN32) || defined(__MSDOS__) + && !(!SLASH_P (*dir) && ROOTED_P (dir) && len <= 3) /* "d:/" */ +#endif + ) + len--; + } + + dir = savestring (dir, len); + if (ROOTED_P (dir)) current_directory = dir; else { - if (SLASH_P (current_directory[0]) && current_directory[1] == '\0') + if (SLASH_P (current_directory[strlen (current_directory) - 1])) current_directory = concat (current_directory, dir, NULL); else current_directory = concat (current_directory, SLASH_STRING, dir, NULL); @@ -2880,9 +3421,9 @@ cd_command (dir, from_tty) if (found_real_path) { /* Search backwards for the directory just before the "/.." - and obliterate it and the "/..". */ + and obliterate it and the "/..". */ char *q = p; - while (q != current_directory && ! SLASH_P (q[-1])) + while (q != current_directory && !SLASH_P (q[-1])) --q; if (q == current_directory) @@ -2913,7 +3454,8 @@ cd_command (dir, from_tty) pwd_command ((char *) 0, 1); } -struct source_cleanup_lines_args { +struct source_cleanup_lines_args +{ int old_line; char *old_file; char *old_pre_error; @@ -2925,7 +3467,7 @@ source_cleanup_lines (args) PTR args; { struct source_cleanup_lines_args *p = - (struct source_cleanup_lines_args *)args; + (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; @@ -2953,10 +3495,15 @@ source_command (args, from_tty) old_cleanups = make_cleanup (free, file); stream = fopen (file, FOPEN_RT); - if (stream == 0) - perror_with_name (file); + if (!stream) + { + if (from_tty) + perror_with_name (file); + else + return; + } - make_cleanup (fclose, stream); + make_cleanup ((make_cleanup_func) fclose, stream); old_lines.old_line = source_line_number; old_lines.old_file = source_file_name; @@ -3021,102 +3568,14 @@ echo_command (text, from_tty) gdb_flush (gdb_stdout); } - -#ifdef TARGET_BYTE_ORDER_SELECTABLE - -/* Functions to manipulate the endianness of the target. */ - -#ifndef TARGET_BYTE_ORDER_DEFAULT -#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN -#endif - -int target_byte_order = TARGET_BYTE_ORDER_DEFAULT; - -static int target_byte_order_auto = 1; - -/* Called if the user enters ``set endian'' without an argument. */ -static void -set_endian (args, from_tty) - char *args; - int from_tty; -{ - printf_unfiltered ("\"set endian\" must be followed by \"auto\", \"big\" or \"little\".\n"); - show_endian (args, from_tty); -} - -/* Called by ``set endian big''. */ -static void -set_endian_big (args, from_tty) - char *args; - int from_tty; -{ - target_byte_order = BIG_ENDIAN; - target_byte_order_auto = 0; -} - -/* Called by ``set endian little''. */ -static void -set_endian_little (args, from_tty) - char *args; - int from_tty; -{ - target_byte_order = LITTLE_ENDIAN; - target_byte_order_auto = 0; -} - -/* Called by ``set endian auto''. */ -static void -set_endian_auto (args, from_tty) - char *args; - int from_tty; -{ - target_byte_order_auto = 1; -} - -/* Called by ``show endian''. */ +/* ARGSUSED */ static void -show_endian (args, from_tty) - char *args; +dont_repeat_command (ignored, from_tty) + char *ignored; int from_tty; { - const char *msg = - (target_byte_order_auto - ? "The target endianness is set automatically (currently %s endian)\n" - : "The target is assumed to be %s endian\n"); - printf_unfiltered ((char *) msg, TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"); -} - -#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */ - -/* Set the endianness from a BFD. */ -void -set_endian_from_file (abfd) - bfd *abfd; -{ -#ifdef TARGET_BYTE_ORDER_SELECTABLE - int want; - - if (abfd->xvec->byteorder_big_p) - want = BIG_ENDIAN; - else - want = LITTLE_ENDIAN; - if (target_byte_order_auto) - target_byte_order = want; - else if (target_byte_order != want) - warning ("%s endian file does not match %s endian target.", - want == BIG_ENDIAN ? "big" : "little", - TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"); - -#else /* ! defined (TARGET_BYTE_ORDER_SELECTABLE) */ - - if (abfd->xvec->byteorder_big_p - ? TARGET_BYTE_ORDER != BIG_ENDIAN - : TARGET_BYTE_ORDER == BIG_ENDIAN) - warning ("%s endian file does not match %s endian target.", - abfd->xvec->byteorder_big_p ? "big" : "little", - TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"); - -#endif /* ! defined (TARGET_BYTE_ORDER_SELECTABLE) */ + *line = 0; /* Can't call dont_repeat here because we're not + necessarily reading from stdin. */ } /* Functions to manipulate command line editing control variables. */ @@ -3183,7 +3642,7 @@ show_commands (args, from_tty) for (offset = num; offset < num + Hist_print && offset < hist_len; offset++) { printf_filtered ("%5d %s\n", history_base + offset, - (history_get (history_base + offset))->line); + (history_get (history_base + offset))->line); } /* The next command we want to display is the next one that we haven't @@ -3267,15 +3726,15 @@ set_verbose (args, from_tty, c) static void float_handler (signo) -int 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."); } - + static void init_cmd_lists () { @@ -3283,22 +3742,19 @@ init_cmd_lists () infolist = NULL; enablelist = NULL; disablelist = NULL; + togglelist = NULL; + stoplist = NULL; deletelist = NULL; enablebreaklist = NULL; setlist = NULL; unsetlist = NULL; showlist = NULL; -#ifdef TARGET_BYTE_ORDER_SELECTABLE - endianlist = NULL; -#endif sethistlist = NULL; showhistlist = NULL; unsethistlist = NULL; -#if MAINTENANCE_CMDS maintenancelist = NULL; maintenanceinfolist = NULL; maintenanceprintlist = NULL; -#endif setprintlist = NULL; showprintlist = NULL; setchecklist = NULL; @@ -3312,7 +3768,7 @@ init_cmd_lists () */ void -init_history() +init_history () { char *tmpenv; @@ -3326,13 +3782,19 @@ init_history() 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 - directories the file written will be the same as the one - that was read. */ - history_filename = concat (current_directory, "/.gdb_history", NULL); - } + history_filename = savestring (tmpenv, strlen (tmpenv)); + 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. */ +#ifdef __MSDOS__ + /* No leading dots in file names are allowed on MSDOS. */ + history_filename = concat (current_directory, "/_gdb_history", NULL); +#else + history_filename = concat (current_directory, "/.gdb_history", NULL); +#endif + } read_history (history_filename); } @@ -3341,27 +3803,35 @@ init_main () { struct cmd_list_element *c; -#ifdef TARGET_BYTE_ORDER_SELECTABLE - - add_prefix_cmd ("endian", class_support, set_endian, - "Set endianness of target.", - &endianlist, "set endian ", 0, &setlist); - add_cmd ("big", class_support, set_endian_big, - "Set target as being big endian.", &endianlist); - add_cmd ("little", class_support, set_endian_little, - "Set target as being little endian.", &endianlist); - add_cmd ("auto", class_support, set_endian_auto, - "Select target endianness automatically.", &endianlist); - add_cmd ("endian", class_support, show_endian, - "Show endianness of target.", &showlist); - -#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */ - + /* If we are running the asynchronous version, + we initialize the prompts differently. */ + if (!async_p) + { +#ifdef DEFAULT_PROMPT + gdb_prompt_string = savestring (DEFAULT_PROMPT, strlen (DEFAULT_PROMPT)); +#else + gdb_prompt_string = savestring ("(gdb) ", 6); +#endif + } + else + { + /* initialize the prompt stack to a simple "(gdb) " prompt or to + whatever the DEFAULT_PROMPT is. */ + the_prompts.top = 0; + PREFIX (0) = ""; #ifdef DEFAULT_PROMPT - prompt = savestring (DEFAULT_PROMPT, strlen(DEFAULT_PROMPT)); + PROMPT (0) = savestring (DEFAULT_PROMPT, strlen (DEFAULT_PROMPT)); #else - prompt = savestring ("(gdb) ", 6); + PROMPT (0) = savestring ("(gdb) ", 6); #endif + SUFFIX (0) = ""; + /* Set things up for annotation_level > 1, if the user ever decides + to use it. */ + async_annotation_suffix = "prompt"; + /* Set the variable associated with the setshow prompt command. */ + new_async_prompt = savestring (PROMPT (0), strlen (PROMPT (0))); + } + gdb_prompt_escape = 0; /* default to none. */ /* Set the important stuff up for command editing. */ command_editing_p = 1; @@ -3389,7 +3859,8 @@ well documented as user commands.", The commands in this class are those defined by the user.\n\ Use the \"define\" command to define a command.", &cmdlist); add_cmd ("support", class_support, NO_FUNCTION, "Support facilities.", &cmdlist); - add_cmd ("status", class_info, NO_FUNCTION, "Status inquiries.", &cmdlist); + if (!dbx_commands) + add_cmd ("status", class_info, NO_FUNCTION, "Status inquiries.", &cmdlist); add_cmd ("files", class_files, NO_FUNCTION, "Specifying and examining files.", &cmdlist); add_cmd ("breakpoints", class_breakpoint, NO_FUNCTION, "Making program stop at certain points.", &cmdlist); add_cmd ("data", class_vars, NO_FUNCTION, "Examining data.", &cmdlist); @@ -3404,17 +3875,39 @@ The commands below can be used to select other frames by number or address.", add_cmd ("running", class_run, NO_FUNCTION, "Running the program.", &cmdlist); add_com ("pwd", class_files, pwd_command, - "Print working directory. This is used for your program as well."); + "Print working directory. This is used for your program as well."); c = add_cmd ("cd", class_files, cd_command, - "Set working directory to DIR for debugger and program being debugged.\n\ + "Set working directory to DIR for debugger and program being debugged.\n\ The change does not take effect for the program being debugged\n\ until the next time it is started.", &cmdlist); c->completer = filename_completer; + /* The set prompt command is different depending whether or not the + async version is run. NOTE: this difference is going to + disappear as we make the event loop be the default engine of + gdb. */ + if (!async_p) + { + add_show_from_set + (add_set_cmd ("prompt", class_support, var_string, + (char *) &gdb_prompt_string, "Set gdb's prompt", + &setlist), + &showlist); + } + else + { + c = add_set_cmd ("prompt", class_support, var_string, + (char *) &new_async_prompt, "Set gdb's prompt", + &setlist); + add_show_from_set (c, &showlist); + c->function.sfunc = set_async_prompt; + } + add_show_from_set - (add_set_cmd ("prompt", class_support, var_string, (char *)&prompt, - "Set gdb's prompt", - &setlist), + (add_set_cmd ("prompt-escape-char", class_support, var_zinteger, + (char *) &gdb_prompt_escape, + "Set escape character for formatting of gdb's prompt", + &setlist), &showlist); add_com ("echo", class_support, echo_command, @@ -3438,13 +3931,13 @@ Commands defined in this way may have up to ten arguments."); #ifdef __STDC__ c = add_cmd ("source", class_support, source_command, - "Read commands from a file named FILE.\n\ + "Read commands from a file named FILE.\n\ Note that the file \"" GDBINIT_FILENAME "\" is read automatically in this way\n\ when gdb is started.", &cmdlist); #else /* Punt file name, we can't help it easily. */ c = add_cmd ("source", class_support, source_command, - "Read commands from a file named FILE.\n\ + "Read commands from a file named FILE.\n\ Note that the file \".gdbinit\" is read automatically in this way\n\ when gdb is started.", &cmdlist); #endif @@ -3455,21 +3948,41 @@ when gdb is started.", &cmdlist); add_com_alias ("q", "quit", class_support, 1); add_com_alias ("h", "help", class_support, 1); + add_com ("dont-repeat", class_support, dont_repeat_command, "Don't repeat this command.\n\ +Primarily used inside of user-defined commands that should not be repeated when\n\ +hitting return."); - c = add_set_cmd ("verbose", class_support, var_boolean, (char *)&info_verbose, + c = add_set_cmd ("verbose", class_support, var_boolean, (char *) &info_verbose, "Set ", &setlist), - add_show_from_set (c, &showlist); + add_show_from_set (c, &showlist); c->function.sfunc = set_verbose; set_verbose (NULL, 0, c); - add_show_from_set - (add_set_cmd ("editing", class_support, var_boolean, (char *)&command_editing_p, - "Set editing of command lines as they are typed.\n\ -Use \"on\" to enable to enable the editing, and \"off\" to disable it.\n\ + /* The set editing command is different depending whether or not the + async version is run. NOTE: this difference is going to disappear + as we make the event loop be the default engine of gdb. */ + if (!async_p) + { + add_show_from_set + (add_set_cmd ("editing", class_support, var_boolean, (char *) &command_editing_p, + "Set editing of command lines as they are typed.\n\ +Use \"on\" to enable the editing, and \"off\" to disable it.\n\ Without an argument, command line editing is enabled. To edit, use\n\ EMACS-like or VI-like commands like control-P or ESC.", &setlist), - &showlist); + &showlist); + } + else + { + c = add_set_cmd ("editing", class_support, var_boolean, (char *) &async_command_editing_p, + "Set editing of command lines as they are typed.\n\ +Use \"on\" to enable the editing, and \"off\" to disable it.\n\ +Without an argument, command line editing is enabled. To edit, use\n\ +EMACS-like or VI-like commands like control-P or ESC.", &setlist); + + add_show_from_set (c, &showlist); + c->function.sfunc = set_async_editing_command; + } add_prefix_cmd ("history", class_support, set_history, "Generic command for setting command history parameters.", @@ -3479,39 +3992,39 @@ EMACS-like or VI-like commands like control-P or ESC.", &setlist), &showhistlist, "show history ", 0, &showlist); add_show_from_set - (add_set_cmd ("expansion", no_class, var_boolean, (char *)&history_expansion_p, - "Set history expansion on command input.\n\ + (add_set_cmd ("expansion", no_class, var_boolean, (char *) &history_expansion_p, + "Set history expansion on command input.\n\ Without an argument, history expansion is enabled.", &sethistlist), &showhistlist); add_show_from_set - (add_set_cmd ("save", no_class, var_boolean, (char *)&write_history_p, - "Set saving of the history record on exit.\n\ -Use \"on\" to enable to enable the saving, and \"off\" to disable it.\n\ + (add_set_cmd ("save", no_class, var_boolean, (char *) &write_history_p, + "Set saving of the history record on exit.\n\ +Use \"on\" to enable the saving, and \"off\" to disable it.\n\ Without an argument, saving is enabled.", &sethistlist), &showhistlist); - c = add_set_cmd ("size", no_class, var_integer, (char *)&history_size, + c = add_set_cmd ("size", no_class, var_integer, (char *) &history_size, "Set the size of the command history, \n\ ie. the number of previous commands to keep a record of.", &sethistlist); add_show_from_set (c, &showhistlist); c->function.sfunc = set_history_size_command; add_show_from_set - (add_set_cmd ("filename", no_class, var_filename, (char *)&history_filename, - "Set the filename in which to record the command history\n\ + (add_set_cmd ("filename", no_class, var_filename, (char *) &history_filename, + "Set the filename in which to record the command history\n\ (the list of previous commands of which a record is kept).", &sethistlist), &showhistlist); add_show_from_set (add_set_cmd ("confirm", class_support, var_boolean, - (char *)&caution, + (char *) &caution, "Set whether to confirm potentially dangerous operations.", &setlist), &showlist); add_prefix_cmd ("info", class_info, info_command, - "Generic command for showing things about the program being debugged.", + "Generic command for showing things about the program being debugged.", &infolist, "info ", 0, &cmdlist); add_com_alias ("i", "info", class_info, 1); @@ -3534,13 +4047,13 @@ the previous command number shown.", "Show what version of GDB this is.", &showlist); add_com ("while", class_support, while_command, -"Execute nested commands WHILE the conditional expression is non zero.\n\ + "Execute nested commands WHILE the conditional expression is non zero.\n\ The conditional expression must follow the word `while' and must in turn be\n\ followed by a new line. The nested commands must be entered one per line,\n\ and should be terminated by the word `end'."); add_com ("if", class_support, if_command, -"Execute nested commands once IF the conditional expression is non zero.\n\ + "Execute nested commands once IF the conditional expression is non zero.\n\ The conditional expression must follow the word `if' and must in turn be\n\ followed by a new line. The nested commands must be entered one per line,\n\ and should be terminated by the word 'else' or `end'. If an else clause\n\ @@ -3549,16 +4062,47 @@ is used, the same rules apply to its nested commands as to the first ones."); /* 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, + 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\ + 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); + &showlist); + + add_show_from_set ( + add_set_cmd ("remotetimeout", no_class, var_integer, (char *) &remote_timeout, + "Set timeout limit to wait for target to respond.\n\ +This value is used to set the time limit for gdb to wait for a response\n\ +from the target.", &setlist), + &showlist); + + /* The set annotate command is different depending whether or not + the async version is run. NOTE: this difference is going to + disappear as we make the event loop be the default engine of + gdb. */ + if (!async_p) + { + c = add_set_cmd ("annotate", class_obscure, var_zinteger, + (char *) &annotation_level, "Set annotation_level.\n\ +0 == normal; 1 == fullname (for use when running under emacs)\n\ +2 == output annotated suitably for use by programs that control GDB.", + &setlist); + c = add_show_from_set (c, &showlist); + } + else + { + c = add_set_cmd ("annotate", class_obscure, var_zinteger, + (char *) &annotation_level, "Set annotation_level.\n\ +0 == normal; 1 == fullname (for use when running under emacs)\n\ +2 == output annotated suitably for use by programs that control GDB.", + &setlist); + add_show_from_set (c, &showlist); + c->function.sfunc = set_async_annotation_level; + } }