X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fprintcmd.c;h=82ae1830a46581afc41b6d5d2310c6d35b09b038;hb=f1a133ffb8d8d1c1c2a35cb5e71d1f22712d757c;hp=bee8a85090439e9738d78e5db98a49cac24e6d17;hpb=0b30217134add051e159a192066a1e568ebd837f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/printcmd.c b/gdb/printcmd.c index bee8a85090..82ae1830a4 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1,6 +1,6 @@ /* Print values for GNU debugger GDB. - Copyright (C) 1986-2012 Free Software Foundation, Inc. + Copyright (C) 1986-2013 Free Software Foundation, Inc. This file is part of GDB. @@ -49,18 +49,12 @@ #include "charset.h" #include "arch-utils.h" #include "cli/cli-utils.h" +#include "format.h" #ifdef TUI #include "tui/tui.h" /* For tui_active et al. */ #endif -#if defined(__MINGW32__) && !defined(PRINTF_HAS_LONG_LONG) -# define USE_PRINTF_I64 1 -# define PRINTF_HAS_LONG_LONG -#else -# define USE_PRINTF_I64 0 -#endif - struct format_data { int count; @@ -151,7 +145,7 @@ struct display struct program_space *pspace; /* Innermost block required by this expression when evaluated. */ - struct block *block; + const struct block *block; /* Status of this display (enabled or disabled). */ int enabled_p; @@ -352,13 +346,12 @@ float_type_from_length (struct type *type) { struct gdbarch *gdbarch = get_type_arch (type); const struct builtin_type *builtin = builtin_type (gdbarch); - unsigned int len = TYPE_LENGTH (type); - if (len == TYPE_LENGTH (builtin->builtin_float)) + if (TYPE_LENGTH (type) == TYPE_LENGTH (builtin->builtin_float)) type = builtin->builtin_float; - else if (len == TYPE_LENGTH (builtin->builtin_double)) + else if (TYPE_LENGTH (type) == TYPE_LENGTH (builtin->builtin_double)) type = builtin->builtin_double; - else if (len == TYPE_LENGTH (builtin->builtin_long_double)) + else if (TYPE_LENGTH (type) == TYPE_LENGTH (builtin->builtin_long_double)) type = builtin->builtin_long_double; return type; @@ -568,9 +561,10 @@ set_next_address (struct gdbarch *gdbarch, CORE_ADDR addr) DO_DEMANGLE controls whether to print a symbol in its native "raw" form, or to interpret it as a possible C++ name and convert it back to source form. However note that DO_DEMANGLE can be overridden by the specific - settings of the demangle and asm_demangle variables. */ + settings of the demangle and asm_demangle variables. Returns + non-zero if anything was printed; zero otherwise. */ -void +int print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr, struct ui_file *stream, int do_demangle, char *leadin) @@ -589,7 +583,7 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr, &filename, &line, &unmapped)) { do_cleanups (cleanup_chain); - return; + return 0; } fputs_filtered (leadin, stream); @@ -616,6 +610,7 @@ print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr, fputs_filtered (">", stream); do_cleanups (cleanup_chain); + return 1; } /* Given an address ADDR return all the elements needed to print the @@ -638,7 +633,7 @@ build_address_symbolic (struct gdbarch *gdbarch, struct symbol *symbol; CORE_ADDR name_location = 0; struct obj_section *section = NULL; - char *name_temp = ""; + const char *name_temp = ""; /* Let's say it is mapped (not unmapped). */ *unmapped = 0; @@ -683,6 +678,14 @@ build_address_symbolic (struct gdbarch *gdbarch, name_temp = SYMBOL_LINKAGE_NAME (symbol); } + if (msymbol != NULL + && MSYMBOL_HAS_SIZE (msymbol) + && MSYMBOL_SIZE (msymbol) == 0 + && MSYMBOL_TYPE (msymbol) != mst_text + && MSYMBOL_TYPE (msymbol) != mst_text_gnu_ifunc + && MSYMBOL_TYPE (msymbol) != mst_file_text) + msymbol = NULL; + if (msymbol != NULL) { if (SYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL) @@ -763,29 +766,23 @@ pc_prefix (CORE_ADDR addr) /* Print address ADDR symbolically on STREAM. Parameter DEMANGLE controls whether to print the symbolic name "raw" or demangled. - Global setting "addressprint" controls whether to print hex address - or not. */ + Return non-zero if anything was printed; zero otherwise. */ -void -print_address_demangle (struct gdbarch *gdbarch, CORE_ADDR addr, +int +print_address_demangle (const struct value_print_options *opts, + struct gdbarch *gdbarch, CORE_ADDR addr, struct ui_file *stream, int do_demangle) { - struct value_print_options opts; - - get_user_print_options (&opts); - if (addr == 0) - { - fprintf_filtered (stream, "0"); - } - else if (opts.addressprint) + if (opts->addressprint) { fputs_filtered (paddress (gdbarch, addr), stream); print_address_symbolic (gdbarch, addr, stream, do_demangle, " "); } else { - print_address_symbolic (gdbarch, addr, stream, do_demangle, ""); + return print_address_symbolic (gdbarch, addr, stream, do_demangle, ""); } + return 1; } @@ -1080,6 +1077,22 @@ set_command (char *exp, int from_tty) struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); + if (expr->nelts >= 1) + switch (expr->elts[0].opcode) + { + case UNOP_PREINCREMENT: + case UNOP_POSTINCREMENT: + case UNOP_PREDECREMENT: + case UNOP_POSTDECREMENT: + case BINOP_ASSIGN: + case BINOP_ASSIGN_MODIFY: + case BINOP_COMMA: + break; + default: + warning + (_("Expression is not an assignment (and might have no effect)")); + } + evaluate_expression (expr); do_cleanups (old_chain); } @@ -1186,8 +1199,7 @@ address_info (char *exp, int from_tty) long val; struct obj_section *section; CORE_ADDR load_addr, context_pc = 0; - int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero - if exp is a field of `this'. */ + struct field_of_this_result is_a_field_of_this; if (exp == 0) error (_("Argument required.")); @@ -1196,7 +1208,7 @@ address_info (char *exp, int from_tty) &is_a_field_of_this); if (sym == NULL) { - if (is_a_field_of_this) + if (is_a_field_of_this.type != NULL) { printf_filtered ("Symbol \""); fprintf_symbol_filtered (gdb_stdout, exp, @@ -1594,7 +1606,6 @@ map_display_numbers (char *args, void *data) { struct get_number_or_range_state state; - struct display *b, *tmp; int num; if (args == NULL) @@ -1637,9 +1648,6 @@ do_delete_display (struct display *d, void *data) static void undisplay_command (char *args, int from_tty) { - int num; - struct get_number_or_range_state state; - if (args == NULL) { if (query (_("Delete all auto-display expressions? "))) @@ -1952,7 +1960,9 @@ clear_dangling_display_expressions (struct so_list *solib) struct symbol. NAME is the name to print; if NULL then VAR's print name will be used. STREAM is the ui_file on which to print the value. INDENT specifies the number of indent levels to print - before printing the variable name. */ + before printing the variable name. + + This function invalidates FRAME. */ void print_variable_and_value (const char *name, struct symbol *var, @@ -1974,6 +1984,10 @@ print_variable_and_value (const char *name, struct symbol *var, get_user_print_options (&opts); opts.deref_ref = 1; common_val_print (val, stream, indent, &opts, current_language); + + /* common_val_print invalidates FRAME when a pretty printer calls inferior + function. */ + frame = NULL; } if (except.reason < 0) fprintf_filtered(stream, "", name, @@ -1986,13 +2000,9 @@ print_variable_and_value (const char *name, struct symbol *var, static void ui_printf (char *arg, struct ui_file *stream) { - char *f = NULL; + struct format_piece *fpieces; char *s = arg; - char *string = NULL; struct value **val_args; - char *substrings; - char *current_substring; - int nargs = 0; int allocated_args = 20; struct cleanup *old_cleanups; @@ -2008,64 +2018,13 @@ ui_printf (char *arg, struct ui_file *stream) if (*s++ != '"') error (_("Bad format string, missing '\"'.")); - /* Parse the format-control string and copy it into the string STRING, - processing some kinds of escape sequence. */ + fpieces = parse_format_string (&s); - f = string = (char *) alloca (strlen (s) + 1); + make_cleanup (free_format_pieces_cleanup, &fpieces); - while (*s != '"') - { - int c = *s++; - switch (c) - { - case '\0': - error (_("Bad format string, non-terminated '\"'.")); - - case '\\': - switch (c = *s++) - { - case '\\': - *f++ = '\\'; - break; - case 'a': - *f++ = '\a'; - break; - case 'b': - *f++ = '\b'; - break; - case 'f': - *f++ = '\f'; - break; - case 'n': - *f++ = '\n'; - break; - case 'r': - *f++ = '\r'; - break; - case 't': - *f++ = '\t'; - break; - case 'v': - *f++ = '\v'; - break; - case '"': - *f++ = '"'; - break; - default: - /* ??? TODO: handle other escape sequences. */ - error (_("Unrecognized escape character \\%c in format string."), - c); - } - break; - - default: - *f++ = c; - } - } - - /* Skip over " and following space and comma. */ - s++; - *f++ = '\0'; + if (*s++ != '"') + error (_("Bad format string, non-terminated '\"'.")); + s = skip_spaces (s); if (*s != ',' && *s != 0) @@ -2075,240 +2034,16 @@ ui_printf (char *arg, struct ui_file *stream) s++; s = skip_spaces (s); - /* Need extra space for the '\0's. Doubling the size is sufficient. */ - substrings = alloca (strlen (string) * 2); - current_substring = substrings; - { - /* Now scan the string for %-specs and see what kinds of args they want. - argclass[I] classifies the %-specs so we can give printf_filtered - something of the right size. */ - - enum argclass - { - int_arg, long_arg, long_long_arg, ptr_arg, - string_arg, wide_string_arg, wide_char_arg, - double_arg, long_double_arg, decfloat_arg - }; - enum argclass *argclass; - enum argclass this_argclass; - char *last_arg; + int nargs = 0; int nargs_wanted; - int i; + int i, fr; + char *current_substring; - argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass); nargs_wanted = 0; - f = string; - last_arg = string; - while (*f) - if (*f++ == '%') - { - int seen_hash = 0, seen_zero = 0, lcount = 0, seen_prec = 0; - int seen_space = 0, seen_plus = 0; - int seen_big_l = 0, seen_h = 0, seen_big_h = 0; - int seen_big_d = 0, seen_double_big_d = 0; - int bad = 0; - - /* Check the validity of the format specifier, and work - out what argument it expects. We only accept C89 - format strings, with the exception of long long (which - we autoconf for). */ - - /* Skip over "%%". */ - if (*f == '%') - { - f++; - continue; - } - - /* The first part of a format specifier is a set of flag - characters. */ - while (strchr ("0-+ #", *f)) - { - if (*f == '#') - seen_hash = 1; - else if (*f == '0') - seen_zero = 1; - else if (*f == ' ') - seen_space = 1; - else if (*f == '+') - seen_plus = 1; - f++; - } - - /* The next part of a format specifier is a width. */ - while (strchr ("0123456789", *f)) - f++; - - /* The next part of a format specifier is a precision. */ - if (*f == '.') - { - seen_prec = 1; - f++; - while (strchr ("0123456789", *f)) - f++; - } - - /* The next part of a format specifier is a length modifier. */ - if (*f == 'h') - { - seen_h = 1; - f++; - } - else if (*f == 'l') - { - f++; - lcount++; - if (*f == 'l') - { - f++; - lcount++; - } - } - else if (*f == 'L') - { - seen_big_l = 1; - f++; - } - /* Decimal32 modifier. */ - else if (*f == 'H') - { - seen_big_h = 1; - f++; - } - /* Decimal64 and Decimal128 modifiers. */ - else if (*f == 'D') - { - f++; - - /* Check for a Decimal128. */ - if (*f == 'D') - { - f++; - seen_double_big_d = 1; - } - else - seen_big_d = 1; - } - - switch (*f) - { - case 'u': - if (seen_hash) - bad = 1; - /* FALLTHROUGH */ - - case 'o': - case 'x': - case 'X': - if (seen_space || seen_plus) - bad = 1; - /* FALLTHROUGH */ - - case 'd': - case 'i': - if (lcount == 0) - this_argclass = int_arg; - else if (lcount == 1) - this_argclass = long_arg; - else - this_argclass = long_long_arg; - - if (seen_big_l) - bad = 1; - break; - - case 'c': - this_argclass = lcount == 0 ? int_arg : wide_char_arg; - if (lcount > 1 || seen_h || seen_big_l) - bad = 1; - if (seen_prec || seen_zero || seen_space || seen_plus) - bad = 1; - break; - - case 'p': - this_argclass = ptr_arg; - if (lcount || seen_h || seen_big_l) - bad = 1; - if (seen_prec || seen_zero || seen_space || seen_plus) - bad = 1; - break; - - case 's': - this_argclass = lcount == 0 ? string_arg : wide_string_arg; - if (lcount > 1 || seen_h || seen_big_l) - bad = 1; - if (seen_zero || seen_space || seen_plus) - bad = 1; - break; - - case 'e': - case 'f': - case 'g': - case 'E': - case 'G': - if (seen_big_h || seen_big_d || seen_double_big_d) - this_argclass = decfloat_arg; - else if (seen_big_l) - this_argclass = long_double_arg; - else - this_argclass = double_arg; - - if (lcount || seen_h) - bad = 1; - break; - - case '*': - error (_("`*' not supported for precision or width in printf")); - - case 'n': - error (_("Format specifier `n' not supported in printf")); - - case '\0': - error (_("Incomplete format specifier at end of format string")); - - default: - error (_("Unrecognized format specifier '%c' in printf"), *f); - } - - if (bad) - error (_("Inappropriate modifiers to " - "format specifier '%c' in printf"), - *f); - - f++; - - if (lcount > 1 && USE_PRINTF_I64) - { - /* Windows' printf does support long long, but not the usual way. - Convert %lld to %I64d. */ - int length_before_ll = f - last_arg - 1 - lcount; - - strncpy (current_substring, last_arg, length_before_ll); - strcpy (current_substring + length_before_ll, "I64"); - current_substring[length_before_ll + 3] = - last_arg[length_before_ll + lcount]; - current_substring += length_before_ll + 4; - } - else if (this_argclass == wide_string_arg - || this_argclass == wide_char_arg) - { - /* Convert %ls or %lc to %s. */ - int length_before_ls = f - last_arg - 2; - - strncpy (current_substring, last_arg, length_before_ls); - strcpy (current_substring + length_before_ls, "s"); - current_substring += length_before_ls + 2; - } - else - { - strncpy (current_substring, last_arg, f - last_arg); - current_substring += f - last_arg; - } - *current_substring++ = '\0'; - last_arg = f; - argclass[nargs_wanted++] = this_argclass; - } + for (fr = 0; fpieces[fr].string != NULL; fr++) + if (fpieces[fr].argclass != literal_piece) + ++nargs_wanted; /* Now, parse all arguments and evaluate them. Store the VALUEs in VAL_ARGS. */ @@ -2334,10 +2069,11 @@ ui_printf (char *arg, struct ui_file *stream) error (_("Wrong number of arguments for specified format-string")); /* Now actually print them. */ - current_substring = substrings; - for (i = 0; i < nargs; i++) + i = 0; + for (fr = 0; fpieces[fr].string != NULL; fr++) { - switch (argclass[i]) + current_substring = fpieces[fr].string; + switch (fpieces[fr].argclass) { case string_arg: { @@ -2484,7 +2220,7 @@ ui_printf (char *arg, struct ui_file *stream) error (_("long double not supported in printf")); #endif case long_long_arg: -#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) +#ifdef PRINTF_HAS_LONG_LONG { long long val = value_as_long (val_args[i]); @@ -2529,7 +2265,6 @@ ui_printf (char *arg, struct ui_file *stream) /* Parameter data. */ struct type *param_type = value_type (val_args[i]); - unsigned int param_len = TYPE_LENGTH (param_type); struct gdbarch *gdbarch = get_type_arch (param_type); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); @@ -2591,8 +2326,8 @@ ui_printf (char *arg, struct ui_file *stream) /* Conversion between different DFP types. */ if (TYPE_CODE (param_type) == TYPE_CODE_DECFLOAT) - decimal_convert (param_ptr, param_len, byte_order, - dec, dfp_len, byte_order); + decimal_convert (param_ptr, TYPE_LENGTH (param_type), + byte_order, dec, dfp_len, byte_order); else /* If this is a non-trivial conversion, just output 0. A correct converted value can be displayed by explicitly @@ -2620,7 +2355,7 @@ ui_printf (char *arg, struct ui_file *stream) handle %p as glibc would: %#x or a literal "(nil)". */ char *p, *fmt, *fmt_p; -#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) +#ifdef PRINTF_HAS_LONG_LONG long long val = value_as_long (val_args[i]); #else long val = value_as_long (val_args[i]); @@ -2655,7 +2390,7 @@ ui_printf (char *arg, struct ui_file *stream) gdb_assert (*p == 'p' && *(p + 1) == '\0'); if (val != 0) { -#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) +#ifdef PRINTF_HAS_LONG_LONG *fmt_p++ = 'l'; #endif *fmt_p++ = 'l'; @@ -2672,20 +2407,25 @@ ui_printf (char *arg, struct ui_file *stream) break; } + case literal_piece: + /* Print a portion of the format string that has no + directives. Note that this will not include any + ordinary %-specs, but it might include "%%". That is + why we use printf_filtered and not puts_filtered here. + Also, we pass a dummy argument because some platforms + have modified GCC to include -Wformat-security by + default, which will warn here if there is no + argument. */ + fprintf_filtered (stream, current_substring, 0); + break; default: internal_error (__FILE__, __LINE__, _("failed internal consistency check")); } - /* Skip to the next substring. */ - current_substring += strlen (current_substring) + 1; + /* Maybe advance to the next argument. */ + if (fpieces[fr].argclass != literal_piece) + ++i; } - /* Print the portion of the format string after the last argument. - Note that this will not include any ordinary %-specs, but it - might include "%%". That is why we use printf_filtered and not - puts_filtered here. Also, we pass a dummy argument because - some platforms have modified GCC to include -Wformat-security - by default, which will warn here if there is no argument. */ - fprintf_filtered (stream, last_arg, 0); } do_cleanups (old_cleanups); }