1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin /*
23da2e3ebdSchin  * AT&T Research
24da2e3ebdSchin  * Glenn Fowler
25da2e3ebdSchin  * Phong Vo
26da2e3ebdSchin  *
27da2e3ebdSchin  * common header and implementation for
28da2e3ebdSchin  *
29da2e3ebdSchin  *	strtol		strtoul		strton
30da2e3ebdSchin  *	strtoll		strtoull	strtonll
31da2e3ebdSchin  *	strntol		strntoul	strnton
32da2e3ebdSchin  *	strntoll	strntoull	strntonll
33da2e3ebdSchin  *
34da2e3ebdSchin  * define these macros to instantiate an implementation:
35da2e3ebdSchin  *
36da2e3ebdSchin  *	S2I_function	the function name
37da2e3ebdSchin  *	S2I_number	the signed number type
38da2e3ebdSchin  *	S2I_unumber	the unsigned number type
39da2e3ebdSchin  *	S2I_unsigned	1 for unsigned, 0 for signed
4034f9b3eeSRoland Mainz  *	S2I_qualifier	1 for optional qualifier suffix, 0 otherwise
41da2e3ebdSchin  *	S2I_multiplier	1 for optional multiplier suffix, 0 otherwise
42da2e3ebdSchin  *	S2I_size	the second argument is the input string size
43da2e3ebdSchin  *
44da2e3ebdSchin  * convert string to number
45da2e3ebdSchin  * errno=ERANGE on overflow (LONG_MAX) or underflow (LONG_MIN)
46da2e3ebdSchin  * if non-null e will point to first unrecognized char in s
47da2e3ebdSchin  * if basep!=0 it points to the default base on input and
48da2e3ebdSchin  * will point to the explicit base on return
49da2e3ebdSchin  * a default base of 0 will determine the base from the input
50da2e3ebdSchin  * a default base of 1 will determine the base from the input using bb#*
51da2e3ebdSchin  * a base prefix in the string overrides *b
52da2e3ebdSchin  * *b will not be set if the string has no base prefix
53da2e3ebdSchin  * if m>1 and no multipler was specified then the result is multiplied by m
54da2e3ebdSchin  * if m<0 then multipliers are not consumed
55da2e3ebdSchin  * if a base arg or prefix is specified then multiplier is not consumed
56da2e3ebdSchin  *
57da2e3ebdSchin  * integer numbers are of the form:
58da2e3ebdSchin  *
59da2e3ebdSchin  *	[sign][base][number[qualifier]][multiplier]
60da2e3ebdSchin  *
61da2e3ebdSchin  *	base:		nnn#		base nnn
62da2e3ebdSchin  *			0[xX]		hex
63da2e3ebdSchin  *			0		octal
64da2e3ebdSchin  *			[1-9]		decimal
65da2e3ebdSchin  *
66da2e3ebdSchin  *	number:		[0-9a-zA-Z]*
67da2e3ebdSchin  *
68da2e3ebdSchin  *	qualifier:	[lL]
69da2e3ebdSchin  *			[uU]
70da2e3ebdSchin  *			[uU][lL]
71da2e3ebdSchin  *			[lL][uU]
72da2e3ebdSchin  *			[lL][lL][uU]
73da2e3ebdSchin  *			[uU][lL][lL]
74da2e3ebdSchin  *
75da2e3ebdSchin  *	multiplier:	.		pseudo-float if m>1
76da2e3ebdSchin  *			[bB]		block (512)
77da2e3ebdSchin  *			[cC]		char (1)
78*b30d1939SAndy Fiddaman  *			[gG]		giga (1000*1000*1000)
79*b30d1939SAndy Fiddaman  *			[gG]i		gibi (1024*1024*1024)
80*b30d1939SAndy Fiddaman  *			[kK]		kilo (1000)
81*b30d1939SAndy Fiddaman  *			[kK]i		kibi (1024)
82*b30d1939SAndy Fiddaman  *			[mM]		mega (1000*1000)
83*b30d1939SAndy Fiddaman  *			[mM]i		mibi (1024*1024)
84da2e3ebdSchin  */
85da2e3ebdSchin 
86da2e3ebdSchin #include <ast.h>
87da2e3ebdSchin #include <ctype.h>
88da2e3ebdSchin 
89da2e3ebdSchin #include "sfhdr.h"
90da2e3ebdSchin 
91da2e3ebdSchin #if !__STD_C && !defined(const)
92da2e3ebdSchin #define const
93da2e3ebdSchin #endif
94da2e3ebdSchin 
95da2e3ebdSchin #ifndef ERANGE
96da2e3ebdSchin #define ERANGE		EINVAL
97da2e3ebdSchin #endif
98da2e3ebdSchin 
99da2e3ebdSchin #define QL		01
100da2e3ebdSchin #define QU		02
101da2e3ebdSchin 
102da2e3ebdSchin #define S2I_umax	(~((S2I_unumber)0))
103da2e3ebdSchin 
104da2e3ebdSchin #if S2I_unsigned
105da2e3ebdSchin #define S2I_type	S2I_unumber
106da2e3ebdSchin #define S2I_min		0
107da2e3ebdSchin #define S2I_max		S2I_umax
108da2e3ebdSchin #else
109da2e3ebdSchin #define S2I_type	S2I_number
110da2e3ebdSchin #define S2I_min		(-S2I_max-1)
111da2e3ebdSchin #define S2I_max		(S2I_umax>>1)
112da2e3ebdSchin #endif
113da2e3ebdSchin 
114da2e3ebdSchin #if S2I_size
115da2e3ebdSchin #define S2I_valid(s)	((s)<(z))
116da2e3ebdSchin #else
117da2e3ebdSchin #define S2I_valid(s)	1
118da2e3ebdSchin #endif
119da2e3ebdSchin 
120da2e3ebdSchin #define ADDOVER(n,c,s)	((S2I_umax-(n))<((S2I_unumber)((c)+(s))))
121da2e3ebdSchin #define MPYOVER(n,c)	(((S2I_unumber)(n))>(S2I_umax/(c)))
122da2e3ebdSchin 
123da2e3ebdSchin static const S2I_unumber	mm[] =
124da2e3ebdSchin {
125da2e3ebdSchin 	0,
126da2e3ebdSchin 	S2I_umax /  1,
127da2e3ebdSchin 	S2I_umax /  2,
128da2e3ebdSchin 	S2I_umax /  3,
129da2e3ebdSchin 	S2I_umax /  4,
130da2e3ebdSchin 	S2I_umax /  5,
131da2e3ebdSchin 	S2I_umax /  6,
132da2e3ebdSchin 	S2I_umax /  7,
133da2e3ebdSchin 	S2I_umax /  8,
134da2e3ebdSchin 	S2I_umax /  9,
135da2e3ebdSchin 	S2I_umax / 10,
136da2e3ebdSchin 	S2I_umax / 11,
137da2e3ebdSchin 	S2I_umax / 12,
138da2e3ebdSchin 	S2I_umax / 13,
139da2e3ebdSchin 	S2I_umax / 14,
140da2e3ebdSchin 	S2I_umax / 15,
141da2e3ebdSchin 	S2I_umax / 16,
142da2e3ebdSchin 	S2I_umax / 17,
143da2e3ebdSchin 	S2I_umax / 18,
144da2e3ebdSchin 	S2I_umax / 19,
145da2e3ebdSchin 	S2I_umax / 20,
146da2e3ebdSchin 	S2I_umax / 21,
147da2e3ebdSchin 	S2I_umax / 22,
148da2e3ebdSchin 	S2I_umax / 23,
149da2e3ebdSchin 	S2I_umax / 24,
150da2e3ebdSchin 	S2I_umax / 25,
151da2e3ebdSchin 	S2I_umax / 26,
152da2e3ebdSchin 	S2I_umax / 27,
153da2e3ebdSchin 	S2I_umax / 28,
154da2e3ebdSchin 	S2I_umax / 29,
155da2e3ebdSchin 	S2I_umax / 30,
156da2e3ebdSchin 	S2I_umax / 31,
157da2e3ebdSchin 	S2I_umax / 32,
158da2e3ebdSchin 	S2I_umax / 33,
159da2e3ebdSchin 	S2I_umax / 34,
160da2e3ebdSchin 	S2I_umax / 35,
161da2e3ebdSchin 	S2I_umax / 36,
162da2e3ebdSchin 	S2I_umax / 37,
163da2e3ebdSchin 	S2I_umax / 38,
164da2e3ebdSchin 	S2I_umax / 39,
165da2e3ebdSchin 	S2I_umax / 40,
166da2e3ebdSchin 	S2I_umax / 41,
167da2e3ebdSchin 	S2I_umax / 42,
168da2e3ebdSchin 	S2I_umax / 43,
169da2e3ebdSchin 	S2I_umax / 44,
170da2e3ebdSchin 	S2I_umax / 45,
171da2e3ebdSchin 	S2I_umax / 46,
172da2e3ebdSchin 	S2I_umax / 47,
173da2e3ebdSchin 	S2I_umax / 48,
174da2e3ebdSchin 	S2I_umax / 49,
175da2e3ebdSchin 	S2I_umax / 50,
176da2e3ebdSchin 	S2I_umax / 51,
177da2e3ebdSchin 	S2I_umax / 52,
178da2e3ebdSchin 	S2I_umax / 53,
179da2e3ebdSchin 	S2I_umax / 54,
180da2e3ebdSchin 	S2I_umax / 55,
181da2e3ebdSchin 	S2I_umax / 56,
182da2e3ebdSchin 	S2I_umax / 57,
183da2e3ebdSchin 	S2I_umax / 58,
184da2e3ebdSchin 	S2I_umax / 59,
185da2e3ebdSchin 	S2I_umax / 60,
186da2e3ebdSchin 	S2I_umax / 61,
187da2e3ebdSchin 	S2I_umax / 62,
188da2e3ebdSchin 	S2I_umax / 63,
189da2e3ebdSchin 	S2I_umax / 64,
190da2e3ebdSchin };
191da2e3ebdSchin 
192da2e3ebdSchin #if defined(__EXPORT__)
193da2e3ebdSchin #define extern		__EXPORT__
194da2e3ebdSchin #endif
195da2e3ebdSchin extern S2I_type
196da2e3ebdSchin #undef	extern
197da2e3ebdSchin #if S2I_size
198da2e3ebdSchin #if S2I_multiplier
199da2e3ebdSchin #if __STD_C
S2I_function(const char * a,size_t size,char ** e,char * basep,int m)200da2e3ebdSchin S2I_function(const char* a, size_t size, char** e, char* basep, int m)
201da2e3ebdSchin #else
202da2e3ebdSchin S2I_function(a, size, e, basep, m) const char* a; size_t size; char** e; char* basep; int m;
203da2e3ebdSchin #endif
204da2e3ebdSchin #else
205da2e3ebdSchin #if __STD_C
206da2e3ebdSchin S2I_function(const char* a, size_t size, char** e, int base)
207da2e3ebdSchin #else
208da2e3ebdSchin S2I_function(a, size, e, base) const char* a; size_t size; char** e; int base;
209da2e3ebdSchin #endif
210da2e3ebdSchin #endif
211da2e3ebdSchin #else
212da2e3ebdSchin #if S2I_multiplier
213da2e3ebdSchin #if __STD_C
214da2e3ebdSchin S2I_function(const char* a, char** e, char* basep, int m)
215da2e3ebdSchin #else
216da2e3ebdSchin S2I_function(a, e, basep, m) const char* a; char** e; char* basep; int m;
217da2e3ebdSchin #endif
218da2e3ebdSchin #else
219da2e3ebdSchin #if __STD_C
220da2e3ebdSchin S2I_function(const char* a, char** e, int base)
221da2e3ebdSchin #else
222da2e3ebdSchin S2I_function(a, e, base) const char* a; char** e; int base;
223da2e3ebdSchin #endif
224da2e3ebdSchin #endif
225da2e3ebdSchin #endif
226da2e3ebdSchin {
227da2e3ebdSchin 	register unsigned char*	s = (unsigned char*)a;
228da2e3ebdSchin #if S2I_size
229da2e3ebdSchin 	register unsigned char*	z = s + size;
230da2e3ebdSchin #endif
231da2e3ebdSchin 	register S2I_unumber	n;
232da2e3ebdSchin 	register S2I_unumber	x;
233da2e3ebdSchin 	register int		c;
234da2e3ebdSchin 	register int		shift;
235da2e3ebdSchin 	register unsigned char*	p;
236da2e3ebdSchin 	register unsigned char*	cv;
237da2e3ebdSchin 	unsigned char*		b;
238da2e3ebdSchin 	unsigned char*		k;
239da2e3ebdSchin 	S2I_unumber		v;
240da2e3ebdSchin #if S2I_multiplier
241da2e3ebdSchin 	register int		base;
242da2e3ebdSchin #endif
243da2e3ebdSchin 	int			negative;
244da2e3ebdSchin 	int			overflow = 0;
245da2e3ebdSchin 	int			decimal = 0;
246da2e3ebdSchin 	int			thousand = 0;
247da2e3ebdSchin #if !S2I_unsigned
248da2e3ebdSchin 	int			qualifier = 0;
249da2e3ebdSchin #endif
250da2e3ebdSchin 
251da2e3ebdSchin #if S2I_multiplier
252da2e3ebdSchin 	base = basep ? *((unsigned char*)basep) : 0;
253da2e3ebdSchin #else
254da2e3ebdSchin 	if (base > 36 && base <= SF_RADIX)
255da2e3ebdSchin 	{
256da2e3ebdSchin 		static int	conformance = -1;
257da2e3ebdSchin 
258da2e3ebdSchin 		if (conformance < 0)
259da2e3ebdSchin 			conformance = !strcmp(astconf("CONFORMANCE", NiL, NiL), "standard");
260da2e3ebdSchin 		if (conformance)
261da2e3ebdSchin 			base = 1;
262da2e3ebdSchin 	}
263da2e3ebdSchin #endif
264da2e3ebdSchin 	if (base && (base < 2 || base > SF_RADIX))
265da2e3ebdSchin 	{
266da2e3ebdSchin 		errno = EINVAL;
267da2e3ebdSchin 		return 0;
268da2e3ebdSchin 	}
269da2e3ebdSchin 	while (S2I_valid(s) && isspace(*s))
270da2e3ebdSchin 		s++;
271da2e3ebdSchin 	if ((negative = S2I_valid(s) && (*s == '-')) || S2I_valid(s) && *s == '+')
272da2e3ebdSchin 		k = ++s;
273da2e3ebdSchin 	else
274da2e3ebdSchin 		k = 0;
275da2e3ebdSchin 	p = s;
276da2e3ebdSchin 	if (!base)
277da2e3ebdSchin 	{
278da2e3ebdSchin 		if (S2I_valid(p) && (c = *p++) >= '0' && c <= '9')
279da2e3ebdSchin 		{
280da2e3ebdSchin 			n = c - '0';
281da2e3ebdSchin 			if (S2I_valid(p) && (c = *p) >= '0' && c <= '9')
282da2e3ebdSchin 			{
283da2e3ebdSchin 				n = (n << 3) + (n << 1) + c - '0';
284da2e3ebdSchin 				p++;
285da2e3ebdSchin 			}
286da2e3ebdSchin 			if (S2I_valid(p) && *p == '#')
287da2e3ebdSchin 			{
288da2e3ebdSchin 				if (n >= 2 && n <= 64)
289da2e3ebdSchin 				{
290da2e3ebdSchin 					k = s = p + 1;
291da2e3ebdSchin 					base = n;
292da2e3ebdSchin 				}
293da2e3ebdSchin 			}
294da2e3ebdSchin 			else if (base)
295da2e3ebdSchin 				base = 0;
296da2e3ebdSchin 			else if (S2I_valid(s) && *s == '0' && S2I_valid(s + 1))
297da2e3ebdSchin 			{
298da2e3ebdSchin 				if ((c = *(s + 1)) == 'x' || c == 'X')
299da2e3ebdSchin 				{
300da2e3ebdSchin 					k = s += 2;
301da2e3ebdSchin 					base = 16;
302da2e3ebdSchin 				}
303da2e3ebdSchin 				else if (c >= '0' && c <= '7')
304da2e3ebdSchin 				{
305da2e3ebdSchin 					s++;
306da2e3ebdSchin 					base = 8;
307da2e3ebdSchin 				}
308da2e3ebdSchin 			}
309da2e3ebdSchin 		}
310da2e3ebdSchin 		if (!base)
311da2e3ebdSchin 			base = 10;
312da2e3ebdSchin 		else if (base < 2 || base > SF_RADIX)
313da2e3ebdSchin 		{
314da2e3ebdSchin 			errno = EINVAL;
315da2e3ebdSchin 			return 0;
316da2e3ebdSchin 		}
317da2e3ebdSchin #if S2I_multiplier
318da2e3ebdSchin 		else
319da2e3ebdSchin 		{
320da2e3ebdSchin 			if (basep)
321da2e3ebdSchin 				*basep = base;
322da2e3ebdSchin 			m = -1;
323da2e3ebdSchin 		}
324da2e3ebdSchin #endif
325da2e3ebdSchin 	}
326da2e3ebdSchin #if S2I_multiplier
327da2e3ebdSchin 	else
328da2e3ebdSchin 		m = -1;
329da2e3ebdSchin #endif
330da2e3ebdSchin 
331da2e3ebdSchin 	/*
332da2e3ebdSchin 	 * this part transcribed from sfvscanf()
333da2e3ebdSchin 	 */
334da2e3ebdSchin 
335da2e3ebdSchin 	SFSETLOCALE(&decimal, &thousand);
336da2e3ebdSchin 	x = mm[base];
337da2e3ebdSchin 	n = 0;
338da2e3ebdSchin 	if (base == 10)
339da2e3ebdSchin 	{
340da2e3ebdSchin 		b = s;
341da2e3ebdSchin 		p = 0;
342da2e3ebdSchin 		for (;;)
343da2e3ebdSchin 		{
344da2e3ebdSchin 			if (S2I_valid(s) && (c = *s++) >= '0' && c <= '9')
345da2e3ebdSchin 			{
346da2e3ebdSchin 				if (n > x)
347da2e3ebdSchin 					overflow = 1;
348da2e3ebdSchin 				else
349da2e3ebdSchin 				{
350da2e3ebdSchin 					n = (n << 3) + (n << 1);
351da2e3ebdSchin 					c -= '0';
352da2e3ebdSchin 					if (ADDOVER(n, c, negative))
353da2e3ebdSchin 						overflow = 1;
354da2e3ebdSchin 					n += c;
355da2e3ebdSchin 				}
356da2e3ebdSchin 			}
357da2e3ebdSchin 			else if (p && (s - p) != (3 + S2I_valid(s)))
358da2e3ebdSchin 			{
359da2e3ebdSchin 				s = p;
360da2e3ebdSchin 				n = v;
361da2e3ebdSchin 				c = 0;
362da2e3ebdSchin 				break;
363da2e3ebdSchin 			}
3647c2fbfb3SApril Chin 			else if (!S2I_valid(s) || c != thousand)
365da2e3ebdSchin 				break;
366da2e3ebdSchin 			else if (!p && (s - b) > 4)
367da2e3ebdSchin 			{
368da2e3ebdSchin 				if (e)
369da2e3ebdSchin 					*e = (char*)s - 1;
370da2e3ebdSchin 				if (overflow)
371da2e3ebdSchin 				{
372da2e3ebdSchin 					errno = ERANGE;
373da2e3ebdSchin #if S2I_unsigned
374da2e3ebdSchin 					n = S2I_max;
375da2e3ebdSchin #else
376da2e3ebdSchin 					n = negative ? S2I_min : S2I_max;
377da2e3ebdSchin #endif
378da2e3ebdSchin 				}
379da2e3ebdSchin 				return n;
380da2e3ebdSchin 			}
381da2e3ebdSchin 			else
382da2e3ebdSchin 			{
383da2e3ebdSchin 				p = s;
384da2e3ebdSchin 				v = n;
385da2e3ebdSchin 			}
386da2e3ebdSchin 		}
387da2e3ebdSchin 	}
388da2e3ebdSchin 	else
389da2e3ebdSchin 	{
390da2e3ebdSchin 		SFCVINIT();
391da2e3ebdSchin 		cv = base <= 36 ? _Sfcv36 : _Sfcv64;
392da2e3ebdSchin 		if ((base & ~(base - 1)) == base)
393da2e3ebdSchin 		{
394da2e3ebdSchin #if !S2I_unsigned
395da2e3ebdSchin 			qualifier |= QU;
396da2e3ebdSchin #endif
397da2e3ebdSchin 			if (base < 8)
398da2e3ebdSchin 				shift = base <  4 ? 1 : 2;
399da2e3ebdSchin 			else if (base < 32)
400da2e3ebdSchin 				shift = base < 16 ? 3 : 4;
401da2e3ebdSchin 			else
402da2e3ebdSchin 				shift = base < 64 ? 5 : 6;
403da2e3ebdSchin 			while (S2I_valid(s) && (c = cv[*s++]) < base)
404da2e3ebdSchin 			{
405da2e3ebdSchin 				if (n > x)
406da2e3ebdSchin 					overflow = 1;
407da2e3ebdSchin 				else
408da2e3ebdSchin 				{
409da2e3ebdSchin 					n <<= shift;
410da2e3ebdSchin 					if (ADDOVER(n, c, negative))
411da2e3ebdSchin 						overflow = 1;
412da2e3ebdSchin 					n += c;
413da2e3ebdSchin 				}
414da2e3ebdSchin 			}
415da2e3ebdSchin 		}
416da2e3ebdSchin 		else
417da2e3ebdSchin 			while (S2I_valid(s) && (c = cv[*s++]) < base)
418da2e3ebdSchin 			{
419da2e3ebdSchin 				if (n > x)
420da2e3ebdSchin 					overflow = 1;
421da2e3ebdSchin 				else
422da2e3ebdSchin 				{
423da2e3ebdSchin 					n *= base;
424da2e3ebdSchin 					if (ADDOVER(n, c, negative))
425da2e3ebdSchin 						overflow = 1;
426da2e3ebdSchin 					n += c;
427da2e3ebdSchin 				}
428da2e3ebdSchin 			}
429da2e3ebdSchin 		c = *(s - 1);
430da2e3ebdSchin 	}
431da2e3ebdSchin 
43234f9b3eeSRoland Mainz #if S2I_qualifier
43334f9b3eeSRoland Mainz 
434da2e3ebdSchin 	/*
435da2e3ebdSchin 	 * optional qualifier suffix
436da2e3ebdSchin 	 */
437da2e3ebdSchin 
438da2e3ebdSchin 	if (S2I_valid(s) && s > (unsigned char*)(a + 1))
439da2e3ebdSchin 	{
440da2e3ebdSchin 		base = 0;
441da2e3ebdSchin 		for (;;)
442da2e3ebdSchin 		{
443da2e3ebdSchin 			if (!(base & QL) && (c == 'l' || c == 'L'))
444da2e3ebdSchin 			{
445da2e3ebdSchin 				base |= QL;
446da2e3ebdSchin 				if (!S2I_valid(s))
447da2e3ebdSchin 					break;
448da2e3ebdSchin 				c = *s++;
449da2e3ebdSchin 				if (c == 'l' || c == 'L')
450da2e3ebdSchin 				{
451da2e3ebdSchin 					if (!S2I_valid(s))
452da2e3ebdSchin 						break;
453da2e3ebdSchin 					c = *s++;
454da2e3ebdSchin 				}
455da2e3ebdSchin 			}
456da2e3ebdSchin 			else if (!(base & QU) && (c == 'u' || c == 'U'))
457da2e3ebdSchin 			{
458da2e3ebdSchin 				base |= QU;
459da2e3ebdSchin #if !S2I_unsigned
460da2e3ebdSchin 				qualifier |= QU;
461da2e3ebdSchin #endif
462da2e3ebdSchin 				if (!S2I_valid(s))
463da2e3ebdSchin 					break;
464da2e3ebdSchin 				c = *s++;
465da2e3ebdSchin 			}
466da2e3ebdSchin 			else
467da2e3ebdSchin 				break;
468da2e3ebdSchin 		}
469da2e3ebdSchin 	}
47034f9b3eeSRoland Mainz #endif
471da2e3ebdSchin 	if (S2I_valid(s))
472da2e3ebdSchin 	{
473da2e3ebdSchin #if S2I_multiplier
474da2e3ebdSchin 		/*
475da2e3ebdSchin 		 * optional multiplier suffix
476da2e3ebdSchin 		 */
477da2e3ebdSchin 
478da2e3ebdSchin 		if (m < 0 || s == (unsigned char*)(a + 1))
479da2e3ebdSchin 			s--;
480da2e3ebdSchin 		else
481da2e3ebdSchin 		{
482*b30d1939SAndy Fiddaman 			x = m != 1;
483da2e3ebdSchin 			switch (c)
484da2e3ebdSchin 			{
485da2e3ebdSchin 			case 'b':
486da2e3ebdSchin 			case 'B':
487da2e3ebdSchin 				shift = 9;
488*b30d1939SAndy Fiddaman 				x = 0;
489da2e3ebdSchin 				break;
490da2e3ebdSchin 			case 'k':
491da2e3ebdSchin 			case 'K':
492da2e3ebdSchin 				shift = 10;
493da2e3ebdSchin 				break;
494da2e3ebdSchin 			case 'm':
495da2e3ebdSchin 			case 'M':
496da2e3ebdSchin 				shift = 20;
497da2e3ebdSchin 				break;
498da2e3ebdSchin 			case 'g':
499da2e3ebdSchin 			case 'G':
500da2e3ebdSchin 				shift = 30;
501da2e3ebdSchin 				break;
502da2e3ebdSchin 			case 't':
503da2e3ebdSchin 			case 'T':
504da2e3ebdSchin 				shift = 40;
505da2e3ebdSchin 				break;
506da2e3ebdSchin 			case 'p':
507da2e3ebdSchin 			case 'P':
508da2e3ebdSchin 				shift = 50;
509da2e3ebdSchin 				break;
510da2e3ebdSchin 			case 'e':
511da2e3ebdSchin 			case 'E':
512da2e3ebdSchin 				shift = 60;
513da2e3ebdSchin 				break;
514da2e3ebdSchin 			default:
515da2e3ebdSchin 				if (m <= 1)
516da2e3ebdSchin 					v = 0;
517da2e3ebdSchin 				else if (c == decimal && S2I_valid(s))
518da2e3ebdSchin 				{
519da2e3ebdSchin 					if (MPYOVER(n, m))
520da2e3ebdSchin 						overflow = 1;
521da2e3ebdSchin 					n *= m;
522da2e3ebdSchin 					v = 0;
523da2e3ebdSchin 					while (S2I_valid(s) && (c = *s++) >= '0' && c <= '9')
524da2e3ebdSchin 						v += (m /= 10) * (c - '0');
525da2e3ebdSchin 					if (ADDOVER(n, v, negative))
526da2e3ebdSchin 						overflow = 1;
527da2e3ebdSchin 					n += v;
528da2e3ebdSchin 					v = 0;
529da2e3ebdSchin 				}
530da2e3ebdSchin 				else
531da2e3ebdSchin 					v = m;
532da2e3ebdSchin 				s--;
533da2e3ebdSchin 				shift = 0;
534da2e3ebdSchin 				break;
535da2e3ebdSchin 			}
536da2e3ebdSchin 			if (shift)
537da2e3ebdSchin 			{
538da2e3ebdSchin 				if (S2I_valid(s))
539da2e3ebdSchin 					switch (*s)
540da2e3ebdSchin 					{
541da2e3ebdSchin 					case 'i':
542da2e3ebdSchin 					case 'I':
543da2e3ebdSchin 						s++;
544*b30d1939SAndy Fiddaman 						x = 0;
545da2e3ebdSchin 						break;
546da2e3ebdSchin 					}
547*b30d1939SAndy Fiddaman 				if (S2I_valid(s))
548*b30d1939SAndy Fiddaman 					switch (*s)
549*b30d1939SAndy Fiddaman 					{
550*b30d1939SAndy Fiddaman 					case 'b':
551*b30d1939SAndy Fiddaman 					case 'B':
552*b30d1939SAndy Fiddaman 						s++;
553*b30d1939SAndy Fiddaman 						break;
554*b30d1939SAndy Fiddaman 					}
555*b30d1939SAndy Fiddaman 				if (x)
556*b30d1939SAndy Fiddaman 				{
557*b30d1939SAndy Fiddaman 					v = 1;
558*b30d1939SAndy Fiddaman 					for (shift /= 10; shift; shift--)
559*b30d1939SAndy Fiddaman 					{
560*b30d1939SAndy Fiddaman 						if (v >= (S2I_max/1000))
561*b30d1939SAndy Fiddaman 						{
562*b30d1939SAndy Fiddaman 							v = 0;
563*b30d1939SAndy Fiddaman 							overflow = 1;
564*b30d1939SAndy Fiddaman 						}
565*b30d1939SAndy Fiddaman 						v *= 1000;
566*b30d1939SAndy Fiddaman 					}
567*b30d1939SAndy Fiddaman 				}
568*b30d1939SAndy Fiddaman 				else
569da2e3ebdSchin #if S2I_unsigned
570da2e3ebdSchin 				if (shift >= (sizeof(S2I_type) * CHAR_BIT))
571da2e3ebdSchin #else
572da2e3ebdSchin 				if (shift >= (sizeof(S2I_type) * CHAR_BIT - 1))
573da2e3ebdSchin #endif
574da2e3ebdSchin 				{
575da2e3ebdSchin 					v = 0;
576da2e3ebdSchin 					overflow = 1;
577da2e3ebdSchin 				}
578da2e3ebdSchin 				else
579da2e3ebdSchin 					v = ((S2I_unumber)1) << shift;
580da2e3ebdSchin 			}
581da2e3ebdSchin 			if (v)
582da2e3ebdSchin 			{
583da2e3ebdSchin 				if (MPYOVER(n, v))
584da2e3ebdSchin 					overflow = 1;
585da2e3ebdSchin 				n *= v;
586da2e3ebdSchin 			}
587da2e3ebdSchin 		}
588da2e3ebdSchin #else
589da2e3ebdSchin 		s--;
590da2e3ebdSchin #endif
591da2e3ebdSchin 	}
592da2e3ebdSchin 	if (s == k)
593da2e3ebdSchin 	{
594da2e3ebdSchin 		s--;
595da2e3ebdSchin #if S2I_multiplier
596da2e3ebdSchin 		if (basep)
597da2e3ebdSchin 			*basep = 10;
598da2e3ebdSchin #endif
599da2e3ebdSchin 	}
600da2e3ebdSchin #if !S2I_unsigned
601da2e3ebdSchin 	else if (!(qualifier & QU))
602da2e3ebdSchin 	{
603da2e3ebdSchin 		if (negative)
604da2e3ebdSchin 		{
605da2e3ebdSchin 			if (!n)
606da2e3ebdSchin 			{
607da2e3ebdSchin 				b = k;
608da2e3ebdSchin 				do
609da2e3ebdSchin 				{
610da2e3ebdSchin 					if (b >= s)
611da2e3ebdSchin 					{
612da2e3ebdSchin 						negative = 0;
613da2e3ebdSchin 						break;
614da2e3ebdSchin 					}
615da2e3ebdSchin 				} while (*b++ == '0');
616da2e3ebdSchin 			}
617da2e3ebdSchin 			if (negative && (n - 1) > S2I_max)
618da2e3ebdSchin 				overflow = 1;
619da2e3ebdSchin 		}
620da2e3ebdSchin 		else if (n > S2I_max)
621da2e3ebdSchin 			overflow = 1;
622da2e3ebdSchin 	}
623da2e3ebdSchin #endif
624da2e3ebdSchin 	if (e)
625da2e3ebdSchin 		*e = (char*)s;
626da2e3ebdSchin 	if (overflow)
627da2e3ebdSchin 	{
628da2e3ebdSchin #if !S2I_unsigned
629da2e3ebdSchin 		if (negative)
630da2e3ebdSchin 		{
631da2e3ebdSchin 			if (x << 1)
632da2e3ebdSchin 				errno = ERANGE;
633da2e3ebdSchin 			return (S2I_type)S2I_min;
634da2e3ebdSchin 		}
635da2e3ebdSchin #endif
636da2e3ebdSchin 		errno = ERANGE;
637da2e3ebdSchin 		return (S2I_type)S2I_max;
638da2e3ebdSchin 	}
639da2e3ebdSchin 	return negative ? -n : n;
640da2e3ebdSchin }
641