diff options
-rw-r--r-- | libc/misc/locale/locale.c | 95 |
1 files changed, 92 insertions, 3 deletions
diff --git a/libc/misc/locale/locale.c b/libc/misc/locale/locale.c index fd587429b..fd52782c1 100644 --- a/libc/misc/locale/locale.c +++ b/libc/misc/locale/locale.c @@ -17,7 +17,6 @@ /* TODO: * Implement the shared mmap code so non-mmu platforms can use this. - * Implement nl_langinfo() for the stub locale support. * Add some basic collate functionality similar to what the previous * locale support had (8-bit codesets only). */ @@ -481,11 +480,101 @@ void _locale_set(const unsigned char *p) /**********************************************************************/ #ifdef L_nl_langinfo -#ifndef __LOCALE_C_ONLY - #include <langinfo.h> #include <nl_types.h> +#ifdef __LOCALE_C_ONLY + +/* We need to index 300 bytes of data, so you might initially think we + * need to store the offsets in shorts. But since the offset of the + * 64th item is 231, we'll store "offset - 64" for all items >= 64 + * and always calculate the data offset as "offset[i] + (i & 64)". + * This allows us to pack the data offsets in an unsigned char while + * also avoiding an "if". + * + * Note: Category order is assumed to be: + * ctype, numeric, monetary, time, collate, messages, all + */ + + +/* Combine the data to avoid size penalty for seperate char arrays when + * compiler aligns objects. The original code is left in as documentation. */ +#define cat_start nl_data +#define C_locale_data nl_data + LC_ALL + 1 + 78 + +static const unsigned char nl_data[LC_ALL + 1 + 78 + 300] = { +/* static const unsigned char cat_start[LC_ALL + 1] = { */ + '\x00', '\x01', '\x04', '\x1a', '\x4c', '\x4c', '\x4e', +/* }; */ +/* static const unsigned char item_offset[78] = { */ + '\x00', '\x06', '\x07', '\x07', '\x07', '\x07', '\x07', '\x07', + '\x07', '\x07', '\x07', '\x08', '\x08', '\x08', '\x08', '\x08', + '\x08', '\x08', '\x08', '\x08', '\x08', '\x08', '\x08', '\x08', + '\x08', '\x0a', '\x0c', '\x10', '\x14', '\x18', '\x1c', '\x20', + '\x24', '\x28', '\x2f', '\x36', '\x3e', '\x48', '\x51', '\x58', + '\x61', '\x65', '\x69', '\x6d', '\x71', '\x75', '\x79', '\x7d', + '\x81', '\x85', '\x89', '\x8d', '\x91', '\x99', '\xa2', '\xa8', + '\xae', '\xb2', '\xb7', '\xbc', '\xc3', '\xcd', '\xd5', '\xde', + '\xa7', '\xaa', '\xad', '\xc2', '\xcb', '\xd4', '\xdf', '\xdf', + '\xdf', '\xdf', '\xdf', '\xdf', '\xe0', '\xe6', +/* }; */ +/* static const unsigned char C_locale_data[300] = { */ + 'A', 'S', 'C', 'I', 'I', '\x00', '.', '\x00', + '\x7f', '\x00', '-', '\x00', 'S', 'u', 'n', '\x00', + 'M', 'o', 'n', '\x00', 'T', 'u', 'e', '\x00', + 'W', 'e', 'd', '\x00', 'T', 'h', 'u', '\x00', + 'F', 'r', 'i', '\x00', 'S', 'a', 't', '\x00', + 'S', 'u', 'n', 'd', 'a', 'y', '\x00', 'M', + 'o', 'n', 'd', 'a', 'y', '\x00', 'T', 'u', + 'e', 's', 'd', 'a', 'y', '\x00', 'W', 'e', + 'd', 'n', 'e', 's', 'd', 'a', 'y', '\x00', + 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', + '\x00', 'F', 'r', 'i', 'd', 'a', 'y', '\x00', + 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', + '\x00', 'J', 'a', 'n', '\x00', 'F', 'e', 'b', + '\x00', 'M', 'a', 'r', '\x00', 'A', 'p', 'r', + '\x00', 'M', 'a', 'y', '\x00', 'J', 'u', 'n', + '\x00', 'J', 'u', 'l', '\x00', 'A', 'u', 'g', + '\x00', 'S', 'e', 'p', '\x00', 'O', 'c', 't', + '\x00', 'N', 'o', 'v', '\x00', 'D', 'e', 'c', + '\x00', 'J', 'a', 'n', 'u', 'a', 'r', 'y', + '\x00', 'F', 'e', 'b', 'r', 'u', 'a', 'r', + 'y', '\x00', 'M', 'a', 'r', 'c', 'h', '\x00', + 'A', 'p', 'r', 'i', 'l', '\x00', 'M', 'a', + 'y', '\x00', 'J', 'u', 'n', 'e', '\x00', 'J', + 'u', 'l', 'y', '\x00', 'A', 'u', 'g', 'u', + 's', 't', '\x00', 'S', 'e', 'p', 't', 'e', + 'm', 'b', 'e', 'r', '\x00', 'O', 'c', 't', + 'o', 'b', 'e', 'r', '\x00', 'N', 'o', 'v', + 'e', 'm', 'b', 'e', 'r', '\x00', 'D', 'e', + 'c', 'e', 'm', 'b', 'e', 'r', '\x00', 'A', + 'M', '\x00', 'P', 'M', '\x00', '%', 'a', ' ', + '%', 'b', ' ', '%', 'e', ' ', '%', 'H', + ':', '%', 'M', ':', '%', 'S', ' ', '%', + 'Y', '\x00', '%', 'm', '/', '%', 'd', '/', + '%', 'y', '\x00', '%', 'H', ':', '%', 'M', + ':', '%', 'S', '\x00', '%', 'I', ':', '%', + 'M', ':', '%', 'S', ' ', '%', 'p', '\x00', + '^', '[', 'y', 'Y', ']', '\x00', '^', '[', + 'n', 'N', ']', '\x00', +}; + +char *nl_langinfo(nl_item item) +{ + unsigned int c; + unsigned int i; + + if ((c = _NL_ITEM_CATEGORY(item)) < LC_ALL) { + if ((i = cat_start[c] + _NL_ITEM_INDEX(item)) < cat_start[c+1]) { +/* return (char *) C_locale_data + item_offset[i] + (i & 64); */ + return (char *) C_locale_data + nl_data[LC_ALL+1+i] + (i & 64); + } + } + return (char *) cat_start; /* Conveniently, this is the empty string. */ +} + +#else /* __LOCALE_C_ONLY */ + static const char empty[] = ""; char *nl_langinfo(nl_item item) |