blob: c4d52ea9f0921a6530bc96de8e02529643856f9e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Uwe Zeisbergerf30c2262006-10-03 23:01:26 +02002 * linux/fs/nls/nls_iso8859-13.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Charset iso8859-13 translation tables.
5 * The Unicode to charset table has only exact mappings.
6 */
7
8#include <linux/module.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/nls.h>
12#include <linux/errno.h>
13
Denys Vlasenkob9ec0332007-10-16 23:29:54 -070014static const wchar_t charset2uni[256] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 /* 0x00*/
16 0x0000, 0x0001, 0x0002, 0x0003,
17 0x0004, 0x0005, 0x0006, 0x0007,
18 0x0008, 0x0009, 0x000a, 0x000b,
19 0x000c, 0x000d, 0x000e, 0x000f,
20 /* 0x10*/
21 0x0010, 0x0011, 0x0012, 0x0013,
22 0x0014, 0x0015, 0x0016, 0x0017,
23 0x0018, 0x0019, 0x001a, 0x001b,
24 0x001c, 0x001d, 0x001e, 0x001f,
25 /* 0x20*/
26 0x0020, 0x0021, 0x0022, 0x0023,
27 0x0024, 0x0025, 0x0026, 0x0027,
28 0x0028, 0x0029, 0x002a, 0x002b,
29 0x002c, 0x002d, 0x002e, 0x002f,
30 /* 0x30*/
31 0x0030, 0x0031, 0x0032, 0x0033,
32 0x0034, 0x0035, 0x0036, 0x0037,
33 0x0038, 0x0039, 0x003a, 0x003b,
34 0x003c, 0x003d, 0x003e, 0x003f,
35 /* 0x40*/
36 0x0040, 0x0041, 0x0042, 0x0043,
37 0x0044, 0x0045, 0x0046, 0x0047,
38 0x0048, 0x0049, 0x004a, 0x004b,
39 0x004c, 0x004d, 0x004e, 0x004f,
40 /* 0x50*/
41 0x0050, 0x0051, 0x0052, 0x0053,
42 0x0054, 0x0055, 0x0056, 0x0057,
43 0x0058, 0x0059, 0x005a, 0x005b,
44 0x005c, 0x005d, 0x005e, 0x005f,
45 /* 0x60*/
46 0x0060, 0x0061, 0x0062, 0x0063,
47 0x0064, 0x0065, 0x0066, 0x0067,
48 0x0068, 0x0069, 0x006a, 0x006b,
49 0x006c, 0x006d, 0x006e, 0x006f,
50 /* 0x70*/
51 0x0070, 0x0071, 0x0072, 0x0073,
52 0x0074, 0x0075, 0x0076, 0x0077,
53 0x0078, 0x0079, 0x007a, 0x007b,
54 0x007c, 0x007d, 0x007e, 0x007f,
55 /* 0x80*/
56 0x0080, 0x0081, 0x0082, 0x0083,
57 0x0084, 0x0085, 0x0086, 0x0087,
58 0x0088, 0x0089, 0x008a, 0x008b,
59 0x008c, 0x008d, 0x008e, 0x008f,
60 /* 0x90*/
61 0x0090, 0x0091, 0x0092, 0x0093,
62 0x0094, 0x0095, 0x0096, 0x0097,
63 0x0098, 0x0099, 0x009a, 0x009b,
64 0x009c, 0x009d, 0x009e, 0x009f,
65 /* 0xa0*/
66 0x00a0, 0x201d, 0x00a2, 0x00a3,
67 0x00a4, 0x201e, 0x00a6, 0x00a7,
68 0x00d8, 0x00a9, 0x0156, 0x00ab,
69 0x00ac, 0x00ad, 0x00ae, 0x00c6,
70 /* 0xb0*/
71 0x00b0, 0x00b1, 0x00b2, 0x00b3,
72 0x201c, 0x00b5, 0x00b6, 0x00b7,
73 0x00f8, 0x00b9, 0x0157, 0x00bb,
74 0x00bc, 0x00bd, 0x00be, 0x00e6,
75 /* 0xc0*/
76 0x0104, 0x012e, 0x0100, 0x0106,
77 0x00c4, 0x00c5, 0x0118, 0x0112,
78 0x010c, 0x00c9, 0x0179, 0x0116,
79 0x0122, 0x0136, 0x012a, 0x013b,
80 /* 0xd0*/
81 0x0160, 0x0143, 0x0145, 0x00d3,
82 0x014c, 0x00d5, 0x00d6, 0x00d7,
83 0x0172, 0x0141, 0x015a, 0x016a,
84 0x00dc, 0x017b, 0x017d, 0x00df,
85 /* 0xe0*/
86 0x0105, 0x012f, 0x0101, 0x0107,
87 0x00e4, 0x00e5, 0x0119, 0x0113,
88 0x010d, 0x00e9, 0x017a, 0x0117,
89 0x0123, 0x0137, 0x012b, 0x013c,
90 /* 0xf0*/
91 0x0161, 0x0144, 0x0146, 0x00f3,
92 0x014d, 0x00f5, 0x00f6, 0x00f7,
93 0x0173, 0x0142, 0x015b, 0x016b,
94 0x00fc, 0x017c, 0x017e, 0x2019,
95};
96
Denys Vlasenkob9ec0332007-10-16 23:29:54 -070097static const unsigned char page00[256] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
99 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
100 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
101 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
102 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
103 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
104 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
105 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
106 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
107 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
108 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
109 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
110 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
111 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
112 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
113 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
114
115 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
116 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
117 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
118 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
119 0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
120 0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
121 0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
122 0x00, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */
123 0x00, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0xaf, 0x00, /* 0xc0-0xc7 */
124 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
125 0x00, 0x00, 0x00, 0xd3, 0x00, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
126 0xa8, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
127 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe5, 0xbf, 0x00, /* 0xe0-0xe7 */
128 0x00, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
129 0x00, 0x00, 0x00, 0xf3, 0x00, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
130 0xb8, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
131};
132
Denys Vlasenkob9ec0332007-10-16 23:29:54 -0700133static const unsigned char page01[256] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 0xc2, 0xe2, 0x00, 0x00, 0xc0, 0xe0, 0xc3, 0xe3, /* 0x00-0x07 */
135 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */
136 0x00, 0x00, 0xc7, 0xe7, 0x00, 0x00, 0xcb, 0xeb, /* 0x10-0x17 */
137 0xc6, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
138 0x00, 0x00, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
139 0x00, 0x00, 0xce, 0xee, 0x00, 0x00, 0xc1, 0xe1, /* 0x28-0x2f */
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xed, /* 0x30-0x37 */
141 0x00, 0x00, 0x00, 0xcf, 0xef, 0x00, 0x00, 0x00, /* 0x38-0x3f */
142 0x00, 0xd9, 0xf9, 0xd1, 0xf1, 0xd2, 0xf2, 0x00, /* 0x40-0x47 */
143 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf4, 0x00, 0x00, /* 0x48-0x4f */
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xba, /* 0x50-0x57 */
145 0x00, 0x00, 0xda, 0xfa, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
146 0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
147 0x00, 0x00, 0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
148 0x00, 0x00, 0xd8, 0xf8, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
149 0x00, 0xca, 0xea, 0xdd, 0xfd, 0xde, 0xfe, 0x00, /* 0x78-0x7f */
150};
151
Denys Vlasenkob9ec0332007-10-16 23:29:54 -0700152static const unsigned char page20[256] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
156 0x00, 0xff, 0x00, 0x00, 0xb4, 0xa1, 0xa5, 0x00, /* 0x18-0x1f */
157};
158
Denys Vlasenkob9ec0332007-10-16 23:29:54 -0700159static const unsigned char *const page_uni2charset[256] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
161 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
162 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
163 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
164 page20, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
165};
166
Denys Vlasenkob9ec0332007-10-16 23:29:54 -0700167static const unsigned char charset2lower[256] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
169 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
170 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
171 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
172 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
173 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
174 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
175 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
176 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
177 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
178 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
179 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
180 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
181 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
182 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
183 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
184
185 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
186 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
187 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
188 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
189 0xa0, 0xb1, 0xa2, 0xb3, 0xa4, 0xb5, 0xb6, 0xa7, /* 0xa0-0xa7 */
190 0xa8, 0xb9, 0xba, 0xbb, 0xbc, 0xad, 0xbe, 0xaf, /* 0xa8-0xaf */
191 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
192 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbf, 0xbe, 0xbf, /* 0xb8-0xbf */
193 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
194 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
195 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
196 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
197 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
198 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
199 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
200 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
201};
202
Denys Vlasenkob9ec0332007-10-16 23:29:54 -0700203static const unsigned char charset2upper[256] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
205 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
206 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
207 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
208 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
209 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
210 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
211 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
212 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
213 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
214 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
215 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
216 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
217 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
218 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
219 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
220
221 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
222 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
223 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
224 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
225 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
226 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
227 0xb0, 0xa1, 0xb2, 0xa3, 0xb4, 0xa5, 0xa6, 0xb7, /* 0xb0-0xb7 */
228 0xb8, 0xa9, 0xaa, 0xab, 0xac, 0xbd, 0xae, 0xbd, /* 0xb8-0xbf */
229 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
230 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
231 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
232 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
233 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
234 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
235 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
236 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff, /* 0xf8-0xff */
237};
238
239static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
240{
Denys Vlasenkob9ec0332007-10-16 23:29:54 -0700241 const unsigned char *uni2charset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 unsigned char cl = uni & 0x00ff;
243 unsigned char ch = (uni & 0xff00) >> 8;
244
245 if (boundlen <= 0)
246 return -ENAMETOOLONG;
247
248 uni2charset = page_uni2charset[ch];
249 if (uni2charset && uni2charset[cl])
250 out[0] = uni2charset[cl];
251 else
252 return -EINVAL;
253 return 1;
254}
255
256static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
257{
258 *uni = charset2uni[*rawstring];
259 if (*uni == 0x0000)
260 return -EINVAL;
261 return 1;
262}
263
264static struct nls_table table = {
265 .charset = "iso8859-13",
266 .uni2char = uni2char,
267 .char2uni = char2uni,
268 .charset2lower = charset2lower,
269 .charset2upper = charset2upper,
270 .owner = THIS_MODULE,
271};
272
273static int __init init_nls_iso8859_13(void)
274{
275 return register_nls(&table);
276}
277
278static void __exit exit_nls_iso8859_13(void)
279{
280 unregister_nls(&table);
281}
282
283module_init(init_nls_iso8859_13)
284module_exit(exit_nls_iso8859_13)
285
286MODULE_LICENSE("Dual BSD/GPL");