diff --git a/libc/stdio/lib_sscanf.c b/libc/stdio/lib_sscanf.c index ae8774cc57e..7c73e476eac 100644 --- a/libc/stdio/lib_sscanf.c +++ b/libc/stdio/lib_sscanf.c @@ -93,8 +93,7 @@ static int findwidth(FAR const char *buf, FAR const char *fmt) FAR const char *next = fmt + 1; /* No... is there a space after the format? Or does the format string end - * here? - */ + * here? */ if (isspace(*next) || *next == 0) { @@ -103,15 +102,13 @@ static int findwidth(FAR const char *buf, FAR const char *fmt) return strcspn(buf, spaces); } - /* No.. Another possibility is the format character is followed by - * some recognizable delimiting value. - */ + /* No.. Another possibility is the format character is followed by some + * recognizable delimiting value. */ if (*next != '%') { /* If so we will say that the string ends there if we can find that - * delimiter in the input string. - */ + * delimiter in the input string. */ FAR const char *ptr = strchr(buf, *next); if (ptr) @@ -120,16 +117,14 @@ static int findwidth(FAR const char *buf, FAR const char *fmt) } } - /* No... the format has no delimiter and is back-to-back with the next - * format (or is followed by a delimiter that does not exist in the - * input string). At this point we just bail and Use the input up until - * the first white space is encountered. - * - * NOTE: This means that values from the following format may be - * concatenated with the first. This is a bug. We have no generic way of - * determining the width of the data if there is no fieldwidth, no space - * separating the input, and no usable delimiter character. - */ + /* No... the format has no delimiter and is back-to-back with the next format + * (or is followed by a delimiter that does not exist in the input string). + * At this point we just bail and Use the input up until the first white + * space is encountered. NOTE: This means that values from the following + * format may be concatenated with the first. This is a bug. We have no + * generic way of determining the width of the data if there is no + * fieldwidth, no space separating the input, and no usable delimiter + * character. */ return strcspn(buf, spaces); } @@ -149,7 +144,7 @@ static int findwidth(FAR const char *buf, FAR const char *fmt) int sscanf(FAR const char *buf, FAR const char *fmt, ...) { va_list ap; - int count; + int count; va_start(ap, fmt); count = vsscanf((FAR const char *)buf, fmt, ap); @@ -168,34 +163,33 @@ int sscanf(FAR const char *buf, FAR const char *fmt, ...) int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) { FAR const char *bufstart; - FAR char *tv; + FAR char *tv; FAR const char *tc; - bool lflag; - bool noassign; - int count; - int width; - int base = 10; - char tmp[MAXLN]; + bool lflag; + bool noassign; + int count; + int width; + int fwidth; + int base = 10; + char tmp[MAXLN]; linfo("vsscanf: buf=\"%s\" fmt=\"%s\"\n", buf, fmt); /* Remember the start of the input buffer. We will need this for %n - * calculations. - */ + * calculations. */ bufstart = buf; /* Parse the format, extracting values from the input buffer as needed */ - count = 0; - width = 0; + count = 0; + width = 0; noassign = false; - lflag = false; + lflag = false; - /* Loop until all characters in the fmt string have been processed. We - * may have to continue loop after reaching the end the input data in - * order to handle trailing %n format specifiers. - */ + /* Loop until all characters in the fmt string have been processed. We may + * have to continue loop after reaching the end the input data in order to + * handle trailing %n format specifiers. */ while (*fmt) { @@ -244,27 +238,25 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) } } - /* Process %s: String conversion */ + /* Process %s: String conversion */ if (*fmt == 's') { linfo("vsscanf: Performing string conversion\n"); - /* Get a pointer to the char * value. We need to do this even - * if we have reached the end of the input data in order to - * update the 'ap' variable. - */ + /* Get a pointer to the char * value. We need to do this even if + * we have reached the end of the input data in order to update + * the 'ap' variable. */ - tv = NULL; /* To avoid warnings about begin uninitialized */ + tv = NULL; /* To avoid warnings about begin uninitialized */ if (!noassign) { - tv = va_arg(ap, FAR char *); + tv = va_arg(ap, FAR char *); tv[0] = '\0'; } - /* But we only perform the data conversion is we still have - * bytes remaining in the input data stream. - */ + /* But we only perform the data conversion is we still have bytes + * remaining in the input data stream. */ if (*buf) { @@ -275,16 +267,21 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) buf++; } - /* Was a fieldwidth specified? */ + /* Guess a field width using some heuristics */ - if (!width) + fwidth = findwidth(buf, fmt); + + /* Use the actual field's width if 1) no fieldwidth specified + * or 2) the actual field's width is smaller than fieldwidth + * specified */ + + if (!width || fwidth < width) { - /* No... Guess a field width using some heuristics */ - - int tmpwidth = findwidth(buf, fmt); - width = MIN(sizeof(tmp) - 1, tmpwidth); + width = fwidth; } + width = MIN(sizeof(tmp) - 1, width); + /* Copy the string (if we are making an assignment) */ if (!noassign) @@ -300,27 +297,25 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) } } - /* Process %c: Character conversion */ + /* Process %c: Character conversion */ else if (*fmt == 'c') { linfo("vsscanf: Performing character conversion\n"); - /* Get a pointer to the char * value. We need to do this even - * if we have reached the end of the input data in order to - * update the 'ap' variable. - */ + /* Get a pointer to the char * value. We need to do this even if + * we have reached the end of the input data in order to update + * the 'ap' variable. */ - tv = NULL; /* To avoid warnings about beign uninitialized */ + tv = NULL; /* To avoid warnings about beign uninitialized */ if (!noassign) { - tv = va_arg(ap, FAR char *); + tv = va_arg(ap, FAR char *); tv[0] = '\0'; } - /* But we only perform the data conversion is we still have - * bytes remaining in the input data stream. - */ + /* But we only perform the data conversion is we still have bytes + * remaining in the input data stream. */ if (*buf) { @@ -343,33 +338,30 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) } /* Update the buffer pointer past the character(s) in the - * input - */ + * input */ buf += width; } } - /* Process %d, %o, %b, %x, %u: Various integer conversions */ + /* Process %d, %o, %b, %x, %u: Various integer conversions */ else if (strchr("dobxu", *fmt)) { FAR long *plong = NULL; - FAR int *pint = NULL; + FAR int *pint = NULL; bool sign; linfo("vsscanf: Performing integer conversion\n"); /* Get a pointer to the integer value. We need to do this even * if we have reached the end of the input data in order to - * update the 'ap' variable. - */ + * update the 'ap' variable. */ if (!noassign) { /* We have to check whether we need to return a long or an - * int. - */ + * int. */ if (lflag) { @@ -383,15 +375,14 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) } } - /* But we only perform the data conversion if we still have - * bytes remaining in the input data stream. - */ + /* But we only perform the data conversion if we still have bytes + * remaining in the input data stream. */ if (*buf) { FAR char *endptr; - int errsave; - long tmplong; + int errsave; + long tmplong; /* Skip over any white space before the integer string */ @@ -400,9 +391,8 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) buf++; } - /* The base of the integer conversion depends on the - * specific conversion specification. - */ + /* The base of the integer conversion depends on the specific + * conversion specification. */ sign = false; switch (*fmt) @@ -438,9 +428,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) width = MIN(sizeof(tmp) - 1, tmpwidth); } - /* Copy the numeric string into a temporary working - * buffer. - */ + /* Copy the numeric string into a temporary working buffer. */ strncpy(tmp, buf, width); tmp[width] = '\0'; @@ -475,9 +463,8 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) if (!noassign) { - /* We have to check whether we need to return a long - * or an int. - */ + /* We have to check whether we need to return a long or + * an int. */ if (lflag) { @@ -487,8 +474,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) } else { - linfo("vsscanf: Return %ld to 0x%p\n", - tmplong, pint); + linfo("vsscanf: Return %ld to 0x%p\n", tmplong, pint); *pint = (int)tmplong; } @@ -497,48 +483,44 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) } } - /* Process %a, %A, %f, %F, %e, %E, %g, and %G: Floating point - * conversions - */ + /* Process %a, %A, %f, %F, %e, %E, %g, and %G: Floating point + * conversions */ else if (strchr("aAfFeEgG", *fmt) != NULL) { #ifdef CONFIG_HAVE_DOUBLE FAR double_t *pd = NULL; #endif - FAR float *pf = NULL; + FAR float *pf = NULL; linfo("vsscanf: Performing floating point conversion\n"); - /* Get a pointer to the double value. We need to do this even - * if we have reached the end of the input data in order to - * update the 'ap' variable. - */ + /* Get a pointer to the double value. We need to do this even if + * we have reached the end of the input data in order to update + * the 'ap' variable. */ if (!noassign) { /* We have to check whether we need to return a float or a - * double. - */ + * double. */ #ifdef CONFIG_HAVE_DOUBLE if (lflag) { - pd = va_arg(ap, FAR double_t *); + pd = va_arg(ap, FAR double_t *); *pd = 0.0; } else #endif { - pf = va_arg(ap, FAR float *); + pf = va_arg(ap, FAR float *); *pf = 0.0; } } #ifdef CONFIG_LIBC_FLOATINGPOINT - /* But we only perform the data conversion is we still have - * bytes remaining in the input data stream. - */ + /* But we only perform the data conversion is we still have bytes + * remaining in the input data stream. */ if (*buf) { @@ -573,14 +555,14 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) /* strtod always returns a double */ FAR char *endptr; - int errsave; - double_t dvalue; + int errsave; + double_t dvalue; /* Preserve the errno value */ errsave = get_errno(); set_errno(0); - dvalue = strtod(tmp, &endptr); + dvalue = strtod(tmp, &endptr); /* Check if the number was successfully converted */ @@ -591,18 +573,17 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) set_errno(errsave); - /* We have to check whether we need to return a float - * or a double. - */ + /* We have to check whether we need to return a float or + * a double. */ -#ifdef CONFIG_HAVE_DOUBLE +# ifdef CONFIG_HAVE_DOUBLE if (lflag) { linfo("vsscanf: Return %f to %p\n", dvalue, pd); *pd = dvalue; } else -#endif +# endif { linfo("vsscanf: Return %f to %p\n", dvalue, pf); *pf = (float)dvalue; @@ -614,7 +595,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) #endif } - /* Process %n: Character count */ + /* Process %n: Character count */ else if (*fmt == 'n') { @@ -622,7 +603,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) if (!noassign) { - size_t nchars = (size_t)(buf - bufstart); + size_t nchars = (size_t) (buf - bufstart); /* Note %n does not count as a conversion */ @@ -639,14 +620,14 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) } } - width = 0; + width = 0; noassign = false; - lflag = false; + lflag = false; fmt++; } - /* It is not a conversion specifier */ + /* It is not a conversion specifier */ else if (*buf) { @@ -678,8 +659,7 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) } /* sscanf is required to return EOF if the input ends before the first - * matching failure or conversion. - */ + * matching failure or conversion. */ return count ? count : EOF; }