or1k: add clone() from old GNU libc implementation
[uclibc-ng.git] / libc / stdlib / stdlib.c
blob075e6e5d6d734173b25f3586e80b871feee97fea
1 /* Copyright (C) 2002 Manuel Novoa III
2 * From my (incomplete) stdlib library for linux and (soon) elks.
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.
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.
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/>.
19 /* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
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
26 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
28 /* Oct 29, 2002
29 * Fix a couple of 'restrict' bugs in mbstowcs and wcstombs.
31 * Nov 21, 2002
32 * Add wscto{inttype} functions.
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>
44 #include <stdlib.h>
45 #include <locale.h>
47 #ifdef __UCLIBC_HAS_WCHAR__
49 #include <wchar.h>
50 #include <wctype.h>
51 #include <bits/uClibc_uwchar.h>
53 /* TODO: clean up the following... */
55 #if WCHAR_MAX > 0xffffUL
56 #define UTF_8_MAX_LEN 6
57 #else
58 #define UTF_8_MAX_LEN 3
59 #endif
61 #ifdef __UCLIBC_HAS_LOCALE__
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
71 #else /* __UCLIBC_HAS_LOCALE__ */
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
81 #endif /* __UCLIBC_HAS_LOCALE__ */
83 /**********************************************************************/
84 #ifdef __UCLIBC_HAS_XLOCALE__
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;
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
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;
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__ */
112 #endif /* __UCLIBC_HAS_XLOCALE__ */
116 extern unsigned long
117 _stdlib_strto_l(register const char * __restrict str,
118 char ** __restrict endptr, int base, int sflag) attribute_hidden;
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
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;
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
141 double atof(const char *nptr)
143 return strtod(nptr, (char **) NULL);
146 #endif
147 /**********************************************************************/
148 #ifdef L_abs
150 #if INT_MAX < LONG_MAX
152 int abs(int j)
154 return (j >= 0) ? j : -j;
157 #endif /* INT_MAX < LONG_MAX */
159 #endif
160 /**********************************************************************/
161 #ifdef L_labs
163 long int labs(long int j)
165 return (j >= 0) ? j : -j;
168 #if UINT_MAX == ULONG_MAX
169 strong_alias_untyped(labs,abs)
170 #endif
172 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
173 strong_alias_untyped(labs,llabs)
174 #endif
176 #if ULONG_MAX == UINTMAX_MAX
177 strong_alias_untyped(labs,imaxabs)
178 #endif
180 #endif
181 /**********************************************************************/
182 #ifdef L_llabs
184 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
186 long long int llabs(long long int j)
188 return (j >= 0) ? j : -j;
191 #if (ULLONG_MAX == UINTMAX_MAX)
192 strong_alias_untyped(llabs,imaxabs)
193 #endif
195 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
197 #endif
198 /**********************************************************************/
199 #ifdef L_atoi
201 #if INT_MAX < LONG_MAX
204 int atoi(const char *nptr)
206 return (int) strtol(nptr, (char **) NULL, 10);
208 libc_hidden_def(atoi)
210 #endif /* INT_MAX < LONG_MAX */
212 #endif
213 /**********************************************************************/
214 #ifdef L_atol
217 long atol(const char *nptr)
219 return strtol(nptr, (char **) NULL, 10);
222 #if UINT_MAX == ULONG_MAX
223 strong_alias_untyped(atol,atoi)
224 libc_hidden_def(atoi)
225 #endif
227 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
228 strong_alias_untyped(atol,atoll)
229 #endif
231 #endif
232 /**********************************************************************/
233 #ifdef L_atoll
235 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
238 long long atoll(const char *nptr)
240 return strtoll(nptr, (char **) NULL, 10);
243 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
245 #endif
246 /**********************************************************************/
247 #ifdef L_rpmatch
248 int rpmatch (const char *__response)
250 return (__response[0] == 'y' || __response[0] == 'Y') ? 1 :
251 (__response[0] == 'n' || __response[0] == 'N') ? 0 : -1;
253 #endif
254 /**********************************************************************/
255 #if defined(L_strtol) || defined(L_strtol_l)
257 long __XL_NPP(strtol)(const char * __restrict str, char ** __restrict endptr,
258 int base __LOCALE_PARAM)
260 return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 1 __LOCALE_ARG);
262 libc_hidden_def(__XL_NPP(strtol))
264 #if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtol_l)
265 strong_alias(strtol,strtoimax)
266 #endif
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
276 #endif
277 /**********************************************************************/
278 #if defined(L_strtoll) || defined(L_strtoll_l)
280 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
282 long long __XL_NPP(strtoll)(const char * __restrict str,
283 char ** __restrict endptr, int base
284 __LOCALE_PARAM)
286 return (long long) __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 1 __LOCALE_ARG);
288 #ifdef L_strtoll
289 libc_hidden_def(__XL_NPP(strtoll))
290 #if (ULLONG_MAX == UINTMAX_MAX)
291 strong_alias(strtoll,strtoimax)
292 #endif
293 strong_alias(strtoll,strtoq)
294 #endif
296 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
298 #endif
299 /**********************************************************************/
300 #if defined(L_strtoul) || defined(L_strtoul_l)
302 unsigned long __XL_NPP(strtoul)(const char * __restrict str,
303 char ** __restrict endptr, int base
304 __LOCALE_PARAM)
306 return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 0 __LOCALE_ARG);
308 libc_hidden_def(__XL_NPP(strtoul))
310 #if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtoul_l)
311 strong_alias(strtoul,strtoumax)
312 #endif
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
322 #endif
323 /**********************************************************************/
324 #if defined(L_strtoull) || defined(L_strtoull_l)
326 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
328 unsigned long long __XL_NPP(strtoull)(const char * __restrict str,
329 char ** __restrict endptr, int base
330 __LOCALE_PARAM)
332 return __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 0 __LOCALE_ARG);
335 #if !defined(L_strtoull_l)
336 #if (ULLONG_MAX == UINTMAX_MAX)
337 strong_alias(strtoull,strtoumax)
338 #endif
339 strong_alias(strtoull,strtouq)
340 #endif
342 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
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
352 /* Set if we want support for the endptr arg. */
353 /* Implied by _STRTO_ERRNO. */
354 #define _STRTO_ENDPTR 1
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
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
371 #if defined(L__stdlib_strto_l) || defined(L__stdlib_strto_l_l)
373 #if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l)
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
385 #else /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */
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
395 #endif /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */
397 #if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
399 unsigned long attribute_hidden _stdlib_strto_l(register const Wchar * __restrict str,
400 Wchar ** __restrict endptr, int base,
401 int sflag)
403 return _stdlib_strto_l_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE);
407 #else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
409 /* This is the main work fuction which handles both strtol (sflag = 1) and
410 * strtoul (sflag = 0). */
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)
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;
425 assert(((unsigned int)sflag) <= 1);
427 SET_FAIL(str);
429 while (ISSPACE(*str)) { /* Skip leading whitespace. */
430 ++str;
433 /* Handle optional sign. */
434 negative = 0;
435 switch (*str) {
436 case '-': negative = 1; /* Fall through to increment str. */
437 case '+': ++str;
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). */
451 if (base > 16) { /* Adjust in case base wasn't dynamic. */
452 base = 16;
456 number = 0;
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 */);
468 if (digit >= base) {
469 break;
472 SET_FAIL(++str);
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;
482 } while (1);
485 #if _STRTO_ENDPTR
486 if (endptr) {
487 *endptr = (Wchar *) fail_char;
489 #endif
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);
501 return negative ? (unsigned long)(-((long)number)) : number;
504 #endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
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
515 #if defined(L__stdlib_strto_ll) || defined(L__stdlib_strto_ll_l)
517 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
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
530 #else /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */
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
540 #endif /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */
542 #if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
544 unsigned long long attribute_hidden _stdlib_strto_ll(register const Wchar * __restrict str,
545 Wchar ** __restrict endptr, int base,
546 int sflag)
548 return _stdlib_strto_ll_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE);
552 #else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
554 /* This is the main work fuction which handles both strtoll (sflag = 1) and
555 * strtoull (sflag = 0). */
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)
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;
571 assert(((unsigned int)sflag) <= 1);
573 SET_FAIL(str);
575 while (ISSPACE(*str)) { /* Skip leading whitespace. */
576 ++str;
579 /* Handle optional sign. */
580 negative = 0;
581 switch (*str) {
582 case '-': negative = 1; /* Fall through to increment str. */
583 case '+': ++str;
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). */
597 if (base > 16) { /* Adjust in case base wasn't dynamic. */
598 base = 16;
602 number = 0;
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 */);
612 if (digit >= base) {
613 break;
616 SET_FAIL(++str);
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
625 n1 = ((unsigned char) number) * base + digit;
626 number = (number >> CHAR_BIT) * base;
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);
637 } while (1);
640 #if _STRTO_ENDPTR
641 if (endptr) {
642 *endptr = (Wchar *) fail_char;
644 #endif
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);
656 return negative ? (unsigned long long)(-((long long)number)) : number;
659 #endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
661 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
663 #endif
665 #ifdef L_bsearch
667 void *bsearch(const void *key, const void *base, size_t /* nmemb */ high,
668 size_t size, int (*compar)(const void *, const void *))
670 register char *p;
671 size_t low;
672 size_t mid;
673 int r;
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;
690 return NULL;
693 #endif
694 /**********************************************************************/
695 #ifdef L_qsort_r
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.
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. */
705 void qsort_r(void *base,
706 size_t nel,
707 size_t width,
708 __compar_d_fn_t comp,
709 void *arg)
711 size_t wgap, i, j, k;
712 char tmp;
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;
732 j -= wgap;
733 a = j + ((char *)base);
734 b = a + wgap;
735 if ((*comp)(a, b, arg) <= 0) {
736 break;
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);
751 libc_hidden_def(qsort_r)
753 /* ---------- original snippets version below ---------- */
755 #if 0
757 ** ssort() -- Fast, small, qsort()-compatible Shell sort
759 ** by Ray Gardner, public domain 5/90
762 #include <stddef.h>
764 void ssort(void *base,
765 size_t nel,
766 size_t width,
767 int (*comp)(const void *, const void *))
769 size_t wnel, gap, wgap, i, j, k;
770 char *a, *b, tmp;
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;
795 #endif
797 #endif
799 #ifdef L_qsort
800 void qsort(void *base,
801 size_t nel,
802 size_t width,
803 __compar_fn_t comp)
805 return qsort_r (base, nel, width, (__compar_d_fn_t) comp, NULL);
807 libc_hidden_def(qsort)
808 #endif
810 /**********************************************************************/
811 #ifdef L__stdlib_mb_cur_max
813 size_t _stdlib_mb_cur_max(void)
815 #ifdef __CTYPE_HAS_UTF_8_LOCALES
816 return __UCLIBC_CURLOCALE->mb_cur_max;
817 #else
818 return 1;
819 #endif
821 libc_hidden_def(_stdlib_mb_cur_max)
823 #endif
825 #ifdef __UCLIBC_HAS_LOCALE__
827 * The following function return 1 if the encoding is stateful, 0 if stateless.
828 * To note, until now all the supported encoding are stateless.
831 static __always_inline int is_stateful(unsigned char encoding)
833 switch (encoding)
835 case __ctype_encoding_7_bit:
836 case __ctype_encoding_utf8:
837 case __ctype_encoding_8_bit:
838 return 0;
839 default:
840 assert(0);
841 return -1;
844 #else
845 #define is_stateful(encoding) 0
846 #endif
848 /**********************************************************************/
849 #ifdef L_mblen
852 int mblen(register const char *s, size_t n)
854 static mbstate_t state;
855 size_t r;
857 if (!s) {
858 state.__mask = 0;
860 In this case we have to return 0 because the only multibyte supported encoding
861 is utf-8, that is a stateless encoding. See mblen() documentation.
863 return is_stateful(ENCODING);
866 if (*s == '\0')
867 /* According to the ISO C 89 standard this is the expected behaviour. */
868 return 0;
870 if ((r = mbrlen(s, n, &state)) == (size_t) -2) {
871 /* TODO: Should we set an error state? */
872 state.__wc = 0xffffU; /* Make sure we're in an error state. */
873 return -1; /* TODO: Change error code above? */
875 return r;
878 #endif
879 /**********************************************************************/
880 #ifdef L_mbtowc
883 int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
885 static mbstate_t state;
886 size_t r;
888 if (!s) {
889 state.__mask = 0;
891 In this case we have to return 0 because the only multibyte supported encoding
892 is utf-8, that is a stateless encoding. See mbtowc() documentation.
895 return is_stateful(ENCODING);
898 if (*s == '\0')
899 /* According to the ISO C 89 standard this is the expected behaviour. */
900 return 0;
902 if ((r = mbrtowc(pwc, s, n, &state)) == (size_t) -2) {
903 /* TODO: Should we set an error state? */
904 state.__wc = 0xffffU; /* Make sure we're in an error state. */
905 return -1; /* TODO: Change error code above? */
907 return r;
910 #endif
911 /**********************************************************************/
912 #ifdef L_wctomb
914 /* Note: We completely ignore state in all currently supported conversions. */
917 int wctomb(register char *__restrict s, wchar_t swc)
919 return (!s)
922 In this case we have to return 0 because the only multibyte supported encoding
923 is utf-8, that is a stateless encoding. See wctomb() documentation.
926 is_stateful(ENCODING)
927 : ((ssize_t) wcrtomb(s, swc, NULL));
930 #endif
931 /**********************************************************************/
932 #ifdef L_mbstowcs
935 size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
937 mbstate_t state;
938 const char *e = s; /* Needed because of restrict. */
940 state.__mask = 0; /* Always start in initial shift state. */
941 return mbsrtowcs(pwcs, &e, n, &state);
944 #endif
945 /**********************************************************************/
946 #ifdef L_wcstombs
948 /* Note: We completely ignore state in all currently supported conversions. */
951 size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
953 const wchar_t *e = pwcs; /* Needed because of restrict. */
955 return wcsrtombs(s, &e, n, NULL);
958 #endif
959 /**********************************************************************/
960 #if defined(L_wcstol) || defined(L_wcstol_l)
962 long __XL_NPP(wcstol)(const wchar_t * __restrict str,
963 wchar_t ** __restrict endptr, int base __LOCALE_PARAM)
965 return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 1 __LOCALE_ARG);
968 #if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstol_l)
969 strong_alias(wcstol,wcstoimax)
970 #endif
972 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
973 strong_alias_untyped(__XL_NPP(wcstol),__XL_NPP(wcstoll))
974 #endif
976 #endif
977 /**********************************************************************/
978 #if defined(L_wcstoll) || defined(L_wcstoll_l)
980 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
982 long long __XL_NPP(wcstoll)(const wchar_t * __restrict str,
983 wchar_t ** __restrict endptr, int base
984 __LOCALE_PARAM)
986 return (long long) __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 1 __LOCALE_ARG);
989 #if !defined(L_wcstoll_l)
990 #if (ULLONG_MAX == UINTMAX_MAX)
991 strong_alias(wcstoll,wcstoimax)
992 #endif
993 strong_alias(wcstoll,wcstoq)
994 #endif
996 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
998 #endif
999 /**********************************************************************/
1000 #if defined(L_wcstoul) || defined(L_wcstoul_l)
1002 unsigned long __XL_NPP(wcstoul)(const wchar_t * __restrict str,
1003 wchar_t ** __restrict endptr, int base
1004 __LOCALE_PARAM)
1006 return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 0 __LOCALE_ARG);
1009 #if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstoul_l)
1010 strong_alias(wcstoul,wcstoumax)
1011 #endif
1013 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
1014 strong_alias_untyped(__XL_NPP(wcstoul),__XL_NPP(wcstoull))
1015 #endif
1017 #endif
1018 /**********************************************************************/
1019 #if defined(L_wcstoull) || defined(L_wcstoull_l)
1021 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
1023 unsigned long long __XL_NPP(wcstoull)(const wchar_t * __restrict str,
1024 wchar_t ** __restrict endptr, int base
1025 __LOCALE_PARAM)
1027 return __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 0 __LOCALE_ARG);
1030 #if !defined(L_wcstoull_l)
1031 #if (ULLONG_MAX == UINTMAX_MAX)
1032 strong_alias(wcstoull,wcstoumax)
1033 #endif
1034 strong_alias(wcstoull,wcstouq)
1035 #endif
1037 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
1039 #endif
1040 /**********************************************************************/