Change boolean options to bool instead of int
[deliverable/binutils-gdb.git] / gdb / utils.c
index b4332f83b72758e906b5dee03b6ff76a727d6694..b2535ebefd3805c27ebcc41b94d2a0cdc0eaeab1 100644 (file)
@@ -1,6 +1,6 @@
 /* General utility routines for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2017 Free Software Foundation, Inc.
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -19,7 +19,7 @@
 
 #include "defs.h"
 #include <ctype.h>
-#include "gdb_wait.h"
+#include "gdbsupport/gdb_wait.h"
 #include "event-top.h"
 #include "gdbthread.h"
 #include "fnmatch.h"
 #include "gdb_usleep.h"
 #include "interps.h"
 #include "gdb_regex.h"
-
-#if !HAVE_DECL_MALLOC
-extern PTR malloc ();          /* ARI: PTR */
-#endif
-#if !HAVE_DECL_REALLOC
-extern PTR realloc ();         /* ARI: PTR */
-#endif
-#if !HAVE_DECL_FREE
-extern void free ();
-#endif
+#include "gdbsupport/job-control.h"
+#include "gdbsupport/selftest.h"
+#include "gdbsupport/gdb_optional.h"
+#include "cp-support.h"
+#include <algorithm>
+#include "gdbsupport/pathstuff.h"
+#include "cli/cli-style.h"
+#include "gdbsupport/scope-exit.h"
+#include "gdbarch.h"
 
 void (*deprecated_error_begin_hook) (void);
 
@@ -100,17 +99,13 @@ static std::chrono::steady_clock::duration prompt_for_continue_wait_time;
 
 /* A flag indicating whether to timestamp debugging messages.  */
 
-static int debug_timestamp = 0;
+static bool debug_timestamp = false;
 
-/* Nonzero if we have job control.  */
-
-int job_control;
-
-/* Nonzero means that strings with character values >0x7F should be printed
-   as octal escapes.  Zero means just print the value (e.g. it's an
+/* True means that strings with character values >0x7F should be printed
+   as octal escapes.  False means just print the value (e.g. it's an
    international character, and the terminal or window can cope.)  */
 
-int sevenbit_strings = 0;
+bool sevenbit_strings = false;
 static void
 show_sevenbit_strings (struct ui_file *file, int from_tty,
                       struct cmd_list_element *c, const char *value)
@@ -124,7 +119,7 @@ show_sevenbit_strings (struct ui_file *file, int from_tty,
 
 const char *warning_pre_print = "\nwarning: ";
 
-int pagination_enabled = 1;
+bool pagination_enabled = true;
 static void
 show_pagination_enabled (struct ui_file *file, int from_tty,
                         struct cmd_list_element *c, const char *value)
@@ -133,261 +128,6 @@ show_pagination_enabled (struct ui_file *file, int from_tty,
 }
 
 \f
-/* Cleanup utilities.
-
-   These are not defined in cleanups.c (nor declared in cleanups.h)
-   because while they use the "cleanup API" they are not part of the
-   "cleanup API".  */
-
-static void
-do_freeargv (void *arg)
-{
-  freeargv ((char **) arg);
-}
-
-struct cleanup *
-make_cleanup_freeargv (char **arg)
-{
-  return make_cleanup (do_freeargv, arg);
-}
-
-/* Helper function which does the work for make_cleanup_fclose.  */
-
-static void
-do_fclose_cleanup (void *arg)
-{
-  FILE *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 = (struct obstack *) 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);
-}
-
-/* Helper function for make_cleanup_ui_out_redirect_pop.  */
-
-static void
-do_ui_out_redirect_pop (void *arg)
-{
-  struct ui_out *uiout = (struct ui_out *) arg;
-
-  uiout->redirect (NULL);
-}
-
-/* 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_cleanup (do_ui_out_redirect_pop, uiout);
-}
-
-static void
-do_free_section_addr_info (void *arg)
-{
-  free_section_addr_info ((struct section_addr_info *) arg);
-}
-
-struct cleanup *
-make_cleanup_free_section_addr_info (struct section_addr_info *addrs)
-{
-  return make_cleanup (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
-    = (struct restore_integer_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_integer (int *variable)
-{
-  struct restore_integer_closure *c = XNEW (struct restore_integer_closure);
-
-  c->variable = variable;
-  c->value = *variable;
-
-  return make_cleanup_dtor (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 = (struct target_ops *) arg;
-
-  unpush_target (ops);
-}
-
-/* Return a new cleanup that unpushes OPS.  */
-
-struct cleanup *
-make_cleanup_unpush_target (struct target_ops *ops)
-{
-  return make_cleanup (do_unpush_target, ops);
-}
-
-/* Helper for make_cleanup_value_free_to_mark.  */
-
-static void
-do_value_free_to_mark (void *value)
-{
-  value_free_to_mark ((struct value *) value);
-}
-
-/* Free all values allocated since MARK was obtained by value_mark
-   (except for those released) when the cleanup is run.  */
-
-struct cleanup *
-make_cleanup_value_free_to_mark (struct value *mark)
-{
-  return make_cleanup (do_value_free_to_mark, mark);
-}
-
-/* Helper for make_cleanup_value_free.  */
-
-static void
-do_value_free (void *value)
-{
-  value_free ((struct value *) value);
-}
-
-/* Free VALUE.  */
-
-struct cleanup *
-make_cleanup_value_free (struct value *value)
-{
-  return make_cleanup (do_value_free, value);
-}
-
-/* Helper for make_cleanup_free_so.  */
-
-static void
-do_free_so (void *arg)
-{
-  struct so_list *so = (struct so_list *) arg;
-
-  free_so (so);
-}
-
-/* Make cleanup handler calling free_so for SO.  */
-
-struct cleanup *
-make_cleanup_free_so (struct so_list *so)
-{
-  return make_cleanup (do_free_so, so);
-}
-
-/* Helper for make_cleanup_restore_current_language.  */
-
-static void
-do_restore_current_language (void *p)
-{
-  enum language saved_lang = (enum language) (uintptr_t) p;
-
-  set_language (saved_lang);
-}
-
-/* Remember the current value of CURRENT_LANGUAGE and make it restored when
-   the cleanup is run.  */
-
-struct cleanup *
-make_cleanup_restore_current_language (void)
-{
-  enum language saved_lang = current_language->la_language;
-
-  return make_cleanup (do_restore_current_language,
-                      (void *) (uintptr_t) saved_lang);
-}
-
-/* Helper function for make_cleanup_clear_parser_state.  */
-
-static void
-do_clear_parser_state (void *ptr)
-{
-  struct parser_state **p = (struct parser_state **) ptr;
-
-  *p = NULL;
-}
-
-/* Clean (i.e., set to NULL) the parser state variable P.  */
-
-struct cleanup *
-make_cleanup_clear_parser_state (struct parser_state **p)
-{
-  return make_cleanup (do_clear_parser_state, (void *) p);
-}
-
-/* This function is useful for cleanups.
-   Do
-
-   foo = xmalloc (...);
-   old_chain = make_cleanup (free_current_contents, &foo);
-
-   to arrange to free the object thus allocated.  */
-
-void
-free_current_contents (void *ptr)
-{
-  void **location = (void **) ptr;
-
-  if (location == NULL)
-    internal_error (__FILE__, __LINE__,
-                   _("free_current_contents: NULL pointer"));
-  if (*location != NULL)
-    {
-      xfree (*location);
-      *location = NULL;
-    }
-}
-\f
 
 
 /* Print a warning message.  The first argument STRING is the warning
@@ -403,12 +143,11 @@ vwarning (const char *string, va_list args)
     (*deprecated_warning_hook) (string, args);
   else
     {
-      struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-
+      gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
       if (target_supports_terminal_ours ())
        {
-         make_cleanup_restore_target_terminal ();
-         target_terminal_ours_for_output ();
+         term_state.emplace ();
+         target_terminal::ours_for_output ();
        }
       if (filtered_printing_initialized ())
        wrap_here ("");         /* Force out any buffered output.  */
@@ -417,8 +156,6 @@ vwarning (const char *string, va_list args)
        fputs_unfiltered (warning_pre_print, gdb_stderr);
       vfprintf_unfiltered (gdb_stderr, string, args);
       fprintf_unfiltered (gdb_stderr, "\n");
-
-      do_cleanups (old_chain);
     }
 }
 
@@ -443,7 +180,7 @@ error_stream (const string_file &stream)
 static void ATTRIBUTE_NORETURN
 abort_with_message (const char *msg)
 {
-  if (gdb_stderr == NULL)
+  if (current_ui == NULL)
     fputs (msg, stderr);
   else
     fputs_unfiltered (msg, gdb_stderr);
@@ -457,7 +194,7 @@ void
 dump_core (void)
 {
 #ifdef HAVE_SETRLIMIT
-  struct rlimit rlim = { RLIM_INFINITY, RLIM_INFINITY };
+  struct rlimit rlim = { (rlim_t) RLIM_INFINITY, (rlim_t) RLIM_INFINITY };
 
   setrlimit (RLIMIT_CORE, &rlim);
 #endif /* HAVE_SETRLIMIT */
@@ -485,6 +222,7 @@ can_dump_core (enum resource_limit_kind limit_kind)
     case LIMIT_CUR:
       if (rlim.rlim_cur == 0)
        return 0;
+      /* Fall through.  */
 
     case LIMIT_MAX:
       if (rlim.rlim_max == 0)
@@ -559,12 +297,11 @@ internal_vproblem (struct internal_problem *problem,
   static int dejavu;
   int quit_p;
   int dump_core_p;
-  char *reason;
-  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+  std::string reason;
 
   /* Don't allow infinite error/warning recursion.  */
   {
-    static char msg[] = "Recursive internal problem.\n";
+    static const char msg[] = "Recursive internal problem.\n";
 
     switch (dejavu)
       {
@@ -593,29 +330,26 @@ internal_vproblem (struct internal_problem *problem,
      style similar to a compiler error message.  Include extra detail
      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);
-    xfree (msg);
-    make_cleanup (xfree, reason);
+    std::string msg = string_vprintf (fmt, ap);
+    reason = string_printf ("%s:%d: %s: %s\n"
+                           "A problem internal to GDB has been detected,\n"
+                           "further debugging may prove unreliable.",
+                           file, line, problem->name, msg.c_str ());
   }
 
   /* Fall back to abort_with_message if gdb_stderr is not set up.  */
-  if (gdb_stderr == NULL)
+  if (current_ui == NULL)
     {
-      fputs (reason, stderr);
+      fputs (reason.c_str (), stderr);
       abort_with_message ("\n");
     }
 
   /* Try to get the message out and at the start of a new line.  */
+  gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
   if (target_supports_terminal_ours ())
     {
-      make_cleanup_restore_target_terminal ();
-      target_terminal_ours_for_output ();
+      term_state.emplace ();
+      target_terminal::ours_for_output ();
     }
   if (filtered_printing_initialized ())
     begin_line ();
@@ -624,7 +358,7 @@ internal_vproblem (struct internal_problem *problem,
   if (problem->should_quit != internal_problem_ask
       || !confirm
       || !filtered_printing_initialized ())
-    fprintf_unfiltered (gdb_stderr, "%s\n", reason);
+    fprintf_unfiltered (gdb_stderr, "%s\n", reason.c_str ());
 
   if (problem->should_quit == internal_problem_ask)
     {
@@ -634,7 +368,8 @@ internal_vproblem (struct internal_problem *problem,
       if (!confirm || !filtered_printing_initialized ())
        quit_p = 1;
       else
-        quit_p = query (_("%s\nQuit this debugging session? "), reason);
+        quit_p = query (_("%s\nQuit this debugging session? "),
+                       reason.c_str ());
     }
   else if (problem->should_quit == internal_problem_yes)
     quit_p = 1;
@@ -651,7 +386,7 @@ internal_vproblem (struct internal_problem *problem,
 
   if (problem->should_dump_core == internal_problem_ask)
     {
-      if (!can_dump_core_warn (LIMIT_MAX, reason))
+      if (!can_dump_core_warn (LIMIT_MAX, reason.c_str ()))
        dump_core_p = 0;
       else if (!filtered_printing_initialized ())
        dump_core_p = 1;
@@ -660,11 +395,12 @@ internal_vproblem (struct internal_problem *problem,
          /* 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);
+         dump_core_p = query (_("%s\nCreate a core file of GDB? "),
+                              reason.c_str ());
        }
     }
   else if (problem->should_dump_core == internal_problem_yes)
-    dump_core_p = can_dump_core_warn (LIMIT_MAX, reason);
+    dump_core_p = can_dump_core_warn (LIMIT_MAX, reason.c_str ());
   else if (problem->should_dump_core == internal_problem_no)
     dump_core_p = 0;
   else
@@ -689,7 +425,6 @@ internal_vproblem (struct internal_problem *problem,
     }
 
   dejavu = 0;
-  do_cleanups (cleanup);
 }
 
 static struct internal_problem internal_error_problem = {
@@ -736,12 +471,12 @@ demangler_warning (const char *file, int line, const char *string, ...)
 /* Dummy functions to keep add_prefix_cmd happy.  */
 
 static void
-set_internal_problem_cmd (char *args, int from_tty)
+set_internal_problem_cmd (const char *args, int from_tty)
 {
 }
 
 static void
-show_internal_problem_cmd (char *args, int from_tty)
+show_internal_problem_cmd (const char *args, int from_tty)
 {
 }
 
@@ -779,14 +514,14 @@ add_internal_problem_command (struct internal_problem *problem)
   show_doc = xstrprintf (_("Show what GDB does when %s is detected."),
                         problem->name);
 
-  add_prefix_cmd ((char*) problem->name,
+  add_prefix_cmd (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,
+  add_prefix_cmd (problem->name,
                  class_maintenance, show_internal_problem_cmd, show_doc,
                  show_cmd_list,
                  concat ("maintenance show ", problem->name, " ",
@@ -796,10 +531,10 @@ add_internal_problem_command (struct internal_problem *problem)
   if (problem->user_settable_should_quit)
     {
       set_doc = xstrprintf (_("Set whether GDB should quit "
-                             "when an %s is detected"),
+                             "when an %s is detected."),
                            problem->name);
       show_doc = xstrprintf (_("Show whether GDB will quit "
-                              "when an %s is detected"),
+                              "when an %s is detected."),
                             problem->name);
       add_setshow_enum_cmd ("quit", class_maintenance,
                            internal_problem_modes,
@@ -819,10 +554,10 @@ add_internal_problem_command (struct internal_problem *problem)
   if (problem->user_settable_should_dump_core)
     {
       set_doc = xstrprintf (_("Set whether GDB should create a core "
-                             "file of GDB when %s is detected"),
+                             "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"),
+                              "file of GDB when %s is detected."),
                             problem->name);
       add_setshow_enum_cmd ("corefile", class_maintenance,
                            internal_problem_modes,
@@ -841,23 +576,15 @@ add_internal_problem_command (struct internal_problem *problem)
 }
 
 /* Return a newly allocated string, containing the PREFIX followed
-   by the system error message for errno (separated by a colon).
+   by the system error message for errno (separated by a colon).  */
 
-   The result must be deallocated after use.  */
-
-static char *
+static std::string
 perror_string (const char *prefix)
 {
   char *err;
-  char *combined;
 
   err = safe_strerror (errno);
-  combined = (char *) xmalloc (strlen (err) + strlen (prefix) + 3);
-  strcpy (combined, prefix);
-  strcat (combined, ": ");
-  strcat (combined, err);
-
-  return combined;
+  return std::string (prefix) + ": " + err;
 }
 
 /* Print the system error message for errno, and also mention STRING
@@ -867,10 +594,7 @@ perror_string (const char *prefix)
 void
 throw_perror_with_name (enum errors errcode, const char *string)
 {
-  char *combined;
-
-  combined = perror_string (string);
-  make_cleanup (xfree, combined);
+  std::string combined = perror_string (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
@@ -878,7 +602,7 @@ throw_perror_with_name (enum errors errcode, const char *string)
   bfd_set_error (bfd_error_no_error);
   errno = 0;
 
-  throw_error (errcode, _("%s."), combined);
+  throw_error (errcode, _("%s."), combined.c_str ());
 }
 
 /* See throw_perror_with_name, ERRCODE defaults here to GENERIC_ERROR.  */
@@ -895,11 +619,8 @@ perror_with_name (const char *string)
 void
 perror_warning_with_name (const char *string)
 {
-  char *combined;
-
-  combined = perror_string (string);
-  warning (_("%s"), combined);
-  xfree (combined);
+  std::string combined = perror_string (string);
+  warning (_("%s"), combined.c_str ());
 }
 
 /* Print the system error message for ERRCODE, and also mention STRING
@@ -928,8 +649,6 @@ print_sys_errmsg (const char *string, int errcode)
 void
 quit (void)
 {
-  struct ui *ui = current_ui;
-
   if (sync_quit_force_run)
     {
       sync_quit_force_run = 0;
@@ -960,9 +679,6 @@ maybe_quit (void)
     quit ();
 
   quit_handler ();
-
-  if (deprecated_interactive_hook)
-    deprecated_interactive_hook ();
 }
 
 \f
@@ -1038,84 +754,42 @@ make_hex_string (const gdb_byte *data, size_t length)
 
 \f
 
-/* A cleanup function that calls regfree.  */
-
-static void
-do_regfree_cleanup (void *r)
-{
-  regfree ((regex_t *) r);
-}
-
-/* Create a new cleanup that frees the compiled regular expression R.  */
-
-struct cleanup *
-make_regfree_cleanup (regex_t *r)
-{
-  return make_cleanup (do_regfree_cleanup, r);
-}
-
-/* Return an xmalloc'd error message resulting from a regular
-   expression compilation failure.  */
-
-char *
-get_regcomp_error (int code, regex_t *rx)
-{
-  size_t length = regerror (code, rx, NULL, 0);
-  char *result = (char *) xmalloc (length);
-
-  regerror (code, rx, result, length);
-  return result;
-}
-
-/* Compile a regexp and throw an exception on error.  This returns a
-   cleanup to free the resulting pattern on success.  RX must not be
-   NULL.  */
+/* An RAII class that sets up to handle input and then tears down
+   during destruction.  */
 
-struct cleanup *
-compile_rx_or_error (regex_t *pattern, const char *rx, const char *message)
+class scoped_input_handler
 {
-  int code;
-
-  gdb_assert (rx != NULL);
-
-  code = regcomp (pattern, rx, REG_NOSUB);
-  if (code != 0)
-    {
-      char *err = get_regcomp_error (code, pattern);
-
-      make_cleanup (xfree, err);
-      error (("%s: %s"), message, err);
-    }
-
-  return make_regfree_cleanup (pattern);
-}
+public:
 
-/* A cleanup that simply calls ui_unregister_input_event_handler.  */
-
-static void
-ui_unregister_input_event_handler_cleanup (void *ui)
-{
-  ui_unregister_input_event_handler ((struct ui *) ui);
-}
+  scoped_input_handler ()
+    : m_quit_handler (&quit_handler, default_quit_handler),
+      m_ui (NULL)
+  {
+    target_terminal::ours ();
+    ui_register_input_event_handler (current_ui);
+    if (current_ui->prompt_state == PROMPT_BLOCKED)
+      m_ui = current_ui;
+  }
 
-/* Set up to handle input.  */
+  ~scoped_input_handler ()
+  {
+    if (m_ui != NULL)
+      ui_unregister_input_event_handler (m_ui);
+  }
 
-static struct cleanup *
-prepare_to_handle_input (void)
-{
-  struct cleanup *old_chain;
+  DISABLE_COPY_AND_ASSIGN (scoped_input_handler);
 
-  old_chain = make_cleanup_restore_target_terminal ();
-  target_terminal_ours ();
+private:
 
-  ui_register_input_event_handler (current_ui);
-  if (current_ui->prompt_state == PROMPT_BLOCKED)
-    make_cleanup (ui_unregister_input_event_handler_cleanup, current_ui);
+  /* Save and restore the terminal state.  */
+  target_terminal::scoped_restore_terminal_state m_term_state;
 
-  make_cleanup_override_quit_handler (default_quit_handler);
+  /* Save and restore the quit handler.  */
+  scoped_restore_tmpl<quit_handler_ftype *> m_quit_handler;
 
-  return old_chain;
-}
+  /* The saved UI, if non-NULL.  */
+  struct ui *m_ui;
+};
 
 \f
 
@@ -1132,13 +806,10 @@ prepare_to_handle_input (void)
 static int ATTRIBUTE_PRINTF (1, 0)
 defaulted_query (const char *ctlstr, const char defchar, va_list args)
 {
-  int ans2;
   int retval;
   int def_value;
   char def_answer, not_def_answer;
   const char *y_string, *n_string;
-  char *question, *prompt;
-  struct cleanup *old_chain;
 
   /* Set up according to which answer is the default.  */
   if (defchar == '\0')
@@ -1180,53 +851,45 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
       /* Restrict queries to the main UI.  */
       || current_ui != main_ui)
     {
-      old_chain = make_cleanup_restore_target_terminal ();
-
-      target_terminal_ours_for_output ();
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
       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);
 
-      do_cleanups (old_chain);
       return def_value;
     }
 
   if (deprecated_query_hook)
     {
-      int res;
-
-      old_chain = make_cleanup_restore_target_terminal ();
-      res = deprecated_query_hook (ctlstr, args);
-      do_cleanups (old_chain);
-      return res;
+      target_terminal::scoped_restore_terminal_state term_state;
+      return deprecated_query_hook (ctlstr, args);
     }
 
   /* Format the question outside of the loop, to avoid reusing args.  */
-  question = xstrvprintf (ctlstr, args);
-  old_chain = make_cleanup (xfree, question);
-  prompt = xstrprintf (_("%s%s(%s or %s) %s"),
-                     annotation_level > 1 ? "\n\032\032pre-query\n" : "",
-                     question, y_string, n_string,
-                     annotation_level > 1 ? "\n\032\032query\n" : "");
-  make_cleanup (xfree, prompt);
+  std::string question = string_vprintf (ctlstr, args);
+  std::string prompt
+    = string_printf (_("%s%s(%s or %s) %s"),
+                    annotation_level > 1 ? "\n\032\032pre-query\n" : "",
+                    question.c_str (), y_string, n_string,
+                    annotation_level > 1 ? "\n\032\032query\n" : "");
 
   /* Used to add duration we waited for user to respond to
      prompt_for_continue_wait_time.  */
   using namespace std::chrono;
   steady_clock::time_point prompt_started = steady_clock::now ();
 
-  prepare_to_handle_input ();
+  scoped_input_handler prepare_input;
 
   while (1)
     {
       char *response, answer;
 
       gdb_flush (gdb_stdout);
-      response = gdb_readline_wrapper (prompt);
+      response = gdb_readline_wrapper (prompt.c_str ());
 
       if (response == NULL)    /* C-d  */
        {
@@ -1266,7 +929,6 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
 
   if (annotation_level > 1)
     printf_filtered (("\n\032\032post-query\n"));
-  do_cleanups (old_chain);
   return retval;
 }
 \f
@@ -1332,13 +994,10 @@ query (const char *ctlstr, ...)
 static int
 host_char_to_target (struct gdbarch *gdbarch, int c, int *target_c)
 {
-  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);
+  auto_obstack host_data;
 
   convert_between_encodings (target_charset (gdbarch), host_charset (),
                             (gdb_byte *) &the_char, 1, 1,
@@ -1350,7 +1009,6 @@ host_char_to_target (struct gdbarch *gdbarch, int c, int *target_c)
       *target_c = *(char *) obstack_base (&host_data);
     }
 
-  do_cleanups (cleanups);
   return result;
 }
 
@@ -1456,9 +1114,7 @@ parse_escape (struct gdbarch *gdbarch, const char **string_ptr)
    character. */
 
 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)
+printchar (int c, do_fputc_ftype do_fputc, ui_file *stream, int quoter)
 {
   c &= 0xFF;                   /* Avoid sign bit follies */
 
@@ -1466,39 +1122,45 @@ printchar (int c, void (*do_fputs) (const char *, struct ui_file *),
       (c >= 0x7F && c < 0xA0) ||       /* DEL, High controls */
       (sevenbit_strings && c >= 0x80))
     {                          /* high order bit set */
+      do_fputc ('\\', stream);
+
       switch (c)
        {
        case '\n':
-         do_fputs ("\\n", stream);
+         do_fputc ('n', stream);
          break;
        case '\b':
-         do_fputs ("\\b", stream);
+         do_fputc ('b', stream);
          break;
        case '\t':
-         do_fputs ("\\t", stream);
+         do_fputc ('t', stream);
          break;
        case '\f':
-         do_fputs ("\\f", stream);
+         do_fputc ('f', stream);
          break;
        case '\r':
-         do_fputs ("\\r", stream);
+         do_fputc ('r', stream);
          break;
        case '\033':
-         do_fputs ("\\e", stream);
+         do_fputc ('e', stream);
          break;
        case '\007':
-         do_fputs ("\\a", stream);
+         do_fputc ('a', stream);
          break;
        default:
-         do_fprintf (stream, "\\%.3o", (unsigned int) c);
-         break;
+         {
+           do_fputc ('0' + ((c >> 6) & 0x7), stream);
+           do_fputc ('0' + ((c >> 3) & 0x7), stream);
+           do_fputc ('0' + ((c >> 0) & 0x7), stream);
+           break;
+         }
        }
     }
   else
     {
       if (quoter != 0 && (c == '\\' || c == quoter))
-       do_fputs ("\\", stream);
-      do_fprintf (stream, "%c", c);
+       do_fputc ('\\', stream);
+      do_fputc (c, stream);
     }
 }
 
@@ -1511,34 +1173,30 @@ void
 fputstr_filtered (const char *str, int quoter, struct ui_file *stream)
 {
   while (*str)
-    printchar (*str++, fputs_filtered, fprintf_filtered, stream, quoter);
+    printchar (*str++, fputc_filtered, stream, quoter);
 }
 
 void
 fputstr_unfiltered (const char *str, int quoter, struct ui_file *stream)
 {
   while (*str)
-    printchar (*str++, fputs_unfiltered, fprintf_unfiltered, stream, quoter);
+    printchar (*str++, fputc_unfiltered, stream, quoter);
 }
 
 void
 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);
+  for (int i = 0; i < n; i++)
+    printchar (str[i], fputc_filtered, stream, quoter);
 }
 
 void
 fputstrn_unfiltered (const char *str, int n, int quoter,
-                    struct ui_file *stream)
+                    do_fputc_ftype do_fputc, struct ui_file *stream)
 {
-  int i;
-
-  for (i = 0; i < n; i++)
-    printchar (str[i], fputs_unfiltered, fprintf_unfiltered, stream, quoter);
+  for (int i = 0; i < n; i++)
+    printchar (str[i], do_fputc, stream, quoter);
 }
 \f
 
@@ -1568,6 +1226,10 @@ show_chars_per_line (struct ui_file *file, int from_tty,
 /* Current count of lines printed on this page, chars on this line.  */
 static unsigned int lines_printed, chars_printed;
 
+/* True if pagination is disabled for just one command.  */
+
+static bool pagination_disabled_for_command;
+
 /* Buffer and start column of buffered text, for doing smarter word-
    wrapping.  When someone calls wrap_here(), we start buffering output
    that comes through fputs_filtered().  If we see a newline, we just
@@ -1576,13 +1238,11 @@ static unsigned int lines_printed, chars_printed;
    the end of the line, we spit out a newline, the indent, and then
    the buffered output.  */
 
-/* Malloc'd buffer with chars_per_line+2 bytes.  Contains characters which
-   are waiting to be output (they have already been counted in chars_printed).
-   When wrap_buffer[0] is null, the buffer is empty.  */
-static char *wrap_buffer;
+static bool filter_initialized = false;
 
-/* Pointer in wrap_buffer to the next character to fill.  */
-static char *wrap_pointer;
+/* Contains characters which are waiting to be output (they have
+   already been counted in chars_printed).  */
+static std::string wrap_buffer;
 
 /* String to indent by if the wrap occurs.  Must not be NULL if wrap_column
    is non-zero.  */
@@ -1591,6 +1251,9 @@ static const char *wrap_indent;
 /* Column number on the screen where wrap_buffer begins, or 0 if wrapping
    is not in effect.  */
 static int wrap_column;
+
+/* The style applied at the time that wrap_here was called.  */
+static ui_file_style wrap_style;
 \f
 
 /* Initialize the number of lines per page and chars per line.  */
@@ -1655,45 +1318,26 @@ init_page_info (void)
 int
 filtered_printing_initialized (void)
 {
-  return wrap_buffer != NULL;
+  return filter_initialized;
 }
 
-/* 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)
+set_batch_flag_and_restore_page_info::set_batch_flag_and_restore_page_info ()
+  : m_save_lines_per_page (lines_per_page),
+    m_save_chars_per_line (chars_per_line),
+    m_save_batch_flag (batch_flag)
 {
-  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;
+  batch_flag = 1;
+  init_page_info ();
 }
 
-/* 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)
+set_batch_flag_and_restore_page_info::~set_batch_flag_and_restore_page_info ()
 {
-  struct cleanup *back_to = make_cleanup_restore_page_info ();
-  
-  make_cleanup_restore_integer (&batch_flag);
-  batch_flag = 1;
-  init_page_info ();
+  batch_flag = m_save_batch_flag;
+  chars_per_line = m_save_chars_per_line;
+  lines_per_page = m_save_lines_per_page;
 
-  return back_to;
+  set_screen_size ();
+  set_width ();
 }
 
 /* Set the screen size based on LINES_PER_PAGE and CHARS_PER_LINE.  */
@@ -1704,18 +1348,36 @@ set_screen_size (void)
   int rows = lines_per_page;
   int cols = chars_per_line;
 
-  if (rows <= 0)
-    rows = INT_MAX;
+  /* If we get 0 or negative ROWS or COLS, treat as "infinite" size.
+     A negative number can be seen here with the "set width/height"
+     commands and either:
+
+     - the user specified "unlimited", which maps to UINT_MAX, or
+     - the user spedified some number between INT_MAX and UINT_MAX.
+
+     Cap "infinity" to approximately sqrt(INT_MAX) so that we don't
+     overflow in rl_set_screen_size, which multiplies rows and columns
+     to compute the number of characters on the screen.  */
+
+  const int sqrt_int_max = INT_MAX >> (sizeof (int) * 8 / 2);
+
+  if (rows <= 0 || rows > sqrt_int_max)
+    {
+      rows = sqrt_int_max;
+      lines_per_page = UINT_MAX;
+    }
 
-  if (cols <= 0)
-    cols = INT_MAX;
+  if (cols <= 0 || cols > sqrt_int_max)
+    {
+      cols = sqrt_int_max;
+      chars_per_line = UINT_MAX;
+    }
 
   /* Update Readline's idea of the terminal size.  */
   rl_set_screen_size (rows, cols);
 }
 
-/* Reinitialize WRAP_BUFFER according to the current value of
-   CHARS_PER_LINE.  */
+/* Reinitialize WRAP_BUFFER.  */
 
 static void
 set_width (void)
@@ -1723,25 +1385,19 @@ set_width (void)
   if (chars_per_line == 0)
     init_page_info ();
 
-  if (!wrap_buffer)
-    {
-      wrap_buffer = (char *) xmalloc (chars_per_line + 2);
-      wrap_buffer[0] = '\0';
-    }
-  else
-    wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2);
-  wrap_pointer = wrap_buffer;  /* Start it at the beginning.  */
+  wrap_buffer.clear ();
+  filter_initialized = true;
 }
 
 static void
-set_width_command (char *args, int from_tty, struct cmd_list_element *c)
+set_width_command (const char *args, int from_tty, struct cmd_list_element *c)
 {
   set_screen_size ();
   set_width ();
 }
 
 static void
-set_height_command (char *args, int from_tty, struct cmd_list_element *c)
+set_height_command (const char *args, int from_tty, struct cmd_list_element *c)
 {
   set_screen_size ();
 }
@@ -1758,6 +1414,55 @@ set_screen_width_and_height (int width, int height)
   set_width ();
 }
 
+/* The currently applied style.  */
+
+static ui_file_style applied_style;
+
+/* Emit an ANSI style escape for STYLE.  If STREAM is nullptr, emit to
+   the wrap buffer; otherwise emit to STREAM.  */
+
+static void
+emit_style_escape (const ui_file_style &style,
+                  struct ui_file *stream = nullptr)
+{
+  applied_style = style;
+
+  if (stream == nullptr)
+    wrap_buffer.append (style.to_ansi ());
+  else
+    fputs_unfiltered (style.to_ansi ().c_str (), stream);
+}
+
+/* Set the current output style.  This will affect future uses of the
+   _filtered output functions.  */
+
+static void
+set_output_style (struct ui_file *stream, const ui_file_style &style)
+{
+  if (!stream->can_emit_style_escape ())
+    return;
+
+  /* Note that we may not pass STREAM here, when we want to emit to
+     the wrap buffer, not directly to STREAM.  */
+  if (stream == gdb_stdout)
+    stream = nullptr;
+  emit_style_escape (style, stream);
+}
+
+/* See utils.h.  */
+
+void
+reset_terminal_style (struct ui_file *stream)
+{
+  if (stream->can_emit_style_escape ())
+    {
+      /* Force the setting, regardless of what we think the setting
+        might already be.  */
+      applied_style = ui_file_style ();
+      wrap_buffer.append (applied_style.to_ansi ());
+    }
+}
+
 /* Wait, so the user can read what's on the screen.  Prompt the user
    to continue by pressing RETURN.  'q' is also provided because
    telling users what to do in the prompt is more user-friendly than
@@ -1766,19 +1471,23 @@ set_screen_width_and_height (int width, int height)
 static void
 prompt_for_continue (void)
 {
-  char *ignore;
   char cont_prompt[120];
-  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   /* Used to add duration we waited for user to respond to
      prompt_for_continue_wait_time.  */
   using namespace std::chrono;
   steady_clock::time_point prompt_started = steady_clock::now ();
+  bool disable_pagination = pagination_disabled_for_command;
+
+  /* Clear the current styling.  */
+  if (gdb_stdout->can_emit_style_escape ())
+    emit_style_escape (ui_file_style (), gdb_stdout);
 
   if (annotation_level > 1)
     printf_unfiltered (("\n\032\032pre-prompt-for-continue\n"));
 
   strcpy (cont_prompt,
-         "---Type <return> to continue, or q <return> to quit---");
+         "--Type <RET> for more, q to quit, "
+         "c to continue without paging--");
   if (annotation_level > 1)
     strcat (cont_prompt, "\n\032\032prompt-for-continue\n");
 
@@ -1787,12 +1496,11 @@ prompt_for_continue (void)
      beyond the end of the screen.  */
   reinitialize_more_filter ();
 
-  prepare_to_handle_input ();
+  scoped_input_handler prepare_input;
 
   /* Call gdb_readline_wrapper, not readline, in order to keep an
      event loop running.  */
-  ignore = gdb_readline_wrapper (cont_prompt);
-  make_cleanup (xfree, ignore);
+  gdb::unique_xmalloc_ptr<char> ignore (gdb_readline_wrapper (cont_prompt));
 
   /* Add time spend in this routine to prompt_for_continue_wait_time.  */
   prompt_for_continue_wait_time += steady_clock::now () - prompt_started;
@@ -1802,22 +1510,23 @@ prompt_for_continue (void)
 
   if (ignore != NULL)
     {
-      char *p = ignore;
+      char *p = ignore.get ();
 
       while (*p == ' ' || *p == '\t')
        ++p;
       if (p[0] == 'q')
        /* Do not call quit here; there is no possibility of SIGINT.  */
        throw_quit ("Quit");
+      if (p[0] == 'c')
+       disable_pagination = true;
     }
 
   /* Now we have to do this again, so that GDB will know that it doesn't
      need to save the ---Type <return>--- line at the top of the screen.  */
   reinitialize_more_filter ();
+  pagination_disabled_for_command = disable_pagination;
 
   dont_repeat ();              /* Forget prev cmd -- CR won't repeat it.  */
-
-  do_cleanups (old_chain);
 }
 
 /* Initialize timer to keep track of how long we waited for the user.  */
@@ -1845,6 +1554,19 @@ reinitialize_more_filter (void)
 {
   lines_printed = 0;
   chars_printed = 0;
+  pagination_disabled_for_command = false;
+}
+
+/* Flush the wrap buffer to STREAM, if necessary.  */
+
+static void
+flush_wrap_buffer (struct ui_file *stream)
+{
+  if (stream == gdb_stdout && !wrap_buffer.empty ())
+    {
+      fputs_unfiltered (wrap_buffer.c_str (), stream);
+      wrap_buffer.clear ();
+    }
 }
 
 /* Indicate that if the next sequence of characters overflows the line,
@@ -1872,17 +1594,11 @@ void
 wrap_here (const char *indent)
 {
   /* This should have been allocated, but be paranoid anyway.  */
-  if (!wrap_buffer)
+  if (!filter_initialized)
     internal_error (__FILE__, __LINE__,
                    _("failed internal consistency check"));
 
-  if (wrap_buffer[0])
-    {
-      *wrap_pointer = '\0';
-      fputs_unfiltered (wrap_buffer, gdb_stdout);
-    }
-  wrap_pointer = wrap_buffer;
-  wrap_buffer[0] = '\0';
+  flush_wrap_buffer (gdb_stdout);
   if (chars_per_line == UINT_MAX)      /* No line overflow checking.  */
     {
       wrap_column = 0;
@@ -1901,6 +1617,7 @@ wrap_here (const char *indent)
        wrap_indent = "";
       else
        wrap_indent = indent;
+      wrap_style = applied_style;
     }
 }
 
@@ -1989,15 +1706,25 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
   /* Don't do any filtering if it is disabled.  */
   if (stream != gdb_stdout
       || !pagination_enabled
+      || pagination_disabled_for_command
       || batch_flag
       || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX)
       || top_level_interpreter () == NULL
-      || interp_ui_out (top_level_interpreter ())->is_mi_like_p ())
+      || top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ())
     {
+      flush_wrap_buffer (stream);
       fputs_unfiltered (linebuffer, stream);
       return;
     }
 
+  auto buffer_clearer
+    = make_scope_exit ([&] ()
+                      {
+                        wrap_buffer.clear ();
+                        wrap_column = 0;
+                        wrap_indent = "";
+                      });
+
   /* Go through and output each character.  Show line extension
      when this is necessary; prompt user for new page when this is
      necessary.  */
@@ -2005,31 +1732,38 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
   lineptr = linebuffer;
   while (*lineptr)
     {
-      /* Possible new page.  */
-      if (filter && (lines_printed >= lines_per_page - 1))
+      /* Possible new page.  Note that PAGINATION_DISABLED_FOR_COMMAND
+        might be set during this loop, so we must continue to check
+        it here.  */
+      if (filter && (lines_printed >= lines_per_page - 1)
+         && !pagination_disabled_for_command)
        prompt_for_continue ();
 
       while (*lineptr && *lineptr != '\n')
        {
+         int skip_bytes;
+
          /* Print a single line.  */
          if (*lineptr == '\t')
            {
-             if (wrap_column)
-               *wrap_pointer++ = '\t';
-             else
-               fputc_unfiltered ('\t', stream);
+             wrap_buffer.push_back ('\t');
              /* Shifting right by 3 produces the number of tab stops
                 we have already passed, and then adding one and
                 shifting left 3 advances to the next tab stop.  */
              chars_printed = ((chars_printed >> 3) + 1) << 3;
              lineptr++;
            }
+         else if (*lineptr == '\033'
+                  && skip_ansi_escape (lineptr, &skip_bytes))
+           {
+             wrap_buffer.append (lineptr, skip_bytes);
+             /* Note that we don't consider this a character, so we
+                don't increment chars_printed here.  */
+             lineptr += skip_bytes;
+           }
          else
            {
-             if (wrap_column)
-               *wrap_pointer++ = *lineptr;
-             else
-               fputc_unfiltered (*lineptr, stream);
+             wrap_buffer.push_back (*lineptr);
              chars_printed++;
              lineptr++;
            }
@@ -2038,24 +1772,50 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
            {
              unsigned int save_chars = chars_printed;
 
+             /* If we change the style, below, we'll want to reset it
+                before continuing to print.  If there is no wrap
+                column, then we'll only reset the style if the pager
+                prompt is given; and to avoid emitting style
+                sequences in the middle of a run of text, we track
+                this as well.  */
+             ui_file_style save_style;
+             bool did_paginate = false;
+
              chars_printed = 0;
              lines_printed++;
-             /* If we aren't actually wrapping, don't output newline --
-                if chars_per_line is right, we probably just overflowed
-                anyway; if it's wrong, let us keep going.  */
              if (wrap_column)
-               fputc_unfiltered ('\n', stream);
+               {
+                 save_style = wrap_style;
+                 if (stream->can_emit_style_escape ())
+                   emit_style_escape (ui_file_style (), stream);
+                 /* If we aren't actually wrapping, don't output
+                    newline -- if chars_per_line is right, we
+                    probably just overflowed anyway; if it's wrong,
+                    let us keep going.  */
+                 fputc_unfiltered ('\n', stream);
+               }
+             else
+               {
+                 save_style = applied_style;
+                 flush_wrap_buffer (stream);
+               }
 
-             /* Possible new page.  */
-             if (lines_printed >= lines_per_page - 1)
-               prompt_for_continue ();
+             /* Possible new page.  Note that
+                PAGINATION_DISABLED_FOR_COMMAND might be set during
+                this loop, so we must continue to check it here.  */
+             if (lines_printed >= lines_per_page - 1
+                 && !pagination_disabled_for_command)
+               {
+                 prompt_for_continue ();
+                 did_paginate = true;
+               }
 
              /* 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.  */
+                 if (stream->can_emit_style_escape ())
+                   emit_style_escape (save_style, stream);
                  /* 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
@@ -2064,10 +1824,10 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
                     if we are printing a long string.  */
                  chars_printed = strlen (wrap_indent)
                    + (save_chars - wrap_column);
-                 wrap_pointer = wrap_buffer;   /* Reset buffer */
-                 wrap_buffer[0] = '\0';
                  wrap_column = 0;      /* And disable fancy wrap */
                }
+             else if (did_paginate && stream->can_emit_style_escape ())
+               emit_style_escape (save_style, stream);
            }
        }
 
@@ -2081,6 +1841,8 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
          lineptr++;
        }
     }
+
+  buffer_clearer.release ();
 }
 
 void
@@ -2089,6 +1851,60 @@ fputs_filtered (const char *linebuffer, struct ui_file *stream)
   fputs_maybe_filtered (linebuffer, stream, 1);
 }
 
+/* See utils.h.  */
+
+void
+fputs_styled (const char *linebuffer, const ui_file_style &style,
+             struct ui_file *stream)
+{
+  /* This just makes it so we emit somewhat fewer escape
+     sequences.  */
+  if (style.is_default ())
+    fputs_maybe_filtered (linebuffer, stream, 1);
+  else
+    {
+      set_output_style (stream, style);
+      fputs_maybe_filtered (linebuffer, stream, 1);
+      set_output_style (stream, ui_file_style ());
+    }
+}
+
+/* See utils.h.  */
+
+void
+fputs_highlighted (const char *str, const compiled_regex &highlight,
+                  struct ui_file *stream)
+{
+  regmatch_t pmatch;
+
+  while (*str && highlight.exec (str, 1, &pmatch, 0) == 0)
+    {
+      size_t n_highlight = pmatch.rm_eo - pmatch.rm_so;
+
+      /* Output the part before pmatch with current style.  */
+      while (pmatch.rm_so > 0)
+       {
+         fputc_filtered (*str, stream);
+         pmatch.rm_so--;
+         str++;
+       }
+
+      /* Output pmatch with the highlight style.  */
+      set_output_style (stream, highlight_style.style ());
+      while (n_highlight > 0)
+       {
+         fputc_filtered (*str, stream);
+         n_highlight--;
+         str++;
+       }
+      set_output_style (stream, ui_file_style ());
+    }
+
+  /* Output the trailing part of STR not matching HIGHLIGHT.  */
+  if (*str)
+    fputs_filtered (str, stream);
+}
+
 int
 putchar_unfiltered (int c)
 {
@@ -2230,13 +2046,8 @@ static void
 vfprintf_maybe_filtered (struct ui_file *stream, const char *format,
                         va_list args, int filter)
 {
-  char *linebuffer;
-  struct cleanup *old_cleanups;
-
-  linebuffer = xstrvprintf (format, args);
-  old_cleanups = make_cleanup (xfree, linebuffer);
-  fputs_maybe_filtered (linebuffer, stream, filter);
-  do_cleanups (old_cleanups);
+  std::string linebuffer = string_vprintf (format, args);
+  fputs_maybe_filtered (linebuffer.c_str (), stream, filter);
 }
 
 
@@ -2249,11 +2060,7 @@ vfprintf_filtered (struct ui_file *stream, const char *format, va_list args)
 void
 vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args)
 {
-  char *linebuffer;
-  struct cleanup *old_cleanups;
-
-  linebuffer = xstrvprintf (format, args);
-  old_cleanups = make_cleanup (xfree, linebuffer);
+  std::string linebuffer = string_vprintf (format, args);
   if (debug_timestamp && stream == gdb_stdlog)
     {
       using namespace std::chrono;
@@ -2263,18 +2070,18 @@ vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args)
       seconds s = duration_cast<seconds> (now.time_since_epoch ());
       microseconds us = duration_cast<microseconds> (now.time_since_epoch () - s);
 
-      len = strlen (linebuffer);
+      len = linebuffer.size ();
       need_nl = (len > 0 && linebuffer[len - 1] != '\n');
 
       std::string timestamp = string_printf ("%ld.%06ld %s%s",
                                             (long) s.count (),
                                             (long) us.count (),
-                                            linebuffer, need_nl ? "\n": "");
+                                            linebuffer.c_str (),
+                                            need_nl ? "\n": "");
       fputs_unfiltered (timestamp.c_str (), stream);
     }
   else
-    fputs_unfiltered (linebuffer, stream);
-  do_cleanups (old_cleanups);
+    fputs_unfiltered (linebuffer.c_str (), stream);
 }
 
 void
@@ -2325,6 +2132,21 @@ fprintfi_filtered (int spaces, struct ui_file *stream, const char *format,
   va_end (args);
 }
 
+/* See utils.h.  */
+
+void
+fprintf_styled (struct ui_file *stream, const ui_file_style &style,
+               const char *format, ...)
+{
+  va_list args;
+
+  set_output_style (stream, style);
+  va_start (args, format);
+  vfprintf_filtered (stream, format, args);
+  va_end (args);
+  set_output_style (stream, ui_file_style ());
+}
+
 
 void
 printf_filtered (const char *format, ...)
@@ -2440,41 +2262,369 @@ fprintf_symbol_filtered (struct ui_file *stream, const char *name,
     }
 }
 
-/* Do a strcmp() type operation on STRING1 and STRING2, ignoring any
-   differences in whitespace.  Returns 0 if they match, non-zero if they
-   don't (slightly different than strcmp()'s range of return values).
+/* True if CH is a character that can be part of a symbol name.  I.e.,
+   either a number, a letter, or a '_'.  */
 
-   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).  */
+static bool
+valid_identifier_name_char (int ch)
+{
+  return (isalnum (ch) || ch == '_');
+}
 
-int
-strcmp_iw (const char *string1, const char *string2)
+/* Skip to end of token, or to END, whatever comes first.  Input is
+   assumed to be a C++ operator name.  */
+
+static const char *
+cp_skip_operator_token (const char *token, const char *end)
 {
-  while ((*string1 != '\0') && (*string2 != '\0'))
+  const char *p = token;
+  while (p != end && !isspace (*p) && *p != '(')
     {
-      while (isspace (*string1))
+      if (valid_identifier_name_char (*p))
        {
-         string1++;
+         while (p != end && valid_identifier_name_char (*p))
+           p++;
+         return p;
        }
-      while (isspace (*string2))
+      else
        {
+         /* Note, ordered such that among ops that share a prefix,
+            longer comes first.  This is so that the loop below can
+            bail on first match.  */
+         static const char *ops[] =
+           {
+             "[",
+             "]",
+             "~",
+             ",",
+             "-=", "--", "->", "-",
+             "+=", "++", "+",
+             "*=", "*",
+             "/=", "/",
+             "%=", "%",
+             "|=", "||", "|",
+             "&=", "&&", "&",
+             "^=", "^",
+             "!=", "!",
+             "<<=", "<=", "<<", "<",
+             ">>=", ">=", ">>", ">",
+             "==", "=",
+           };
+
+         for (const char *op : ops)
+           {
+             size_t oplen = strlen (op);
+             size_t lencmp = std::min<size_t> (oplen, end - p);
+
+             if (strncmp (p, op, lencmp) == 0)
+               return p + lencmp;
+           }
+         /* Some unidentified character.  Return it.  */
+         return p + 1;
+       }
+    }
+
+  return p;
+}
+
+/* Advance STRING1/STRING2 past whitespace.  */
+
+static void
+skip_ws (const char *&string1, const char *&string2, const char *end_str2)
+{
+  while (isspace (*string1))
+    string1++;
+  while (string2 < end_str2 && isspace (*string2))
+    string2++;
+}
+
+/* True if STRING points at the start of a C++ operator name.  START
+   is the start of the string that STRING points to, hence when
+   reading backwards, we must not read any character before START.  */
+
+static bool
+cp_is_operator (const char *string, const char *start)
+{
+  return ((string == start
+          || !valid_identifier_name_char (string[-1]))
+         && strncmp (string, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
+         && !valid_identifier_name_char (string[CP_OPERATOR_LEN]));
+}
+
+/* If *NAME points at an ABI tag, skip it and return true.  Otherwise
+   leave *NAME unmodified and return false.  (see GCC's abi_tag
+   attribute), such names are demangled as e.g.,
+   "function[abi:cxx11]()".  */
+
+static bool
+skip_abi_tag (const char **name)
+{
+  const char *p = *name;
+
+  if (startswith (p, "[abi:"))
+    {
+      p += 5;
+
+      while (valid_identifier_name_char (*p))
+       p++;
+
+      if (*p == ']')
+       {
+         p++;
+         *name = p;
+         return true;
+       }
+    }
+  return false;
+}
+
+/* See utils.h.  */
+
+int
+strncmp_iw_with_mode (const char *string1, const char *string2,
+                     size_t string2_len, strncmp_iw_mode mode,
+                     enum language language,
+                     completion_match_for_lcd *match_for_lcd)
+{
+  const char *string1_start = string1;
+  const char *end_str2 = string2 + string2_len;
+  bool skip_spaces = true;
+  bool have_colon_op = (language == language_cplus
+                       || language == language_rust
+                       || language == language_fortran);
+
+  while (1)
+    {
+      if (skip_spaces
+         || ((isspace (*string1) && !valid_identifier_name_char (*string2))
+             || (isspace (*string2) && !valid_identifier_name_char (*string1))))
+       {
+         skip_ws (string1, string2, end_str2);
+         skip_spaces = false;
+       }
+
+      /* Skip [abi:cxx11] tags in the symbol name if the lookup name
+        doesn't include them.  E.g.:
+
+        string1: function[abi:cxx1](int)
+        string2: function
+
+        string1: function[abi:cxx1](int)
+        string2: function(int)
+
+        string1: Struct[abi:cxx1]::function()
+        string2: Struct::function()
+
+        string1: function(Struct[abi:cxx1], int)
+        string2: function(Struct, int)
+      */
+      if (string2 == end_str2
+         || (*string2 != '[' && !valid_identifier_name_char (*string2)))
+       {
+         const char *abi_start = string1;
+
+         /* There can be more than one tag.  */
+         while (*string1 == '[' && skip_abi_tag (&string1))
+           ;
+
+         if (match_for_lcd != NULL && abi_start != string1)
+           match_for_lcd->mark_ignored_range (abi_start, string1);
+
+         while (isspace (*string1))
+           string1++;
+       }
+
+      if (*string1 == '\0' || string2 == end_str2)
+       break;
+
+      /* Handle the :: operator.  */
+      if (have_colon_op && string1[0] == ':' && string1[1] == ':')
+       {
+         if (*string2 != ':')
+           return 1;
+
+         string1++;
          string2++;
+
+         if (string2 == end_str2)
+           break;
+
+         if (*string2 != ':')
+           return 1;
+
+         string1++;
+         string2++;
+
+         while (isspace (*string1))
+           string1++;
+         while (string2 < end_str2 && isspace (*string2))
+           string2++;
+         continue;
+       }
+
+      /* Handle C++ user-defined operators.  */
+      else if (language == language_cplus
+              && *string1 == 'o')
+       {
+         if (cp_is_operator (string1, string1_start))
+           {
+             /* An operator name in STRING1.  Check STRING2.  */
+             size_t cmplen
+               = std::min<size_t> (CP_OPERATOR_LEN, end_str2 - string2);
+             if (strncmp (string1, string2, cmplen) != 0)
+               return 1;
+
+             string1 += cmplen;
+             string2 += cmplen;
+
+             if (string2 != end_str2)
+               {
+                 /* Check for "operatorX" in STRING2.  */
+                 if (valid_identifier_name_char (*string2))
+                   return 1;
+
+                 skip_ws (string1, string2, end_str2);
+               }
+
+             /* Handle operator().  */
+             if (*string1 == '(')
+               {
+                 if (string2 == end_str2)
+                   {
+                     if (mode == strncmp_iw_mode::NORMAL)
+                       return 0;
+                     else
+                       {
+                         /* Don't break for the regular return at the
+                            bottom, because "operator" should not
+                            match "operator()", since this open
+                            parentheses is not the parameter list
+                            start.  */
+                         return *string1 != '\0';
+                       }
+                   }
+
+                 if (*string1 != *string2)
+                   return 1;
+
+                 string1++;
+                 string2++;
+               }
+
+             while (1)
+               {
+                 skip_ws (string1, string2, end_str2);
+
+                 /* Skip to end of token, or to END, whatever comes
+                    first.  */
+                 const char *end_str1 = string1 + strlen (string1);
+                 const char *p1 = cp_skip_operator_token (string1, end_str1);
+                 const char *p2 = cp_skip_operator_token (string2, end_str2);
+
+                 cmplen = std::min (p1 - string1, p2 - string2);
+                 if (p2 == end_str2)
+                   {
+                     if (strncmp (string1, string2, cmplen) != 0)
+                       return 1;
+                   }
+                 else
+                   {
+                     if (p1 - string1 != p2 - string2)
+                       return 1;
+                     if (strncmp (string1, string2, cmplen) != 0)
+                       return 1;
+                   }
+
+                 string1 += cmplen;
+                 string2 += cmplen;
+
+                 if (*string1 == '\0' || string2 == end_str2)
+                   break;
+                 if (*string1 == '(' || *string2 == '(')
+                   break;
+               }
+
+             continue;
+           }
        }
+
       if (case_sensitivity == case_sensitive_on && *string1 != *string2)
        break;
       if (case_sensitivity == case_sensitive_off
          && (tolower ((unsigned char) *string1)
              != tolower ((unsigned char) *string2)))
        break;
-      if (*string1 != '\0')
+
+      /* If we see any non-whitespace, non-identifier-name character
+        (any of "()<>*&" etc.), then skip spaces the next time
+        around.  */
+      if (!isspace (*string1) && !valid_identifier_name_char (*string1))
+       skip_spaces = true;
+
+      string1++;
+      string2++;
+    }
+
+  if (string2 == end_str2)
+    {
+      if (mode == strncmp_iw_mode::NORMAL)
        {
-         string1++;
-         string2++;
+         /* Strip abi tag markers from the matched symbol name.
+            Usually the ABI marker will be found on function name
+            (automatically added because the function returns an
+            object marked with an ABI tag).  However, it's also
+            possible to see a marker in one of the function
+            parameters, for example.
+
+            string2 (lookup name):
+              func
+            symbol name:
+              function(some_struct[abi:cxx11], int)
+
+            and for completion LCD computation we want to say that
+            the match was for:
+              function(some_struct, int)
+         */
+         if (match_for_lcd != NULL)
+           {
+             while ((string1 = strstr (string1, "[abi:")) != NULL)
+               {
+                 const char *abi_start = string1;
+
+                 /* There can be more than one tag.  */
+                 while (skip_abi_tag (&string1) && *string1 == '[')
+                   ;
+
+                 if (abi_start != string1)
+                   match_for_lcd->mark_ignored_range (abi_start, string1);
+               }
+           }
+
+         return 0;
        }
+      else
+       return (*string1 != '\0' && *string1 != '(');
     }
-  return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0');
+  else
+    return 1;
+}
+
+/* See utils.h.  */
+
+int
+strncmp_iw (const char *string1, const char *string2, size_t string2_len)
+{
+  return strncmp_iw_with_mode (string1, string2, string2_len,
+                              strncmp_iw_mode::NORMAL, language_minimal);
+}
+
+/* See utils.h.  */
+
+int
+strcmp_iw (const char *string1, const char *string2)
+{
+  return strncmp_iw_with_mode (string1, string2, strlen (string2),
+                              strncmp_iw_mode::MATCH_PARAMS, language_minimal);
 }
 
 /* This is like strcmp except that it ignores whitespace and treats
@@ -2592,13 +2742,22 @@ strcmp_iw_ordered (const char *string1, const char *string2)
     }
 }
 
-/* A simple comparison function with opposite semantics to strcmp.  */
+/* See utils.h.  */
 
-int
+bool
 streq (const char *lhs, const char *rhs)
 {
   return !strcmp (lhs, rhs);
 }
+
+/* See utils.h.  */
+
+int
+streq_hash (const void *lhs, const void *rhs)
+{
+  return streq ((const char *) lhs, (const char *) rhs);
+}
+
 \f
 
 /*
@@ -2612,7 +2771,7 @@ subset_compare (const char *string_to_compare, const char *template_string)
 {
   int match;
 
-  if (template_string != (char *) NULL && string_to_compare != (char *) NULL
+  if (template_string != NULL && string_to_compare != NULL
       && strlen (string_to_compare) <= strlen (template_string))
     match =
       (startswith (template_string, string_to_compare));
@@ -2681,6 +2840,28 @@ When set, debugging messages will be marked with seconds and microseconds."),
                           &setdebuglist, &showdebuglist);
 }
 
+/* See utils.h.  */
+
+CORE_ADDR
+address_significant (gdbarch *gdbarch, CORE_ADDR addr)
+{
+  /* Clear insignificant bits of a target address and sign extend resulting
+     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.  Skip updating of target address if current target
+     has not set gdbarch significant_addr_bit.  */
+  int addr_bit = gdbarch_significant_addr_bit (gdbarch);
+
+  if (addr_bit && (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT)))
+    {
+      CORE_ADDR sign = (CORE_ADDR) 1 << (addr_bit - 1);
+      addr &= ((CORE_ADDR) 1 << addr_bit) - 1;
+      addr = (addr ^ sign) - sign;
+    }
+
+  return addr;
+}
+
 const char *
 paddress (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
@@ -2778,144 +2959,41 @@ string_to_core_addr (const char *my_string)
   return addr;
 }
 
-char *
-gdb_realpath (const char *filename)
-{
-/* On most hosts, we rely on canonicalize_file_name to compute
-   the FILENAME's realpath.
-
-   But the situation is slightly more complex on Windows, due to some
-   versions of GCC which were reported to generate paths where
-   backlashes (the directory separator) were doubled.  For instance:
-      c:\\some\\double\\slashes\\dir
-   ... instead of ...
-      c:\some\double\slashes\dir
-   Those double-slashes were getting in the way when comparing paths,
-   for instance when trying to insert a breakpoint as follow:
-      (gdb) b c:/some/double/slashes/dir/foo.c:4
-      No source file named c:/some/double/slashes/dir/foo.c:4.
-      (gdb) b c:\some\double\slashes\dir\foo.c:4
-      No source file named c:\some\double\slashes\dir\foo.c:4.
-   To prevent this from happening, we need this function to always
-   strip those extra backslashes.  While canonicalize_file_name does
-   perform this simplification, it only works when the path is valid.
-   Since the simplification would be useful even if the path is not
-   valid (one can always set a breakpoint on a file, even if the file
-   does not exist locally), we rely instead on GetFullPathName to
-   perform the canonicalization.  */
-
-#if defined (_WIN32)
-  {
-    char buf[MAX_PATH];
-    DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL);
-
-    /* The file system is case-insensitive but case-preserving.
-       So it is important we do not lowercase the path.  Otherwise,
-       we might not be able to display the original casing in a given
-       path.  */
-    if (len > 0 && len < MAX_PATH)
-      return xstrdup (buf);
-  }
-#else
-  {
-    char *rp = canonicalize_file_name (filename);
+#if GDB_SELF_TEST
 
-    if (rp != NULL)
-      return rp;
-  }
-#endif
-
-  /* This system is a lost cause, just dup the buffer.  */
-  return xstrdup (filename);
-}
-
-/* Return a copy of FILENAME, with its directory prefix canonicalized
-   by gdb_realpath.  */
-
-char *
-gdb_realpath_keepfile (const char *filename)
-{
-  const char *base_name = lbasename (filename);
-  char *dir_name;
-  char *real_path;
-  char *result;
-
-  /* Extract the basename of filename, and return immediately 
-     a copy of filename if it does not contain any directory prefix.  */
-  if (base_name == filename)
-    return xstrdup (filename);
-
-  dir_name = (char *) 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.  */
-  strncpy (dir_name, filename, base_name - filename);
-  dir_name[base_name - filename] = '\000';
-
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-  /* We need to be careful when filename is of the form 'd:foo', which
-     is equivalent of d:./foo, which is totally different from d:/foo.  */
-  if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
-    {
-      dir_name[2] = '.';
-      dir_name[3] = '\000';
-    }
-#endif
-
-  /* Canonicalize the directory prefix, and build the resulting
-     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);
-  else
-    result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
-
-  xfree (real_path);
-  return result;
-}
-
-/* Return PATH in absolute form, performing tilde-expansion if necessary.
-   PATH cannot be NULL or the empty string.
-   This does not resolve symlinks however, use gdb_realpath for that.
-   Space for the result is allocated with malloc.
-   If the path is already absolute, it is strdup'd.
-   If there is a problem computing the absolute path, the path is returned
-   unchanged (still strdup'd).  */
-
-char *
-gdb_abspath (const char *path)
+static void
+gdb_realpath_check_trailer (const char *input, const char *trailer)
 {
-  gdb_assert (path != NULL && path[0] != '\0');
+  gdb::unique_xmalloc_ptr<char> result = gdb_realpath (input);
 
-  if (path[0] == '~')
-    return tilde_expand (path);
+  size_t len = strlen (result.get ());
+  size_t trail_len = strlen (trailer);
 
-  if (IS_ABSOLUTE_PATH (path))
-    return xstrdup (path);
-
-  /* Beware the // my son, the Emacs barfs, the botch that catch...  */
-  return concat (current_directory,
-           IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
-                ? "" : SLASH_STRING,
-                path, (char *) NULL);
+  SELF_CHECK (len >= trail_len
+             && strcmp (result.get () + len - trail_len, trailer) == 0);
 }
 
-ULONGEST
-align_up (ULONGEST v, int n)
-{
-  /* Check that N is really a power of two.  */
-  gdb_assert (n && (n & (n-1)) == 0);
-  return (v + n - 1) & -n;
-}
-
-ULONGEST
-align_down (ULONGEST v, int n)
-{
-  /* Check that N is really a power of two.  */
-  gdb_assert (n && (n & (n-1)) == 0);
-  return (v & -n);
-}
+static void
+gdb_realpath_tests ()
+{
+  /* A file which contains a directory prefix.  */
+  gdb_realpath_check_trailer ("./xfullpath.exp", "/xfullpath.exp");
+  /* A file which contains a directory prefix.  */
+  gdb_realpath_check_trailer ("../../defs.h", "/defs.h");
+  /* A one-character filename.  */
+  gdb_realpath_check_trailer ("./a", "/a");
+  /* A file in the root directory.  */
+  gdb_realpath_check_trailer ("/root_file_which_should_exist",
+                             "/root_file_which_should_exist");
+  /* A file which does not have a directory prefix.  */
+  gdb_realpath_check_trailer ("xfullpath.exp", "xfullpath.exp");
+  /* A one-char filename without any directory prefix.  */
+  gdb_realpath_check_trailer ("a", "a");
+  /* An empty filename.  */
+  gdb_realpath_check_trailer ("", "");
+}
+
+#endif /* GDB_SELF_TEST */
 
 /* Allocation function for the libiberty hash table which uses an
    obstack.  The obstack is passed as DATA.  */
@@ -2967,19 +3045,18 @@ ldirname (const char *filename)
   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.  */
+/* See utils.h.  */
 
-char **
-gdb_buildargv (const char *s)
+void
+gdb_argv::reset (const char *s)
 {
   char **argv = buildargv (s);
 
   if (s != NULL && argv == NULL)
     malloc_failure (0);
-  return argv;
+
+  freeargv (m_argv);
+  m_argv = argv;
 }
 
 int
@@ -2990,54 +3067,30 @@ compare_positive_ints (const void *ap, const void *bp)
   return * (int *) ap - * (int *) bp;
 }
 
-/* String compare function for qsort.  */
-
-int
-compare_strings (const void *arg1, const void *arg2)
-{
-  const char **s1 = (const char **) arg1;
-  const char **s2 = (const char **) arg2;
-
-  return strcmp (*s1, *s2);
-}
-
 #define AMBIGUOUS_MESS1        ".\nMatching formats:"
 #define AMBIGUOUS_MESS2        \
   ".\nUse \"set gnutarget format-name\" to specify the format."
 
-const char *
+std::string
 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 = (char *) 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);
+  std::string ret (bfd_errmsg (error_tag));
+  ret += AMBIGUOUS_MESS1;
 
   for (p = matching; *p; p++)
     {
-      sprintf (retp, " %s", *p);
-      retp += strlen (retp);
+      ret += " ";
+      ret += *p;
     }
-  xfree (matching);
+  ret += AMBIGUOUS_MESS2;
 
-  strcpy (retp, AMBIGUOUS_MESS2);
+  xfree (matching);
 
   return ret;
 }
@@ -3062,101 +3115,6 @@ parse_pid_to_attach (const char *args)
   return pid;
 }
 
-/* Helper for make_bpstat_clear_actions_cleanup.  */
-
-static void
-do_bpstat_clear_actions_cleanup (void *unused)
-{
-  bpstat_clear_actions ();
-}
-
-/* Call bpstat_clear_actions for the case an exception is throw.  You should
-   discard_cleanups if no exception is caught.  */
-
-struct cleanup *
-make_bpstat_clear_actions_cleanup (void)
-{
-  return make_cleanup (do_bpstat_clear_actions_cleanup, NULL);
-}
-
-/* Check for GCC >= 4.x according to the symtab->producer string.  Return minor
-   version (x) of 4.x in such case.  If it is not GCC or it is GCC older than
-   4.x return -1.  If it is GCC 5.x or higher return INT_MAX.  */
-
-int
-producer_is_gcc_ge_4 (const char *producer)
-{
-  int major, minor;
-
-  if (! producer_is_gcc (producer, &major, &minor))
-    return -1;
-  if (major < 4)
-    return -1;
-  if (major > 4)
-    return INT_MAX;
-  return minor;
-}
-
-/* Returns nonzero if the given PRODUCER string is GCC and sets the MAJOR
-   and MINOR versions when not NULL.  Returns zero if the given PRODUCER
-   is NULL or it isn't GCC.  */
-
-int
-producer_is_gcc (const char *producer, int *major, int *minor)
-{
-  const char *cs;
-
-  if (producer != NULL && startswith (producer, "GNU "))
-    {
-      int maj, min;
-
-      if (major == NULL)
-       major = &maj;
-      if (minor == NULL)
-       minor = &min;
-
-      /* Skip any identifier after "GNU " - such as "C11" or "C++".
-        A full producer string might look like:
-        "GNU C 4.7.2"
-        "GNU Fortran 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic ..."
-        "GNU C++14 5.0.0 20150123 (experimental)"
-      */
-      cs = &producer[strlen ("GNU ")];
-      while (*cs && !isspace (*cs))
-        cs++;
-      if (*cs && isspace (*cs))
-        cs++;
-      if (sscanf (cs, "%d.%d", major, minor) == 2)
-       return 1;
-    }
-
-  /* Not recognized as GCC.  */
-  return 0;
-}
-
-/* Helper for make_cleanup_free_char_ptr_vec.  */
-
-static void
-do_free_char_ptr_vec (void *arg)
-{
-  VEC (char_ptr) *char_ptr_vec = (VEC (char_ptr) *) arg;
-
-  free_char_ptr_vec (char_ptr_vec);
-}
-
-/* Make cleanup handler calling xfree for each element of CHAR_PTR_VEC and
-   final VEC_free for CHAR_PTR_VEC itself.
-
-   You must not modify CHAR_PTR_VEC after this cleanup registration as the
-   CHAR_PTR_VEC base address may change on its updates.  Contrary to VEC_free
-   this function does not (cannot) clear the pointer.  */
-
-struct cleanup *
-make_cleanup_free_char_ptr_vec (VEC (char_ptr) *char_ptr_vec)
-{
-  return make_cleanup (do_free_char_ptr_vec, char_ptr_vec);
-}
-
 /* Substitute all occurences of string FROM by string TO in *STRINGP.  *STRINGP
    must come from xrealloc-compatible allocator and it may be updated.  FROM
    needs to be delimited by IS_DIR_SEPARATOR or DIRNAME_SEPARATOR (or be
@@ -3394,8 +3352,98 @@ strip_leading_path_elements (const char *path, int n)
   return p;
 }
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern initialize_file_ftype _initialize_utils;
+/* See utils.h.  */
+
+void
+copy_bitwise (gdb_byte *dest, ULONGEST dest_offset,
+             const gdb_byte *source, ULONGEST source_offset,
+             ULONGEST nbits, int bits_big_endian)
+{
+  unsigned int buf, avail;
+
+  if (nbits == 0)
+    return;
+
+  if (bits_big_endian)
+    {
+      /* Start from the end, then work backwards.  */
+      dest_offset += nbits - 1;
+      dest += dest_offset / 8;
+      dest_offset = 7 - dest_offset % 8;
+      source_offset += nbits - 1;
+      source += source_offset / 8;
+      source_offset = 7 - source_offset % 8;
+    }
+  else
+    {
+      dest += dest_offset / 8;
+      dest_offset %= 8;
+      source += source_offset / 8;
+      source_offset %= 8;
+    }
+
+  /* Fill BUF with DEST_OFFSET bits from the destination and 8 -
+     SOURCE_OFFSET bits from the source.  */
+  buf = *(bits_big_endian ? source-- : source++) >> source_offset;
+  buf <<= dest_offset;
+  buf |= *dest & ((1 << dest_offset) - 1);
+
+  /* NBITS: bits yet to be written; AVAIL: BUF's fill level.  */
+  nbits += dest_offset;
+  avail = dest_offset + 8 - source_offset;
+
+  /* Flush 8 bits from BUF, if appropriate.  */
+  if (nbits >= 8 && avail >= 8)
+    {
+      *(bits_big_endian ? dest-- : dest++) = buf;
+      buf >>= 8;
+      avail -= 8;
+      nbits -= 8;
+    }
+
+  /* Copy the middle part.  */
+  if (nbits >= 8)
+    {
+      size_t len = nbits / 8;
+
+      /* Use a faster method for byte-aligned copies.  */
+      if (avail == 0)
+       {
+         if (bits_big_endian)
+           {
+             dest -= len;
+             source -= len;
+             memcpy (dest + 1, source + 1, len);
+           }
+         else
+           {
+             memcpy (dest, source, len);
+             dest += len;
+             source += len;
+           }
+       }
+      else
+       {
+         while (len--)
+           {
+             buf |= *(bits_big_endian ? source-- : source++) << avail;
+             *(bits_big_endian ? dest-- : dest++) = buf;
+             buf >>= 8;
+           }
+       }
+      nbits %= 8;
+    }
+
+  /* Write the last byte.  */
+  if (nbits)
+    {
+      if (avail < nbits)
+       buf |= *source << avail;
+
+      buf &= (1 << nbits) - 1;
+      *dest = (*dest & (~0 << nbits)) | buf;
+    }
+}
 
 void
 _initialize_utils (void)
@@ -3403,4 +3451,8 @@ _initialize_utils (void)
   add_internal_problem_command (&internal_error_problem);
   add_internal_problem_command (&internal_warning_problem);
   add_internal_problem_command (&demangler_warning_problem);
+
+#if GDB_SELF_TEST
+  selftests::register_test ("gdb_realpath", gdb_realpath_tests);
+#endif
 }
This page took 0.060337 seconds and 4 git commands to generate.