* vax-tdep.c (vax_frame_chain): New function.
[deliverable/binutils-gdb.git] / gdb / utils.c
index 5abb741dea749150c3e2d46f544921e7cd7e0124..4baea62426456e966a844c02fa76d327eb1f46c0 100644 (file)
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include "defs.h"
-#include "gdb_assert.h"
-#include <ctype.h>
-#include "gdb_string.h"
-#include "event-top.h"
+/* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
+   "defs.h" should be included first.  Unfortunatly some systems
+   (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
+   and they clash with "bfd.h"'s definiton of true/false.  The correct
+   fix is to remove true/false from "bfd.h", however, until that
+   happens, hack around it by including "config.h" and <curses.h>
+   first.  */
+
+#include "config.h"
 
 #ifdef HAVE_CURSES_H
 #include <curses.h>
 #include <term.h>
 #endif
 
+#include "defs.h"
+#include "gdb_assert.h"
+#include <ctype.h>
+#include "gdb_string.h"
+#include "event-top.h"
+
 #ifdef __GO32__
 #include <pc.h>
 #endif
 #include "expression.h"
 #include "language.h"
 #include "annotate.h"
+#include "filenames.h"
 
 #include "inferior.h" /* for signed_pointer_to_address */
 
+#include <sys/param.h>         /* For MAXPATHLEN */
+
 #include <readline/readline.h>
 
 #ifdef USE_MMALLOC
 #include "mmalloc.h"
 #endif
 
-#ifndef MALLOC_INCOMPATIBLE
 #ifdef NEED_DECLARATION_MALLOC
 extern PTR malloc ();
 #endif
@@ -70,11 +82,12 @@ extern PTR realloc ();
 #ifdef NEED_DECLARATION_FREE
 extern void free ();
 #endif
+/* Actually, we'll never have the decl, since we don't define _GNU_SOURCE.  */
+#if defined(HAVE_CANONICALIZE_FILE_NAME) \
+    && defined(NEED_DECLARATION_CANONICALIZE_FILE_NAME)
+extern char *canonicalize_file_name (const char *);
 #endif
 
-#undef XMALLOC
-#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
-
 /* readline defines this.  */
 #undef savestring
 
@@ -554,23 +567,28 @@ discard_all_intermediate_continuations (void)
 
 \f
 
-/* Print a warning message.  Way to use this is to call warning_begin,
-   output the warning message (use unfiltered output to gdb_stderr),
-   ending in a newline.  There is not currently a warning_end that you
-   call afterwards, but such a thing might be added if it is useful
-   for a GUI to separate warning messages from other output.
-
-   FIXME: Why do warnings use unfiltered output and errors filtered?
-   Is this anything other than a historical accident?  */
+/* Print a warning message.  The first argument STRING is the warning
+   message, used as an fprintf format string, the second is the
+   va_list of arguments for that string.  A warning is unfiltered (not
+   paginated) so that the user does not need to page through each
+   screen full of warnings when there are lots of them.  */
 
 void
-warning_begin (void)
+vwarning (const char *string, va_list args)
 {
-  target_terminal_ours ();
-  wrap_here ("");              /* Force out any buffered output */
-  gdb_flush (gdb_stdout);
-  if (warning_pre_print)
-    fprintf_unfiltered (gdb_stderr, warning_pre_print);
+  if (warning_hook)
+    (*warning_hook) (string, args);
+  else
+    {
+      target_terminal_ours ();
+      wrap_here ("");          /* Force out any buffered output */
+      gdb_flush (gdb_stdout);
+      if (warning_pre_print)
+       fprintf_unfiltered (gdb_stderr, warning_pre_print);
+      vfprintf_unfiltered (gdb_stderr, string, args);
+      fprintf_unfiltered (gdb_stderr, "\n");
+      va_end (args);
+    }
 }
 
 /* Print a warning message.
@@ -584,38 +602,8 @@ warning (const char *string,...)
 {
   va_list args;
   va_start (args, string);
-  if (warning_hook)
-    (*warning_hook) (string, args);
-  else
-    {
-      warning_begin ();
-      vfprintf_unfiltered (gdb_stderr, string, args);
-      fprintf_unfiltered (gdb_stderr, "\n");
-      va_end (args);
-    }
-}
-
-/* Start the printing of an error message.  Way to use this is to call
-   this, output the error message (use filtered output to gdb_stderr
-   (FIXME: Some callers, like memory_error, use gdb_stdout)), ending
-   in a newline, and then call return_to_top_level (RETURN_ERROR).
-   error() provides a convenient way to do this for the special case
-   that the error message can be formatted with a single printf call,
-   but this is more general.  */
-void
-error_begin (void)
-{
-  if (error_begin_hook)
-    error_begin_hook ();
-
-  target_terminal_ours ();
-  wrap_here ("");              /* Force out any buffered output */
-  gdb_flush (gdb_stdout);
-
-  annotate_error_begin ();
-
-  if (error_pre_print)
-    fprintf_filtered (gdb_stderr, error_pre_print);
+  vwarning (string, args);
+  va_end (args);
 }
 
 /* Print an error message and return to command level.
@@ -625,29 +613,10 @@ error_begin (void)
 NORETURN void
 verror (const char *string, va_list args)
 {
-  char *err_string;
-  struct cleanup *err_string_cleanup;
-  /* FIXME: cagney/1999-11-10: All error calls should come here.
-     Unfortunately some code uses the sequence: error_begin(); print
-     error message; return_to_top_level.  That code should be
-     flushed. */
-  error_begin ();
-  /* NOTE: It's tempting to just do the following...
-       vfprintf_filtered (gdb_stderr, string, args);
-     and then follow with a similar looking statement to cause the message
-     to also go to gdb_lasterr.  But if we do this, we'll be traversing the
-     va_list twice which works on some platforms and fails miserably on
-     others. */
-  /* Save it as the last error */
-  ui_file_rewind (gdb_lasterr);
-  vfprintf_filtered (gdb_lasterr, string, args);
-  /* Retrieve the last error and print it to gdb_stderr */
-  err_string = error_last_message ();
-  err_string_cleanup = make_cleanup (xfree, err_string);
-  fputs_filtered (err_string, gdb_stderr);
-  fprintf_filtered (gdb_stderr, "\n");
-  do_cleanups (err_string_cleanup);
-  return_to_top_level (RETURN_ERROR);
+  struct ui_file *tmp_stream = mem_fileopen ();
+  make_cleanup_ui_file_delete (tmp_stream);
+  vfprintf_unfiltered (tmp_stream, string, args);
+  error_stream (tmp_stream);
 }
 
 NORETURN void
@@ -659,13 +628,33 @@ error (const char *string,...)
   va_end (args);
 }
 
+static void
+do_write (void *data, const char *buffer, long length_buffer)
+{
+  ui_file_write (data, buffer, length_buffer);
+}
+
 NORETURN void
 error_stream (struct ui_file *stream)
 {
-  long size;
-  char *msg = ui_file_xstrdup (stream, &size);
-  make_cleanup (xfree, msg);
-  error ("%s", msg);
+  if (error_begin_hook)
+    error_begin_hook ();
+
+  /* Copy the stream into the GDB_LASTERR buffer.  */
+  ui_file_rewind (gdb_lasterr);
+  ui_file_put (stream, do_write, gdb_lasterr);
+
+  /* Write the message plus any error_pre_print to gdb_stderr.  */
+  target_terminal_ours ();
+  wrap_here ("");              /* Force out any buffered output */
+  gdb_flush (gdb_stdout);
+  annotate_error_begin ();
+  if (error_pre_print)
+    fprintf_filtered (gdb_stderr, error_pre_print);
+  ui_file_put (stream, do_write, gdb_stderr);
+  fprintf_filtered (gdb_stderr, "\n");
+
+  throw_exception (RETURN_ERROR);
 }
 
 /* Get the last error message issued by gdb */
@@ -694,7 +683,7 @@ internal_verror (const char *file, int line,
 {
   static char msg[] = "Internal GDB error: recursive internal error.\n";
   static int dejavu = 0;
-  int continue_p;
+  int quit_p;
   int dump_core_p;
 
   /* don't allow infinite error recursion. */
@@ -719,35 +708,36 @@ internal_verror (const char *file, int line,
   vfprintf_unfiltered (gdb_stderr, fmt, ap);
   fputs_unfiltered ("\n", gdb_stderr);
 
-  /* Default (no case) is to quit GDB.  When in batch mode this
+  /* Default (yes/batch case) is to quit GDB.  When in batch mode this
      lessens the likelhood of GDB going into an infinate loop. */
-  continue_p = query ("\
+  quit_p = query ("\
 An internal GDB error was detected.  This may make further\n\
-debugging unreliable.  Continue this debugging session? ");
+debugging unreliable.  Quit this debugging session? ");
 
-  /* Default (no case) is to not dump core.  Lessen the chance of GDB
-     leaving random core files around. */
+  /* Default (yes/batch case) is to dump core.  This leaves a GDB
+     dropping so that it is easier to see that something went wrong to
+     GDB. */
   dump_core_p = query ("\
 Create a core file containing the current state of GDB? ");
 
-  if (continue_p)
+  if (quit_p)
     {
       if (dump_core_p)
-       {
-         if (fork () == 0)
-           abort (); /* NOTE: GDB has only three calls to abort().  */
-       }
+       abort (); /* NOTE: GDB has only three calls to abort().  */
+      else
+       exit (1);
     }
   else
     {
       if (dump_core_p)
-       abort (); /* NOTE: GDB has only three calls to abort().  */
-      else
-       exit (1);
+       {
+         if (fork () == 0)
+           abort (); /* NOTE: GDB has only three calls to abort().  */
+       }
     }
 
   dejavu = 0;
-  return_to_top_level (RETURN_ERROR);
+  throw_exception (RETURN_ERROR);
 }
 
 NORETURN void
@@ -783,7 +773,7 @@ safe_strerror (int errnum)
    Then return to command level.  */
 
 NORETURN void
-perror_with_name (char *string)
+perror_with_name (const char *string)
 {
   char *err;
   char *combined;
@@ -807,7 +797,7 @@ perror_with_name (char *string)
    as the file name for which the error was encountered.  */
 
 void
-print_sys_errmsg (char *string, int errcode)
+print_sys_errmsg (const char *string, int errcode)
 {
   char *err;
   char *combined;
@@ -869,7 +859,7 @@ quit (void)
     fprintf_unfiltered (gdb_stderr,
               "Quit (expect signal SIGINT when the program is resumed)\n");
 #endif
-  return_to_top_level (RETURN_QUIT);
+  throw_exception (RETURN_QUIT);
 }
 
 /* Control C comes here */
@@ -1220,7 +1210,7 @@ gdb_print_host_address (void *addr, struct ui_file *stream)
 
 /* VARARGS */
 int
-query (char *ctlstr,...)
+query (const char *ctlstr,...)
 {
   va_list args;
   register int answer;
@@ -2261,7 +2251,7 @@ initialize_utils (void)
                   "Set number of characters gdb thinks are in a line.",
                   &setlist);
   add_show_from_set (c, &showlist);
-  c->function.sfunc = set_width_command;
+  set_cmd_sfunc (c, set_width_command);
 
   add_show_from_set
     (add_set_cmd ("height", class_support,
@@ -2492,6 +2482,15 @@ address_to_host_pointer (CORE_ADDR addr)
 /* Convert a CORE_ADDR into a string.  */
 const char *
 core_addr_to_string (const CORE_ADDR addr)
+{
+  char *str = get_cell ();
+  strcpy (str, "0x");
+  strcat (str, phex (addr, sizeof (addr)));
+  return str;
+}
+
+const char *
+core_addr_to_string_nz (const CORE_ADDR addr)
 {
   char *str = get_cell ();
   strcpy (str, "0x");
@@ -2536,11 +2535,76 @@ string_to_core_addr (const char *my_string)
 char *
 gdb_realpath (const char *filename)
 {
-#ifdef HAVE_REALPATH
+#if defined(HAVE_REALPATH)
+# if defined (PATH_MAX)
   char buf[PATH_MAX];
+#  define USE_REALPATH
+# elif defined (MAXPATHLEN)
+  char buf[MAXPATHLEN];
+#  define USE_REALPATH
+# elif defined (HAVE_UNISTD_H) && defined(HAVE_ALLOCA)
+  char *buf = alloca ((size_t)pathconf ("/", _PC_PATH_MAX));
+#  define USE_REALPATH
+# endif
+#endif /* HAVE_REALPATH */
+
+#if defined(USE_REALPATH)
   char *rp = realpath (filename, buf);
   return xstrdup (rp ? rp : filename);
+#elif defined(HAVE_CANONICALIZE_FILE_NAME)
+  char *rp = canonicalize_file_name (filename);
+  if (rp == NULL)
+    return xstrdup (filename);
+  else
+    return rp;
 #else
   return xstrdup (filename);
 #endif
 }
+
+/* Return a copy of FILENAME, with its directory prefix canonicalized
+   by gdb_realpath.  */
+
+char *
+xfullpath (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 = 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, NULL);
+  else
+    result = concat (real_path, SLASH_STRING, base_name, NULL);
+
+  xfree (real_path);
+  return result;
+}
This page took 0.043317 seconds and 4 git commands to generate.