Fix PR gdb/22491: Regression when setting SystemTap probe semaphores
[deliverable/binutils-gdb.git] / gdb / printcmd.c
index d5c83f0a7273f7f7c637c5d25dbee5434f286979..2e596d1f09b5124a21339980e3407fbd9c83dc92 100644 (file)
@@ -38,7 +38,7 @@
 #include "ui-out.h"
 #include "block.h"
 #include "disasm.h"
-#include "dfp.h"
+#include "target-float.h"
 #include "observer.h"
 #include "solist.h"
 #include "parser-defs.h"
@@ -158,10 +158,6 @@ static int display_number;
        B ? (TMP = B->next, 1): 0;              \
        B = TMP)
 
-/* Prototypes for exported functions.  */
-
-void _initialize_printcmd (void);
-
 /* Prototypes for local functions.  */
 
 static void do_one_display (struct display *);
@@ -413,7 +409,9 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
       && (options->format == 'o'
          || options->format == 'x'
          || options->format == 't'
-         || options->format == 'z'))
+         || options->format == 'z'
+         || options->format == 'd'
+         || options->format == 'u'))
     {
       LONGEST val_long = unpack_long (type, valaddr);
       converted_float_bytes.resize (TYPE_LENGTH (type));
@@ -422,16 +420,29 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
       valaddr = converted_float_bytes.data ();
     }
 
-  switch (options->format)
+  /* Printing a non-float type as 'f' will interpret the data as if it were
+     of a floating-point type of the same length, if that exists.  Otherwise,
+     the data is printed as integer.  */
+  char format = options->format;
+  if (format == 'f' && TYPE_CODE (type) != TYPE_CODE_FLT)
+    {
+      type = float_type_from_length (type);
+      if (TYPE_CODE (type) != TYPE_CODE_FLT)
+        format = 0;
+    }
+
+  switch (format)
     {
     case 'o':
       print_octal_chars (stream, valaddr, len, byte_order);
       break;
+    case 'd':
+      print_decimal_chars (stream, valaddr, len, true, byte_order);
+      break;
     case 'u':
       print_decimal_chars (stream, valaddr, len, false, byte_order);
       break;
     case 0:
-    case 'd':
       if (TYPE_CODE (type) != TYPE_CODE_FLT)
        {
          print_decimal_chars (stream, valaddr, len, !TYPE_UNSIGNED (type),
@@ -440,7 +451,6 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
        }
       /* FALLTHROUGH */
     case 'f':
-      type = float_type_from_length (type);
       print_floating (valaddr, type, stream);
       break;
 
@@ -478,7 +488,7 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
       break;
 
     default:
-      error (_("Undefined output format \"%c\"."), options->format);
+      error (_("Undefined output format \"%c\"."), format);
     }
 }
 
@@ -1204,14 +1214,14 @@ print_command_1 (const char *exp, int voidprint)
 }
 
 static void
-print_command (char *exp, int from_tty)
+print_command (const char *exp, int from_tty)
 {
   print_command_1 (exp, 1);
 }
 
 /* Same as print, except it doesn't print void results.  */
 static void
-call_command (char *exp, int from_tty)
+call_command (const char *exp, int from_tty)
 {
   print_command_1 (exp, 0);
 }
@@ -1219,7 +1229,7 @@ call_command (char *exp, int from_tty)
 /* Implementation of the "output" command.  */
 
 static void
-output_command (char *exp, int from_tty)
+output_command (const char *exp, int from_tty)
 {
   output_command_const (exp, from_tty);
 }
@@ -1262,7 +1272,7 @@ output_command_const (const char *exp, int from_tty)
 }
 
 static void
-set_command (char *exp, int from_tty)
+set_command (const char *exp, int from_tty)
 {
   expression_up expr = parse_expression (exp);
 
@@ -1286,7 +1296,7 @@ set_command (char *exp, int from_tty)
 }
 
 static void
-sym_info (char *arg, int from_tty)
+info_symbol_command (const char *arg, int from_tty)
 {
   struct minimal_symbol *msymbol;
   struct objfile *objfile;
@@ -1314,7 +1324,7 @@ sym_info (char *arg, int from_tty)
            = lookup_minimal_symbol_by_pc_section (sect_addr, osect).minsym))
       {
        const char *obj_name, *mapped, *sec_name, *msym_name;
-       char *loc_string;
+       const char *loc_string;
        struct cleanup *old_chain;
 
        matches = 1;
@@ -1325,14 +1335,14 @@ sym_info (char *arg, int from_tty)
 
        /* Don't print the offset if it is zero.
           We assume there's no need to handle i18n of "sym + offset".  */
+       std::string string_holder;
        if (offset)
-         loc_string = xstrprintf ("%s + %u", msym_name, offset);
+         {
+           string_holder = string_printf ("%s + %u", msym_name, offset);
+           loc_string = string_holder.c_str ();
+         }
        else
-         loc_string = xstrprintf ("%s", msym_name);
-
-       /* Use a cleanup to free loc_string in case the user quits
-          a pagination request inside printf_filtered.  */
-       old_chain = make_cleanup (xfree, loc_string);
+         loc_string = msym_name;
 
        gdb_assert (osect->objfile && objfile_name (osect->objfile));
        obj_name = objfile_name (osect->objfile);
@@ -1370,8 +1380,6 @@ sym_info (char *arg, int from_tty)
            else
              printf_filtered (_("%s in section %s\n"),
                               loc_string, sec_name);
-
-       do_cleanups (old_chain);
       }
   }
   if (matches == 0)
@@ -1379,7 +1387,7 @@ sym_info (char *arg, int from_tty)
 }
 
 static void
-address_info (char *exp, int from_tty)
+info_address_command (const char *exp, int from_tty)
 {
   struct gdbarch *gdbarch;
   int regno;
@@ -1603,10 +1611,9 @@ address_info (char *exp, int from_tty)
 \f
 
 static void
-x_command (char *exp, int from_tty)
+x_command (const char *exp, int from_tty)
 {
   struct format_data fmt;
-  struct cleanup *old_chain;
   struct value *val;
 
   fmt.format = last_format ? last_format : 'x';
@@ -1631,7 +1638,7 @@ x_command (char *exp, int from_tty)
          repeated with Newline.  But don't clobber a user-defined
          command's definition.  */
       if (from_tty)
-       *exp = 0;
+       set_repeat_arguments ("");
       val = evaluate_expression (expr.get ());
       if (TYPE_IS_REFERENCE (value_type (val)))
        val = coerce_ref (val);
@@ -1687,7 +1694,7 @@ x_command (char *exp, int from_tty)
    Specify the expression.  */
 
 static void
-display_command (char *arg, int from_tty)
+display_command (const char *arg, int from_tty)
 {
   struct format_data fmt;
   struct display *newobj;
@@ -1795,7 +1802,7 @@ delete_display (struct display *display)
    ARGS.  DATA is passed unmodified to FUNCTION.  */
 
 static void
-map_display_numbers (char *args,
+map_display_numbers (const char *args,
                     void (*function) (struct display *,
                                       void *),
                     void *data)
@@ -1840,7 +1847,7 @@ do_delete_display (struct display *d, void *data)
 /* "undisplay" command.  */
 
 static void
-undisplay_command (char *args, int from_tty)
+undisplay_command (const char *args, int from_tty)
 {
   if (args == NULL)
     {
@@ -2046,7 +2053,7 @@ disable_current_display (void)
 }
 
 static void
-display_info (char *ignore, int from_tty)
+info_display_command (const char *ignore, int from_tty)
 {
   struct display *d;
 
@@ -2085,7 +2092,7 @@ do_enable_disable_display (struct display *d, void *data)
    commands.  ENABLE decides what to do.  */
 
 static void
-enable_disable_display_command (char *args, int from_tty, int enable)
+enable_disable_display_command (const char *args, int from_tty, int enable)
 {
   if (args == NULL)
     {
@@ -2102,7 +2109,7 @@ enable_disable_display_command (char *args, int from_tty, int enable)
 /* The "enable display" command.  */
 
 static void
-enable_display_command (char *args, int from_tty)
+enable_display_command (const char *args, int from_tty)
 {
   enable_disable_display_command (args, from_tty, 1);
 }
@@ -2110,7 +2117,7 @@ enable_display_command (char *args, int from_tty)
 /* The "disable display" command.  */
 
 static void
-disable_display_command (char *args, int from_tty)
+disable_display_command (const char *args, int from_tty)
 {
   enable_disable_display_command (args, from_tty, 0);
 }
@@ -2281,88 +2288,73 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
 }
 
 /* Subroutine of ui_printf to simplify it.
-   Print VALUE, a decimal floating point value, to STREAM using FORMAT.  */
+   Print VALUE, a floating point value, to STREAM using FORMAT.  */
 
 static void
-printf_decfloat (struct ui_file *stream, const char *format,
-                struct value *value)
+printf_floating (struct ui_file *stream, const char *format,
+                struct value *value, enum argclass argclass)
 {
-  const gdb_byte *param_ptr = value_contents (value);
-
-#if defined (PRINTF_HAS_DECFLOAT)
-  /* If we have native support for Decimal floating
-     printing, handle it here.  */
-  fprintf_filtered (stream, format, param_ptr);
-#else
-  /* 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.  */
-  const char *p;
-
   /* Parameter data.  */
   struct type *param_type = value_type (value);
   struct gdbarch *gdbarch = get_type_arch (param_type);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
-  /* DFP output data.  */
-  struct value *dfp_value = NULL;
-  gdb_byte *dfp_ptr;
-  int dfp_len = 16;
-  gdb_byte dec[16];
-  struct type *dfp_type = NULL;
-  char decstr[MAX_DECIMAL_STRING];
-
-  /* Points to the end of the string so that we can go back
-     and check for DFP length modifiers.  */
-  p = format + strlen (format);
-
-  /* Look for the float/double format specifier.  */
-  while (*p != 'f' && *p != 'e' && *p != 'E'
-        && *p != 'g' && *p != 'G')
-    p--;
-
-  /* Search for the '%' char and extract the size and type of
-     the output decimal value based on its modifiers
-     (%Hf, %Df, %DDf).  */
-  while (*--p != '%')
+  /* Determine target type corresponding to the format string.  */
+  struct type *fmt_type;
+  switch (argclass)
     {
-      if (*p == 'H')
-       {
-         dfp_len = 4;
-         dfp_type = builtin_type (gdbarch)->builtin_decfloat;
-       }
-      else if (*p == 'D' && *(p - 1) == 'D')
-       {
-         dfp_len = 16;
-         dfp_type = builtin_type (gdbarch)->builtin_declong;
-         p--;
-       }
-      else
-       {
-         dfp_len = 8;
-         dfp_type = builtin_type (gdbarch)->builtin_decdouble;
-       }
+      case double_arg:
+       fmt_type = builtin_type (gdbarch)->builtin_double;
+       break;
+      case long_double_arg:
+       fmt_type = builtin_type (gdbarch)->builtin_long_double;
+       break;
+      case dec32float_arg:
+       fmt_type = builtin_type (gdbarch)->builtin_decfloat;
+       break;
+      case dec64float_arg:
+       fmt_type = builtin_type (gdbarch)->builtin_decdouble;
+       break;
+      case dec128float_arg:
+       fmt_type = builtin_type (gdbarch)->builtin_declong;
+       break;
+      default:
+       gdb_assert_not_reached ("unexpected argument class");
     }
 
-  /* Conversion between different DFP types.  */
-  if (TYPE_CODE (param_type) == TYPE_CODE_DECFLOAT)
-    decimal_convert (param_ptr, TYPE_LENGTH (param_type),
-                    byte_order, dec, dfp_len, byte_order);
-  else
-    /* If this is a non-trivial conversion, just output 0.
-       A correct converted value can be displayed by explicitly
-       casting to a DFP type.  */
-    decimal_from_string (dec, dfp_len, byte_order, "0");
+  /* To match the traditional GDB behavior, the conversion is
+     done differently depending on the type of the parameter:
 
-  dfp_value = value_from_decfloat (dfp_type, dec);
+     - if the parameter has floating-point type, it's value
+       is converted to the target type;
 
-  dfp_ptr = (gdb_byte *) value_contents (dfp_value);
+     - otherwise, if the parameter has a type that is of the
+       same size as a built-in floating-point type, the value
+       bytes are interpreted as if they were of that type, and
+       then converted to the target type (this is not done for
+       decimal floating-point argument classes);
 
-  decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr);
+     - otherwise, if the source value has an integer value,
+       it's value is converted to the target type;
 
-  /* Print the DFP value.  */
-  fprintf_filtered (stream, "%s", decstr);
-#endif
+     - otherwise, an error is raised.
+
+     In either case, the result of the conversion is a byte buffer
+     formatted in the target format for the target type.  */
+
+  if (TYPE_CODE (fmt_type) == TYPE_CODE_FLT)
+    {
+      param_type = float_type_from_length (param_type);
+      if (param_type != value_type (value))
+       value = value_from_contents (param_type, value_contents (value));
+    }
+
+  value = value_cast (fmt_type, value);
+
+  /* Convert the value to a string and print it.  */
+  std::string str
+    = target_float_to_string (value_contents (value), fmt_type, format);
+  fputs_filtered (str.c_str (), stream);
 }
 
 /* Subroutine of ui_printf to simplify it.
@@ -2447,7 +2439,7 @@ ui_printf (const char *arg, struct ui_file *stream)
   if (s == 0)
     error_no_arg (_("format-control string and values to print"));
 
-  s = skip_spaces_const (s);
+  s = skip_spaces (s);
 
   /* A format string should follow, enveloped in double quotes.  */
   if (*s++ != '"')
@@ -2460,14 +2452,14 @@ ui_printf (const char *arg, struct ui_file *stream)
   if (*s++ != '"')
     error (_("Bad format string, non-terminated '\"'."));
   
-  s = skip_spaces_const (s);
+  s = skip_spaces (s);
 
   if (*s != ',' && *s != 0)
     error (_("Invalid argument syntax"));
 
   if (*s == ',')
     s++;
-  s = skip_spaces_const (s);
+  s = skip_spaces (s);
 
   {
     int nargs = 0;
@@ -2545,43 +2537,6 @@ ui_printf (const char *arg, struct ui_file *stream)
                                 obstack_base (&output));
            }
            break;
-         case double_arg:
-           {
-             struct type *type = value_type (val_args[i]);
-             DOUBLEST val;
-             int inv;
-
-             /* If format string wants a float, unchecked-convert the value
-                to floating point of the same size.  */
-             type = float_type_from_length (type);
-             val = unpack_double (type, value_contents (val_args[i]), &inv);
-             if (inv)
-               error (_("Invalid floating value found in program."));
-
-              fprintf_filtered (stream, current_substring, (double) val);
-             break;
-           }
-         case long_double_arg:
-#ifdef HAVE_LONG_DOUBLE
-           {
-             struct type *type = value_type (val_args[i]);
-             DOUBLEST val;
-             int inv;
-
-             /* If format string wants a float, unchecked-convert the value
-                to floating point of the same size.  */
-             type = float_type_from_length (type);
-             val = unpack_double (type, value_contents (val_args[i]), &inv);
-             if (inv)
-               error (_("Invalid floating value found in program."));
-
-             fprintf_filtered (stream, current_substring,
-                                (long double) val);
-             break;
-           }
-#else
-           error (_("long double not supported in printf"));
-#endif
          case long_long_arg:
 #ifdef PRINTF_HAS_LONG_LONG
            {
@@ -2607,9 +2562,14 @@ ui_printf (const char *arg, struct ui_file *stream)
               fprintf_filtered (stream, current_substring, val);
              break;
            }
-         /* Handles decimal floating values.  */
-         case decfloat_arg:
-           printf_decfloat (stream, current_substring, val_args[i]);
+         /* Handles floating-point values.  */
+         case double_arg:
+         case long_double_arg:
+         case dec32float_arg:
+         case dec64float_arg:
+         case dec128float_arg:
+           printf_floating (stream, current_substring, val_args[i],
+                            fpieces[fr].argclass);
            break;
          case ptr_arg:
            printf_pointer (stream, current_substring, val_args[i]);
@@ -2640,7 +2600,7 @@ ui_printf (const char *arg, struct ui_file *stream)
 /* Implement the "printf" command.  */
 
 static void
-printf_command (char *arg, int from_tty)
+printf_command (const char *arg, int from_tty)
 {
   ui_printf (arg, gdb_stdout);
   gdb_flush (gdb_stdout);
@@ -2649,7 +2609,7 @@ printf_command (char *arg, int from_tty)
 /* Implement the "eval" command.  */
 
 static void
-eval_command (char *arg, int from_tty)
+eval_command (const char *arg, int from_tty)
 {
   string_file stb;
 
@@ -2657,7 +2617,7 @@ eval_command (char *arg, int from_tty)
 
   std::string expanded = insert_user_defined_cmd_args (stb.c_str ());
 
-  execute_command (&expanded[0], from_tty);
+  execute_command (expanded.c_str (), from_tty);
 }
 
 void
@@ -2669,10 +2629,10 @@ _initialize_printcmd (void)
 
   observer_attach_free_objfile (clear_dangling_display_expressions);
 
-  add_info ("address", address_info,
+  add_info ("address", info_address_command,
            _("Describe where symbol SYM is stored."));
 
-  add_info ("symbol", sym_info, _("\
+  add_info ("symbol", info_symbol_command, _("\
 Describe what symbol is at location ADDR.\n\
 Only for symbols with fixed locations (global or static scope)."));
 
@@ -2696,7 +2656,7 @@ with this command or \"print\"."));
           _("Print line number and file of definition of variable."));
 #endif
 
-  add_info ("display", display_info, _("\
+  add_info ("display", info_display_command, _("\
 Expressions to display when program stops, with code numbers."));
 
   add_cmd ("undisplay", class_vars, undisplay_command, _("\
This page took 0.035454 seconds and 4 git commands to generate.