From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26272 invoked by alias); 15 Sep 2005 08:35:27 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 26212 invoked by uid 22791); 15 Sep 2005 08:35:12 -0000 Received: from ausmtp02.au.ibm.com (HELO ausmtp02.au.ibm.com) (202.81.18.187) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Thu, 15 Sep 2005 08:35:12 +0000 Received: from sd0112e0.au.ibm.com (d23rh903.au.ibm.com [202.81.18.201]) by ausmtp02.au.ibm.com (8.12.10/8.12.10) with ESMTP id j8F8TfAj072874 for ; Thu, 15 Sep 2005 18:29:43 +1000 Received: from d23av03.au.ibm.com (d23av03.au.ibm.com [9.190.250.244]) by sd0112e0.au.ibm.com (8.12.10/NCO/VERS6.7) with ESMTP id j8F8bfGF094652 for ; Thu, 15 Sep 2005 18:37:43 +1000 Received: from d23av03.au.ibm.com (loopback [127.0.0.1]) by d23av03.au.ibm.com (8.12.11/8.13.3) with ESMTP id j8F8Ydf1019137 for ; Thu, 15 Sep 2005 18:34:39 +1000 Received: from [9.181.133.252] ([9.181.133.252]) by d23av03.au.ibm.com (8.12.11/8.12.11) with ESMTP id j8F8YbUO019055 for ; Thu, 15 Sep 2005 18:34:38 +1000 Date: Thu, 15 Sep 2005 08:35:00 -0000 From: Wu Zhou To: gdb-patches@sources.redhat.com Subject: Re: [RFC] A patch for parse_number (c-exp.y) to recognize 1.25f In-Reply-To: Message-ID: References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-SW-Source: 2005-09/txt/msg00109.txt.bz2 > To fix this kind of false-negative and not to introduce false-positive, I > am thinking of changing the second format in sscanf to "%s" (string). > Thus the parser could get the trailing characters following the float. > Then we can add some code to parse them to eliminate false-positive. Any > points on this idea? Is it worthwhile to do this? Please comment. TIA. Following the above point, I coded another patch. It can fix the problem and don't introduce any false-positive mentioned above. I had also coded a testcase for that. Had tested on i386. With the patched GDB, it reported 18 PASS; with the original GDB, it report 9 PASS and 9 FAIL (all of these failure is due to the fact that GDB can't handle the suffix following the float constants.) IMHO, there are yet another advantage for this patch: it is easy to be extended to handle other suffixes, such "df" for _Decimal32, "dd" for _Decimal64 and "dl" for _Decimal128, all of which are described in IEEE 754R for decimal floating point. Here goes the patch and the testcase. 2005-09-15 Wu Zhou * c-exp.y (parse-number): Modify the float parsing logic to let it recognize the suffix. Index: c-exp.y =================================================================== RCS file: /cvs/src/src/gdb/c-exp.y,v retrieving revision 1.29 diff -c -3 -p -r1.29 c-exp.y *** c-exp.y 8 Mar 2005 14:35:17 -0000 1.29 --- c-exp.y 15 Sep 2005 08:26:36 -0000 *************** parse_number (p, len, parsed_float, puti *** 1074,1116 **** 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 */ if (sizeof (putithere->typed_val_float.dval) <= sizeof (float)) ! num = sscanf (p, "%g%c", (float *) &putithere->typed_val_float.dval,&c); else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double)) ! num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval,&c); else { #ifdef SCANF_HAS_LONG_DOUBLE ! num = sscanf (p, "%Lg%c", &putithere->typed_val_float.dval,&c); #else /* Scan it into a double, then assign it to the long double. This at least wins with values representable in the range of doubles. */ double temp; ! num = sscanf (p, "%lg%c", &temp,&c); putithere->typed_val_float.dval = temp; #endif } p[len] = saved_char; /* restore the input stream */ ! if (num != 1) /* check scanf found ONLY a float ... */ ! 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 = builtin_type (current_gdbarch)->builtin_float; ! else if (c == 'l') ! putithere->typed_val_float.type = builtin_type (current_gdbarch)->builtin_long_double; ! else if (isdigit (c) || c == '.') ! putithere->typed_val_float.type = builtin_type (current_gdbarch)->builtin_double; ! else ! return ERROR; return FLOAT; } --- 1074,1121 ---- if (parsed_float) { /* It's a float since it contains a point or an exponent. */ ! char *s = malloc (len); int num = 0; /* number of tokens scanned by scanf */ char saved_char = p[len]; p[len] = 0; /* null-terminate the token */ + if (sizeof (putithere->typed_val_float.dval) <= sizeof (float)) ! num = sscanf (p, "%g%s", (float *) &putithere->typed_val_float.dval,s); else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double)) ! num = sscanf (p, "%lg%s", (double *) &putithere->typed_val_float.dval,s); else { #ifdef SCANF_HAS_LONG_DOUBLE ! num = sscanf (p, "%Lg%s", &putithere->typed_val_float.dval,s); #else /* Scan it into a double, then assign it to the long double. This at least wins with values representable in the range of doubles. */ double temp; ! num = sscanf (p, "%lg%s", &temp,s); putithere->typed_val_float.dval = temp; #endif } p[len] = saved_char; /* restore the input stream */ ! ! if (num == 1) ! putithere->typed_val_float.type = builtin_type (current_gdbarch) ! ->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 = builtin_type (current_gdbarch) ! ->builtin_float; ! else if (!strcasecmp (s, "l")) ! putithere->typed_val_float.type = builtin_type (current_gdbarch) ! ->builtin_long_double; ! else ! return ERROR; ! } return FLOAT; } 2005-09-15 Wu Zhou * bfp-test.c: New file. * bfp-test.exp: New testcase. Index: gdb.base/bfp-test.c =================================================================== RCS file: gdb.base/bfp-test.c diff -N gdb.base/bfp-test.c *** /dev/null 1 Jan 1970 00:00:00 -0000 --- gdb.base/bfp-test.c 15 Sep 2005 06:49:51 -0000 *************** *** 0 **** --- 1,15 ---- + #include + #include + + float b32; + double b64; + long double b128; + + int main() + { + b32 = 1.5f; + b64 = 2.25; + b128 = 3.375l; + + return 0; + } Index: gdb.base/bfp-test.exp =================================================================== RCS file: gdb.base/bfp-test.exp diff -N gdb.base/bfp-test.exp *** /dev/null 1 Jan 1970 00:00:00 -0000 --- gdb.base/bfp-test.exp 15 Sep 2005 06:49:51 -0000 *************** *** 0 **** --- 1,109 ---- + # Copyright 2005 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 2 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, write to the Free Software + # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + # This file is part of the gdb testsuite. It is intended to test that + # gdb could correctly handle floating point constant with a suffix. + + if $tracelevel { + strace $tracelevel + } + + set testfile "bfp-test" + set srcfile ${testfile}.c + set binfile ${objdir}/${subdir}/${testfile} + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "Couldn't compile ${srcfile}" + return -1 + } + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + + if ![runto_main] then { + perror "couldn't run to breakpoint" + continue + } + + # Run to the breakpoint at return. + set bp_location [gdb_get_line_number "return"] + gdb_test "break $bp_location" \ + "Breakpoint.*at.* file .*$srcfile, line $bp_location\\." \ + "breakpoint at return" + gdb_test "continue" \ + "Continuing\\..*Breakpoint.*" \ + "continue to breakpoint" + + # Print the original value of b32, b64 and b128. + gdb_test "print b32" ".*1 = 1\.5.*" "The original value of b32 is 1.5" + gdb_test "print b64" ".*2 = 2\.25.*" "The original value of b64 is 2.25" + gdb_test "print b128" ".*3 = 3\.375.*" "The original value of b128 is 3.375" + + # Test that gdb could correctly recognize float constant expression with a suffix. + gdb_test "print b32=-1.5f" ".*4 = -1\.5.*" "Try to change b32 to -1.5 with 'print b32=-1.5f'" + gdb_test "print b64=-2.25f" ".*5 = -2\.25.*" "Try to change b64 to -2.25 with 'print b64=-2.25f'" + gdb_test "print b128=-3.375l" ".*6 = -3\.375.*" "Try to change b128 to -3.375 with 'print b128=-3.375l'" + + # Test that gdb could handle the above correctly with "set var" command. + send_gdb "set var b32=10.5f\n" + gdb_expect { + -re "$gdb_prompt $" { pass "set var b32=10.5f" } + -re "Invalid number" { fail "do not recognize 10.5f" } + timeout {fail "set var b32=10.5f" } + } + send_gdb "set var b64=20.25f\n" + gdb_expect { + -re "$gdb_prompt $" { pass "set var b64=20.25f" } + -re "Invalid number" { fail "do not recognize 20.25f" } + timeout {fail "set var b64=20.25f" } + } + send_gdb "set var b128=30.375f\n" + gdb_expect { + -re "$gdb_prompt $" { pass "set var b128=30.375f" } + -re "Invalid number" { fail "do not recognize 30.375f" } + timeout {fail "set var b128=30.375f" } + } + gdb_test "print b32" ".*7 = 10\.5.*" "The value of b32 is changed to 10.5" + gdb_test "print b64" ".*8 = 20\.25.*" "The value of b64 is changed to 20.25" + gdb_test "print b128" ".*9 = 30\.375.*" "The value of b128 is changed to 30.375" + + # Test that gdb could handle invalid suffix correctly. + send_gdb "set var b32=100.5a\n" + gdb_expect { + -re "$gdb_prompt $" { fail "don't report error on 100.5a" } + -re "Invalid number" { pass "100.5a is invalid number" } + timeout {fail "set var b32=100.5a" } + } + send_gdb "set var b64=200.25x\n" + gdb_expect { + -re "$gdb_prompt $" { fail "don't report error on 200.25x" } + -re "Invalid number" { pass "200.25x is invalid number" } + timeout {fail "set var b64=200.25x" } + } + send_gdb "set var b128=300.375fl\n" + gdb_expect { + -re "$gdb_prompt $" { fail "don't report error on 300.375fl" } + -re "Invalid number" { pass "300.375fl is invalid number" } + timeout {fail "set var b128=300.375fl" } + } + send_gdb "set var b32=300.375fff\n" + gdb_expect { + -re "$gdb_prompt $" { fail "don't report error on 300.375fff" } + -re "Invalid number" { pass "300.375fff is invalid number" } + timeout {fail "set var b128=300.375fff" } + } + Regards - Wu Zhou