common/
[deliverable/binutils-gdb.git] / gdb / c-lang.c
index 55dc042dfeea526b6efd84c80c0d2edf27fd7f4b..d620881b0d832e17d46773e8f2d379744cb8e006 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.
 
@@ -52,17 +52,17 @@ charset_for_string_type (enum c_string_type str_type,
     case C_WIDE_STRING:
       return target_wide_charset (byte_order);
     case C_STRING_16:
-      /* FIXME: UCS-2 is not always correct.  */
+      /* FIXME: UTF-16 is not always correct.  */
       if (byte_order == BFD_ENDIAN_BIG)
-       return "UCS-2BE";
+       return "UTF-16BE";
       else
-       return "UCS-2LE";
+       return "UTF-16LE";
     case C_STRING_32:
-      /* FIXME: UCS-4 is not always correct.  */
+      /* FIXME: UTF-32 is not always correct.  */
       if (byte_order == BFD_ENDIAN_BIG)
-       return "UCS-4BE";
+       return "UTF-32BE";
       else
-       return "UCS-4LE";
+       return "UTF-32LE";
     }
   internal_error (__FILE__, __LINE__, "unhandled c_string_type");
 }
@@ -225,7 +225,12 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
                char octal[30];
                ULONGEST value;
                value = extract_unsigned_integer (&orig[i], width, byte_order);
-               sprintf (octal, "\\%lo", (long) value);
+               /* 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.  */
@@ -364,7 +369,7 @@ 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));
@@ -376,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;
@@ -390,7 +396,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
                                    width, byte_order) == 0))
     length--;
 
-  str_type = classify_type (type, byte_order, &encoding) & ~C_CHAR;
+  str_type = classify_type (type, byte_order, &type_encoding) & ~C_CHAR;
   switch (str_type)
     {
     case C_STRING:
@@ -406,6 +412,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);
@@ -454,7 +462,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;
@@ -599,28 +607,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;
@@ -647,16 +656,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,
+                       gdbarch_byte_order (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
@@ -666,13 +673,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,
-                                     byte_order) == 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);
@@ -680,8 +692,8 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
     }
   else
     {
-      err = read_string (value_as_address (value), -1, width, fetchlimit,
-                        byte_order, buffer, length);
+      err = read_string (value_as_address (value), *length, width, fetchlimit,
+                        byte_order, buffer, length);
       if (err)
        {
          xfree (*buffer);
@@ -690,13 +702,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,
-                                  byte_order) == 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;
 
@@ -742,7 +765,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;
@@ -770,9 +793,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;
This page took 0.028092 seconds and 4 git commands to generate.