2005-01-19 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / utils.c
index e350c25d1af96969e36378aac22614aa67b4b44c..243fc754db6398f470a9693f1c8b9f8857b3958a 100644 (file)
@@ -1,8 +1,8 @@
 /* General utility routines for GDB, the GNU debugger.
 
    Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
-   Foundation, Inc.
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free
+   Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,6 +26,7 @@
 #include <ctype.h>
 #include "gdb_string.h"
 #include "event-top.h"
+#include "exceptions.h"
 
 #ifdef TUI
 #include "tui/tui.h"           /* For tui_get_command_dimension.   */
 #include "charset.h"
 #include "annotate.h"
 #include "filenames.h"
+#include "symfile.h"
 
 #include "inferior.h"          /* for signed_pointer_to_address */
 
 #include <sys/param.h>         /* For MAXPATHLEN */
 
-#ifdef HAVE_CURSES_H
-#include <curses.h>
-#endif
-#ifdef HAVE_TERM_H
-#include <term.h>
-#endif
+#include "gdb_curses.h"
 
 #include "readline/readline.h"
 
@@ -85,10 +82,6 @@ extern char *canonicalize_file_name (const char *);
 
 void (*deprecated_error_begin_hook) (void);
 
-/* Holds the last error message issued by gdb */
-
-static struct ui_file *gdb_lasterr;
-
 /* Prototypes for local functions */
 
 static void vfprintf_maybe_filtered (struct ui_file *, const char *,
@@ -260,6 +253,19 @@ make_cleanup_ui_file_delete (struct ui_file *arg)
   return make_my_cleanup (&cleanup_chain, do_ui_file_delete, arg);
 }
 
+static void
+do_free_section_addr_info (void *arg)
+{
+  free_section_addr_info (arg);
+}
+
+struct cleanup *
+make_cleanup_free_section_addr_info (struct section_addr_info *addrs)
+{
+  return make_my_cleanup (&cleanup_chain, do_free_section_addr_info, addrs);
+}
+
+
 struct cleanup *
 make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
                 void *arg)
@@ -453,7 +459,7 @@ add_continuation (void (*continuation_hook) (struct continuation_arg *),
    before we have a chance of exhausting those that were already
    there. We need to then save the beginning of the list in a pointer
    and do the continuations from there on, instead of using the
-   global beginning of list as our iteration pointer.*/
+   global beginning of list as our iteration pointer.  */
 void
 do_all_continuations (void)
 {
@@ -467,7 +473,7 @@ do_all_continuations (void)
   continuation_ptr = cmd_continuation;
   cmd_continuation = NULL;
 
-  /* Work now on the list we have set aside. */
+  /* Work now on the list we have set aside.  */
   while (continuation_ptr)
     {
       (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
@@ -493,7 +499,8 @@ discard_all_continuations (void)
 }
 
 /* Add a continuation to the continuation list, the global list
-   intermediate_continuation. The new continuation will be added at the front.*/
+   intermediate_continuation.  The new continuation will be added at
+   the front.  */
 void
 add_intermediate_continuation (void (*continuation_hook)
                               (struct continuation_arg *),
@@ -530,7 +537,7 @@ do_all_intermediate_continuations (void)
   continuation_ptr = intermediate_continuation;
   intermediate_continuation = NULL;
 
-  /* Work now on the list we have set aside. */
+  /* Work now on the list we have set aside.  */
   while (continuation_ptr)
     {
       (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
@@ -603,10 +610,7 @@ warning (const char *string, ...)
 NORETURN void
 verror (const char *string, va_list args)
 {
-  struct ui_file *tmp_stream = mem_fileopen ();
-  make_cleanup_ui_file_delete (tmp_stream);
-  vfprintf_unfiltered (tmp_stream, string, args);
-  error_stream (tmp_stream);
+  throw_verror (GENERIC_ERROR, string, args);
 }
 
 NORETURN void
@@ -614,86 +618,36 @@ error (const char *string, ...)
 {
   va_list args;
   va_start (args, string);
-  verror (string, args);
+  throw_verror (GENERIC_ERROR, string, args);
   va_end (args);
 }
 
-static void
-do_write (void *data, const char *buffer, long length_buffer)
+/* Print an error message and quit.
+   The first argument STRING is the error message, used as a fprintf string,
+   and the remaining args are passed as arguments to it.  */
+
+NORETURN void
+vfatal (const char *string, va_list args)
 {
-  ui_file_write (data, buffer, length_buffer);
+  throw_vfatal (string, args);
 }
 
-/* Cause a silent error to occur.  Any error message is recorded
-   though it is not issued.  */
 NORETURN void
-error_silent (const char *string, ...)
+fatal (const char *string, ...)
 {
   va_list args;
-  struct ui_file *tmp_stream = mem_fileopen ();
   va_start (args, string);
-  make_cleanup_ui_file_delete (tmp_stream);
-  vfprintf_unfiltered (tmp_stream, string, args);
-  /* Copy the stream into the GDB_LASTERR buffer.  */
-  ui_file_rewind (gdb_lasterr);
-  ui_file_put (tmp_stream, do_write, gdb_lasterr);
+  throw_vfatal (string, args);
   va_end (args);
-
-  throw_exception (RETURN_ERROR);
-}
-
-/* Output an error message including any pre-print text to gdb_stderr.  */
-void
-error_output_message (char *pre_print, char *msg)
-{
-  target_terminal_ours ();
-  wrap_here ("");              /* Force out any buffered output */
-  gdb_flush (gdb_stdout);
-  annotate_error_begin ();
-  if (pre_print)
-    fputs_filtered (pre_print, gdb_stderr);
-  fputs_filtered (msg, gdb_stderr);
-  fprintf_filtered (gdb_stderr, "\n");
 }
 
 NORETURN void
 error_stream (struct ui_file *stream)
-{
-  if (deprecated_error_begin_hook)
-    deprecated_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)
-    fputs_filtered (error_pre_print, gdb_stderr);
-  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 */
-
-char *
-error_last_message (void)
 {
   long len;
-  return ui_file_xstrdup (gdb_lasterr, &len);
-}
-
-/* This is to be called by main() at the very beginning */
-
-void
-error_init (void)
-{
-  gdb_lasterr = mem_fileopen ();
+  char *message = ui_file_xstrdup (stream, &len);
+  make_cleanup (xfree, message);
+  error ("%s", message);
 }
 
 /* Print a message reporting an internal error/warning. Ask the user
@@ -825,7 +779,7 @@ NORETURN void
 internal_verror (const char *file, int line, const char *fmt, va_list ap)
 {
   internal_vproblem (&internal_error_problem, file, line, fmt, ap);
-  throw_exception (RETURN_ERROR);
+  deprecated_throw_reason (RETURN_ERROR);
 }
 
 NORETURN void
@@ -966,7 +920,7 @@ quit (void)
     fprintf_unfiltered (gdb_stderr,
                        "Quit (expect signal SIGINT when the program is resumed)\n");
 #endif
-  throw_exception (RETURN_QUIT);
+  deprecated_throw_reason (RETURN_QUIT);
 }
 
 /* Control C comes here */
@@ -1154,21 +1108,6 @@ savestring (const char *ptr, size_t size)
   return p;
 }
 
-char *
-msavestring (void *md, const char *ptr, size_t size)
-{
-  char *p = (char *) xmalloc (size + 1);
-  memcpy (p, ptr, size);
-  p[size] = 0;
-  return p;
-}
-
-char *
-mstrsave (void *md, const char *ptr)
-{
-  return (msavestring (md, ptr, strlen (ptr)));
-}
-
 void
 print_spaces (int n, struct ui_file *file)
 {
@@ -1788,12 +1727,7 @@ prompt_for_continue (void)
       while (*p == ' ' || *p == '\t')
        ++p;
       if (p[0] == 'q')
-       {
-         if (!event_loop_p)
-           request_quit (SIGINT);
-         else
-           async_request_quit (0);
-       }
+       async_request_quit (0);
       xfree (ignore);
     }
   immediate_quit--;
@@ -2592,7 +2526,7 @@ SIGWINCH_HANDLER_BODY
 /* print routines to handle variable size regs, etc. */
 /* temporary storage using circular buffer */
 #define NUMCELLS 16
-#define CELLSIZE 32
+#define CELLSIZE 50
 static char *
 get_cell (void)
 {
@@ -2622,7 +2556,7 @@ paddr_nz (CORE_ADDR addr)
 }
 
 static void
-decimal2str (char *paddr_str, char *sign, ULONGEST addr)
+decimal2str (char *paddr_str, char *sign, ULONGEST addr, int width)
 {
   /* steal code from valprint.c:print_decimal().  Should this worry
      about the real size of addr as the above does? */
@@ -2633,18 +2567,60 @@ decimal2str (char *paddr_str, char *sign, ULONGEST addr)
       temp[i] = addr % (1000 * 1000 * 1000);
       addr /= (1000 * 1000 * 1000);
       i++;
+      width -= 9;
+    }
+  while (addr != 0 && i < (sizeof (temp) / sizeof (temp[0])));
+  width += 9;
+  if (width < 0)
+    width = 0;
+  switch (i)
+    {
+    case 1:
+      sprintf (paddr_str, "%s%0*lu", sign, width, temp[0]);
+      break;
+    case 2:
+      sprintf (paddr_str, "%s%0*lu%09lu", sign, width, temp[1], temp[0]);
+      break;
+    case 3:
+      sprintf (paddr_str, "%s%0*lu%09lu%09lu", sign, width,
+              temp[2], temp[1], temp[0]);
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+                     "failed internal consistency check");
+    }
+}
+
+static void
+octal2str (char *paddr_str, ULONGEST addr, int width)
+{
+  unsigned long temp[3];
+  int i = 0;
+  do
+    {
+      temp[i] = addr % (0100000 * 0100000);
+      addr /= (0100000 * 0100000);
+      i++;
+      width -= 10;
     }
   while (addr != 0 && i < (sizeof (temp) / sizeof (temp[0])));
+  width += 10;
+  if (width < 0)
+    width = 0;
   switch (i)
     {
     case 1:
-      sprintf (paddr_str, "%s%lu", sign, temp[0]);
+      if (temp[0] == 0)
+       sprintf (paddr_str, "%*o", width, 0);
+      else
+       sprintf (paddr_str, "0%0*lo", width, temp[0]);
       break;
     case 2:
-      sprintf (paddr_str, "%s%lu%09lu", sign, temp[1], temp[0]);
+      sprintf (paddr_str, "0%0*lo%010lo", width, temp[1], temp[0]);
       break;
     case 3:
-      sprintf (paddr_str, "%s%lu%09lu%09lu", sign, temp[2], temp[1], temp[0]);
+      sprintf (paddr_str, "0%0*lo%010lo%010lo", width,
+              temp[2], temp[1], temp[0]);
       break;
     default:
       internal_error (__FILE__, __LINE__,
@@ -2656,7 +2632,7 @@ char *
 paddr_u (CORE_ADDR addr)
 {
   char *paddr_str = get_cell ();
-  decimal2str (paddr_str, "", addr);
+  decimal2str (paddr_str, "", addr, 0);
   return paddr_str;
 }
 
@@ -2665,9 +2641,9 @@ paddr_d (LONGEST addr)
 {
   char *paddr_str = get_cell ();
   if (addr < 0)
-    decimal2str (paddr_str, "-", -addr);
+    decimal2str (paddr_str, "-", -addr, 0);
   else
-    decimal2str (paddr_str, "", addr);
+    decimal2str (paddr_str, "", addr, 0);
   return paddr_str;
 }
 
@@ -2732,6 +2708,87 @@ phex_nz (ULONGEST l, int sizeof_l)
   return str;
 }
 
+/* Converts a LONGEST to a C-format hexadecimal literal and stores it
+   in a static string.  Returns a pointer to this string.  */
+char *
+hex_string (LONGEST num)
+{
+  char *result = get_cell ();
+  snprintf (result, CELLSIZE, "0x%s", phex_nz (num, sizeof (num)));
+  return result;
+}
+
+/* Converts a LONGEST number to a C-format hexadecimal literal and
+   stores it in a static string.  Returns a pointer to this string
+   that is valid until the next call.  The number is padded on the
+   left with 0s to at least WIDTH characters.  */
+char *
+hex_string_custom (LONGEST num, int width)
+{
+  char *result = get_cell ();
+  char *result_end = result + CELLSIZE - 1;
+  const char *hex = phex_nz (num, sizeof (num));
+  int hex_len = strlen (hex);
+
+  if (hex_len > width)
+    width = hex_len;
+  if (width + 2 >= CELLSIZE)
+    internal_error (__FILE__, __LINE__,
+                   "hex_string_custom: insufficient space to store result");
+
+  strcpy (result_end - width - 2, "0x");
+  memset (result_end - width, '0', width);
+  strcpy (result_end - hex_len, hex);
+  return result_end - width - 2;
+}
+
+/* Convert VAL to a numeral in the given radix.  For
+ * radix 10, IS_SIGNED may be true, indicating a signed quantity;
+ * otherwise VAL is interpreted as unsigned.  If WIDTH is supplied, 
+ * it is the minimum width (0-padded if needed).  USE_C_FORMAT means
+ * to use C format in all cases.  If it is false, then 'x' 
+ * and 'o' formats do not include a prefix (0x or leading 0). */
+
+char *
+int_string (LONGEST val, int radix, int is_signed, int width, 
+           int use_c_format)
+{
+  switch (radix) 
+    {
+    case 16:
+      {
+       char *result;
+       if (width == 0)
+         result = hex_string (val);
+       else
+         result = hex_string_custom (val, width);
+       if (! use_c_format)
+         result += 2;
+       return result;
+      }
+    case 10:
+      {
+       char *result = get_cell ();
+       if (is_signed && val < 0)
+         decimal2str (result, "-", -val, width);
+       else
+         decimal2str (result, "", val, width);
+       return result;
+      }
+    case 8:
+      {
+       char *result = get_cell ();
+       octal2str (result, val, width);
+       if (use_c_format || val == 0)
+         return result;
+       else
+         return result + 1;
+      }
+    default:
+      internal_error (__FILE__, __LINE__,
+                     "failed internal consistency check");
+    }
+}      
 
 /* Convert a CORE_ADDR into a string.  */
 const char *
This page took 0.030325 seconds and 4 git commands to generate.