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