1 /*  Copyright (C) 2002     Manuel Novoa III
2  *  From my (incomplete) stdlib library for linux and (soon) elks.
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Library General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Library General Public
15  *  License along with this library; if not, see
16  *  <http://www.gnu.org/licenses/>.
17  */
18 
19 /*  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!
20  *
21  *  This code is currently under development.  Also, I plan to port
22  *  it to elks which is a 16-bit environment with a fairly limited
23  *  compiler.  Therefore, please refrain from modifying this code
24  *  and, instead, pass any bug-fixes, etc. to me.  Thanks.  Manuel
25  *
26  *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */
27 
28 /* Oct 29, 2002
29  * Fix a couple of 'restrict' bugs in mbstowcs and wcstombs.
30  *
31  * Nov 21, 2002
32  * Add wscto{inttype} functions.
33  */
34 
35 #include <limits.h>
36 #include <stdint.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 #include <ctype.h>
40 #include <errno.h>
41 #include <assert.h>
42 #include <unistd.h>
43 
44 #include <stdlib.h>
45 #include <locale.h>
46 
47 #ifdef __UCLIBC_HAS_WCHAR__
48 
49 #include <wchar.h>
50 #include <wctype.h>
51 #include <bits/uClibc_uwchar.h>
52 
53 /* TODO: clean up the following... */
54 
55 #if WCHAR_MAX > 0xffffUL
56 #define UTF_8_MAX_LEN 6
57 #else
58 #define UTF_8_MAX_LEN 3
59 #endif
60 
61 #ifdef __UCLIBC_HAS_LOCALE__
62 
63 #define ENCODING		(__UCLIBC_CURLOCALE->encoding)
64 #ifndef __CTYPE_HAS_UTF_8_LOCALES
65 #ifdef L_mblen
66 /* emit only once */
67 #warning __CTYPE_HAS_UTF_8_LOCALES not set!
68 #endif
69 #endif
70 
71 #else  /* __UCLIBC_HAS_LOCALE__ */
72 
73 #ifdef __UCLIBC_MJN3_ONLY__
74 #ifdef L_mblen
75 /* emit only once */
76 #warning devel checks
77 #endif
78 #endif
79 #ifdef __CTYPE_HAS_8_BIT_LOCALES
80 #error __CTYPE_HAS_8_BIT_LOCALES is defined!
81 #endif
82 #ifdef __CTYPE_HAS_UTF_8_LOCALES
83 #error __CTYPE_HAS_UTF_8_LOCALES is defined!
84 #endif
85 #endif
86 
87 #endif /* __UCLIBC_HAS_LOCALE__ */
88 
89 /**********************************************************************/
90 #ifdef __UCLIBC_HAS_XLOCALE__
91 
92 extern unsigned long
93 _stdlib_strto_l_l(register const char * __restrict str,
94 				  char ** __restrict endptr, int base, int sflag,
95 				  __locale_t locale_arg) attribute_hidden;
96 
97 #if defined(ULLONG_MAX)
98 extern unsigned long long
99 _stdlib_strto_ll_l(register const char * __restrict str,
100 				   char ** __restrict endptr, int base, int sflag,
101 				  __locale_t locale_arg) attribute_hidden;
102 #endif
103 
104 #ifdef __UCLIBC_HAS_WCHAR__
105 extern unsigned long
106 _stdlib_wcsto_l_l(register const wchar_t * __restrict str,
107 				  wchar_t ** __restrict endptr, int base, int sflag,
108 				  __locale_t locale_arg) attribute_hidden;
109 
110 #if defined(ULLONG_MAX)
111 extern unsigned long long
112 _stdlib_wcsto_ll_l(register const wchar_t * __restrict str,
113 				   wchar_t ** __restrict endptr, int base, int sflag,
114 				  __locale_t locale_arg) attribute_hidden;
115 #endif
116 #endif /* __UCLIBC_HAS_WCHAR__ */
117 
118 #endif /* __UCLIBC_HAS_XLOCALE__ */
119 
120 
121 
122 extern unsigned long
123 _stdlib_strto_l(register const char * __restrict str,
124 				char ** __restrict endptr, int base, int sflag) attribute_hidden;
125 
126 #if defined(ULLONG_MAX)
127 extern unsigned long long
128 _stdlib_strto_ll(register const char * __restrict str,
129 				 char ** __restrict endptr, int base, int sflag) attribute_hidden;
130 #endif
131 
132 #ifdef __UCLIBC_HAS_WCHAR__
133 extern unsigned long
134 _stdlib_wcsto_l(register const wchar_t * __restrict str,
135 				wchar_t ** __restrict endptr, int base, int sflag) attribute_hidden;
136 
137 #if defined(ULLONG_MAX)
138 extern unsigned long long
139 _stdlib_wcsto_ll(register const wchar_t * __restrict str,
140 				 wchar_t ** __restrict endptr, int base, int sflag) attribute_hidden;
141 #endif
142 #endif /* __UCLIBC_HAS_WCHAR__ */
143 /**********************************************************************/
144 #ifdef L_atof
145 
146 
atof(const char * nptr)147 double atof(const char *nptr)
148 {
149 	return strtod(nptr, (char **) NULL);
150 }
151 
152 #endif
153 /**********************************************************************/
154 #ifdef L_abs
155 
156 #if INT_MAX < LONG_MAX
157 
abs(int j)158 int abs(int j)
159 {
160 	return (j >= 0) ? j : -j;
161 }
162 
163 #endif /* INT_MAX < LONG_MAX */
164 
165 #endif
166 /**********************************************************************/
167 #ifdef L_labs
168 
labs(long int j)169 long int labs(long int j)
170 {
171 	return (j >= 0) ? j : -j;
172 }
173 
174 #if UINT_MAX == ULONG_MAX
strong_alias_untyped(labs,abs)175 strong_alias_untyped(labs,abs)
176 #endif
177 
178 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
179 strong_alias_untyped(labs,llabs)
180 #endif
181 
182 #if ULONG_MAX == UINTMAX_MAX
183 strong_alias_untyped(labs,imaxabs)
184 #endif
185 
186 #endif
187 /**********************************************************************/
188 #ifdef L_llabs
189 
190 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
191 
192 long long int llabs(long long int j)
193 {
194 	return (j >= 0) ? j : -j;
195 }
196 
197 #if (ULLONG_MAX == UINTMAX_MAX)
strong_alias_untyped(llabs,imaxabs)198 strong_alias_untyped(llabs,imaxabs)
199 #endif
200 
201 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
202 
203 #endif
204 /**********************************************************************/
205 #ifdef L_atoi
206 
207 #if INT_MAX < LONG_MAX
208 
209 
210 int atoi(const char *nptr)
211 {
212 	return (int) strtol(nptr, (char **) NULL, 10);
213 }
libc_hidden_def(atoi)214 libc_hidden_def(atoi)
215 
216 #endif /* INT_MAX < LONG_MAX  */
217 
218 #endif
219 /**********************************************************************/
220 #ifdef L_atol
221 
222 
223 long atol(const char *nptr)
224 {
225 	return strtol(nptr, (char **) NULL, 10);
226 }
227 
228 #if UINT_MAX == ULONG_MAX
strong_alias_untyped(atol,atoi)229 strong_alias_untyped(atol,atoi)
230 libc_hidden_def(atoi)
231 #endif
232 
233 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
234 strong_alias_untyped(atol,atoll)
235 #endif
236 
237 #endif
238 /**********************************************************************/
239 #ifdef L_atoll
240 
241 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
242 
243 
244 long long atoll(const char *nptr)
245 {
246 	return strtoll(nptr, (char **) NULL, 10);
247 }
248 
249 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
250 
251 #endif
252 /**********************************************************************/
253 #ifdef L_rpmatch
rpmatch(const char * __response)254 int rpmatch (const char *__response)
255 {
256 	return (__response[0] == 'y' || __response[0] == 'Y') ? 1 :
257 		(__response[0] == 'n' || __response[0] == 'N') ? 0 : -1;
258 }
259 #endif
260 /**********************************************************************/
261 #if defined(L_strtol) || defined(L_strtol_l)
262 
__XL_NPP(strtol)263 long __XL_NPP(strtol)(const char * __restrict str, char ** __restrict endptr,
264 				  int base __LOCALE_PARAM)
265 {
266 	return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 1 __LOCALE_ARG);
267 }
268 libc_hidden_def(__XL_NPP(strtol))
269 
270 #if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtol_l)
strong_alias(strtol,strtoimax)271 strong_alias(strtol,strtoimax)
272 #endif
273 
274 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
275 strong_alias_untyped(__XL_NPP(strtol),__XL_NPP(strtoll))
276 #ifdef L_strtol
277 libc_hidden_def(__XL_NPP(strtoll))
278 strong_alias(strtol,strtoq)
279 #endif
280 #endif
281 
282 #endif
283 /**********************************************************************/
284 #if defined(L_strtoll) || defined(L_strtoll_l)
285 
286 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
287 
288 long long __XL_NPP(strtoll)(const char * __restrict str,
289 						char ** __restrict endptr, int base
290 						__LOCALE_PARAM)
291 {
292 	return (long long) __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 1 __LOCALE_ARG);
293 }
294 #ifdef L_strtoll
295 libc_hidden_def(__XL_NPP(strtoll))
296 #if (ULLONG_MAX == UINTMAX_MAX)
strong_alias(strtoll,strtoimax)297 strong_alias(strtoll,strtoimax)
298 #endif
299 strong_alias(strtoll,strtoq)
300 #endif
301 
302 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
303 
304 #endif
305 /**********************************************************************/
306 #if defined(L_strtoul) || defined(L_strtoul_l)
307 
308 unsigned long __XL_NPP(strtoul)(const char * __restrict str,
309 							char ** __restrict endptr, int base
310 							__LOCALE_PARAM)
311 {
312 	return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 0 __LOCALE_ARG);
313 }
314 libc_hidden_def(__XL_NPP(strtoul))
315 
316 #if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtoul_l)
strong_alias(strtoul,strtoumax)317 strong_alias(strtoul,strtoumax)
318 #endif
319 
320 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
321 strong_alias_untyped(__XL_NPP(strtoul),__XL_NPP(strtoull))
322 #if !defined(L_strtoul_l)
323 strong_alias(strtoul,strtouq)
324 #endif
325 #endif
326 
327 
328 #endif
329 /**********************************************************************/
330 #if defined(L_strtoull) || defined(L_strtoull_l)
331 
332 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
333 
334 unsigned long long __XL_NPP(strtoull)(const char * __restrict str,
335 								  char ** __restrict endptr, int base
336 								  __LOCALE_PARAM)
337 {
338 	return __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 0 __LOCALE_ARG);
339 }
340 
341 #if !defined(L_strtoull_l)
342 #if (ULLONG_MAX == UINTMAX_MAX)
strong_alias(strtoull,strtoumax)343 strong_alias(strtoull,strtoumax)
344 #endif
345 strong_alias(strtoull,strtouq)
346 #endif
347 
348 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
349 
350 #endif
351 /**********************************************************************/
352 /* Support routines follow */
353 /**********************************************************************/
354 /* Set if we want errno set appropriately. */
355 /* NOTE: Implies _STRTO_ENDPTR below */
356 #define _STRTO_ERRNO            1
357 
358 /* Set if we want support for the endptr arg. */
359 /* Implied by _STRTO_ERRNO. */
360 #define _STRTO_ENDPTR           1
361 
362 #if _STRTO_ERRNO
363 #undef _STRTO_ENDPTR
364 #define _STRTO_ENDPTR           1
365 #define SET_ERRNO(X)            __set_errno(X)
366 #else
367 #define SET_ERRNO(X)            ((void)(X))	/* keep side effects */
368 #endif
369 
370 /**********************************************************************/
371 #if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l)
372 #ifndef L__stdlib_strto_l
373 #define L__stdlib_strto_l
374 #endif
375 #endif
376 
377 #if defined(L__stdlib_strto_l) || defined(L__stdlib_strto_l_l)
378 
379 #if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l)
380 
381 #define _stdlib_strto_l _stdlib_wcsto_l
382 #define _stdlib_strto_l_l _stdlib_wcsto_l_l
383 #define Wchar wchar_t
384 #define Wuchar __uwchar_t
385 #ifdef __UCLIBC_DO_XLOCALE
386 #define ISSPACE(C) iswspace_l((C), locale_arg)
387 #else
388 #define ISSPACE(C) iswspace((C))
389 #endif
390 
391 #else  /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */
392 
393 #define Wchar char
394 #define Wuchar unsigned char
395 #ifdef __UCLIBC_DO_XLOCALE
396 #define ISSPACE(C) isspace_l((C), locale_arg)
397 #else
398 #define ISSPACE(C) isspace((C))
399 #endif
400 
401 #endif /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */
402 
403 #if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
404 
405 unsigned long attribute_hidden _stdlib_strto_l(register const Wchar * __restrict str,
406 							  Wchar ** __restrict endptr, int base,
407 							  int sflag)
408 {
409 	return _stdlib_strto_l_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE);
410 }
411 
412 
413 #else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
414 
415 /* This is the main work fuction which handles both strtol (sflag = 1) and
416  * strtoul (sflag = 0). */
417 
418 unsigned long attribute_hidden __XL_NPP(_stdlib_strto_l)(register const Wchar * __restrict str,
419 										Wchar ** __restrict endptr, int base,
420 										int sflag __LOCALE_PARAM)
421 {
422 	unsigned long number, cutoff;
423 #if _STRTO_ENDPTR
424 	const Wchar *fail_char;
425 #define SET_FAIL(X) fail_char = (X)
426 #else
427 #define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
428 #endif
429 	unsigned char negative, digit, cutoff_digit;
430 
431 	assert(((unsigned int)sflag) <= 1);
432 
433 	SET_FAIL(str);
434 
435 	while (ISSPACE(*str)) { /* Skip leading whitespace. */
436 		++str;
437 	}
438 
439 	/* Handle optional sign. */
440 	negative = 0;
441 	switch (*str) {
442 		case '-': negative = 1;	/* Fall through to increment str. */
443 		case '+': ++str;
444 	}
445 
446 	if (!(base & ~0x10)) {		/* Either dynamic (base = 0) or base 16. */
447 		base += 10;				/* Default is 10 (26). */
448 		if (*str == '0') {
449 			SET_FAIL(++str);
450 			base -= 2;			/* Now base is 8 or 16 (24). */
451 			if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
452 				++str;
453 				base += base;	/* Base is 16 (16 or 48). */
454 			}
455 		}
456 
457 		if (base > 16) {		/* Adjust in case base wasn't dynamic. */
458 			base = 16;
459 		}
460 	}
461 
462 	number = 0;
463 
464 	if (((unsigned)(base - 2)) < 35) { /* Legal base. */
465 		cutoff_digit = ULONG_MAX % base;
466 		cutoff = ULONG_MAX / base;
467 		do {
468 			digit = ((Wuchar)(*str - '0') <= 9)
469 				? /* 0..9 */ (*str - '0')
470 				: /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */
471 				   ? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10))
472 				   : /* else   */ 40 /* bad value */);
473 
474 			if (digit >= base) {
475 				break;
476 			}
477 
478 			SET_FAIL(++str);
479 
480 			if ((number > cutoff)
481 				|| ((number == cutoff) && (digit > cutoff_digit))) {
482 				number = ULONG_MAX;
483 				negative &= sflag;
484 				SET_ERRNO(ERANGE);
485 			} else {
486 				number = number * base + digit;
487 			}
488 		} while (1);
489 	}
490 
491 #if _STRTO_ENDPTR
492 	if (endptr) {
493 		*endptr = (Wchar *) fail_char;
494 	}
495 #endif
496 
497 	{
498 		unsigned long tmp = (negative
499 							 ? ((unsigned long)(-(1+LONG_MIN)))+1
500 							 : LONG_MAX);
501 		if (sflag && (number > tmp)) {
502 			number = tmp;
503 			SET_ERRNO(ERANGE);
504 		}
505 	}
506 
507 	return negative ? (unsigned long)(-((long)number)) : number;
508 }
509 
510 #endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
511 
512 
513 #endif
514 /**********************************************************************/
515 #if defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l)
516 #ifndef L__stdlib_strto_ll
517 #define L__stdlib_strto_ll
518 #endif
519 #endif
520 
521 #if defined(L__stdlib_strto_ll) || defined(L__stdlib_strto_ll_l)
522 
523 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
524 
525 #if defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l)
526 #define _stdlib_strto_ll _stdlib_wcsto_ll
527 #define _stdlib_strto_ll_l _stdlib_wcsto_ll_l
528 #define Wchar wchar_t
529 #define Wuchar __uwchar_t
530 #ifdef __UCLIBC_DO_XLOCALE
531 #define ISSPACE(C) iswspace_l((C), locale_arg)
532 #else
533 #define ISSPACE(C) iswspace((C))
534 #endif
535 
536 #else  /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */
537 
538 #define Wchar char
539 #define Wuchar unsigned char
540 #ifdef __UCLIBC_DO_XLOCALE
541 #define ISSPACE(C) isspace_l((C), locale_arg)
542 #else
543 #define ISSPACE(C) isspace((C))
544 #endif
545 
546 #endif /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */
547 
548 #if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
549 
_stdlib_strto_ll(register const Wchar * __restrict str,Wchar ** __restrict endptr,int base,int sflag)550 unsigned long long attribute_hidden _stdlib_strto_ll(register const Wchar * __restrict str,
551 									Wchar ** __restrict endptr, int base,
552 									int sflag)
553 {
554 	return _stdlib_strto_ll_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE);
555 }
556 
557 
558 #else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
559 
560 /* This is the main work fuction which handles both strtoll (sflag = 1) and
561  * strtoull (sflag = 0). */
562 
__XL_NPP(_stdlib_strto_ll)563 unsigned long long attribute_hidden __XL_NPP(_stdlib_strto_ll)(register const Wchar * __restrict str,
564 											  Wchar ** __restrict endptr, int base,
565 											  int sflag __LOCALE_PARAM)
566 {
567 	unsigned long long number;
568 #if _STRTO_ENDPTR
569 	const Wchar *fail_char;
570 #define SET_FAIL(X) fail_char = (X)
571 #else
572 #define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
573 #endif
574 	unsigned int n1;
575 	unsigned char negative, digit;
576 
577 	assert(((unsigned int)sflag) <= 1);
578 
579 	SET_FAIL(str);
580 
581 	while (ISSPACE(*str)) {		/* Skip leading whitespace. */
582 		++str;
583 	}
584 
585 	/* Handle optional sign. */
586 	negative = 0;
587 	switch (*str) {
588 		case '-': negative = 1;	/* Fall through to increment str. */
589 		case '+': ++str;
590 	}
591 
592 	if (!(base & ~0x10)) {		/* Either dynamic (base = 0) or base 16. */
593 		base += 10;				/* Default is 10 (26). */
594 		if (*str == '0') {
595 			SET_FAIL(++str);
596 			base -= 2;			/* Now base is 8 or 16 (24). */
597 			if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
598 				++str;
599 				base += base;	/* Base is 16 (16 or 48). */
600 			}
601 		}
602 
603 		if (base > 16) {		/* Adjust in case base wasn't dynamic. */
604 			base = 16;
605 		}
606 	}
607 
608 	number = 0;
609 
610 	if (((unsigned)(base - 2)) < 35) { /* Legal base. */
611 		do {
612 			digit = ((Wuchar)(*str - '0') <= 9)
613 				? /* 0..9 */ (*str - '0')
614 				: /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */
615 				   ? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10))
616 				   : /* else   */ 40 /* bad value */);
617 
618 			if (digit >= base) {
619 				break;
620 			}
621 
622 			SET_FAIL(++str);
623 
624 #if 1
625 			/* Optional, but speeds things up in the usual case. */
626 			if (number <= (ULLONG_MAX >> 6)) {
627 				number = number * base + digit;
628 			} else
629 #endif
630 			{
631 				n1 = ((unsigned char) number) * base + digit;
632 				number = (number >> CHAR_BIT) * base;
633 
634 				if (number + (n1 >> CHAR_BIT) <= (ULLONG_MAX >> CHAR_BIT)) {
635 					number = (number << CHAR_BIT) + n1;
636 				} else {		/* Overflow. */
637 					number = ULLONG_MAX;
638 					negative &= sflag;
639 					SET_ERRNO(ERANGE);
640 				}
641 			}
642 
643 		} while (1);
644 	}
645 
646 #if _STRTO_ENDPTR
647 	if (endptr) {
648 		*endptr = (Wchar *) fail_char;
649 	}
650 #endif
651 
652 	{
653 		unsigned long long tmp = ((negative)
654 								  ? ((unsigned long long)(-(1+LLONG_MIN)))+1
655 								  : LLONG_MAX);
656 		if (sflag && (number > tmp)) {
657 			number = tmp;
658 			SET_ERRNO(ERANGE);
659 		}
660 	}
661 
662 	return negative ? (unsigned long long)(-((long long)number)) : number;
663 }
664 
665 #endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
666 
667 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
668 
669 #endif
670 
671 #ifdef L_bsearch
672 
bsearch(const void * key,const void * base,size_t high,size_t size,int (* compar)(const void *,const void *))673 void *bsearch(const void *key, const void *base, size_t /* nmemb */ high,
674 			  size_t size, int (*compar)(const void *, const void *))
675 {
676 	register char *p;
677 	size_t low;
678 	size_t mid;
679 	int r;
680 
681 	if (size > 0) {				/* TODO: change this to an assert?? */
682 		low = 0;
683 		while (low < high) {
684 			mid = low + ((high - low) >> 1); /* Avoid possible overflow here. */
685 			p = ((char *)base) + mid * size; /* Could overflow here... */
686 			r = (*compar)(key, p); /* but that's an application problem! */
687 			if (r > 0) {
688 				low = mid + 1;
689 			} else if (r < 0) {
690 				high = mid;
691 			} else {
692 				return p;
693 			}
694 		}
695 	}
696 	return NULL;
697 }
698 
699 #endif
700 /**********************************************************************/
701 #ifdef L_qsort_r
702 
703 /* This code is derived from a public domain shell sort routine by
704  * Ray Gardner and found in Bob Stout's snippets collection.  The
705  * original code is included below in an #if 0/#endif block.
706  *
707  * I modified it to avoid the possibility of overflow in the wgap
708  * calculation, as well as to reduce the generated code size with
709  * bcc and gcc. */
710 
qsort_r(void * base,size_t nel,size_t width,__compar_d_fn_t comp,void * arg)711 void qsort_r(void  *base,
712            size_t nel,
713            size_t width,
714            __compar_d_fn_t comp,
715 		   void *arg)
716 {
717 	size_t wgap, i, j, k;
718 	char tmp;
719 
720 	if ((nel > 1) && (width > 0)) {
721 		assert(nel <= ((size_t)(-1)) / width); /* check for overflow */
722 		wgap = 0;
723 		do {
724 			wgap = 3 * wgap + 1;
725 		} while (wgap < (nel-1)/3);
726 		/* From the above, we know that either wgap == 1 < nel or */
727 		/* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap <  nel. */
728 		wgap *= width;			/* So this can not overflow if wnel doesn't. */
729 		nel *= width;			/* Convert nel to 'wnel' */
730 		do {
731 			i = wgap;
732 			do {
733 				j = i;
734 				do {
735 					register char *a;
736 					register char *b;
737 
738 					j -= wgap;
739 					a = j + ((char *)base);
740 					b = a + wgap;
741 					if ((*comp)(a, b, arg) <= 0) {
742 						break;
743 					}
744 					k = width;
745 					do {
746 						tmp = *a;
747 						*a++ = *b;
748 						*b++ = tmp;
749 					} while (--k);
750 				} while (j >= wgap);
751 				i += width;
752 			} while (i < nel);
753 			wgap = (wgap - width)/3;
754 		} while (wgap);
755 	}
756 }
libc_hidden_def(qsort_r)757 libc_hidden_def(qsort_r)
758 
759 /* ---------- original snippets version below ---------- */
760 
761 #if 0
762 /*
763 **  ssort()  --  Fast, small, qsort()-compatible Shell sort
764 **
765 **  by Ray Gardner,  public domain   5/90
766 */
767 
768 #include <stddef.h>
769 
770 void ssort(void  *base,
771            size_t nel,
772            size_t width,
773            int (*comp)(const void *, const void *))
774 {
775 	size_t wnel, gap, wgap, i, j, k;
776 	char *a, *b, tmp;
777 
778 	wnel = width * nel;
779 	for (gap = 0; ++gap < nel;)
780 		gap *= 3;
781 	while ((gap /= 3) != 0) {
782 		wgap = width * gap;
783 		for (i = wgap; i < wnel; i += width) {
784 			for (j = i - wgap; ;j -= wgap) {
785 				a = j + (char *)base;
786 				b = a + wgap;
787 				if ((*comp)(a, b) <= 0)
788 					break;
789 				k = width;
790 				do {
791 					tmp = *a;
792 					*a++ = *b;
793 					*b++ = tmp;
794 				} while (--k);
795 				if (j < wgap)
796 					break;
797 			}
798 		}
799 	}
800 }
801 #endif
802 
803 #endif
804 
805 #ifdef L_qsort
806 void qsort(void  *base,
807            size_t nel,
808            size_t width,
809            __compar_fn_t comp)
810 {
811 	return qsort_r (base, nel, width, (__compar_d_fn_t) comp, NULL);
812 }
libc_hidden_def(qsort)813 libc_hidden_def(qsort)
814 #endif
815 
816 /**********************************************************************/
817 #ifdef L__stdlib_mb_cur_max
818 
819 size_t _stdlib_mb_cur_max(void)
820 {
821 #ifdef __CTYPE_HAS_UTF_8_LOCALES
822 	return __UCLIBC_CURLOCALE->mb_cur_max;
823 #else
824 #ifdef __CTYPE_HAS_8_BIT_LOCALES
825 #ifdef __UCLIBC_MJN3_ONLY__
826 #warning need to change this when/if transliteration is implemented
827 #endif
828 #endif
829 	return 1;
830 #endif
831 }
libc_hidden_def(_stdlib_mb_cur_max)832 libc_hidden_def(_stdlib_mb_cur_max)
833 
834 #endif
835 
836 #ifdef __UCLIBC_HAS_LOCALE__
837 /*
838  * The following function return 1 if the encoding is stateful, 0 if stateless.
839  * To note, until now all the supported encoding are stateless.
840  */
841 
842 static __always_inline int is_stateful(unsigned char encoding)
843 {
844 	switch (encoding)
845 	{
846 		case __ctype_encoding_7_bit:
847 		case __ctype_encoding_utf8:
848 		case __ctype_encoding_8_bit:
849 			return 0;
850 		default:
851 			assert(0);
852 			return -1;
853 	}
854 }
855 #else
856 #define is_stateful(encoding) 0
857 #endif
858 
859 /**********************************************************************/
860 #ifdef L_mblen
861 
862 
mblen(register const char * s,size_t n)863 int mblen(register const char *s, size_t n)
864 {
865 	static mbstate_t state;
866 	size_t r;
867 
868 	if (!s) {
869 		state.__mask = 0;
870 		/*
871 			In this case we have to return 0 because the only multibyte supported encoding
872 			is utf-8, that is a stateless encoding. See mblen() documentation.
873 		*/
874 		return is_stateful(ENCODING);
875 	}
876 
877 	if (*s == '\0')
878 		/* According to the ISO C 89 standard this is the expected behaviour.  */
879 		return 0;
880 
881 	if ((r = mbrlen(s, n, &state)) == (size_t) -2) {
882 		/* TODO: Should we set an error state? */
883 		state.__wc = 0xffffU;	/* Make sure we're in an error state. */
884 		return -1;		/* TODO: Change error code above? */
885 	}
886 	return r;
887 }
888 
889 #endif
890 /**********************************************************************/
891 #ifdef L_mbtowc
892 
893 
mbtowc(wchar_t * __restrict pwc,register const char * __restrict s,size_t n)894 int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
895 {
896 	static mbstate_t state;
897 	size_t r;
898 
899 	if (!s) {
900 		state.__mask = 0;
901 		/*
902 			In this case we have to return 0 because the only multibyte supported encoding
903 			is utf-8, that is a stateless encoding. See mbtowc() documentation.
904 		*/
905 
906 		return is_stateful(ENCODING);
907 	}
908 
909 	if (*s == '\0')
910 		/* According to the ISO C 89 standard this is the expected behaviour.  */
911 		return 0;
912 
913 	if ((r = mbrtowc(pwc, s, n, &state)) == (size_t) -2) {
914 		/* TODO: Should we set an error state? */
915 		state.__wc = 0xffffU;	/* Make sure we're in an error state. */
916 		return -1;		/* TODO: Change error code above? */
917 	}
918 	return r;
919 }
920 
921 #endif
922 /**********************************************************************/
923 #ifdef L_wctomb
924 
925 /* Note: We completely ignore state in all currently supported conversions. */
926 
927 
wctomb(register char * __restrict s,wchar_t swc)928 int wctomb(register char *__restrict s, wchar_t swc)
929 {
930 	return (!s)
931 		?
932 		/*
933 			In this case we have to return 0 because the only multibyte supported encoding
934 			is utf-8, that is a stateless encoding. See wctomb() documentation.
935 		*/
936 
937 		is_stateful(ENCODING)
938 		: ((ssize_t) wcrtomb(s, swc, NULL));
939 }
940 
941 #endif
942 /**********************************************************************/
943 #ifdef L_mbstowcs
944 
945 
mbstowcs(wchar_t * __restrict pwcs,const char * __restrict s,size_t n)946 size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
947 {
948 	mbstate_t state;
949 	const char *e = s;			/* Needed because of restrict. */
950 
951 	state.__mask = 0;			/* Always start in initial shift state. */
952 	return mbsrtowcs(pwcs, &e, n, &state);
953 }
954 
955 #endif
956 /**********************************************************************/
957 #ifdef L_wcstombs
958 
959 /* Note: We completely ignore state in all currently supported conversions. */
960 
961 
wcstombs(char * __restrict s,const wchar_t * __restrict pwcs,size_t n)962 size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
963 {
964 	const wchar_t *e = pwcs;	/* Needed because of restrict. */
965 
966 	return wcsrtombs(s, &e, n, NULL);
967 }
968 
969 #endif
970 /**********************************************************************/
971 #if defined(L_wcstol) || defined(L_wcstol_l)
972 
__XL_NPP(wcstol)973 long __XL_NPP(wcstol)(const wchar_t * __restrict str,
974 				  wchar_t ** __restrict endptr, int base __LOCALE_PARAM)
975 {
976 	return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 1 __LOCALE_ARG);
977 }
978 
979 #if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstol_l)
strong_alias(wcstol,wcstoimax)980 strong_alias(wcstol,wcstoimax)
981 #endif
982 
983 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
984 strong_alias_untyped(__XL_NPP(wcstol),__XL_NPP(wcstoll))
985 #endif
986 
987 #endif
988 /**********************************************************************/
989 #if defined(L_wcstoll) || defined(L_wcstoll_l)
990 
991 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
992 
993 long long __XL_NPP(wcstoll)(const wchar_t * __restrict str,
994 						wchar_t ** __restrict endptr, int base
995 						__LOCALE_PARAM)
996 {
997 	return (long long) __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 1 __LOCALE_ARG);
998 }
999 
1000 #if !defined(L_wcstoll_l)
1001 #if (ULLONG_MAX == UINTMAX_MAX)
strong_alias(wcstoll,wcstoimax)1002 strong_alias(wcstoll,wcstoimax)
1003 #endif
1004 strong_alias(wcstoll,wcstoq)
1005 #endif
1006 
1007 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
1008 
1009 #endif
1010 /**********************************************************************/
1011 #if defined(L_wcstoul) || defined(L_wcstoul_l)
1012 
1013 unsigned long __XL_NPP(wcstoul)(const wchar_t * __restrict str,
1014 							wchar_t ** __restrict endptr, int base
1015 							__LOCALE_PARAM)
1016 {
1017 	return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 0 __LOCALE_ARG);
1018 }
1019 
1020 #if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstoul_l)
strong_alias(wcstoul,wcstoumax)1021 strong_alias(wcstoul,wcstoumax)
1022 #endif
1023 
1024 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
1025 strong_alias_untyped(__XL_NPP(wcstoul),__XL_NPP(wcstoull))
1026 #endif
1027 
1028 #endif
1029 /**********************************************************************/
1030 #if defined(L_wcstoull) || defined(L_wcstoull_l)
1031 
1032 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
1033 
1034 unsigned long long __XL_NPP(wcstoull)(const wchar_t * __restrict str,
1035 								  wchar_t ** __restrict endptr, int base
1036 								  __LOCALE_PARAM)
1037 {
1038 	return __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 0 __LOCALE_ARG);
1039 }
1040 
1041 #if !defined(L_wcstoull_l)
1042 #if (ULLONG_MAX == UINTMAX_MAX)
1043 strong_alias(wcstoull,wcstoumax)
1044 #endif
1045 strong_alias(wcstoull,wcstouq)
1046 #endif
1047 
1048 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
1049 
1050 #endif
1051 /**********************************************************************/
1052