OSDN Git Service

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