X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Futils.c;h=9aab625f63cf51fb20ab30e016a4001bec57a06b;hb=e36180d7954250489b69c8ad2050bc6b2af27b5c;hp=3323193b79a94192d8b49929bd8d53bd2e794997;hpb=520f6ade4aea34bb0f76138cdf9141edc7486ce5;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/utils.c b/gdb/utils.c index 3323193b79..9aab625f63 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -60,7 +60,9 @@ #include "demangle.h" #include "expression.h" #include "language.h" +#include "charset.h" #include "annotate.h" +#include "filenames.h" #include "inferior.h" /* for signed_pointer_to_address */ @@ -673,19 +675,34 @@ error_init (void) gdb_lasterr = mem_fileopen (); } -/* Print a message reporting an internal error. Ask the user if they - want to continue, dump core, or just exit. */ +/* Print a message reporting an internal error/warning. Ask the user + if they want to continue, dump core, or just exit. Return + something to indicate a quit. */ -NORETURN void -internal_verror (const char *file, int line, - const char *fmt, va_list ap) +struct internal_problem { - static char msg[] = "Internal GDB error: recursive internal error.\n"; - static int dejavu = 0; + const char *name; + /* FIXME: cagney/2002-08-15: There should be ``maint set/show'' + commands available for controlling these variables. */ + enum auto_boolean should_quit; + enum auto_boolean should_dump_core; +}; + +/* Report a problem, internal to GDB, to the user. Once the problem + has been reported, and assuming GDB didn't quit, the caller can + either allow execution to resume or throw an error. */ + +static void +internal_vproblem (struct internal_problem *problem, +const char *file, int line, + const char *fmt, va_list ap) +{ + static char msg[] = "Recursive internal problem.\n"; + static int dejavu; int quit_p; int dump_core_p; - /* don't allow infinite error recursion. */ + /* Don't allow infinite error/warning recursion. */ switch (dejavu) { case 0: @@ -701,23 +718,58 @@ internal_verror (const char *file, int line, exit (1); } - /* Try to get the message out */ + /* Try to get the message out and at the start of a new line. */ target_terminal_ours (); - fprintf_unfiltered (gdb_stderr, "%s:%d: gdb-internal-error: ", file, line); + begin_line (); + + /* The error/warning message. Format using a style similar to a + compiler error message. */ + fprintf_unfiltered (gdb_stderr, "%s:%d: %s: ", file, line, problem->name); vfprintf_unfiltered (gdb_stderr, fmt, ap); fputs_unfiltered ("\n", gdb_stderr); - /* Default (yes/batch case) is to quit GDB. When in batch mode this - lessens the likelhood of GDB going into an infinate loop. */ - quit_p = query ("\ -An internal GDB error was detected. This may make further\n\ -debugging unreliable. Quit this debugging session? "); + /* Provide more details so that the user knows that they are living + on the edge. */ + fprintf_unfiltered (gdb_stderr, "\ +A problem internal to GDB has been detected. Further\n\ +debugging may prove unreliable.\n"); - /* 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? "); + switch (problem->should_quit) + { + case AUTO_BOOLEAN_AUTO: + /* Default (yes/batch case) is to quit GDB. When in batch mode + this lessens the likelhood of GDB going into an infinate + loop. */ + quit_p = query ("Quit this debugging session? "); + break; + case AUTO_BOOLEAN_TRUE: + quit_p = 1; + break; + case AUTO_BOOLEAN_FALSE: + quit_p = 0; + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); + } + + switch (problem->should_dump_core) + { + case AUTO_BOOLEAN_AUTO: + /* Default (yes/batch case) is to dump core. This leaves a GDB + `dropping' so that it is easier to see that something went + wrong in GDB. */ + dump_core_p = query ("Create a core file of GDB? "); + break; + break; + case AUTO_BOOLEAN_TRUE: + dump_core_p = 1; + break; + case AUTO_BOOLEAN_FALSE: + dump_core_p = 0; + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); + } if (quit_p) { @@ -736,6 +788,17 @@ Create a core file containing the current state of GDB? "); } dejavu = 0; +} + +static struct internal_problem internal_error_problem = { + "internal-error", AUTO_BOOLEAN_AUTO, AUTO_BOOLEAN_AUTO +}; + +NORETURN void +internal_verror (const char *file, int line, + const char *fmt, va_list ap) +{ + internal_vproblem (&internal_error_problem, file, line, fmt, ap); throw_exception (RETURN_ERROR); } @@ -744,11 +807,30 @@ 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); } +static struct internal_problem internal_warning_problem = { + "internal-error", AUTO_BOOLEAN_AUTO, AUTO_BOOLEAN_AUTO +}; + +void +internal_vwarning (const char *file, int line, + const char *fmt, va_list ap) +{ + internal_vproblem (&internal_warning_problem, file, line, fmt, ap); +} + +void +internal_warning (const char *file, int line, const char *string, ...) +{ + va_list ap; + va_start (ap, string); + internal_vwarning (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. */ @@ -1281,6 +1363,23 @@ query (const char *ctlstr,...) } +/* 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 + erroneous backslash sequence, missing the initial backslash. */ +static NORETURN int +no_control_char_error (const char *start, const char *end) +{ + int len = end - start; + char *copy = alloca (end - start + 1); + + memcpy (copy, start, len); + copy[len] = '\0'; + + error ("There is no control character `\\%s' in the `%s' character set.", + copy, target_charset ()); +} + /* 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 @@ -1299,37 +1398,55 @@ query (const char *ctlstr,...) int parse_escape (char **string_ptr) { + int target_char; register int c = *(*string_ptr)++; - switch (c) + if (c_parse_backslash (c, &target_char)) + return target_char; + else switch (c) { - case 'a': - return 007; /* Bell (alert) char */ - case 'b': - return '\b'; - case 'e': /* Escape character */ - return 033; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'v': - return '\v'; case '\n': return -2; case 0: (*string_ptr)--; return 0; case '^': - c = *(*string_ptr)++; - if (c == '\\') - c = parse_escape (string_ptr); - if (c == '?') - return 0177; - return (c & 0200) | (c & 037); + { + /* Remember where this escape sequence started, for reporting + errors. */ + char *sequence_start_pos = *string_ptr - 1; + + c = *(*string_ptr)++; + + if (c == '?') + { + /* XXXCHARSET: What is `delete' in the host character set? */ + c = 0177; + + if (! host_char_to_target (c, &target_char)) + error ("There is no character corresponding to `Delete' " + "in the target character set `%s'.", + host_charset ()); + + return target_char; + } + else if (c == '\\') + target_char = parse_escape (string_ptr); + else + { + if (! host_char_to_target (c, &target_char)) + no_control_char_error (sequence_start_pos, *string_ptr); + } + + /* Now target_char is something like `c', and we want to find + its control-character equivalent. */ + if (! target_char_to_control_char (target_char, &target_char)) + no_control_char_error (sequence_start_pos, *string_ptr); + + return target_char; + } + + /* XXXCHARSET: we need to use isdigit and value-of-digit + methods of the host character set here. */ case '0': case '1': @@ -1358,7 +1475,12 @@ parse_escape (char **string_ptr) return i; } default: - return c; + if (! host_char_to_target (c, &target_char)) + error ("The escape sequence `\%c' is equivalent to plain `%c', which" + " has no equivalent\n" + "in the `%s' character set.", + c, c, target_charset ()); + return target_char; } } @@ -1602,7 +1724,7 @@ prompt_for_continue (void) /* Call readline, not gdb_readline, because GO32 readline handles control-C whereas control-C to gdb_readline will cause the user to get dumped out to DOS. */ - ignore = readline (cont_prompt); + ignore = gdb_readline_wrapper (cont_prompt); if (annotation_level > 1) printf_unfiltered ("\n\032\032post-prompt-for-continue\n"); @@ -2152,9 +2274,11 @@ fprintf_symbol_filtered (struct ui_file *stream, char *name, enum language lang, case language_java: demangled = cplus_demangle (name, arg_mode | DMGL_JAVA); break; - case language_chill: - demangled = chill_demangle (name); - break; +#if 0 + /* OBSOLETE case language_chill: */ + /* OBSOLETE demangled = chill_demangle (name); */ + /* OBSOLETE break; */ +#endif default: demangled = NULL; break; @@ -2461,9 +2585,7 @@ phex_nz (ULONGEST l, int sizeof_l) CORE_ADDR host_pointer_to_address (void *ptr) { - if (sizeof (ptr) != TYPE_LENGTH (builtin_type_void_data_ptr)) - internal_error (__FILE__, __LINE__, - "core_addr_to_void_ptr: bad cast"); + gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr)); return POINTER_TO_ADDRESS (builtin_type_void_data_ptr, &ptr); } @@ -2471,9 +2593,8 @@ void * address_to_host_pointer (CORE_ADDR addr) { void *ptr; - if (sizeof (ptr) != TYPE_LENGTH (builtin_type_void_data_ptr)) - internal_error (__FILE__, __LINE__, - "core_addr_to_void_ptr: bad cast"); + + gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr)); ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr); return ptr; } @@ -2560,3 +2681,50 @@ gdb_realpath (const char *filename) 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; +}