+ get_discrete_bounds (TYPE_FIELD_TYPE (type, 0),
+ &low_bound, &high_bound);
+ fetchlimit = high_bound - low_bound + 1;
+ }
+ else
+ fetchlimit = UINT_MAX;
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ fetchlimit = UINT_MAX;
+ else
+ /* We work only with arrays and pointers. */
+ goto error;
+
+ if (! c_textual_element_type (element_type, 0))
+ goto error;
+ kind = 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 ((VALUE_LVAL (value) == not_lval
+ || VALUE_LVAL (value) == lval_internalvar)
+ && fetchlimit != UINT_MAX)
+ {
+ int i;
+ const gdb_byte *contents = value_contents (value);
+
+ /* If a length is specified, use that. */
+ 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;
+
+ /* I is now either a user-defined length, the number of non-null
+ characters, or FETCHLIMIT. */
+ *length = i * width;
+ *buffer = xmalloc (*length);
+ memcpy (*buffer, contents, *length);
+ err = 0;
+ }
+ else
+ {
+ err = read_string (value_as_address (value), *length, width, fetchlimit,
+ byte_order, buffer, length);
+ if (err)
+ {
+ xfree (*buffer);
+ error (_("Error reading string from inferior: %s"),
+ safe_strerror (err));
+ }
+ }
+
+ /* If the LENGTH is specified at -1, we want to return the string
+ length up to the terminating null character. If an actual length
+ was specified, we want to return the length of exactly what was
+ read. */
+ 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)
+ *length -= width;
+
+ /* The read_string function will return the number of bytes read.
+ If length returned from read_string was > 0, return the number of
+ characters read by dividing the number of bytes by width. */
+ if (*length != 0)
+ *length = *length / width;
+
+ *char_type = element_type;
+
+ return;
+
+ error:
+ {
+ char *type_str;
+
+ type_str = type_to_string (type);
+ if (type_str)
+ {
+ make_cleanup (xfree, type_str);
+ error (_("Trying to read string with inappropriate type `%s'."),
+ type_str);
+ }
+ else
+ error (_("Trying to read string with inappropriate type."));
+ }
+}
+
+\f
+/* Evaluating C and C++ expressions. */
+
+/* Convert a UCN. The digits of the UCN start at P and extend no
+ farther than LIMIT. DEST_CHARSET is the name of the character set
+ into which the UCN should be converted. The results are written to
+ OUTPUT. LENGTH is the maximum length of the UCN, either 4 or 8.
+ Returns a pointer to just after the final digit of the UCN. */
+
+static char *
+convert_ucn (char *p, char *limit, const char *dest_charset,
+ struct obstack *output, int length)
+{
+ unsigned long result = 0;
+ gdb_byte data[4];
+ int i;
+
+ for (i = 0; i < length && p < limit && isxdigit (*p); ++i, ++p)
+ result = (result << 4) + host_hex_value (*p);
+
+ for (i = 3; i >= 0; --i)
+ {
+ data[i] = result & 0xff;
+ result >>= 8;
+ }
+
+ convert_between_encodings ("UTF-32BE", dest_charset, data, 4, 4, output,
+ translit_none);
+
+ return p;
+}
+
+/* Emit a character, VALUE, which was specified numerically, to
+ OUTPUT. TYPE is the target character type. */
+
+static void
+emit_numeric_character (struct type *type, unsigned long value,
+ struct obstack *output)
+{
+ gdb_byte *buffer;
+
+ buffer = alloca (TYPE_LENGTH (type));
+ pack_long (buffer, type, value);
+ obstack_grow (output, buffer, TYPE_LENGTH (type));
+}
+
+/* Convert an octal escape sequence. TYPE is the target character
+ type. The digits of the escape sequence begin at P and extend no
+ farther than LIMIT. The result is written to OUTPUT. Returns a
+ 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)
+{
+ int i;
+ unsigned long value = 0;
+
+ for (i = 0;
+ i < 3 && p < limit && isdigit (*p) && *p != '8' && *p != '9';
+ ++i)
+ {
+ value = 8 * value + host_hex_value (*p);
+ ++p;
+ }
+
+ emit_numeric_character (type, value, output);
+
+ return p;
+}
+
+/* Convert a hex escape sequence. TYPE is the target character type.
+ The digits of the escape sequence begin at P and extend no farther
+ than LIMIT. The result is written to OUTPUT. Returns a pointer to
+ just after the final digit of the escape sequence. */
+
+static char *
+convert_hex (struct type *type, char *p, char *limit, struct obstack *output)
+{
+ unsigned long value = 0;
+
+ while (p < limit && isxdigit (*p))
+ {
+ value = 16 * value + host_hex_value (*p);
+ ++p;
+ }
+
+ emit_numeric_character (type, value, output);
+
+ return p;
+}
+
+#define ADVANCE \
+ do { \
+ ++p; \
+ if (p == limit) \
+ error (_("Malformed escape sequence")); \
+ } while (0)
+
+/* Convert an escape sequence to a target format. TYPE is the target
+ character type to use, and DEST_CHARSET is the name of the target
+ character set. The backslash of the escape sequence is at *P, and
+ the escape sequence will not extend past LIMIT. The results are
+ written to OUTPUT. Returns a pointer to just past the final
+ character of the escape sequence. */
+
+static char *
+convert_escape (struct type *type, const char *dest_charset,
+ char *p, char *limit, struct obstack *output)
+{
+ /* Skip the backslash. */
+ ADVANCE;
+
+ switch (*p)
+ {
+ case '\\':
+ obstack_1grow (output, '\\');
+ ++p;