X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Futils.c;h=76ea6b12b8f12a86aa8af456dfc8ad5720e9096d;hb=17ea7499a94cca815ea904ccfdb2743d208a6688;hp=e99164cd3ca4765642f020ef81b442d431f7eca1;hpb=6a83354a43c2dc48a253ee15eb62ccd1a8cd1b48;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/utils.c b/gdb/utils.c index e99164cd3c..76ea6b12b8 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1,14 +1,14 @@ /* 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. + Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,15 +17,14 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "gdb_assert.h" #include #include "gdb_string.h" #include "event-top.h" +#include "exceptions.h" #ifdef TUI #include "tui/tui.h" /* For tui_get_command_dimension. */ @@ -51,48 +50,41 @@ #include "charset.h" #include "annotate.h" #include "filenames.h" +#include "symfile.h" +#include "gdb_obstack.h" +#include "gdbcore.h" +#include "top.h" #include "inferior.h" /* for signed_pointer_to_address */ #include /* For MAXPATHLEN */ -#ifdef HAVE_CURSES_H -#include -#endif -#ifdef HAVE_TERM_H -#include -#endif +#include "gdb_curses.h" -#include +#include "readline/readline.h" -#ifdef NEED_DECLARATION_MALLOC +#include +#include + +#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 (*error_begin_hook) (void); - -/* Holds the last error message issued by gdb */ - -static struct ui_file *gdb_lasterr; +void (*deprecated_error_begin_hook) (void); /* Prototypes for local functions */ static void vfprintf_maybe_filtered (struct ui_file *, const char *, - va_list, int); + va_list, int) ATTR_FORMAT (printf, 2, 0); static void fputs_maybe_filtered (const char *, struct ui_file *, int); @@ -103,15 +95,15 @@ static void prompt_for_continue (void); static void set_screen_size (void); static void set_width (void); +/* A flag indicating whether to timestamp debugging messages. */ + +static int debug_timestamp = 0; + /* Chain of cleanup actions established with make_cleanup, to be executed if an error happens. */ static struct cleanup *cleanup_chain; /* cleaned up after a failed command */ static struct cleanup *final_cleanup_chain; /* cleaned up when gdb exits */ -static struct cleanup *run_cleanup_chain; /* cleaned up on each 'run' */ -static struct cleanup *exec_cleanup_chain; /* cleaned up on each execution command */ -/* cleaned up on each error from within an execution command */ -static struct cleanup *exec_error_cleanup_chain; /* Pointer to what is left to do for an execution command after the target stops. Used only in asynchronous mode, by targets that @@ -145,18 +137,42 @@ int immediate_quit; C++/ObjC form rather than raw. */ 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); +} /* Nonzero means that encoded C++/ObjC names should be printed out in their C++/ObjC form even in assembler language displays. If this is set, but DEMANGLE is zero, names are printed raw, i.e. DEMANGLE controls. */ 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); +} /* Nonzero means that strings with character values >0x7F should be printed as octal escapes. Zero means just print the value (e.g. it's an international character, and the terminal or window can cope.) */ 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); +} /* String to be printed before error messages, if any. */ @@ -171,6 +187,13 @@ 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); +} + /* Add a new cleanup to the cleanup_chain, @@ -190,24 +213,6 @@ 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) { @@ -260,6 +265,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) @@ -291,24 +309,6 @@ 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) -{ - 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) @@ -337,12 +337,6 @@ 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) @@ -410,7 +404,7 @@ free_current_contents (void *ptr) 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); @@ -433,7 +427,7 @@ null_cleanup (void *arg) /* Add a continuation to the continuation list, the global list cmd_continuation. The new continuation will be added at the front.*/ void -add_continuation (void (*continuation_hook) (struct continuation_arg *), +add_continuation (void (*continuation_hook) (struct continuation_arg *, int), struct continuation_arg *arg_list) { struct continuation *continuation_ptr; @@ -453,9 +447,9 @@ 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) +do_all_continuations (int error) { struct continuation *continuation_ptr; struct continuation *saved_continuation; @@ -467,10 +461,10 @@ 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); + (continuation_ptr->continuation_hook) (continuation_ptr->arg_list, error); saved_continuation = continuation_ptr; continuation_ptr = continuation_ptr->next; xfree (saved_continuation); @@ -493,10 +487,11 @@ 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 *), + (struct continuation_arg *, int), struct continuation_arg *arg_list) { struct continuation *continuation_ptr; @@ -518,7 +513,7 @@ add_intermediate_continuation (void (*continuation_hook) and do the continuations from there on, instead of using the global beginning of list as our iteration pointer.*/ void -do_all_intermediate_continuations (void) +do_all_intermediate_continuations (int error) { struct continuation *continuation_ptr; struct continuation *saved_continuation; @@ -530,10 +525,10 @@ 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); + (continuation_ptr->continuation_hook) (continuation_ptr->arg_list, error); saved_continuation = continuation_ptr; continuation_ptr = continuation_ptr->next; xfree (saved_continuation); @@ -566,8 +561,8 @@ discard_all_intermediate_continuations (void) void vwarning (const char *string, va_list args) { - if (warning_hook) - (*warning_hook) (string, args); + if (deprecated_warning_hook) + (*deprecated_warning_hook) (string, args); else { target_terminal_ours (); @@ -603,10 +598,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 +606,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 (error_begin_hook) - error_begin_hook (); - - /* Copy the stream into the GDB_LASTERR buffer. */ - ui_file_rewind (gdb_lasterr); - ui_file_put (stream, do_write, gdb_lasterr); - - /* Write the message plus any error_pre_print to gdb_stderr. */ - target_terminal_ours (); - wrap_here (""); /* Force out any buffered output */ - gdb_flush (gdb_stdout); - annotate_error_begin (); - if (error_pre_print) - 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 @@ -713,7 +655,7 @@ struct internal_problem has been reported, and assuming GDB didn't quit, the caller can either allow execution to resume or throw an error. */ -static void +static void ATTR_FORMAT (printf, 4, 0) internal_vproblem (struct internal_problem *problem, const char *file, int line, const char *fmt, va_list ap) { @@ -752,8 +694,8 @@ internal_vproblem (struct internal_problem *problem, so that the user knows that they are living on the edge. */ { char *msg; - xvasprintf (&msg, fmt, ap); - xasprintf (&reason, "\ + 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); @@ -767,7 +709,7 @@ further debugging may prove unreliable.", file, line, problem->name, msg); /* 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; @@ -776,7 +718,7 @@ further debugging may prove unreliable.", file, line, problem->name, msg); quit_p = 0; break; default: - internal_error (__FILE__, __LINE__, "bad switch"); + internal_error (__FILE__, __LINE__, _("bad switch")); } switch (problem->should_dump_core) @@ -785,7 +727,7 @@ further debugging may prove unreliable.", file, line, problem->name, msg); /* 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: @@ -795,7 +737,7 @@ further debugging may prove unreliable.", file, line, problem->name, msg); dump_core_p = 0; break; default: - internal_error (__FILE__, __LINE__, "bad switch"); + internal_error (__FILE__, __LINE__, _("bad switch")); } if (quit_p) @@ -809,8 +751,10 @@ further debugging may prove unreliable.", file, line, problem->name, msg); { if (dump_core_p) { +#ifdef HAVE_WORKING_FORK if (fork () == 0) abort (); /* NOTE: GDB has only three calls to abort(). */ +#endif } } @@ -825,7 +769,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 @@ -838,7 +782,7 @@ internal_error (const char *file, int line, const char *string, ...) } static struct internal_problem internal_warning_problem = { - "internal-error", AUTO_BOOLEAN_AUTO, AUTO_BOOLEAN_AUTO + "internal-warning", AUTO_BOOLEAN_AUTO, AUTO_BOOLEAN_AUTO }; void @@ -856,25 +800,6 @@ internal_warning (const char *file, int line, const char *string, ...) va_end (ap); } -/* The strerror() function can return NULL for errno values that are - out of range. Provide a "safe" version that always returns a - printable string. */ - -char * -safe_strerror (int errnum) -{ - char *msg; - static char buf[32]; - - msg = strerror (errnum); - if (msg == NULL) - { - sprintf (buf, "(undocumented errno %d)", errnum); - msg = buf; - } - return (msg); -} - /* Print the system error message for errno, and also mention STRING as the file name for which the error was encountered. Then return to command level. */ @@ -897,7 +822,7 @@ perror_with_name (const char *string) 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 @@ -926,103 +851,22 @@ print_sys_errmsg (const char *string, int errcode) 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 */ -void -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. */ - signal (signo, request_quit); - -#ifdef REQUEST_QUIT - REQUEST_QUIT; -#else - if (immediate_quit) - quit (); -#endif -} -/* 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. */ @@ -1032,27 +876,26 @@ nomem (long size) 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.")); } } -/* 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; @@ -1061,7 +904,7 @@ xmmalloc (void *md, size_t size) if (size == 0) size = 1; - val = mmalloc (md, size); + val = malloc (size); /* OK: malloc */ if (val == NULL) nomem (size); @@ -1069,7 +912,13 @@ xmmalloc (void *md, size_t size) } void * -xmrealloc (void *md, void *ptr, size_t size) +xzalloc (size_t size) +{ + return xcalloc (1, size); +} + +PTR /* OK: PTR */ +xrealloc (PTR ptr, size_t size) /* OK: PTR */ { void *val; @@ -1079,17 +928,17 @@ xmrealloc (void *md, void *ptr, size_t size) 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; @@ -1101,53 +950,18 @@ xmcalloc (void *md, size_t number, size_t size) 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 */ } @@ -1160,7 +974,7 @@ xstrprintf (const char *format, ...) char *ret; va_list args; va_start (args, format); - xvasprintf (&ret, format, args); + ret = xstrvprintf (format, args); va_end (args); return ret; } @@ -1170,26 +984,43 @@ xasprintf (char **ret, const char *format, ...) { va_list args; va_start (args, format); - xvasprintf (ret, format, args); + (*ret) = xstrvprintf (format, args); va_end (args); } void xvasprintf (char **ret, const char *format, va_list ap) { - int status = vasprintf (ret, format, ap); - /* NULL could be returned due to a memory allocation problem; a - badly format string; or something else. */ - if ((*ret) == NULL) - internal_error (__FILE__, __LINE__, - "vasprintf returned NULL buffer (errno %d)", errno); - /* A negative status with a non-NULL buffer shouldn't never - happen. But to be sure. */ - if (status < 0) - internal_error (__FILE__, __LINE__, - "vasprintf call failed (errno %d)", errno); + (*ret) = xstrvprintf (format, ap); } +char * +xstrvprintf (const char *format, va_list ap) +{ + char *ret = NULL; + int status = vasprintf (&ret, format, ap); + /* NULL is returned when there was a memory allocation problem, or + any other error (for instance, a bad format string). A negative + status (the printed length) with a non-NULL buffer should never + happen, but just to be sure. */ + if (ret == NULL || status < 0) + internal_error (__FILE__, __LINE__, _("vasprintf call failed")); + 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; +} /* My replacement for the read system call. Used like `read' but keeps going if `read' returns too soon. */ @@ -1226,21 +1057,6 @@ savestring (const char *ptr, size_t size) 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) { @@ -1259,31 +1075,87 @@ gdb_print_host_address (const void *addr, struct ui_file *stream) fprintf_filtered (stream, "0x%lx", (unsigned long) addr); } + -/* Ask user a y-or-n question and return 1 iff answer is yes. - Takes three args which are given to printf to print the question. - The first, a control string, should end in "? ". - It should not say how to answer, because we do that. */ +/* This function supports the query, nquery, and yquery functions. + Ask user a y-or-n question and return 0 if answer is no, 1 if + answer is yes, or default the answer to the specified default + (for yquery or nquery). DEFCHAR may be 'y' or 'n' to provide a + default answer, or '\0' for no default. + CTLSTR is the control string and should end in "? ". It should + not say how to answer, because we do that. + ARGS are the arguments passed along with the CTLSTR argument to + printf. */ -/* VARARGS */ -int -query (const char *ctlstr, ...) +static int ATTR_FORMAT (printf, 1, 0) +defaulted_query (const char *ctlstr, const char defchar, va_list args) { - va_list args; int answer; int ans2; int retval; + int def_value; + char def_answer, not_def_answer; + char *y_string, *n_string, *question; - va_start (args, ctlstr); + /* Set up according to which answer is the default. */ + if (defchar == '\0') + { + def_value = 1; + def_answer = 'Y'; + not_def_answer = 'N'; + y_string = "y"; + n_string = "n"; + } + else 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]"; + } + + /* Automatically answer the default value if the user did not want + prompts. */ + if (! caution) + return def_value; - if (query_hook) + /* If input isn't coming from the user directly, just say what + question we're asking, and then answer "yes" automatically. This + way, important error messages don't get lost when talking to GDB + over a pipe. */ + if (! input_from_terminal_p ()) { - return query_hook (ctlstr, args); + wrap_here (""); + vfprintf_filtered (gdb_stdout, ctlstr, args); + + printf_filtered (_("(%s or %s) [answered %c; input not from terminal]\n"), + y_string, n_string, def_answer); + gdb_flush (gdb_stdout); + + return def_value; + } + + /* Automatically answer the default value if input is not from the user + directly, or if the user did not want prompts. */ + if (!input_from_terminal_p () || !caution) + return def_value; + + if (deprecated_query_hook) + { + return deprecated_query_hook (ctlstr, args); } - /* Automatically answer "yes" if input is not from a terminal. */ - if (!input_from_terminal_p ()) - return 1; + /* Format the question outside of the loop, to avoid reusing args. */ + question = xstrvprintf (ctlstr, args); while (1) { @@ -1291,13 +1163,13 @@ query (const char *ctlstr, ...) 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 ("(y or n) "); + fputs_filtered (question, gdb_stdout); + 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); @@ -1306,7 +1178,8 @@ query (const char *ctlstr, ...) clearerr (stdin); /* in case of C-d */ if (answer == EOF) /* C-d */ { - retval = 1; + printf_filtered ("EOF [assumed %c]\n", def_answer); + retval = def_value; break; } /* Eat rest of input line, to EOF or newline */ @@ -1320,25 +1193,82 @@ query (const char *ctlstr, ...) if (answer >= 'a') answer -= 040; - if (answer == 'Y') + /* Check answer. For the non-default, the user must specify + the non-default explicitly. */ + if (answer == not_def_answer) { - retval = 1; + retval = !def_value; break; } - if (answer == 'N') + /* Otherwise, if a default was specified, the user may either + specify the required input or have it default by entering + nothing. */ + if (answer == def_answer + || (defchar != '\0' && + (answer == '\n' || answer == '\r' || answer == EOF))) { - retval = 0; + retval = def_value; break; } - printf_filtered ("Please answer y or n.\n"); + /* Invalid entries are not defaulted and require another selection. */ + printf_filtered (_("Please answer %s or %s.\n"), + y_string, n_string); } + xfree (question); if (annotation_level > 1) - printf_filtered ("\n\032\032post-query\n"); + printf_filtered (("\n\032\032post-query\n")); return retval; } +/* Ask user a y-or-n question and return 0 if answer is no, 1 if + answer is yes, or 0 if answer is defaulted. + Takes three args which are given to printf to print the question. + The first, a control string, should end in "? ". + It should not say how to answer, because we do that. */ + +int +nquery (const char *ctlstr, ...) +{ + va_list args; + + va_start (args, ctlstr); + return defaulted_query (ctlstr, 'n', args); + va_end (args); +} + +/* Ask user a y-or-n question and return 0 if answer is no, 1 if + answer is yes, or 1 if answer is defaulted. + Takes three args which are given to printf to print the question. + The first, a control string, should end in "? ". + It should not say how to answer, because we do that. */ + +int +yquery (const char *ctlstr, ...) +{ + va_list args; + + va_start (args, ctlstr); + return defaulted_query (ctlstr, 'y', args); + va_end (args); +} + +/* Ask user a y-or-n question and return 1 iff answer is yes. + Takes three args which are given to printf to print the question. + The first, a control string, should end in "? ". + It should not say how to answer, because we do that. */ + +int +query (const char *ctlstr, ...) +{ + va_list args; + + va_start (args, ctlstr); + return defaulted_query (ctlstr, '\0', args); + va_end (args); +} + /* Print an error message saying that we couldn't make sense of a \^mumble sequence in a string or character constant. START and END indicate a substring of some larger string that contains the @@ -1352,7 +1282,7 @@ no_control_char_error (const char *start, const char *end) 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 ()); } @@ -1400,8 +1330,8 @@ parse_escape (char **string_ptr) 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; } @@ -1468,8 +1398,8 @@ parse_escape (char **string_ptr) static void printchar (int c, void (*do_fputs) (const char *, struct ui_file *), - void (*do_fprintf) (struct ui_file *, const char *, ...), - struct ui_file *stream, int quoter) + void (*do_fprintf) (struct ui_file *, const char *, ...) + ATTRIBUTE_FPTR_PRINTF_2, struct ui_file *stream, int quoter) { c &= 0xFF; /* Avoid sign bit follies */ @@ -1533,6 +1463,15 @@ fputstr_unfiltered (const char *str, int quoter, struct ui_file *stream) printchar (*str++, fputs_unfiltered, fprintf_unfiltered, stream, quoter); } +void +fputstrn_filtered (const char *str, int n, int quoter, + struct ui_file *stream) +{ + int i; + for (i = 0; i < n; i++) + printchar (str[i], fputs_filtered, fprintf_filtered, stream, quoter); +} + void fputstrn_unfiltered (const char *str, int n, int quoter, struct ui_file *stream) @@ -1545,9 +1484,25 @@ fputstrn_unfiltered (const char *str, int n, int quoter, /* Number of lines per page or UINT_MAX if paging is disabled. */ 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); +} /* Number of chars per line or UINT_MAX if line folding is disabled. */ 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); +} /* Current count of lines printed on this page, chars on this line. */ static unsigned int lines_printed, chars_printed; @@ -1638,7 +1593,7 @@ set_screen_size (void) rows = INT_MAX; if (cols <= 0) - rl_get_screen_size (NULL, &cols); + cols = INT_MAX; /* Update Readline's idea of the terminal size. */ rl_set_screen_size (rows, cols); @@ -1686,7 +1641,7 @@ prompt_for_continue (void) 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 to continue, or q to quit---"); @@ -1712,7 +1667,7 @@ prompt_for_continue (void) 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) { @@ -1720,12 +1675,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--; @@ -1772,7 +1722,7 @@ wrap_here (char *indent) { /* 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]) { @@ -2124,7 +2074,7 @@ vfprintf_maybe_filtered (struct ui_file *stream, const char *format, char *linebuffer; struct cleanup *old_cleanups; - xvasprintf (&linebuffer, format, args); + linebuffer = xstrvprintf (format, args); old_cleanups = make_cleanup (xfree, linebuffer); fputs_maybe_filtered (linebuffer, stream, filter); do_cleanups (old_cleanups); @@ -2143,8 +2093,18 @@ vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args) char *linebuffer; struct cleanup *old_cleanups; - xvasprintf (&linebuffer, format, args); + linebuffer = xstrvprintf (format, args); old_cleanups = make_cleanup (xfree, linebuffer); + if (debug_timestamp && stream == gdb_stdlog) + { + struct timeval tm; + char *timestamp; + + gettimeofday (&tm, NULL); + timestamp = xstrprintf ("%ld:%ld ", (long) tm.tv_sec, (long) tm.tv_usec); + make_cleanup (xfree, timestamp); + fputs_unfiltered (timestamp, stream); + } fputs_unfiltered (linebuffer, stream); do_cleanups (old_cleanups); } @@ -2450,20 +2410,24 @@ subset_compare (char *string_to_compare, char *template_string) 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; } + +static void +show_debug_timestamp (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Timestamping debugging messages is %s.\n"), value); +} void @@ -2471,49 +2435,68 @@ initialize_utils (void) { struct cmd_list_element *c; - c = add_set_cmd ("width", class_support, var_uinteger, &chars_per_line, - "Set number of characters gdb thinks are in a line.", - &setlist); - add_show_from_set (c, &showlist); - set_cmd_sfunc (c, set_width_command); + 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); - c = add_set_cmd ("height", class_support, var_uinteger, &lines_per_page, - "Set number of lines gdb thinks are in a page.", &setlist); - add_show_from_set (c, &showlist); - set_cmd_sfunc (c, set_height_command); + 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_show_from_set - (add_set_cmd ("demangle", class_support, var_boolean, - (char *) &demangle, - "Set demangling of encoded C++/ObjC names when displaying symbols.", - &setprintlist), &showprintlist); - - add_show_from_set - (add_set_cmd ("pagination", class_support, - var_boolean, (char *) &pagination_enabled, - "Set state of pagination.", &setlist), &showlist); + 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"); + _("Enable pagination")); add_com ("sm", class_support, pagination_off_command, - "Disable pagination"); + _("Disable pagination")); } - add_show_from_set - (add_set_cmd ("sevenbit-strings", class_support, var_boolean, - (char *) &sevenbit_strings, - "Set printing of 8-bit characters in strings as \\nnn.", - &setprintlist), &showprintlist); - - add_show_from_set - (add_set_cmd ("asm-demangle", class_support, var_boolean, - (char *) &asm_demangle, - "Set demangling of C++/ObjC names in disassembly listings.", - &setprintlist), &showprintlist); + 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); + + add_setshow_boolean_cmd ("timestamp", class_maintenance, + &debug_timestamp, _("\ +Set timestamping of debugging messages."), _("\ +Show timestamping of debugging messages."), _("\ +When set, debugging messages will be marked with seconds and microseconds."), + NULL, + show_debug_timestamp, + &setdebuglist, &showdebuglist); } /* Machine specific function to handle SIGWINCH signal. */ @@ -2524,7 +2507,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) { @@ -2538,98 +2521,170 @@ get_cell (void) int strlen_paddr (void) { - return (TARGET_ADDR_BIT / 8 * 2); + return (gdbarch_addr_bit (current_gdbarch) / 8 * 2); } char * paddr (CORE_ADDR addr) { - return phex (addr, TARGET_ADDR_BIT / 8); + return phex (addr, gdbarch_addr_bit (current_gdbarch) / 8); } char * paddr_nz (CORE_ADDR addr) { - return phex_nz (addr, TARGET_ADDR_BIT / 8); + return phex_nz (addr, gdbarch_addr_bit (current_gdbarch) / 8); } -static void -decimal2str (char *paddr_str, char *sign, ULONGEST addr) +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 gdbarch_address_to_pointer or + some ADDRESS_TO_PRINTABLE() be used to do the conversion? */ + + int addr_bit = gdbarch_addr_bit (current_gdbarch); + + 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) { - /* steal code from valprint.c:print_decimal(). Should this worry + /* Steal code from valprint.c:print_decimal(). Should this worry about the real size of addr as the above does? */ 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: - sprintf (paddr_str, "%s%lu", sign, temp[0]); + if (temp[0] == 0) + xsnprintf (str, CELLSIZE, "%*o", width, 0); + else + xsnprintf (str, CELLSIZE, "0%0*lo", width, temp[0]); break; case 2: - sprintf (paddr_str, "%s%lu%09lu", sign, temp[1], temp[0]); + xsnprintf (str, CELLSIZE, "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]); + 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"); + _("failed internal consistency check")); } + + return str; } char * paddr_u (CORE_ADDR addr) { - char *paddr_str = get_cell (); - decimal2str (paddr_str, "", addr); - return paddr_str; + return decimal2str ("", addr, 0); } char * paddr_d (LONGEST addr) { - char *paddr_str = get_cell (); if (addr < 0) - decimal2str (paddr_str, "-", -addr); + return decimal2str ("-", -addr, 0); else - decimal2str (paddr_str, "", addr); - return paddr_str; + return decimal2str ("", addr, 0); } -/* eliminate warning from compiler on 32-bit systems */ +/* Eliminate warning from compiler on 32-bit systems. */ static int thirty_two = 32; char * phex (ULONGEST l, int sizeof_l) { char *str; + switch (sizeof_l) { case 8: str = get_cell (); - sprintf (str, "%08lx%08lx", - (unsigned long) (l >> thirty_two), - (unsigned long) (l & 0xffffffff)); + xsnprintf (str, CELLSIZE, "%08lx%08lx", + (unsigned long) (l >> thirty_two), + (unsigned long) (l & 0xffffffff)); break; case 4: str = get_cell (); - sprintf (str, "%08lx", (unsigned long) l); + xsnprintf (str, CELLSIZE, "%08lx", (unsigned long) l); break; case 2: str = get_cell (); - sprintf (str, "%04x", (unsigned short) (l & 0xffff)); + xsnprintf (str, CELLSIZE, "%04x", (unsigned short) (l & 0xffff)); break; default: str = phex (l, sizeof (l)); break; } + return str; } @@ -2637,6 +2692,7 @@ char * phex_nz (ULONGEST l, int sizeof_l) { char *str; + switch (sizeof_l) { case 8: @@ -2644,26 +2700,107 @@ phex_nz (ULONGEST l, int sizeof_l) unsigned long high = (unsigned long) (l >> thirty_two); str = get_cell (); if (high == 0) - sprintf (str, "%lx", (unsigned long) (l & 0xffffffff)); + xsnprintf (str, CELLSIZE, "%lx", + (unsigned long) (l & 0xffffffff)); else - sprintf (str, "%lx%08lx", high, (unsigned long) (l & 0xffffffff)); + xsnprintf (str, CELLSIZE, "%lx%08lx", high, + (unsigned long) (l & 0xffffffff)); break; } case 4: str = get_cell (); - sprintf (str, "%lx", (unsigned long) l); + xsnprintf (str, CELLSIZE, "%lx", (unsigned long) l); break; case 2: str = get_cell (); - sprintf (str, "%x", (unsigned short) (l & 0xffff)); + xsnprintf (str, CELLSIZE, "%x", (unsigned short) (l & 0xffff)); break; default: str = phex_nz (l, sizeof (l)); break; } + 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 (); + xsnprintf (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: + { + 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")); + } +} /* Convert a CORE_ADDR into a string. */ const char * @@ -2688,10 +2825,12 @@ core_addr_to_string_nz (const CORE_ADDR addr) CORE_ADDR string_to_core_addr (const char *my_string) { + int addr_bit = gdbarch_addr_bit (current_gdbarch); CORE_ADDR addr = 0; + if (my_string[0] == '0' && tolower (my_string[1]) == 'x') { - /* Assume that it is in decimal. */ + /* Assume that it is in hex. */ int i; for (i = 2; my_string[i] != '\0'; i++) { @@ -2700,8 +2839,19 @@ string_to_core_addr (const char *my_string) else if (isxdigit (my_string[i])) addr = (tolower (my_string[i]) - 'a' + 0xa) + (addr * 16); else - internal_error (__FILE__, __LINE__, "invalid hex"); + error (_("invalid hex \"%s\""), my_string); } + + /* Not very modular, but if the executable format expects + addresses to be sign-extended, then do so if the address was + specified with only 32 significant bits. Really this should + be determined by the target architecture, not by the object + file. */ + if (i - 2 == addr_bit / 4 + && exec_bfd + && bfd_get_sign_extend_vma (exec_bfd)) + addr = (addr ^ ((CORE_ADDR) 1 << (addr_bit - 1))) + - ((CORE_ADDR) 1 << (addr_bit - 1)); } else { @@ -2712,12 +2862,21 @@ string_to_core_addr (const char *my_string) if (isdigit (my_string[i])) addr = (my_string[i] - '0') + (addr * 10); else - internal_error (__FILE__, __LINE__, "invalid decimal"); + error (_("invalid decimal \"%s\""), my_string); } } + return addr; } +const char * +host_address_to_string (const void *addr) +{ + char *str = get_cell (); + sprintf (str, "0x%lx", (unsigned long) addr); + return str; +} + char * gdb_realpath (const char *filename) { @@ -2828,9 +2987,9 @@ xfullpath (const char *filename) directory separator, avoid doubling it. */ real_path = gdb_realpath (dir_name); if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1])) - result = concat (real_path, base_name, NULL); + result = concat (real_path, base_name, (char *)NULL); else - result = concat (real_path, SLASH_STRING, base_name, NULL); + result = concat (real_path, SLASH_STRING, base_name, (char *)NULL); xfree (real_path); return result; @@ -2922,3 +3081,153 @@ align_down (ULONGEST v, int n) gdb_assert (n && (n & (n-1)) == 0); return (v & -n); } + +/* Allocation function for the libiberty hash table which uses an + obstack. The obstack is passed as DATA. */ + +void * +hashtab_obstack_allocate (void *data, size_t size, size_t count) +{ + unsigned int total = size * count; + void *ptr = obstack_alloc ((struct obstack *) data, total); + memset (ptr, 0, total); + return ptr; +} + +/* Trivial deallocation function for the libiberty splay tree and hash + table - don't deallocate anything. Rely on later deletion of the + obstack. DATA will be the obstack, although it is not needed + here. */ + +void +dummy_obstack_deallocate (void *object, void *data) +{ + return; +} + +/* The bit offset of the highest byte in a ULONGEST, for overflow + checking. */ + +#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT) + +/* True (non-zero) iff DIGIT is a valid digit in radix BASE, + where 2 <= BASE <= 36. */ + +static int +is_digit_in_base (unsigned char digit, int base) +{ + if (!isalnum (digit)) + return 0; + if (base <= 10) + return (isdigit (digit) && digit < base + '0'); + else + return (isdigit (digit) || tolower (digit) < base - 10 + 'a'); +} + +static int +digit_to_int (unsigned char c) +{ + if (isdigit (c)) + return c - '0'; + else + return tolower (c) - 'a' + 10; +} + +/* As for strtoul, but for ULONGEST results. */ + +ULONGEST +strtoulst (const char *num, const char **trailer, int base) +{ + unsigned int high_part; + ULONGEST result; + int minus = 0; + int i = 0; + + /* Skip leading whitespace. */ + while (isspace (num[i])) + i++; + + /* Handle prefixes. */ + if (num[i] == '+') + i++; + else if (num[i] == '-') + { + minus = 1; + i++; + } + + if (base == 0 || base == 16) + { + if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X')) + { + i += 2; + if (base == 0) + base = 16; + } + } + + if (base == 0 && num[i] == '0') + base = 8; + + if (base == 0) + base = 10; + + if (base < 2 || base > 36) + { + errno = EINVAL; + return 0; + } + + result = high_part = 0; + for (; is_digit_in_base (num[i], base); i += 1) + { + result = result * base + digit_to_int (num[i]); + high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN); + result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1; + if (high_part > 0xff) + { + errno = ERANGE; + result = ~ (ULONGEST) 0; + high_part = 0; + minus = 0; + break; + } + } + + if (trailer != NULL) + *trailer = &num[i]; + + result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN); + if (minus) + return -result; + else + return result; +} + +/* Simple, portable version of dirname that does not modify its + argument. */ + +char * +ldirname (const char *filename) +{ + const char *base = lbasename (filename); + char *dirname; + + while (base > filename && IS_DIR_SEPARATOR (base[-1])) + --base; + + if (base == filename) + return NULL; + + dirname = xmalloc (base - filename + 2); + memcpy (dirname, filename, base - filename); + + /* On DOS based file systems, convert "d:foo" to "d:.", so that we + create "d:./bar" later instead of the (different) "d:/bar". */ + if (base - filename == 2 && IS_ABSOLUTE_PATH (base) + && !IS_DIR_SEPARATOR (filename[0])) + dirname[base++ - filename] = '.'; + + dirname[base - filename] = '\0'; + return dirname; +}