Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "defs.h"
-#include "gdb_assert.h"
-#include <ctype.h>
-#include "gdb_string.h"
-#include "event-top.h"
+/* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
+ "defs.h" should be included first. Unfortunatly some systems
+ (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
+ and they clash with "bfd.h"'s definiton of true/false. The correct
+ fix is to remove true/false from "bfd.h", however, until that
+ happens, hack around it by including "config.h" and <curses.h>
+ first. */
+
+#include "config.h"
#ifdef HAVE_CURSES_H
#include <curses.h>
#include <term.h>
#endif
+#include "defs.h"
+#include "gdb_assert.h"
+#include <ctype.h>
+#include "gdb_string.h"
+#include "event-top.h"
+
#ifdef __GO32__
#include <pc.h>
#endif
#include "expression.h"
#include "language.h"
#include "annotate.h"
+#include "filenames.h"
#include "inferior.h" /* for signed_pointer_to_address */
+#include <sys/param.h> /* For MAXPATHLEN */
+
#include <readline/readline.h>
#ifdef USE_MMALLOC
#include "mmalloc.h"
#endif
-#ifndef MALLOC_INCOMPATIBLE
#ifdef NEED_DECLARATION_MALLOC
extern PTR malloc ();
#endif
#ifdef NEED_DECLARATION_FREE
extern void free ();
#endif
+/* Actually, we'll never have the decl, since we don't define _GNU_SOURCE. */
+#if defined(HAVE_CANONICALIZE_FILE_NAME) \
+ && defined(NEED_DECLARATION_CANONICALIZE_FILE_NAME)
+extern char *canonicalize_file_name (const char *);
#endif
-#undef XMALLOC
-#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
-
/* readline defines this. */
#undef savestring
\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
- call afterwards, but such a thing might be added if it is useful
- for a GUI to separate warning messages from other output.
-
- FIXME: Why do warnings use unfiltered output and errors filtered?
- Is this anything other than a historical accident? */
+/* Print a warning message. The first argument STRING is the warning
+ message, used as an fprintf format string, the second is the
+ va_list of arguments for that string. A warning is unfiltered (not
+ paginated) so that the user does not need to page through each
+ screen full of warnings when there are lots of them. */
void
-warning_begin (void)
+vwarning (const char *string, va_list args)
{
- target_terminal_ours ();
- wrap_here (""); /* Force out any buffered output */
- gdb_flush (gdb_stdout);
- if (warning_pre_print)
- fprintf_unfiltered (gdb_stderr, warning_pre_print);
+ if (warning_hook)
+ (*warning_hook) (string, args);
+ else
+ {
+ target_terminal_ours ();
+ wrap_here (""); /* Force out any buffered output */
+ gdb_flush (gdb_stdout);
+ if (warning_pre_print)
+ fprintf_unfiltered (gdb_stderr, warning_pre_print);
+ vfprintf_unfiltered (gdb_stderr, string, args);
+ fprintf_unfiltered (gdb_stderr, "\n");
+ va_end (args);
+ }
}
/* Print a warning message.
{
va_list args;
va_start (args, string);
- if (warning_hook)
- (*warning_hook) (string, args);
- else
- {
- 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
- this, output the error message (use filtered output to gdb_stderr
- (FIXME: Some callers, like memory_error, use gdb_stdout)), ending
- in a newline, and then call return_to_top_level (RETURN_ERROR).
- error() provides a convenient way to do this for the special case
- that the error message can be formatted with a single printf call,
- but this is more general. */
-void
-error_begin (void)
-{
- if (error_begin_hook)
- error_begin_hook ();
-
- target_terminal_ours ();
- wrap_here (""); /* Force out any buffered output */
- gdb_flush (gdb_stdout);
-
- annotate_error_begin ();
-
- if (error_pre_print)
- fprintf_filtered (gdb_stderr, error_pre_print);
+ vwarning (string, args);
+ va_end (args);
}
/* Print an error message and return to command level.
NORETURN void
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);
+ struct ui_file *tmp_stream = mem_fileopen ();
+ make_cleanup_ui_file_delete (tmp_stream);
+ vfprintf_unfiltered (tmp_stream, string, args);
+ error_stream (tmp_stream);
}
NORETURN void
va_end (args);
}
+static void
+do_write (void *data, const char *buffer, long length_buffer)
+{
+ ui_file_write (data, buffer, length_buffer);
+}
+
NORETURN void
error_stream (struct ui_file *stream)
{
- long size;
- char *msg = ui_file_xstrdup (stream, &size);
- make_cleanup (xfree, msg);
- error ("%s", msg);
+ if (error_begin_hook)
+ error_begin_hook ();
+
+ /* Copy the stream into the GDB_LASTERR buffer. */
+ ui_file_rewind (gdb_lasterr);
+ ui_file_put (stream, do_write, gdb_lasterr);
+
+ /* Write the message plus any error_pre_print to gdb_stderr. */
+ target_terminal_ours ();
+ wrap_here (""); /* Force out any buffered output */
+ gdb_flush (gdb_stdout);
+ annotate_error_begin ();
+ if (error_pre_print)
+ fprintf_filtered (gdb_stderr, error_pre_print);
+ ui_file_put (stream, do_write, gdb_stderr);
+ fprintf_filtered (gdb_stderr, "\n");
+
+ throw_exception (RETURN_ERROR);
}
/* Get the last error message issued by gdb */
{
static char msg[] = "Internal GDB error: recursive internal error.\n";
static int dejavu = 0;
- int continue_p;
+ int quit_p;
int dump_core_p;
/* don't allow infinite error recursion. */
vfprintf_unfiltered (gdb_stderr, fmt, ap);
fputs_unfiltered ("\n", gdb_stderr);
- /* Default (no case) is to quit GDB. When in batch mode this
+ /* Default (yes/batch case) is to quit GDB. When in batch mode this
lessens the likelhood of GDB going into an infinate loop. */
- continue_p = query ("\
+ quit_p = query ("\
An internal GDB error was detected. This may make further\n\
-debugging unreliable. Continue this debugging session? ");
+debugging unreliable. Quit this debugging session? ");
- /* Default (no case) is to not dump core. Lessen the chance of GDB
- leaving random core files around. */
+ /* Default (yes/batch case) is to dump core. This leaves a GDB
+ dropping so that it is easier to see that something went wrong to
+ GDB. */
dump_core_p = query ("\
Create a core file containing the current state of GDB? ");
- if (continue_p)
+ if (quit_p)
{
if (dump_core_p)
- {
- if (fork () == 0)
- abort (); /* NOTE: GDB has only three calls to abort(). */
- }
+ abort (); /* NOTE: GDB has only three calls to abort(). */
+ else
+ exit (1);
}
else
{
if (dump_core_p)
- abort (); /* NOTE: GDB has only three calls to abort(). */
- else
- exit (1);
+ {
+ if (fork () == 0)
+ abort (); /* NOTE: GDB has only three calls to abort(). */
+ }
}
dejavu = 0;
- return_to_top_level (RETURN_ERROR);
+ throw_exception (RETURN_ERROR);
}
NORETURN void
Then return to command level. */
NORETURN void
-perror_with_name (char *string)
+perror_with_name (const char *string)
{
char *err;
char *combined;
as the file name for which the error was encountered. */
void
-print_sys_errmsg (char *string, int errcode)
+print_sys_errmsg (const char *string, int errcode)
{
char *err;
char *combined;
fprintf_unfiltered (gdb_stderr,
"Quit (expect signal SIGINT when the program is resumed)\n");
#endif
- return_to_top_level (RETURN_QUIT);
+ throw_exception (RETURN_QUIT);
}
/* Control C comes here */
/* VARARGS */
int
-query (char *ctlstr,...)
+query (const char *ctlstr,...)
{
va_list args;
register int answer;
"Set number of characters gdb thinks are in a line.",
&setlist);
add_show_from_set (c, &showlist);
- c->function.sfunc = set_width_command;
+ set_cmd_sfunc (c, set_width_command);
add_show_from_set
(add_set_cmd ("height", class_support,
/* Convert a CORE_ADDR into a string. */
const char *
core_addr_to_string (const CORE_ADDR addr)
+{
+ char *str = get_cell ();
+ strcpy (str, "0x");
+ strcat (str, phex (addr, sizeof (addr)));
+ return str;
+}
+
+const char *
+core_addr_to_string_nz (const CORE_ADDR addr)
{
char *str = get_cell ();
strcpy (str, "0x");
char *
gdb_realpath (const char *filename)
{
-#ifdef HAVE_REALPATH
+#if defined(HAVE_REALPATH)
+# if defined (PATH_MAX)
char buf[PATH_MAX];
+# define USE_REALPATH
+# elif defined (MAXPATHLEN)
+ char buf[MAXPATHLEN];
+# define USE_REALPATH
+# elif defined (HAVE_UNISTD_H) && defined(HAVE_ALLOCA)
+ char *buf = alloca ((size_t)pathconf ("/", _PC_PATH_MAX));
+# define USE_REALPATH
+# endif
+#endif /* HAVE_REALPATH */
+
+#if defined(USE_REALPATH)
char *rp = realpath (filename, buf);
return xstrdup (rp ? rp : filename);
+#elif defined(HAVE_CANONICALIZE_FILE_NAME)
+ char *rp = canonicalize_file_name (filename);
+ if (rp == NULL)
+ return xstrdup (filename);
+ else
+ return rp;
#else
return xstrdup (filename);
#endif
}
+
+/* Return a copy of FILENAME, with its directory prefix canonicalized
+ by gdb_realpath. */
+
+char *
+xfullpath (const char *filename)
+{
+ const char *base_name = lbasename (filename);
+ char *dir_name;
+ char *real_path;
+ char *result;
+
+ /* Extract the basename of filename, and return immediately
+ a copy of filename if it does not contain any directory prefix. */
+ if (base_name == filename)
+ return xstrdup (filename);
+
+ dir_name = alloca ((size_t) (base_name - filename + 2));
+ /* Allocate enough space to store the dir_name + plus one extra
+ character sometimes needed under Windows (see below), and
+ then the closing \000 character */
+ strncpy (dir_name, filename, base_name - filename);
+ dir_name[base_name - filename] = '\000';
+
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ /* We need to be careful when filename is of the form 'd:foo', which
+ is equivalent of d:./foo, which is totally different from d:/foo. */
+ if (strlen (dir_name) == 2 &&
+ isalpha (dir_name[0]) && dir_name[1] == ':')
+ {
+ dir_name[2] = '.';
+ dir_name[3] = '\000';
+ }
+#endif
+
+ /* Canonicalize the directory prefix, and build the resulting
+ filename. If the dirname realpath already contains an ending
+ directory separator, avoid doubling it. */
+ real_path = gdb_realpath (dir_name);
+ if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
+ result = concat (real_path, base_name, NULL);
+ else
+ result = concat (real_path, SLASH_STRING, base_name, NULL);
+
+ xfree (real_path);
+ return result;
+}