1 /* Copyright (c) 2002,2004,2005 Joerg Wunsch
2    Copyright (c) 2008  Dmitry Xmelkov
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 are met:
7 
8    * Redistributions of source code must retain the above copyright
9      notice, this list of conditions and the following disclaimer.
10 
11    * Redistributions in binary form must reproduce the above copyright
12      notice, this list of conditions and the following disclaimer in
13      the documentation and/or other materials provided with the
14      distribution.
15 
16    * Neither the name of the copyright holders nor the names of
17      contributors may be used to endorse or promote products derived
18      from this software without specific prior written permission.
19 
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   POSSIBILITY OF SUCH DAMAGE.
31 */
32 
33 #include "scanf_private.h"
34 #include "../../libm/common/math_config.h"
35 
36 static const char pstr_nfinity[] = "nfinity";
37 static const char pstr_an[] = "an";
38 
39 #if defined(STRTOD) || defined(STRTOF) || defined(STRTOLD)
40 # define CHECK_WIDTH()   1
41 # define CHECK_RANGE(flt) do {                                          \
42         if (CHECK_LONG()) {                                             \
43             if ((double) flt == 0.0 || (double) flt == (double) INFINITY) \
44                 errno = ERANGE;                                         \
45         } else if (CHECK_LONG_LONG()) {                                 \
46             if (flt == (FLOAT) 0.0 || flt == (FLOAT) INFINITY)          \
47                 errno = ERANGE;                                         \
48         } else {                                                        \
49             if ((float) flt == 0.0f || (float) flt == (float) INFINITY) \
50                 errno = ERANGE;                                         \
51         }                                                               \
52     } while (0);
53 # ifdef STRTOD
54 #  define CHECK_LONG()          1
55 #  define CHECK_LONG_LONG()     0
56 #  define FLOAT_MIN             __DBL_MIN__
57 #  define FLOAT_MANT_DIG        __DBL_MANT_DIG__
58 #  define FLOAT_MAX_EXP         __DBL_MAX_EXP__
59 #  define FLOAT_MIN_EXP         __DBL_MIN_EXP__
60 #  define ASFLOAT(x)            _asdouble(x)
61 #  define TOFLOAT(x)            ((double) (x))
62 # elif defined(STRTOLD)
63 #  define CHECK_LONG()          0
64 #  define CHECK_LONG_LONG()     1
65 #  define FLOAT_MIN             __LDBL_MIN__
66 #  define FLOAT_MANT_DIG        __LDBL_MANT_DIG__
67 #  define FLOAT_MAX_EXP         __LDBL_MAX_EXP__
68 #  define FLOAT_MIN_EXP         __LDBL_MIN_EXP__
69 #  define ASFLOAT(x)            aslongdouble(x)
70 #  define TOFLOAT(x)            _u128_to_ld(x)
71 typedef long double FLOAT;
72 typedef _u128 UINTFLOAT;
73 #define UINTFLOAT_128
74 # else
75 #  define CHECK_LONG()          0
76 #  define CHECK_LONG_LONG()     0
77 #  define PICOLIBC_FLOAT_PRINTF_SCANF
78 #  define FLOAT_MIN             __FLT_MIN__
79 #  define FLOAT_MANT_DIG        __FLT_MANT_DIG__
80 #  define FLOAT_MAX_EXP         __FLT_MAX_EXP__
81 #  define FLOAT_MIN_EXP         __FLT_MIN_EXP__
82 #  define ASFLOAT(x)            _asfloat(x)
83 #  define TOFLOAT(x)            ((float) (x))
84 # endif
85 
86 #define FLT_STREAM const char
87 
scanf_getc(const char * s,int * lenp)88 static inline int scanf_getc(const char *s, int *lenp)
89 {
90     int l = *lenp;
91     int c = s[l];
92     *lenp = l + 1;
93     return c;
94 }
95 
scanf_ungetc(int c,const char * s,int * lenp)96 static inline void scanf_ungetc(int c, const char *s, int *lenp)
97 {
98     (void) c;
99     (void) s;
100     *lenp = *lenp - 1;
101 }
102 
103 #undef EOF
104 #define EOF -1
105 
106 #else
107 # define CHECK_WIDTH()   (--width != 0)
108 # define CHECK_RANGE(flt)
109 # ifdef PICOLIBC_FLOAT_PRINTF_SCANF
110 #  define CHECK_LONG()    0
111 #  define CHECK_LONG_LONG()     0
112 #  define FLOAT_MANT_DIG        __FLT_MANT_DIG__
113 #  define FLOAT_MAX_EXP         __FLT_MAX_EXP__
114 #  define FLOAT_MIN_EXP         __FLT_MIN_EXP__
115 #  define ASFLOAT(x) _asfloat(x)
116 #  define TOFLOAT(x) ((float) (x))
117 # else
118 #  if __SIZEOF_LONG_DOUBLE__ == __SIZEOF_DOUBLE__
119 #   define CHECK_LONG()         (flags & (FL_LONG|FL_LONGLONG))
120 #   define CHECK_LONG_LONG()    0
121 #  else
122 #   define CHECK_LONG()    (flags & FL_LONG)
123 #   if defined(_WANT_IO_LONG_DOUBLE)
124 #    define CHECK_LONG_LONG()     (flags & FL_LONGLONG)
125 #    define FLOAT_MANT_DIG        __LDBL_MANT_DIG__
126 #    define FLOAT_MAX_EXP         __LDBL_MAX_EXP__
127 #    define FLOAT_MIN_EXP         __LDBL_MIN_EXP__
128 #    define UINTFLOAT_128
129 
130 typedef long double FLOAT;
131 typedef _u128 UINTFLOAT;
132 
133 #    define ASFLOAT(x) aslongdouble(x)
134 #    define TOFLOAT(x) _u128_to_ld(x)
135 #   else
136 #    define CHECK_LONG_LONG()     0
137 #   endif
138 #  endif
139 #  if __SIZEOF_LONG_DOUBLE__ == __SIZEOF_DOUBLE__ || !defined(_WANT_IO_LONG_DOUBLE)
140 #   define FLOAT_MANT_DIG        __DBL_MANT_DIG__
141 #   define FLOAT_MAX_EXP         __DBL_MAX_EXP__
142 #   define FLOAT_MIN_EXP         __DBL_MIN_EXP__
143 #   define ASFLOAT(x) _asdouble(x)
144 #   define TOFLOAT(x) ((double) (x))
145 #  endif
146 # endif
147 #endif
148 
149 #ifdef UINTFLOAT_128
150 #define U32_TO_UF(x)    to_u128(x)
151 #define U64_TO_UF(x)    to_u128(x)
152 #define U128_TO_UF(x)   (x)
153 #define UF_TO_U32(x)    from_u128(x)
154 #define UF_TO_U64(x)    from_u128(x)
155 #define UF_TO_U128(x)   (x)
156 #define UF_IS_ZERO(x)   _u128_is_zero(x)
157 #define UF_TIMES_BASE(a,b)      _u128_times_base(a,b)
158 #define UF_PLUS_DIGIT(a,b)      _u128_plus_64(a,b)
159 #define UF_RSHIFT(a,b)          _u128_rshift(a,b)
160 #define UF_LSHIFT(a,b)          _u128_lshift(a,b)
161 #define UF_LSHIFT_64(a,b)       _u128_lshift_64(a,b)
162 #define UF_LT(a,b)              _u128_lt(a,b)
163 #define UF_GE(a,b)              _u128_ge(a,b)
164 #define UF_OR_64(a,b)           _u128_or_64(a,b)
165 #define UF_AND_64(a,b)          _u128_and_64(a,b)
166 #define UF_AND(a,b)             _u128_and(a,b)
167 #define UF_NOT(a)               _u128_not(a)
168 #define UF_OR(a,b)              _u128_or(a,b)
169 #else
170 #define U32_TO_UF(x)    (x)
171 #define U64_TO_UF(x)    (x)
172 #define U128_TO_UF(x)   from_u128(x)
173 #define UF_TO_U32(x)    (x)
174 #define UF_TO_U64(x)    (x)
175 #define UF_TO_U128(x)   to_u128(x)
176 #define UF_IS_ZERO(x)   ((x) == 0)
177 #define UF_TIMES_BASE(a,b)      ((a) * (b))
178 #define UF_PLUS_DIGIT(a,b)      ((a) + (b))
179 #define UF_RSHIFT(a,b)          ((a) >> (b))
180 #define UF_LSHIFT(a,b)          ((a) << (b))
181 #define UF_LSHIFT_64(a,b)       ((UINTFLOAT) (a) << (b))
182 #define UF_LT(a,b)              ((a) < (b))
183 #define UF_GE(a,b)              ((a) >= (b))
184 #define UF_OR_64(a,b)           ((a) | (b))
185 #define UF_AND_64(a,b)          ((a) & (b))
186 #define UF_AND(a,b)             ((a) & (b))
187 #define UF_NOT(a)               (~(a))
188 #define UF_OR(a,b)              ((a) | (b))
189 #endif
190 
191 #ifndef UINTFLOAT_128
192 #include "dtoa_engine.h"
193 #endif
194 
195 static unsigned char
conv_flt(FLT_STREAM * stream,int * lenp,width_t width,void * addr,uint16_t flags)196 conv_flt (FLT_STREAM *stream, int *lenp, width_t width, void *addr, uint16_t flags)
197 {
198     UINTFLOAT uint;
199     unsigned int overflow = 0;
200     int uintdigits = 0;
201     FLOAT flt;
202     int i;
203     const char *p;
204     int exp;
205 
206     i = scanf_getc (stream, lenp);		/* after scanf_ungetc()	*/
207 
208     switch ((unsigned char)i) {
209     case '-':
210         flags |= FL_MINUS;
211 	FALLTHROUGH;
212     case '+':
213 	if (!CHECK_WIDTH() || (i = scanf_getc (stream, lenp)) < 0)
214 	    return 0;
215     }
216 
217     switch (TOLOWER (i)) {
218     case 'n':
219 	p = pstr_an;
220         flt = (FLOAT) NAN;
221         goto operate_pstr;
222 
223     case 'i':
224 	p = pstr_nfinity;
225         flt = (FLOAT) INFINITY;
226     operate_pstr:
227         {
228 	    unsigned char c;
229 
230 	    while ((c = *p++) != 0) {
231 		if (CHECK_WIDTH()) {
232                     if ((i = scanf_getc (stream, lenp)) >= 0) {
233                         if ((unsigned char)TOLOWER(i) == c)
234                             continue;
235                         scanf_ungetc (i, stream, lenp);
236                     }
237 		    if (p == pstr_nfinity + 3)
238 			break;
239 		    return 0;
240 		}
241 	    }
242         }
243 	break;
244 
245     default:
246         exp = 0;
247 	uint = U32_TO_UF(0);
248 #define uintdigitsmax_10_float  8
249 #define uintdigitsmax_10_double 16
250 #define uintdigitsmax_10_long_double    32
251 #define uintdigitsmax_16_float  7
252 #define uintdigitsmax_16_double 15
253 #define uintdigitsmax_16_long_double    30
254 
255 #ifdef _WANT_IO_C99_FORMATS
256         int base = 10;
257 #else
258 #define base 10
259 #endif
260 
261 #define uintdigitsmax                                                   \
262         ((base) == 10 ?                                                 \
263             (CHECK_LONG() ?                                             \
264              uintdigitsmax_10_double :                                  \
265              (CHECK_LONG_LONG() ? uintdigitsmax_10_long_double :        \
266               uintdigitsmax_10_float)) :                                \
267             (CHECK_LONG() ?                                             \
268              uintdigitsmax_16_double :                                  \
269              (CHECK_LONG_LONG() ? uintdigitsmax_16_long_double :        \
270               uintdigitsmax_16_float)))
271 
272 	do {
273 
274 	    unsigned char c;
275 
276 #ifdef _WANT_IO_C99_FORMATS
277             if ((flags & FL_FHEX) && (c = TOLOWER(i) - 'a') <= 5)
278                 c += 10;
279             else
280 #endif
281                 c = i - '0';
282 
283 	    if (c < base) {
284 		flags |= FL_ANY;
285 		if (flags & FL_OVFL) {
286                     overflow |= (c != 0);
287 		    if (!(flags & FL_DOT))
288 			exp += 1;
289 		} else {
290 		    if (flags & FL_DOT)
291 			exp -= 1;
292                     uint = UF_PLUS_DIGIT(UF_TIMES_BASE(uint, base), c);
293 		    if (!UF_IS_ZERO(uint)) {
294 			uintdigits++;
295                         if (uintdigits > uintdigitsmax)
296                             flags |= FL_OVFL;
297 		    }
298 	        }
299 
300 	    } else if (c == (('.'-'0') & 0xff) && !(flags & FL_DOT)) {
301 		flags |= FL_DOT;
302 #ifdef _WANT_IO_C99_FORMATS
303             } else if (TOLOWER(i) == 'x' && (flags & FL_ANY) && UF_IS_ZERO(uint)) {
304                 flags |= FL_FHEX;
305                 base = 16;
306 #endif
307 	    } else {
308 		break;
309 	    }
310 	} while (CHECK_WIDTH() && (i = scanf_getc (stream, lenp)) >= 0);
311 
312 	if (!(flags & FL_ANY))
313 	    return 0;
314 
315 #ifdef _WANT_IO_C99_FORMATS
316         int exp_match = (flags & FL_FHEX) ? 'p' : 'e';
317 #else
318 #define exp_match 'e'
319 #endif
320 	if (TOLOWER(i) == exp_match)
321 	{
322             int esign, edig;
323 	    int expacc;
324 
325 	    if (!CHECK_WIDTH())
326                 goto no_exp;
327 
328             esign = scanf_getc (stream, lenp);
329 
330 	    switch ((unsigned char)esign) {
331             case '-':
332 		flags |= FL_MEXP;
333 		FALLTHROUGH;
334             case '+':
335                 if (!CHECK_WIDTH()) {
336                     scanf_ungetc(esign, stream, lenp);
337                     goto no_exp;
338                 }
339 		edig = scanf_getc (stream, lenp);		/* test EOF will below	*/
340                 break;
341             default:
342                 edig = esign;
343                 esign = EOF;
344                 break;
345 	    }
346 
347 	    if (!ISDIGIT (edig))
348             {
349                 scanf_ungetc(edig, stream, lenp);
350                 if (esign != EOF)
351                     scanf_ungetc(esign, stream, lenp);
352                 goto no_exp;
353             }
354 
355             i = edig;
356 	    expacc = 0;
357 #define MAX_POSSIBLE_EXP        (FLOAT_MAX_EXP + FLOAT_MANT_DIG * 4)
358 	    do {
359                 if (expacc < MAX_POSSIBLE_EXP)
360                     expacc = expacc * 10 + (i - '0');
361 	    } while (CHECK_WIDTH() && ISDIGIT (i = scanf_getc(stream, lenp)));
362 	    if (flags & FL_MEXP)
363 		expacc = -expacc;
364 #ifdef _WANT_IO_C99_FORMATS
365             if (flags & FL_FHEX)
366                 exp *= 4;
367 #endif
368             exp += expacc;
369 	}
370 
371     no_exp:
372 	if (width)
373             scanf_ungetc (i, stream, lenp);
374 
375 	if (UF_IS_ZERO(uint)) {
376 	    flt = (FLOAT) 0;
377 	    break;
378 	}
379 
380 #ifdef _WANT_IO_C99_FORMATS
381         if (flags & FL_FHEX)
382         {
383             int sig_bits;
384             int min_exp;
385 
386             if (CHECK_LONG()) {
387                 sig_bits = __DBL_MANT_DIG__;
388                 min_exp = __DBL_MIN_EXP__ - 1;
389             } else if (CHECK_LONG_LONG()) {
390                 sig_bits = __LDBL_MANT_DIG__;
391                 min_exp = __LDBL_MIN_EXP__ - 1;
392             } else {
393                 sig_bits = __FLT_MANT_DIG__;
394                 min_exp = __FLT_MIN_EXP__ - 1;
395             }
396 
397             /* We're using two guard bits, one for the
398              * 'half' value and the second to indicate whether
399              * there is any non-zero value beyond that
400              */
401             exp += (sig_bits + 2 - 1);
402 
403             /* Make significand larger than 1.0 */
404             while (UF_LT(uint, UF_LSHIFT_64(1, (sig_bits + 2 - 1)))) {
405                 uint = UF_LSHIFT(uint, 1);
406                 exp--;
407             }
408 
409             /* Now shift right until the exponent is in range and the
410              * value is less than 2.0. Capture any value > 0.5 in the
411              * LSB of uint.  This may generate a denorm.
412              */
413             while (UF_GE(uint, UF_LSHIFT_64(1, (sig_bits + 2))) || exp < min_exp) {
414                 /* squash extra bits into  the second guard bit */
415                 uint = UF_OR_64(UF_RSHIFT(uint, 1), UF_AND_64(uint, 1));
416                 exp++;
417             }
418 
419             /* Mix in the overflow bit computed while scanning the
420              * string
421              */
422             uint = UF_OR_64(uint, overflow);
423 
424             /* Round even */
425             if (UF_AND_64(uint, 3) == 3 || UF_AND_64(uint, 6) == 6) {
426                 uint = UF_PLUS_DIGIT(uint, 4);
427                 if (UF_GE(uint, UF_LSHIFT_64(1, FLOAT_MANT_DIG + 2))) {
428                     uint = UF_RSHIFT(uint, 1);
429                     exp++;
430                 }
431             }
432 
433             /* remove guard bits */
434             uint = UF_RSHIFT(uint, 2);
435 
436             /* align from target to FLOAT */
437             uint = UF_LSHIFT(uint, FLOAT_MANT_DIG - sig_bits);
438 
439             if (min_exp != (FLOAT_MIN_EXP - 1)) {
440 
441                 /* Convert from target denorm to FLOAT value */
442                 while (UF_LT(uint, UF_LSHIFT_64(1, (FLOAT_MANT_DIG - 1))) && exp > FLOAT_MIN_EXP) {
443                     uint = UF_LSHIFT(uint, 1);
444                     exp--;
445                 }
446             }
447 
448             if (exp >= FLOAT_MAX_EXP) {
449                 flt = (FLOAT) INFINITY;
450             } else {
451 #if !defined(UINTFLOAT_128) || __LDBL_IS_IEC_60559__ != 0
452                 if (UF_LT(uint, UF_LSHIFT_64(1, (FLOAT_MANT_DIG-1)))) {
453                     exp = 0;
454                 } else {
455                     exp += (FLOAT_MAX_EXP - 1);
456 #if defined(UINTFLOAT_128) && (defined(__x86_64__) || defined(__i386__))
457                     /*
458                      * Intel 80-bit format is weird -- there's an
459                      * integer bit so denorms can have the 'real'
460                      * exponent value. That means we don't mask off
461                      * the integer bit
462                      */
463 #define EXP_SHIFT       FLOAT_MANT_DIG
464 #else
465                     uint = UF_AND(uint, UF_NOT(UF_LSHIFT_64(1, (FLOAT_MANT_DIG-1))));
466 #define EXP_SHIFT       (FLOAT_MANT_DIG-1)
467 #endif
468                 }
469                 uint = UF_OR(uint, UF_LSHIFT_64(exp, EXP_SHIFT));
470                 flt = ASFLOAT(uint);
471 #else /* !defined(UINTFLOAT_128) || __LDBL_IS_IEC_60559__ != 0 */
472                 flt = scalbnl(TOFLOAT(uint), exp - (FLOAT_MANT_DIG-1));
473 #endif
474             }
475         }
476         else
477 #endif
478         {
479             if (CHECK_LONG())
480             {
481 		if (uintdigits + exp <= -324) {
482                     // Number is less than 1e-324, which should be rounded down to 0; return +/-0.0.
483                     flt = (FLOAT) 0.0;
484 		} else if (uintdigits + exp >= 310) {
485                     // Number is larger than 1e+309, which should be rounded to +/-Infinity.
486                     flt = (FLOAT) INFINITY;
487 		} else {
488                     flt = (FLOAT) __atod_engine(UF_TO_U64(uint), exp);
489                 }
490             }
491             else if (CHECK_LONG_LONG())
492             {
493                 flt = (FLOAT) __atold_engine(UF_TO_U128(uint), exp);
494             }
495             else
496             {
497 		if (uintdigits + exp <= -46) {
498                     // Number is less than 1e-46, which should be rounded down to 0; return 0.0.
499                     flt = (FLOAT) 0.0f;
500 		} else if (uintdigits + exp >= 40) {
501                     // Number is larger than 1e+39, which should be rounded to +/-Infinity.
502                     flt = (FLOAT) INFINITY;
503 		} else {
504                     flt = (FLOAT) __atof_engine(UF_TO_U32(uint), exp);
505                 }
506             }
507         }
508         CHECK_RANGE(flt)
509 	break;
510     } /* switch */
511 
512     if (flags & FL_MINUS)
513 	flt = -flt;
514     if (addr) {
515 	if (CHECK_LONG())
516 	    *((double *) addr) = (double) flt;
517 	else if (CHECK_LONG_LONG())
518             *((long double *) addr) = (long double) flt;
519         else
520 	    *((float *) addr) = (float) flt;
521     }
522     return 1;
523 }
524 
525 #undef base
526