diff options
author | Bruce Mitchener <bruce.mitchener@gmail.com> | 2013-04-15 01:19:23 +0700 |
---|---|---|
committer | Bruce Mitchener <bruce.mitchener@gmail.com> | 2013-04-22 16:45:07 +0700 |
commit | b9090fa1f2ba90a5745981d1a4d4108915ddd6e9 (patch) | |
tree | cd895bd69944b4f763b31a0d3ead492f952fc6dd /system | |
parent | 58175e72768f0697e83b91f752c9be533f613c25 (diff) |
Add musl wchar function implementations.
Diffstat (limited to 'system')
30 files changed, 421 insertions, 0 deletions
diff --git a/system/lib/libc/musl/src/internal/libc.c b/system/lib/libc/musl/src/internal/libc.c new file mode 100644 index 00000000..942f6b44 --- /dev/null +++ b/system/lib/libc/musl/src/internal/libc.c @@ -0,0 +1,22 @@ +#include "libc.h" + +#ifdef USE_LIBC_ACCESSOR +struct __libc *__libc_loc() +{ + static struct __libc __libc; + return &__libc; +} +#else +struct __libc __libc; +#endif + +#ifdef BROKEN_VISIBILITY +__asm__(".hidden __libc"); +#endif + +size_t __hwcap; +size_t __sysinfo; +char *__progname=0, *__progname_full=0; + +weak_alias(__progname, program_invocation_short_name); +weak_alias(__progname_full, program_invocation_name); diff --git a/system/lib/libc/musl/src/internal/libc.h b/system/lib/libc/musl/src/internal/libc.h new file mode 100644 index 00000000..c9416f07 --- /dev/null +++ b/system/lib/libc/musl/src/internal/libc.h @@ -0,0 +1,71 @@ +#ifndef LIBC_H +#define LIBC_H + +#include <stdlib.h> +#include <stdio.h> + +struct __libc { + void *main_thread; + int threaded; + int secure; + size_t *auxv; + int (*atexit)(void (*)(void)); + void (*fini)(void); + void (*ldso_fini)(void); + volatile int threads_minus_1; + int canceldisable; + FILE *ofl_head; + int ofl_lock[2]; + size_t tls_size; +}; + +extern size_t __hwcap; + +#if !defined(__PIC__) || (100*__GNUC__+__GNUC_MINOR__ >= 303 && !defined(__PCC__)) + +#ifdef __PIC__ +#if __GNUC__ < 4 +#define BROKEN_VISIBILITY 1 +#endif +#define ATTR_LIBC_VISIBILITY __attribute__((visibility("hidden"))) +#else +#define ATTR_LIBC_VISIBILITY +#endif + +extern struct __libc __libc ATTR_LIBC_VISIBILITY; +#define libc __libc + +#else + +#define USE_LIBC_ACCESSOR +#define ATTR_LIBC_VISIBILITY +extern struct __libc *__libc_loc(void) __attribute__((const)); +#define libc (*__libc_loc()) + +#endif + + +/* Designed to avoid any overhead in non-threaded processes */ +void __lock(volatile int *) ATTR_LIBC_VISIBILITY; +void __unlock(volatile int *) ATTR_LIBC_VISIBILITY; +int __lockfile(FILE *) ATTR_LIBC_VISIBILITY; +void __unlockfile(FILE *) ATTR_LIBC_VISIBILITY; +#define LOCK(x) (libc.threads_minus_1 ? (__lock(x),1) : ((void)(x),1)) +#define UNLOCK(x) (libc.threads_minus_1 ? (__unlock(x),1) : ((void)(x),1)) + +void __synccall(void (*)(void *), void *); +int __setxid(int, int, int, int); + +extern char **__environ; + +#undef weak_alias +#define weak_alias(old, new) \ + extern __typeof(old) new __attribute__((weak, alias(#old))) + +#undef LFS64_2 +#define LFS64_2(x, y) weak_alias(x, y) + +#undef LFS64 +#define LFS64(x) LFS64_2(x, x##64) + +#endif diff --git a/system/lib/libc/musl/src/string/wcpcpy.c b/system/lib/libc/musl/src/string/wcpcpy.c new file mode 100644 index 00000000..ef401343 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcpcpy.c @@ -0,0 +1,6 @@ +#include <wchar.h> + +wchar_t *wcpcpy(wchar_t *restrict d, const wchar_t *restrict s) +{ + return wcscpy(d, s) + wcslen(s); +} diff --git a/system/lib/libc/musl/src/string/wcpncpy.c b/system/lib/libc/musl/src/string/wcpncpy.c new file mode 100644 index 00000000..b667f6d6 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcpncpy.c @@ -0,0 +1,6 @@ +#include <wchar.h> + +wchar_t *wcpncpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n) +{ + return wcsncpy(d, s, n) + wcsnlen(s, n); +} diff --git a/system/lib/libc/musl/src/string/wcscasecmp.c b/system/lib/libc/musl/src/string/wcscasecmp.c new file mode 100644 index 00000000..3edeec7d --- /dev/null +++ b/system/lib/libc/musl/src/string/wcscasecmp.c @@ -0,0 +1,7 @@ +#include <wchar.h> +#include <wctype.h> + +int wcscasecmp(const wchar_t *l, const wchar_t *r) +{ + return wcsncasecmp(l, r, -1); +} diff --git a/system/lib/libc/musl/src/string/wcscasecmp_l.c b/system/lib/libc/musl/src/string/wcscasecmp_l.c new file mode 100644 index 00000000..065dd0aa --- /dev/null +++ b/system/lib/libc/musl/src/string/wcscasecmp_l.c @@ -0,0 +1,6 @@ +#include <wchar.h> + +int wcscasecmp_l(const wchar_t *l, const wchar_t *r, locale_t locale) +{ + return wcscasecmp(l, r); +} diff --git a/system/lib/libc/musl/src/string/wcscat.c b/system/lib/libc/musl/src/string/wcscat.c new file mode 100644 index 00000000..d4f00ebd --- /dev/null +++ b/system/lib/libc/musl/src/string/wcscat.c @@ -0,0 +1,7 @@ +#include <wchar.h> + +wchar_t *wcscat(wchar_t *restrict dest, const wchar_t *restrict src) +{ + wcscpy(dest + wcslen(dest), src); + return dest; +} diff --git a/system/lib/libc/musl/src/string/wcschr.c b/system/lib/libc/musl/src/string/wcschr.c new file mode 100644 index 00000000..8dfc2f31 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcschr.c @@ -0,0 +1,8 @@ +#include <wchar.h> + +wchar_t *wcschr(const wchar_t *s, wchar_t c) +{ + if (!c) return (wchar_t *)s + wcslen(s); + for (; *s && *s != c; s++); + return *s ? (wchar_t *)s : 0; +} diff --git a/system/lib/libc/musl/src/string/wcscmp.c b/system/lib/libc/musl/src/string/wcscmp.c new file mode 100644 index 00000000..26eeee70 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcscmp.c @@ -0,0 +1,7 @@ +#include <wchar.h> + +int wcscmp(const wchar_t *l, const wchar_t *r) +{ + for (; *l==*r && *l && *r; l++, r++); + return *l - *r; +} diff --git a/system/lib/libc/musl/src/string/wcscpy.c b/system/lib/libc/musl/src/string/wcscpy.c new file mode 100644 index 00000000..625bf53d --- /dev/null +++ b/system/lib/libc/musl/src/string/wcscpy.c @@ -0,0 +1,8 @@ +#include <wchar.h> + +wchar_t *wcscpy(wchar_t *restrict d, const wchar_t *restrict s) +{ + wchar_t *a = d; + while ((*d++ = *s++)); + return a; +} diff --git a/system/lib/libc/musl/src/string/wcscspn.c b/system/lib/libc/musl/src/string/wcscspn.c new file mode 100644 index 00000000..c4e52722 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcscspn.c @@ -0,0 +1,10 @@ +#include <wchar.h> + +size_t wcscspn(const wchar_t *s, const wchar_t *c) +{ + const wchar_t *a; + if (!c[0]) return wcslen(s); + if (!c[1]) return (s=wcschr(a=s, *c)) ? s-a : wcslen(a); + for (a=s; *s && !wcschr(c, *s); s++); + return s-a; +} diff --git a/system/lib/libc/musl/src/string/wcsdup.c b/system/lib/libc/musl/src/string/wcsdup.c new file mode 100644 index 00000000..dd49c1b6 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsdup.c @@ -0,0 +1,11 @@ +#include <stdlib.h> +#include <wchar.h> +#include "libc.h" + +wchar_t *wcsdup(const wchar_t *s) +{ + size_t l = wcslen(s); + wchar_t *d = malloc((l+1)*sizeof(wchar_t)); + if (!d) return NULL; + return wmemcpy(d, s, l+1); +} diff --git a/system/lib/libc/musl/src/string/wcslen.c b/system/lib/libc/musl/src/string/wcslen.c new file mode 100644 index 00000000..1b7b6655 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcslen.c @@ -0,0 +1,8 @@ +#include <wchar.h> + +size_t wcslen(const wchar_t *s) +{ + const wchar_t *a; + for (a=s; *s; s++); + return s-a; +} diff --git a/system/lib/libc/musl/src/string/wcsncasecmp.c b/system/lib/libc/musl/src/string/wcsncasecmp.c new file mode 100644 index 00000000..8fefe799 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsncasecmp.c @@ -0,0 +1,9 @@ +#include <wchar.h> +#include <wctype.h> + +int wcsncasecmp(const wchar_t *l, const wchar_t *r, size_t n) +{ + if (!n--) return 0; + for (; *l && *r && n && (*l == *r || towlower(*l) == towlower(*r)); l++, r++, n--); + return towlower(*l) - towlower(*r); +} diff --git a/system/lib/libc/musl/src/string/wcsncasecmp_l.c b/system/lib/libc/musl/src/string/wcsncasecmp_l.c new file mode 100644 index 00000000..63872481 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsncasecmp_l.c @@ -0,0 +1,6 @@ +#include <wchar.h> + +int wcsncasecmp_l(const wchar_t *l, const wchar_t *r, size_t n, locale_t locale) +{ + return wcsncasecmp(l, r, n); +} diff --git a/system/lib/libc/musl/src/string/wcsncat.c b/system/lib/libc/musl/src/string/wcsncat.c new file mode 100644 index 00000000..8563f1a2 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsncat.c @@ -0,0 +1,10 @@ +#include <wchar.h> + +wchar_t *wcsncat(wchar_t *restrict d, const wchar_t *restrict s, size_t n) +{ + wchar_t *a = d; + d += wcslen(d); + while (n && *s) n--, *d++ = *s++; + *d++ = 0; + return a; +} diff --git a/system/lib/libc/musl/src/string/wcsncmp.c b/system/lib/libc/musl/src/string/wcsncmp.c new file mode 100644 index 00000000..4ab32a92 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsncmp.c @@ -0,0 +1,7 @@ +#include <wchar.h> + +int wcsncmp(const wchar_t *l, const wchar_t *r, size_t n) +{ + for (; n && *l==*r && *l && *r; n--, l++, r++); + return n ? *l - *r : 0; +} diff --git a/system/lib/libc/musl/src/string/wcsncpy.c b/system/lib/libc/musl/src/string/wcsncpy.c new file mode 100644 index 00000000..4bede04d --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsncpy.c @@ -0,0 +1,9 @@ +#include <wchar.h> + +wchar_t *wcsncpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n) +{ + wchar_t *a = d; + while (n && *s) n--, *d++ = *s++; + wmemset(d, 0, n); + return a; +} diff --git a/system/lib/libc/musl/src/string/wcsnlen.c b/system/lib/libc/musl/src/string/wcsnlen.c new file mode 100644 index 00000000..a7763373 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsnlen.c @@ -0,0 +1,8 @@ +#include <wchar.h> + +size_t wcsnlen(const wchar_t *s, size_t n) +{ + const wchar_t *z = wmemchr(s, 0, n); + if (z) n = z-s; + return n; +} diff --git a/system/lib/libc/musl/src/string/wcspbrk.c b/system/lib/libc/musl/src/string/wcspbrk.c new file mode 100644 index 00000000..0c72c197 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcspbrk.c @@ -0,0 +1,7 @@ +#include <wchar.h> + +wchar_t *wcspbrk(const wchar_t *s, const wchar_t *b) +{ + s += wcscspn(s, b); + return *s ? (wchar_t *)s : NULL; +} diff --git a/system/lib/libc/musl/src/string/wcsrchr.c b/system/lib/libc/musl/src/string/wcsrchr.c new file mode 100644 index 00000000..8961b9e2 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsrchr.c @@ -0,0 +1,8 @@ +#include <wchar.h> + +wchar_t *wcsrchr(const wchar_t *s, wchar_t c) +{ + const wchar_t *p; + for (p=s+wcslen(s); p>=s && *p!=c; p--); + return p>=s ? (wchar_t *)p : 0; +} diff --git a/system/lib/libc/musl/src/string/wcsspn.c b/system/lib/libc/musl/src/string/wcsspn.c new file mode 100644 index 00000000..4320d8f6 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsspn.c @@ -0,0 +1,8 @@ +#include <wchar.h> + +size_t wcsspn(const wchar_t *s, const wchar_t *c) +{ + const wchar_t *a; + for (a=s; *s && wcschr(c, *s); s++); + return s-a; +} diff --git a/system/lib/libc/musl/src/string/wcsstr.c b/system/lib/libc/musl/src/string/wcsstr.c new file mode 100644 index 00000000..037d0965 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcsstr.c @@ -0,0 +1,108 @@ +#include <wchar.h> +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + +static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n) +{ + const wchar_t *z; + size_t l, ip, jp, k, p, ms, p0, mem, mem0; + + /* Computing length of needle */ + for (l=0; n[l] && h[l]; l++); + if (n[l]) return 0; /* hit the end of h */ + + /* Compute maximal suffix */ + ip = -1; jp = 0; k = p = 1; + while (jp+k<l) { + if (n[ip+k] == n[jp+k]) { + if (k == p) { + jp += p; + k = 1; + } else k++; + } else if (n[ip+k] > n[jp+k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + ms = ip; + p0 = p; + + /* And with the opposite comparison */ + ip = -1; jp = 0; k = p = 1; + while (jp+k<l) { + if (n[ip+k] == n[jp+k]) { + if (k == p) { + jp += p; + k = 1; + } else k++; + } else if (n[ip+k] < n[jp+k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + if (ip+1 > ms+1) ms = ip; + else p = p0; + + /* Periodic needle? */ + if (wmemcmp(n, n+p, ms+1)) { + mem0 = 0; + p = MAX(ms, l-ms-1) + 1; + } else mem0 = l-p; + mem = 0; + + /* Initialize incremental end-of-haystack pointer */ + z = h; + + /* Search loop */ + for (;;) { + /* Update incremental end-of-haystack pointer */ + if (z-h < l) { + /* Fast estimate for MIN(l,63) */ + size_t grow = l | 63; + const wchar_t *z2 = wmemchr(z, 0, grow); + if (z2) { + z = z2; + if (z-h < l) return 0; + } else z += grow; + } + + /* Compare right half */ + for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++); + if (n[k]) { + h += k-ms; + mem = 0; + continue; + } + /* Compare left half */ + for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--); + if (k == mem) return (wchar_t *)h; + h += p; + mem = mem0; + } +} + +wchar_t *wcsstr(const wchar_t *restrict h, const wchar_t *restrict n) +{ + /* Return immediately on empty needle or haystack */ + if (!n[0]) return (wchar_t *)h; + if (!h[0]) return 0; + + /* Use faster algorithms for short needles */ + h = wcschr(h, *n); + if (!h || !n[1]) return (wchar_t *)h; + if (!h[1]) return 0; + + return twoway_wcsstr(h, n); +} diff --git a/system/lib/libc/musl/src/string/wcstok.c b/system/lib/libc/musl/src/string/wcstok.c new file mode 100644 index 00000000..ecc80331 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcstok.c @@ -0,0 +1,12 @@ +#include <wchar.h> + +wchar_t *wcstok(wchar_t *restrict s, const wchar_t *restrict sep, wchar_t **restrict p) +{ + if (!s && !(s = *p)) return NULL; + s += wcsspn(s, sep); + if (!*s) return *p = 0; + *p = s + wcscspn(s, sep); + if (**p) *(*p)++ = 0; + else *p = 0; + return s; +} diff --git a/system/lib/libc/musl/src/string/wcswcs.c b/system/lib/libc/musl/src/string/wcswcs.c new file mode 100644 index 00000000..9cfe4ac4 --- /dev/null +++ b/system/lib/libc/musl/src/string/wcswcs.c @@ -0,0 +1,6 @@ +#include <wchar.h> + +wchar_t *wcswcs(const wchar_t *haystack, const wchar_t *needle) +{ + return wcsstr(haystack, needle); +} diff --git a/system/lib/libc/musl/src/string/wmemchr.c b/system/lib/libc/musl/src/string/wmemchr.c new file mode 100644 index 00000000..37d69629 --- /dev/null +++ b/system/lib/libc/musl/src/string/wmemchr.c @@ -0,0 +1,8 @@ +#include <string.h> +#include <wchar.h> + +wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n) +{ + for (; n && *s != c; n--, s++); + return n ? (wchar_t *)s : 0; +} diff --git a/system/lib/libc/musl/src/string/wmemcmp.c b/system/lib/libc/musl/src/string/wmemcmp.c new file mode 100644 index 00000000..6788a383 --- /dev/null +++ b/system/lib/libc/musl/src/string/wmemcmp.c @@ -0,0 +1,8 @@ +#include <string.h> +#include <wchar.h> + +int wmemcmp(const wchar_t *l, const wchar_t *r, size_t n) +{ + for (; n && *l==*r; n--, l++, r++); + return n ? *l-*r : 0; +} diff --git a/system/lib/libc/musl/src/string/wmemcpy.c b/system/lib/libc/musl/src/string/wmemcpy.c new file mode 100644 index 00000000..55a8e1d8 --- /dev/null +++ b/system/lib/libc/musl/src/string/wmemcpy.c @@ -0,0 +1,9 @@ +#include <string.h> +#include <wchar.h> + +wchar_t *wmemcpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n) +{ + wchar_t *a = d; + while (n--) *d++ = *s++; + return a; +} diff --git a/system/lib/libc/musl/src/string/wmemmove.c b/system/lib/libc/musl/src/string/wmemmove.c new file mode 100644 index 00000000..cde4feec --- /dev/null +++ b/system/lib/libc/musl/src/string/wmemmove.c @@ -0,0 +1,12 @@ +#include <string.h> +#include <wchar.h> + +wchar_t *wmemmove(wchar_t *d, const wchar_t *s, size_t n) +{ + wchar_t *d0 = d; + if ((size_t)(d-s) < n) + while (n--) d[n] = s[n]; + else + while (n--) *d++ = *s++; + return d0; +} diff --git a/system/lib/libc/musl/src/string/wmemset.c b/system/lib/libc/musl/src/string/wmemset.c new file mode 100644 index 00000000..1a2a8618 --- /dev/null +++ b/system/lib/libc/musl/src/string/wmemset.c @@ -0,0 +1,9 @@ +#include <string.h> +#include <wchar.h> + +wchar_t *wmemset(wchar_t *d, wchar_t c, size_t n) +{ + wchar_t *ret = d; + while (n--) *d++ = c; + return ret; +} |