sscanf.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. // SPDX-License-Identifier: BSD-3-Clause
  2. /*
  3. * Copyright (c) 1990, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Chris Torek.
  8. *
  9. * Copyright (c) 2011 The FreeBSD Foundation
  10. * All rights reserved.
  11. * Portions of this software were developed by David Chisnall
  12. * under sponsorship from the FreeBSD Foundation.
  13. *
  14. * Author: Juergen Gross <jgross@suse.com>
  15. * Date: Jun 2016
  16. */
  17. #if !defined HAVE_LIBC
  18. #include <os.h>
  19. #include <linux/kernel.h>
  20. #include <linux/ctype.h>
  21. #include <vsprintf.h>
  22. #include <linux/string.h>
  23. #include <malloc.h>
  24. #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
  25. /**
  26. * struct str_info - Input string parameters
  27. * @neg: negative number or not
  28. * 0 - not negative
  29. * 1 - negative
  30. * @any: set any if any `digits' consumed; make it negative to indicate
  31. * overflow
  32. * @acc: accumulated value
  33. */
  34. struct str_info {
  35. int neg, any;
  36. u64 acc;
  37. };
  38. /**
  39. * str_to_int_convert() - Write string data to structure
  40. * @nptr: pointer to string
  41. * @base: number's base
  42. * @unsign: describes what integer is expected
  43. * 0 - not unsigned
  44. * 1 - unsigned
  45. *
  46. * Ignores `locale' stuff. Assumes that the upper and lower case
  47. * alphabets and digits are each contiguous.
  48. *
  49. * Return: struct str_info *, which contains string data to future process
  50. */
  51. static struct str_info *
  52. str_to_int_convert(const char **nptr, int base, unsigned int unsign)
  53. {
  54. const char *s = *nptr;
  55. u64 acc;
  56. unsigned char c;
  57. u64 cutoff;
  58. int neg, any, cutlim;
  59. u64 qbase;
  60. struct str_info *info;
  61. /*
  62. * Skip white space and pick up leading +/- sign if any.
  63. * If base is 0, allow 0x for hex and 0 for octal, else
  64. * assume decimal; if base is already 16, allow 0x.
  65. */
  66. info = (struct str_info *)malloc(sizeof(struct str_info));
  67. if (!info)
  68. return NULL;
  69. do {
  70. c = *s++;
  71. } while (isspace(c));
  72. if (c == '-') {
  73. neg = 1;
  74. c = *s++;
  75. } else {
  76. neg = 0;
  77. if (c == '+')
  78. c = *s++;
  79. }
  80. if ((base == 0 || base == 16) &&
  81. c == '0' && (*s == 'x' || *s == 'X')) {
  82. c = s[1];
  83. s += 2;
  84. base = 16;
  85. }
  86. if (base == 0)
  87. base = c == '0' ? 8 : 10;
  88. /*
  89. * Compute the cutoff value between legal numbers and illegal
  90. * numbers. That is the largest legal value, divided by the
  91. * base. An input number that is greater than this value, if
  92. * followed by a legal input character, is too big. One that
  93. * is equal to this value may be valid or not; the limit
  94. * between valid and invalid numbers is then based on the last
  95. * digit. For instance, if the range for quads is
  96. * [-9223372036854775808..9223372036854775807] and the input base
  97. * is 10, cutoff will be set to 922337203685477580 and cutlim to
  98. * either 7 (neg==0) or 8 (neg==1), meaning that if we have
  99. * accumulated a value > 922337203685477580, or equal but the
  100. * next digit is > 7 (or 8), the number is too big, and we will
  101. * return a range error.
  102. *
  103. * Set any if any `digits' consumed; make it negative to indicate
  104. * overflow.
  105. */
  106. qbase = (unsigned int)base;
  107. if (!unsign) {
  108. cutoff = neg ? (u64)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX : LLONG_MAX;
  109. cutlim = cutoff % qbase;
  110. cutoff /= qbase;
  111. } else {
  112. cutoff = (u64)ULLONG_MAX / qbase;
  113. cutlim = (u64)ULLONG_MAX % qbase;
  114. }
  115. for (acc = 0, any = 0;; c = *s++) {
  116. if (!isascii(c))
  117. break;
  118. if (isdigit(c))
  119. c -= '0';
  120. else if (isalpha(c))
  121. c -= isupper(c) ? 'A' - 10 : 'a' - 10;
  122. else
  123. break;
  124. if (c >= base)
  125. break;
  126. if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
  127. any = -1;
  128. } else {
  129. any = 1;
  130. acc *= qbase;
  131. acc += c;
  132. }
  133. }
  134. info->any = any;
  135. info->neg = neg;
  136. info->acc = acc;
  137. *nptr = s;
  138. return info;
  139. }
  140. /**
  141. * strtoq() - Convert a string to a quad integer
  142. * @nptr: pointer to string
  143. * @endptr: pointer to number's end in the string
  144. * @base: number's base
  145. *
  146. * Return: s64 quad integer number converted from input string
  147. */
  148. static s64
  149. strtoq(const char *nptr, char **endptr, int base)
  150. {
  151. const char *s = nptr;
  152. u64 acc;
  153. int unsign = 0;
  154. struct str_info *info;
  155. info = str_to_int_convert(&s, base, unsign);
  156. if (!info)
  157. return -1;
  158. acc = info->acc;
  159. if (info->any < 0)
  160. acc = info->neg ? LLONG_MIN : LLONG_MAX;
  161. else if (info->neg)
  162. acc = -acc;
  163. if (endptr != 0)
  164. *endptr = __DECONST(char *, info->any ? s - 1 : nptr);
  165. free(info);
  166. return acc;
  167. }
  168. /**
  169. * strtouq() - Convert a string to an unsigned quad integer
  170. * @nptr: pointer to string
  171. * @endptr: pointer to number's end in the string
  172. * @base: number's base
  173. *
  174. * Return: s64 unsigned quad integer number converted from
  175. * input string
  176. */
  177. u64
  178. strtouq(const char *nptr, char **endptr, int base)
  179. {
  180. const char *s = nptr;
  181. u64 acc;
  182. int unsign = 1;
  183. struct str_info *info;
  184. info = str_to_int_convert(&s, base, unsign);
  185. if (!info)
  186. return -1;
  187. acc = info->acc;
  188. if (info->any < 0)
  189. acc = ULLONG_MAX;
  190. else if (info->neg)
  191. acc = -acc;
  192. if (endptr != 0)
  193. *endptr = __DECONST(char *, info->any ? s - 1 : nptr);
  194. free(info);
  195. return acc;
  196. }
  197. /**
  198. * __sccl() - Fill in the given table from the scanset at the given format
  199. * (just after `[')
  200. * @tab: table to fill in
  201. * @fmt: format of buffer
  202. *
  203. * The table has a 1 wherever characters should be considered part of the
  204. * scanset.
  205. *
  206. * Return: pointer to the character past the closing `]'
  207. */
  208. static const u_char *
  209. __sccl(char *tab, const u_char *fmt)
  210. {
  211. int c, n, v;
  212. /* first `clear' the whole table */
  213. c = *fmt++; /* first char hat => negated scanset */
  214. if (c == '^') {
  215. v = 1; /* default => accept */
  216. c = *fmt++; /* get new first char */
  217. } else {
  218. v = 0; /* default => reject */
  219. }
  220. /* XXX: Will not work if sizeof(tab*) > sizeof(char) */
  221. for (n = 0; n < 256; n++)
  222. tab[n] = v; /* memset(tab, v, 256) */
  223. if (c == 0)
  224. return (fmt - 1);/* format ended before closing ] */
  225. /*
  226. * Now set the entries corresponding to the actual scanset
  227. * to the opposite of the above.
  228. *
  229. * The first character may be ']' (or '-') without being special;
  230. * the last character may be '-'.
  231. */
  232. v = 1 - v;
  233. for (;;) {
  234. tab[c] = v; /* take character c */
  235. doswitch:
  236. n = *fmt++; /* and examine the next */
  237. switch (n) {
  238. case 0: /* format ended too soon */
  239. return (fmt - 1);
  240. case '-':
  241. /*
  242. * A scanset of the form
  243. * [01+-]
  244. * is defined as `the digit 0, the digit 1,
  245. * the character +, the character -', but
  246. * the effect of a scanset such as
  247. * [a-zA-Z0-9]
  248. * is implementation defined. The V7 Unix
  249. * scanf treats `a-z' as `the letters a through
  250. * z', but treats `a-a' as `the letter a, the
  251. * character -, and the letter a'.
  252. *
  253. * For compatibility, the `-' is not considerd
  254. * to define a range if the character following
  255. * it is either a close bracket (required by ANSI)
  256. * or is not numerically greater than the character
  257. * we just stored in the table (c).
  258. */
  259. n = *fmt;
  260. if (n == ']' || n < c) {
  261. c = '-';
  262. break; /* resume the for(;;) */
  263. }
  264. fmt++;
  265. /* fill in the range */
  266. do {
  267. tab[++c] = v;
  268. } while (c < n);
  269. c = n;
  270. /*
  271. * Alas, the V7 Unix scanf also treats formats
  272. * such as [a-c-e] as `the letters a through e'.
  273. * This too is permitted by the standard....
  274. */
  275. goto doswitch;
  276. break;
  277. case ']': /* end of scanset */
  278. return (fmt);
  279. default: /* just another character */
  280. c = n;
  281. break;
  282. }
  283. }
  284. /* NOTREACHED */
  285. }
  286. /**
  287. * vsscanf - Unformat a buffer into a list of arguments
  288. * @buf: input buffer
  289. * @fmt: format of buffer
  290. * @args: arguments
  291. */
  292. #define BUF 32 /* Maximum length of numeric string. */
  293. /*
  294. * Flags used during conversion.
  295. */
  296. #define LONG 0x01 /* l: long or double */
  297. #define SHORT 0x04 /* h: short */
  298. #define SUPPRESS 0x08 /* suppress assignment */
  299. #define POINTER 0x10 /* weird %p pointer (`fake hex') */
  300. #define NOSKIP 0x20 /* do not skip blanks */
  301. #define QUAD 0x400
  302. #define SHORTSHORT 0x4000 /** hh: char */
  303. /*
  304. * The following are used in numeric conversions only:
  305. * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
  306. * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
  307. */
  308. #define SIGNOK 0x40 /* +/- is (still) legal */
  309. #define NDIGITS 0x80 /* no digits detected */
  310. #define DPTOK 0x100 /* (float) decimal point is still legal */
  311. #define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */
  312. #define PFXOK 0x100 /* 0x prefix is (still) legal */
  313. #define NZDIGITS 0x200 /* no zero digits detected */
  314. /*
  315. * Conversion types.
  316. */
  317. #define CT_CHAR 0 /* %c conversion */
  318. #define CT_CCL 1 /* %[...] conversion */
  319. #define CT_STRING 2 /* %s conversion */
  320. #define CT_INT 3 /* integer, i.e., strtoq or strtouq */
  321. typedef u64 (*ccfntype)(const char *, char **, int);
  322. int
  323. vsscanf(const char *inp, char const *fmt0, va_list ap)
  324. {
  325. int inr;
  326. const u_char *fmt = (const u_char *)fmt0;
  327. int c; /* character from format, or conversion */
  328. size_t width; /* field width, or 0 */
  329. char *p; /* points into all kinds of strings */
  330. int n; /* handy integer */
  331. int flags; /* flags as defined above */
  332. char *p0; /* saves original value of p when necessary */
  333. int nassigned; /* number of fields assigned */
  334. int nconversions; /* number of conversions */
  335. int nread; /* number of characters consumed from fp */
  336. int base; /* base argument to strtoq/strtouq */
  337. ccfntype ccfn; /* conversion function (strtoq/strtouq) */
  338. char ccltab[256]; /* character class table for %[...] */
  339. char buf[BUF]; /* buffer for numeric conversions */
  340. /* `basefix' is used to avoid `if' tests in the integer scanner */
  341. static short basefix[17] = { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
  342. 12, 13, 14, 15, 16 };
  343. inr = strlen(inp);
  344. nassigned = 0;
  345. nconversions = 0;
  346. nread = 0;
  347. base = 0; /* XXX just to keep gcc happy */
  348. ccfn = NULL; /* XXX just to keep gcc happy */
  349. for (;;) {
  350. c = *fmt++;
  351. if (c == 0)
  352. return (nassigned);
  353. if (isspace(c)) {
  354. while (inr > 0 && isspace(*inp))
  355. nread++, inr--, inp++;
  356. continue;
  357. }
  358. if (c != '%')
  359. goto literal;
  360. width = 0;
  361. flags = 0;
  362. /*
  363. * switch on the format. continue if done;
  364. * break once format type is derived.
  365. */
  366. again: c = *fmt++;
  367. switch (c) {
  368. case '%':
  369. literal:
  370. if (inr <= 0)
  371. goto input_failure;
  372. if (*inp != c)
  373. goto match_failure;
  374. inr--, inp++;
  375. nread++;
  376. continue;
  377. case '*':
  378. flags |= SUPPRESS;
  379. goto again;
  380. case 'l':
  381. if (flags & LONG) {
  382. flags &= ~LONG;
  383. flags |= QUAD;
  384. } else {
  385. flags |= LONG;
  386. }
  387. goto again;
  388. case 'q':
  389. flags |= QUAD;
  390. goto again;
  391. case 'h':
  392. if (flags & SHORT) {
  393. flags &= ~SHORT;
  394. flags |= SHORTSHORT;
  395. } else {
  396. flags |= SHORT;
  397. }
  398. goto again;
  399. case '0': case '1': case '2': case '3': case '4':
  400. case '5': case '6': case '7': case '8': case '9':
  401. width = width * 10 + c - '0';
  402. goto again;
  403. /*
  404. * Conversions.
  405. *
  406. */
  407. case 'd':
  408. c = CT_INT;
  409. ccfn = (ccfntype)strtoq;
  410. base = 10;
  411. break;
  412. case 'i':
  413. c = CT_INT;
  414. ccfn = (ccfntype)strtoq;
  415. base = 0;
  416. break;
  417. case 'o':
  418. c = CT_INT;
  419. ccfn = strtouq;
  420. base = 8;
  421. break;
  422. case 'u':
  423. c = CT_INT;
  424. ccfn = strtouq;
  425. base = 10;
  426. break;
  427. case 'x':
  428. flags |= PFXOK; /* enable 0x prefixing */
  429. c = CT_INT;
  430. ccfn = strtouq;
  431. base = 16;
  432. break;
  433. case 's':
  434. c = CT_STRING;
  435. break;
  436. case '[':
  437. fmt = __sccl(ccltab, fmt);
  438. flags |= NOSKIP;
  439. c = CT_CCL;
  440. break;
  441. case 'c':
  442. flags |= NOSKIP;
  443. c = CT_CHAR;
  444. break;
  445. case 'p': /* pointer format is like hex */
  446. flags |= POINTER | PFXOK;
  447. c = CT_INT;
  448. ccfn = strtouq;
  449. base = 16;
  450. break;
  451. case 'n':
  452. nconversions++;
  453. if (flags & SUPPRESS) /* ??? */
  454. continue;
  455. if (flags & SHORTSHORT)
  456. *va_arg(ap, char *) = nread;
  457. else if (flags & SHORT)
  458. *va_arg(ap, short *) = nread;
  459. else if (flags & LONG)
  460. *va_arg(ap, long *) = nread;
  461. else if (flags & QUAD)
  462. *va_arg(ap, s64 *) = nread;
  463. else
  464. *va_arg(ap, int *) = nread;
  465. continue;
  466. }
  467. /*
  468. * We have a conversion that requires input.
  469. */
  470. if (inr <= 0)
  471. goto input_failure;
  472. /*
  473. * Consume leading white space, except for formats
  474. * that suppress this.
  475. */
  476. if ((flags & NOSKIP) == 0) {
  477. while (isspace(*inp)) {
  478. nread++;
  479. if (--inr > 0)
  480. inp++;
  481. else
  482. goto input_failure;
  483. }
  484. /*
  485. * Note that there is at least one character in
  486. * the buffer, so conversions that do not set NOSKIP
  487. * can no longer result in an input failure.
  488. */
  489. }
  490. /*
  491. * Do the conversion.
  492. */
  493. switch (c) {
  494. case CT_CHAR:
  495. /* scan arbitrary characters (sets NOSKIP) */
  496. if (width == 0)
  497. width = 1;
  498. if (flags & SUPPRESS) {
  499. size_t sum = 0;
  500. if ((n = inr) < width) {
  501. sum += n;
  502. width -= n;
  503. inp += n;
  504. if (sum == 0)
  505. goto input_failure;
  506. } else {
  507. sum += width;
  508. inr -= width;
  509. inp += width;
  510. }
  511. nread += sum;
  512. } else {
  513. memcpy(va_arg(ap, char *), inp, width);
  514. inr -= width;
  515. inp += width;
  516. nread += width;
  517. nassigned++;
  518. }
  519. nconversions++;
  520. break;
  521. case CT_CCL:
  522. /* scan a (nonempty) character class (sets NOSKIP) */
  523. if (width == 0)
  524. width = (size_t)~0; /* `infinity' */
  525. /* take only those things in the class */
  526. if (flags & SUPPRESS) {
  527. n = 0;
  528. while (ccltab[(unsigned char)*inp]) {
  529. n++, inr--, inp++;
  530. if (--width == 0)
  531. break;
  532. if (inr <= 0) {
  533. if (n == 0)
  534. goto input_failure;
  535. break;
  536. }
  537. }
  538. if (n == 0)
  539. goto match_failure;
  540. } else {
  541. p = va_arg(ap, char *);
  542. p0 = p;
  543. while (ccltab[(unsigned char)*inp]) {
  544. inr--;
  545. *p++ = *inp++;
  546. if (--width == 0)
  547. break;
  548. if (inr <= 0) {
  549. if (p == p0)
  550. goto input_failure;
  551. break;
  552. }
  553. }
  554. n = p - p0;
  555. if (n == 0)
  556. goto match_failure;
  557. *p = 0;
  558. nassigned++;
  559. }
  560. nread += n;
  561. nconversions++;
  562. break;
  563. case CT_STRING:
  564. /* like CCL, but zero-length string OK, & no NOSKIP */
  565. if (width == 0)
  566. width = (size_t)~0;
  567. if (flags & SUPPRESS) {
  568. n = 0;
  569. while (!isspace(*inp)) {
  570. n++, inr--, inp++;
  571. if (--width == 0)
  572. break;
  573. if (inr <= 0)
  574. break;
  575. }
  576. nread += n;
  577. } else {
  578. p = va_arg(ap, char *);
  579. p0 = p;
  580. while (!isspace(*inp)) {
  581. inr--;
  582. *p++ = *inp++;
  583. if (--width == 0)
  584. break;
  585. if (inr <= 0)
  586. break;
  587. }
  588. *p = 0;
  589. nread += p - p0;
  590. nassigned++;
  591. }
  592. nconversions++;
  593. continue;
  594. case CT_INT:
  595. /* scan an integer as if by strtoq/strtouq */
  596. #ifdef hardway
  597. if (width == 0 || width > sizeof(buf) - 1)
  598. width = sizeof(buf) - 1;
  599. #else
  600. /* size_t is unsigned, hence this optimisation */
  601. if (--width > sizeof(buf) - 2)
  602. width = sizeof(buf) - 2;
  603. width++;
  604. #endif
  605. flags |= SIGNOK | NDIGITS | NZDIGITS;
  606. for (p = buf; width; width--) {
  607. c = *inp;
  608. /*
  609. * Switch on the character; `goto ok'
  610. * if we accept it as a part of number.
  611. */
  612. switch (c) {
  613. /*
  614. * The digit 0 is always legal, but is
  615. * special. For %i conversions, if no
  616. * digits (zero or nonzero) have been
  617. * scanned (only signs), we will have
  618. * base==0. In that case, we should set
  619. * it to 8 and enable 0x prefixing.
  620. * Also, if we have not scanned zero digits
  621. * before this, do not turn off prefixing
  622. * (someone else will turn it off if we
  623. * have scanned any nonzero digits).
  624. */
  625. case '0':
  626. if (base == 0) {
  627. base = 8;
  628. flags |= PFXOK;
  629. }
  630. if (flags & NZDIGITS)
  631. flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
  632. else
  633. flags &= ~(SIGNOK | PFXOK | NDIGITS);
  634. goto ok;
  635. /* 1 through 7 always legal */
  636. case '1': case '2': case '3':
  637. case '4': case '5': case '6': case '7':
  638. base = basefix[base];
  639. flags &= ~(SIGNOK | PFXOK | NDIGITS);
  640. goto ok;
  641. /* digits 8 and 9 ok iff decimal or hex */
  642. case '8': case '9':
  643. base = basefix[base];
  644. if (base <= 8)
  645. break; /* not legal here */
  646. flags &= ~(SIGNOK | PFXOK | NDIGITS);
  647. goto ok;
  648. /* letters ok iff hex */
  649. case 'A': case 'B': case 'C':
  650. case 'D': case 'E': case 'F':
  651. case 'a': case 'b': case 'c':
  652. case 'd': case 'e': case 'f':
  653. /* no need to fix base here */
  654. if (base <= 10)
  655. break; /* not legal here */
  656. flags &= ~(SIGNOK | PFXOK | NDIGITS);
  657. goto ok;
  658. /* sign ok only as first character */
  659. case '+': case '-':
  660. if (flags & SIGNOK) {
  661. flags &= ~SIGNOK;
  662. goto ok;
  663. }
  664. break;
  665. /* x ok iff flag still set & 2nd char */
  666. case 'x': case 'X':
  667. if (flags & PFXOK && p == buf + 1) {
  668. base = 16; /* if %i */
  669. flags &= ~PFXOK;
  670. goto ok;
  671. }
  672. break;
  673. }
  674. /*
  675. * If we got here, c is not a legal character
  676. * for a number. Stop accumulating digits.
  677. */
  678. break;
  679. ok:
  680. /*
  681. * c is legal: store it and look at the next.
  682. */
  683. *p++ = c;
  684. if (--inr > 0)
  685. inp++;
  686. else
  687. break; /* end of input */
  688. }
  689. /*
  690. * If we had only a sign, it is no good; push
  691. * back the sign. If the number ends in `x',
  692. * it was [sign] '' 'x', so push back the x
  693. * and treat it as [sign] ''.
  694. */
  695. if (flags & NDIGITS) {
  696. if (p > buf) {
  697. inp--;
  698. inr++;
  699. }
  700. goto match_failure;
  701. }
  702. c = ((u_char *)p)[-1];
  703. if (c == 'x' || c == 'X') {
  704. --p;
  705. inp--;
  706. inr++;
  707. }
  708. if ((flags & SUPPRESS) == 0) {
  709. u64 res;
  710. *p = 0;
  711. res = (*ccfn)(buf, (char **)NULL, base);
  712. if (flags & POINTER)
  713. *va_arg(ap, void **) =
  714. (void *)(uintptr_t)res;
  715. else if (flags & SHORTSHORT)
  716. *va_arg(ap, char *) = res;
  717. else if (flags & SHORT)
  718. *va_arg(ap, short *) = res;
  719. else if (flags & LONG)
  720. *va_arg(ap, long *) = res;
  721. else if (flags & QUAD)
  722. *va_arg(ap, s64 *) = res;
  723. else
  724. *va_arg(ap, int *) = res;
  725. nassigned++;
  726. }
  727. nread += p - buf;
  728. nconversions++;
  729. break;
  730. }
  731. }
  732. input_failure:
  733. return (nconversions != 0 ? nassigned : -1);
  734. match_failure:
  735. return (nassigned);
  736. }
  737. /**
  738. * sscanf - Unformat a buffer into a list of arguments
  739. * @buf: input buffer
  740. * @fmt: formatting of buffer
  741. * @...: resulting arguments
  742. */
  743. int sscanf(const char *buf, const char *fmt, ...)
  744. {
  745. va_list args;
  746. int i;
  747. va_start(args, fmt);
  748. i = vsscanf(buf, fmt, args);
  749. va_end(args);
  750. return i;
  751. }
  752. #endif