Update Musl Libc code

We now have implement all of Musl's localization code, the same way that
Musl implements localization. You may need setlocale(LC_ALL, "C.UTF-8"),
just in case anything stops working as expected.
This commit is contained in:
Justine Tunney 2024-07-30 09:14:57 -07:00
parent d0360bf4bd
commit bb815eafaf
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
116 changed files with 6525 additions and 5523 deletions

View file

@ -246,8 +246,6 @@ o/$(MODE)/ape: $(APE_CHECKS) \
o/$(MODE)/ape/ape.lds \
o/$(MODE)/ape/ape.elf \
o/$(MODE)/ape/ape.macho \
o/$(MODE)/ape/ape-copy-self.o \
o/$(MODE)/ape/ape-no-modify-self.o
endif

View file

@ -104,6 +104,8 @@ static bool IsMyDebugBinary(const char *path) {
static void FindDebugBinaryInit(void) {
const char *comdbg;
if (issetugid())
return;
if ((comdbg = getenv("COMDBG")) && IsMyDebugBinary(comdbg)) {
g_comdbg.res = comdbg;
return;

View file

@ -1,6 +1,4 @@
#ifndef _LANGINFO_H
#define _LANGINFO_H
#include "libc/str/langinfo.h"
#include "libc/str/locale.h"
#include "libc/str/nltypes.h"
#endif /* _LANGINFO_H */

View file

@ -40,7 +40,7 @@ void GetAddr2linePathInit(void) {
char *res;
int e = errno;
const char *env, *cmd, *path;
if ((env = getenv("ADDR2LINE"))) {
if ((env = secure_getenv("ADDR2LINE"))) {
cmd = env;
path = env;
} else {

View file

@ -37,6 +37,7 @@
#include "libc/runtime/syslib.internal.h"
#include "libc/stdalign.internal.h"
#include "libc/str/locale.h"
#include "libc/str/locale.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
@ -213,7 +214,6 @@ textstartup void __enable_tls(void) {
tib->tib_errno = __errno;
tib->tib_strace = __strace;
tib->tib_ftrace = __ftrace;
tib->tib_locale = (intptr_t)&__c_dot_utf8_locale;
tib->tib_pthread = (pthread_t)&_pthread_static;
if (IsWindows()) {
intptr_t hThread;
@ -246,6 +246,7 @@ textstartup void __enable_tls(void) {
// initialize posix threads
_pthread_static.tib = tib;
_pthread_static.pt_flags = PT_STATIC;
_pthread_static.pt_locale = &__global_locale;
dll_init(&_pthread_static.list);
_pthread_list = &_pthread_static.list;
atomic_store_explicit(&_pthread_static.ptid, tid, memory_order_release);

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/intrin/getenv.h"
#include "libc/intrin/safemacros.h"
#include "libc/log/libfatal.internal.h"
@ -27,8 +28,9 @@
*/
textstartup int __strace_init(int argc, char **argv, char **envp, long *auxv) {
/* asan isn't initialized yet at runlevel 300 */
if (__intercept_flag(&argc, argv, "--strace") ||
__atoul(nulltoempty(__getenv(envp, "STRACE").s))) {
if ((__intercept_flag(&argc, argv, "--strace") ||
__atoul(nulltoempty(__getenv(envp, "STRACE").s))) &&
!issetugid()) {
strace_enabled(+1);
}
return (__argc = argc);

View file

@ -112,7 +112,7 @@ static void __zipos_init(void) {
const char *progpath;
if (!(s = getenv("COSMOPOLITAN_DISABLE_ZIPOS"))) {
// this environment variable may be a filename or file descriptor
if ((progpath = getenv("COSMOPOLITAN_INIT_ZIPOS")) &&
if ((progpath = secure_getenv("COSMOPOLITAN_INIT_ZIPOS")) &&
(x = strtol(progpath, &endptr, 10)) >= 0 && !*endptr) {
fd = x;
} else {

View file

@ -32,7 +32,6 @@ LIBC_SOCK_A_DIRECTDEPS = \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_NT_IPHLPAPI \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_WS2_32 \

View file

@ -1,23 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
size_t c32rtomb(char *s, char32_t c, mbstate_t *t) {
return wcrtomb(s, c, t);
}

View file

@ -1,23 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/locale.h"
void freelocale(locale_t l) {
// TODO: implement me
}

View file

@ -1,5 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_STR_LANGINFO_H_
#define COSMOPOLITAN_LIBC_STR_LANGINFO_H_
#include "libc/str/locale.h"
#include "libc/str/nltypes.h"
COSMOPOLITAN_C_START_
#define ABDAY_1 0x20000
@ -78,7 +80,8 @@ COSMOPOLITAN_C_START_
#define NOSTR 0x50003
#endif
char *nl_langinfo(int);
char *nl_langinfo(nl_item);
char *nl_langinfo_l(nl_item, locale_t);
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_STR_LANGINFO_H_ */

View file

@ -16,10 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/locale.h"
#include "libc/str/locale.internal.h"
#include "libc/str/str.h"
static const uint32_t empty_mo[] = {0x950412de, 0, -1, -1, -1};
static const uint32_t empty_mo[] = {
0x950412de, 0, -1, -1, -1,
};
const struct __locale_map __c_dot_utf8 = {
.map = empty_mo,
@ -27,8 +29,11 @@ const struct __locale_map __c_dot_utf8 = {
.name = "C.UTF-8",
};
const struct __locale_struct __c_locale;
const struct __locale_struct __c_locale = {0};
const struct __locale_struct __c_dot_utf8_locale = {
.cat[LC_CTYPE] = &__c_dot_utf8,
};
struct __locale_struct __global_locale;
pthread_mutex_t __locale_lock = PTHREAD_MUTEX_INITIALIZER;

View file

@ -17,29 +17,13 @@
#define LC_MONETARY_MASK 16
#define LC_MESSAGES_MASK 32
#define LC_ALL_MASK 0x1fbf
#define LOCALE_NAME_MAX 23
COSMOPOLITAN_C_START_
#define LC_GLOBAL_LOCALE ((locale_t) - 1)
struct __locale_map {
const void *map;
size_t map_size;
char name[LOCALE_NAME_MAX + 1];
const struct __locale_map *next;
};
struct __locale_struct {
const struct __locale_map *cat[6];
};
typedef struct __locale_struct *locale_t;
extern const struct __locale_map __c_dot_utf8;
extern const struct __locale_struct __c_locale;
extern const struct __locale_struct __c_dot_utf8_locale;
char *nl_langinfo_l(int, locale_t) libcesque;
char *setlocale(int, const char *) libcesque;
double strtod_l(const char *, char **, locale_t) libcesque;

View file

@ -0,0 +1,52 @@
#ifndef COSMOPOLITAN_LIBC_STR_LOCALE_INTERNAL_H_
#define COSMOPOLITAN_LIBC_STR_LOCALE_INTERNAL_H_
#include "libc/limits.h"
#include "libc/str/locale.h"
#include "libc/thread/posixthread.internal.h"
COSMOPOLITAN_C_START_
#define LOCALE_NAME_MAX 23
struct __locale_map {
const void *map;
size_t map_size;
char name[LOCALE_NAME_MAX + 1];
const struct __locale_map *next;
};
struct __locale_struct {
const struct __locale_map *cat[6];
};
extern pthread_mutex_t __locale_lock;
extern struct __locale_struct __global_locale;
extern const struct __locale_map __c_dot_utf8;
extern const struct __locale_struct __c_locale;
extern const struct __locale_struct __c_dot_utf8_locale;
const struct __locale_map *__get_locale(int, const char *);
const char *__mo_lookup(const void *, size_t, const char *);
const char *__lctrans(const char *, const struct __locale_map *);
const char *__lctrans_cur(const char *);
const char *__lctrans_impl(const char *, const struct __locale_map *);
int __loc_is_allocated(locale_t);
char *__gettextdomain(void);
#define LOC_MAP_FAILED ((const struct __locale_map *)-1)
#define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)])
#define LCTRANS_CUR(msg) __lctrans_cur(msg)
#define C_LOCALE ((locale_t) & __c_locale)
#define UTF8_LOCALE ((locale_t) & __c_dot_utf8_locale)
#define CURRENT_LOCALE _pthread_self()->pt_locale
#define CURRENT_UTF8 (!!_pthread_self()->pt_locale->cat[LC_CTYPE])
#undef MB_CUR_MAX
#define MB_CUR_MAX (CURRENT_UTF8 ? 4 : 1)
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_STR_LOCALE_INTERNAL_H_ */

View file

@ -1,17 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_STR_MB_INTERNAL_H_
#define COSMOPOLITAN_LIBC_STR_MB_INTERNAL_H_
COSMOPOLITAN_C_START_
#define SA 0xc2u
#define SB 0xf4u
#define CODEUNIT(c) (0xdfff & (signed char)(c))
#define IS_CODEUNIT(c) ((unsigned)(c) - 0xdf80 < 0x80)
#define R(a, b) ((uint32_t)((a == 0x80 ? 0x40u - b : 0u - a) << 23))
#define FAILSTATE R(0x80, 0x80)
#define OOB(c, b) \
(((((b) >> 3) - 0x10) | (((b) >> 3) + ((int32_t)(c) >> 26))) & ~7)
extern const uint32_t kMbBittab[51];
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_STR_MB_INTERNAL_H_ */

View file

@ -1,23 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
int mblen(const char *s, size_t n) {
return mbtowc(0, s, n);
}

View file

@ -1,26 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
size_t mbrlen(const char *s, size_t n, mbstate_t *t) {
static mbstate_t ss;
if (!t)
t = &ss;
return mbrtowc(0, s, n, t);
}

View file

@ -1,23 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
int mbsinit(const mbstate_t *t) {
return !t || !*t;
}

View file

@ -1,147 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/str/mb.internal.h"
#include "libc/str/str.h"
__static_yoink("musl_libc_notice");
size_t mbsrtowcs(wchar_t *ws, const char **src, size_t wn, mbstate_t *st) {
const unsigned char *s = (const void *)*src;
size_t wn0 = wn;
unsigned c = 0;
if (st && (c = *(unsigned *)st)) {
if (ws) {
*(unsigned *)st = 0;
goto resume;
} else {
goto resume0;
}
}
if (MB_CUR_MAX == 1) {
if (!ws)
return strlen((const char *)s);
for (;;) {
if (!wn) {
*src = (const void *)s;
return wn0;
}
if (!*s)
break;
c = *s++;
*ws++ = CODEUNIT(c);
wn--;
}
*ws = 0;
*src = 0;
return wn0 - wn;
}
if (!ws)
for (;;) {
if (*s - 1u < 0x7f) {
s++;
wn--;
continue;
}
if (*s - SA > SB - SA)
break;
c = kMbBittab[*s++ - SA];
resume0:
if (OOB(c, *s)) {
s--;
break;
}
s++;
if (c & (1U << 25)) {
if (*s - 0x80u >= 0x40) {
s -= 2;
break;
}
s++;
if (c & (1U << 19)) {
if (*s - 0x80u >= 0x40) {
s -= 3;
break;
}
s++;
}
}
wn--;
c = 0;
}
else
for (;;) {
if (!wn) {
*src = (const void *)s;
return wn0;
}
if (*s - 1u < 0x7f) {
*ws++ = *s++;
wn--;
continue;
}
if (*s - SA > SB - SA)
break;
c = kMbBittab[*s++ - SA];
resume:
if (OOB(c, *s)) {
s--;
break;
}
c = (c << 6) | (*s++ - 0x80);
if (c & (1U << 31)) {
if (*s - 0x80u >= 0x40) {
s -= 2;
break;
}
c = (c << 6) | (*s++ - 0x80);
if (c & (1U << 31)) {
if (*s - 0x80u >= 0x40) {
s -= 3;
break;
}
c = (c << 6) | (*s++ - 0x80);
}
}
*ws++ = c;
wn--;
c = 0;
}
if (!c && !*s) {
if (ws) {
*ws = 0;
*src = 0;
}
return wn0 - wn;
}
errno = EILSEQ;
if (ws)
*src = (const void *)s;
return -1;
}

View file

@ -1,23 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
size_t mbstowcs(wchar_t *pwc, const char *s, size_t wn) {
return mbsrtowcs(pwc, (void *)&s, wn, 0);
}

View file

@ -1,25 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/locale.h"
#include "libc/sysv/errfuns.h"
locale_t newlocale(int catmask, const char *locale, locale_t base) {
// TODO: implement me
return 0;
}

View file

@ -1,43 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/safemacros.h"
#include "libc/intrin/strace.h"
#include "libc/str/locale.h"
#include "libc/str/str.h"
/**
* Sets program locale.
*
* Cosmopolitan only supports the C or POSIX locale with UTF-8.
*/
char *setlocale(int category, const char *locale) {
char *res;
if (!locale || (*locale == '\0')) {
res = "C";
} else if (!strcmp(locale, "C") || //
!strcmp(locale, "POSIX") || //
!strcmp(locale, "C.UTF-8") || //
!strcmp(locale, "en_US.UTF-8")) {
res = (char *)locale;
} else {
res = NULL;
}
STRACE("setlocale(%d, %#s) → %s", category, locale, res);
return res;
}

View file

@ -27,10 +27,7 @@ COSMOPOLITAN_C_START_
void *memset(void *, int, size_t) memcpyesque;
void *memmove(void *, const void *, size_t) memcpyesque;
void *memcpy(void *, const void *, size_t) memcpyesque;
void *mempcpy(void *, const void *, size_t) memcpyesque;
char *hexpcpy(char *, const void *, size_t) memcpyesque;
void *memccpy(void *, const void *, int, size_t) memcpyesque;
void explicit_bzero(void *, size_t);
int memcmp(const void *, const void *, size_t) strlenesque;
int timingsafe_bcmp(const void *, const void *, size_t) libcesque;
@ -41,7 +38,6 @@ size_t strnlen(const char *, size_t) strlenesque;
size_t strnlen_s(const char *, size_t) libcesque;
char *strchr(const char *, int) strlenesque;
void *memchr(const void *, int, size_t) strlenesque;
char *strchrnul(const char *, int) strlenesque returnsnonnull;
void *rawmemchr(const void *, int) strlenesque returnsnonnull;
size_t wcslen(const wchar_t *) strlenesque;
size_t wcsnlen(const wchar_t *, size_t) strlenesque;
@ -51,7 +47,6 @@ wchar_t *wmemchr(const wchar_t *, wchar_t, size_t) strlenesque;
wchar_t *wcschrnul(const wchar_t *, wchar_t)
strlenesque returnsnonnull;
char *strstr(const char *, const char *) strlenesque;
char *strcasestr(const char *, const char *) strlenesque;
wchar_t *wcsstr(const wchar_t *, const wchar_t *) strlenesque;
int strcmp(const char *, const char *) strlenesque;
int strncmp(const char *, const char *, size_t) strlenesque;
@ -59,14 +54,11 @@ int wcscmp(const wchar_t *, const wchar_t *) strlenesque;
int wcsncmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
int wmemcmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
int strcasecmp(const char *, const char *) strlenesque;
int memcasecmp(const void *, const void *, size_t) strlenesque;
int wcscasecmp(const wchar_t *, const wchar_t *) strlenesque;
int strncasecmp(const char *, const char *, size_t) strlenesque;
int wcsncasecmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
char *strrchr(const char *, int) strlenesque;
void *memrchr(const void *, int, size_t) strlenesque;
wchar_t *wcsrchr(const wchar_t *, wchar_t) strlenesque;
void *wmemrchr(const wchar_t *, wchar_t, size_t) strlenesque;
char *strpbrk(const char *, const char *) strlenesque;
wchar_t *wcspbrk(const wchar_t *, const wchar_t *) strlenesque;
size_t strspn(const char *, const char *) strlenesque;
@ -75,13 +67,10 @@ size_t strcspn(const char *, const char *) strlenesque;
size_t wcscspn(const wchar_t *, const wchar_t *) strlenesque;
void *memfrob(void *, size_t) memcpyesque;
int strcoll(const char *, const char *) strlenesque;
char *strsep(char **, const char *) libcesque paramsnonnull();
char *stpcpy(char *, const char *) memcpyesque;
char *stpncpy(char *, const char *, size_t) memcpyesque;
char *strcat(char *, const char *) memcpyesque;
wchar_t *wcscat(wchar_t *, const wchar_t *) memcpyesque;
size_t strlcpy(char *, const char *, size_t) libcesque;
size_t strlcat(char *, const char *, size_t) libcesque;
size_t strxfrm(char *, const char *, size_t) libcesque;
char *strcpy(char *, const char *) memcpyesque;
wchar_t *wcscpy(wchar_t *, const wchar_t *) memcpyesque;
@ -91,13 +80,9 @@ char *strncpy(char *, const char *, size_t) memcpyesque;
char *strtok(char *, const char *) paramsnonnull((2)) libcesque;
char *strtok_r(char *, const char *, char **) paramsnonnull((2, 3));
wchar_t *wcstok(wchar_t *, const wchar_t *, wchar_t **) paramsnonnull((2, 3));
int strverscmp(const char *, const char *) libcesque;
wchar_t *wmemset(wchar_t *, wchar_t, size_t) memcpyesque;
wchar_t *wmemcpy(wchar_t *, const wchar_t *, size_t) memcpyesque;
wchar_t *wmempcpy(wchar_t *, const wchar_t *, size_t) memcpyesque;
wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t) memcpyesque;
void *memmem(const void *, size_t, const void *, size_t)
libcesque nosideeffect;
ssize_t strfmon(char *, size_t, const char *, ...) libcesque;
long a64l(const char *) libcesque;
char *l64a(long) libcesque;
@ -131,6 +116,33 @@ char *strerror(int) returnsnonnull dontthrow dontcallback;
errno_t strerror_r(int, char *, size_t) libcesque;
char *__xpg_strerror_r(int, char *, size_t) libcesque;
int bcmp(const void *, const void *, size_t) strlenesque;
void bcopy(const void *, void *, size_t) memcpyesque;
void bzero(void *, size_t) memcpyesque;
char *index(const char *, int) strlenesque;
char *rindex(const char *, int) strlenesque;
#if defined(_COSMO_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || \
defined(_XOPEN_SOURCE)
void *memccpy(void *, const void *, int, size_t) memcpyesque;
#endif
#if defined(_COSMO_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
char *strsep(char **, const char *) libcesque paramsnonnull();
void explicit_bzero(void *, size_t);
size_t strlcpy(char *, const char *, size_t) libcesque;
size_t strlcat(char *, const char *, size_t) libcesque;
#endif
#if defined(_COSMO_SOURCE) || defined(_GNU_SOURCE)
int strverscmp(const char *, const char *) libcesque;
char *strchrnul(const char *, int) strlenesque returnsnonnull;
char *strcasestr(const char *, const char *) strlenesque;
void *memmem(const void *, size_t, const void *, size_t) libcesque;
void *memrchr(const void *, int, size_t) strlenesque;
void *mempcpy(void *, const void *, size_t) memcpyesque;
#endif
#ifdef _COSMO_SOURCE
pureconst uint64_t tpenc(uint32_t) libcesque;
char *chomp(char *) libcesque;
@ -141,6 +153,7 @@ bool32 startswithi(const char *, const char *) strlenesque;
bool32 endswith(const char *, const char *) strlenesque;
bool32 istext(const void *, size_t) libcesque;
bool32 isutf8(const void *, size_t) libcesque;
void *wmemrchr(const wchar_t *, wchar_t, size_t) strlenesque;
const char *strsignal_r(int, char[21]) returnsnonnull libcesque __wur;
char16_t *chomp16(char16_t *) libcesque;
size_t strlen16(const char16_t *) strlenesque;
@ -150,6 +163,7 @@ void *memchr16(const void *, int, size_t) strlenesque;
char16_t *strchrnul16(const char16_t *, int) strlenesque returnsnonnull;
void *rawmemchr16(const void *, int) strlenesque returnsnonnull;
char16_t *strstr16(const char16_t *, const char16_t *) strlenesque;
int memcasecmp(const void *, const void *, size_t) strlenesque;
int strcmp16(const char16_t *, const char16_t *) strlenesque;
int strncmp16(const char16_t *, const char16_t *, size_t) strlenesque;
int strcasecmp16(const char16_t *, const char16_t *) strlenesque;
@ -171,14 +185,9 @@ bool32 wcsstartswith(const wchar_t *, const wchar_t *) strlenesque;
bool32 wcsendswith(const wchar_t *, const wchar_t *) strlenesque;
char *__join_paths(char *, size_t, const char *, const char *) libcesque __wur;
int __mkntpathat(int, const char *, int, char16_t[hasatleast 1024]);
wchar_t *wmempcpy(wchar_t *, const wchar_t *, size_t) memcpyesque;
#endif /* _COSMO_SOURCE */
int bcmp(const void *, const void *, size_t) strlenesque;
void bcopy(const void *, void *, size_t) memcpyesque;
void bzero(void *, size_t) memcpyesque;
char *index(const char *, int) strlenesque;
char *rindex(const char *, int) strlenesque;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_STR_STR_H_ */

View file

@ -1,90 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/str/mb.internal.h"
#include "libc/str/str.h"
__static_yoink("musl_libc_notice");
size_t wcsrtombs(char *s, const wchar_t **ws, size_t n, mbstate_t *st) {
const wchar_t *ws2;
char buf[4];
size_t N = n, l;
if (!s) {
for (n = 0, ws2 = *ws; *ws2; ws2++) {
if (*ws2 >= 0x80u) {
l = wcrtomb(buf, *ws2, 0);
if (!(l + 1))
return -1;
n += l;
} else
n++;
}
return n;
}
while (n >= 4) {
if (**ws - 1u >= 0x7fu) {
if (!**ws) {
*s = 0;
*ws = 0;
return N - n;
}
l = wcrtomb(s, **ws, 0);
if (!(l + 1))
return -1;
s += l;
n -= l;
} else {
*s++ = **ws;
n--;
}
(*ws)++;
}
while (n) {
if (**ws - 1u >= 0x7fu) {
if (!**ws) {
*s = 0;
*ws = 0;
return N - n;
}
l = wcrtomb(buf, **ws, 0);
if (!(l + 1))
return -1;
if (l > n)
return N - n;
wcrtomb(s, **ws, 0);
s += l;
n -= l;
} else {
*s++ = **ws;
n--;
}
(*ws)++;
}
return N;
}

View file

@ -1,23 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
size_t wcstombs(char *s, const wchar_t *ws, size_t n) {
return wcsrtombs(s, &(const wchar_t *){ws}, n, 0);
}

View file

@ -1,26 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/limits.h"
#include "libc/str/str.h"
int wctomb(char *s, wchar_t wc) {
if (!s)
return 0;
return wcrtomb(s, wc, 0);
}

View file

@ -40,7 +40,6 @@ static char *_mktls_finish(struct CosmoTib **out_tib, char *mem,
tib->tib_ftrace = old->tib_ftrace;
tib->tib_strace = old->tib_strace;
tib->tib_sigmask = old->tib_sigmask;
tib->tib_locale = (intptr_t)&__c_dot_utf8_locale;
atomic_store_explicit(&tib->tib_tid, -1, memory_order_relaxed);
if (out_tib) {
*out_tib = tib;

View file

@ -69,6 +69,8 @@ enum PosixThreadStatus {
#define POSIXTHREAD_CONTAINER(e) DLL_CONTAINER(struct PosixThread, list, e)
typedef struct __locale_struct *locale_t;
struct PosixThread {
int pt_flags; // 0x00: see PT_* constants
atomic_int pt_canceled; // 0x04: thread has bad beliefs
@ -86,6 +88,7 @@ struct PosixThread {
uint64_t pt_blkmask;
int64_t pt_semaphore;
intptr_t pt_iohandle;
locale_t pt_locale;
void *pt_ioverlap;
jmp_buf pt_exiter;
pthread_attr_t pt_attr;

View file

@ -44,6 +44,7 @@
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/str/locale.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/clone.h"
@ -235,6 +236,7 @@ static errno_t pthread_create_impl(pthread_t *thread,
return EAGAIN;
}
dll_init(&pt->list);
pt->pt_locale = &__global_locale;
pt->pt_start = start_routine;
pt->pt_arg = arg;

View file

@ -23,7 +23,7 @@ struct CosmoTib {
struct CosmoTib *tib_self; /* 0x00 */
struct CosmoFtrace tib_ftracer; /* 0x08 */
void *tib_garbages; /* 0x18 */
intptr_t tib_locale; /* 0x20 */
intptr_t __unused; /* 0x20 */
intptr_t tib_pthread; /* 0x28 */
struct CosmoTib *tib_self2; /* 0x30 */
_Atomic(int32_t) tib_tid; /* 0x38 transitions -1 → tid → 0 */

View file

@ -33,11 +33,14 @@ LIBC_X_A_DIRECTDEPS = \
LIBC_PROC \
LIBC_RUNTIME \
LIBC_NT_KERNEL32 \
LIBC_NT_ADVAPI32 \
LIBC_STDIO \
LIBC_SOCK \
LIBC_STR \
LIBC_SYSV \
THIRD_PARTY_GDTOA \
THIRD_PARTY_MUSL
THIRD_PARTY_MUSL \
THIRD_PARTY_TZ \
LIBC_X_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_X_A_DIRECTDEPS),$($(x))))

View file

@ -36,7 +36,6 @@ TEST_LIBC_STR_DIRECTDEPS = \
LIBC_FMT \
LIBC_INTRIN \
LIBC_LOG \
LIBC_TINYMATH \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
@ -45,14 +44,16 @@ TEST_LIBC_STR_DIRECTDEPS = \
LIBC_SYSV \
LIBC_SYSV_CALLS \
LIBC_TESTLIB \
LIBC_TINYMATH \
LIBC_X \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_REGEX \
THIRD_PARTY_ZLIB \
THIRD_PARTY_LIBCXX \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_MUSL \
THIRD_PARTY_REGEX \
THIRD_PARTY_SMALLZ4 \
THIRD_PARTY_VQSORT
THIRD_PARTY_VQSORT \
THIRD_PARTY_ZLIB \
TEST_LIBC_STR_DEPS := \
$(call uniq,$(foreach x,$(TEST_LIBC_STR_DIRECTDEPS),$($(x))))

View file

@ -19,10 +19,15 @@
#include "third_party/regex/regex.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/str/locale.h"
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
void SetUpOnce(void) {
setlocale(LC_ALL, "C.UTF-8");
}
TEST(regex, test) {
regex_t rx;
EXPECT_EQ(REG_OK, regcomp(&rx, "^[A-Za-z\x7f-\uffff]{2}$", REG_EXTENDED));

View file

@ -1,30 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Gavin Arthur Hayes
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/locale.h"
#include "libc/testlib/testlib.h"
TEST(setlocale, test) {
EXPECT_STREQ("C", setlocale(LC_ALL, NULL));
EXPECT_STREQ("C", setlocale(LC_ALL, "C"));
EXPECT_STREQ("C", setlocale(LC_ALL, NULL));
EXPECT_STREQ("POSIX", setlocale(LC_ALL, "POSIX"));
EXPECT_STREQ("C", setlocale(LC_ALL, ""));
EXPECT_EQ(0, setlocale(LC_ALL, "ja_JP.PCK"));
EXPECT_STREQ("C", setlocale(LC_ALL, NULL));
}

View file

@ -28,7 +28,8 @@ TEST_LIBC_TIME_DIRECTDEPS = \
LIBC_SYSV \
LIBC_TESTLIB \
LIBC_X \
THIRD_PARTY_TZ
THIRD_PARTY_MUSL \
THIRD_PARTY_TZ \
TEST_LIBC_TIME_DEPS := \
$(call uniq,$(foreach x,$(TEST_LIBC_TIME_DIRECTDEPS),$($(x))))

View file

@ -8,15 +8,16 @@ TEST_LIBC_TINYMATH_SRCS_CC := $(wildcard test/libc/tinymath/*.cc)
TEST_LIBC_TINYMATH_SRCS_TEST = $(filter %_test.c,$(TEST_LIBC_TINYMATH_SRCS))
TEST_LIBC_TINYMATH_SRCS = \
$(TEST_LIBC_TINYMATH_SRCS_C:%.c=o/$(MODE)/%.o) \
$(TEST_LIBC_TINYMATH_SRCS_CC:%.cc=o/$(MODE)/%.o)
$(TEST_LIBC_TINYMATH_SRCS_C) \
$(TEST_LIBC_TINYMATH_SRCS_CC)
TEST_LIBC_TINYMATH_OBJS = \
$(TEST_LIBC_TINYMATH_SRCS_C:%.c=o/$(MODE)/%.o) \
$(TEST_LIBC_TINYMATH_SRCS_CC:%.cc=o/$(MODE)/%.o)
TEST_LIBC_TINYMATH_COMS = \
$(TEST_LIBC_TINYMATH_SRCS:%.c=o/$(MODE)/%)
$(TEST_LIBC_TINYMATH_SRCS_C:%.c=o/$(MODE)/%) \
$(TEST_LIBC_TINYMATH_SRCS_CC:%.cc=o/$(MODE)/%)
TEST_LIBC_TINYMATH_BINS = \
$(TEST_LIBC_TINYMATH_COMS) \
@ -68,10 +69,6 @@ $(TEST_LIBC_TINYMATH_OBJS): private \
CFLAGS += \
-fno-builtin
$(TEST_LIBC_TINYMATH_OBJS): private \
CXXFLAGS += \
#-ffast-math
.PHONY: o/$(MODE)/test/libc/tinymath
o/$(MODE)/test/libc/tinymath: \
$(TEST_LIBC_TINYMATH_BINS) \

View file

@ -35,7 +35,8 @@ TEST_POSIX_DIRECTDEPS = \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
LIBC_THREAD
LIBC_THREAD \
THIRD_PARTY_MUSL \
TEST_POSIX_DEPS := \
$(call uniq,$(foreach x,$(TEST_POSIX_DIRECTDEPS),$($(x))))

View file

@ -0,0 +1,173 @@
#include <errno.h>
#include <iconv.h>
#include <stdlib.h>
#include <string.h>
#include <uchar.h>
#define INBUF_SIZE 1024
#define OUTBUF_SIZE 2048
int g_count;
int check_conversion(const char* input, size_t input_len,
const char16_t* expected_output, size_t expected_len) {
iconv_t cd;
char inbuf[INBUF_SIZE];
char outbuf[OUTBUF_SIZE];
char* inptr = inbuf;
char* outptr = outbuf;
size_t inbytesleft = input_len;
size_t outbytesleft = OUTBUF_SIZE;
size_t result;
++g_count;
memcpy(inbuf, input, input_len);
cd = iconv_open("UTF-16LE", "UTF-8");
if (cd == (iconv_t)-1) {
return 10 + g_count; // iconv_open failed
}
result = iconv(cd, &inptr, &inbytesleft, &outptr, &outbytesleft);
if (result == (size_t)-1) {
iconv_close(cd);
return 20 + g_count; // iconv failed, return 20 + specific errno
}
if (inbytesleft != 0) {
iconv_close(cd);
return 40 + g_count; // Not all input was converted
}
size_t output_len = OUTBUF_SIZE - outbytesleft;
if (output_len != expected_len) {
iconv_close(cd);
return 50 + g_count; // Output length mismatch
}
if (memcmp(outbuf, expected_output, output_len) != 0) {
iconv_close(cd);
return 60 + g_count; // Output content mismatch
}
if (iconv_close(cd) == -1)
return 70 + g_count; // iconv_close failed
// Reverse direction check: UTF-16LE back to UTF-8
cd = iconv_open("UTF-8", "UTF-16LE");
if (cd == (iconv_t)-1) {
return 80 + g_count; // iconv_open failed for reverse direction
}
char reverse_inbuf[OUTBUF_SIZE];
char reverse_outbuf[INBUF_SIZE];
char* reverse_inptr = reverse_inbuf;
char* reverse_outptr = reverse_outbuf;
size_t reverse_inbytesleft = output_len;
size_t reverse_outbytesleft = INBUF_SIZE;
memcpy(reverse_inbuf, outbuf, output_len);
result = iconv(cd, &reverse_inptr, &reverse_inbytesleft, &reverse_outptr,
&reverse_outbytesleft);
if (result == (size_t)-1) {
iconv_close(cd);
return 90 + g_count; // iconv failed for reverse direction
}
if (reverse_inbytesleft != 0) {
iconv_close(cd);
return 100 + g_count; // Not all input was converted in reverse direction
}
size_t reverse_output_len = INBUF_SIZE - reverse_outbytesleft;
if (reverse_output_len != input_len) {
iconv_close(cd);
return 110 + g_count; // Reverse output length mismatch
}
if (memcmp(reverse_outbuf, input, input_len) != 0) {
iconv_close(cd);
return 120 + g_count; // Reverse output content mismatch
}
if (iconv_close(cd) == -1)
return 130 + g_count; // iconv_close failed for reverse direction
return 0; // Success
}
int main() {
// Test case 1: Basic ASCII
const char input1[] = "Hello, world!";
const char16_t expected1[] = u"Hello, world!";
int result = check_conversion(input1, sizeof(input1) - 1, expected1,
sizeof(expected1) - 2);
if (result != 0)
return result;
// Test case 2: Non-ASCII characters and newline
const char input2[] = "こんにちは\nWorld! ☺";
const char16_t expected2[] = u"こんにちは\nWorld! ☺";
result = check_conversion(input2, sizeof(input2) - 1, expected2,
sizeof(expected2) - 2);
if (result != 0)
return result;
// Test case 3: Empty string
const char input3[] = "";
const char16_t expected3[] = u"";
result = check_conversion(input3, 0, expected3, 0);
if (result != 0)
return result;
// Test case 4: String with null characters
const char input4[] = "Hello\0World";
const char16_t expected4[] = u"Hello\0World";
result = check_conversion(input4, sizeof(input4) - 1, expected4,
sizeof(expected4) - 2);
if (result != 0)
return result;
// Test case 5: Long string to test buffer handling
char input5[INBUF_SIZE];
char16_t expected5[INBUF_SIZE];
memset(input5, 'A', INBUF_SIZE - 1);
input5[INBUF_SIZE - 1] = '\0';
for (int i = 0; i < INBUF_SIZE - 1; i++) {
expected5[i] = u'A';
}
result =
check_conversion(input5, INBUF_SIZE - 1, expected5, (INBUF_SIZE - 1) * 2);
if (result != 0)
return result;
// Test case 6: Invalid UTF-8 sequence
const char input6[] = {0xC0, 0x80};
result = check_conversion(input6, sizeof(input6), NULL, 0);
if (result != 26) {
if (errno != EILSEQ)
return 201;
return 200;
}
// Test case 7: Mixing ASCII and non-ASCII
const char input7[] = "Hello, 世界!";
const char16_t expected7[] = u"Hello, 世界!";
result = check_conversion(input7, sizeof(input7) - 1, expected7,
sizeof(expected7) - 2);
if (result != 0)
return result;
// Test case 8: Surrogate pairs
const char input8[] = "𐐷"; // U+10437
const char16_t expected8[] =
u"𐐷"; // This will be encoded as a surrogate pair
result = check_conversion(input8, sizeof(input8) - 1, expected8,
sizeof(expected8) - 2);
if (result != 0)
return result;
return 0; // All tests passed
}

View file

@ -0,0 +1,172 @@
#include <errno.h>
#include <iconv.h>
#include <stdlib.h>
#include <string.h>
#include <uchar.h>
#define INBUF_SIZE 1024
#define OUTBUF_SIZE 4096
int g_count;
int check_conversion(const char* input, size_t input_len,
const wchar_t* expected_output, size_t expected_len) {
iconv_t cd;
char inbuf[INBUF_SIZE];
char outbuf[OUTBUF_SIZE];
char* inptr = inbuf;
char* outptr = outbuf;
size_t inbytesleft = input_len;
size_t outbytesleft = OUTBUF_SIZE;
size_t result;
++g_count;
memcpy(inbuf, input, input_len);
cd = iconv_open("UTF-32LE", "UTF-8");
if (cd == (iconv_t)-1) {
return 10 + g_count; // iconv_open failed
}
result = iconv(cd, &inptr, &inbytesleft, &outptr, &outbytesleft);
if (result == (size_t)-1) {
iconv_close(cd);
return 20 + g_count; // iconv failed, return 20 + specific errno
}
if (inbytesleft != 0) {
iconv_close(cd);
return 40 + g_count; // Not all input was converted
}
size_t output_len = OUTBUF_SIZE - outbytesleft;
if (output_len != expected_len) {
iconv_close(cd);
return 50 + g_count; // Output length mismatch
}
if (memcmp(outbuf, expected_output, output_len) != 0) {
iconv_close(cd);
return 60 + g_count; // Output content mismatch
}
if (iconv_close(cd) == -1)
return 70 + g_count; // iconv_close failed
// Reverse direction check: UTF-32LE back to UTF-8
cd = iconv_open("UTF-8", "UTF-32LE");
if (cd == (iconv_t)-1) {
return 80 + g_count; // iconv_open failed for reverse direction
}
char reverse_inbuf[OUTBUF_SIZE];
char reverse_outbuf[INBUF_SIZE];
char* reverse_inptr = reverse_inbuf;
char* reverse_outptr = reverse_outbuf;
size_t reverse_inbytesleft = output_len;
size_t reverse_outbytesleft = INBUF_SIZE;
memcpy(reverse_inbuf, outbuf, output_len);
result = iconv(cd, &reverse_inptr, &reverse_inbytesleft, &reverse_outptr,
&reverse_outbytesleft);
if (result == (size_t)-1) {
iconv_close(cd);
return 90 + g_count; // iconv failed for reverse direction
}
if (reverse_inbytesleft != 0) {
iconv_close(cd);
return 100 + g_count; // Not all input was converted in reverse direction
}
size_t reverse_output_len = INBUF_SIZE - reverse_outbytesleft;
if (reverse_output_len != input_len) {
iconv_close(cd);
return 110 + g_count; // Reverse output length mismatch
}
if (memcmp(reverse_outbuf, input, input_len) != 0) {
iconv_close(cd);
return 120 + g_count; // Reverse output content mismatch
}
if (iconv_close(cd) == -1)
return 130 + g_count; // iconv_close failed for reverse direction
return 0; // Success
}
int main() {
// Test case 1: Basic ASCII
const char input1[] = "Hello, world!";
const wchar_t expected1[] = L"Hello, world!";
int result = check_conversion(input1, sizeof(input1) - 1, expected1,
sizeof(expected1) - 4);
if (result != 0)
return result;
// Test case 2: Non-ASCII characters and newline
const char input2[] = "こんにちは\nWorld! ☺";
const wchar_t expected2[] = L"こんにちは\nWorld! ☺";
result = check_conversion(input2, sizeof(input2) - 1, expected2,
sizeof(expected2) - 4);
if (result != 0)
return result;
// Test case 3: Empty string
const char input3[] = "";
const wchar_t expected3[] = L"";
result = check_conversion(input3, 0, expected3, 0);
if (result != 0)
return result;
// Test case 4: String with null characters
const char input4[] = "Hello\0World";
const wchar_t expected4[] = L"Hello\0World";
result = check_conversion(input4, sizeof(input4) - 1, expected4,
sizeof(expected4) - 4);
if (result != 0)
return result;
// Test case 5: Long string to test buffer handling
char input5[INBUF_SIZE];
wchar_t expected5[INBUF_SIZE];
memset(input5, 'A', INBUF_SIZE - 1);
input5[INBUF_SIZE - 1] = '\0';
for (int i = 0; i < INBUF_SIZE - 1; i++) {
expected5[i] = u'A';
}
result =
check_conversion(input5, INBUF_SIZE - 1, expected5, (INBUF_SIZE - 1) * 4);
if (result != 0)
return result;
// Test case 6: Invalid UTF-8 sequence
const char input6[] = {0xC0, 0x80};
result = check_conversion(input6, sizeof(input6), NULL, 0);
if (result != 26) {
if (errno != EILSEQ)
return 201;
return 200;
}
// Test case 7: Mixing ASCII and non-ASCII
const char input7[] = "Hello, 世界!";
const wchar_t expected7[] = L"Hello, 世界!";
result = check_conversion(input7, sizeof(input7) - 1, expected7,
sizeof(expected7) - 4);
if (result != 0)
return result;
// Test case 8: Surrogate pairs
const char input8[] = "𐐷"; // U+10437
const wchar_t expected8[] = L"𐐷"; // This will be encoded as a surrogate pair
result = check_conversion(input8, sizeof(input8) - 1, expected8,
sizeof(expected8) - 4);
if (result != 0)
return result;
return 0; // All tests passed
}

View file

@ -25,7 +25,8 @@ THIRD_PARTY_AWK_A_DIRECTDEPS = \
LIBC_SYSV \
LIBC_TINYMATH \
TOOL_ARGS \
THIRD_PARTY_GDTOA
THIRD_PARTY_GDTOA \
THIRD_PARTY_MUSL \
THIRD_PARTY_AWK_A_DEPS := \
$(call uniq,$(foreach x,$(THIRD_PARTY_AWK_A_DIRECTDEPS),$($(x))))

View file

@ -63,6 +63,7 @@ THIRD_PARTY_CHIBICC_A_DIRECTDEPS = \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_GDTOA \
THIRD_PARTY_MUSL \
THIRD_PARTY_TZ \
TOOL_BUILD_LIB

View file

@ -27,8 +27,9 @@ THIRD_PARTY_LESS_DIRECTDEPS = \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \
THIRD_PARTY_MUSL \
THIRD_PARTY_NCURSES \
THIRD_PARTY_PCRE
THIRD_PARTY_PCRE \
THIRD_PARTY_LESS_DEPS := \
$(call uniq,$(foreach x,$(THIRD_PARTY_LESS_DIRECTDEPS),$($(x))))

View file

@ -139,7 +139,8 @@ THIRD_PARTY_LUA_A_DIRECTDEPS = \
THIRD_PARTY_DOUBLECONVERSION \
THIRD_PARTY_GDTOA \
THIRD_PARTY_LINENOISE \
THIRD_PARTY_TZ
THIRD_PARTY_MUSL \
THIRD_PARTY_TZ \
THIRD_PARTY_LUA_A_DEPS := \
$(call uniq,$(foreach x,$(THIRD_PARTY_LUA_A_DIRECTDEPS),$($(x))))

View file

@ -30,7 +30,8 @@ THIRD_PARTY_MUSL_A_DIRECTDEPS = \
LIBC_STR \
LIBC_SYSV \
LIBC_THREAD \
THIRD_PARTY_ZLIB
THIRD_PARTY_TZ \
THIRD_PARTY_ZLIB \
THIRD_PARTY_MUSL_A_DEPS := \
$(call uniq,$(foreach x,$(THIRD_PARTY_MUSL_A_DIRECTDEPS),$($(x))))

72
third_party/musl/__mo_lookup.c vendored Normal file
View file

@ -0,0 +1,72 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/str/str.h"
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
#pragma GCC diagnostic ignored "-Wparentheses"
static inline uint32_t swapc(uint32_t x, int c)
{
return c ? x>>24 | x>>8&0xff00 | x<<8&0xff0000 | x<<24 : x;
}
const char *__mo_lookup(const void *p, size_t size, const char *s)
{
const uint32_t *mo = p;
int sw = *mo - 0x950412de;
uint32_t b = 0, n = swapc(mo[2], sw);
uint32_t o = swapc(mo[3], sw);
uint32_t t = swapc(mo[4], sw);
if (n>=size/4 || o>=size-4*n || t>=size-4*n || ((o|t)%4))
return 0;
o/=4;
t/=4;
for (;;) {
uint32_t ol = swapc(mo[o+2*(b+n/2)], sw);
uint32_t os = swapc(mo[o+2*(b+n/2)+1], sw);
if (os >= size || ol >= size-os || ((char *)p)[os+ol])
return 0;
int sign = strcmp(s, (char *)p + os);
if (!sign) {
uint32_t tl = swapc(mo[t+2*(b+n/2)], sw);
uint32_t ts = swapc(mo[t+2*(b+n/2)+1], sw);
if (ts >= size || tl >= size-ts || ((char *)p)[ts+tl])
return 0;
return (char *)p + ts;
}
else if (n == 1) return 0;
else if (sign < 0)
n /= 2;
else {
b += n/2;
n -= n/2;
}
}
return 0;
}

10
third_party/musl/__month_to_secs.c vendored Normal file
View file

@ -0,0 +1,10 @@
int __month_to_secs(int month, int is_leap)
{
static const int secs_through_month[] = {
0, 31*86400, 59*86400, 90*86400,
120*86400, 151*86400, 181*86400, 212*86400,
243*86400, 273*86400, 304*86400, 334*86400 };
int t = secs_through_month[month];
if (is_leap && month >= 2) t+=86400;
return t;
}

82
third_party/musl/__secs_to_tm.c vendored Normal file
View file

@ -0,0 +1,82 @@
#include "time_impl.h"
#include <limits.h>
/* 2000-03-01 (mod 400 year, immediately after feb29 */
#define LEAPOCH (946684800LL + 86400*(31+29))
#define DAYS_PER_400Y (365*400 + 97)
#define DAYS_PER_100Y (365*100 + 24)
#define DAYS_PER_4Y (365*4 + 1)
int __secs_to_tm(long long t, struct tm *tm)
{
long long days, secs, years;
int remdays, remsecs, remyears;
int qc_cycles, c_cycles, q_cycles;
int months;
int wday, yday, leap;
static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29};
/* Reject time_t values whose year would overflow int */
if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL)
return -1;
secs = t - LEAPOCH;
days = secs / 86400;
remsecs = secs % 86400;
if (remsecs < 0) {
remsecs += 86400;
days--;
}
wday = (3+days)%7;
if (wday < 0) wday += 7;
qc_cycles = days / DAYS_PER_400Y;
remdays = days % DAYS_PER_400Y;
if (remdays < 0) {
remdays += DAYS_PER_400Y;
qc_cycles--;
}
c_cycles = remdays / DAYS_PER_100Y;
if (c_cycles == 4) c_cycles--;
remdays -= c_cycles * DAYS_PER_100Y;
q_cycles = remdays / DAYS_PER_4Y;
if (q_cycles == 25) q_cycles--;
remdays -= q_cycles * DAYS_PER_4Y;
remyears = remdays / 365;
if (remyears == 4) remyears--;
remdays -= remyears * 365;
leap = !remyears && (q_cycles || !c_cycles);
yday = remdays + 31 + 28 + leap;
if (yday >= 365+leap) yday -= 365+leap;
years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles;
for (months=0; days_in_month[months] <= remdays; months++)
remdays -= days_in_month[months];
if (months >= 10) {
months -= 12;
years++;
}
if (years+100 > INT_MAX || years+100 < INT_MIN)
return -1;
tm->tm_year = years + 100;
tm->tm_mon = months + 2;
tm->tm_mday = remdays + 1;
tm->tm_wday = wday;
tm->tm_yday = yday;
tm->tm_hour = remsecs / 3600;
tm->tm_min = remsecs / 60 % 60;
tm->tm_sec = remsecs % 60;
return 0;
}

24
third_party/musl/__tm_to_secs.c vendored Normal file
View file

@ -0,0 +1,24 @@
#include "time_impl.h"
long long __tm_to_secs(const struct tm *tm)
{
int is_leap;
long long year = tm->tm_year;
int month = tm->tm_mon;
if (month >= 12 || month < 0) {
int adj = month / 12;
month %= 12;
if (month < 0) {
adj--;
month += 12;
}
year += adj;
}
long long t = __year_to_secs(year, &is_leap);
t += __month_to_secs(month, is_leap);
t += 86400LL * (tm->tm_mday-1);
t += 3600LL * tm->tm_hour;
t += 60LL * tm->tm_min;
t += tm->tm_sec;
return t;
}

47
third_party/musl/__year_to_secs.c vendored Normal file
View file

@ -0,0 +1,47 @@
long long __year_to_secs(long long year, int *is_leap)
{
if (year-2ULL <= 136) {
int y = year;
int leaps = (y-68)>>2;
if (!((y-68)&3)) {
leaps--;
if (is_leap) *is_leap = 1;
} else if (is_leap) *is_leap = 0;
return 31536000*(y-70) + 86400*leaps;
}
int cycles, centuries, leaps, rem, dummy;
if (!is_leap) is_leap = &dummy;
cycles = (year-100) / 400;
rem = (year-100) % 400;
if (rem < 0) {
cycles--;
rem += 400;
}
if (!rem) {
*is_leap = 1;
centuries = 0;
leaps = 0;
} else {
if (rem >= 200) {
if (rem >= 300) centuries = 3, rem -= 300;
else centuries = 2, rem -= 200;
} else {
if (rem >= 100) centuries = 1, rem -= 100;
else centuries = 0;
}
if (!rem) {
*is_leap = 0;
leaps = 0;
} else {
leaps = rem / 4U;
rem %= 4U;
*is_leap = !rem;
}
}
leaps += 97*cycles + 24*centuries - *is_leap;
return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
}

10
third_party/musl/asctime.c vendored Normal file
View file

@ -0,0 +1,10 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
*/
#include "libc/time.h"
char *asctime(const struct tm *tm)
{
static char buf[26];
return asctime_r(tm, buf);
}

52
third_party/musl/asctime_r.c vendored Normal file
View file

@ -0,0 +1,52 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/stdio/stdio.h"
#include "libc/str/langinfo.h"
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
char *asctime_r(const struct tm *tm, char *buf)
{
if (snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
nl_langinfo_l(ABDAY_1+tm->tm_wday, C_LOCALE),
nl_langinfo_l(ABMON_1+tm->tm_mon, C_LOCALE),
tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec,
1900 + tm->tm_year) >= 26)
{
/* ISO C requires us to use the above format string,
* even if it will not fit in the buffer. Thus asctime_r
* is _supposed_ to crash if the fields in tm are too large.
* We follow this behavior and crash "gracefully" to warn
* application developers that they may not be so lucky
* on other implementations (e.g. stack smashing..).
*/
__builtin_trap();
}
return buf;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,13 +25,14 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/limits.h"
#include "libc/stdio/stdio.h"
#include "libc/str/mb.internal.h"
#include "libc/str/str.h"
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include "multibyte.h"
__static_yoink("musl_libc_notice");
wint_t btowc(int c) {
int b = (unsigned char)c;
return b < 128U ? b : (MB_CUR_MAX == 1 && c != EOF) ? CODEUNIT(c) : WEOF;
wint_t btowc(int c)
{
int b = (unsigned char)c;
return b<128U ? b : (MB_CUR_MAX==1 && c!=EOF) ? CODEUNIT(c) : WEOF;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,40 +25,41 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/str/mb.internal.h"
#include "libc/str/str.h"
#include <uchar.h>
#include <errno.h>
#include <wchar.h>
__static_yoink("musl_libc_notice");
size_t c16rtomb(char *restrict s, char16_t c16, mbstate_t *restrict ps) {
static unsigned internal_state;
if (!ps)
ps = (void *)&internal_state;
unsigned *x = (unsigned *)ps;
wchar_t wc;
if (!s) {
if (*x)
goto ilseq;
return 1;
}
if (!*x && c16 - 0xd800u < 0x400) {
*x = (c16 - 0xd7c0) << 10;
return 0;
}
if (*x) {
if (c16 - 0xdc00u >= 0x400)
goto ilseq;
else
wc = *x + c16 - 0xdc00;
*x = 0;
} else {
wc = c16;
}
return wcrtomb(s, wc, 0);
#pragma GCC diagnostic ignored "-Wparentheses"
size_t c16rtomb(char *restrict s, char16_t c16, mbstate_t *restrict ps)
{
static unsigned internal_state;
if (!ps) ps = (void *)&internal_state;
unsigned *x = (unsigned *)ps;
wchar_t wc;
if (!s) {
if (*x) goto ilseq;
return 1;
}
if (!*x && c16 - 0xd800u < 0x400) {
*x = c16 - 0xd7c0 << 10;
return 0;
}
if (*x) {
if (c16 - 0xdc00u >= 0x400) goto ilseq;
else wc = *x + c16 - 0xdc00;
*x = 0;
} else {
wc = c16;
}
return wcrtomb(s, wc, 0);
ilseq:
*x = 0;
errno = EILSEQ;
return -1;
*x = 0;
errno = EILSEQ;
return -1;
}

35
third_party/musl/c32rtomb.c vendored Normal file
View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <uchar.h>
#include <wchar.h>
__static_yoink("musl_libc_notice");
size_t c32rtomb(char *restrict s, char32_t c32, mbstate_t *restrict ps)
{
return wcrtomb(s, c32, ps);
}

View file

@ -30,6 +30,7 @@
#include <stdint.h>
#include <endian.h>
#include <sys/mman.h>
__static_yoink("musl_libc_notice");
#define V(p) be32toh(*(uint32_t *)(p))

View file

@ -31,6 +31,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
__static_yoink("musl_libc_notice");
#define V(p) be32toh(*(uint32_t *)(p))

View file

@ -35,6 +35,7 @@
#include <locale.h>
#include "third_party/musl/mapfile.internal.h"
#include <sys/mman.h>
__static_yoink("musl_libc_notice");
#define V(p) be32toh(*(uint32_t *)(p))

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,43 +25,21 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/str/mb.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/locale.internal.h"
#include "libc/str/str.h"
__static_yoink("musl_libc_notice");
size_t wcsnrtombs(char *dst, const wchar_t **wcs, size_t wn, size_t n,
mbstate_t *st) {
const wchar_t *ws = *wcs;
size_t cnt = 0;
if (!dst)
n = 0;
while (ws && wn) {
char tmp[MB_LEN_MAX] = {0};
size_t l = wcrtomb(n < MB_LEN_MAX ? tmp : dst, *ws, 0);
if (l == -1) {
cnt = -1;
break;
}
if (dst) {
if (n < MB_LEN_MAX) {
if (l > n)
break;
memcpy(dst, tmp, l);
}
dst += l;
n -= l;
}
if (!*ws) {
ws = 0;
break;
}
ws++;
wn--;
cnt += l;
}
if (dst)
*wcs = ws;
return cnt;
#define malloc _mapanon
#define calloc undef
#define realloc undef
#define free undef
locale_t duplocale(locale_t old)
{
locale_t new = malloc(sizeof *new);
if (!new) return 0;
if (old == LC_GLOBAL_LOCALE) old = &__global_locale;
*new = *old;
return new;
}

View file

@ -25,10 +25,12 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/limits.h"
#include "libc/str/str.h"
#include "libc/wctype.h"
#include "third_party/musl/fnmatch.h"
#include <string.h>
#include <fnmatch.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
/*
@ -46,284 +48,279 @@ __static_yoink("musl_libc_notice");
* - Rich Felker, April 2012
*/
#define END 0
#define END 0
#define UNMATCHABLE -2
#define BRACKET -3
#define QUESTION -4
#define STAR -5
#define BRACKET -3
#define QUESTION -4
#define STAR -5
static int FnmatchNextString(const char *str, size_t n, size_t *step) {
if (!n) {
*step = 0;
return 0;
}
if (str[0] >= 128U) {
wchar_t wc;
int k = mbtowc(&wc, str, n);
if (k < 0) {
*step = 1;
return -1;
}
*step = k;
return wc;
}
*step = 1;
return str[0];
static int str_next(const char *str, size_t n, size_t *step)
{
if (!n) {
*step = 0;
return 0;
}
if (str[0] >= 128U) {
wchar_t wc;
int k = mbtowc(&wc, str, n);
if (k<0) {
*step = 1;
return -1;
}
*step = k;
return wc;
}
*step = 1;
return str[0];
}
static int FnmatchNextPattern(const char *pat, size_t m, size_t *step,
int flags) {
int esc = 0;
if (!m || !*pat) {
*step = 0;
return END;
}
*step = 1;
if (pat[0] == '\\' && pat[1] && !(flags & FNM_NOESCAPE)) {
*step = 2;
pat++;
esc = 1;
goto escaped;
}
if (pat[0] == '[') {
size_t k = 1;
if (k < m)
if (pat[k] == '^' || pat[k] == '!') k++;
if (k < m)
if (pat[k] == ']') k++;
for (; k < m && pat[k] && pat[k] != ']'; k++) {
if (k + 1 < m && pat[k + 1] && pat[k] == '[' &&
(pat[k + 1] == ':' || pat[k + 1] == '.' || pat[k + 1] == '=')) {
int z = pat[k + 1];
k += 2;
if (k < m && pat[k]) k++;
while (k < m && pat[k] && (pat[k - 1] != z || pat[k] != ']')) k++;
if (k == m || !pat[k]) break;
}
}
if (k == m || !pat[k]) {
*step = 1;
return '[';
}
*step = k + 1;
return BRACKET;
}
if (pat[0] == '*') return STAR;
if (pat[0] == '?') return QUESTION;
static int pat_next(const char *pat, size_t m, size_t *step, int flags)
{
int esc = 0;
if (!m || !*pat) {
*step = 0;
return END;
}
*step = 1;
if (pat[0]=='\\' && pat[1] && !(flags & FNM_NOESCAPE)) {
*step = 2;
pat++;
esc = 1;
goto escaped;
}
if (pat[0]=='[') {
size_t k = 1;
if (k<m) if (pat[k] == '^' || pat[k] == '!') k++;
if (k<m) if (pat[k] == ']') k++;
for (; k<m && pat[k] && pat[k]!=']'; k++) {
if (k+1<m && pat[k+1] && pat[k]=='[' && (pat[k+1]==':' || pat[k+1]=='.' || pat[k+1]=='=')) {
int z = pat[k+1];
k+=2;
if (k<m && pat[k]) k++;
while (k<m && pat[k] && (pat[k-1]!=z || pat[k]!=']')) k++;
if (k==m || !pat[k]) break;
}
}
if (k==m || !pat[k]) {
*step = 1;
return '[';
}
*step = k+1;
return BRACKET;
}
if (pat[0] == '*')
return STAR;
if (pat[0] == '?')
return QUESTION;
escaped:
if (pat[0] >= 128U) {
wchar_t wc;
int k = mbtowc(&wc, pat, m);
if (k < 0) {
*step = 0;
return UNMATCHABLE;
}
*step = k + esc;
return wc;
}
return pat[0];
if (pat[0] >= 128U) {
wchar_t wc;
int k = mbtowc(&wc, pat, m);
if (k<0) {
*step = 0;
return UNMATCHABLE;
}
*step = k + esc;
return wc;
}
return pat[0];
}
static int FnmatchCaseFold(int k) {
int c = towupper(k);
return c == k ? towlower(k) : c;
static int casefold(int k)
{
int c = towupper(k);
return c == k ? towlower(k) : c;
}
static int FnmatchBracket(const char *p, int k, int kfold) {
wchar_t wc;
int inv = 0;
p++;
if (*p == '^' || *p == '!') {
inv = 1;
p++;
}
if (*p == ']') {
if (k == ']') return !inv;
p++;
} else if (*p == '-') {
if (k == '-') return !inv;
p++;
}
wc = p[-1];
for (; *p != ']'; p++) {
if (p[0] == '-' && p[1] != ']') {
wchar_t wc2;
int l = mbtowc(&wc2, p + 1, 4);
if (l < 0) return 0;
if (wc <= wc2)
if ((unsigned)k - wc <= wc2 - wc || (unsigned)kfold - wc <= wc2 - wc)
return !inv;
p += l - 1;
continue;
}
if (p[0] == '[' && (p[1] == ':' || p[1] == '.' || p[1] == '=')) {
const char *p0 = p + 2;
int z = p[1];
p += 3;
while (p[-1] != z || p[0] != ']') p++;
if (z == ':' && p - 1 - p0 < 16) {
char buf[16];
memcpy(buf, p0, p - 1 - p0);
buf[p - 1 - p0] = 0;
if (iswctype(k, wctype(buf)) || iswctype(kfold, wctype(buf)))
return !inv;
}
continue;
}
if (*p < 128U) {
wc = (unsigned char)*p;
} else {
int l = mbtowc(&wc, p, 4);
if (l < 0) return 0;
p += l - 1;
}
if (wc == k || wc == kfold) return !inv;
}
return inv;
static int match_bracket(const char *p, int k, int kfold)
{
wchar_t wc;
int inv = 0;
p++;
if (*p=='^' || *p=='!') {
inv = 1;
p++;
}
if (*p==']') {
if (k==']') return !inv;
p++;
} else if (*p=='-') {
if (k=='-') return !inv;
p++;
}
wc = p[-1];
for (; *p != ']'; p++) {
if (p[0]=='-' && p[1]!=']') {
wchar_t wc2;
int l = mbtowc(&wc2, p+1, 4);
if (l < 0) return 0;
if (wc <= wc2)
if ((unsigned)k-wc <= wc2-wc ||
(unsigned)kfold-wc <= wc2-wc)
return !inv;
p += l-1;
continue;
}
if (p[0]=='[' && (p[1]==':' || p[1]=='.' || p[1]=='=')) {
const char *p0 = p+2;
int z = p[1];
p+=3;
while (p[-1]!=z || p[0]!=']') p++;
if (z == ':' && p-1-p0 < 16) {
char buf[16];
memcpy(buf, p0, p-1-p0);
buf[p-1-p0] = 0;
if (iswctype(k, wctype(buf)) ||
iswctype(kfold, wctype(buf)))
return !inv;
}
continue;
}
if (*p < 128U) {
wc = (unsigned char)*p;
} else {
int l = mbtowc(&wc, p, 4);
if (l < 0) return 0;
p += l-1;
}
if (wc==k || wc==kfold) return !inv;
}
return inv;
}
static int FnmatchPerform(const char *pat, size_t m, const char *str, size_t n,
int flags) {
const char *p, *ptail, *endpat;
const char *s, *stail, *endstr;
size_t pinc, sinc, tailcnt = 0;
int c, k, kfold;
static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n, int flags)
{
const char *p, *ptail, *endpat;
const char *s, *stail, *endstr;
size_t pinc, sinc, tailcnt=0;
int c, k, kfold;
if (flags & FNM_PERIOD) {
if (*str == '.' && *pat != '.') {
return FNM_NOMATCH;
}
}
if (flags & FNM_PERIOD) {
if (*str == '.' && *pat != '.')
return FNM_NOMATCH;
}
for (;;) {
switch ((c = pat_next(pat, m, &pinc, flags))) {
case UNMATCHABLE:
return FNM_NOMATCH;
case STAR:
pat++;
m--;
break;
default:
k = str_next(str, n, &sinc);
if (k <= 0)
return (c==END) ? 0 : FNM_NOMATCH;
str += sinc;
n -= sinc;
kfold = flags & FNM_CASEFOLD ? casefold(k) : k;
if (c == BRACKET) {
if (!match_bracket(pat, k, kfold))
return FNM_NOMATCH;
} else if (c != QUESTION && k != c && kfold != c) {
return FNM_NOMATCH;
}
pat+=pinc;
m-=pinc;
continue;
}
break;
}
for (;;) {
switch ((c = FnmatchNextPattern(pat, m, &pinc, flags))) {
case UNMATCHABLE:
return FNM_NOMATCH;
case STAR:
pat++;
m--;
break;
default:
k = FnmatchNextString(str, n, &sinc);
if (k <= 0) return (c == END) ? 0 : FNM_NOMATCH;
str += sinc;
n -= sinc;
kfold = flags & FNM_CASEFOLD ? FnmatchCaseFold(k) : k;
if (c == BRACKET) {
if (!FnmatchBracket(pat, k, kfold)) return FNM_NOMATCH;
} else if (c != QUESTION && k != c && kfold != c) {
return FNM_NOMATCH;
}
pat += pinc;
m -= pinc;
continue;
}
break;
}
/* Compute real pat length if it was initially unknown/-1 */
m = strnlen(pat, m);
endpat = pat + m;
/* Compute real pat length if it was initially unknown/-1 */
m = strnlen(pat, m);
endpat = pat + m;
/* Find the last * in pat and count chars needed after it */
for (p=ptail=pat; p<endpat; p+=pinc) {
switch (pat_next(p, endpat-p, &pinc, flags)) {
case UNMATCHABLE:
return FNM_NOMATCH;
case STAR:
tailcnt=0;
ptail = p+1;
break;
default:
tailcnt++;
break;
}
}
/* Find the last * in pat and count chars needed after it */
for (p = ptail = pat; p < endpat; p += pinc) {
switch (FnmatchNextPattern(p, endpat - p, &pinc, flags)) {
case UNMATCHABLE:
return FNM_NOMATCH;
case STAR:
tailcnt = 0;
ptail = p + 1;
break;
default:
tailcnt++;
break;
}
}
/* Past this point we need not check for UNMATCHABLE in pat,
* because all of pat has already been parsed once. */
/* Past this point we need not check for UNMATCHABLE in pat,
* because all of pat has already been parsed once. */
/* Compute real str length if it was initially unknown/-1 */
n = strnlen(str, n);
endstr = str + n;
if (n < tailcnt) return FNM_NOMATCH;
/* Compute real str length if it was initially unknown/-1 */
n = strnlen(str, n);
endstr = str + n;
if (n < tailcnt) {
return FNM_NOMATCH;
}
/* Find the final tailcnt chars of str, accounting for UTF-8.
* On illegal sequences we may get it wrong, but in that case
* we necessarily have a matching failure anyway. */
for (s=endstr; s>str && tailcnt; tailcnt--) {
if (s[-1] < 128U || MB_CUR_MAX==1) s--;
else while ((unsigned char)*--s-0x80U<0x40 && s>str);
}
if (tailcnt) return FNM_NOMATCH;
stail = s;
/* Find the final tailcnt chars of str, accounting for UTF-8.
* On illegal sequences we may get it wrong, but in that case
* we necessarily have a matching failure anyway. */
for (s = endstr; s > str && tailcnt; tailcnt--) {
if (s[-1] < 128U || MB_CUR_MAX == 1) {
s--;
} else {
while ((unsigned char)*--s - 0x80U < 0x40 && s > str)
;
}
}
if (tailcnt) return FNM_NOMATCH;
stail = s;
/* Check that the pat and str tails match */
p = ptail;
for (;;) {
c = pat_next(p, endpat-p, &pinc, flags);
p += pinc;
if ((k = str_next(s, endstr-s, &sinc)) <= 0) {
if (c != END) return FNM_NOMATCH;
break;
}
s += sinc;
kfold = flags & FNM_CASEFOLD ? casefold(k) : k;
if (c == BRACKET) {
if (!match_bracket(p-pinc, k, kfold))
return FNM_NOMATCH;
} else if (c != QUESTION && k != c && kfold != c) {
return FNM_NOMATCH;
}
}
/* Check that the pat and str tails match */
p = ptail;
for (;;) {
c = FnmatchNextPattern(p, endpat - p, &pinc, flags);
p += pinc;
if ((k = FnmatchNextString(s, endstr - s, &sinc)) <= 0) {
if (c != END) return FNM_NOMATCH;
break;
}
s += sinc;
kfold = flags & FNM_CASEFOLD ? FnmatchCaseFold(k) : k;
if (c == BRACKET) {
if (!FnmatchBracket(p - pinc, k, kfold)) return FNM_NOMATCH;
} else if (c != QUESTION && k != c && kfold != c) {
return FNM_NOMATCH;
}
}
/* We're all done with the tails now, so throw them out */
endstr = stail;
endpat = ptail;
/* We're all done with the tails now, so throw them out */
endstr = stail;
endpat = ptail;
/* Match pattern components until there are none left */
while (pat<endpat) {
p = pat;
s = str;
for (;;) {
c = pat_next(p, endpat-p, &pinc, flags);
p += pinc;
/* Encountering * completes/commits a component */
if (c == STAR) {
pat = p;
str = s;
break;
}
k = str_next(s, endstr-s, &sinc);
if (!k)
return FNM_NOMATCH;
kfold = flags & FNM_CASEFOLD ? casefold(k) : k;
if (c == BRACKET) {
if (!match_bracket(p-pinc, k, kfold))
break;
} else if (c != QUESTION && k != c && kfold != c) {
break;
}
s += sinc;
}
if (c == STAR) continue;
/* If we failed, advance str, by 1 char if it's a valid
* char, or past all invalid bytes otherwise. */
k = str_next(str, endstr-str, &sinc);
if (k > 0) str += sinc;
else for (str++; str_next(str, endstr-str, &sinc)<0; str++);
}
/* Match pattern components until there are none left */
while (pat < endpat) {
p = pat;
s = str;
for (;;) {
c = FnmatchNextPattern(p, endpat - p, &pinc, flags);
p += pinc;
/* Encountering * completes/commits a component */
if (c == STAR) {
pat = p;
str = s;
break;
}
k = FnmatchNextString(s, endstr - s, &sinc);
if (!k) return FNM_NOMATCH;
kfold = flags & FNM_CASEFOLD ? FnmatchCaseFold(k) : k;
if (c == BRACKET) {
if (!FnmatchBracket(p - pinc, k, kfold)) break;
} else if (c != QUESTION && k != c && kfold != c) {
break;
}
s += sinc;
}
if (c == STAR) continue;
/* If we failed, advance str, by 1 char if it's a valid
* char, or past all invalid bytes otherwise. */
k = FnmatchNextString(str, endstr - str, &sinc);
if (k > 0) {
str += sinc;
} else {
str++;
while (FnmatchNextString(str, endstr - str, &sinc) < 0) {
str++;
}
}
}
return 0;
return 0;
}
/**
@ -337,29 +334,27 @@ static int FnmatchPerform(const char *pat, size_t m, const char *str, size_t n,
*
* @see glob()
*/
int fnmatch(const char *pat, const char *str, int flags) {
const char *s, *p;
size_t inc;
int c;
if (flags & FNM_PATHNAME) {
for (;;) {
for (s = str; *s && *s != '/'; s++)
;
for (p = pat;
(c = FnmatchNextPattern(p, -1, &inc, flags)) != END && c != '/';
p += inc)
;
if (c != *s && (!*s || !(flags & FNM_LEADING_DIR))) return FNM_NOMATCH;
if (FnmatchPerform(pat, p - pat, str, s - str, flags)) return FNM_NOMATCH;
if (!c) return 0;
str = s + 1;
pat = p + inc;
}
} else if (flags & FNM_LEADING_DIR) {
for (s = str; *s; s++) {
if (*s != '/') continue;
if (!FnmatchPerform(pat, -1, str, s - str, flags)) return 0;
}
}
return FnmatchPerform(pat, -1, str, -1, flags);
int fnmatch(const char *pat, const char *str, int flags)
{
const char *s, *p;
size_t inc;
int c;
if (flags & FNM_PATHNAME) for (;;) {
for (s=str; *s && *s!='/'; s++);
for (p=pat; (c=pat_next(p, -1, &inc, flags))!=END && c!='/'; p+=inc);
if (c!=*s && (!*s || !(flags & FNM_LEADING_DIR)))
return FNM_NOMATCH;
if (fnmatch_internal(pat, p-pat, str, s-str, flags))
return FNM_NOMATCH;
if (!c) return 0;
str = s+1;
pat = p+inc;
} else if (flags & FNM_LEADING_DIR) {
for (s=str; *s; s++) {
if (*s != '/') continue;
if (!fnmatch_internal(pat, -1, str, s-str, flags))
return 0;
}
}
return fnmatch_internal(pat, -1, str, -1, flags);
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,36 +25,17 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/limits.h"
#include "libc/str/mb.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
size_t mbrtoc16(char16_t *pc16, const char *s, size_t n, mbstate_t *ps) {
static unsigned internal_state;
if (!ps)
ps = (void *)&internal_state;
unsigned *pending = (unsigned *)ps;
if (!s)
return mbrtoc16(0, "", 1, ps);
/* mbrtowc states for partial UTF-8 characters have the high bit set;
* we use nonzero states without high bit for pending surrogates. */
if ((int)*pending > 0) {
if (pc16)
*pc16 = *pending;
*pending = 0;
return -3;
}
wchar_t wc;
size_t ret = mbrtowc(&wc, s, n, ps);
if (ret <= 4) {
if (wc >= 0x10000) {
*pending = (wc & 0x3ff) + 0xdc00;
wc = 0xd7c0 + (wc >> 10);
}
if (pc16)
*pc16 = wc;
}
return ret;
#define malloc undef
#define calloc undef
#define realloc undef
#define free(p) munmap(p, sizeof(struct __locale_struct))
void freelocale(locale_t l)
{
if (__loc_is_allocated(l)) free(l);
}

View file

@ -35,190 +35,227 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/dt.h"
#include "libc/sysv/consts/s.h"
#include "libc/limits.h"
#include "libc/str/str.h"
#include "libc/runtime/runtime.h"
#include "third_party/musl/passwd.h"
#include "third_party/musl/fnmatch.h"
__static_yoink("musl_libc_notice");
#define MAXPATH 1024
#pragma GCC diagnostic ignored "-Wparentheses"
struct GlobList {
struct GlobList *next;
char name[];
struct match
{
struct match *next;
char name[];
};
static int AppendGlob(struct GlobList **tail, const char *name, size_t len,
int mark) {
struct GlobList *new;
if ((new = malloc(sizeof(struct GlobList) + len + 2))) {
(*tail)->next = new;
new->next = NULL;
memcpy(new->name, name, len + 1);
if (mark && len && name[len - 1] != '/') {
new->name[len] = '/';
new->name[len + 1] = 0;
}
*tail = new;
return 0;
} else {
return -1;
}
static int append(struct match **tail, const char *name, size_t len, int mark)
{
struct match *new = malloc(sizeof(struct match) + len + 2);
if (!new) return -1;
(*tail)->next = new;
new->next = NULL;
memcpy(new->name, name, len+1);
if (mark && len && name[len-1]!='/') {
new->name[len] = '/';
new->name[len+1] = 0;
}
*tail = new;
return 0;
}
static int PerformGlob(char *buf, size_t pos, int type, char *pat, int flags,
int (*errfunc)(const char *path, int err),
struct GlobList **tail) {
DIR *dir;
size_t l;
char *p, *p2;
char saved_sep;
ptrdiff_t i, j;
struct stat st;
struct dirent *de;
int r, readerr, in_bracket, overflow, old_errno, fnm_flags;
/* If GLOB_MARK is unused, we don't care about type. */
if (!type && !(flags & GLOB_MARK)) type = DT_REG;
/* Special-case the remaining pattern being all slashes, in
* which case we can use caller-passed type if it's a dir. */
if (*pat && type != DT_DIR) type = 0;
while (pos + 1 < MAXPATH && *pat == '/') {
buf[pos++] = *pat++;
}
/* Consume maximal [escaped-]literal prefix of pattern, copying
* and un-escaping it to the running buffer as we go. */
i = 0;
j = 0;
overflow = 0;
in_bracket = 0;
for (; pat[i] != '*' && pat[i] != '?' && (!in_bracket || pat[i] != ']');
i++) {
if (!pat[i]) {
if (overflow) return 0;
pat += i;
pos += j;
i = j = 0;
break;
} else if (pat[i] == '[') {
in_bracket = 1;
} else if (pat[i] == '\\' && !(flags & GLOB_NOESCAPE)) {
/* Backslashes inside a bracket are (at least by
* our interpretation) non-special, so if next
* char is ']' we have a complete expression. */
if (in_bracket && pat[i + 1] == ']') break;
/* Unpaired final backslash never matches. */
if (!pat[i + 1]) return 0;
i++;
}
if (pat[i] == '/') {
if (overflow) return 0;
in_bracket = 0;
pat += i + 1;
i = -1;
pos += j + 1;
j = -1;
}
/* Only store a character if it fits in the buffer, but if
* a potential bracket expression is open, the overflow
* must be remembered and handled later only if the bracket
* is unterminated (and thereby a literal), so as not to
* disallow long bracket expressions with short matches. */
if (pos + (j + 1) < MAXPATH) {
buf[pos + j++] = pat[i];
} else if (in_bracket) {
overflow = 1;
} else {
return 0;
}
/* If we consume any new components, the caller-passed type
* or dummy type from above is no longer valid. */
type = 0;
}
buf[pos] = 0;
if (!*pat) {
/* If we consumed any components above, or if GLOB_MARK is
* requested and we don't yet know if the match is a dir,
* we must call stat to confirm the file exists and/or
* determine its type. */
if ((flags & GLOB_MARK) && type == DT_LNK) type = 0;
if (!type && stat(buf, &st)) {
if (errno != ENOENT && (errfunc(buf, errno) || (flags & GLOB_ERR))) {
return GLOB_ABORTED;
}
return 0;
}
if (!type && S_ISDIR(st.st_mode)) type = DT_DIR;
if (AppendGlob(tail, buf, pos, (flags & GLOB_MARK) && type == DT_DIR)) {
return GLOB_NOSPACE;
}
return 0;
}
p2 = strchr(pat, '/');
saved_sep = '/';
/* Check if the '/' was escaped and, if so, remove the escape char
* so that it will not be unpaired when passed to fnmatch. */
if (p2 && !(flags & GLOB_NOESCAPE)) {
for (p = p2; p > pat && p[-1] == '\\'; p--)
;
if ((p2 - p) % 2) {
p2--;
saved_sep = '\\';
}
}
dir = opendir(pos ? buf : ".");
if (!dir) {
if (errfunc(buf, errno) || (flags & GLOB_ERR)) return GLOB_ABORTED;
return 0;
}
old_errno = errno;
while (errno = 0, de = readdir(dir)) {
/* Quickly skip non-directories when there's pattern left. */
if (p2 && de->d_type && de->d_type != DT_DIR && de->d_type != DT_LNK) {
continue;
}
l = strlen(de->d_name);
if (l >= MAXPATH - pos) continue;
if (p2) *p2 = 0;
fnm_flags = ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) |
((!(flags & GLOB_PERIOD)) ? FNM_PERIOD : 0);
if (fnmatch(pat, de->d_name, fnm_flags)) continue;
/* With GLOB_PERIOD don't allow matching . or .. unless fnmatch()
* would match them with FNM_PERIOD rules in effect. */
if (p2 && (flags & GLOB_PERIOD) && de->d_name[0] == '.' &&
(!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2])) &&
fnmatch(pat, de->d_name, fnm_flags | FNM_PERIOD)) {
continue;
}
memcpy(buf + pos, de->d_name, l + 1);
if (p2) *p2 = saved_sep;
r = PerformGlob(buf, pos + l, de->d_type, p2 ? p2 : "", flags, errfunc,
tail);
if (r) {
closedir(dir);
return r;
}
}
readerr = errno;
if (p2) *p2 = saved_sep;
closedir(dir);
if (readerr && (errfunc(buf, errno) || (flags & GLOB_ERR))) {
return GLOB_ABORTED;
}
errno = old_errno;
return 0;
static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (*errfunc)(const char *path, int err), struct match **tail)
{
/* If GLOB_MARK is unused, we don't care about type. */
if (!type && !(flags & GLOB_MARK)) type = DT_REG;
/* Special-case the remaining pattern being all slashes, in
* which case we can use caller-passed type if it's a dir. */
if (*pat && type!=DT_DIR) type = 0;
while (pos+1 < PATH_MAX && *pat=='/') buf[pos++] = *pat++;
/* Consume maximal [escaped-]literal prefix of pattern, copying
* and un-escaping it to the running buffer as we go. */
ptrdiff_t i=0, j=0;
int in_bracket = 0, overflow = 0;
for (; pat[i]!='*' && pat[i]!='?' && (!in_bracket || pat[i]!=']'); i++) {
if (!pat[i]) {
if (overflow) return 0;
pat += i;
pos += j;
i = j = 0;
break;
} else if (pat[i] == '[') {
in_bracket = 1;
} else if (pat[i] == '\\' && !(flags & GLOB_NOESCAPE)) {
/* Backslashes inside a bracket are (at least by
* our interpretation) non-special, so if next
* char is ']' we have a complete expression. */
if (in_bracket && pat[i+1]==']') break;
/* Unpaired final backslash never matches. */
if (!pat[i+1]) return 0;
i++;
}
if (pat[i] == '/') {
if (overflow) return 0;
in_bracket = 0;
pat += i+1;
i = -1;
pos += j+1;
j = -1;
}
/* Only store a character if it fits in the buffer, but if
* a potential bracket expression is open, the overflow
* must be remembered and handled later only if the bracket
* is unterminated (and thereby a literal), so as not to
* disallow long bracket expressions with short matches. */
if (pos+(j+1) < PATH_MAX) {
buf[pos+j++] = pat[i];
} else if (in_bracket) {
overflow = 1;
} else {
return 0;
}
/* If we consume any new components, the caller-passed type
* or dummy type from above is no longer valid. */
type = 0;
}
buf[pos] = 0;
if (!*pat) {
/* If we consumed any components above, or if GLOB_MARK is
* requested and we don't yet know if the match is a dir,
* we must confirm the file exists and/or determine its type.
*
* If marking dirs, symlink type is inconclusive; we need the
* type for the symlink target, and therefore must try stat
* first unless type is known not to be a symlink. Otherwise,
* or if that fails, use lstat for determining existence to
* avoid false negatives in the case of broken symlinks. */
struct stat st;
if ((flags & GLOB_MARK) && (!type||type==DT_LNK) && !stat(buf, &st)) {
if (S_ISDIR(st.st_mode)) type = DT_DIR;
else type = DT_REG;
}
if (!type && lstat(buf, &st)) {
if (errno!=ENOENT && (errfunc(buf, errno) || (flags & GLOB_ERR)))
return GLOB_ABORTED;
return 0;
}
if (append(tail, buf, pos, (flags & GLOB_MARK) && type==DT_DIR))
return GLOB_NOSPACE;
return 0;
}
char *p2 = strchr(pat, '/'), saved_sep = '/';
/* Check if the '/' was escaped and, if so, remove the escape char
* so that it will not be unpaired when passed to fnmatch. */
if (p2 && !(flags & GLOB_NOESCAPE)) {
char *p;
for (p=p2; p>pat && p[-1]=='\\'; p--);
if ((p2-p)%2) {
p2--;
saved_sep = '\\';
}
}
DIR *dir = opendir(pos ? buf : ".");
if (!dir) {
if (errfunc(buf, errno) || (flags & GLOB_ERR))
return GLOB_ABORTED;
return 0;
}
int old_errno = errno;
struct dirent *de;
while (errno=0, de=readdir(dir)) {
/* Quickly skip non-directories when there's pattern left. */
if (p2 && de->d_type && de->d_type!=DT_DIR && de->d_type!=DT_LNK)
continue;
size_t l = strlen(de->d_name);
if (l >= PATH_MAX-pos) continue;
if (p2) *p2 = 0;
int fnm_flags= ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
| ((!(flags & GLOB_PERIOD)) ? FNM_PERIOD : 0);
if (fnmatch(pat, de->d_name, fnm_flags))
continue;
/* With GLOB_PERIOD, don't allow matching . or .. unless
* fnmatch would match them with FNM_PERIOD rules in effect. */
if (p2 && (flags & GLOB_PERIOD) && de->d_name[0]=='.'
&& (!de->d_name[1] || de->d_name[1]=='.' && !de->d_name[2])
&& fnmatch(pat, de->d_name, fnm_flags | FNM_PERIOD))
continue;
memcpy(buf+pos, de->d_name, l+1);
if (p2) *p2 = saved_sep;
int r = do_glob(buf, pos+l, de->d_type, p2 ? p2 : "", flags, errfunc, tail);
if (r) {
closedir(dir);
return r;
}
}
int readerr = errno;
if (p2) *p2 = saved_sep;
closedir(dir);
if (readerr && (errfunc(buf, errno) || (flags & GLOB_ERR)))
return GLOB_ABORTED;
errno = old_errno;
return 0;
}
static int IgnoreGlobError(const char *path, int err) {
return 0;
static int ignore_err(const char *path, int err)
{
return 0;
}
static void FreeGlobList(struct GlobList *head) {
struct GlobList *match, *next;
for (match = head->next; match; match = next) {
next = match->next;
free(match);
}
static void freelist(struct match *head)
{
struct match *match, *next;
for (match=head->next; match; match=next) {
next = match->next;
free(match);
}
}
static int GlobPredicate(const void *a, const void *b) {
return strcmp(*(const char **)a, *(const char **)b);
static int sort(const void *a, const void *b)
{
return strcmp(*(const char **)a, *(const char **)b);
}
static int expand_tilde(char **pat, char *buf, size_t *pos)
{
char *p = *pat + 1;
size_t i = 0;
char delim, *name_end = strchrnul(p, '/');
if ((delim = *name_end)) *name_end++ = 0;
*pat = name_end;
char *home = *p ? NULL : getenv("HOME");
if (!home) {
struct passwd pw, *res;
int e = *p ? getpwnam_r(p, &pw, buf, PATH_MAX, &res)
: getpwuid_r(getuid(), &pw, buf, PATH_MAX, &res);
if (e == ENOMEM) {
return GLOB_NOSPACE;
} else if (e == 0) {
if (!res)
return GLOB_NOMATCH;
} else {
return GLOB_NOMATCH;
}
home = pw.pw_dir;
}
while (i < PATH_MAX - 2 && *home)
buf[i++] = *home++;
if (*home)
return GLOB_NOMATCH;
if ((buf[i] = delim))
buf[++i] = 0;
*pos = i;
return 0;
}
/**
@ -239,81 +276,88 @@ static int GlobPredicate(const void *a, const void *b) {
* @return 0 on success or GLOB_NOMATCH, GLOB_NOSPACE on OOM, or
* GLOB_ABORTED on read error
*/
int glob(const char *pat, int flags, int errfunc(const char *path, int err),
glob_t *g) {
int error = 0;
size_t cnt, i;
char **pathv, buf[MAXPATH];
struct GlobList head = {.next = NULL}, *tail = &head;
size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
if (!errfunc) errfunc = IgnoreGlobError;
if (!(flags & GLOB_APPEND)) {
g->gl_offs = offs;
g->gl_pathc = 0;
g->gl_pathv = NULL;
}
if (*pat) {
char *p = strdup(pat);
if (!p) return GLOB_NOSPACE;
buf[0] = 0;
error = PerformGlob(buf, 0, 0, p, flags, errfunc, &tail);
free(p);
}
if (error == GLOB_NOSPACE) {
FreeGlobList(&head);
return error;
}
for (cnt = 0, tail = head.next; tail; tail = tail->next, cnt++)
;
if (!cnt) {
if (flags & GLOB_NOCHECK) {
tail = &head;
if (AppendGlob(&tail, pat, strlen(pat), 0)) {
return GLOB_NOSPACE;
}
cnt++;
} else
return GLOB_NOMATCH;
}
if (flags & GLOB_APPEND) {
pathv =
realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *));
if (!pathv) {
FreeGlobList(&head);
return GLOB_NOSPACE;
}
g->gl_pathv = pathv;
offs += g->gl_pathc;
} else {
g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *));
if (!g->gl_pathv) {
FreeGlobList(&head);
return GLOB_NOSPACE;
}
for (i = 0; i < offs; i++) {
g->gl_pathv[i] = NULL;
}
}
for (i = 0, tail = head.next; i < cnt; tail = tail->next, i++) {
g->gl_pathv[offs + i] = tail->name;
}
g->gl_pathv[offs + i] = NULL;
g->gl_pathc += cnt;
if (!(flags & GLOB_NOSORT)) {
qsort(g->gl_pathv + offs, cnt, sizeof(char *), GlobPredicate);
}
return error;
int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, int err), glob_t *restrict g)
{
struct match head = { .next = NULL }, *tail = &head;
size_t cnt, i;
size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
int error = 0;
char buf[PATH_MAX];
if (!errfunc) errfunc = ignore_err;
if (!(flags & GLOB_APPEND)) {
g->gl_offs = offs;
g->gl_pathc = 0;
g->gl_pathv = NULL;
}
if (*pat) {
char *p = strdup(pat);
if (!p) return GLOB_NOSPACE;
buf[0] = 0;
size_t pos = 0;
char *s = p;
if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) && *p == '~')
error = expand_tilde(&s, buf, &pos);
if (!error)
error = do_glob(buf, pos, 0, s, flags, errfunc, &tail);
free(p);
}
if (error == GLOB_NOSPACE) {
freelist(&head);
return error;
}
for (cnt=0, tail=head.next; tail; tail=tail->next, cnt++);
if (!cnt) {
if (flags & GLOB_NOCHECK) {
tail = &head;
if (append(&tail, pat, strlen(pat), 0))
return GLOB_NOSPACE;
cnt++;
} else if (!error)
return GLOB_NOMATCH;
}
if (flags & GLOB_APPEND) {
char **pathv = realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *));
if (!pathv) {
freelist(&head);
return GLOB_NOSPACE;
}
g->gl_pathv = pathv;
offs += g->gl_pathc;
} else {
g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *));
if (!g->gl_pathv) {
freelist(&head);
return GLOB_NOSPACE;
}
for (i=0; i<offs; i++)
g->gl_pathv[i] = NULL;
}
for (i=0, tail=head.next; i<cnt; tail=tail->next, i++)
g->gl_pathv[offs + i] = tail->name;
g->gl_pathv[offs + i] = NULL;
g->gl_pathc += cnt;
if (!(flags & GLOB_NOSORT))
qsort(g->gl_pathv+offs, cnt, sizeof(char *), sort);
return error;
}
/**
* Frees entries allocated by glob().
*/
void globfree(glob_t *g) {
size_t i;
for (i = 0; i < g->gl_pathc; i++) {
free(g->gl_pathv[g->gl_offs + i] - offsetof(struct GlobList, name));
}
free(g->gl_pathv);
g->gl_pathc = 0;
g->gl_pathv = NULL;
void globfree(glob_t *g)
{
size_t i;
for (i=0; i<g->gl_pathc; i++)
free(g->gl_pathv[g->gl_offs + i] - offsetof(struct match, name));
free(g->gl_pathv);
g->gl_pathc = 0;
g->gl_pathv = NULL;
}

View file

@ -29,12 +29,12 @@
#include "libc/errno.h"
#include "libc/mem/mem.h"
#include "libc/str/locale.h"
#include "libc/str/locale.internal.h"
#include "libc/str/str.h"
#include "libc/thread/tls.h"
// clang-format off
__static_yoink("musl_libc_notice");
#define UTF_32BE 0300
#define UTF_16LE 0301
#define UTF_16BE 0302
@ -77,10 +77,10 @@ static const unsigned char charmaps[] =
"ucs4\0utf32\0\0\313"
"ucs2\0\0\314"
"eucjp\0\0\320"
"shiftjis\0sjis\0\0\321"
"shiftjis\0sjis\0cp932\0\0\321"
"iso2022jp\0\0\322"
"gb18030\0\0\330"
"gbk\0\0\331"
"gbk\0cp936\0windows936\0\0\331"
"gb2312\0\0\332"
"big5\0bigfive\0cp950\0big5hkscs\0\0\340"
"euckr\0ksc5601\0ksx1001\0cp949\0\0\350"
@ -88,6 +88,7 @@ static const unsigned char charmaps[] =
;
#pragma GCC diagnostic ignored "-Wmissing-braces"
#pragma GCC diagnostic ignored "-Wparentheses"
/* Table of characters that appear in legacy 8-bit codepages,
* limited to 1024 slots (10 bit indices). The first 256 entries
@ -237,7 +238,7 @@ static unsigned legacy_map(const unsigned char *map, unsigned c)
{
if (c < 4*map[-1]) return c;
unsigned x = c - 4*map[-1];
x = (map[x*5/4]>>(2*x%8)) | ((map[x*5/4+1]<<(8-(2*x%8))) & 1023);
x = map[x*5/4]>>2*x%8 | map[x*5/4+1]<<8-2*x%8 & 1023;
return x < 256 ? x : legacy_chars[x-256];
}
@ -279,12 +280,11 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
int err;
unsigned char type = map[-1];
unsigned char totype = tomap[-1];
locale_t *ploc = (locale_t *)&__get_tls()->tib_locale;
locale_t loc = *ploc;
locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
if (!in || !*in || !*inb) return 0;
*ploc = 0; // TODO(jart): UTF8_LOCALE?
*ploc = UTF8_LOCALE;
for (; *inb; *in+=l, *inb-=l) {
c = *(unsigned char *)*in;
@ -334,8 +334,6 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
case UCS2:
case UTF_16:
l = 0;
if (!scd)
goto starved;
if (!scd->state) {
if (*inb < 2) goto starved;
c = get_16((void *)*in, 0);
@ -349,8 +347,6 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
continue;
case UTF_32:
l = 0;
if (!scd)
goto starved;
if (!scd->state) {
if (*inb < 4) goto starved;
c = get_32((void *)*in, 0);
@ -381,6 +377,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
c++;
d -= 159;
}
if (c>=84) goto ilseq;
c = jis0208[c][d];
if (!c) goto ilseq;
break;
@ -402,7 +399,6 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (!c) goto ilseq;
break;
case ISO2022_JP:
if (!scd) goto starved;
if (c >= 128) goto ilseq;
if (c == '\033') {
l = 3;
@ -445,6 +441,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (c < 128) break;
if (c < 0xa1) goto ilseq;
case GBK:
if (c == 128) {
c = 0x20ac;
break;
}
case GB18030:
if (c < 128) break;
c -= 0x81;
@ -537,7 +537,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (c >= 93 || d >= 94) {
c += (0xa1-0x81);
d += 0xa1;
if (c >= 93 || ((c>=0xc6-0x81) && d>0x52))
if (c >= 93 || c>=0xc6-0x81 && d>0x52)
goto ilseq;
if (d-'A'<26) d = d-'A';
else if (d-'a'<26) d = d-'a'+26;

View file

@ -25,14 +25,12 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/str/langinfo.h"
#include "libc/str/locale.h"
#include "libc/str/nltypes.h"
#include "libc/thread/tls.h"
#include <locale.h>
#include <langinfo.h>
#include "libc/intrin/kprintf.h"
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
// clang-format off
static const char c_time[] =
"Sun\0" "Mon\0" "Tue\0" "Wed\0" "Thu\0" "Fri\0" "Sat\0"
"Sunday\0" "Monday\0" "Tuesday\0" "Wednesday\0"
@ -63,9 +61,6 @@ char *nl_langinfo_l(nl_item item, locale_t loc)
int idx = item & 65535;
const char *str;
if (!loc)
return "";
if (item == CODESET) return loc->cat[LC_CTYPE] ? "UTF-8" : "ASCII";
/* _NL_LOCALE_NAME extension */
@ -94,11 +89,11 @@ char *nl_langinfo_l(nl_item item, locale_t loc)
}
for (; idx; idx--, str++) for (; *str; str++);
// if (cat != LC_NUMERIC && *str) str = LCTRANS(str, cat, loc);
if (cat != LC_NUMERIC && *str) str = LCTRANS(str, cat, loc);
return (char *)str;
}
char *nl_langinfo(nl_item item)
{
return nl_langinfo_l(item, (locale_t)__get_tls()->tib_locale);
return nl_langinfo_l(item, CURRENT_LOCALE);
}

46
third_party/musl/lctrans.c vendored Normal file
View file

@ -0,0 +1,46 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
const char *__lctrans_dummy(const char *msg, const struct __locale_map *lm)
{
return msg;
}
__weak_reference(__lctrans_dummy, __lctrans_impl);
const char *__lctrans(const char *msg, const struct __locale_map *lm)
{
return __lctrans_impl(msg, lm);
}
const char *__lctrans_cur(const char *msg)
{
return __lctrans_impl(msg, CURRENT_LOCALE->cat[LC_MESSAGES]);
}

137
third_party/musl/locale_map.c vendored Normal file
View file

@ -0,0 +1,137 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/str/str.h"
#include "libc/calls/calls.h"
#include "third_party/musl/mapfile.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
#define malloc _mapanon
#define calloc undef
#define realloc undef
#define free undef
#pragma GCC diagnostic ignored "-Wparentheses"
const char *__lctrans_impl(const char *msg, const struct __locale_map *lm)
{
const char *trans = 0;
if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg);
return trans ? trans : msg;
}
static const char envvars[][12] = {
"LC_CTYPE",
"LC_NUMERIC",
"LC_TIME",
"LC_COLLATE",
"LC_MONETARY",
"LC_MESSAGES",
};
const struct __locale_map *__get_locale(int cat, const char *val)
{
static void *volatile loc_head;
const struct __locale_map *p;
struct __locale_map *new = 0;
const char *path = 0, *z;
char buf[256];
size_t l, n;
if (!*val) {
(val = getenv("LC_ALL")) && *val ||
(val = getenv(envvars[cat])) && *val ||
(val = getenv("LANG")) && *val ||
(val = "C.UTF-8");
}
/* Limit name length and forbid leading dot or any slashes. */
for (n=0; n<LOCALE_NAME_MAX && val[n] && val[n]!='/'; n++);
if (val[0]=='.' || val[n]) val = "C.UTF-8";
int builtin = (val[0]=='C' && !val[1])
|| !strcmp(val, "C.UTF-8")
|| !strcmp(val, "POSIX");
if (builtin) {
if (cat == LC_CTYPE && val[1]=='.')
return (void *)&__c_dot_utf8;
return 0;
}
for (p=loc_head; p; p=p->next)
if (!strcmp(val, p->name)) return p;
path = secure_getenv("MUSL_LOCPATH");
/* FIXME: add a default path? */
if (path) for (; *path; path=z+!!*z) {
z = strchrnul(path, ':');
l = z - path;
if (l >= sizeof buf - n - 2) continue;
memcpy(buf, path, l);
buf[l] = '/';
memcpy(buf+l+1, val, n);
buf[l+1+n] = 0;
size_t map_size;
const void *map = __map_file(buf, &map_size);
if (map) {
new = malloc(sizeof *new);
if (!new) {
munmap((void *)map, map_size);
break;
}
new->map = map;
new->map_size = map_size;
memcpy(new->name, val, n);
new->name[n] = 0;
new->next = loc_head;
loc_head = new;
break;
}
}
/* If no locale definition was found, make a locale map
* object anyway to store the name, which is kept for the
* sake of being able to do message translations at the
* application level. */
if (!new && (new = malloc(sizeof *new))) {
new->map = __c_dot_utf8.map;
new->map_size = __c_dot_utf8.map_size;
memcpy(new->name, val, n);
new->name[n] = 0;
new->next = loc_head;
loc_head = new;
}
/* For LC_CTYPE, never return a null pointer unless the
* requested name was "C" or "POSIX". */
if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8;
return new;
}

34
third_party/musl/mblen.c vendored Normal file
View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <stdlib.h>
__static_yoink("musl_libc_notice");
int mblen(const char *s, size_t n)
{
return mbtowc(0, s, n);
}

35
third_party/musl/mbrlen.c vendored Normal file
View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <wchar.h>
__static_yoink("musl_libc_notice");
size_t mbrlen(const char *restrict s, size_t n, mbstate_t *restrict st)
{
static unsigned internal;
return mbrtowc(0, s, n, st ? st : (mbstate_t *)&internal);
}

58
third_party/musl/mbrtoc16.c vendored Normal file
View file

@ -0,0 +1,58 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <uchar.h>
#include <wchar.h>
__static_yoink("musl_libc_notice");
size_t mbrtoc16(char16_t *restrict pc16, const char *restrict s, size_t n, mbstate_t *restrict ps)
{
static unsigned internal_state;
if (!ps) ps = (void *)&internal_state;
unsigned *pending = (unsigned *)ps;
if (!s) return mbrtoc16(0, "", 1, ps);
/* mbrtowc states for partial UTF-8 characters have the high bit set;
* we use nonzero states without high bit for pending surrogates. */
if ((int)*pending > 0) {
if (pc16) *pc16 = *pending;
*pending = 0;
return -3;
}
wchar_t wc;
size_t ret = mbrtowc(&wc, s, n, ps);
if (ret <= 4) {
if (wc >= 0x10000) {
*pending = (wc & 0x3ff) + 0xdc00;
wc = 0xd7c0 + (wc >> 10);
}
if (pc16) *pc16 = wc;
}
return ret;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,21 +25,17 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include <uchar.h>
#include <wchar.h>
__static_yoink("musl_libc_notice");
size_t mbrtoc32(char32_t *pc32, const char *s, size_t n, mbstate_t *ps) {
static unsigned internal_state;
if (!ps)
ps = (void *)&internal_state;
if (!s)
return mbrtoc32(0, "", 1, ps);
wchar_t wc;
size_t ret = mbrtowc(&wc, s, n, ps);
if (ret <= 4 && pc32)
*pc32 = wc;
return ret;
size_t mbrtoc32(char32_t *restrict pc32, const char *restrict s, size_t n, mbstate_t *restrict ps)
{
static unsigned internal_state;
if (!ps) ps = (void *)&internal_state;
if (!s) return mbrtoc32(0, "", 1, ps);
wchar_t wc;
size_t ret = mbrtowc(&wc, s, n, ps);
if (ret <= 4 && pc32) *pc32 = wc;
return ret;
}

81
third_party/musl/mbrtowc.c vendored Normal file
View file

@ -0,0 +1,81 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <stdlib.h>
#include <wchar.h>
#include <errno.h>
#include "multibyte.h"
__static_yoink("musl_libc_notice");
#pragma GCC diagnostic ignored "-Wparentheses"
size_t mbrtowc(wchar_t *restrict wc, const char *restrict src, size_t n, mbstate_t *restrict st)
{
static unsigned internal_state;
unsigned c;
const unsigned char *s = (const void *)src;
const size_t N = n;
wchar_t dummy;
if (!st) st = (void *)&internal_state;
c = *(unsigned *)st;
if (!s) {
if (c) goto ilseq;
return 0;
} else if (!wc) wc = &dummy;
if (!n) return -2;
if (!c) {
if (*s < 0x80) return !!(*wc = *s);
if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1;
if (*s-SA > SB-SA) goto ilseq;
c = bittab[*s++-SA]; n--;
}
if (n) {
if (OOB(c,*s)) goto ilseq;
loop:
c = c<<6 | *s++-0x80; n--;
if (!(c&(1U<<31))) {
*(unsigned *)st = 0;
*wc = c;
return N-n;
}
if (n) {
if (*s-0x80u >= 0x40) goto ilseq;
goto loop;
}
}
*(unsigned *)st = c;
return -2;
ilseq:
*(unsigned *)st = 0;
errno = EILSEQ;
return -1;
}

34
third_party/musl/mbsinit.c vendored Normal file
View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <wchar.h>
__static_yoink("musl_libc_notice");
int mbsinit(const mbstate_t *st)
{
return !st || !*(unsigned *)st;
}

83
third_party/musl/mbsnrtowcs.c vendored Normal file
View file

@ -0,0 +1,83 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <wchar.h>
__static_yoink("musl_libc_notice");
size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, size_t wn, mbstate_t *restrict st)
{
size_t l, cnt=0, n2;
wchar_t *ws, wbuf[256];
const char *s = *src;
const char *tmp_s;
if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf;
else ws = wcs;
/* making sure output buffer size is at most n/4 will ensure
* that mbsrtowcs never reads more than n input bytes. thus
* we can use mbsrtowcs as long as it's practical.. */
while ( s && wn && ( (n2=n/4)>=wn || n2>32 ) ) {
if (n2>=wn) n2=wn;
tmp_s = s;
l = mbsrtowcs(ws, &s, n2, st);
if (!(l+1)) {
cnt = l;
wn = 0;
break;
}
if (ws != wbuf) {
ws += l;
wn -= l;
}
n = s ? n - (s - tmp_s) : 0;
cnt += l;
}
if (s) while (wn && n) {
l = mbrtowc(ws, s, n, st);
if (l+2<=2) {
if (!(l+1)) {
cnt = l;
break;
}
if (!l) {
s = 0;
break;
}
/* have to roll back partial character */
*(unsigned *)st = 0;
break;
}
s += l; n -= l;
/* safe - this loop runs fewer than sizeof(wbuf)/8 times */
ws++; wn--;
cnt++;
}
if (wcs) *src = s;
return cnt;
}

150
third_party/musl/mbsrtowcs.c vendored Normal file
View file

@ -0,0 +1,150 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <stdint.h>
#include <wchar.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "multibyte.h"
__static_yoink("musl_libc_notice");
#pragma GCC diagnostic ignored "-Wparentheses"
size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st)
{
const unsigned char *s = (const void *)*src;
size_t wn0 = wn;
unsigned c = 0;
if (st && (c = *(unsigned *)st)) {
if (ws) {
*(unsigned *)st = 0;
goto resume;
} else {
goto resume0;
}
}
if (MB_CUR_MAX==1) {
if (!ws) return strlen((const char *)s);
for (;;) {
if (!wn) {
*src = (const void *)s;
return wn0;
}
if (!*s) break;
c = *s++;
*ws++ = CODEUNIT(c);
wn--;
}
*ws = 0;
*src = 0;
return wn0-wn;
}
if (!ws) for (;;) {
#ifdef __GNUC__
typedef uint32_t __attribute__((__may_alias__)) w32;
if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
while (!(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) {
s += 4;
wn -= 4;
}
}
#endif
if (*s-1u < 0x7f) {
s++;
wn--;
continue;
}
if (*s-SA > SB-SA) break;
c = bittab[*s++-SA];
resume0:
if (OOB(c,*s)) { s--; break; }
s++;
if (c&(1U<<25)) {
if (*s-0x80u >= 0x40) { s-=2; break; }
s++;
if (c&(1U<<19)) {
if (*s-0x80u >= 0x40) { s-=3; break; }
s++;
}
}
wn--;
c = 0;
} else for (;;) {
if (!wn) {
*src = (const void *)s;
return wn0;
}
#ifdef __GNUC__
typedef uint32_t __attribute__((__may_alias__)) w32;
if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
while (wn>=5 && !(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) {
*ws++ = *s++;
*ws++ = *s++;
*ws++ = *s++;
*ws++ = *s++;
wn -= 4;
}
}
#endif
if (*s-1u < 0x7f) {
*ws++ = *s++;
wn--;
continue;
}
if (*s-SA > SB-SA) break;
c = bittab[*s++-SA];
resume:
if (OOB(c,*s)) { s--; break; }
c = (c<<6) | *s++-0x80;
if (c&(1U<<31)) {
if (*s-0x80u >= 0x40) { s-=2; break; }
c = (c<<6) | *s++-0x80;
if (c&(1U<<31)) {
if (*s-0x80u >= 0x40) { s-=3; break; }
c = (c<<6) | *s++-0x80;
}
}
*ws++ = c;
wn--;
c = 0;
}
if (!c && !*s) {
if (ws) {
*ws = 0;
*src = 0;
}
return wn0-wn;
}
errno = EILSEQ;
if (ws) *src = (const void *)s;
return -1;
}

35
third_party/musl/mbstowcs.c vendored Normal file
View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <stdlib.h>
#include <wchar.h>
__static_yoink("musl_libc_notice");
size_t mbstowcs(wchar_t *restrict ws, const char *restrict s, size_t wn)
{
return mbsrtowcs(ws, (void*)&s, wn, 0);
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,53 +25,53 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/str/mb.internal.h"
#include "libc/str/str.h"
#include <stdlib.h>
#include <wchar.h>
#include <errno.h>
#include "multibyte.h"
__static_yoink("musl_libc_notice");
int mbtowc(wchar_t *restrict wc, const char *restrict src, size_t n) {
unsigned c;
const unsigned char *s = (const void *)src;
wchar_t dummy;
if (!s)
return 0;
if (!n)
goto ilseq;
if (!wc)
wc = &dummy;
if (*s < 0x80)
return !!(*wc = *s);
if (MB_CUR_MAX == 1)
return (*wc = CODEUNIT(*s)), 1;
if (*s - SA > SB - SA)
goto ilseq;
c = kMbBittab[*s++ - SA];
/* Avoid excessive checks against n: If shifting the state n-1
* times does not clear the high bit, then the value of n is
* insufficient to read a character */
if (n < 4 && ((c << (6 * n - 6)) & (1U << 31)))
goto ilseq;
if (OOB(c, *s))
goto ilseq;
c = c << 6 | (*s++ - 0x80);
if (!(c & (1U << 31))) {
*wc = c;
return 2;
}
if (*s - 0x80u >= 0x40)
goto ilseq;
c = c << 6 | (*s++ - 0x80);
if (!(c & (1U << 31))) {
*wc = c;
return 3;
}
if (*s - 0x80u >= 0x40)
goto ilseq;
*wc = c << 6 | (*s++ - 0x80);
return 4;
#pragma GCC diagnostic ignored "-Wparentheses"
int mbtowc(wchar_t *restrict wc, const char *restrict src, size_t n)
{
unsigned c;
const unsigned char *s = (const void *)src;
wchar_t dummy;
if (!s) return 0;
if (!n) goto ilseq;
if (!wc) wc = &dummy;
if (*s < 0x80) return !!(*wc = *s);
if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1;
if (*s-SA > SB-SA) goto ilseq;
c = bittab[*s++-SA];
/* Avoid excessive checks against n: If shifting the state n-1
* times does not clear the high bit, then the value of n is
* insufficient to read a character */
if (n<4 && ((c<<(6*n-6)) & (1U<<31))) goto ilseq;
if (OOB(c,*s)) goto ilseq;
c = c<<6 | *s++-0x80;
if (!(c&(1U<<31))) {
*wc = c;
return 2;
}
if (*s-0x80u >= 0x40) goto ilseq;
c = c<<6 | *s++-0x80;
if (!(c&(1U<<31))) {
*wc = c;
return 3;
}
if (*s-0x80u >= 0x40) goto ilseq;
*wc = c<<6 | *s++-0x80;
return 4;
ilseq:
errno = EILSEQ;
return -1;
errno = EILSEQ;
return -1;
}

53
third_party/musl/multibyte.c vendored Normal file
View file

@ -0,0 +1,53 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "multibyte.h"
#define C(x) ( x<2 ? -1 : ( R(0x80,0xc0) | x ) )
#define D(x) C((x+16))
#define E(x) ( ( x==0 ? R(0xa0,0xc0) : \
x==0xd ? R(0x80,0xa0) : \
R(0x80,0xc0) ) \
| ( R(0x80,0xc0) >> 6 ) \
| x )
#define F(x) ( ( x>=5 ? 0 : \
x==0 ? R(0x90,0xc0) : \
x==4 ? R(0x80,0x90) : \
R(0x80,0xc0) ) \
| ( R(0x80,0xc0) >> 6 ) \
| ( R(0x80,0xc0) >> 12 ) \
| x )
const uint32_t bittab[] = {
C(0x2),C(0x3),C(0x4),C(0x5),C(0x6),C(0x7),
C(0x8),C(0x9),C(0xa),C(0xb),C(0xc),C(0xd),C(0xe),C(0xf),
D(0x0),D(0x1),D(0x2),D(0x3),D(0x4),D(0x5),D(0x6),D(0x7),
D(0x8),D(0x9),D(0xa),D(0xb),D(0xc),D(0xd),D(0xe),D(0xf),
E(0x0),E(0x1),E(0x2),E(0x3),E(0x4),E(0x5),E(0x6),E(0x7),
E(0x8),E(0x9),E(0xa),E(0xb),E(0xc),E(0xd),E(0xe),E(0xf),
F(0x0),F(0x1),F(0x2),F(0x3),F(0x4)
};

26
third_party/musl/multibyte.h vendored Normal file
View file

@ -0,0 +1,26 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_MULTIBYTE_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_MULTIBYTE_H_
#define bittab __fsmu8
extern const uint32_t bittab[];
/* Upper 6 state bits are a negative integer offset to bound-check next byte */
/* equivalent to: ( (b-0x80) | (b+offset) ) & ~0x3f */
#define OOB(c,b) (((((b)>>3)-0x10)|(((b)>>3)+((int32_t)(c)>>26))) & ~7)
/* Interval [a,b). Either a must be 80 or b must be c0, lower 3 bits clear. */
#define R(a,b) ((uint32_t)((a==0x80 ? 0x40u-b : 0u-a) << 23))
#define FAILSTATE R(0x80,0x80)
#define SA 0xc2u
#define SB 0xf4u
/* Arbitrary encoding for representing code units instead of characters. */
#define CODEUNIT(c) (0xdfff & (signed char)(c))
#define IS_CODEUNIT(c) ((unsigned)(c)-0xdf80 < 0x80)
/* Get inline definition of MB_CUR_MAX. */
#include "libc/str/locale.internal.h"
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_MULTIBYTE_H_ */

94
third_party/musl/newlocale.c vendored Normal file
View file

@ -0,0 +1,94 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
#define malloc _mapanon
#define calloc undef
#define realloc undef
#define free undef
static int default_locale_init_done;
static struct __locale_struct default_locale, default_ctype_locale;
int __loc_is_allocated(locale_t loc)
{
return loc && loc != C_LOCALE && loc != UTF8_LOCALE
&& loc != &default_locale && loc != &default_ctype_locale;
}
static locale_t do_newlocale(int mask, const char *name, locale_t loc)
{
struct __locale_struct tmp;
for (int i=0; i<LC_ALL; i++) {
tmp.cat[i] = (!(mask & (1<<i)) && loc) ? loc->cat[i] :
__get_locale(i, (mask & (1<<i)) ? name : "");
if (tmp.cat[i] == LOC_MAP_FAILED)
return 0;
}
/* For locales with allocated storage, modify in-place. */
if (__loc_is_allocated(loc)) {
*loc = tmp;
return loc;
}
/* Otherwise, first see if we can use one of the builtin locales.
* This makes the common usage case for newlocale, getting a C locale
* with predictable behavior, very fast, and more importantly, fail-safe. */
if (!memcmp(&tmp, C_LOCALE, sizeof tmp)) return C_LOCALE;
if (!memcmp(&tmp, UTF8_LOCALE, sizeof tmp)) return UTF8_LOCALE;
/* And provide builtins for the initial default locale, and a
* variant of the C locale honoring the default locale's encoding. */
if (!default_locale_init_done) {
for (int i=0; i<LC_ALL; i++)
default_locale.cat[i] = __get_locale(i, "");
default_ctype_locale.cat[LC_CTYPE] = default_locale.cat[LC_CTYPE];
default_locale_init_done = 1;
}
if (!memcmp(&tmp, &default_locale, sizeof tmp)) return &default_locale;
if (!memcmp(&tmp, &default_ctype_locale, sizeof tmp))
return &default_ctype_locale;
/* If no builtin locale matched, attempt to allocate and copy. */
if ((loc = malloc(sizeof *loc))) *loc = tmp;
return loc;
}
locale_t newlocale(int mask, const char *name, locale_t loc)
{
pthread_mutex_lock(&__locale_lock);
loc = do_newlocale(mask, name, loc);
pthread_mutex_unlock(&__locale_lock);
return loc;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,68 +25,78 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/str/mb.internal.h"
#include "libc/str/str.h"
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
size_t mbsnrtowcs(wchar_t *wcs, const char **src, size_t n, size_t wn,
mbstate_t *st) {
size_t l, cnt = 0, n2;
wchar_t *ws, wbuf[256];
const char *s = *src;
const char *tmp_s;
if (!wcs) {
ws = wbuf, wn = sizeof(wbuf) / sizeof(*wbuf);
} else {
ws = wcs;
}
/* making sure output buffer size is at most n/4 will ensure
* that mbsrtowcs never reads more than n input bytes. thus
* we can use mbsrtowcs as long as it's practical.. */
while (s && wn && ((n2 = n / 4) >= wn || n2 > 32)) {
if (n2 >= wn)
n2 = wn;
tmp_s = s;
l = mbsrtowcs(ws, &s, n2, st);
if (!(l + 1)) {
cnt = l;
wn = 0;
break;
}
if (ws != wbuf) {
ws += l;
wn -= l;
}
n = s ? n - (s - tmp_s) : 0;
cnt += l;
}
if (s)
while (wn && n) {
l = mbrtowc(ws, s, n, st);
if (l + 2 <= 2) {
if (!(l + 1)) {
cnt = l;
break;
}
if (!l) {
s = 0;
break;
}
/* have to roll back partial character */
*(unsigned *)st = 0;
break;
}
s += l;
n -= l;
/* safe - this loop runs fewer than sizeof(wbuf)/8 times */
ws++;
wn--;
cnt++;
}
if (wcs)
*src = s;
return cnt;
static char buf[LC_ALL*(LOCALE_NAME_MAX+1)];
char *setlocale(int cat, const char *name)
{
const struct __locale_map *lm;
if ((unsigned)cat > LC_ALL) return 0;
pthread_mutex_lock(&__locale_lock);
/* For LC_ALL, setlocale is required to return a string which
* encodes the current setting for all categories. The format of
* this string is unspecified, and only the following code, which
* performs both the serialization and deserialization, depends
* on the format, so it can easily be changed if needed. */
if (cat == LC_ALL) {
int i;
if (name) {
struct __locale_struct tmp_locale;
char part[LOCALE_NAME_MAX+1] = "C.UTF-8";
const char *p = name;
for (i=0; i<LC_ALL; i++) {
const char *z = strchrnul(p, ';');
if (z-p <= LOCALE_NAME_MAX) {
memcpy(part, p, z-p);
part[z-p] = 0;
if (*z) p = z+1;
}
lm = __get_locale(i, part);
if (lm == LOC_MAP_FAILED) {
pthread_mutex_unlock(&__locale_lock);
return 0;
}
tmp_locale.cat[i] = lm;
}
__global_locale = tmp_locale;
}
char *s = buf;
const char *part;
int same = 0;
for (i=0; i<LC_ALL; i++) {
const struct __locale_map *lm =
__global_locale.cat[i];
if (lm == __global_locale.cat[0]) same++;
part = lm ? lm->name : "C";
size_t l = strlen(part);
memcpy(s, part, l);
s[l] = ';';
s += l+1;
}
*--s = 0;
pthread_mutex_unlock(&__locale_lock);
return same==LC_ALL ? (char *)part : buf;
}
if (name) {
lm = __get_locale(cat, name);
if (lm == LOC_MAP_FAILED) {
pthread_mutex_unlock(&__locale_lock);
return 0;
}
__global_locale.cat[cat] = lm;
} else {
lm = __global_locale.cat[cat];
}
char *ret = lm ? (char *)lm->name : "C";
pthread_mutex_unlock(&__locale_lock);
return ret;
}

View file

@ -27,7 +27,7 @@
*/
#include "libc/errno.h"
#include "libc/stdio/stdio.h"
#include "libc/str/locale.h"
#include "libc/str/locale.internal.h"
#include "libc/str/str.h"
#include "libc/ctype.h"
#include "libc/thread/tls.h"
@ -37,7 +37,7 @@ static ssize_t vstrfmon_l(char *s, size_t n, locale_t loc, const char *fmt, va_l
{
size_t l;
double x;
int left;
int fill, nogrp, negpar, nosym, left, intl;
int lp, rp, w, fw;
char *s0=s;
for (; n && *fmt; ) {
@ -50,17 +50,29 @@ static ssize_t vstrfmon_l(char *s, size_t n, locale_t loc, const char *fmt, va_l
fmt++;
if (*fmt == '%') goto literal;
fill = ' ';
nogrp = 0;
negpar = 0;
nosym = 0;
left = 0;
for (; ; fmt++) {
switch (*fmt) {
case '=':
fill = *++fmt;
(void)fill;
continue;
case '^':
nogrp = 1;
(void)nogrp;
continue;
case '(':
negpar = 1;
(void)negpar;
case '+':
continue;
case '!':
nosym = 1;
(void)nosym;
continue;
case '-':
left = 1;
@ -78,6 +90,9 @@ static ssize_t vstrfmon_l(char *s, size_t n, locale_t loc, const char *fmt, va_l
if (*fmt=='.') for (rp=0, fmt++; isdigit(*fmt); fmt++)
rp = 10*rp + (*fmt-'0');
intl = *fmt++ == 'i';
(void)intl;
w = lp + 1 + rp;
if (!left && fw>w) w = fw;
@ -112,7 +127,7 @@ ssize_t strfmon(char *restrict s, size_t n, const char *restrict fmt, ...)
ssize_t ret;
va_start(ap, fmt);
ret = vstrfmon_l(s, n, (locale_t)__get_tls()->tib_locale, fmt, ap);
ret = vstrfmon_l(s, n, CURRENT_LOCALE, fmt, ap);
va_end(ap);
return ret;

313
third_party/musl/strftime.c vendored Normal file
View file

@ -0,0 +1,313 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/ctype.h"
#include "libc/limits.h"
#include "libc/stdio/stdio.h"
#include "libc/str/langinfo.h"
#include "libc/str/locale.h"
#include "libc/str/locale.internal.h"
#include "libc/str/nltypes.h"
#include "libc/str/str.h"
#include "libc/time.h"
#include "third_party/musl/time_impl.h"
__static_yoink("musl_libc_notice");
static int is_leap(int y)
{
/* Avoid overflow */
if (y>INT_MAX-1900) y -= 2000;
y += 1900;
return !(y%4) && ((y%100) || !(y%400));
}
static int week_num(const struct tm *tm)
{
int val = (tm->tm_yday + 7U - (tm->tm_wday+6U)%7) / 7;
/* If 1 Jan is just 1-3 days past Monday,
* the previous week is also in this year. */
if ((tm->tm_wday + 371U - tm->tm_yday - 2) % 7 <= 2)
val++;
if (!val) {
val = 52;
/* If 31 December of prev year a Thursday,
* or Friday of a leap year, then the
* prev year has 53 weeks. */
int dec31 = (tm->tm_wday + 7U - tm->tm_yday - 1) % 7;
if (dec31 == 4 || (dec31 == 5 && is_leap(tm->tm_year%400-1)))
val++;
} else if (val == 53) {
/* If 1 January is not a Thursday, and not
* a Wednesday of a leap year, then this
* year has only 52 weeks. */
int jan1 = (tm->tm_wday + 371U - tm->tm_yday) % 7;
if (jan1 != 4 && (jan1 != 3 || !is_leap(tm->tm_year)))
val = 1;
}
return val;
}
const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc, int pad)
{
nl_item item;
long long val;
const char *fmt = "-";
int width = 2, def_pad = '0';
switch (f) {
case 'a':
if (tm->tm_wday > 6U) goto string;
item = ABDAY_1 + tm->tm_wday;
goto nl_strcat;
case 'A':
if (tm->tm_wday > 6U) goto string;
item = DAY_1 + tm->tm_wday;
goto nl_strcat;
case 'h':
case 'b':
if (tm->tm_mon > 11U) goto string;
item = ABMON_1 + tm->tm_mon;
goto nl_strcat;
case 'B':
if (tm->tm_mon > 11U) goto string;
item = MON_1 + tm->tm_mon;
goto nl_strcat;
case 'c':
item = D_T_FMT;
goto nl_strftime;
case 'C':
val = (1900LL+tm->tm_year) / 100;
goto number;
case 'e':
def_pad = '_';
case 'd':
val = tm->tm_mday;
goto number;
case 'D':
fmt = "%m/%d/%y";
goto recu_strftime;
case 'F':
fmt = "%Y-%m-%d";
goto recu_strftime;
case 'g':
case 'G':
val = tm->tm_year + 1900LL;
if (tm->tm_yday < 3 && week_num(tm) != 1) val--;
else if (tm->tm_yday > 360 && week_num(tm) == 1) val++;
if (f=='g') val %= 100;
else width = 4;
goto number;
case 'H':
val = tm->tm_hour;
goto number;
case 'I':
val = tm->tm_hour;
if (!val) val = 12;
else if (val > 12) val -= 12;
goto number;
case 'j':
val = tm->tm_yday+1;
width = 3;
goto number;
case 'm':
val = tm->tm_mon+1;
goto number;
case 'M':
val = tm->tm_min;
goto number;
case 'n':
*l = 1;
return "\n";
case 'p':
item = tm->tm_hour >= 12 ? PM_STR : AM_STR;
goto nl_strcat;
case 'r':
item = T_FMT_AMPM;
goto nl_strftime;
case 'R':
fmt = "%H:%M";
goto recu_strftime;
case 's':
val = __tm_to_secs(tm) - tm->tm_gmtoff;
width = 1;
goto number;
case 'S':
val = tm->tm_sec;
goto number;
case 't':
*l = 1;
return "\t";
case 'T':
fmt = "%H:%M:%S";
goto recu_strftime;
case 'u':
val = tm->tm_wday ? tm->tm_wday : 7;
width = 1;
goto number;
case 'U':
val = (tm->tm_yday + 7U - tm->tm_wday) / 7;
goto number;
case 'W':
val = (tm->tm_yday + 7U - (tm->tm_wday+6U)%7) / 7;
goto number;
case 'V':
val = week_num(tm);
goto number;
case 'w':
val = tm->tm_wday;
width = 1;
goto number;
case 'x':
item = D_FMT;
goto nl_strftime;
case 'X':
item = T_FMT;
goto nl_strftime;
case 'y':
val = (tm->tm_year + 1900LL) % 100;
if (val < 0) val = -val;
goto number;
case 'Y':
val = tm->tm_year + 1900LL;
if (val >= 10000) {
*l = snprintf(*s, sizeof *s, "%lld", val);
return *s;
}
width = 4;
goto number;
case 'z':
if (tm->tm_isdst < 0) {
*l = 0;
return "";
}
*l = snprintf(*s, sizeof *s, "%+.4ld",
tm->tm_gmtoff/3600*100 + tm->tm_gmtoff%3600/60);
return *s;
case 'Z':
if (tm->tm_isdst < 0 || !tm->tm_zone) {
*l = 0;
return "";
}
fmt = tm->tm_zone;
goto string;
case '%':
*l = 1;
return "%";
default:
return 0;
}
number:
switch (pad ? pad : def_pad) {
case '-': *l = snprintf(*s, sizeof *s, "%lld", val); break;
case '_': *l = snprintf(*s, sizeof *s, "%*lld", width, val); break;
case '0':
default: *l = snprintf(*s, sizeof *s, "%0*lld", width, val); break;
}
return *s;
nl_strcat:
fmt = nl_langinfo_l(item, loc);
string:
*l = strlen(fmt);
return fmt;
nl_strftime:
fmt = nl_langinfo_l(item, loc);
recu_strftime:
*l = strftime_l(*s, sizeof *s, fmt, tm, loc);
if (!*l) return 0;
return *s;
}
size_t strftime_l(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm, locale_t loc)
{
size_t l, k;
char buf[100];
char *p;
const char *t;
int pad, plus;
unsigned long width;
for (l=0; l<n; f++) {
if (!*f) {
s[l] = 0;
return l;
}
if (*f != '%') {
s[l++] = *f;
continue;
}
f++;
pad = 0;
if (*f == '-' || *f == '_' || *f == '0') pad = *f++;
if ((plus = (*f == '+'))) f++;
if (isdigit(*f)) {
width = strtoul(f, &p, 10);
} else {
width = 0;
p = (void *)f;
}
if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') {
if (!width && p!=f) width = 1;
} else {
width = 0;
}
f = p;
if (*f == 'E' || *f == 'O') f++;
t = __strftime_fmt_1(&buf, &k, *f, tm, loc, pad);
if (!t) break;
if (width) {
/* Trim off any sign and leading zeros, then
* count remaining digits to determine behavior
* for the + flag. */
if (*t=='+' || *t=='-') t++, k--;
for (; *t=='0' && t[1]-'0'<10U; t++, k--);
if (width < k) width = k;
size_t d;
for (d=0; t[d]-'0'<10U; d++);
if (tm->tm_year < -1900) {
s[l++] = '-';
width--;
} else if (plus && d+(width-k) >= (*p=='C'?3:5)) {
s[l++] = '+';
width--;
}
for (; width > k && l < n; width--)
s[l++] = '0';
}
if (k > n-l) k = n-l;
memcpy(s+l, t, k);
l += k;
}
if (n) {
if (l==n) l=n-1;
s[l] = 0;
}
return 0;
}
size_t strftime(char *restrict s, size_t n, const char *restrict f, const struct tm *restrict tm)
{
return strftime_l(s, n, f, tm, CURRENT_LOCALE);
}

View file

@ -29,248 +29,269 @@
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/ctype.h"
#include "libc/str/langinfo.h"
#include "libc/time.h"
__static_yoink("musl_libc_notice");
char *
strptime(const char *s, const char *f, struct tm *tm)
char *strptime(const char *restrict s, const char *restrict f, struct tm *restrict tm)
{
int i, w, neg, adj, min, range, itemsize, *dest, dummy;
const char *ex, *ss;
int i, w, neg, adj, min, range, *dest, dummy;
const char *ex;
size_t len;
int want_century = 0, century = 0, relyear = 0;
while (*f) {
if (*f != '%') {
if (isspace(*f)) {
for (; *s && isspace(*s); s++);
} else if (*s != *f) {
return 0;
} else {
s++;
}
if (isspace(*f)) for (; *s && isspace(*s); s++);
else if (*s != *f) return 0;
else s++;
f++;
continue;
}
f++;
if (*f == '+')
f++;
if (*f == '+') f++;
if (isdigit(*f)) {
char *new_f;
w = strtoul(f, &new_f, 10);
w=strtoul(f, &new_f, 10);
f = new_f;
} else {
w = -1;
w=-1;
}
adj = 0;
adj=0;
switch (*f++) {
case 'a':
dest = &tm->tm_wday;
ss = (const char *)kWeekdayNameShort;
range = ARRAYLEN(kWeekdayNameShort);
itemsize = sizeof(kWeekdayNameShort[0]);
goto symbolic_range;
case 'A':
dest = &tm->tm_wday;
ss = (const char *)kWeekdayName;
range = ARRAYLEN(kWeekdayName);
itemsize = sizeof(kWeekdayName[0]);
goto symbolic_range;
case 'b':
case 'h':
dest = &tm->tm_mon;
ss = (const char *)kMonthNameShort;
range = ARRAYLEN(kMonthNameShort);
itemsize = sizeof(kMonthNameShort[0]);
goto symbolic_range;
case 'B':
dest = &tm->tm_mon;
ss = (const char *)kMonthName;
range = ARRAYLEN(kMonthName);
itemsize = sizeof(kMonthName[0]);
goto symbolic_range;
case 'c':
s = strptime(s, "%a %b %e %T %Y", tm);
if (!s)
return 0;
case 'a': case 'A':
dest = &tm->tm_wday;
min = ABDAY_1;
range = 7;
goto symbolic_range;
case 'b': case 'B': case 'h':
dest = &tm->tm_mon;
min = ABMON_1;
range = 12;
goto symbolic_range;
case 'c':
s = strptime(s, nl_langinfo(D_T_FMT), tm);
if (!s) return 0;
break;
case 'C':
dest = &century;
if (w<0) w=2;
want_century |= 2;
goto numeric_digits;
case 'd': case 'e':
dest = &tm->tm_mday;
min = 1;
range = 31;
goto numeric_range;
case 'D':
s = strptime(s, "%m/%d/%y", tm);
if (!s) return 0;
break;
case 'F':
/* Use temp buffer to implement the odd requirement
* that entire field be width-limited but the year
* subfield not itself be limited. */
i = 0;
char tmp[20];
if (*s == '-' || *s == '+') tmp[i++] = *s++;
while (*s=='0' && isdigit(s[1])) s++;
for (; *s && i<(size_t)w && i+1<sizeof tmp; i++) {
tmp[i] = *s++;
}
tmp[i] = 0;
char *p = strptime(tmp, "%12Y-%m-%d", tm);
if (!p) return 0;
s -= tmp+i-p;
break;
case 'H':
dest = &tm->tm_hour;
min = 0;
range = 24;
goto numeric_range;
case 'I':
dest = &tm->tm_hour;
min = 1;
range = 12;
goto numeric_range;
case 'j':
dest = &tm->tm_yday;
min = 1;
range = 366;
adj = 1;
goto numeric_range;
case 'm':
dest = &tm->tm_mon;
min = 1;
range = 12;
adj = 1;
goto numeric_range;
case 'M':
dest = &tm->tm_min;
min = 0;
range = 60;
goto numeric_range;
case 'n': case 't':
for (; *s && isspace(*s); s++);
break;
case 'p':
ex = nl_langinfo(AM_STR);
len = strlen(ex);
if (!strncasecmp(s, ex, len)) {
tm->tm_hour %= 12;
s += len;
break;
case 'C':
dest = &century;
if (w < 0)
w = 2;
want_century |= 2;
goto numeric_digits;
case 'd':
case 'e':
dest = &tm->tm_mday;
min = 1;
range = 31;
goto numeric_range;
case 'D':
s = strptime(s, "%m/%d/%y", tm);
if (!s)
return 0;
}
ex = nl_langinfo(PM_STR);
len = strlen(ex);
if (!strncasecmp(s, ex, len)) {
tm->tm_hour %= 12;
tm->tm_hour += 12;
s += len;
break;
case 'H':
dest = &tm->tm_hour;
min = 0;
range = 24;
goto numeric_range;
case 'I':
dest = &tm->tm_hour;
min = 1;
range = 12;
goto numeric_range;
case 'j':
dest = &tm->tm_yday;
min = 1;
range = 366;
adj = 1;
goto numeric_range;
case 'm':
dest = &tm->tm_mon;
min = 1;
range = 12;
adj = 1;
goto numeric_range;
case 'M':
dest = &tm->tm_min;
min = 0;
range = 60;
goto numeric_range;
case 'n':
case 't':
for (; *s && isspace(*s); s++);
break;
case 'p':
ex = "AM";
}
return 0;
case 'r':
s = strptime(s, nl_langinfo(T_FMT_AMPM), tm);
if (!s) return 0;
break;
case 'R':
s = strptime(s, "%H:%M", tm);
if (!s) return 0;
break;
case 's':
/* Parse only. Effect on tm is unspecified
* and presently no effect is implemented.. */
if (*s == '-') s++;
if (!isdigit(*s)) return 0;
while (isdigit(*s)) s++;
break;
case 'S':
dest = &tm->tm_sec;
min = 0;
range = 61;
goto numeric_range;
case 'T':
s = strptime(s, "%H:%M:%S", tm);
if (!s) return 0;
break;
case 'U':
case 'W':
/* Throw away result of %U, %V, %W, %g, and %G. Effect
* is unspecified and there is no clear right choice. */
dest = &dummy;
min = 0;
range = 54;
goto numeric_range;
case 'V':
dest = &dummy;
min = 1;
range = 53;
goto numeric_range;
case 'g':
dest = &dummy;
w = 2;
goto numeric_digits;
case 'G':
dest = &dummy;
if (w<0) w=4;
goto numeric_digits;
case 'u':
dest = &tm->tm_wday;
min = 1;
range = 7;
goto numeric_range;
case 'w':
dest = &tm->tm_wday;
min = 0;
range = 7;
goto numeric_range;
case 'x':
s = strptime(s, nl_langinfo(D_FMT), tm);
if (!s) return 0;
break;
case 'X':
s = strptime(s, nl_langinfo(T_FMT), tm);
if (!s) return 0;
break;
case 'y':
dest = &relyear;
w = 2;
want_century |= 1;
goto numeric_digits;
case 'Y':
dest = &tm->tm_year;
if (w<0) w=4;
adj = 1900;
want_century = 0;
goto numeric_digits;
case 'z':
if (*s == '+') neg = 0;
else if (*s == '-') neg = 1;
else return 0;
for (i=0; i<4; i++) if (!isdigit(s[1+i])) return 0;
tm->tm_gmtoff = (s[1]-'0')*36000+(s[2]-'0')*3600
+ (s[3]-'0')*600 + (s[4]-'0')*60;
if (neg) tm->tm_gmtoff = -tm->tm_gmtoff;
s += 5;
break;
case 'Z':
if (!strncmp(s, tzname[0], len = strlen(tzname[0]))) {
tm->tm_isdst = 0;
s += len;
} else if (!strncmp(s, tzname[1], len=strlen(tzname[1]))) {
tm->tm_isdst = 1;
s += len;
} else {
/* FIXME: is this supposed to be an error? */
while ((*s|32)-'a' <= 'z'-'a') s++;
}
break;
case '%':
if (*s++ != '%') return 0;
break;
default:
return 0;
numeric_range:
if (!isdigit(*s)) return 0;
*dest = 0;
for (i=1; i<=min+range && isdigit(*s); i*=10)
*dest = *dest * 10 + *s++ - '0';
if (*dest - min >= (unsigned)range) return 0;
*dest -= adj;
switch((char *)dest - (char *)tm) {
case offsetof(struct tm, tm_yday):
;
}
goto update;
numeric_digits:
neg = 0;
if (*s == '+') s++;
else if (*s == '-') neg=1, s++;
if (!isdigit(*s)) return 0;
for (*dest=i=0; i<w && isdigit(*s); i++)
*dest = *dest * 10 + *s++ - '0';
if (neg) *dest = -*dest;
*dest -= adj;
goto update;
symbolic_range:
for (i=2*range-1; i>=0; i--) {
ex = nl_langinfo(min+i);
len = strlen(ex);
if (!strncasecmp(s, ex, len)) {
tm->tm_hour %= 12;
s += len;
break;
}
ex = "PM";
len = strlen(ex);
if (!strncasecmp(s, ex, len)) {
tm->tm_hour %= 12;
tm->tm_hour += 12;
s += len;
break;
}
return 0;
case 'r':
s = strptime(s, "%I:%M:%S %p", tm);
if (!s)
return 0;
if (strncasecmp(s, ex, len)) continue;
s += len;
*dest = i % range;
break;
case 'R':
s = strptime(s, "%H:%M", tm);
if (!s)
return 0;
break;
case 'S':
dest = &tm->tm_sec;
min = 0;
range = 61;
goto numeric_range;
case 'T':
s = strptime(s, "%H:%M:%S", tm);
if (!s)
return 0;
break;
case 'U':
case 'W':
/* Throw away result, for now. (FIXME?) */
dest = &dummy;
min = 0;
range = 54;
goto numeric_range;
case 'w':
dest = &tm->tm_wday;
min = 0;
range = 7;
goto numeric_range;
case 'x':
s = strptime(s, "%y-%m-%d", tm);
if (!s)
return 0;
break;
case 'X':
s = strptime(s, "%H:%M:%S", tm);
if (!s)
return 0;
break;
case 'y':
dest = &relyear;
w = 2;
want_century |= 1;
goto numeric_digits;
case 'Y':
dest = &tm->tm_year;
if (w < 0)
w = 4;
adj = 1900;
want_century = 0;
goto numeric_digits;
case '%':
if (*s++ != '%')
return 0;
break;
default:
return 0;
numeric_range:
if (!isdigit(*s))
return 0;
*dest = 0;
for (i = 1; i <= min + range && isdigit(*s); i *= 10) {
*dest = *dest * 10 + *s++ - '0';
}
if (*dest - min >= (unsigned)range)
return 0;
*dest -= adj;
switch ((char *)dest - (char *)tm) {
case offsetof(struct tm, tm_yday):;
}
goto update;
numeric_digits:
neg = 0;
if (*s == '+')
s++;
else if (*s == '-')
neg = 1, s++;
if (!isdigit(*s))
return 0;
for (*dest = i = 0; i < w && isdigit(*s); i++)
*dest = *dest * 10 + *s++ - '0';
if (neg)
*dest = -*dest;
*dest -= adj;
goto update;
symbolic_range:
for (i = 0; i < range; i--) {
ex = &ss[i * itemsize];
len = strlen(ex);
if (strncasecmp(s, ex, len)) {
s += len;
*dest = i;
break;
}
}
if (i == range)
return 0;
goto update;
update:
// FIXME
donothing;
}
if (i<0) return 0;
goto update;
update:
//FIXME
;
}
}
if (want_century) {
tm->tm_year = relyear;
if (want_century & 2) {
tm->tm_year += century * 100 - 1900;
} else if (tm->tm_year <= 68) {
tm->tm_year += 100;
}
if (want_century & 2) tm->tm_year += century * 100 - 1900;
else if (tm->tm_year <= 68) tm->tm_year += 100;
}
return (char *)s;
}

19
third_party/musl/time_impl.h vendored Normal file
View file

@ -0,0 +1,19 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_TIME_IMPL_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_TIME_IMPL_H_
#include "libc/time.h"
#include "libc/str/locale.h"
#include "libc/calls/weirdtypes.h"
COSMOPOLITAN_C_START_
int __days_in_month(int, int);
int __month_to_secs(int, int);
long long __year_to_secs(long long, int *);
long long __tm_to_secs(const struct tm *);
const char *__tm_to_tzname(const struct tm *);
int __secs_to_tm(long long, struct tm *);
void __secs_to_zone(long long, int, int *, long *, long *, const char **);
const char *__strftime_fmt_1(char (*)[100], size_t *, int, const struct tm *, locale_t, int);
extern const char __utc[];
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_TIME_IMPL_H_ */

39
third_party/musl/uselocale.c vendored Normal file
View file

@ -0,0 +1,39 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
locale_t uselocale(locale_t new)
{
locale_t old = CURRENT_LOCALE;
locale_t global = &__global_locale;
if (new) CURRENT_LOCALE = new == LC_GLOBAL_LOCALE ? global : new;
return old == global ? LC_GLOBAL_LOCALE : old;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,41 +25,41 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/str/mb.internal.h"
#include "libc/str/str.h"
#include <stdlib.h>
#include <wchar.h>
#include <errno.h>
#include "multibyte.h"
__static_yoink("musl_libc_notice");
size_t wcrtomb(char *s, wchar_t wc, mbstate_t *st) {
if (!s)
return 1;
if ((unsigned)wc < 0x80) {
*s = wc;
return 1;
} else if (MB_CUR_MAX == 1) {
if (!IS_CODEUNIT(wc)) {
errno = EILSEQ;
return -1;
}
*s = wc;
return 1;
} else if ((unsigned)wc < 0x800) {
*s++ = 0xc0 | (wc >> 6);
*s = 0x80 | (wc & 0x3f);
return 2;
} else if ((unsigned)wc < 0xd800 || (unsigned)wc - 0xe000 < 0x2000) {
*s++ = 0xe0 | (wc >> 12);
*s++ = 0x80 | ((wc >> 6) & 0x3f);
*s = 0x80 | (wc & 0x3f);
return 3;
} else if ((unsigned)wc - 0x10000 < 0x100000) {
*s++ = 0xf0 | (wc >> 18);
*s++ = 0x80 | ((wc >> 12) & 0x3f);
*s++ = 0x80 | ((wc >> 6) & 0x3f);
*s = 0x80 | (wc & 0x3f);
return 4;
}
errno = EILSEQ;
return -1;
size_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st)
{
if (!s) return 1;
if ((unsigned)wc < 0x80) {
*s = wc;
return 1;
} else if (MB_CUR_MAX == 1) {
if (!IS_CODEUNIT(wc)) {
errno = EILSEQ;
return -1;
}
*s = wc;
return 1;
} else if ((unsigned)wc < 0x800) {
*s++ = 0xc0 | (wc>>6);
*s = 0x80 | (wc&0x3f);
return 2;
} else if ((unsigned)wc < 0xd800 || (unsigned)wc-0xe000 < 0x2000) {
*s++ = 0xe0 | (wc>>12);
*s++ = 0x80 | ((wc>>6)&0x3f);
*s = 0x80 | (wc&0x3f);
return 3;
} else if ((unsigned)wc-0x10000 < 0x100000) {
*s++ = 0xf0 | (wc>>18);
*s++ = 0x80 | ((wc>>12)&0x3f);
*s++ = 0x80 | ((wc>>6)&0x3f);
*s = 0x80 | (wc&0x3f);
return 4;
}
errno = EILSEQ;
return -1;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,65 +25,71 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/str/mb.internal.h"
#include "third_party/musl/time_impl.h"
#include "libc/str/str.h"
#include "libc/str/locale.internal.h"
__static_yoink("musl_libc_notice");
size_t mbrtowc(wchar_t *wc, const char *src, size_t n, mbstate_t *st) {
static unsigned internal_state;
long wut;
unsigned c;
const unsigned char *s = (const void *)src;
const unsigned N = n;
wchar_t dummy;
if (!st)
st = (void *)&internal_state;
c = *(unsigned *)st;
if (!s) {
if (c)
goto ilseq;
return 0;
} else if (!wc) {
wc = &dummy;
}
if (!n)
return -2;
if (!c) {
if (*s < 0x80)
return !!(*wc = *s);
if (MB_CUR_MAX == 1)
return (*wc = CODEUNIT(*s)), 1;
if (*s - SA > SB - SA)
goto ilseq;
wut = *s++ - SA;
wut = MAX(0, MIN(ARRAYLEN(kMbBittab) - 1, wut));
c = kMbBittab[wut];
n--;
}
if (n) {
if (OOB(c, *s))
goto ilseq;
loop:
c = c << 6 | (*s++ - 0x80);
n--;
if (!(c & (1U << 31))) {
*(unsigned *)st = 0;
*wc = c;
return N - n;
}
if (n) {
if (*s - 0x80u >= 0x40)
goto ilseq;
goto loop;
}
}
*(unsigned *)st = c;
return -2;
ilseq:
*(unsigned *)st = 0;
errno = EILSEQ;
return -1;
size_t wcsftime_l(wchar_t *restrict s, size_t n, const wchar_t *restrict f, const struct tm *restrict tm, locale_t loc)
{
size_t l, k;
char buf[100];
wchar_t wbuf[100];
wchar_t *p;
const char *t_mb;
const wchar_t *t;
int pad, plus;
unsigned long width;
for (l=0; l<n; f++) {
if (!*f) {
s[l] = 0;
return l;
}
if (*f != '%') {
s[l++] = *f;
continue;
}
f++;
pad = 0;
if (*f == '-' || *f == '_' || *f == '0') pad = *f++;
if ((plus = (*f == '+'))) f++;
width = wcstoul(f, &p, 10);
if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') {
if (!width && p!=f) width = 1;
} else {
width = 0;
}
f = p;
if (*f == 'E' || *f == 'O') f++;
t_mb = __strftime_fmt_1(&buf, &k, *f, tm, loc, pad);
if (!t_mb) break;
k = mbstowcs(wbuf, t_mb, sizeof wbuf / sizeof *wbuf);
if (k == (size_t)-1) return 0;
t = wbuf;
if (width) {
for (; *t=='+' || *t=='-' || (*t=='0'&&t[1]); t++, k--);
width--;
if (plus && tm->tm_year >= 10000-1900)
s[l++] = '+';
else if (tm->tm_year < -1900)
s[l++] = '-';
else
width++;
for (; width > k && l < n; width--)
s[l++] = '0';
}
if (k >= n-l) k = n-l;
wmemcpy(s+l, t, k);
l += k;
}
if (n) {
if (l==n) l=n-1;
s[l] = 0;
}
return 0;
}
size_t wcsftime(wchar_t *restrict wcs, size_t n, const wchar_t *restrict f, const struct tm *restrict tm)
{
return wcsftime_l(wcs, n, f, tm, CURRENT_LOCALE);
}

63
third_party/musl/wcsnrtombs.c vendored Normal file
View file

@ -0,0 +1,63 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <wchar.h>
#include <limits.h>
#include <string.h>
__static_yoink("musl_libc_notice");
size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st)
{
const wchar_t *ws = *wcs;
size_t cnt = 0;
if (!dst) n=0;
while (ws && wn) {
char tmp[MB_LEN_MAX];
size_t l = wcrtomb(n<MB_LEN_MAX ? tmp : dst, *ws, 0);
if (l==-1) {
cnt = -1;
break;
}
if (dst) {
if (n<MB_LEN_MAX) {
if (l>n) break;
memcpy(dst, tmp, l);
}
dst += l;
n -= l;
}
if (!*ws) {
ws = 0;
break;
}
ws++;
wn--;
cnt += l;
}
if (dst) *wcs = ws;
return cnt;
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,28 +25,59 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/str/mb.internal.h"
#include <wchar.h>
__static_yoink("musl_libc_notice");
#define C(x) (x < 2 ? -1 : (R(0x80, 0xc0) | x))
#define D(x) C((x + 16))
#define E(x) \
((x == 0 ? R(0xa0, 0xc0) \
: x == 0xd ? R(0x80, 0xa0) \
: R(0x80, 0xc0)) | \
(R(0x80, 0xc0) >> 6) | x)
#define F(x) \
((x >= 5 ? 0 \
: x == 0 ? R(0x90, 0xc0) \
: x == 4 ? R(0x80, 0x90) \
: R(0x80, 0xc0)) | \
(R(0x80, 0xc0) >> 6) | (R(0x80, 0xc0) >> 12) | x)
const uint32_t kMbBittab[51 /* ?! */] = {
C(0x2), C(0x3), C(0x4), C(0x5), C(0x6), C(0x7), C(0x8), C(0x9), C(0xa),
C(0xb), C(0xc), C(0xd), C(0xe), C(0xf), D(0x0), D(0x1), D(0x2), D(0x3),
D(0x4), D(0x5), D(0x6), D(0x7), D(0x8), D(0x9), D(0xa), D(0xb), D(0xc),
D(0xd), D(0xe), D(0xf), E(0x0), E(0x1), E(0x2), E(0x3), E(0x4), E(0x5),
E(0x6), E(0x7), E(0x8), E(0x9), E(0xa), E(0xb), E(0xc), E(0xd), E(0xe),
E(0xf), F(0x0), F(0x1), F(0x2), F(0x3), F(0x4),
};
size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstate_t *restrict st)
{
const wchar_t *ws2;
char buf[4];
size_t N = n, l;
if (!s) {
for (n=0, ws2=*ws; *ws2; ws2++) {
if (*ws2 >= 0x80u) {
l = wcrtomb(buf, *ws2, 0);
if (!(l+1)) return -1;
n += l;
} else n++;
}
return n;
}
while (n>=4) {
if (**ws-1u >= 0x7fu) {
if (!**ws) {
*s = 0;
*ws = 0;
return N-n;
}
l = wcrtomb(s, **ws, 0);
if (!(l+1)) return -1;
s += l;
n -= l;
} else {
*s++ = **ws;
n--;
}
(*ws)++;
}
while (n) {
if (**ws-1u >= 0x7fu) {
if (!**ws) {
*s = 0;
*ws = 0;
return N-n;
}
l = wcrtomb(buf, **ws, 0);
if (!(l+1)) return -1;
if (l>n) return N-n;
wcrtomb(s, **ws, 0);
s += l;
n -= l;
} else {
*s++ = **ws;
n--;
}
(*ws)++;
}
return N;
}

35
third_party/musl/wcstombs.c vendored Normal file
View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <stdlib.h>
#include <wchar.h>
__static_yoink("musl_libc_notice");
size_t wcstombs(char *restrict s, const wchar_t *restrict ws, size_t n)
{
return wcsrtombs(s, &(const wchar_t *){ws}, n, 0);
}

View file

@ -1,5 +1,5 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
@ -25,16 +25,15 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/limits.h"
#include "libc/stdio/stdio.h"
#include "libc/str/mb.internal.h"
#include "libc/str/str.h"
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>
#include "multibyte.h"
__static_yoink("musl_libc_notice");
int wctob(wint_t c) {
if (c < 128U)
return c;
if (MB_CUR_MAX == 1 && IS_CODEUNIT(c))
return (unsigned char)c;
return EOF;
int wctob(wint_t c)
{
if (c < 128U) return c;
if (MB_CUR_MAX==1 && IS_CODEUNIT(c)) return (unsigned char)c;
return EOF;
}

36
third_party/musl/wctomb.c vendored Normal file
View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
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.
*/
#include <stdlib.h>
#include <wchar.h>
__static_yoink("musl_libc_notice");
int wctomb(char *s, wchar_t wc)
{
if (!s) return 0;
return wcrtomb(s, wc, 0);
}

View file

@ -26,7 +26,8 @@ THIRD_PARTY_PCRE_A_DIRECTDEPS = \
LIBC_RUNTIME \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV
LIBC_SYSV \
THIRD_PARTY_MUSL \
THIRD_PARTY_PCRE_A_DEPS := \
$(call uniq,$(foreach x,$(THIRD_PARTY_PCRE_A_DIRECTDEPS),$($(x))))

View file

@ -476,6 +476,7 @@ THIRD_PARTY_PYTHON_STAGE1_A_DIRECTDEPS = \
LIBC_X \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_GETOPT \
THIRD_PARTY_MUSL \
THIRD_PARTY_TZ \
THIRD_PARTY_XED \
TOOL_BUILD_LIB \
@ -528,7 +529,6 @@ THIRD_PARTY_PYTHON_STAGE2_A_SRCS = \
third_party/python/runpythonmodule.c \
third_party/python/launch.c \
third_party/python/Objects/fromfd.c \
third_party/python/Objects/unicodeobject-deadcode.c \
third_party/python/Modules/_bisectmodule.c \
third_party/python/Modules/_bz2module.c \
third_party/python/Modules/_codecsmodule.c \
@ -1748,7 +1748,6 @@ THIRD_PARTY_PYTHON_PYTEST_A_DIRECTDEPS = \
THIRD_PARTY_PYTHON_PYTEST_PYMAINS = \
third_party/python/Lib/test/signalinterproctester.py \
third_party/python/Lib/test/test___future__.py \
third_party/python/Lib/test/test__locale.py \
third_party/python/Lib/test/test__opcode.py \
third_party/python/Lib/test/test_abc.py \
third_party/python/Lib/test/test_abstract_numbers.py \
@ -1966,7 +1965,6 @@ THIRD_PARTY_PYTHON_PYTEST_PYMAINS = \
third_party/python/Lib/test/test_string.py \
third_party/python/Lib/test/test_string_literals.py \
third_party/python/Lib/test/test_stringprep.py \
third_party/python/Lib/test/test_strptime.py \
third_party/python/Lib/test/test_strtod.py \
third_party/python/Lib/test/test_struct.py \
third_party/python/Lib/test/test_structmembers.py \
@ -2200,8 +2198,8 @@ o/$(MODE)/third_party/python/Lib/test/test_binhex.py.runs: $(PYTHONTESTER)
o/$(MODE)/third_party/python/Lib/test/test_capi.py.runs: $(PYTHONTESTER)
@$(COMPILE) -ACHECK -wtT$@ $(PYHARNESSARGS) $(PYTHONTESTER) -m test.test_capi $(PYTESTARGS)
o/$(MODE)/third_party/python/Lib/test/test__locale.py.runs: $(PYTHONTESTER)
@$(COMPILE) -ACHECK -wtT$@ $(PYHARNESSARGS) $(PYTHONTESTER) -m test.test__locale $(PYTESTARGS)
# o/$(MODE)/third_party/python/Lib/test/test__locale.py.runs: $(PYTHONTESTER)
# @$(COMPILE) -ACHECK -wtT$@ $(PYHARNESSARGS) $(PYTHONTESTER) -m test.test__locale $(PYTESTARGS)
o/$(MODE)/third_party/python/Lib/test/test_binop.py.runs: $(PYTHONTESTER)
@$(COMPILE) -ACHECK -wtT$@ $(PYHARNESSARGS) $(PYTHONTESTER) -m test.test_binop $(PYTESTARGS)

View file

@ -2,6 +2,7 @@
#define Py_ATOMIC_H
#include "libc/assert.h"
#include "third_party/python/Include/dynamic_annotations.h"
#include "libc/intrin/atomic.h"
#include "third_party/python/pyconfig.h"
/* This is modeled after the atomics interface from C1x, according to

View file

@ -1754,11 +1754,11 @@ SUBPATTERN None 0 0
self.skipTest('test needs %s locale' % loc)
re.purge()
self.check_en_US_iso88591()
# self.check_en_US_iso88591()
self.check_en_US_utf8()
re.purge()
self.check_en_US_utf8()
self.check_en_US_iso88591()
# self.check_en_US_iso88591()
def check_en_US_iso88591(self):
locale.setlocale(locale.LC_CTYPE, 'en_US.iso88591')

View file

@ -52,6 +52,8 @@
#include "third_party/python/Include/warnings.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/musl/netdb.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/af.h"
#include "third_party/python/pyconfig.h"
PYTHON_PROVIDE("_socket");
@ -1043,16 +1045,15 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int
set_gaierror(error);
return -1;
}
switch (res->ai_family) {
case AF_INET:
if (res->ai_family == AF_INET) {
siz = 4;
break;
}
#ifdef ENABLE_IPV6
case AF_INET6:
else if (res->ai_family == AF_INET6) {
siz = 16;
break;
}
#endif
default:
else {
freeaddrinfo(res);
PyErr_SetString(PyExc_OSError,
"unsupported address family");
@ -1159,17 +1160,14 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int
addr_ret_size = res->ai_addrlen;
memcpy((char *) addr_ret, res->ai_addr, addr_ret_size);
freeaddrinfo(res);
switch (addr_ret->sa_family) {
case AF_INET:
if (addr_ret->sa_family == AF_INET)
return 4;
#ifdef ENABLE_IPV6
case AF_INET6:
if (addr_ret->sa_family == AF_INET6)
return 16;
#endif
default:
PyErr_SetString(PyExc_OSError, "unknown address family");
return -1;
}
PyErr_SetString(PyExc_OSError, "unknown address family");
return -1;
}

View file

@ -3,6 +3,7 @@
#include "libc/sock/sock.h"
#include "libc/sock/struct/sockaddr.h"
#include "third_party/python/Include/object.h"
#include "libc/sock/struct/sockaddr6.h"
#include "third_party/python/Include/pytime.h"
COSMOPOLITAN_C_START_

Some files were not shown because too many files have changed in this diff Show more