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 static const char pstr_nfinity[] = "nfinity";
34 static const char pstr_an[] = "an";
35 
36 #if defined(STRTOD) || defined(STRTOF) || defined(STRTOLD)
37 # define CHECK_WIDTH()   1
38 # define CHECK_RANGE(flt) do {                                          \
39         int __class = fpclassify(flt);                                  \
40         if (__class == FP_INFINITE || __class == FP_SUBNORMAL || __class == FP_ZERO) \
41             errno = ERANGE;                                             \
42     } while (0);
43 # ifdef _WANT_IO_C99_FORMATS
44 #  define _NEED_IO_C99_FORMATS
45 # endif
46 # if defined(STRTOD)
47 #  define _NEED_IO_DOUBLE
48 #  define SCANF_LEVEL           SCANF_DBL
49 #  define CHECK_LONG()          1
50 #  define CHECK_LONG_LONG()     0
51 # elif defined(STRTOLD)
52 #  define _NEED_IO_LONG_DOUBLE
53 #  define SCANF_LEVEL           SCANF_DBL
54 #  define CHECK_LONG()          0
55 #  define CHECK_LONG_LONG()     1
56 # elif defined(STRTOF)
57 #  define _NEED_IO_FLOAT
58 #  define SCANF_LEVEL           SCANF_FLT
59 #  define CHECK_LONG()          0
60 #  define CHECK_LONG_LONG()     0
61 # endif
62 
63 #define FLT_STREAM const char
64 #define FLT_CONTEXT int
65 
scanf_getc(const char * s,int * lenp)66 static inline int scanf_getc(const char *s, int *lenp)
67 {
68     int l = *lenp;
69     int c = s[l];
70     *lenp = l + 1;
71     return c;
72 }
73 
scanf_ungetc(int c,FLT_STREAM * s,int * lenp)74 static inline void scanf_ungetc(int c, FLT_STREAM *s, int *lenp)
75 {
76     (void) c;
77     (void) s;
78     --(*lenp);
79 }
80 
81 #undef EOF
82 #define EOF -1
83 
84 #else
85 
86 # define CHECK_WIDTH()   (--width != 0)
87 # define CHECK_RANGE(flt)
88 
89 # ifdef _NEED_IO_FLOAT
90 
91 #  define CHECK_LONG()          0
92 #  define CHECK_LONG_LONG()     0
93 
94 # elif defined(_NEED_IO_DOUBLE)
95 
96 #  ifdef _NEED_IO_LONG_DOUBLE
97 #   define CHECK_LONG()         (flags & FL_LONG)
98 #   define CHECK_LONG_LONG()    (flags & FL_LONGLONG)
99 #  else
100 #   define CHECK_LONG()         (flags & (FL_LONG|FL_LONGLONG))
101 #   define CHECK_LONG_LONG()    0
102 #  endif
103 # else
104 #  define CHECK_LONG()          0
105 #  define CHECK_LONG_LONG()     0
106 # endif
107 
108 #define FLT_STREAM      FILE
109 #define FLT_CONTEXT     scanf_context_t
110 
111 #endif
112 
113 #include "scanf_private.h"
114 
115 #include "dtoa.h"
116 
117 #ifdef _NEED_IO_LONG_DOUBLE
118 # define FLOAT                  long double
119 # define FLOAT_MIN              __LDBL_MIN__
120 # define FLOAT_MANT_DIG         __LDBL_MANT_DIG__
121 # define FLOAT_MAX_EXP          __LDBL_MAX_EXP__
122 # define FLOAT_MIN_EXP          __LDBL_MIN_EXP__
123 # define ASFLOAT(x)             aslongdouble(x)
124 # if __SIZEOF_LONG_DOUBLE__ > 8
125 #  define TOFLOAT(x)            _u128_to_ld(x)
126 #  define UINTFLOAT             _u128
127 # elif __SIZEOF_LONG_DOUBLE__ == 8
128 #  define TOFLOAT(x)            ((long double) (x))
129 #  define UINTFLOAT             uint64_t
130 # elif __SIZEOF_LONG_DOUBLE__ == 4
131 #  define TOFLOAT(x)            ((long double) (x))
132 #  define UINTFLOAT             uint32_t
133 # endif
134 #elif defined(_NEED_IO_DOUBLE)
135 # define FLOAT                  double
136 # define FLOAT_MIN              __DBL_MIN__
137 # define FLOAT_MANT_DIG         __DBL_MANT_DIG__
138 # define FLOAT_MAX_EXP          __DBL_MAX_EXP__
139 # define FLOAT_MIN_EXP          __DBL_MIN_EXP__
140 # define ASFLOAT(x)             _asdouble(x)
141 # define TOFLOAT(x)             ((double) (x))
142 # if __SIZEOF_DOUBLE__ == 4
143 #  define UINTFLOAT             uint32_t
144 # elif __SIZEOF_DOUBLE__ == 8
145 #  define UINTFLOAT             uint64_t
146 # endif
147 #elif defined(_NEED_IO_FLOAT)
148 # define FLOAT                  float
149 # define FLOAT_MIN              __FLT_MIN__
150 # define FLOAT_MANT_DIG         __FLT_MANT_DIG__
151 # define FLOAT_MAX_EXP          __FLT_MAX_EXP__
152 # define FLOAT_MIN_EXP          __FLT_MIN_EXP__
153 # define ASFLOAT(x)             _asfloat(x)
154 # define TOFLOAT(x)             ((float) (x))
155 # define UINTFLOAT              uint32_t
156 #endif
157 
158 #if FLOAT_MANT_DIG > 53
159 #define U32_TO_UF(x)    to_u128(x)
160 #define U64_TO_UF(x)    to_u128(x)
161 #define U128_TO_UF(x)   (x)
162 #define UF_TO_U32(x)    from_u128(x)
163 #define UF_TO_U64(x)    from_u128(x)
164 #define UF_TO_U128(x)   (x)
165 #define UF_IS_ZERO(x)   _u128_is_zero(x)
166 #define UF_TIMES_BASE(a,b)      _u128_times_base(a,b)
167 #define UF_PLUS_DIGIT(a,b)      _u128_plus_64(a,b)
168 #define UF_RSHIFT(a,b)          _u128_rshift(a,b)
169 #define UF_LSHIFT(a,b)          _u128_lshift(a,b)
170 #define UF_LSHIFT_64(a,b)       _u128_lshift_64(a,b)
171 #define UF_LT(a,b)              _u128_lt(a,b)
172 #define UF_GE(a,b)              _u128_ge(a,b)
173 #define UF_OR_64(a,b)           _u128_or_64(a,b)
174 #define UF_AND_64(a,b)          _u128_and_64(a,b)
175 #define UF_AND(a,b)             _u128_and(a,b)
176 #define UF_NOT(a)               _u128_not(a)
177 #define UF_OR(a,b)              _u128_or(a,b)
178 #else
179 #define U32_TO_UF(x)    (x)
180 #define U64_TO_UF(x)    (x)
181 #define U128_TO_UF(x)   from_u128(x)
182 #define UF_TO_U32(x)    (x)
183 #define UF_TO_U64(x)    (x)
184 #define UF_TO_U128(x)   to_u128(x)
185 #define UF_IS_ZERO(x)   ((x) == 0)
186 #define UF_TIMES_BASE(a,b)      ((a) * (b))
187 #define UF_PLUS_DIGIT(a,b)      ((a) + (b))
188 #define UF_RSHIFT(a,b)          ((a) >> (b))
189 #define UF_LSHIFT(a,b)          ((a) << (b))
190 #define UF_LSHIFT_64(a,b)       ((UINTFLOAT) (a) << (b))
191 #define UF_LT(a,b)              ((a) < (b))
192 #define UF_GE(a,b)              ((a) >= (b))
193 #define UF_OR_64(a,b)           ((a) | (b))
194 #define UF_AND_64(a,b)          ((a) & (b))
195 #define UF_AND(a,b)             ((a) & (b))
196 #define UF_NOT(a)               (~(a))
197 #define UF_OR(a,b)              ((a) | (b))
198 #endif
199 
200 static unsigned char
conv_flt(FLT_STREAM * stream,FLT_CONTEXT * context,width_t width,void * addr,uint16_t flags)201 conv_flt (FLT_STREAM *stream, FLT_CONTEXT *context, width_t width, void *addr, uint16_t flags)
202 {
203     UINTFLOAT uint;
204     unsigned int overflow = 0;
205     int uintdigits = 0;
206     FLOAT flt;
207     int i;
208     const char *p;
209     int exp;
210 
211     i = scanf_getc (stream, context);		/* after scanf_ungetc()	*/
212 
213     switch ((unsigned char)i) {
214     case '-':
215         flags |= FL_MINUS;
216 	__PICOLIBC_FALLTHROUGH;
217     case '+':
218 	if (!CHECK_WIDTH() || (i = scanf_getc (stream, context)) < 0)
219 	    return 0;
220     }
221 
222     switch (TOLOWER (i)) {
223     case 'n':
224 	p = pstr_an;
225         flt = (FLOAT) NAN;
226         goto operate_pstr;
227 
228     case 'i':
229 	p = pstr_nfinity;
230         flt = (FLOAT) INFINITY;
231     operate_pstr:
232         {
233 	    unsigned char c;
234 
235 	    while ((c = *p++) != 0) {
236 		if (CHECK_WIDTH()) {
237                     if ((i = scanf_getc (stream, context)) >= 0) {
238                         if (TOLOWER(i) == c)
239                             continue;
240                         scanf_ungetc (i, stream, context);
241                     }
242                 }
243                 if (p == pstr_nfinity + 3)
244                     break;
245                 return 0;
246 	    }
247             if (flt != flt) {
248                 if (CHECK_WIDTH()) {
249                     if ((i = scanf_getc (stream, context)) == '(') {
250                         while (CHECK_WIDTH() && (i = scanf_getc (stream, context)) != ')') {
251                             if (isalnum(i) || i == '_' )
252                                 continue;
253                             else
254                                 break;
255                         }
256                         if (i != ')')
257                             return 0;
258                     } else {
259                         scanf_ungetc (i, stream, context);
260                     }
261                 }
262             }
263         }
264 	break;
265 
266     default:
267         exp = 0;
268 	uint = U32_TO_UF(0);
269 #define uintdigitsmax_10_float  8
270 #define uintdigitsmax_16_float  7
271 #if __SIZEOF_DOUBLE__ == 8
272 #define uintdigitsmax_10_double 16
273 #define uintdigitsmax_16_double 15
274 #elif __SIZEOF_DOUBLE__ ==4
275 #define uintdigitsmax_10_double 8
276 #define uintdigitsmax_16_double 7
277 #endif
278 #if __SIZEOF_LONG_DOUBLE__ > 8
279 #define uintdigitsmax_10_long_double    32
280 #define uintdigitsmax_16_long_double    30
281 #elif __SIZEOF_LONG_DOUBLE__ == 8
282 #define uintdigitsmax_10_long_double    16
283 #define uintdigitsmax_16_long_double    15
284 #elif __SIZEOF_LONG_DOUBLE__ == 4
285 #define uintdigitsmax_10_long_double    8
286 #define uintdigitsmax_16_long_double    7
287 #endif
288 
289 #ifdef _NEED_IO_C99_FORMATS
290         int base = 10;
291 #else
292 #define base 10
293 #endif
294 
295 #define uintdigitsmax                                                   \
296         ((base) == 10 ?                                                 \
297             (CHECK_LONG_LONG() ? uintdigitsmax_10_long_double :         \
298              (CHECK_LONG() ?                                            \
299               uintdigitsmax_10_double :                                 \
300               uintdigitsmax_10_float)) :                                \
301             (CHECK_LONG_LONG() ? uintdigitsmax_16_long_double :         \
302              (CHECK_LONG() ?                                            \
303               uintdigitsmax_16_double :                                 \
304               uintdigitsmax_16_float)))
305 
306 	do {
307 
308 	    unsigned char c;
309 
310 #ifdef _NEED_IO_C99_FORMATS
311             if ((flags & FL_FHEX) && (c = TOLOWER(i) - 'a') <= 5)
312                 c += 10;
313             else
314 #endif
315                 c = i - '0';
316 
317 	    if (c < base) {
318 		flags |= FL_ANY;
319                 if (!(flags & FL_OVFL) && uintdigits > uintdigitsmax) {
320                     flags |= FL_OVFL;
321                     if (base == 10) {
322                         /* Check if overflow is >= 0.5 */
323                         if (c >= 5) {
324                             overflow = 2;
325                             /* Check if overflow might be == 0.5 */
326                             if (c == 5)
327                                 c = 0;
328                         }
329                     }
330                 }
331 		if (flags & FL_OVFL) {
332                     overflow |= (c != 0);
333 		    if (!(flags & FL_DOT))
334 			exp += 1;
335 		} else {
336 		    if (flags & FL_DOT)
337 			exp -= 1;
338                     uint = UF_PLUS_DIGIT(UF_TIMES_BASE(uint, base), c);
339 		    if (!UF_IS_ZERO(uint))
340 			uintdigits++;
341 	        }
342 
343 	    } else if (c == (('.'-'0') & 0xff) && !(flags & FL_DOT)) {
344 		flags |= FL_DOT;
345 #ifdef _NEED_IO_C99_FORMATS
346             } else if (TOLOWER(i) == 'x' && (flags & FL_ANY) && UF_IS_ZERO(uint)) {
347                 flags |= FL_FHEX;
348                 base = 16;
349 #endif
350 	    } else {
351 		break;
352 	    }
353 	} while (CHECK_WIDTH() && (i = scanf_getc (stream, context)) >= 0);
354 
355 	if (!(flags & FL_ANY))
356 	    return 0;
357 
358 #ifdef _NEED_IO_C99_FORMATS
359         int exp_match = 'e';
360         if (flags & FL_FHEX) {
361             exp_match = 'p';
362             exp *= 4;
363         }
364 #else
365 #define exp_match 'e'
366 #endif
367 	if (TOLOWER(i) == exp_match)
368 	{
369             int esign, edig;
370 	    int expacc;
371 
372 	    if (!CHECK_WIDTH())
373                 goto no_exp;
374 
375             esign = scanf_getc (stream, context);
376 
377 	    switch ((unsigned char)esign) {
378             case '-':
379 		flags |= FL_MEXP;
380 		__PICOLIBC_FALLTHROUGH;
381             case '+':
382                 if (!CHECK_WIDTH()) {
383                     scanf_ungetc(esign, stream, context);
384                     goto no_exp;
385                 }
386 		edig = scanf_getc (stream, context);		/* test EOF will below	*/
387                 break;
388             default:
389                 edig = esign;
390                 esign = EOF;
391                 break;
392 	    }
393 
394 	    if (!isdigit (edig))
395             {
396                 scanf_ungetc(edig, stream, context);
397                 if (esign != EOF)
398                     scanf_ungetc(esign, stream, context);
399                 goto no_exp;
400             }
401 
402             i = edig;
403 	    expacc = 0;
404 #define MAX_POSSIBLE_EXP        (FLOAT_MAX_EXP + FLOAT_MANT_DIG * 4)
405 	    do {
406                 if (expacc < MAX_POSSIBLE_EXP)
407                     expacc = expacc * 10 + (i - '0');
408 	    } while (CHECK_WIDTH() && isdigit (i = scanf_getc(stream, context)));
409 	    if (flags & FL_MEXP)
410 		expacc = -expacc;
411             exp += expacc;
412 	}
413 
414     no_exp:
415 	if (width)
416             scanf_ungetc (i, stream, context);
417 
418 	if (UF_IS_ZERO(uint)) {
419 	    flt = (FLOAT) 0;
420 	    break;
421 	}
422 
423 #ifdef _NEED_IO_C99_FORMATS
424         if (flags & FL_FHEX)
425         {
426             int sig_bits;
427             int min_exp;
428 
429             if (CHECK_LONG_LONG()) {
430                 sig_bits = __LDBL_MANT_DIG__;
431                 min_exp = __LDBL_MIN_EXP__ - 1;
432             } else if (CHECK_LONG()) {
433                 sig_bits = __DBL_MANT_DIG__;
434                 min_exp = __DBL_MIN_EXP__ - 1;
435             } else {
436                 sig_bits = __FLT_MANT_DIG__;
437                 min_exp = __FLT_MIN_EXP__ - 1;
438             }
439 
440             /* We're using two guard bits, one for the
441              * 'half' value and the second to indicate whether
442              * there is any non-zero value beyond that
443              */
444             exp += (sig_bits + 2 - 1);
445 
446             /* Make significand larger than 1.0 */
447             while (UF_LT(uint, UF_LSHIFT_64(1, (sig_bits + 2 - 1)))) {
448                 uint = UF_LSHIFT(uint, 1);
449                 exp--;
450             }
451 
452             /* Now shift right until the exponent is in range and the
453              * value is less than 2.0. Capture any value > 0.5 in the
454              * LSB of uint.  This may generate a denorm.
455              */
456             while (UF_GE(uint, UF_LSHIFT_64(1, (sig_bits + 2))) || exp < min_exp) {
457                 /* squash extra bits into  the second guard bit */
458                 uint = UF_OR_64(UF_RSHIFT(uint, 1), UF_AND_64(uint, 1));
459                 exp++;
460             }
461 
462             /* Mix in the overflow bit computed while scanning the
463              * string
464              */
465             uint = UF_OR_64(uint, overflow);
466 
467             /* Round even */
468             if (UF_AND_64(uint, 3) == 3 || UF_AND_64(uint, 6) == 6) {
469                 uint = UF_PLUS_DIGIT(uint, 4);
470                 if (UF_GE(uint, UF_LSHIFT_64(1, FLOAT_MANT_DIG + 2))) {
471                     uint = UF_RSHIFT(uint, 1);
472                     exp++;
473                 }
474             }
475 
476             /* remove guard bits */
477             uint = UF_RSHIFT(uint, 2);
478 
479             /* align from target to FLOAT */
480             uint = UF_LSHIFT(uint, FLOAT_MANT_DIG - sig_bits);
481 
482             if (min_exp != (FLOAT_MIN_EXP - 1)) {
483 
484                 /* Convert from target denorm to FLOAT value */
485                 while (UF_LT(uint, UF_LSHIFT_64(1, (FLOAT_MANT_DIG - 1))) && exp > FLOAT_MIN_EXP) {
486                     uint = UF_LSHIFT(uint, 1);
487                     exp--;
488                 }
489             }
490 
491             if (exp >= FLOAT_MAX_EXP) {
492                 flt = (FLOAT) INFINITY;
493             } else {
494 #if FLOAT_MANT_DIG <= 53 || __LDBL_IS_IEC_60559__ != 0 || defined(__m68k__)
495                 if (UF_LT(uint, UF_LSHIFT_64(1, (FLOAT_MANT_DIG-1)))) {
496                     exp = 0;
497                 } else {
498                     exp += (FLOAT_MAX_EXP - 1);
499 #if FLOAT_MANT_DIG > 53 && (defined(__x86_64__) || defined(__i386__))
500                     /*
501                      * Intel 80-bit format is weird -- there's an
502                      * integer bit so denorms can have the 'real'
503                      * exponent value. That means we don't mask off
504                      * the integer bit
505                      */
506 #define EXP_SHIFT       FLOAT_MANT_DIG
507 #elif FLOAT_MANT_DIG > 53 && defined(__m68k__)
508 #define EXP_SHIFT   FLOAT_MANT_DIG + 16
509 #else
510                     uint = UF_AND(uint, UF_NOT(UF_LSHIFT_64(1, (FLOAT_MANT_DIG-1))));
511 #define EXP_SHIFT       (FLOAT_MANT_DIG-1)
512 #endif
513                 }
514                 uint = UF_OR(uint, UF_LSHIFT_64(exp, EXP_SHIFT));
515                 flt = ASFLOAT(uint);
516 #else /* FLOAT_MANT_DIG <= 53 || __LDBL_IS_IEC_60559__ != 0 */
517                 flt = scalbnl(TOFLOAT(uint), exp - (FLOAT_MANT_DIG-1));
518 #endif
519                 CHECK_RANGE(flt);
520             }
521         }
522         else
523 #endif
524         {
525             /*
526              * Mix in overflow. Overflow has four possible values:
527              *
528              * 0: overflow == 0
529              * 1: overflow < 0.5
530              * 2: overflow == 0.5
531              * 3: overflow > 0.5
532              *
533              * We want to increment in case 2 if uint is odd
534              * and always in case 3.
535              */
536             overflow |= UF_AND_64(uint, 1);
537             uint = UF_PLUS_DIGIT(uint, (overflow + 1) >> 2);
538 
539 #ifdef _NEED_IO_FLOAT_LARGE
540             if (CHECK_LONG_LONG() && __SIZEOF_LONG_DOUBLE__ > 8)
541             {
542                 flt = (FLOAT) __atold_engine(UF_TO_U128(uint), exp);
543             }
544             else
545 #endif
546 #ifdef _NEED_IO_FLOAT64
547             if ((CHECK_LONG() && __SIZEOF_DOUBLE__ == 8) ||
548                      (CHECK_LONG_LONG() && __SIZEOF_LONG_DOUBLE__ == 8))
549             {
550 		if (uintdigits + exp <= -324) {
551                     // Number is less than 1e-324, which should be rounded down to 0; return +/-0.0.
552                     flt = (FLOAT) 0.0;
553 		} else if (uintdigits + exp >= 310) {
554                     // Number is larger than 1e+309, which should be rounded to +/-Infinity.
555                     flt = (FLOAT) INFINITY;
556 		} else {
557                     flt = (FLOAT) __atod_engine(UF_TO_U64(uint), exp);
558                 }
559             }
560             else
561 #endif
562             {
563 		if (uintdigits + exp <= -46) {
564                     // Number is less than 1e-46, which should be rounded down to 0; return 0.0.
565                     flt = (FLOAT) 0.0f;
566 		} else if (uintdigits + exp >= 40) {
567                     // Number is larger than 1e+39, which should be rounded to +/-Infinity.
568                     flt = (FLOAT) INFINITY;
569 		} else {
570                     flt = (FLOAT) __atof_engine(UF_TO_U32(uint), exp);
571                 }
572             }
573         }
574         CHECK_RANGE(flt)
575 	break;
576     } /* switch */
577 
578 #if defined(__riscv) || defined(__ARC64__) || defined(__mips)
579     /*
580      * Some processors don't preserve the sign of NAN across
581      * conversions, so we have to negate after the cast
582      */
583     if (addr) {
584 	if (CHECK_LONG_LONG()) {
585             long double ld = (long double) flt;
586             if (flags & FL_MINUS)
587                 ld = -ld;
588             *((long double *) addr) = ld;
589 	} else if (CHECK_LONG()) {
590             double d = (double) flt;
591             if (flags & FL_MINUS)
592                 d = -d;
593 	    *((double *) addr) = d;
594         } else {
595             float f = (float) flt;
596             if (flags & FL_MINUS)
597                 f = -f;
598 	    *((float *) addr) = f;
599         }
600     }
601 #else
602     if (flags & FL_MINUS)
603 	flt = -flt;
604     if (addr) {
605 	if (CHECK_LONG_LONG())
606             *((long double *) addr) = (long double) flt;
607 	else if (CHECK_LONG())
608 	    *((double *) addr) = (double) flt;
609         else
610 	    *((float *) addr) = (float) flt;
611     }
612 #endif
613     return 1;
614 }
615 
616 #undef base
617