/* 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.
#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"
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 *,
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)
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)
{
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);
}
/* 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 *),
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);
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
{
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
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
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 */
request_quit (int signo)
{
quit_flag = 1;
- /* Restore the signal handler. Harmless with BSD-style signals, needed
- for System V-style signals. So just always do it, rather than worrying
- about USG defines and stuff like that. */
+ /* Restore the signal handler. Harmless with BSD-style signals,
+ needed for System V-style signals. */
signal (signo, request_quit);
if (immediate_quit)
quit ();
}
\f
-/* Memory management stuff (malloc friends). */
-
-static void *
-mmalloc (void *md, size_t size)
-{
- return malloc (size); /* NOTE: GDB's only call to malloc() */
-}
-
-static void *
-mrealloc (void *md, void *ptr, size_t size)
-{
- if (ptr == 0) /* Guard against old realloc's */
- return mmalloc (md, size);
- else
- return realloc (ptr, size); /* NOTE: GDB's only call to ralloc() */
-}
-
-static void *
-mcalloc (void *md, size_t number, size_t size)
-{
- return calloc (number, size); /* NOTE: GDB's only call to calloc() */
-}
-
-static void
-mfree (void *md, void *ptr)
-{
- free (ptr); /* NOTE: GDB's only call to free() */
-}
-
-/* This used to do something interesting with USE_MMALLOC.
- * It can be retired any time. -- chastain 2004-01-19. */
-void
-init_malloc (void *md)
-{
-}
-
/* Called when a memory allocation fails, with the number of bytes of
memory requested in SIZE. */
}
}
-/* The xmmalloc() family of memory management routines.
+/* The xmalloc() (libiberty.h) family of memory management routines.
- These are are like the mmalloc() family except that they implement
+ These are like the ISO-C malloc() family except that they implement
consistent semantics and guard against typical memory management
- problems: if a malloc fails, an internal error is thrown; if
- free(NULL) is called, it is ignored; if *alloc(0) is called, NULL
- is returned.
+ problems. */
- All these routines are implemented using the mmalloc() family. */
+/* NOTE: These are declared using PTR to ensure consistency with
+ "libiberty.h". xfree() is GDB local. */
-void *
-xmmalloc (void *md, size_t size)
+PTR /* OK: PTR */
+xmalloc (size_t size)
{
void *val;
if (size == 0)
size = 1;
- val = mmalloc (md, size);
+ val = malloc (size); /* OK: malloc */
if (val == NULL)
nomem (size);
return (val);
}
-void *
-xmrealloc (void *md, void *ptr, size_t size)
+PTR /* OK: PTR */
+xrealloc (PTR ptr, size_t size) /* OK: PTR */
{
void *val;
size = 1;
if (ptr != NULL)
- val = mrealloc (md, ptr, size);
+ val = realloc (ptr, size); /* OK: realloc */
else
- val = mmalloc (md, size);
+ val = malloc (size); /* OK: malloc */
if (val == NULL)
nomem (size);
return (val);
}
-void *
-xmcalloc (void *md, size_t number, size_t size)
+PTR /* OK: PTR */
+xcalloc (size_t number, size_t size)
{
void *mem;
size = 1;
}
- mem = mcalloc (md, number, size);
+ mem = calloc (number, size); /* OK: xcalloc */
if (mem == NULL)
nomem (number * size);
return mem;
}
-void
-xmfree (void *md, void *ptr)
-{
- if (ptr != NULL)
- mfree (md, ptr);
-}
-
-/* The xmalloc() (libiberty.h) family of memory management routines.
-
- These are like the ISO-C malloc() family except that they implement
- consistent semantics and guard against typical memory management
- problems. See xmmalloc() above for further information.
-
- All these routines are wrappers to the xmmalloc() family. */
-
-/* NOTE: These are declared using PTR to ensure consistency with
- "libiberty.h". xfree() is GDB local. */
-
-PTR /* OK: PTR */
-xmalloc (size_t size)
-{
- return xmmalloc (NULL, size);
-}
-
-PTR /* OK: PTR */
-xrealloc (PTR ptr, size_t size) /* OK: PTR */
-{
- return xmrealloc (NULL, ptr, size);
-}
-
-PTR /* OK: PTR */
-xcalloc (size_t number, size_t size)
-{
- return xmcalloc (NULL, number, size);
-}
-
void
xfree (void *ptr)
{
- xmfree (NULL, ptr);
+ if (ptr != NULL)
+ free (ptr); /* OK: free */
}
\f
return p;
}
-char *
-msavestring (void *md, const char *ptr, size_t size)
-{
- char *p = (char *) xmmalloc (md, 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)
{
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--;
/* 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)
{
}
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? */
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%lu", sign, temp[0]);
+ sprintf (paddr_str, "%s%0*lu", sign, width, temp[0]);
break;
case 2:
- sprintf (paddr_str, "%s%lu%09lu", sign, temp[1], temp[0]);
+ sprintf (paddr_str, "%s%0*lu%09lu", sign, 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, "%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:
+ 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, "0%0*lo%010lo", width, temp[1], temp[0]);
+ break;
+ case 3:
+ sprintf (paddr_str, "0%0*lo%010lo%010lo", width,
+ temp[2], temp[1], temp[0]);
break;
default:
internal_error (__FILE__, __LINE__,
paddr_u (CORE_ADDR addr)
{
char *paddr_str = get_cell ();
- decimal2str (paddr_str, "", addr);
+ decimal2str (paddr_str, "", addr, 0);
return paddr_str;
}
{
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;
}
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 *