4 * vsscanf(), from which the rest of the scanf()
8 * The Regents of the University of California. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 #define LONG_BIT (CHAR_BIT*sizeof(long))
52 FL_SPLAT
= 0x01, /* Drop the value, do not assign */
53 FL_INV
= 0x02, /* Character-set with inverse */
54 FL_WIDTH
= 0x04, /* Field width specified */
55 FL_MINUS
= 0x08, /* Negative number */
64 rank_ptr
= INT_MAX
/* Special value used for pointers */
67 #define MIN_RANK rank_char
68 #define MAX_RANK rank_longlong
70 #define INTMAX_RANK rank_longlong
71 #define SIZE_T_RANK rank_long
72 #define PTRDIFF_T_RANK rank_long
75 bail_none
= 0, /* No error condition */
76 bail_eof
, /* Hit EOF */
77 bail_err
/* Conversion mismatch */
80 static inline const char *skipspace(const char *p
)
82 while (isspace((unsigned char)*p
))
88 static inline void set_bit(unsigned long *bitmap
, unsigned int bit
)
90 bitmap
[bit
/ LONG_BIT
] |= 1UL << (bit
% LONG_BIT
);
94 static inline int test_bit(unsigned long *bitmap
, unsigned int bit
)
96 return (int)(bitmap
[bit
/ LONG_BIT
] >> (bit
% LONG_BIT
)) & 1;
99 int vsscanf(const char *buffer
, const char *format
, va_list ap
)
101 const char *p
= format
;
104 const char *q
= buffer
;
107 int rank
= rank_int
; /* Default rank */
108 unsigned int width
= UINT_MAX
;
110 enum flags flags
= 0;
112 st_normal
, /* Ground state */
113 st_flags
, /* Special flags */
114 st_width
, /* Field width */
115 st_modifiers
, /* Length or conversion modifiers */
116 st_match_init
, /* Initial state of %[ sequence */
117 st_match
, /* Main state of %[ sequence */
118 st_match_range
, /* After - in a %[ sequence */
120 char *sarg
= NULL
; /* %s %c or %[ string argument */
121 enum bail bail
= bail_none
;
123 int converted
= 0; /* Successful conversions */
124 unsigned long matchmap
[((1 << CHAR_BIT
) + (LONG_BIT
- 1)) / LONG_BIT
];
125 int matchinv
= 0; /* Is match map inverted? */
126 unsigned char range_start
= 0;
128 while ((ch
= *p
++) && !bail
) {
136 } else if (isspace((unsigned char)ch
)) {
142 bail
= bail_err
; /* Match failure */
157 state
= st_modifiers
;
158 p
--; /* Process this character again */
164 if (ch
>= '0' && ch
<= '9') {
165 width
= width
* 10 + (ch
- '0');
167 state
= st_modifiers
;
168 p
--; /* Process this character again */
174 /* Length modifiers - nonterminal sequences */
176 rank
--; /* Shorter rank */
179 rank
++; /* Longer rank */
188 rank
= PTRDIFF_T_RANK
;
192 rank
= rank_longlong
; /* long double/long long */
196 /* Output modifiers - terminal sequences */
197 /* Next state will be normal */
200 /* Canonicalize rank */
203 else if (rank
> MAX_RANK
)
207 case 'P': /* Upper case pointer */
208 case 'p': /* Pointer */
214 case 'i': /* Base-independent integer */
219 case 'd': /* Decimal integer */
224 case 'o': /* Octal integer */
229 case 'u': /* Unsigned decimal integer */
234 case 'x': /* Hexadecimal integer */
240 case 'n': /* # of characters consumed */
251 strntoumax(q
, (char **)&qq
, base
,
258 if (!(flags
& FL_SPLAT
))
263 if (!(flags
& FL_SPLAT
)) {
291 *va_arg(ap
, void **) =
299 case 'c': /* Character */
300 /* Default width == 1 */
301 width
= (flags
& FL_WIDTH
) ? width
: 1;
302 if (flags
& FL_SPLAT
) {
310 sarg
= va_arg(ap
, char *);
323 case 's': /* String */
324 uc
= 1; /* Anything nonzero */
325 if (flags
& FL_SPLAT
) {
326 while (width
-- && (uc
= *q
) &&
332 sp
= sarg
= va_arg(ap
, char *);
333 while (width
-- && (uc
= *q
) &&
339 /* Terminate output */
348 case '[': /* Character range */
349 sarg
= (flags
& FL_SPLAT
) ? NULL
350 : va_arg(ap
, char *);
351 state
= st_match_init
;
353 memset(matchmap
, 0, sizeof matchmap
);
356 case '%': /* %% sequence */
363 default: /* Anything else */
364 /* Unknown sequence */
371 case st_match_init
: /* Initial state for %[ match */
372 if (ch
== '^' && !(flags
& FL_INV
)) {
375 set_bit(matchmap
, (unsigned char)ch
);
380 case st_match
: /* Main state for %[ match */
383 } else if (ch
== '-') {
384 range_start
= (unsigned char)ch
;
385 state
= st_match_range
;
387 set_bit(matchmap
, (unsigned char)ch
);
391 case st_match_range
: /* %[ match after - */
393 /* - was last character */
394 set_bit(matchmap
, (unsigned char)'-');
398 for (i
= range_start
; i
< (unsigned char)ch
;
400 set_bit(matchmap
, i
);
405 match_run
: /* Match expression finished */
407 uc
= 1; /* Anything nonzero */
408 while (width
&& (uc
= *q
)
409 && test_bit(matchmap
, uc
)^matchinv
) {
414 if (q
!= qq
&& sarg
) {
426 if (bail
== bail_eof
&& !converted
)
427 converted
= -1; /* Return EOF (-1) */