045ddc8991
As requested by NamJae Jeon, this patch (as1503) changes the name of the "maxlen" parameters to "maxout" in the various UTF conversion routines. This should make the role of that parameter more clear. The patch also renames the "len" parameters to "inlen", for the same reason. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Reviewed-by: NamJae Jeon <linkinjeon@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
547 lines
16 KiB
C
547 lines
16 KiB
C
/*
|
|
* linux/fs/nls/nls_base.c
|
|
*
|
|
* Native language support--charsets and unicode translations.
|
|
* By Gordon Chaffee 1996, 1997
|
|
*
|
|
* Unicode based case conversion 1999 by Wolfram Pienkoss
|
|
*
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/string.h>
|
|
#include <linux/nls.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/kmod.h>
|
|
#include <linux/spinlock.h>
|
|
#include <asm/byteorder.h>
|
|
|
|
static struct nls_table default_table;
|
|
static struct nls_table *tables = &default_table;
|
|
static DEFINE_SPINLOCK(nls_lock);
|
|
|
|
/*
|
|
* Sample implementation from Unicode home page.
|
|
* http://www.stonehand.com/unicode/standard/fss-utf.html
|
|
*/
|
|
struct utf8_table {
|
|
int cmask;
|
|
int cval;
|
|
int shift;
|
|
long lmask;
|
|
long lval;
|
|
};
|
|
|
|
static const struct utf8_table utf8_table[] =
|
|
{
|
|
{0x80, 0x00, 0*6, 0x7F, 0, /* 1 byte sequence */},
|
|
{0xE0, 0xC0, 1*6, 0x7FF, 0x80, /* 2 byte sequence */},
|
|
{0xF0, 0xE0, 2*6, 0xFFFF, 0x800, /* 3 byte sequence */},
|
|
{0xF8, 0xF0, 3*6, 0x1FFFFF, 0x10000, /* 4 byte sequence */},
|
|
{0xFC, 0xF8, 4*6, 0x3FFFFFF, 0x200000, /* 5 byte sequence */},
|
|
{0xFE, 0xFC, 5*6, 0x7FFFFFFF, 0x4000000, /* 6 byte sequence */},
|
|
{0, /* end of table */}
|
|
};
|
|
|
|
#define UNICODE_MAX 0x0010ffff
|
|
#define PLANE_SIZE 0x00010000
|
|
|
|
#define SURROGATE_MASK 0xfffff800
|
|
#define SURROGATE_PAIR 0x0000d800
|
|
#define SURROGATE_LOW 0x00000400
|
|
#define SURROGATE_BITS 0x000003ff
|
|
|
|
int utf8_to_utf32(const u8 *s, int inlen, unicode_t *pu)
|
|
{
|
|
unsigned long l;
|
|
int c0, c, nc;
|
|
const struct utf8_table *t;
|
|
|
|
nc = 0;
|
|
c0 = *s;
|
|
l = c0;
|
|
for (t = utf8_table; t->cmask; t++) {
|
|
nc++;
|
|
if ((c0 & t->cmask) == t->cval) {
|
|
l &= t->lmask;
|
|
if (l < t->lval || l > UNICODE_MAX ||
|
|
(l & SURROGATE_MASK) == SURROGATE_PAIR)
|
|
return -1;
|
|
*pu = (unicode_t) l;
|
|
return nc;
|
|
}
|
|
if (inlen <= nc)
|
|
return -1;
|
|
s++;
|
|
c = (*s ^ 0x80) & 0xFF;
|
|
if (c & 0xC0)
|
|
return -1;
|
|
l = (l << 6) | c;
|
|
}
|
|
return -1;
|
|
}
|
|
EXPORT_SYMBOL(utf8_to_utf32);
|
|
|
|
int utf32_to_utf8(unicode_t u, u8 *s, int maxout)
|
|
{
|
|
unsigned long l;
|
|
int c, nc;
|
|
const struct utf8_table *t;
|
|
|
|
if (!s)
|
|
return 0;
|
|
|
|
l = u;
|
|
if (l > UNICODE_MAX || (l & SURROGATE_MASK) == SURROGATE_PAIR)
|
|
return -1;
|
|
|
|
nc = 0;
|
|
for (t = utf8_table; t->cmask && maxout; t++, maxout--) {
|
|
nc++;
|
|
if (l <= t->lmask) {
|
|
c = t->shift;
|
|
*s = (u8) (t->cval | (l >> c));
|
|
while (c > 0) {
|
|
c -= 6;
|
|
s++;
|
|
*s = (u8) (0x80 | ((l >> c) & 0x3F));
|
|
}
|
|
return nc;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
EXPORT_SYMBOL(utf32_to_utf8);
|
|
|
|
static inline void put_utf16(wchar_t *s, unsigned c, enum utf16_endian endian)
|
|
{
|
|
switch (endian) {
|
|
default:
|
|
*s = (wchar_t) c;
|
|
break;
|
|
case UTF16_LITTLE_ENDIAN:
|
|
*s = __cpu_to_le16(c);
|
|
break;
|
|
case UTF16_BIG_ENDIAN:
|
|
*s = __cpu_to_be16(c);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int utf8s_to_utf16s(const u8 *s, int inlen, enum utf16_endian endian,
|
|
wchar_t *pwcs, int maxout)
|
|
{
|
|
u16 *op;
|
|
int size;
|
|
unicode_t u;
|
|
|
|
op = pwcs;
|
|
while (inlen > 0 && maxout > 0 && *s) {
|
|
if (*s & 0x80) {
|
|
size = utf8_to_utf32(s, inlen, &u);
|
|
if (size < 0)
|
|
return -EINVAL;
|
|
s += size;
|
|
inlen -= size;
|
|
|
|
if (u >= PLANE_SIZE) {
|
|
if (maxout < 2)
|
|
break;
|
|
u -= PLANE_SIZE;
|
|
put_utf16(op++, SURROGATE_PAIR |
|
|
((u >> 10) & SURROGATE_BITS),
|
|
endian);
|
|
put_utf16(op++, SURROGATE_PAIR |
|
|
SURROGATE_LOW |
|
|
(u & SURROGATE_BITS),
|
|
endian);
|
|
maxout -= 2;
|
|
} else {
|
|
put_utf16(op++, u, endian);
|
|
maxout--;
|
|
}
|
|
} else {
|
|
put_utf16(op++, *s++, endian);
|
|
inlen--;
|
|
maxout--;
|
|
}
|
|
}
|
|
return op - pwcs;
|
|
}
|
|
EXPORT_SYMBOL(utf8s_to_utf16s);
|
|
|
|
static inline unsigned long get_utf16(unsigned c, enum utf16_endian endian)
|
|
{
|
|
switch (endian) {
|
|
default:
|
|
return c;
|
|
case UTF16_LITTLE_ENDIAN:
|
|
return __le16_to_cpu(c);
|
|
case UTF16_BIG_ENDIAN:
|
|
return __be16_to_cpu(c);
|
|
}
|
|
}
|
|
|
|
int utf16s_to_utf8s(const wchar_t *pwcs, int inlen, enum utf16_endian endian,
|
|
u8 *s, int maxout)
|
|
{
|
|
u8 *op;
|
|
int size;
|
|
unsigned long u, v;
|
|
|
|
op = s;
|
|
while (inlen > 0 && maxout > 0) {
|
|
u = get_utf16(*pwcs, endian);
|
|
if (!u)
|
|
break;
|
|
pwcs++;
|
|
inlen--;
|
|
if (u > 0x7f) {
|
|
if ((u & SURROGATE_MASK) == SURROGATE_PAIR) {
|
|
if (u & SURROGATE_LOW) {
|
|
/* Ignore character and move on */
|
|
continue;
|
|
}
|
|
if (inlen <= 0)
|
|
break;
|
|
v = get_utf16(*pwcs, endian);
|
|
if ((v & SURROGATE_MASK) != SURROGATE_PAIR ||
|
|
!(v & SURROGATE_LOW)) {
|
|
/* Ignore character and move on */
|
|
continue;
|
|
}
|
|
u = PLANE_SIZE + ((u & SURROGATE_BITS) << 10)
|
|
+ (v & SURROGATE_BITS);
|
|
pwcs++;
|
|
inlen--;
|
|
}
|
|
size = utf32_to_utf8(u, op, maxout);
|
|
if (size == -1) {
|
|
/* Ignore character and move on */
|
|
} else {
|
|
op += size;
|
|
maxout -= size;
|
|
}
|
|
} else {
|
|
*op++ = (u8) u;
|
|
maxout--;
|
|
}
|
|
}
|
|
return op - s;
|
|
}
|
|
EXPORT_SYMBOL(utf16s_to_utf8s);
|
|
|
|
int register_nls(struct nls_table * nls)
|
|
{
|
|
struct nls_table ** tmp = &tables;
|
|
|
|
if (nls->next)
|
|
return -EBUSY;
|
|
|
|
spin_lock(&nls_lock);
|
|
while (*tmp) {
|
|
if (nls == *tmp) {
|
|
spin_unlock(&nls_lock);
|
|
return -EBUSY;
|
|
}
|
|
tmp = &(*tmp)->next;
|
|
}
|
|
nls->next = tables;
|
|
tables = nls;
|
|
spin_unlock(&nls_lock);
|
|
return 0;
|
|
}
|
|
|
|
int unregister_nls(struct nls_table * nls)
|
|
{
|
|
struct nls_table ** tmp = &tables;
|
|
|
|
spin_lock(&nls_lock);
|
|
while (*tmp) {
|
|
if (nls == *tmp) {
|
|
*tmp = nls->next;
|
|
spin_unlock(&nls_lock);
|
|
return 0;
|
|
}
|
|
tmp = &(*tmp)->next;
|
|
}
|
|
spin_unlock(&nls_lock);
|
|
return -EINVAL;
|
|
}
|
|
|
|
static struct nls_table *find_nls(char *charset)
|
|
{
|
|
struct nls_table *nls;
|
|
spin_lock(&nls_lock);
|
|
for (nls = tables; nls; nls = nls->next) {
|
|
if (!strcmp(nls->charset, charset))
|
|
break;
|
|
if (nls->alias && !strcmp(nls->alias, charset))
|
|
break;
|
|
}
|
|
if (nls && !try_module_get(nls->owner))
|
|
nls = NULL;
|
|
spin_unlock(&nls_lock);
|
|
return nls;
|
|
}
|
|
|
|
struct nls_table *load_nls(char *charset)
|
|
{
|
|
return try_then_request_module(find_nls(charset), "nls_%s", charset);
|
|
}
|
|
|
|
void unload_nls(struct nls_table *nls)
|
|
{
|
|
if (nls)
|
|
module_put(nls->owner);
|
|
}
|
|
|
|
static const wchar_t charset2uni[256] = {
|
|
/* 0x00*/
|
|
0x0000, 0x0001, 0x0002, 0x0003,
|
|
0x0004, 0x0005, 0x0006, 0x0007,
|
|
0x0008, 0x0009, 0x000a, 0x000b,
|
|
0x000c, 0x000d, 0x000e, 0x000f,
|
|
/* 0x10*/
|
|
0x0010, 0x0011, 0x0012, 0x0013,
|
|
0x0014, 0x0015, 0x0016, 0x0017,
|
|
0x0018, 0x0019, 0x001a, 0x001b,
|
|
0x001c, 0x001d, 0x001e, 0x001f,
|
|
/* 0x20*/
|
|
0x0020, 0x0021, 0x0022, 0x0023,
|
|
0x0024, 0x0025, 0x0026, 0x0027,
|
|
0x0028, 0x0029, 0x002a, 0x002b,
|
|
0x002c, 0x002d, 0x002e, 0x002f,
|
|
/* 0x30*/
|
|
0x0030, 0x0031, 0x0032, 0x0033,
|
|
0x0034, 0x0035, 0x0036, 0x0037,
|
|
0x0038, 0x0039, 0x003a, 0x003b,
|
|
0x003c, 0x003d, 0x003e, 0x003f,
|
|
/* 0x40*/
|
|
0x0040, 0x0041, 0x0042, 0x0043,
|
|
0x0044, 0x0045, 0x0046, 0x0047,
|
|
0x0048, 0x0049, 0x004a, 0x004b,
|
|
0x004c, 0x004d, 0x004e, 0x004f,
|
|
/* 0x50*/
|
|
0x0050, 0x0051, 0x0052, 0x0053,
|
|
0x0054, 0x0055, 0x0056, 0x0057,
|
|
0x0058, 0x0059, 0x005a, 0x005b,
|
|
0x005c, 0x005d, 0x005e, 0x005f,
|
|
/* 0x60*/
|
|
0x0060, 0x0061, 0x0062, 0x0063,
|
|
0x0064, 0x0065, 0x0066, 0x0067,
|
|
0x0068, 0x0069, 0x006a, 0x006b,
|
|
0x006c, 0x006d, 0x006e, 0x006f,
|
|
/* 0x70*/
|
|
0x0070, 0x0071, 0x0072, 0x0073,
|
|
0x0074, 0x0075, 0x0076, 0x0077,
|
|
0x0078, 0x0079, 0x007a, 0x007b,
|
|
0x007c, 0x007d, 0x007e, 0x007f,
|
|
/* 0x80*/
|
|
0x0080, 0x0081, 0x0082, 0x0083,
|
|
0x0084, 0x0085, 0x0086, 0x0087,
|
|
0x0088, 0x0089, 0x008a, 0x008b,
|
|
0x008c, 0x008d, 0x008e, 0x008f,
|
|
/* 0x90*/
|
|
0x0090, 0x0091, 0x0092, 0x0093,
|
|
0x0094, 0x0095, 0x0096, 0x0097,
|
|
0x0098, 0x0099, 0x009a, 0x009b,
|
|
0x009c, 0x009d, 0x009e, 0x009f,
|
|
/* 0xa0*/
|
|
0x00a0, 0x00a1, 0x00a2, 0x00a3,
|
|
0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
|
0x00a8, 0x00a9, 0x00aa, 0x00ab,
|
|
0x00ac, 0x00ad, 0x00ae, 0x00af,
|
|
/* 0xb0*/
|
|
0x00b0, 0x00b1, 0x00b2, 0x00b3,
|
|
0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
|
0x00b8, 0x00b9, 0x00ba, 0x00bb,
|
|
0x00bc, 0x00bd, 0x00be, 0x00bf,
|
|
/* 0xc0*/
|
|
0x00c0, 0x00c1, 0x00c2, 0x00c3,
|
|
0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
|
0x00c8, 0x00c9, 0x00ca, 0x00cb,
|
|
0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
|
/* 0xd0*/
|
|
0x00d0, 0x00d1, 0x00d2, 0x00d3,
|
|
0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
|
0x00d8, 0x00d9, 0x00da, 0x00db,
|
|
0x00dc, 0x00dd, 0x00de, 0x00df,
|
|
/* 0xe0*/
|
|
0x00e0, 0x00e1, 0x00e2, 0x00e3,
|
|
0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
|
0x00e8, 0x00e9, 0x00ea, 0x00eb,
|
|
0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
|
/* 0xf0*/
|
|
0x00f0, 0x00f1, 0x00f2, 0x00f3,
|
|
0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
|
0x00f8, 0x00f9, 0x00fa, 0x00fb,
|
|
0x00fc, 0x00fd, 0x00fe, 0x00ff,
|
|
};
|
|
|
|
static const unsigned char page00[256] = {
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
|
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
|
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
|
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
|
|
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
|
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
|
|
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
|
|
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
|
|
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
|
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
|
|
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
|
|
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
|
|
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
|
|
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
|
|
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
|
|
|
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
|
|
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
|
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
|
|
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
|
|
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
|
|
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
|
|
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
|
|
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
|
|
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
|
|
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
|
|
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
|
|
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
|
|
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
|
|
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
|
|
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
|
|
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
|
|
};
|
|
|
|
static const unsigned char *const page_uni2charset[256] = {
|
|
page00
|
|
};
|
|
|
|
static const unsigned char charset2lower[256] = {
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
|
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
|
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
|
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
|
|
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
|
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
|
|
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
|
|
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
|
|
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
|
|
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
|
|
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
|
|
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
|
|
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
|
|
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
|
|
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
|
|
|
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
|
|
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
|
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
|
|
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
|
|
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
|
|
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
|
|
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
|
|
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
|
|
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
|
|
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
|
|
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
|
|
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
|
|
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
|
|
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
|
|
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
|
|
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
|
|
};
|
|
|
|
static const unsigned char charset2upper[256] = {
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
|
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
|
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
|
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
|
|
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
|
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
|
|
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
|
|
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
|
|
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
|
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
|
|
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
|
|
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
|
|
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
|
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
|
|
0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
|
|
|
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
|
|
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
|
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
|
|
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
|
|
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
|
|
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
|
|
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
|
|
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
|
|
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
|
|
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
|
|
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
|
|
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
|
|
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
|
|
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
|
|
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
|
|
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
|
|
};
|
|
|
|
|
|
static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
|
|
{
|
|
const unsigned char *uni2charset;
|
|
unsigned char cl = uni & 0x00ff;
|
|
unsigned char ch = (uni & 0xff00) >> 8;
|
|
|
|
if (boundlen <= 0)
|
|
return -ENAMETOOLONG;
|
|
|
|
uni2charset = page_uni2charset[ch];
|
|
if (uni2charset && uni2charset[cl])
|
|
out[0] = uni2charset[cl];
|
|
else
|
|
return -EINVAL;
|
|
return 1;
|
|
}
|
|
|
|
static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
|
|
{
|
|
*uni = charset2uni[*rawstring];
|
|
if (*uni == 0x0000)
|
|
return -EINVAL;
|
|
return 1;
|
|
}
|
|
|
|
static struct nls_table default_table = {
|
|
.charset = "default",
|
|
.uni2char = uni2char,
|
|
.char2uni = char2uni,
|
|
.charset2lower = charset2lower,
|
|
.charset2upper = charset2upper,
|
|
};
|
|
|
|
/* Returns a simple default translation table */
|
|
struct nls_table *load_nls_default(void)
|
|
{
|
|
struct nls_table *default_nls;
|
|
|
|
default_nls = load_nls(CONFIG_NLS_DEFAULT);
|
|
if (default_nls != NULL)
|
|
return default_nls;
|
|
else
|
|
return &default_table;
|
|
}
|
|
|
|
EXPORT_SYMBOL(register_nls);
|
|
EXPORT_SYMBOL(unregister_nls);
|
|
EXPORT_SYMBOL(unload_nls);
|
|
EXPORT_SYMBOL(load_nls);
|
|
EXPORT_SYMBOL(load_nls_default);
|
|
|
|
MODULE_LICENSE("Dual BSD/GPL");
|