fix sscanf

git-svn-id: svn://kolibrios.org@9861 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
eastorwest 2022-07-23 15:02:09 +00:00
parent a13c32585b
commit b3232bd390

View File

@ -254,12 +254,12 @@ int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vge
long double *arg_longdouble; long double *arg_longdouble;
long long digit; long long digit;
long double real; long double real;
int skip_next; // skip arguments with * char format
pos = 0; pos = 0;
while(*fmt) while(*fmt)
{ {
while (*fmt && isspace(*fmt)) fmt++; // skip paces in format str while (*fmt && isspace(*fmt)) fmt++; // skip spaces in format str
if (*fmt != '%') // usual char if (*fmt != '%') // usual char
{ {
@ -289,6 +289,7 @@ int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vge
fmtc = fmt; fmtc = fmt;
posc = pos; posc = pos;
skip_next = 0;
flags = 0; flags = 0;
format_flag = 0; format_flag = 0;
flag_long = 0; // 2 = long double or long long int or wchar flag_long = 0; // 2 = long double or long long int or wchar
@ -315,7 +316,10 @@ int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vge
format_flag = 1; format_flag = 1;
flags |= flag_unsigned; flags |= flag_unsigned;
break; break;
case '*': case '.': // just skip case '*':
skip_next = 1;
break;
case '.': // just skip
break; break;
default: default:
if(isdigit(*fmtc)) break; if(isdigit(*fmtc)) break;
@ -374,34 +378,37 @@ int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vge
vungetc(&save, ch, src); vungetc(&save, ch, src);
break; break;
case 'c': // read width chars, ever spaces case 'c': // read width chars, ever spaces
arg_str = va_arg(argp, char*); if (!skip_next) arg_str = va_arg(argp, char*);
if (fmt1 == 0) length = 1; if (fmt1 == 0) length = 1;
else length = fmt1; else length = fmt1;
for (i = 0; i < length;) for (i = 0; i < length;)
{ {
*arg_str++ = ch; i++; if (!skip_next) *arg_str++ = ch;
i++;
ch = vgetc(&save, src); ch = vgetc(&save, src);
if (ch == EOF) break; if (ch == EOF) break;
} }
if (i < length) goto exit_me; // not enough chars if (i < length) goto exit_me; // not enough chars
break; break;
case 's': case 's':
arg_str = va_arg(argp, char*); if (!skip_next) arg_str = va_arg(argp, char*);
if (fmt1 == 0) length = 4095; // max string scan 4096 if (fmt1 == 0) length = 4095; // max string scan 4096
else length = fmt1; else length = fmt1;
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
{ {
*arg_str++ = ch; if (!skip_next) *arg_str++ = ch;
ch = vgetc(&save, src); ch = vgetc(&save, src);
if (ch == EOF || isspace(ch)) break; // ok, just finish string if (ch == EOF || isspace(ch)) break; // ok, just finish string
} }
*arg_str++ = '\0'; if (!skip_next) *arg_str++ = '\0';
break; break;
case 'd': case 'i': case 'u': case 'd': case 'i': case 'u':
case 'o': case 'p': case 'x': case 'o': case 'p': case 'x':
i = try_parse_int(&digit, ch, src, &save, vgetc, vungetc); i = try_parse_int(&digit, ch, src, &save, vgetc, vungetc);
if (i < 0) goto exit_me; if (i < 0) goto exit_me;
if (!skip_next)
if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else if (flag_long == 0) { arg_int = va_arg(argp, int*); *arg_int = (int)digit; } else
if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else if (flag_long == 1) { arg_long = va_arg(argp, long*); *arg_long = (long)digit; } else
if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; } if (flag_long == 2) { arg_longlong = va_arg(argp, long long*); *arg_longlong = digit; }
@ -412,6 +419,7 @@ int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vge
i = try_parse_real(&real, ch, src, &save, vgetc, vungetc); i = try_parse_real(&real, ch, src, &save, vgetc, vungetc);
if (i < 0) goto exit_me; if (i < 0) goto exit_me;
if (!skip_next)
if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else if (flag_long == 0) { arg_float = va_arg(argp, float*); *arg_float = (float)real; } else
if (flag_long == 1) { arg_double = va_arg(argp, double*); *arg_double = (double)real; } else if (flag_long == 1) { arg_double = va_arg(argp, double*); *arg_double = (double)real; } else
if (flag_long == 2) { arg_longdouble = va_arg(argp, long double*); *arg_longdouble = real; } if (flag_long == 2) { arg_longdouble = va_arg(argp, long double*); *arg_longdouble = real; }
@ -419,7 +427,7 @@ int format_scan(const void *src, const char *fmt, va_list argp, virtual_getc vge
} }
fmt = fmtc + 1; fmt = fmtc + 1;
nread++; if (!skip_next) nread++;
} }
exit_me: exit_me:
if (point_to_n) *point_to_n = nread; if (point_to_n) *point_to_n = nread;