* sscanf("-1", "%d", &i) fails, returns 0
@ 2002-11-08 13:32 Douglas Gilbert
2002-11-08 19:22 ` [PATCH] " Randy.Dunlap
0 siblings, 1 reply; 12+ messages in thread
From: Douglas Gilbert @ 2002-11-08 13:32 UTC (permalink / raw)
To: linux-kernel
In lk 2.5.46-bk3 the expression in the subject line
fails to write into "i" and returns 0. Drop the minus
sign and it works.
Doug Gilbert
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-08 13:32 sscanf("-1", "%d", &i) fails, returns 0 Douglas Gilbert
@ 2002-11-08 19:22 ` Randy.Dunlap
2002-11-08 19:41 ` Richard B. Johnson
0 siblings, 1 reply; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-08 19:22 UTC (permalink / raw)
To: Douglas Gilbert; +Cc: linux-kernel, torvalds
On Sat, 9 Nov 2002, Douglas Gilbert wrote:
| In lk 2.5.46-bk3 the expression in the subject line
| fails to write into "i" and returns 0. Drop the minus
| sign and it works.
Here's an unobstrusive patch to correct that.
Please apply.
--
~Randy
--- ./lib/vsprintf.c%signed Mon Nov 4 14:30:49 2002
+++ ./lib/vsprintf.c Fri Nov 8 11:20:03 2002
@@ -517,6 +517,7 @@
{
const char *str = buf;
char *next;
+ char *dig;
int num = 0;
int qualifier;
int base;
@@ -638,12 +639,13 @@
while (isspace(*str))
str++;
- if (!*str
- || (base == 16 && !isxdigit(*str))
- || (base == 10 && !isdigit(*str))
- || (base == 8 && (!isdigit(*str) || *str > '7'))
- || (base == 0 && !isdigit(*str)))
- break;
+ dig = (*str == '-') ? (str + 1) : str;
+ if (!*dig
+ || (base == 16 && !isxdigit(*dig))
+ || (base == 10 && !isdigit(*dig))
+ || (base == 8 && (!isdigit(*dig) || *dig > '7'))
+ || (base == 0 && !isdigit(*dig)))
+ break;
switch(qualifier) {
case 'h':
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-08 19:22 ` [PATCH] " Randy.Dunlap
@ 2002-11-08 19:41 ` Richard B. Johnson
2002-11-08 19:59 ` Randy.Dunlap
0 siblings, 1 reply; 12+ messages in thread
From: Richard B. Johnson @ 2002-11-08 19:41 UTC (permalink / raw)
To: Randy.Dunlap; +Cc: Douglas Gilbert, linux-kernel, torvalds
On Fri, 8 Nov 2002, Randy.Dunlap wrote:
> On Sat, 9 Nov 2002, Douglas Gilbert wrote:
>
> | In lk 2.5.46-bk3 the expression in the subject line
> | fails to write into "i" and returns 0. Drop the minus
> | sign and it works.
>
> Here's an unobstrusive patch to correct that.
> Please apply.
>
> --
> ~Randy
>
>
>
> --- ./lib/vsprintf.c%signed Mon Nov 4 14:30:49 2002
> +++ ./lib/vsprintf.c Fri Nov 8 11:20:03 2002
> @@ -517,6 +517,7 @@
> {
> const char *str = buf;
> char *next;
> + char *dig;
> int num = 0;
> int qualifier;
> int base;
> @@ -638,12 +639,13 @@
> while (isspace(*str))
> str++;
>
> - if (!*str
> - || (base == 16 && !isxdigit(*str))
> - || (base == 10 && !isdigit(*str))
> - || (base == 8 && (!isdigit(*str) || *str > '7'))
> - || (base == 0 && !isdigit(*str)))
> - break;
> + dig = (*str == '-') ? (str + 1) : str;
> + if (!*dig
> + || (base == 16 && !isxdigit(*dig))
> + || (base == 10 && !isdigit(*dig))
> + || (base == 8 && (!isdigit(*dig) || *dig > '7'))
> + || (base == 0 && !isdigit(*dig)))
> + break;
>
> switch(qualifier) {
> case 'h':
>
> -
I was thinking that if anybody ever had to change any of this
stuff, it might be a good idea to do the indirection only once?
All those "splats" over and over again are costly.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Bush : The Fourth Reich of America
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-08 19:41 ` Richard B. Johnson
@ 2002-11-08 19:59 ` Randy.Dunlap
2002-11-08 20:19 ` Linus Torvalds
2002-11-08 20:23 ` Richard B. Johnson
0 siblings, 2 replies; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-08 19:59 UTC (permalink / raw)
To: Richard B. Johnson; +Cc: Douglas Gilbert, linux-kernel, torvalds
On Fri, 8 Nov 2002, Richard B. Johnson wrote:
| On Fri, 8 Nov 2002, Randy.Dunlap wrote:
|
| > On Sat, 9 Nov 2002, Douglas Gilbert wrote:
| >
| > | In lk 2.5.46-bk3 the expression in the subject line
| > | fails to write into "i" and returns 0. Drop the minus
| > | sign and it works.
| >
| > Here's an unobstrusive patch to correct that.
| > Please apply.
| >
| > --
| > ~Randy
| > -
|
| I was thinking that if anybody ever had to change any of this
| stuff, it might be a good idea to do the indirection only once?
| All those "splats" over and over again are costly.
Sure, it looks cleaner that way, although gcc has already put <*dig>
in a local register; i.e., it's not pulled from memory for each test.
Here's a (tested) version that does that.
--
~Randy
--- ./lib/vsprintf.c%signed Mon Nov 4 14:30:49 2002
+++ ./lib/vsprintf.c Fri Nov 8 12:03:15 2002
@@ -517,6 +517,7 @@
{
const char *str = buf;
char *next;
+ char *dig, onedig;
int num = 0;
int qualifier;
int base;
@@ -638,12 +639,14 @@
while (isspace(*str))
str++;
- if (!*str
- || (base == 16 && !isxdigit(*str))
- || (base == 10 && !isdigit(*str))
- || (base == 8 && (!isdigit(*str) || *str > '7'))
- || (base == 0 && !isdigit(*str)))
- break;
+ dig = (*str == '-') ? (str + 1) : str;
+ onedig = *dig;
+ if (!onedig
+ || (base == 16 && !isxdigit(onedig))
+ || (base == 10 && !isdigit(onedig))
+ || (base == 8 && (!isdigit(onedig) || onedig > '7'))
+ || (base == 0 && !isdigit(onedig)))
+ break;
switch(qualifier) {
case 'h':
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-08 19:59 ` Randy.Dunlap
@ 2002-11-08 20:19 ` Linus Torvalds
2002-11-08 22:09 ` Randy.Dunlap
2002-11-08 20:23 ` Richard B. Johnson
1 sibling, 1 reply; 12+ messages in thread
From: Linus Torvalds @ 2002-11-08 20:19 UTC (permalink / raw)
To: Randy.Dunlap; +Cc: Richard B. Johnson, Douglas Gilbert, linux-kernel
On Fri, 8 Nov 2002, Randy.Dunlap wrote:
?
> Sure, it looks cleaner that way, although gcc has already put <*dig>
> in a local register; i.e., it's not pulled from memory for each test.
> Here's a (tested) version that does that.
Why do you have that "dig" pointer at all? It's not really used.
Why not just do
+ char digit;
...
+ digit = str;
+ if (digit == '-')
+ digit = str[1];
(and maybe it should also test for whether signed stuff is even alloed or
not, ie maybe the test should be "if (is_sign && digit == '-')" instead)
Linus
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-08 19:59 ` Randy.Dunlap
2002-11-08 20:19 ` Linus Torvalds
@ 2002-11-08 20:23 ` Richard B. Johnson
1 sibling, 0 replies; 12+ messages in thread
From: Richard B. Johnson @ 2002-11-08 20:23 UTC (permalink / raw)
To: Randy.Dunlap; +Cc: Douglas Gilbert, linux-kernel, torvalds
On Fri, 8 Nov 2002, Randy.Dunlap wrote:
> On Fri, 8 Nov 2002, Richard B. Johnson wrote:
>
> | On Fri, 8 Nov 2002, Randy.Dunlap wrote:
> |
> | > On Sat, 9 Nov 2002, Douglas Gilbert wrote:
> | >
> | > | In lk 2.5.46-bk3 the expression in the subject line
> | > | fails to write into "i" and returns 0. Drop the minus
> | > | sign and it works.
> | >
> | > Here's an unobstrusive patch to correct that.
> | > Please apply.
> | >
> | > --
> | > ~Randy
> | > -
> |
> | I was thinking that if anybody ever had to change any of this
> | stuff, it might be a good idea to do the indirection only once?
> | All those "splats" over and over again are costly.
>
> Sure, it looks cleaner that way, although gcc has already put <*dig>
> in a local register; i.e., it's not pulled from memory for each test.
> Here's a (tested) version that does that.
>
> --
> ~Randy
>
>
>
> --- ./lib/vsprintf.c%signed Mon Nov 4 14:30:49 2002
> +++ ./lib/vsprintf.c Fri Nov 8 12:03:15 2002
> @@ -517,6 +517,7 @@
> {
> const char *str = buf;
> char *next;
> + char *dig, onedig;
> int num = 0;
> int qualifier;
> int base;
> @@ -638,12 +639,14 @@
> while (isspace(*str))
> str++;
>
> - if (!*str
> - || (base == 16 && !isxdigit(*str))
> - || (base == 10 && !isdigit(*str))
> - || (base == 8 && (!isdigit(*str) || *str > '7'))
> - || (base == 0 && !isdigit(*str)))
> - break;
> + dig = (*str == '-') ? (str + 1) : str;
> + onedig = *dig;
> + if (!onedig
> + || (base == 16 && !isxdigit(onedig))
> + || (base == 10 && !isdigit(onedig))
> + || (base == 8 && (!isdigit(onedig) || onedig > '7'))
> + || (base == 0 && !isdigit(onedig)))
> + break;
>
> switch(qualifier) {
> case 'h':
>
I like it much better.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Bush : The Fourth Reich of America
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-08 20:19 ` Linus Torvalds
@ 2002-11-08 22:09 ` Randy.Dunlap
2002-11-10 13:41 ` Henning P. Schmiedehausen
0 siblings, 1 reply; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-08 22:09 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Richard B. Johnson, Douglas Gilbert, linux-kernel
On Fri, 8 Nov 2002, Linus Torvalds wrote:
|
| On Fri, 8 Nov 2002, Randy.Dunlap wrote:
| ?
| > Sure, it looks cleaner that way, although gcc has already put <*dig>
| > in a local register; i.e., it's not pulled from memory for each test.
| > Here's a (tested) version that does that.
|
| Why do you have that "dig" pointer at all? It's not really used.
|
| Why not just do
|
| + char digit;
| ...
|
| + digit = str;
| + if (digit == '-')
| + digit = str[1];
|
|
| (and maybe it should also test for whether signed stuff is even alloed or
| not, ie maybe the test should be "if (is_sign && digit == '-')" instead)
OK, I've cleaned it up as suggested...
--
~Randy
--- ./lib/vsprintf.c%signed Mon Nov 4 14:30:49 2002
+++ ./lib/vsprintf.c Fri Nov 8 13:54:33 2002
@@ -517,6 +517,7 @@
{
const char *str = buf;
char *next;
+ char digit;
int num = 0;
int qualifier;
int base;
@@ -638,12 +639,16 @@
while (isspace(*str))
str++;
- if (!*str
- || (base == 16 && !isxdigit(*str))
- || (base == 10 && !isdigit(*str))
- || (base == 8 && (!isdigit(*str) || *str > '7'))
- || (base == 0 && !isdigit(*str)))
- break;
+ digit = *str;
+ if (is_sign && digit == '-')
+ digit = *(str + 1);
+
+ if (!digit
+ || (base == 16 && !isxdigit(digit))
+ || (base == 10 && !isdigit(digit))
+ || (base == 8 && (!isdigit(digit) || digit > '7'))
+ || (base == 0 && !isdigit(digit)))
+ break;
switch(qualifier) {
case 'h':
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-08 22:09 ` Randy.Dunlap
@ 2002-11-10 13:41 ` Henning P. Schmiedehausen
2002-11-11 3:05 ` Randy.Dunlap
0 siblings, 1 reply; 12+ messages in thread
From: Henning P. Schmiedehausen @ 2002-11-10 13:41 UTC (permalink / raw)
To: linux-kernel
"Randy.Dunlap" <rddunlap@osdl.org> writes:
>+ digit = *str;
>+ if (is_sign && digit == '-')
>+ digit = *(str + 1);
If signed is not allowed and you get a "-", you're in an error case
again...
Regards
Henning
--
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH hps@intermeta.de
Am Schwabachgrund 22 Fon.: 09131 / 50654-0 info@intermeta.de
D-91054 Buckenhof Fax.: 09131 / 50654-20
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-10 13:41 ` Henning P. Schmiedehausen
@ 2002-11-11 3:05 ` Randy.Dunlap
2002-11-11 4:19 ` Randy.Dunlap
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-11 3:05 UTC (permalink / raw)
To: Henning P. Schmiedehausen; +Cc: linux-kernel
On Sun, 10 Nov 2002, Henning P. Schmiedehausen wrote:
| "Randy.Dunlap" <rddunlap@osdl.org> writes:
|
| >+ digit = *str;
| >+ if (is_sign && digit == '-')
| >+ digit = *(str + 1);
|
| If signed is not allowed and you get a "-", you're in an error case
| again...
Yes, and a 0 value is returned.
IOW, asking for an unsigned number (in the format string)
and getting "-123" does return 0.
What should it do?
This function can't return -EINPUTERROR or -EILSEQ.
(since it's after feature-freeze :)
And the original problem was that a leading '-' sign on a
signed number (!) caused a return of 0. At least that is fixed.
So now the problem (?) is that a '-' sign on an unsigned number
returns 0. We can always add a big printk() there that
something is foul. Other ideas?
--
~Randy
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-11 3:05 ` Randy.Dunlap
@ 2002-11-11 4:19 ` Randy.Dunlap
2002-11-11 9:27 ` Henning Schmiedehausen
2002-11-11 14:38 ` Andreas Schwab
2 siblings, 0 replies; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-11 4:19 UTC (permalink / raw)
To: Henning P. Schmiedehausen; +Cc: linux-kernel
On Sun, 10 Nov 2002, Randy.Dunlap wrote:
| On Sun, 10 Nov 2002, Henning P. Schmiedehausen wrote:
|
| | "Randy.Dunlap" <rddunlap@osdl.org> writes:
| |
| | >+ digit = *str;
| | >+ if (is_sign && digit == '-')
| | >+ digit = *(str + 1);
| |
| | If signed is not allowed and you get a "-", you're in an error case
| | again...
|
| Yes, and a 0 value is returned.
| IOW, asking for an unsigned number (in the format string)
| and getting "-123" does return 0.
|
| What should it do?
| This function can't return -EINPUTERROR or -EILSEQ.
| (since it's after feature-freeze :)
| And the original problem was that a leading '-' sign on a
| signed number (!) caused a return of 0. At least that is fixed.
|
| So now the problem (?) is that a '-' sign on an unsigned number
| returns 0. We can always add a big printk() there that
| something is foul. Other ideas?
It's noteworthy that vsscanf() completely gives up on scanning
the rest of the input data at this point. E.g.:
count = sscanf (input, "%x %i %i", &level, &next, &other);
with <input> = "-42 -86 -99" gives up on "-42" and returns 0
(as number of items scanned/converted).
--
~Randy
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-11 3:05 ` Randy.Dunlap
2002-11-11 4:19 ` Randy.Dunlap
@ 2002-11-11 9:27 ` Henning Schmiedehausen
2002-11-11 14:38 ` Andreas Schwab
2 siblings, 0 replies; 12+ messages in thread
From: Henning Schmiedehausen @ 2002-11-11 9:27 UTC (permalink / raw)
To: Randy.Dunlap; +Cc: linux-kernel
Hi,
On Mon, 2002-11-11 at 04:05, Randy.Dunlap wrote:
> On Sun, 10 Nov 2002, Henning P. Schmiedehausen wrote:
>
> | "Randy.Dunlap" <rddunlap@osdl.org> writes:
> |
> | >+ digit = *str;
> | >+ if (is_sign && digit == '-')
> | >+ digit = *(str + 1);
> |
> | If signed is not allowed and you get a "-", you're in an error case
> | again...
>
> Yes, and a 0 value is returned.
> IOW, asking for an unsigned number (in the format string)
> and getting "-123" does return 0.
>
> What should it do?
I would model this after user space. (Which does strange things:
--- cut ---
#include <stdio.h>
main()
{
char *scan = "-100";
unsigned int foo;
int bar;
int res = sscanf(scan, "%ud", &foo);
printf("%s = %ud = %d\n", scan, foo, res);
res = sscanf(scan, "%ud", &bar);
printf("%s = %d = %d\n", scan, bar, res);
}
--- cut ---
% gcc -o xxx xxx.c
./xxx
-100 = 4294967196d = 1
-100 = -100 = 1
Hm, so I guess, yes, a warning message would be nice IMHO. Returning an
error code would IMHO moot, because noone is checking these codes
anyway.
Regards
Henning
> This function can't return -EINPUTERROR or -EILSEQ.
> (since it's after feature-freeze :)
> And the original problem was that a leading '-' sign on a
> signed number (!) caused a return of 0. At least that is fixed.
>
> So now the problem (?) is that a '-' sign on an unsigned number
> returns 0. We can always add a big printk() there that
> something is foul. Other ideas?
--
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH hps@intermeta.de
Am Schwabachgrund 22 Fon.: 09131 / 50654-0 info@intermeta.de
D-91054 Buckenhof Fax.: 09131 / 50654-20
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
2002-11-11 3:05 ` Randy.Dunlap
2002-11-11 4:19 ` Randy.Dunlap
2002-11-11 9:27 ` Henning Schmiedehausen
@ 2002-11-11 14:38 ` Andreas Schwab
2 siblings, 0 replies; 12+ messages in thread
From: Andreas Schwab @ 2002-11-11 14:38 UTC (permalink / raw)
To: Randy.Dunlap; +Cc: Henning P. Schmiedehausen, linux-kernel
"Randy.Dunlap" <rddunlap@osdl.org> writes:
|> On Sun, 10 Nov 2002, Henning P. Schmiedehausen wrote:
|>
|> | "Randy.Dunlap" <rddunlap@osdl.org> writes:
|> |
|> | >+ digit = *str;
|> | >+ if (is_sign && digit == '-')
|> | >+ digit = *(str + 1);
|> |
|> | If signed is not allowed and you get a "-", you're in an error case
|> | again...
|>
|> Yes, and a 0 value is returned.
|> IOW, asking for an unsigned number (in the format string)
|> and getting "-123" does return 0.
Not in C. According to the standard scanf is supposed to convert the
value to unsinged and return that.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2002-11-11 14:31 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-11-08 13:32 sscanf("-1", "%d", &i) fails, returns 0 Douglas Gilbert
2002-11-08 19:22 ` [PATCH] " Randy.Dunlap
2002-11-08 19:41 ` Richard B. Johnson
2002-11-08 19:59 ` Randy.Dunlap
2002-11-08 20:19 ` Linus Torvalds
2002-11-08 22:09 ` Randy.Dunlap
2002-11-10 13:41 ` Henning P. Schmiedehausen
2002-11-11 3:05 ` Randy.Dunlap
2002-11-11 4:19 ` Randy.Dunlap
2002-11-11 9:27 ` Henning Schmiedehausen
2002-11-11 14:38 ` Andreas Schwab
2002-11-08 20:23 ` Richard B. Johnson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox