1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22/*
23 * AT&T Research
24 * Glenn Fowler & Phong Vo
25 *
26 * common header and implementation for
27 *
28 *	strtof		strtod		strtold		_sfdscan
29 *	strntof		strntod		strntold
30 *
31 * define these macros to instantiate an implementation:
32 *
33 *	S2F_function	the function name
34 *	S2F_static	<0:export =0:extern >0:static
35 *	S2F_type	0:float 1:double 2:long.double
36 *	S2F_qualifier	1 for optional [fFlL] qualifier suffix
37 *	S2F_size	1 for interface with size_t second arg
38 *	S2F_scan	1 for alternate interface with these arguments:
39 *				void* handle
40 *				int (*getchar)(void* handle, int flag)
41 *			exactly one extra (*getchar)() is done, i.e.,
42 *			the caller must do the pushback
43 *				flag==0		get next char
44 *				flag==1		no number seen
45 *			return 0 on error or EOF
46 */
47
48#include "sfhdr.h"
49#include "FEATURE/float"
50
51/*
52 * the default is _sfdscan for standalone sfio compatibility
53 */
54
55#if !defined(S2F_function)
56#define S2F_function	_sfdscan
57#define S2F_static	1
58#define S2F_type	2
59#define S2F_scan	1
60#ifndef elementsof
61#define elementsof(a)	(sizeof(a)/sizeof(a[0]))
62#endif
63#endif
64
65#if S2F_type == 2 && _ast_fltmax_double
66#undef	S2F_type
67#define S2F_type	1
68#endif
69
70#if S2F_type == 0
71#define S2F_number	float
72#define S2F_ldexp	ldexp
73#define S2F_pow10	_Sffpow10
74#define S2F_inf		_Sffinf
75#define S2F_nan		_Sffnan
76#define S2F_min		(FLT_MIN)
77#define S2F_max		(FLT_MAX)
78#define S2F_exp_10_min	(FLT_MIN_10_EXP)
79#define S2F_exp_10_max	(FLT_MAX_10_EXP)
80#define S2F_exp_2_min	(FLT_MIN_EXP)
81#define S2F_exp_2_max	(FLT_MAX_EXP)
82#endif
83#if S2F_type == 1
84#define S2F_number	double
85#define S2F_ldexp	ldexp
86#define S2F_pow10	_Sfdpow10
87#define S2F_inf		_Sfdinf
88#define S2F_nan		_Sfdnan
89#define S2F_min		(DBL_MIN)
90#define S2F_max		(DBL_MAX)
91#define S2F_exp_10_min	(DBL_MIN_10_EXP)
92#define S2F_exp_10_max	(DBL_MAX_10_EXP)
93#define S2F_exp_2_min	(DBL_MIN_EXP)
94#define S2F_exp_2_max	(DBL_MAX_EXP)
95#endif
96#if S2F_type == 2
97#define S2F_number	long double
98#define S2F_ldexp	ldexpl
99#define S2F_pow10	_Sflpow10
100#define S2F_inf		_Sflinf
101#define S2F_nan		_Sflnan
102#define S2F_min		(LDBL_MIN)
103#define S2F_max		(LDBL_MAX)
104#define S2F_exp_10_min	(LDBL_MIN_10_EXP)
105#define S2F_exp_10_max	(LDBL_MAX_10_EXP)
106#define S2F_exp_2_min	(LDBL_MIN_EXP)
107#define S2F_exp_2_max	(LDBL_MAX_EXP)
108#endif
109
110#if -S2F_exp_10_min < S2F_exp_10_max
111#define S2F_exp_10_abs	(-S2F_exp_10_min)
112#else
113#define S2F_exp_10_abs	S2F_exp_10_max
114#endif
115
116#define S2F_batch	_ast_flt_unsigned_max_t
117
118#undef	ERR		/* who co-opted this namespace? */
119
120#if S2F_scan
121
122typedef int (*S2F_get_f)_ARG_((void*, int));
123
124#define ERR(e)
125#define GET(p)		(*get)(p,0)
126#define NON(p)		(*get)(p,1)
127#define PUT(p)
128#define REV(p,t,b)
129#define SET(p,t,b)
130
131#else
132
133#define ERR(e)		(errno=(e))
134#define NON(p)
135
136#if S2F_size
137#define GET(p)		(((p)<(z))?(*p++):(back=0))
138#define PUT(p)		(end?(*end=(char*)p-back):(char*)0)
139#define REV(p,t,b)	(p=t,back=b)
140#define SET(p,t,b)	(t=p,b=back)
141#else
142#define GET(p)		(*p++)
143#define PUT(p)		(end?(*end=(char*)p-1):(char*)0)
144#define REV(p,t,b)	(p=t)
145#define SET(p,t,b)	(t=p)
146#endif
147
148#endif
149
150typedef struct S2F_part_s
151{
152	S2F_batch	batch;
153	int		digits;
154} S2F_part_t;
155
156#if !defined(ERANGE)
157#define ERANGE		EINVAL
158#endif
159
160#if S2F_static > 0
161static
162#else
163#if S2F_static < 0 || !defined(S2F_static)
164#if defined(__EXPORT__)
165#define extern		__EXPORT__
166#endif
167extern
168#undef	extern
169#endif
170#endif
171S2F_number
172#if S2F_scan
173#if __STD_C
174S2F_function(void* s, S2F_get_f get)
175#else
176S2F_function(s, get) void* s; S2F_get_f get;
177#endif
178#else
179#if S2F_size
180#if __STD_C
181S2F_function(const char* str, size_t size, char** end)
182#else
183S2F_function(str, size, end) char* str; size_t size; char** end;
184#endif
185#else
186#if __STD_C
187S2F_function(const char* str, char** end)
188#else
189S2F_function(str, end) char* str; char** end;
190#endif
191#endif
192#endif
193{
194#if !S2F_scan
195	register unsigned char*	s = (unsigned char*)str;
196#if S2F_size
197	register unsigned char*	z = s + size;
198	int			back = 1;
199	int			b;
200#endif
201	unsigned char*		t;
202#endif
203	register S2F_batch	n;
204	register int		c;
205	register int		digits;
206	register int		m;
207	register unsigned char*	cv;
208	int			negative;
209	int			enegative;
210	int			fraction;
211	int			decimal = 0;
212	int			thousand = 0;
213	int			part = 0;
214	int			back_part;
215	S2F_batch		back_n;
216	S2F_number		v;
217	S2F_number		p;
218	S2F_part_t		parts[16];
219
220	/*
221	 * radix char and thousands separator are locale specific
222	 */
223
224	SFSETLOCALE(&decimal, &thousand);
225	SFCVINIT();
226
227	/*
228	 * skip initial blanks
229	 */
230
231	do c = GET(s); while (isspace(c));
232	SET(s, t, b);
233
234	/*
235	 * get the sign
236	 */
237
238	if ((negative = (c == '-')) || c == '+')
239		c = GET(s);
240
241	/*
242	 * drop leading 0's
243	 */
244
245	digits = 0;
246	fraction = -1;
247	if (c == '0')
248	{
249		c = GET(s);
250		if (c == 'x' || c == 'X')
251		{
252			/*
253			 * hex floating point -- easy
254			 */
255
256			cv = _Sfcv36;
257			v = 0;
258			for (;;)
259			{
260				c = GET(s);
261				if ((part = cv[c]) < 16)
262				{
263					digits++;
264					v *= 16;
265					v += part;
266				}
267				else if (c == decimal)
268				{
269					decimal = -1;
270					fraction = digits;
271				}
272				else
273					break;
274			}
275			m = 0;
276			if (c == 'p' || c == 'P')
277			{
278				c = GET(s);
279				if ((enegative = c == '-') || c == '+')
280					c = GET(s);
281				while (c >= '0' && c <= '9')
282				{
283					m = (m << 3) + (m << 1) + (c - '0');
284					c = GET(s);
285				}
286				if (enegative)
287					m = -m;
288			}
289
290#if S2F_qualifier
291
292			/*
293			 * consume the optional suffix
294			 */
295
296			switch (c)
297			{
298			case 'f':
299			case 'F':
300			case 'l':
301			case 'L':
302				c = GET(s);
303				break;
304			}
305#endif
306			PUT(s);
307			if (v == 0)
308				return negative ? -v : v;
309			if (fraction >= 0)
310				m -= 4 * (digits - fraction);
311			if (m < S2F_exp_2_min)
312			{
313				if ((m -= S2F_exp_2_min) < S2F_exp_2_min)
314				{
315					ERR(ERANGE);
316					return 0;
317				}
318				v = S2F_ldexp(v, S2F_exp_2_min);
319			}
320			else if (m > S2F_exp_2_max)
321			{
322				ERR(ERANGE);
323				return negative ? -S2F_inf : S2F_inf;
324			}
325			v = S2F_ldexp(v, m);
326			goto check;
327		}
328		while (c == '0')
329			c = GET(s);
330	}
331	else if (c == decimal)
332	{
333		decimal = -1;
334		fraction = 0;
335		for (;;)
336		{
337			c = GET(s);
338			if (c != '0')
339				break;
340			digits++;
341		}
342	}
343	else if (c == 'i' || c == 'I')
344	{
345		if ((c = GET(s)) != 'n' && c != 'N' ||
346		    (c = GET(s)) != 'f' && c != 'F')
347		{
348			REV(s, t, b);
349			PUT(s);
350			return 0;
351		}
352		c = GET(s);
353		SET(s, t, b);
354		if (((c)          == 'i' || c == 'I') &&
355		    ((c = GET(s)) == 'n' || c == 'N') &&
356		    ((c = GET(s)) == 'i' || c == 'I') &&
357		    ((c = GET(s)) == 't' || c == 'T') &&
358		    ((c = GET(s)) == 'y' || c == 'Y'))
359		{
360			c = GET(s);
361			SET(s, t, b);
362		}
363		REV(s, t, b);
364		PUT(s);
365		return negative ? -S2F_inf : S2F_inf;
366	}
367	else if (c == 'n' || c == 'N')
368	{
369		if ((c = GET(s)) != 'a' && c != 'A' ||
370		    (c = GET(s)) != 'n' && c != 'N')
371		{
372			REV(s, t, b);
373			PUT(s);
374			return 0;
375		}
376		do c = GET(s); while (c && !isspace(c));
377		PUT(s);
378		return negative ? -S2F_nan : S2F_nan;
379	}
380	else if (c < '1' || c > '9')
381	{
382		REV(s, t, b);
383		PUT(s);
384		NON(s);
385		return 0;
386	}
387
388	/*
389	 * consume the integral and fractional parts
390	 */
391
392	n = 0;
393	m = 0;
394	for (;;)
395	{
396		if (c >= '0' && c <= '9')
397		{
398			digits++;
399			n = (n << 3) + (n << 1) + (c - '0');
400			if (n >= ((~((S2F_batch)0)) / 10) && part < elementsof(parts))
401			{
402				parts[part].batch = n;
403				n = 0;
404				parts[part].digits = digits;
405				part++;
406			}
407		}
408		else if (m && (digits - m) != 3)
409			break;
410		else if (c == decimal)
411		{
412			decimal = -1;
413			thousand = -1;
414			m = 0;
415			fraction = digits;
416		}
417		else if (c != thousand)
418			break;
419		else if (!(m = digits))
420		{
421			SET(s, t, b);
422			break;
423		}
424		else
425		{
426			SET(s, t, b);
427			back_n = n;
428			back_part = part;
429		}
430		c = GET(s);
431	}
432	if (m && (digits - m) != 3)
433	{
434		REV(s, t, b);
435		n = back_n;
436		part = back_part;
437	}
438
439	/*
440	 * don't forget the last part
441	 */
442
443	if (n && part < elementsof(parts))
444	{
445		parts[part].batch = n;
446		parts[part].digits = digits;
447		part++;
448	}
449
450	/*
451	 * consume the exponent
452	 */
453
454	if (fraction >= 0)
455		digits = fraction;
456	if (c == 'e' || c == 'E')
457	{
458		c = GET(s);
459		if ((enegative = (c == '-')) || c == '+')
460			c = GET(s);
461		n = 0;
462		while (c >= '0' && c <= '9')
463		{
464			n = (n << 3) + (n << 1) + (c - '0');
465			c = GET(s);
466		}
467		if (enegative)
468			digits -= n;
469		else
470			digits += n;
471	}
472
473#if S2F_qualifier
474
475	/*
476	 * consume the optional suffix
477	 */
478
479	switch (c)
480	{
481	case 'f':
482	case 'F':
483	case 'l':
484	case 'L':
485		c = GET(s);
486		break;
487	}
488#endif
489	PUT(s);
490
491	/*
492	 * adjust for at most one multiply per part
493	 * and at most one divide overall
494	 */
495
496	v = 0;
497	if (!part)
498		return negative ? -v : v;
499	else if ((m = parts[part-1].digits - digits) > 0)
500		digits += m;
501	else
502		m = 0;
503
504	/*
505	 * combine the parts
506	 */
507
508	while (part--)
509	{
510		p = parts[part].batch;
511		c = digits - parts[part].digits;
512		if (c > S2F_exp_10_max)
513		{
514			ERR(ERANGE);
515			return negative ? -S2F_inf : S2F_inf;
516		}
517		if (c > 0)
518		{
519#if _ast_mpy_overflow_fpe
520			if ((S2F_max / p) < S2F_pow10[c])
521			{
522				ERR(ERANGE);
523				return negative ? -S2F_inf : S2F_inf;
524			}
525#endif
526			p *= S2F_pow10[c];
527		}
528		v += p;
529	}
530	if (m)
531	{
532		while (m > S2F_exp_10_max)
533		{
534			m -= S2F_exp_10_max;
535			v /= S2F_pow10[S2F_exp_10_max];
536		}
537#if _ast_div_underflow_fpe
538		if ((S2F_min * p) > S2F_pow10[c])
539		{
540			ERR(ERANGE);
541			return negative ? -S2F_inf : S2F_inf;
542		}
543#endif
544		v /= S2F_pow10[m];
545	}
546
547	/*
548	 * check the range
549	 */
550
551 check:
552	if (v < S2F_min)
553	{
554		ERR(ERANGE);
555		v = 0;
556	}
557	else if (v > S2F_max)
558	{
559		ERR(ERANGE);
560		v = S2F_inf;
561	}
562
563	/*
564	 * done
565	 */
566
567	return negative ? -v : v;
568}
569