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