import gdb-1999-06-21 snapshot
authorJason Molenda <jmolenda@apple.com>
Mon, 21 Jun 1999 13:27:42 +0000 (13:27 +0000)
committerJason Molenda <jmolenda@apple.com>
Mon, 21 Jun 1999 13:27:42 +0000 (13:27 +0000)
18 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/alpha-tdep.c
gdb/doc/ChangeLog
gdb/doc/gdbint.texinfo
gdb/event-loop.c
gdb/event-loop.h
gdb/event-top.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/jv-exp.y
gdb/main.c
gdb/printcmd.c
gdb/source.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.c++/overload.exp
gdb/testsuite/lib/gdb.exp
gdb/top.c

index 8c72e762a333438de27b4c524dc33657a05ccef8..6a4c613a48cf93355b055673d98d07c423eac622 100644 (file)
@@ -1,3 +1,61 @@
+1999-06-18  Elena Zannoni  <ezannoni@kwikemart.cygnus.com>
+
+       * top.c: Move include of event-loop.h, to avoid redefinition of
+       NFDBITS.
+
+       * event-loop.c (create_file_handler): Do not do a realloc of the
+       pollfd structure of the notifier, unless there is already one.
+       Include <sys/types.h> for platforms that have no poll.
+       
+       * event-top.c: Fix prototype for _initialize_event_loop.
+       (_initialize_event_loop): Do something only if running in async
+       mode.
+
+1999-06-17  Jim Blandy  <jimb@zwingli.cygnus.com>
+
+       Make the '/c' print format use a true character type.  This is
+       more appropriate than builtin_type_char for languages other than
+       C, and C tolerates it.
+       * gdbtypes.c (builtin_type_true_char): New variable.
+       (build_gdbtypes): Initialize it.
+       * gdbtypes.h (builtin_type_true_char): New declaration.
+       * printcmd.c (print_scalar_formatted): When the format is 'c',
+       extract the value as a builtin_type_true_char.
+
+       * jv-exp.y (yylex): Say character literals are java_char_type, not
+       builtin_type_char.  Java treats the latter like `byte'.
+
+1999-06-17  Elena Zannoni  <ezannoni@kwikemart.cygnus.com>
+
+       * Makefile.in (top_h): Define.
+       (event-loop.o): Add dependencies on top.h and defs.h.
+       (event-top.o): Add dependency on terminal.h.
+       * event-loop.c: Get rid of #include <readline.h>.
+
+       * event-loop.h: Get rid of nested #include's. 
+       * event-loop.c: Rearrange includes to accomodate change in
+       event-loop.h. Include poll.h, not sys/poll.h.
+       * event-top.c: Ditto.
+       * main.c: Ditto.
+       
+1999-06-16  David Taylor  <taylor@louisiana.cygnus.com>
+
+       * alpha-tdep.c (alpha_pop_frame): if frame->proc_desc
+       is NULL, call find_proc_desc so we know how to restore
+       the registers.
+
+1999-06-15  Michael Snyder  <msnyder@cleaver.cygnus.com>
+
+       * event-top.c (start_event_loop): call get_prompt.
+       (display_gdb_prompt): call get_prompt.
+       (async_stop_sig): call get_prompt.
+
+1999-06-15  Elena Zannoni  <ezannoni@kwikemart.cygnus.com>
+
+       * event-loop.c (delete_file_handler): When positioning prev_ptr,
+       keep looping while the one after is not equal to file_ptr, instead
+       of equal.
+
 1999-06-14  Stan Shebs  <shebs@andros.cygnus.com>
 
        * MAINTAINERS: Add Jimmy Guo and Jim Blandy as HP testsuite and
@@ -12,7 +70,6 @@
        (read_command_lines): rename "prompt" to prompt_arg for clarity.
        (stop_sig): call get_prompt instead of reading prompt string directly.
        (command_loop): ditto.
-       (simplified_command_loop): ditto.
        (gdb_prompt_escape): New variable.  Esc char for prompt parameters.
        (get_prompt_1): New function, workhorse for get_prompt.
        (get_prompt): Completely rewrite.  Add functionality for a 
index 48baccfc87795b6189905c04b5942bf1eb5b7391..d2f2e4e31e641a1de1ed09deac65d7afe6e4d8a1 100644 (file)
@@ -219,7 +219,7 @@ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \
 ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
 ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
 
-VERSION = 19990614
+VERSION = 19990621
 DIST=gdb
 
 LINT=/usr/5bin/lint
@@ -436,6 +436,7 @@ gdbcmd_h =  gdbcmd.h $(command_h)
 
 defs_h =       defs.h xm.h tm.h nm.h config.status config.h gdbarch.h
 
+top_h =                top.h
 inferior_h =   inferior.h $(breakpoint_h)
 tracepoint_h = tracepoint.h
 ax_h =                 ax.h
@@ -1108,10 +1109,10 @@ eval.o: eval.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \
        $(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \
        gdb_string.h
 
-event-loop.o: event-loop.c $(event_loop_h)
+event-loop.o: event-loop.c $(defs_h) $(top_h) $(event_loop_h)
 
 event-top.o: event-top.c top.h $(readline_headers) \
-      $(defs_h) $(inferior_h) $(event_loop_h)
+      $(defs_h) $(inferior_h) $(event_loop_h) terminal.h
 
 exec.o: exec.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
        target.h language.h gdb_string.h
index 99fde377a75c22c6b1afe0b6c8f20dbd2b869927..7d851d94de3635f27e19b37f3a15b82b9040a5d9 100644 (file)
@@ -1114,6 +1114,15 @@ alpha_pop_frame()
 
   alpha_extra_func_info_t proc_desc = frame->proc_desc;
 
+  /* we need proc_desc to know how to restore the registers;
+     if it is NULL, construct (a temporary) one */
+  if (proc_desc == NULL)
+    proc_desc = find_proc_desc(frame->pc, frame->next);
+
+  /* Question: should we copy this proc_desc and save it in
+     frame->proc_desc?  If we do, who will free it?
+     For now, we don't save a copy... */
+
   write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
   if (frame->saved_regs == NULL)
     alpha_find_saved_regs (frame);
index f527a438fdabb211104614013b206323547de192..11124c70553769c2ce67a52693910c3755ef583a 100644 (file)
@@ -1,3 +1,8 @@
+Thu Jun 17 17:23:25 1999  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * gdbint.texinfo: Add an anti-printf exhortation, and update the
+       info about patch submission.
+
 Mon Jun  7 15:49:40 1999  Stan Shebs  <shebs@andros.cygnus.com>
 
        From Per Bothner  <bothner@cygnus.com>:
index 0793ddb22527ce02095752680bd65fd99dabecde..10e5278dbe5906f0d0a28edb7088924a4691a70a 100644 (file)
@@ -2474,6 +2474,7 @@ any system-independent file would (hooks, #if defined, etc.), and
 machines which are radically different don't need to use infptrace.c at
 all.
 
+Don't put debugging printfs in the code.
 
 @node Porting GDB
 
@@ -2682,9 +2683,8 @@ GDB users.  In general we like to get well designed enhancements.
 Thanks also for checking in advance about the best way to transfer the
 changes.
 
-The GDB maintainers will only install ``cleanly designed'' patches.  You
-may not always agree on what is clean design.
-@c @pxref{Coding Style}, @pxref{Clean Design}.
+The GDB maintainers will only install ``cleanly designed'' patches.
+This manual summarizes what we believe to be clean design for GDB.
 
 If the maintainers don't have time to put the patch in when it arrives,
 or if there is any question about a patch, it goes into a large queue
@@ -2693,55 +2693,51 @@ with everyone else's patches and bug reports.
 The legal issue is that to incorporate substantial changes requires a
 copyright assignment from you and/or your employer, granting ownership
 of the changes to the Free Software Foundation.  You can get the
-standard document for doing this by sending mail to
-@code{gnu@@prep.ai.mit.edu} and asking for it.  I recommend that people
-write in "All programs owned by the Free Software Foundation" as "NAME
-OF PROGRAM", so that changes in many programs (not just GDB, but GAS,
-Emacs, GCC, etc) can be contributed with only one piece of legalese
-pushed through the bureacracy and filed with the FSF.  I can't start
-merging changes until this paperwork is received by the FSF (their
-rules, which I follow since I maintain it for them).
+standard documents for doing this by sending mail to @code{gnu@@gnu.org}
+and asking for it.  We recommend that people write in "All programs
+owned by the Free Software Foundation" as "NAME OF PROGRAM", so that
+changes in many programs (not just GDB, but GAS, Emacs, GCC, etc) can be
+contributed with only one piece of legalese pushed through the
+bureacracy and filed with the FSF.  We can't start merging changes until
+this paperwork is received by the FSF (their rules, which we follow
+since we maintain it for them).
 
 Technically, the easiest way to receive changes is to receive each
-feature as a small context diff or unidiff, suitable for "patch".
-Each message sent to me should include the changes to C code and
-header files for a single feature, plus ChangeLog entries for each
-directory where files were modified, and diffs for any changes needed
-to the manuals (gdb/doc/gdb.texi or gdb/doc/gdbint.texi).  If there
-are a lot of changes for a single feature, they can be split down
-into multiple messages.
-
-In this way, if I read and like the feature, I can add it to the
+feature as a small context diff or unidiff, suitable for "patch".  Each
+message sent to me should include the changes to C code and header files
+for a single feature, plus ChangeLog entries for each directory where
+files were modified, and diffs for any changes needed to the manuals
+(gdb/doc/gdb.texinfo or gdb/doc/gdbint.texinfo).  If there are a lot of
+changes for a single feature, they can be split down into multiple
+messages.
+
+In this way, if we read and like the feature, we can add it to the
 sources with a single patch command, do some testing, and check it in.
-If you leave out the ChangeLog, I have to write one.  If you leave
-out the doc, I have to puzzle out what needs documenting.  Etc.
+If you leave out the ChangeLog, we have to write one.  If you leave
+out the doc, we have to puzzle out what needs documenting.  Etc.
 
-The reason to send each change in a separate message is that I will
-not install some of the changes.  They'll be returned to you with
-questions or comments.  If I'm doing my job, my message back to you
+The reason to send each change in a separate message is that we will not
+install some of the changes.  They'll be returned to you with questions
+or comments.  If we're doing our job correctly, the message back to you
 will say what you have to fix in order to make the change acceptable.
-The reason to have separate messages for separate features is so
-that other changes (which I @emph{am} willing to accept) can be installed
-while one or more changes are being reworked.  If multiple features
-are sent in a single message, I tend to not put in the effort to sort
-out the acceptable changes from the unacceptable, so none of the
-features get installed until all are acceptable.
-
-If this sounds painful or authoritarian, well, it is.  But I get a lot
-of bug reports and a lot of patches, and most of them don't get
-installed because I don't have the time to finish the job that the bug
+The reason to have separate messages for separate features is so that
+the acceptable changes can be installed while one or more changes are
+being reworked.  If multiple features are sent in a single message, we
+tend to not put in the effort to sort out the acceptable changes from
+the unacceptable, so none of the features get installed until all are
+acceptable.
+
+If this sounds painful or authoritarian, well, it is.  But we get a lot
+of bug reports and a lot of patches, and many of them don't get
+installed because we don't have the time to finish the job that the bug
 reporter or the contributor could have done.  Patches that arrive
 complete, working, and well designed, tend to get installed on the day
-they arrive.  The others go into a queue and get installed if and when
-I scan back over the queue -- which can literally take months
-sometimes.  It's in both our interests to make patch installation easy
--- you get your changes installed, and I make some forward progress on
-GDB in a normal 12-hour day (instead of them having to wait until I
-have a 14-hour or 16-hour day to spend cleaning up patches before I
-can install them).
+they arrive.  The others go into a queue and get installed as time
+permits, which, since the maintainers have many demands to meet, may not
+be for quite some time.
 
 Please send patches directly to the GDB maintainers at
-@code{gdb-patches@@cygnus.com}.
+@code{gdb-patches@@sourceware.cygnus.com}.
 
 @section Obsolete Conditionals
 
index 77f46bb6478a92ffca4fde956d8ad37c4901a1fd..fc20df10bb9f9c94c8ea2f45b15eb7c02c57eb09 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
-#include "event-loop.h"
-#include <readline/readline.h>
-#include <setjmp.h>
-#include "top.h"
-
-/* For config.h which may define HAVE_POLL */
 #include "defs.h"
-
+#include "top.h"
+#include "event-loop.h"
 #ifdef HAVE_POLL
-#include <sys/poll.h>
+#include <poll.h>
+#else
+#include <sys/types.h>
 #endif
 #include <errno.h>
+#include <setjmp.h>
 
 /* Event queue:  
    - the first event in the queue is the head of the queue. 
@@ -337,9 +335,13 @@ create_file_handler (fd, mask, proc, client_data)
 #ifdef HAVE_POLL
 
   gdb_notifier.num_fds++;
-  gdb_notifier.poll_fds =
-    (struct pollfd *) realloc (gdb_notifier.poll_fds,
-                          (gdb_notifier.num_fds) * sizeof (struct pollfd));
+  if (gdb_notifier.poll_fds)
+    gdb_notifier.poll_fds =
+      (struct pollfd *) realloc (gdb_notifier.poll_fds,
+                                (gdb_notifier.num_fds) * sizeof (struct pollfd));
+  else
+     gdb_notifier.poll_fds = 
+       (struct pollfd *) xmalloc (sizeof (struct pollfd));
   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd;
   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask;
   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0;
@@ -463,7 +465,7 @@ delete_file_handler (fd)
   else
     {
       for (prev_ptr = gdb_notifier.first_file_handler;
-          prev_ptr->next_file == file_ptr;
+          prev_ptr->next_file != file_ptr;
           prev_ptr = prev_ptr->next_file)
        ;
       prev_ptr->next_file = file_ptr->next_file;
index 5debe0f2e694174d81c4827f7b36f4e1ef67dda0..5305a673bc84f454c009bba2e6f7428b7c21dcb8 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#include "defs.h"
-
 /* An event loop listens for events from multiple event sources. When
    an event arrives, it is queued and processed by calling the
    appropriate event handler. The event loop then continues to listen
index ad269eb25fac6ae04327454fc71a9ce1cfc042bf..f658b715d50234e2df0232e690b5412dbfa9e08c 100644 (file)
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
 #include "defs.h"
-#include "event-loop.h"
 #include "top.h"
 #ifdef HAVE_POLL
-#include <sys/poll.h>
+#include <poll.h>
 #endif
 #include "inferior.h"
 #include "terminal.h" /* for job_control*/
+#include <signal.h>
+#include "event-loop.h"
 
 /* readline include files */
 #include <readline/readline.h>
@@ -34,7 +35,7 @@
 /* readline defines this.  */
 #undef savestring
 
-extern void _initialize_event_loop (void);
+extern void _initialize_event_loop PARAMS ((void));
 
 static void command_line_handler PARAMS ((char *));
 static void gdb_readline2 PARAMS ((void));
@@ -165,6 +166,7 @@ start_event_loop ()
 {
   int length;
   char *a_prompt;
+  char *gdb_prompt = get_prompt ();
 
   /* If we are using readline, set things up and display the first
      prompt, otherwise just print the prompt. */
@@ -173,10 +175,10 @@ start_event_loop ()
       /* Tell readline what the prompt to display is and what function it
         will need to call after a whole line is read. This also displays
         the first prompt.*/
-      length = strlen (PREFIX (0)) + strlen (PROMPT (0)) + strlen (SUFFIX (0)) + 1;
+      length = strlen (PREFIX (0)) + strlen (gdb_prompt) + strlen (SUFFIX (0)) + 1;
       a_prompt = (char *) xmalloc (length);
       strcpy (a_prompt, PREFIX (0));
-      strcat (a_prompt, PROMPT (0));
+      strcat (a_prompt, gdb_prompt);
       strcat (a_prompt, SUFFIX (0));
       rl_callback_handler_install (a_prompt, input_handler);
     }
@@ -251,19 +253,20 @@ display_gdb_prompt (new_prompt)
      char *new_prompt;
 {
   int prompt_length = 0;
+  char *gdb_prompt  = get_prompt ();
 
   if (!new_prompt)
     {
       /* Just use the top of the prompt stack. */
       prompt_length = strlen (PREFIX (0)) +
        strlen (SUFFIX (0)) +
-       strlen (PROMPT (0)) + 1;
+       strlen (gdb_prompt) + 1;
 
       new_prompt = (char *) alloca (prompt_length);
 
       /* Prefix needs to have new line at end. */
       strcpy (new_prompt, PREFIX (0));
-      strcat (new_prompt, PROMPT (0));
+      strcat (new_prompt, gdb_prompt);
       /* Suffix needs to have a new line at end and \032 \032 at
          beginning. */
       strcat (new_prompt, SUFFIX (0));
@@ -894,7 +897,7 @@ static void
 async_stop_sig (arg)
      gdb_client_data arg;
 {
- char *prompt = PROMPT (0);
+ char *prompt = get_prompt ();
 #if STOP_SIGNAL == SIGTSTP
   signal (SIGTSTP, SIG_DFL);
   sigsetmask (0);
@@ -983,34 +986,38 @@ set_async_prompt (args, from_tty, c)
 void
 _initialize_event_loop ()
 {
-  /* When a character is detected on instream by select or poll, readline
-     will be invoked via this callback function. */
-  call_readline = rl_callback_read_char;
-
-  /* When readline has read an end-of-line character, it passes the
-     complete line to gdb for processing. command_line_handler is the
-     function that does this. */
-  input_handler = command_line_handler;
-
-  /* Tell readline to use the same input stream that gdb uses. */
-  rl_instream = instream;
-
-  /* Get a file descriptor for the input stream, so that we can
-     register it with the event loop. */
-  input_fd = fileno (instream);
-
-  /* Now we need to create the event sources for the input file descriptor. */
-  /* At this point in time, this is the only event source that we
-     register with the even loop. Another source is going to be the
-     target program (inferior), but that must be registered only when
-     it actually exists (I.e. after we say 'run' or after we connect
-     to a remote target. */
+  if (async_p)
+    {
+      /* When a character is detected on instream by select or poll,
+        readline will be invoked via this callback function. */
+      call_readline = rl_callback_read_char;
+
+      /* When readline has read an end-of-line character, it passes
+        the complete line to gdb for processing. command_line_handler
+        is the function that does this. */
+      input_handler = command_line_handler;
+
+      /* Tell readline to use the same input stream that gdb uses. */
+      rl_instream = instream;
+
+      /* Get a file descriptor for the input stream, so that we can
+        register it with the event loop. */
+      input_fd = fileno (instream);
+
+      /* Now we need to create the event sources for the input file
+         descriptor. */
+      /* At this point in time, this is the only event source that we
+        register with the even loop. Another source is going to be
+        the target program (inferior), but that must be registered
+        only when it actually exists (I.e. after we say 'run' or
+        after we connect to a remote target. */
 #ifdef HAVE_POLL
-  create_file_handler (input_fd, POLLIN,
-                      (file_handler_func *) call_readline, 0);
+      create_file_handler (input_fd, POLLIN,
+                          (file_handler_func *) call_readline, 0);
 #else
-  create_file_handler (input_fd, GDB_READABLE,
-                      (file_handler_func *) call_readline, 0);
+      create_file_handler (input_fd, GDB_READABLE,
+                          (file_handler_func *) call_readline, 0);
 #endif
+    }
 }
 
index 64407668b824d5112535cf9a3c35c22f3751f68a..1037be72a2b80143de33077c96a4bf958fec17e2 100644 (file)
@@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 struct type *builtin_type_void;
 struct type *builtin_type_char;
+struct type *builtin_type_true_char;
 struct type *builtin_type_short;
 struct type *builtin_type_int;
 struct type *builtin_type_long;
@@ -2777,7 +2778,10 @@ build_gdbtypes ()
               0,
               "char", (struct objfile *) NULL);
   TYPE_FLAGS (builtin_type_char) |= TYPE_FLAG_NOSIGN;
-  
+  builtin_type_true_char = 
+    init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+              0,
+              "true character", (struct objfile *) NULL);
   builtin_type_signed_char =
     init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
               0,
index 5b7d77d07632df09e9ce9fe0d1b59e914886693c..92ecd9ab738ddc299c738f3ed9001ce75492fb1f 100644 (file)
@@ -844,6 +844,11 @@ extern struct type *builtin_type_uint32;
 extern struct type *builtin_type_int64;
 extern struct type *builtin_type_uint64;
 
+/* We use this for the '/c' print format, because builtin_type_char is
+   just a one-byte integral type, which languages less laid back than
+   C will print as ... well, a one-byte integral type.  */
+extern struct type *builtin_type_true_char;
+
 /* This type represents a type that was unrecognized in symbol
    read-in.  */
 
index d17c4f3a8b94995b90f61d45d480458d1408192c..be5b590a36074ce65dbd30612da983dc9013a6c0 100644 (file)
@@ -899,7 +899,7 @@ yylex ()
        error ("Empty character constant.");
 
       yylval.typed_val_int.val = c;
-      yylval.typed_val_int.type = builtin_type_char;
+      yylval.typed_val_int.type = java_char_type;
 
       c = *lexptr++;
       if (c != '\'')
index db624b23c2c100ddd93c456a6893e09681a517df..12522ff77dccd212c1f9c77e8690337f0b53a12c 100644 (file)
@@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "top.h"
-#include "event-loop.h"
 #include "target.h"
 #include "inferior.h"
 #include "call-cmds.h"
@@ -35,6 +34,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include <ctype.h>
 
 #include "gdb_string.h"
+#include "event-loop.h"
 
 /* If nonzero, display time usage both at startup and for each command.  */
 
index 306fa7449eb73ab03462fdcf848a29436730ae5f..839d1c14bfcd35edc61567c82d8f1823410541b6 100644 (file)
@@ -442,8 +442,8 @@ print_scalar_formatted (valaddr, type, format, size, stream)
       break;
 
     case 'c':
-      value_print (value_from_longest (builtin_type_char, val_long), stream, 0,
-                  Val_pretty_default);
+      value_print (value_from_longest (builtin_type_true_char, val_long),
+                  stream, 0, Val_pretty_default);
       break;
 
     case 'f':
index 2ee51b6a2b8160ab8a2d1ead1f3d3c5ba31be8ba..2d80b77064645f37a054eeb0d654497b7ffa7c3a 100644 (file)
@@ -994,7 +994,6 @@ print_source_lines_base (s, line, stopline, noerror)
   current_source_line = line;
   first_line_listed = line;
 
-
   /* Only prints "No such file or directory" once */
   if ((s != last_source_visited) || (! last_source_error))
     {
index 2014e7fa0443a2b939c76242fb432040dc4ad908..93630d27034999d7ec036ce18ff82d90aa5caf68 100644 (file)
@@ -1,3 +1,24 @@
+1999-06-18  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * gdb.c++/overload.exp: XFAIL everything if using G++, add a
+       simpler match case for the ptype of the big class.
+
+1999-06-16  Fernando Nasser  <fnasser@totem.to.cygnus.com>
+
+       * gdb.exp: Fix test for gdb_prompt existence.
+
+1999-06-16  Fernando Nasser  <fnasser@totem.to.cygnus.com>
+
+       * gdb.exp (gdb_test): Add fail after calls to perror.
+
+1999-06-16  Fernando Nasser  <fnasser@totem.to.cygnus.com>
+
+       * gdb.exp (gdb_test): Accept variations of Undefined command messages.
+
+1999-06-16  Fernando Nasser  <fnasser@totem.to.cygnus.com>
+
+       * gdb.exp (gdb_test): Fix anchors on gdb_expect statement.
+
 Fri Jun 11 12:56:50 1999  Andrew Cagney  <cagney@b1.cygnus.com>
 
        * gdb.base/call-strs.c (link_malloc): New function.  Ensure that
index b1ddb16303a46bbfe754ca9936806846360480a9..e77d2dc9704def0d56a1ab5d16ba73e07d95be5e 100644 (file)
@@ -43,6 +43,12 @@ if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
      gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
 }
 
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile} "c++"] {
+    return -1
+}
 
 gdb_exit
 gdb_start
@@ -87,6 +93,9 @@ gdb_expect {
   -re "type = class foo \{.*public:.*int ifoo;.*const char \\*ccpfoo;.*foo\\(int\\);.*foo\\(int, (const char|char const) \\*\\);.*foo\\(foo &\\);.*~foo\\(void\\);.*void foofunc\\(int\\);.*void foofunc\\(int, signed char \\*\\);.*int overload1arg\\(void\\);.*int overload1arg\\(char\\);.*int overload1arg\\(signed char\\);.*int overload1arg\\(unsigned char\\);.*int overload1arg\\(short\\);.*int overload1arg\\(unsigned short\\);.*int overload1arg\\(int\\);.*int overload1arg\\(unsigned int\\);.*int overload1arg\\(long\\);.*int overload1arg\\(unsigned long\\);.*int overload1arg\\(float\\);.*int overload1arg\\(double\\);.*int overloadargs\\(int\\);.*int overloadargs\\(int, int\\);.*int overloadargs\\(int, int, int\\);.*int overloadargs\\(int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int, int, int, int\\);.*int overloadargs\\(int, int, int, int, int, int, int, int, int, int, int\\);\r\n\}\r\n$gdb_prompt $" {
         pass "ptype foo_instance1 (HP aCC -- known quirk with ~foo parameter list)"
       }
+    -re "type = class foo .*int overloadargs\\(int, int, int, int, int, int, int, int, int, int, int\\);\r\n\}\r\n$gdb_prompt $" {
+       pass "ptype foo_instance1 (shorter match)"
+    }
     -re ".*$gdb_prompt $" { fail "ptype foo_instance1" }
     timeout           { fail "(timeout) ptype foo_instance1" }
   }
@@ -110,6 +119,11 @@ gdb_expect {
   }
 
 
+# The overload resolver added by HP (valops.c:find_overload_match) doesn't
+# work right for G++ output, since the list of parameters seems not to
+# be filled in correctly.  Until this gets fixed, don't expect to pass
+# these tests.
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
 
 send_gdb "print foo_instance1.overloadargs(1)\n"
 gdb_expect {
@@ -120,6 +134,9 @@ gdb_expect {
     timeout           { fail "(timeout) print call overloaded func 1 arg" }
   }
 
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2)\n"
 gdb_expect {
     -re ".\[0-9\]* = 2\r\n$gdb_prompt $" {
@@ -130,6 +147,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3)\n"
 gdb_expect {
     -re ".\[0-9\]* = 3\r\n$gdb_prompt $" {
@@ -140,6 +159,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4)\n"
 gdb_expect {
     -re ".\[0-9\]* = 4\r\n$gdb_prompt $" {
@@ -150,6 +171,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5)\n"
 gdb_expect {
     -re ".\[0-9\]* = 5\r\n$gdb_prompt $" {
@@ -160,6 +183,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6)\n"
 gdb_expect {
     -re ".\[0-9\]* = 6\r\n$gdb_prompt $" {
@@ -170,6 +195,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7)\n"
 gdb_expect {
     -re ".\[0-9\]* = 7\r\n$gdb_prompt $" {
@@ -180,6 +207,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8)\n"
 gdb_expect {
     -re ".\[0-9\]* = 8\r\n$gdb_prompt $" {
@@ -190,6 +219,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9)\n"
 gdb_expect {
     -re ".\[0-9\]* = 9\r\n$gdb_prompt $" {
@@ -200,6 +231,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)\n"
 gdb_expect {
     -re ".\[0-9\]* = 10\r\n$gdb_prompt $" {
@@ -210,6 +243,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overloadargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)\n"
 gdb_expect {
     -re ".\[0-9\]* = 11\r\n$gdb_prompt $" {
@@ -220,6 +255,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg()\n"
 gdb_expect {
     -re ".\[0-9\]* = 1\r\n$gdb_prompt $" {
@@ -229,6 +266,9 @@ gdb_expect {
     timeout           { fail "(timeout) print call overloaded func void arg" }
   }
 
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((char)arg2)\n"
 gdb_expect {
     -re ".\[0-9\]* = 2\r\n$gdb_prompt $" {
@@ -238,6 +278,9 @@ gdb_expect {
     timeout           { fail "(timeout) print call overloaded func char arg" }
   }
 
+
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((signed char)arg3)\n"
 gdb_expect {
     -re ".\[0-9\]* = 3\r\n$gdb_prompt $" {
@@ -248,6 +291,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((unsigned char)arg4)\n"
 gdb_expect {
     -re ".\[0-9\]* = 4\r\n$gdb_prompt $" {
@@ -258,6 +303,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((short)arg5)\n"
 gdb_expect {
     -re ".\[0-9\]* = 5\r\n$gdb_prompt $" {
@@ -268,6 +315,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((unsigned short)arg6)\n"
 gdb_expect {
     -re ".\[0-9\]* = 6\r\n$gdb_prompt $" {
@@ -278,6 +327,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((int)arg7)\n"
 gdb_expect {
     -re ".\[0-9\]* = 7\r\n$gdb_prompt $" {
@@ -288,6 +339,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((unsigned int)arg8)\n"
 gdb_expect {
     -re ".\[0-9\]* = 8\r\n$gdb_prompt $" {
@@ -298,6 +351,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((long)arg9)\n"
 gdb_expect {
     -re ".\[0-9\]* = 9\r\n$gdb_prompt $" {
@@ -308,6 +363,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((unsigned long)arg10)\n"
 gdb_expect {
     -re ".\[0-9\]* = 10\r\n$gdb_prompt $" {
@@ -318,6 +375,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((float)arg11)\n"
 gdb_expect {
     -re ".\[0-9\]* = 11\r\n$gdb_prompt $" {
@@ -328,6 +387,8 @@ gdb_expect {
   }
 
 
+if {$gcc_compiled} then { setup_xfail "*-*-*" }
+
 send_gdb "print foo_instance1.overload1arg((double)arg12)\n"
 gdb_expect {
     -re ".\[0-9\]* = 12\r\n$gdb_prompt $" {
index 0e9bd2957a7554bb94031433d728d4e64a0d094f..95ed5348b462727e4b8901daab94ab67a5aa0dab 100644 (file)
@@ -56,10 +56,10 @@ if ![info exists GDBFLAGS] {
 }
 verbose "using GDBFLAGS = $GDBFLAGS" 2
 
-# The variable prompt is a regexp which matches the gdb prompt.  Set it if it
-# is not already set.
+# The variable gdb_prompt is a regexp which matches the gdb prompt.
+# Set it if it is not already set.
 global gdb_prompt
-if ![info exists prompt] then {
+if ![info exists gdb_prompt] then {
     set gdb_prompt "\[(\]gdb\[)\]"
 }
 
@@ -414,7 +414,7 @@ proc gdb_test { args } {
             gdb_suppress_entire_file "GDB died";
             return -1;
         }
-        -re "Ending remote debugging.*$gdb_prompt$" {
+        -re "Ending remote debugging.*$gdb_prompt $" {
            if ![isnative] then {
                warning "Can`t communicate to remote target."
            }
@@ -432,12 +432,14 @@ proc gdb_test { args } {
            send_gdb "$response_string\n";
            exp_continue;
        }
-        -re "Undefined command:.*$gdb_prompt" {
+        -re "Undefined\[a-z\]* command:.*$gdb_prompt $" {
            perror "Undefined command \"$command\"."
+            fail "$message"
            set result 1
        }
         -re "Ambiguous command.*$gdb_prompt $" {
            perror "\"$command\" is not a unique command name."
+            fail "$message"
            set result 1
        }
         -re "Program exited with code \[0-9\]+.*$gdb_prompt $" {
@@ -467,10 +469,12 @@ proc gdb_test { args } {
         "<return>" {
            send_gdb "\n"
            perror "Window too small."
+            fail "$message"
        }
         -re "\\(y or n\\) " {
            send_gdb "n\n"
            perror "Got interactive prompt."
+            fail "$message"
        }
         eof {
             perror "Process no longer exists"
@@ -481,6 +485,7 @@ proc gdb_test { args } {
        }
         full_buffer {
            perror "internal buffer is full."
+            fail "$message"
        }
        timeout {
            if ![string match "" $message] then {
index 1f2a21724666ec20997477c48c527b5d46070e46..af5c40b27154340a99f9513866c5e9f28db52ee5 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -33,7 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "terminal.h" /* For job_control.  */
 #include "annotate.h"
 #include "top.h"
-#include "event-loop.h"
 
 /* readline include files */
 #include <readline/readline.h>
@@ -47,6 +46,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include <unistd.h>
 #endif
 
+#include "event-loop.h"
 #include "gdb_string.h"
 #include "gdb_stat.h"
 #include <ctype.h>
@@ -1422,3 +1422,2623 @@ command_loop ()
     }
 }
 
+\f
+/* Commands call this if they do not want to be repeated by null lines.  */
+
+void
+dont_repeat ()
+{
+  if (server_command)
+    return;
+
+  /* If we aren't reading from standard input, we are saving the last
+     thing read from stdin in line and don't want to delete it.  Null lines
+     won't repeat here in any case.  */
+  if (instream == stdin)
+    *line = 0;
+}
+\f
+/* Read a line from the stream "instream" without command line editing.
+
+   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 (prompt_arg)
+     char *prompt_arg;
+{
+  int c;
+  char *result;
+  int input_index = 0;
+  int result_size = 80;
+
+  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 (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. */
+      fputs_unfiltered ("\n", gdb_stdout);
+#endif /* MPW */
+      gdb_flush (gdb_stdout);
+    }
+
+  result = (char *) xmalloc (result_size);
+
+  while (1)
+    {
+      /* Read from stdin if we are executing a user defined command.
+        This is the right thing for prompt_for_continue, at least.  */
+      c = fgetc (instream ? instream : stdin);
+
+      if (c == EOF)
+       {
+         if (input_index > 0)
+           /* The last line does not end with a newline.  Return it, and
+              if we are called again fgetc will still return EOF and
+              we'll return NULL then.  */
+           break;
+         free (result);
+         return NULL;
+       }
+
+      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)
+       {
+         result_size *= 2;
+         result = (char *) xrealloc (result, result_size);
+       }
+    }
+
+  result[input_index++] = '\0';
+  return result;
+}
+
+/* Variables which control command line editing and history
+   substitution.  These variables are given default values at the end
+   of this file.  */
+static int command_editing_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;
+
+/* readline uses the word breaks for two things:
+   (1) In figuring out where to point the TEXT parameter to the
+   rl_completion_entry_function.  Since we don't use TEXT for much,
+   it doesn't matter a lot what the word breaks are for this purpose, but
+   it does affect how much stuff M-? lists.
+   (2) If one of the matches contains a word break character, readline
+   will quote it.  That's why we switch between
+   gdb_completer_word_break_characters and
+   gdb_completer_command_word_break_characters.  I'm not sure when
+   we need this behavior (perhaps for funky characters in C++ symbols?).  */
+
+/* Variables which are necessary for fancy command line editing.  */
+char *gdb_completer_word_break_characters =
+  " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,-";
+
+/* When completing on command names, we remove '-' from the list of
+   word break characters, since we use it in command names.  If the
+   readline library sees one in any of the current completion strings,
+   it thinks that the string needs to be quoted and automatically supplies
+   a leading quote. */
+char *gdb_completer_command_word_break_characters =
+  " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,";
+
+/* Characters that can be used to quote completion strings.  Note that we
+   can't include '"' because the gdb C parser treats such quoted sequences
+   as strings. */
+char *gdb_completer_quote_characters =
+  "'";
+
+/* Functions that are used as part of the fancy command line editing.  */
+
+/* This can be used for functions which don't want to complete on symbols
+   but don't want to complete on anything else either.  */
+/* ARGSUSED */
+char **
+noop_completer (text, prefix)
+     char *text;
+     char *prefix;
+{
+  return NULL;
+}
+
+/* Complete on filenames.  */
+char **
+filename_completer (text, word)
+     char *text;
+     char *word;
+{
+  /* From readline.  */
+  extern char *filename_completion_function PARAMS ((char *, int));
+  int subsequent_name;
+  char **return_val;
+  int return_val_used;
+  int return_val_alloced;
+
+  return_val_used = 0;
+  /* Small for testing.  */
+  return_val_alloced = 1;
+  return_val = (char **) xmalloc (return_val_alloced * sizeof (char *));
+
+  subsequent_name = 0;
+  while (1)
+    {
+      char *p;
+      p = filename_completion_function (text, subsequent_name);
+      if (return_val_used >= return_val_alloced)
+       {
+         return_val_alloced *= 2;
+         return_val =
+           (char **) xrealloc (return_val,
+                               return_val_alloced * sizeof (char *));
+       }
+      if (p == NULL)
+       {
+         return_val[return_val_used++] = p;
+         break;
+       }
+      /* Like emacs, don't complete on old versions.  Especially useful
+        in the "source" command.  */
+      if (p[strlen (p) - 1] == '~')
+       continue;
+
+      {
+       char *q;
+       if (word == text)
+         /* Return exactly p.  */
+         return_val[return_val_used++] = p;
+       else if (word > text)
+         {
+           /* Return some portion of p.  */
+           q = xmalloc (strlen (p) + 5);
+           strcpy (q, p + (word - text));
+           return_val[return_val_used++] = q;
+           free (p);
+         }
+       else
+         {
+           /* Return some of TEXT plus p.  */
+           q = xmalloc (strlen (p) + (text - word) + 5);
+           strncpy (q, word, text - word);
+           q[text - word] = '\0';
+           strcat (q, p);
+           return_val[return_val_used++] = q;
+           free (p);
+         }
+      }
+      subsequent_name = 1;
+    }
+#if 0
+  /* There is no way to do this just long enough to affect quote inserting
+     without also affecting the next completion.  This should be fixed in
+     readline.  FIXME.  */
+  /* Insure that readline does the right thing
+     with respect to inserting quotes.  */
+  rl_completer_word_break_characters = "";
+#endif
+  return return_val;
+}
+
+/* Here are some useful test cases for completion.  FIXME: These should
+   be put in the test suite.  They should be tested with both M-? and TAB.
+
+   "show output-" "radix"
+   "show output" "-radix"
+   "p" ambiguous (commands starting with p--path, print, printf, etc.)
+   "p "  ambiguous (all symbols)
+   "info t foo" no completions
+   "info t " no completions
+   "info t" ambiguous ("info target", "info terminal", etc.)
+   "info ajksdlfk" no completions
+   "info ajksdlfk " no completions
+   "info" " "
+   "info " ambiguous (all info commands)
+   "p \"a" no completions (string constant)
+   "p 'a" ambiguous (all symbols starting with a)
+   "p b-a" ambiguous (all symbols starting with a)
+   "p b-" ambiguous (all symbols)
+   "file Make" "file" (word break hard to screw up here)
+   "file ../gdb.stabs/we" "ird" (needs to not break word at slash)
+   */
+
+/* Generate completions one by one for the completer.  Each time we are
+   called return another potential completion to the caller.
+   line_completion just completes on commands or passes the buck to the
+   command's completer function, the stuff specific to symbol completion
+   is in make_symbol_completion_list.
+
+   TEXT is the caller's idea of the "word" we are looking at.
+
+   MATCHES is the number of matches that have currently been collected from
+   calling this completion function.  When zero, then we need to initialize,
+   otherwise the initialization has already taken place and we can just
+   return the next potential completion string.
+
+   LINE_BUFFER is available to be looked at; it contains the entire text
+   of the line.  POINT is the offset in that line of the cursor.  You
+   should pretend that the line ends at POINT.
+
+   Returns NULL if there are no more completions, else a pointer to a string
+   which is a possible completion, it is the caller's responsibility to
+   free the string.  */
+
+static char *
+line_completion_function (text, matches, line_buffer, point)
+     char *text;
+     int matches;
+     char *line_buffer;
+     int point;
+{
+  static char **list = (char **)NULL;          /* Cache of completions */
+  static int index;                            /* Next cached completion */
+  char *output = NULL;
+  char *tmp_command, *p;
+  /* Pointer within tmp_command which corresponds to text.  */
+  char *word;
+  struct cmd_list_element *c, *result_list;
+
+  if (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. */
+
+      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);
+       }
+      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.  */
+
+      rl_completer_word_break_characters =
+         gdb_completer_word_break_characters;
+
+      /* Decide whether to complete on a list of gdb commands or on symbols. */
+      tmp_command = (char *) alloca (point + 1);
+      p = tmp_command;
+
+      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.  */
+      word = tmp_command + point - strlen (text);
+
+      if (point == 0)
+       {
+         /* An empty line we want to consider ambiguous; that is, it
+            could be any command.  */
+         c = (struct cmd_list_element *) -1;
+         result_list = 0;
+       }
+      else
+       {
+         c = lookup_cmd_1 (&p, cmdlist, &result_list, 1);
+       }
+
+      /* Move p up to the next interesting thing.  */
+      while (*p == ' ' || *p == '\t')
+       {
+         p++;
+       }
+
+      if (!c)
+       {
+         /* It is an unrecognized command.  So there are no
+            possible completions.  */
+         list = NULL;
+       }
+      else if (c == (struct cmd_list_element *) -1)
+       {
+         char *q;
+
+         /* lookup_cmd_1 advances p up to the first ambiguous thing, but
+            doesn't advance over that thing itself.  Do so now.  */
+         q = p;
+         while (*q && (isalnum (*q) || *q == '-' || *q == '_'))
+           ++q;
+         if (q != tmp_command + point)
+           {
+             /* There is something beyond the ambiguous
+                command, so there are no possible completions.  For
+                example, "info t " or "info t foo" does not complete
+                to anything, because "info t" can be "info target" or
+                "info terminal".  */
+             list = NULL;
+           }
+         else
+           {
+             /* We're trying to complete on the command which was ambiguous.
+                This we can deal with.  */
+             if (result_list)
+               {
+                 list = complete_on_cmdlist (*result_list->prefixlist, p,
+                                             word);
+               }
+             else
+               {
+                 list = complete_on_cmdlist (cmdlist, p, word);
+               }
+             /* Insure that readline does the right thing with respect to
+                inserting quotes.  */
+             rl_completer_word_break_characters =
+               gdb_completer_command_word_break_characters;
+           }
+       }
+      else
+       {
+         /* We've recognized a full command.  */
+
+         if (p == tmp_command + point)
+           {
+             /* There is no non-whitespace in the line beyond the command.  */
+
+             if (p[-1] == ' ' || p[-1] == '\t')
+               {
+                 /* The command is followed by whitespace; we need to complete
+                    on whatever comes after command.  */
+                 if (c->prefixlist)
+                   {
+                     /* It is a prefix command; what comes after it is
+                        a subcommand (e.g. "info ").  */
+                     list = complete_on_cmdlist (*c->prefixlist, p, word);
+
+                     /* Insure that readline does the right thing
+                        with respect to inserting quotes.  */
+                     rl_completer_word_break_characters =
+                       gdb_completer_command_word_break_characters;
+                   }
+                 else if (c->enums)
+                   {
+                     list = complete_on_enum (c->enums, p, word);
+                     rl_completer_word_break_characters =
+                       gdb_completer_command_word_break_characters;
+                   }
+                 else
+                   {
+                     /* It is a normal command; what comes after it is
+                        completed by the command's completer function.  */
+                     list = (*c->completer) (p, word);
+                   }
+               }
+             else
+               {
+                 /* The command is not followed by whitespace; we need to
+                    complete on the command itself.  e.g. "p" which is a
+                    command itself but also can complete to "print", "ptype"
+                    etc.  */
+                 char *q;
+
+                 /* Find the command we are completing on.  */
+                 q = p;
+                 while (q > tmp_command)
+                   {
+                     if (isalnum (q[-1]) || q[-1] == '-' || q[-1] == '_')
+                       --q;
+                     else
+                       break;
+                   }
+
+                 list = complete_on_cmdlist (result_list, q, word);
+
+                 /* Insure that readline does the right thing
+                    with respect to inserting quotes.  */
+                 rl_completer_word_break_characters =
+                   gdb_completer_command_word_break_characters;
+               }
+           }
+         else
+           {
+             /* There is non-whitespace beyond the command.  */
+
+             if (c->prefixlist && !c->allow_unknown)
+               {
+                 /* It is an unrecognized subcommand of a prefix command,
+                    e.g. "info adsfkdj".  */
+                 list = NULL;
+               }
+             else if (c->enums)
+               {
+                 list = complete_on_enum (c->enums, p, word);
+               }
+             else
+               {
+                 /* It is a normal command.  */
+                 list = (*c->completer) (p, word);
+               }
+           }
+       }
+    }
+
+  /* If we found a list of potential completions during initialization then
+     dole them out one at a time.  The vector of completions is NULL
+     terminated, so after returning the last one, return NULL (and continue
+     to do so) each time we are called after that, until a new list is
+     available. */
+
+  if (list)
+    {
+      output = list[index];
+      if (output)
+       {
+         index++;
+       }
+    }
+
+#if 0
+  /* Can't do this because readline hasn't yet checked the word breaks
+     for figuring out whether to insert a quote.  */
+  if (output == NULL)
+    /* Make sure the word break characters are set back to normal for the
+       next time that readline tries to complete something.  */
+    rl_completer_word_break_characters =
+      gdb_completer_word_break_characters;
+#endif
+
+  return (output);
+}
+
+/* Line completion interface function for readline.  */
+
+static char *
+readline_line_completion_function (text, matches)
+     char *text;
+     int matches;
+{
+  return line_completion_function (text, matches, rl_line_buffer, rl_point);
+}
+
+/* Skip over a possibly quoted word (as defined by the quote characters
+   and word break characters the completer uses).  Returns pointer to the
+   location after the "word". */
+
+char *
+skip_quoted (str)
+     char *str;
+{
+  char quote_char = '\0';
+  char *scan;
+
+  for (scan = str; *scan != '\0'; scan++)
+    {
+      if (quote_char != '\0')
+       {
+         /* Ignore everything until the matching close quote char */
+         if (*scan == quote_char)
+           {
+             /* Found matching close quote. */
+             scan++;
+             break;
+           }
+       }
+      else if (strchr (gdb_completer_quote_characters, *scan))
+       {
+         /* Found start of a quoted string. */
+         quote_char = *scan;
+       }
+      else if (strchr (gdb_completer_word_break_characters, *scan))
+       {
+         break;
+       }
+    }
+  return (scan);
+}
+
+\f
+#ifdef STOP_SIGNAL
+static void
+stop_sig (signo)
+int signo;
+{
+#if STOP_SIGNAL == SIGTSTP
+  signal (SIGTSTP, SIG_DFL);
+  sigsetmask (0);
+  kill (getpid (), SIGTSTP);
+  signal (SIGTSTP, stop_sig);
+#else
+  signal (STOP_SIGNAL, stop_sig);
+#endif
+  printf_unfiltered ("%s", get_prompt ());
+  gdb_flush (gdb_stdout);
+
+  /* Forget about any previous command -- null line now will do nothing.  */
+  dont_repeat ();
+}
+#endif /* STOP_SIGNAL */
+
+/* Initialize signal handlers. */
+static void
+do_nothing (signo)
+int signo;
+{
+  /* Under System V the default disposition of a signal is reinstated after
+     the signal is caught and delivered to an application process.  On such
+     systems one must restore the replacement signal handler if one wishes
+     to continue handling the signal in one's program.  On BSD systems this
+     is not needed but it is harmless, and it simplifies the code to just do
+     it unconditionally. */
+  signal (signo, do_nothing);
+}
+
+static void
+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
+     on BSD4.3 systems using vfork, that can affect the
+     GDB process as well as the inferior (the signal handling tables
+     might be in memory, shared between the two).  Since we establish
+     a handler for SIGQUIT, when we call exec it will set the signal
+     to SIG_DFL for us.  */
+  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)
+  signal (SIGWINCH, SIGWINCH_HANDLER);
+#endif
+}
+\f
+/* Read one line from the command input stream `instream'
+   into the local static buffer `linebuffer' (whose current length
+   is `linelength').
+   The buffer is made bigger as necessary.
+   Returns the address of the start of the line.
+
+   NULL is returned for end of file.
+
+   *If* the instream == stdin & stdin is a terminal, the line read
+   is copied into the file line saver (global var char *line,
+   length linesize) so that it can be duplicated.
+
+   This routine either uses fancy command line editing or
+   simple input as the user has requested.  */
+
+char *
+command_line_input (prompt_arg, repeat, annotation_suffix)
+     char *prompt_arg;
+     int repeat;
+     char *annotation_suffix;
+{
+  static char *linebuffer = 0;
+  static unsigned linelength = 0;
+  register char *p;
+  char *p1;
+  char *rl;
+  char *local_prompt = prompt_arg;
+  char *nline;
+  char got_eof = 0;
+
+  /* The annotation suffix must be non-NULL.  */
+  if (annotation_suffix == NULL)
+    annotation_suffix = "";
+
+  if (annotation_level > 1 && instream == stdin)
+    {
+      local_prompt = alloca ((prompt_arg == NULL ? 0 : strlen (prompt_arg))
+                            + strlen (annotation_suffix) + 40);
+      if (prompt_arg == NULL)
+       local_prompt[0] = '\0';
+      else
+       strcpy (local_prompt, prompt_arg);
+      strcat (local_prompt, "\n\032\032");
+      strcat (local_prompt, annotation_suffix);
+      strcat (local_prompt, "\n");
+    }
+
+  if (linebuffer == 0)
+    {
+      linelength = 80;
+      linebuffer = (char *) xmalloc (linelength);
+    }
+
+  p = linebuffer;
+
+  /* Control-C quits instantly if typed while in this loop
+     since it should not wait until the user types a newline.  */
+  immediate_quit++;
+#ifdef STOP_SIGNAL
+  if (job_control)
+    {
+      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.  */
+      wrap_here ("");
+      gdb_flush (gdb_stdout);
+      gdb_flush (gdb_stderr);
+
+      if (source_file_name != NULL)
+       {
+         ++source_line_number;
+         sprintf (source_error,
+                  "%s%s:%d: Error in sourced command file:\n",
+                  source_pre_error,
+                  source_file_name,
+                  source_line_number);
+         error_pre_print = source_error;
+       }
+
+      if (annotation_level > 1 && instream == stdin)
+       {
+         printf_unfiltered ("\n\032\032pre-");
+         printf_unfiltered (annotation_suffix);
+         printf_unfiltered ("\n");
+       }
+
+      /* Don't use fancy stuff if not talking to stdin.  */
+      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);
+       }
+
+      if (annotation_level > 1 && instream == stdin)
+       {
+         printf_unfiltered ("\n\032\032post-");
+         printf_unfiltered (annotation_suffix);
+         printf_unfiltered ("\n");
+       }
+
+      if (!rl || rl == (char *) EOF)
+       {
+         got_eof = 1;
+         break;
+       }
+      if (strlen(rl) + 1 + (p - linebuffer) > linelength)
+       {
+         linelength = strlen(rl) + 1 + (p - linebuffer);
+         nline = (char *) xrealloc (linebuffer, linelength);
+         p += nline - linebuffer;
+         linebuffer = nline;
+       }
+      p1 = rl;
+      /* Copy line.  Don't copy null at end.  (Leaves line alone
+         if this was just a newline)  */
+      while (*p1)
+       *p++ = *p1++;
+
+      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)
+    signal (STOP_SIGNAL, SIG_DFL);
+#endif
+  immediate_quit--;
+
+  if (got_eof)
+    return NULL;
+
+#define SERVER_COMMAND_LENGTH 7
+  server_command =
+    (p - linebuffer > 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.  */
+      *p = '\0';
+      return linebuffer + SERVER_COMMAND_LENGTH;
+    }
+
+  /* Do history expansion if that is wished.  */
+  if (history_expansion_p && instream == stdin
+      && ISATTY (instream))
+    {
+      char *history_value;
+      int expanded;
+
+      *p = '\0';               /* Insert null now.  */
+      expanded = history_expand (linebuffer, &history_value);
+      if (expanded)
+       {
+         /* Print the changes.  */
+         printf_unfiltered ("%s\n", history_value);
+
+         /* If there was an error, call this function again.  */
+         if (expanded < 0)
+           {
+             free (history_value);
+             return command_line_input (prompt_arg, repeat, annotation_suffix);
+           }
+         if (strlen (history_value) > linelength)
+           {
+             linelength = strlen (history_value) + 1;
+             linebuffer = (char *) xrealloc (linebuffer, linelength);
+           }
+         strcpy (linebuffer, history_value);
+         p = linebuffer + strlen(linebuffer);
+         free (history_value);
+       }
+    }
+
+  /* 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 && p == linebuffer)
+    return line;
+  for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++) ;
+  if (repeat && !*p1)
+    return line;
+
+  *p = 0;
+
+  /* Add line to history if appropriate.  */
+  if (instream == stdin
+      && ISATTY (stdin) && *linebuffer)
+    add_history (linebuffer);
+
+  /* Note: lines consisting solely of comments are added to the command
+     history.  This is useful when you type a command, and then
+     realize you don't want to execute it quite yet.  You can comment
+     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.  */
+  if (*p1 == '#')
+    *p1 = '\0';  /* Found a comment. */
+
+  /* Save into global buffer if appropriate.  */
+  if (repeat)
+    {
+      if (linelength > linesize)
+       {
+         line = xrealloc (line, linelength);
+         linesize = linelength;
+       }
+      strcpy (line, linebuffer);
+      return line;
+    }
+
+  return linebuffer;
+}
+\f
+
+/* Expand the body_list of COMMAND so that it can hold NEW_LENGTH
+   code bodies.  This is typically used when we encounter an "else"
+   clause for an "if" command.  */
+
+static void
+realloc_body_list (command, new_length)
+     struct command_line *command;
+     int new_length;
+{
+  int n;
+  struct command_line **body_list;
+
+  n = command->body_count;
+
+  /* Nothing to do?  */
+  if (new_length <= n)
+    return;
+
+  body_list = (struct command_line **)
+    xmalloc (sizeof (struct command_line *) * new_length);
+
+  memcpy (body_list, command->body_list, sizeof (struct command_line *) * n);
+
+  free (command->body_list);
+  command->body_list = body_list;
+  command->body_count = new_length;
+}
+
+/* Read one line from the input stream.  If the command is an "else" or
+   "end", return such an indication to the caller.  */
+
+static enum misc_command_type
+read_next_line (command)
+     struct command_line **command;
+{
+  char *p, *p1, *prompt_ptr, control_prompt[256];
+  int i = 0;
+
+  if (control_level >= 254)
+    error ("Control nesting too deep!\n");
+
+  /* Set a prompt based on the nesting of the control commands.  */
+  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];
+    }
+  else
+    prompt_ptr = NULL;
+
+  p = command_line_input (prompt_ptr, instream == stdin, "commands");
+
+  /* Not sure what to do here.  */
+  if (p == NULL)
+    return end_command;
+
+  /* Strip leading and trailing whitespace.  */
+  while (*p == ' ' || *p == '\t')
+    p++;
+
+  p1 = p + strlen (p);
+  while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t'))
+    p1--;
+
+  /* Blanks and comments don't really do anything, but we need to
+     distinguish them from else, end and other commands which can be
+     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;
+
+  /* Is the else clause of an if control structure?  */
+  if (p1 - p == 4 && !strncmp (p, "else", 4))
+    return else_command;
+
+  /* Check for while, if, break, continue, etc and build a new command
+     line structure for them.  */
+  if (p1 - p > 5 && !strncmp (p, "while", 5))
+    *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 == 10 && !strncmp (p, "loop_break", 10))
+    {
+      *command = (struct command_line *)
+       xmalloc (sizeof (struct command_line));
+      (*command)->next = NULL;
+      (*command)->line = NULL;
+      (*command)->control_type = break_control;
+      (*command)->body_count = 0;
+      (*command)->body_list = NULL;
+    }
+  else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13))
+    {
+      *command = (struct command_line *)
+       xmalloc (sizeof (struct command_line));
+      (*command)->next = NULL;
+      (*command)->line = NULL;
+      (*command)->control_type = continue_control;
+      (*command)->body_count = 0;
+      (*command)->body_list = NULL;
+    }
+  else
+    {
+      /* A normal command.  */
+      *command = (struct command_line *)
+       xmalloc (sizeof (struct command_line));
+      (*command)->next = NULL;
+      (*command)->line = savestring (p, p1 - p);
+      (*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 
+   structure from them.
+
+   The parent_control parameter is the control structure in which the
+   following commands are nested.  */
+
+static enum command_control_type
+recurse_read_control_structure (current_cmd)
+     struct command_line *current_cmd;
+{
+  int current_body, i;
+  enum misc_command_type val;
+  enum command_control_type ret;
+  struct command_line **body_ptr, *child_tail, *next;
+
+  child_tail = NULL;
+  current_body = 1;
+
+  /* Sanity checks.  */
+  if (current_cmd->control_type == simple_control)
+    {
+      error ("Recursed on a simple control type\n");
+      return invalid_control;
+    }
+
+  if (current_body > current_cmd->body_count)
+    {
+      error ("Allocated body is smaller than this command type needs\n");
+      return invalid_control;
+    }
+
+  /* Read lines from the input stream and build control structures.  */
+  while (1)
+    {
+      dont_repeat ();
+
+      next = NULL;
+      val = read_next_line (&next);
+
+      /* Just skip blanks and comments.  */
+      if (val == nop_command)
+       continue;
+
+      if (val == end_command)
+       {
+         if (current_cmd->control_type == while_control
+             || current_cmd->control_type == if_control)
+           {
+             /* Success reading an entire control structure.  */
+             ret = simple_control;
+             break;
+           }
+         else
+           {
+             ret = invalid_control;
+             break;
+           }
+       }
+      
+      /* Not the end of a control structure.  */
+      if (val == else_command)
+       {
+         if (current_cmd->control_type == if_control
+             && current_body == 1)
+           {
+             realloc_body_list (current_cmd, 2);
+             current_body = 2;
+             child_tail = NULL;
+             continue;
+           }
+         else
+           {
+             ret = invalid_control;
+             break;
+           }
+       }
+
+      if (child_tail)
+       {
+         child_tail->next = next;
+       }
+      else
+       {
+         body_ptr = current_cmd->body_list;
+         for (i = 1; i < current_body; i++)
+           body_ptr++;
+
+         *body_ptr = next;
+
+       }
+
+      child_tail = next;
+
+      /* If the latest line is another control structure, then recurse
+        on it.  */
+      if (next->control_type == while_control
+         || next->control_type == if_control)
+       {
+         control_level++;
+         ret = recurse_read_control_structure (next);
+         control_level--;
+
+         if (ret != simple_control)
+           break;
+       }
+    }
+
+  dont_repeat ();
+
+  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. */
+
+#define END_MESSAGE "End with a line saying just \"end\"."
+
+struct command_line *
+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;
+
+  while (1)
+    {
+      val = read_next_line (&next);
+
+      /* Ignore blank lines or comments.  */
+      if (val == nop_command)
+       continue;
+
+      if (val == end_command)
+       {
+         ret = simple_control;
+         break;
+       }
+
+      if (val != ok_command)
+       {
+         ret = invalid_control;
+         break;
+       }
+
+      if (next->control_type == while_control
+         || next->control_type == if_control)
+       {
+         control_level++;
+         ret = recurse_read_control_structure (next);
+         control_level--;
+
+         if (ret == invalid_control)
+           break;
+       }
+      
+      if (tail)
+       {
+         tail->next = next;
+       }
+      else
+       {
+         head = next;
+         old_chain = make_cleanup ((make_cleanup_func) free_command_lines, 
+                                    &head);
+       }
+      tail = next;
+    }
+
+  dont_repeat ();
+
+  if (head)
+    {
+      if (ret != invalid_control)
+       {
+         discard_cleanups (old_chain);
+       }
+      else
+       do_cleanups (old_chain);
+    }
+
+  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;
+{
+  register struct command_line *l = *lptr;
+  register struct command_line *next;
+  struct command_line **blist;
+  int i;
+
+  while (l)
+    {
+      if (l->body_count > 0)
+       {
+         blist = l->body_list;
+         for (i = 0; i < l->body_count; i++, blist++)
+           free_command_lines (blist);
+       }
+      next = l->next;
+      free (l->line);
+      free ((PTR)l);
+      l = next;
+    }
+}
+\f
+/* Add an element to the list of info subcommands.  */
+
+void
+add_info (name, fun, doc)
+     char *name;
+     void (*fun) PARAMS ((char *, int));
+     char *doc;
+{
+  add_cmd (name, no_class, fun, doc, &infolist);
+}
+
+/* Add an alias to the list of info subcommands.  */
+
+void
+add_info_alias (name, oldname, abbrev_flag)
+     char *name;
+     char *oldname;
+     int abbrev_flag;
+{
+  add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist);
+}
+
+/* The "info" command is defined as a prefix, with allow_unknown = 0.
+   Therefore, its own definition is called only for "info" with no args.  */
+
+/* ARGSUSED */
+static void
+info_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  printf_unfiltered ("\"info\" must be followed by the name of an info command.\n");
+  help_list (infolist, "info ", -1, gdb_stdout);
+}
+
+/* The "complete" command is used by Emacs to implement completion.  */
+
+/* ARGSUSED */
+static void
+complete_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  int i;
+  int argpoint;
+  char *completion;
+
+  dont_repeat ();
+
+  if (arg == NULL)
+    arg = "";
+  argpoint = strlen (arg);
+
+  for (completion = line_completion_function (arg, i = 0, arg, argpoint);
+       completion;
+       completion = line_completion_function (arg, ++i, arg, argpoint))
+    {
+      printf_unfiltered ("%s\n", completion);
+      free (completion);
+    }
+}
+
+/* The "show" command with no arguments shows all the settings.  */
+
+/* ARGSUSED */
+static void
+show_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  cmd_show_list (showlist, from_tty, "");
+}
+\f
+/* Add an element to the list of commands.  */
+
+void
+add_com (name, class, fun, doc)
+     char *name;
+     enum command_class class;
+     void (*fun) PARAMS ((char *, int));
+     char *doc;
+{
+  add_cmd (name, class, fun, doc, &cmdlist);
+}
+
+/* Add an alias or abbreviation command to the list of commands.  */
+
+void
+add_com_alias (name, oldname, class, abbrev_flag)
+     char *name;
+     char *oldname;
+     enum command_class class;
+     int abbrev_flag;
+{
+  add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist);
+}
+
+void
+error_no_arg (why)
+     char *why;
+{
+  error ("Argument required (%s).", why);
+}
+
+/* ARGSUSED */
+static void
+help_command (command, from_tty)
+     char *command;
+     int from_tty; /* Ignored */
+{
+  help_cmd (command, gdb_stdout);
+}
+\f
+static void
+validate_comname (comname)
+     char *comname;
+{
+  register char *p;
+
+  if (comname == 0)
+    error_no_arg ("name of command to define");
+
+  p = comname;
+  while (*p)
+    {
+      if (!isalnum(*p) && *p != '-' && *p != '_')
+       error ("Junk in argument list: \"%s\"", p);
+      p++;
+    }
+}
+
+/* This is just a placeholder in the command data structures.  */
+static void
+user_defined_command (ignore, from_tty)
+     char *ignore;
+     int from_tty;
+{
+}
+
+static void
+define_command (comname, from_tty)
+     char *comname;
+     int from_tty;
+{
+  register struct command_line *cmds;
+  register struct cmd_list_element *c, *newc, *hookc = 0;
+  char *tem = comname;
+  char tmpbuf[128];
+#define        HOOK_STRING     "hook-"
+#define        HOOK_LEN 5
+
+  validate_comname (comname);
+
+  /* Look it up, and verify that we got an exact match.  */
+  c = lookup_cmd (&tem, cmdlist, "", -1, 1);
+  if (c && !STREQ (comname, c->name))
+    c = 0;
+
+  if (c)
+    {
+      if (c->class == class_user || c->class == class_alias)
+       tem = "Redefine command \"%s\"? ";
+      else
+       tem = "Really redefine built-in command \"%s\"? ";
+      if (!query (tem, c->name))
+       error ("Command \"%s\" not redefined.", c->name);
+    }
+
+  /* If this new command is a hook, then mark the command which it
+     is hooking.  Note that we allow hooking `help' commands, so that
+     we can hook the `stop' pseudo-command.  */
+
+  if (!strncmp (comname, HOOK_STRING, HOOK_LEN))
+    {
+      /* Look up cmd it hooks, and verify that we got an exact match.  */
+      tem = comname+HOOK_LEN;
+      hookc = lookup_cmd (&tem, cmdlist, "", -1, 0);
+      if (hookc && !STREQ (comname+HOOK_LEN, hookc->name))
+       hookc = 0;
+      if (!hookc)
+       {
+         warning ("Your new `%s' command does not hook any existing command.",
+                  comname);
+         if (!query ("Proceed? "))
+           error ("Not confirmed.");
+       }
+    }
+
+  comname = savestring (comname, strlen (comname));
+
+  /* If the rest of the commands will be case insensitive, this one
+     should behave in the same manner. */
+  for (tem = comname; *tem; tem++)
+    if (isupper(*tem)) *tem = tolower(*tem);
+
+  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);
+  newc->user_commands = cmds;
+
+  /* If this new command is a hook, then mark both commands as being
+     tied.  */
+  if (hookc)
+    {
+      hookc->hook = newc;      /* Target gets hooked.  */
+      newc->hookee = hookc;    /* We are marked as hooking target cmd.  */
+    }
+}
+
+static void
+document_command (comname, from_tty)
+     char *comname;
+     int from_tty;
+{
+  struct command_line *doclines;
+  register struct cmd_list_element *c;
+  char *tem = comname;
+  char tmpbuf[128];
+
+  validate_comname (comname);
+
+  c = lookup_cmd (&tem, cmdlist, "", 0, 1);
+
+  if (c->class != class_user)
+    error ("Command \"%s\" is built-in.", comname);
+
+  sprintf (tmpbuf, "Type documentation for \"%s\".", comname);
+  doclines = read_command_lines (tmpbuf, from_tty);
+
+  if (c->doc) free (c->doc);
+
+  {
+    register struct command_line *cl1;
+    register int len = 0;
+
+    for (cl1 = doclines; cl1; cl1 = cl1->next)
+      len += strlen (cl1->line) + 1;
+
+    c->doc = (char *) xmalloc (len + 1);
+    *c->doc = 0;
+
+    for (cl1 = doclines; cl1; cl1 = cl1->next)
+      {
+       strcat (c->doc, cl1->line);
+       if (cl1->next)
+         strcat (c->doc, "\n");
+      }
+  }
+
+  free_command_lines (&doclines);
+}
+\f
+/* Print the GDB banner. */
+void
+print_gdb_version (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 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");
+
+  /* After the required info we print the configuration information. */
+
+  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 */
+static void
+show_version (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  immediate_quit++;
+  print_gdb_version (gdb_stdout);
+  printf_filtered ("\n");
+  immediate_quit--;
+}
+\f
+/* 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, "<true>");
+                       else
+                         strcpy (outp, "<false>");
+                     }
+                   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
+set_prompt (s)
+     char *s;
+{
+/* ??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));
+}
+
+\f
+/* If necessary, make the user confirm that we should quit.  Return
+   non-zero if we should quit, zero if we shouldn't.  */
+
+int
+quit_confirm ()
+{
+  if (inferior_pid != 0 && target_has_execution)
+    {
+      char *s;
+
+      /* This is something of a hack.  But there's no reliable way to
+        see if a GUI is running.  The `use_windows' variable doesn't
+        cut it.  */
+      if (init_ui_hook)
+       s = "A debugging session is active.\nDo you still want to close the debugger?";
+      else if (attach_flag)
+       s = "The program is running.  Quit anyway (and detach it)? ";
+      else
+       s = "The program is running.  Exit anyway? ";
+
+      if (! query (s))
+       return 0;
+    }
+
+  return 1;
+}
+
+/* Quit without asking for confirmation.  */
+
+void
+quit_force (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  int exit_code = 0;
+
+  /* An optional expression may be used to cause gdb to terminate with the 
+     value of that expression. */
+  if (args)
+    {
+      value_ptr val = parse_and_eval (args);
+
+      exit_code = (int) value_as_long (val);
+    }
+
+  if (inferior_pid != 0 && target_has_execution)
+    {
+      if (attach_flag)
+       target_detach (args, from_tty);
+      else
+       target_kill ();
+    }
+
+  /* UDI wants this, to kill the TIP.  */
+  target_close (1);
+
+  /* Save the history information if it is appropriate to do so.  */
+  if (write_history_p && history_filename)
+    write_history (history_filename);
+
+  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.  */
+
+int
+input_from_terminal_p ()
+{
+  return gdb_has_a_terminal () && (instream == stdin) & caution;
+}
+\f
+/* ARGSUSED */
+static void
+pwd_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  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);
+  else
+    printf_unfiltered ("Working directory %s.\n", current_directory);
+}
+
+void
+cd_command (dir, from_tty)
+     char *dir;
+     int from_tty;
+{
+  int len;
+  /* Found something other than leading repetitions of "/..".  */
+  int found_real_path;
+  char *p;
+
+  /* If the new directory is absolute, repeat is a no-op; if relative,
+     repeat might be useful but is more likely to be a mistake.  */
+  dont_repeat ();
+
+  if (dir == 0)
+    error_no_arg ("new working directory");
+
+  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 && SLASH_P(dir[len-1])));
+  if (ROOTED_P(dir))
+    current_directory = dir;
+  else
+    {
+      if (SLASH_P (current_directory[0]) && current_directory[1] == '\0')
+       current_directory = concat (current_directory, dir, NULL);
+      else
+       current_directory = concat (current_directory, SLASH_STRING, dir, NULL);
+      free (dir);
+    }
+
+  /* Now simplify any occurrences of `.' and `..' in the pathname.  */
+
+  found_real_path = 0;
+  for (p = current_directory; *p;)
+    {
+      if (SLASH_P (p[0]) && p[1] == '.' && (p[2] == 0 || SLASH_P (p[2])))
+       strcpy (p, p + 2);
+      else if (SLASH_P (p[0]) && p[1] == '.' && p[2] == '.'
+              && (p[3] == 0 || SLASH_P (p[3])))
+       {
+         if (found_real_path)
+           {
+             /* Search backwards for the directory just before the "/.."
+                and obliterate it and the "/..".  */
+             char *q = p;
+             while (q != current_directory && ! SLASH_P (q[-1]))
+               --q;
+
+             if (q == current_directory)
+               /* current_directory is
+                  a relative pathname ("can't happen"--leave it alone).  */
+               ++p;
+             else
+               {
+                 strcpy (q - 1, p + 3);
+                 p = q - 1;
+               }
+           }
+         else
+           /* We are dealing with leading repetitions of "/..", for example
+              "/../..", which is the Mach super-root.  */
+           p += 3;
+       }
+      else
+       {
+         found_real_path = 1;
+         ++p;
+       }
+    }
+
+  forget_cached_source_info ();
+
+  if (from_tty)
+    pwd_command ((char *) 0, 1);
+}
+\f
+struct source_cleanup_lines_args {
+  int old_line;
+  char *old_file;
+  char *old_pre_error;
+  char *old_error_pre_print;
+};
+
+static void
+source_cleanup_lines (args)
+     PTR args;
+{
+  struct source_cleanup_lines_args *p =
+    (struct source_cleanup_lines_args *)args;
+  source_line_number = p->old_line;
+  source_file_name = p->old_file;
+  source_pre_error = p->old_pre_error;
+  error_pre_print = p->old_error_pre_print;
+}
+
+/* ARGSUSED */
+void
+source_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  FILE *stream;
+  struct cleanup *old_cleanups;
+  char *file = args;
+  struct source_cleanup_lines_args old_lines;
+  int needed_length;
+
+  if (file == NULL)
+    {
+      error ("source command requires pathname of file to source.");
+    }
+
+  file = tilde_expand (file);
+  old_cleanups = make_cleanup (free, file);
+
+  stream = fopen (file, FOPEN_RT);
+  if (!stream)
+    {
+      if (from_tty)
+       perror_with_name (file);
+      else
+       return;
+    }
+
+  make_cleanup ((make_cleanup_func) fclose, stream);
+
+  old_lines.old_line = source_line_number;
+  old_lines.old_file = source_file_name;
+  old_lines.old_pre_error = source_pre_error;
+  old_lines.old_error_pre_print = error_pre_print;
+  make_cleanup (source_cleanup_lines, &old_lines);
+  source_line_number = 0;
+  source_file_name = file;
+  source_pre_error = error_pre_print == NULL ? "" : error_pre_print;
+  source_pre_error = savestring (source_pre_error, strlen (source_pre_error));
+  make_cleanup (free, source_pre_error);
+  /* This will get set every time we read a line.  So it won't stay "" for
+     long.  */
+  error_pre_print = "";
+
+  needed_length = strlen (source_file_name) + strlen (source_pre_error) + 80;
+  if (source_error_allocated < needed_length)
+    {
+      source_error_allocated *= 2;
+      if (source_error_allocated < needed_length)
+       source_error_allocated = needed_length;
+      if (source_error == NULL)
+       source_error = xmalloc (source_error_allocated);
+      else
+       source_error = xrealloc (source_error, source_error_allocated);
+    }
+
+  read_command_file (stream);
+
+  do_cleanups (old_cleanups);
+}
+
+/* ARGSUSED */
+static void
+echo_command (text, from_tty)
+     char *text;
+     int from_tty;
+{
+  char *p = text;
+  register int c;
+
+  if (text)
+    while ((c = *p++) != '\0')
+      {
+       if (c == '\\')
+         {
+           /* \ at end of argument is used after spaces
+              so they won't be lost.  */
+           if (*p == 0)
+             return;
+
+           c = parse_escape (&p);
+           if (c >= 0)
+             printf_filtered ("%c", c);
+         }
+       else
+         printf_filtered ("%c", c);
+      }
+
+  /* Force this output to appear now.  */
+  wrap_here ("");
+  gdb_flush (gdb_stdout);
+}
+
+/* ARGSUSED */
+static void
+dont_repeat_command (ignored, from_tty)
+     char *ignored;
+     int from_tty;
+{
+  *line = 0;           /* Can't call dont_repeat here because we're not
+                          necessarily reading from stdin.  */
+}
+\f
+/* Functions to manipulate command line editing control variables.  */
+
+/* Number of commands to print in each call to show_commands.  */
+#define Hist_print 10
+static void
+show_commands (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  /* Index for history commands.  Relative to history_base.  */
+  int offset;
+
+  /* Number of the history entry which we are planning to display next.
+     Relative to history_base.  */
+  static int num = 0;
+
+  /* The first command in the history which doesn't exist (i.e. one more
+     than the number of the last command).  Relative to history_base.  */
+  int hist_len;
+
+  extern HIST_ENTRY *history_get PARAMS ((int));
+
+  /* Print out some of the commands from the command history.  */
+  /* First determine the length of the history list.  */
+  hist_len = history_size;
+  for (offset = 0; offset < history_size; offset++)
+    {
+      if (!history_get (history_base + offset))
+       {
+         hist_len = offset;
+         break;
+       }
+    }
+
+  if (args)
+    {
+      if (args[0] == '+' && args[1] == '\0')
+       /* "info editing +" should print from the stored position.  */
+       ;
+      else
+       /* "info editing <exp>" should print around command number <exp>.  */
+       num = (parse_and_eval_address (args) - history_base) - Hist_print / 2;
+    }
+  /* "show commands" means print the last Hist_print commands.  */
+  else
+    {
+      num = hist_len - Hist_print;
+    }
+
+  if (num < 0)
+    num = 0;
+
+  /* If there are at least Hist_print commands, we want to display the last
+     Hist_print rather than, say, the last 6.  */
+  if (hist_len - num < Hist_print)
+    {
+      num = hist_len - Hist_print;
+      if (num < 0)
+       num = 0;
+    }
+
+  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);
+    }
+
+  /* The next command we want to display is the next one that we haven't
+     displayed yet.  */
+  num += Hist_print;
+
+  /* If the user repeats this command with return, it should do what
+     "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] = '+';
+      args[1] = '\0';
+    }
+}
+
+/* Called by do_setshow_command.  */
+/* ARGSUSED */
+static void
+set_history_size_command (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  if (history_size == INT_MAX)
+    unstifle_history ();
+  else if (history_size >= 0)
+    stifle_history (history_size);
+  else
+    {
+      history_size = INT_MAX;
+      error ("History size must be non-negative");
+    }
+}
+
+/* ARGSUSED */
+static void
+set_history (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  printf_unfiltered ("\"set history\" must be followed by the name of a history subcommand.\n");
+  help_list (sethistlist, "set history ", -1, gdb_stdout);
+}
+
+/* ARGSUSED */
+static void
+show_history (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  cmd_show_list (showhistlist, from_tty, "");
+}
+
+int info_verbose = 0;          /* Default verbose msgs off */
+
+/* Called by do_setshow_command.  An elaborate joke.  */
+/* ARGSUSED */
+static void
+set_verbose (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  char *cmdname = "verbose";
+  struct cmd_list_element *showcmd;
+
+  showcmd = lookup_cmd_1 (&cmdname, showlist, NULL, 1);
+
+  if (info_verbose)
+    {
+      c->doc = "Set verbose printing of informational messages.";
+      showcmd->doc = "Show verbose printing of informational messages.";
+    }
+  else
+    {
+      c->doc = "Set verbosity.";
+      showcmd->doc = "Show verbosity.";
+    }
+}
+
+static void
+float_handler (signo)
+int signo;
+{
+  /* This message is based on ANSI C, section 4.7.  Note that integer
+     divide by zero causes this, so "float" is a misnomer.  */
+  signal (SIGFPE, float_handler);
+  error ("Erroneous arithmetic operation.");
+}
+
+\f
+static void
+init_cmd_lists ()
+{
+  cmdlist = NULL;
+  infolist = NULL;
+  enablelist = NULL;
+  disablelist = NULL;
+  togglelist = NULL;
+  stoplist = NULL;
+  deletelist = NULL;
+  enablebreaklist = NULL;
+  setlist = NULL;
+  unsetlist = NULL;
+  showlist = NULL;
+  sethistlist = NULL;
+  showhistlist = NULL;
+  unsethistlist = NULL;
+  maintenancelist = NULL;
+  maintenanceinfolist = NULL;
+  maintenanceprintlist = NULL;
+  setprintlist = NULL;
+  showprintlist = NULL;
+  setchecklist = NULL;
+  showchecklist = NULL;
+}
+
+/* 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.
+ */
+
+void
+init_history()
+{
+  char *tmpenv;
+
+  tmpenv = getenv ("HISTSIZE");
+  if (tmpenv)
+    history_size = atoi (tmpenv);
+  else if (!history_size)
+    history_size = 256;
+
+  stifle_history (history_size);
+
+  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);
+  }
+  read_history (history_filename);
+}
+
+static void
+init_main ()
+{
+  struct cmd_list_element *c;
+
+  /* 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 DEFULAT_PROMPT is. */
+      the_prompts.top = 0;
+      PREFIX(0) = "";
+#ifdef DEFAULT_PROMPT
+      PROMPT(0) = savestring (DEFAULT_PROMPT, strlen(DEFAULT_PROMPT));
+#else
+      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;
+  async_command_editing_p = 1;
+  history_expansion_p = 0;
+  write_history_p = 0;
+
+  /* Setup important stuff for command line editing.  */
+  rl_completion_entry_function = (int (*)()) readline_line_completion_function;
+  rl_completer_word_break_characters = gdb_completer_word_break_characters;
+  rl_completer_quote_characters = gdb_completer_quote_characters;
+  rl_readline_name = "gdb";
+
+  /* Define the classes of commands.
+     They will appear in the help list in the reverse of this order.  */
+
+  add_cmd ("internals", class_maintenance, NO_FUNCTION,
+          "Maintenance commands.\n\
+Some gdb commands are provided just for use by gdb maintainers.\n\
+These commands are subject to frequent change, and may not be as\n\
+well documented as user commands.",
+          &cmdlist);
+  add_cmd ("obscure", class_obscure, NO_FUNCTION, "Obscure features.", &cmdlist);
+  add_cmd ("aliases", class_alias, NO_FUNCTION, "Aliases of other commands.", &cmdlist);
+  add_cmd ("user-defined", class_user, NO_FUNCTION, "User-defined commands.\n\
+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);
+  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);
+  add_cmd ("stack", class_stack, NO_FUNCTION, "Examining the stack.\n\
+The stack is made up of stack frames.  Gdb assigns numbers to stack frames\n\
+counting from zero for the innermost (currently executing) frame.\n\n\
+At any time gdb identifies one frame as the \"selected\" frame.\n\
+Variable lookups are done with respect to the selected frame.\n\
+When the program being debugged stops, gdb selects the innermost frame.\n\
+The commands below can be used to select other frames by number or address.",
+          &cmdlist);
+  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.");
+  c = add_cmd ("cd", class_files, cd_command,
+          "Set working directory to DIR for debugger and program being debugged.\n\
+The change does not take effect for the program being debugged\n\
+until the next time it is started.", &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-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,
+          "Print a constant string.  Give string as argument.\n\
+C escape sequences may be used in the argument.\n\
+No newline is added at the end of the argument;\n\
+use \"\\n\" if you want a newline to be printed.\n\
+Since leading and trailing whitespace are ignored in command arguments,\n\
+if you want to print some you must use \"\\\" before leading whitespace\n\
+to be printed or after trailing whitespace.");
+  add_com ("document", class_support, document_command,
+          "Document a user-defined command.\n\
+Give command name as argument.  Give documentation on following lines.\n\
+End with a line of just \"end\".");
+  add_com ("define", class_support, define_command,
+          "Define a new command name.  Command name is argument.\n\
+Definition appears on following lines, one command per line.\n\
+End with a line of just \"end\".\n\
+Use the \"document\" command to give documentation for the new command.\n\
+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\
+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\
+Note that the file \".gdbinit\" is read automatically in this way\n\
+when gdb is started.", &cmdlist);
+#endif
+  c->completer = filename_completer;
+
+  add_com ("quit", class_support, quit_command, "Exit gdb.");
+  add_com ("help", class_support, help_command, "Print list of commands.");
+  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,
+                  "Set ",
+                  &setlist),
+  add_show_from_set (c, &showlist);
+  c->function.sfunc = set_verbose;
+  set_verbose (NULL, 0, c);
+
+  /* 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);
+    }
+  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.",
+                 &sethistlist, "set history ", 0, &setlist);
+  add_prefix_cmd ("history", class_support, show_history,
+                 "Generic command for showing command history parameters.",
+                 &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\
+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 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,
+                  "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\
+ (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,
+                 "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.",
+                 &infolist, "info ", 0, &cmdlist);
+  add_com_alias ("i", "info", class_info, 1);
+
+  add_com ("complete", class_obscure, complete_command,
+          "List the completions for the rest of the line as a command.");
+
+  add_prefix_cmd ("show", class_info, show_command,
+                 "Generic command for showing things 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,
+          "Show 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,
+          "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\
+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\
+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\
+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,
+                                 "Set baud rate for remote serial I/O.\n\
+This value is used to set the speed of the serial port when debugging\n\
+using remote targets.", &setlist),
+                    &showlist);
+
+  add_show_from_set (
+    add_set_cmd ("remotedebug", no_class, var_zinteger, (char *)&remote_debug,
+                  "Set debugging of remote protocol.\n\
+When enabled, each packet sent or received with the remote target\n\
+is displayed.", &setlist),
+                    &showlist);
+
+  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;
+    }
+}