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