OSDN Git Service

Merge branch 'binutils' into tmp
[pf3gnuchains/pf3gnuchains4x.git] / gdb / c-lang.c
index d620881..c4d841f 100644 (file)
@@ -1,7 +1,7 @@
 /* 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-1996, 1998-2000, 2002-2005, 2007-2012 Free
+   Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -35,6 +35,7 @@
 #include "cp-support.h"
 #include "gdb_obstack.h"
 #include <ctype.h>
+#include "exceptions.h"
 
 extern void _initialize_c_language (void);
 
@@ -43,40 +44,40 @@ extern void _initialize_c_language (void);
 
 static const char *
 charset_for_string_type (enum c_string_type str_type,
-                        enum bfd_endian byte_order)
+                        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,
+classify_type (struct type *elttype, struct gdbarch *gdbarch,
               const char **encoding)
 {
-  struct type *saved_type;
   enum c_string_type result;
 
   /* We loop because ELTTYPE may be a typedef, and we want to
@@ -134,205 +135,23 @@ classify_type (struct type *elttype, enum bfd_endian byte_order,
 
  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.  */
+/* 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 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. */
-
-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
@@ -340,7 +159,7 @@ c_printchar (int c, struct type *type, struct ui_file *stream)
 {
   enum 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:
@@ -361,17 +180,23 @@ 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 c_string_type str_type;
+  const char *type_encoding;
+  const char *encoding;
+
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
   unsigned int i;
   unsigned int things_printed = 0;
@@ -380,23 +205,12 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
   int width = TYPE_LENGTH (type);
   struct obstack wchar_buf, output;
   struct cleanup *cleanup;
-  enum 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, &type_encoding) & ~C_CHAR;
+  str_type = (classify_type (type, get_type_arch (type), &type_encoding)
+             & ~C_CHAR);
   switch (str_type)
     {
     case C_STRING:
@@ -414,221 +228,35 @@ 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 (_(" <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;
-               }
-           }
-       }
-
-      /* 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.
-   On completion, *LENGTH will be set to the size of the string read in
+   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.  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_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 bfd_endian byte_order
+    = gdbarch_byte_order (get_type_arch (type));
   enum c_string_type kind;
 
   if (element_type == NULL)
@@ -636,8 +264,8 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
 
   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,13 +287,14 @@ 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,
-                       gdbarch_byte_order (get_type_arch (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.  */
   if ((VALUE_LVAL (value) == not_lval
        || VALUE_LVAL (value) == lval_internalvar)
       && fetchlimit != UINT_MAX)
@@ -679,8 +308,8 @@ c_get_string (struct value *value, gdb_byte **buffer, int *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)
+         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
@@ -692,13 +321,19 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
     }
   else
     {
-      err = read_string (value_as_address (value), *length, width, fetchlimit,
-                        byte_order, buffer, length);
+      CORE_ADDR addr = value_as_address (value);
+
+      err = read_string (addr, *length, width, fetchlimit,
+                        byte_order, buffer, length);
       if (err)
        {
          xfree (*buffer);
-         error (_("Error reading string from inferior: %s"),
-                safe_strerror (err));
+         if (err == EIO)
+           throw_error (MEMORY_ERROR, "Address %s out of bounds",
+                        paddress (get_type_arch (type), addr));
+         else
+           error (_("Error reading string from inferior: %s"),
+                  safe_strerror (err));
        }
     }
 
@@ -709,8 +344,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 + *length - width,
+                                    width, byte_order) == 0)
       *length -= width;
   
   /* The read_string function will return the number of bytes read.
@@ -765,8 +400,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;
 }
@@ -791,7 +426,8 @@ 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;
@@ -815,7 +451,8 @@ 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;
 
@@ -880,6 +517,7 @@ convert_escape (struct type *type, const char *dest_charset,
     case 'U':
       {
        int length = *p == 'u' ? 4 : 8;
+
        ADVANCE;
        if (!isxdigit (*p))
          error (_("\\u used with no following hex digits"));
@@ -907,13 +545,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);
+                                  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);
@@ -925,7 +565,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)
 {
@@ -942,7 +582,7 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp,
        struct value *result;
        enum 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);
@@ -973,14 +613,29 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp,
                                    "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)
@@ -1002,7 +657,9 @@ 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);
@@ -1015,19 +672,42 @@ 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"));
+             error (_("Could not convert character "
+                      "constant to target character set"));
            value = unpack_long (type, 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 (obstack_base (&output),
+                                     obstack_object_size (&output),
+                                     type);
          }
        do_cleanups (cleanup);
        return result;
@@ -1108,6 +788,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,
@@ -1136,10 +817,11 @@ 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,
+  operator_check_standard,
   op_name_standard,
   dump_subexp_body_standard,
   evaluate_subexp_c
@@ -1170,7 +852,8 @@ const struct language_defn c_language_defn =
   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,                                /* Language specific
+                                  class_name_from_physname */
   c_op_print_tab,              /* expression operators for printing */
   1,                           /* c-style arrays */
   0,                           /* String lower bound */
@@ -1180,6 +863,8 @@ const struct language_defn c_language_defn =
   default_print_array_index,
   default_pass_by_reference,
   c_get_string,
+  strcmp_iw_ordered,
+  iterate_over_symbols,
   LANG_MAGIC
 };
 
@@ -1213,6 +898,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,
@@ -1289,7 +975,8 @@ const struct language_defn cplus_language_defn =
   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 */
+  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 */
@@ -1299,6 +986,8 @@ const struct language_defn cplus_language_defn =
   default_print_array_index,
   cp_pass_by_reference,
   c_get_string,
+  strcmp_iw_ordered,
+  iterate_over_symbols,
   LANG_MAGIC
 };
 
@@ -1327,16 +1016,19 @@ const struct language_defn asm_language_defn =
   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,                                /* 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.  */
+  c_language_arch_info,        /* FIXME: la_language_arch_info.  */
   default_print_array_index,
   default_pass_by_reference,
   c_get_string,
+  strcmp_iw_ordered,
+  iterate_over_symbols,
   LANG_MAGIC
 };
 
@@ -1370,7 +1062,8 @@ const struct language_defn minimal_language_defn =
   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,                                /* Language specific
+                                  class_name_from_physname */
   c_op_print_tab,              /* expression operators for printing */
   1,                           /* c-style arrays */
   0,                           /* String lower bound */
@@ -1380,6 +1073,8 @@ const struct language_defn minimal_language_defn =
   default_print_array_index,
   default_pass_by_reference,
   c_get_string,
+  strcmp_iw_ordered,
+  iterate_over_symbols,
   LANG_MAGIC
 };