X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fc-lang.c;h=1f40e885d99aac3e41227fd22e15f7ccb40d8ce2;hb=e623f035020ea7baa64933b4afaaa564b4c7e26d;hp=805c57255d9c165f61e7551668f136c4567aa4db;hpb=c0201579c8cd0c319fa851c98b0adf21ac013489;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 805c57255d..1f40e885d9 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -1,7 +1,6 @@ /* C language support routines for GDB, the GNU debugger. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003, - 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1992-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -24,26 +23,25 @@ #include "expression.h" #include "parser-defs.h" #include "language.h" +#include "varobj.h" #include "c-lang.h" +#include "c-support.h" #include "valprint.h" #include "macroscope.h" -#include "gdb_assert.h" #include "charset.h" -#include "gdb_string.h" #include "demangle.h" #include "cp-abi.h" #include "cp-support.h" #include "gdb_obstack.h" #include - -extern void _initialize_c_language (void); +#include "gdbcore.h" +#include "gdbarch.h" /* Given a C string type, STR_TYPE, return the corresponding target character set name. */ static const char * -charset_for_string_type (enum c_string_type str_type, - struct gdbarch *gdbarch) +charset_for_string_type (c_string_type str_type, struct gdbarch *gdbarch) { switch (str_type & ~C_CHAR) { @@ -64,20 +62,20 @@ charset_for_string_type (enum c_string_type str_type, else return "UTF-32LE"; } - internal_error (__FILE__, __LINE__, "unhandled c_string_type"); + internal_error (__FILE__, __LINE__, _("unhandled c_string_type")); } /* Classify ELTTYPE according to what kind of character it is. Return the enum constant representing the character type. Also set *ENCODING to the name of the character set to use when converting - characters of this type in target BYTE_ORDER to the host character set. */ + characters of this type in target BYTE_ORDER to the host character + set. */ -static enum c_string_type +static c_string_type classify_type (struct type *elttype, struct gdbarch *gdbarch, const char **encoding) { - struct type *saved_type; - enum c_string_type result; + c_string_type result; /* We loop because ELTTYPE may be a typedef, and we want to successively peel each typedef until we reach a type we @@ -86,7 +84,7 @@ classify_type (struct type *elttype, struct gdbarch *gdbarch, that would do the wrong thing. */ while (elttype) { - char *name = TYPE_NAME (elttype); + const char *name = TYPE_NAME (elttype); if (TYPE_CODE (elttype) == TYPE_CODE_CHAR || !name) { @@ -125,7 +123,7 @@ classify_type (struct type *elttype, struct gdbarch *gdbarch, /* Perhaps check_typedef did not update the target type. In this case, force the lookup again and hope it works out. It never will for C, but it might for C++. */ - CHECK_TYPEDEF (elttype); + elttype = check_typedef (elttype); } } @@ -139,206 +137,24 @@ classify_type (struct type *elttype, struct gdbarch *gdbarch, return result; } -/* Return true if print_wchar can display W without resorting to a - numeric escape, false otherwise. */ - -static int -wchar_printable (gdb_wchar_t w) -{ - return (gdb_iswprint (w) - || w == LCST ('\a') || w == LCST ('\b') - || w == LCST ('\f') || w == LCST ('\n') - || w == LCST ('\r') || w == LCST ('\t') - || w == LCST ('\v')); -} - -/* A helper function that converts the contents of STRING to wide - characters and then appends them to OUTPUT. */ - -static void -append_string_as_wide (const char *string, struct obstack *output) -{ - for (; *string; ++string) - { - gdb_wchar_t w = gdb_btowc (*string); - obstack_grow (output, &w, sizeof (gdb_wchar_t)); - } -} - -/* Print a wide character W to OUTPUT. ORIG is a pointer to the - original (target) bytes representing the character, ORIG_LEN is the - number of valid bytes. WIDTH is the number of bytes in a base - characters of the type. OUTPUT is an obstack to which wide - characters are emitted. QUOTER is a (narrow) character indicating - the style of quotes surrounding the character to be printed. - NEED_ESCAPE is an in/out flag which is used to track numeric - escapes across calls. */ - -static void -print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len, - int width, enum bfd_endian byte_order, struct obstack *output, - int quoter, int *need_escapep) -{ - int need_escape = *need_escapep; - *need_escapep = 0; - if (gdb_iswprint (w) && (!need_escape || (!gdb_iswdigit (w) - && w != LCST ('8') - && w != LCST ('9')))) - { - gdb_wchar_t wchar = w; - - if (w == gdb_btowc (quoter) || w == LCST ('\\')) - obstack_grow_wstr (output, LCST ("\\")); - obstack_grow (output, &wchar, sizeof (gdb_wchar_t)); - } - else - { - switch (w) - { - case LCST ('\a'): - obstack_grow_wstr (output, LCST ("\\a")); - break; - case LCST ('\b'): - obstack_grow_wstr (output, LCST ("\\b")); - break; - case LCST ('\f'): - obstack_grow_wstr (output, LCST ("\\f")); - break; - case LCST ('\n'): - obstack_grow_wstr (output, LCST ("\\n")); - break; - case LCST ('\r'): - obstack_grow_wstr (output, LCST ("\\r")); - break; - case LCST ('\t'): - obstack_grow_wstr (output, LCST ("\\t")); - break; - case LCST ('\v'): - obstack_grow_wstr (output, LCST ("\\v")); - break; - default: - { - int i; - - for (i = 0; i + width <= orig_len; i += width) - { - char octal[30]; - ULONGEST value; - value = extract_unsigned_integer (&orig[i], width, byte_order); - /* If the value fits in 3 octal digits, print it that - way. Otherwise, print it as a hex escape. */ - if (value <= 0777) - sprintf (octal, "\\%.3o", (int) (value & 0777)); - else - sprintf (octal, "\\x%lx", (long) value); - append_string_as_wide (octal, output); - } - /* If we somehow have extra bytes, print them now. */ - while (i < orig_len) - { - char octal[5]; - sprintf (octal, "\\%.3o", orig[i] & 0xff); - append_string_as_wide (octal, output); - ++i; - } - - *need_escapep = 1; - } - break; - } - } -} - -/* Print the character C on STREAM as part of the contents of a literal - string whose delimiter is QUOTER. Note that that format for printing - characters and strings is language specific. */ +/* Print the character C on STREAM as part of the contents of a + literal string whose delimiter is QUOTER. Note that that format + for printing characters and strings is language specific. */ -static void -c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) +void +c_emit_char (int c, struct type *type, + struct ui_file *stream, int quoter) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); - struct obstack wchar_buf, output; - struct cleanup *cleanups; const char *encoding; - gdb_byte *buf; - struct wchar_iterator *iter; - int need_escape = 0; classify_type (type, get_type_arch (type), &encoding); - - buf = alloca (TYPE_LENGTH (type)); - pack_long (buf, type, c); - - iter = make_wchar_iterator (buf, TYPE_LENGTH (type), encoding, - TYPE_LENGTH (type)); - cleanups = make_cleanup_wchar_iterator (iter); - - /* This holds the printable form of the wchar_t data. */ - obstack_init (&wchar_buf); - make_cleanup_obstack_free (&wchar_buf); - - while (1) - { - int num_chars; - gdb_wchar_t *chars; - const gdb_byte *buf; - size_t buflen; - int print_escape = 1; - enum wchar_iterate_result result; - - num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); - if (num_chars < 0) - break; - if (num_chars > 0) - { - /* If all characters are printable, print them. Otherwise, - we're going to have to print an escape sequence. We - check all characters because we want to print the target - bytes in the escape sequence, and we don't know character - boundaries there. */ - int i; - - print_escape = 0; - for (i = 0; i < num_chars; ++i) - if (!wchar_printable (chars[i])) - { - print_escape = 1; - break; - } - - if (!print_escape) - { - for (i = 0; i < num_chars; ++i) - print_wchar (chars[i], buf, buflen, TYPE_LENGTH (type), - byte_order, &wchar_buf, quoter, &need_escape); - } - } - - /* This handles the NUM_CHARS == 0 case as well. */ - if (print_escape) - print_wchar (gdb_WEOF, buf, buflen, TYPE_LENGTH (type), byte_order, - &wchar_buf, quoter, &need_escape); - } - - /* The output in the host encoding. */ - obstack_init (&output); - make_cleanup_obstack_free (&output); - - convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (), - obstack_base (&wchar_buf), - obstack_object_size (&wchar_buf), - 1, &output, translit_char); - obstack_1grow (&output, '\0'); - - fputs_filtered (obstack_base (&output), stream); - - do_cleanups (cleanups); + generic_emit_char (c, type, stream, quoter, encoding); } void c_printchar (int c, struct type *type, struct ui_file *stream) { - enum c_string_type str_type; + c_string_type str_type; str_type = classify_type (type, get_type_arch (type), NULL); switch (str_type) @@ -361,40 +177,22 @@ c_printchar (int c, struct type *type, struct ui_file *stream) fputc_filtered ('\'', stream); } -/* Print the character string STRING, printing at most LENGTH characters. - LENGTH is -1 if the string is nul terminated. Each character is WIDTH bytes - long. Printing stops early if the number hits print_max; repeat counts are - printed as appropriate. Print ellipses at the end if we had to stop before - printing LENGTH characters, or if FORCE_ELLIPSES. */ +/* Print the character string STRING, printing at most LENGTH + characters. LENGTH is -1 if the string is nul terminated. Each + character is WIDTH bytes long. Printing stops early if the number + hits print_max; repeat counts are printed as appropriate. Print + ellipses at the end if we had to stop before printing LENGTH + characters, or if FORCE_ELLIPSES. */ void -c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, - unsigned int length, const char *user_encoding, int force_ellipses, +c_printstr (struct ui_file *stream, struct type *type, + const gdb_byte *string, unsigned int length, + const char *user_encoding, int force_ellipses, const struct value_print_options *options) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); - unsigned int i; - unsigned int things_printed = 0; - int in_quotes = 0; - int need_comma = 0; - int width = TYPE_LENGTH (type); - struct obstack wchar_buf, output; - struct cleanup *cleanup; - enum c_string_type str_type; + c_string_type str_type; const char *type_encoding; const char *encoding; - struct wchar_iterator *iter; - int finished = 0; - int need_escape = 0; - - /* If the string was not truncated due to `set print elements', and - the last byte of it is a null, we don't print that, in traditional C - style. */ - if (!force_ellipses - && length > 0 - && (extract_unsigned_integer (string + (length - 1) * width, - width, byte_order) == 0)) - length--; str_type = (classify_type (type, get_type_arch (type), &type_encoding) & ~C_CHAR); @@ -415,230 +213,47 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding; - if (length == 0) - { - fputs_filtered ("\"\"", stream); - return; - } - - if (length == -1) - { - unsigned long current_char = 1; - for (i = 0; current_char; ++i) - { - QUIT; - current_char = extract_unsigned_integer (string + i * width, - width, byte_order); - } - length = i; - } - - /* Arrange to iterate over the characters, in wchar_t form. */ - iter = make_wchar_iterator (string, length * width, encoding, width); - cleanup = make_cleanup_wchar_iterator (iter); - - /* WCHAR_BUF is the obstack we use to represent the string in - wchar_t form. */ - obstack_init (&wchar_buf); - make_cleanup_obstack_free (&wchar_buf); - - while (!finished && things_printed < options->print_max) - { - int num_chars; - enum wchar_iterate_result result; - gdb_wchar_t *chars; - const gdb_byte *buf; - size_t buflen; - - QUIT; - - if (need_comma) - { - obstack_grow_wstr (&wchar_buf, LCST (", ")); - need_comma = 0; - } - - num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); - /* We only look at repetitions when we were able to convert a - single character in isolation. This makes the code simpler - and probably does the sensible thing in the majority of - cases. */ - while (num_chars == 1 && things_printed < options->print_max) - { - /* Count the number of repetitions. */ - unsigned int reps = 0; - gdb_wchar_t current_char = chars[0]; - const gdb_byte *orig_buf = buf; - int orig_len = buflen; - - if (need_comma) - { - obstack_grow_wstr (&wchar_buf, LCST (", ")); - need_comma = 0; - } - - while (num_chars == 1 && current_char == chars[0]) - { - num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); - ++reps; - } - - /* Emit CURRENT_CHAR according to the repetition count and - options. */ - if (reps > options->repeat_count_threshold) - { - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\", ")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\", ")); - in_quotes = 0; - } - obstack_grow_wstr (&wchar_buf, LCST ("'")); - need_escape = 0; - print_wchar (current_char, orig_buf, orig_len, width, - byte_order, &wchar_buf, '\'', &need_escape); - obstack_grow_wstr (&wchar_buf, LCST ("'")); - { - /* Painful gyrations. */ - int j; - char *s = xstrprintf (_(" "), reps); - for (j = 0; s[j]; ++j) - { - gdb_wchar_t w = gdb_btowc (s[j]); - obstack_grow (&wchar_buf, &w, sizeof (gdb_wchar_t)); - } - xfree (s); - } - things_printed += options->repeat_count_threshold; - need_comma = 1; - } - else - { - /* Saw the character one or more times, but fewer than - the repetition threshold. */ - if (!in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\"")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\"")); - in_quotes = 1; - need_escape = 0; - } - - while (reps-- > 0) - { - print_wchar (current_char, orig_buf, orig_len, width, - byte_order, &wchar_buf, '"', &need_escape); - ++things_printed; - } - } - } - - /* NUM_CHARS and the other outputs from wchar_iterate are valid - here regardless of which branch was taken above. */ - if (num_chars < 0) - { - /* Hit EOF. */ - finished = 1; - break; - } - - switch (result) - { - case wchar_iterate_invalid: - if (!in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\"")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\"")); - in_quotes = 1; - } - need_escape = 0; - print_wchar (gdb_WEOF, buf, buflen, width, byte_order, &wchar_buf, - '"', &need_escape); - break; - - case wchar_iterate_incomplete: - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\",")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\",")); - in_quotes = 0; - } - obstack_grow_wstr (&wchar_buf, LCST (" ")); - finished = 1; - break; - } - } - - /* Terminate the quotes if necessary. */ - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\"")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\"")); - } - - if (force_ellipses || !finished) - obstack_grow_wstr (&wchar_buf, LCST ("...")); - - /* OUTPUT is where we collect `char's for printing. */ - obstack_init (&output); - make_cleanup_obstack_free (&output); - - convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (), - obstack_base (&wchar_buf), - obstack_object_size (&wchar_buf), - 1, &output, translit_char); - obstack_1grow (&output, '\0'); - - fputs_filtered (obstack_base (&output), stream); - - do_cleanups (cleanup); + generic_printstr (stream, type, string, length, encoding, force_ellipses, + '"', 1, options); } /* Obtain a C string from the inferior storing it in a newly allocated - buffer in BUFFER, which should be freed by the caller. If the - in- and out-parameter *LENGTH is specified at -1, the string is read + buffer in BUFFER, which should be freed by the caller. If the in- + and out-parameter *LENGTH is specified at -1, the string is read until a null character of the appropriate width is found, otherwise - the string is read to the length of characters specified. - The size of a character is determined by the length of the target - type of the pointer or array. If VALUE is an array with a known - length, the function will not read past the end of the array. + the string is read to the length of characters specified. The size + of a character is determined by the length of the target type of + the pointer or array. + + If VALUE is an array with a known length, and *LENGTH is -1, + the function will not read past the end of the array. However, any + declared size of the array is ignored if *LENGTH > 0. + On completion, *LENGTH will be set to the size of the string read in characters. (If a length of -1 is specified, the length returned will not include the null character). CHARSET is always set to the target charset. */ void -c_get_string (struct value *value, gdb_byte **buffer, int *length, - struct type **char_type, const char **charset) +c_get_string (struct value *value, gdb::unique_xmalloc_ptr *buffer, + int *length, struct type **char_type, + const char **charset) { int err, width; unsigned int fetchlimit; struct type *type = check_typedef (value_type (value)); struct type *element_type = TYPE_TARGET_TYPE (type); int req_length = *length; - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); - enum c_string_type kind; + enum bfd_endian byte_order + = type_byte_order (type); if (element_type == NULL) goto error; if (TYPE_CODE (type) == TYPE_CODE_ARRAY) { - /* If we know the size of the array, we can use it as a limit on the - number of characters to be fetched. */ + /* If we know the size of the array, we can use it as a limit on + the number of characters to be fetched. */ if (TYPE_NFIELDS (type) == 1 && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_RANGE) { @@ -659,17 +274,27 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, if (! c_textual_element_type (element_type, 0)) goto error; - kind = classify_type (element_type, - get_type_arch (element_type), - charset); + classify_type (element_type, get_type_arch (element_type), charset); width = TYPE_LENGTH (element_type); - /* If the string lives in GDB's memory instead of the inferior's, then we - just need to copy it to BUFFER. Also, since such strings are arrays - with known size, FETCHLIMIT will hold the size of the array. */ + /* If the string lives in GDB's memory instead of the inferior's, + then we just need to copy it to BUFFER. Also, since such strings + are arrays with known size, FETCHLIMIT will hold the size of the + array. + + An array is assumed to live in GDB's memory, so we take this path + here. + + However, it's possible for the caller to request more array + elements than apparently exist -- this can happen when using the + C struct hack. So, only do this if either no length was + specified, or the length is within the existing bounds. This + avoids running off the end of the value's contents. */ if ((VALUE_LVAL (value) == not_lval - || VALUE_LVAL (value) == lval_internalvar) - && fetchlimit != UINT_MAX) + || VALUE_LVAL (value) == lval_internalvar + || TYPE_CODE (type) == TYPE_CODE_ARRAY) + && fetchlimit != UINT_MAX + && (*length < 0 || *length <= fetchlimit)) { int i; const gdb_byte *contents = value_contents (value); @@ -678,29 +303,54 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, if (*length >= 0) i = *length; else - /* Otherwise, look for a null character. */ - for (i = 0; i < fetchlimit; i++) - if (extract_unsigned_integer (contents + i * width, width, - byte_order) == 0) - break; + /* Otherwise, look for a null character. */ + for (i = 0; i < fetchlimit; i++) + if (extract_unsigned_integer (contents + i * width, + width, byte_order) == 0) + break; /* I is now either a user-defined length, the number of non-null - characters, or FETCHLIMIT. */ + characters, or FETCHLIMIT. */ *length = i * width; - *buffer = xmalloc (*length); - memcpy (*buffer, contents, *length); + buffer->reset ((gdb_byte *) xmalloc (*length)); + memcpy (buffer->get (), contents, *length); err = 0; } else { - err = read_string (value_as_address (value), *length, width, fetchlimit, - byte_order, buffer, length); - if (err) + /* value_as_address does not return an address for an array when + c_style_arrays is false, so we handle that specially + here. */ + CORE_ADDR addr; + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) { - xfree (*buffer); - error (_("Error reading string from inferior: %s"), - safe_strerror (err)); + if (VALUE_LVAL (value) != lval_memory) + error (_("Attempt to take address of value " + "not located in memory.")); + addr = value_address (value); } + else + addr = value_as_address (value); + + /* Prior to the fix for PR 16196 read_string would ignore fetchlimit + if length > 0. The old "broken" behaviour is the behaviour we want: + The caller may want to fetch 100 bytes from a variable length array + implemented using the common idiom of having an array of length 1 at + the end of a struct. In this case we want to ignore the declared + size of the array. However, it's counterintuitive to implement that + behaviour in read_string: what does fetchlimit otherwise mean if + length > 0. Therefore we implement the behaviour we want here: + If *length > 0, don't specify a fetchlimit. This preserves the + previous behaviour. We could move this check above where we know + whether the array is declared with a fixed size, but we only want + to apply this behaviour when calling read_string. PR 16286. */ + if (*length > 0) + fetchlimit = UINT_MAX; + + err = read_string (addr, *length, width, fetchlimit, + byte_order, buffer, length); + if (err != 0) + memory_error (TARGET_XFER_E_IO, addr); } /* If the LENGTH is specified at -1, we want to return the string @@ -710,8 +360,8 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, if (req_length == -1) /* If the last character is null, subtract it from LENGTH. */ if (*length > 0 - && extract_unsigned_integer (*buffer + *length - width, width, - byte_order) == 0) + && extract_unsigned_integer (buffer->get () + *length - width, + width, byte_order) == 0) *length -= width; /* The read_string function will return the number of bytes read. @@ -726,14 +376,11 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length, error: { - char *type_str; - - type_str = type_to_string (type); - if (type_str) + std::string type_str = type_to_string (type); + if (!type_str.empty ()) { - make_cleanup (xfree, type_str); error (_("Trying to read string with inappropriate type `%s'."), - type_str); + type_str.c_str ()); } else error (_("Trying to read string with inappropriate type.")); @@ -757,7 +404,7 @@ convert_ucn (char *p, char *limit, const char *dest_charset, gdb_byte data[4]; int i; - for (i = 0; i < length && p < limit && isxdigit (*p); ++i, ++p) + for (i = 0; i < length && p < limit && ISXDIGIT (*p); ++i, ++p) result = (result << 4) + host_hex_value (*p); for (i = 3; i >= 0; --i) @@ -766,8 +413,8 @@ convert_ucn (char *p, char *limit, const char *dest_charset, result >>= 8; } - convert_between_encodings ("UTF-32BE", dest_charset, data, 4, 4, output, - translit_none); + convert_between_encodings ("UTF-32BE", dest_charset, data, + 4, 4, output, translit_none); return p; } @@ -781,7 +428,7 @@ emit_numeric_character (struct type *type, unsigned long value, { gdb_byte *buffer; - buffer = alloca (TYPE_LENGTH (type)); + buffer = (gdb_byte *) alloca (TYPE_LENGTH (type)); pack_long (buffer, type, value); obstack_grow (output, buffer, TYPE_LENGTH (type)); } @@ -792,13 +439,14 @@ emit_numeric_character (struct type *type, unsigned long value, pointer to just after the final digit of the escape sequence. */ static char * -convert_octal (struct type *type, char *p, char *limit, struct obstack *output) +convert_octal (struct type *type, char *p, + char *limit, struct obstack *output) { int i; unsigned long value = 0; for (i = 0; - i < 3 && p < limit && isdigit (*p) && *p != '8' && *p != '9'; + i < 3 && p < limit && ISDIGIT (*p) && *p != '8' && *p != '9'; ++i) { value = 8 * value + host_hex_value (*p); @@ -816,11 +464,12 @@ convert_octal (struct type *type, char *p, char *limit, struct obstack *output) just after the final digit of the escape sequence. */ static char * -convert_hex (struct type *type, char *p, char *limit, struct obstack *output) +convert_hex (struct type *type, char *p, + char *limit, struct obstack *output) { unsigned long value = 0; - while (p < limit && isxdigit (*p)) + while (p < limit && ISXDIGIT (*p)) { value = 16 * value + host_hex_value (*p); ++p; @@ -861,7 +510,7 @@ convert_escape (struct type *type, const char *dest_charset, case 'x': ADVANCE; - if (!isxdigit (*p)) + if (!ISXDIGIT (*p)) error (_("\\x used with no following hex digits.")); p = convert_hex (type, p, limit, output); break; @@ -881,8 +530,9 @@ convert_escape (struct type *type, const char *dest_charset, case 'U': { int length = *p == 'u' ? 4 : 8; + ADVANCE; - if (!isxdigit (*p)) + if (!ISXDIGIT (*p)) error (_("\\u used with no following hex digits")); p = convert_ucn (p, limit, dest_charset, output, length); } @@ -908,13 +558,15 @@ parse_one_string (struct obstack *output, char *data, int len, while (data < limit) { char *p = data; + /* Look for next escape, or the end of the input. */ while (p < limit && *p != '\\') ++p; /* If we saw a run of characters, convert them all. */ if (p > data) convert_between_encodings (host_charset (), dest_charset, - data, p - data, 1, output, translit_none); + (gdb_byte *) data, p - data, 1, + output, translit_none); /* If we saw an escape, convert it. */ if (p < limit) p = convert_escape (type, dest_charset, p, limit, output); @@ -926,7 +578,7 @@ parse_one_string (struct obstack *output, char *data, int len, are delegated to evaluate_subexp_standard; see that function for a description of the arguments. */ -static struct value * +struct value * evaluate_subexp_c (struct type *expect_type, struct expression *exp, int *pos, enum noside noside) { @@ -938,22 +590,20 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, { int oplen, limit; struct type *type; - struct obstack output; - struct cleanup *cleanup; struct value *result; - enum c_string_type dest_type; + c_string_type dest_type; const char *dest_charset; + int satisfy_expected = 0; - obstack_init (&output); - cleanup = make_cleanup_obstack_free (&output); + auto_obstack output; ++*pos; oplen = longest_to_int (exp->elts[*pos].longconst); ++*pos; limit = *pos + BYTES_TO_EXP_ELEM (oplen + 1); - dest_type - = (enum c_string_type) longest_to_int (exp->elts[*pos].longconst); + dest_type = ((enum c_string_type_values) + longest_to_int (exp->elts[*pos].longconst)); switch (dest_type & ~C_CHAR) { case C_STRING: @@ -961,24 +611,37 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, exp->gdbarch); break; case C_WIDE_STRING: - type = lookup_typename (exp->language_defn, exp->gdbarch, - "wchar_t", NULL, 0); + type = lookup_typename (exp->language_defn, "wchar_t", NULL, 0); break; case C_STRING_16: - type = lookup_typename (exp->language_defn, exp->gdbarch, - "char16_t", NULL, 0); + type = lookup_typename (exp->language_defn, "char16_t", NULL, 0); break; case C_STRING_32: - type = lookup_typename (exp->language_defn, exp->gdbarch, - "char32_t", NULL, 0); + type = lookup_typename (exp->language_defn, "char32_t", NULL, 0); break; default: - internal_error (__FILE__, __LINE__, "unhandled c_string_type"); + internal_error (__FILE__, __LINE__, _("unhandled c_string_type")); } /* Ensure TYPE_LENGTH is valid for TYPE. */ check_typedef (type); + /* If the caller expects an array of some integral type, + satisfy them. If something odder is expected, rely on the + caller to cast. */ + if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_ARRAY) + { + struct type *element_type + = check_typedef (TYPE_TARGET_TYPE (expect_type)); + + if (TYPE_CODE (element_type) == TYPE_CODE_INT + || TYPE_CODE (element_type) == TYPE_CODE_CHAR) + { + type = element_type; + satisfy_expected = 1; + } + } + dest_charset = charset_for_string_type (dest_type, exp->gdbarch); ++*pos; @@ -1001,11 +664,12 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, if (noside == EVAL_SKIP) { /* Return a dummy value of the appropriate type. */ - if ((dest_type & C_CHAR) != 0) + if (expect_type != NULL) + result = allocate_value (expect_type); + else if ((dest_type & C_CHAR) != 0) result = allocate_value (type); else result = value_cstring ("", 0, type); - do_cleanups (cleanup); return result; } @@ -1014,21 +678,43 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, LONGEST value; if (obstack_object_size (&output) != TYPE_LENGTH (type)) - error (_("Could not convert character constant to target character set")); - value = unpack_long (type, obstack_base (&output)); + error (_("Could not convert character " + "constant to target character set")); + value = unpack_long (type, (gdb_byte *) obstack_base (&output)); result = value_from_longest (type, value); } else { int i; + /* Write the terminating character. */ for (i = 0; i < TYPE_LENGTH (type); ++i) obstack_1grow (&output, 0); - result = value_cstring (obstack_base (&output), - obstack_object_size (&output), - type); + + if (satisfy_expected) + { + LONGEST low_bound, high_bound; + int element_size = TYPE_LENGTH (type); + + if (get_discrete_bounds (TYPE_INDEX_TYPE (expect_type), + &low_bound, &high_bound) < 0) + { + low_bound = 0; + high_bound = (TYPE_LENGTH (expect_type) / element_size) - 1; + } + if (obstack_object_size (&output) / element_size + > (high_bound - low_bound + 1)) + error (_("Too many array elements")); + + result = allocate_value (expect_type); + memcpy (value_contents_raw (result), obstack_base (&output), + obstack_object_size (&output)); + } + else + result = value_cstring ((const char *) obstack_base (&output), + obstack_object_size (&output), + type); } - do_cleanups (cleanup); return result; } break; @@ -1038,7 +724,53 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, } return evaluate_subexp_standard (expect_type, exp, pos, noside); } + +/* la_watch_location_expression for C. */ + +gdb::unique_xmalloc_ptr +c_watch_location_expression (struct type *type, CORE_ADDR addr) +{ + type = check_typedef (TYPE_TARGET_TYPE (check_typedef (type))); + std::string name = type_to_string (type); + return gdb::unique_xmalloc_ptr + (xstrprintf ("* (%s *) %s", name.c_str (), core_addr_to_string (addr))); +} +/* See c-lang.h. */ + +bool +c_is_string_type_p (struct type *type) +{ + type = check_typedef (type); + while (TYPE_CODE (type) == TYPE_CODE_REF) + { + type = TYPE_TARGET_TYPE (type); + type = check_typedef (type); + } + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + { + /* See if target type looks like a string. */ + struct type *array_target_type = TYPE_TARGET_TYPE (type); + return (TYPE_LENGTH (type) > 0 + && TYPE_LENGTH (array_target_type) > 0 + && c_textual_element_type (array_target_type, 0)); + } + case TYPE_CODE_STRING: + return true; + case TYPE_CODE_PTR: + { + struct type *element_type = TYPE_TARGET_TYPE (type); + return c_textual_element_type (element_type, 0); + } + default: + break; + } + + return false; +} /* Table mapping opcodes into strings for printing operators @@ -1067,15 +799,17 @@ const struct op_print c_op_print_tab[] = {"/", BINOP_DIV, PREC_MUL, 0}, {"%", BINOP_REM, PREC_MUL, 0}, {"@", BINOP_REPEAT, PREC_REPEAT, 0}, + {"+", UNOP_PLUS, PREC_PREFIX, 0}, {"-", UNOP_NEG, PREC_PREFIX, 0}, {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0}, {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0}, {"*", UNOP_IND, PREC_PREFIX, 0}, {"&", UNOP_ADDR, PREC_PREFIX, 0}, {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0}, + {"alignof ", UNOP_ALIGNOF, PREC_PREFIX, 0}, {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0}, {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}, - {NULL, 0, 0, 0} + {NULL, OP_NULL, PREC_PREFIX, 0} }; enum c_primitive_types { @@ -1107,6 +841,7 @@ c_language_arch_info (struct gdbarch *gdbarch, struct language_arch_info *lai) { const struct builtin_type *builtin = builtin_type (gdbarch); + lai->string_char_type = builtin->builtin_char; lai->primitive_type_vector = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_c_primitive_types + 1, @@ -1135,7 +870,7 @@ c_language_arch_info (struct gdbarch *gdbarch, lai->bool_type_default = builtin->builtin_int; } -static const struct exp_descriptor exp_descriptor_c = +const struct exp_descriptor exp_descriptor_c = { print_subexp_standard, operator_length_standard, @@ -1145,18 +880,23 @@ static const struct exp_descriptor exp_descriptor_c = evaluate_subexp_c }; -const struct language_defn c_language_defn = +static const char *c_extensions[] = +{ + ".c", NULL +}; + +extern const struct language_defn c_language_defn = { "c", /* Language name */ + "C", language_c, range_check_off, - type_check_off, case_sensitive_on, array_row_major, macro_expansion_c, + c_extensions, &exp_descriptor_c, c_parse, - c_error, null_post_parser, c_printchar, /* Print a character constant */ c_printstr, /* Function to print string constant */ @@ -1165,22 +905,33 @@ const struct language_defn c_language_defn = c_print_typedef, /* Print a typedef using appropriate syntax */ c_val_print, /* Print a value using appropriate syntax */ c_value_print, /* Print a top-level value */ + default_read_var_value, /* la_read_var_value */ NULL, /* Language specific skip_trampoline */ NULL, /* name_of_this */ + true, /* la_store_sym_names_in_linkage_form_p */ basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, + NULL, /* Language specific + class_name_from_physname */ c_op_print_tab, /* expression operators for printing */ 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, - default_make_symbol_completion_list, + default_collect_symbol_completion_matches, c_language_arch_info, default_print_array_index, default_pass_by_reference, - c_get_string, - LANG_MAGIC + c_watch_location_expression, + NULL, /* la_get_symbol_name_matcher */ + iterate_over_symbols, + default_search_name_hash, + &c_varobj_ops, + c_get_compile_context, + c_compute_program, + c_is_string_type_p, + "{...}" /* la_struct_too_deep_ellipsis */ }; enum cplus_primitive_types { @@ -1205,6 +956,9 @@ enum cplus_primitive_types { cplus_primitive_type_decfloat, cplus_primitive_type_decdouble, cplus_primitive_type_declong, + cplus_primitive_type_char16_t, + cplus_primitive_type_char32_t, + cplus_primitive_type_wchar_t, nr_cplus_primitive_types }; @@ -1213,6 +967,7 @@ cplus_language_arch_info (struct gdbarch *gdbarch, struct language_arch_info *lai) { const struct builtin_type *builtin = builtin_type (gdbarch); + lai->string_char_type = builtin->builtin_char; lai->primitive_type_vector = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_cplus_primitive_types + 1, @@ -1259,23 +1014,34 @@ cplus_language_arch_info (struct gdbarch *gdbarch, = builtin->builtin_decdouble; lai->primitive_type_vector [cplus_primitive_type_declong] = builtin->builtin_declong; + lai->primitive_type_vector [cplus_primitive_type_char16_t] + = builtin->builtin_char16; + lai->primitive_type_vector [cplus_primitive_type_char32_t] + = builtin->builtin_char32; + lai->primitive_type_vector [cplus_primitive_type_wchar_t] + = builtin->builtin_wchar; lai->bool_type_symbol = "bool"; lai->bool_type_default = builtin->builtin_bool; } -const struct language_defn cplus_language_defn = +static const char *cplus_extensions[] = +{ + ".C", ".cc", ".cp", ".cpp", ".cxx", ".c++", NULL +}; + +extern const struct language_defn cplus_language_defn = { "c++", /* Language name */ + "C++", language_cplus, range_check_off, - type_check_off, case_sensitive_on, array_row_major, macro_expansion_c, + cplus_extensions, &exp_descriptor_c, c_parse, - c_error, null_post_parser, c_printchar, /* Print a character constant */ c_printstr, /* Function to print string constant */ @@ -1284,36 +1050,52 @@ const struct language_defn cplus_language_defn = c_print_typedef, /* Print a typedef using appropriate syntax */ c_val_print, /* Print a value using appropriate syntax */ c_value_print, /* Print a top-level value */ + default_read_var_value, /* la_read_var_value */ cplus_skip_trampoline, /* Language specific skip_trampoline */ "this", /* name_of_this */ + false, /* la_store_sym_names_in_linkage_form_p */ cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ cp_lookup_transparent_type, /* lookup_transparent_type */ - cplus_demangle, /* Language specific symbol demangler */ - cp_class_name_from_physname, /* Language specific class_name_from_physname */ + gdb_demangle, /* Language specific symbol demangler */ + gdb_sniff_from_mangled_name, + cp_class_name_from_physname, /* Language specific + class_name_from_physname */ c_op_print_tab, /* expression operators for printing */ 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, - default_make_symbol_completion_list, + default_collect_symbol_completion_matches, cplus_language_arch_info, default_print_array_index, cp_pass_by_reference, - c_get_string, - LANG_MAGIC + c_watch_location_expression, + cp_get_symbol_name_matcher, + iterate_over_symbols, + cp_search_name_hash, + &cplus_varobj_ops, + cplus_get_compile_context, + cplus_compute_program, + c_is_string_type_p, + "{...}" /* la_struct_too_deep_ellipsis */ +}; + +static const char *asm_extensions[] = +{ + ".s", ".sx", ".S", NULL }; -const struct language_defn asm_language_defn = +extern const struct language_defn asm_language_defn = { "asm", /* Language name */ + "assembly", language_asm, range_check_off, - type_check_off, case_sensitive_on, array_row_major, macro_expansion_c, + asm_extensions, &exp_descriptor_c, c_parse, - c_error, null_post_parser, c_printchar, /* Print a character constant */ c_printstr, /* Function to print string constant */ @@ -1322,22 +1104,33 @@ const struct language_defn asm_language_defn = c_print_typedef, /* Print a typedef using appropriate syntax */ c_val_print, /* Print a value using appropriate syntax */ c_value_print, /* Print a top-level value */ + default_read_var_value, /* la_read_var_value */ NULL, /* Language specific skip_trampoline */ NULL, /* name_of_this */ + true, /* la_store_sym_names_in_linkage_form_p */ basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, + NULL, /* Language specific + class_name_from_physname */ c_op_print_tab, /* expression operators for printing */ 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, - default_make_symbol_completion_list, - c_language_arch_info, /* FIXME: la_language_arch_info. */ + default_collect_symbol_completion_matches, + c_language_arch_info, /* FIXME: la_language_arch_info. */ default_print_array_index, default_pass_by_reference, - c_get_string, - LANG_MAGIC + c_watch_location_expression, + NULL, /* la_get_symbol_name_matcher */ + iterate_over_symbols, + default_search_name_hash, + &default_varobj_ops, + NULL, + NULL, + c_is_string_type_p, + "{...}" /* la_struct_too_deep_ellipsis */ }; /* The following language_defn does not represent a real language. @@ -1345,18 +1138,18 @@ const struct language_defn asm_language_defn = to do some simple operations when debugging applications that use a language currently not supported by GDB. */ -const struct language_defn minimal_language_defn = +extern const struct language_defn minimal_language_defn = { "minimal", /* Language name */ + "Minimal", language_minimal, range_check_off, - type_check_off, case_sensitive_on, array_row_major, macro_expansion_c, + NULL, &exp_descriptor_c, c_parse, - c_error, null_post_parser, c_printchar, /* Print a character constant */ c_printstr, /* Function to print string constant */ @@ -1365,29 +1158,31 @@ const struct language_defn minimal_language_defn = c_print_typedef, /* Print a typedef using appropriate syntax */ c_val_print, /* Print a value using appropriate syntax */ c_value_print, /* Print a top-level value */ + default_read_var_value, /* la_read_var_value */ NULL, /* Language specific skip_trampoline */ NULL, /* name_of_this */ + true, /* la_store_sym_names_in_linkage_form_p */ basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ basic_lookup_transparent_type,/* lookup_transparent_type */ NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ + NULL, + NULL, /* Language specific + class_name_from_physname */ c_op_print_tab, /* expression operators for printing */ 1, /* c-style arrays */ 0, /* String lower bound */ default_word_break_characters, - default_make_symbol_completion_list, + default_collect_symbol_completion_matches, c_language_arch_info, default_print_array_index, default_pass_by_reference, - c_get_string, - LANG_MAGIC + c_watch_location_expression, + NULL, /* la_get_symbol_name_matcher */ + iterate_over_symbols, + default_search_name_hash, + &default_varobj_ops, + NULL, + NULL, + c_is_string_type_p, + "{...}" /* la_struct_too_deep_ellipsis */ }; - -void -_initialize_c_language (void) -{ - add_language (&c_language_defn); - add_language (&cplus_language_defn); - add_language (&asm_language_defn); - add_language (&minimal_language_defn); -}