/* 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.
#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 <ctype.h>
-
-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,
- enum bfd_endian byte_order)
+charset_for_string_type (c_string_type str_type, struct gdbarch *gdbarch)
{
switch (str_type & ~C_CHAR)
{
case C_STRING:
- return target_charset ();
+ return target_charset (gdbarch);
case C_WIDE_STRING:
- return target_wide_charset (byte_order);
+ return target_wide_charset (gdbarch);
case C_STRING_16:
/* FIXME: UTF-16 is not always correct. */
- if (byte_order == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
return "UTF-16BE";
else
return "UTF-16LE";
case C_STRING_32:
/* FIXME: UTF-32 is not always correct. */
- if (byte_order == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
return "UTF-32BE";
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
-classify_type (struct type *elttype, enum bfd_endian byte_order,
+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
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)
{
/* 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);
}
}
done:
if (encoding)
- *encoding = charset_for_string_type (result, byte_order);
+ *encoding = charset_for_string_type (result, 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, byte_order, &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);
+ classify_type (type, get_type_arch (type), &encoding);
+ 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, BFD_ENDIAN_UNKNOWN, NULL);
+ str_type = classify_type (type, get_type_arch (type), NULL);
switch (str_type)
{
case C_CHAR:
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, 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, byte_order, &encoding) & ~C_CHAR;
+
+ str_type = (classify_type (type, get_type_arch (type), &type_encoding)
+ & ~C_CHAR);
switch (str_type)
{
case C_STRING:
break;
}
- 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 (_(" <repeats %u times>"), 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;
- }
- }
- }
+ encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding;
- /* 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 (" <incomplete sequence "));
- print_wchar (gdb_WEOF, buf, buflen, width, byte_order, &wchar_buf,
- 0, &need_escape);
- 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<gdb_byte> *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)
{
if (! c_textual_element_type (element_type, 0))
goto error;
- kind = classify_type (element_type,
- gdbarch_byte_order (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);
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
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.
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."));
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)
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;
}
{
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));
}
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);
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;
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;
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);
}
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);
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)
{
{
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;
- enum bfd_endian byte_order;
+ 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:
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);
- byte_order = gdbarch_byte_order (exp->gdbarch);
- dest_charset = charset_for_string_type (dest_type, byte_order);
+ /* 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;
while (*pos < limit)
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;
}
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;
}
return evaluate_subexp_standard (expect_type, exp, pos, noside);
}
+\f
+/* la_watch_location_expression for C. */
+
+gdb::unique_xmalloc_ptr<char>
+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<char>
+ (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;
+}
\f
/* Table mapping opcodes into strings for printing operators
{"/", 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}
};
\f
enum c_primitive_types {
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,
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,
+ operator_check_standard,
op_name_standard,
dump_subexp_body_standard,
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 */
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 {
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
};
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,
= 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 */
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 */
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.
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 */
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);
-}