OSDN Git Service

100ba0a9415910fbae32b3e8637f8892a8a13e0a
[pf3gnuchains/sourceware.git] / tcl / generic / regc_locale.c
1 /* 
2  * regc_locale.c --
3  *
4  *      This file contains the Unicode locale specific regexp routines.
5  *      This file is #included by regcomp.c.
6  *
7  * Copyright (c) 1998 by Scriptics Corporation.
8  *
9  * See the file "license.terms" for information on usage and redistribution
10  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  *
12  * RCS: @(#) $Id$
13  */
14
15 /* ASCII character-name table */
16
17 static struct cname {
18         char *name;
19         char code;
20 } cnames[] = {
21         {"NUL", '\0'},
22         {"SOH", '\001'},
23         {"STX", '\002'},
24         {"ETX", '\003'},
25         {"EOT", '\004'},
26         {"ENQ", '\005'},
27         {"ACK", '\006'},
28         {"BEL", '\007'},
29         {"alert",       '\007'},
30         {"BS",          '\010'},
31         {"backspace",   '\b'},
32         {"HT",          '\011'},
33         {"tab",         '\t'},
34         {"LF",          '\012'},
35         {"newline",     '\n'},
36         {"VT",          '\013'},
37         {"vertical-tab",        '\v'},
38         {"FF",          '\014'},
39         {"form-feed",   '\f'},
40         {"CR",          '\015'},
41         {"carriage-return",     '\r'},
42         {"SO",  '\016'},
43         {"SI",  '\017'},
44         {"DLE", '\020'},
45         {"DC1", '\021'},
46         {"DC2", '\022'},
47         {"DC3", '\023'},
48         {"DC4", '\024'},
49         {"NAK", '\025'},
50         {"SYN", '\026'},
51         {"ETB", '\027'},
52         {"CAN", '\030'},
53         {"EM",  '\031'},
54         {"SUB", '\032'},
55         {"ESC", '\033'},
56         {"IS4", '\034'},
57         {"FS",  '\034'},
58         {"IS3", '\035'},
59         {"GS",  '\035'},
60         {"IS2", '\036'},
61         {"RS",  '\036'},
62         {"IS1", '\037'},
63         {"US",  '\037'},
64         {"space",               ' '},
65         {"exclamation-mark",    '!'},
66         {"quotation-mark",      '"'},
67         {"number-sign",         '#'},
68         {"dollar-sign",         '$'},
69         {"percent-sign",                '%'},
70         {"ampersand",           '&'},
71         {"apostrophe",          '\''},
72         {"left-parenthesis",    '('},
73         {"right-parenthesis",   ')'},
74         {"asterisk",    '*'},
75         {"plus-sign",   '+'},
76         {"comma",       ','},
77         {"hyphen",      '-'},
78         {"hyphen-minus",        '-'},
79         {"period",      '.'},
80         {"full-stop",   '.'},
81         {"slash",       '/'},
82         {"solidus",     '/'},
83         {"zero",                '0'},
84         {"one",         '1'},
85         {"two",         '2'},
86         {"three",       '3'},
87         {"four",                '4'},
88         {"five",                '5'},
89         {"six",         '6'},
90         {"seven",       '7'},
91         {"eight",       '8'},
92         {"nine",                '9'},
93         {"colon",       ':'},
94         {"semicolon",   ';'},
95         {"less-than-sign",      '<'},
96         {"equals-sign",         '='},
97         {"greater-than-sign",   '>'},
98         {"question-mark",       '?'},
99         {"commercial-at",       '@'},
100         {"left-square-bracket", '['},
101         {"backslash",           '\\'},
102         {"reverse-solidus",     '\\'},
103         {"right-square-bracket",        ']'},
104         {"circumflex",          '^'},
105         {"circumflex-accent",   '^'},
106         {"underscore",          '_'},
107         {"low-line",            '_'},
108         {"grave-accent",                '`'},
109         {"left-brace",          '{'},
110         {"left-curly-bracket",  '{'},
111         {"vertical-line",       '|'},
112         {"right-brace",         '}'},
113         {"right-curly-bracket", '}'},
114         {"tilde",               '~'},
115         {"DEL", '\177'},
116         {NULL,  0}
117 };
118
119 /* Unicode character-class tables */
120
121 typedef struct crange {
122     chr start;
123     chr end;
124 } crange;
125
126 /* Unicode: (Alphabetic) */
127
128 static crange alphaRangeTable[] = {
129     {0x0041, 0x005a}, {0x0061, 0x007a}, {0x00c0, 0x00d6}, {0x00d8, 0x00f6}, 
130     {0x00f8, 0x01f5}, {0x01fa, 0x0217}, {0x0250, 0x02a8}, {0x02b0, 0x02b8}, 
131     {0x02bb, 0x02c1}, {0x02e0, 0x02e4}, {0x0388, 0x038a}, {0x038e, 0x03a1}, 
132     {0x03a3, 0x03ce}, {0x03d0, 0x03d6}, {0x03e2, 0x03f3}, {0x0401, 0x040c}, 
133     {0x040e, 0x044f}, {0x0451, 0x045c}, {0x045e, 0x0481}, {0x0490, 0x04c4}, 
134     {0x04d0, 0x04eb}, {0x04ee, 0x04f5}, {0x0531, 0x0556}, {0x0561, 0x0587}, 
135     {0x05d0, 0x05ea}, {0x05f0, 0x05f2}, {0x0621, 0x063a}, {0x0640, 0x064a}, 
136     {0x0671, 0x06b7}, {0x06ba, 0x06be}, {0x06c0, 0x06ce}, {0x06d0, 0x06d3}, 
137     {0x0905, 0x0939}, {0x0958, 0x0961}, {0x0985, 0x098c}, {0x0993, 0x09a8}, 
138     {0x09aa, 0x09b0}, {0x09b6, 0x09b9}, {0x09df, 0x09e1}, {0x0a05, 0x0a0a}, 
139     {0x0a13, 0x0a28}, {0x0a2a, 0x0a30}, {0x0a59, 0x0a5c}, {0x0a72, 0x0a74}, 
140     {0x0a85, 0x0a8b}, {0x0a8f, 0x0a91}, {0x0a93, 0x0aa8}, {0x0aaa, 0x0ab0}, 
141     {0x0ab5, 0x0ab9}, {0x0b05, 0x0b0c}, {0x0b13, 0x0b28}, {0x0b2a, 0x0b30}, 
142     {0x0b36, 0x0b39}, {0x0b5f, 0x0b61}, {0x0b85, 0x0b8a}, {0x0b8e, 0x0b90}, 
143     {0x0b92, 0x0b95}, {0x0ba8, 0x0baa}, {0x0bae, 0x0bb5}, {0x0bb7, 0x0bb9}, 
144     {0x0c05, 0x0c0c}, {0x0c0e, 0x0c10}, {0x0c12, 0x0c28}, {0x0c2a, 0x0c33}, 
145     {0x0c35, 0x0c39}, {0x0c85, 0x0c8c}, {0x0c8e, 0x0c90}, {0x0c92, 0x0ca8}, 
146     {0x0caa, 0x0cb3}, {0x0cb5, 0x0cb9}, {0x0d05, 0x0d0c}, {0x0d0e, 0x0d10}, 
147     {0x0d12, 0x0d28}, {0x0d2a, 0x0d39}, {0x0e01, 0x0e30}, {0x0e40, 0x0e46}, 
148     {0x0e94, 0x0e97}, {0x0e99, 0x0e9f}, {0x0ea1, 0x0ea3}, {0x0ead, 0x0eb0}, 
149     {0x0ec0, 0x0ec4}, {0x0f40, 0x0f47}, {0x0f49, 0x0f69}, {0x0f88, 0x0f8b}, 
150     {0x10a0, 0x10c5}, {0x10d0, 0x10f6}, {0x1100, 0x1159}, {0x115f, 0x11a2}, 
151     {0x11a8, 0x11f9}, {0x1e00, 0x1e9b}, {0x1ea0, 0x1ef9}, {0x1f00, 0x1f15}, 
152     {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, 
153     {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4}, 
154     {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, 
155     {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc}, {0x210a, 0x2113}, {0x2118, 0x211d}, 
156     {0x212a, 0x2131}, {0x2133, 0x2138}, {0x3031, 0x3035}, {0x3041, 0x3094}, 
157     {0x30a1, 0x30fa}, {0x30fc, 0x30fe}, {0x3105, 0x312c}, {0x3131, 0x318e}, 
158     {0x4e00, 0x9fa5}, {0xac00, 0xd7a3}, {0xf900, 0xfa2d}, {0xfb00, 0xfb06}, 
159     {0xfb13, 0xfb17}, {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, 
160     {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, 
161     {0xfdf0, 0xfdfb}, {0xfe70, 0xfe72}, {0xfe76, 0xfefc}, {0xff21, 0xff3a}, 
162     {0xff41, 0xff5a}, {0xff66, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, 
163     {0xffd2, 0xffd7}, {0xffda, 0xffdc}
164 };
165
166 #define NUM_ALPHA_RANGE (sizeof(alphaRangeTable)/sizeof(crange))
167
168 static chr alphaCharTable[] = {
169     0x00aa, 0x00b5, 0x00ba, 0x02d0, 0x02d1, 0x037a, 0x0386, 0x038c, 0x03da, 
170     0x03dc, 0x03de, 0x03e0, 0x04c7, 0x04c8, 0x04cb, 0x04cc, 0x04f8, 0x04f9, 
171     0x0559, 0x06d5, 0x06e5, 0x06e6, 0x093d, 0x0950, 0x098f, 0x0990, 0x09b2, 
172     0x09dc, 0x09dd, 0x09f0, 0x09f1, 0x0a0f, 0x0a10, 0x0a32, 0x0a33, 0x0a35, 
173     0x0a36, 0x0a38, 0x0a39, 0x0a5e, 0x0a8d, 0x0ab2, 0x0ab3, 0x0abd, 0x0ad0, 
174     0x0ae0, 0x0b0f, 0x0b10, 0x0b32, 0x0b33, 0x0b3d, 0x0b5c, 0x0b5d, 0x0b99, 
175     0x0b9a, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0c60, 0x0c61, 0x0cde, 
176     0x0ce0, 0x0ce1, 0x0d60, 0x0d61, 0x0e32, 0x0e33, 0x0e81, 0x0e82, 0x0e84, 
177     0x0e87, 0x0e88, 0x0e8a, 0x0e8d, 0x0ea5, 0x0ea7, 0x0eaa, 0x0eab, 0x0eb2, 
178     0x0eb3, 0x0ebd, 0x0ec6, 0x0edc, 0x0edd, 0x0f00, 0x1f59, 0x1f5b, 0x1f5d, 
179     0x1fbe, 0x207f, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x3005, 
180     0x3006, 0x309d, 0x309e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfe74
181 };
182
183 #define NUM_ALPHA_CHAR (sizeof(alphaCharTable)/sizeof(chr))
184
185 /* Unicode: (Decimal digit) */
186
187 static crange digitRangeTable[] = {
188     {0x0030, 0x0039}, {0x0660, 0x0669}, {0x06f0, 0x06f9}, {0x0966, 0x096f}, 
189     {0x09e6, 0x09ef}, {0x0a66, 0x0a6f}, {0x0ae6, 0x0aef}, {0x0b66, 0x0b6f}, 
190     {0x0be7, 0x0bef}, {0x0c66, 0x0c6f}, {0x0ce6, 0x0cef}, {0x0d66, 0x0d6f}, 
191     {0x0e50, 0x0e59}, {0x0ed0, 0x0ed9}, {0x0f20, 0x0f29}, {0xff10, 0xff19}
192 };
193
194 #define NUM_DIGIT_RANGE (sizeof(digitRangeTable)/sizeof(crange))
195
196 /* Unicode: (Punctuation) */
197
198 static crange punctRangeTable[] = {
199     {0x0021, 0x0023}, {0x0025, 0x002a}, {0x002c, 0x002f}, {0x005b, 0x005d}, 
200     {0x055a, 0x055f}, {0x066a, 0x066d}, {0x0f04, 0x0f12}, {0x0f3a, 0x0f3d}, 
201     {0x2010, 0x2027}, {0x2030, 0x2043}, {0x3001, 0x3003}, {0x3008, 0x3011}, 
202     {0x3014, 0x301f}, {0xfe30, 0xfe44}, {0xfe49, 0xfe52}, {0xfe54, 0xfe61}, 
203     {0xff01, 0xff03}, {0xff05, 0xff0a}, {0xff0c, 0xff0f}, {0xff3b, 0xff3d}, 
204     {0xff61, 0xff65}
205 };
206
207 #define NUM_PUNCT_RANGE (sizeof(punctRangeTable)/sizeof(crange))
208
209 static chr punctCharTable[] = {
210     0x003a, 0x003b, 0x003f, 0x0040, 0x005f, 0x007b, 0x007d, 0x00a1, 0x00ab, 
211     0x00ad, 0x00b7, 0x00bb, 0x00bf, 0x037e, 0x0387, 0x0589, 0x05be, 0x05c0, 
212     0x05c3, 0x05f3, 0x05f4, 0x060c, 0x061b, 0x061f, 0x06d4, 0x0964, 0x0965, 
213     0x0970, 0x0e5a, 0x0e5b, 0x0f85, 0x10fb, 0x2045, 0x2046, 0x207d, 0x207e, 
214     0x208d, 0x208e, 0x2329, 0x232a, 0x3030, 0x30fb, 0xfd3e, 0xfd3f, 0xfe63, 
215     0xfe68, 0xfe6a, 0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 
216     0xff5d
217 };
218
219 #define NUM_PUNCT_CHAR (sizeof(punctCharTable)/sizeof(chr))
220
221 /* Unicode: (White space) */
222
223 static crange spaceRangeTable[] = {
224     {0x0009, 0x000d}, {0x2000, 0x200b},
225 };
226
227 #define NUM_SPACE_RANGE (sizeof(spaceRangeTable)/sizeof(crange))
228
229 static chr spaceCharTable[] = {
230     0x0020, 0x00a0, 0x2028, 0x2029, 0x3000
231 };
232
233 #define NUM_SPACE_CHAR (sizeof(spaceCharTable)/sizeof(chr))
234
235 /* Unicode: lowercase characters */
236
237 static crange lowerRangeTable[] = {
238     {0x0061, 0x007a}, {0x00df, 0x00f6}, {0x00f8, 0x00ff}, {0x017e, 0x0180}, 
239     {0x0199, 0x019b}, {0x0250, 0x02a8}, {0x03ac, 0x03ce}, {0x03ef, 0x03f2}, 
240     {0x0430, 0x044f}, {0x0451, 0x045c}, {0x0561, 0x0587}, {0x10d0, 0x10f6}, 
241     {0x1e95, 0x1e9b}, {0x1f00, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, 
242     {0x1f30, 0x1f37}, {0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, 
243     {0x1f70, 0x1f7d}, {0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, 
244     {0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4}, {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, 
245     {0x1ff2, 0x1ff4}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xff41, 0xff5a}
246 };
247
248 #define NUM_LOWER_RANGE (sizeof(lowerRangeTable)/sizeof(crange))
249
250 static chr lowerCharTable[] = {
251     0x00aa, 0x00b5, 0x00ba, 0x0101, 0x0103, 0x0105, 0x0107, 0x0109, 0x010b, 
252     0x010d, 0x010f, 0x0111, 0x0113, 0x0115, 0x0117, 0x0119, 0x011b, 0x011d, 
253     0x011f, 0x0121, 0x0123, 0x0125, 0x0127, 0x0129, 0x012b, 0x012d, 0x012f, 
254     0x0131, 0x0133, 0x0135, 0x0137, 0x0138, 0x013a, 0x013c, 0x013e, 0x0140, 
255     0x0142, 0x0144, 0x0146, 0x0148, 0x0149, 0x014b, 0x014d, 0x014f, 0x0151, 
256     0x0153, 0x0155, 0x0157, 0x0159, 0x015b, 0x015d, 0x015f, 0x0161, 0x0163, 
257     0x0165, 0x0167, 0x0169, 0x016b, 0x016d, 0x016f, 0x0171, 0x0173, 0x0175, 
258     0x0177, 0x017a, 0x017c, 0x0183, 0x0185, 0x0188, 0x018c, 0x018d, 0x0192, 
259     0x0195, 0x019e, 0x01a1, 0x01a3, 0x01a5, 0x01a8, 0x01ab, 0x01ad, 0x01b0, 
260     0x01b4, 0x01b6, 0x01b9, 0x01ba, 0x01bd, 0x01c6, 0x01c9, 0x01cc, 0x01ce, 
261     0x01d0, 0x01d2, 0x01d4, 0x01d6, 0x01d8, 0x01da, 0x01dc, 0x01dd, 0x01df, 
262     0x01e1, 0x01e3, 0x01e5, 0x01e7, 0x01e9, 0x01eb, 0x01ed, 0x01ef, 0x01f0, 
263     0x01f3, 0x01f5, 0x01fb, 0x01fd, 0x01ff, 0x0201, 0x0203, 0x0205, 0x0207, 
264     0x0209, 0x020b, 0x020d, 0x020f, 0x0211, 0x0213, 0x0215, 0x0217, 0x0390, 
265     0x03d0, 0x03d1, 0x03d5, 0x03d6, 0x03e3, 0x03e5, 0x03e7, 0x03e9, 0x03eb, 
266     0x03ed, 0x045e, 0x045f, 0x0461, 0x0463, 0x0465, 0x0467, 0x0469, 0x046b, 
267     0x046d, 0x046f, 0x0471, 0x0473, 0x0475, 0x0477, 0x0479, 0x047b, 0x047d, 
268     0x047f, 0x0481, 0x0491, 0x0493, 0x0495, 0x0497, 0x0499, 0x049b, 0x049d, 
269     0x049f, 0x04a1, 0x04a3, 0x04a5, 0x04a7, 0x04a9, 0x04ab, 0x04ad, 0x04af, 
270     0x04b1, 0x04b3, 0x04b5, 0x04b7, 0x04b9, 0x04bb, 0x04bd, 0x04bf, 0x04c2, 
271     0x04c4, 0x04c8, 0x04cc, 0x04d1, 0x04d3, 0x04d5, 0x04d7, 0x04d9, 0x04db, 
272     0x04dd, 0x04df, 0x04e1, 0x04e3, 0x04e5, 0x04e7, 0x04e9, 0x04eb, 0x04ef, 
273     0x04f1, 0x04f3, 0x04f5, 0x04f9, 0x1e01, 0x1e03, 0x1e05, 0x1e07, 0x1e09, 
274     0x1e0b, 0x1e0d, 0x1e0f, 0x1e11, 0x1e13, 0x1e15, 0x1e17, 0x1e19, 0x1e1b, 
275     0x1e1d, 0x1e1f, 0x1e21, 0x1e23, 0x1e25, 0x1e27, 0x1e29, 0x1e2b, 0x1e2d, 
276     0x1e2f, 0x1e31, 0x1e33, 0x1e35, 0x1e37, 0x1e39, 0x1e3b, 0x1e3d, 0x1e3f, 
277     0x1e41, 0x1e43, 0x1e45, 0x1e47, 0x1e49, 0x1e4b, 0x1e4d, 0x1e4f, 0x1e51, 
278     0x1e53, 0x1e55, 0x1e57, 0x1e59, 0x1e5b, 0x1e5d, 0x1e5f, 0x1e61, 0x1e63, 
279     0x1e65, 0x1e67, 0x1e69, 0x1e6b, 0x1e6d, 0x1e6f, 0x1e71, 0x1e73, 0x1e75, 
280     0x1e77, 0x1e79, 0x1e7b, 0x1e7d, 0x1e7f, 0x1e81, 0x1e83, 0x1e85, 0x1e87, 
281     0x1e89, 0x1e8b, 0x1e8d, 0x1e8f, 0x1e91, 0x1e93, 0x1ea1, 0x1ea3, 0x1ea5, 
282     0x1ea7, 0x1ea9, 0x1eab, 0x1ead, 0x1eaf, 0x1eb1, 0x1eb3, 0x1eb5, 0x1eb7, 
283     0x1eb9, 0x1ebb, 0x1ebd, 0x1ebf, 0x1ec1, 0x1ec3, 0x1ec5, 0x1ec7, 0x1ec9, 
284     0x1ecb, 0x1ecd, 0x1ecf, 0x1ed1, 0x1ed3, 0x1ed5, 0x1ed7, 0x1ed9, 0x1edb, 
285     0x1edd, 0x1edf, 0x1ee1, 0x1ee3, 0x1ee5, 0x1ee7, 0x1ee9, 0x1eeb, 0x1eed, 
286     0x1eef, 0x1ef1, 0x1ef3, 0x1ef5, 0x1ef7, 0x1ef9, 0x1fb6, 0x1fb7, 0x1fbe, 
287     0x1fc6, 0x1fc7, 0x1fd6, 0x1fd7, 0x1ff6, 0x1ff7, 0x207f, 0x210a, 0x210e, 
288     0x210f, 0x2113, 0x2118, 0x212e, 0x212f, 0x2134
289 };
290
291 #define NUM_LOWER_CHAR (sizeof(lowerCharTable)/sizeof(chr))
292
293 /* Unicode: uppercase characters */
294
295 static crange upperRangeTable[] = {
296     {0x0041, 0x005a}, {0x00c0, 0x00d6}, {0x00d8, 0x00de}, {0x0189, 0x018b}, 
297     {0x018e, 0x0191}, {0x0196, 0x0198}, {0x01b1, 0x01b3}, {0x0388, 0x038a}, 
298     {0x0391, 0x03a1}, {0x03a3, 0x03ab}, {0x03d2, 0x03d4}, {0x0401, 0x040c}, 
299     {0x040e, 0x042f}, {0x0531, 0x0556}, {0x10a0, 0x10c5}, {0x1f08, 0x1f0f}, 
300     {0x1f18, 0x1f1d}, {0x1f28, 0x1f2f}, {0x1f38, 0x1f3f}, {0x1f48, 0x1f4d}, 
301     {0x1f68, 0x1f6f}, {0x1f88, 0x1f8f}, {0x1f98, 0x1f9f}, {0x1fa8, 0x1faf}, 
302     {0x1fb8, 0x1fbc}, {0x1fc8, 0x1fcc}, {0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, 
303     {0x1ff8, 0x1ffc}, {0x210b, 0x210d}, {0x2110, 0x2112}, {0x2119, 0x211d}, 
304     {0x212a, 0x212d}, {0xff21, 0xff3a}
305 };
306
307 #define NUM_UPPER_RANGE (sizeof(upperRangeTable)/sizeof(crange))
308
309 static chr upperCharTable[] = {
310     0x0100, 0x0102, 0x0104, 0x0106, 0x0108, 0x010a, 0x010c, 0x010e, 0x0110, 
311     0x0112, 0x0114, 0x0116, 0x0118, 0x011a, 0x011c, 0x011e, 0x0120, 0x0122, 
312     0x0124, 0x0126, 0x0128, 0x012a, 0x012c, 0x012e, 0x0130, 0x0132, 0x0134, 
313     0x0136, 0x0139, 0x013b, 0x013d, 0x013f, 0x0141, 0x0143, 0x0145, 0x0147, 
314     0x014a, 0x014c, 0x014e, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158, 0x015a, 
315     0x015c, 0x015e, 0x0160, 0x0162, 0x0164, 0x0166, 0x0168, 0x016a, 0x016c, 
316     0x016e, 0x0170, 0x0172, 0x0174, 0x0176, 0x0178, 0x0179, 0x017b, 0x017d, 
317     0x0181, 0x0182, 0x0184, 0x0186, 0x0187, 0x0193, 0x0194, 0x019c, 0x019d, 
318     0x019f, 0x01a0, 0x01a2, 0x01a4, 0x01a6, 0x01a7, 0x01a9, 0x01ac, 0x01ae, 
319     0x01af, 0x01b5, 0x01b7, 0x01b8, 0x01bc, 0x01c4, 0x01c7, 0x01ca, 0x01cd, 
320     0x01cf, 0x01d1, 0x01d3, 0x01d5, 0x01d7, 0x01d9, 0x01db, 0x01de, 0x01e0, 
321     0x01e2, 0x01e4, 0x01e6, 0x01e8, 0x01ea, 0x01ec, 0x01ee, 0x01f1, 0x01f4, 
322     0x01fa, 0x01fc, 0x01fe, 0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 
323     0x020c, 0x020e, 0x0210, 0x0212, 0x0214, 0x0216, 0x0386, 0x038c, 0x038e, 
324     0x038f, 0x03da, 0x03dc, 0x03de, 0x03e0, 0x03e2, 0x03e4, 0x03e6, 0x03e8, 
325     0x03ea, 0x03ec, 0x03ee, 0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046a, 
326     0x046c, 0x046e, 0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047a, 0x047c, 
327     0x047e, 0x0480, 0x0490, 0x0492, 0x0494, 0x0496, 0x0498, 0x049a, 0x049c, 
328     0x049e, 0x04a0, 0x04a2, 0x04a4, 0x04a6, 0x04a8, 0x04aa, 0x04ac, 0x04ae, 
329     0x04b0, 0x04b2, 0x04b4, 0x04b6, 0x04b8, 0x04ba, 0x04bc, 0x04be, 0x04c1, 
330     0x04c3, 0x04c7, 0x04cb, 0x04d0, 0x04d2, 0x04d4, 0x04d6, 0x04d8, 0x04da, 
331     0x04dc, 0x04de, 0x04e0, 0x04e2, 0x04e4, 0x04e6, 0x04e8, 0x04ea, 0x04ee, 
332     0x04f0, 0x04f2, 0x04f4, 0x04f8, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 
333     0x1e0a, 0x1e0c, 0x1e0e, 0x1e10, 0x1e12, 0x1e14, 0x1e16, 0x1e18, 0x1e1a, 
334     0x1e1c, 0x1e1e, 0x1e20, 0x1e22, 0x1e24, 0x1e26, 0x1e28, 0x1e2a, 0x1e2c, 
335     0x1e2e, 0x1e30, 0x1e32, 0x1e34, 0x1e36, 0x1e38, 0x1e3a, 0x1e3c, 0x1e3e, 
336     0x1e40, 0x1e42, 0x1e44, 0x1e46, 0x1e48, 0x1e4a, 0x1e4c, 0x1e4e, 0x1e50, 
337     0x1e52, 0x1e54, 0x1e56, 0x1e58, 0x1e5a, 0x1e5c, 0x1e5e, 0x1e60, 0x1e62, 
338     0x1e64, 0x1e66, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e, 0x1e70, 0x1e72, 0x1e74, 
339     0x1e76, 0x1e78, 0x1e7a, 0x1e7c, 0x1e7e, 0x1e80, 0x1e82, 0x1e84, 0x1e86, 
340     0x1e88, 0x1e8a, 0x1e8c, 0x1e8e, 0x1e90, 0x1e92, 0x1e94, 0x1ea0, 0x1ea2, 
341     0x1ea4, 0x1ea6, 0x1ea8, 0x1eaa, 0x1eac, 0x1eae, 0x1eb0, 0x1eb2, 0x1eb4, 
342     0x1eb6, 0x1eb8, 0x1eba, 0x1ebc, 0x1ebe, 0x1ec0, 0x1ec2, 0x1ec4, 0x1ec6, 
343     0x1ec8, 0x1eca, 0x1ecc, 0x1ece, 0x1ed0, 0x1ed2, 0x1ed4, 0x1ed6, 0x1ed8, 
344     0x1eda, 0x1edc, 0x1ede, 0x1ee0, 0x1ee2, 0x1ee4, 0x1ee6, 0x1ee8, 0x1eea, 
345     0x1eec, 0x1eee, 0x1ef0, 0x1ef2, 0x1ef4, 0x1ef6, 0x1ef8, 0x1f59, 0x1f5b, 
346     0x1f5d, 0x1f5f, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x2130, 
347     0x2131, 0x2133
348 };
349
350 #define NUM_UPPER_CHAR (sizeof(upperCharTable)/sizeof(chr))
351
352 /*
353  * The graph table includes the set of characters that are Unicode
354  * print characters excluding space.
355  */
356
357 static crange graphRangeTable[] = {
358     {0x0021, 0x007e}, {0x00a0, 0x011f}, {0x0121, 0x01f5}, {0x01fa, 0x0217}, 
359     {0x0250, 0x02a8}, {0x02b0, 0x02de}, {0x02e0, 0x02e9}, {0x0300, 0x031f}, 
360     {0x0321, 0x0345}, {0x0384, 0x038a}, {0x038e, 0x03a1}, {0x03a3, 0x03ce}, 
361     {0x03d0, 0x03d6}, {0x03e2, 0x03f3}, {0x0401, 0x040c}, {0x040e, 0x041f}, 
362     {0x0421, 0x044f}, {0x0451, 0x045c}, {0x045e, 0x0486}, {0x0490, 0x04c4}, 
363     {0x04d0, 0x04eb}, {0x04ee, 0x04f5}, {0x0531, 0x0556}, {0x0559, 0x055f}, 
364     {0x0561, 0x0587}, {0x0591, 0x05a1}, {0x05a3, 0x05b9}, {0x05bb, 0x05c4}, 
365     {0x05d0, 0x05ea}, {0x05f0, 0x05f4}, {0x0621, 0x063a}, {0x0640, 0x0652}, 
366     {0x0660, 0x066d}, {0x0670, 0x06b7}, {0x06ba, 0x06be}, {0x06c0, 0x06ce}, 
367     {0x06d0, 0x06ed}, {0x06f0, 0x06f9}, {0x0901, 0x0903}, {0x0905, 0x091f}, 
368     {0x0921, 0x0939}, {0x093c, 0x094d}, {0x0950, 0x0954}, {0x0958, 0x0970}, 
369     {0x0981, 0x0983}, {0x0985, 0x098c}, {0x0993, 0x09a8}, {0x09aa, 0x09b0}, 
370     {0x09b6, 0x09b9}, {0x09be, 0x09c4}, {0x09cb, 0x09cd}, {0x09df, 0x09e3}, 
371     {0x09e6, 0x09fa}, {0x0a05, 0x0a0a}, {0x0a13, 0x0a1f}, {0x0a21, 0x0a28}, 
372     {0x0a2a, 0x0a30}, {0x0a3e, 0x0a42}, {0x0a4b, 0x0a4d}, {0x0a59, 0x0a5c}, 
373     {0x0a66, 0x0a74}, {0x0a81, 0x0a83}, {0x0a85, 0x0a8b}, {0x0a8f, 0x0a91}, 
374     {0x0a93, 0x0aa8}, {0x0aaa, 0x0ab0}, {0x0ab5, 0x0ab9}, {0x0abc, 0x0ac5}, 
375     {0x0ac7, 0x0ac9}, {0x0acb, 0x0acd}, {0x0ae6, 0x0aef}, {0x0b01, 0x0b03}, 
376     {0x0b05, 0x0b0c}, {0x0b13, 0x0b1f}, {0x0b21, 0x0b28}, {0x0b2a, 0x0b30}, 
377     {0x0b36, 0x0b39}, {0x0b3c, 0x0b43}, {0x0b4b, 0x0b4d}, {0x0b5f, 0x0b61}, 
378     {0x0b66, 0x0b70}, {0x0b85, 0x0b8a}, {0x0b8e, 0x0b90}, {0x0b92, 0x0b95}, 
379     {0x0ba8, 0x0baa}, {0x0bae, 0x0bb5}, {0x0bb7, 0x0bb9}, {0x0bbe, 0x0bc2}, 
380     {0x0bc6, 0x0bc8}, {0x0bca, 0x0bcd}, {0x0be7, 0x0bf2}, {0x0c01, 0x0c03}, 
381     {0x0c05, 0x0c0c}, {0x0c0e, 0x0c10}, {0x0c12, 0x0c1f}, {0x0c21, 0x0c28}, 
382     {0x0c2a, 0x0c33}, {0x0c35, 0x0c39}, {0x0c3e, 0x0c44}, {0x0c46, 0x0c48}, 
383     {0x0c4a, 0x0c4d}, {0x0c66, 0x0c6f}, {0x0c85, 0x0c8c}, {0x0c8e, 0x0c90}, 
384     {0x0c92, 0x0ca8}, {0x0caa, 0x0cb3}, {0x0cb5, 0x0cb9}, {0x0cbe, 0x0cc4}, 
385     {0x0cc6, 0x0cc8}, {0x0cca, 0x0ccd}, {0x0ce6, 0x0cef}, {0x0d05, 0x0d0c}, 
386     {0x0d0e, 0x0d10}, {0x0d12, 0x0d1f}, {0x0d21, 0x0d28}, {0x0d2a, 0x0d39}, 
387     {0x0d3e, 0x0d43}, {0x0d46, 0x0d48}, {0x0d4a, 0x0d4d}, {0x0d66, 0x0d6f}, 
388     {0x0e01, 0x0e1f}, {0x0e21, 0x0e3a}, {0x0e3f, 0x0e5b}, {0x0e94, 0x0e97}, 
389     {0x0e99, 0x0e9f}, {0x0ea1, 0x0ea3}, {0x0ead, 0x0eb9}, {0x0ebb, 0x0ebd}, 
390     {0x0ec0, 0x0ec4}, {0x0ec8, 0x0ecd}, {0x0ed0, 0x0ed9}, {0x0f00, 0x0f1f}, 
391     {0x0f21, 0x0f47}, {0x0f49, 0x0f69}, {0x0f71, 0x0f8b}, {0x0f90, 0x0f95}, 
392     {0x0f99, 0x0fad}, {0x0fb1, 0x0fb7}, {0x10a0, 0x10c5}, {0x10d0, 0x10f6}, 
393     {0x1100, 0x111f}, {0x1121, 0x1159}, {0x115f, 0x11a2}, {0x11a8, 0x11f9}, 
394     {0x1e00, 0x1e1f}, {0x1e21, 0x1e9b}, {0x1ea0, 0x1ef9}, {0x1f00, 0x1f15}, 
395     {0x1f18, 0x1f1d}, {0x1f21, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, 
396     {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3}, 
397     {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe}, 
398     {0x2000, 0x200b}, {0x2010, 0x201f}, {0x2021, 0x2029}, {0x2030, 0x2046}, 
399     {0x2074, 0x208e}, {0x20a0, 0x20ac}, {0x20d0, 0x20e1}, {0x2100, 0x211f}, 
400     {0x2121, 0x2138}, {0x2153, 0x2182}, {0x2190, 0x21ea}, {0x2200, 0x221f}, 
401     {0x2221, 0x22f1}, {0x2302, 0x231f}, {0x2321, 0x237a}, {0x2400, 0x241f}, 
402     {0x2421, 0x2424}, {0x2440, 0x244a}, {0x2460, 0x24ea}, {0x2500, 0x251f}, 
403     {0x2521, 0x2595}, {0x25a0, 0x25ef}, {0x2600, 0x2613}, {0x261a, 0x261f}, 
404     {0x2621, 0x266f}, {0x2701, 0x2704}, {0x2706, 0x2709}, {0x270c, 0x271f}, 
405     {0x2721, 0x2727}, {0x2729, 0x274b}, {0x274f, 0x2752}, {0x2758, 0x275e}, 
406     {0x2761, 0x2767}, {0x2776, 0x2794}, {0x2798, 0x27af}, {0x27b1, 0x27be}, 
407     {0x3000, 0x301f}, {0x3021, 0x3037}, {0x3041, 0x3094}, {0x3099, 0x309e}, 
408     {0x30a1, 0x30fe}, {0x3105, 0x311f}, {0x3121, 0x312c}, {0x3131, 0x318e}, 
409     {0x3190, 0x319f}, {0x3200, 0x321c}, {0x3221, 0x3243}, {0x3260, 0x327b}, 
410     {0x327f, 0x32b0}, {0x32c0, 0x32cb}, {0x32d0, 0x32fe}, {0x3300, 0x331f}, 
411     {0x3321, 0x3376}, {0x337b, 0x33dd}, {0x33e0, 0x33fe}, {0x4e00, 0x4e1f}, 
412     {0x4e21, 0x4f1f}, {0x4f21, 0x501f}, {0x5021, 0x511f}, {0x5121, 0x521f}, 
413     {0x5221, 0x531f}, {0x5321, 0x541f}, {0x5421, 0x551f}, {0x5521, 0x561f}, 
414     {0x5621, 0x571f}, {0x5721, 0x581f}, {0x5821, 0x591f}, {0x5921, 0x5a1f}, 
415     {0x5a21, 0x5b1f}, {0x5b21, 0x5c1f}, {0x5c21, 0x5d1f}, {0x5d21, 0x5e1f}, 
416     {0x5e21, 0x5f1f}, {0x5f21, 0x601f}, {0x6021, 0x611f}, {0x6121, 0x621f}, 
417     {0x6221, 0x631f}, {0x6321, 0x641f}, {0x6421, 0x651f}, {0x6521, 0x661f}, 
418     {0x6621, 0x671f}, {0x6721, 0x681f}, {0x6821, 0x691f}, {0x6921, 0x6a1f}, 
419     {0x6a21, 0x6b1f}, {0x6b21, 0x6c1f}, {0x6c21, 0x6d1f}, {0x6d21, 0x6e1f}, 
420     {0x6e21, 0x6f1f}, {0x6f21, 0x701f}, {0x7021, 0x711f}, {0x7121, 0x721f}, 
421     {0x7221, 0x731f}, {0x7321, 0x741f}, {0x7421, 0x751f}, {0x7521, 0x761f}, 
422     {0x7621, 0x771f}, {0x7721, 0x781f}, {0x7821, 0x791f}, {0x7921, 0x7a1f}, 
423     {0x7a21, 0x7b1f}, {0x7b21, 0x7c1f}, {0x7c21, 0x7d1f}, {0x7d21, 0x7e1f}, 
424     {0x7e21, 0x7f1f}, {0x7f21, 0x801f}, {0x8021, 0x811f}, {0x8121, 0x821f}, 
425     {0x8221, 0x831f}, {0x8321, 0x841f}, {0x8421, 0x851f}, {0x8521, 0x861f}, 
426     {0x8621, 0x871f}, {0x8721, 0x881f}, {0x8821, 0x891f}, {0x8921, 0x8a1f}, 
427     {0x8a21, 0x8b1f}, {0x8b21, 0x8c1f}, {0x8c21, 0x8d1f}, {0x8d21, 0x8e1f}, 
428     {0x8e21, 0x8f1f}, {0x8f21, 0x901f}, {0x9021, 0x911f}, {0x9121, 0x921f}, 
429     {0x9221, 0x931f}, {0x9321, 0x941f}, {0x9421, 0x951f}, {0x9521, 0x961f}, 
430     {0x9621, 0x971f}, {0x9721, 0x981f}, {0x9821, 0x991f}, {0x9921, 0x9a1f}, 
431     {0x9a21, 0x9b1f}, {0x9b21, 0x9c1f}, {0x9c21, 0x9d1f}, {0x9d21, 0x9e1f}, 
432     {0x9e21, 0x9f1f}, {0x9f21, 0x9fa5}, {0xac00, 0xac1f}, {0xac21, 0xad1f}, 
433     {0xad21, 0xae1f}, {0xae21, 0xaf1f}, {0xaf21, 0xb01f}, {0xb021, 0xb11f}, 
434     {0xb121, 0xb21f}, {0xb221, 0xb31f}, {0xb321, 0xb41f}, {0xb421, 0xb51f}, 
435     {0xb521, 0xb61f}, {0xb621, 0xb71f}, {0xb721, 0xb81f}, {0xb821, 0xb91f}, 
436     {0xb921, 0xba1f}, {0xba21, 0xbb1f}, {0xbb21, 0xbc1f}, {0xbc21, 0xbd1f}, 
437     {0xbd21, 0xbe1f}, {0xbe21, 0xbf1f}, {0xbf21, 0xc01f}, {0xc021, 0xc11f}, 
438     {0xc121, 0xc21f}, {0xc221, 0xc31f}, {0xc321, 0xc41f}, {0xc421, 0xc51f}, 
439     {0xc521, 0xc61f}, {0xc621, 0xc71f}, {0xc721, 0xc81f}, {0xc821, 0xc91f}, 
440     {0xc921, 0xca1f}, {0xca21, 0xcb1f}, {0xcb21, 0xcc1f}, {0xcc21, 0xcd1f}, 
441     {0xcd21, 0xce1f}, {0xce21, 0xcf1f}, {0xcf21, 0xd01f}, {0xd021, 0xd11f}, 
442     {0xd121, 0xd21f}, {0xd221, 0xd31f}, {0xd321, 0xd41f}, {0xd421, 0xd51f}, 
443     {0xd521, 0xd61f}, {0xd621, 0xd71f}, {0xd721, 0xd7a3}, {0xf900, 0xf91f}, 
444     {0xf921, 0xfa1f}, {0xfa21, 0xfa2d}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, 
445     {0xfb21, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfc1f}, 
446     {0xfc21, 0xfd1f}, {0xfd21, 0xfd3f}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, 
447     {0xfdf0, 0xfdfb}, {0xfe21, 0xfe23}, {0xfe30, 0xfe44}, {0xfe49, 0xfe52}, 
448     {0xfe54, 0xfe66}, {0xfe68, 0xfe6b}, {0xfe70, 0xfe72}, {0xfe76, 0xfefc}, 
449     {0xff01, 0xff1f}, {0xff21, 0xff5e}, {0xff61, 0xffbe}, {0xffc2, 0xffc7}, 
450     {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}, {0xffe0, 0xffe6}, 
451     {0xffe8, 0xffee}
452 };
453
454 #define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange))
455
456 static chr graphCharTable[] = {
457     0x0360, 0x0361, 0x0374, 0x0375, 0x037a, 0x037e, 0x038c, 0x03da, 0x03dc, 
458     0x03de, 0x03e0, 0x04c7, 0x04c8, 0x04cb, 0x04cc, 0x04f8, 0x04f9, 0x0589, 
459     0x060c, 0x061b, 0x061f, 0x098f, 0x0990, 0x09b2, 0x09bc, 0x09c7, 0x09c8, 
460     0x09d7, 0x09dc, 0x09dd, 0x0a02, 0x0a0f, 0x0a10, 0x0a32, 0x0a33, 0x0a35, 
461     0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a47, 0x0a48, 0x0a5e, 0x0a8d, 0x0ab2, 
462     0x0ab3, 0x0ad0, 0x0ae0, 0x0b0f, 0x0b10, 0x0b32, 0x0b33, 0x0b47, 0x0b48, 
463     0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b82, 0x0b83, 0x0b99, 0x0b9a, 0x0b9c, 
464     0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0bd7, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 
465     0x0c82, 0x0c83, 0x0cd5, 0x0cd6, 0x0cde, 0x0ce0, 0x0ce1, 0x0d02, 0x0d03, 
466     0x0d57, 0x0d60, 0x0d61, 0x0e81, 0x0e82, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 
467     0x0e8d, 0x0ea5, 0x0ea7, 0x0eaa, 0x0eab, 0x0ec6, 0x0edc, 0x0edd, 0x0f97, 
468     0x0fb9, 0x10fb, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2300, 0x274d, 0x2756, 
469     0x303f, 0xfb1e, 0xfb1f, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfe74, 
470     0xfffc, 0xfffd
471 };
472
473 #define NUM_GRAPH_CHAR (sizeof(graphCharTable)/sizeof(chr))
474
475
476 #define CH      NOCELT
477
478 /*
479  - nmcces - how many distinct MCCEs are there?
480  ^ static int nmcces(struct vars *);
481  */
482 static int
483 nmcces(v)
484 struct vars *v;
485 {
486         return 0;
487 }
488
489 /*
490  - nleaders - how many chrs can be first chrs of MCCEs?
491  ^ static int nleaders(struct vars *);
492  */
493 static int
494 nleaders(v)
495 struct vars *v;
496 {
497         return 0;
498 }
499
500 /*
501  - allmcces - return a cvec with all the MCCEs of the locale
502  ^ static struct cvec *allmcces(struct vars *, struct cvec *);
503  */
504 static struct cvec *
505 allmcces(v, cv)
506 struct vars *v;
507 struct cvec *cv;                /* this is supposed to have enough room */
508 {
509         return clearcvec(cv);
510 }
511
512 /*
513  - element - map collating-element name to celt
514  ^ static celt element(struct vars *, chr *, chr *);
515  */
516 static celt
517 element(v, startp, endp)
518 struct vars *v;
519 chr *startp;                    /* points to start of name */
520 chr *endp;                      /* points just past end of name */
521 {
522         struct cname *cn;
523         size_t len;
524         Tcl_DString ds;
525         char *np;
526
527         /* generic:  one-chr names stand for themselves */
528         assert(startp < endp);
529         len = endp - startp;
530         if (len == 1)
531                 return *startp;
532
533         NOTE(REG_ULOCALE);
534
535         /* search table */
536         Tcl_DStringInit(&ds);
537         np = Tcl_UniCharToUtfDString(startp, (int)len, &ds);
538         for (cn = cnames; cn->name != NULL; cn++)
539                 if (strlen(cn->name) == len && strncmp(cn->name, np, len) == 0)
540                         break;          /* NOTE BREAK OUT */
541         Tcl_DStringFree(&ds);
542         if (cn->name != NULL)
543                 return CHR(cn->code);
544
545         /* couldn't find it */
546         ERR(REG_ECOLLATE);
547         return 0;
548 }
549
550 /*
551  - range - supply cvec for a range, including legality check
552  ^ static struct cvec *range(struct vars *, celt, celt, int);
553  */
554 static struct cvec *
555 range(v, a, b, cases)
556 struct vars *v;
557 celt a;
558 celt b;                         /* might equal a */
559 int cases;                      /* case-independent? */
560 {
561         int nchrs;
562         struct cvec *cv;
563         celt c, lc, uc, tc;
564
565         if (a != b && !before(a, b)) {
566                 ERR(REG_ERANGE);
567                 return NULL;
568         }
569
570         if (!cases) {           /* easy version */
571                 cv = getcvec(v, 0, 1, 0);
572                 NOERRN();
573                 addrange(cv, a, b);
574                 return cv;
575         }
576
577         /*
578          * When case-independent, it's hard to decide when cvec ranges are
579          * usable, so for now at least, we won't try.  We allocate enough
580          * space for two case variants plus a little extra for the two
581          * title case variants.
582          */
583
584         nchrs = (b - a + 1)*2 + 4;
585
586         cv = getcvec(v, nchrs, 0, 0);
587         NOERRN();
588
589         for (c = a; c <= b; c++) {
590                 addchr(cv, c);
591                 lc = Tcl_UniCharToLower((chr)c);
592                 uc = Tcl_UniCharToUpper((chr)c);
593                 tc = Tcl_UniCharToTitle((chr)c);
594                 if (c != lc) {
595                         addchr(cv, lc);
596                 }
597                 if (c != uc) {
598                         addchr(cv, uc);
599                 }
600                 if (c != tc && tc != uc) {
601                         addchr(cv, tc);
602                 }
603         }
604
605         return cv;
606 }
607
608 /*
609  - before - is celt x before celt y, for purposes of range legality?
610  ^ static int before(celt, celt);
611  */
612 static int                      /* predicate */
613 before(x, y)
614 celt x;
615 celt y;
616 {
617         /* trivial because no MCCEs */
618         if (x < y)
619                 return 1;
620         return 0;
621 }
622
623 /*
624  - eclass - supply cvec for an equivalence class
625  * Must include case counterparts on request.
626  ^ static struct cvec *eclass(struct vars *, celt, int);
627  */
628 static struct cvec *
629 eclass(v, c, cases)
630 struct vars *v;
631 celt c;
632 int cases;                      /* all cases? */
633 {
634         struct cvec *cv;
635
636         /* crude fake equivalence class for testing */
637         if ((v->cflags&REG_FAKE) && c == 'x') {
638                 cv = getcvec(v, 4, 0, 0);
639                 addchr(cv, (chr)'x');
640                 addchr(cv, (chr)'y');
641                 if (cases) {
642                         addchr(cv, (chr)'X');
643                         addchr(cv, (chr)'Y');
644                 }
645                 return cv;
646         }
647
648         /* otherwise, none */
649         if (cases)
650                 return allcases(v, c);
651         cv = getcvec(v, 1, 0, 0);
652         assert(cv != NULL);
653         addchr(cv, (chr)c);
654         return cv;
655 }
656
657 /*
658  - cclass - supply cvec for a character class
659  * Must include case counterparts on request.
660  ^ static struct cvec *cclass(struct vars *, chr *, chr *, int);
661  */
662 static struct cvec *
663 cclass(v, startp, endp, cases)
664 struct vars *v;
665 chr *startp;                    /* where the name starts */
666 chr *endp;                      /* just past the end of the name */
667 int cases;                      /* case-independent? */
668 {
669     size_t len;
670     struct cvec *cv = NULL;
671     Tcl_DString ds;
672     char *np, **namePtr;
673     int i, index;
674
675     /*
676      * The following arrays define the valid character class names.
677      */
678
679     static char *classNames[] = {
680         "alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph",
681         "lower", "print", "punct", "space", "upper", "xdigit", NULL
682     };
683
684     enum classes {
685         CC_ALNUM, CC_ALPHA, CC_ASCII, CC_BLANK, CC_CNTRL, CC_DIGIT, CC_GRAPH,
686         CC_LOWER, CC_PRINT, CC_PUNCT, CC_SPACE, CC_UPPER, CC_XDIGIT
687     };
688     
689
690     /*
691      * Extract the class name
692      */
693
694     len = endp - startp;
695     Tcl_DStringInit(&ds);
696     np = Tcl_UniCharToUtfDString(startp, (int)len, &ds);
697
698     /*
699      * Remap lower and upper to alpha if the match is case insensitive.
700      */
701
702     if (cases && len == 5 && (strncmp("lower", np, 5) == 0
703             || strncmp("upper", np, 5) == 0)) {
704         np = "alpha";
705     }
706
707     /*
708      * Map the name to the corresponding enumerated value.
709      */
710
711     index = -1;
712     for (namePtr = classNames, i = 0; *namePtr != NULL; namePtr++, i++) {
713         if ((strlen(*namePtr) == len) && (strncmp(*namePtr, np, len) == 0)) {
714             index = i;
715             break;
716         }
717     }
718     Tcl_DStringInit(&ds);
719     if (index == -1) {
720         ERR(REG_ECTYPE);
721         return NULL;
722     }
723     
724     /*
725      * Now compute the character class contents.
726      */
727
728     switch((enum classes) index) {
729         case CC_PRINT:
730         case CC_ALNUM:
731             cv = getcvec(v, NUM_ALPHA_CHAR,
732                     NUM_DIGIT_RANGE + NUM_ALPHA_RANGE, 0);
733             if (cv) {
734                 for (i = 0; i < NUM_ALPHA_CHAR; i++) {
735                     addchr(cv, alphaCharTable[i]);
736                 }
737                 for (i = 0; i < NUM_ALPHA_RANGE; i++) {
738                     addrange(cv, alphaRangeTable[i].start,
739                              alphaRangeTable[i].end);
740                 }
741                 for (i = 0; i < NUM_DIGIT_RANGE; i++) {
742                     addrange(cv, digitRangeTable[i].start,
743                             digitRangeTable[i].end);
744                 }
745             }
746             break;
747         case CC_ALPHA:
748             cv = getcvec(v, NUM_ALPHA_CHAR, NUM_ALPHA_RANGE, 0);
749             if (cv) {
750                 for (i = 0; i < NUM_ALPHA_RANGE; i++) {
751                     addrange(cv, alphaRangeTable[i].start,
752                              alphaRangeTable[i].end);
753                 }
754                 for (i = 0; i < NUM_ALPHA_CHAR; i++) {
755                     addchr(cv, alphaCharTable[i]);
756                 }
757             }
758             break;
759         case CC_ASCII:
760             cv = getcvec(v, 0, 1, 0);
761             if (cv) {
762                 addrange(cv, 0, 0x7f);
763             }
764             break;
765         case CC_BLANK:
766             cv = getcvec(v, 2, 0, 0);
767             addchr(cv, '\t');
768             addchr(cv, ' ');
769             break;
770         case CC_CNTRL:
771             cv = getcvec(v, 0, 2, 0);
772             addrange(cv, 0x0, 0x1f);
773             addrange(cv, 0x7f, 0x9f);
774             break;
775         case CC_DIGIT:
776             cv = getcvec(v, 0, NUM_DIGIT_RANGE, 0);
777             if (cv) {   
778                 for (i = 0; i < NUM_DIGIT_RANGE; i++) {
779                     addrange(cv, digitRangeTable[i].start,
780                             digitRangeTable[i].end);
781                 }
782             }
783             break;
784         case CC_PUNCT:
785             cv = getcvec(v, NUM_PUNCT_CHAR, NUM_PUNCT_RANGE, 0);
786             if (cv) {
787                 for (i = 0; i < NUM_PUNCT_RANGE; i++) {
788                     addrange(cv, punctRangeTable[i].start,
789                              punctRangeTable[i].end);
790                 }
791                 for (i = 0; i < NUM_PUNCT_CHAR; i++) {
792                     addchr(cv, punctCharTable[i]);
793                 }
794             }
795             break;
796         case CC_XDIGIT:
797             cv = getcvec(v, 0, NUM_DIGIT_RANGE+2, 0);
798             if (cv) {   
799                 addrange(cv, '0', '9');
800                 addrange(cv, 'a', 'f');
801                 addrange(cv, 'A', 'F');
802             }
803             break;
804         case CC_SPACE:
805             cv = getcvec(v, NUM_SPACE_CHAR, NUM_SPACE_RANGE, 0);
806             if (cv) {
807                 for (i = 0; i < NUM_SPACE_RANGE; i++) {
808                     addrange(cv, spaceRangeTable[i].start,
809                              spaceRangeTable[i].end);
810                 }
811                 for (i = 0; i < NUM_SPACE_CHAR; i++) {
812                     addchr(cv, spaceCharTable[i]);
813                 }
814             }
815             break;
816         case CC_LOWER:
817             cv  = getcvec(v, NUM_LOWER_CHAR, NUM_LOWER_RANGE, 0);
818             if (cv) {
819                 for (i = 0; i < NUM_LOWER_RANGE; i++) {
820                     addrange(cv, lowerRangeTable[i].start,
821                              lowerRangeTable[i].end);
822                 }
823                 for (i = 0; i < NUM_LOWER_CHAR; i++) {
824                     addchr(cv, lowerCharTable[i]);
825                 }
826             }
827             break;
828         case CC_UPPER:
829             cv  = getcvec(v, NUM_UPPER_CHAR, NUM_UPPER_RANGE, 0);
830             if (cv) {
831                 for (i = 0; i < NUM_UPPER_RANGE; i++) {
832                     addrange(cv, upperRangeTable[i].start,
833                              upperRangeTable[i].end);
834                 }
835                 for (i = 0; i < NUM_UPPER_CHAR; i++) {
836                     addchr(cv, upperCharTable[i]);
837                 }
838             }
839             break;
840         case CC_GRAPH:
841             cv  = getcvec(v, NUM_GRAPH_CHAR, NUM_GRAPH_RANGE, 0);
842             if (cv) {
843                 for (i = 0; i < NUM_GRAPH_RANGE; i++) {
844                     addrange(cv, graphRangeTable[i].start,
845                              graphRangeTable[i].end);
846                 }
847                 for (i = 0; i < NUM_GRAPH_CHAR; i++) {
848                     addchr(cv, graphCharTable[i]);
849                 }
850             }
851             break;
852     }
853     if (cv == NULL) {
854         ERR(REG_ESPACE);
855     }
856     return cv;
857 }
858
859 /*
860  - allcases - supply cvec for all case counterparts of a chr (including itself)
861  * This is a shortcut, preferably an efficient one, for simple characters;
862  * messy cases are done via range().
863  ^ static struct cvec *allcases(struct vars *, pchr);
864  */
865 static struct cvec *
866 allcases(v, pc)
867 struct vars *v;
868 pchr pc;
869 {
870         struct cvec *cv;
871         chr c = (chr)pc;
872         chr lc, uc, tc;
873
874         lc = Tcl_UniCharToLower((chr)c);
875         uc = Tcl_UniCharToUpper((chr)c);
876         tc = Tcl_UniCharToTitle((chr)c);
877
878         if (tc != uc) {
879             cv = getcvec(v, 3, 0, 0);
880             addchr(cv, tc);
881         } else {
882             cv = getcvec(v, 2, 0, 0);
883         }
884         addchr(cv, lc);
885         if (lc != uc) {
886             addchr(cv, uc);
887         }
888         return cv;
889 }
890
891 /*
892  - cmp - chr-substring compare
893  * Backrefs need this.  It should preferably be efficient.
894  * Note that it does not need to report anything except equal/unequal.
895  * Note also that the length is exact, and the comparison should not
896  * stop at embedded NULs!
897  ^ static int cmp(CONST chr *, CONST chr *, size_t);
898  */
899 static int                      /* 0 for equal, nonzero for unequal */
900 cmp(x, y, len)
901 CONST chr *x;
902 CONST chr *y;
903 size_t len;                     /* exact length of comparison */
904 {
905         return memcmp(VS(x), VS(y), len*sizeof(chr));
906 }
907
908 /*
909  - casecmp - case-independent chr-substring compare
910  * REG_ICASE backrefs need this.  It should preferably be efficient.
911  * Note that it does not need to report anything except equal/unequal.
912  * Note also that the length is exact, and the comparison should not
913  * stop at embedded NULs!
914  ^ static int casecmp(CONST chr *, CONST chr *, size_t);
915  */
916 static int                      /* 0 for equal, nonzero for unequal */
917 casecmp(x, y, len)
918 CONST chr *x;
919 CONST chr *y;
920 size_t len;                     /* exact length of comparison */
921 {
922         size_t i;
923         CONST chr *xp;
924         CONST chr *yp;
925
926         for (xp = x, yp = y, i = len; i > 0; i--)
927                 if (Tcl_UniCharToLower(*xp++) != Tcl_UniCharToLower(*yp++))
928                         return 1;
929         return 0;
930 }