gdb
[deliverable/binutils-gdb.git] / gdb / c-lang.c
index f95c98f336915b4c506837c04212cabe11cfa0b2..fefd67556459156040fe5f3ed9dedaa9edbba0a5 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 Free Software Foundation, Inc.
+   2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -42,26 +42,27 @@ extern void _initialize_c_language (void);
    character set name.  */
 
 static const char *
-charset_for_string_type (enum c_string_type str_type)
+charset_for_string_type (enum 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 ();
+      return target_wide_charset (gdbarch);
     case C_STRING_16:
-      /* FIXME: UCS-2 is not always correct.  */
-      if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
-       return "UCS-2BE";
+      /* FIXME: UTF-16 is not always correct.  */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+       return "UTF-16BE";
       else
-       return "UCS-2LE";
+       return "UTF-16LE";
     case C_STRING_32:
-      /* FIXME: UCS-4 is not always correct.  */
-      if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
-       return "UCS-4BE";
+      /* FIXME: UTF-32 is not always correct.  */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+       return "UTF-32BE";
       else
-       return "UCS-4LE";
+       return "UTF-32LE";
     }
   internal_error (__FILE__, __LINE__, "unhandled c_string_type");
 }
@@ -69,17 +70,21 @@ charset_for_string_type (enum c_string_type str_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 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, const char **encoding)
+classify_type (struct type *elttype, struct gdbarch *gdbarch,
+              const char **encoding)
 {
   struct type *saved_type;
   enum c_string_type result;
 
-  /* We do one or two passes -- one on ELTTYPE, and then maybe a
-     second one on a typedef target.  */
-  do
+  /* We loop because ELTTYPE may be a typedef, and we want to
+     successively peel each typedef until we reach a type we
+     understand.  We don't use CHECK_TYPEDEF because that will strip
+     all typedefs at once -- but in C, wchar_t is itself a typedef, so
+     that would do the wrong thing.  */
+  while (elttype)
     {
       char *name = TYPE_NAME (elttype);
 
@@ -107,16 +112,30 @@ classify_type (struct type *elttype, const char **encoding)
          goto done;
        }
 
-      saved_type = elttype;
-      CHECK_TYPEDEF (elttype);
+      if (TYPE_CODE (elttype) != TYPE_CODE_TYPEDEF)
+       break;
+
+      /* Call for side effects.  */
+      check_typedef (elttype);
+
+      if (TYPE_TARGET_TYPE (elttype))
+       elttype = TYPE_TARGET_TYPE (elttype);
+      else
+       {
+         /* 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);
+       }
     }
-  while (elttype != saved_type);
 
   /* Punt.  */
   result = C_CHAR;
 
  done:
-  *encoding = charset_for_string_type (result);
+  if (encoding)
+    *encoding = charset_for_string_type (result, gdbarch);
+
   return result;
 }
 
@@ -157,8 +176,8 @@ append_string_as_wide (const char *string, struct obstack *output)
 
 static void
 print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
-            int width, struct obstack *output, int quoter,
-            int *need_escapep)
+            int width, enum bfd_endian byte_order, struct obstack *output,
+            int quoter, int *need_escapep)
 {
   int need_escape = *need_escapep;
   *need_escapep = 0;
@@ -166,7 +185,7 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
                                            && w != LCST ('8')
                                            && w != LCST ('9'))))
     {
-      gdb_wchar_t wchar = (gdb_wchar_t) w;
+      gdb_wchar_t wchar = w;
 
       if (w == gdb_btowc (quoter) || w == LCST ('\\'))
        obstack_grow_wstr (output, LCST ("\\"));
@@ -204,8 +223,14 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
            for (i = 0; i + width <= orig_len; i += width)
              {
                char octal[30];
-               ULONGEST value = extract_unsigned_integer (&orig[i], width);
-               sprintf (octal, "\\%lo", (long) value);
+               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.  */
@@ -231,6 +256,7 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
 static 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;
@@ -238,7 +264,7 @@ c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
   struct wchar_iterator *iter;
   int need_escape = 0;
 
-  classify_type (type, &encoding);
+  classify_type (type, get_type_arch (type), &encoding);
 
   buf = alloca (TYPE_LENGTH (type));
   pack_long (buf, type, c);
@@ -284,14 +310,14 @@ c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
            {
              for (i = 0; i < num_chars; ++i)
                print_wchar (chars[i], buf, buflen, TYPE_LENGTH (type),
-                            &wchar_buf, quoter, &need_escape);
+                            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), &wchar_buf,
-                    quoter, &need_escape);
+       print_wchar (gdb_WEOF, buf, buflen, TYPE_LENGTH (type), byte_order,
+                    &wchar_buf, quoter, &need_escape);
     }
 
   /* The output in the host encoding.  */
@@ -313,9 +339,8 @@ void
 c_printchar (int c, struct type *type, struct ui_file *stream)
 {
   enum c_string_type str_type;
-  const char *encoding;
 
-  str_type = classify_type (type, &encoding);
+  str_type = classify_type (type, get_type_arch (type), NULL);
   switch (str_type)
     {
     case C_CHAR:
@@ -344,9 +369,10 @@ c_printchar (int c, struct type *type, struct ui_file *stream)
 
 void
 c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
-           unsigned int length, int force_ellipses,
+           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;
@@ -355,6 +381,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
   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;
@@ -365,10 +392,12 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
      style.  */
   if (!force_ellipses
       && length > 0
-      && (extract_unsigned_integer (string + (length - 1) * width, width) == 0))
+      && (extract_unsigned_integer (string + (length - 1) * width,
+                                   width, byte_order) == 0))
     length--;
 
-  str_type = classify_type (type, &encoding) & ~C_CHAR;
+  str_type = (classify_type (type, get_type_arch (type), &type_encoding)
+             & ~C_CHAR);
   switch (str_type)
     {
     case C_STRING:
@@ -384,6 +413,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
       break;
     }
 
+  encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding;
+
   if (length == 0)
     {
       fputs_filtered ("\"\"", stream);
@@ -396,7 +427,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
       for (i = 0; current_char; ++i)
        {
          QUIT;
-         current_char = extract_unsigned_integer (string + i * width, width);
+         current_char = extract_unsigned_integer (string + i * width,
+                                                  width, byte_order);
        }
       length = i;
     }
@@ -431,7 +463,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
         single character in isolation.  This makes the code simpler
         and probably does the sensible thing in the majority of
         cases.  */
-      while (num_chars == 1)
+      while (num_chars == 1 && things_printed < options->print_max)
        {
          /* Count the number of repetitions.  */
          unsigned int reps = 0;
@@ -466,7 +498,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
              obstack_grow_wstr (&wchar_buf, LCST ("'"));
              need_escape = 0;
              print_wchar (current_char, orig_buf, orig_len, width,
-                          &wchar_buf, '\'', &need_escape);
+                          byte_order, &wchar_buf, '\'', &need_escape);
              obstack_grow_wstr (&wchar_buf, LCST ("'"));
              {
                /* Painful gyrations.  */
@@ -499,7 +531,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
              while (reps-- > 0)
                {
                  print_wchar (current_char, orig_buf, orig_len, width,
-                              &wchar_buf, '"', &need_escape);
+                              byte_order, &wchar_buf, '"', &need_escape);
                  ++things_printed;
                }
            }
@@ -526,7 +558,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
              in_quotes = 1;
            }
          need_escape = 0;
-         print_wchar (gdb_WEOF, buf, buflen, width, &wchar_buf,
+         print_wchar (gdb_WEOF, buf, buflen, width, byte_order, &wchar_buf,
                       '"', &need_escape);
          break;
 
@@ -540,7 +572,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
              in_quotes = 0;
            }
          obstack_grow_wstr (&wchar_buf, LCST (" <incomplete sequence "));
-         print_wchar (gdb_WEOF, buf, buflen, width, &wchar_buf,
+         print_wchar (gdb_WEOF, buf, buflen, width, byte_order, &wchar_buf,
                       0, &need_escape);
          obstack_grow_wstr (&wchar_buf, LCST (">"));
          finished = 1;
@@ -576,27 +608,29 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
 }
 
 /* Obtain a C string from the inferior storing it in a newly allocated
-   buffer in BUFFER, which should be freed by the caller.  The string is
-   read until a null character is found. If VALUE is an array with known
-   length, the function will not read past the end of the array.  LENGTH
-   will contain the size of the string in bytes (not counting the null
-   character).
-
-   Assumes strings are terminated by a null character.  The size of a character
-   is determined by the length of the target type of the pointer or array.
-   This means that a null byte present in a multi-byte character will not
-   terminate the string unless the whole character is null.
-
-   CHARSET is always set to the target charset.  */
+   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
+   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,
-             const char **charset)
+             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;
 
   if (element_type == NULL)
     goto error;
@@ -623,16 +657,14 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
     /* We work only with arrays and pointers.  */
     goto error;
 
-  element_type = check_typedef (element_type);
-  if (TYPE_CODE (element_type) != TYPE_CODE_INT
-      && TYPE_CODE (element_type) != TYPE_CODE_CHAR)
-    /* If the elements are not integers or characters, we don't consider it
-       a string.  */
+  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 intead of the inferior's, then we
+  /* 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
@@ -642,12 +674,18 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
       int i;
       const gdb_byte *contents = value_contents (value);
 
-      /* Look for a null character.  */
-      for (i = 0; i < fetchlimit; i++)
-       if (extract_unsigned_integer (contents + i * width, width) == 0)
-         break;
-
-      /* I is now either the number of non-null characters, or FETCHLIMIT.  */
+      /* 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);
@@ -655,8 +693,8 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
     }
   else
     {
-      err = read_string (value_as_address (value), -1, width, fetchlimit,
-                        buffer, length);
+      err = read_string (value_as_address (value), *length, width, fetchlimit,
+                        byte_order, buffer, length);
       if (err)
        {
          xfree (*buffer);
@@ -665,12 +703,24 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
        }
     }
 
-  /* If the last character is null, subtract it from LENGTH.  */
-  if (*length > 0
-      && extract_unsigned_integer (*buffer + *length - width, width) == 0)
-    *length -= width;
-
-  *charset = target_charset ();
+  /* 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;
 
@@ -716,7 +766,7 @@ convert_ucn (char *p, char *limit, const char *dest_charset,
       result >>= 8;
     }
 
-  convert_between_encodings ("UCS-4BE", dest_charset, data, 4, 4, output,
+  convert_between_encodings ("UTF-32BE", dest_charset, data, 4, 4, output,
                             translit_none);
 
   return p;
@@ -744,9 +794,12 @@ emit_numeric_character (struct type *type, unsigned long value,
 static char *
 convert_octal (struct type *type, char *p, char *limit, struct obstack *output)
 {
+  int i;
   unsigned long value = 0;
 
-  while (p < limit && isdigit (*p) && *p != '8' && *p != '9')
+  for (i = 0;
+       i < 3 && p < limit && isdigit (*p) && *p != '8' && *p != '9';
+       ++i)
     {
       value = 8 * value + host_hex_value (*p);
       ++p;
@@ -904,17 +957,20 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp,
        switch (dest_type & ~C_CHAR)
          {
          case C_STRING:
-           type = language_string_char_type (current_language,
-                                             current_gdbarch);
+           type = language_string_char_type (exp->language_defn,
+                                             exp->gdbarch);
            break;
          case C_WIDE_STRING:
-           type = lookup_typename ("wchar_t", NULL, 0);
+           type = lookup_typename (exp->language_defn, exp->gdbarch,
+                                   "wchar_t", NULL, 0);
            break;
          case C_STRING_16:
-           type = lookup_typename ("char16_t", NULL, 0);
+           type = lookup_typename (exp->language_defn, exp->gdbarch,
+                                   "char16_t", NULL, 0);
            break;
          case C_STRING_32:
-           type = lookup_typename ("char32_t", NULL, 0);
+           type = lookup_typename (exp->language_defn, exp->gdbarch,
+                                   "char32_t", NULL, 0);
            break;
          default:
            internal_error (__FILE__, __LINE__, "unhandled c_string_type");
@@ -923,7 +979,7 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp,
        /* Ensure TYPE_LENGTH is valid for TYPE.  */
        check_typedef (type);
 
-       dest_charset = charset_for_string_type (dest_type);
+       dest_charset = charset_for_string_type (dest_type, exp->gdbarch);
 
        ++*pos;
        while (*pos < limit)
@@ -948,7 +1004,7 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp,
            if ((dest_type & C_CHAR) != 0)
              result = allocate_value (type);
            else
-             result = value_typed_string ("", 0, type);
+             result = value_cstring ("", 0, type);
            do_cleanups (cleanup);
            return result;
          }
@@ -968,9 +1024,9 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp,
            /* Write the terminating character.  */
            for (i = 0; i < TYPE_LENGTH (type); ++i)
              obstack_1grow (&output, 0);
-           result = value_typed_string (obstack_base (&output),
-                                        obstack_object_size (&output),
-                                        type);
+           result = value_cstring (obstack_base (&output),
+                                   obstack_object_size (&output),
+                                   type);
          }
        do_cleanups (cleanup);
        return result;
This page took 0.04942 seconds and 4 git commands to generate.