/* General utility routines for GDB, the GNU debugger.
- Copyright 1986, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright 1986, 1989, 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
This file is part of GDB.
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
-#if !defined(__GO32__)
+#if !defined(__GO32__) && !defined(WIN32)
#include <sys/ioctl.h>
#include <sys/param.h>
#include <pwd.h>
#endif
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
#include <varargs.h>
+#endif
#include <ctype.h>
#include <string.h>
#include "signals.h"
#include "gdbcmd.h"
#include "serial.h"
-#include "terminal.h" /* For job_control */
#include "bfd.h"
#include "target.h"
#include "demangle.h"
#include "expression.h"
#include "language.h"
+#include "annotate.h"
#include "readline.h"
#endif /* NO_MMALLOC, etc */
static void
-fatal_dump_core (); /* Can't prototype with <varargs.h> usage... */
+fatal_dump_core PARAMS((char *, ...));
static void
prompt_for_continue PARAMS ((void));
static struct cleanup *cleanup_chain;
+/* Nonzero if we have job control. */
+
+int job_control;
+
/* Nonzero means a quit has been requested. */
int quit_flag;
/* String to be printed before error messages, if any. */
char *error_pre_print;
+
+/* String to be printed before quit messages, if any. */
+
+char *quit_pre_print;
+
+/* String to be printed before warning messages, if any. */
+
char *warning_pre_print = "\nwarning: ";
\f
/* Add a new cleanup to the cleanup_chain,
}
\f
-/* Provide a hook for modules wishing to print their own warning messages
- to set up the terminal state in a compatible way, without them having
- to import all the target_<...> macros. */
+/* 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? */
void
-warning_setup ()
+warning_begin ()
{
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);
}
/* Print a warning message.
The first argument STRING is the warning message, used as a fprintf string,
and the remaining args are passed as arguments to it.
The primary difference between warnings and errors is that a warning
- does not force the return to command level. */
+ does not force the return to command level. */
/* VARARGS */
void
+#ifdef ANSI_PROTOTYPES
+warning (char *string, ...)
+#else
warning (va_alist)
va_dcl
+#endif
{
va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
char *string;
va_start (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);
string = va_arg (args, char *);
+#endif
+ 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, 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. */
+ 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 ()
{
wrap_here (""); /* Force out any buffered output */
gdb_flush (gdb_stdout);
- if (annotation_level > 1)
- fprintf_filtered (gdb_stderr, "\n\032\032error-begin\n");
+ annotate_error_begin ();
if (error_pre_print)
fprintf_filtered (gdb_stderr, error_pre_print);
The first argument STRING is the error message, used as a fprintf string,
and the remaining args are passed as arguments to it. */
-/* VARARGS */
+#ifdef ANSI_PROTOTYPES
NORETURN void
+error (char *string, ...)
+#else
error (va_alist)
va_dcl
+#endif
{
+#ifdef ANSI_PROTOTYPES
va_list args;
- char *string;
-
- error_begin ();
+ va_start (args, string);
+#else
va_start (args);
- string = va_arg (args, char *);
- vfprintf_filtered (gdb_stderr, string, args);
- fprintf_filtered (gdb_stderr, "\n");
- va_end (args);
- return_to_top_level (RETURN_ERROR);
+#endif
+ if (error_hook)
+ error_hook();
+ else
+ {
+ char *string1;
+ error_begin ();
+#ifdef ANSI_PROTOTYPES
+ vfprintf_filtered (gdb_stderr, string, args);
+#else
+ 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);
+ }
}
+
/* 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.
/* VARARGS */
NORETURN void
+#ifdef ANSI_PROTOTYPES
+fatal (char *string, ...)
+#else
fatal (va_alist)
va_dcl
+#endif
{
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");
/* VARARGS */
static void
+#ifdef ANSI_PROTOTYPES
+fatal_dump_core (char *string, ...)
+#else
fatal_dump_core (va_alist)
va_dcl
+#endif
{
va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
char *string;
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: ");
SERIAL_FLUSH_OUTPUT (gdb_stdout_serial);
SERIAL_UN_FDOPEN (gdb_stdout_serial);
- if (annotation_level > 1)
- fprintf_filtered (gdb_stderr, "\n\032\032error-begin\n");
+ annotate_error_begin ();
/* Don't use *_filtered; we don't want to prompt the user to continue. */
- if (error_pre_print)
- fprintf_unfiltered (gdb_stderr, error_pre_print);
+ if (quit_pre_print)
+ fprintf_unfiltered (gdb_stderr, quit_pre_print);
if (job_control
/* If there is no terminal switching for this target, then we can't
possibly get screwed by the lack of job control. */
- || current_target->to_terminal_ours == NULL)
+ || current_target.to_terminal_ours == NULL)
fprintf_unfiltered (gdb_stderr, "Quit\n");
else
fprintf_unfiltered (gdb_stderr,
}
-#ifdef __GO32__
+#if defined(__GO32__)||defined(WIN32)
/* In the absence of signals, poll keyboard for a quit.
Called from #define QUIT pollquit() in xm-go32.h. */
#endif
-#ifdef __GO32__
+#if defined(__GO32__)||defined(WIN32)
void notice_quit()
{
if (kbhit ())
about USG defines and stuff like that. */
signal (signo, request_quit);
+#ifdef REQUEST_QUIT
+ REQUEST_QUIT;
+#else
if (immediate_quit)
quit ();
+#endif
}
\f
#if defined (NO_MMALLOC)
+/* Make a substitute size_t for non-ANSI compilers. */
+
+#ifdef _AIX
+#include <stddef.h>
+#else /* Not AIX */
+#ifndef __STDC__
+#ifndef size_t
+#define size_t unsigned int
+#endif
+#endif
+#endif /* Not AIX */
+
PTR
mmalloc (md, size)
PTR md;
- long size;
+ size_t size;
{
- return (malloc (size));
+ return malloc (size);
}
PTR
mrealloc (md, ptr, size)
PTR md;
PTR ptr;
- long size;
+ size_t size;
{
if (ptr == 0) /* Guard against old realloc's */
return malloc (size);
/* VARARGS */
int
+#ifdef ANSI_PROTOTYPES
+query (char *ctlstr, ...)
+#else
query (va_alist)
va_dcl
+#endif
{
va_list args;
- char *ctlstr;
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)
+ {
+ return query_hook (ctlstr, args);
+ }
+
/* 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 */
while (1)
{
if (annotation_level > 1)
printf_filtered ("\n\032\032pre-query\n");
- va_start (args);
- ctlstr = va_arg (args, char *);
vfprintf_filtered (gdb_stdout, ctlstr, args);
- va_end (args);
printf_filtered ("(y or n) ");
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 */
+
gdb_flush (gdb_stdout);
answer = fgetc (stdin);
clearerr (stdin); /* in case of C-d */
wrap_here(indent)
char *indent;
{
+ /* This should have been allocated, but be paranoid anyway. */
+ if (!wrap_buffer)
+ abort ();
+
if (wrap_buffer[0])
{
*wrap_pointer = '\0';
- fputs (wrap_buffer, gdb_stdout);
+ fputs_unfiltered (wrap_buffer, gdb_stdout);
}
wrap_pointer = wrap_buffer;
wrap_buffer[0] = '\0';
gdb_flush (stream)
FILE *stream;
{
+ if (flush_hook)
+ {
+ flush_hook (stream);
+ return;
+ }
+
fflush (stream);
}
if (linebuffer == 0)
return;
-
+
/* Don't do any filtering if it is disabled. */
if (stream != gdb_stdout
|| (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX))
{
- fputs (linebuffer, stream);
+ fputs_unfiltered (linebuffer, stream);
return;
}
if (wrap_column)
*wrap_pointer++ = '\t';
else
- putc ('\t', stream);
+ 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. */
if (wrap_column)
*wrap_pointer++ = *lineptr;
else
- putc (*lineptr, stream);
+ fputc_unfiltered (*lineptr, stream);
chars_printed++;
lineptr++;
}
if chars_per_line is right, we probably just overflowed
anyway; if it's wrong, let us keep going. */
if (wrap_column)
- putc ('\n', stream);
+ fputc_unfiltered ('\n', stream);
/* Possible new page. */
if (lines_printed >= lines_per_page - 1)
/* Now output indentation and wrapped string */
if (wrap_column)
{
- fputs (wrap_indent, stream);
- *wrap_pointer = '\0'; /* Null-terminate saved stuff */
- fputs (wrap_buffer, stream); /* and eject it */
+ fputs_unfiltered (wrap_indent, stream);
+ *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
chars_printed = 0;
wrap_here ((char *)0); /* Spit out chars, cancel further wraps */
lines_printed++;
- putc ('\n', stream);
+ fputc_unfiltered ('\n', stream);
lineptr++;
}
}
fputs_maybe_filtered (linebuffer, stream, 1);
}
-void
-fputs_unfiltered (linebuffer, stream)
- const char *linebuffer;
- FILE *stream;
-{
-#if 0
-
- /* This gets the wrap_buffer buffering wrong when called from
- gdb_readline (GDB was sometimes failing to print the prompt
- before reading input). Even at other times, it seems kind of
- misguided, especially now that printf_unfiltered doesn't use
- printf_maybe_filtered. */
-
- fputs_maybe_filtered (linebuffer, stream, 0);
-#else
- fputs (linebuffer, stream);
-#endif
-}
-
-void
-putc_unfiltered (c)
+int
+putchar_unfiltered (c)
int c;
{
char buf[2];
+
buf[0] = c;
buf[1] = 0;
fputs_unfiltered (buf, gdb_stdout);
+ return c;
}
-void
+int
fputc_unfiltered (c, stream)
int c;
FILE * stream;
{
char buf[2];
+
buf[0] = c;
buf[1] = 0;
fputs_unfiltered (buf, stream);
+ return c;
}
/* Print a variable number of ARGS using format FORMAT. If this
information is going to put the amount written (since the last call
to REINITIALIZE_MORE_FILTER or the last page break) over the page size,
- print out a pause message and do a gdb_readline to get the users
- permision to continue.
+ call prompt_for_continue to get the users permision to continue.
Unlike fprintf, this function does not return a value.
We implement three variants, vfprintf (takes a vararg list and stream),
fprintf (takes a stream to write on), and printf (the usual).
- Note that this routine has a restriction that the length of the
- final output line must be less than 255 characters *or* it must be
- less than twice the size of the format string. This is a very
- arbitrary restriction, but it is an internal restriction, so I'll
- put it in. This means that the %s format specifier is almost
- useless; unless the caller can GUARANTEE that the string is short
- enough, fputs_filtered should be used instead.
-
Note also that a longjmp to top level may occur in this routine
(since prompt_for_continue may do so) so this routine should not be
called when cleanups are not in place. */
-#define MIN_LINEBUF 255
-
static void
vfprintf_maybe_filtered (stream, format, args, filter)
FILE *stream;
va_list args;
int filter;
{
- char line_buf[MIN_LINEBUF+10];
- char *linebuffer = line_buf;
- int format_length;
+ char *linebuffer;
+ struct cleanup *old_cleanups;
- format_length = strlen (format);
-
- /* Reallocate buffer to a larger size if this is necessary. */
- if (format_length * 2 > MIN_LINEBUF)
+ vasprintf (&linebuffer, format, args);
+ if (linebuffer == NULL)
{
- linebuffer = alloca (10 + format_length * 2);
+ fputs_unfiltered ("\ngdb: virtual memory exhausted.\n", gdb_stderr);
+ exit (1);
}
-
- /* This won't blow up if the restrictions described above are
- followed. */
- vsprintf (linebuffer, format, args);
-
+ old_cleanups = make_cleanup (free, linebuffer);
fputs_maybe_filtered (linebuffer, stream, filter);
+ do_cleanups (old_cleanups);
}
char *format;
va_list args;
{
- vfprintf (stream, format, 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);
+ fputs_unfiltered (linebuffer, stream);
+ do_cleanups (old_cleanups);
}
void
char *format;
va_list args;
{
- vfprintf (gdb_stdout, format, args);
+ vfprintf_unfiltered (gdb_stdout, format, args);
}
/* VARARGS */
void
+#ifdef ANSI_PROTOTYPES
+fprintf_filtered (FILE *stream, char *format, ...)
+#else
fprintf_filtered (va_alist)
va_dcl
+#endif
{
va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
FILE *stream;
char *format;
va_start (args);
stream = va_arg (args, FILE *);
format = va_arg (args, char *);
-
- /* This won't blow up if the restrictions described above are
- followed. */
+#endif
vfprintf_filtered (stream, format, args);
va_end (args);
}
/* VARARGS */
void
+#ifdef ANSI_PROTOTYPES
+fprintf_unfiltered (FILE *stream, char *format, ...)
+#else
fprintf_unfiltered (va_alist)
va_dcl
+#endif
{
va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
FILE *stream;
char *format;
va_start (args);
stream = va_arg (args, FILE *);
format = va_arg (args, char *);
-
- /* This won't blow up if the restrictions described above are
- followed. */
+#endif
vfprintf_unfiltered (stream, format, args);
va_end (args);
}
-/* Like fprintf_filtered, but prints it's result indent.
+/* Like fprintf_filtered, but prints its result indented.
Called as fprintfi_filtered (spaces, stream, format, ...); */
/* VARARGS */
void
+#ifdef ANSI_PROTOTYPES
+fprintfi_filtered (int spaces, FILE *stream, char *format, ...)
+#else
fprintfi_filtered (va_alist)
va_dcl
+#endif
{
va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
int spaces;
FILE *stream;
char *format;
spaces = va_arg (args, int);
stream = va_arg (args, FILE *);
format = va_arg (args, char *);
+#endif
print_spaces_filtered (spaces, stream);
- /* This won't blow up if the restrictions described above are
- followed. */
vfprintf_filtered (stream, format, args);
va_end (args);
}
/* VARARGS */
void
+#ifdef ANSI_PROTOTYPES
+printf_filtered (char *format, ...)
+#else
printf_filtered (va_alist)
va_dcl
+#endif
{
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 (char *format, ...)
+#else
printf_unfiltered (va_alist)
va_dcl
+#endif
{
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);
}
/* VARARGS */
void
+#ifdef ANSI_PROTOTYPES
+printfi_filtered (int spaces, char *format, ...)
+#else
printfi_filtered (va_alist)
va_dcl
+#endif
{
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);
\f
void
-_initialize_utils ()
+initialize_utils ()
{
struct cmd_list_element *c;
/* These defaults will be used if we are unable to get the correct
values from termcap. */
-#if defined(__GO32__)
+#if defined(__GO32__) || defined(WIN32)
lines_per_page = ScreenRows();
chars_per_line = ScreenCols();
#else
lines_per_page = 24;
chars_per_line = 80;
+
+#ifndef MPW
+ /* 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. */
{
char *termtype = getenv ("TERM");
}
}
}
+#endif /* MPW */
#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)