151 int nrn_vsscanf(
const char *str,
const char** rs,
const char *
format, va_list args)
153 int vsscanf(
const char *str,
const char *format, va_list args)
158 const char point =
'.';
160 const char point = localeconv()->decimal_point[0];
164 for (s = str, f = format; *f; ++f)
175 for (; isdigit((
int)(
unsigned int)*f); ++f)
176 width *= 10, width += *f -
'0';
178 if (*f ==
'h' || *f ==
'l' || *f ==
'L')
181 if (*f !=
'[' && *f !=
'c' && *f !=
'n')
182 while (isspace((
int)(
unsigned int)*s))
185 #define COPY *b++ = *s++, --width 186 #define MATCH(cond) if (width && (cond)) COPY; 187 #define MATCH_ACTION(cond, action) if (width && (cond)) { COPY; action; } 188 #define MATCHES_ACTION(cond, action) while (width && (cond)) { COPY; action; } 189 #define FAIL (cnv) ? cnv : EOF 192 case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X':
195 static const char types[] =
"diouxXp";
196 static const int bases[] = { 10, 0, 8, 10, 16, 16, 16 };
197 static const char digitset[] =
"0123456789abcdefABCDEF";
198 static const int setsizes[] = { 10, 0, 0, 0, 0, 0, 0, 0, 8, 0, 10, 0, 0, 0, 0, 0, 22 };
199 int base = bases[strchr(types, *f) - types];
204 if (width <= 0 || width > 512) width = 512;
205 MATCH(*s ==
'+' || *s ==
'-')
208 MATCH_ACTION((*s ==
'x' || *s ==
'X') && (base == 0 || base == 16), base = 16)
else base = 8;
210 setsize = setsizes[base];
212 if (!digit) { *rs =
s;
return FAIL; }
216 if (*f ==
'd' || *f ==
'i')
218 long data = strtol(buf,
NULL, base);
220 *va_arg(args,
short *) = (short)data;
221 else if (size ==
'l')
222 *va_arg(args,
long *) =
data;
224 *va_arg(args,
int *) = (
int)data;
228 unsigned long data = strtoul(buf,
NULL, base);
230 *va_arg(args,
void **) = (
void *)data;
231 else if (size ==
'h')
232 *va_arg(args,
unsigned short *) = (
unsigned short)data;
233 else if (size ==
'l')
234 *va_arg(args,
unsigned long *) =
data;
236 *va_arg(args,
unsigned int *) = (
unsigned int)data;
243 case 'e':
case 'E':
case 'f':
case 'g':
case 'G':
248 if (width <= 0 || width > 512) width = 512;
249 MATCH(*s ==
'+' || *s ==
'-')
254 MATCH(*s ==
'+' || *s ==
'-')
258 if (!digit) { *rs =
s;
return FAIL; }
264 *va_arg(args,
double *) =
data;
265 else if (size ==
'L')
266 *va_arg(args,
long double *) = (
long double)data;
268 *va_arg(args,
float *) = (float)data;
276 char *
arg = va_arg(args,
char *);
277 if (width <= 0) width =
INT_MAX;
278 while (width-- && *s && !isspace((
int)(
unsigned int)*s))
279 if (do_cnv) *arg++ = *s++;
280 if (do_cnv) *arg =
'\0', ++cnv;
286 char *
arg = va_arg(args,
char *);
290 if (width <= 0) width =
INT_MAX;
291 if (*++f ==
'^') setcomp = 1, ++f;
292 end = strchr((*f ==
']') ? f + 1 : f,
']');
293 if (!end) { *rs =
s;
return FAIL; }
295 while (width-- && *s)
297 if (!setcomp && !memchr(f, *s, setsize))
break;
298 if (setcomp && memchr(f, *s, setsize))
break;
299 if (do_cnv) *arg++ = *s++;
301 if (do_cnv) *arg =
'\0', ++cnv;
308 char *
arg = va_arg(args,
char *);
309 if (width <= 0) width = 1;
312 if (!*s) { *rs =
s;
return FAIL; }
313 if (do_cnv) *arg++ = *s++;
322 *va_arg(args,
short *) = (short)(s - str);
323 else if (size ==
'l')
324 *va_arg(args,
long *) = (
long)(s - str);
326 *va_arg(args,
int *) = (
int)(s - str);
332 if (*s++ !=
'%') { *rs =
s;
return cnv; }
337 *rs =
s;
return FAIL;
340 else if (isspace((
int)(
unsigned int)*f))
342 while (isspace((
int)(
unsigned int)f[1]))
344 while (isspace((
int)(
unsigned int)*s))
361 #undef _ISOC9X_SOURCE 366 int test_sscanf(
const char *str,
const char *format, ...)
370 va_start(args, format);
371 rc =
vsscanf(str, format, args);
376 int main(
int ac,
char **av)
384 long double ld1, ld2;
386 char b1[128], b2[128];
387 char c1[128], c2[128];
388 char s1[128], s2[128];
392 unsigned short su1, su2;
394 unsigned long lu1, lu2;
398 if (ac == 2 && !strcmp(av[1],
"help"))
400 printf(
"usage: %s [show]\n", *av);
404 printf(
"Testing: %s\n",
"vsscanf");
408 sprintf(str,
" abc -12 37 101 3.4e-1 12.34 102.23 xyz %p def ghi jkl %% ",
409 p1 = (
void *)0xdeadbeef
412 if (ac >= 2 && !strcmp(av[1],
"show"))
416 " abc %hd %d %ld %e %le %Le xyz %p %[^abc ] %3c %s%hn %n%% %ln",
417 &si1, &i1, &li1, &f1, &d1, &ld1, &p1, b1, c1, s1, &sn1, &in1, &ln1
420 rc2 = test_sscanf(str,
421 " abc %hd %d %ld %e %le %Le xyz %p %[^abc ] %3c %s%hn %n%% %ln",
422 &si2, &i2, &li2, &f2, &d2, &ld2, &p2, b2, c2, s2, &sn2, &in2, &ln2
426 ++errors,
printf(
"Test1: failed (returned %d, not %d)\n", rc2, rc1);
428 ++errors,
printf(
"Test2: failed (%%hd scanned %hd, not %hd)\n", si2, si1);
430 ++errors,
printf(
"Test3: failed (%%d scanned %d, not %d)\n", i2, i1);
432 ++errors,
printf(
"Test4: failed (%%ld scanned %ld, not %ld)\n", li2, li1);
433 if (
fabs(f2 - 3.4
e-1) / 3.4
e-1 >= 4 * FLT_EPSILON)
434 ++errors,
printf(
"Test5: failed (%%e scanned %e, not %e)\n", f2, f1);
435 if (
fabs(d2 - 12.34) / 12.34 >= 4 * DBL_EPSILON)
436 ++errors,
printf(
"Test6: failed (%%le scanned %le, not %le)\n", d2, d1);
437 if (
fabs(ld2 - 102.23) / 102.23 >= 4 * LDBL_EPSILON)
438 ++errors,
printf(
"Test7: failed (%%Le scanned %Le, not %Le)\n", ld2, ld1);
440 ++errors,
printf(
"Test8: failed (%%p scanned %p, not %p)\n", p2, p1);
442 ++errors,
printf(
"Test9: failed (%%[^abc ] scanned \"%s\", not \"%s\")\n", b2, b1);
443 if (memcmp(c1, c2, 3))
444 ++errors,
printf(
"Test10: failed (%%3c scanned \"%3.3s\", not \"%3.3s\")\n", c2, c1);
446 ++errors,
printf(
"Test11: failed (%%s scanned \"%s\", not \"%s\")\n", s2, s1);
448 ++errors,
printf(
"Test12: failed (%%hn scanned %hd, not %hd)\n", sn2, sn1);
450 ++errors,
printf(
"Test13: failed (%%n scanned %d, not %d)\n", in2, in1);
452 ++errors,
printf(
"Test14: failed (%%ln scanned %ld, not %ld)\n", ln2, ln1);
456 #define TEST_NUM(i, var, tst, str, format) \ 457 rc1 = sscanf(str, format, &s##var##1, &var##1, &l##var##1); \ 458 rc2 = test_sscanf(str, format, &s##var##2, &var##2, &l##var##2); \ 460 ++errors, printf("Test%d: failed (returned %d, not %d)\n", (i), rc2, rc1); \ 461 if (s##var##1 != s##var##2) \ 462 ++errors, printf("Test%d: failed (%%h%c scanned %hd, not %hd)\n", (i), tst, s##var##2, s##var##1); \ 463 if (var##1 != var##2) \ 464 ++errors, printf("Test%d: failed (%%%c scanned %d, not %d)\n", (i), tst, var##2, var##1); \ 465 if (l##var##1 != l##var##2) \ 466 ++errors, printf("Test%d: failed (%%l%c scanned %ld, not %ld)\n", (i), tst, l##var##2, l##var##1) 468 #define TEST_STR(i, len, str, format) \ 469 rc1 = sscanf(str, format, b1, c1, s1); \ 470 rc2 = test_sscanf(str, format, b2, c2, s2); \ 472 ++errors, printf("Test%d: failed (returned %d, not %d)\n", (i), rc2, rc1); \ 473 if (strcmp(b1, b2)) \ 474 ++errors, printf("Test%d: failed (%%%d[ scanned \"%s\", not \"%s\")\n", (i), (len), b2, b1); \ 475 if (memcmp(c1, c2, len)) \ 476 ++errors, printf("Test%d: failed (%%%dc scanned \"%*.*s\", not \"%*.*s\")\n", (i), (len), (len), (len), c2, (len), (len), c1); \ 477 if (strcmp(s1, s2)) \ 478 ++errors, printf("Test%d: failed (%%%ds scanned \"%s\", not \"%s\")\n", (i), (len), s2, s1) 480 TEST_NUM(15,
i,
'i',
"37 21 53",
"%hi %i %li");
481 TEST_NUM(16,
i,
'i',
"037 021 053",
"%hi %i %li");
482 TEST_NUM(17,
i,
'i',
"0x37 0x21 0x53",
"%hi %i %li");
483 TEST_NUM(18, u,
'o',
"037 021 053",
"%ho %o %lo");
484 TEST_NUM(19, u,
'u',
"37 21 53",
"%hu %u %lu");
485 TEST_NUM(20, u,
'x',
"0x37 0x21 0x53",
"%hx %x %lx");
486 TEST_NUM(21, u,
'X',
"0x37 0x21 0x53",
"%hx %x %lx");
490 TEST_NUM(22,
i,
'd',
"123456789",
"%3hd %2d %4ld");
491 TEST_NUM(23,
i,
'i',
"123456789",
"%3hi %2i %4li");
492 TEST_NUM(24,
i,
'i',
"012340789",
"%3hi %2i %4li");
493 TEST_NUM(25,
i,
'x',
"123456789",
"%3hi %2i %4li");
494 TEST_NUM(26, u,
'o',
"012340789",
"%3ho %2o %4lo");
495 TEST_NUM(27, u,
'u',
"123456789",
"%3hu %2u %4lu");
496 TEST_NUM(28, u,
'x',
"123456789",
"%3hx %2x %4lx");
497 TEST_NUM(29, u,
'X',
"123456789",
"%3hx %2X %4lX");
498 TEST_STR(30, 1,
"abcd",
"%1[a]%c%1s");
500 TEST_STR(31, 5,
"abc\001d e f g h i",
"%5[][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()_=+\\|{};':\",./<>? -]%5c%5s");
501 TEST_STR(32, 3,
"abc\001d e f g h i",
"%3[][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()_=+\\|{};':\",./<>? -]%3c%3s");
502 TEST_STR(33, 7,
"abc\001d e f g h i",
"%7[][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()_=+\\|{};':\",./<>? -]%7c%7s");
503 TEST_STR(34, 2,
"abc\001d e f g h i",
"%2[][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()_=+\\|{};':\",./<>? -]%2c%2s");
507 #define TEST_ERR(i, str, format) \ 508 rc1 = sscanf(str, format); \ 509 rc2 = test_sscanf(str, format); \ 511 ++errors, printf("Test%d: failed (returned %d, not %d)\n", (i), rc2, rc1) 513 #define TEST_ERR_ARG(i, str, format, var) \ 514 rc1 = sscanf(str, format, &var##1); \ 515 rc2 = test_sscanf(str, format, &var##1); \ 517 ++errors, printf("Test%d: failed (returned %d, not %d)\n", (i), rc2, rc1) 519 TEST_ERR_ARG(35,
"",
"%d",
i);
520 TEST_ERR_ARG(36,
"",
"%i",
i);
521 TEST_ERR_ARG(37,
"",
"%o", u);
522 TEST_ERR_ARG(38,
"",
"%u", u);
523 TEST_ERR_ARG(39,
"",
"%x", u);
524 TEST_ERR_ARG(40,
"",
"%X", u);
525 TEST_ERR_ARG(41,
"",
"%p",
p);
526 TEST_ERR_ARG(42,
"",
"%e", f);
527 TEST_ERR_ARG(43,
"",
"%E", f);
528 TEST_ERR_ARG(44,
"",
"%f", f);
529 TEST_ERR_ARG(45,
"",
"%g", f);
530 TEST_ERR_ARG(46,
"",
"%G", f);
531 TEST_ERR_ARG(47,
"",
"%[^]", *b);
532 TEST_ERR_ARG(48,
"",
"%c", *
c);
533 TEST_ERR(49,
"a",
"%%");
534 TEST_ERR(50,
"a",
"b");
537 printf(
"%d/50 tests failed (This system's sscanf(3) is probably wrong)\n", errors);
539 printf(
"All tests passed\n");
541 return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
#define MATCHES_ACTION(cond, action)
#define MATCH_ACTION(cond, action)
int vsscanf(const char *str, const char *format, va_list args)