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