PR exp/11926
authorDoug Evans <dje@google.com>
Thu, 19 Aug 2010 13:33:15 +0000 (13:33 +0000)
committerDoug Evans <dje@google.com>
Thu, 19 Aug 2010 13:33:15 +0000 (13:33 +0000)
* parser-defs.h (parse_float, parse_c_float): Declare.
* parse.c (parse_float, parse_c_float): New function.
* c-exp.y (parse_number): Call parse_c_float.
* objc-exp.y (parse_number): Ditto.
* p-exp.y (parse_number): Ditto.  Use ANSI/ISO-style definition.
* jv-exp.y (parse_number): Call parse_float, fix suffix handling.

testsuite/
* gdb.base/printcmds.exp (test_float_accepted): New function.
Move existing float tests there.  Add tests for floats with suffixes.
(test_float_rejected): New function.
* gdb.java/jv-print.exp (test_float_accepted): New function.
(test_float_rejected): New function.
* gdb.objc/print.exp: New file.
* gdb.pascal/print.exp: New file.
* lib/objc.exp: New file.

13 files changed:
gdb/ChangeLog
gdb/c-exp.y
gdb/jv-exp.y
gdb/objc-exp.y
gdb/p-exp.y
gdb/parse.c
gdb/parser-defs.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/printcmds.exp
gdb/testsuite/gdb.java/jv-print.exp
gdb/testsuite/gdb.objc/print.exp [new file with mode: 0644]
gdb/testsuite/gdb.pascal/print.exp [new file with mode: 0644]
gdb/testsuite/lib/objc.exp [new file with mode: 0644]

index 580be2bfa72a47caf4e902f345444c0dd5896d3f..b165bf8655d2827019e92eb867b2ea47b8cb93b8 100644 (file)
@@ -1,3 +1,13 @@
+2010-08-19  Doug Evans  <dje@google.com>
+
+       PR exp/11926
+       * parser-defs.h (parse_float, parse_c_float): Declare.
+       * parse.c (parse_float, parse_c_float): New function.
+       * c-exp.y (parse_number): Call parse_c_float.
+       * objc-exp.y (parse_number): Ditto.
+       * p-exp.y (parse_number): Ditto.  Use ANSI/ISO-style definition.
+       * jv-exp.y (parse_number): Call parse_float, fix suffix handling.
+
 2010-08-19  Joel Brobecker  <brobecker@adacore.com>
 
        * psymtab.c (map_symbol_filenames_psymtab): Call FUN with
index 030554c9823da302a790f21f1dfd6af562750b39..663e778bd412cad466be823d8aee8bc6fb532eb3 100644 (file)
@@ -1323,10 +1323,8 @@ parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere)
 
   if (parsed_float)
     {
-      /* It's a float since it contains a point or an exponent.  */
-      char *s;
-      int num; /* number of tokens scanned by scanf */
-      char saved_char;
+      const char *suffix;
+      int suffix_len;
 
       /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
          point.  Return DECFLOAT.  */
@@ -1364,35 +1362,10 @@ parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere)
          return DECFLOAT;
        }
 
-      s = malloc (len);
-      saved_char = p[len];
-      p[len] = 0;      /* null-terminate the token */
-      num = sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%s",
-                   &putithere->typed_val_float.dval, s);
-      p[len] = saved_char;     /* restore the input stream */
-
-      if (num == 1)
-       putithere->typed_val_float.type = 
-         parse_type->builtin_double;
-
-      if (num == 2 )
-       {
-         /* See if it has any float suffix: 'f' for float, 'l' for long 
-            double.  */
-         if (!strcasecmp (s, "f"))
-           putithere->typed_val_float.type = 
-             parse_type->builtin_float;
-         else if (!strcasecmp (s, "l"))
-           putithere->typed_val_float.type = 
-             parse_type->builtin_long_double;
-         else
-           {
-             free (s);
-             return ERROR;
-           }
-       }
-
-      free (s);
+      if (! parse_c_float (parse_gdbarch, p, len,
+                          &putithere->typed_val_float.dval,
+                          &putithere->typed_val_float.type))
+       return ERROR;
       return FLOAT;
     }
 
index 8109e0c59a8535fde7a98414e58aa12a6a7639e1..678a4341923f5ef3c51a12698089f4388f8ebc0b 100644 (file)
@@ -703,25 +703,28 @@ parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere)
 
   if (parsed_float)
     {
-      /* It's a float since it contains a point or an exponent.  */
-      char c;
-      int num = 0;     /* number of tokens scanned by scanf */
-      char saved_char = p[len];
-
-      p[len] = 0;      /* null-terminate the token */
-      num = sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%c",
-                   &putithere->typed_val_float.dval, &c);
-      p[len] = saved_char;     /* restore the input stream */
-      if (num != 1)            /* check scanf found ONLY a float ... */
+      const char *suffix;
+      int suffix_len;
+
+      if (! parse_float (p, len, &putithere->typed_val_float.dval, &suffix))
        return ERROR;
-      /* See if it has `f' or `d' suffix (float or double).  */
 
-      c = tolower (p[len - 1]);
+      suffix_len = p + len - suffix;
 
-      if (c == 'f' || c == 'F')
-       putithere->typed_val_float.type = parse_type->builtin_float;
-      else if (isdigit (c) || c == '.' || c == 'd' || c == 'D')
+      if (suffix_len == 0)
        putithere->typed_val_float.type = parse_type->builtin_double;
+      else if (suffix_len == 1)
+       {
+         /* See if it has `f' or `d' suffix (float or double).  */
+         if (tolower (*suffix) == 'f')
+           putithere->typed_val_float.type =
+             parse_type->builtin_float;
+         else if (tolower (*suffix) == 'd')
+           putithere->typed_val_float.type =
+             parse_type->builtin_double;
+         else
+           return ERROR;
+       }
       else
        return ERROR;
 
index 888bd201e4f4867df7ba21c5c8cfe36e26c56f89..1f3d1e7fa7e2372888910f86c74798ff6df82507 100644 (file)
@@ -1012,26 +1012,10 @@ parse_number (p, len, parsed_float, putithere)
 
   if (parsed_float)
     {
-      char c;
-
-      /* It's a float since it contains a point or an exponent.  */
-
-      sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%c",
-             &putithere->typed_val_float.dval, &c);
-
-      /* See if it has `f' or `l' suffix (float or long double).  */
-
-      c = tolower (p[len - 1]);
-
-      if (c == 'f')
-       putithere->typed_val_float.type = parse_type->builtin_float;
-      else if (c == 'l')
-       putithere->typed_val_float.type = parse_type->builtin_long_double;
-      else if (isdigit (c) || c == '.')
-       putithere->typed_val_float.type = parse_type->builtin_double;
-      else
+      if (! parse_c_float (parse_gdbarch, p, len,
+                          &putithere->typed_val_float.dval,
+                          &putithere->typed_val_float.type))
        return ERROR;
-
       return FLOAT;
     }
 
index 2aec487463c672c78d6db11f1d2c06a6b0c94151..19f5cebb06ac245c3d1f0650efd80b97cc9d0e2d 100644 (file)
@@ -791,11 +791,7 @@ name_not_typename :        NAME
 /*** Needs some error checking for the float case ***/
 
 static int
-parse_number (p, len, parsed_float, putithere)
-     char *p;
-     int len;
-     int parsed_float;
-     YYSTYPE *putithere;
+parse_number (char *p, int len, int parsed_float, YYSTYPE *putithere)
 {
   /* FIXME: Shouldn't these be unsigned?  We don't deal with negative values
      here, and we do kind of silly things like cast to unsigned.  */
@@ -820,30 +816,10 @@ parse_number (p, len, parsed_float, putithere)
 
   if (parsed_float)
     {
-      /* It's a float since it contains a point or an exponent.  */
-      char c;
-      int num = 0;     /* number of tokens scanned by scanf */
-      char saved_char = p[len];
-
-      p[len] = 0;      /* null-terminate the token */
-      num = sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%c",
-                   &putithere->typed_val_float.dval, &c);
-      p[len] = saved_char;     /* restore the input stream */
-      if (num != 1)            /* check scanf found ONLY a float ... */
+      if (! parse_c_float (parse_gdbarch, p, len,
+                          &putithere->typed_val_float.dval,
+                          &putithere->typed_val_float.type))
        return ERROR;
-      /* See if it has `f' or `l' suffix (float or long double).  */
-
-      c = tolower (p[len - 1]);
-
-      if (c == 'f')
-       putithere->typed_val_float.type = parse_type->builtin_float;
-      else if (c == 'l')
-       putithere->typed_val_float.type = parse_type->builtin_long_double;
-      else if (isdigit (c) || c == '.')
-       putithere->typed_val_float.type = parse_type->builtin_double;
-      else
-       return ERROR;
-
       return FLOAT;
     }
 
index 035572e65bc1b522ca22bf8cdb8e8a7da577cf7c..18038ed0cd3fc671a8a529c947f16a226781627e 100644 (file)
@@ -1038,8 +1038,6 @@ prefixify_subexp (struct expression *inexpr,
   return result;
 }
 \f
-/* This page contains the two entry points to this file.  */
-
 /* Read an expression from the string *STRINGPTR points to,
    parse it, and return a pointer to a  struct expression  that we malloc.
    Use block BLOCK as the lexical context for variable names;
@@ -1252,6 +1250,73 @@ void
 null_post_parser (struct expression **exp, int void_context_p)
 {
 }
+
+/* Parse floating point value P of length LEN.
+   Return 0 (false) if invalid, 1 (true) if valid.
+   The successfully parsed number is stored in D.
+   *SUFFIX points to the suffix of the number in P.
+
+   NOTE: This accepts the floating point syntax that sscanf accepts.  */
+
+int
+parse_float (const char *p, int len, DOUBLEST *d, const char **suffix)
+{
+  char *copy;
+  char *s;
+  int n, num;
+
+  copy = xmalloc (len + 1);
+  memcpy (copy, p, len);
+  copy[len] = 0;
+
+  num = sscanf (copy, "%" DOUBLEST_SCAN_FORMAT "%n", d, &n);
+  xfree (copy);
+
+  /* The sscanf man page suggests not making any assumptions on the effect
+     of %n on the result, so we don't.
+     That is why we simply test num == 0.  */
+  if (num == 0)
+    return 0;
+
+  *suffix = p + n;
+  return 1;
+}
+
+/* Parse floating point value P of length LEN, using the C syntax for floats.
+   Return 0 (false) if invalid, 1 (true) if valid.
+   The successfully parsed number is stored in *D.
+   Its type is taken from builtin_type (gdbarch) and is stored in *T.  */
+
+int
+parse_c_float (struct gdbarch *gdbarch, const char *p, int len,
+              DOUBLEST *d, struct type **t)
+{
+  const char *suffix;
+  int suffix_len;
+  const struct builtin_type *builtin_types = builtin_type (gdbarch);
+
+  if (! parse_float (p, len, d, &suffix))
+    return 0;
+
+  suffix_len = p + len - suffix;
+
+  if (suffix_len == 0)
+    *t = builtin_types->builtin_double;
+  else if (suffix_len == 1)
+    {
+      /* Handle suffixes: 'f' for float, 'l' for long double.  */
+      if (tolower (*suffix) == 'f')
+       *t = builtin_types->builtin_float;
+      else if (tolower (*suffix) == 'l')
+       *t = builtin_types->builtin_long_double;
+      else
+       return 0;
+    }
+  else
+    return 0;
+
+  return 1;
+}
 \f
 /* Stuff for maintaining a stack of types.  Currently just used by C, but
    probably useful for any language which declares its types "backwards".  */
index bb79ae13914081036652f633b6687024cebb4aa8..16255755498cb4a8f1a9a3eba5bce9a8593e4d86 100644 (file)
@@ -204,6 +204,12 @@ extern struct type *follow_types (struct type *);
 
 extern void null_post_parser (struct expression **, int);
 
+extern int parse_float (const char *p, int len, DOUBLEST *d,
+                       const char **suffix);
+
+extern int parse_c_float (struct gdbarch *gdbarch, const char *p, int len,
+                         DOUBLEST *d, struct type **t);
+
 /* During parsing of a C expression, the pointer to the next character
    is in this variable.  */
 
index 3bc7810108978ba9e5f53bf15ad55cc8b94057a7..547deaf0345a02b6d2663896b74302abe6bf5f5b 100644 (file)
@@ -1,3 +1,15 @@
+2010-08-19  Doug Evans  <dje@google.com>
+
+       PR exp/11926
+       * gdb.base/printcmds.exp (test_float_accepted): New function.
+       Move existing float tests there.  Add tests for floats with suffixes.
+       (test_float_rejected): New function.
+       * gdb.java/jv-print.exp (test_float_accepted): New function.
+       (test_float_rejected): New function.
+       * gdb.objc/print.exp: New file.
+       * gdb.pascal/print.exp: New file.
+       * lib/objc.exp: New file.
+
 2010-08-19  Pierre Muller  <muller@ics.u-strasbg.fr>
 
        * gdb.base/default.exp (info set): Avoid full buffer error and force
index 4c82ab31015f67a9742516b981ad1307d4e61141..d377597c59baa0b234979b629c4f0afec4e0c5af 100644 (file)
@@ -102,17 +102,6 @@ proc test_integer_literals_rejected {} {
 
     test_print_reject "p DEADBEEF"
 
-    # Gdb currently fails this test for all configurations.  The C
-    # lexer thinks that 123DEADBEEF is a floating point number, but
-    # then fails to notice that atof() only eats the 123 part.
-    # FIXME:  This should be put into PRMS.
-    # Fixed, 4/25/97, by Bob Manson.
-
-    test_print_reject "p 123DEADBEEF"
-    test_print_reject "p 123foobar.bazfoo3"
-    test_print_reject "p 123EEEEEEEEEEEEEEEEE33333k333"
-    gdb_test "p 123.4+56.7" "180.(099\[0-9]*|100\[0-9\]*)" "check for floating addition"
-
     # Test various octal values.
 
     test_print_reject "p 09" 
@@ -129,6 +118,36 @@ proc test_integer_literals_rejected {} {
     test_print_reject "p 0b12" 
 }
 
+proc test_float_accepted {} {
+    # This test is useful to catch successful parsing of the first fp value.
+    gdb_test "p 123.4+56.7" " = 180.(099\[0-9]*|100\[0-9\]*)" "check for floating addition"
+
+    # Test all the suffixes (including no suffix).
+    gdb_test "p 1." " = 1"
+    gdb_test "p 1.5" " = 1.5"
+    gdb_test "p 1.f" " = 1"
+    gdb_test "p 1.5f" " = 1.5"
+    gdb_test "p 1.l" " = 1"
+    gdb_test "p 1.5l" " = 1.5"
+}
+
+proc test_float_rejected {} {
+    # Gdb use to fail this test for all configurations.  The C
+    # lexer thought that 123DEADBEEF was a floating point number, but
+    # then failed to notice that atof() only eats the 123 part.
+    # Fixed, 4/25/97, by Bob Manson.
+    test_print_reject "p 123DEADBEEF"
+
+    test_print_reject "p 123foobar.bazfoo3"
+    test_print_reject "p 123EEEEEEEEEEEEEEEEE33333k333"
+    test_print_reject "p 0x1.1"
+
+    # Test bad suffixes.
+    test_print_reject "p 1.1x"
+    test_print_reject "p 1.1ff"
+    test_print_reject "p 1.1ll"
+}
+
 proc test_print_all_chars {} {
     global gdb_prompt
 
@@ -781,6 +800,8 @@ if ![runto_main] then {
 
 test_integer_literals_accepted
 test_integer_literals_rejected
+test_float_accepted
+test_float_rejected
 test_character_literals_accepted
 test_print_all_chars
 test_print_repeats_10
index c78f7d76c2c78dff903fb89e39368c0247bc5ed0..cdb598ce0a798b247108caea60512f36a76e06db 100644 (file)
@@ -97,6 +97,28 @@ proc test_integer_literals_rejected {} {
     test_print_reject "p 0xAG" 
 }
 
+proc test_float_accepted {} {
+    # Test parsing of fp value with legit text following.
+    gdb_test "p 1234.5+1" " = 1235.5" "check fp + text"
+
+    # Test all the suffixes (including no suffix).
+    gdb_test "p 1." " = 1"
+    gdb_test "p 1.5" " = 1.5"
+    gdb_test "p 1.f" " = 1"
+    gdb_test "p 1.5f" " = 1.5"
+    gdb_test "p 1.d" " = 1"
+    gdb_test "p 1.5d" " = 1.5"
+}
+
+proc test_float_rejected {} {
+    # Test invalid fp values.
+    test_print_reject "p 0x1.1"
+
+    # Test bad suffixes.
+    test_print_reject "p 1.1x"
+    test_print_reject "p 1.1ff"
+    test_print_reject "p 1.1dd"
+}
 
 
 # Start with a fresh gdb.
@@ -117,6 +139,8 @@ if [set_lang_java] then {
     test_integer_literals_accepted
     test_character_literals_accepted
     test_integer_literals_rejected
+    test_float_accepted
+    test_float_rejected
 } else {
     warning "Java print command tests suppressed"
 }
diff --git a/gdb/testsuite/gdb.objc/print.exp b/gdb/testsuite/gdb.objc/print.exp
new file mode 100644 (file)
index 0000000..2988d20
--- /dev/null
@@ -0,0 +1,68 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@gnu.org
+
+# Test printing of various values.
+# NOTE: The tests here intentionally do not require an objc compiler.
+
+if $tracelevel {
+    strace $tracelevel
+}
+
+load_lib "objc.exp"
+
+proc test_float_accepted {} {
+    # Test parsing of fp value with legit text following.
+    gdb_test "p 1234.5+1" " = 1235.5" "check fp + text"
+
+    # Test all the suffixes (including no suffix).
+    gdb_test "p 1." " = 1"
+    gdb_test "p 1.5" " = 1.5"
+    setup_kfail gdb/11925 "*-*-*"
+    gdb_test "p 1.f" " = 1"
+    setup_kfail gdb/11925 "*-*-*"
+    gdb_test "p 1.5f" " = 1.5"
+    setup_kfail gdb/11925 "*-*-*"
+    gdb_test "p 1.l" " = 1"
+    setup_kfail gdb/11925 "*-*-*"
+    gdb_test "p 1.5l" " = 1.5"
+}
+
+proc test_float_rejected {} {
+    # Test invalid fp values.
+    test_print_reject "p 0x1.1"
+
+    # Test bad suffixes.
+    test_print_reject "p 1.1x"
+    test_print_reject "p 1.1ff"
+    test_print_reject "p 1.1ll"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+if [set_lang_objc] {
+    test_float_accepted
+    test_float_rejected
+} else {
+    warning "Objective-c print tests suppressed"
+}
diff --git a/gdb/testsuite/gdb.pascal/print.exp b/gdb/testsuite/gdb.pascal/print.exp
new file mode 100644 (file)
index 0000000..61f6d37
--- /dev/null
@@ -0,0 +1,64 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@gnu.org
+
+# Test printing of various values.
+# NOTE: The tests here intentionally do not require a pascal compiler.
+
+if $tracelevel {
+    strace $tracelevel
+}
+
+load_lib "pascal.exp"
+
+proc test_float_accepted {} {
+    # Test parsing of fp value with legit text following.
+    gdb_test "p 1234.5+1" " = 1235.5" "check fp + text"
+
+    # Test all the suffixes (including no suffix).
+    gdb_test "p 1." " = 1"
+    gdb_test "p 1.5" " = 1.5"
+    gdb_test "p 1.f" " = 1"
+    gdb_test "p 1.5f" " = 1.5"
+    gdb_test "p 1.l" " = 1"
+    gdb_test "p 1.5l" " = 1.5"
+}
+
+proc test_float_rejected {} {
+    # Test invalid fp values.
+    test_print_reject "p 0x1.1"
+
+    # Test bad suffixes.
+    test_print_reject "p 1.1x"
+    test_print_reject "p 1.1ff"
+    test_print_reject "p 1.1ll"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+if [set_lang_pascal] {
+    test_float_accepted
+    test_float_rejected
+} else {
+    warning "Pascal print tests suppressed"
+}
diff --git a/gdb/testsuite/lib/objc.exp b/gdb/testsuite/lib/objc.exp
new file mode 100644 (file)
index 0000000..190c715
--- /dev/null
@@ -0,0 +1,30 @@
+# This test code is part of GDB, the GNU debugger.
+
+# Copyright 2010 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Auxiliary function to set the language to fortran.
+# The result is 1 (true) for success, 0 (false) for failure.
+
+proc set_lang_objc {} {
+    if [gdb_test_no_output "set language objective-c"] {
+       return 0
+    }
+    if [gdb_test "show language" ".* source language is \"objective-c\"." \
+          "set language to \"objective-c\""] {
+       return 0
+    }
+    return 1;
+}