#include "defs.h"
#include "gdb_assert.h"
#include <ctype.h>
#include "gdb_string.h"
#include "event-top.h"
#include "exceptions.h"
#include "macosx-self-backtrace.h"
#ifdef TUI
#include "tui/tui.h"
#endif
#ifdef __GO32__
#include <pc.h>
#endif
#ifdef reg
#undef reg
#endif
#include <signal.h>
#include "gdbcmd.h"
#include "serial.h"
#include "bfd.h"
#include "target.h"
#include "demangle.h"
#include "expression.h"
#include "language.h"
#include "charset.h"
#include "annotate.h"
#include "filenames.h"
#include "symfile.h"
#include "inferior.h"
#include <sys/param.h>
#include "gdb_curses.h"
#include "readline/readline.h"
#ifdef USE_MMALLOC
#include "mmalloc.h"
#endif
#if !HAVE_DECL_MALLOC
extern PTR malloc ();
#endif
#if !HAVE_DECL_REALLOC
extern PTR realloc ();
#endif
#if !HAVE_DECL_FREE
extern void free ();
#endif
#undef savestring
void (*deprecated_error_begin_hook) (void);
static struct ui_file *gdb_lasterr;
static void vfprintf_maybe_filtered (struct ui_file *, const char *,
va_list, int) ATTR_FORMAT (printf, 2, 0);
static void fputs_maybe_filtered (const char *, struct ui_file *, int);
static void do_my_cleanups (struct cleanup **, struct cleanup *);
static void prompt_for_continue (void);
static void set_width_command (char *, int, struct cmd_list_element *);
static struct cleanup *cleanup_chain;
static struct cleanup *final_cleanup_chain;
static struct cleanup *run_cleanup_chain;
static struct cleanup *exec_cleanup_chain;
static struct cleanup *exec_error_cleanup_chain;
struct continuation *cmd_continuation;
struct continuation *intermediate_continuation;
int job_control;
int quit_flag;
int immediate_quit;
int demangle = 1;
static void
show_demangle (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Demangling of encoded C++/ObjC names when displaying symbols is %s.\n"),
value);
}
int asm_demangle = 0;
static void
show_asm_demangle (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Demangling of C++/ObjC names in disassembly listings is %s.\n"),
value);
}
int sevenbit_strings = 0;
static void
show_sevenbit_strings (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Printing of 8-bit characters in strings as \\nnn is %s.\n"),
value);
}
char *error_pre_print;
char *quit_pre_print;
char *warning_pre_print = "\nwarning: ";
int pagination_enabled = 1;
static void
show_pagination_enabled (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("State of pagination is %s.\n"), value);
}
struct cleanup *
make_cleanup (make_cleanup_ftype *function, void *arg)
{
return make_my_cleanup (&cleanup_chain, function, arg);
}
struct cleanup *
make_final_cleanup (make_cleanup_ftype *function, void *arg)
{
return make_my_cleanup (&final_cleanup_chain, function, arg);
}
struct cleanup *
make_run_cleanup (make_cleanup_ftype *function, void *arg)
{
return make_my_cleanup (&run_cleanup_chain, function, arg);
}
struct cleanup *
make_exec_cleanup (make_cleanup_ftype *function, void *arg)
{
return make_my_cleanup (&exec_cleanup_chain, function, arg);
}
struct cleanup *
make_exec_error_cleanup (make_cleanup_ftype *function, void *arg)
{
return make_my_cleanup (&exec_error_cleanup_chain, function, arg);
}
static void
do_freeargv (void *arg)
{
freeargv ((char **) arg);
}
struct cleanup *
make_cleanup_freeargv (char **arg)
{
return make_my_cleanup (&cleanup_chain, do_freeargv, arg);
}
static void
do_bfd_close_cleanup (void *arg)
{
bfd_close (arg);
}
struct cleanup *
make_cleanup_bfd_close (bfd *abfd)
{
return make_cleanup (do_bfd_close_cleanup, abfd);
}
static void
do_close_cleanup (void *arg)
{
int *fd = arg;
close (*fd);
xfree (fd);
}
struct cleanup *
make_cleanup_close (int fd)
{
int *saved_fd = xmalloc (sizeof (fd));
*saved_fd = fd;
return make_cleanup (do_close_cleanup, saved_fd);
}
static void
do_ui_file_delete (void *arg)
{
ui_file_delete (arg);
}
struct cleanup *
make_cleanup_ui_file_delete (struct ui_file *arg)
{
return make_my_cleanup (&cleanup_chain, do_ui_file_delete, arg);
}
static void
do_ui_out_delete (void *arg)
{
ui_out_delete (arg);
}
struct cleanup *
make_cleanup_ui_out_delete (struct ui_out *arg)
{
return make_my_cleanup (&cleanup_chain, do_ui_out_delete, arg);
}
static void
do_restore_uiout_cleanup (void *arg)
{
uiout = (struct ui_out *) arg;
}
static void
do_free_section_addr_info (void *arg)
{
free_section_addr_info (arg);
}
struct cleanup *
make_cleanup_restore_uiout (struct ui_out *old_uiout)
{
return make_my_cleanup (&cleanup_chain, do_restore_uiout_cleanup, old_uiout);
}
static void
do_set_schedlock_mode (void *in_mode)
{
enum scheduler_locking_mode mode = (enum scheduler_locking_mode) in_mode;
set_scheduler_locking_mode (mode);
}
struct cleanup *
make_cleanup_set_restore_scheduler_locking_mode (enum scheduler_locking_mode new_mode)
{
enum scheduler_locking_mode old_mode = set_scheduler_locking_mode (new_mode);
return make_my_cleanup (&cleanup_chain, do_set_schedlock_mode, (void *) old_mode);
}
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)
{
struct cleanup *new;
struct cleanup *old_chain = *pmy_chain;
if (!function)
internal_error (__FILE__, __LINE__,
"Someone tried to put a null function on the cleanup chain!");
new = (struct cleanup *) xmalloc (sizeof (struct cleanup));
new->next = *pmy_chain;
new->function = function;
new->arg = arg;
*pmy_chain = new;
return old_chain;
}
void
do_cleanups (struct cleanup *old_chain)
{
do_my_cleanups (&cleanup_chain, old_chain);
}
void
do_final_cleanups (struct cleanup *old_chain)
{
do_my_cleanups (&final_cleanup_chain, old_chain);
}
void
do_run_cleanups (struct cleanup *old_chain)
{
do_my_cleanups (&run_cleanup_chain, old_chain);
}
void
do_exec_cleanups (struct cleanup *old_chain)
{
if (exec_cleanup_chain == NULL)
return;
do_my_cleanups (&exec_cleanup_chain, old_chain);
}
void
do_exec_error_cleanups (struct cleanup *old_chain)
{
do_my_cleanups (&exec_error_cleanup_chain, old_chain);
}
static void
do_my_cleanups (struct cleanup **pmy_chain,
struct cleanup *old_chain)
{
struct cleanup *ptr;
while ((ptr = *pmy_chain) != old_chain)
{
*pmy_chain = ptr->next;
(*ptr->function) (ptr->arg);
xfree (ptr);
}
}
void
discard_cleanups (struct cleanup *old_chain)
{
discard_my_cleanups (&cleanup_chain, old_chain);
}
void
discard_final_cleanups (struct cleanup *old_chain)
{
discard_my_cleanups (&final_cleanup_chain, old_chain);
}
void
discard_exec_error_cleanups (struct cleanup *old_chain)
{
discard_my_cleanups (&exec_error_cleanup_chain, old_chain);
}
void
discard_my_cleanups (struct cleanup **pmy_chain,
struct cleanup *old_chain)
{
struct cleanup *ptr;
while ((ptr = *pmy_chain) != old_chain)
{
*pmy_chain = ptr->next;
xfree (ptr);
}
}
struct cleanup *
save_cleanups (void)
{
return save_my_cleanups (&cleanup_chain);
}
struct cleanup *
save_final_cleanups (void)
{
return save_my_cleanups (&final_cleanup_chain);
}
struct cleanup *
save_my_cleanups (struct cleanup **pmy_chain)
{
struct cleanup *old_chain = *pmy_chain;
*pmy_chain = 0;
return old_chain;
}
void
restore_cleanups (struct cleanup *chain)
{
restore_my_cleanups (&cleanup_chain, chain);
}
void
restore_final_cleanups (struct cleanup *chain)
{
restore_my_cleanups (&final_cleanup_chain, chain);
}
void
restore_my_cleanups (struct cleanup **pmy_chain, struct cleanup *chain)
{
*pmy_chain = chain;
}
void
free_current_contents (void *ptr)
{
void **location = ptr;
if (location == NULL)
internal_error (__FILE__, __LINE__,
_("free_current_contents: NULL pointer"));
if (*location != NULL)
{
xfree (*location);
*location = NULL;
}
}
void
null_cleanup (void *arg)
{
}
void
add_continuation (void (*continuation_hook) (struct continuation_arg *),
struct continuation_arg *arg_list)
{
struct continuation *continuation_ptr;
continuation_ptr =
(struct continuation *) xmalloc (sizeof (struct continuation));
continuation_ptr->continuation_hook = continuation_hook;
continuation_ptr->arg_list = arg_list;
continuation_ptr->next = cmd_continuation;
cmd_continuation = continuation_ptr;
}
void
do_all_continuations (void)
{
struct continuation *continuation_ptr;
struct continuation *saved_continuation;
continuation_ptr = cmd_continuation;
cmd_continuation = NULL;
while (continuation_ptr)
{
(continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
saved_continuation = continuation_ptr;
continuation_ptr = continuation_ptr->next;
xfree (saved_continuation);
}
}
void
discard_all_continuations (void)
{
struct continuation *continuation_ptr;
while (cmd_continuation)
{
continuation_ptr = cmd_continuation;
cmd_continuation = continuation_ptr->next;
xfree (continuation_ptr);
}
}
void
add_intermediate_continuation (void (*continuation_hook)
(struct continuation_arg *),
struct continuation_arg *arg_list)
{
struct continuation *continuation_ptr;
continuation_ptr =
(struct continuation *) xmalloc (sizeof (struct continuation));
continuation_ptr->continuation_hook = continuation_hook;
continuation_ptr->arg_list = arg_list;
continuation_ptr->next = intermediate_continuation;
intermediate_continuation = continuation_ptr;
}
void
do_all_intermediate_continuations (void)
{
struct continuation *continuation_ptr;
struct continuation *saved_continuation;
continuation_ptr = intermediate_continuation;
intermediate_continuation = NULL;
while (continuation_ptr)
{
(continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
saved_continuation = continuation_ptr;
continuation_ptr = continuation_ptr->next;
xfree (saved_continuation);
}
}
void
discard_all_intermediate_continuations (void)
{
struct continuation *continuation_ptr;
while (intermediate_continuation)
{
continuation_ptr = intermediate_continuation;
intermediate_continuation = continuation_ptr->next;
xfree (continuation_ptr);
}
}
void
vwarning (const char *string, va_list args)
{
if (deprecated_warning_hook)
(*deprecated_warning_hook) (string, args);
else
{
target_terminal_ours ();
wrap_here ("");
gdb_flush (gdb_stdout);
if (warning_pre_print)
fputs_unfiltered (warning_pre_print, gdb_stderr);
vfprintf_unfiltered (gdb_stderr, string, args);
fprintf_unfiltered (gdb_stderr, "\n");
va_end (args);
}
}
void
warning (const char *string, ...)
{
va_list args;
va_start (args, string);
vwarning (string, args);
va_end (args);
}
NORETURN void
verror (const char *string, va_list args)
{
throw_verror (GENERIC_ERROR, string, args);
}
NORETURN void
error (const char *string, ...)
{
va_list args;
va_start (args, string);
throw_verror (GENERIC_ERROR, string, args);
va_end (args);
}
NORETURN void
vfatal (const char *string, va_list args)
{
throw_vfatal (string, args);
}
NORETURN void
fatal (const char *string, ...)
{
va_list args;
va_start (args, string);
throw_vfatal (string, args);
va_end (args);
}
NORETURN void
error_stream (struct ui_file *stream)
{
long len;
char *message = ui_file_xstrdup (stream, &len);
make_cleanup (xfree, message);
error (("%s"), message);
}
struct internal_problem
{
const char *name;
enum auto_boolean should_quit;
enum auto_boolean should_dump_core;
};
static void ATTR_FORMAT (printf, 4, 0)
internal_vproblem (struct internal_problem *problem,
const char *file, int line, const char *fmt, va_list ap)
{
static int dejavu;
int quit_p;
int dump_core_p;
char *reason;
{
static char msg[] = "Recursive internal problem.\n";
switch (dejavu)
{
case 0:
dejavu = 1;
break;
case 1:
dejavu = 2;
fputs_unfiltered (msg, gdb_stderr);
abort ();
default:
dejavu = 3;
write (STDERR_FILENO, msg, sizeof (msg));
exit (1);
}
}
if (! gdb_stderr) {
fprintf (stderr, "gdb-internal-error: ");
vfprintf (stderr, fmt, ap);
fputs ("\n", stderr);
abort ();
}
target_terminal_ours ();
begin_line ();
{
void *bt_buffer[15];
int count = gdb_self_backtrace (bt_buffer, 15);
fprintf (stderr, "gdb stack crawl at point of internal error:\n");
gdb_self_backtrace_symbols_fd (bt_buffer, count, STDERR_FILENO, 2, 14);
}
{
char *msg;
msg = xstrvprintf (fmt, ap);
reason = xstrprintf ("\
%s:%d: %s: %s\n\
A problem internal to GDB has been detected,\n\
further debugging may prove unreliable.", file, line, problem->name, msg);
xfree (msg);
make_cleanup (xfree, reason);
}
switch (problem->should_quit)
{
case AUTO_BOOLEAN_AUTO:
quit_p = query (_("%s\nQuit this debugging session? "), reason);
break;
case AUTO_BOOLEAN_TRUE:
quit_p = 1;
break;
case AUTO_BOOLEAN_FALSE:
quit_p = 0;
break;
default:
internal_error (__FILE__, __LINE__, _("bad switch"));
}
switch (problem->should_dump_core)
{
case AUTO_BOOLEAN_AUTO:
dump_core_p = query (_("%s\nCreate a core file of GDB? "), reason);
break;
break;
case AUTO_BOOLEAN_TRUE:
dump_core_p = 1;
break;
case AUTO_BOOLEAN_FALSE:
dump_core_p = 0;
break;
default:
internal_error (__FILE__, __LINE__, _("bad switch"));
}
if (quit_p)
{
if (dump_core_p)
abort ();
else
{
if (quit_p == 2)
printf_filtered ("%s\n",reason);
exit (1);
}
}
else
{
if (dump_core_p)
{
#ifdef HAVE_WORKING_FORK
if (fork () == 0)
abort ();
#endif
}
}
dejavu = 0;
}
static struct internal_problem internal_error_problem = {
"internal-error", AUTO_BOOLEAN_AUTO, AUTO_BOOLEAN_FALSE
};
NORETURN void
internal_verror (const char *file, int line, const char *fmt, va_list ap)
{
internal_vproblem (&internal_error_problem, file, line, fmt, ap);
deprecated_throw_reason (RETURN_ERROR);
}
NORETURN void
internal_error (const char *file, int line, const char *string, ...)
{
va_list ap;
va_start (ap, string);
internal_verror (file, line, string, ap);
va_end (ap);
}
static struct internal_problem internal_warning_problem = {
"internal-error", AUTO_BOOLEAN_AUTO, AUTO_BOOLEAN_FALSE
};
void
internal_vwarning (const char *file, int line, const char *fmt, va_list ap)
{
internal_vproblem (&internal_warning_problem, file, line, fmt, ap);
}
void
internal_warning (const char *file, int line, const char *string, ...)
{
va_list ap;
va_start (ap, string);
internal_vwarning (file, line, string, ap);
va_end (ap);
}
char *
safe_strerror (int errnum)
{
char *msg;
msg = strerror (errnum);
if (msg == NULL)
{
static char buf[32];
xsnprintf (buf, sizeof buf, "(undocumented errno %d)", errnum);
msg = buf;
}
return (msg);
}
NORETURN void
perror_with_name (const char *string)
{
char *err;
char *combined;
err = safe_strerror (errno);
combined = (char *) alloca (strlen (err) + strlen (string) + 3);
strcpy (combined, string);
strcat (combined, ": ");
strcat (combined, err);
bfd_set_error (bfd_error_no_error);
errno = 0;
error (_("%s."), combined);
}
void
print_sys_errmsg (const char *string, int errcode)
{
char *err;
char *combined;
err = safe_strerror (errcode);
combined = (char *) alloca (strlen (err) + strlen (string) + 3);
strcpy (combined, string);
strcat (combined, ": ");
strcat (combined, err);
gdb_flush (gdb_stdout);
fprintf_unfiltered (gdb_stderr, "%s.\n", combined);
}
void
quit (void)
{
#ifdef __MSDOS__
fatal ("Quit");
#else
if (job_control
|| current_target.to_terminal_ours == NULL)
fatal ("Quit");
else
fatal ("Quit (expect signal SIGINT when the program is resumed)");
#endif
}
void
request_quit (int signo)
{
quit_flag = 1;
signal (signo, request_quit);
if (immediate_quit)
quit ();
}
#if !defined (USE_MMALLOC)
static void *
mmalloc (void *md, size_t size)
{
return malloc (size);
}
static void *
mrealloc (void *md, void *ptr, size_t size)
{
if (ptr == 0)
return mmalloc (md, size);
else
return realloc (ptr, size);
}
static void *
mcalloc (void *md, size_t number, size_t size)
{
return calloc (number, size);
}
static void
mfree (void *md, void *ptr)
{
free (ptr);
}
#endif
#if !defined (USE_MMALLOC)
void *
init_malloc (void *md)
{
return md;
}
#else
void *
init_malloc (void *md)
{
return mmalloc_check_create (md);
}
void
init_mmalloc_default_pool (void *md)
{
char *s;
s = getenv ("GDB_ENABLE_PAGECHECK");
if (s != NULL)
md = mmalloc_pagecheck_create ();
else
md = mmalloc_malloc_create ();
if (md == NULL)
internal_error (__FILE__, __LINE__, "unable to create default mmalloc allocator");
s = getenv ("GDB_ENABLE_MMALLOC_CHECK");
if (s != NULL)
{
md = mmalloc_check_create (md);
if (md == NULL)
internal_error (__FILE__, __LINE__, "unable to add error-checking to default mmalloc allocator");
}
mmalloc_set_default_allocator (md);
}
#endif
NORETURN void
nomem (long size)
{
if (size > 0)
{
internal_error (__FILE__, __LINE__,
_("virtual memory exhausted: can't allocate %ld bytes."),
size);
}
else
{
internal_error (__FILE__, __LINE__, _("virtual memory exhausted."));
}
}
void *
xmmalloc (void *md, size_t size)
{
void *val;
if (size == 0)
size = 1;
val = mmalloc (md, size);
if (val == NULL)
nomem (size);
return (val);
}
void *
xmrealloc (void *md, void *ptr, size_t size)
{
void *val;
if (size == 0)
size = 1;
if (ptr != NULL)
val = mrealloc (md, ptr, size);
else
val = mmalloc (md, size);
if (val == NULL)
nomem (size);
return (val);
}
void *
xmcalloc (void *md, size_t number, size_t size)
{
void *mem;
if (number == 0 || size == 0)
{
number = 1;
size = 1;
}
mem = mcalloc (md, number, size);
if (mem == NULL)
nomem (number * size);
return mem;
}
void
xmfree (void *md, void *ptr)
{
if (ptr != NULL)
mfree (md, ptr);
}
PTR
xmalloc (size_t size)
{
void *val;
if (size == 0)
size = 1;
val = malloc (size);
if (val == NULL)
nomem (size);
return (val);
}
void *
xzalloc (size_t size)
{
return xcalloc (1, size);
}
PTR
xrealloc (PTR ptr, size_t size)
{
void *val;
if (size == 0)
size = 1;
if (ptr != NULL)
val = realloc (ptr, size);
else
val = malloc (size);
if (val == NULL)
nomem (size);
return (val);
}
PTR
xcalloc (size_t number, size_t size)
{
void *mem;
if (number == 0 || size == 0)
{
number = 1;
size = 1;
}
mem = calloc (number, size);
if (mem == NULL)
nomem (number * size);
return mem;
}
void
xfree (void *ptr)
{
if (ptr != NULL)
free (ptr);
}
PTR
gmalloc (size_t size)
{
return xmmalloc (NULL, size);
}
PTR
grealloc (PTR ptr, size_t size)
{
return xmrealloc (NULL, ptr, size);
}
PTR
gcalloc (size_t number, size_t size)
{
return xmcalloc (NULL, number, size);
}
void
gfree (void *ptr)
{
xmfree (NULL, ptr);
}
char *
xstrprintf (const char *format, ...)
{
char *ret;
va_list args;
va_start (args, format);
ret = xstrvprintf (format, args);
va_end (args);
return ret;
}
void
xasprintf (char **ret, const char *format, ...)
{
va_list args;
va_start (args, format);
(*ret) = xstrvprintf (format, args);
va_end (args);
}
void
xvasprintf (char **ret, const char *format, va_list ap)
{
char *tmp;
int status = vasprintf (ret, format, ap);
if ((*ret) == NULL)
internal_error (__FILE__, __LINE__,
"vasprintf returned NULL buffer (errno %d)", errno);
(*ret) = xstrvprintf (format, ap);
}
char *
xstrvprintf (const char *format, va_list ap)
{
char *ret = NULL;
int status = vasprintf (&ret, format, ap);
if (ret == NULL)
nomem (0);
if (status < 0)
internal_error (__FILE__, __LINE__,
_("vasprintf call failed (errno %d)"), errno);
return ret;
}
int
xsnprintf (char *str, size_t size, const char *format, ...)
{
va_list args;
int ret;
va_start (args, format);
ret = vsnprintf (str, size, format, args);
gdb_assert (ret < size);
va_end (args);
return ret;
}
int
myread (int desc, char *addr, int len)
{
int val;
int orglen = len;
while (len > 0)
{
val = read (desc, addr, len);
if (val < 0)
return val;
if (val == 0)
return orglen - len;
len -= val;
addr += val;
}
return orglen;
}
char *
savestring (const char *ptr, size_t size)
{
char *p = (char *) xmalloc (size + 1);
memcpy (p, ptr, size);
p[size] = 0;
return p;
}
void
print_spaces (int n, struct ui_file *file)
{
fputs_unfiltered (n_spaces (n), file);
}
void
gdb_print_host_address (const void *addr, struct ui_file *stream)
{
fprintf_filtered (stream, "0x%lx", (unsigned long) addr);
}
int
query (const char *ctlstr, ...)
{
va_list args;
int answer;
int ans2;
int retval;
if (deprecated_query_hook)
{
va_start (args, ctlstr);
return deprecated_query_hook (ctlstr, args);
}
if (!input_from_terminal_p ())
return 2;
while (1)
{
wrap_here ("");
gdb_flush (gdb_stdout);
if (annotation_level > 1)
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) "));
if (annotation_level > 1)
printf_filtered (("\n\032\032query\n"));
wrap_here ("");
gdb_flush (gdb_stdout);
answer = fgetc (stdin);
clearerr (stdin);
if (answer == EOF)
{
retval = 1;
break;
}
if (answer != '\n')
do
{
ans2 = fgetc (stdin);
clearerr (stdin);
}
while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
if (answer >= 'a')
answer -= 040;
if (answer == 'Y')
{
retval = 1;
break;
}
if (answer == 'N')
{
retval = 0;
break;
}
printf_filtered (_("Please answer y or n.\n"));
}
quit_flag = 0;
if (annotation_level > 1)
printf_filtered (("\n\032\032post-query\n"));
return retval;
}
static int ATTR_FORMAT (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;
if (defchar == 'y')
{
def_value = 1;
def_answer = 'Y';
not_def_answer = 'N';
y_string = "[y]";
n_string = "n";
}
else
{
def_value = 0;
def_answer = 'N';
not_def_answer = 'Y';
y_string = "y";
n_string = "[n]";
}
if (deprecated_query_hook)
{
return deprecated_query_hook (ctlstr, args);
}
if (!input_from_terminal_p ())
return def_value;
while (1)
{
wrap_here ("");
gdb_flush (gdb_stdout);
if (annotation_level > 1)
printf_filtered (("\n\032\032pre-query\n"));
vfprintf_filtered (gdb_stdout, ctlstr, args);
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);
answer = fgetc (stdin);
clearerr (stdin);
if (answer == EOF)
{
retval = def_value;
break;
}
if (answer != '\n')
do
{
ans2 = fgetc (stdin);
clearerr (stdin);
}
while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
if (answer >= 'a')
answer -= 040;
if (answer == not_def_answer)
{
retval = !def_value;
break;
}
if (answer == def_answer || answer == '\n' ||
answer == '\r' || answer == EOF)
{
retval = def_value;
break;
}
printf_filtered (_("Please answer %s or %s.\n"),
y_string, n_string);
}
if (annotation_level > 1)
printf_filtered (("\n\032\032post-query\n"));
return retval;
}
int
nquery (const char *ctlstr, ...)
{
va_list args;
va_start (args, ctlstr);
return defaulted_query (ctlstr, 'n', args);
va_end (args);
}
int
yquery (const char *ctlstr, ...)
{
va_list args;
va_start (args, ctlstr);
return defaulted_query (ctlstr, 'y', args);
va_end (args);
}
static NORETURN int
no_control_char_error (const char *start, const char *end)
{
int len = end - start;
char *copy = alloca (end - start + 1);
memcpy (copy, start, len);
copy[len] = '\0';
error (_("There is no control character `\\%s' in the `%s' character set."),
copy, target_charset ());
}
int
parse_escape (char **string_ptr)
{
int target_char;
int c = *(*string_ptr)++;
if (c_parse_backslash (c, &target_char))
return target_char;
else
switch (c)
{
case '\n':
return -2;
case 0:
(*string_ptr)--;
return 0;
case '^':
{
char *sequence_start_pos = *string_ptr - 1;
c = *(*string_ptr)++;
if (c == '?')
{
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 ());
return target_char;
}
else if (c == '\\')
target_char = parse_escape (string_ptr);
else
{
if (!host_char_to_target (c, &target_char))
no_control_char_error (sequence_start_pos, *string_ptr);
}
if (!target_char_to_control_char (target_char, &target_char))
no_control_char_error (sequence_start_pos, *string_ptr);
return target_char;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
{
int i = c - '0';
int count = 0;
while (++count < 3)
{
c = (**string_ptr);
if (c >= '0' && c <= '7')
{
(*string_ptr)++;
i *= 8;
i += c - '0';
}
else
{
break;
}
}
return i;
}
default:
if (!host_char_to_target (c, &target_char))
error
("The escape sequence `\%c' is equivalent to plain `%c', which"
" has no equivalent\n" "in the `%s' character set.", c, c,
target_charset ());
return target_char;
}
}
static void
printchar (int c, void (*do_fputs) (const char *, struct ui_file *),
void (*do_fprintf) (struct ui_file *, const char *, ...)
ATTRIBUTE_FPTR_PRINTF_2, struct ui_file *stream, int quoter)
{
c &= 0xFF;
if (c < 0x20 ||
(c >= 0x7F && c < 0xA0) ||
(sevenbit_strings && c >= 0x80))
{
switch (c)
{
case '\n':
do_fputs ("\\n", stream);
break;
case '\b':
do_fputs ("\\b", stream);
break;
case '\t':
do_fputs ("\\t", stream);
break;
case '\f':
do_fputs ("\\f", stream);
break;
case '\r':
do_fputs ("\\r", stream);
break;
case '\033':
do_fputs ("\\e", stream);
break;
case '\007':
do_fputs ("\\a", stream);
break;
default:
do_fprintf (stream, "\\%.3o", (unsigned int) c);
break;
}
}
else
{
if (c == '\\' || c == quoter)
do_fputs ("\\", stream);
do_fprintf (stream, "%c", c);
}
}
void
fputstr_filtered (const char *str, int quoter, struct ui_file *stream)
{
while (*str)
printchar (*str++, fputs_filtered, fprintf_filtered, stream, quoter);
}
void
fputstr_unfiltered (const char *str, int quoter, struct ui_file *stream)
{
while (*str)
printchar (*str++, fputs_unfiltered, fprintf_unfiltered, stream, quoter);
}
void
fputstrn_unfiltered (const char *str, int n, int quoter,
struct ui_file *stream)
{
int i;
for (i = 0; i < n; i++)
printchar (str[i], fputs_unfiltered, fprintf_unfiltered, stream, quoter);
}
static unsigned int lines_per_page;
static void
show_lines_per_page (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Number of lines gdb thinks are in a page is %s.\n"),
value);
}
static unsigned int chars_per_line;
static void
show_chars_per_line (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Number of characters gdb thinks are in a line is %s.\n"),
value);
}
static unsigned int lines_printed, chars_printed;
static char *wrap_buffer;
static char *wrap_pointer;
static char *wrap_indent;
static int wrap_column;
void
init_page_info (void)
{
#if defined(TUI)
if (!tui_get_command_dimension (&chars_per_line, &lines_per_page))
#endif
{
int rows, cols;
#if defined(__GO32__)
rows = ScreenRows ();
cols = ScreenCols ();
lines_per_page = rows;
chars_per_line = cols;
#else
rl_reset_terminal (NULL);
rl_get_screen_size (&rows, &cols);
lines_per_page = rows;
chars_per_line = cols;
if (tgetnum ("li") < 0 || getenv ("EMACS"))
{
lines_per_page = UINT_MAX;
}
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
SIGWINCH_HANDLER (SIGWINCH);
#endif
if (!ui_file_isatty (gdb_stdout))
lines_per_page = UINT_MAX;
#endif
}
set_screen_size ();
set_width ();
}
void
set_screen_size (void)
{
int rows = lines_per_page;
int cols = chars_per_line;
if (rows <= 0)
rows = INT_MAX;
if (cols <= 0)
rl_get_screen_size (NULL, &cols);
rl_set_screen_size (rows, cols);
}
void
set_width (void)
{
if (chars_per_line == 0)
{
chars_per_line = UINT_MAX;
}
if (!wrap_buffer)
{
wrap_buffer = (char *) xmalloc (chars_per_line + 2);
wrap_buffer[0] = '\0';
}
else
wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2);
wrap_pointer = wrap_buffer;
}
static void
set_width_command (char *args, int from_tty, struct cmd_list_element *c)
{
set_screen_size ();
set_width ();
}
static void
set_height_command (char *args, int from_tty, struct cmd_list_element *c)
{
set_screen_size ();
}
static void
prompt_for_continue (void)
{
char *ignore;
char cont_prompt[120];
if (annotation_level > 1)
printf_unfiltered (("\n\032\032pre-prompt-for-continue\n"));
strcpy (cont_prompt,
"---Type <return> to continue, or q <return> to quit---");
if (annotation_level > 1)
strcat (cont_prompt, "\n\032\032prompt-for-continue\n");
reinitialize_more_filter ();
immediate_quit++;
ignore = gdb_readline_wrapper (cont_prompt);
if (annotation_level > 1)
printf_unfiltered (("\n\032\032post-prompt-for-continue\n"));
if (ignore)
{
char *p = ignore;
while (*p == ' ' || *p == '\t')
++p;
if (p[0] == 'q')
async_request_quit (0);
xfree (ignore);
}
immediate_quit--;
reinitialize_more_filter ();
dont_repeat ();
}
void
reinitialize_more_filter (void)
{
lines_printed = 0;
chars_printed = 0;
}
void
wrap_here (char *indent)
{
if (!wrap_buffer)
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
if (wrap_buffer[0])
{
*wrap_pointer = '\0';
fputs_unfiltered (wrap_buffer, gdb_stdout);
}
wrap_pointer = wrap_buffer;
wrap_buffer[0] = '\0';
if (chars_per_line == UINT_MAX)
{
wrap_column = 0;
}
else if (chars_printed >= chars_per_line)
{
puts_filtered ("\n");
if (indent != NULL)
puts_filtered (indent);
wrap_column = 0;
}
else
{
wrap_column = chars_printed;
if (indent == NULL)
wrap_indent = "";
else
wrap_indent = indent;
}
}
void
puts_filtered_tabular (char *string, int width, int right)
{
int spaces = 0;
int stringlen;
char *spacebuf;
gdb_assert (chars_per_line > 0);
if (chars_per_line == UINT_MAX)
{
fputs_filtered (string, gdb_stdout);
fputs_filtered ("\n", gdb_stdout);
return;
}
if (((chars_printed - 1) / width + 2) * width >= chars_per_line)
fputs_filtered ("\n", gdb_stdout);
if (width >= chars_per_line)
width = chars_per_line - 1;
stringlen = strlen (string);
if (chars_printed > 0)
spaces = width - (chars_printed - 1) % width - 1;
if (right)
spaces += width - stringlen;
spacebuf = alloca (spaces + 1);
spacebuf[spaces] = '\0';
while (spaces--)
spacebuf[spaces] = ' ';
fputs_filtered (spacebuf, gdb_stdout);
fputs_filtered (string, gdb_stdout);
}
void
begin_line (void)
{
if (chars_printed > 0)
{
puts_filtered ("\n");
}
}
static void
fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
int filter)
{
const char *lineptr;
gdb_assert (chars_per_line > 0);
if (linebuffer == 0)
return;
if ((stream != gdb_stdout) || !pagination_enabled
|| (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX))
{
fputs_unfiltered (linebuffer, stream);
return;
}
lineptr = linebuffer;
while (*lineptr)
{
if (filter && (lines_printed >= lines_per_page - 1))
prompt_for_continue ();
while (*lineptr && *lineptr != '\n')
{
if (*lineptr == '\t')
{
if (wrap_column)
*wrap_pointer++ = '\t';
else
fputc_unfiltered ('\t', stream);
chars_printed = ((chars_printed >> 3) + 1) << 3;
lineptr++;
}
else
{
if (wrap_column)
*wrap_pointer++ = *lineptr;
else
fputc_unfiltered (*lineptr, stream);
chars_printed++;
lineptr++;
}
if (chars_printed >= chars_per_line)
{
unsigned int save_chars = chars_printed;
chars_printed = 0;
lines_printed++;
if (wrap_column)
fputc_unfiltered ('\n', stream);
if (lines_printed >= lines_per_page - 1)
prompt_for_continue ();
if (wrap_column)
{
fputs_unfiltered (wrap_indent, stream);
*wrap_pointer = '\0';
fputs_unfiltered (wrap_buffer, stream);
chars_printed = strlen (wrap_indent)
+ (save_chars - wrap_column);
wrap_pointer = wrap_buffer;
wrap_buffer[0] = '\0';
wrap_column = 0;
}
}
}
if (*lineptr == '\n')
{
chars_printed = 0;
wrap_here ((char *) 0);
lines_printed++;
fputc_unfiltered ('\n', stream);
lineptr++;
}
}
}
void
fputs_filtered (const char *linebuffer, struct ui_file *stream)
{
fputs_maybe_filtered (linebuffer, stream, 1);
}
int
putchar_unfiltered (int c)
{
char buf = c;
ui_file_write (gdb_stdout, &buf, 1);
return c;
}
int
putchar_filtered (int c)
{
return fputc_filtered (c, gdb_stdout);
}
int
fputc_unfiltered (int c, struct ui_file *stream)
{
char buf = c;
ui_file_write (stream, &buf, 1);
return c;
}
int
fputc_filtered (int c, struct ui_file *stream)
{
char buf[2];
buf[0] = c;
buf[1] = 0;
fputs_filtered (buf, stream);
return c;
}
void
puts_debug (char *prefix, char *string, char *suffix)
{
int ch;
static int new_line = 1;
static int return_p = 0;
static char *prev_prefix = "";
static char *prev_suffix = "";
if (*string == '\n')
return_p = 0;
if ((return_p || (strcmp (prev_prefix, prefix) != 0)) && !new_line)
{
fputs_unfiltered (prev_suffix, gdb_stdlog);
fputs_unfiltered ("\n", gdb_stdlog);
fputs_unfiltered (prefix, gdb_stdlog);
}
if (new_line)
{
new_line = 0;
fputs_unfiltered (prefix, gdb_stdlog);
}
prev_prefix = prefix;
prev_suffix = suffix;
while ((ch = *string++) != '\0')
{
switch (ch)
{
default:
if (isprint (ch))
fputc_unfiltered (ch, gdb_stdlog);
else
fprintf_unfiltered (gdb_stdlog, "\\x%02x", ch & 0xff);
break;
case '\\':
fputs_unfiltered ("\\\\", gdb_stdlog);
break;
case '\b':
fputs_unfiltered ("\\b", gdb_stdlog);
break;
case '\f':
fputs_unfiltered ("\\f", gdb_stdlog);
break;
case '\n':
new_line = 1;
fputs_unfiltered ("\\n", gdb_stdlog);
break;
case '\r':
fputs_unfiltered ("\\r", gdb_stdlog);
break;
case '\t':
fputs_unfiltered ("\\t", gdb_stdlog);
break;
case '\v':
fputs_unfiltered ("\\v", gdb_stdlog);
break;
}
return_p = ch == '\r';
}
if (new_line)
{
fputs_unfiltered (suffix, gdb_stdlog);
fputs_unfiltered ("\n", gdb_stdlog);
}
}
static void
vfprintf_maybe_filtered (struct ui_file *stream, const char *format,
va_list args, int filter)
{
char *linebuffer;
struct cleanup *old_cleanups;
linebuffer = xstrvprintf (format, args);
old_cleanups = make_cleanup (xfree, linebuffer);
fputs_maybe_filtered (linebuffer, stream, filter);
do_cleanups (old_cleanups);
}
void
vfprintf_filtered (struct ui_file *stream, const char *format, va_list args)
{
vfprintf_maybe_filtered (stream, format, args, 1);
}
void
vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args)
{
char *linebuffer;
struct cleanup *old_cleanups;
linebuffer = xstrvprintf (format, args);
old_cleanups = make_cleanup (xfree, linebuffer);
fputs_unfiltered (linebuffer, stream);
do_cleanups (old_cleanups);
}
void
vprintf_filtered (const char *format, va_list args)
{
vfprintf_maybe_filtered (gdb_stdout, format, args, 1);
}
void
vprintf_unfiltered (const char *format, va_list args)
{
vfprintf_unfiltered (gdb_stdout, format, args);
}
void
fprintf_filtered (struct ui_file *stream, const char *format, ...)
{
va_list args;
va_start (args, format);
vfprintf_filtered (stream, format, args);
va_end (args);
}
void
fprintf_unfiltered (struct ui_file *stream, const char *format, ...)
{
va_list args;
va_start (args, format);
vfprintf_unfiltered (stream, format, args);
va_end (args);
}
void
fprintfi_filtered (int spaces, struct ui_file *stream, const char *format,
...)
{
va_list args;
va_start (args, format);
print_spaces_filtered (spaces, stream);
vfprintf_filtered (stream, format, args);
va_end (args);
}
void
printf_filtered (const char *format, ...)
{
va_list args;
va_start (args, format);
vfprintf_filtered (gdb_stdout, format, args);
va_end (args);
}
void
printf_unfiltered (const char *format, ...)
{
va_list args;
va_start (args, format);
vfprintf_unfiltered (gdb_stdout, format, args);
va_end (args);
}
void
printfi_filtered (int spaces, const char *format, ...)
{
va_list args;
va_start (args, format);
print_spaces_filtered (spaces, gdb_stdout);
vfprintf_filtered (gdb_stdout, format, args);
va_end (args);
}
void
puts_filtered (const char *string)
{
fputs_filtered (string, gdb_stdout);
}
void
puts_unfiltered (const char *string)
{
fputs_unfiltered (string, gdb_stdout);
}
char *
n_spaces (int n)
{
char *t;
static char *spaces = 0;
static int max_spaces = -1;
if (n > max_spaces)
{
if (spaces)
xfree (spaces);
spaces = (char *) xmalloc (n + 1);
for (t = spaces + n; t != spaces;)
*--t = ' ';
spaces[n] = '\0';
max_spaces = n;
}
return spaces + max_spaces - n;
}
void
print_spaces_filtered (int n, struct ui_file *stream)
{
fputs_filtered (n_spaces (n), stream);
}
void
fprintf_symbol_filtered (struct ui_file *stream, char *name,
enum language lang, int arg_mode)
{
char *demangled;
if (name != NULL)
{
if (!demangle)
{
fputs_filtered (name, stream);
}
else
{
demangled = language_demangle (language_def (lang), name, arg_mode);
fputs_filtered (demangled ? demangled : name, stream);
if (demangled != NULL)
{
xfree (demangled);
}
}
}
}
int
strcmp_iw (const char *string1, const char *string2)
{
while ((*string1 != '\0') && (*string2 != '\0'))
{
while (isspace (*string1))
{
string1++;
}
while (isspace (*string2))
{
string2++;
}
if (*string1 != *string2)
{
break;
}
if (*string1 != '\0')
{
string1++;
string2++;
}
}
return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0');
}
int
strcmp_iw_ordered (const char *string1, const char *string2)
{
while ((*string1 != '\0') && (*string2 != '\0'))
{
while (isspace (*string1))
{
string1++;
}
while (isspace (*string2))
{
string2++;
}
if (*string1 != *string2)
{
break;
}
if (*string1 != '\0')
{
string1++;
string2++;
}
}
switch (*string1)
{
case '\0':
if (*string2 == '\0')
return 0;
else
return -1;
case '(':
if (*string2 == '\0')
return 1;
else
return -1;
default:
if (*string2 == '(')
return 1;
else
return *string1 - *string2;
}
}
int
streq (const char *lhs, const char *rhs)
{
return !strcmp (lhs, rhs);
}
int
subset_compare (char *string_to_compare, char *template_string)
{
int match;
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);
else
match = 0;
return match;
}
static void pagination_on_command (char *arg, int from_tty);
static void
pagination_on_command (char *arg, int from_tty)
{
pagination_enabled = 1;
}
static void pagination_on_command (char *arg, int from_tty);
static void
pagination_off_command (char *arg, int from_tty)
{
pagination_enabled = 0;
}
void
initialize_utils (void)
{
struct cmd_list_element *c;
add_setshow_uinteger_cmd ("width", class_support, &chars_per_line, _("\
Set number of characters gdb thinks are in a line."), _("\
Show number of characters gdb thinks are in a line."), NULL,
set_width_command,
show_chars_per_line,
&setlist, &showlist);
add_setshow_uinteger_cmd ("height", class_support, &lines_per_page, _("\
Set number of lines gdb thinks are in a page."), _("\
Show number of lines gdb thinks are in a page."), NULL,
set_height_command,
show_lines_per_page,
&setlist, &showlist);
init_page_info ();
add_setshow_boolean_cmd ("demangle", class_support, &demangle, _("\
Set demangling of encoded C++/ObjC names when displaying symbols."), _("\
Show demangling of encoded C++/ObjC names when displaying symbols."), NULL,
NULL,
show_demangle,
&setprintlist, &showprintlist);
add_setshow_boolean_cmd ("pagination", class_support,
&pagination_enabled, _("\
Set state of pagination."), _("\
Show state of pagination."), NULL,
NULL,
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."), _("\
Show printing of 8-bit characters in strings as \\nnn."), NULL,
NULL,
show_sevenbit_strings,
&setprintlist, &showprintlist);
add_setshow_boolean_cmd ("asm-demangle", class_support, &asm_demangle, _("\
Set demangling of C++/ObjC names in disassembly listings."), _("\
Show demangling of C++/ObjC names in disassembly listings."), NULL,
NULL,
show_asm_demangle,
&setprintlist, &showprintlist);
}
#ifdef SIGWINCH_HANDLER_BODY
SIGWINCH_HANDLER_BODY
#endif
#define NUMCELLS 16
#define CELLSIZE 50
static char *
get_cell (void)
{
static char buf[NUMCELLS][CELLSIZE];
static int cell = 0;
if (++cell >= NUMCELLS)
cell = 0;
return buf[cell];
}
int
strlen_paddr (void)
{
return (TARGET_ADDR_BIT / 8 * 2);
}
char *
paddr (CORE_ADDR addr)
{
return phex (addr, TARGET_ADDR_BIT / 8);
}
char *
paddr_nz (CORE_ADDR addr)
{
return phex_nz (addr, TARGET_ADDR_BIT / 8);
}
const char *
paddress (CORE_ADDR addr)
{
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 char *
decimal2str (char *sign, ULONGEST addr, int width)
{
unsigned long temp[3];
char *str = get_cell ();
int i = 0;
do
{
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:
xsnprintf (str, CELLSIZE, "%s%0*lu", sign, width, temp[0]);
break;
case 2:
xsnprintf (str, CELLSIZE, "%s%0*lu%09lu", sign, width,
temp[1], temp[0]);
break;
case 3:
xsnprintf (str, CELLSIZE, "%s%0*lu%09lu%09lu", sign, width,
temp[2], temp[1], temp[0]);
break;
default:
internal_error (__FILE__, __LINE__,
_("failed internal consistency check"));
}
return str;
}
static char *
octal2str (ULONGEST addr, int width)
{
unsigned long temp[3];
char *str = get_cell ();
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)
xsnprintf (str, CELLSIZE, "%*o", width, 0);
else
xsnprintf (str, CELLSIZE, "0%0*lo", width, temp[0]);
break;
case 2:
xsnprintf (str, CELLSIZE, "0%0*lo%010lo", width, temp[1], temp[0]);
break;
case 3:
xsnprintf (str, CELLSIZE, "0%0*lo%010lo%010lo", width,
temp[2], temp[1], temp[0]);
break;
default:
internal_error (__FILE__, __LINE__,
_("failed internal consistency check"));
}
return str;
}
char *
paddr_u (CORE_ADDR addr)
{
return decimal2str ("", addr, 0);
}
char *
paddr_d (LONGEST addr)
{
if (addr < 0)
return decimal2str ("-", -addr, 0);
else
return decimal2str ("", addr, 0);
}
static int thirty_two = 32;
char *
phex (ULONGEST l, int sizeof_l)
{
char *str;
switch (sizeof_l)
{
case 8:
str = get_cell ();
xsnprintf (str, CELLSIZE, "%08lx%08lx",
(unsigned long) (l >> thirty_two),
(unsigned long) (l & 0xffffffff));
break;
case 4:
str = get_cell ();
xsnprintf (str, CELLSIZE, "%08lx", (unsigned long) l);
break;
case 2:
str = get_cell ();
xsnprintf (str, CELLSIZE, "%04x", (unsigned short) (l & 0xffff));
break;
default:
str = phex (l, sizeof (l));
break;
}
return str;
}
char *
phex_nz (ULONGEST l, int sizeof_l)
{
char *str;
switch (sizeof_l)
{
case 8:
{
unsigned long high = (unsigned long) (l >> thirty_two);
str = get_cell ();
if (high == 0)
xsnprintf (str, CELLSIZE, "%lx",
(unsigned long) (l & 0xffffffff));
else
xsnprintf (str, CELLSIZE, "%lx%08lx", high,
(unsigned long) (l & 0xffffffff));
break;
}
case 4:
str = get_cell ();
xsnprintf (str, CELLSIZE, "%lx", (unsigned long) l);
break;
case 2:
str = get_cell ();
xsnprintf (str, CELLSIZE, "%x", (unsigned short) (l & 0xffff));
break;
default:
str = phex_nz (l, sizeof (l));
break;
}
return str;
}
void gdb_check (const char *str, const char *file, unsigned int line, const char *func)
{
error ("assertion failure on line %u of \"%s\" in function \"%s\": %s\n",
line, file, func, str);
}
void gdb_check_fatal (const char *str, const char *file, unsigned int line, const char *func)
{
internal_error (file, line, "assertion failure in function \"%s\": %s\n",
func, str);
}
char *
hex_string (LONGEST num)
{
char *result = get_cell ();
xsnprintf (result, CELLSIZE, "0x%s", phex_nz (num, sizeof (num)));
return result;
}
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;
}
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:
{
if (is_signed && val < 0)
return decimal2str ("-", -val, width);
else
return decimal2str ("", val, width);
}
case 8:
{
char *result = octal2str (val, width);
if (use_c_format || val == 0)
return result;
else
return result + 1;
}
default:
internal_error (__FILE__, __LINE__,
_("failed internal consistency check"));
}
}
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");
strcat (str, phex_nz (addr, sizeof (addr)));
return str;
}
CORE_ADDR
string_to_core_addr (const char *my_string)
{
CORE_ADDR addr = 0;
if (my_string[0] == '0' && tolower (my_string[1]) == 'x')
{
int i;
for (i = 2; my_string[i] != '\0'; i++)
{
if (isdigit (my_string[i]))
addr = (my_string[i] - '0') + (addr * 16);
else if (isxdigit (my_string[i]))
addr = (tolower (my_string[i]) - 'a' + 0xa) + (addr * 16);
else
internal_error (__FILE__, __LINE__, _("invalid hex"));
}
}
else
{
int i;
for (i = 0; my_string[i] != '\0'; i++)
{
if (isdigit (my_string[i]))
addr = (my_string[i] - '0') + (addr * 10);
else
internal_error (__FILE__, __LINE__, _("invalid decimal"));
}
}
return addr;
}
char *
gdb_realpath (const char *filename)
{
#if defined(HAVE_REALPATH)
{
# if defined (PATH_MAX)
char buf[PATH_MAX];
# define USE_REALPATH
# elif defined (MAXPATHLEN)
char buf[MAXPATHLEN];
# define USE_REALPATH
# endif
# if defined (USE_REALPATH)
const char *rp = realpath (filename, buf);
if (rp == NULL)
rp = filename;
return xstrdup (rp);
# endif
}
#endif
#if defined(HAVE_CANONICALIZE_FILE_NAME)
{
char *rp = canonicalize_file_name (filename);
if (rp == NULL)
return xstrdup (filename);
else
return rp;
}
#endif
#if defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H) && defined(HAVE_ALLOCA)
{
long path_max = pathconf ("/", _PC_PATH_MAX);
if (path_max > 0)
{
char *buf = alloca (path_max);
char *rp = realpath (filename, buf);
return xstrdup (rp ? rp : filename);
}
}
#endif
return xstrdup (filename);
}
char *
xfullpath (const char *filename)
{
const char *base_name = lbasename (filename);
char *dir_name;
char *real_path;
char *result;
if (base_name == filename)
return xstrdup (filename);
dir_name = alloca ((size_t) (base_name - filename + 2));
strncpy (dir_name, filename, base_name - filename);
dir_name[base_name - filename] = '\000';
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
{
dir_name[2] = '.';
dir_name[3] = '\000';
}
#endif
real_path = gdb_realpath (dir_name);
if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
result = concat (real_path, base_name, (char *)NULL);
else
result = concat (real_path, SLASH_STRING, base_name, (char *)NULL);
xfree (real_path);
return result;
}
unsigned long
gnu_debuglink_crc32 (unsigned long crc, unsigned char *buf, size_t len)
{
static const unsigned long crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
0x2d02ef8d
};
unsigned char *end;
crc = ~crc & 0xffffffff;
for (end = buf + len; buf < end; ++buf)
crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
return ~crc & 0xffffffff;;
}
ULONGEST
align_up (ULONGEST v, int n)
{
gdb_assert (n && (n & (n-1)) == 0);
return (v + n - 1) & -n;
}
ULONGEST
align_down (ULONGEST v, int n)
{
gdb_assert (n && (n & (n-1)) == 0);
return (v & -n);
}
void
breakup_args (char *scratch, int *argc, char **argv)
{
char *cp = scratch;
*argc = 0;
for (;;)
{
while (*cp == ' ' || *cp == '\t' || *cp == '\n')
cp++;
if (*cp == '\0')
break;
*argv++ = cp;
(*argc)++;
while (!(*cp == '\0' || *cp == ' ' || *cp == '\t' || *cp == '\n'))
{
cp++;
}
if (*cp == '\0')
break;
*cp++ = '\0';
}
*argv = NULL;
}