X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Futils.c;h=ba73d8d573423540dcadd9d7242392457e26ac1d;hb=f7926acf2069d786c592ea5beb5d35ee52711ed3;hp=1111eeacd2534ada0513e80ba7b40f3309d5c4a1;hpb=da59e08184255e09e51e54bb356e4448d33b2245;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/utils.c b/gdb/utils.c index 1111eeacd2..ba73d8d573 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1,5 +1,7 @@ /* General utility routines for GDB, the GNU debugger. - Copyright 1986, 89, 90, 91, 92, 95, 96, 1998 Free Software Foundation, Inc. + Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of GDB. @@ -19,6 +21,7 @@ Boston, MA 02111-1307, USA. */ #include "defs.h" +#include "gdb_assert.h" #include #include "gdb_string.h" #include "event-top.h" @@ -30,12 +33,16 @@ #include #endif +#ifdef __GO32__ +#include +#endif + /* SunOS's curses.h has a '#define reg register' in it. Thank you Sun. */ #ifdef reg #undef reg #endif -#include "signals.h" +#include #include "gdbcmd.h" #include "serial.h" #include "bfd.h" @@ -45,43 +52,50 @@ #include "language.h" #include "annotate.h" +#include "inferior.h" /* for signed_pointer_to_address */ + #include +#ifndef MALLOC_INCOMPATIBLE +#ifdef NEED_DECLARATION_MALLOC +extern PTR malloc (); +#endif +#ifdef NEED_DECLARATION_REALLOC +extern PTR realloc (); +#endif +#ifdef NEED_DECLARATION_FREE +extern void free (); +#endif +#endif + #undef XMALLOC #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) /* readline defines this. */ #undef savestring -void (*error_begin_hook) PARAMS ((void)); +void (*error_begin_hook) (void); /* Holds the last error message issued by gdb */ -static GDB_FILE *gdb_lasterr; +static struct ui_file *gdb_lasterr; /* Prototypes for local functions */ -static void vfprintf_maybe_filtered PARAMS ((GDB_FILE *, const char *, - va_list, int)); +static void vfprintf_maybe_filtered (struct ui_file *, const char *, + va_list, int); -static void fputs_maybe_filtered PARAMS ((const char *, GDB_FILE *, int)); +static void fputs_maybe_filtered (const char *, struct ui_file *, int); #if defined (USE_MMALLOC) && !defined (NO_MMCHECK) -static void malloc_botch PARAMS ((void)); +static void malloc_botch (void); #endif -static void -prompt_for_continue PARAMS ((void)); - -static void -set_width_command PARAMS ((char *, int, struct cmd_list_element *)); +static void prompt_for_continue (void); -static void -set_width PARAMS ((void)); +static void set_width_command (char *, int, struct cmd_list_element *); -#ifndef GDB_FILE_ISATTY -#define GDB_FILE_ISATTY(GDB_FILE_PTR) (gdb_file_isatty(GDB_FILE_PTR)) -#endif +static void set_width (void); /* Chain of cleanup actions established with make_cleanup, to be executed if an error happens. */ @@ -159,76 +173,90 @@ int pagination_enabled = 1; Args are FUNCTION to clean up with, and ARG to pass to it. */ struct cleanup * -make_cleanup (function, arg) - void (*function) PARAMS ((PTR)); - PTR arg; +make_cleanup (make_cleanup_ftype *function, void *arg) { return make_my_cleanup (&cleanup_chain, function, arg); } struct cleanup * -make_final_cleanup (function, arg) - void (*function) PARAMS ((PTR)); - PTR arg; +make_final_cleanup (make_cleanup_ftype *function, void *arg) { return make_my_cleanup (&final_cleanup_chain, function, arg); } struct cleanup * -make_run_cleanup (function, arg) - void (*function) PARAMS ((PTR)); - PTR arg; +make_run_cleanup (make_cleanup_ftype *function, void *arg) { return make_my_cleanup (&run_cleanup_chain, function, arg); } struct cleanup * -make_exec_cleanup (function, arg) - void (*function) PARAMS ((PTR)); - PTR arg; +make_exec_cleanup (make_cleanup_ftype *function, void *arg) { return make_my_cleanup (&exec_cleanup_chain, function, arg); } struct cleanup * -make_exec_error_cleanup (function, arg) - void (*function) PARAMS ((PTR)); - PTR arg; +make_exec_error_cleanup (make_cleanup_ftype *function, void *arg) { return make_my_cleanup (&exec_error_cleanup_chain, function, arg); } static void -do_freeargv (arg) - void *arg; +do_freeargv (void *arg) { freeargv ((char **) arg); } struct cleanup * -make_cleanup_freeargv (arg) - char **arg; +make_cleanup_freeargv (char **arg) { return make_my_cleanup (&cleanup_chain, do_freeargv, arg); } static void -do_gdb_file_delete (void *arg) +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) { - gdb_file_delete (arg); + ui_file_delete (arg); } struct cleanup * -make_cleanup_gdb_file_delete (struct gdb_file *arg) +make_cleanup_ui_file_delete (struct ui_file *arg) { - return make_my_cleanup (&cleanup_chain, do_gdb_file_delete, arg); + return make_my_cleanup (&cleanup_chain, do_ui_file_delete, arg); } struct cleanup * -make_my_cleanup (pmy_chain, function, arg) - struct cleanup **pmy_chain; - void (*function) PARAMS ((PTR)); - PTR arg; +make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function, + void *arg) { register struct cleanup *new = (struct cleanup *) xmalloc (sizeof (struct cleanup)); @@ -246,51 +274,45 @@ make_my_cleanup (pmy_chain, function, arg) until we get back to the point OLD_CHAIN in the cleanup_chain. */ void -do_cleanups (old_chain) - register struct cleanup *old_chain; +do_cleanups (register struct cleanup *old_chain) { do_my_cleanups (&cleanup_chain, old_chain); } void -do_final_cleanups (old_chain) - register struct cleanup *old_chain; +do_final_cleanups (register struct cleanup *old_chain) { do_my_cleanups (&final_cleanup_chain, old_chain); } void -do_run_cleanups (old_chain) - register struct cleanup *old_chain; +do_run_cleanups (register struct cleanup *old_chain) { do_my_cleanups (&run_cleanup_chain, old_chain); } void -do_exec_cleanups (old_chain) - register struct cleanup *old_chain; +do_exec_cleanups (register struct cleanup *old_chain) { do_my_cleanups (&exec_cleanup_chain, old_chain); } void -do_exec_error_cleanups (old_chain) - register struct cleanup *old_chain; +do_exec_error_cleanups (register struct cleanup *old_chain) { do_my_cleanups (&exec_error_cleanup_chain, old_chain); } void -do_my_cleanups (pmy_chain, old_chain) - register struct cleanup **pmy_chain; - register struct cleanup *old_chain; +do_my_cleanups (register struct cleanup **pmy_chain, + register struct cleanup *old_chain) { register struct cleanup *ptr; while ((ptr = *pmy_chain) != old_chain) { *pmy_chain = ptr->next; /* Do this first incase recursion */ (*ptr->function) (ptr->arg); - free (ptr); + xfree (ptr); } } @@ -298,55 +320,50 @@ do_my_cleanups (pmy_chain, old_chain) until we get back to the point OLD_CHAIN in the cleanup_chain. */ void -discard_cleanups (old_chain) - register struct cleanup *old_chain; +discard_cleanups (register struct cleanup *old_chain) { discard_my_cleanups (&cleanup_chain, old_chain); } void -discard_final_cleanups (old_chain) - register struct cleanup *old_chain; +discard_final_cleanups (register struct cleanup *old_chain) { discard_my_cleanups (&final_cleanup_chain, old_chain); } void -discard_exec_error_cleanups (old_chain) - register struct cleanup *old_chain; +discard_exec_error_cleanups (register struct cleanup *old_chain) { discard_my_cleanups (&exec_error_cleanup_chain, old_chain); } void -discard_my_cleanups (pmy_chain, old_chain) - register struct cleanup **pmy_chain; - register struct cleanup *old_chain; +discard_my_cleanups (register struct cleanup **pmy_chain, + register struct cleanup *old_chain) { register struct cleanup *ptr; while ((ptr = *pmy_chain) != old_chain) { *pmy_chain = ptr->next; - free ((PTR) ptr); + xfree (ptr); } } /* Set the cleanup_chain to 0, and return the old cleanup chain. */ struct cleanup * -save_cleanups () +save_cleanups (void) { return save_my_cleanups (&cleanup_chain); } struct cleanup * -save_final_cleanups () +save_final_cleanups (void) { return save_my_cleanups (&final_cleanup_chain); } struct cleanup * -save_my_cleanups (pmy_chain) - struct cleanup **pmy_chain; +save_my_cleanups (struct cleanup **pmy_chain) { struct cleanup *old_chain = *pmy_chain; @@ -356,23 +373,19 @@ save_my_cleanups (pmy_chain) /* Restore the cleanup chain from a previously saved chain. */ void -restore_cleanups (chain) - struct cleanup *chain; +restore_cleanups (struct cleanup *chain) { restore_my_cleanups (&cleanup_chain, chain); } void -restore_final_cleanups (chain) - struct cleanup *chain; +restore_final_cleanups (struct cleanup *chain) { restore_my_cleanups (&final_cleanup_chain, chain); } void -restore_my_cleanups (pmy_chain, chain) - struct cleanup **pmy_chain; - struct cleanup *chain; +restore_my_cleanups (struct cleanup **pmy_chain, struct cleanup *chain) { *pmy_chain = chain; } @@ -386,10 +399,17 @@ restore_my_cleanups (pmy_chain, chain) to arrange to free the object thus allocated. */ void -free_current_contents (location) - char **location; +free_current_contents (void *ptr) { - free (*location); + void **location = ptr; + if (location == NULL) + internal_error (__FILE__, __LINE__, + "free_current_contents: NULL pointer"); + if (*location != NULL) + { + xfree (*location); + *location = NULL; + } } /* Provide a known function that does nothing, to use as a base for @@ -401,17 +421,15 @@ free_current_contents (location) /* ARGSUSED */ void -null_cleanup (arg) - PTR arg; +null_cleanup (void *arg) { } -/* Add a continuation to the continuation list, the gloabl list +/* Add a continuation to the continuation list, the global list cmd_continuation. The new continuation will be added at the front.*/ void -add_continuation (continuation_hook, arg_list) - void (*continuation_hook) PARAMS ((struct continuation_arg *)); - struct continuation_arg *arg_list; +add_continuation (void (*continuation_hook) (struct continuation_arg *), + struct continuation_arg *arg_list) { struct continuation *continuation_ptr; @@ -431,7 +449,7 @@ add_continuation (continuation_hook, arg_list) and do the continuations from there on, instead of using the global beginning of list as our iteration pointer.*/ void -do_all_continuations () +do_all_continuations (void) { struct continuation *continuation_ptr; struct continuation *saved_continuation; @@ -449,14 +467,14 @@ do_all_continuations () (continuation_ptr->continuation_hook) (continuation_ptr->arg_list); saved_continuation = continuation_ptr; continuation_ptr = continuation_ptr->next; - free (saved_continuation); + xfree (saved_continuation); } } /* Walk down the cmd_continuation list, and get rid of all the continuations. */ void -discard_all_continuations () +discard_all_continuations (void) { struct continuation *continuation_ptr; @@ -464,16 +482,16 @@ discard_all_continuations () { continuation_ptr = cmd_continuation; cmd_continuation = continuation_ptr->next; - free (continuation_ptr); + xfree (continuation_ptr); } } -/* Add a continuation to the continuation list, the gloabl list +/* Add a continuation to the continuation list, the global list intermediate_continuation. The new continuation will be added at the front.*/ void -add_intermediate_continuation (continuation_hook, arg_list) - void (*continuation_hook) PARAMS ((struct continuation_arg *)); - struct continuation_arg *arg_list; +add_intermediate_continuation (void (*continuation_hook) + (struct continuation_arg *), + struct continuation_arg *arg_list) { struct continuation *continuation_ptr; @@ -493,7 +511,7 @@ add_intermediate_continuation (continuation_hook, arg_list) and do the continuations from there on, instead of using the global beginning of list as our iteration pointer.*/ void -do_all_intermediate_continuations () +do_all_intermediate_continuations (void) { struct continuation *continuation_ptr; struct continuation *saved_continuation; @@ -511,14 +529,14 @@ do_all_intermediate_continuations () (continuation_ptr->continuation_hook) (continuation_ptr->arg_list); saved_continuation = continuation_ptr; continuation_ptr = continuation_ptr->next; - free (saved_continuation); + xfree (saved_continuation); } } /* Walk down the cmd_continuation list, and get rid of all the continuations. */ void -discard_all_intermediate_continuations () +discard_all_intermediate_continuations (void) { struct continuation *continuation_ptr; @@ -526,7 +544,7 @@ discard_all_intermediate_continuations () { continuation_ptr = intermediate_continuation; intermediate_continuation = continuation_ptr->next; - free (continuation_ptr); + xfree (continuation_ptr); } } @@ -542,7 +560,7 @@ discard_all_intermediate_continuations () Is this anything other than a historical accident? */ void -warning_begin () +warning_begin (void) { target_terminal_ours (); wrap_here (""); /* Force out any buffered output */ @@ -581,7 +599,7 @@ warning (const char *string,...) that the error message can be formatted with a single printf call, but this is more general. */ void -error_begin () +error_begin (void) { if (error_begin_hook) error_begin_hook (); @@ -606,7 +624,7 @@ verror (const char *string, va_list args) char *err_string; struct cleanup *err_string_cleanup; /* FIXME: cagney/1999-11-10: All error calls should come here. - Unfortunatly some code uses the sequence: error_begin(); print + Unfortunately some code uses the sequence: error_begin(); print error message; return_to_top_level. That code should be flushed. */ error_begin (); @@ -617,11 +635,11 @@ verror (const char *string, va_list args) va_list twice which works on some platforms and fails miserably on others. */ /* Save it as the last error */ - gdb_file_rewind (gdb_lasterr); + ui_file_rewind (gdb_lasterr); vfprintf_filtered (gdb_lasterr, string, args); /* Retrieve the last error and print it to gdb_stderr */ err_string = error_last_message (); - err_string_cleanup = make_cleanup (free, err_string); + err_string_cleanup = make_cleanup (xfree, err_string); fputs_filtered (err_string, gdb_stderr); fprintf_filtered (gdb_stderr, "\n"); do_cleanups (err_string_cleanup); @@ -638,11 +656,11 @@ error (const char *string,...) } NORETURN void -error_stream (GDB_FILE *stream) +error_stream (struct ui_file *stream) { long size; - char *msg = gdb_file_xstrdup (stream, &size); - make_cleanup (free, msg); + char *msg = ui_file_xstrdup (stream, &size); + make_cleanup (xfree, msg); error ("%s", msg); } @@ -652,7 +670,7 @@ char * error_last_message (void) { long len; - return gdb_file_xstrdup (gdb_lasterr, &len); + return ui_file_xstrdup (gdb_lasterr, &len); } /* This is to be called by main() at the very beginning */ @@ -667,7 +685,8 @@ error_init (void) want to continue, dump core, or just exit. */ NORETURN void -internal_verror (const char *fmt, va_list ap) +internal_verror (const char *file, int line, + const char *fmt, va_list ap) { static char msg[] = "Internal GDB error: recursive internal error.\n"; static int dejavu = 0; @@ -683,7 +702,7 @@ internal_verror (const char *fmt, va_list ap) case 1: dejavu = 2; fputs_unfiltered (msg, gdb_stderr); - abort (); + internal_error (__FILE__, __LINE__, "failed internal consistency check"); default: dejavu = 3; write (STDERR_FILENO, msg, sizeof (msg)); @@ -691,14 +710,15 @@ internal_verror (const char *fmt, va_list ap) } /* Try to get the message out */ - fputs_unfiltered ("gdb-internal-error: ", gdb_stderr); + target_terminal_ours (); + fprintf_unfiltered (gdb_stderr, "%s:%d: gdb-internal-error: ", file, line); vfprintf_unfiltered (gdb_stderr, fmt, ap); fputs_unfiltered ("\n", gdb_stderr); /* Default (no case) is to quit GDB. When in batch mode this lessens the likelhood of GDB going into an infinate loop. */ continue_p = query ("\ -An internal GDB error was detected. This may make make further\n\ +An internal GDB error was detected. This may make further\n\ debugging unreliable. Continue this debugging session? "); /* Default (no case) is to not dump core. Lessen the chance of GDB @@ -711,13 +731,13 @@ Create a core file containing the current state of GDB? "); if (dump_core_p) { if (fork () == 0) - abort (); + internal_error (__FILE__, __LINE__, "failed internal consistency check"); } } else { if (dump_core_p) - abort (); + internal_error (__FILE__, __LINE__, "failed internal consistency check"); else exit (1); } @@ -727,11 +747,12 @@ Create a core file containing the current state of GDB? "); } NORETURN void -internal_error (char *string, ...) +internal_error (const char *file, int line, const char *string, ...) { va_list ap; va_start (ap, string); - internal_verror (string, ap); + + internal_verror (file, line, string, ap); va_end (ap); } @@ -740,8 +761,7 @@ internal_error (char *string, ...) printable string. */ char * -safe_strerror (errnum) - int errnum; +safe_strerror (int errnum) { char *msg; static char buf[32]; @@ -754,33 +774,12 @@ safe_strerror (errnum) return (msg); } -/* The strsignal() function can return NULL for signal values that are - out of range. Provide a "safe" version that always returns a - printable string. */ - -char * -safe_strsignal (signo) - int signo; -{ - char *msg; - static char buf[32]; - - if ((msg = strsignal (signo)) == NULL) - { - sprintf (buf, "(undocumented signal %d)", signo); - 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. */ NORETURN void -perror_with_name (string) - char *string; +perror_with_name (char *string) { char *err; char *combined; @@ -804,9 +803,7 @@ perror_with_name (string) as the file name for which the error was encountered. */ void -print_sys_errmsg (string, errcode) - char *string; - int errcode; +print_sys_errmsg (char *string, int errcode) { char *err; char *combined; @@ -826,9 +823,9 @@ print_sys_errmsg (string, errcode) /* Control C eventually causes this to be called, at a convenient time. */ void -quit () +quit (void) { - serial_t gdb_stdout_serial = serial_fdopen (1); + struct serial *gdb_stdout_serial = serial_fdopen (1); target_terminal_ours (); @@ -845,8 +842,8 @@ quit () gdb_flush (gdb_stderr); /* 3. The system-level buffer. */ - SERIAL_DRAIN_OUTPUT (gdb_stdout_serial); - SERIAL_UN_FDOPEN (gdb_stdout_serial); + serial_drain_output (gdb_stdout_serial); + serial_un_fdopen (gdb_stdout_serial); annotate_error_begin (); @@ -871,39 +868,9 @@ quit () return_to_top_level (RETURN_QUIT); } - -#if defined(_MSC_VER) /* should test for wingdb instead? */ - -/* - * Windows translates all keyboard and mouse events - * into a message which is appended to the message - * queue for the process. - */ - -void -notice_quit () -{ - int k = win32pollquit (); - if (k == 1) - quit_flag = 1; - else if (k == 2) - immediate_quit = 1; -} - -#else /* !defined(_MSC_VER) */ - -void -notice_quit () -{ - /* Done by signals */ -} - -#endif /* !defined(_MSC_VER) */ - /* Control C comes here */ void -request_quit (signo) - int signo; +request_quit (int signo) { quit_flag = 1; /* Restore the signal handler. Harmless with BSD-style signals, needed @@ -921,48 +888,36 @@ request_quit (signo) /* Memory management stuff (malloc friends). */ -/* Make a substitute size_t for non-ANSI compilers. */ - -#ifndef HAVE_STDDEF_H -#ifndef size_t -#define size_t unsigned int -#endif -#endif - #if !defined (USE_MMALLOC) -void * -mcalloc (void *md, size_t number, size_t size) -{ - return calloc (number, size); -} +/* NOTE: These must use PTR so that their definition matches the + declaration found in "mmalloc.h". */ PTR -mmalloc (md, size) - PTR md; - size_t size; +mmalloc (PTR md, size_t size) { - return malloc (size); + return malloc (size); /* NOTE: GDB's only call to malloc() */ } PTR -mrealloc (md, ptr, size) - PTR md; - PTR ptr; - size_t size; +mrealloc (PTR md, PTR ptr, size_t size) { if (ptr == 0) /* Guard against old realloc's */ - return malloc (size); + return mmalloc (md, size); else - return realloc (ptr, size); + return realloc (ptr, size); /* NOTE: GDB's only call to ralloc() */ +} + +PTR +mcalloc (PTR md, size_t number, size_t size) +{ + return calloc (number, size); /* NOTE: GDB's only call to calloc() */ } void -mfree (md, ptr) - PTR md; - PTR ptr; +mfree (PTR md, PTR ptr) { - free (ptr); + free (ptr); /* NOTE: GDB's only call to free() */ } #endif /* USE_MMALLOC */ @@ -970,18 +925,17 @@ mfree (md, ptr) #if !defined (USE_MMALLOC) || defined (NO_MMCHECK) void -init_malloc (md) - PTR md; +init_malloc (void *md) { } #else /* Have mmalloc and want corruption checking */ static void -malloc_botch () +malloc_botch (void) { fprintf_unfiltered (gdb_stderr, "Memory corruption\n"); - abort (); + internal_error (__FILE__, __LINE__, "failed internal consistency check"); } /* Attempt to install hooks in mmalloc/mrealloc/mfree for the heap specified @@ -1003,8 +957,7 @@ malloc_botch () #endif void -init_malloc (md) - PTR md; +init_malloc (void *md) { if (!mmcheckf (md, malloc_botch, MMCHECK_FORCE)) { @@ -1027,107 +980,171 @@ init_malloc (md) memory requested in SIZE. */ NORETURN void -nomem (size) - long size; +nomem (long size) { if (size > 0) { - internal_error ("virtual memory exhausted: can't allocate %ld bytes.", size); + internal_error (__FILE__, __LINE__, + "virtual memory exhausted: can't allocate %ld bytes.", size); } else { - internal_error ("virtual memory exhausted."); + internal_error (__FILE__, __LINE__, + "virtual memory exhausted."); } } -/* Like mmalloc but get error if no storage available, and protect against - the caller wanting to allocate zero bytes. Whether to return NULL for - a zero byte request, or translate the request into a request for one - byte of zero'd storage, is a religious issue. */ +/* The xmmalloc() family of memory management routines. -PTR -xmmalloc (md, size) - PTR md; - long size; + These are are like the mmalloc() 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. + + All these routines are implemented using the mmalloc() family. */ + +void * +xmmalloc (void *md, size_t size) { - register PTR val; + void *val; if (size == 0) { val = NULL; } - else if ((val = mmalloc (md, size)) == NULL) + else { - nomem (size); + val = mmalloc (md, size); + if (val == NULL) + nomem (size); } return (val); } -/* Like mrealloc but get error if no storage available. */ - -PTR -xmrealloc (md, ptr, size) - PTR md; - PTR ptr; - long size; +void * +xmrealloc (void *md, void *ptr, size_t size) { - register PTR val; + void *val; - if (ptr != NULL) + if (size == 0) { - val = mrealloc (md, ptr, size); + if (ptr != NULL) + mfree (md, ptr); + val = NULL; } else { - val = mmalloc (md, size); + if (ptr != NULL) + { + val = mrealloc (md, ptr, size); + } + else + { + val = mmalloc (md, size); + } + if (val == NULL) + { + nomem (size); + } } - if (val == NULL) + return (val); +} + +void * +xmcalloc (void *md, size_t number, size_t size) +{ + void *mem; + if (number == 0 || size == 0) + mem = NULL; + else { - nomem (size); + mem = mcalloc (md, number, size); + if (mem == NULL) + nomem (number * size); } - return (val); + return mem; +} + +void +xmfree (void *md, void *ptr) +{ + if (ptr != NULL) + mfree (md, ptr); } -/* Like malloc but get error if no storage available, and protect against - the caller wanting to allocate zero bytes. */ +/* 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 -xmalloc (size) - size_t size; +xmalloc (size_t size) { - return (xmmalloc ((PTR) NULL, size)); + return xmmalloc (NULL, size); } -/* Like calloc but get error if no storage available */ +PTR +xrealloc (PTR ptr, size_t size) +{ + return xmrealloc (NULL, ptr, size); +} PTR xcalloc (size_t number, size_t size) { - void *mem = mcalloc (NULL, number, size); - if (mem == NULL) - nomem (number * size); - return mem; + return xmcalloc (NULL, number, size); } -/* Like mrealloc but get error if no storage available. */ - -PTR -xrealloc (ptr, size) - PTR ptr; - size_t size; +void +xfree (void *ptr) { - return (xmrealloc ((PTR) NULL, ptr, size)); + xmfree (NULL, ptr); } +/* Like asprintf/vasprintf but get an internal_error if the call + fails. */ + +void +xasprintf (char **ret, const char *format, ...) +{ + va_list args; + va_start (args, format); + xvasprintf (ret, 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); +} + + /* My replacement for the read system call. Used like `read' but keeps going if `read' returns too soon. */ int -myread (desc, addr, len) - int desc; - char *addr; - int len; +myread (int desc, char *addr, int len) { register int val; int orglen = len; @@ -1150,9 +1167,7 @@ myread (desc, addr, len) Uses malloc to get the space. Returns the address of the copy. */ char * -savestring (ptr, size) - const char *ptr; - int size; +savestring (const char *ptr, size_t size) { register char *p = (char *) xmalloc (size + 1); memcpy (p, ptr, size); @@ -1161,10 +1176,7 @@ savestring (ptr, size) } char * -msavestring (md, ptr, size) - PTR md; - const char *ptr; - int size; +msavestring (void *md, const char *ptr, size_t size) { register char *p = (char *) xmmalloc (md, size + 1); memcpy (p, ptr, size); @@ -1172,28 +1184,14 @@ msavestring (md, ptr, size) return p; } -/* The "const" is so it compiles under DGUX (which prototypes strsave - in . FIXME: This should be named "xstrsave", shouldn't it? - Doesn't real strsave return NULL if out of memory? */ -char * -strsave (ptr) - const char *ptr; -{ - return savestring (ptr, strlen (ptr)); -} - char * -mstrsave (md, ptr) - PTR md; - const char *ptr; +mstrsave (void *md, const char *ptr) { return (msavestring (md, ptr, strlen (ptr))); } void -print_spaces (n, file) - register int n; - register GDB_FILE *file; +print_spaces (register int n, register struct ui_file *file) { fputs_unfiltered (n_spaces (n), file); } @@ -1201,7 +1199,7 @@ print_spaces (n, file) /* Print a host address. */ void -gdb_print_host_address (void *addr, struct gdb_file *stream) +gdb_print_host_address (void *addr, struct ui_file *stream) { /* We could use the %p conversion specifier to fprintf if we had any @@ -1235,11 +1233,11 @@ query (char *ctlstr,...) /* Automatically answer "yes" if input is not from a terminal. */ if (!input_from_terminal_p ()) return 1; -#ifdef MPW - /* FIXME Automatically answer "yes" if called from MacGDB. */ - if (mac_app) - return 1; -#endif /* MPW */ + /* OBSOLETE #ifdef MPW */ + /* OBSOLETE *//* FIXME Automatically answer "yes" if called from MacGDB. */ + /* OBSOLETE if (mac_app) */ + /* OBSOLETE return 1; */ + /* OBSOLETE #endif *//* MPW */ while (1) { @@ -1255,25 +1253,17 @@ query (char *ctlstr,...) if (annotation_level > 1) printf_filtered ("\n\032\032query\n"); -#ifdef MPW - /* If not in MacGDB, move to a new line so the entered line doesn't - have a prompt on the front of it. */ - if (!mac_app) - fputs_unfiltered ("\n", gdb_stdout); -#endif /* MPW */ + /* OBSOLETE #ifdef MPW */ + /* OBSOLETE *//* If not in MacGDB, move to a new line so the entered line doesn't */ + /* OBSOLETE have a prompt on the front of it. */ + /* OBSOLETE if (!mac_app) */ + /* OBSOLETE fputs_unfiltered ("\n", gdb_stdout); */ + /* OBSOLETE #endif *//* MPW */ wrap_here (""); gdb_flush (gdb_stdout); -#if defined(TUI) - if (!tui_version || cmdWin == tuiWinWithFocus ()) -#endif - answer = fgetc (stdin); -#if defined(TUI) - else - answer = (unsigned char) tuiBufferGetc (); - -#endif + answer = fgetc (stdin); clearerr (stdin); /* in case of C-d */ if (answer == EOF) /* C-d */ { @@ -1281,21 +1271,13 @@ query (char *ctlstr,...) break; } /* Eat rest of input line, to EOF or newline */ - if ((answer != '\n') || (tui_version && answer != '\r')) + if (answer != '\n') do { -#if defined(TUI) - if (!tui_version || cmdWin == tuiWinWithFocus ()) -#endif - ans2 = fgetc (stdin); -#if defined(TUI) - else - ans2 = (unsigned char) tuiBufferGetc (); -#endif + ans2 = fgetc (stdin); clearerr (stdin); } while (ans2 != EOF && ans2 != '\n' && ans2 != '\r'); - TUIDO (((TuiOpaqueFuncPtr) tui_vStartNewLines, 1)); if (answer >= 'a') answer -= 040; @@ -1334,8 +1316,7 @@ query (char *ctlstr,...) after the zeros. A value of 0 does not mean end of string. */ int -parse_escape (string_ptr) - char **string_ptr; +parse_escape (char **string_ptr) { register int c = *(*string_ptr)++; switch (c) @@ -1405,15 +1386,10 @@ parse_escape (string_ptr) be call for printing things which are independent of the language of the program being debugged. */ -static void printchar PARAMS ((int c, void (*do_fputs) (const char *, GDB_FILE*), void (*do_fprintf) (GDB_FILE*, const char *, ...), GDB_FILE *stream, int quoter)); - static void -printchar (c, do_fputs, do_fprintf, stream, quoter) - int c; - void (*do_fputs) PARAMS ((const char *, GDB_FILE*)); - void (*do_fprintf) PARAMS ((GDB_FILE*, const char *, ...)); - GDB_FILE *stream; - int quoter; +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) { c &= 0xFF; /* Avoid sign bit follies */ @@ -1464,31 +1440,21 @@ printchar (c, do_fputs, do_fprintf, stream, quoter) the language of the program being debugged. */ void -fputstr_filtered (str, quoter, stream) - const char *str; - int quoter; - GDB_FILE *stream; +fputstr_filtered (const char *str, int quoter, struct ui_file *stream) { while (*str) printchar (*str++, fputs_filtered, fprintf_filtered, stream, quoter); } void -fputstr_unfiltered (str, quoter, stream) - const char *str; - int quoter; - GDB_FILE *stream; +fputstr_unfiltered (const char *str, int quoter, struct ui_file *stream) { while (*str) printchar (*str++, fputs_unfiltered, fprintf_unfiltered, stream, quoter); } void -fputstrn_unfiltered (str, n, quoter, stream) - const char *str; - int n; - int quoter; - GDB_FILE *stream; +fputstrn_unfiltered (const char *str, int n, int quoter, struct ui_file *stream) { int i; for (i = 0; i < n; i++) @@ -1499,7 +1465,7 @@ fputstrn_unfiltered (str, n, quoter, stream) /* Number of lines per page or UINT_MAX if paging is disabled. */ static unsigned int lines_per_page; -/* Number of chars per line or UNIT_MAX if line folding is disabled. */ +/* Number of chars per line or UINT_MAX if line folding is disabled. */ static unsigned int chars_per_line; /* Current count of lines printed on this page, chars on this line. */ static unsigned int lines_printed, chars_printed; @@ -1531,15 +1497,10 @@ static int wrap_column; /* Inialize the lines and chars per page */ void -init_page_info () +init_page_info (void) { #if defined(TUI) - if (tui_version && m_winPtrNotNull (cmdWin)) - { - lines_per_page = cmdWin->generic.height; - chars_per_line = cmdWin->generic.width; - } - else + if (!tui_get_command_dimension (&chars_per_line, &lines_per_page)) #endif { /* These defaults will be used if we are unable to get the correct @@ -1551,7 +1512,7 @@ init_page_info () lines_per_page = 24; chars_per_line = 80; -#if !defined (MPW) && !defined (_WIN32) +#if !defined (_WIN32) /* No termcap under MPW, although might be cool to do something by looking at worksheet or console window sizes. */ /* Initialize the screen height and width from termcap. */ @@ -1598,14 +1559,14 @@ init_page_info () #endif #endif /* If the output is not a terminal, don't paginate it. */ - if (!GDB_FILE_ISATTY (gdb_stdout)) + if (!ui_file_isatty (gdb_stdout)) lines_per_page = UINT_MAX; } /* the command_line_version */ set_width (); } static void -set_width () +set_width (void) { if (chars_per_line == 0) init_page_info (); @@ -1622,10 +1583,7 @@ set_width () /* ARGSUSED */ static void -set_width_command (args, from_tty, c) - char *args; - int from_tty; - struct cmd_list_element *c; +set_width_command (char *args, int from_tty, struct cmd_list_element *c) { set_width (); } @@ -1634,7 +1592,7 @@ set_width_command (args, from_tty, c) to continue by pressing RETURN. */ static void -prompt_for_continue () +prompt_for_continue (void) { char *ignore; char cont_prompt[120]; @@ -1680,7 +1638,7 @@ prompt_for_continue () else async_request_quit (0); } - free (ignore); + xfree (ignore); } immediate_quit--; @@ -1694,7 +1652,7 @@ prompt_for_continue () /* Reinitialize filter; ie. tell it to reset to original values. */ void -reinitialize_more_filter () +reinitialize_more_filter (void) { lines_printed = 0; chars_printed = 0; @@ -1722,12 +1680,11 @@ reinitialize_more_filter () used to force out output from the wrap_buffer. */ void -wrap_here (indent) - char *indent; +wrap_here (char *indent) { /* This should have been allocated, but be paranoid anyway. */ if (!wrap_buffer) - abort (); + internal_error (__FILE__, __LINE__, "failed internal consistency check"); if (wrap_buffer[0]) { @@ -1763,7 +1720,7 @@ wrap_here (indent) line. Otherwise do nothing. */ void -begin_line () +begin_line (void) { if (chars_printed > 0) { @@ -1786,10 +1743,8 @@ begin_line () routine should not be called when cleanups are not in place. */ static void -fputs_maybe_filtered (linebuffer, stream, filter) - const char *linebuffer; - GDB_FILE *stream; - int filter; +fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream, + int filter) { const char *lineptr; @@ -1890,36 +1845,38 @@ fputs_maybe_filtered (linebuffer, stream, filter) } void -fputs_filtered (linebuffer, stream) - const char *linebuffer; - GDB_FILE *stream; +fputs_filtered (const char *linebuffer, struct ui_file *stream) { fputs_maybe_filtered (linebuffer, stream, 1); } int -putchar_unfiltered (c) - int c; +putchar_unfiltered (int c) { char buf = c; - gdb_file_write (gdb_stdout, &buf, 1); + ui_file_write (gdb_stdout, &buf, 1); return c; } +/* Write character C to gdb_stdout using GDB's paging mechanism and return C. + May return nonlocally. */ + int -fputc_unfiltered (c, stream) - int c; - GDB_FILE *stream; +putchar_filtered (int c) +{ + return fputc_filtered (c, gdb_stdout); +} + +int +fputc_unfiltered (int c, struct ui_file *stream) { char buf = c; - gdb_file_write (stream, &buf, 1); + ui_file_write (stream, &buf, 1); return c; } int -fputc_filtered (c, stream) - int c; - GDB_FILE *stream; +fputc_filtered (int c, struct ui_file *stream) { char buf[2]; @@ -1933,10 +1890,7 @@ fputc_filtered (c, stream) characters in printable fashion. */ void -puts_debug (prefix, string, suffix) - char *prefix; - char *string; - char *suffix; +puts_debug (char *prefix, char *string, char *suffix) { int ch; @@ -2032,74 +1986,51 @@ puts_debug (prefix, string, suffix) called when cleanups are not in place. */ static void -vfprintf_maybe_filtered (stream, format, args, filter) - GDB_FILE *stream; - const char *format; - va_list args; - int filter; +vfprintf_maybe_filtered (struct ui_file *stream, const char *format, + va_list args, int filter) { char *linebuffer; struct cleanup *old_cleanups; - vasprintf (&linebuffer, format, args); - if (linebuffer == NULL) - { - fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr); - exit (1); - } - old_cleanups = make_cleanup (free, linebuffer); + xvasprintf (&linebuffer, format, args); + old_cleanups = make_cleanup (xfree, linebuffer); fputs_maybe_filtered (linebuffer, stream, filter); do_cleanups (old_cleanups); } void -vfprintf_filtered (stream, format, args) - GDB_FILE *stream; - const char *format; - va_list args; +vfprintf_filtered (struct ui_file *stream, const char *format, va_list args) { vfprintf_maybe_filtered (stream, format, args, 1); } void -vfprintf_unfiltered (stream, format, args) - GDB_FILE *stream; - const char *format; - va_list args; +vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args) { char *linebuffer; struct cleanup *old_cleanups; - vasprintf (&linebuffer, format, args); - if (linebuffer == NULL) - { - fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr); - exit (1); - } - old_cleanups = make_cleanup (free, linebuffer); + xvasprintf (&linebuffer, format, args); + old_cleanups = make_cleanup (xfree, linebuffer); fputs_unfiltered (linebuffer, stream); do_cleanups (old_cleanups); } void -vprintf_filtered (format, args) - const char *format; - va_list args; +vprintf_filtered (const char *format, va_list args) { vfprintf_maybe_filtered (gdb_stdout, format, args, 1); } void -vprintf_unfiltered (format, args) - const char *format; - va_list args; +vprintf_unfiltered (const char *format, va_list args) { vfprintf_unfiltered (gdb_stdout, format, args); } void -fprintf_filtered (GDB_FILE * stream, const char *format,...) +fprintf_filtered (struct ui_file * stream, const char *format,...) { va_list args; va_start (args, format); @@ -2108,7 +2039,7 @@ fprintf_filtered (GDB_FILE * stream, const char *format,...) } void -fprintf_unfiltered (GDB_FILE * stream, const char *format,...) +fprintf_unfiltered (struct ui_file * stream, const char *format,...) { va_list args; va_start (args, format); @@ -2120,7 +2051,7 @@ fprintf_unfiltered (GDB_FILE * stream, const char *format,...) Called as fprintfi_filtered (spaces, stream, format, ...); */ void -fprintfi_filtered (int spaces, GDB_FILE * stream, const char *format,...) +fprintfi_filtered (int spaces, struct ui_file * stream, const char *format,...) { va_list args; va_start (args, format); @@ -2169,15 +2100,13 @@ printfi_filtered (int spaces, const char *format,...) This one doesn't, and had better not! */ void -puts_filtered (string) - const char *string; +puts_filtered (const char *string) { fputs_filtered (string, gdb_stdout); } void -puts_unfiltered (string) - const char *string; +puts_unfiltered (const char *string) { fputs_unfiltered (string, gdb_stdout); } @@ -2185,8 +2114,7 @@ puts_unfiltered (string) /* Return a pointer to N spaces and a null. The pointer is good until the next call to here. */ char * -n_spaces (n) - int n; +n_spaces (int n) { char *t; static char *spaces = 0; @@ -2195,7 +2123,7 @@ n_spaces (n) if (n > max_spaces) { if (spaces) - free (spaces); + xfree (spaces); spaces = (char *) xmalloc (n + 1); for (t = spaces + n; t != spaces;) *--t = ' '; @@ -2208,9 +2136,7 @@ n_spaces (n) /* Print N spaces. */ void -print_spaces_filtered (n, stream) - int n; - GDB_FILE *stream; +print_spaces_filtered (int n, struct ui_file *stream) { fputs_filtered (n_spaces (n), stream); } @@ -2223,11 +2149,8 @@ print_spaces_filtered (n, stream) demangling is off, the name is printed in its "raw" form. */ void -fprintf_symbol_filtered (stream, name, lang, arg_mode) - GDB_FILE *stream; - char *name; - enum language lang; - int arg_mode; +fprintf_symbol_filtered (struct ui_file *stream, char *name, enum language lang, + int arg_mode) { char *demangled; @@ -2258,7 +2181,7 @@ fprintf_symbol_filtered (stream, name, lang, arg_mode) fputs_filtered (demangled ? demangled : name, stream); if (demangled != NULL) { - free (demangled); + xfree (demangled); } } } @@ -2274,9 +2197,7 @@ fprintf_symbol_filtered (stream, name, lang, arg_mode) function). */ int -strcmp_iw (string1, string2) - const char *string1; - const char *string2; +strcmp_iw (const char *string1, const char *string2) { while ((*string1 != '\0') && (*string2 != '\0')) { @@ -2309,9 +2230,7 @@ strcmp_iw (string1, string2) ** at index 0. */ int -subset_compare (string_to_compare, template_string) - char *string_to_compare; - char *template_string; +subset_compare (char *string_to_compare, char *template_string) { int match; if (template_string != (char *) NULL && string_to_compare != (char *) NULL && @@ -2325,27 +2244,23 @@ subset_compare (string_to_compare, template_string) } -static void pagination_on_command PARAMS ((char *arg, int from_tty)); +static void pagination_on_command (char *arg, int from_tty); static void -pagination_on_command (arg, from_tty) - char *arg; - int from_tty; +pagination_on_command (char *arg, int from_tty) { pagination_enabled = 1; } -static void pagination_on_command PARAMS ((char *arg, int from_tty)); +static void pagination_on_command (char *arg, int from_tty); static void -pagination_off_command (arg, from_tty) - char *arg; - int from_tty; +pagination_off_command (char *arg, int from_tty) { pagination_enabled = 0; } void -initialize_utils () +initialize_utils (void) { struct cmd_list_element *c; @@ -2365,7 +2280,7 @@ initialize_utils () init_page_info (); /* If the output is not a terminal, don't paginate it. */ - if (!GDB_FILE_ISATTY (gdb_stdout)) + if (!ui_file_isatty (gdb_stdout)) lines_per_page = UINT_MAX; set_width_command ((char *) NULL, 0, c); @@ -2382,6 +2297,7 @@ initialize_utils () var_boolean, (char *) &pagination_enabled, "Set state of pagination.", &setlist), &showlist); + if (xdb_commands) { add_com ("am", class_support, pagination_on_command, @@ -2410,433 +2326,14 @@ initialize_utils () #ifdef SIGWINCH_HANDLER_BODY SIGWINCH_HANDLER_BODY #endif - -/* Support for converting target fp numbers into host DOUBLEST format. */ - -/* XXX - This code should really be in libiberty/floatformat.c, however - configuration issues with libiberty made this very difficult to do in the - available time. */ - -#include "floatformat.h" -#include /* ldexp */ - -/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not - going to bother with trying to muck around with whether it is defined in - a system header, what we do if not, etc. */ -#define FLOATFORMAT_CHAR_BIT 8 - -static unsigned long get_field PARAMS ((unsigned char *, - enum floatformat_byteorders, - unsigned int, - unsigned int, - unsigned int)); - -/* Extract a field which starts at START and is LEN bytes long. DATA and - TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ -static unsigned long -get_field (data, order, total_len, start, len) - unsigned char *data; - enum floatformat_byteorders order; - unsigned int total_len; - unsigned int start; - unsigned int len; -{ - unsigned long result; - unsigned int cur_byte; - int cur_bitshift; - - /* Start at the least significant part of the field. */ - if (order == floatformat_little || order == floatformat_littlebyte_bigword) - { - /* We start counting from the other end (i.e, from the high bytes - rather than the low bytes). As such, we need to be concerned - with what happens if bit 0 doesn't start on a byte boundary. - I.e, we need to properly handle the case where total_len is - not evenly divisible by 8. So we compute ``excess'' which - represents the number of bits from the end of our starting - byte needed to get to bit 0. */ - int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); - cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - - ((start + len + excess) / FLOATFORMAT_CHAR_BIT); - cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) - - FLOATFORMAT_CHAR_BIT; - } - else - { - cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; - cur_bitshift = - ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; - } - if (cur_bitshift > -FLOATFORMAT_CHAR_BIT) - result = *(data + cur_byte) >> (-cur_bitshift); - else - result = 0; - cur_bitshift += FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little || order == floatformat_littlebyte_bigword) - ++cur_byte; - else - --cur_byte; - - /* Move towards the most significant part of the field. */ - while (cur_bitshift < len) - { - result |= (unsigned long)*(data + cur_byte) << cur_bitshift; - cur_bitshift += FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little || order == floatformat_littlebyte_bigword) - ++cur_byte; - else - --cur_byte; - } - if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT) - /* Mask out bits which are not part of the field */ - result &= ((1UL << len) - 1); - return result; -} - -/* Convert from FMT to a DOUBLEST. - FROM is the address of the extended float. - Store the DOUBLEST in *TO. */ -void -floatformat_to_doublest (fmt, from, to) - const struct floatformat *fmt; - char *from; - DOUBLEST *to; -{ - unsigned char *ufrom = (unsigned char *) from; - DOUBLEST dto; - long exponent; - unsigned long mant; - unsigned int mant_bits, mant_off; - int mant_bits_left; - int special_exponent; /* It's a NaN, denorm or zero */ - - /* If the mantissa bits are not contiguous from one end of the - mantissa to the other, we need to make a private copy of the - source bytes that is in the right order since the unpacking - algorithm assumes that the bits are contiguous. - - Swap the bytes individually rather than accessing them through - "long *" since we have no guarantee that they start on a long - alignment, and also sizeof(long) for the host could be different - than sizeof(long) for the target. FIXME: Assumes sizeof(long) - for the target is 4. */ - - if (fmt->byteorder == floatformat_littlebyte_bigword) - { - static unsigned char *newfrom; - unsigned char *swapin, *swapout; - int longswaps; - - longswaps = fmt->totalsize / FLOATFORMAT_CHAR_BIT; - longswaps >>= 3; - - if (newfrom == NULL) - { - newfrom = (unsigned char *) xmalloc (fmt->totalsize); - } - swapout = newfrom; - swapin = ufrom; - ufrom = newfrom; - while (longswaps-- > 0) - { - /* This is ugly, but efficient */ - *swapout++ = swapin[4]; - *swapout++ = swapin[5]; - *swapout++ = swapin[6]; - *swapout++ = swapin[7]; - *swapout++ = swapin[0]; - *swapout++ = swapin[1]; - *swapout++ = swapin[2]; - *swapout++ = swapin[3]; - swapin += 8; - } - } - - exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, - fmt->exp_start, fmt->exp_len); - /* Note that if exponent indicates a NaN, we can't really do anything useful - (not knowing if the host has NaN's, or how to build one). So it will - end up as an infinity or something close; that is OK. */ - - mant_bits_left = fmt->man_len; - mant_off = fmt->man_start; - dto = 0.0; - - special_exponent = exponent == 0 || exponent == fmt->exp_nan; - -/* Don't bias NaNs. Use minimum exponent for denorms. For simplicity, - we don't check for zero as the exponent doesn't matter. */ - if (!special_exponent) - exponent -= fmt->exp_bias; - else if (exponent == 0) - exponent = 1 - fmt->exp_bias; - - /* Build the result algebraically. Might go infinite, underflow, etc; - who cares. */ - -/* If this format uses a hidden bit, explicitly add it in now. Otherwise, - increment the exponent by one to account for the integer bit. */ - - if (!special_exponent) - { - if (fmt->intbit == floatformat_intbit_no) - dto = ldexp (1.0, exponent); - else - exponent++; - } - - while (mant_bits_left > 0) - { - mant_bits = min (mant_bits_left, 32); - - mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, - mant_off, mant_bits); - - dto += ldexp ((double) mant, exponent - mant_bits); - exponent -= mant_bits; - mant_off += mant_bits; - mant_bits_left -= mant_bits; - } - - /* Negate it if negative. */ - if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) - dto = -dto; - *to = dto; -} - -static void put_field PARAMS ((unsigned char *, enum floatformat_byteorders, - unsigned int, - unsigned int, - unsigned int, - unsigned long)); - -/* Set a field which starts at START and is LEN bytes long. DATA and - TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ -static void -put_field (data, order, total_len, start, len, stuff_to_put) - unsigned char *data; - enum floatformat_byteorders order; - unsigned int total_len; - unsigned int start; - unsigned int len; - unsigned long stuff_to_put; -{ - unsigned int cur_byte; - int cur_bitshift; - - /* Start at the least significant part of the field. */ - if (order == floatformat_little || order == floatformat_littlebyte_bigword) - { - int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); - cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - - ((start + len + excess) / FLOATFORMAT_CHAR_BIT); - cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT) - - FLOATFORMAT_CHAR_BIT; - } - else - { - cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; - cur_bitshift = - ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; - } - if (cur_bitshift > -FLOATFORMAT_CHAR_BIT) - { - *(data + cur_byte) &= - ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) - << (-cur_bitshift)); - *(data + cur_byte) |= - (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift); - } - cur_bitshift += FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little || order == floatformat_littlebyte_bigword) - ++cur_byte; - else - --cur_byte; - - /* Move towards the most significant part of the field. */ - while (cur_bitshift < len) - { - if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT) - { - /* This is the last byte. */ - *(data + cur_byte) &= - ~((1 << (len - cur_bitshift)) - 1); - *(data + cur_byte) |= (stuff_to_put >> cur_bitshift); - } - else - *(data + cur_byte) = ((stuff_to_put >> cur_bitshift) - & ((1 << FLOATFORMAT_CHAR_BIT) - 1)); - cur_bitshift += FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little || order == floatformat_littlebyte_bigword) - ++cur_byte; - else - --cur_byte; - } -} - -#ifdef HAVE_LONG_DOUBLE -/* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR. - The range of the returned value is >= 0.5 and < 1.0. This is equivalent to - frexp, but operates on the long double data type. */ - -static long double ldfrexp PARAMS ((long double value, int *eptr)); - -static long double -ldfrexp (value, eptr) - long double value; - int *eptr; -{ - long double tmp; - int exp; - - /* Unfortunately, there are no portable functions for extracting the exponent - of a long double, so we have to do it iteratively by multiplying or dividing - by two until the fraction is between 0.5 and 1.0. */ - - if (value < 0.0l) - value = -value; - - tmp = 1.0l; - exp = 0; - - if (value >= tmp) /* Value >= 1.0 */ - while (value >= tmp) - { - tmp *= 2.0l; - exp++; - } - else if (value != 0.0l) /* Value < 1.0 and > 0.0 */ - { - while (value < tmp) - { - tmp /= 2.0l; - exp--; - } - tmp *= 2.0l; - exp++; - } - - *eptr = exp; - return value / tmp; -} -#endif /* HAVE_LONG_DOUBLE */ - - -/* The converse: convert the DOUBLEST *FROM to an extended float - and store where TO points. Neither FROM nor TO have any alignment - restrictions. */ - -void -floatformat_from_doublest (fmt, from, to) - CONST struct floatformat *fmt; - DOUBLEST *from; - char *to; -{ - DOUBLEST dfrom; - int exponent; - DOUBLEST mant; - unsigned int mant_bits, mant_off; - int mant_bits_left; - unsigned char *uto = (unsigned char *) to; - - memcpy (&dfrom, from, sizeof (dfrom)); - memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT); - if (dfrom == 0) - return; /* Result is zero */ - if (dfrom != dfrom) /* Result is NaN */ - { - /* From is NaN */ - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, - fmt->exp_len, fmt->exp_nan); - /* Be sure it's not infinity, but NaN value is irrel */ - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, - 32, 1); - return; - } - - /* If negative, set the sign bit. */ - if (dfrom < 0) - { - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); - dfrom = -dfrom; - } - - if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity */ - { - /* Infinity exponent is same as NaN's. */ - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, - fmt->exp_len, fmt->exp_nan); - /* Infinity mantissa is all zeroes. */ - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, - fmt->man_len, 0); - return; - } - -#ifdef HAVE_LONG_DOUBLE - mant = ldfrexp (dfrom, &exponent); -#else - mant = frexp (dfrom, &exponent); -#endif - - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, - exponent + fmt->exp_bias - 1); - - mant_bits_left = fmt->man_len; - mant_off = fmt->man_start; - while (mant_bits_left > 0) - { - unsigned long mant_long; - mant_bits = mant_bits_left < 32 ? mant_bits_left : 32; - - mant *= 4294967296.0; - mant_long = (unsigned long) mant; - mant -= mant_long; - - /* If the integer bit is implicit, then we need to discard it. - If we are discarding a zero, we should be (but are not) creating - a denormalized number which means adjusting the exponent - (I think). */ - if (mant_bits_left == fmt->man_len - && fmt->intbit == floatformat_intbit_no) - { - mant_long <<= 1; - mant_bits -= 1; - } - - if (mant_bits < 32) - { - /* The bits we want are in the most significant MANT_BITS bits of - mant_long. Move them to the least significant. */ - mant_long >>= 32 - mant_bits; - } - - put_field (uto, fmt->byteorder, fmt->totalsize, - mant_off, mant_bits, mant_long); - mant_off += mant_bits; - mant_bits_left -= mant_bits; - } - if (fmt->byteorder == floatformat_littlebyte_bigword) - { - int count; - unsigned char *swaplow = uto; - unsigned char *swaphigh = uto + 4; - unsigned char tmp; - - for (count = 0; count < 4; count++) - { - tmp = *swaplow; - *swaplow++ = *swaphigh; - *swaphigh++ = tmp; - } - } -} +/* print routines to handle variable size regs, etc. */ /* temporary storage using circular buffer */ #define NUMCELLS 16 #define CELLSIZE 32 static char * -get_cell () +get_cell (void) { static char buf[NUMCELLS][CELLSIZE]; static int cell = 0; @@ -2845,79 +2342,22 @@ get_cell () return buf[cell]; } -/* print routines to handle variable size regs, etc. - - FIXME: Note that t_addr is a bfd_vma, which is currently either an - unsigned long or unsigned long long, determined at configure time. - If t_addr is an unsigned long long and sizeof (unsigned long long) - is greater than sizeof (unsigned long), then I believe this code will - probably lose, at least for little endian machines. I believe that - it would also be better to eliminate the switch on the absolute size - of t_addr and replace it with a sequence of if statements that compare - sizeof t_addr with sizeof the various types and do the right thing, - which includes knowing whether or not the host supports long long. - -fnf - - */ - int strlen_paddr (void) { - return (TARGET_PTR_BIT / 8 * 2); + return (TARGET_ADDR_BIT / 8 * 2); } - -/* eliminate warning from compiler on 32-bit systems */ -static int thirty_two = 32; - char * paddr (CORE_ADDR addr) { - char *paddr_str = get_cell (); - switch (TARGET_PTR_BIT / 8) - { - case 8: - sprintf (paddr_str, "%08lx%08lx", - (unsigned long) (addr >> thirty_two), (unsigned long) (addr & 0xffffffff)); - break; - case 4: - sprintf (paddr_str, "%08lx", (unsigned long) addr); - break; - case 2: - sprintf (paddr_str, "%04x", (unsigned short) (addr & 0xffff)); - break; - default: - sprintf (paddr_str, "%lx", (unsigned long) addr); - } - return paddr_str; + return phex (addr, TARGET_ADDR_BIT / 8); } char * paddr_nz (CORE_ADDR addr) { - char *paddr_str = get_cell (); - switch (TARGET_PTR_BIT / 8) - { - case 8: - { - unsigned long high = (unsigned long) (addr >> thirty_two); - if (high == 0) - sprintf (paddr_str, "%lx", (unsigned long) (addr & 0xffffffff)); - else - sprintf (paddr_str, "%lx%08lx", - high, (unsigned long) (addr & 0xffffffff)); - break; - } - case 4: - sprintf (paddr_str, "%lx", (unsigned long) addr); - break; - case 2: - sprintf (paddr_str, "%x", (unsigned short) (addr & 0xffff)); - break; - default: - sprintf (paddr_str, "%lx", (unsigned long) addr); - } - return paddr_str; + return phex_nz (addr, TARGET_ADDR_BIT / 8); } static void @@ -2949,7 +2389,7 @@ decimal2str (char *paddr_str, char *sign, ULONGEST addr) sign, temp[2], temp[1], temp[0]); break; default: - abort (); + internal_error (__FILE__, __LINE__, "failed internal consistency check"); } } @@ -2972,71 +2412,81 @@ paddr_d (LONGEST addr) return paddr_str; } +/* eliminate warning from compiler on 32-bit systems */ +static int thirty_two = 32; + char * -preg (reg) - t_reg reg; +phex (ULONGEST l, int sizeof_l) { - char *preg_str = get_cell (); - switch (sizeof (t_reg)) + char *str = get_cell (); + switch (sizeof_l) { case 8: - sprintf (preg_str, "%08lx%08lx", - (unsigned long) (reg >> thirty_two), (unsigned long) (reg & 0xffffffff)); + sprintf (str, "%08lx%08lx", + (unsigned long) (l >> thirty_two), + (unsigned long) (l & 0xffffffff)); break; case 4: - sprintf (preg_str, "%08lx", (unsigned long) reg); + sprintf (str, "%08lx", (unsigned long) l); break; case 2: - sprintf (preg_str, "%04x", (unsigned short) (reg & 0xffff)); + sprintf (str, "%04x", (unsigned short) (l & 0xffff)); break; default: - sprintf (preg_str, "%lx", (unsigned long) reg); + phex (l, sizeof (l)); + break; } - return preg_str; + return str; } char * -preg_nz (reg) - t_reg reg; +phex_nz (ULONGEST l, int sizeof_l) { - char *preg_str = get_cell (); - switch (sizeof (t_reg)) + char *str = get_cell (); + switch (sizeof_l) { case 8: { - unsigned long high = (unsigned long) (reg >> thirty_two); + unsigned long high = (unsigned long) (l >> thirty_two); if (high == 0) - sprintf (preg_str, "%lx", (unsigned long) (reg & 0xffffffff)); + sprintf (str, "%lx", (unsigned long) (l & 0xffffffff)); else - sprintf (preg_str, "%lx%08lx", - high, (unsigned long) (reg & 0xffffffff)); + sprintf (str, "%lx%08lx", + high, (unsigned long) (l & 0xffffffff)); break; } case 4: - sprintf (preg_str, "%lx", (unsigned long) reg); + sprintf (str, "%lx", (unsigned long) l); break; case 2: - sprintf (preg_str, "%x", (unsigned short) (reg & 0xffff)); + sprintf (str, "%x", (unsigned short) (l & 0xffff)); break; default: - sprintf (preg_str, "%lx", (unsigned long) reg); + phex_nz (l, sizeof (l)); + break; } - return preg_str; + return str; } -/* Helper functions for INNER_THAN */ -int -core_addr_lessthan (lhs, rhs) - CORE_ADDR lhs; - CORE_ADDR rhs; + +/* Convert to / from the hosts pointer to GDB's internal CORE_ADDR + using the target's conversion routines. */ +CORE_ADDR +host_pointer_to_address (void *ptr) { - return (lhs < rhs); + if (sizeof (ptr) != TYPE_LENGTH (builtin_type_void_data_ptr)) + internal_error (__FILE__, __LINE__, + "core_addr_to_void_ptr: bad cast"); + return POINTER_TO_ADDRESS (builtin_type_void_data_ptr, &ptr); } -int -core_addr_greaterthan (lhs, rhs) - CORE_ADDR lhs; - CORE_ADDR rhs; -{ - return (lhs > rhs); +void * +address_to_host_pointer (CORE_ADDR addr) +{ + void *ptr; + if (sizeof (ptr) != TYPE_LENGTH (builtin_type_void_data_ptr)) + internal_error (__FILE__, __LINE__, + "core_addr_to_void_ptr: bad cast"); + ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr); + return ptr; }