From: Doug Evans Date: Thu, 19 Aug 2010 13:33:15 +0000 (+0000) Subject: PR exp/11926 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d30f5e1f70ffa9fab08ccdacdba1bd6365d2511d;p=binutils-gdb.git 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. 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 580be2bfa72..b165bf8655d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2010-08-19 Doug Evans + + 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 * psymtab.c (map_symbol_filenames_psymtab): Call FUN with diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 030554c9823..663e778bd41 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -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; } diff --git a/gdb/jv-exp.y b/gdb/jv-exp.y index 8109e0c59a8..678a4341923 100644 --- a/gdb/jv-exp.y +++ b/gdb/jv-exp.y @@ -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; diff --git a/gdb/objc-exp.y b/gdb/objc-exp.y index 888bd201e4f..1f3d1e7fa7e 100644 --- a/gdb/objc-exp.y +++ b/gdb/objc-exp.y @@ -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; } diff --git a/gdb/p-exp.y b/gdb/p-exp.y index 2aec487463c..19f5cebb06a 100644 --- a/gdb/p-exp.y +++ b/gdb/p-exp.y @@ -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; } diff --git a/gdb/parse.c b/gdb/parse.c index 035572e65bc..18038ed0cd3 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -1038,8 +1038,6 @@ prefixify_subexp (struct expression *inexpr, return result; } -/* 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; +} /* Stuff for maintaining a stack of types. Currently just used by C, but probably useful for any language which declares its types "backwards". */ diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h index bb79ae13914..16255755498 100644 --- a/gdb/parser-defs.h +++ b/gdb/parser-defs.h @@ -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. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 3bc78101089..547deaf0345 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2010-08-19 Doug Evans + + 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 * gdb.base/default.exp (info set): Avoid full buffer error and force diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index 4c82ab31015..d377597c59b 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -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 diff --git a/gdb/testsuite/gdb.java/jv-print.exp b/gdb/testsuite/gdb.java/jv-print.exp index c78f7d76c2c..cdb598ce0a7 100644 --- a/gdb/testsuite/gdb.java/jv-print.exp +++ b/gdb/testsuite/gdb.java/jv-print.exp @@ -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 index 00000000000..2988d200f96 --- /dev/null +++ b/gdb/testsuite/gdb.objc/print.exp @@ -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 . + +# 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 index 00000000000..61f6d3744d0 --- /dev/null +++ b/gdb/testsuite/gdb.pascal/print.exp @@ -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 . + +# 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 index 00000000000..190c7153fb1 --- /dev/null +++ b/gdb/testsuite/lib/objc.exp @@ -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 . + +# 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; +}