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