25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-20 16:15:59 +01:00

*** empty log message ***

SVN Revision: 143
This commit is contained in:
Alexey Shchepin 2003-10-06 20:12:11 +00:00
parent 94690e5eb6
commit e1de741cfc
6 changed files with 3588 additions and 363 deletions

View File

@ -27,7 +27,7 @@ $(OUTDIR)/%.beam: %.erl
#all: $(ERLSHLIBS)
# erl -s make all report "{outdir, \"..\"}" -noinput -s erlang halt
$(ERLSHLIBS): ../%.so: %.c
$(ERLSHLIBS): ../%.so: %.c uni_data.c uni_norm.c
gcc -Wall $(INCLUDES) $(LIBDIRS) \
$(subst ../,,$(subst .so,.c,$@)) \
-lerl_interface \

View File

@ -6,6 +6,7 @@
#include <iconv.h>
#include "uni_data.c"
#include "uni_norm.c"
#define NAMEPREP_COMMAND 1
#define NODEPREP_COMMAND 2
@ -31,12 +32,71 @@ static void stringprep_erl_stop(ErlDrvData handle)
driver_free((char*)handle);
}
static int combine(int ch1, int ch2)
{
int info1, info2;
info1 = GetUniCharCompInfo(ch1);
if(info1 != -1) {
if(info1 & CompSingleMask) {
if (ch2 == compFirstList[info1 & CompMask][0]) {
return compFirstList[info1 & CompMask][1];
} else
return 0;
}
} else
return 0;
info2 = GetUniCharCompInfo(ch2);
if(info2 != -1) {
if (info2 & CompSingleMask) {
if (ch1 == compSecondList[info2 & CompMask][0]) {
return compSecondList[info2 & CompMask][1];
} else
return 0;
}
} else
return 0;
return compBothList[info1][info2];
}
#define ADD_UCHAR(ruc) \
if(ruc < 0x80) { \
if(pos >= size) { \
size = 2*size + 1; \
rstring = driver_realloc(rstring, size); \
} \
rstring[pos] = (char) ruc; \
pos++; \
} else if(ruc < 0x7FF) { \
if(pos + 1 >= size) { \
size = 2*size + 2; \
rstring = driver_realloc(rstring, size); \
} \
rstring[pos] = (char) ((ruc >> 6) | 0xC0); \
rstring[pos+1] = (char) ((ruc | 0x80) & 0xBF); \
pos += 2; \
} else if(ruc < 0xFFFF) { \
if(pos + 2 >= size) { \
size = 2*size + 3; \
rstring = driver_realloc(rstring, size); \
} \
rstring[pos] = (char) ((ruc >> 12) | 0xE0); \
rstring[pos+1] = (char) (((ruc >> 6) | 0x80) & 0xBF); \
rstring[pos+2] = (char) ((ruc | 0x80) & 0xBF); \
pos += 3; \
}
static int stringprep_erl_control(ErlDrvData drv_data,
unsigned int command,
char *buf, int len,
char **rbuf, int rlen)
{
int i, j=1;
int i, j, pos=1;
unsigned char c;
int bad = 0;
int uc, ruc;
@ -44,7 +104,8 @@ static int stringprep_erl_control(ErlDrvData drv_data,
int info;
int prohibit, tolower;
char *rstring;
int *mc;
size = len + 1;
rstring = driver_alloc(size);
@ -116,43 +177,41 @@ static int stringprep_erl_control(ErlDrvData drv_data,
if(!(info & B1Mask))
{
if(tolower) {
ruc = uc + GetDelta(info);
if(!(info & MCMask))
{
ruc = uc + GetDelta(info);
//info = GetUniCharDecompInfo(ruc);
//if(info >= 0) {
// printf("Decomposition %x: ", ruc);
// for(j = 0; j < GetDecompLen(info); j++) {
// printf("%x ", decompList[GetDecompShift(info) + j]);
// }
// printf("\r\n");
//}
ADD_UCHAR(ruc);
} else {
mc = GetMC(info);
for(j = 1; j <= mc[0]; j++) {
ruc = mc[j];
//printf("Char %x cclass %d\r\n", ruc, GetUniCharCClass(ruc));
ADD_UCHAR(ruc);
}
}
} else {
ruc = uc;
}
if(ruc < 0x80) {
if(j >= size) {
size = 2*size + 1;
rstring = driver_realloc(rstring, size);
}
rstring[j] = (char) ruc;
j++;
} else if(ruc < 0x7FF) {
if(j + 1 >= size) {
size = 2*size + 2;
rstring = driver_realloc(rstring, size);
}
rstring[j] = (char) ((ruc >> 6) | 0xC0);
rstring[j+1] = (char) ((ruc | 0x80) & 0xBF);
j += 2;
} else if(ruc < 0xFFFF) {
if(j + 2 >= size) {
size = 2*size + 3;
rstring = driver_realloc(rstring, size);
}
rstring[j] = (char) ((ruc >> 12) | 0xE0);
rstring[j+1] = (char) (((ruc >> 6) | 0x80) & 0xBF);
rstring[j+2] = (char) ((ruc | 0x80) & 0xBF);
j += 3;
ADD_UCHAR(ruc);
}
}
}
//printf("Combine: %x\r\n", combine(0x438, 0x301));
rstring[0] = 1;
*rbuf = rstring;
return j;
return pos;
}

View File

@ -42,17 +42,17 @@ static unsigned char pageMap[] = {
124, 125, 126, 127, 18, 18, 128, 18, 129, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 130, 8, 8, 131, 132, 133,
134, 135, 18, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 51,
146, 147, 148, 149, 150, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 151, 18, 152, 153, 22, 143, 4, 22, 154, 51, 22, 155, 156, 157,
158, 22, 22, 22, 22, 22, 22, 22, 22, 159, 22, 22, 160, 161, 4, 4, 4,
162, 163, 164, 165, 166, 167, 145, 168, 22, 22, 22, 22, 22, 22, 22,
134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 51,
147, 148, 149, 150, 151, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 152, 18, 153, 154, 22, 144, 4, 22, 155, 51, 22, 156, 157, 158,
159, 22, 22, 22, 22, 22, 22, 22, 22, 160, 22, 22, 161, 162, 4, 4, 4,
163, 164, 165, 166, 167, 168, 146, 169, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 169, 22, 22, 170, 22, 22, 22, 22, 22, 22, 171, 4, 172,
173, 37, 18, 174, 175, 18, 176, 177, 178, 18, 18, 113, 128, 4, 17,
179, 18, 180, 181, 18, 182, 183, 184, 18, 18, 18, 185, 18, 18, 186,
184, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
4, 4, 4, 4, 4, 170, 22, 22, 171, 22, 22, 22, 22, 22, 22, 172, 4, 173,
174, 37, 18, 175, 176, 18, 177, 178, 179, 18, 18, 113, 128, 4, 17,
180, 18, 181, 182, 18, 183, 184, 185, 18, 18, 18, 186, 18, 18, 187,
185, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
@ -64,7 +64,7 @@ static unsigned char pageMap[] = {
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 187, 4, 4, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 188, 4, 4, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
@ -102,10 +102,10 @@ static unsigned char pageMap[] = {
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 188, 4, 4, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 189, 4, 4, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
189, 22, 154, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
190, 22, 155, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
@ -128,29 +128,29 @@ static unsigned char pageMap[] = {
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 190, 4, 4, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191,
191, 191, 191, 191, 18, 18, 18, 18, 18, 18, 18, 18, 18, 192, 18, 193,
4, 4, 4, 4, 194, 195, 196, 46, 46, 197, 198, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 199, 200, 46, 201, 46, 202, 203, 204, 205, 206, 207,
46, 46, 46, 208, 165, 209, 210, 211, 18, 184, 212, 213
18, 18, 18, 18, 191, 4, 4, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 18, 18, 18, 18, 18, 18, 18, 18, 18, 193, 18, 194,
4, 4, 4, 4, 195, 196, 197, 46, 46, 198, 199, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 200, 201, 46, 202, 46, 203, 204, 205, 206, 207, 208,
46, 46, 46, 209, 166, 210, 211, 212, 18, 185, 213, 214
};
/*
@ -169,306 +169,314 @@ static unsigned char groupMap[] = {
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 7, 2, 2, 2, 2, 2, 2, 2, 8, 2, 2,
2, 2, 5, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 9, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5,
5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9,
5, 9, 5, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9,
5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9,
5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
9, 5, 9, 5, 9, 5, 9, 5, 10, 9, 5, 9, 5, 9, 5, 11, 5, 12, 9, 5, 9, 5,
13, 9, 5, 14, 14, 9, 5, 5, 15, 16, 17, 9, 5, 14, 18, 5, 19, 20, 9,
5, 5, 5, 19, 21, 5, 22, 9, 5, 9, 5, 9, 5, 23, 9, 5, 23, 5, 5, 9, 5,
23, 9, 5, 24, 24, 9, 5, 9, 5, 25, 9, 5, 5, 5, 9, 5, 5, 5, 5, 5, 5,
5, 26, 9, 5, 26, 9, 5, 26, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
5, 26, 9, 5, 9, 5, 27, 28, 9, 5, 9, 5, 9, 5, 9, 5, 29, 6, 9, 5, 9,
5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
5, 5, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 11, 5, 10, 5, 10, 5, 10, 5, 5,
10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 12, 10, 5,
10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 13, 10, 5, 10, 5, 10, 5, 14, 5, 15, 10, 5, 10, 5,
16, 10, 5, 17, 17, 10, 5, 5, 18, 19, 20, 10, 5, 17, 21, 5, 22, 23,
10, 5, 5, 5, 22, 24, 5, 25, 10, 5, 10, 5, 10, 5, 26, 10, 5, 26, 5,
5, 10, 5, 26, 10, 5, 27, 27, 10, 5, 10, 5, 28, 10, 5, 5, 5, 10, 5,
5, 5, 5, 5, 5, 5, 29, 10, 5, 29, 10, 5, 29, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5, 10, 5, 10, 5,
10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 30, 29, 10, 5, 10, 5, 31, 32, 10,
5, 10, 5, 10, 5, 10, 5, 33, 6, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5,
5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 2,
2, 2, 2, 2, 2, 2, 2, 2, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 30, 2, 2, 2, 2,
2, 2, 2, 2, 2, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6,
6, 6, 5, 6, 6, 6, 2, 6, 6, 6, 6, 6, 2, 2, 31, 2, 32, 32, 32, 6, 33,
6, 34, 34, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6,
4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 35,
36, 5, 5, 5, 37, 38, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9,
5, 9, 5, 9, 5, 9, 5, 9, 5, 39, 40, 41, 5, 42, 43, 2, 6, 6, 6, 6, 6,
6, 6, 6, 6, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
44, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 9, 5, 5, 2, 2, 2, 2, 6, 2, 2, 9, 5, 9, 5, 9, 5, 9, 5,
9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5,
9, 5, 9, 5, 9, 5, 6, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 6,
6, 9, 5, 6, 6, 6, 6, 6, 6, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
9, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 45, 45, 45, 45, 45, 45, 45, 45,
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 6, 6, 5, 5, 5,
5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5,
2, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 6, 2, 2, 2, 46, 2, 46, 2, 2, 46, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 6, 6, 6, 6, 6, 46, 46,
46, 46, 46, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 46, 6, 6,
6, 46, 6, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 6, 6, 6, 6, 6, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
46, 46, 46, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 2, 2, 2, 2, 2, 2, 2, 47, 2, 2, 2, 2, 2, 2, 2, 46,
46, 2, 2, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 46, 46,
46, 46, 46, 6, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 6, 6, 46, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 6, 6, 6, 2,
5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5,
5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2,
2, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 46, 46, 46, 46, 46, 46, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 46, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 5, 6, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 34, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 6, 6, 5, 6, 6, 6, 2,
6, 6, 6, 6, 6, 2, 2, 35, 2, 36, 36, 36, 6, 37, 6, 38, 38, 39, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4,
4, 4, 5, 5, 5, 5, 40, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 41, 42, 5, 5, 5, 43,
44, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 45, 46, 47, 5, 48, 49, 2, 6, 6, 6, 6, 6, 6,
6, 6, 6, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 10, 5, 5, 2, 2, 2, 2, 6, 2, 2, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5,
10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 6, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 10, 5, 6, 6, 10, 5, 6, 6, 6, 6, 6, 6, 10, 5,
10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51, 51, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 52, 6, 5, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 53,
2, 53, 2, 2, 53, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 6, 6, 6, 6, 6, 53, 53, 53, 53, 53, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 53, 6, 6, 6, 53, 6, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 6, 6, 6, 6, 6, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 53, 53, 53, 2, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
2, 2, 2, 2, 2, 2, 2, 54, 2, 2, 2, 2, 2, 2, 2, 53, 53, 2, 2, 2, 2, 2,
2, 2, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 6, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 6, 6, 53, 2, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 53, 53, 53, 53,
53, 53, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 53, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 2, 2, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 2, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 2, 6,
6, 5, 2, 2, 2, 2, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 2, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 6, 6, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5,
5, 5, 5, 5, 5, 5, 6, 5, 6, 6, 6, 5, 5, 5, 5, 6, 6, 2, 6, 5, 5, 5, 2,
2, 2, 2, 6, 6, 5, 5, 6, 6, 5, 5, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6,
6, 6, 6, 5, 5, 6, 5, 5, 5, 2, 2, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 2, 6, 6, 5, 5,
5, 5, 5, 5, 6, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 6,
5, 5, 6, 5, 5, 6, 6, 2, 6, 5, 5, 5, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2,
2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 6, 5, 6, 6, 6, 6,
6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 2, 2, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5,
5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 6, 5, 5, 5, 5, 5, 6, 6, 2, 5, 5,
5, 5, 2, 2, 2, 2, 2, 6, 2, 2, 5, 6, 5, 5, 2, 6, 6, 5, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 6, 6, 5, 5, 5, 5, 6,
6, 2, 5, 5, 2, 5, 2, 2, 2, 6, 6, 6, 5, 5, 6, 6, 5, 5, 2, 6, 6, 6, 6,
6, 6, 6, 6, 2, 5, 6, 6, 6, 6, 5, 5, 6, 5, 5, 5, 6, 6, 6, 6, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 2, 5, 6, 5, 5, 5, 5, 5, 5, 6, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 6,
6, 6, 5, 5, 6, 5, 6, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 5, 5, 5, 6, 6, 6,
5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 6, 6, 6, 6, 5, 5, 2, 5, 5, 6, 6,
6, 5, 5, 5, 6, 5, 5, 5, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 5,
5, 5, 5, 6, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5,
5, 5, 6, 6, 6, 6, 2, 2, 2, 5, 5, 5, 5, 6, 2, 2, 2, 6, 2, 2, 2, 2, 6,
6, 6, 6, 6, 6, 6, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 6, 6, 6, 6,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 6, 6, 6, 6, 5, 2, 5, 5,
5, 5, 5, 6, 2, 5, 5, 6, 5, 5, 2, 2, 6, 6, 6, 6, 6, 6, 6, 5, 5, 6, 6,
6, 6, 6, 6, 6, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 5, 5, 5, 2, 2, 2, 6, 6, 5,
5, 5, 6, 5, 5, 5, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 6, 5, 5, 5,
5, 5, 5, 5, 6, 6, 6, 2, 6, 6, 6, 6, 5, 5, 5, 2, 2, 2, 6, 2, 6, 5, 5,
5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 5, 5, 6, 5, 6, 6, 5, 5, 6, 5, 6, 6,
5, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5,
6, 5, 6, 5, 6, 6, 5, 5, 6, 5, 5, 5, 5, 2, 5, 5, 2, 2, 2, 2, 2, 2, 6,
2, 2, 5, 6, 6, 5, 5, 5, 5, 5, 6, 5, 6, 2, 2, 2, 2, 2, 2, 6, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5,
2, 5, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 5, 2, 2, 2, 2, 2, 5, 2, 2, 5, 5, 5, 5, 6, 6, 6, 6, 2, 2, 2,
2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 5, 5, 5,
5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 6, 5, 5, 5, 5, 5, 6, 5, 5, 6, 5, 2, 2,
2, 2, 5, 2, 6, 6, 6, 2, 2, 5, 2, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 6, 6, 6,
6, 6, 6, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 6, 6, 6, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 6, 6, 6, 6, 6, 5, 5, 5, 5, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5,
5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 5, 5, 6, 6, 5, 5, 5,
5, 5, 5, 5, 6, 5, 6, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5,
6, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 5, 5, 6, 6,
5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 2, 5, 5,
5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 2, 6, 6, 5, 2, 2, 2, 2, 6,
6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 5, 5,
6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6,
5, 6, 6, 6, 5, 5, 5, 5, 6, 6, 2, 6, 5, 5, 5, 2, 2, 2, 2, 6, 6, 5, 5,
6, 6, 5, 5, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 5, 5, 6, 5,
5, 5, 2, 2, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5,
5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 2, 6, 6, 5, 5, 5, 5, 5, 5, 6, 6, 6,
6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 6, 5, 5, 6, 5, 5, 6, 6,
2, 6, 5, 5, 5, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 2, 2, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2, 2, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 5, 6, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5, 5, 6, 5, 5, 6, 5, 5, 5, 5, 5, 6, 6, 2, 5, 5, 5, 5, 2, 2, 2, 2, 2,
6, 2, 2, 5, 6, 5, 5, 2, 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 5, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5,
5, 5, 5, 5, 5, 5, 6, 5, 5, 6, 6, 5, 5, 5, 5, 6, 6, 2, 5, 5, 2, 5, 2,
2, 2, 6, 6, 6, 5, 5, 6, 6, 5, 5, 2, 6, 6, 6, 6, 6, 6, 6, 6, 2, 5, 6,
6, 6, 6, 5, 5, 6, 5, 5, 5, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 5, 6, 5, 5,
5, 5, 5, 5, 6, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 6, 6, 6, 5, 5, 6, 5, 6,
5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 5, 5, 5, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5,
5, 6, 5, 5, 5, 6, 6, 6, 6, 5, 5, 2, 5, 5, 6, 6, 6, 5, 5, 5, 6, 5, 5,
5, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5,
6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 2, 2, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
2, 2, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 6, 2, 2, 6, 6, 6, 6,
5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 6, 6, 6, 6, 2,
2, 2, 5, 5, 5, 5, 6, 2, 2, 2, 6, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 2,
2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5,
6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 5, 5, 5, 5, 5, 6, 6, 6, 6, 5, 2, 5, 5, 5, 5, 5, 6, 2, 5, 5,
6, 5, 5, 2, 2, 6, 6, 6, 6, 6, 6, 6, 5, 5, 6, 6, 6, 6, 6, 6, 6, 5, 6,
5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 5, 5, 5, 2, 2, 2, 6, 6, 5, 5, 5, 6, 5, 5, 5, 2,
6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 6,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
2, 6, 6, 6, 6, 5, 5, 5, 2, 2, 2, 6, 2, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5,
2, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5,
6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 7, 2, 2, 2, 2,
7, 7, 7, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 5, 5,
5, 5, 2, 5, 5, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 2, 5, 5, 5, 5, 5, 5,
5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
6, 6, 6, 6, 5, 5, 6, 5, 6, 6, 5, 5, 6, 5, 6, 6, 5, 6, 6, 6, 6, 6, 6,
5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 6, 5, 6, 5, 6, 6, 5,
5, 6, 5, 5, 5, 5, 2, 5, 5, 2, 2, 2, 2, 2, 2, 6, 2, 2, 5, 6, 6, 5, 5,
5, 5, 5, 6, 5, 6, 2, 2, 2, 2, 2, 2, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 5, 2, 2, 2, 2, 2,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 5, 9, 5, 9, 5, 9,
5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 5, 5, 5, 5, 48, 6,
6, 6, 6, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
9, 5, 9, 5, 9, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49,
49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 5, 5, 6, 6, 49, 49, 49, 49, 49,
49, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, 5,
5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49, 49, 49, 5, 5, 5, 5, 5,
5, 6, 6, 49, 49, 49, 49, 49, 49, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 49,
6, 49, 6, 49, 6, 49, 5, 5, 5, 5, 5, 5, 5, 5, 49, 49, 49, 49, 49, 49,
49, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 49, 49,
50, 50, 5, 2, 51, 2, 2, 2, 5, 5, 5, 6, 5, 5, 52, 52, 52, 52, 5, 2,
2, 2, 5, 5, 5, 5, 6, 6, 5, 5, 49, 49, 53, 53, 6, 2, 2, 2, 5, 5, 5,
5, 5, 5, 5, 5, 49, 49, 54, 54, 55, 2, 2, 2, 6, 6, 5, 5, 5, 6, 5, 5,
56, 56, 57, 57, 5, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 58, 58,
58, 59, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2,
2, 2, 5, 2, 2, 5, 5, 5, 5, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 58, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 5, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 5, 2, 60,
2, 5, 2, 61, 62, 5, 5, 2, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, 6, 6,
5, 5, 5, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 6, 6, 6, 6, 6, 6, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 63,
63, 63, 63, 63, 63, 63, 63, 63, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5,
5, 5, 5, 5, 5, 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 5, 5, 6, 5, 5, 5, 5, 5, 6, 5, 5, 6, 5, 2, 2, 2, 2, 5, 2, 6, 6, 6,
2, 2, 5, 2, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,
6, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 6, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 6, 2, 2, 2, 2, 6, 6, 6,
2, 6, 2, 2, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 2, 2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
6, 2, 2, 2, 2, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5,
5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 5,
5, 5, 5, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5,
5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 5, 5, 6, 6, 5, 5, 5,
5, 5, 5, 5, 6, 5, 6, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6,
5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 5, 5, 6, 6,
5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5,
6, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 6,
6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 6, 5, 5, 5, 5, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 5, 5, 6, 6, 6,
6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 6, 5, 5, 5, 6, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 6, 6, 6, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 7, 2, 2, 2, 2, 7, 7, 7, 6, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5,
10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 55, 56, 57, 58, 59, 60, 6, 6, 6,
6, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5, 10,
5, 10, 5, 10, 5, 10, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 61,
61, 61, 61, 61, 61, 61, 61, 5, 5, 5, 5, 5, 5, 6, 6, 61, 61, 61, 61,
61, 61, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 61, 61, 61, 61, 61, 61, 61, 61,
5, 5, 5, 5, 5, 5, 5, 5, 61, 61, 61, 61, 61, 61, 61, 61, 5, 5, 5, 5,
5, 5, 6, 6, 61, 61, 61, 61, 61, 61, 6, 6, 62, 5, 63, 5, 64, 5, 65,
5, 6, 61, 6, 61, 6, 61, 6, 61, 5, 5, 5, 5, 5, 5, 5, 5, 61, 61, 61,
61, 61, 61, 61, 61, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
5, 5, 114, 115, 116, 6, 117, 118, 61, 61, 119, 119, 120, 2, 121, 2,
2, 2, 122, 123, 124, 6, 125, 126, 127, 127, 127, 127, 128, 2, 2, 2,
5, 5, 129, 130, 6, 6, 131, 132, 61, 61, 133, 133, 6, 2, 2, 2, 5, 5,
134, 135, 136, 5, 137, 138, 61, 61, 139, 139, 140, 2, 2, 2, 6, 6, 141,
142, 143, 6, 144, 145, 146, 146, 147, 147, 148, 2, 2, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 149, 149, 149, 150, 54, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 2, 6, 6, 6, 6, 6,
6, 6, 6, 149, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 5, 6,
6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2,
2, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5,
5, 2, 2, 2, 2, 2, 2, 5, 2, 151, 2, 5, 2, 152, 153, 5, 5, 2, 5, 5, 5,
2, 5, 5, 5, 5, 5, 5, 5, 2, 6, 6, 5, 5, 5, 2, 2, 2, 2, 2, 5, 5, 5, 5,
5, 2, 2, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
154, 154, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155,
155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155,
155, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 6, 6, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 6, 2, 2, 2, 2, 6, 6, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 6, 2, 2, 2, 2, 6,
6, 6, 2, 6, 2, 2, 2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5,
5, 5, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 5, 2, 2,
2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 6, 6, 2, 2, 2, 2, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 5, 5, 5, 5, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 6, 6, 6, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 6, 6, 6, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 59, 59, 59, 59, 59, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 46, 2, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 6, 46, 46, 46, 46, 46, 6, 46, 6, 46, 46, 6, 46, 46, 6, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 6, 6, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 150, 150, 150, 150,
150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 156, 157, 158,
159, 160, 161, 162, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 163, 164, 165,
166, 167, 6, 6, 6, 6, 6, 53, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 6, 53, 53,
53, 53, 53, 6, 53, 6, 53, 53, 6, 53, 53, 6, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 6,
6, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 6, 6, 6, 6,
46, 46, 46, 46, 46, 6, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 6, 6, 58, 2, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
6, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5,
6, 6, 5, 5, 5, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
6, 6, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 6, 6, 6, 6, 53, 53,
53, 53, 53, 6, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
53, 53, 53, 53, 53, 53, 53, 53, 53, 6, 6, 149, 2, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2,
2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5,
5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 6, 6,
5, 5, 5, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 2, 2, 2, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
};
/*
@ -489,22 +497,148 @@ static unsigned char groupMap[] = {
*
* Bit 6 D.2
*
* Bits 7-15 Reserved for future use.
* Bit 7 Case maps to several characters
*
* Bits 8-15 Reserved for future use.
*
* Bits 16-31 Case delta: delta for case conversions. This should be the
* highest field so we can easily sign extend.
*/
static int groups[] = {
4, 2, 0, 64, 2097184, 32, 1, 8, 50790432, 65568, -7929824, -17563616,
13762592, 13500448, 13434912, 5177376, 13238304, 13303840, 13565984,
13828128, 13697056, 13959200, 14024736, 14286880, 14221344, 14352416,
131104, -6356960, -3669984, -8519648, 7602176, 2490400, 2424864,
4194336, 4128800, -1966048, -1638368, -983008, -1441760, -3538912,
-3145696, -3080160, -3932128, -4194272, 5242912, 3145760, 16,
17, -3801056, -524256, -4849632, -470089696, -5636064, -6553568,
-7340000, -458720, -8388576, -8257504, 9, 33, -492634080, -549388256,
-541458400, 1048608, 1703968
4, 2, 0, 64, 2097184, 32, 1, 8, 50790432, 160, 65568, 65696, 131232,
-7929824, -17563616, 13762592, 13500448, 13434912, 5177376, 13238304,
13303840, 13565984, 13828128, 13697056, 13959200, 14024736, 14286880,
14221344, 14352416, 131104, 196768, -6356960, -3669984, -8519648,
7602176, 2490400, 2424864, 4194336, 4128800, 262304, 327840, -1966048,
-1638368, -983008, -1441760, -3538912, -3145696, -3080160, -3932128,
-4194272, 5242912, 3145760, 393376, 16, 17, 458912, 524448, 589984,
655520, 721056, -3801056, -524256, 786592, 852128, 917664, 983200,
1048736, 1114272, 1179808, 1245344, 1310880, 1376416, 1441952,
1507488, 1573024, 1638560, 1704096, 1769632, 1835168, 1900704,
1966240, 2031776, 2097312, 2162848, 2228384, 2293920, 2359456,
2424992, 2490528, 2556064, 2621600, 2687136, 2752672, 2818208,
2883744, 2949280, 3014816, 3080352, 3145888, 3211424, 3276960,
3342496, 3408032, 3473568, 3539104, 3604640, 3670176, 3735712,
3801248, 3866784, 3932320, 3997856, 4063392, 4128928, 4194464,
4260000, 4325536, 4391072, 4456608, -4849632, 4522144, -470089696,
4587680, 4653216, 4718752, 4784288, 4849824, -5636064, 4915360,
4980896, 5046432, 5111968, 5177504, -6553568, 5243040, 5308576,
5374112, 5439648, 5505184, -7340000, -458720, 5570720, 5636256,
5701792, 5767328, 5832864, -8388576, -8257504, 5898400, 9, 33,
-492634080, -549388256, -541458400, 1048608, 1703968, 5963936,
6029472, 6095008, 6160544, 6226080, 6291616, 6357152, 6422688,
6488224, 6553760, 6619296, 6684832
};
/*
* Table for characters that lowercased to multiple ones
*/
static int multiCaseTable[][4] = {
{2, 115, 115},
{2, 105, 775},
{2, 700, 110},
{2, 106, 780},
{3, 953, 776, 769},
{3, 965, 776, 769},
{2, 1381, 1410},
{2, 104, 817},
{2, 116, 776},
{2, 119, 778},
{2, 121, 778},
{2, 97, 702},
{2, 965, 787},
{3, 965, 787, 768},
{3, 965, 787, 769},
{3, 965, 787, 834},
{2, 7936, 953},
{2, 7937, 953},
{2, 7938, 953},
{2, 7939, 953},
{2, 7940, 953},
{2, 7941, 953},
{2, 7942, 953},
{2, 7943, 953},
{2, 7936, 953},
{2, 7937, 953},
{2, 7938, 953},
{2, 7939, 953},
{2, 7940, 953},
{2, 7941, 953},
{2, 7942, 953},
{2, 7943, 953},
{2, 7968, 953},
{2, 7969, 953},
{2, 7970, 953},
{2, 7971, 953},
{2, 7972, 953},
{2, 7973, 953},
{2, 7974, 953},
{2, 7975, 953},
{2, 7968, 953},
{2, 7969, 953},
{2, 7970, 953},
{2, 7971, 953},
{2, 7972, 953},
{2, 7973, 953},
{2, 7974, 953},
{2, 7975, 953},
{2, 8032, 953},
{2, 8033, 953},
{2, 8034, 953},
{2, 8035, 953},
{2, 8036, 953},
{2, 8037, 953},
{2, 8038, 953},
{2, 8039, 953},
{2, 8032, 953},
{2, 8033, 953},
{2, 8034, 953},
{2, 8035, 953},
{2, 8036, 953},
{2, 8037, 953},
{2, 8038, 953},
{2, 8039, 953},
{2, 8048, 953},
{2, 945, 953},
{2, 940, 953},
{2, 945, 834},
{3, 945, 834, 953},
{2, 945, 953},
{2, 8052, 953},
{2, 951, 953},
{2, 942, 953},
{2, 951, 834},
{3, 951, 834, 953},
{2, 951, 953},
{3, 953, 776, 768},
{3, 953, 776, 769},
{2, 953, 834},
{3, 953, 776, 834},
{3, 965, 776, 768},
{3, 965, 776, 769},
{2, 961, 787},
{2, 965, 834},
{3, 965, 776, 834},
{2, 8060, 953},
{2, 969, 953},
{2, 974, 953},
{2, 969, 834},
{3, 969, 834, 953},
{2, 969, 953},
{2, 102, 102},
{2, 102, 105},
{2, 102, 108},
{3, 102, 102, 105},
{3, 102, 102, 108},
{2, 115, 116},
{2, 115, 116},
{2, 1396, 1398},
{2, 1396, 1381},
{2, 1396, 1387},
{2, 1406, 1398},
{2, 1396, 1389}
};
/*
@ -519,6 +653,7 @@ static int groups[] = {
#define D1Mask (1 << 4)
#define D2Mask (1 << 5)
#define XNPMask (1 << 6)
#define MCMask (1 << 7)
/*
* The following macros extract the fields of the character info. The
@ -529,6 +664,7 @@ static int groups[] = {
#define GetCaseType(info) (((info) & 0xE0) >> 5)
#define GetCategory(info) ((info) & 0x1F)
#define GetDelta(info) (((info) > 0) ? ((info) >> 16) : (~(~((info)) >> 16)))
#define GetMC(info) (multiCaseTable[GetDelta(info)])
/*
* This macro extracts the information about a character from the

2231
src/stringprep/uni_norm.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,20 @@ namespace eval uni {
# unassigned character group
}
proc uni::getValue {tables delta} {
proc uni::getValue {i} {
variable casemap
variable casemap2
variable tablemap
set tables $tablemap($i)
if {[info exists casemap2($i)]} {
set multicase 1
set delta $casemap2($i)
} else {
set multicase 0
set delta $casemap($i)
}
set ac 0
set c11 0
set c21 0
@ -57,6 +70,7 @@ proc uni::getValue {tables delta} {
($d1 << 4) |
($d2 << 5) |
($xnp << 6) |
($multicase << 7) |
($delta << 16)}]
return $val
@ -88,6 +102,8 @@ proc uni::addPage {info} {
proc uni::load_tables {data} {
variable casemap
variable casemap2
variable multicasemap
variable tablemap
for {set i 0} {$i <= 0xffff} {incr i} {
@ -95,6 +111,7 @@ proc uni::load_tables {data} {
set tablemap($i) {}
}
set multicasemap {}
set table ""
foreach line [split $data \n] {
@ -122,8 +139,30 @@ proc uni::load_tables {data} {
if {$from <= 0xffff && $to <= 0xffff} {
set casemap($from) [expr {$to - $from}]
}
} elseif {[regexp {^ ([[:xdigit:]]+); ([[:xdigit:]]+) ([[:xdigit:]]+);} $line \
temp from to1 to2]} {
scan $from %x from
scan $to1 %x to1
scan $to2 %x to2
if {$from <= 0xffff && \
$to1 <= 0xffff && $to2 <= 0xffff} {
set casemap2($from) [llength $multicasemap]
lappend multicasemap [list $to1 $to2]
}
} elseif {[regexp {^ ([[:xdigit:]]+); ([[:xdigit:]]+) ([[:xdigit:]]+) ([[:xdigit:]]+);} $line \
temp from to1 to2 to3]} {
scan $from %x from
scan $to1 %x to1
scan $to2 %x to2
scan $to3 %x to3
if {$from <= 0xffff && \
$to1 <= 0xffff && $to2 <= 0xffff && \
$to3 <= 0xffff} {
set casemap2($from) [llength $multicasemap]
lappend multicasemap [list $to1 $to2 $to3]
}
} else {
# TODO
#puts "missed: $line"
}
} elseif {$table != "B.2"} {
@ -169,7 +208,7 @@ proc uni::buildTables {} {
set next 0
for {set i 0} {$i <= 0xffff} {incr i} {
set gIndex [getGroup [getValue $tablemap($i) $casemap($i)]]
set gIndex [getGroup [getValue $i]]
# Split character index into offset and page number
set offset [expr {$i & $mask}]
@ -193,6 +232,7 @@ proc uni::main {} {
variable pages
variable groups
variable shift
variable multicasemap
if {$argc != 2} {
puts stderr "\nusage: $argv0 <datafile> <outdir>\n"
@ -299,7 +339,9 @@ static unsigned char groupMap\[\] = {"
*
* Bit 6 D.2
*
* Bits 7-15 Reserved for future use.
* Bit 7 Case maps to several characters
*
* Bits 8-15 Reserved for future use.
*
* Bits 16-31 Case delta: delta for case conversions. This should be the
* highest field so we can easily sign extend.
@ -323,6 +365,24 @@ static int groups\[\] = {"
puts $f $line
puts $f "};
/*
* Table for characters that lowercased to multiple ones
*/
static int multiCaseTable\[\]\[4\] = {"
set last [expr {[llength $multicasemap] - 1}]
for {set i 0} {$i <= $last} {incr i} {
set val [lindex $multicasemap $i]
set line " "
append line [format "{%d, %s}" [llength $val] [join $val ", "]]
if {$i != $last} {
append line ", "
}
puts $f $line
}
puts $f "};
/*
* The following constants are used to determine the category of a
* Unicode character.
@ -335,6 +395,7 @@ static int groups\[\] = {"
#define D1Mask (1 << 4)
#define D2Mask (1 << 5)
#define XNPMask (1 << 6)
#define MCMask (1 << 7)
/*
* The following macros extract the fields of the character info. The
@ -345,6 +406,7 @@ static int groups\[\] = {"
#define GetCaseType(info) (((info) & 0xE0) >> 5)
#define GetCategory(info) ((info) & 0x1F)
#define GetDelta(info) (((info) > 0) ? ((info) >> 16) : (~(~((info)) >> 16)))
#define GetMC(info) (multiCaseTable\[GetDelta(info)\])
/*
* This macro extracts the information about a character from the

View File

@ -0,0 +1,737 @@
# uni_parse2.tcl --
#
# This program parses the UnicodeData file and generates the
# corresponding uni_norm.c file with compressed character
# data tables. The input to this program should be the latest
# UnicodeData.txt and CompositionExclusions.txt files from:
# ftp://ftp.unicode.org/Public/UNIDATA/
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
# Modified for ejabberd by Alexey Shchepin
#
# RCS: @(#) $Id$
namespace eval uni {
set cclass_shift 6
set decomp_shift 5
set comp_shift 5
set shift 5; # number of bits of data within a page
# This value can be adjusted to find the
# best split to minimize table size
variable pMap; # map from page to page index, each entry is
# an index into the pages table, indexed by
# page number
variable pages; # map from page index to page info, each
# entry is a list of indices into the groups
# table, the list is indexed by the offset
variable groups; # list of character info values, indexed by
# group number, initialized with the
# unassigned character group
variable categories {
Cn Lu Ll Lt Lm Lo Mn Me Mc Nd Nl No Zs Zl Zp
Cc Cf Co Cs Pc Pd Ps Pe Pi Pf Po Sm Sc Sk So
}; # Ordered list of character categories, must
# match the enumeration in the header file.
variable titleCount 0; # Count of the number of title case
# characters. This value is used in the
# regular expression code to allocate enough
# space for the title case variants.
}
proc uni::getValue {items index} {
variable categories
variable titleCount
# Extract character info
set category [lindex $items 2]
if {[scan [lindex $items 12] %4x toupper] == 1} {
set toupper [expr {$index - $toupper}]
} else {
set toupper {}
}
if {[scan [lindex $items 13] %4x tolower] == 1} {
set tolower [expr {$tolower - $index}]
} else {
set tolower {}
}
if {[scan [lindex $items 14] %4x totitle] == 1} {
set totitle [expr {$index - $totitle}]
} else {
set totitle {}
}
set categoryIndex [lsearch -exact $categories $category]
if {$categoryIndex < 0} {
puts "Unexpected character category: $index($category)"
set categoryIndex 0
} elseif {$category == "Lt"} {
incr titleCount
}
return "$categoryIndex,$toupper,$tolower,$totitle"
}
proc uni::getGroup {value} {
variable groups
set gIndex [lsearch -exact $groups $value]
if {$gIndex == -1} {
set gIndex [llength $groups]
lappend groups $value
}
return $gIndex
}
proc uni::addPage {info} {
variable pMap
variable pages
set pIndex [lsearch -exact $pages $info]
if {$pIndex == -1} {
set pIndex [llength $pages]
lappend pages $info
}
lappend pMap $pIndex
return
}
proc uni::addPage {map_var pages_var info} {
variable $map_var
variable $pages_var
set pIndex [lsearch -exact [set $pages_var] $info]
if {$pIndex == -1} {
set pIndex [llength [set $pages_var]]
lappend $pages_var $info
}
lappend $map_var $pIndex
return
}
proc uni::load_exclusions {data} {
variable exclusions
foreach line [split $data \n] {
if {$line == ""} continue
set items [split $line " "]
if {[lindex $items 0] == "#"} continue
scan [lindex $items 0] %x index
set exclusions($index) ""
}
}
proc uni::load_tables {data} {
variable cclass_map
variable decomp_map
variable comp_map
variable comp_first
variable comp_second
variable exclusions
foreach line [split $data \n] {
if {$line == ""} continue
set items [split $line \;]
scan [lindex $items 0] %x index
set cclass [lindex $items 3]
set decomp [lindex $items 5]
set cclass_map($index) $cclass
#set decomp_map($index) $cclass
if {$decomp != ""} {
if {[string index [lindex $decomp 0] 0] == "<"} {
set decomp1 [lreplace $decomp 0 0]
set decomp {}
foreach ch $decomp1 {
scan $ch %x ch
lappend decomp $ch
}
set decomp_map($index) $decomp
} else {
switch -- [llength $decomp] {
1 {
scan $decomp %x ch
set decomp_map($index) $ch
}
2 {
scan $decomp "%x %x" ch1 ch2
set decomp [list $ch1 $ch2]
set decomp_map($index) $decomp
# hackish
if {(![info exists cclass_map($ch1)] || \
$cclass_map($ch1) == 0) && \
![info exists exclusions($index)]} {
if {[info exists comp_first($ch1)]} {
incr comp_first($ch1)
} else {
set comp_first($ch1) 1
}
if {[info exists comp_second($ch2)]} {
incr comp_second($ch2)
} else {
set comp_second($ch2) 1
}
set comp_map($decomp) $index
} else {
puts "Excluded $index"
}
}
default {
puts "Bad canonical decomposition: $line"
}
}
}
#puts "[format 0x%0.4x $index]\t$cclass\t$decomp_map($index)"
}
}
#puts [array get comp_first]
#puts [array get comp_second]
}
proc uni::buildTables {} {
variable cclass_shift
variable decomp_shift
variable comp_shift
variable cclass_map
variable cclass_pmap {}
variable cclass_pages {}
variable decomp_map
variable decomp_pmap {}
variable decomp_pages {}
variable decomp_list {}
variable comp_map
variable comp_pmap {}
variable comp_pages {}
variable comp_first
variable comp_second
variable comp_first_list {}
variable comp_second_list {}
variable comp_x_list {}
variable comp_y_list {}
variable comp_both_map {}
set cclass_info {}
set decomp_info {}
set comp_info {}
set cclass_mask [expr {(1 << $cclass_shift) - 1}]
set decomp_mask [expr {(1 << $decomp_shift) - 1}]
set comp_mask [expr {(1 << $comp_shift) - 1}]
foreach comp [array names comp_map] {
set ch1 [lindex $comp 0]
set ch2 [lindex $comp 1]
if {$comp_first($ch1) == 1} {
set i [llength $comp_first_list]
lappend comp_first_list [list $ch2 $comp_map($comp)]
set comp_info_map($ch1) [expr {$i | (1 << 16)}]
} elseif {$comp_second($ch2) == 1} {
set i [llength $comp_second_list]
lappend comp_second_list [list $ch1 $comp_map($comp)]
set comp_info_map($ch2) [expr {$i | (1 << 16)}]
} else {
if {[lsearch -exact $comp_x_list $ch1] < 0} {
set i [llength $comp_x_list]
lappend comp_x_list $ch1
set comp_info_map($ch1) $i
}
if {[lsearch -exact $comp_y_list $ch2] < 0} {
set i [llength $comp_y_list]
lappend comp_y_list $ch2
set comp_info_map($ch2) $i
}
}
}
set next 0
for {set i 0} {$i <= 0xffff} {incr i} {
#set gIndex [getGroup [getValue $i]]
set cclass_offset [expr {$i & $cclass_mask}]
if {[info exists cclass_map($i)]} {
set cclass $cclass_map($i)
} else {
set cclass 0
}
lappend cclass_info $cclass
if {$cclass_offset == $cclass_mask} {
addPage cclass_pmap cclass_pages $cclass_info
set cclass_info {}
}
set decomp_offset [expr {$i & $decomp_mask}]
if {[info exists decomp_map($i)]} {
set decomp $decomp_map($i)
if {[info exists decomp_used($decomp)]} {
lappend decomp_info $decomp_used($decomp)
} else {
set val [expr {([llength $decomp] << 16) + \
[llength $decomp_list]}]
#set val [expr {[llength $decomp_list]}]
lappend decomp_info $val
set decomp_used($decomp) $val
#puts "$val $decomp"
foreach d $decomp {
lappend decomp_list $d
}
}
} else {
lappend decomp_info -1
}
if {$decomp_offset == $decomp_mask} {
addPage decomp_pmap decomp_pages $decomp_info
set decomp_info {}
}
set comp_offset [expr {$i & $comp_mask}]
if {[info exists comp_info_map($i)]} {
set comp $comp_info_map($i)
} else {
set comp -1
}
lappend comp_info $comp
if {$comp_offset == $comp_mask} {
addPage comp_pmap comp_pages $comp_info
set comp_info {}
}
}
#puts [array get decomp_map]
#puts $decomp_list
return
}
proc uni::main {} {
global argc argv0 argv
variable cclass_shift
variable cclass_pmap
variable cclass_pages
variable decomp_shift
variable decomp_pmap
variable decomp_pages
variable decomp_list
variable comp_shift
variable comp_map
variable comp_pmap
variable comp_pages
variable comp_first_list
variable comp_second_list
variable comp_x_list
variable comp_y_list
variable pages
variable groups {}
variable titleCount
if {$argc != 3} {
puts stderr "\nusage: $argv0 <datafile> <exclusionsfile> <outdir>\n"
exit 1
}
set f [open [lindex $argv 1] r]
set data [read $f]
close $f
load_exclusions $data
set f [open [lindex $argv 0] r]
set data [read $f]
close $f
load_tables $data
buildTables
#puts "X = [llength $pMap] Y= [llength $pages] A= [llength $groups]"
#set size [expr {[llength $pMap] + [llength $pages]*(1<<$shift)}]
#puts "shift = 6, space = $size"
#puts "title case count = $titleCount"
set f [open [file join [lindex $argv 2] uni_norm.c] w]
fconfigure $f -translation lf
puts $f "/*
* uni_norm.c --
*
* Declarations of Unicode character information tables. This file is
* automatically generated by the uni_parse2.tcl script. Do not
* modify this file by hand.
*
* Copyright (c) 1998 by Scriptics Corporation.
* All rights reserved.
*
* Modified for ejabberd by Alexey Shchepin
*
* RCS: @(#) \$Id\$
*/
/*
* A 16-bit Unicode character is split into two parts in order to index
* into the following tables. The lower CCLASS_OFFSET_BITS comprise an offset
* into a page of characters. The upper bits comprise the page number.
*/
#define CCLASS_OFFSET_BITS $cclass_shift
/*
* The pageMap is indexed by page number and returns an alternate page number
* that identifies a unique page of characters. Many Unicode characters map
* to the same alternate page number.
*/
static unsigned char cclassPageMap\[\] = {"
set line " "
set last [expr {[llength $cclass_pmap] - 1}]
for {set i 0} {$i <= $last} {incr i} {
append line [lindex $cclass_pmap $i]
if {$i != $last} {
append line ", "
}
if {[string length $line] > 70} {
puts $f $line
set line " "
}
}
puts $f $line
puts $f "};
/*
* The groupMap is indexed by combining the alternate page number with
* the page offset and returns a group number that identifies a unique
* set of character attributes.
*/
static unsigned char cclassGroupMap\[\] = {"
set line " "
set lasti [expr {[llength $cclass_pages] - 1}]
for {set i 0} {$i <= $lasti} {incr i} {
set page [lindex $cclass_pages $i]
set lastj [expr {[llength $page] - 1}]
for {set j 0} {$j <= $lastj} {incr j} {
append line [lindex $page $j]
if {$j != $lastj || $i != $lasti} {
append line ", "
}
if {[string length $line] > 70} {
puts $f $line
set line " "
}
}
}
puts $f $line
puts $f "};
/*
* Each group represents a unique set of character attributes. The attributes
* are encoded into a 32-bit value as follows:
*
* Bits 0-4 Character category: see the constants listed below.
*
* Bits 5-7 Case delta type: 000 = identity
* 010 = add delta for lower
* 011 = add delta for lower, add 1 for title
* 100 = sutract delta for title/upper
* 101 = sub delta for upper, sub 1 for title
* 110 = sub delta for upper, add delta for lower
*
* Bits 8-21 Reserved for future use.
*
* Bits 22-31 Case delta: delta for case conversions. This should be the
* highest field so we can easily sign extend.
*/
static int cclass_groups\[\] = {"
set line " "
set last [expr {[llength $groups] - 1}]
for {set i 0} {$i <= $last} {incr i} {
foreach {type toupper tolower totitle} [split [lindex $groups $i] ,] {}
# Compute the case conversion type and delta
if {$totitle != ""} {
if {$totitle == $toupper} {
# subtract delta for title or upper
set case 4
set delta $toupper
} elseif {$toupper != ""} {
# subtract delta for upper, subtract 1 for title
set case 5
set delta $toupper
} else {
# add delta for lower, add 1 for title
set case 3
set delta $tolower
}
} elseif {$toupper != ""} {
# subtract delta for upper, add delta for lower
set case 6
set delta $toupper
} elseif {$tolower != ""} {
# add delta for lower
set case 2
set delta $tolower
} else {
# noop
set case 0
set delta 0
}
set val [expr {($delta << 22) | ($case << 5) | $type}]
append line [format "%d" $val]
if {$i != $last} {
append line ", "
}
if {[string length $line] > 65} {
puts $f $line
set line " "
}
}
puts $f $line
puts $f "};
#define GetUniCharCClass(ch) (cclassGroupMap\[(cclassPageMap\[(((int)(ch)) & 0xffff) >> CCLASS_OFFSET_BITS\] << CCLASS_OFFSET_BITS) | ((ch) & ((1 << CCLASS_OFFSET_BITS)-1))\])
#define DECOMP_OFFSET_BITS $decomp_shift
/*
* The pageMap is indexed by page number and returns an alternate page number
* that identifies a unique page of characters. Many Unicode characters map
* to the same alternate page number.
*/
static unsigned char decompPageMap\[\] = {"
set line " "
set last [expr {[llength $decomp_pmap] - 1}]
for {set i 0} {$i <= $last} {incr i} {
append line [lindex $decomp_pmap $i]
if {$i != $last} {
append line ", "
}
if {[string length $line] > 70} {
puts $f $line
set line " "
}
}
puts $f $line
puts $f "};
/*
* The groupMap is indexed by combining the alternate page number with
* the page offset and returns a group number that identifies a unique
* set of character attributes.
*/
static int decompGroupMap\[\] = {"
set line " "
set lasti [expr {[llength $decomp_pages] - 1}]
for {set i 0} {$i <= $lasti} {incr i} {
set page [lindex $decomp_pages $i]
set lastj [expr {[llength $page] - 1}]
for {set j 0} {$j <= $lastj} {incr j} {
append line [lindex $page $j]
if {$j != $lastj || $i != $lasti} {
append line ", "
}
if {[string length $line] > 70} {
puts $f $line
set line " "
}
}
}
puts $f $line
puts $f "};
/*
* Each group represents a unique set of character attributes. The attributes...
*/
static int decompList\[\] = {"
set line " "
set last [expr {[llength $decomp_list] - 1}]
for {set i 0} {$i <= $last} {incr i} {
set val [lindex $decomp_list $i]
append line [format "%d" $val]
if {$i != $last} {
append line ", "
}
if {[string length $line] > 70} {
puts $f $line
set line " "
}
}
puts $f $line
puts $f "};
/*
* This macro extracts the information about a character from the
* Unicode character tables.
*/
//#define GetUniCharInfo(ch) (groups\[groupMap\[(pageMap\[(((int)(ch)) & 0xffff) >> CCLASS_OFFSET_BITS\] << CCLASS_OFFSET_BITS) | ((ch) & ((1 << CCLASS_OFFSET_BITS)-1))\]\])
#define GetUniCharDecompInfo(ch) (decompGroupMap\[(decompPageMap\[(((int)(ch)) & 0xffff) >> DECOMP_OFFSET_BITS\] << DECOMP_OFFSET_BITS) | ((ch) & ((1 << DECOMP_OFFSET_BITS)-1))\])
#define GetDecompShift(info) ((info) & 0xffff)
#define GetDecompLen(info) ((info) >> 16)
#define COMP_OFFSET_BITS $comp_shift
/*
* The pageMap is indexed by page number and returns an alternate page number
* that identifies a unique page of characters. Many Unicode characters map
* to the same alternate page number.
*/
static unsigned char compPageMap\[\] = {"
set line " "
set last [expr {[llength $comp_pmap] - 1}]
for {set i 0} {$i <= $last} {incr i} {
append line [lindex $comp_pmap $i]
if {$i != $last} {
append line ", "
}
if {[string length $line] > 70} {
puts $f $line
set line " "
}
}
puts $f $line
puts $f "};
/*
* The groupMap is indexed by combining the alternate page number with
* the page offset and returns a group number that identifies a unique
* set of character attributes.
*/
static int compGroupMap\[\] = {"
set line " "
set lasti [expr {[llength $comp_pages] - 1}]
for {set i 0} {$i <= $lasti} {incr i} {
set page [lindex $comp_pages $i]
set lastj [expr {[llength $page] - 1}]
for {set j 0} {$j <= $lastj} {incr j} {
append line [lindex $page $j]
if {$j != $lastj || $i != $lasti} {
append line ", "
}
if {[string length $line] > 70} {
puts $f $line
set line " "
}
}
}
puts $f $line
puts $f "};
/*
* ...
*/
static int compFirstList\[\]\[2\] = {"
set line " "
set last [expr {[llength $comp_first_list] - 1}]
for {set i 0} {$i <= $last} {incr i} {
set val [lindex $comp_first_list $i]
append line [format "{%d, %d}" [lindex $val 0] [lindex $val 1]]
if {$i != $last} {
append line ", "
}
if {[string length $line] > 60} {
puts $f $line
set line " "
}
}
puts $f $line
puts $f "};
static int compSecondList\[\]\[2\] = {"
set line " "
set last [expr {[llength $comp_second_list] - 1}]
for {set i 0} {$i <= $last} {incr i} {
set val [lindex $comp_second_list $i]
append line [format "{%d, %d}" [lindex $val 0] [lindex $val 1]]
if {$i != $last} {
append line ", "
}
if {[string length $line] > 60} {
puts $f $line
set line " "
}
}
puts $f $line
puts $f "};
static int compBothList\[[llength $comp_x_list]\]\[[llength $comp_y_list]\] = {"
set lastx [expr {[llength $comp_x_list] - 1}]
set lasty [expr {[llength $comp_y_list] - 1}]
for {set i 0} {$i <= $lastx} {incr i} {
puts $f " \{"
set line " "
for {set j 0} {$j <= $lasty} {incr j} {
set comp [list [lindex $comp_x_list $i] [lindex $comp_y_list $j]]
if {[info exists comp_map($comp)]} {
set val $comp_map($comp)
} else {
set val 0
}
append line [format "%d" $val]
if {$j != $lasty} {
append line ", "
}
if {[string length $line] > 70} {
puts $f $line
set line " "
}
}
puts $f $line
if {$j != $lasty} {
puts $f " \},"
} else {
puts $f " \}"
}
}
puts $f "};
#define GetUniCharCompInfo(ch) (compGroupMap\[(compPageMap\[(((int)(ch)) & 0xffff) >> COMP_OFFSET_BITS\] << COMP_OFFSET_BITS) | ((ch) & ((1 << COMP_OFFSET_BITS)-1))\])
#define CompSingleMask (1 << 16)
#define CompMask ((1 << 16) - 1)
"
close $f
}
uni::main
return