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