OSDN Git Service

122289c2c948203512d243a67f36ec0e63eb350d
[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 #define _GNU_SOURCE
37 #include <limits.h>
38 #include <stdint.h>
39 #include <inttypes.h>
40 #include <ctype.h>
41 #include <errno.h>
42 #include <assert.h>
43 #include <unistd.h>
44
45 /* Work around gcc's refusal to create aliases. 
46  * TODO: Add in a define to disable the aliases? */
47
48 #if UINT_MAX == ULONG_MAX
49 #define atoi __ignore_atoi
50 #define abs __ignore_abs
51 #endif
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
59 #endif
60
61 #include <stdlib.h>
62
63 #ifdef __UCLIBC_HAS_WCHAR__
64
65 #include <locale.h>
66 #include <wchar.h>
67 #include <wctype.h>
68
69 /* TODO: clean up the following... */
70
71 #if WCHAR_MAX > 0xffffUL
72 #define UTF_8_MAX_LEN 6
73 #else
74 #define UTF_8_MAX_LEN 3
75 #endif
76
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!
81 #endif
82 #else
83 #ifdef __UCLIBC_MJN3_ONLY__
84 #warning devel checks
85 #endif
86 #define ENCODING (__ctype_encoding_7_bit)
87 #ifdef __CTYPE_HAS_8_BIT_LOCALES
88 #error __CTYPE_HAS_8_BIT_LOCALES is defined!
89 #endif
90 #ifdef __CTYPE_HAS_UTF_8_LOCALES
91 #error __CTYPE_HAS_UTF_8_LOCALES is defined!
92 #endif
93 #endif
94
95 #endif
96
97 #if UINT_MAX == ULONG_MAX
98 #undef atoi
99 #undef abs
100 #endif
101 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
102 #undef llabs
103 #undef atoll
104 #undef strtoll
105 #undef strtoull
106 #undef wcstoll
107 #undef wcstoull
108 #endif /* __UCLIBC_HAS_WCHAR__ */
109
110 /**********************************************************************/
111
112 extern unsigned long
113 _stdlib_strto_l(register const char * __restrict str,
114                                 char ** __restrict endptr, int base, int sflag);
115
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);
120 #endif
121
122 #ifdef __UCLIBC_HAS_WCHAR__
123 extern unsigned long
124 _stdlib_wcsto_l(register const wchar_t * __restrict str,
125                                 wchar_t ** __restrict endptr, int base, int sflag);
126
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);
131 #endif
132 #endif /* __UCLIBC_HAS_WCHAR__ */
133
134 /**********************************************************************/
135 #ifdef L_atof
136
137 double atof(const char *nptr)
138 {
139         return strtod(nptr, (char **) NULL);
140 }
141
142 #endif
143 /**********************************************************************/
144 #ifdef L_abs
145
146 #if INT_MAX < LONG_MAX
147
148 int abs(int j)
149 {
150         return (j >= 0) ? j : -j;
151 }
152
153 #endif /* INT_MAX < LONG_MAX */
154
155 #endif
156 /**********************************************************************/
157 #ifdef L_labs
158
159 #if UINT_MAX == ULONG_MAX
160 strong_alias(labs,abs)
161 #endif
162
163 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
164 strong_alias(labs,llabs)
165 #endif
166
167 #if ULONG_MAX == UINTMAX_MAX
168 strong_alias(labs,imaxabs)
169 #endif
170
171 long int labs(long int j)
172 {
173         return (j >= 0) ? j : -j;
174 }
175
176 #endif
177 /**********************************************************************/
178 #ifdef L_llabs
179
180 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
181
182 #if (ULLONG_MAX == UINTMAX_MAX)
183 strong_alias(llabs,imaxabs)
184 #endif
185
186 long long int llabs(long long int j)
187 {
188         return (j >= 0) ? j : -j;
189 }
190
191 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
192
193 #endif
194 /**********************************************************************/
195 #ifdef L_atoi
196
197 #if INT_MAX < LONG_MAX 
198
199 int atoi(const char *nptr)
200 {
201         return (int) strtol(nptr, (char **) NULL, 10);
202 }
203
204 #endif /* INT_MAX < LONG_MAX  */
205
206 #endif
207 /**********************************************************************/
208 #ifdef L_atol
209
210 #if UINT_MAX == ULONG_MAX
211 strong_alias(atol,atoi)
212 #endif
213
214 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
215 strong_alias(atol,atoll)
216 #endif
217
218 long atol(const char *nptr)
219 {
220         return strtol(nptr, (char **) NULL, 10);
221 }
222
223 #endif
224 /**********************************************************************/
225 #ifdef L_atoll
226
227 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
228
229 long long atoll(const char *nptr)
230 {
231         return strtoll(nptr, (char **) NULL, 10);
232 }
233
234 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
235
236 #endif
237 /**********************************************************************/
238 #ifdef L_strtol
239
240 #if ULONG_MAX == UINTMAX_MAX
241 strong_alias(strtol,strtoimax)
242 #endif
243
244 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
245 strong_alias(strtol,strtoll)
246 #endif
247
248 long strtol(const char * __restrict str, char ** __restrict endptr, int base)
249 {
250     return _stdlib_strto_l(str, endptr, base, 1);
251 }
252
253 #endif
254 /**********************************************************************/
255 #ifdef L_strtoll
256
257 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
258
259 #if (ULLONG_MAX == UINTMAX_MAX)
260 strong_alias(strtoll,strtoimax)
261 #endif
262 strong_alias(strtoll,strtoq)
263
264 long long strtoll(const char * __restrict str,
265                                   char ** __restrict endptr, int base)
266 {
267     return (long long) _stdlib_strto_ll(str, endptr, base, 1);
268 }
269
270 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
271
272 #endif
273 /**********************************************************************/
274 #ifdef L_strtoul
275
276 #if ULONG_MAX == UINTMAX_MAX
277 strong_alias(strtoul,strtoumax)
278 #endif
279
280 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
281 strong_alias(strtoul,strtoull)
282 #endif
283
284 unsigned long strtoul(const char * __restrict str,
285                                           char ** __restrict endptr, int base)
286 {
287     return _stdlib_strto_l(str, endptr, base, 0);
288 }
289
290 #endif
291 /**********************************************************************/
292 #ifdef L_strtoull
293
294 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
295
296 #if (ULLONG_MAX == UINTMAX_MAX)
297 strong_alias(strtoull,strtoumax)
298 #endif
299 strong_alias(strtoull,strtouq)
300
301 unsigned long long strtoull(const char * __restrict str,
302                                                         char ** __restrict endptr, int base)
303 {
304     return _stdlib_strto_ll(str, endptr, base, 0);
305 }
306
307 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
308
309 #endif
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
316
317 /* Set if we want support for the endptr arg. */
318 /* Implied by _STRTO_ERRNO. */
319 #define _STRTO_ENDPTR           1
320
321 #if _STRTO_ERRNO
322 #undef _STRTO_ENDPTR
323 #define _STRTO_ENDPTR           1
324 #define SET_ERRNO(X)            __set_errno(X)
325 #else
326 #define SET_ERRNO(X)            ((void)(X))     /* keep side effects */
327 #endif
328
329 /**********************************************************************/
330 #ifdef L__stdlib_wcsto_l
331 #define L__stdlib_strto_l
332 #endif
333
334 #ifdef L__stdlib_strto_l
335
336 #ifdef L__stdlib_wcsto_l
337 #define _stdlib_strto_l _stdlib_wcsto_l
338 #define Wchar wchar_t
339 #define ISSPACE iswspace
340 #else
341 #define Wchar char
342 #define ISSPACE isspace
343 #endif
344
345 /* This is the main work fuction which handles both strtol (sflag = 1) and
346  * strtoul (sflag = 0). */
347
348 unsigned long _stdlib_strto_l(register const Wchar * __restrict str,
349                                                           Wchar ** __restrict endptr, int base, int sflag)
350 {
351     unsigned long number, cutoff;
352 #if _STRTO_ENDPTR
353     const Wchar *fail_char;
354 #define SET_FAIL(X)       fail_char = (X)
355 #else
356 #define SET_FAIL(X)       ((void)(X)) /* Keep side effects. */
357 #endif
358     unsigned char negative, digit, cutoff_digit;
359
360         assert(((unsigned int)sflag) <= 1);
361
362         SET_FAIL(str);
363
364     while (ISSPACE(*str)) {             /* Skip leading whitespace. */
365                 ++str;
366     }
367
368     /* Handle optional sign. */
369     negative = 0;
370     switch(*str) {
371                 case '-': negative = 1; /* Fall through to increment str. */
372                 case '+': ++str;
373     }
374
375     if (!(base & ~0x10)) {              /* Either dynamic (base = 0) or base 16. */
376                 base += 10;                             /* Default is 10 (26). */
377                 if (*str == '0') {
378                         SET_FAIL(++str);
379                         base -= 2;                      /* Now base is 8 or 16 (24). */
380                         if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
381                                 ++str;
382                                 base += base;   /* Base is 16 (16 or 48). */
383                         }
384                 }
385
386                 if (base > 16) {                /* Adjust in case base wasn't dynamic. */
387                         base = 16;
388                 }
389     }
390
391         number = 0;
392
393     if (((unsigned)(base - 2)) < 35) { /* Legal base. */
394                 cutoff_digit = ULONG_MAX % base;
395                 cutoff = ULONG_MAX / base;
396                 do {
397                         digit = (((unsigned char)(*str - '0')) <= 9)
398                                 ? (*str - '0')
399                                 : ((*str >= 'A')
400                                    ? (((0x20|(*str)) - 'a' + 10)) /* WARNING: assumes ascii. */
401                                           : 40);
402
403                         if (digit >= base) {
404                                 break;
405                         }
406
407                         SET_FAIL(++str);
408
409                         if ((number > cutoff)
410                                 || ((number == cutoff) && (digit > cutoff_digit))) {
411                                 number = ULONG_MAX;
412                                 negative &= sflag;
413                                 SET_ERRNO(ERANGE);
414                         } else {
415                                 number = number * base + digit;
416                         }
417                 } while (1);
418         }
419
420 #if _STRTO_ENDPTR
421     if (endptr) {
422                 *endptr = (Wchar *) fail_char;
423     }
424 #endif
425
426         {
427                 unsigned long tmp = ((negative)
428                                                          ? ((unsigned long)(-(1+LONG_MIN)))+1
429                                                          : LONG_MAX);
430                 if (sflag && (number > tmp)) {
431                         number = tmp;
432                         SET_ERRNO(ERANGE);
433                 }
434         }
435
436         return negative ? (unsigned long)(-((long)number)) : number;
437 }
438
439 #endif
440 /**********************************************************************/
441 #ifdef L__stdlib_wcsto_ll
442 #define L__stdlib_strto_ll
443 #endif
444
445 #ifdef L__stdlib_strto_ll
446
447 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
448
449 #ifdef L__stdlib_wcsto_ll
450 #define _stdlib_strto_ll _stdlib_wcsto_ll
451 #define Wchar wchar_t
452 #define ISSPACE iswspace
453 #else
454 #define Wchar char
455 #define ISSPACE isspace
456 #endif
457
458 /* This is the main work fuction which handles both strtoll (sflag = 1) and
459  * strtoull (sflag = 0). */
460
461 unsigned long long _stdlib_strto_ll(register const Wchar * __restrict str,
462                                                                         Wchar ** __restrict endptr, int base,
463                                                                         int sflag)
464 {
465     unsigned long long number;
466 #if _STRTO_ENDPTR
467     const Wchar *fail_char;
468 #define SET_FAIL(X)       fail_char = (X)
469 #else
470 #define SET_FAIL(X)       ((void)(X)) /* Keep side effects. */
471 #endif
472         unsigned int n1;
473     unsigned char negative, digit;
474
475         assert(((unsigned int)sflag) <= 1);
476
477         SET_FAIL(str);
478
479     while (ISSPACE(*str)) {             /* Skip leading whitespace. */
480                 ++str;
481     }
482
483     /* Handle optional sign. */
484     negative = 0;
485     switch(*str) {
486                 case '-': negative = 1; /* Fall through to increment str. */
487                 case '+': ++str;
488     }
489
490     if (!(base & ~0x10)) {              /* Either dynamic (base = 0) or base 16. */
491                 base += 10;                             /* Default is 10 (26). */
492                 if (*str == '0') {
493                         SET_FAIL(++str);
494                         base -= 2;                      /* Now base is 8 or 16 (24). */
495                         if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
496                                 ++str;
497                                 base += base;   /* Base is 16 (16 or 48). */
498                         }
499                 }
500
501                 if (base > 16) {                /* Adjust in case base wasn't dynamic. */
502                         base = 16;
503                 }
504     }
505
506         number = 0;
507
508     if (((unsigned)(base - 2)) < 35) { /* Legal base. */
509                 do {
510                         digit = (((unsigned char)(*str - '0')) <= 9)
511                                 ? (*str - '0')
512                                 : ((*str >= 'A')
513                                    ? (((0x20|(*str)) - 'a' + 10)) /* WARNING: assumes ascii. */
514                                           : 40);
515
516                         if (digit >= base) {
517                                 break;
518                         }
519
520                         SET_FAIL(++str);
521
522 #if 1
523                         /* Optional, but speeds things up in the usual case. */
524                         if (number <= (ULLONG_MAX >> 6)) {
525                                 number = number * base + digit;
526                         } else
527 #endif
528                         {
529                                 n1 = ((unsigned char) number) * base + digit;
530                                 number = (number >> CHAR_BIT) * base;
531
532                                 if (number + (n1 >> CHAR_BIT) <= (ULLONG_MAX >> CHAR_BIT)) {
533                                         number = (number << CHAR_BIT) + n1;
534                                 } else {                /* Overflow. */
535                                         number = ULLONG_MAX;
536                                         negative &= sflag;
537                                         SET_ERRNO(ERANGE);
538                                 }
539                         }
540
541                 } while (1);
542         }
543
544 #if _STRTO_ENDPTR
545     if (endptr) {
546                 *endptr = (Wchar *) fail_char;
547     }
548 #endif
549
550         {
551                 unsigned long long tmp = ((negative)
552                                                                   ? ((unsigned long long)(-(1+LLONG_MIN)))+1
553                                                                   : LLONG_MAX);
554                 if (sflag && (number > tmp)) {
555                         number = tmp;
556                         SET_ERRNO(ERANGE);
557                 }
558         }
559
560         return negative ? (unsigned long long)(-((long long)number)) : number;
561 }
562
563 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
564
565 #endif
566 /**********************************************************************/
567 /* Made _Exit() an alias for _exit(), as per C99. */
568 /*  #ifdef L__Exit */
569
570 /*  void _Exit(int status) */
571 /*  { */
572 /*      _exit(status); */
573 /*  } */
574
575 /*  #endif */
576 /**********************************************************************/
577 #ifdef L_bsearch
578
579 void *bsearch(const void *key, const void *base, size_t /* nmemb */ high,
580                           size_t size, int (*compar)(const void *, const void *))
581 {
582         register char *p;
583         size_t low;
584         size_t mid;
585         int r;
586
587         if (size > 0) {                         /* TODO: change this to an assert?? */
588                 low = 0;
589                 while (low < high) {
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! */
593                         if (r > 0) {
594                                 low = mid + 1;
595                         } else if (r < 0) {
596                                 high = mid;
597                         } else {
598                                 return p;
599                         }
600                 }
601         }
602         return NULL;
603 }
604
605 #endif
606 /**********************************************************************/
607 #ifdef L_qsort
608
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.
612  *
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
615  * bcc and gcc. */
616
617 void qsort (void  *base,
618             size_t nel,
619             size_t width,
620             int (*comp)(const void *, const void *))
621 {
622         size_t wgap, i, j, k;
623         char tmp;
624
625         if ((nel > 1) && (width > 0)) {
626                 assert( nel <= ((size_t)(-1)) / width ); /* check for overflow */
627                 wgap = 0;
628                 do {
629                         wgap = 3 * wgap + 1;
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' */
635                 do {
636                         i = wgap;
637                         do {
638                                 j = i;
639                                 do {
640                                         register char *a;
641                                         register char *b;
642
643                                         j -= wgap;
644                                         a = j + ((char *)base);
645                                         b = a + wgap;
646                                         if ( (*comp)(a, b) <= 0 ) {
647                                                 break;
648                                         }
649                                         k = width;
650                                         do {
651                                                 tmp = *a;
652                                                 *a++ = *b;
653                                                 *b++ = tmp;
654                                         } while ( --k );
655                                 } while (j >= wgap);
656                                 i += width;
657                         } while (i < nel);
658                         wgap = (wgap - width)/3;
659                 } while (wgap);
660         }
661 }
662
663 /* ---------- original snippets version below ---------- */
664
665 #if 0
666 /*
667 **  ssort()  --  Fast, small, qsort()-compatible Shell sort
668 **
669 **  by Ray Gardner,  public domain   5/90
670 */
671
672 #include <stddef.h>
673
674 void ssort (void  *base,
675             size_t nel,
676             size_t width,
677             int (*comp)(const void *, const void *))
678 {
679       size_t wnel, gap, wgap, i, j, k;
680       char *a, *b, tmp;
681
682       wnel = width * nel;
683       for (gap = 0; ++gap < nel;)
684             gap *= 3;
685       while ( gap /= 3 )
686       {
687             wgap = width * gap;
688             for (i = wgap; i < wnel; i += width)
689             {
690                   for (j = i - wgap; ;j -= wgap)
691                   {
692                         a = j + (char *)base;
693                         b = a + wgap;
694                         if ( (*comp)(a, b) <= 0 )
695                               break;
696                         k = width;
697                         do
698                         {
699                               tmp = *a;
700                               *a++ = *b;
701                               *b++ = tmp;
702                         } while ( --k );
703                         if (j < wgap)
704                               break;
705                   }
706             }
707       }
708 }
709 #endif
710
711 #endif
712 /**********************************************************************/
713 #ifdef L__stdlib_mb_cur_max
714
715 size_t _stdlib_mb_cur_max(void)
716 {
717 #ifdef __CTYPE_HAS_UTF_8_LOCALES
718         return __global_locale.mb_cur_max;
719 #else
720 #ifdef __CTYPE_HAS_8_BIT_LOCALES
721 #ifdef __UCLIBC_MJN3_ONLY__
722 #warning need to change this when/if transliteration is implemented
723 #endif
724 #endif
725         return 1;
726 #endif
727 }
728
729 #endif
730 /**********************************************************************/
731 #ifdef L_mblen
732
733 int mblen(register const char *s, size_t n)
734 {
735         static mbstate_t state;
736         size_t r;
737
738         if (!s) {
739                 state.mask = 0;
740 #ifdef __CTYPE_HAS_UTF_8_LOCALES
741                 return ENCODING == __ctype_encoding_utf8;
742 #else
743                 return 0;
744 #endif
745         }
746
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? */
751         }
752         return r;
753 }
754
755 #endif
756 /**********************************************************************/
757 #ifdef L_mbtowc
758
759 int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
760 {
761         static mbstate_t state;
762         size_t r;
763
764         if (!s) {
765                 state.mask = 0;
766 #ifdef __CTYPE_HAS_UTF_8_LOCALES
767                 return ENCODING == __ctype_encoding_utf8;
768 #else
769                 return 0;
770 #endif
771         }
772
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? */
777         }
778         return r;
779 }
780
781 #endif
782 /**********************************************************************/
783 #ifdef L_wctomb
784
785 /* Note: We completely ignore state in all currently supported conversions. */
786
787 int wctomb(register char *__restrict s, wchar_t swc)
788 {
789         return (!s)
790                 ?
791 #ifdef __CTYPE_HAS_UTF_8_LOCALES
792                 (ENCODING == __ctype_encoding_utf8)
793 #else
794                 0                                               /* Encoding is stateless. */
795 #endif
796                 : ((ssize_t) wcrtomb(s, swc, NULL));
797 }
798
799 #endif
800 /**********************************************************************/
801 #ifdef L_mbstowcs
802
803 size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
804 {
805         mbstate_t state;
806         const char *e = s;                      /* Needed because of restrict. */
807
808         state.mask = 0;                         /* Always start in initial shift state. */
809         return mbsrtowcs(pwcs, &e, n, &state);
810 }
811
812 #endif
813 /**********************************************************************/
814 #ifdef L_wcstombs
815
816 /* Note: We completely ignore state in all currently supported conversions. */
817
818 size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
819 {
820         const wchar_t *e = pwcs;        /* Needed because of restrict. */
821
822         return wcsrtombs(s, &e, n, NULL);
823 }
824
825 #endif
826 /**********************************************************************/
827 #ifdef L_wcstol
828
829 #if ULONG_MAX == UINTMAX_MAX
830 strong_alias(wcstol,wcstoimax)
831 #endif
832
833 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
834 strong_alias(wcstol,wcstoll)
835 #endif
836
837 long wcstol(const wchar_t * __restrict str, wchar_t ** __restrict endptr, int base)
838 {
839     return _stdlib_wcsto_l(str, endptr, base, 1);
840 }
841
842 #endif
843 /**********************************************************************/
844 #ifdef L_wcstoll
845
846 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
847
848 #if (ULLONG_MAX == UINTMAX_MAX)
849 strong_alias(wcstoll,wcstoimax)
850 #endif
851 strong_alias(wcstoll,wcstoq)
852
853 long long wcstoll(const wchar_t * __restrict str,
854                                   wchar_t ** __restrict endptr, int base)
855 {
856     return (long long) _stdlib_wcsto_ll(str, endptr, base, 1);
857 }
858
859 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
860
861 #endif
862 /**********************************************************************/
863 #ifdef L_wcstoul
864
865 #if ULONG_MAX == UINTMAX_MAX
866 strong_alias(wcstoul,wcstoumax)
867 #endif
868
869 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
870 strong_alias(wcstoul,wcstoull)
871 #endif
872
873 unsigned long wcstoul(const wchar_t * __restrict str,
874                                           wchar_t ** __restrict endptr, int base)
875 {
876     return _stdlib_wcsto_l(str, endptr, base, 0);
877 }
878
879 #endif
880 /**********************************************************************/
881 #ifdef L_wcstoull
882
883 #if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
884
885 #if (ULLONG_MAX == UINTMAX_MAX)
886 strong_alias(wcstoull,wcstoumax)
887 #endif
888 strong_alias(wcstoull,wcstouq)
889
890 unsigned long long wcstoull(const wchar_t * __restrict str,
891                                                         wchar_t ** __restrict endptr, int base)
892 {
893     return _stdlib_wcsto_ll(str, endptr, base, 0);
894 }
895
896 #endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
897
898 #endif
899 /**********************************************************************/
900