2011-02-21 Hui Zhu <teawater@gmail.com>
[deliverable/binutils-gdb.git] / gdb / utils.c
index cf5ef19b9d9b78e85d84b884010acaac182b37b0..82e3adbafb7e2c01fb5d6c9178e0a5f5042a975a 100644 (file)
@@ -1,14 +1,14 @@
 /* General utility routines for GDB, the GNU debugger.
 
-   Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009, 2010, 2011 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "gdb_assert.h"
 #include "gdb_string.h"
 #include "event-top.h"
 #include "exceptions.h"
+#include "gdbthread.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif /* HAVE_SYS_RESOURCE_H */
 
 #ifdef TUI
 #include "tui/tui.h"           /* For tui_get_command_dimension.   */
@@ -36,7 +38,7 @@
 #include <pc.h>
 #endif
 
-/* SunOS's curses.h has a '#define reg register' in it.  Thank you Sun. */
+/* SunOS's curses.h has a '#define reg register' in it.  Thank you Sun.  */
 #ifdef reg
 #undef reg
 #endif
@@ -54,7 +56,9 @@
 #include "filenames.h"
 #include "symfile.h"
 #include "gdb_obstack.h"
+#include "gdbcore.h"
 #include "top.h"
+#include "main.h"
 
 #include "inferior.h"          /* for signed_pointer_to_address */
 
 
 #include "readline/readline.h"
 
+#include <sys/time.h>
+#include <time.h>
+
+#include "gdb_usleep.h"
+#include "interps.h"
+#include "gdb_regex.h"
+
 #if !HAVE_DECL_MALLOC
-extern PTR malloc ();          /* OK: PTR */
+extern PTR malloc ();          /* ARI: PTR */
 #endif
 #if !HAVE_DECL_REALLOC
-extern PTR realloc ();         /* OK: PTR */
+extern PTR realloc ();         /* ARI: PTR */
 #endif
 #if !HAVE_DECL_FREE
 extern void free ();
@@ -82,7 +93,7 @@ void (*deprecated_error_begin_hook) (void);
 /* Prototypes for local functions */
 
 static void vfprintf_maybe_filtered (struct ui_file *, const char *,
-                                    va_list, int) ATTR_FORMAT (printf, 2, 0);
+                                    va_list, int) ATTRIBUTE_PRINTF (2, 0);
 
 static void fputs_maybe_filtered (const char *, struct ui_file *, int);
 
@@ -93,24 +104,17 @@ static void prompt_for_continue (void);
 static void set_screen_size (void);
 static void set_width (void);
 
+/* A flag indicating whether to timestamp debugging messages.  */
+
+static int debug_timestamp = 0;
+
 /* Chain of cleanup actions established with make_cleanup,
    to be executed if an error happens.  */
 
 static struct cleanup *cleanup_chain;  /* cleaned up after a failed command */
 static struct cleanup *final_cleanup_chain;    /* cleaned up when gdb exits */
-static struct cleanup *run_cleanup_chain;      /* cleaned up on each 'run' */
-static struct cleanup *exec_cleanup_chain;     /* cleaned up on each execution command */
-/* cleaned up on each error from within an execution command */
-static struct cleanup *exec_error_cleanup_chain;
-
-/* Pointer to what is left to do for an execution command after the
-   target stops. Used only in asynchronous mode, by targets that
-   support async execution.  The finish and until commands use it. So
-   does the target extended-remote command. */
-struct continuation *cmd_continuation;
-struct continuation *intermediate_continuation;
 
-/* Nonzero if we have job control. */
+/* Nonzero if we have job control.  */
 
 int job_control;
 
@@ -139,8 +143,9 @@ static void
 show_demangle (struct ui_file *file, int from_tty,
               struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Demangling of encoded C++/ObjC names when displaying symbols is %s.\n"),
+  fprintf_filtered (file,
+                   _("Demangling of encoded C++/ObjC names "
+                     "when displaying symbols is %s.\n"),
                    value);
 }
 
@@ -153,8 +158,9 @@ static void
 show_asm_demangle (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Demangling of C++/ObjC names in disassembly listings is %s.\n"),
+  fprintf_filtered (file,
+                   _("Demangling of C++/ObjC names in "
+                     "disassembly listings is %s.\n"),
                    value);
 }
 
@@ -167,8 +173,8 @@ static void
 show_sevenbit_strings (struct ui_file *file, int from_tty,
                       struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Printing of 8-bit characters in strings as \\nnn is %s.\n"),
+  fprintf_filtered (file, _("Printing of 8-bit characters "
+                           "in strings as \\nnn is %s.\n"),
                    value);
 }
 
@@ -206,27 +212,17 @@ make_cleanup (make_cleanup_ftype *function, void *arg)
 }
 
 struct cleanup *
-make_final_cleanup (make_cleanup_ftype *function, void *arg)
-{
-  return make_my_cleanup (&final_cleanup_chain, function, arg);
-}
-
-struct cleanup *
-make_run_cleanup (make_cleanup_ftype *function, void *arg)
-{
-  return make_my_cleanup (&run_cleanup_chain, function, arg);
-}
-
-struct cleanup *
-make_exec_cleanup (make_cleanup_ftype *function, void *arg)
+make_cleanup_dtor (make_cleanup_ftype *function, void *arg,
+                  void (*dtor) (void *))
 {
-  return make_my_cleanup (&exec_cleanup_chain, function, arg);
+  return make_my_cleanup2 (&cleanup_chain,
+                          function, arg, dtor);
 }
 
 struct cleanup *
-make_exec_error_cleanup (make_cleanup_ftype *function, void *arg)
+make_final_cleanup (make_cleanup_ftype *function, void *arg)
 {
-  return make_my_cleanup (&exec_error_cleanup_chain, function, arg);
+  return make_my_cleanup (&final_cleanup_chain, function, arg);
 }
 
 static void
@@ -257,16 +253,53 @@ static void
 do_close_cleanup (void *arg)
 {
   int *fd = arg;
+
   close (*fd);
-  xfree (fd);
 }
 
 struct cleanup *
 make_cleanup_close (int fd)
 {
   int *saved_fd = xmalloc (sizeof (fd));
+
   *saved_fd = fd;
-  return make_cleanup (do_close_cleanup, saved_fd);
+  return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
+}
+
+/* Helper function which does the work for make_cleanup_fclose.  */
+
+static void
+do_fclose_cleanup (void *arg)
+{
+  FILE *file = arg;
+
+  fclose (file);
+}
+
+/* Return a new cleanup that closes FILE.  */
+
+struct cleanup *
+make_cleanup_fclose (FILE *file)
+{
+  return make_cleanup (do_fclose_cleanup, file);
+}
+
+/* Helper function which does the work for make_cleanup_obstack_free.  */
+
+static void
+do_obstack_free (void *arg)
+{
+  struct obstack *ob = arg;
+
+  obstack_free (ob, NULL);
+}
+
+/* Return a new cleanup that frees OBSTACK.  */
+
+struct cleanup *
+make_cleanup_obstack_free (struct obstack *obstack)
+{
+  return make_cleanup (do_obstack_free, obstack);
 }
 
 static void
@@ -281,6 +314,26 @@ make_cleanup_ui_file_delete (struct ui_file *arg)
   return make_my_cleanup (&cleanup_chain, do_ui_file_delete, arg);
 }
 
+/* Helper function for make_cleanup_ui_out_redirect_pop.  */
+
+static void
+do_ui_out_redirect_pop (void *arg)
+{
+  struct ui_out *uiout = arg;
+
+  if (ui_out_redirect (uiout, NULL) < 0)
+    warning (_("Cannot restore redirection of the current output protocol"));
+}
+
+/* Return a new cleanup that pops the last redirection by ui_out_redirect
+   with NULL parameter.  */
+
+struct cleanup *
+make_cleanup_ui_out_redirect_pop (struct ui_out *uiout)
+{
+  return make_my_cleanup (&cleanup_chain, do_ui_out_redirect_pop, uiout);
+}
+
 static void
 do_free_section_addr_info (void *arg)
 {
@@ -293,10 +346,94 @@ make_cleanup_free_section_addr_info (struct section_addr_info *addrs)
   return make_my_cleanup (&cleanup_chain, do_free_section_addr_info, addrs);
 }
 
+struct restore_integer_closure
+{
+  int *variable;
+  int value;
+};
+
+static void
+restore_integer (void *p)
+{
+  struct restore_integer_closure *closure = p;
+
+  *(closure->variable) = closure->value;
+}
+
+/* Remember the current value of *VARIABLE and make it restored when
+   the cleanup is run.  */
 
 struct cleanup *
-make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
-                void *arg)
+make_cleanup_restore_integer (int *variable)
+{
+  struct restore_integer_closure *c =
+    xmalloc (sizeof (struct restore_integer_closure));
+
+  c->variable = variable;
+  c->value = *variable;
+
+  return make_my_cleanup2 (&cleanup_chain, restore_integer, (void *)c,
+                          xfree);
+}
+
+/* Remember the current value of *VARIABLE and make it restored when
+   the cleanup is run.  */
+
+struct cleanup *
+make_cleanup_restore_uinteger (unsigned int *variable)
+{
+  return make_cleanup_restore_integer ((int *) variable);
+}
+
+/* Helper for make_cleanup_unpush_target.  */
+
+static void
+do_unpush_target (void *arg)
+{
+  struct target_ops *ops = arg;
+
+  unpush_target (ops);
+}
+
+/* Return a new cleanup that unpushes OPS.  */
+
+struct cleanup *
+make_cleanup_unpush_target (struct target_ops *ops)
+{
+  return make_my_cleanup (&cleanup_chain, do_unpush_target, ops);
+}
+
+struct restore_ui_file_closure
+{
+  struct ui_file **variable;
+  struct ui_file *value;
+};
+
+static void
+do_restore_ui_file (void *p)
+{
+  struct restore_ui_file_closure *closure = p;
+
+  *(closure->variable) = closure->value;
+}
+
+/* Remember the current value of *VARIABLE and make it restored when
+   the cleanup is run.  */
+
+struct cleanup *
+make_cleanup_restore_ui_file (struct ui_file **variable)
+{
+  struct restore_ui_file_closure *c = XNEW (struct restore_ui_file_closure);
+
+  c->variable = variable;
+  c->value = *variable;
+
+  return make_cleanup_dtor (do_restore_ui_file, (void *) c, xfree);
+}
+
+struct cleanup *
+make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
+                 void *arg,  void (*free_arg) (void *))
 {
   struct cleanup *new
     = (struct cleanup *) xmalloc (sizeof (struct cleanup));
@@ -304,12 +441,20 @@ make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
 
   new->next = *pmy_chain;
   new->function = function;
+  new->free_arg = free_arg;
   new->arg = arg;
   *pmy_chain = new;
 
   return old_chain;
 }
 
+struct cleanup *
+make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
+                void *arg)
+{
+  return make_my_cleanup2 (pmy_chain, function, arg, NULL);
+}
+
 /* Discard cleanups and do the actions they describe
    until we get back to the point OLD_CHAIN in the cleanup_chain.  */
 
@@ -325,33 +470,18 @@ do_final_cleanups (struct cleanup *old_chain)
   do_my_cleanups (&final_cleanup_chain, old_chain);
 }
 
-void
-do_run_cleanups (struct cleanup *old_chain)
-{
-  do_my_cleanups (&run_cleanup_chain, old_chain);
-}
-
-void
-do_exec_cleanups (struct cleanup *old_chain)
-{
-  do_my_cleanups (&exec_cleanup_chain, old_chain);
-}
-
-void
-do_exec_error_cleanups (struct cleanup *old_chain)
-{
-  do_my_cleanups (&exec_error_cleanup_chain, old_chain);
-}
-
 static void
 do_my_cleanups (struct cleanup **pmy_chain,
                struct cleanup *old_chain)
 {
   struct cleanup *ptr;
+
   while ((ptr = *pmy_chain) != old_chain)
     {
-      *pmy_chain = ptr->next;  /* Do this first incase recursion */
+      *pmy_chain = ptr->next;  /* Do this first in case of recursion.  */
       (*ptr->function) (ptr->arg);
+      if (ptr->free_arg)
+       (*ptr->free_arg) (ptr->arg);
       xfree (ptr);
     }
 }
@@ -371,20 +501,17 @@ discard_final_cleanups (struct cleanup *old_chain)
   discard_my_cleanups (&final_cleanup_chain, old_chain);
 }
 
-void
-discard_exec_error_cleanups (struct cleanup *old_chain)
-{
-  discard_my_cleanups (&exec_error_cleanup_chain, old_chain);
-}
-
 void
 discard_my_cleanups (struct cleanup **pmy_chain,
                     struct cleanup *old_chain)
 {
   struct cleanup *ptr;
+
   while ((ptr = *pmy_chain) != old_chain)
     {
       *pmy_chain = ptr->next;
+      if (ptr->free_arg)
+       (*ptr->free_arg) (ptr->arg);
       xfree (ptr);
     }
 }
@@ -442,6 +569,7 @@ void
 free_current_contents (void *ptr)
 {
   void **location = ptr;
+
   if (location == NULL)
     internal_error (__FILE__, __LINE__,
                    _("free_current_contents: NULL pointer"));
@@ -457,137 +585,367 @@ free_current_contents (void *ptr)
    use the cleanup chain for handling normal cleanups as well as dealing
    with cleanups that need to be done as a result of a call to error().
    In such cases, we may not be certain where the first cleanup is, unless
-   we have a do-nothing one to always use as the base. */
+   we have a do-nothing one to always use as the base.  */
 
 void
 null_cleanup (void *arg)
 {
 }
 
-/* Add a continuation to the continuation list, the global list
-   cmd_continuation. The new continuation will be added at the front.*/
+/* If nonzero, display time usage both at startup and for each command.  */
+
+static int display_time;
+
+/* If nonzero, display space usage both at startup and for each command.  */
+
+static int display_space;
+
+/* Records a run time and space usage to be used as a base for
+   reporting elapsed time or change in space.  In addition,
+   the msg_type field indicates whether the saved time is from the
+   beginning of GDB execution (0) or the beginning of an individual 
+   command execution (1).  */
+struct cmd_stats 
+{
+  int msg_type;
+  long start_time;
+  long start_space;
+};
+
+/* Set whether to display time statistics to NEW_VALUE (non-zero 
+   means true).  */
 void
-add_continuation (void (*continuation_hook) (struct continuation_arg *),
-                 struct continuation_arg *arg_list)
+set_display_time (int new_value)
 {
-  struct continuation *continuation_ptr;
+  display_time = new_value;
+}
 
-  continuation_ptr =
-    (struct continuation *) xmalloc (sizeof (struct continuation));
-  continuation_ptr->continuation_hook = continuation_hook;
-  continuation_ptr->arg_list = arg_list;
-  continuation_ptr->next = cmd_continuation;
-  cmd_continuation = continuation_ptr;
+/* Set whether to display space statistics to NEW_VALUE (non-zero
+   means true).  */
+void
+set_display_space (int new_value)
+{
+  display_space = new_value;
 }
 
-/* Walk down the cmd_continuation list, and execute all the
-   continuations. There is a problem though. In some cases new
-   continuations may be added while we are in the middle of this
-   loop. If this happens they will be added in the front, and done
-   before we have a chance of exhausting those that were already
-   there. We need to then save the beginning of the list in a pointer
-   and do the continuations from there on, instead of using the
-   global beginning of list as our iteration pointer.  */
+/* As indicated by display_time and display_space, report GDB's elapsed time
+   and space usage from the base time and space provided in ARG, which
+   must be a pointer to a struct cmd_stat.  This function is intended
+   to be called as a cleanup.  */
+static void
+report_command_stats (void *arg)
+{
+  struct cmd_stats *start_stats = (struct cmd_stats *) arg;
+  int msg_type = start_stats->msg_type;
+
+  if (display_time)
+    {
+      long cmd_time = get_run_time () - start_stats->start_time;
+
+      printf_unfiltered (msg_type == 0
+                        ? _("Startup time: %ld.%06ld\n")
+                        : _("Command execution time: %ld.%06ld\n"),
+                        cmd_time / 1000000, cmd_time % 1000000);
+    }
+
+  if (display_space)
+    {
+#ifdef HAVE_SBRK
+      char *lim = (char *) sbrk (0);
+
+      long space_now = lim - lim_at_start;
+      long space_diff = space_now - start_stats->start_space;
+
+      printf_unfiltered (msg_type == 0
+                        ? _("Space used: %ld (%c%ld during startup)\n")
+                        : _("Space used: %ld (%c%ld for this command)\n"),
+                        space_now,
+                        (space_diff >= 0 ? '+' : '-'),
+                        space_diff);
+#endif
+    }
+}
+
+/* Create a cleanup that reports time and space used since its
+   creation.  Precise messages depend on MSG_TYPE:
+      0:  Initial time/space
+      1:  Individual command time/space.  */
+struct cleanup *
+make_command_stats_cleanup (int msg_type)
+{
+  struct cmd_stats *new_stat = XMALLOC (struct cmd_stats);
+  
+#ifdef HAVE_SBRK
+  char *lim = (char *) sbrk (0);
+  new_stat->start_space = lim - lim_at_start;
+#endif
+
+  new_stat->msg_type = msg_type;
+  new_stat->start_time = get_run_time ();
+
+  return make_cleanup_dtor (report_command_stats, new_stat, xfree);
+}
+
+/* Continuations are implemented as cleanups internally.  Inherit from
+   cleanups.  */
+struct continuation
+{
+  struct cleanup base;
+};
+
+/* Add a continuation to the continuation list of THREAD.  The new
+   continuation will be added at the front.  */
 void
-do_all_continuations (void)
+add_continuation (struct thread_info *thread,
+                 void (*continuation_hook) (void *), void *args,
+                 void (*continuation_free_args) (void *))
 {
-  struct continuation *continuation_ptr;
-  struct continuation *saved_continuation;
+  struct cleanup *as_cleanup = &thread->continuations->base;
+  make_cleanup_ftype *continuation_hook_fn = continuation_hook;
+
+  make_my_cleanup2 (&as_cleanup,
+                   continuation_hook_fn,
+                   args,
+                   continuation_free_args);
+
+  thread->continuations = (struct continuation *) as_cleanup;
+}
+
+/* Add a continuation to the continuation list of INFERIOR.  The new
+   continuation will be added at the front.  */
+
+void
+add_inferior_continuation (void (*continuation_hook) (void *), void *args,
+                          void (*continuation_free_args) (void *))
+{
+  struct inferior *inf = current_inferior ();
+  struct cleanup *as_cleanup = &inf->continuations->base;
+  make_cleanup_ftype *continuation_hook_fn = continuation_hook;
+
+  make_my_cleanup2 (&as_cleanup,
+                   continuation_hook_fn,
+                   args,
+                   continuation_free_args);
+
+  inf->continuations = (struct continuation *) as_cleanup;
+}
+
+/* Do all continuations of the current inferior.  */
+
+void
+do_all_inferior_continuations (void)
+{
+  struct cleanup *as_cleanup;
+  struct inferior *inf = current_inferior ();
+
+  if (inf->continuations == NULL)
+    return;
 
   /* Copy the list header into another pointer, and set the global
      list header to null, so that the global list can change as a side
-     effect of invoking the continuations and the processing of
-     the preexisting continuations will not be affected. */
-  continuation_ptr = cmd_continuation;
-  cmd_continuation = NULL;
+     effect of invoking the continuations and the processing of the
+     preexisting continuations will not be affected.  */
+
+  as_cleanup = &inf->continuations->base;
+  inf->continuations = NULL;
 
   /* Work now on the list we have set aside.  */
-  while (continuation_ptr)
-    {
-      (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
-      saved_continuation = continuation_ptr;
-      continuation_ptr = continuation_ptr->next;
-      xfree (saved_continuation);
-    }
+  do_my_cleanups (&as_cleanup, NULL);
 }
 
-/* Walk down the cmd_continuation list, and get rid of all the
-   continuations. */
+/* Get rid of all the inferior-wide continuations of INF.  */
+
 void
-discard_all_continuations (void)
+discard_all_inferior_continuations (struct inferior *inf)
 {
-  struct continuation *continuation_ptr;
+  struct cleanup *continuation_ptr = &inf->continuations->base;
 
-  while (cmd_continuation)
-    {
-      continuation_ptr = cmd_continuation;
-      cmd_continuation = continuation_ptr->next;
-      xfree (continuation_ptr);
-    }
+  discard_my_cleanups (&continuation_ptr, NULL);
+  inf->continuations = NULL;
 }
 
-/* Add a continuation to the continuation list, the global list
-   intermediate_continuation.  The new continuation will be added at
-   the front.  */
+static void
+restore_thread_cleanup (void *arg)
+{
+  ptid_t *ptid_p = arg;
+
+  switch_to_thread (*ptid_p);
+}
+
+/* Walk down the continuation list of PTID, and execute all the
+   continuations.  There is a problem though.  In some cases new
+   continuations may be added while we are in the middle of this loop.
+   If this happens they will be added in the front, and done before we
+   have a chance of exhausting those that were already there.  We need
+   to then save the beginning of the list in a pointer and do the
+   continuations from there on, instead of using the global beginning
+   of list as our iteration pointer.  */
+static void
+do_all_continuations_ptid (ptid_t ptid,
+                          struct continuation **continuations_p)
+{
+  struct cleanup *old_chain;
+  ptid_t current_thread;
+  struct cleanup *as_cleanup;
+
+  if (*continuations_p == NULL)
+    return;
+
+  current_thread = inferior_ptid;
+
+  /* Restore selected thread on exit.  Don't try to restore the frame
+     as well, because:
+
+    - When running continuations, the selected frame is always #0.
+
+    - The continuations may trigger symbol file loads, which may
+      change the frame layout (frame ids change), which would trigger
+      a warning if we used make_cleanup_restore_current_thread.  */
+
+  old_chain = make_cleanup (restore_thread_cleanup, &current_thread);
+
+  /* Let the continuation see this thread as selected.  */
+  switch_to_thread (ptid);
+
+  /* Copy the list header into another pointer, and set the global
+     list header to null, so that the global list can change as a side
+     effect of invoking the continuations and the processing of the
+     preexisting continuations will not be affected.  */
+
+  as_cleanup = &(*continuations_p)->base;
+  *continuations_p = NULL;
+
+  /* Work now on the list we have set aside.  */
+  do_my_cleanups (&as_cleanup, NULL);
+
+  do_cleanups (old_chain);
+}
+
+/* Callback for iterate over threads.  */
+static int
+do_all_continuations_thread_callback (struct thread_info *thread, void *data)
+{
+  do_all_continuations_ptid (thread->ptid, &thread->continuations);
+  return 0;
+}
+
+/* Do all continuations of thread THREAD.  */
 void
-add_intermediate_continuation (void (*continuation_hook)
-                              (struct continuation_arg *),
-                              struct continuation_arg *arg_list)
+do_all_continuations_thread (struct thread_info *thread)
 {
-  struct continuation *continuation_ptr;
+  do_all_continuations_thread_callback (thread, NULL);
+}
 
-  continuation_ptr =
-    (struct continuation *) xmalloc (sizeof (struct continuation));
-  continuation_ptr->continuation_hook = continuation_hook;
-  continuation_ptr->arg_list = arg_list;
-  continuation_ptr->next = intermediate_continuation;
-  intermediate_continuation = continuation_ptr;
+/* Do all continuations of all threads.  */
+void
+do_all_continuations (void)
+{
+  iterate_over_threads (do_all_continuations_thread_callback, NULL);
+}
+
+/* Callback for iterate over threads.  */
+static int
+discard_all_continuations_thread_callback (struct thread_info *thread,
+                                          void *data)
+{
+  struct cleanup *continuation_ptr = &thread->continuations->base;
+
+  discard_my_cleanups (&continuation_ptr, NULL);
+  thread->continuations = NULL;
+  return 0;
+}
+
+/* Get rid of all the continuations of THREAD.  */
+void
+discard_all_continuations_thread (struct thread_info *thread)
+{
+  discard_all_continuations_thread_callback (thread, NULL);
+}
+
+/* Get rid of all the continuations of all threads.  */
+void
+discard_all_continuations (void)
+{
+  iterate_over_threads (discard_all_continuations_thread_callback, NULL);
+}
+
+
+/* Add a continuation to the intermediate continuation list of THREAD.
+   The new continuation will be added at the front.  */
+void
+add_intermediate_continuation (struct thread_info *thread,
+                              void (*continuation_hook)
+                              (void *), void *args,
+                              void (*continuation_free_args) (void *))
+{
+  struct cleanup *as_cleanup = &thread->intermediate_continuations->base;
+  make_cleanup_ftype *continuation_hook_fn = continuation_hook;
+
+  make_my_cleanup2 (&as_cleanup,
+                   continuation_hook_fn,
+                   args,
+                   continuation_free_args);
+
+  thread->intermediate_continuations = (struct continuation *) as_cleanup;
 }
 
 /* Walk down the cmd_continuation list, and execute all the
-   continuations. There is a problem though. In some cases new
+   continuations.  There is a problem though.  In some cases new
    continuations may be added while we are in the middle of this
-   loop. If this happens they will be added in the front, and done
+   loop.  If this happens they will be added in the front, and done
    before we have a chance of exhausting those that were already
-   there. We need to then save the beginning of the list in a pointer
+   there.  We need to then save the beginning of the list in a pointer
    and do the continuations from there on, instead of using the
-   global beginning of list as our iteration pointer.*/
+   global beginning of list as our iteration pointer.  */
+static int
+do_all_intermediate_continuations_thread_callback (struct thread_info *thread,
+                                                  void *data)
+{
+  do_all_continuations_ptid (thread->ptid,
+                            &thread->intermediate_continuations);
+  return 0;
+}
+
+/* Do all intermediate continuations of thread THREAD.  */
+void
+do_all_intermediate_continuations_thread (struct thread_info *thread)
+{
+  do_all_intermediate_continuations_thread_callback (thread, NULL);
+}
+
+/* Do all intermediate continuations of all threads.  */
 void
 do_all_intermediate_continuations (void)
 {
-  struct continuation *continuation_ptr;
-  struct continuation *saved_continuation;
+  iterate_over_threads (do_all_intermediate_continuations_thread_callback,
+                       NULL);
+}
 
-  /* Copy the list header into another pointer, and set the global
-     list header to null, so that the global list can change as a side
-     effect of invoking the continuations and the processing of
-     the preexisting continuations will not be affected. */
-  continuation_ptr = intermediate_continuation;
-  intermediate_continuation = NULL;
+/* Callback for iterate over threads.  */
+static int
+discard_all_intermediate_continuations_thread_callback (struct thread_info *thread,
+                                                       void *data)
+{
+  struct cleanup *continuation_ptr = &thread->intermediate_continuations->base;
 
-  /* Work now on the list we have set aside.  */
-  while (continuation_ptr)
-    {
-      (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
-      saved_continuation = continuation_ptr;
-      continuation_ptr = continuation_ptr->next;
-      xfree (saved_continuation);
-    }
+  discard_my_cleanups (&continuation_ptr, NULL);
+  thread->intermediate_continuations = NULL;
+  return 0;
 }
 
-/* Walk down the cmd_continuation list, and get rid of all the
-   continuations. */
+/* Get rid of all the intermediate continuations of THREAD.  */
 void
-discard_all_intermediate_continuations (void)
+discard_all_intermediate_continuations_thread (struct thread_info *thread)
 {
-  struct continuation *continuation_ptr;
+  discard_all_intermediate_continuations_thread_callback (thread, NULL);
+}
 
-  while (intermediate_continuation)
-    {
-      continuation_ptr = intermediate_continuation;
-      intermediate_continuation = continuation_ptr->next;
-      xfree (continuation_ptr);
-    }
+/* Get rid of all the intermediate continuations of all threads.  */
+void
+discard_all_intermediate_continuations (void)
+{
+  iterate_over_threads (discard_all_intermediate_continuations_thread_callback,
+                       NULL);
 }
 \f
 
@@ -606,7 +964,7 @@ vwarning (const char *string, va_list args)
   else
     {
       target_terminal_ours ();
-      wrap_here ("");          /* Force out any buffered output */
+      wrap_here ("");          /* Force out any buffered output */
       gdb_flush (gdb_stdout);
       if (warning_pre_print)
        fputs_unfiltered (warning_pre_print, gdb_stderr);
@@ -626,6 +984,7 @@ void
 warning (const char *string, ...)
 {
   va_list args;
+
   va_start (args, string);
   vwarning (string, args);
   va_end (args);
@@ -635,16 +994,17 @@ warning (const char *string, ...)
    The first argument STRING is the error message, used as a fprintf string,
    and the remaining args are passed as arguments to it.  */
 
-NORETURN void
+void
 verror (const char *string, va_list args)
 {
   throw_verror (GENERIC_ERROR, string, args);
 }
 
-NORETURN void
+void
 error (const char *string, ...)
 {
   va_list args;
+
   va_start (args, string);
   throw_verror (GENERIC_ERROR, string, args);
   va_end (args);
@@ -654,48 +1014,101 @@ error (const char *string, ...)
    The first argument STRING is the error message, used as a fprintf string,
    and the remaining args are passed as arguments to it.  */
 
-NORETURN void
+void
 vfatal (const char *string, va_list args)
 {
   throw_vfatal (string, args);
 }
 
-NORETURN void
+void
 fatal (const char *string, ...)
 {
   va_list args;
+
   va_start (args, string);
   throw_vfatal (string, args);
   va_end (args);
 }
 
-NORETURN void
+void
 error_stream (struct ui_file *stream)
 {
-  long len;
-  char *message = ui_file_xstrdup (stream, &len);
+  char *message = ui_file_xstrdup (stream, NULL);
+
   make_cleanup (xfree, message);
   error (("%s"), message);
 }
 
-/* Print a message reporting an internal error/warning. Ask the user
+/* Dump core trying to increase the core soft limit to hard limit first.  */
+
+static void
+dump_core (void)
+{
+#ifdef HAVE_SETRLIMIT
+  struct rlimit rlim = { RLIM_INFINITY, RLIM_INFINITY };
+
+  setrlimit (RLIMIT_CORE, &rlim);
+#endif /* HAVE_SETRLIMIT */
+
+  abort ();            /* NOTE: GDB has only three calls to abort().  */
+}
+
+/* Check whether GDB will be able to dump core using the dump_core
+   function.  */
+
+static int
+can_dump_core (const char *reason)
+{
+#ifdef HAVE_GETRLIMIT
+  struct rlimit rlim;
+
+  /* Be quiet and assume we can dump if an error is returned.  */
+  if (getrlimit (RLIMIT_CORE, &rlim) != 0)
+    return 1;
+
+  if (rlim.rlim_max == 0)
+    {
+      fprintf_unfiltered (gdb_stderr,
+                         _("%s\nUnable to dump core, use `ulimit -c"
+                           " unlimited' before executing GDB next time.\n"),
+                         reason);
+      return 0;
+    }
+#endif /* HAVE_GETRLIMIT */
+
+  return 1;
+}
+
+/* Allow the user to configure the debugger behavior with respect to
+   what to do when an internal problem is detected.  */
+
+const char internal_problem_ask[] = "ask";
+const char internal_problem_yes[] = "yes";
+const char internal_problem_no[] = "no";
+static const char *internal_problem_modes[] =
+{
+  internal_problem_ask,
+  internal_problem_yes,
+  internal_problem_no,
+  NULL
+};
+
+/* Print a message reporting an internal error/warning.  Ask the user
    if they want to continue, dump core, or just exit.  Return
    something to indicate a quit.  */
 
 struct internal_problem
 {
   const char *name;
-  /* FIXME: cagney/2002-08-15: There should be ``maint set/show''
-     commands available for controlling these variables.  */
-  enum auto_boolean should_quit;
-  enum auto_boolean should_dump_core;
+  const char *should_quit;
+  const char *should_dump_core;
 };
 
 /* Report a problem, internal to GDB, to the user.  Once the problem
    has been reported, and assuming GDB didn't quit, the caller can
    either allow execution to resume or throw an error.  */
 
-static void ATTR_FORMAT (printf, 4, 0)
+static void ATTRIBUTE_PRINTF (4, 0)
 internal_vproblem (struct internal_problem *problem,
                   const char *file, int line, const char *fmt, va_list ap)
 {
@@ -707,6 +1120,7 @@ internal_vproblem (struct internal_problem *problem,
   /* Don't allow infinite error/warning recursion.  */
   {
     static char msg[] = "Recursive internal problem.\n";
+
     switch (dejavu)
       {
       case 0:
@@ -718,7 +1132,13 @@ internal_vproblem (struct internal_problem *problem,
        abort ();       /* NOTE: GDB has only three calls to abort().  */
       default:
        dejavu = 3;
-       write (STDERR_FILENO, msg, sizeof (msg));
+        /* Newer GLIBC versions put the warn_unused_result attribute
+           on write, but this is one of those rare cases where
+           ignoring the return value is correct.  Casting to (void)
+           does not fix this problem.  This is the solution suggested
+           at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509.  */
+       if (write (STDERR_FILENO, msg, sizeof (msg)) != sizeof (msg))
+          abort (); /* NOTE: GDB has only three calls to abort().  */
        exit (1);
       }
   }
@@ -734,56 +1154,61 @@ internal_vproblem (struct internal_problem *problem,
      so that the user knows that they are living on the edge.  */
   {
     char *msg;
+
     msg = xstrvprintf (fmt, ap);
-    reason = xstrprintf ("\
-%s:%d: %s: %s\n\
-A problem internal to GDB has been detected,\n\
-further debugging may prove unreliable.", file, line, problem->name, msg);
+    reason = xstrprintf ("%s:%d: %s: %s\n"
+                        "A problem internal to GDB has been detected,\n"
+                        "further debugging may prove unreliable.",
+                        file, line, problem->name, msg);
     xfree (msg);
     make_cleanup (xfree, reason);
   }
 
-  switch (problem->should_quit)
+  if (problem->should_quit == internal_problem_ask)
     {
-    case AUTO_BOOLEAN_AUTO:
       /* Default (yes/batch case) is to quit GDB.  When in batch mode
-         this lessens the likelhood of GDB going into an infinate
-         loop.  */
-      quit_p = query (_("%s\nQuit this debugging session? "), reason);
-      break;
-    case AUTO_BOOLEAN_TRUE:
-      quit_p = 1;
-      break;
-    case AUTO_BOOLEAN_FALSE:
-      quit_p = 0;
-      break;
-    default:
-      internal_error (__FILE__, __LINE__, _("bad switch"));
+        this lessens the likelihood of GDB going into an infinite
+        loop.  */
+      if (caution == 0)
+        {
+          /* Emit the message and quit.  */
+          fputs_unfiltered (reason, gdb_stderr);
+          fputs_unfiltered ("\n", gdb_stderr);
+          quit_p = 1;
+        }
+      else
+        quit_p = query (_("%s\nQuit this debugging session? "), reason);
     }
+  else if (problem->should_quit == internal_problem_yes)
+    quit_p = 1;
+  else if (problem->should_quit == internal_problem_no)
+    quit_p = 0;
+  else
+    internal_error (__FILE__, __LINE__, _("bad switch"));
 
-  switch (problem->should_dump_core)
+  if (problem->should_dump_core == internal_problem_ask)
     {
-    case AUTO_BOOLEAN_AUTO:
-      /* Default (yes/batch case) is to dump core.  This leaves a GDB
-         `dropping' so that it is easier to see that something went
-         wrong in GDB.  */
-      dump_core_p = query (_("%s\nCreate a core file of GDB? "), reason);
-      break;
-      break;
-    case AUTO_BOOLEAN_TRUE:
-      dump_core_p = 1;
-      break;
-    case AUTO_BOOLEAN_FALSE:
-      dump_core_p = 0;
-      break;
-    default:
-      internal_error (__FILE__, __LINE__, _("bad switch"));
+      if (!can_dump_core (reason))
+       dump_core_p = 0;
+      else
+       {
+         /* Default (yes/batch case) is to dump core.  This leaves a GDB
+            `dropping' so that it is easier to see that something went
+            wrong in GDB.  */
+         dump_core_p = query (_("%s\nCreate a core file of GDB? "), reason);
+       }
     }
+  else if (problem->should_dump_core == internal_problem_yes)
+    dump_core_p = can_dump_core (reason);
+  else if (problem->should_dump_core == internal_problem_no)
+    dump_core_p = 0;
+  else
+    internal_error (__FILE__, __LINE__, _("bad switch"));
 
   if (quit_p)
     {
       if (dump_core_p)
-       abort ();               /* NOTE: GDB has only three calls to abort().  */
+       dump_core ();
       else
        exit (1);
     }
@@ -793,7 +1218,7 @@ further debugging may prove unreliable.", file, line, problem->name, msg);
        {
 #ifdef HAVE_WORKING_FORK
          if (fork () == 0)
-           abort ();           /* NOTE: GDB has only three calls to abort().  */
+           dump_core ();
 #endif
        }
     }
@@ -802,27 +1227,28 @@ further debugging may prove unreliable.", file, line, problem->name, msg);
 }
 
 static struct internal_problem internal_error_problem = {
-  "internal-error", AUTO_BOOLEAN_AUTO, AUTO_BOOLEAN_AUTO
+  "internal-error", internal_problem_ask, internal_problem_ask
 };
 
-NORETURN void
+void
 internal_verror (const char *file, int line, const char *fmt, va_list ap)
 {
   internal_vproblem (&internal_error_problem, file, line, fmt, ap);
   deprecated_throw_reason (RETURN_ERROR);
 }
 
-NORETURN void
+void
 internal_error (const char *file, int line, const char *string, ...)
 {
   va_list ap;
+
   va_start (ap, string);
   internal_verror (file, line, string, ap);
   va_end (ap);
 }
 
 static struct internal_problem internal_warning_problem = {
-  "internal-warning", AUTO_BOOLEAN_AUTO, AUTO_BOOLEAN_AUTO
+  "internal-warning", internal_problem_ask, internal_problem_ask
 };
 
 void
@@ -835,16 +1261,118 @@ void
 internal_warning (const char *file, int line, const char *string, ...)
 {
   va_list ap;
+
   va_start (ap, string);
   internal_vwarning (file, line, string, ap);
   va_end (ap);
 }
 
+/* Dummy functions to keep add_prefix_cmd happy.  */
+
+static void
+set_internal_problem_cmd (char *args, int from_tty)
+{
+}
+
+static void
+show_internal_problem_cmd (char *args, int from_tty)
+{
+}
+
+/* When GDB reports an internal problem (error or warning) it gives
+   the user the opportunity to quit GDB and/or create a core file of
+   the current debug session.  This function registers a few commands
+   that make it possible to specify that GDB should always or never
+   quit or create a core file, without asking.  The commands look
+   like:
+
+   maint set PROBLEM-NAME quit ask|yes|no
+   maint show PROBLEM-NAME quit
+   maint set PROBLEM-NAME corefile ask|yes|no
+   maint show PROBLEM-NAME corefile
+
+   Where PROBLEM-NAME is currently "internal-error" or
+   "internal-warning".  */
+
+static void
+add_internal_problem_command (struct internal_problem *problem)
+{
+  struct cmd_list_element **set_cmd_list;
+  struct cmd_list_element **show_cmd_list;
+  char *set_doc;
+  char *show_doc;
+
+  set_cmd_list = xmalloc (sizeof (*set_cmd_list));
+  show_cmd_list = xmalloc (sizeof (*set_cmd_list));
+  *set_cmd_list = NULL;
+  *show_cmd_list = NULL;
+
+  set_doc = xstrprintf (_("Configure what GDB does when %s is detected."),
+                       problem->name);
+
+  show_doc = xstrprintf (_("Show what GDB does when %s is detected."),
+                        problem->name);
+
+  add_prefix_cmd ((char*) problem->name,
+                 class_maintenance, set_internal_problem_cmd, set_doc,
+                 set_cmd_list,
+                 concat ("maintenance set ", problem->name, " ",
+                         (char *) NULL),
+                 0/*allow-unknown*/, &maintenance_set_cmdlist);
+
+  add_prefix_cmd ((char*) problem->name,
+                 class_maintenance, show_internal_problem_cmd, show_doc,
+                 show_cmd_list,
+                 concat ("maintenance show ", problem->name, " ",
+                         (char *) NULL),
+                 0/*allow-unknown*/, &maintenance_show_cmdlist);
+
+  set_doc = xstrprintf (_("Set whether GDB should quit "
+                         "when an %s is detected"),
+                       problem->name);
+  show_doc = xstrprintf (_("Show whether GDB will quit "
+                          "when an %s is detected"),
+                        problem->name);
+  add_setshow_enum_cmd ("quit", class_maintenance,
+                       internal_problem_modes,
+                       &problem->should_quit,
+                       set_doc,
+                       show_doc,
+                       NULL, /* help_doc */
+                       NULL, /* setfunc */
+                       NULL, /* showfunc */
+                       set_cmd_list,
+                       show_cmd_list);
+
+  xfree (set_doc);
+  xfree (show_doc);
+
+  set_doc = xstrprintf (_("Set whether GDB should create a core "
+                         "file of GDB when %s is detected"),
+                       problem->name);
+  show_doc = xstrprintf (_("Show whether GDB will create a core "
+                          "file of GDB when %s is detected"),
+                        problem->name);
+  add_setshow_enum_cmd ("corefile", class_maintenance,
+                       internal_problem_modes,
+                       &problem->should_dump_core,
+                       set_doc,
+                       show_doc,
+                       NULL, /* help_doc */
+                       NULL, /* setfunc */
+                       NULL, /* showfunc */
+                       set_cmd_list,
+                       show_cmd_list);
+
+  xfree (set_doc);
+  xfree (show_doc);
+}
+
 /* Print the system error message for errno, and also mention STRING
    as the file name for which the error was encountered.
    Then return to command level.  */
 
-NORETURN void
+void
 perror_with_name (const char *string)
 {
   char *err;
@@ -858,7 +1386,7 @@ perror_with_name (const char *string)
 
   /* I understand setting these is a matter of taste.  Still, some people
      may clear errno but not know about bfd_error.  Doing this here is not
-     unreasonable. */
+     unreasonable.  */
   bfd_set_error (bfd_error_no_error);
   errno = 0;
 
@@ -906,23 +1434,11 @@ quit (void)
 #endif
 }
 
-/* Control C comes here */
-void
-request_quit (int signo)
-{
-  quit_flag = 1;
-  /* Restore the signal handler.  Harmless with BSD-style signals,
-     needed for System V-style signals.  */
-  signal (signo, request_quit);
-
-  if (immediate_quit)
-    quit ();
-}
 \f
 /* Called when a memory allocation fails, with the number of bytes of
-   memory requested in SIZE. */
+   memory requested in SIZE.  */
 
-NORETURN void
+void
 nomem (long size)
 {
   if (size > 0)
@@ -946,7 +1462,7 @@ nomem (long size)
 /* NOTE: These are declared using PTR to ensure consistency with
    "libiberty.h".  xfree() is GDB local.  */
 
-PTR                            /* OK: PTR */
+PTR                            /* ARI: PTR */
 xmalloc (size_t size)
 {
   void *val;
@@ -956,7 +1472,7 @@ xmalloc (size_t size)
   if (size == 0)
     size = 1;
 
-  val = malloc (size);         /* OK: malloc */
+  val = malloc (size);         /* ARI: malloc */
   if (val == NULL)
     nomem (size);
 
@@ -969,8 +1485,8 @@ xzalloc (size_t size)
   return xcalloc (1, size);
 }
 
-PTR                            /* OK: PTR */
-xrealloc (PTR ptr, size_t size)        /* OK: PTR */
+PTR                            /* ARI: PTR */
+xrealloc (PTR ptr, size_t size)        /* ARI: PTR */
 {
   void *val;
 
@@ -980,16 +1496,16 @@ xrealloc (PTR ptr, size_t size)  /* OK: PTR */
     size = 1;
 
   if (ptr != NULL)
-    val = realloc (ptr, size); /* OK: realloc */
+    val = realloc (ptr, size); /* ARI: realloc */
   else
-    val = malloc (size);               /* OK: malloc */
+    val = malloc (size);               /* ARI: malloc */
   if (val == NULL)
     nomem (size);
 
   return (val);
 }
 
-PTR                            /* OK: PTR */
+PTR                            /* ARI: PTR */
 xcalloc (size_t number, size_t size)
 {
   void *mem;
@@ -1002,7 +1518,7 @@ xcalloc (size_t number, size_t size)
       size = 1;
     }
 
-  mem = calloc (number, size);         /* OK: xcalloc */
+  mem = calloc (number, size);         /* ARI: xcalloc */
   if (mem == NULL)
     nomem (number * size);
 
@@ -1013,18 +1529,19 @@ void
 xfree (void *ptr)
 {
   if (ptr != NULL)
-    free (ptr);                /* OK: free */
+    free (ptr);                /* ARI: free */
 }
 \f
 
 /* Like asprintf/vasprintf but get an internal_error if the call
-   fails. */
+   fails.  */
 
 char *
 xstrprintf (const char *format, ...)
 {
   char *ret;
   va_list args;
+
   va_start (args, format);
   ret = xstrvprintf (format, args);
   va_end (args);
@@ -1035,6 +1552,7 @@ void
 xasprintf (char **ret, const char *format, ...)
 {
   va_list args;
+
   va_start (args, format);
   (*ret) = xstrvprintf (format, args);
   va_end (args);
@@ -1051,6 +1569,7 @@ xstrvprintf (const char *format, va_list ap)
 {
   char *ret = NULL;
   int status = vasprintf (&ret, format, ap);
+
   /* NULL is returned when there was a memory allocation problem, or
      any other error (for instance, a bad format string).  A negative
      status (the printed length) with a non-NULL buffer should never
@@ -1104,6 +1623,7 @@ char *
 savestring (const char *ptr, size_t size)
 {
   char *p = (char *) xmalloc (size + 1);
+
   memcpy (p, ptr, size);
   p[size] = 0;
   return p;
@@ -1120,105 +1640,52 @@ print_spaces (int n, struct ui_file *file)
 void
 gdb_print_host_address (const void *addr, struct ui_file *stream)
 {
-
-  /* We could use the %p conversion specifier to fprintf if we had any
-     way of knowing whether this host supports it.  But the following
-     should work on the Alpha and on 32 bit machines.  */
-
-  fprintf_filtered (stream, "0x%lx", (unsigned long) addr);
+  fprintf_filtered (stream, "%s", host_address_to_string (addr));
 }
+\f
 
-/* Ask user a y-or-n question and return 1 iff answer is yes.
-   Takes three args which are given to printf to print the question.
-   The first, a control string, should end in "? ".
-   It should not say how to answer, because we do that.  */
-
-/* VARARGS */
-int
-query (const char *ctlstr, ...)
-{
-  va_list args;
-  int answer;
-  int ans2;
-  int retval;
-
-  /* Automatically answer "yes" if input is not from the user
-     directly, or if the user did not want prompts.  */
-  if (!input_from_terminal_p () || !caution)
-    return 1;
-
-  if (deprecated_query_hook)
-    {
-      va_start (args, ctlstr);
-      return deprecated_query_hook (ctlstr, args);
-    }
-
-  while (1)
-    {
-      wrap_here ("");          /* Flush any buffered output */
-      gdb_flush (gdb_stdout);
-
-      if (annotation_level > 1)
-       printf_filtered (("\n\032\032pre-query\n"));
-
-      va_start (args, ctlstr);
-      vfprintf_filtered (gdb_stdout, ctlstr, args);
-      va_end (args);
-      printf_filtered (_("(y or n) "));
+/* A cleanup function that calls regfree.  */
 
-      if (annotation_level > 1)
-       printf_filtered (("\n\032\032query\n"));
+static void
+do_regfree_cleanup (void *r)
+{
+  regfree (r);
+}
 
-      wrap_here ("");
-      gdb_flush (gdb_stdout);
+/* Create a new cleanup that frees the compiled regular expression R.  */
 
-      answer = fgetc (stdin);
-      clearerr (stdin);                /* in case of C-d */
-      if (answer == EOF)       /* C-d */
-       {
-         retval = 1;
-         break;
-       }
-      /* Eat rest of input line, to EOF or newline */
-      if (answer != '\n')
-       do
-         {
-           ans2 = fgetc (stdin);
-           clearerr (stdin);
-         }
-       while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
+struct cleanup *
+make_regfree_cleanup (regex_t *r)
+{
+  return make_cleanup (do_regfree_cleanup, r);
+}
 
-      if (answer >= 'a')
-       answer -= 040;
-      if (answer == 'Y')
-       {
-         retval = 1;
-         break;
-       }
-      if (answer == 'N')
-       {
-         retval = 0;
-         break;
-       }
-      printf_filtered (_("Please answer y or n.\n"));
-    }
+/* Return an xmalloc'd error message resulting from a regular
+   expression compilation failure.  */
 
-  if (annotation_level > 1)
-    printf_filtered (("\n\032\032post-query\n"));
-  return retval;
+char *
+get_regcomp_error (int code, regex_t *rx)
+{
+  size_t length = regerror (code, rx, NULL, 0);
+  char *result = xmalloc (length);
+
+  regerror (code, rx, result, length);
+  return result;
 }
+
 \f
 
-/* This function supports the nquery() and yquery() functions.
+/* This function supports the query, nquery, and yquery functions.
    Ask user a y-or-n question and return 0 if answer is no, 1 if
-   answer is yes, or default the answer to the specified default.
-   DEFCHAR is either 'y' or 'n' and refers to the default answer.
+   answer is yes, or default the answer to the specified default
+   (for yquery or nquery).  DEFCHAR may be 'y' or 'n' to provide a
+   default answer, or '\0' for no default.
    CTLSTR is the control string and should end in "? ".  It should
    not say how to answer, because we do that.
    ARGS are the arguments passed along with the CTLSTR argument to
    printf.  */
 
-static int ATTR_FORMAT (printf, 1, 0)
+static int ATTRIBUTE_PRINTF (1, 0)
 defaulted_query (const char *ctlstr, const char defchar, va_list args)
 {
   int answer;
@@ -1226,10 +1693,18 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
   int retval;
   int def_value;
   char def_answer, not_def_answer;
-  char *y_string, *n_string;
+  char *y_string, *n_string, *question;
 
   /* Set up according to which answer is the default.  */
-  if (defchar == 'y')
+  if (defchar == '\0')
+    {
+      def_value = 1;
+      def_answer = 'Y';
+      not_def_answer = 'N';
+      y_string = "y";
+      n_string = "n";
+    }
+  else if (defchar == 'y')
     {
       def_value = 1;
       def_answer = 'Y';
@@ -1246,25 +1721,45 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
       n_string = "[n]";
     }
 
-  /* Automatically answer the default value if input is not from the user
-     directly, or if the user did not want prompts.  */
-  if (!input_from_terminal_p () || !caution)
+  /* Automatically answer the default value if the user did not want
+     prompts or the command was issued with the server prefix.  */
+  if (! caution || server_command)
     return def_value;
 
+  /* If input isn't coming from the user directly, just say what
+     question we're asking, and then answer the default automatically.  This
+     way, important error messages don't get lost when talking to GDB
+     over a pipe.  */
+  if (! input_from_terminal_p ())
+    {
+      wrap_here ("");
+      vfprintf_filtered (gdb_stdout, ctlstr, args);
+
+      printf_filtered (_("(%s or %s) [answered %c; "
+                        "input not from terminal]\n"),
+                      y_string, n_string, def_answer);
+      gdb_flush (gdb_stdout);
+
+      return def_value;
+    }
+
   if (deprecated_query_hook)
     {
       return deprecated_query_hook (ctlstr, args);
     }
 
+  /* Format the question outside of the loop, to avoid reusing args.  */
+  question = xstrvprintf (ctlstr, args);
+
   while (1)
     {
-      wrap_here ("");          /* Flush any buffered output */
+      wrap_here ("");          /* Flush any buffered output */
       gdb_flush (gdb_stdout);
 
       if (annotation_level > 1)
        printf_filtered (("\n\032\032pre-query\n"));
 
-      vfprintf_filtered (gdb_stdout, ctlstr, args);
+      fputs_filtered (question, gdb_stdout);
       printf_filtered (_("(%s or %s) "), y_string, n_string);
 
       if (annotation_level > 1)
@@ -1274,13 +1769,33 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
       gdb_flush (gdb_stdout);
 
       answer = fgetc (stdin);
+
+      /* We expect fgetc to block until a character is read.  But
+         this may not be the case if the terminal was opened with
+         the NONBLOCK flag.  In that case, if there is nothing to
+         read on stdin, fgetc returns EOF, but also sets the error
+         condition flag on stdin and errno to EAGAIN.  With a true
+         EOF, stdin's error condition flag is not set.
+
+         A situation where this behavior was observed is a pseudo
+         terminal on AIX.  */
+      while (answer == EOF && ferror (stdin) && errno == EAGAIN)
+        {
+          /* Not a real EOF.  Wait a little while and try again until
+             we read something.  */
+          clearerr (stdin);
+          gdb_usleep (10000);
+          answer = fgetc (stdin);
+        }
+
       clearerr (stdin);                /* in case of C-d */
       if (answer == EOF)       /* C-d */
        {
+         printf_filtered ("EOF [assumed %c]\n", def_answer);
          retval = def_value;
          break;
        }
-      /* Eat rest of input line, to EOF or newline */
+      /* Eat rest of input line, to EOF or newline */
       if (answer != '\n')
        do
          {
@@ -1298,10 +1813,12 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
          retval = !def_value;
          break;
        }
-      /* Otherwise, for the default, the user may either specify
-         the required input or have it default by entering nothing.  */
-      if (answer == def_answer || answer == '\n' || 
-         answer == '\r' || answer == EOF)
+      /* Otherwise, if a default was specified, the user may either
+         specify the required input or have it default by entering
+         nothing.  */
+      if (answer == def_answer
+         || (defchar != '\0' &&
+             (answer == '\n' || answer == '\r' || answer == EOF)))
        {
          retval = def_value;
          break;
@@ -1311,6 +1828,7 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
                       y_string, n_string);
     }
 
+  xfree (question);
   if (annotation_level > 1)
     printf_filtered (("\n\032\032post-query\n"));
   return retval;
@@ -1349,21 +1867,48 @@ yquery (const char *ctlstr, ...)
   va_end (args);
 }
 
-/* Print an error message saying that we couldn't make sense of a
-   \^mumble sequence in a string or character constant.  START and END
-   indicate a substring of some larger string that contains the
-   erroneous backslash sequence, missing the initial backslash.  */
-static NORETURN int
-no_control_char_error (const char *start, const char *end)
+/* Ask user a y-or-n question and return 1 iff answer is yes.
+   Takes three args which are given to printf to print the question.
+   The first, a control string, should end in "? ".
+   It should not say how to answer, because we do that.  */
+
+int
+query (const char *ctlstr, ...)
+{
+  va_list args;
+
+  va_start (args, ctlstr);
+  return defaulted_query (ctlstr, '\0', args);
+  va_end (args);
+}
+
+/* A helper for parse_escape that converts a host character to a
+   target character.  C is the host character.  If conversion is
+   possible, then the target character is stored in *TARGET_C and the
+   function returns 1.  Otherwise, the function returns 0.  */
+
+static int
+host_char_to_target (struct gdbarch *gdbarch, int c, int *target_c)
 {
-  int len = end - start;
-  char *copy = alloca (end - start + 1);
+  struct obstack host_data;
+  char the_char = c;
+  struct cleanup *cleanups;
+  int result = 0;
+
+  obstack_init (&host_data);
+  cleanups = make_cleanup_obstack_free (&host_data);
 
-  memcpy (copy, start, len);
-  copy[len] = '\0';
+  convert_between_encodings (target_charset (gdbarch), host_charset (),
+                            &the_char, 1, 1, &host_data, translit_none);
+
+  if (obstack_object_size (&host_data) == 1)
+    {
+      result = 1;
+      *target_c = *(char *) obstack_base (&host_data);
+    }
 
-  error (_("There is no control character `\\%s' in the `%s' character set."),
-        copy, target_charset ());
+  do_cleanups (cleanups);
+  return result;
 }
 
 /* Parse a C escape sequence.  STRING_PTR points to a variable
@@ -1382,57 +1927,18 @@ no_control_char_error (const char *start, const char *end)
    after the zeros.  A value of 0 does not mean end of string.  */
 
 int
-parse_escape (char **string_ptr)
+parse_escape (struct gdbarch *gdbarch, char **string_ptr)
 {
-  int target_char;
+  int target_char = -2;        /* Initialize to avoid GCC warnings.  */
   int c = *(*string_ptr)++;
-  if (c_parse_backslash (c, &target_char))
-    return target_char;
-  else
-    switch (c)
-      {
+
+  switch (c)
+    {
       case '\n':
        return -2;
       case 0:
        (*string_ptr)--;
        return 0;
-      case '^':
-       {
-         /* Remember where this escape sequence started, for reporting
-            errors.  */
-         char *sequence_start_pos = *string_ptr - 1;
-
-         c = *(*string_ptr)++;
-
-         if (c == '?')
-           {
-             /* XXXCHARSET: What is `delete' in the host character set?  */
-             c = 0177;
-
-             if (!host_char_to_target (c, &target_char))
-               error (_("There is no character corresponding to `Delete' "
-                      "in the target character set `%s'."), host_charset ());
-
-             return target_char;
-           }
-         else if (c == '\\')
-           target_char = parse_escape (string_ptr);
-         else
-           {
-             if (!host_char_to_target (c, &target_char))
-               no_control_char_error (sequence_start_pos, *string_ptr);
-           }
-
-         /* Now target_char is something like `c', and we want to find
-            its control-character equivalent.  */
-         if (!target_char_to_control_char (target_char, &target_char))
-           no_control_char_error (sequence_start_pos, *string_ptr);
-
-         return target_char;
-       }
-
-       /* XXXCHARSET: we need to use isdigit and value-of-digit
-          methods of the host character set here.  */
 
       case '0':
       case '1':
@@ -1443,16 +1949,16 @@ parse_escape (char **string_ptr)
       case '6':
       case '7':
        {
-         int i = c - '0';
+         int i = host_hex_value (c);
          int count = 0;
          while (++count < 3)
            {
              c = (**string_ptr);
-             if (c >= '0' && c <= '7')
+             if (isdigit (c) && c != '8' && c != '9')
                {
                  (*string_ptr)++;
                  i *= 8;
-                 i += c - '0';
+                 i += host_hex_value (c);
                }
              else
                {
@@ -1461,27 +1967,51 @@ parse_escape (char **string_ptr)
            }
          return i;
        }
-      default:
-       if (!host_char_to_target (c, &target_char))
-         error
-           ("The escape sequence `\%c' is equivalent to plain `%c', which"
-            " has no equivalent\n" "in the `%s' character set.", c, c,
-            target_charset ());
-       return target_char;
-      }
+
+    case 'a':
+      c = '\a';
+      break;
+    case 'b':
+      c = '\b';
+      break;
+    case 'f':
+      c = '\f';
+      break;
+    case 'n':
+      c = '\n';
+      break;
+    case 'r':
+      c = '\r';
+      break;
+    case 't':
+      c = '\t';
+      break;
+    case 'v':
+      c = '\v';
+      break;
+
+    default:
+      break;
+    }
+
+  if (!host_char_to_target (gdbarch, c, &target_char))
+    error
+      ("The escape sequence `\%c' is equivalent to plain `%c', which"
+       " has no equivalent\n" "in the `%s' character set.", c, c,
+       target_charset (gdbarch));
+  return target_char;
 }
 \f
 /* Print the character C on STREAM as part of the contents of a literal
    string whose delimiter is QUOTER.  Note that this routine should only
    be call for printing things which are independent of the language
-   of the program being debugged. */
+   of the program being debugged.  */
 
 static void
 printchar (int c, void (*do_fputs) (const char *, struct ui_file *),
           void (*do_fprintf) (struct ui_file *, const char *, ...)
           ATTRIBUTE_FPTR_PRINTF_2, struct ui_file *stream, int quoter)
 {
-
   c &= 0xFF;                   /* Avoid sign bit follies */
 
   if (c < 0x20 ||              /* Low control chars */
@@ -1527,7 +2057,7 @@ printchar (int c, void (*do_fputs) (const char *, struct ui_file *),
 /* Print the character C on STREAM as part of the contents of a
    literal string whose delimiter is QUOTER.  Note that these routines
    should only be call for printing things which are independent of
-   the language of the program being debugged. */
+   the language of the program being debugged.  */
 
 void
 fputstr_filtered (const char *str, int quoter, struct ui_file *stream)
@@ -1548,6 +2078,7 @@ fputstrn_filtered (const char *str, int n, int quoter,
                   struct ui_file *stream)
 {
   int i;
+
   for (i = 0; i < n; i++)
     printchar (str[i], fputs_filtered, fprintf_filtered, stream, quoter);
 }
@@ -1557,6 +2088,7 @@ fputstrn_unfiltered (const char *str, int n, int quoter,
                     struct ui_file *stream)
 {
   int i;
+
   for (i = 0; i < n; i++)
     printchar (str[i], fputs_unfiltered, fprintf_unfiltered, stream, quoter);
 }
@@ -1568,8 +2100,8 @@ static void
 show_lines_per_page (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Number of lines gdb thinks are in a page is %s.\n"),
+  fprintf_filtered (file,
+                   _("Number of lines gdb thinks are in a page is %s.\n"),
                    value);
 }
 
@@ -1579,8 +2111,9 @@ static void
 show_chars_per_line (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Number of characters gdb thinks are in a line is %s.\n"),
+  fprintf_filtered (file,
+                   _("Number of characters gdb thinks "
+                     "are in a line is %s.\n"),
                    value);
 }
 
@@ -1617,6 +2150,12 @@ static int wrap_column;
 void
 init_page_info (void)
 {
+  if (batch_flag)
+    {
+      lines_per_page = UINT_MAX;
+      chars_per_line = UINT_MAX;
+    }
+  else
 #if defined(TUI)
   if (!tui_get_command_dimension (&chars_per_line, &lines_per_page))
 #endif
@@ -1661,6 +2200,44 @@ init_page_info (void)
   set_width ();
 }
 
+/* Helper for make_cleanup_restore_page_info.  */
+
+static void
+do_restore_page_info_cleanup (void *arg)
+{
+  set_screen_size ();
+  set_width ();
+}
+
+/* Provide cleanup for restoring the terminal size.  */
+
+struct cleanup *
+make_cleanup_restore_page_info (void)
+{
+  struct cleanup *back_to;
+
+  back_to = make_cleanup (do_restore_page_info_cleanup, NULL);
+  make_cleanup_restore_uinteger (&lines_per_page);
+  make_cleanup_restore_uinteger (&chars_per_line);
+
+  return back_to;
+}
+
+/* Temporarily set BATCH_FLAG and the associated unlimited terminal size.
+   Provide cleanup for restoring the original state.  */
+
+struct cleanup *
+set_batch_flag_and_make_cleanup_restore_page_info (void)
+{
+  struct cleanup *back_to = make_cleanup_restore_page_info ();
+  
+  make_cleanup_restore_integer (&batch_flag);
+  batch_flag = 1;
+  init_page_info ();
+
+  return back_to;
+}
+
 /* Set the screen size based on LINES_PER_PAGE and CHARS_PER_LINE.  */
 
 static void
@@ -1673,7 +2250,7 @@ set_screen_size (void)
     rows = INT_MAX;
 
   if (cols <= 0)
-    rl_get_screen_size (NULL, &cols);
+    cols = INT_MAX;
 
   /* Update Readline's idea of the terminal size.  */
   rl_set_screen_size (rows, cols);
@@ -1752,6 +2329,7 @@ prompt_for_continue (void)
   if (ignore)
     {
       char *p = ignore;
+
       while (*p == ' ' || *p == '\t')
        ++p;
       if (p[0] == 'q')
@@ -1764,7 +2342,7 @@ prompt_for_continue (void)
      need to save the ---Type <return>--- line at the top of the screen.  */
   reinitialize_more_filter ();
 
-  dont_repeat ();              /* Forget prev cmd -- CR won't repeat it. */
+  dont_repeat ();              /* Forget prev cmd -- CR won't repeat it.  */
 }
 
 /* Reinitialize filter; ie. tell it to reset to original values.  */
@@ -1777,7 +2355,7 @@ reinitialize_more_filter (void)
 }
 
 /* Indicate that if the next sequence of characters overflows the line,
-   a newline should be inserted here rather than when it hits the end. 
+   a newline should be inserted here rather than when it hits the end.
    If INDENT is non-null, it is a string to be printed to indent the
    wrapped part on the next line.  INDENT must remain accessible until
    the next call to wrap_here() or until a newline is printed through
@@ -1800,9 +2378,10 @@ reinitialize_more_filter (void)
 void
 wrap_here (char *indent)
 {
-  /* This should have been allocated, but be paranoid anyway. */
+  /* This should have been allocated, but be paranoid anyway.  */
   if (!wrap_buffer)
-    internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+    internal_error (__FILE__, __LINE__,
+                   _("failed internal consistency check"));
 
   if (wrap_buffer[0])
     {
@@ -1811,7 +2390,7 @@ wrap_here (char *indent)
     }
   wrap_pointer = wrap_buffer;
   wrap_buffer[0] = '\0';
-  if (chars_per_line == UINT_MAX)      /* No line overflow checking */
+  if (chars_per_line == UINT_MAX)      /* No line overflow checking */
     {
       wrap_column = 0;
     }
@@ -1833,11 +2412,11 @@ wrap_here (char *indent)
 }
 
 /* Print input string to gdb_stdout, filtered, with wrap, 
-   arranging strings in columns of n chars. String can be
+   arranging strings in columns of n chars.  String can be
    right or left justified in the column.  Never prints 
    trailing spaces.  String should never be longer than
    width.  FIXME: this could be useful for the EXAMINE 
-   command, which currently doesn't tabulate very well */
+   command, which currently doesn't tabulate very well */
 
 void
 puts_filtered_tabular (char *string, int width, int right)
@@ -1878,9 +2457,9 @@ puts_filtered_tabular (char *string, int width, int right)
 
 
 /* Ensure that whatever gets printed next, using the filtered output
-   commands, starts at the beginning of the line.  I.E. if there is
+   commands, starts at the beginning of the line.  I.e. if there is
    any pending output for the current line, flush it and start a new
-   line.  Otherwise do nothing. */
+   line.  Otherwise do nothing.  */
 
 void
 begin_line (void)
@@ -1915,8 +2494,12 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
     return;
 
   /* Don't do any filtering if it is disabled.  */
-  if ((stream != gdb_stdout) || !pagination_enabled
-      || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX))
+  if (stream != gdb_stdout
+      || ! pagination_enabled
+      || ! input_from_terminal_p ()
+      || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX)
+      || top_level_interpreter () == NULL
+      || ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
     {
       fputs_unfiltered (linebuffer, stream);
       return;
@@ -1974,16 +2557,16 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
              if (lines_printed >= lines_per_page - 1)
                prompt_for_continue ();
 
-             /* Now output indentation and wrapped string */
+             /* Now output indentation and wrapped string */
              if (wrap_column)
                {
                  fputs_unfiltered (wrap_indent, stream);
-                 *wrap_pointer = '\0'; /* Null-terminate saved stuff */
-                 fputs_unfiltered (wrap_buffer, stream);       /* and eject it */
+                 *wrap_pointer = '\0'; /* Null-terminate saved stuff, */
+                 fputs_unfiltered (wrap_buffer, stream); /* and eject it.  */
                  /* FIXME, this strlen is what prevents wrap_indent from
                     containing tabs.  However, if we recurse to print it
                     and count its chars, we risk trouble if wrap_indent is
-                    longer than (the user settable) chars_per_line. 
+                    longer than (the user settable) chars_per_line.
                     Note also that this can set chars_printed > chars_per_line
                     if we are printing a long string.  */
                  chars_printed = strlen (wrap_indent)
@@ -1998,7 +2581,8 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
       if (*lineptr == '\n')
        {
          chars_printed = 0;
-         wrap_here ((char *) 0);       /* Spit out chars, cancel further wraps */
+         wrap_here ((char *) 0);       /* Spit out chars, cancel
+                                          further wraps.  */
          lines_printed++;
          fputc_unfiltered ('\n', stream);
          lineptr++;
@@ -2016,6 +2600,7 @@ int
 putchar_unfiltered (int c)
 {
   char buf = c;
+
   ui_file_write (gdb_stdout, &buf, 1);
   return c;
 }
@@ -2033,6 +2618,7 @@ int
 fputc_unfiltered (int c, struct ui_file *stream)
 {
   char buf = c;
+
   ui_file_write (stream, &buf, 1);
   return c;
 }
@@ -2175,7 +2761,26 @@ vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args)
 
   linebuffer = xstrvprintf (format, args);
   old_cleanups = make_cleanup (xfree, linebuffer);
-  fputs_unfiltered (linebuffer, stream);
+  if (debug_timestamp && stream == gdb_stdlog)
+    {
+      struct timeval tm;
+      char *timestamp;
+      int len, need_nl;
+
+      gettimeofday (&tm, NULL);
+
+      len = strlen (linebuffer);
+      need_nl = (len > 0 && linebuffer[len - 1] != '\n');
+
+      timestamp = xstrprintf ("%ld:%ld %s%s",
+                             (long) tm.tv_sec, (long) tm.tv_usec,
+                             linebuffer,
+                             need_nl ? "\n": "");
+      make_cleanup (xfree, timestamp);
+      fputs_unfiltered (timestamp, stream);
+    }
+  else
+    fputs_unfiltered (linebuffer, stream);
   do_cleanups (old_cleanups);
 }
 
@@ -2195,6 +2800,7 @@ void
 fprintf_filtered (struct ui_file *stream, const char *format, ...)
 {
   va_list args;
+
   va_start (args, format);
   vfprintf_filtered (stream, format, args);
   va_end (args);
@@ -2204,6 +2810,7 @@ void
 fprintf_unfiltered (struct ui_file *stream, const char *format, ...)
 {
   va_list args;
+
   va_start (args, format);
   vfprintf_unfiltered (stream, format, args);
   va_end (args);
@@ -2217,6 +2824,7 @@ fprintfi_filtered (int spaces, struct ui_file *stream, const char *format,
                   ...)
 {
   va_list args;
+
   va_start (args, format);
   print_spaces_filtered (spaces, stream);
 
@@ -2229,6 +2837,7 @@ void
 printf_filtered (const char *format, ...)
 {
   va_list args;
+
   va_start (args, format);
   vfprintf_filtered (gdb_stdout, format, args);
   va_end (args);
@@ -2239,6 +2848,7 @@ void
 printf_unfiltered (const char *format, ...)
 {
   va_list args;
+
   va_start (args, format);
   vfprintf_unfiltered (gdb_stdout, format, args);
   va_end (args);
@@ -2251,6 +2861,7 @@ void
 printfi_filtered (int spaces, const char *format, ...)
 {
   va_list args;
+
   va_start (args, format);
   print_spaces_filtered (spaces, gdb_stdout);
   vfprintf_filtered (gdb_stdout, format, args);
@@ -2309,7 +2920,7 @@ print_spaces_filtered (int n, struct ui_file *stream)
 /* fprintf_symbol_filtered attempts to demangle NAME, a symbol in language
    LANG, using demangling args ARG_MODE, and print it filtered to STREAM.
    If the name is not mangled, or the language for the name is unknown, or
-   demangling is off, the name is printed in its "raw" form. */
+   demangling is off, the name is printed in its "raw" form.  */
 
 void
 fprintf_symbol_filtered (struct ui_file *stream, char *name,
@@ -2343,7 +2954,7 @@ fprintf_symbol_filtered (struct ui_file *stream, char *name,
    As an extra hack, string1=="FOO(ARGS)" matches string2=="FOO".
    This "feature" is useful when searching for matching C++ function names
    (such as if the user types 'break FOO', where FOO is a mangled C++
-   function). */
+   function).  */
 
 int
 strcmp_iw (const char *string1, const char *string2)
@@ -2470,6 +3081,7 @@ int
 subset_compare (char *string_to_compare, char *template_string)
 {
   int match;
+
   if (template_string != (char *) NULL && string_to_compare != (char *) NULL
       && strlen (string_to_compare) <= strlen (template_string))
     match =
@@ -2480,27 +3092,30 @@ subset_compare (char *string_to_compare, char *template_string)
   return match;
 }
 
-
-static void pagination_on_command (char *arg, int from_tty);
 static void
 pagination_on_command (char *arg, int from_tty)
 {
   pagination_enabled = 1;
 }
 
-static void pagination_on_command (char *arg, int from_tty);
 static void
 pagination_off_command (char *arg, int from_tty)
 {
   pagination_enabled = 0;
 }
+
+static void
+show_debug_timestamp (struct ui_file *file, int from_tty,
+                     struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Timestamping debugging messages is %s.\n"),
+                   value);
+}
 \f
 
 void
 initialize_utils (void)
 {
-  struct cmd_list_element *c;
-
   add_setshow_uinteger_cmd ("width", class_support, &chars_per_line, _("\
 Set number of characters gdb thinks are in a line."), _("\
 Show number of characters gdb thinks are in a line."), NULL,
@@ -2554,15 +3169,24 @@ Show demangling of C++/ObjC names in disassembly listings."), NULL,
                           NULL,
                           show_asm_demangle,
                           &setprintlist, &showprintlist);
+
+  add_setshow_boolean_cmd ("timestamp", class_maintenance,
+                           &debug_timestamp, _("\
+Set timestamping of debugging messages."), _("\
+Show timestamping of debugging messages."), _("\
+When set, debugging messages will be marked with seconds and microseconds."),
+                          NULL,
+                          show_debug_timestamp,
+                          &setdebuglist, &showdebuglist);
 }
 
-/* Machine specific function to handle SIGWINCH signal. */
+/* Machine specific function to handle SIGWINCH signal.  */
 
 #ifdef  SIGWINCH_HANDLER_BODY
 SIGWINCH_HANDLER_BODY
 #endif
-/* print routines to handle variable size regs, etc. */
-/* temporary storage using circular buffer */
+/* Print routines to handle variable size regs, etc.  */
+/* Temporary storage using circular buffer.  */
 #define NUMCELLS 16
 #define CELLSIZE 50
 static char *
@@ -2570,42 +3194,25 @@ get_cell (void)
 {
   static char buf[NUMCELLS][CELLSIZE];
   static int cell = 0;
+
   if (++cell >= NUMCELLS)
     cell = 0;
   return buf[cell];
 }
 
-int
-strlen_paddr (void)
-{
-  return (TARGET_ADDR_BIT / 8 * 2);
-}
-
-char *
-paddr (CORE_ADDR addr)
-{
-  return phex (addr, TARGET_ADDR_BIT / 8);
-}
-
-char *
-paddr_nz (CORE_ADDR addr)
-{
-  return phex_nz (addr, TARGET_ADDR_BIT / 8);
-}
-
 const char *
-paddress (CORE_ADDR addr)
+paddress (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
   /* Truncate address to the size of a target address, avoiding shifts
      larger or equal than the width of a CORE_ADDR.  The local
      variable ADDR_BIT stops the compiler reporting a shift overflow
-     when it won't occur. */
+     when it won't occur.  */
   /* NOTE: This assumes that the significant address information is
      kept in the least significant bits of ADDR - the upper bits were
-     either zero or sign extended.  Should ADDRESS_TO_POINTER() or
+     either zero or sign extended.  Should gdbarch_address_to_pointer or
      some ADDRESS_TO_PRINTABLE() be used to do the conversion?  */
 
-  int addr_bit = TARGET_ADDR_BIT;
+  int addr_bit = gdbarch_addr_bit (gdbarch);
 
   if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
     addr &= ((CORE_ADDR) 1 << addr_bit) - 1;
@@ -2616,11 +3223,11 @@ static char *
 decimal2str (char *sign, ULONGEST addr, int width)
 {
   /* Steal code from valprint.c:print_decimal().  Should this worry
-     about the real size of addr as the above does? */
+     about the real size of addr as the above does?  */
   unsigned long temp[3];
   char *str = get_cell ();
-
   int i = 0;
+
   do
     {
       temp[i] = addr % (1000 * 1000 * 1000);
@@ -2660,8 +3267,8 @@ octal2str (ULONGEST addr, int width)
 {
   unsigned long temp[3];
   char *str = get_cell ();
-
   int i = 0;
+
   do
     {
       temp[i] = addr % (0100000 * 0100000);
@@ -2699,18 +3306,18 @@ octal2str (ULONGEST addr, int width)
 }
 
 char *
-paddr_u (CORE_ADDR addr)
+pulongest (ULONGEST u)
 {
-  return decimal2str ("", addr, 0);
+  return decimal2str ("", u, 0);
 }
 
 char *
-paddr_d (LONGEST addr)
+plongest (LONGEST l)
 {
-  if (addr < 0)
-    return decimal2str ("-", -addr, 0);
+  if (l < 0)
+    return decimal2str ("-", -l, 0);
   else
-    return decimal2str ("", addr, 0);
+    return decimal2str ("", l, 0);
 }
 
 /* Eliminate warning from compiler on 32-bit systems.  */
@@ -2755,6 +3362,7 @@ phex_nz (ULONGEST l, int sizeof_l)
     case 8:
       {
        unsigned long high = (unsigned long) (l >> thirty_two);
+
        str = get_cell ();
        if (high == 0)
          xsnprintf (str, CELLSIZE, "%lx",
@@ -2786,6 +3394,7 @@ char *
 hex_string (LONGEST num)
 {
   char *result = get_cell ();
+
   xsnprintf (result, CELLSIZE, "0x%s", phex_nz (num, sizeof (num)));
   return result;
 }
@@ -2805,8 +3414,8 @@ hex_string_custom (LONGEST num, int width)
   if (hex_len > width)
     width = hex_len;
   if (width + 2 >= CELLSIZE)
-    internal_error (__FILE__, __LINE__,
-                   _("hex_string_custom: insufficient space to store result"));
+    internal_error (__FILE__, __LINE__, _("\
+hex_string_custom: insufficient space to store result"));
 
   strcpy (result_end - width - 2, "0x");
   memset (result_end - width, '0', width);
@@ -2819,7 +3428,7 @@ hex_string_custom (LONGEST num, int width)
  * otherwise VAL is interpreted as unsigned.  If WIDTH is supplied, 
  * it is the minimum width (0-padded if needed).  USE_C_FORMAT means
  * to use C format in all cases.  If it is false, then 'x' 
- * and 'o' formats do not include a prefix (0x or leading 0). */
+ * and 'o' formats do not include a prefix (0x or leading 0).  */
 
 char *
 int_string (LONGEST val, int radix, int is_signed, int width, 
@@ -2830,6 +3439,7 @@ int_string (LONGEST val, int radix, int is_signed, int width,
     case 16:
       {
        char *result;
+
        if (width == 0)
          result = hex_string (val);
        else
@@ -2848,6 +3458,7 @@ int_string (LONGEST val, int radix, int is_signed, int width,
     case 8:
       {
        char *result = octal2str (val, width);
+
        if (use_c_format || val == 0)
          return result;
        else
@@ -2864,6 +3475,7 @@ const char *
 core_addr_to_string (const CORE_ADDR addr)
 {
   char *str = get_cell ();
+
   strcpy (str, "0x");
   strcat (str, phex (addr, sizeof (addr)));
   return str;
@@ -2873,6 +3485,7 @@ const char *
 core_addr_to_string_nz (const CORE_ADDR addr)
 {
   char *str = get_cell ();
+
   strcpy (str, "0x");
   strcat (str, phex_nz (addr, sizeof (addr)));
   return str;
@@ -2883,10 +3496,12 @@ CORE_ADDR
 string_to_core_addr (const char *my_string)
 {
   CORE_ADDR addr = 0;
+
   if (my_string[0] == '0' && tolower (my_string[1]) == 'x')
     {
-      /* Assume that it is in decimal.  */
+      /* Assume that it is in hex.  */
       int i;
+
       for (i = 2; my_string[i] != '\0'; i++)
        {
          if (isdigit (my_string[i]))
@@ -2894,24 +3509,35 @@ string_to_core_addr (const char *my_string)
          else if (isxdigit (my_string[i]))
            addr = (tolower (my_string[i]) - 'a' + 0xa) + (addr * 16);
          else
-           internal_error (__FILE__, __LINE__, _("invalid hex"));
+           error (_("invalid hex \"%s\""), my_string);
        }
     }
   else
     {
       /* Assume that it is in decimal.  */
       int i;
+
       for (i = 0; my_string[i] != '\0'; i++)
        {
          if (isdigit (my_string[i]))
            addr = (my_string[i] - '0') + (addr * 10);
          else
-           internal_error (__FILE__, __LINE__, _("invalid decimal"));
+           error (_("invalid decimal \"%s\""), my_string);
        }
     }
+
   return addr;
 }
 
+const char *
+host_address_to_string (const void *addr)
+{
+  char *str = get_cell ();
+
+  xsnprintf (str, CELLSIZE, "0x%s", phex_nz ((uintptr_t) addr, sizeof (addr)));
+  return str;
+}
+
 char *
 gdb_realpath (const char *filename)
 {
@@ -2930,6 +3556,7 @@ gdb_realpath (const char *filename)
 # endif
 # if defined (USE_REALPATH)
     const char *rp = realpath (filename, buf);
+
     if (rp == NULL)
       rp = filename;
     return xstrdup (rp);
@@ -2943,6 +3570,7 @@ gdb_realpath (const char *filename)
 #if defined(HAVE_CANONICALIZE_FILE_NAME)
   {
     char *rp = canonicalize_file_name (filename);
+
     if (rp == NULL)
       return xstrdup (filename);
     else
@@ -2970,11 +3598,13 @@ gdb_realpath (const char *filename)
   {
     /* Find out the max path size.  */
     long path_max = pathconf ("/", _PC_PATH_MAX);
+
     if (path_max > 0)
       {
        /* PATH_MAX is bounded.  */
        char *buf = alloca (path_max);
        char *rp = realpath (filename, buf);
+
        return xstrdup (rp ? rp : filename);
       }
   }
@@ -2996,14 +3626,14 @@ xfullpath (const char *filename)
   char *result;
 
   /* Extract the basename of filename, and return immediately 
-     a copy of filename if it does not contain any directory prefix. */
+     a copy of filename if it does not contain any directory prefix.  */
   if (base_name == filename)
     return xstrdup (filename);
 
   dir_name = alloca ((size_t) (base_name - filename + 2));
   /* Allocate enough space to store the dir_name + plus one extra
      character sometimes needed under Windows (see below), and
-     then the closing \000 character */
+     then the closing \000 character */
   strncpy (dir_name, filename, base_name - filename);
   dir_name[base_name - filename] = '\000';
 
@@ -3018,13 +3648,13 @@ xfullpath (const char *filename)
 #endif
 
   /* Canonicalize the directory prefix, and build the resulting
-     filename. If the dirname realpath already contains an ending
+     filename.  If the dirname realpath already contains an ending
      directory separator, avoid doubling it.  */
   real_path = gdb_realpath (dir_name);
   if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
-    result = concat (real_path, base_name, (char *)NULL);
+    result = concat (real_path, base_name, (char *) NULL);
   else
-    result = concat (real_path, SLASH_STRING, base_name, (char *)NULL);
+    result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
 
   xfree (real_path);
   return result;
@@ -3039,7 +3669,7 @@ xfullpath (const char *filename)
 unsigned long
 gnu_debuglink_crc32 (unsigned long crc, unsigned char *buf, size_t len)
 {
-  static const unsigned long crc32_table[256] = {
+  static const unsigned int crc32_table[256] = {
     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
     0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
     0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
@@ -3125,6 +3755,7 @@ hashtab_obstack_allocate (void *data, size_t size, size_t count)
 {
   unsigned int total = size * count;
   void *ptr = obstack_alloc ((struct obstack *) data, total);
+
   memset (ptr, 0, total);
   return ptr;
 }
@@ -3238,3 +3869,125 @@ strtoulst (const char *num, const char **trailer, int base)
   else
     return result;
 }
+
+/* Simple, portable version of dirname that does not modify its
+   argument.  */
+
+char *
+ldirname (const char *filename)
+{
+  const char *base = lbasename (filename);
+  char *dirname;
+
+  while (base > filename && IS_DIR_SEPARATOR (base[-1]))
+    --base;
+
+  if (base == filename)
+    return NULL;
+
+  dirname = xmalloc (base - filename + 2);
+  memcpy (dirname, filename, base - filename);
+
+  /* On DOS based file systems, convert "d:foo" to "d:.", so that we
+     create "d:./bar" later instead of the (different) "d:/bar".  */
+  if (base - filename == 2 && IS_ABSOLUTE_PATH (base)
+      && !IS_DIR_SEPARATOR (filename[0]))
+    dirname[base++ - filename] = '.';
+
+  dirname[base - filename] = '\0';
+  return dirname;
+}
+
+/* Call libiberty's buildargv, and return the result.
+   If buildargv fails due to out-of-memory, call nomem.
+   Therefore, the returned value is guaranteed to be non-NULL,
+   unless the parameter itself is NULL.  */
+
+char **
+gdb_buildargv (const char *s)
+{
+  char **argv = buildargv (s);
+
+  if (s != NULL && argv == NULL)
+    nomem (0);
+  return argv;
+}
+
+int
+compare_positive_ints (const void *ap, const void *bp)
+{
+  /* Because we know we're comparing two ints which are positive,
+     there's no danger of overflow here.  */
+  return * (int *) ap - * (int *) bp;
+}
+
+#define AMBIGUOUS_MESS1        ".\nMatching formats:"
+#define AMBIGUOUS_MESS2        \
+  ".\nUse \"set gnutarget format-name\" to specify the format."
+
+const char *
+gdb_bfd_errmsg (bfd_error_type error_tag, char **matching)
+{
+  char *ret, *retp;
+  int ret_len;
+  char **p;
+
+  /* Check if errmsg just need simple return.  */
+  if (error_tag != bfd_error_file_ambiguously_recognized || matching == NULL)
+    return bfd_errmsg (error_tag);
+
+  ret_len = strlen (bfd_errmsg (error_tag)) + strlen (AMBIGUOUS_MESS1)
+            + strlen (AMBIGUOUS_MESS2);
+  for (p = matching; *p; p++)
+    ret_len += strlen (*p) + 1;
+  ret = xmalloc (ret_len + 1);
+  retp = ret;
+  make_cleanup (xfree, ret);
+
+  strcpy (retp, bfd_errmsg (error_tag));
+  retp += strlen (retp);
+
+  strcpy (retp, AMBIGUOUS_MESS1);
+  retp += strlen (retp);
+
+  for (p = matching; *p; p++)
+    {
+      sprintf (retp, " %s", *p);
+      retp += strlen (retp);
+    }
+  xfree (matching);
+
+  strcpy (retp, AMBIGUOUS_MESS2);
+
+  return ret;
+}
+
+/* Return ARGS parsed as a valid pid, or throw an error.  */
+
+int
+parse_pid_to_attach (char *args)
+{
+  unsigned long pid;
+  char *dummy;
+
+  if (!args)
+    error_no_arg (_("process-id to attach"));
+
+  dummy = args;
+  pid = strtoul (args, &dummy, 0);
+  /* Some targets don't set errno on errors, grrr!  */
+  if ((pid == 0 && dummy == args) || dummy != &args[strlen (args)])
+    error (_("Illegal process-id: %s."), args);
+
+  return pid;
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_utils;
+
+void
+_initialize_utils (void)
+{
+  add_internal_problem_command (&internal_error_problem);
+  add_internal_problem_command (&internal_warning_problem);
+}
This page took 0.062028 seconds and 4 git commands to generate.