* symtab.c (find_pc_sect_line): Use SYMBOL_VALUE_ADDRESS instead
[deliverable/binutils-gdb.git] / gdb / printcmd.c
index 019a4a627032f6109c57a061e585abdfa02ecd92..51b5efc115765c79f9b7c1fe24772ee7903561f0 100644 (file)
@@ -1,8 +1,8 @@
 /* Print values for GNU debugger GDB.
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+   2008 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -41,6 +41,7 @@
 #include "gdb_assert.h"
 #include "block.h"
 #include "disasm.h"
+#include "dfp.h"
 
 #ifdef TUI
 #include "tui/tui.h"           /* For tui_active et.al.   */
@@ -250,7 +251,8 @@ decode_format (char **string_ptr, int oformat, int osize)
    Do not end with a newline.
    0 means print VAL according to its own type.
    SIZE is the letter for the size of datum being printed.
-   This is used to pad hex numbers so they line up.  */
+   This is used to pad hex numbers so they line up.  SIZE is 0
+   for print / output and set for examine.  */
 
 static void
 print_formatted (struct value *val, int format, int size,
@@ -262,45 +264,41 @@ print_formatted (struct value *val, int format, int size,
   if (VALUE_LVAL (val) == lval_memory)
     next_address = VALUE_ADDRESS (val) + len;
 
-  switch (format)
+  if (size)
     {
-    case 's':
-      /* FIXME: Need to handle wchar_t's here... */
-      next_address = VALUE_ADDRESS (val)
-       + val_print_string (VALUE_ADDRESS (val), -1, 1, stream);
-      break;
-
-    case 'i':
-      /* The old comment says
-         "Force output out, print_insn not using _filtered".
-         I'm not completely sure what that means, I suspect most print_insn
-         now do use _filtered, so I guess it's obsolete.
-         --Yes, it does filter now, and so this is obsolete.  -JB  */
-
-      /* We often wrap here if there are long symbolic names.  */
-      wrap_here ("    ");
-      next_address = (VALUE_ADDRESS (val)
-                     + gdb_print_insn (VALUE_ADDRESS (val), stream,
-                                       &branch_delay_insns));
-      break;
+      switch (format)
+       {
+       case 's':
+         /* FIXME: Need to handle wchar_t's here... */
+         next_address = VALUE_ADDRESS (val)
+           + val_print_string (VALUE_ADDRESS (val), -1, 1, stream);
+         return;
 
-    default:
-      if (format == 0
-         || TYPE_CODE (type) == TYPE_CODE_ARRAY
-         || TYPE_CODE (type) == TYPE_CODE_STRING
-         || TYPE_CODE (type) == TYPE_CODE_STRUCT
-         || TYPE_CODE (type) == TYPE_CODE_UNION
-         || TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
-       /* If format is 0, use the 'natural' format for that type of
-          value.  If the type is non-scalar, we have to use language
-          rules to print it as a series of scalars.  */
-       value_print (val, stream, format, Val_pretty_default);
-      else
-       /* User specified format, so don't look to the the type to
-          tell us what to do.  */
-       print_scalar_formatted (value_contents (val), type,
-                               format, size, stream);
+       case 'i':
+         /* We often wrap here if there are long symbolic names.  */
+         wrap_here ("    ");
+         next_address = (VALUE_ADDRESS (val)
+                         + gdb_print_insn (VALUE_ADDRESS (val), stream,
+                                           &branch_delay_insns));
+         return;
+       }
     }
+
+  if (format == 0 || format == 's'
+      || TYPE_CODE (type) == TYPE_CODE_ARRAY
+      || TYPE_CODE (type) == TYPE_CODE_STRING
+      || TYPE_CODE (type) == TYPE_CODE_STRUCT
+      || TYPE_CODE (type) == TYPE_CODE_UNION
+      || TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
+    /* If format is 0, use the 'natural' format for that type of
+       value.  If the type is non-scalar, we have to use language
+       rules to print it as a series of scalars.  */
+    value_print (val, stream, format, Val_pretty_default);
+  else
+    /* User specified format, so don't look to the the type to
+       tell us what to do.  */
+    print_scalar_formatted (value_contents (val), type,
+                           format, size, stream);
 }
 
 /* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,
@@ -317,6 +315,15 @@ print_scalar_formatted (const void *valaddr, struct type *type,
   LONGEST val_long = 0;
   unsigned int len = TYPE_LENGTH (type);
 
+  /* If we get here with a string format, try again without it.  Go
+     all the way back to the language printers, which may call us
+     again.  */
+  if (format == 's')
+    {
+      val_print (type, valaddr, 0, 0, stream, 0, 0, 0, Val_pretty_default);
+      return;
+    }
+
   if (len > sizeof(LONGEST) &&
       (TYPE_CODE (type) == TYPE_CODE_INT
        || TYPE_CODE (type) == TYPE_CODE_ENUM))
@@ -407,8 +414,17 @@ print_scalar_formatted (const void *valaddr, struct type *type,
       break;
 
     case 'c':
-      value_print (value_from_longest (builtin_type_true_char, val_long),
-                  stream, 0, Val_pretty_default);
+      if (TYPE_UNSIGNED (type))
+       {
+         struct type *utype;
+
+         utype = builtin_type (current_gdbarch)->builtin_true_unsigned_char;
+         value_print (value_from_longest (utype, val_long),
+                      stream, 0, Val_pretty_default);
+       }
+      else
+       value_print (value_from_longest (builtin_type_true_char, val_long),
+                    stream, 0, Val_pretty_default);
       break;
 
     case 'f':
@@ -809,7 +825,7 @@ validate_format (struct format_data fmt, char *cmdname)
   if (fmt.count != 1)
     error (_("Item count other than 1 is meaningless in \"%s\" command."),
           cmdname);
-  if (fmt.format == 'i' || fmt.format == 's')
+  if (fmt.format == 'i')
     error (_("Format letter \"%c\" is meaningless in \"%s\" command."),
           fmt.format, cmdname);
 }
@@ -1804,7 +1820,7 @@ printf_command (char *arg, int from_tty)
     enum argclass
       {
        int_arg, long_arg, long_long_arg, ptr_arg, string_arg,
-       double_arg, long_double_arg
+       double_arg, long_double_arg, decfloat_arg
       };
     enum argclass *argclass;
     enum argclass this_argclass;
@@ -1913,6 +1929,34 @@ printf_command (char *arg, int from_tty)
                bad = 1;
              break;
 
+           /* DFP Decimal32 types.  */
+           case 'H':
+             this_argclass = decfloat_arg;
+
+#ifndef PRINTF_HAS_DECFLOAT
+              if (lcount || seen_h || seen_big_l)
+                bad = 1;
+              if (seen_prec || seen_zero || seen_space || seen_plus)
+                bad = 1;
+#endif
+             break;
+
+           /* DFP Decimal64 and Decimal128 types.  */
+           case 'D':
+             this_argclass = decfloat_arg;
+
+#ifndef PRINTF_HAS_DECFLOAT
+              if (lcount || seen_h || seen_big_l)
+                bad = 1;
+              if (seen_prec || seen_zero || seen_space || seen_plus)
+                bad = 1;
+#endif
+             /* Check for a Decimal128.  */
+             if (*(f + 1) == 'D')
+               f++;
+
+             break;
+
            case 'c':
              this_argclass = int_arg;
              if (lcount || seen_h || seen_big_l)
@@ -2079,6 +2123,55 @@ printf_command (char *arg, int from_tty)
              printf_filtered (current_substring, val);
              break;
            }
+
+         /* Handles decimal floating point values.  */
+         case decfloat_arg:
+           {
+             char *eos;
+             char decstr[MAX_DECIMAL_STRING];
+             unsigned int dfp_len = TYPE_LENGTH (value_type (val_args[i]));
+             unsigned char *dfp_value_ptr = (unsigned char *) value_contents_all (val_args[i])
+                                      + value_offset (val_args[i]);
+
+#if defined (PRINTF_HAS_DECFLOAT)
+             printf_filtered (current_substring, dfp_value_ptr);
+#else
+             if (TYPE_CODE (value_type (val_args[i])) != TYPE_CODE_DECFLOAT)
+               error (_("Cannot convert parameter to decfloat."));
+
+             /* As a workaround until vasprintf has native support for DFP
+                we convert the DFP values to string and print them using
+                the %s format specifier.  */
+             decimal_to_string (dfp_value_ptr, dfp_len, decstr);
+
+             /* Points to the end of the string so that we can go back
+                and check for DFP format specifiers.  */
+             eos = current_substring + strlen (current_substring);
+
+             /* Replace %H, %D and %DD with %s's.  */
+             while (*--eos != '%')
+               if (*eos == 'D' && *(eos - 1) == 'D')
+                 {
+                   *(eos - 1) = 's';
+
+                   /* If we've found a %DD format specifier we need to go
+                      through the whole string pulling back one character
+                      since this format specifier has two chars.  */
+                   while (eos < last_arg)
+                     {
+                       *eos = *(eos + 1);
+                       eos++;
+                     }
+                 }
+               else if (*eos == 'D' || *eos == 'H')
+                 *eos = 's';
+
+             /* Print the DFP value.  */
+             printf_filtered (current_substring, decstr);
+             break;
+#endif
+           }
+
          case ptr_arg:
            {
              /* We avoid the host's %p because pointers are too
This page took 0.026305 seconds and 4 git commands to generate.