source: trunk/libs/newlib/src/newlib/libc/stdio/nano-vfscanf_i.c @ 567

Last change on this file since 567 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2012-2014 ARM Ltd
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
15 *    permission.
16 *
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.
27 */
28
29#include <_ansi.h>
30#include <reent.h>
31#include <newlib.h>
32#include <ctype.h>
33#include <wctype.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <stdint.h>
37#include <limits.h>
38#include <wchar.h>
39#include <string.h>
40#include <stdarg.h>
41#include <errno.h>
42#include "local.h"
43#include "../stdlib/local.h"
44
45#include "nano-vfscanf_local.h"
46
47int
48_scanf_chars (struct _reent *rptr,
49              struct _scan_data_t *pdata,
50              FILE *fp, va_list *ap)
51{
52  int n;
53  char *p;
54
55  if (pdata->width == 0)
56    pdata->width = (pdata->code == CT_CHAR) ? 1 : (size_t)~0;
57
58  n = 0;
59  if ((pdata->flags & SUPPRESS) == 0)
60    p = GET_ARG (N, *ap, char *);
61
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)))
66    {
67      n++;
68      if ((pdata->flags & SUPPRESS) == 0)
69        *p++ = *fp->_p;
70       
71      fp->_r--, fp->_p++;
72      if (--pdata->width == 0)
73        break;
74
75      if ((fp->_r <= 0 && pdata->pfn_refill (rptr, fp)))
76        break;
77    }
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)
82    return MATCH_FAILURE;
83
84  if ((pdata->flags & SUPPRESS) == 0)
85    {
86      pdata->nassigned++;
87      if (pdata->code != CT_CHAR)
88        *p = 0;
89    }
90  pdata->nread += n;
91  return 0;
92}
93int
94_scanf_i (struct _reent *rptr,
95          struct _scan_data_t *pdata,
96          FILE *fp, va_list *ap)
97{
98#define CCFN_PARAMS     (struct _reent *, const char *, char **, int)
99  /* Conversion function (strtol/strtoul).  */
100  u_long (*ccfn)CCFN_PARAMS=0;
101  char *p;
102  int n;
103  char *xdigits = "A-Fa-f8901234567]";
104  char *prefix_chars[3] = {"+-", "00", "xX"};
105
106  /* Scan an integer as if by strtol/strtoul.  */
107  unsigned width_left = 0;
108  int skips = 0;
109
110  ccfn = (pdata->code == CT_INT) ? (u_long (*)CCFN_PARAMS)_strtol_r : _strtoul_r;
111#ifdef hardway
112  if (pdata->width == 0 || pdata->width > BUF - 1)
113#else
114  /* size_t is unsigned, hence this optimisation.  */
115  if (pdata->width - 1 > BUF - 2)
116#endif
117    {
118      width_left = pdata->width - (BUF - 1);
119      pdata->width = BUF - 1;
120    }
121  p = pdata->buf;
122  pdata->flags |= NDIGITS | NZDIGITS | NNZDIGITS;
123
124  /* Process [sign] [0] [xX] prefixes sequently.  */
125  for (n = 0; n < 3; n++)
126    {
127      if (!memchr (prefix_chars[n], *fp->_p, 2))
128        continue;
129
130      if (n == 1)
131        {
132          if (pdata->base == 0)
133            {
134              pdata->base = 8;
135              pdata->flags |= PFXOK;
136            }
137          pdata->flags &= ~(NZDIGITS | NDIGITS);
138        }
139      else if (n == 2)
140        {
141          if ((pdata->flags & (PFXOK | NZDIGITS)) != PFXOK)
142            continue;
143          pdata->base = 16;
144
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.
148
149             ??? It seems unnecessary to reset the NZDIGITS.  */
150          pdata->flags |= NDIGITS;
151        }
152      if (pdata->width-- > 0)
153        {
154          *p++ = *fp->_p++;
155          fp->_r--;
156          if ((fp->_r <= 0 && pdata->pfn_refill (rptr, fp)))
157            goto match_end;
158        }
159    }
160
161  if (pdata->base == 0)
162    pdata->base = 10;
163
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.  */
166#if 0
167  if (pdata->base != 16)
168#endif
169  xdigits = xdigits + 16 - pdata->base;
170
171  /* Initilize ccltab according to pdata->base.  */
172  __sccl (pdata->ccltab, (unsigned char *) xdigits);
173  for (; pdata->width; pdata->width--)
174    {
175      n = *fp->_p;
176      if (pdata->ccltab[n] == 0)
177        break;
178      else if (n == '0' && (pdata->flags & NNZDIGITS))
179        {
180          ++skips;
181          if (width_left)
182            {
183              width_left--;
184              pdata->width++;
185            }
186          goto skip;
187        }
188      pdata->flags &= ~(NDIGITS | NNZDIGITS);
189      /* Char is legal: store it and look at the next.  */
190      *p++ = *fp->_p;
191skip:
192      if (--fp->_r > 0)
193        fp->_p++;
194      else if (pdata->pfn_refill (rptr, fp))
195        /* "EOF".  */
196        break;
197    }
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
203     not necessary.  */
204match_end:
205  if (pdata->flags & NDIGITS)
206    {
207      if (p > pdata->buf)
208        pdata->pfn_ungetc (rptr, *--p, fp); /* "[-+xX]".  */
209
210      if (p == pdata->buf)
211        return MATCH_FAILURE;
212    }
213  if ((pdata->flags & SUPPRESS) == 0)
214    {
215      u_long ul;
216      *p = 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;
224      else
225        *GET_ARG (N, *ap, int *) = ul;
226     
227      pdata->nassigned++;
228    }
229  pdata->nread += p - pdata->buf + skips;
230  return 0;
231}
232
Note: See TracBrowser for help on using the repository browser.