sscanf.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  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. n = inr;
  501. if (n < width) {
  502. sum += n;
  503. width -= n;
  504. inp += n;
  505. if (sum == 0)
  506. goto input_failure;
  507. } else {
  508. sum += width;
  509. inr -= width;
  510. inp += width;
  511. }
  512. nread += sum;
  513. } else {
  514. memcpy(va_arg(ap, char *), inp, width);
  515. inr -= width;
  516. inp += width;
  517. nread += width;
  518. nassigned++;
  519. }
  520. nconversions++;
  521. break;
  522. case CT_CCL:
  523. /* scan a (nonempty) character class (sets NOSKIP) */
  524. if (width == 0)
  525. width = (size_t)~0; /* `infinity' */
  526. /* take only those things in the class */
  527. if (flags & SUPPRESS) {
  528. n = 0;
  529. while (ccltab[(unsigned char)*inp]) {
  530. n++, inr--, inp++;
  531. if (--width == 0)
  532. break;
  533. if (inr <= 0) {
  534. if (n == 0)
  535. goto input_failure;
  536. break;
  537. }
  538. }
  539. if (n == 0)
  540. goto match_failure;
  541. } else {
  542. p = va_arg(ap, char *);
  543. p0 = p;
  544. while (ccltab[(unsigned char)*inp]) {
  545. inr--;
  546. *p++ = *inp++;
  547. if (--width == 0)
  548. break;
  549. if (inr <= 0) {
  550. if (p == p0)
  551. goto input_failure;
  552. break;
  553. }
  554. }
  555. n = p - p0;
  556. if (n == 0)
  557. goto match_failure;
  558. *p = 0;
  559. nassigned++;
  560. }
  561. nread += n;
  562. nconversions++;
  563. break;
  564. case CT_STRING:
  565. /* like CCL, but zero-length string OK, & no NOSKIP */
  566. if (width == 0)
  567. width = (size_t)~0;
  568. if (flags & SUPPRESS) {
  569. n = 0;
  570. while (!isspace(*inp)) {
  571. n++, inr--, inp++;
  572. if (--width == 0)
  573. break;
  574. if (inr <= 0)
  575. break;
  576. }
  577. nread += n;
  578. } else {
  579. p = va_arg(ap, char *);
  580. p0 = p;
  581. while (!isspace(*inp)) {
  582. inr--;
  583. *p++ = *inp++;
  584. if (--width == 0)
  585. break;
  586. if (inr <= 0)
  587. break;
  588. }
  589. *p = 0;
  590. nread += p - p0;
  591. nassigned++;
  592. }
  593. nconversions++;
  594. continue;
  595. case CT_INT:
  596. /* scan an integer as if by strtoq/strtouq */
  597. #ifdef hardway
  598. if (width == 0 || width > sizeof(buf) - 1)
  599. width = sizeof(buf) - 1;
  600. #else
  601. /* size_t is unsigned, hence this optimisation */
  602. if (--width > sizeof(buf) - 2)
  603. width = sizeof(buf) - 2;
  604. width++;
  605. #endif
  606. flags |= SIGNOK | NDIGITS | NZDIGITS;
  607. for (p = buf; width; width--) {
  608. c = *inp;
  609. /*
  610. * Switch on the character; `goto ok'
  611. * if we accept it as a part of number.
  612. */
  613. switch (c) {
  614. /*
  615. * The digit 0 is always legal, but is
  616. * special. For %i conversions, if no
  617. * digits (zero or nonzero) have been
  618. * scanned (only signs), we will have
  619. * base==0. In that case, we should set
  620. * it to 8 and enable 0x prefixing.
  621. * Also, if we have not scanned zero digits
  622. * before this, do not turn off prefixing
  623. * (someone else will turn it off if we
  624. * have scanned any nonzero digits).
  625. */
  626. case '0':
  627. if (base == 0) {
  628. base = 8;
  629. flags |= PFXOK;
  630. }
  631. if (flags & NZDIGITS)
  632. flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
  633. else
  634. flags &= ~(SIGNOK | PFXOK | NDIGITS);
  635. goto ok;
  636. /* 1 through 7 always legal */
  637. case '1': case '2': case '3':
  638. case '4': case '5': case '6': case '7':
  639. base = basefix[base];
  640. flags &= ~(SIGNOK | PFXOK | NDIGITS);
  641. goto ok;
  642. /* digits 8 and 9 ok iff decimal or hex */
  643. case '8': case '9':
  644. base = basefix[base];
  645. if (base <= 8)
  646. break; /* not legal here */
  647. flags &= ~(SIGNOK | PFXOK | NDIGITS);
  648. goto ok;
  649. /* letters ok iff hex */
  650. case 'A': case 'B': case 'C':
  651. case 'D': case 'E': case 'F':
  652. case 'a': case 'b': case 'c':
  653. case 'd': case 'e': case 'f':
  654. /* no need to fix base here */
  655. if (base <= 10)
  656. break; /* not legal here */
  657. flags &= ~(SIGNOK | PFXOK | NDIGITS);
  658. goto ok;
  659. /* sign ok only as first character */
  660. case '+': case '-':
  661. if (flags & SIGNOK) {
  662. flags &= ~SIGNOK;
  663. goto ok;
  664. }
  665. break;
  666. /* x ok iff flag still set & 2nd char */
  667. case 'x': case 'X':
  668. if (flags & PFXOK && p == buf + 1) {
  669. base = 16; /* if %i */
  670. flags &= ~PFXOK;
  671. goto ok;
  672. }
  673. break;
  674. }
  675. /*
  676. * If we got here, c is not a legal character
  677. * for a number. Stop accumulating digits.
  678. */
  679. break;
  680. ok:
  681. /*
  682. * c is legal: store it and look at the next.
  683. */
  684. *p++ = c;
  685. if (--inr > 0)
  686. inp++;
  687. else
  688. break; /* end of input */
  689. }
  690. /*
  691. * If we had only a sign, it is no good; push
  692. * back the sign. If the number ends in `x',
  693. * it was [sign] '' 'x', so push back the x
  694. * and treat it as [sign] ''.
  695. */
  696. if (flags & NDIGITS) {
  697. if (p > buf) {
  698. inp--;
  699. inr++;
  700. }
  701. goto match_failure;
  702. }
  703. c = ((u_char *)p)[-1];
  704. if (c == 'x' || c == 'X') {
  705. --p;
  706. inp--;
  707. inr++;
  708. }
  709. if ((flags & SUPPRESS) == 0) {
  710. u64 res;
  711. *p = 0;
  712. res = (*ccfn)(buf, (char **)NULL, base);
  713. if (flags & POINTER)
  714. *va_arg(ap, void **) =
  715. (void *)(uintptr_t)res;
  716. else if (flags & SHORTSHORT)
  717. *va_arg(ap, char *) = res;
  718. else if (flags & SHORT)
  719. *va_arg(ap, short *) = res;
  720. else if (flags & LONG)
  721. *va_arg(ap, long *) = res;
  722. else if (flags & QUAD)
  723. *va_arg(ap, s64 *) = res;
  724. else
  725. *va_arg(ap, int *) = res;
  726. nassigned++;
  727. }
  728. nread += p - buf;
  729. nconversions++;
  730. break;
  731. }
  732. }
  733. input_failure:
  734. return (nconversions != 0 ? nassigned : -1);
  735. match_failure:
  736. return (nassigned);
  737. }
  738. /**
  739. * sscanf - Unformat a buffer into a list of arguments
  740. * @buf: input buffer
  741. * @fmt: formatting of buffer
  742. * @...: resulting arguments
  743. */
  744. int sscanf(const char *buf, const char *fmt, ...)
  745. {
  746. va_list args;
  747. int i;
  748. va_start(args, fmt);
  749. i = vsscanf(buf, fmt, args);
  750. va_end(args);
  751. return i;
  752. }
  753. #endif