From a7c8a57aa744497746c0b8743116cd3e1978bf23 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig <hch@cloudius-systems.com> Date: Mon, 21 Jan 2013 15:48:22 +0100 Subject: [PATCH] import stdlib from musl except for the floating point functionality for now. --- libc/build.mak | 20 +++- libc/libc.cc | 77 --------------- libc/qsort.c | 197 -------------------------------------- libc/stdlib/abs.c | 4 + libc/stdlib/atoi.c | 16 ++++ libc/stdlib/atol.c | 17 ++++ libc/stdlib/atoll.c | 17 ++++ libc/stdlib/bsearch.c | 20 ++++ libc/stdlib/div.c | 6 ++ libc/stdlib/ecvt.c | 19 ++++ libc/stdlib/fcvt.c | 25 +++++ libc/stdlib/gcvt.c | 8 ++ libc/stdlib/imaxabs.c | 6 ++ libc/stdlib/imaxdiv.c | 6 ++ libc/stdlib/labs.c | 4 + libc/stdlib/ldiv.c | 6 ++ libc/stdlib/llabs.c | 4 + libc/stdlib/lldiv.c | 6 ++ libc/stdlib/qsort.c | 215 ++++++++++++++++++++++++++++++++++++++++++ libc/stdlib/strtol.c | 56 +++++++++++ libc/stdlib/wcstol.c | 82 ++++++++++++++++ 21 files changed, 536 insertions(+), 275 deletions(-) delete mode 100644 libc/qsort.c create mode 100644 libc/stdlib/abs.c create mode 100644 libc/stdlib/atoi.c create mode 100644 libc/stdlib/atol.c create mode 100644 libc/stdlib/atoll.c create mode 100644 libc/stdlib/bsearch.c create mode 100644 libc/stdlib/div.c create mode 100644 libc/stdlib/ecvt.c create mode 100644 libc/stdlib/fcvt.c create mode 100644 libc/stdlib/gcvt.c create mode 100644 libc/stdlib/imaxabs.c create mode 100644 libc/stdlib/imaxdiv.c create mode 100644 libc/stdlib/labs.c create mode 100644 libc/stdlib/ldiv.c create mode 100644 libc/stdlib/llabs.c create mode 100644 libc/stdlib/lldiv.c create mode 100644 libc/stdlib/qsort.c create mode 100644 libc/stdlib/strtol.c create mode 100644 libc/stdlib/wcstol.c diff --git a/libc/build.mak b/libc/build.mak index 07a1ba656..845928f76 100644 --- a/libc/build.mak +++ b/libc/build.mak @@ -247,6 +247,25 @@ libc += stdio/vwscanf.o libc += stdio/wprintf.o libc += stdio/wscanf.o +libc += stdlib/abs.o +libc += stdlib/atoi.o +libc += stdlib/atol.o +libc += stdlib/atoll.o +libc += stdlib/bsearch.o +libc += stdlib/div.o +libc += stdlib/ecvt.o +libc += stdlib/fcvt.o +libc += stdlib/gcvt.o +libc += stdlib/imaxabs.o +libc += stdlib/imaxdiv.o +libc += stdlib/labs.o +libc += stdlib/ldiv.o +libc += stdlib/llabs.o +libc += stdlib/lldiv.o +libc += stdlib/qsort.o +libc += stdlib/strtol.o +libc += stdlib/wcstol.o + libc += string/bcmp.o libc += string/bcopy.o libc += string/bzero.o @@ -352,5 +371,4 @@ libc += dlfcn.o libc += time.o libc += signal.o libc += mman.o -libc += qsort.o libc += sem.o diff --git a/libc/libc.cc b/libc/libc.cc index d3711e5bd..5076982f8 100644 --- a/libc/libc.cc +++ b/libc/libc.cc @@ -65,83 +65,6 @@ int putenv(char* string) return 0; // no environent } -template <typename N> -N strtoN(const char* s, char** e, int base) -{ - typedef typename std::make_unsigned<N>::type tmp_type; - tmp_type tmp = 0; - auto max = std::numeric_limits<N>::max(); - auto min = std::numeric_limits<N>::min(); - - while (*s && isspace(*s)) { - ++s; - } - int sign = 1; - if (*s == '+' || *s == '-') { - sign = *s++ == '-' ? -1 : 1; - } - auto overflow = sign > 0 ? max : min; - if (base == 0 && s[0] == '0' && s[1] == 'x') { - base = 16; - } else if (base == 0 && s[0] == '0') { - base = 8; - } - if (base == 16 && s[0] == '0' && s[1] == 'x') { - s += 2; - } - if (base == 0) { - base = 10; - } - - auto convdigit = [=] (char c, int& digit) { - if (isdigit(c)) { - digit = c - '0'; - } else if (isalpha(c)) { - digit = tolower(c) - 'a' + 10; - } else { - return false; - } - return digit < base; - }; - - int digit; - while (*s && convdigit(*s, digit)) { - auto old = tmp; - tmp = tmp * base + digit; - if (tmp < old) { - errno = ERANGE; - return overflow; - } - ++s; - } - if ((sign < 0 && tmp > tmp_type(max)) || (tmp > tmp_type(-min))) { - errno = ERANGE; - return overflow; - } - if (sign < 0) { - tmp = -tmp; - } - if (e) { - *e = const_cast<char*>(s); - } - return tmp; -} - -long strtol(const char* s, char** e, int base) -{ - return strtoN<long>(s, e, base); -} - -unsigned long strtoul(const char* s, char** e, int base) -{ - return strtoN<unsigned long>(s, e, base); -} - -long long strtoll(const char* s, char** e, int base) -{ - return strtoN<long long>(s, e, base); -} - int getrlimit(int resource, struct rlimit *rlim) { auto set = [=] (rlim_t r) { rlim->rlim_cur = rlim->rlim_max = r; }; diff --git a/libc/qsort.c b/libc/qsort.c deleted file mode 100644 index 7069106b5..000000000 --- a/libc/qsort.c +++ /dev/null @@ -1,197 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -//__FBSDID("$FreeBSD$"); - -#define __unused __attribute__((unused)) - -#include <stdlib.h> - -#ifdef I_AM_QSORT_R -typedef int cmp_t(void *, const void *, const void *); -#else -typedef int cmp_t(const void *, const void *); -#endif -static inline char *med3(char *, char *, char *, cmp_t *, void *); -static inline void swapfunc(char *, char *, int, int); - -#define min(a, b) (a) < (b) ? a : b - -/* - * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". - */ -#define swapcode(TYPE, parmi, parmj, n) { \ - long i = (n) / sizeof (TYPE); \ - TYPE *pi = (TYPE *) (parmi); \ - TYPE *pj = (TYPE *) (parmj); \ - do { \ - TYPE t = *pi; \ - *pi++ = *pj; \ - *pj++ = t; \ - } while (--i > 0); \ -} - -#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ - es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; - -static inline void -swapfunc(a, b, n, swaptype) - char *a, *b; - int n, swaptype; -{ - if(swaptype <= 1) - swapcode(long, a, b, n) - else - swapcode(char, a, b, n) -} - -#define swap(a, b) \ - if (swaptype == 0) { \ - long t = *(long *)(a); \ - *(long *)(a) = *(long *)(b); \ - *(long *)(b) = t; \ - } else \ - swapfunc(a, b, es, swaptype) - -#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) - -#ifdef I_AM_QSORT_R -#define CMP(t, x, y) (cmp((t), (x), (y))) -#else -#define CMP(t, x, y) (cmp((x), (y))) -#endif - -static inline char * -med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk -#ifndef I_AM_QSORT_R -__unused -#endif -) -{ - return CMP(thunk, a, b) < 0 ? - (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) - :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); -} - -#ifdef I_AM_QSORT_R -void -qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) -#else -#define thunk NULL -void -qsort(void *a, size_t n, size_t es, cmp_t *cmp) -#endif -{ - char *pa, *pb, *pc, *pd, *pl, *pm, *pn; - size_t d, r; - int cmp_result; - int swaptype, swap_cnt; - -loop: SWAPINIT(a, es); - swap_cnt = 0; - if (n < 7) { - for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; - pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) - swap(pl, pl - es); - return; - } - pm = (char *)a + (n / 2) * es; - if (n > 7) { - pl = a; - pn = (char *)a + (n - 1) * es; - if (n > 40) { - d = (n / 8) * es; - pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); - pm = med3(pm - d, pm, pm + d, cmp, thunk); - pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); - } - pm = med3(pl, pm, pn, cmp, thunk); - } - swap(a, pm); - pa = pb = (char *)a + es; - - pc = pd = (char *)a + (n - 1) * es; - for (;;) { - while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { - if (cmp_result == 0) { - swap_cnt = 1; - swap(pa, pb); - pa += es; - } - pb += es; - } - while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { - if (cmp_result == 0) { - swap_cnt = 1; - swap(pc, pd); - pd -= es; - } - pc -= es; - } - if (pb > pc) - break; - swap(pb, pc); - swap_cnt = 1; - pb += es; - pc -= es; - } - if (swap_cnt == 0) { /* Switch to insertion sort */ - for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; - pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) - swap(pl, pl - es); - return; - } - - pn = (char *)a + n * es; - r = min(pa - (char *)a, pb - pa); - vecswap(a, pb - r, r); - r = min(pd - pc, pn - pd - es); - vecswap(pb, pn - r, r); - if ((r = pb - pa) > es) -#ifdef I_AM_QSORT_R - qsort_r(a, r / es, es, thunk, cmp); -#else - qsort(a, r / es, es, cmp); -#endif - if ((r = pd - pc) > es) { - /* Iterate rather than recurse to save stack space */ - a = pn - r; - n = r / es; - goto loop; - } -/* qsort(pn - r, r / es, es, cmp);*/ -} diff --git a/libc/stdlib/abs.c b/libc/stdlib/abs.c new file mode 100644 index 000000000..4806d629d --- /dev/null +++ b/libc/stdlib/abs.c @@ -0,0 +1,4 @@ +int abs(int a) +{ + return a>0 ? a : -a; +} diff --git a/libc/stdlib/atoi.c b/libc/stdlib/atoi.c new file mode 100644 index 000000000..9baca7b89 --- /dev/null +++ b/libc/stdlib/atoi.c @@ -0,0 +1,16 @@ +#include <stdlib.h> +#include <ctype.h> + +int atoi(const char *s) +{ + int n=0, neg=0; + while (isspace(*s)) s++; + switch (*s) { + case '-': neg=1; + case '+': s++; + } + /* Compute n as a negative number to avoid overflow on INT_MIN */ + while (isdigit(*s)) + n = 10*n - (*s++ - '0'); + return neg ? n : -n; +} diff --git a/libc/stdlib/atol.c b/libc/stdlib/atol.c new file mode 100644 index 000000000..140ea3ea3 --- /dev/null +++ b/libc/stdlib/atol.c @@ -0,0 +1,17 @@ +#include <stdlib.h> +#include <ctype.h> + +long atol(const char *s) +{ + long n=0; + int neg=0; + while (isspace(*s)) s++; + switch (*s) { + case '-': neg=1; + case '+': s++; + } + /* Compute n as a negative number to avoid overflow on LONG_MIN */ + while (isdigit(*s)) + n = 10*n - (*s++ - '0'); + return neg ? n : -n; +} diff --git a/libc/stdlib/atoll.c b/libc/stdlib/atoll.c new file mode 100644 index 000000000..b69304895 --- /dev/null +++ b/libc/stdlib/atoll.c @@ -0,0 +1,17 @@ +#include <stdlib.h> +#include <ctype.h> + +long long atoll(const char *s) +{ + long long n=0; + int neg=0; + while (isspace(*s)) s++; + switch (*s) { + case '-': neg=1; + case '+': s++; + } + /* Compute n as a negative number to avoid overflow on LLONG_MIN */ + while (isdigit(*s)) + n = 10*n - (*s++ - '0'); + return neg ? n : -n; +} diff --git a/libc/stdlib/bsearch.c b/libc/stdlib/bsearch.c new file mode 100644 index 000000000..61d89367e --- /dev/null +++ b/libc/stdlib/bsearch.c @@ -0,0 +1,20 @@ +#include <stdlib.h> + +void *bsearch(const void *key, const void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *)) +{ + void *try; + int sign; + while (nel > 0) { + try = (char *)base + width*(nel/2); + sign = cmp(key, try); + if (!sign) return try; + else if (nel == 1) break; + else if (sign < 0) + nel /= 2; + else { + base = try; + nel -= nel/2; + } + } + return NULL; +} diff --git a/libc/stdlib/div.c b/libc/stdlib/div.c new file mode 100644 index 000000000..e42c1f14f --- /dev/null +++ b/libc/stdlib/div.c @@ -0,0 +1,6 @@ +#include <stdlib.h> + +div_t div(int num, int den) +{ + return (div_t){ num/den, num%den }; +} diff --git a/libc/stdlib/ecvt.c b/libc/stdlib/ecvt.c new file mode 100644 index 000000000..48e70cd86 --- /dev/null +++ b/libc/stdlib/ecvt.c @@ -0,0 +1,19 @@ +#include <stdlib.h> +#include <stdio.h> + +char *ecvt(double x, int n, int *dp, int *sign) +{ + static char buf[16]; + char tmp[32]; + int i, j; + + if (n-1U > 15) n = 15; + sprintf(tmp, "%.*e", n-1, x); + i = *sign = (tmp[0]=='-'); + for (j=0; tmp[i]!='e'; j+=(tmp[i++]!='.')) + buf[j] = tmp[i]; + buf[j] = 0; + *dp = atoi(tmp+i+1); + + return buf; +} diff --git a/libc/stdlib/fcvt.c b/libc/stdlib/fcvt.c new file mode 100644 index 000000000..003aa5aaa --- /dev/null +++ b/libc/stdlib/fcvt.c @@ -0,0 +1,25 @@ +#define _GNU_SOURCE +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +char *fcvt(double x, int n, int *dp, int *sign) +{ + char tmp[1500]; + int i, lz; + + if (n > 1400U) n = 1400; + sprintf(tmp, "%.*f", n, x); + i = (tmp[0] == '-'); + if (tmp[i] == '0') lz = strspn(tmp+i+2, "0"); + else lz = -(int)strcspn(tmp+i, "."); + + if (n<=lz) { + *sign = i; + *dp = 0; + if (n>14U) n = 14; + return "000000000000000"+14-n; + } + + return ecvt(x, n-lz, dp, sign); +} diff --git a/libc/stdlib/gcvt.c b/libc/stdlib/gcvt.c new file mode 100644 index 000000000..6c075e258 --- /dev/null +++ b/libc/stdlib/gcvt.c @@ -0,0 +1,8 @@ +#include <stdlib.h> +#include <stdio.h> + +char *gcvt(double x, int n, char *b) +{ + sprintf(b, "%.*g", n, x); + return b; +} diff --git a/libc/stdlib/imaxabs.c b/libc/stdlib/imaxabs.c new file mode 100644 index 000000000..810018193 --- /dev/null +++ b/libc/stdlib/imaxabs.c @@ -0,0 +1,6 @@ +#include <inttypes.h> + +intmax_t imaxabs(intmax_t a) +{ + return a>0 ? a : -a; +} diff --git a/libc/stdlib/imaxdiv.c b/libc/stdlib/imaxdiv.c new file mode 100644 index 000000000..b2ce821f5 --- /dev/null +++ b/libc/stdlib/imaxdiv.c @@ -0,0 +1,6 @@ +#include <inttypes.h> + +imaxdiv_t imaxdiv(intmax_t num, intmax_t den) +{ + return (imaxdiv_t){ num/den, num%den }; +} diff --git a/libc/stdlib/labs.c b/libc/stdlib/labs.c new file mode 100644 index 000000000..675b95b8e --- /dev/null +++ b/libc/stdlib/labs.c @@ -0,0 +1,4 @@ +long labs(long a) +{ + return a>0 ? a : -a; +} diff --git a/libc/stdlib/ldiv.c b/libc/stdlib/ldiv.c new file mode 100644 index 000000000..36eb960b0 --- /dev/null +++ b/libc/stdlib/ldiv.c @@ -0,0 +1,6 @@ +#include <stdlib.h> + +ldiv_t ldiv(long num, long den) +{ + return (ldiv_t){ num/den, num%den }; +} diff --git a/libc/stdlib/llabs.c b/libc/stdlib/llabs.c new file mode 100644 index 000000000..bec4a03d6 --- /dev/null +++ b/libc/stdlib/llabs.c @@ -0,0 +1,4 @@ +long long llabs(long long a) +{ + return a>0 ? a : -a; +} diff --git a/libc/stdlib/lldiv.c b/libc/stdlib/lldiv.c new file mode 100644 index 000000000..7aaf7a0e6 --- /dev/null +++ b/libc/stdlib/lldiv.c @@ -0,0 +1,6 @@ +#include <stdlib.h> + +lldiv_t lldiv(long long num, long long den) +{ + return (lldiv_t){ num/den, num%den }; +} diff --git a/libc/stdlib/qsort.c b/libc/stdlib/qsort.c new file mode 100644 index 000000000..434d93507 --- /dev/null +++ b/libc/stdlib/qsort.c @@ -0,0 +1,215 @@ +/* Copyright (C) 2011 by Valentin Ochs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* Minor changes by Rich Felker for integration in musl, 2011-04-27. */ + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "atomic.h" +#define ntz(x) a_ctz_l((x)) + +typedef int (*cmpfun)(const void *, const void *); + +static inline int pntz(size_t p[2]) { + int r = ntz(p[0] - 1); + if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) { + return r; + } + return 0; +} + +static void cycle(size_t width, unsigned char* ar[], int n) +{ + unsigned char tmp[256]; + size_t l; + int i; + + if(n < 2) { + return; + } + + ar[n] = tmp; + while(width) { + l = sizeof(tmp) < width ? sizeof(tmp) : width; + memcpy(ar[n], ar[0], l); + for(i = 0; i < n; i++) { + memcpy(ar[i], ar[i + 1], l); + ar[i] += l; + } + width -= l; + } +} + +/* shl() and shr() need n > 0 */ +static inline void shl(size_t p[2], int n) +{ + if(n >= 8 * sizeof(size_t)) { + n -= 8 * sizeof(size_t); + p[1] = p[0]; + p[0] = 0; + } + p[1] <<= n; + p[1] |= p[0] >> (sizeof(size_t) * 8 - n); + p[0] <<= n; +} + +static inline void shr(size_t p[2], int n) +{ + if(n >= 8 * sizeof(size_t)) { + n -= 8 * sizeof(size_t); + p[0] = p[1]; + p[1] = 0; + } + p[0] >>= n; + p[0] |= p[1] << (sizeof(size_t) * 8 - n); + p[1] >>= n; +} + +static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size_t lp[]) +{ + unsigned char *rt, *lf; + unsigned char *ar[14 * sizeof(size_t) + 1]; + int i = 1; + + ar[0] = head; + while(pshift > 1) { + rt = head - width; + lf = head - width - lp[pshift - 2]; + + if((*cmp)(ar[0], lf) >= 0 && (*cmp)(ar[0], rt) >= 0) { + break; + } + if((*cmp)(lf, rt) >= 0) { + ar[i++] = lf; + head = lf; + pshift -= 1; + } else { + ar[i++] = rt; + head = rt; + pshift -= 2; + } + } + cycle(width, ar, i); +} + +static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], int pshift, int trusty, size_t lp[]) +{ + unsigned char *stepson, + *rt, *lf; + size_t p[2]; + unsigned char *ar[14 * sizeof(size_t) + 1]; + int i = 1; + int trail; + + p[0] = pp[0]; + p[1] = pp[1]; + + ar[0] = head; + while(p[0] != 1 || p[1] != 0) { + stepson = head - lp[pshift]; + if((*cmp)(stepson, ar[0]) <= 0) { + break; + } + if(!trusty && pshift > 1) { + rt = head - width; + lf = head - width - lp[pshift - 2]; + if((*cmp)(rt, stepson) >= 0 || (*cmp)(lf, stepson) >= 0) { + break; + } + } + + ar[i++] = stepson; + head = stepson; + trail = pntz(p); + shr(p, trail); + pshift += trail; + trusty = 0; + } + if(!trusty) { + cycle(width, ar, i); + sift(head, width, cmp, pshift, lp); + } +} + +void qsort(void *base, size_t nel, size_t width, cmpfun cmp) +{ + size_t lp[12*sizeof(size_t)]; + size_t i, size = width * nel; + unsigned char *head, *high; + size_t p[2] = {1, 0}; + int pshift = 1; + int trail; + + if (!size) return; + + head = base; + high = head + size - width; + + /* Precompute Leonardo numbers, scaled by element width */ + for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++); + + while(head < high) { + if((p[0] & 3) == 3) { + sift(head, width, cmp, pshift, lp); + shr(p, 2); + pshift += 2; + } else { + if(lp[pshift - 1] >= high - head) { + trinkle(head, width, cmp, p, pshift, 0, lp); + } else { + sift(head, width, cmp, pshift, lp); + } + + if(pshift == 1) { + shl(p, 1); + pshift = 0; + } else { + shl(p, pshift - 1); + pshift = 1; + } + } + + p[0] |= 1; + head += width; + } + + trinkle(head, width, cmp, p, pshift, 0, lp); + + while(pshift != 1 || p[0] != 1 || p[1] != 0) { + if(pshift <= 1) { + trail = pntz(p); + shr(p, trail); + pshift += trail; + } else { + shl(p, 2); + pshift -= 2; + p[0] ^= 7; + shr(p, 1); + trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp); + shl(p, 1); + p[0] |= 1; + trinkle(head - width, width, cmp, p, pshift, 1, lp); + } + head -= width; + } +} diff --git a/libc/stdlib/strtol.c b/libc/stdlib/strtol.c new file mode 100644 index 000000000..4af0cf826 --- /dev/null +++ b/libc/stdlib/strtol.c @@ -0,0 +1,56 @@ +#include "../stdio/stdio_impl.h" +#include "intscan.h" +#include "../stdio/shgetc.h" +#include <inttypes.h> +#include <limits.h> +#include <ctype.h> + +static unsigned long long strtox(const char *s, char **p, int base, unsigned long long lim) +{ + /* FIXME: use a helper function or macro to setup the FILE */ + FILE f; + f.flags = 0; + f.buf = f.rpos = (void *)s; + if ((size_t)s > (size_t)-1/2) + f.rend = (void *)-1; + else + f.rend = (unsigned char *)s+(size_t)-1/2; + f.lock = -1; + shlim(&f, 0); + unsigned long long y = __intscan(&f, base, 1, lim); + if (p) { + size_t cnt = shcnt(&f); + *p = (char *)s + cnt; + } + return y; +} + +unsigned long long strtoull(const char *restrict s, char **restrict p, int base) +{ + return strtox(s, p, base, ULLONG_MAX); +} + +long long strtoll(const char *restrict s, char **restrict p, int base) +{ + return strtox(s, p, base, LLONG_MIN); +} + +unsigned long strtoul(const char *restrict s, char **restrict p, int base) +{ + return strtox(s, p, base, ULONG_MAX); +} + +long strtol(const char *restrict s, char **restrict p, int base) +{ + return strtox(s, p, base, 0UL+LONG_MIN); +} + +intmax_t strtoimax(const char *restrict s, char **restrict p, int base) +{ + return strtoll(s, p, base); +} + +uintmax_t strtoumax(const char *restrict s, char **restrict p, int base) +{ + return strtoull(s, p, base); +} diff --git a/libc/stdlib/wcstol.c b/libc/stdlib/wcstol.c new file mode 100644 index 000000000..000e266a9 --- /dev/null +++ b/libc/stdlib/wcstol.c @@ -0,0 +1,82 @@ +#include "../stdio/stdio_impl.h" +#include "intscan.h" +#include "../stdio/shgetc.h" +#include <inttypes.h> +#include <limits.h> +#include <wctype.h> +#include <wchar.h> + +/* This read function heavily cheats. It knows: + * (1) len will always be 1 + * (2) non-ascii characters don't matter */ + +static size_t do_read(FILE *f, unsigned char *buf, size_t len) +{ + size_t i; + const wchar_t *wcs = f->cookie; + + if (!wcs[0]) wcs=L"@"; + for (i=0; i<f->buf_size && wcs[i]; i++) + f->buf[i] = wcs[i] < 128 ? wcs[i] : '@'; + f->rpos = f->buf; + f->rend = f->buf + i; + f->cookie = (void *)(wcs+i); + + if (i && len) { + *buf = *f->rpos++; + return 1; + } + return 0; +} + +static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, unsigned long long lim) +{ + wchar_t *t = (wchar_t *)s; + unsigned char buf[64]; + FILE f = {0}; + f.flags = 0; + f.rpos = f.rend = 0; + f.buf = buf + 4; + f.buf_size = sizeof buf - 4; + f.lock = -1; + f.read = do_read; + while (iswspace(*t)) t++; + f.cookie = (void *)t; + shlim(&f, 0); + unsigned long long y = __intscan(&f, base, 1, lim); + if (p) { + size_t cnt = shcnt(&f); + *p = cnt ? t + cnt : (wchar_t *)s; + } + return y; +} + +unsigned long long wcstoull(const wchar_t *restrict s, wchar_t **restrict p, int base) +{ + return wcstox(s, p, base, ULLONG_MAX); +} + +long long wcstoll(const wchar_t *restrict s, wchar_t **restrict p, int base) +{ + return wcstox(s, p, base, LLONG_MIN); +} + +unsigned long wcstoul(const wchar_t *restrict s, wchar_t **restrict p, int base) +{ + return wcstox(s, p, base, ULONG_MAX); +} + +long wcstol(const wchar_t *restrict s, wchar_t **restrict p, int base) +{ + return wcstox(s, p, base, 0UL+LONG_MIN); +} + +intmax_t wcstoimax(const wchar_t *restrict s, wchar_t **restrict p, int base) +{ + return wcstoll(s, p, base); +} + +uintmax_t wcstoumax(const wchar_t *restrict s, wchar_t **restrict p, int base) +{ + return wcstoull(s, p, base); +} -- GitLab