sscanf(): Was returning the wrong number of conversions in many cases; Also, needs to return EOF if there were no conversions

This commit is contained in:
Gregory Nutt 2014-03-30 14:24:38 -06:00
parent 85b0a1a544
commit 6bb8cc02df
2 changed files with 19 additions and 11 deletions

View File

@ -7084,4 +7084,7 @@
own file (2014-3-30). own file (2014-3-30).
* arch/arm/src/sama5/sam_boot.c: Fix some backward conditional * arch/arm/src/sama5/sam_boot.c: Fix some backward conditional
compilation (2014-3-30). compilation (2014-3-30).
* libc/stdio/lib_sccanf.c: Fix a counting error in the return
value from sscanf(). Noted by kfrolov. Also, sscanf() should
return EOF if no values were converted (2014-3-30).

View File

@ -271,7 +271,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
* update the 'ap' variable. * update the 'ap' variable.
*/ */
tv = NULL; /* To avoid warnings about beign uninitialized */ tv = NULL; /* To avoid warnings about begin uninitialized */
if (!noassign) if (!noassign)
{ {
tv = va_arg(ap, char*); tv = va_arg(ap, char*);
@ -307,6 +307,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
{ {
strncpy(tv, buf, width); strncpy(tv, buf, width);
tv[width] = '\0'; tv[width] = '\0';
count++;
} }
/* Update the buffer pointer past the string in the input */ /* Update the buffer pointer past the string in the input */
@ -339,7 +340,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
if (*buf) if (*buf)
{ {
/* Was a fieldwidth specified? */ /* Was a field width specified? */
if (!width) if (!width)
{ {
@ -354,6 +355,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
{ {
strncpy(tv, buf, width); strncpy(tv, buf, width);
tv[width] = '\0'; tv[width] = '\0';
count++;
} }
/* Update the buffer pointer past the character(s) in the /* Update the buffer pointer past the character(s) in the
@ -396,7 +398,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
} }
} }
/* But we only perform the data conversion is we still have /* But we only perform the data conversion if we still have
* bytes remaining in the input data stream. * bytes remaining in the input data stream.
*/ */
@ -489,6 +491,8 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
tmplong, pint); tmplong, pint);
*pint = (int)tmplong; *pint = (int)tmplong;
} }
count++;
} }
} }
} }
@ -601,6 +605,8 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
lvdbg("vsscanf: Return %f to %p\n", dvalue, pf); lvdbg("vsscanf: Return %f to %p\n", dvalue, pf);
*pf = (float)dvalue; *pf = (float)dvalue;
} }
count++;
} }
} }
#endif #endif
@ -616,6 +622,8 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
{ {
size_t nchars = (size_t)(buf - bufstart); size_t nchars = (size_t)(buf - bufstart);
/* Note %n does not count as a conversion */
if (lflag) if (lflag)
{ {
FAR long *plong = va_arg(ap, long*); FAR long *plong = va_arg(ap, long*);
@ -629,13 +637,6 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
} }
} }
/* Note %n does not count as a conversion */
if (!noassign && *fmt != 'n')
{
count++;
}
width = 0; width = 0;
noassign = false; noassign = false;
lflag = false; lflag = false;
@ -674,5 +675,9 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
} }
} }
return count; /* sscanf is required to return EOF if the input ends before the first
* matching failure or conversion.
*/
return count ? count : EOF;
} }