Make reinsert_breakpoint thread specific
[deliverable/binutils-gdb.git] / gdb / utils.c
index ea2b18a801e8fc803df7ca6a38cb785ed26f9b55..c70e99cea4924a3dc5093b3d340db29a03b85784 100644 (file)
@@ -1,6 +1,6 @@
 /* General utility routines for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2014 Free Software Foundation, Inc.
+   Copyright (C) 1986-2016 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -62,7 +62,7 @@
 
 #include "readline/readline.h"
 
-#include <sys/time.h>
+#include "gdb_sys_time.h"
 #include <time.h>
 
 #include "gdb_usleep.h"
@@ -109,19 +109,6 @@ static int debug_timestamp = 0;
 
 int job_control;
 
-/* Nonzero means quit immediately if Control-C is typed now, rather
-   than waiting until QUIT is executed.  Be careful in setting this;
-   code which executes with immediate_quit set has to be very careful
-   about being able to deal with being interrupted at any time.  It is
-   almost always better to use QUIT; the only exception I can think of
-   is being able to quit out of a system call (using EINTR loses if
-   the SIGINT happens between the previous QUIT and the system call).
-   To immediately quit in the case in which a SIGINT happens between
-   the previous QUIT and setting immediate_quit (desirable anytime we
-   expect to block), call QUIT after setting immediate_quit.  */
-
-int immediate_quit;
-
 /* 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
    international character, and the terminal or window can cope.)  */
@@ -182,7 +169,7 @@ make_cleanup_dyn_string_delete (dyn_string_t arg)
 static void
 do_bfd_close_cleanup (void *arg)
 {
-  gdb_bfd_unref (arg);
+  gdb_bfd_unref ((bfd *) arg);
 }
 
 struct cleanup *
@@ -191,29 +178,12 @@ make_cleanup_bfd_unref (bfd *abfd)
   return make_cleanup (do_bfd_close_cleanup, abfd);
 }
 
-static void
-do_close_cleanup (void *arg)
-{
-  int *fd = arg;
-
-  close (*fd);
-}
-
-struct cleanup *
-make_cleanup_close (int fd)
-{
-  int *saved_fd = xmalloc (sizeof (fd));
-
-  *saved_fd = 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;
+  FILE *file = (FILE *) arg;
 
   fclose (file);
 }
@@ -231,7 +201,7 @@ make_cleanup_fclose (FILE *file)
 static void
 do_obstack_free (void *arg)
 {
-  struct obstack *ob = arg;
+  struct obstack *ob = (struct obstack *) arg;
 
   obstack_free (ob, NULL);
 }
@@ -247,7 +217,7 @@ make_cleanup_obstack_free (struct obstack *obstack)
 static void
 do_ui_file_delete (void *arg)
 {
-  ui_file_delete (arg);
+  ui_file_delete ((struct ui_file *) arg);
 }
 
 struct cleanup *
@@ -261,7 +231,7 @@ make_cleanup_ui_file_delete (struct ui_file *arg)
 static void
 do_ui_out_redirect_pop (void *arg)
 {
-  struct ui_out *uiout = arg;
+  struct ui_out *uiout = (struct ui_out *) arg;
 
   if (ui_out_redirect (uiout, NULL) < 0)
     warning (_("Cannot restore redirection of the current output protocol"));
@@ -279,7 +249,7 @@ make_cleanup_ui_out_redirect_pop (struct ui_out *uiout)
 static void
 do_free_section_addr_info (void *arg)
 {
-  free_section_addr_info (arg);
+  free_section_addr_info ((struct section_addr_info *) arg);
 }
 
 struct cleanup *
@@ -297,7 +267,8 @@ struct restore_integer_closure
 static void
 restore_integer (void *p)
 {
-  struct restore_integer_closure *closure = p;
+  struct restore_integer_closure *closure
+    = (struct restore_integer_closure *) p;
 
   *(closure->variable) = closure->value;
 }
@@ -308,8 +279,7 @@ restore_integer (void *p)
 struct cleanup *
 make_cleanup_restore_integer (int *variable)
 {
-  struct restore_integer_closure *c =
-    xmalloc (sizeof (struct restore_integer_closure));
+  struct restore_integer_closure *c = XNEW (struct restore_integer_closure);
 
   c->variable = variable;
   c->value = *variable;
@@ -331,7 +301,7 @@ make_cleanup_restore_uinteger (unsigned int *variable)
 static void
 do_unpush_target (void *arg)
 {
-  struct target_ops *ops = arg;
+  struct target_ops *ops = (struct target_ops *) arg;
 
   unpush_target (ops);
 }
@@ -349,7 +319,7 @@ make_cleanup_unpush_target (struct target_ops *ops)
 static void
 do_htab_delete_cleanup (void *htab_voidp)
 {
-  htab_t htab = htab_voidp;
+  htab_t htab = (htab_t) htab_voidp;
 
   htab_delete (htab);
 }
@@ -362,6 +332,35 @@ make_cleanup_htab_delete (htab_t htab)
   return make_cleanup (do_htab_delete_cleanup, htab);
 }
 
+struct restore_ui_out_closure
+{
+  struct ui_out **variable;
+  struct ui_out *value;
+};
+
+static void
+do_restore_ui_out (void *p)
+{
+  struct restore_ui_out_closure *closure
+    = (struct restore_ui_out_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_out (struct ui_out **variable)
+{
+  struct restore_ui_out_closure *c = XNEW (struct restore_ui_out_closure);
+
+  c->variable = variable;
+  c->value = *variable;
+
+  return make_cleanup_dtor (do_restore_ui_out, (void *) c, xfree);
+}
+
 struct restore_ui_file_closure
 {
   struct ui_file **variable;
@@ -371,7 +370,8 @@ struct restore_ui_file_closure
 static void
 do_restore_ui_file (void *p)
 {
-  struct restore_ui_file_closure *closure = p;
+  struct restore_ui_file_closure *closure
+    = (struct restore_ui_file_closure *) p;
 
   *(closure->variable) = closure->value;
 }
@@ -412,7 +412,7 @@ make_cleanup_value_free_to_mark (struct value *mark)
 static void
 do_value_free (void *value)
 {
-  value_free (value);
+  value_free ((struct value *) value);
 }
 
 /* Free VALUE.  */
@@ -428,7 +428,7 @@ make_cleanup_value_free (struct value *value)
 static void
 do_free_so (void *arg)
 {
-  struct so_list *so = arg;
+  struct so_list *so = (struct so_list *) arg;
 
   free_so (so);
 }
@@ -446,7 +446,7 @@ make_cleanup_free_so (struct so_list *so)
 static void
 do_restore_current_language (void *p)
 {
-  enum language saved_lang = (uintptr_t) p;
+  enum language saved_lang = (enum language) (uintptr_t) p;
 
   set_language (saved_lang);
 }
@@ -492,7 +492,7 @@ make_cleanup_clear_parser_state (struct parser_state **p)
 void
 free_current_contents (void *ptr)
 {
-  void **location = ptr;
+  void **location = (void **) ptr;
 
   if (location == NULL)
     internal_error (__FILE__, __LINE__,
@@ -519,8 +519,13 @@ vwarning (const char *string, va_list args)
     (*deprecated_warning_hook) (string, args);
   else
     {
+      struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+
       if (target_supports_terminal_ours ())
-       target_terminal_ours ();
+       {
+         make_cleanup_restore_target_terminal ();
+         target_terminal_ours_for_output ();
+       }
       if (filtered_printing_initialized ())
        wrap_here ("");         /* Force out any buffered output.  */
       gdb_flush (gdb_stdout);
@@ -528,6 +533,8 @@ 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);
     }
 }
 
@@ -725,7 +732,10 @@ internal_vproblem (struct internal_problem *problem,
 
   /* Try to get the message out and at the start of a new line.  */
   if (target_supports_terminal_ours ())
-    target_terminal_ours ();
+    {
+      make_cleanup_restore_target_terminal ();
+      target_terminal_ours_for_output ();
+    }
   if (filtered_printing_initialized ())
     begin_line ();
 
@@ -877,8 +887,8 @@ add_internal_problem_command (struct internal_problem *problem)
   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 = XNEW (struct cmd_list_element *);
+  show_cmd_list = XNEW (struct cmd_list_element *);
   *set_cmd_list = NULL;
   *show_cmd_list = NULL;
 
@@ -1037,10 +1047,12 @@ 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;
-      quit_force (NULL, stdin == instream);
+      quit_force (NULL, 0);
     }
 
 #ifdef __MSDOS__
@@ -1058,6 +1070,20 @@ quit (void)
 #endif
 }
 
+/* See defs.h.  */
+
+void
+maybe_quit (void)
+{
+  if (sync_quit_force_run)
+    quit ();
+
+  quit_handler ();
+
+  if (deprecated_interactive_hook)
+    deprecated_interactive_hook ();
+}
+
 \f
 /* Called when a memory allocation fails, with the number of bytes of
    memory requested in SIZE.  */
@@ -1108,7 +1134,7 @@ print_spaces (int n, struct ui_file *file)
 /* Print a host address.  */
 
 void
-gdb_print_host_address (const void *addr, struct ui_file *stream)
+gdb_print_host_address_1 (const void *addr, struct ui_file *stream)
 {
   fprintf_filtered (stream, "%s", host_address_to_string (addr));
 }
@@ -1118,13 +1144,13 @@ gdb_print_host_address (const void *addr, struct ui_file *stream)
 char *
 make_hex_string (const gdb_byte *data, size_t length)
 {
-  char *result = xmalloc (length * 2 + 1);
+  char *result = (char *) xmalloc (length * 2 + 1);
   char *p;
   size_t i;
 
   p = result;
   for (i = 0; i < length; ++i)
-    p += xsnprintf (p, 2, "%02x", data[i]);
+    p += xsnprintf (p, 3, "%02x", data[i]);
   *p = '\0';
   return result;
 }
@@ -1136,7 +1162,7 @@ make_hex_string (const gdb_byte *data, size_t length)
 static void
 do_regfree_cleanup (void *r)
 {
-  regfree (r);
+  regfree ((regex_t *) r);
 }
 
 /* Create a new cleanup that frees the compiled regular expression R.  */
@@ -1154,7 +1180,7 @@ char *
 get_regcomp_error (int code, regex_t *rx)
 {
   size_t length = regerror (code, rx, NULL, 0);
-  char *result = xmalloc (length);
+  char *result = (char *) xmalloc (length);
 
   regerror (code, rx, result, length);
   return result;
@@ -1198,15 +1224,15 @@ compile_rx_or_error (regex_t *pattern, const char *rx, const char *message)
 static int ATTRIBUTE_PRINTF (1, 0)
 defaulted_query (const char *ctlstr, const char defchar, va_list args)
 {
-  int answer;
   int ans2;
   int retval;
   int def_value;
   char def_answer, not_def_answer;
-  char *y_string, *n_string, *question;
+  char *y_string, *n_string, *question, *prompt;
   /* Used to add duration we waited for user to respond to
      prompt_for_continue_wait_time.  */
   struct timeval prompt_started, prompt_ended, prompt_delta;
+  struct cleanup *old_chain;
 
   /* Set up according to which answer is the default.  */
   if (defchar == '\0')
@@ -1239,12 +1265,16 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
   if (!confirm || server_command)
     return def_value;
 
+  old_chain = make_cleanup_restore_target_terminal ();
+
   /* 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 ())
+  if (current_ui->instream != current_ui->stdin_stream
+      || !input_interactive_p (current_ui))
     {
+      target_terminal_ours_for_output ();
       wrap_here ("");
       vfprintf_filtered (gdb_stdout, ctlstr, args);
 
@@ -1253,72 +1283,51 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
                       y_string, n_string, def_answer);
       gdb_flush (gdb_stdout);
 
+      do_cleanups (old_chain);
       return def_value;
     }
 
   if (deprecated_query_hook)
     {
-      return deprecated_query_hook (ctlstr, args);
+      int res;
+
+      res = deprecated_query_hook (ctlstr, args);
+      do_cleanups (old_chain);
+      return res;
     }
 
   /* Format the question outside of the loop, to avoid reusing args.  */
   question = xstrvprintf (ctlstr, args);
+  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);
 
   /* Used for calculating time spend waiting for user.  */
   gettimeofday (&prompt_started, NULL);
 
+  /* We'll need to handle input.  */
+  target_terminal_ours ();
+  make_cleanup_override_quit_handler (default_quit_handler);
+
   while (1)
     {
-      wrap_here ("");          /* Flush any buffered output.  */
-      gdb_flush (gdb_stdout);
-
-      if (annotation_level > 1)
-       printf_filtered (("\n\032\032pre-query\n"));
+      char *response, answer;
 
-      fputs_filtered (question, gdb_stdout);
-      printf_filtered (_("(%s or %s) "), y_string, n_string);
-
-      if (annotation_level > 1)
-       printf_filtered (("\n\032\032query\n"));
-
-      wrap_here ("");
       gdb_flush (gdb_stdout);
+      response = gdb_readline_wrapper (prompt);
 
-      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 */
+      if (response == NULL)    /* C-d  */
        {
          printf_filtered ("EOF [assumed %c]\n", def_answer);
          retval = def_value;
          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');
+
+      answer = response[0];
+      xfree (response);
 
       if (answer >= 'a')
        answer -= 040;
@@ -1333,8 +1342,7 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
          specify the required input or have it default by entering
          nothing.  */
       if (answer == def_answer
-         || (defchar != '\0' &&
-             (answer == '\n' || answer == '\r' || answer == EOF)))
+         || (defchar != '\0' && answer == '\0'))
        {
          retval = def_value;
          break;
@@ -1350,9 +1358,9 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
   timeval_add (&prompt_for_continue_wait_time,
                &prompt_for_continue_wait_time, &prompt_delta);
 
-  xfree (question);
   if (annotation_level > 1)
     printf_filtered (("\n\032\032post-query\n"));
+  do_cleanups (old_chain);
   return retval;
 }
 \f
@@ -1532,7 +1540,7 @@ parse_escape (struct gdbarch *gdbarch, const char **string_ptr)
 \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
+   be called for printing things which are independent of the language
    of the program being debugged.
 
    printchar will normally escape backslashes and instances of QUOTER. If
@@ -1714,8 +1722,9 @@ init_page_info (void)
          Only try to use tgetnum function if rl_get_screen_size
          did not return a useful value. */
       if (((rows <= 0) && (tgetnum ("li") < 0))
-       /* Also disable paging if inside EMACS.  */
-         || getenv ("EMACS"))
+       /* Also disable paging if inside Emacs.  $EMACS was used
+          before Emacs v25.1, $INSIDE_EMACS is used since then.  */
+         || getenv ("EMACS") || getenv ("INSIDE_EMACS"))
        {
          /* The number of lines per page is not mentioned in the terminal
             description or EMACS evironment variable is set.  This probably
@@ -1729,6 +1738,9 @@ init_page_info (void)
 #endif
     }
 
+  /* We handle SIGWINCH ourselves.  */
+  rl_catch_sigwinch = 0;
+
   set_screen_size ();
   set_width ();
 }
@@ -1828,8 +1840,22 @@ set_height_command (char *args, int from_tty, struct cmd_list_element *c)
   set_screen_size ();
 }
 
+/* See utils.h.  */
+
+void
+set_screen_width_and_height (int width, int height)
+{
+  lines_per_page = height;
+  chars_per_line = width;
+
+  set_screen_size ();
+  set_width ();
+}
+
 /* Wait, so the user can read what's on the screen.  Prompt the user
-   to continue by pressing RETURN.  */
+   to continue by pressing RETURN.  'q' is also provided because
+   telling users what to do in the prompt is more user-friendly than
+   expecting them to think of Ctrl-C/SIGINT.  */
 
 static void
 prompt_for_continue (void)
@@ -1839,6 +1865,7 @@ prompt_for_continue (void)
   /* Used to add duration we waited for user to respond to
      prompt_for_continue_wait_time.  */
   struct timeval prompt_started, prompt_ended, prompt_delta;
+  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
 
   gettimeofday (&prompt_started, NULL);
 
@@ -1850,28 +1877,20 @@ prompt_for_continue (void)
   if (annotation_level > 1)
     strcat (cont_prompt, "\n\032\032prompt-for-continue\n");
 
-  /* We must do this *before* we call gdb_readline, else it will eventually
-     call us -- thinking that we're trying to print beyond the end of the 
-     screen.  */
+  /* We must do this *before* we call gdb_readline_wrapper, else it
+     will eventually call us -- thinking that we're trying to print
+     beyond the end of the screen.  */
   reinitialize_more_filter ();
 
-  immediate_quit++;
-  QUIT;
-
   /* We'll need to handle input.  */
+  make_cleanup_restore_target_terminal ();
   target_terminal_ours ();
+  make_cleanup_override_quit_handler (default_quit_handler);
 
-  /* On a real operating system, the user can quit with SIGINT.
-     But not on GO32.
-
-     'q' is provided on all systems so users don't have to change habits
-     from system to system, and because telling them what to do in
-     the prompt is more user-friendly than expecting them to think of
-     SIGINT.  */
-  /* Call readline, not gdb_readline, because GO32 readline handles control-C
-     whereas control-C to gdb_readline will cause the user to get dumped
-     out to DOS.  */
+  /* Call gdb_readline_wrapper, not readline, in order to keep an
+     event loop running.  */
   ignore = gdb_readline_wrapper (cont_prompt);
+  make_cleanup (xfree, ignore);
 
   /* Add time spend in this routine to prompt_for_continue_wait_time.  */
   gettimeofday (&prompt_ended, NULL);
@@ -1882,23 +1901,24 @@ prompt_for_continue (void)
   if (annotation_level > 1)
     printf_unfiltered (("\n\032\032post-prompt-for-continue\n"));
 
-  if (ignore)
+  if (ignore != NULL)
     {
       char *p = ignore;
 
       while (*p == ' ' || *p == '\t')
        ++p;
       if (p[0] == 'q')
-       quit ();
-      xfree (ignore);
+       /* Do not call quit here; there is no possibility of SIGINT.  */
+       throw_quit ("Quit");
     }
-  immediate_quit--;
 
   /* 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 ();
 
   dont_repeat ();              /* Forget prev cmd -- CR won't repeat it.  */
+
+  do_cleanups (old_chain);
 }
 
 /* Initalize timer to keep track of how long we waited for the user.  */
@@ -2020,7 +2040,7 @@ puts_filtered_tabular (char *string, int width, int right)
   if (right)
     spaces += width - stringlen;
 
-  spacebuf = alloca (spaces + 1);
+  spacebuf = (char *) alloca (spaces + 1);
   spacebuf[spaces] = '\0';
   while (spaces--)
     spacebuf[spaces] = ' ';
@@ -2696,25 +2716,12 @@ subset_compare (char *string_to_compare, char *template_string)
   if (template_string != (char *) NULL && string_to_compare != (char *) NULL
       && strlen (string_to_compare) <= strlen (template_string))
     match =
-      (strncmp
-       (template_string, string_to_compare, strlen (string_to_compare)) == 0);
+      (startswith (template_string, string_to_compare));
   else
     match = 0;
   return match;
 }
 
-static void
-pagination_on_command (char *arg, int from_tty)
-{
-  pagination_enabled = 1;
-}
-
-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)
@@ -2746,8 +2753,6 @@ Setting this to \"unlimited\" or zero causes GDB never pause during output."),
                            show_lines_per_page,
                            &setlist, &showlist);
 
-  init_page_info ();
-
   add_setshow_boolean_cmd ("pagination", class_support,
                           &pagination_enabled, _("\
 Set state of GDB output pagination."), _("\
@@ -2759,14 +2764,6 @@ Turning pagination off is an alternative to \"set height unlimited\"."),
                           show_pagination_enabled,
                           &setlist, &showlist);
 
-  if (xdb_commands)
-    {
-      add_com ("am", class_support, pagination_on_command,
-              _("Enable pagination"));
-      add_com ("sm", class_support, pagination_off_command,
-              _("Disable pagination"));
-    }
-
   add_setshow_boolean_cmd ("sevenbit-strings", class_support,
                           &sevenbit_strings, _("\
 Set printing of 8-bit characters in strings as \\nnn."), _("\
@@ -2828,7 +2825,7 @@ print_core_address (struct gdbarch *gdbarch, CORE_ADDR address)
 hashval_t
 core_addr_hash (const void *ap)
 {
-  const CORE_ADDR *addrp = ap;
+  const CORE_ADDR *addrp = (const CORE_ADDR *) ap;
 
   return *addrp;
 }
@@ -2838,8 +2835,8 @@ core_addr_hash (const void *ap)
 int
 core_addr_eq (const void *ap, const void *bp)
 {
-  const CORE_ADDR *addr_ap = ap;
-  const CORE_ADDR *addr_bp = bp;
+  const CORE_ADDR *addr_ap = (const CORE_ADDR *) ap;
+  const CORE_ADDR *addr_bp = (const CORE_ADDR *) bp;
 
   return *addr_ap == *addr_bp;
 }
@@ -2949,7 +2946,7 @@ gdb_realpath_keepfile (const char *filename)
   if (base_name == filename)
     return xstrdup (filename);
 
-  dir_name = alloca ((size_t) (base_name - filename + 2));
+  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.  */
@@ -3021,23 +3018,6 @@ align_down (ULONGEST v, int n)
   return (v & -n);
 }
 
-/* See utils.h.  */
-
-LONGEST
-gdb_sign_extend (LONGEST value, int bit)
-{
-  gdb_assert (bit >= 1 && bit <= 8 * sizeof (LONGEST));
-
-  if (((value >> (bit - 1)) & 1) != 0)
-    {
-      LONGEST signbit = ((LONGEST) 1) << (bit - 1);
-
-      value = (value ^ signbit) - signbit;
-    }
-
-  return value;
-}
-
 /* Allocation function for the libiberty hash table which uses an
    obstack.  The obstack is passed as DATA.  */
 
@@ -3062,105 +3042,6 @@ dummy_obstack_deallocate (void *object, void *data)
   return;
 }
 
-/* The bit offset of the highest byte in a ULONGEST, for overflow
-   checking.  */
-
-#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
-
-/* True (non-zero) iff DIGIT is a valid digit in radix BASE,
-   where 2 <= BASE <= 36.  */
-
-static int
-is_digit_in_base (unsigned char digit, int base)
-{
-  if (!isalnum (digit))
-    return 0;
-  if (base <= 10)
-    return (isdigit (digit) && digit < base + '0');
-  else
-    return (isdigit (digit) || tolower (digit) < base - 10 + 'a');
-}
-
-static int
-digit_to_int (unsigned char c)
-{
-  if (isdigit (c))
-    return c - '0';
-  else
-    return tolower (c) - 'a' + 10;
-}
-
-/* As for strtoul, but for ULONGEST results.  */
-
-ULONGEST
-strtoulst (const char *num, const char **trailer, int base)
-{
-  unsigned int high_part;
-  ULONGEST result;
-  int minus = 0;
-  int i = 0;
-
-  /* Skip leading whitespace.  */
-  while (isspace (num[i]))
-    i++;
-
-  /* Handle prefixes.  */
-  if (num[i] == '+')
-    i++;
-  else if (num[i] == '-')
-    {
-      minus = 1;
-      i++;
-    }
-
-  if (base == 0 || base == 16)
-    {
-      if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X'))
-       {
-         i += 2;
-         if (base == 0)
-           base = 16;
-       }
-    }
-
-  if (base == 0 && num[i] == '0')
-    base = 8;
-
-  if (base == 0)
-    base = 10;
-
-  if (base < 2 || base > 36)
-    {
-      errno = EINVAL;
-      return 0;
-    }
-
-  result = high_part = 0;
-  for (; is_digit_in_base (num[i], base); i += 1)
-    {
-      result = result * base + digit_to_int (num[i]);
-      high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN);
-      result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
-      if (high_part > 0xff)
-       {
-         errno = ERANGE;
-         result = ~ (ULONGEST) 0;
-         high_part = 0;
-         minus = 0;
-         break;
-       }
-    }
-
-  if (trailer != NULL)
-    *trailer = &num[i];
-
-  result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
-  if (minus)
-    return -result;
-  else
-    return result;
-}
-
 /* Simple, portable version of dirname that does not modify its
    argument.  */
 
@@ -3176,7 +3057,7 @@ ldirname (const char *filename)
   if (base == filename)
     return NULL;
 
-  dirname = xmalloc (base - filename + 2);
+  dirname = (char *) xmalloc (base - filename + 2);
   memcpy (dirname, filename, base - filename);
 
   /* On DOS based file systems, convert "d:foo" to "d:.", so that we
@@ -3242,7 +3123,7 @@ gdb_bfd_errmsg (bfd_error_type error_tag, char **matching)
             + strlen (AMBIGUOUS_MESS2);
   for (p = matching; *p; p++)
     ret_len += strlen (*p) + 1;
-  ret = xmalloc (ret_len + 1);
+  ret = (char *) xmalloc (ret_len + 1);
   retp = ret;
   make_cleanup (xfree, ret);
 
@@ -3308,41 +3189,52 @@ make_bpstat_clear_actions_cleanup (void)
 int
 producer_is_gcc_ge_4 (const char *producer)
 {
-  const char *cs;
   int major, minor;
 
-  if (producer == NULL)
-    {
-      /* For unknown compilers expect their behavior is not compliant.  For GCC
-        this case can also happen for -gdwarf-4 type units supported since
-        gcc-4.5.  */
-
-      return -1;
-    }
+  if (! producer_is_gcc (producer, &major, &minor))
+    return -1;
+  if (major < 4)
+    return -1;
+  if (major > 4)
+    return INT_MAX;
+  return minor;
+}
 
-  /* Skip any identifier after "GNU " - such as "C++" or "Java".  */
+/* 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.  */
 
-  if (strncmp (producer, "GNU ", strlen ("GNU ")) != 0)
-    {
-      /* For non-GCC compilers expect their behavior is not compliant.  */
+int
+producer_is_gcc (const char *producer, int *major, int *minor)
+{
+  const char *cs;
 
-      return -1;
-    }
-  cs = &producer[strlen ("GNU ")];
-  while (*cs && !isdigit (*cs))
-    cs++;
-  if (sscanf (cs, "%d.%d", &major, &minor) != 2)
+  if (producer != NULL && startswith (producer, "GNU "))
     {
-      /* Not recognized as GCC.  */
-
-      return -1;
+      int maj, min;
+
+      if (major == NULL)
+       major = &maj;
+      if (minor == NULL)
+       minor = &min;
+
+      /* Skip any identifier after "GNU " - such as "C11" "C++" or "Java".
+        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;
     }
 
-  if (major < 4)
-    return -1;
-  if (major > 4)
-    return INT_MAX;
-  return minor;
+  /* Not recognized as GCC.  */
+  return 0;
 }
 
 /* Helper for make_cleanup_free_char_ptr_vec.  */
@@ -3350,7 +3242,7 @@ producer_is_gcc_ge_4 (const char *producer)
 static void
 do_free_char_ptr_vec (void *arg)
 {
-  VEC (char_ptr) *char_ptr_vec = arg;
+  VEC (char_ptr) *char_ptr_vec = (VEC (char_ptr) *) arg;
 
   free_char_ptr_vec (char_ptr_vec);
 }
@@ -3393,7 +3285,8 @@ substitute_path_component (char **stringp, const char *from, const char *to)
        {
          char *string_new;
 
-         string_new = xrealloc (string, (strlen (string) + to_len + 1));
+         string_new
+           = (char *) xrealloc (string, (strlen (string) + to_len + 1));
 
          /* Relocate the current S pointer.  */
          s = s - string + string_new;
@@ -3454,9 +3347,9 @@ wait_to_die_with_timeout (pid_t pid, int *status, int timeout)
       sa.sa_flags = 0;
       sigaction (SIGALRM, &sa, &old_sa);
 #else
-      void (*ofunc) ();
+      sighandler_t ofunc;
 
-      ofunc = (void (*)()) signal (SIGALRM, sigalrm_handler);
+      ofunc = signal (SIGALRM, sigalrm_handler);
 #endif
 
       alarm (timeout);
@@ -3504,14 +3397,14 @@ gdb_filename_fnmatch (const char *pattern, const char *string, int flags)
 
     /* Replace '\' by '/' in both strings.  */
 
-    pattern_slash = alloca (strlen (pattern) + 1);
+    pattern_slash = (char *) alloca (strlen (pattern) + 1);
     strcpy (pattern_slash, pattern);
     pattern = pattern_slash;
     for (; *pattern_slash != 0; pattern_slash++)
       if (IS_DIR_SEPARATOR (*pattern_slash))
        *pattern_slash = '/';
 
-    string_slash = alloca (strlen (string) + 1);
+    string_slash = (char *) alloca (strlen (string) + 1);
     strcpy (string_slash, string);
     string = string_slash;
     for (; *string_slash != 0; string_slash++)
@@ -3527,6 +3420,83 @@ gdb_filename_fnmatch (const char *pattern, const char *string, int flags)
   return fnmatch (pattern, string, flags);
 }
 
+/* Return the number of path elements in PATH.
+   / = 1
+   /foo = 2
+   /foo/ = 2
+   foo/bar = 2
+   foo/ = 1  */
+
+int
+count_path_elements (const char *path)
+{
+  int count = 0;
+  const char *p = path;
+
+  if (HAS_DRIVE_SPEC (p))
+    {
+      p = STRIP_DRIVE_SPEC (p);
+      ++count;
+    }
+
+  while (*p != '\0')
+    {
+      if (IS_DIR_SEPARATOR (*p))
+       ++count;
+      ++p;
+    }
+
+  /* Backup one if last character is /, unless it's the only one.  */
+  if (p > path + 1 && IS_DIR_SEPARATOR (p[-1]))
+    --count;
+
+  /* Add one for the file name, if present.  */
+  if (p > path && !IS_DIR_SEPARATOR (p[-1]))
+    ++count;
+
+  return count;
+}
+
+/* Remove N leading path elements from PATH.
+   N must be non-negative.
+   If PATH has more than N path elements then return NULL.
+   If PATH has exactly N path elements then return "".
+   See count_path_elements for a description of how we do the counting.  */
+
+const char *
+strip_leading_path_elements (const char *path, int n)
+{
+  int i = 0;
+  const char *p = path;
+
+  gdb_assert (n >= 0);
+
+  if (n == 0)
+    return p;
+
+  if (HAS_DRIVE_SPEC (p))
+    {
+      p = STRIP_DRIVE_SPEC (p);
+      ++i;
+    }
+
+  while (i < n)
+    {
+      while (*p != '\0' && !IS_DIR_SEPARATOR (*p))
+       ++p;
+      if (*p == '\0')
+       {
+         if (i + 1 == n)
+           return "";
+         return NULL;
+       }
+      ++p;
+      ++i;
+    }
+
+  return p;
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_utils;
 
This page took 0.036672 seconds and 4 git commands to generate.