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, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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! */
29 * Fix a couple of 'restrict' bugs in mbstowcs and wcstombs.
32 * Add wscto{inttype} functions.
35 #define _ISOC99_SOURCE /* for ULLONG primarily... */
45 /* Work around gcc's refusal to create aliases.
46 * TODO: Add in a define to disable the aliases? */
48 #if UINT_MAX == ULONG_MAX
49 #define atoi __ignore_atoi
50 #define abs __ignore_abs
52 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
53 #define llabs __ignore_llabs
54 #define atoll __ignore_atoll
55 #define strtoll __ignore_strtoll
56 #define strtoull __ignore_strtoull
57 #define wcstoll __ignore_wcstoll
58 #define wcstoull __ignore_wcstoull
63 #ifdef __UCLIBC_HAS_WCHAR__
69 /* TODO: clean up the following... */
71 #if WCHAR_MAX > 0xffffUL
72 #define UTF_8_MAX_LEN 6
74 #define UTF_8_MAX_LEN 3
77 #ifdef __UCLIBC_HAS_LOCALE__
78 #define ENCODING (__global_locale.encoding)
79 #ifndef __CTYPE_HAS_UTF_8_LOCALES
80 #warning __CTYPE_HAS_UTF_8_LOCALES not set!
83 #ifdef __UCLIBC_MJN3_ONLY__
86 #define ENCODING (__ctype_encoding_7_bit)
87 #ifdef __CTYPE_HAS_8_BIT_LOCALES
88 #error __CTYPE_HAS_8_BIT_LOCALES is defined!
90 #ifdef __CTYPE_HAS_UTF_8_LOCALES
91 #error __CTYPE_HAS_UTF_8_LOCALES is defined!
97 #if UINT_MAX == ULONG_MAX
101 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
108 #endif /* __UCLIBC_HAS_WCHAR__ */
110 /**********************************************************************/
113 _stdlib_strto_l(register const char * __restrict str,
114 char ** __restrict endptr, int base, int sflag);
116 #if defined(ULLONG_MAX)
117 extern unsigned long long
118 _stdlib_strto_ll(register const char * __restrict str,
119 char ** __restrict endptr, int base, int sflag);
122 #ifdef __UCLIBC_HAS_WCHAR__
124 _stdlib_wcsto_l(register const wchar_t * __restrict str,
125 wchar_t ** __restrict endptr, int base, int sflag);
127 #if defined(ULLONG_MAX)
128 extern unsigned long long
129 _stdlib_wcsto_ll(register const wchar_t * __restrict str,
130 wchar_t ** __restrict endptr, int base, int sflag);
132 #endif /* __UCLIBC_HAS_WCHAR__ */
134 /**********************************************************************/
137 double atof(const char *nptr)
139 return strtod(nptr, (char **) NULL);
143 /**********************************************************************/
146 #if INT_MAX < LONG_MAX
150 return (j >= 0) ? j : -j;
153 #endif /* INT_MAX < LONG_MAX */
156 /**********************************************************************/
159 #if UINT_MAX == ULONG_MAX
160 strong_alias(labs,abs)
163 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
164 strong_alias(labs,llabs)
167 #if ULONG_MAX == UINTMAX_MAX
168 strong_alias(labs,imaxabs)
171 long int labs(long int j)
173 return (j >= 0) ? j : -j;
177 /**********************************************************************/
180 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
182 #if (ULLONG_MAX == UINTMAX_MAX)
183 strong_alias(llabs,imaxabs)
186 long long int llabs(long long int j)
188 return (j >= 0) ? j : -j;
191 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
194 /**********************************************************************/
197 #if INT_MAX < LONG_MAX
199 int atoi(const char *nptr)
201 return (int) strtol(nptr, (char **) NULL, 10);
204 #endif /* INT_MAX < LONG_MAX */
207 /**********************************************************************/
210 #if UINT_MAX == ULONG_MAX
211 strong_alias(atol,atoi)
214 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
215 strong_alias(atol,atoll)
218 long atol(const char *nptr)
220 return strtol(nptr, (char **) NULL, 10);
224 /**********************************************************************/
227 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
229 long long atoll(const char *nptr)
231 return strtoll(nptr, (char **) NULL, 10);
234 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
237 /**********************************************************************/
240 #if ULONG_MAX == UINTMAX_MAX
241 strong_alias(strtol,strtoimax)
244 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
245 strong_alias(strtol,strtoll)
248 long strtol(const char * __restrict str, char ** __restrict endptr, int base)
250 return _stdlib_strto_l(str, endptr, base, 1);
254 /**********************************************************************/
257 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
259 #if (ULLONG_MAX == UINTMAX_MAX)
260 strong_alias(strtoll,strtoimax)
262 strong_alias(strtoll,strtoq)
264 long long strtoll(const char * __restrict str,
265 char ** __restrict endptr, int base)
267 return (long long) _stdlib_strto_ll(str, endptr, base, 1);
270 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
273 /**********************************************************************/
276 #if ULONG_MAX == UINTMAX_MAX
277 strong_alias(strtoul,strtoumax)
280 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
281 strong_alias(strtoul,strtoull)
284 unsigned long strtoul(const char * __restrict str,
285 char ** __restrict endptr, int base)
287 return _stdlib_strto_l(str, endptr, base, 0);
291 /**********************************************************************/
294 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
296 #if (ULLONG_MAX == UINTMAX_MAX)
297 strong_alias(strtoull,strtoumax)
299 strong_alias(strtoull,strtouq)
301 unsigned long long strtoull(const char * __restrict str,
302 char ** __restrict endptr, int base)
304 return _stdlib_strto_ll(str, endptr, base, 0);
307 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
310 /**********************************************************************/
311 /* Support routines follow */
312 /**********************************************************************/
313 /* Set if we want errno set appropriately. */
314 /* NOTE: Implies _STRTO_ENDPTR below */
315 #define _STRTO_ERRNO 1
317 /* Set if we want support for the endptr arg. */
318 /* Implied by _STRTO_ERRNO. */
319 #define _STRTO_ENDPTR 1
323 #define _STRTO_ENDPTR 1
324 #define SET_ERRNO(X) __set_errno(X)
326 #define SET_ERRNO(X) ((void)(X)) /* keep side effects */
329 /**********************************************************************/
330 #ifdef L__stdlib_wcsto_l
331 #define L__stdlib_strto_l
334 #ifdef L__stdlib_strto_l
336 #ifdef L__stdlib_wcsto_l
337 #define _stdlib_strto_l _stdlib_wcsto_l
338 #define Wchar wchar_t
339 #define ISSPACE iswspace
342 #define ISSPACE isspace
345 /* This is the main work fuction which handles both strtol (sflag = 1) and
346 * strtoul (sflag = 0). */
348 unsigned long _stdlib_strto_l(register const Wchar * __restrict str,
349 Wchar ** __restrict endptr, int base, int sflag)
351 unsigned long number, cutoff;
353 const Wchar *fail_char;
354 #define SET_FAIL(X) fail_char = (X)
356 #define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
358 unsigned char negative, digit, cutoff_digit;
360 assert(((unsigned int)sflag) <= 1);
364 while (ISSPACE(*str)) { /* Skip leading whitespace. */
368 /* Handle optional sign. */
371 case '-': negative = 1; /* Fall through to increment str. */
375 if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */
376 base += 10; /* Default is 10 (26). */
379 base -= 2; /* Now base is 8 or 16 (24). */
380 if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
382 base += base; /* Base is 16 (16 or 48). */
386 if (base > 16) { /* Adjust in case base wasn't dynamic. */
393 if (((unsigned)(base - 2)) < 35) { /* Legal base. */
394 cutoff_digit = ULONG_MAX % base;
395 cutoff = ULONG_MAX / base;
397 digit = (((unsigned char)(*str - '0')) <= 9)
400 ? (((0x20|(*str)) - 'a' + 10)) /* WARNING: assumes ascii. */
409 if ((number > cutoff)
410 || ((number == cutoff) && (digit > cutoff_digit))) {
415 number = number * base + digit;
422 *endptr = (Wchar *) fail_char;
427 unsigned long tmp = ((negative)
428 ? ((unsigned long)(-(1+LONG_MIN)))+1
430 if (sflag && (number > tmp)) {
436 return negative ? (unsigned long)(-((long)number)) : number;
440 /**********************************************************************/
441 #ifdef L__stdlib_wcsto_ll
442 #define L__stdlib_strto_ll
445 #ifdef L__stdlib_strto_ll
447 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
449 #ifdef L__stdlib_wcsto_ll
450 #define _stdlib_strto_ll _stdlib_wcsto_ll
451 #define Wchar wchar_t
452 #define ISSPACE iswspace
455 #define ISSPACE isspace
458 /* This is the main work fuction which handles both strtoll (sflag = 1) and
459 * strtoull (sflag = 0). */
461 unsigned long long _stdlib_strto_ll(register const Wchar * __restrict str,
462 Wchar ** __restrict endptr, int base,
465 unsigned long long number;
467 const Wchar *fail_char;
468 #define SET_FAIL(X) fail_char = (X)
470 #define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
473 unsigned char negative, digit;
475 assert(((unsigned int)sflag) <= 1);
479 while (ISSPACE(*str)) { /* Skip leading whitespace. */
483 /* Handle optional sign. */
486 case '-': negative = 1; /* Fall through to increment str. */
490 if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */
491 base += 10; /* Default is 10 (26). */
494 base -= 2; /* Now base is 8 or 16 (24). */
495 if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
497 base += base; /* Base is 16 (16 or 48). */
501 if (base > 16) { /* Adjust in case base wasn't dynamic. */
508 if (((unsigned)(base - 2)) < 35) { /* Legal base. */
510 digit = (((unsigned char)(*str - '0')) <= 9)
513 ? (((0x20|(*str)) - 'a' + 10)) /* WARNING: assumes ascii. */
523 /* Optional, but speeds things up in the usual case. */
524 if (number <= (ULLONG_MAX >> 6)) {
525 number = number * base + digit;
529 n1 = ((unsigned char) number) * base + digit;
530 number = (number >> CHAR_BIT) * base;
532 if (number + (n1 >> CHAR_BIT) <= (ULLONG_MAX >> CHAR_BIT)) {
533 number = (number << CHAR_BIT) + n1;
534 } else { /* Overflow. */
546 *endptr = (Wchar *) fail_char;
551 unsigned long long tmp = ((negative)
552 ? ((unsigned long long)(-(1+LLONG_MIN)))+1
554 if (sflag && (number > tmp)) {
560 return negative ? (unsigned long long)(-((long long)number)) : number;
563 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
566 /**********************************************************************/
567 /* Made _Exit() an alias for _exit(), as per C99. */
570 /* void _Exit(int status) */
576 /**********************************************************************/
579 void *bsearch(const void *key, const void *base, size_t /* nmemb */ high,
580 size_t size, int (*compar)(const void *, const void *))
587 if (size > 0) { /* TODO: change this to an assert?? */
590 mid = low + ((high - low) >> 1); /* Avoid possible overflow here. */
591 p = ((char *)base) + mid * size; /* Could overflow here... */
592 r = (*compar)(key, p); /* but that's an application problem! */
606 /**********************************************************************/
609 /* This code is derived from a public domain shell sort routine by
610 * Ray Gardner and found in Bob Stout's snippets collection. The
611 * original code is included below in an #if 0/#endif block.
613 * I modified it to avoid the possibility of overflow in the wgap
614 * calculation, as well as to reduce the generated code size with
617 void qsort (void *base,
620 int (*comp)(const void *, const void *))
622 size_t wgap, i, j, k;
625 if ((nel > 1) && (width > 0)) {
626 assert( nel <= ((size_t)(-1)) / width ); /* check for overflow */
630 } while (wgap < (nel-1)/3);
631 /* From the above, we know that either wgap == 1 < nel or */
632 /* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */
633 wgap *= width; /* So this can not overflow if wnel doesn't. */
634 nel *= width; /* Convert nel to 'wnel' */
644 a = j + ((char *)base);
646 if ( (*comp)(a, b) <= 0 ) {
658 wgap = (wgap - width)/3;
663 /* ---------- original snippets version below ---------- */
667 ** ssort() -- Fast, small, qsort()-compatible Shell sort
669 ** by Ray Gardner, public domain 5/90
674 void ssort (void *base,
677 int (*comp)(const void *, const void *))
679 size_t wnel, gap, wgap, i, j, k;
683 for (gap = 0; ++gap < nel;)
688 for (i = wgap; i < wnel; i += width)
690 for (j = i - wgap; ;j -= wgap)
692 a = j + (char *)base;
694 if ( (*comp)(a, b) <= 0 )
712 /**********************************************************************/
713 #ifdef L__stdlib_mb_cur_max
715 size_t _stdlib_mb_cur_max(void)
717 #ifdef __CTYPE_HAS_UTF_8_LOCALES
718 return __global_locale.mb_cur_max;
720 #ifdef __CTYPE_HAS_8_BIT_LOCALES
721 #ifdef __UCLIBC_MJN3_ONLY__
722 #warning need to change this when/if transliteration is implemented
730 /**********************************************************************/
733 int mblen(register const char *s, size_t n)
735 static mbstate_t state;
740 #ifdef __CTYPE_HAS_UTF_8_LOCALES
741 return ENCODING == __ctype_encoding_utf8;
747 if ((r = mbrlen(s, n, &state)) == (size_t) -2) {
748 /* TODO: Should we set an error state? */
749 state.wc = 0xffffU; /* Make sure we're in an error state. */
750 return (size_t) -1; /* TODO: Change error code above? */
756 /**********************************************************************/
759 int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
761 static mbstate_t state;
766 #ifdef __CTYPE_HAS_UTF_8_LOCALES
767 return ENCODING == __ctype_encoding_utf8;
773 if ((r = mbrtowc(pwc, s, n, &state)) == (size_t) -2) {
774 /* TODO: Should we set an error state? */
775 state.wc = 0xffffU; /* Make sure we're in an error state. */
776 return (size_t) -1; /* TODO: Change error code above? */
782 /**********************************************************************/
785 /* Note: We completely ignore state in all currently supported conversions. */
787 int wctomb(register char *__restrict s, wchar_t swc)
791 #ifdef __CTYPE_HAS_UTF_8_LOCALES
792 (ENCODING == __ctype_encoding_utf8)
794 0 /* Encoding is stateless. */
796 : ((ssize_t) wcrtomb(s, swc, NULL));
800 /**********************************************************************/
803 size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
806 const char *e = s; /* Needed because of restrict. */
808 state.mask = 0; /* Always start in initial shift state. */
809 return mbsrtowcs(pwcs, &e, n, &state);
813 /**********************************************************************/
816 /* Note: We completely ignore state in all currently supported conversions. */
818 size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
820 const wchar_t *e = pwcs; /* Needed because of restrict. */
822 return wcsrtombs(s, &e, n, NULL);
826 /**********************************************************************/
829 #if ULONG_MAX == UINTMAX_MAX
830 strong_alias(wcstol,wcstoimax)
833 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
834 strong_alias(wcstol,wcstoll)
837 long wcstol(const wchar_t * __restrict str, wchar_t ** __restrict endptr, int base)
839 return _stdlib_wcsto_l(str, endptr, base, 1);
843 /**********************************************************************/
846 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
848 #if (ULLONG_MAX == UINTMAX_MAX)
849 strong_alias(wcstoll,wcstoimax)
851 strong_alias(wcstoll,wcstoq)
853 long long wcstoll(const wchar_t * __restrict str,
854 wchar_t ** __restrict endptr, int base)
856 return (long long) _stdlib_wcsto_ll(str, endptr, base, 1);
859 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
862 /**********************************************************************/
865 #if ULONG_MAX == UINTMAX_MAX
866 strong_alias(wcstoul,wcstoumax)
869 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
870 strong_alias(wcstoul,wcstoull)
873 unsigned long wcstoul(const wchar_t * __restrict str,
874 wchar_t ** __restrict endptr, int base)
876 return _stdlib_wcsto_l(str, endptr, base, 0);
880 /**********************************************************************/
883 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
885 #if (ULLONG_MAX == UINTMAX_MAX)
886 strong_alias(wcstoull,wcstoumax)
888 strong_alias(wcstoull,wcstouq)
890 unsigned long long wcstoull(const wchar_t * __restrict str,
891 wchar_t ** __restrict endptr, int base)
893 return _stdlib_wcsto_ll(str, endptr, base, 0);
896 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
899 /**********************************************************************/