diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/internal/locale_impl.h | 6 | ||||
-rw-r--r-- | src/locale/__lctrans.c | 20 | ||||
-rw-r--r-- | src/locale/__mo_lookup.c | 38 | ||||
-rw-r--r-- | src/locale/__setlocalecat.c | 7 |
4 files changed, 71 insertions, 0 deletions
diff --git a/src/internal/locale_impl.h b/src/internal/locale_impl.h index 0ee72d3e..9142f0c2 100644 --- a/src/internal/locale_impl.h +++ b/src/internal/locale_impl.h @@ -13,6 +13,12 @@ struct __locale_map { }; int __setlocalecat(locale_t, 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 *); + +#define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)-2]) +#define LCTRANS_CUR(msg) __lctrans_cur(msg) #define CURRENT_LOCALE \ (libc.uselocale_cnt ? __pthread_self()->locale : &libc.global_locale) diff --git a/src/locale/__lctrans.c b/src/locale/__lctrans.c new file mode 100644 index 00000000..2769c084 --- /dev/null +++ b/src/locale/__lctrans.c @@ -0,0 +1,20 @@ +#include <locale.h> +#include "locale_impl.h" +#include "libc.h" + +const char *dummy(const char *msg, const struct __locale_map *lm) +{ + return msg; +} + +weak_alias(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-2]); +} diff --git a/src/locale/__mo_lookup.c b/src/locale/__mo_lookup.c new file mode 100644 index 00000000..8112d91c --- /dev/null +++ b/src/locale/__mo_lookup.c @@ -0,0 +1,38 @@ +#include <stdint.h> +#include <string.h> + +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 os = swapc(mo[o+2*(b+n/2)+1], sw); + if (os >= size) return 0; + int sign = strcmp(s, (char *)p + os); + if (!sign) { + uint32_t ts = swapc(mo[t+2*(b+n/2)+1], sw); + if (ts >= size) 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; +} diff --git a/src/locale/__setlocalecat.c b/src/locale/__setlocalecat.c index bbecde41..44385e02 100644 --- a/src/locale/__setlocalecat.c +++ b/src/locale/__setlocalecat.c @@ -4,6 +4,13 @@ #include "libc.h" #include "atomic.h" +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; +} + const unsigned char *__map_file(const char *, size_t *); int __munmap(void *, size_t); char *__strchrnul(const char *, int); |