/* 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.
+ 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
-(at your option) any later version.
+ 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
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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. */
+ 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. */
#include "defs.h"
#include <ctype.h>
#include "gdb_string.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
+#include "event-top.h"
#ifdef HAVE_CURSES_H
#include <curses.h>
#include <term.h>
#endif
+#ifdef __GO32__
+#include <pc.h>
+#endif
+
/* SunOS's curses.h has a '#define reg register' in it. Thank you Sun. */
#ifdef reg
#undef reg
#endif
-#include "signals.h"
+#include <signal.h>
#include "gdbcmd.h"
#include "serial.h"
#include "bfd.h"
#include "language.h"
#include "annotate.h"
+#include "inferior.h" /* for signed_pointer_to_address */
+
#include <readline/readline.h>
+#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 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
-fatal_dump_core PARAMS((char *, ...));
+static void prompt_for_continue (void);
-static void
-prompt_for_continue PARAMS ((void));
-
-static void
-set_width_command PARAMS ((char *, int, struct cmd_list_element *));
-
-static void
-set_width PARAMS ((void));
+static void set_width_command (char *, int, struct cmd_list_element *);
-/* If this definition isn't overridden by the header files, assume
- that isatty and fileno exist on this system. */
-#ifndef ISATTY
-#define ISATTY(FP) (isatty (fileno (FP)))
-#endif
-
-#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. */
-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 *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
+ support async execution. The finish and until commands use it. So
+ does the target extended-remote command. */
+struct continuation *cmd_continuation;
+struct continuation *intermediate_continuation;
/* Nonzero if we have job control. */
char *warning_pre_print = "\nwarning: ";
int pagination_enabled = 1;
-
\f
+
/* Add a new cleanup to the cleanup_chain,
and return the previous chain pointer
to be passed later to do_cleanups or discard_cleanups.
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 (make_cleanup_ftype *function, void *arg)
{
- return make_my_cleanup (&cleanup_chain, function, arg);
+ return make_my_cleanup (&final_cleanup_chain, function, arg);
}
struct cleanup *
-make_final_cleanup (function, arg)
- void (*function) PARAMS ((PTR));
- PTR arg;
+make_run_cleanup (make_cleanup_ftype *function, void *arg)
{
- return make_my_cleanup (&final_cleanup_chain, function, arg);
+ return make_my_cleanup (&run_cleanup_chain, function, arg);
}
struct cleanup *
-make_run_cleanup (function, arg)
- void (*function) PARAMS ((PTR));
- PTR arg;
+make_exec_cleanup (make_cleanup_ftype *function, void *arg)
{
- return make_my_cleanup (&run_cleanup_chain, function, 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 (arg)
- void *arg;
+do_freeargv (void *arg)
{
- freeargv ((char**) 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_bfd_close_cleanup (void *arg)
+{
+ bfd_close (arg);
+}
+
struct cleanup *
-make_my_cleanup (pmy_chain, function, arg)
- struct cleanup **pmy_chain;
- void (*function) PARAMS ((PTR));
- PTR arg;
+make_cleanup_bfd_close (bfd *abfd)
+{
+ return make_cleanup (do_bfd_close_cleanup, abfd);
+}
+
+static void
+do_close_cleanup (void *arg)
+{
+ int *fd = arg;
+ close (*fd);
+ xfree (fd);
+}
+
+struct cleanup *
+make_cleanup_close (int fd)
+{
+ int *saved_fd = xmalloc (sizeof (fd));
+ *saved_fd = fd;
+ return make_cleanup (do_close_cleanup, saved_fd);
+}
+
+static void
+do_ui_file_delete (void *arg)
+{
+ ui_file_delete (arg);
+}
+
+struct cleanup *
+make_cleanup_ui_file_delete (struct ui_file *arg)
+{
+ return make_my_cleanup (&cleanup_chain, do_ui_file_delete, arg);
+}
+
+struct cleanup *
+make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
+ void *arg)
{
register struct cleanup *new
- = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+ = (struct cleanup *) xmalloc (sizeof (struct cleanup));
register struct cleanup *old_chain = *pmy_chain;
new->next = *pmy_chain;
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);
+ 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);
+ 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);
+ do_my_cleanups (&run_cleanup_chain, old_chain);
}
void
-do_my_cleanups (pmy_chain, old_chain)
- register struct cleanup **pmy_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 (register struct cleanup *old_chain)
+{
+ do_my_cleanups (&exec_error_cleanup_chain, old_chain);
+}
+
+void
+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);
}
}
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);
+ 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);
+ discard_my_cleanups (&final_cleanup_chain, old_chain);
}
void
-discard_my_cleanups (pmy_chain, old_chain)
- register struct cleanup **pmy_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 (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);
+ return save_my_cleanups (&cleanup_chain);
}
struct cleanup *
-save_final_cleanups ()
+save_final_cleanups (void)
{
- return save_my_cleanups (&final_cleanup_chain);
+ 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;
/* 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);
+ 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);
+ 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;
}
/* This function is useful for cleanups.
Do
- foo = xmalloc (...);
- old_chain = make_cleanup (free_current_contents, &foo);
+ foo = xmalloc (...);
+ old_chain = make_cleanup (free_current_contents, &foo);
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
/* ARGSUSED */
void
-null_cleanup (arg)
- PTR arg;
+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 *),
+ struct continuation_arg *arg_list)
+{
+ struct continuation *continuation_ptr;
+
+ continuation_ptr = (struct continuation *) xmalloc (sizeof (struct continuation));
+ continuation_ptr->continuation_hook = continuation_hook;
+ continuation_ptr->arg_list = arg_list;
+ continuation_ptr->next = cmd_continuation;
+ cmd_continuation = continuation_ptr;
+}
+
+/* Walk down the cmd_continuation list, and execute all the
+ continuations. There is a problem though. In some cases new
+ continuations may be added while we are in the middle of this
+ loop. If this happens they will be added in the front, and done
+ 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.*/
+void
+do_all_continuations (void)
+{
+ struct continuation *continuation_ptr;
+ struct continuation *saved_continuation;
+
+ /* Copy the list header into another pointer, and set the global
+ list header to null, so that the global list can change as a side
+ effect of invoking the continuations and the processing of
+ the preexisting continuations will not be affected. */
+ continuation_ptr = cmd_continuation;
+ cmd_continuation = NULL;
+
+ /* Work now on the list we have set aside. */
+ while (continuation_ptr)
+ {
+ (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
+ saved_continuation = continuation_ptr;
+ continuation_ptr = continuation_ptr->next;
+ xfree (saved_continuation);
+ }
+}
+
+/* Walk down the cmd_continuation list, and get rid of all the
+ continuations. */
+void
+discard_all_continuations (void)
+{
+ struct continuation *continuation_ptr;
+
+ while (cmd_continuation)
+ {
+ continuation_ptr = cmd_continuation;
+ cmd_continuation = continuation_ptr->next;
+ xfree (continuation_ptr);
+ }
+}
+
+/* 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 (void (*continuation_hook)
+ (struct continuation_arg *),
+ struct continuation_arg *arg_list)
+{
+ struct continuation *continuation_ptr;
+
+ continuation_ptr = (struct continuation *) xmalloc (sizeof (struct continuation));
+ continuation_ptr->continuation_hook = continuation_hook;
+ continuation_ptr->arg_list = arg_list;
+ continuation_ptr->next = intermediate_continuation;
+ intermediate_continuation = continuation_ptr;
+}
+
+/* Walk down the cmd_continuation list, and execute all the
+ continuations. There is a problem though. In some cases new
+ continuations may be added while we are in the middle of this
+ loop. If this happens they will be added in the front, and done
+ 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.*/
+void
+do_all_intermediate_continuations (void)
+{
+ struct continuation *continuation_ptr;
+ struct continuation *saved_continuation;
+
+ /* Copy the list header into another pointer, and set the global
+ list header to null, so that the global list can change as a side
+ effect of invoking the continuations and the processing of
+ the preexisting continuations will not be affected. */
+ continuation_ptr = intermediate_continuation;
+ intermediate_continuation = NULL;
+
+ /* Work now on the list we have set aside. */
+ while (continuation_ptr)
+ {
+ (continuation_ptr->continuation_hook) (continuation_ptr->arg_list);
+ saved_continuation = continuation_ptr;
+ continuation_ptr = continuation_ptr->next;
+ xfree (saved_continuation);
+ }
+}
+
+/* Walk down the cmd_continuation list, and get rid of all the
+ continuations. */
+void
+discard_all_intermediate_continuations (void)
{
+ struct continuation *continuation_ptr;
+
+ while (intermediate_continuation)
+ {
+ continuation_ptr = intermediate_continuation;
+ intermediate_continuation = continuation_ptr->next;
+ xfree (continuation_ptr);
+ }
}
\f
+
/* Print a warning message. Way to use this is to call warning_begin,
output the warning message (use unfiltered output to gdb_stderr),
ending in a newline. There is not currently a warning_end that you
Is this anything other than a historical accident? */
void
-warning_begin ()
+warning_begin (void)
{
target_terminal_ours ();
- wrap_here(""); /* Force out any buffered output */
+ wrap_here (""); /* Force out any buffered output */
gdb_flush (gdb_stdout);
if (warning_pre_print)
fprintf_unfiltered (gdb_stderr, warning_pre_print);
The primary difference between warnings and errors is that a warning
does not force the return to command level. */
-/* VARARGS */
void
-#ifdef ANSI_PROTOTYPES
-warning (const char *string, ...)
-#else
-warning (va_alist)
- va_dcl
-#endif
+warning (const char *string,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, string);
-#else
- char *string;
-
- va_start (args);
- string = va_arg (args, char *);
-#endif
if (warning_hook)
(*warning_hook) (string, args);
else
- {
- warning_begin ();
- vfprintf_unfiltered (gdb_stderr, string, args);
- fprintf_unfiltered (gdb_stderr, "\n");
- va_end (args);
- }
+ {
+ warning_begin ();
+ vfprintf_unfiltered (gdb_stderr, string, args);
+ fprintf_unfiltered (gdb_stderr, "\n");
+ va_end (args);
+ }
}
/* Start the printing of an error message. Way to use this is to call
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 ();
target_terminal_ours ();
- wrap_here (""); /* Force out any buffered output */
+ wrap_here (""); /* Force out any buffered output */
gdb_flush (gdb_stdout);
annotate_error_begin ();
The first argument STRING is the error message, used as a fprintf string,
and the remaining args are passed as arguments to it. */
-/* VARARGS */
NORETURN void
-#ifdef ANSI_PROTOTYPES
-error (const char *string, ...)
-#else
-error (va_alist)
- va_dcl
-#endif
-{
- va_list args;
-#ifdef ANSI_PROTOTYPES
- va_start (args, string);
-#else
- va_start (args);
-#endif
- if (error_hook)
- (*error_hook) ();
- else
- {
- error_begin ();
-#ifdef ANSI_PROTOTYPES
- vfprintf_filtered (gdb_stderr, string, args);
-#else
- {
- char *string1;
-
- string1 = va_arg (args, char *);
- vfprintf_filtered (gdb_stderr, string1, args);
- }
-#endif
- fprintf_filtered (gdb_stderr, "\n");
- va_end (args);
- return_to_top_level (RETURN_ERROR);
- }
+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.
+ Unfortunately some code uses the sequence: error_begin(); print
+ error message; return_to_top_level. That code should be
+ flushed. */
+ error_begin ();
+ /* NOTE: It's tempting to just do the following...
+ vfprintf_filtered (gdb_stderr, string, args);
+ and then follow with a similar looking statement to cause the message
+ to also go to gdb_lasterr. But if we do this, we'll be traversing the
+ va_list twice which works on some platforms and fails miserably on
+ others. */
+ /* Save it as the last error */
+ 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 (xfree, err_string);
+ fputs_filtered (err_string, gdb_stderr);
+ fprintf_filtered (gdb_stderr, "\n");
+ do_cleanups (err_string_cleanup);
+ return_to_top_level (RETURN_ERROR);
}
-
-/* Print an error message and exit reporting failure.
- This is for a error that we cannot continue from.
- The arguments are printed a la printf.
-
- This function cannot be declared volatile (NORETURN) in an
- ANSI environment because exit() is not declared volatile. */
-
-/* VARARGS */
NORETURN void
-#ifdef ANSI_PROTOTYPES
-fatal (char *string, ...)
-#else
-fatal (va_alist)
- va_dcl
-#endif
+error (const char *string,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, string);
-#else
- char *string;
- va_start (args);
- string = va_arg (args, char *);
-#endif
- fprintf_unfiltered (gdb_stderr, "\ngdb: ");
- vfprintf_unfiltered (gdb_stderr, string, args);
- fprintf_unfiltered (gdb_stderr, "\n");
+ verror (string, args);
va_end (args);
- exit (1);
}
-/* Print an error message and exit, dumping core.
- The arguments are printed a la printf (). */
-
-/* VARARGS */
-static void
-#ifdef ANSI_PROTOTYPES
-fatal_dump_core (char *string, ...)
-#else
-fatal_dump_core (va_alist)
- va_dcl
-#endif
+NORETURN void
+error_stream (struct ui_file *stream)
{
- va_list args;
-#ifdef ANSI_PROTOTYPES
- va_start (args, string);
-#else
- char *string;
+ long size;
+ char *msg = ui_file_xstrdup (stream, &size);
+ make_cleanup (xfree, msg);
+ error ("%s", msg);
+}
- va_start (args);
- string = va_arg (args, char *);
-#endif
- /* "internal error" is always correct, since GDB should never dump
- core, no matter what the input. */
- fprintf_unfiltered (gdb_stderr, "\ngdb internal error: ");
- vfprintf_unfiltered (gdb_stderr, string, args);
- fprintf_unfiltered (gdb_stderr, "\n");
- va_end (args);
+/* Get the last error message issued by gdb */
- signal (SIGQUIT, SIG_DFL);
- kill (getpid (), SIGQUIT);
- /* We should never get here, but just in case... */
- exit (1);
+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 */
-/* The strerror() function can return NULL for errno values that are
- out of range. Provide a "safe" version that always returns a
- printable string. */
+void
+error_init (void)
+{
+ gdb_lasterr = mem_fileopen ();
+}
-char *
-safe_strerror (errnum)
- int errnum;
+/* Print a message reporting an internal error. Ask the user if they
+ want to continue, dump core, or just exit. */
+
+NORETURN void
+internal_verror (const char *file, int line,
+ const char *fmt, va_list ap)
{
- char *msg;
- static char buf[32];
+ static char msg[] = "Internal GDB error: recursive internal error.\n";
+ static int dejavu = 0;
+ int continue_p;
+ int dump_core_p;
- if ((msg = strerror (errnum)) == NULL)
+ /* don't allow infinite error recursion. */
+ switch (dejavu)
{
- sprintf (buf, "(undocumented errno %d)", errnum);
- msg = buf;
+ case 0:
+ dejavu = 1;
+ break;
+ case 1:
+ dejavu = 2;
+ fputs_unfiltered (msg, gdb_stderr);
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
+ default:
+ dejavu = 3;
+ write (STDERR_FILENO, msg, sizeof (msg));
+ exit (1);
}
- return (msg);
+
+ /* Try to get the message out */
+ 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 further\n\
+debugging unreliable. Continue this debugging session? ");
+
+ /* Default (no case) is to not dump core. Lessen the chance of GDB
+ leaving random core files around. */
+ dump_core_p = query ("\
+Create a core file containing the current state of GDB? ");
+
+ if (continue_p)
+ {
+ if (dump_core_p)
+ {
+ if (fork () == 0)
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
+ }
+ }
+ else
+ {
+ if (dump_core_p)
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
+ else
+ exit (1);
+ }
+
+ dejavu = 0;
+ return_to_top_level (RETURN_ERROR);
}
-/* The strsignal() function can return NULL for signal values that are
+NORETURN void
+internal_error (const char *file, int line, const char *string, ...)
+{
+ va_list ap;
+ va_start (ap, string);
+
+ internal_verror (file, line, string, ap);
+ va_end (ap);
+}
+
+/* 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_strsignal (signo)
- int signo;
+safe_strerror (int errnum)
{
char *msg;
static char buf[32];
- if ((msg = strsignal (signo)) == NULL)
+ if ((msg = strerror (errnum)) == NULL)
{
- sprintf (buf, "(undocumented signal %d)", signo);
+ 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. */
NORETURN void
-perror_with_name (string)
- char *string;
+perror_with_name (char *string)
{
char *err;
char *combined;
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
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;
/* Control C eventually causes this to be called, at a convenient time. */
void
-quit ()
+quit (void)
{
serial_t gdb_stdout_serial = serial_fdopen (1);
too): */
/* 1. The _filtered buffer. */
- wrap_here ((char *)0);
+ wrap_here ((char *) 0);
/* 2. The stdio buffer. */
gdb_flush (gdb_stdout);
if (quit_pre_print)
fprintf_unfiltered (gdb_stderr, quit_pre_print);
+#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");
+#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. */
+ /* 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");
else
fprintf_unfiltered (gdb_stderr,
- "Quit (expect signal SIGINT when the program is resumed)\n");
+ "Quit (expect signal SIGINT when the program is resumed)\n");
+#endif
return_to_top_level (RETURN_QUIT);
}
-#if defined(__GO32__)
-
-/* In the absence of signals, poll keyboard for a quit.
- Called from #define QUIT pollquit() in xm-go32.h. */
-
-void
-notice_quit()
-{
- if (kbhit ())
- switch (getkey ())
- {
- case 1:
- quit_flag = 1;
- break;
- case 2:
- immediate_quit = 2;
- break;
- default:
- /* We just ignore it */
- /* FIXME!! Don't think this actually works! */
- fprintf_unfiltered (gdb_stderr, "CTRL-A to quit, CTRL-B to quit harder\n");
- break;
- }
-}
-
-#elif defined(_MSC_VER) /* should test for wingdb instead? */
+#if defined(_MSC_VER) /* should test for wingdb instead? */
/*
* Windows translates all keyboard and mouse events
* queue for the process.
*/
-void notice_quit()
+void
+notice_quit (void)
{
- int k = win32pollquit();
+ int k = win32pollquit ();
if (k == 1)
quit_flag = 1;
else if (k == 2)
immediate_quit = 1;
}
-#else /* !defined(__GO32__) && !defined(_MSC_VER) */
+#else /* !defined(_MSC_VER) */
-void notice_quit()
+void
+notice_quit (void)
{
/* Done by signals */
}
-#endif /* !defined(__GO32__) && !defined(_MSC_VER) */
+#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
#ifdef REQUEST_QUIT
REQUEST_QUIT;
#else
- if (immediate_quit)
+ if (immediate_quit)
quit ();
#endif
}
-
\f
/* Memory management stuff (malloc friends). */
#if !defined (USE_MMALLOC)
PTR
-mmalloc (md, size)
- PTR md;
- size_t size;
+mcalloc (PTR md, size_t number, size_t size)
+{
+ return calloc (number, size);
+}
+
+PTR
+mmalloc (PTR md, size_t size)
{
return malloc (size);
}
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 */
+ if (ptr == 0) /* Guard against old realloc's */
return malloc (size);
else
return realloc (ptr, size);
}
void
-mfree (md, ptr)
- PTR md;
- PTR ptr;
+mfree (PTR md, PTR ptr)
{
- free (ptr);
+ xfree (ptr);
}
-#endif /* USE_MMALLOC */
+#endif /* USE_MMALLOC */
#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)
{
- fatal_dump_core ("Memory corruption");
+ fprintf_unfiltered (gdb_stderr, "Memory corruption\n");
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
}
/* Attempt to install hooks in mmalloc/mrealloc/mfree for the heap specified
#endif
void
-init_malloc (md)
- PTR md;
+init_malloc (void *md)
{
if (!mmcheckf (md, malloc_botch, MMCHECK_FORCE))
{
/* Don't use warning(), which relies on current_target being set
- to something other than dummy_target, until after
- initialize_all_files(). */
+ to something other than dummy_target, until after
+ initialize_all_files(). */
fprintf_unfiltered
(gdb_stderr, "warning: failed to install memory consistency checks; ");
memory requested in SIZE. */
NORETURN void
-nomem (size)
- long size;
+nomem (long size)
{
if (size > 0)
{
- fatal ("virtual memory exhausted: can't allocate %ld bytes.", size);
+ internal_error (__FILE__, __LINE__,
+ "virtual memory exhausted: can't allocate %ld bytes.", size);
}
else
{
- fatal ("virtual memory exhausted.");
+ internal_error (__FILE__, __LINE__,
+ "virtual memory exhausted.");
}
}
byte of zero'd storage, is a religious issue. */
PTR
-xmmalloc (md, size)
- PTR md;
- long size;
+xmmalloc (PTR md, long size)
{
register PTR val;
/* Like mrealloc but get error if no storage available. */
PTR
-xmrealloc (md, ptr, size)
- PTR md;
- PTR ptr;
- long size;
+xmrealloc (PTR md, PTR ptr, long size)
{
register PTR val;
the caller wanting to allocate zero bytes. */
PTR
-xmalloc (size)
- size_t size;
+xmalloc (size_t size)
{
return (xmmalloc ((PTR) NULL, size));
}
+/* Like calloc but get error if no storage available */
+
+PTR
+xcalloc (size_t number, size_t size)
+{
+ void *mem = mcalloc (NULL, number, size);
+ if (mem == NULL)
+ nomem (number * size);
+ return mem;
+}
+
/* Like mrealloc but get error if no storage available. */
PTR
-xrealloc (ptr, size)
- PTR ptr;
- size_t size;
+xrealloc (PTR ptr, size_t size)
{
return (xmrealloc ((PTR) NULL, ptr, size));
}
+/* Free up space allocated by one of xmalloc(), xcalloc(), or
+ xrealloc(). */
+
+void
+xfree (void *ptr)
+{
+ if (ptr != NULL)
+ free (ptr);
+}
\f
+
+/* 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;
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);
}
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);
return p;
}
-/* The "const" is so it compiles under DGUX (which prototypes strsave
- in <string.h>. 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);
}
/* Print a host address. */
void
-gdb_print_address (addr, stream)
- PTR addr;
- 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
way of knowing whether this host supports it. But the following
should work on the Alpha and on 32 bit machines. */
- fprintf_filtered (stream, "0x%lx", (unsigned long)addr);
+ fprintf_filtered (stream, "0x%lx", (unsigned long) addr);
}
/* Ask user a y-or-n question and return 1 iff answer is yes.
/* VARARGS */
int
-#ifdef ANSI_PROTOTYPES
-query (char *ctlstr, ...)
-#else
-query (va_alist)
- va_dcl
-#endif
+query (char *ctlstr,...)
{
va_list args;
register int answer;
register int ans2;
int retval;
-#ifdef ANSI_PROTOTYPES
va_start (args, ctlstr);
-#else
- char *ctlstr;
- va_start (args);
- ctlstr = va_arg (args, char *);
-#endif
if (query_hook)
{
#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. */
+ have a prompt on the front of it. */
if (!mac_app)
fputs_unfiltered ("\n", gdb_stdout);
#endif /* MPW */
- wrap_here("");
+ wrap_here ("");
gdb_flush (gdb_stdout);
#if defined(TUI)
- if (!tui_version || cmdWin == tuiWinWithFocus())
+ if (!tui_version || cmdWin == tuiWinWithFocus ())
#endif
answer = fgetc (stdin);
#if defined(TUI)
else
-
- answer = (unsigned char)tuiBufferGetc();
+ answer = (unsigned char) tuiBufferGetc ();
#endif
clearerr (stdin); /* in case of C-d */
if (answer == EOF) /* C-d */
- {
+ {
retval = 1;
break;
}
/* Eat rest of input line, to EOF or newline */
if ((answer != '\n') || (tui_version && answer != '\r'))
- do
+ do
{
#if defined(TUI)
- if (!tui_version || cmdWin == tuiWinWithFocus())
+ if (!tui_version || cmdWin == tuiWinWithFocus ())
#endif
ans2 = fgetc (stdin);
#if defined(TUI)
else
-
- ans2 = (unsigned char)tuiBufferGetc();
+ ans2 = (unsigned char) tuiBufferGetc ();
#endif
clearerr (stdin);
}
- while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
- TUIDO(((TuiOpaqueFuncPtr)tui_vStartNewLines, 1));
+ while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
+ TUIDO (((TuiOpaqueFuncPtr) tui_vStartNewLines, 1));
if (answer >= 'a')
answer -= 040;
printf_filtered ("\n\032\032post-query\n");
return retval;
}
-
\f
+
/* Parse a C escape sequence. STRING_PTR points to a variable
containing a pointer to the string to parse. That pointer
should point to the character after the \. That pointer
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)
if (c == '?')
return 0177;
return (c & 0200) | (c & 037);
-
+
case '0':
case '1':
case '2':
be call for printing things which are independent of the language
of the program being debugged. */
-void
-gdb_printchar (c, stream, quoter)
- register int c;
- GDB_FILE *stream;
- int quoter;
+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)
{
c &= 0xFF; /* Avoid sign bit follies */
- if ( c < 0x20 || /* Low control chars */
- (c >= 0x7F && c < 0xA0) || /* DEL, High controls */
- (sevenbit_strings && c >= 0x80)) { /* high order bit set */
- switch (c)
- {
- case '\n':
- fputs_filtered ("\\n", stream);
- break;
- case '\b':
- fputs_filtered ("\\b", stream);
- break;
- case '\t':
- fputs_filtered ("\\t", stream);
- break;
- case '\f':
- fputs_filtered ("\\f", stream);
- break;
- case '\r':
- fputs_filtered ("\\r", stream);
- break;
- case '\033':
- fputs_filtered ("\\e", stream);
- break;
- case '\007':
- fputs_filtered ("\\a", stream);
- break;
- default:
- fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
- break;
- }
- } else {
- if (c == '\\' || c == quoter)
- fputs_filtered ("\\", stream);
- fprintf_filtered (stream, "%c", c);
- }
+ if (c < 0x20 || /* Low control chars */
+ (c >= 0x7F && c < 0xA0) || /* DEL, High controls */
+ (sevenbit_strings && c >= 0x80))
+ { /* high order bit set */
+ switch (c)
+ {
+ case '\n':
+ do_fputs ("\\n", stream);
+ break;
+ case '\b':
+ do_fputs ("\\b", stream);
+ break;
+ case '\t':
+ do_fputs ("\\t", stream);
+ break;
+ case '\f':
+ do_fputs ("\\f", stream);
+ break;
+ case '\r':
+ do_fputs ("\\r", stream);
+ break;
+ case '\033':
+ do_fputs ("\\e", stream);
+ break;
+ case '\007':
+ do_fputs ("\\a", stream);
+ break;
+ default:
+ do_fprintf (stream, "\\%.3o", (unsigned int) c);
+ break;
+ }
+ }
+ else
+ {
+ if (c == '\\' || c == quoter)
+ do_fputs ("\\", stream);
+ do_fprintf (stream, "%c", c);
+ }
+}
+
+/* Print the character C on STREAM as part of the contents of a
+ literal string whose delimiter is QUOTER. Note that these routines
+ should only be call for printing things which are independent of
+ the language of the program being debugged. */
+
+void
+fputstr_filtered (const char *str, int quoter, struct ui_file *stream)
+{
+ while (*str)
+ printchar (*str++, fputs_filtered, fprintf_filtered, stream, quoter);
+}
+
+void
+fputstr_unfiltered (const char *str, int quoter, struct ui_file *stream)
+{
+ while (*str)
+ printchar (*str++, fputs_unfiltered, fprintf_unfiltered, stream, quoter);
+}
+
+void
+fputstrn_unfiltered (const char *str, int n, int quoter, struct ui_file *stream)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ printchar (str[i], fputs_unfiltered, fprintf_unfiltered, stream, quoter);
}
\f
+
/* 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 is 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;
/* Column number on the screen where wrap_buffer begins, or 0 if wrapping
is not in effect. */
static int wrap_column;
-
\f
+
/* Inialize the lines and chars per page */
void
-init_page_info()
+init_page_info (void)
{
#if defined(TUI)
- if (tui_version && m_winPtrNotNull(cmdWin))
+ if (tui_version && m_winPtrNotNull (cmdWin))
{
lines_per_page = cmdWin->generic.height;
chars_per_line = cmdWin->generic.width;
/* These defaults will be used if we are unable to get the correct
values from termcap. */
#if defined(__GO32__)
- lines_per_page = ScreenRows();
- chars_per_line = ScreenCols();
-#else
+ lines_per_page = ScreenRows ();
+ chars_per_line = ScreenCols ();
+#else
lines_per_page = 24;
chars_per_line = 80;
by looking at worksheet or console window sizes. */
/* Initialize the screen height and width from termcap. */
{
- char *termtype = getenv ("TERM");
+ char *termtype = getenv ("TERM");
- /* Positive means success, nonpositive means failure. */
- int status;
+ /* Positive means success, nonpositive means failure. */
+ int status;
- /* 2048 is large enough for all known terminals, according to the
- GNU termcap manual. */
- char term_buffer[2048];
+ /* 2048 is large enough for all known terminals, according to the
+ GNU termcap manual. */
+ char term_buffer[2048];
- if (termtype)
- {
+ if (termtype)
+ {
status = tgetent (term_buffer, termtype);
if (status > 0)
{
- int val;
+ int val;
int running_in_emacs = getenv ("EMACS") != NULL;
-
- val = tgetnum ("li");
- if (val >= 0 && !running_in_emacs)
- lines_per_page = val;
- else
- /* The number of lines per page is not mentioned
+
+ val = tgetnum ("li");
+ if (val >= 0 && !running_in_emacs)
+ lines_per_page = val;
+ else
+ /* The number of lines per page is not mentioned
in the terminal description. This probably means
that paging is not useful (e.g. emacs shell window),
so disable paging. */
- lines_per_page = UINT_MAX;
-
- val = tgetnum ("co");
- if (val >= 0)
- chars_per_line = val;
+ lines_per_page = UINT_MAX;
+
+ val = tgetnum ("co");
+ if (val >= 0)
+ chars_per_line = val;
}
- }
+ }
}
#endif /* MPW */
#endif
#endif
/* If the output is not a terminal, don't paginate it. */
- if (!GDB_FILE_ISATTY (gdb_stdout))
- lines_per_page = UINT_MAX;
- } /* the command_line_version */
- set_width();
+ 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();
+ init_page_info ();
if (!wrap_buffer)
{
}
else
wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2);
- wrap_pointer = wrap_buffer; /* Start it at the beginning */
+ wrap_pointer = wrap_buffer; /* Start it at the beginning */
}
/* ARGSUSED */
-static void
-set_width_command (args, from_tty, c)
- char *args;
- int from_tty;
- struct cmd_list_element *c;
+static void
+set_width_command (char *args, int from_tty, struct cmd_list_element *c)
{
set_width ();
}
to continue by pressing RETURN. */
static void
-prompt_for_continue ()
+prompt_for_continue (void)
{
char *ignore;
char cont_prompt[120];
while (*p == ' ' || *p == '\t')
++p;
if (p[0] == 'q')
- request_quit (SIGINT);
- free (ignore);
+ {
+ if (!event_loop_p)
+ request_quit (SIGINT);
+ else
+ async_request_quit (0);
+ }
+ xfree (ignore);
}
immediate_quit--;
/* Reinitialize filter; ie. tell it to reset to original values. */
void
-reinitialize_more_filter ()
+reinitialize_more_filter (void)
{
lines_printed = 0;
chars_printed = 0;
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])
{
}
wrap_pointer = wrap_buffer;
wrap_buffer[0] = '\0';
- if (chars_per_line == UINT_MAX) /* No line overflow checking */
+ if (chars_per_line == UINT_MAX) /* No line overflow checking */
{
wrap_column = 0;
}
line. Otherwise do nothing. */
void
-begin_line ()
+begin_line (void)
{
if (chars_printed > 0)
{
}
}
-int
-gdb_file_isatty (stream)
- GDB_FILE *stream;
-{
-
- if (stream->ts_streamtype == afile)
- return (isatty(fileno(stream->ts_filestream)));
- else return 0;
-}
-
-GDB_FILE *
-gdb_file_init_astring (n)
- int n;
-{
- GDB_FILE *tmpstream;
-
- tmpstream = xmalloc (sizeof(GDB_FILE));
- tmpstream->ts_streamtype = astring;
- tmpstream->ts_filestream = NULL;
- if (n > 0)
- {
- tmpstream->ts_strbuf = xmalloc ((n + 1)*sizeof(char));
- tmpstream->ts_strbuf[0] = '\0';
- }
- else
- tmpstream->ts_strbuf = NULL;
- tmpstream->ts_buflen = n;
-
- return tmpstream;
-}
-
-void
-gdb_file_deallocate (streamptr)
- GDB_FILE **streamptr;
-{
- GDB_FILE *tmpstream;
-
- tmpstream = *streamptr;
- if ((tmpstream->ts_streamtype == astring) &&
- (tmpstream->ts_strbuf != NULL))
- {
- free (tmpstream->ts_strbuf);
- }
-
- free (tmpstream);
- *streamptr = NULL;
-}
-
-char *
-gdb_file_get_strbuf (stream)
- GDB_FILE *stream;
-{
- return (stream->ts_strbuf);
-}
-
-/* adjust the length of the buffer by the amount necessary
- to accomodate appending a string of length N to the buffer contents */
-void
-gdb_file_adjust_strbuf (n, stream)
- int n;
- GDB_FILE *stream;
-{
- int non_null_chars;
-
- if (stream->ts_streamtype != astring)
- return;
-
- if (stream->ts_strbuf)
- {
- /* There is already a buffer allocated */
- non_null_chars = strlen(stream->ts_strbuf);
-
- if (n > (stream->ts_buflen - non_null_chars - 1))
- {
- stream->ts_buflen = n + non_null_chars + 1;
- stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen);
- }
- }
- else
- /* No buffer yet, so allocate one of the desired size */
- stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
-}
-
-GDB_FILE *
-gdb_fopen (name, mode)
- char * name;
- char * mode;
-{
- int gdb_file_size;
- GDB_FILE *tmp;
-
- gdb_file_size = sizeof(GDB_FILE);
- tmp = (GDB_FILE *) xmalloc (gdb_file_size);
- tmp->ts_streamtype = afile;
- tmp->ts_filestream = fopen (name, mode);
- tmp->ts_strbuf = NULL;
- tmp->ts_buflen = 0;
-
- return tmp;
-}
-
-void
-gdb_flush (stream)
- GDB_FILE *stream;
-{
- if (flush_hook
- && (stream == gdb_stdout
- || stream == gdb_stderr))
- {
- flush_hook (stream);
- return;
- }
-
- fflush (stream->ts_filestream);
-}
-
-void
-gdb_fclose(streamptr)
- GDB_FILE **streamptr;
-{
- GDB_FILE *tmpstream;
-
- tmpstream = *streamptr;
- fclose (tmpstream->ts_filestream);
- gdb_file_deallocate (streamptr);
-}
/* Like fputs but if FILTER is true, pause after every screenful.
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;
/* Don't do any filtering if it is disabled. */
if ((stream != gdb_stdout) || !pagination_enabled
- || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX))
+ || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX))
{
fputs_unfiltered (linebuffer, stream);
return;
/* Go through and output each character. Show line extension
when this is necessary; prompt user for new page when this is
necessary. */
-
+
lineptr = linebuffer;
while (*lineptr)
{
fputc_unfiltered ('\t', stream);
/* Shifting right by 3 produces the number of tab stops
we have already passed, and then adding one and
- shifting left 3 advances to the next tab stop. */
+ shifting left 3 advances to the next tab stop. */
chars_printed = ((chars_printed >> 3) + 1) << 3;
lineptr++;
}
if (wrap_column)
*wrap_pointer++ = *lineptr;
else
- fputc_unfiltered (*lineptr, stream);
+ fputc_unfiltered (*lineptr, stream);
chars_printed++;
lineptr++;
}
-
+
if (chars_printed >= chars_per_line)
{
unsigned int save_chars = chars_printed;
chars_printed = 0;
lines_printed++;
/* If we aren't actually wrapping, don't output newline --
- if chars_per_line is right, we probably just overflowed
- anyway; if it's wrong, let us keep going. */
+ if chars_per_line is right, we probably just overflowed
+ anyway; if it's wrong, let us keep going. */
if (wrap_column)
fputc_unfiltered ('\n', stream);
if (wrap_column)
{
fputs_unfiltered (wrap_indent, stream);
- *wrap_pointer = '\0'; /* Null-terminate saved stuff */
- fputs_unfiltered (wrap_buffer, stream); /* and eject it */
+ *wrap_pointer = '\0'; /* Null-terminate saved stuff */
+ fputs_unfiltered (wrap_buffer, stream); /* and eject it */
/* FIXME, this strlen is what prevents wrap_indent from
containing tabs. However, if we recurse to print it
and count its chars, we risk trouble if wrap_indent is
Note also that this can set chars_printed > chars_per_line
if we are printing a long string. */
chars_printed = strlen (wrap_indent)
- + (save_chars - wrap_column);
+ + (save_chars - wrap_column);
wrap_pointer = wrap_buffer; /* Reset buffer */
wrap_buffer[0] = '\0';
- wrap_column = 0; /* And disable fancy wrap */
- }
+ wrap_column = 0; /* And disable fancy wrap */
+ }
}
}
if (*lineptr == '\n')
{
chars_printed = 0;
- wrap_here ((char *)0); /* Spit out chars, cancel further wraps */
+ wrap_here ((char *) 0); /* Spit out chars, cancel further wraps */
lines_printed++;
fputc_unfiltered ('\n', stream);
lineptr++;
}
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[2];
-
- buf[0] = c;
- buf[1] = 0;
- fputs_unfiltered (buf, gdb_stdout);
+ char buf = c;
+ 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)
{
- char buf[2];
+ return fputc_filtered (c, gdb_stdout);
+}
- buf[0] = c;
- buf[1] = 0;
- fputs_unfiltered (buf, stream);
+int
+fputc_unfiltered (int c, struct ui_file *stream)
+{
+ char buf = c;
+ 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];
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;
/* If the prefix is changing, print the previous suffix, a new line,
and the new prefix. */
- if ((return_p || (strcmp(prev_prefix, prefix) != 0)) && !new_line)
+ if ((return_p || (strcmp (prev_prefix, prefix) != 0)) && !new_line)
{
- fputs_unfiltered (prev_suffix, gdb_stderr);
- fputs_unfiltered ("\n", gdb_stderr);
- fputs_unfiltered (prefix, gdb_stderr);
+ fputs_unfiltered (prev_suffix, gdb_stdlog);
+ fputs_unfiltered ("\n", gdb_stdlog);
+ fputs_unfiltered (prefix, gdb_stdlog);
}
/* Print prefix if we printed a newline during the previous call. */
if (new_line)
{
new_line = 0;
- fputs_unfiltered (prefix, gdb_stderr);
+ fputs_unfiltered (prefix, gdb_stdlog);
}
prev_prefix = prefix;
while ((ch = *string++) != '\0')
{
switch (ch)
- {
+ {
default:
if (isprint (ch))
- fputc_unfiltered (ch, gdb_stderr);
+ fputc_unfiltered (ch, gdb_stdlog);
else
- fprintf_unfiltered (gdb_stderr, "\\x%02x", ch & 0xff);
+ fprintf_unfiltered (gdb_stdlog, "\\x%02x", ch & 0xff);
break;
- case '\\': fputs_unfiltered ("\\\\", gdb_stderr); break;
- case '\b': fputs_unfiltered ("\\b", gdb_stderr); break;
- case '\f': fputs_unfiltered ("\\f", gdb_stderr); break;
- case '\n': new_line = 1;
- fputs_unfiltered ("\\n", gdb_stderr); break;
- case '\r': fputs_unfiltered ("\\r", gdb_stderr); break;
- case '\t': fputs_unfiltered ("\\t", gdb_stderr); break;
- case '\v': fputs_unfiltered ("\\v", gdb_stderr); break;
- }
+ case '\\':
+ fputs_unfiltered ("\\\\", gdb_stdlog);
+ break;
+ case '\b':
+ fputs_unfiltered ("\\b", gdb_stdlog);
+ break;
+ case '\f':
+ fputs_unfiltered ("\\f", gdb_stdlog);
+ break;
+ case '\n':
+ new_line = 1;
+ fputs_unfiltered ("\\n", gdb_stdlog);
+ break;
+ case '\r':
+ fputs_unfiltered ("\\r", gdb_stdlog);
+ break;
+ case '\t':
+ fputs_unfiltered ("\\t", gdb_stdlog);
+ break;
+ case '\v':
+ fputs_unfiltered ("\\v", gdb_stdlog);
+ break;
+ }
return_p = ch == '\r';
}
/* Print suffix if we printed a newline. */
if (new_line)
{
- fputs_unfiltered (suffix, gdb_stderr);
- fputs_unfiltered ("\n", gdb_stderr);
+ fputs_unfiltered (suffix, gdb_stdlog);
+ fputs_unfiltered ("\n", gdb_stdlog);
}
}
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);
}
-/* VARARGS */
void
-#ifdef ANSI_PROTOTYPES
-fprintf_filtered (GDB_FILE *stream, const char *format, ...)
-#else
-fprintf_filtered (va_alist)
- va_dcl
-#endif
+fprintf_filtered (struct ui_file * stream, const char *format,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, format);
-#else
- GDB_FILE *stream;
- char *format;
-
- va_start (args);
- stream = va_arg (args, GDB_FILE *);
- format = va_arg (args, char *);
-#endif
vfprintf_filtered (stream, format, args);
va_end (args);
}
-/* VARARGS */
void
-#ifdef ANSI_PROTOTYPES
-fprintf_unfiltered (GDB_FILE *stream, const char *format, ...)
-#else
-fprintf_unfiltered (va_alist)
- va_dcl
-#endif
+fprintf_unfiltered (struct ui_file * stream, const char *format,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, format);
-#else
- GDB_FILE *stream;
- char *format;
-
- va_start (args);
- stream = va_arg (args, GDB_FILE *);
- format = va_arg (args, char *);
-#endif
vfprintf_unfiltered (stream, format, args);
va_end (args);
}
/* Like fprintf_filtered, but prints its result indented.
Called as fprintfi_filtered (spaces, stream, format, ...); */
-/* VARARGS */
void
-#ifdef ANSI_PROTOTYPES
-fprintfi_filtered (int spaces, GDB_FILE *stream, const char *format, ...)
-#else
-fprintfi_filtered (va_alist)
- va_dcl
-#endif
+fprintfi_filtered (int spaces, struct ui_file * stream, const char *format,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, format);
-#else
- int spaces;
- GDB_FILE *stream;
- char *format;
-
- va_start (args);
- spaces = va_arg (args, int);
- stream = va_arg (args, GDB_FILE *);
- format = va_arg (args, char *);
-#endif
print_spaces_filtered (spaces, stream);
vfprintf_filtered (stream, format, args);
}
-/* VARARGS */
void
-#ifdef ANSI_PROTOTYPES
-printf_filtered (const char *format, ...)
-#else
-printf_filtered (va_alist)
- va_dcl
-#endif
+printf_filtered (const char *format,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, format);
-#else
- char *format;
-
- va_start (args);
- format = va_arg (args, char *);
-#endif
vfprintf_filtered (gdb_stdout, format, args);
va_end (args);
}
-/* VARARGS */
void
-#ifdef ANSI_PROTOTYPES
-printf_unfiltered (const char *format, ...)
-#else
-printf_unfiltered (va_alist)
- va_dcl
-#endif
+printf_unfiltered (const char *format,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, format);
-#else
- char *format;
-
- va_start (args);
- format = va_arg (args, char *);
-#endif
vfprintf_unfiltered (gdb_stdout, format, args);
va_end (args);
}
/* Like printf_filtered, but prints it's result indented.
Called as printfi_filtered (spaces, format, ...); */
-/* VARARGS */
void
-#ifdef ANSI_PROTOTYPES
-printfi_filtered (int spaces, const char *format, ...)
-#else
-printfi_filtered (va_alist)
- va_dcl
-#endif
+printfi_filtered (int spaces, const char *format,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, format);
-#else
- int spaces;
- char *format;
-
- va_start (args);
- spaces = va_arg (args, int);
- format = va_arg (args, char *);
-#endif
print_spaces_filtered (spaces, gdb_stdout);
vfprintf_filtered (gdb_stdout, format, args);
va_end (args);
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);
}
/* 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;
if (n > max_spaces)
{
if (spaces)
- free (spaces);
- spaces = (char *) xmalloc (n+1);
- for (t = spaces+n; t != spaces;)
+ xfree (spaces);
+ spaces = (char *) xmalloc (n + 1);
+ for (t = spaces + n; t != spaces;)
*--t = ' ';
spaces[n] = '\0';
max_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);
}
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;
fputs_filtered (demangled ? demangled : name, stream);
if (demangled != NULL)
{
- free (demangled);
+ xfree (demangled);
}
}
}
/* Do a strcmp() type operation on STRING1 and STRING2, ignoring any
differences in whitespace. Returns 0 if they match, non-zero if they
don't (slightly different than strcmp()'s range of return values).
-
+
As an extra hack, string1=="FOO(ARGS)" matches string2=="FOO".
This "feature" is useful when searching for matching C++ function names
(such as if the user types 'break FOO', where FOO is a mangled C++
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'))
{
}
return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0');
}
-
\f
+
/*
-** subset_compare()
-** Answer whether string_to_compare is a full or partial match to
-** template_string. The partial match must be in sequence starting
-** at index 0.
-*/
+ ** subset_compare()
+ ** Answer whether string_to_compare is a full or partial match to
+ ** template_string. The partial match must be in sequence starting
+ ** 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 &&
- strlen(string_to_compare) <= strlen(template_string))
- match = (strncmp(template_string,
- string_to_compare,
- strlen(string_to_compare)) == 0);
+ if (template_string != (char *) NULL && string_to_compare != (char *) NULL &&
+ strlen (string_to_compare) <= strlen (template_string))
+ match = (strncmp (template_string,
+ string_to_compare,
+ strlen (string_to_compare)) == 0);
else
match = 0;
return match;
}
-static void pagination_on_command 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;
}
-
\f
+
void
-initialize_utils ()
+initialize_utils (void)
{
struct cmd_list_element *c;
- c = add_set_cmd ("width", class_support, var_uinteger,
- (char *)&chars_per_line,
- "Set number of characters gdb thinks are in a line.",
- &setlist);
+ c = add_set_cmd ("width", class_support, var_uinteger,
+ (char *) &chars_per_line,
+ "Set number of characters gdb thinks are in a line.",
+ &setlist);
add_show_from_set (c, &showlist);
c->function.sfunc = set_width_command;
add_show_from_set
(add_set_cmd ("height", class_support,
- var_uinteger, (char *)&lines_per_page,
+ var_uinteger, (char *) &lines_per_page,
"Set number of lines gdb thinks are in a page.", &setlist),
&showlist);
-
+
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);
+ set_width_command ((char *) NULL, 0, c);
add_show_from_set
- (add_set_cmd ("demangle", class_support, var_boolean,
- (char *)&demangle,
- "Set demangling of encoded C++ names when displaying symbols.",
+ (add_set_cmd ("demangle", class_support, var_boolean,
+ (char *) &demangle,
+ "Set demangling of encoded C++ names when displaying symbols.",
&setprintlist),
&showprintlist);
add_show_from_set
(add_set_cmd ("pagination", class_support,
- var_boolean, (char *)&pagination_enabled,
+ var_boolean, (char *) &pagination_enabled,
"Set state of pagination.", &setlist),
&showlist);
+
if (xdb_commands)
{
- add_com("am", class_support, pagination_on_command,
- "Enable pagination");
- add_com("sm", class_support, pagination_off_command,
- "Disable pagination");
+ add_com ("am", class_support, pagination_on_command,
+ "Enable pagination");
+ add_com ("sm", class_support, pagination_off_command,
+ "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.",
+ (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++ names in disassembly listings.",
+ (add_set_cmd ("asm-demangle", class_support, var_boolean,
+ (char *) &asm_demangle,
+ "Set demangling of C++ names in disassembly listings.",
&setprintlist),
&showprintlist);
}
/* Machine specific function to handle SIGWINCH signal. */
#ifdef SIGWINCH_HANDLER_BODY
- SIGWINCH_HANDLER_BODY
+SIGWINCH_HANDLER_BODY
#endif
\f
/* Support for converting target fp numbers into host DOUBLEST format. */
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));
+static unsigned long get_field (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;
+get_field (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. */
- cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
if (order == floatformat_little || order == floatformat_littlebyte_bigword)
- cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
- cur_bitshift =
- ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
- result = *(data + cur_byte) >> (-cur_bitshift);
+ {
+ /* 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;
/* 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; zero out the bits which are not part of
- this field. */
- result |=
- (*(data + cur_byte) & ((1 << (len - cur_bitshift)) - 1))
- << cur_bitshift;
- else
- result |= *(data + cur_byte) << cur_bitshift;
+ 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;
+floatformat_to_doublest (const struct floatformat *fmt, char *from,
+ DOUBLEST *to)
{
- unsigned char *ufrom = (unsigned char *)from;
+ unsigned char *ufrom = (unsigned char *) from;
DOUBLEST dto;
long exponent;
unsigned long mant;
than sizeof(long) for the target. FIXME: Assumes sizeof(long)
for the target is 4. */
- if (fmt -> byteorder == floatformat_littlebyte_bigword)
+ if (fmt->byteorder == floatformat_littlebyte_bigword)
{
static unsigned char *newfrom;
unsigned char *swapin, *swapout;
int longswaps;
- longswaps = fmt -> totalsize / FLOATFORMAT_CHAR_BIT;
+ longswaps = fmt->totalsize / FLOATFORMAT_CHAR_BIT;
longswaps >>= 3;
-
+
if (newfrom == NULL)
{
- newfrom = (unsigned char *) xmalloc (fmt -> totalsize);
+ newfrom = (unsigned char *) xmalloc (fmt->totalsize);
}
swapout = newfrom;
swapin = ufrom;
special_exponent = exponent == 0 || exponent == fmt->exp_nan;
-/* Don't bias zero's, denorms or NaNs. */
+/* 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. */
mant_bits = min (mant_bits_left, 32);
mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
- mant_off, mant_bits);
+ mant_off, mant_bits);
- dto += ldexp ((double)mant, exponent - mant_bits);
+ dto += ldexp ((double) mant, exponent - mant_bits);
exponent -= mant_bits;
mant_off += mant_bits;
mant_bits_left -= mant_bits;
*to = dto;
}
\f
-static void put_field PARAMS ((unsigned char *, enum floatformat_byteorders,
- unsigned int,
- unsigned int,
- unsigned int,
- unsigned long));
+static void put_field (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;
+put_field (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. */
- cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
if (order == floatformat_little || order == floatformat_littlebyte_bigword)
- cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
- cur_bitshift =
- ((start + len) % FLOATFORMAT_CHAR_BIT) - 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);
+ {
+ 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;
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 (long double value, int *eptr);
static long double
-ldfrexp (value, eptr)
- long double value;
- int *eptr;
+ldfrexp (long double value, int *eptr)
{
long double tmp;
int exp;
}
*eptr = exp;
- return value/tmp;
+ return value / tmp;
}
#endif /* HAVE_LONG_DOUBLE */
restrictions. */
void
-floatformat_from_doublest (fmt, from, to)
- CONST struct floatformat *fmt;
- DOUBLEST *from;
- char *to;
+floatformat_from_doublest (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;
+ unsigned char *uto = (unsigned char *) to;
memcpy (&dfrom, from, sizeof (dfrom));
- memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
+ memset (uto, 0, (fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1)
+ / FLOATFORMAT_CHAR_BIT);
if (dfrom == 0)
return; /* Result is zero */
if (dfrom != dfrom) /* Result is NaN */
mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
mant *= 4294967296.0;
- mant_long = (unsigned long)mant;
+ mant_long = ((unsigned long) mant) & 0xffffffffL;
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 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_long &= 0xffffffffL;
mant_bits -= 1;
}
mant_off += mant_bits;
mant_bits_left -= mant_bits;
}
- if (fmt -> byteorder == floatformat_littlebyte_bigword)
+ if (fmt->byteorder == floatformat_littlebyte_bigword)
{
int count;
unsigned char *swaplow = uto;
}
}
+/* print routines to handle variable size regs, etc. */
+
/* temporary storage using circular buffer */
#define NUMCELLS 16
#define CELLSIZE 32
-static char*
-get_cell()
+static char *
+get_cell (void)
{
static char buf[NUMCELLS][CELLSIZE];
- static int cell=0;
- if (++cell>=NUMCELLS) cell=0;
+ static int cell = 0;
+ if (++cell >= NUMCELLS)
+ cell = 0;
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_ADDR_BIT / 8 * 2);
+}
- */
+char *
+paddr (CORE_ADDR addr)
+{
+ return phex (addr, TARGET_ADDR_BIT / 8);
+}
-static int thirty_two = 32; /* eliminate warning from compiler on 32-bit systems */
+char *
+paddr_nz (CORE_ADDR addr)
+{
+ return phex_nz (addr, TARGET_ADDR_BIT / 8);
+}
-char*
-paddr(addr)
- t_addr addr;
+static void
+decimal2str (char *paddr_str, char *sign, ULONGEST addr)
{
- char *paddr_str=get_cell();
- switch (sizeof(t_addr))
+ /* steal code from valprint.c:print_decimal(). Should this worry
+ about the real size of addr as the above does? */
+ unsigned long temp[3];
+ int i = 0;
+ do
{
- 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);
+ temp[i] = addr % (1000 * 1000 * 1000);
+ addr /= (1000 * 1000 * 1000);
+ i++;
+ }
+ while (addr != 0 && i < (sizeof (temp) / sizeof (temp[0])));
+ switch (i)
+ {
+ case 1:
+ sprintf (paddr_str, "%s%lu",
+ sign, temp[0]);
+ break;
+ case 2:
+ sprintf (paddr_str, "%s%lu%09lu",
+ sign, temp[1], temp[0]);
+ break;
+ case 3:
+ sprintf (paddr_str, "%s%lu%09lu%09lu",
+ sign, temp[2], temp[1], temp[0]);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
}
+}
+
+char *
+paddr_u (CORE_ADDR addr)
+{
+ char *paddr_str = get_cell ();
+ decimal2str (paddr_str, "", addr);
return paddr_str;
}
-char*
-preg(reg)
- t_reg reg;
+char *
+paddr_d (LONGEST addr)
{
- char *preg_str=get_cell();
- switch (sizeof(t_reg))
- {
- case 8:
- sprintf (preg_str, "%08lx%08lx",
- (unsigned long) (reg >> thirty_two), (unsigned long) (reg & 0xffffffff));
- break;
- case 4:
- sprintf (preg_str, "%08lx", (unsigned long) reg);
- break;
- case 2:
- sprintf (preg_str, "%04x", (unsigned short) (reg & 0xffff));
- break;
- default:
- sprintf (preg_str, "%lx", (unsigned long) reg);
- }
- return preg_str;
+ char *paddr_str = get_cell ();
+ if (addr < 0)
+ decimal2str (paddr_str, "-", -addr);
+ else
+ decimal2str (paddr_str, "", addr);
+ return paddr_str;
}
-char*
-paddr_nz(addr)
- t_addr addr;
+/* eliminate warning from compiler on 32-bit systems */
+static int thirty_two = 32;
+
+char *
+phex (ULONGEST l, int sizeof_l)
{
- char *paddr_str=get_cell();
- switch (sizeof(t_addr))
+ char *str = get_cell ();
+ switch (sizeof_l)
{
- 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);
+ case 8:
+ sprintf (str, "%08lx%08lx",
+ (unsigned long) (l >> thirty_two),
+ (unsigned long) (l & 0xffffffff));
+ break;
+ case 4:
+ sprintf (str, "%08lx", (unsigned long) l);
+ break;
+ case 2:
+ sprintf (str, "%04x", (unsigned short) (l & 0xffff));
+ break;
+ default:
+ phex (l, sizeof (l));
+ break;
}
- return paddr_str;
+ return str;
}
-char*
-preg_nz(reg)
- t_reg reg;
+char *
+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);
- if (high == 0)
- sprintf (preg_str, "%lx", (unsigned long) (reg & 0xffffffff));
- else
- sprintf (preg_str, "%lx%08lx",
- high, (unsigned long) (reg & 0xffffffff));
- break;
- }
- case 4:
- sprintf (preg_str, "%lx", (unsigned long) reg);
- break;
- case 2:
- sprintf (preg_str, "%x", (unsigned short) (reg & 0xffff));
+ case 8:
+ {
+ unsigned long high = (unsigned long) (l >> thirty_two);
+ if (high == 0)
+ sprintf (str, "%lx", (unsigned long) (l & 0xffffffff));
+ else
+ sprintf (str, "%lx%08lx",
+ high, (unsigned long) (l & 0xffffffff));
break;
- default:
- sprintf (preg_str, "%lx", (unsigned long) reg);
+ }
+ case 4:
+ sprintf (str, "%lx", (unsigned long) l);
+ break;
+ case 2:
+ sprintf (str, "%x", (unsigned short) (l & 0xffff));
+ break;
+ default:
+ 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_ptr))
+ internal_error (__FILE__, __LINE__,
+ "core_addr_to_void_ptr: bad cast");
+ return POINTER_TO_ADDRESS (builtin_type_ptr, &ptr);
}
-int
-core_addr_greaterthan (lhs, rhs)
- CORE_ADDR lhs;
- CORE_ADDR rhs;
+void *
+address_to_host_pointer (CORE_ADDR addr)
{
- return (lhs > rhs);
+ void *ptr;
+ if (sizeof (ptr) != TYPE_LENGTH (builtin_type_ptr))
+ internal_error (__FILE__, __LINE__,
+ "core_addr_to_void_ptr: bad cast");
+ ADDRESS_TO_POINTER (builtin_type_ptr, &ptr, addr);
+ return ptr;
}
-
-