/* General utility routines for GDB, the GNU debugger.
- Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+ 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GDB.
#endif
}
-/* Control C comes here */
-void
-request_quit (int signo)
-{
- quit_flag = 1;
- /* Restore the signal handler. Harmless with BSD-style signals,
- needed for System V-style signals. */
- signal (signo, request_quit);
-
- if (immediate_quit)
- quit ();
-}
\f
/* Called when a memory allocation fails, with the number of bytes of
memory requested in SIZE. */
fprintf_filtered (stream, "0x%lx", (unsigned long) addr);
}
-
-/* Ask user a y-or-n question and return 1 iff answer is yes.
- Takes three args which are given to printf to print the question.
- The first, a control string, should end in "? ".
- It should not say how to answer, because we do that. */
-
-/* VARARGS */
-int
-query (const char *ctlstr, ...)
-{
- va_list args;
- int answer;
- int ans2;
- int retval;
-
- /* Automatically answer "yes" if input is not from the user
- directly, or if the user did not want prompts. */
- if (!input_from_terminal_p () || !caution)
- return 1;
-
- if (deprecated_query_hook)
- {
- va_start (args, ctlstr);
- return deprecated_query_hook (ctlstr, args);
- }
-
- while (1)
- {
- wrap_here (""); /* Flush any buffered output */
- gdb_flush (gdb_stdout);
-
- if (annotation_level > 1)
- printf_filtered (("\n\032\032pre-query\n"));
-
- va_start (args, ctlstr);
- vfprintf_filtered (gdb_stdout, ctlstr, args);
- va_end (args);
- printf_filtered (_("(y or n) "));
-
- if (annotation_level > 1)
- printf_filtered (("\n\032\032query\n"));
-
- wrap_here ("");
- gdb_flush (gdb_stdout);
-
- answer = fgetc (stdin);
- 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')
- do
- {
- ans2 = fgetc (stdin);
- clearerr (stdin);
- }
- while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
-
- if (answer >= 'a')
- answer -= 040;
- if (answer == 'Y')
- {
- retval = 1;
- break;
- }
- if (answer == 'N')
- {
- retval = 0;
- break;
- }
- printf_filtered (_("Please answer y or n.\n"));
- }
-
- if (annotation_level > 1)
- printf_filtered (("\n\032\032post-query\n"));
- return retval;
-}
\f
-/* This function supports the nquery() and yquery() functions.
+/* This function supports the query, nquery, and yquery functions.
Ask user a y-or-n question and return 0 if answer is no, 1 if
- answer is yes, or default the answer to the specified default.
- DEFCHAR is either 'y' or 'n' and refers to the default answer.
+ answer is yes, or default the answer to the specified default
+ (for yquery or nquery). DEFCHAR may be 'y' or 'n' to provide a
+ default answer, or '\0' for no default.
CTLSTR is the control string and should end in "? ". It should
not say how to answer, because we do that.
ARGS are the arguments passed along with the CTLSTR argument to
int retval;
int def_value;
char def_answer, not_def_answer;
- char *y_string, *n_string;
+ char *y_string, *n_string, *question;
/* Set up according to which answer is the default. */
- if (defchar == 'y')
+ if (defchar == '\0')
+ {
+ def_value = 1;
+ def_answer = 'Y';
+ not_def_answer = 'N';
+ y_string = "y";
+ n_string = "n";
+ }
+ else if (defchar == 'y')
{
def_value = 1;
def_answer = 'Y';
n_string = "[n]";
}
+ /* Automatically answer the default value if the user did not want
+ prompts. */
+ if (! caution)
+ return def_value;
+
+ /* If input isn't coming from the user directly, just say what
+ question we're asking, and then answer "yes" automatically. This
+ way, important error messages don't get lost when talking to GDB
+ over a pipe. */
+ if (! input_from_terminal_p ())
+ {
+ wrap_here ("");
+ vfprintf_filtered (gdb_stdout, ctlstr, args);
+
+ printf_filtered (_("(%s or %s) [answered %c; input not from terminal]\n"),
+ y_string, n_string, def_answer);
+ gdb_flush (gdb_stdout);
+
+ return def_value;
+ }
+
/* Automatically answer the default value if input is not from the user
directly, or if the user did not want prompts. */
if (!input_from_terminal_p () || !caution)
return deprecated_query_hook (ctlstr, args);
}
+ /* Format the question outside of the loop, to avoid reusing args. */
+ question = xstrvprintf (ctlstr, args);
+
while (1)
{
wrap_here (""); /* Flush any buffered output */
if (annotation_level > 1)
printf_filtered (("\n\032\032pre-query\n"));
- vfprintf_filtered (gdb_stdout, ctlstr, args);
+ fputs_filtered (question, gdb_stdout);
printf_filtered (_("(%s or %s) "), y_string, n_string);
if (annotation_level > 1)
clearerr (stdin); /* in case of C-d */
if (answer == EOF) /* C-d */
{
+ printf_filtered ("EOF [assumed %c]\n", def_answer);
retval = def_value;
break;
}
retval = !def_value;
break;
}
- /* Otherwise, for the default, the user may either specify
- the required input or have it default by entering nothing. */
- if (answer == def_answer || answer == '\n' ||
- answer == '\r' || answer == EOF)
+ /* Otherwise, if a default was specified, the user may either
+ specify the required input or have it default by entering
+ nothing. */
+ if (answer == def_answer
+ || (defchar != '\0' &&
+ (answer == '\n' || answer == '\r' || answer == EOF)))
{
retval = def_value;
break;
y_string, n_string);
}
+ xfree (question);
if (annotation_level > 1)
printf_filtered (("\n\032\032post-query\n"));
return retval;
va_end (args);
}
+/* Ask user a y-or-n question and return 1 iff answer is yes.
+ Takes three args which are given to printf to print the question.
+ The first, a control string, should end in "? ".
+ It should not say how to answer, because we do that. */
+
+int
+query (const char *ctlstr, ...)
+{
+ va_list args;
+
+ va_start (args, ctlstr);
+ return defaulted_query (ctlstr, '\0', args);
+ va_end (args);
+}
+
/* Print an error message saying that we couldn't make sense of a
\^mumble sequence in a string or character constant. START and END
indicate a substring of some larger string that contains the
printchar (*str++, fputs_unfiltered, fprintf_unfiltered, stream, quoter);
}
+void
+fputstrn_filtered (const char *str, int n, int quoter,
+ struct ui_file *stream)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ printchar (str[i], fputs_filtered, fprintf_filtered, stream, quoter);
+}
+
void
fputstrn_unfiltered (const char *str, int n, int quoter,
struct ui_file *stream)
rows = INT_MAX;
if (cols <= 0)
- rl_get_screen_size (NULL, &cols);
+ cols = INT_MAX;
/* Update Readline's idea of the terminal size. */
rl_set_screen_size (rows, cols);
return match;
}
-
-static void pagination_on_command (char *arg, int from_tty);
static void
pagination_on_command (char *arg, int from_tty)
{
pagination_enabled = 1;
}
-static void pagination_on_command (char *arg, int from_tty);
static void
pagination_off_command (char *arg, int from_tty)
{
int
strlen_paddr (void)
{
- return (TARGET_ADDR_BIT / 8 * 2);
+ return (gdbarch_addr_bit (current_gdbarch) / 8 * 2);
}
char *
paddr (CORE_ADDR addr)
{
- return phex (addr, TARGET_ADDR_BIT / 8);
+ return phex (addr, gdbarch_addr_bit (current_gdbarch) / 8);
}
char *
paddr_nz (CORE_ADDR addr)
{
- return phex_nz (addr, TARGET_ADDR_BIT / 8);
+ return phex_nz (addr, gdbarch_addr_bit (current_gdbarch) / 8);
}
const char *
when it won't occur. */
/* NOTE: This assumes that the significant address information is
kept in the least significant bits of ADDR - the upper bits were
- either zero or sign extended. Should ADDRESS_TO_POINTER() or
+ either zero or sign extended. Should gdbarch_address_to_pointer or
some ADDRESS_TO_PRINTABLE() be used to do the conversion? */
- int addr_bit = TARGET_ADDR_BIT;
+ int addr_bit = gdbarch_addr_bit (current_gdbarch);
if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
addr &= ((CORE_ADDR) 1 << addr_bit) - 1;
CORE_ADDR addr = 0;
if (my_string[0] == '0' && tolower (my_string[1]) == 'x')
{
- /* Assume that it is in decimal. */
+ /* Assume that it is in hex. */
int i;
for (i = 2; my_string[i] != '\0'; i++)
{
else if (isxdigit (my_string[i]))
addr = (tolower (my_string[i]) - 'a' + 0xa) + (addr * 16);
else
- internal_error (__FILE__, __LINE__, _("invalid hex"));
+ error (_("invalid hex \"%s\""), my_string);
}
}
else
if (isdigit (my_string[i]))
addr = (my_string[i] - '0') + (addr * 10);
else
- internal_error (__FILE__, __LINE__, _("invalid decimal"));
+ error (_("invalid decimal \"%s\""), my_string);
}
}
return addr;
{
return;
}
+
+/* The bit offset of the highest byte in a ULONGEST, for overflow
+ checking. */
+
+#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
+
+/* True (non-zero) iff DIGIT is a valid digit in radix BASE,
+ where 2 <= BASE <= 36. */
+
+static int
+is_digit_in_base (unsigned char digit, int base)
+{
+ if (!isalnum (digit))
+ return 0;
+ if (base <= 10)
+ return (isdigit (digit) && digit < base + '0');
+ else
+ return (isdigit (digit) || tolower (digit) < base - 10 + 'a');
+}
+
+static int
+digit_to_int (unsigned char c)
+{
+ if (isdigit (c))
+ return c - '0';
+ else
+ return tolower (c) - 'a' + 10;
+}
+
+/* As for strtoul, but for ULONGEST results. */
+
+ULONGEST
+strtoulst (const char *num, const char **trailer, int base)
+{
+ unsigned int high_part;
+ ULONGEST result;
+ int minus = 0;
+ int i = 0;
+
+ /* Skip leading whitespace. */
+ while (isspace (num[i]))
+ i++;
+
+ /* Handle prefixes. */
+ if (num[i] == '+')
+ i++;
+ else if (num[i] == '-')
+ {
+ minus = 1;
+ i++;
+ }
+
+ if (base == 0 || base == 16)
+ {
+ if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X'))
+ {
+ i += 2;
+ if (base == 0)
+ base = 16;
+ }
+ }
+
+ if (base == 0 && num[i] == '0')
+ base = 8;
+
+ if (base == 0)
+ base = 10;
+
+ if (base < 2 || base > 36)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+
+ result = high_part = 0;
+ for (; is_digit_in_base (num[i], base); i += 1)
+ {
+ result = result * base + digit_to_int (num[i]);
+ high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN);
+ result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
+ if (high_part > 0xff)
+ {
+ errno = ERANGE;
+ result = ~ (ULONGEST) 0;
+ high_part = 0;
+ minus = 0;
+ break;
+ }
+ }
+
+ if (trailer != NULL)
+ *trailer = &num[i];
+
+ result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
+ if (minus)
+ return -result;
+ else
+ return result;
+}
+
+/* Simple, portable version of dirname that does not modify its
+ argument. */
+
+char *
+ldirname (const char *filename)
+{
+ const char *base = lbasename (filename);
+ char *dirname;
+
+ while (base > filename && IS_DIR_SEPARATOR (base[-1]))
+ --base;
+
+ if (base == filename)
+ return NULL;
+
+ dirname = xmalloc (base - filename + 2);
+ memcpy (dirname, filename, base - filename);
+
+ /* On DOS based file systems, convert "d:foo" to "d:.", so that we
+ create "d:./bar" later instead of the (different) "d:/bar". */
+ if (base - filename == 2 && IS_ABSOLUTE_PATH (base)
+ && !IS_DIR_SEPARATOR (filename[0]))
+ dirname[base++ - filename] = '.';
+
+ dirname[base - filename] = '\0';
+ return dirname;
+}