2 * Copyright (c) 2012-2014 ARM Ltd
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the company may not be used to endorse or promote
14 * products derived from this software without specific prior written
17 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 #include "../stdlib/local.h"
45 #include "nano-vfscanf_local.h"
48 _scanf_chars (struct _reent
*rptr
,
49 struct _scan_data_t
*pdata
,
50 FILE *fp
, va_list *ap
)
55 if (pdata
->width
== 0)
56 pdata
->width
= (pdata
->code
== CT_CHAR
) ? 1 : (size_t)~0;
59 if ((pdata
->flags
& SUPPRESS
) == 0)
60 p
= GET_ARG (N
, *ap
, char *);
62 /* It's impossible to have EOF when we get here. */
63 while ((pdata
->code
== CT_CHAR
)
64 || (pdata
->code
== CT_CCL
&& pdata
->ccltab
[*fp
->_p
])
65 || (pdata
->code
== CT_STRING
&& !isspace (*fp
->_p
)))
68 if ((pdata
->flags
& SUPPRESS
) == 0)
72 if (--pdata
->width
== 0)
75 if ((fp
->_r
<= 0 && pdata
->pfn_refill (rptr
, fp
)))
78 /* For CT_CHAR, it is impossible to have input_failure(n == 0) here.
79 For CT_CCL, it is impossible to have input_failure here.
80 For CT_STRING, it is possible to have empty string. */
81 if (n
== 0 && pdata
->code
== CT_CCL
)
84 if ((pdata
->flags
& SUPPRESS
) == 0)
87 if (pdata
->code
!= CT_CHAR
)
94 _scanf_i (struct _reent
*rptr
,
95 struct _scan_data_t
*pdata
,
96 FILE *fp
, va_list *ap
)
98 #define CCFN_PARAMS (struct _reent *, const char *, char **, int)
99 /* Conversion function (strtol/strtoul). */
100 u_long (*ccfn
)CCFN_PARAMS
=0;
103 char *xdigits
= "A-Fa-f8901234567]";
104 char *prefix_chars
[3] = {"+-", "00", "xX"};
106 /* Scan an integer as if by strtol/strtoul. */
107 unsigned width_left
= 0;
110 ccfn
= (pdata
->code
== CT_INT
) ? (u_long (*)CCFN_PARAMS
)_strtol_r
: _strtoul_r
;
112 if (pdata
->width
== 0 || pdata
->width
> BUF
- 1)
114 /* size_t is unsigned, hence this optimisation. */
115 if (pdata
->width
- 1 > BUF
- 2)
118 width_left
= pdata
->width
- (BUF
- 1);
119 pdata
->width
= BUF
- 1;
122 pdata
->flags
|= NDIGITS
| NZDIGITS
| NNZDIGITS
;
124 /* Process [sign] [0] [xX] prefixes sequently. */
125 for (n
= 0; n
< 3; n
++)
127 if (!memchr (prefix_chars
[n
], *fp
->_p
, 2))
132 if (pdata
->base
== 0)
135 pdata
->flags
|= PFXOK
;
137 pdata
->flags
&= ~(NZDIGITS
| NDIGITS
);
141 if ((pdata
->flags
& (PFXOK
| NZDIGITS
)) != PFXOK
)
145 /* We must reset the NZDIGITS and NDIGITS
146 flags that would have been unset by seeing
147 the zero that preceded the X or x.
149 ??? It seems unnecessary to reset the NZDIGITS. */
150 pdata
->flags
|= NDIGITS
;
152 if (pdata
->width
-- > 0)
156 if ((fp
->_r
<= 0 && pdata
->pfn_refill (rptr
, fp
)))
161 if (pdata
->base
== 0)
164 /* The check is un-necessary if xdigits points to exactly the string:
165 "A-Fa-f8901234567]". The code is kept only for reading's sake. */
167 if (pdata
->base
!= 16)
169 xdigits
= xdigits
+ 16 - pdata
->base
;
171 /* Initilize ccltab according to pdata->base. */
172 __sccl (pdata
->ccltab
, (unsigned char *) xdigits
);
173 for (; pdata
->width
; pdata
->width
--)
176 if (pdata
->ccltab
[n
] == 0)
178 else if (n
== '0' && (pdata
->flags
& NNZDIGITS
))
188 pdata
->flags
&= ~(NDIGITS
| NNZDIGITS
);
189 /* Char is legal: store it and look at the next. */
194 else if (pdata
->pfn_refill (rptr
, fp
))
198 /* If we had only a sign, it is no good; push back the sign.
199 If the number ends in `x', it was [sign] '0' 'x', so push back
200 the x and treat it as [sign] '0'.
201 Use of ungetc here and below assumes ASCII encoding; we are only
202 pushing back 7-bit characters, so casting to unsigned char is
205 if (pdata
->flags
& NDIGITS
)
208 pdata
->pfn_ungetc (rptr
, *--p
, fp
); /* "[-+xX]". */
211 return MATCH_FAILURE
;
213 if ((pdata
->flags
& SUPPRESS
) == 0)
217 ul
= (*ccfn
) (rptr
, pdata
->buf
, (char **) NULL
, pdata
->base
);
218 if (pdata
->flags
& POINTER
)
219 *GET_ARG (N
, *ap
, void **) = (void *) (uintptr_t) ul
;
220 else if (pdata
->flags
& SHORT
)
221 *GET_ARG (N
, *ap
, short *) = ul
;
222 else if (pdata
->flags
& LONG
)
223 *GET_ARG (N
, *ap
, long *) = ul
;
225 *GET_ARG (N
, *ap
, int *) = ul
;
229 pdata
->nread
+= p
- pdata
->buf
+ skips
;