/* 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"
-#ifdef NEED_DECLARATION_MALLOC
+#if !HAVE_DECL_MALLOC
extern PTR malloc (); /* OK: PTR */
#endif
-#ifdef NEED_DECLARATION_REALLOC
+#if !HAVE_DECL_REALLOC
extern PTR realloc (); /* OK: PTR */
#endif
-#ifdef NEED_DECLARATION_FREE
+#if !HAVE_DECL_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
/* readline defines this. */
#undef savestring
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)
void **location = ptr;
if (location == NULL)
internal_error (__FILE__, __LINE__,
- "free_current_contents: NULL pointer");
+ _("free_current_contents: NULL pointer"));
if (*location != NULL)
{
xfree (*location);
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
/* Default (yes/batch case) is to quit GDB. When in batch mode
this lessens the likelhood of GDB going into an infinate
loop. */
- quit_p = query ("%s\nQuit this debugging session? ", reason);
+ quit_p = query (_("%s\nQuit this debugging session? "), reason);
break;
case AUTO_BOOLEAN_TRUE:
quit_p = 1;
quit_p = 0;
break;
default:
- internal_error (__FILE__, __LINE__, "bad switch");
+ internal_error (__FILE__, __LINE__, _("bad switch"));
}
switch (problem->should_dump_core)
/* 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);
break;
break;
case AUTO_BOOLEAN_TRUE:
dump_core_p = 0;
break;
default:
- internal_error (__FILE__, __LINE__, "bad switch");
+ internal_error (__FILE__, __LINE__, _("bad switch"));
}
if (quit_p)
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
bfd_set_error (bfd_error_no_error);
errno = 0;
- error ("%s.", combined);
+ error (_("%s."), combined);
}
/* Print the system error message for ERRCODE, and also mention STRING
void
quit (void)
{
- struct serial *gdb_stdout_serial = serial_fdopen (1);
-
- target_terminal_ours ();
-
- /* We want all output to appear now, before we print "Quit". We
- have 3 levels of buffering we have to flush (it's possible that
- some of these should be changed to flush the lower-level ones
- too): */
-
- /* 1. The _filtered buffer. */
- wrap_here ((char *) 0);
-
- /* 2. The stdio buffer. */
- gdb_flush (gdb_stdout);
- gdb_flush (gdb_stderr);
-
- /* 3. The system-level buffer. */
- serial_drain_output (gdb_stdout_serial);
- serial_un_fdopen (gdb_stdout_serial);
-
- annotate_error_begin ();
-
- /* Don't use *_filtered; we don't want to prompt the user to continue. */
- if (quit_pre_print)
- fputs_unfiltered (quit_pre_print, gdb_stderr);
-
#ifdef __MSDOS__
/* No steenking SIGINT will ever be coming our way when the
program is resumed. Don't lie. */
- fprintf_unfiltered (gdb_stderr, "Quit\n");
+ fatal ("Quit");
#else
if (job_control
/* If there is no terminal switching for this target, then we can't
possibly get screwed by the lack of job control. */
|| current_target.to_terminal_ours == NULL)
- fprintf_unfiltered (gdb_stderr, "Quit\n");
+ fatal ("Quit");
else
- fprintf_unfiltered (gdb_stderr,
- "Quit (expect signal SIGINT when the program is resumed)\n");
+ fatal ("Quit (expect signal SIGINT when the program is resumed)");
#endif
- throw_exception (RETURN_QUIT);
}
/* Control C comes here */
if (size > 0)
{
internal_error (__FILE__, __LINE__,
- "virtual memory exhausted: can't allocate %ld bytes.",
+ _("virtual memory exhausted: can't allocate %ld bytes."),
size);
}
else
{
- internal_error (__FILE__, __LINE__, "virtual memory exhausted.");
+ internal_error (__FILE__, __LINE__, _("virtual memory exhausted."));
}
}
return (val);
}
+void *
+xzalloc (size_t size)
+{
+ return xcalloc (1, size);
+}
+
PTR /* OK: PTR */
xrealloc (PTR ptr, size_t size) /* OK: PTR */
{
should never happen, but just to be sure. */
if (status < 0)
internal_error (__FILE__, __LINE__,
- "vasprintf call failed (errno %d)", errno);
+ _("vasprintf call failed (errno %d)"), errno);
return ret;
}
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)
{
gdb_flush (gdb_stdout);
if (annotation_level > 1)
- printf_filtered ("\n\032\032pre-query\n");
+ printf_filtered (("\n\032\032pre-query\n"));
va_start (args, ctlstr);
vfprintf_filtered (gdb_stdout, ctlstr, args);
va_end (args);
- printf_filtered ("(y or n) ");
+ printf_filtered (_("(y or n) "));
if (annotation_level > 1)
- printf_filtered ("\n\032\032query\n");
+ printf_filtered (("\n\032\032query\n"));
wrap_here ("");
gdb_flush (gdb_stdout);
retval = 0;
break;
}
- printf_filtered ("Please answer y or n.\n");
+ printf_filtered (_("Please answer y or n.\n"));
}
if (annotation_level > 1)
- printf_filtered ("\n\032\032post-query\n");
+ printf_filtered (("\n\032\032post-query\n"));
return retval;
}
\f
gdb_flush (gdb_stdout);
if (annotation_level > 1)
- printf_filtered ("\n\032\032pre-query\n");
+ printf_filtered (("\n\032\032pre-query\n"));
vfprintf_filtered (gdb_stdout, ctlstr, args);
- printf_filtered ("(%s or %s) ", y_string, n_string);
+ printf_filtered (_("(%s or %s) "), y_string, n_string);
if (annotation_level > 1)
- printf_filtered ("\n\032\032query\n");
+ printf_filtered (("\n\032\032query\n"));
wrap_here ("");
gdb_flush (gdb_stdout);
break;
}
/* Invalid entries are not defaulted and require another selection. */
- printf_filtered ("Please answer %s or %s.\n",
+ printf_filtered (_("Please answer %s or %s.\n"),
y_string, n_string);
}
if (annotation_level > 1)
- printf_filtered ("\n\032\032post-query\n");
+ printf_filtered (("\n\032\032post-query\n"));
return retval;
}
\f
memcpy (copy, start, len);
copy[len] = '\0';
- error ("There is no control character `\\%s' in the `%s' character set.",
+ error (_("There is no control character `\\%s' in the `%s' character set."),
copy, target_charset ());
}
c = 0177;
if (!host_char_to_target (c, &target_char))
- error ("There is no character corresponding to `Delete' "
- "in the target character set `%s'.", host_charset ());
+ error (_("There is no character corresponding to `Delete' "
+ "in the target character set `%s'."), host_charset ());
return target_char;
}
char cont_prompt[120];
if (annotation_level > 1)
- printf_unfiltered ("\n\032\032pre-prompt-for-continue\n");
+ printf_unfiltered (("\n\032\032pre-prompt-for-continue\n"));
strcpy (cont_prompt,
"---Type <return> to continue, or q <return> to quit---");
ignore = gdb_readline_wrapper (cont_prompt);
if (annotation_level > 1)
- printf_unfiltered ("\n\032\032post-prompt-for-continue\n");
+ printf_unfiltered (("\n\032\032post-prompt-for-continue\n"));
if (ignore)
{
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--;
{
/* This should have been allocated, but be paranoid anyway. */
if (!wrap_buffer)
- internal_error (__FILE__, __LINE__, "failed internal consistency check");
+ internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
if (wrap_buffer[0])
{
if (xdb_commands)
{
add_com ("am", class_support, pagination_on_command,
- "Enable pagination");
+ _("Enable pagination"));
add_com ("sm", class_support, pagination_off_command,
- "Disable pagination");
+ _("Disable pagination"));
}
deprecated_add_show_from_set
/* 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)
{
return phex_nz (addr, TARGET_ADDR_BIT / 8);
}
+const char *
+paddress (CORE_ADDR addr)
+{
+ /* Truncate address to the size of a target 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. */
+ /* NOTE: This assumes that the significant address information is
+ kept in the least significant bits of ADDR - the upper bits were
+ either zero or sign extended. Should ADDRESS_TO_POINTER() or
+ some ADDRESS_TO_PRINTABLE() be used to do the conversion? */
+
+ int addr_bit = TARGET_ADDR_BIT;
+
+ if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
+ addr &= ((CORE_ADDR) 1 << addr_bit) - 1;
+ return hex_string (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? */
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__,
- "failed internal consistency check");
+ _("failed internal consistency check"));
}
}
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 *
else if (isxdigit (my_string[i]))
addr = (tolower (my_string[i]) - 'a' + 0xa) + (addr * 16);
else
- internal_error (__FILE__, __LINE__, "invalid hex");
+ internal_error (__FILE__, __LINE__, _("invalid hex"));
}
}
else
if (isdigit (my_string[i]))
addr = (my_string[i] - '0') + (addr * 10);
else
- internal_error (__FILE__, __LINE__, "invalid decimal");
+ internal_error (__FILE__, __LINE__, _("invalid decimal"));
}
}
return addr;