const char COPYING[]= "\
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.\n\
Copyright ( c ) 2009 , 2023 , MariaDB Corporation . \ n \
\ n \
This program is free software ; you can redistribute it and / or modify \ n \
it under the terms of the GNU General Public License as published by \ n \
the Free Software Foundation ; version 2 of the License . \ n \
\ n \
This program is distributed in the hope that it will be useful , \ n \
but WITHOUT ANY WARRANTY ; without even the implied warranty of \ n \
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the \ n \
GNU General Public License for more details . \ n \
\ n \
You should have received a copy of the GNU General Public License \ n \
along with this program ; if not , write to the Free Software \ n \
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1335 USA \ n \
*/ \n";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_UNI_CHAR 0 x10FFFF
#define MAX_UNI_PAGE 0 x10FF
#define STRING_WITH_LEN(X) (X), ((size_t) (sizeof (X) - 1 ))
typedef unsigned int my_wchar_t;
/* Character types, as in m_ctype.h */
#define _MY_U 01 /* Upper case */
#define _MY_L 02 /* Lower case */
#define _MY_NMR 04 /* Numeral (digit) */
#define _MY_SPC 010 /* Spacing character */
#define _MY_PNT 020 /* Punctuation */
#define _MY_CTR 040 /* Control character */
#define _MY_B 0100 /* Blank */
#define _MY_X 0200 /* heXadecimal digit */
#define CT_MAX _MY_X
#define CT_CJK _MY_L | _MY_U
#define CT_HANGUL _MY_L | _MY_U
#define CT_NONE 0
/* Decomposition types */
typedef enum
{
DT_UNKNOWN,
DT_FONT,
DT_NOBREAK,
DT_INITIAL,
DT_MEDIAL,
DT_FINAL,
DT_ISOLATED,
DT_CIRCLE,
DT_SUPER,
DT_SUB,
DT_VERTICAL,
DT_WIDE,
DT_NARROW,
DT_SMALL,
DT_SQUARE,
DT_FRACTION,
DT_COMPAT
} decomposition_type_t;
typedef enum
{
PAGE_DATA_USELESS= 0 ,
PAGE_DATA_IMPORTANT= 1 ,
PAGE_DATA_DUMMY= 2
} page_data_type_t;
typedef struct
{
page_data_type_t page_tab;
int page_overridden;
int page_ctype;
} PAGE_STAT;
typedef struct
{
const char *mode_name;
int print_ctype;
int print_toupper;
int print_tolower;
int print_noaccent;
int print_noaccent_tolower;
int print_noaccent_toupper;
int print_curly_brackets_in_items;
int print_curly_brackets_in_index;
int chars_per_line;
int single_array;
int pages_per_line_in_index;
int const_data;
const char *page_data_type_name;
const char *page_name;
const char *page_name_derived;
const char *index_data_type_name;
const char *index_name;
} UNIDATA_OPT_MODE;
typedef struct
{
my_wchar_t max_char;
my_wchar_t dummy_pages_codepoint_max;
const char *filename;
UNIDATA_OPT_MODE mode;
} UNIDATA_OPT;
my_wchar_t npages_by_opt(const UNIDATA_OPT *opt)
{
return (opt->max_char + 1 ) / 256 ;
}
typedef struct my_ctype_name_st
{
const char *name;
int val;
int to_be_decomposed;
} MY_CTYPE_NAME_ST;
static MY_CTYPE_NAME_ST my_ctype_name[]=
{
{"Lu" , _MY_U, 1 }, /* Letter, Uppercase */
{"Ll" , _MY_L, 1 }, /* Letter, Lowercase */
{"Lt" , _MY_U, 1 }, /* Letter, Titlecase */
{"Lo" , _MY_L, 1 }, /* Letter, other */
{"Lm" , _MY_L, 0 }, /* Letter, Modifier */
{"Nd" , _MY_NMR, 0 }, /* Number, Decimal Digit */
{"Nl" , _MY_NMR|_MY_U|_MY_L, 0 }, /* Number, Letter */
{"No" , _MY_NMR|_MY_PNT, 0 }, /* Number, Other */
{"Mn" , _MY_L|_MY_PNT, 0 }, /* Mark, Nonspacing */
{"Mc" , _MY_L|_MY_PNT, 1 }, /* Mark, Spacing Combining */
{"Me" , _MY_L|_MY_PNT, 0 }, /* Mark, Enclosing */
{"Pc" , _MY_PNT, 0 }, /* Punctuation, Connector */
{"Pd" , _MY_PNT, 0 }, /* Punctuation, Dash */
{"Ps" , _MY_PNT, 0 }, /* Punctuation, Open */
{"Pe" , _MY_PNT, 0 }, /* Punctuation, Close */
{"Pi" , _MY_PNT, 0 }, /* Punctuation, Initial quote */
{"Pf" , _MY_PNT, 0 }, /* Punctuation, Final quote */
{"Po" , _MY_PNT, 0 }, /* Punctuation, Other */
{"Sm" , _MY_PNT, 0 }, /* Symbol, Math */
{"Sc" , _MY_PNT, 0 }, /* Symbol, Currency */
{"Sk" , _MY_PNT, 0 }, /* Symbol, Modifier */
{"So" , _MY_PNT, 0 }, /* Symbol, Other */
{"Zs" , _MY_SPC, 0 }, /* Separator, Space */
{"Zl" , _MY_SPC, 0 }, /* Separator, Line */
{"Zp" , _MY_SPC, 0 }, /* Separator, Paragraph */
{"Cc" , _MY_CTR, 0 }, /* Other, Control */
{"Cf" , _MY_CTR, 0 }, /* Other, Format */
{"Cs" , _MY_CTR, 0 }, /* Other, Surrogate */
{"Co" , _MY_CTR, 0 }, /* Other, Private Use */
{"Cn" , _MY_CTR, 0 }, /* Other, Not Assigned */
{NULL, 0 , 0 }
};
static const MY_CTYPE_NAME_ST *
ctype_name_st_find(my_wchar_t codepoint, const char *tok)
{
MY_CTYPE_NAME_ST *p;
for (p= my_ctype_name; p->name; p++)
{
if (!strncasecmp(p->name, tok, 2 ))
return p;
}
return NULL;
}
static int
ctype_name_st_to_num(const MY_CTYPE_NAME_ST *st, my_wchar_t codepoint)
{
if ((codepoint >= 'a' && codepoint <= 'z' ) ||
(codepoint >= 'A' && codepoint <= 'Z' ))
return st->val | _MY_X;
return st->val;
}
static UNIDATA_OPT opt_caseinfo=
{
0 x10FFFF, /* max_char */
0 x7FF, /* dummy_pages_codepoint_max == utf8 mb2 range */
NULL, /*filename*/
{
"caseinfo" , /* mode name */
0 , /* print_ctype */
1 , /* print_toupper */
1 , /* print_tolower */
0 , /* print_noaccent */
0 , /* print_noaccent_tolower */
1 , /* print_noaccent_toupper */
1 , /* print_curly_brackets_in_items */
0 , /* print_curly_brackets_in_index */
2 , /* chars_per_line */
0 , /* single_array */
8 , /* pages_per_line_in_index */
0 , /* const_data */
"MY_UNICASE_CHARACTER" , /* page_data_type_name */
"plane" , /* page_name */
NULL, /* page_name_derived */
"MY_UNICASE_CHARACTER *" , /* index_data_type_name */
"my_unicase_default_pages" /* index_name */
}
};
static UNIDATA_OPT opt_casefold=
{
0 x10FFFF, /* max_char */
0 x7FF, /* dummy_pages_codepoint_max == utf8 mb2 range */
NULL, /*filename*/
{
"casefold" , /* mode name */
0 , /* print_ctype */
1 , /* print_toupper */
1 , /* print_tolower */
0 , /* print_noaccent */
0 , /* print_noaccent_tolower */
0 , /* print_noaccent_toupper */
1 , /* print_curly_brackets_in_items */
0 , /* print_curly_brackets_in_index */
2 , /* chars_per_line */
0 , /* single_array */
8 , /* pages_per_line_in_index */
1 , /* const_data */
"MY_CASEFOLD_CHARACTER" , /* page_data_type_name */
"page" , /* page_name */
NULL, /* page_name_derived */
"MY_CASEFOLD_CHARACTER *" , /* index_data_type_name */
"my_casefold_default_pages" /* index_name */
}
};
static UNIDATA_OPT opt_casefold_tr=
{
0 x10FFFF, /* max_char */
0 x7FF, /* dummy_pages_codepoint_max == utf8 mb2 range */
NULL, /*filename*/
{
"casefold-tr" , /* mode name */
0 , /* print_ctype */
1 , /* print_toupper */
1 , /* print_tolower */
0 , /* print_noaccent */
0 , /* print_noaccent_tolower */
0 , /* print_noaccent_toupper */
1 , /* print_curly_brackets_in_items */
0 , /* print_curly_brackets_in_index */
2 , /* chars_per_line */
0 , /* single_array */
8 , /* pages_per_line_in_index */
1 , /* const_data */
"MY_CASEFOLD_CHARACTER" , /* page_data_type_name */
"page_tr" , /* page_name */
"page" , /* page_name_derived */
"MY_CASEFOLD_CHARACTER *" , /* index_data_type_name */
"my_casefold_tr_pages" /* index_name */
}
};
static UNIDATA_OPT opt_weight_general_ci=
{
0 xFFFF, /* max_char */
0 x7FF, /* dummy_pages_codepoint_max == utf8 mb2 range */
NULL, /*filename*/
{
"weight_general_ci" , /* mode name */
0 , /* print_ctype */
0 , /* print_toupper */
0 , /* print_tolower */
0 , /* print_noaccent */
0 , /* print_noaccent_tolower */
1 , /* print_noaccent_toupper */
0 , /* print_curly_brackets_in_items */
0 , /* print_curly_brackets_in_index */
8 , /* chars_per_line */
0 , /* single_array */
2 , /* pages_per_line_in_index */
1 , /* const_data */
"uint16" , /* page_data_type_name */
"weight_general_ci_page" , /* page_name */
NULL, /* page_name_derived */
"uint16 *" , /* index_data_type_name */
"weight_general_ci_index" /* index_name */
}
};
static UNIDATA_OPT opt_weight_general_mysql500_ci=
{
0 xFFFF, /* max_char */
0 x7FF, /* dummy_pages_codepoint_max == utf8 mb2 range */
NULL, /*filename*/
{
"weight_general_mysql500_ci" , /* mode name */
0 , /* print_ctype */
0 , /* print_toupper */
0 , /* print_tolower */
0 , /* print_noaccent */
0 , /* print_noaccent_tolower */
1 , /* print_noaccent_toupper */
0 , /* print_curly_brackets_in_items */
0 , /* print_curly_brackets_in_index */
8 , /* chars_per_line */
0 , /* single_array */
2 , /* pages_per_line_in_index */
1 , /* const_data */
"uint16" , /* page_data_type_name */
"weight_general_mysql500_ci_page" , /* page_name */
"weight_general_ci_page" , /* page_name_derived */
"uint16 *" , /* index_data_type_name */
"weight_general_mysql500_ci_index" /* index_name */
}
};
static UNIDATA_OPT opt_ctype=
{
0 x10FFFF, /* max_char */
0 x7FF, /* dummy_pages_codepoint_max == utf8 mb2 range */
NULL, /*filename*/
{
"ctype" , /* mode name */
1 , /* print_ctype */
0 , /* print_toupper */
0 , /* print_tolower */
0 , /* print_noaccent */
0 , /* print_noaccent_tolower */
0 , /* print_noaccent_toupper */
0 , /* print_curly_brackets_in_items */
1 , /* print_curly_brackets_in_index */
16 , /* chars_per_line */
0 , /* single_array */
1 , /* pages_per_line_in_index */
1 , /* const_data */
"unsigned char" , /* page_data_type_name */
"uctype_page" , /* page_name */
NULL, /* page_name_derived */
"MY_UNI_CTYPE" , /* index_data_type_name */
"my_uni_ctype" /* index_name */
}
};
int opt_set_mode(UNIDATA_OPT *to, const char *name_and_value, const char *value)
{
if (!strcmp(value, "casefold" ))
{
to->mode= opt_casefold.mode;
return 0 ;
}
else if (!strcmp(value, "casefold-tr" ))
{
to->mode= opt_casefold_tr.mode;
return 0 ;
}
else if (!strcmp(value, "caseinfo" ))
{
to->mode= opt_caseinfo.mode;
return 0 ;
}
else if (!strcmp(value, "weight_general_ci" ))
{
to->mode= opt_weight_general_ci.mode;
return 0 ;
}
else if (!strcmp(value, "weight_general_mysql500_ci" ))
{
to->mode= opt_weight_general_mysql500_ci.mode;
return 0 ;
}
else if (!strcmp(value, "ctype" ))
{
to->mode= opt_ctype.mode;
return 0 ;
}
fprintf(stderr, "Bad option: %s\n" , name_and_value);
return 1 ;
}
static decomposition_type_t
get_decomposition_type(const char *str)
{
if (!strcmp(str, "<font>" )) return DT_FONT;
if (!strcmp(str, "<noBreak>" )) return DT_NOBREAK;
if (!strcmp(str, "<initial>" )) return DT_INITIAL;
if (!strcmp(str, "<medial>" )) return DT_MEDIAL;
if (!strcmp(str, "<final>" )) return DT_FINAL;
if (!strcmp(str, "<isolated>" )) return DT_ISOLATED;
if (!strcmp(str, "<circle>" )) return DT_CIRCLE;
if (!strcmp(str, "<super>" )) return DT_SUPER;
if (!strcmp(str, "<sub>" )) return DT_SUB;
if (!strcmp(str, "<vertical>" )) return DT_VERTICAL;
if (!strcmp(str, "<wide>" )) return DT_WIDE;
if (!strcmp(str, "<narrow>" )) return DT_NARROW;
if (!strcmp(str, "<small>" )) return DT_SMALL;
if (!strcmp(str, "<square>" )) return DT_SQUARE;
if (!strcmp(str, "<fraction>" )) return DT_FRACTION;
if (!strcmp(str, "<compat>" )) return DT_COMPAT;
return DT_UNKNOWN;
}
#define MAX_DECOMP 20
typedef struct
{
int ctype;
int toupper;
int tolower;
int noaccent;
int noaccent_tolower;
int noaccent_toupper;
int decomp_type;
int decomp[MAX_DECOMP];
int to_be_decomposed;
} UNIDATA_CHAR;
/************* Initialization functions *********/
static int
strip_accent(UNIDATA_CHAR *code, int i)
{
if (code[i].decomp[0 ] &&
code[i].decomp[1 ] >= 0 x0300 &&
code[i].decomp[1 ] <= 0 x036F &&
code[i].decomp[2 ] == 0 )
return strip_accent(code, code[i].decomp[0 ]);
return i;
}
static void
set_noaccent(const UNIDATA_OPT *opt, UNIDATA_CHAR *code)
{
my_wchar_t i;
for (i= 0 ; i <= opt->max_char; i++)
{
code[i].noaccent= strip_accent(code, i);
}
}
static void
set_noaccent_tolower(const UNIDATA_OPT *opt, UNIDATA_CHAR *code)
{
my_wchar_t i;
for (i= 0 ; i <= opt->max_char; i++)
{
code[i].noaccent_tolower= code[code[i].noaccent].tolower;
}
}
static void
set_noaccent_toupper(const UNIDATA_OPT *opt, UNIDATA_CHAR *code)
{
my_wchar_t i;
for (i= 0 ; i <= opt->max_char; i++)
{
code[i].noaccent_toupper= code[code[i].noaccent].toupper;
}
}
static void
set_default_case_folding(const UNIDATA_OPT *opt, UNIDATA_CHAR *code)
{
my_wchar_t i;
for (i= 0 ; i <= opt->max_char; i++)
{
code[i].tolower= i;
code[i].toupper= i;
}
}
/*
Fill ideographs
*/
static void
fill_cjk(UNIDATA_CHAR *code)
{
size_t i;
/* CJK Ideographs Extension A (U+3400 - U+4DB5) */
for (i=0 x3400;i<=0 x4DB5;i++)
{
code[i].tolower=i;
code[i].ctype= CT_CJK;
}
/* CJK Ideographs (U+4E00 - U+9FA5) */
for (i=0 x4E00;i<=0 x9FA5;i++)
{
code[i].tolower=i;
code[i].ctype= CT_CJK;
}
/* Hangul Syllables (U+AC00 - U+D7A3) */
for (i=0 xAC00;i<=0 xD7A3;i++)
{
code[i].tolower=i;
code[i].ctype= CT_HANGUL;
}
}
/************* Loading functions ***************/
static void handle_general_category(const UNIDATA_OPT *opt,
UNIDATA_CHAR *ch,
const char *tok,
my_wchar_t codepoint)
{
/*
TODO : check if ctype is set correctly .
A difference can break fulltext indexes .
*/
const MY_CTYPE_NAME_ST *ct= ctype_name_st_find(
(my_wchar_t) codepoint, tok);
if (ct)
{
ch->ctype|= ctype_name_st_to_num(
ct,
(my_wchar_t) codepoint);
ch->to_be_decomposed= ct->to_be_decomposed;
}
}
int handle_decomposition(UNIDATA_CHAR *ch, char *tok, const char *str)
{
char *lt, *part;
size_t num;
if (!ch->to_be_decomposed)
return 0 ; /* Decompose only letters */
for (part= strtok_r(tok, " " , <), num= 0 ;
part;
part= strtok_r(NULL, " " , <))
{
char *end;
if (part[0 ] == '<' )
{
if ((ch->decomp_type= get_decomposition_type(part)) == DT_UNKNOWN)
{
fprintf(stderr, "Unknown decomposition type:\n%s\n" , str);
return 1 ;
}
continue ;
}
if (num + 1 >= MAX_DECOMP)
{
fprintf(stderr, "Too many decomposition parts:\n%s\n" , str);
return 1 ;
}
ch->decomp[num]= strtol(part,&end,16 );
ch->decomp[num+1 ]= 0 ;
num++;
}
return 0 ;
}
static int
parse_unidata_line(const UNIDATA_OPT *opt, char *str, UNIDATA_CHAR *unidata)
{
unsigned long codepoint= 0 ;
int fieldno= 0 ;
char *s;
for (s= str; *s; fieldno++)
{
char *tok= s, *e;
if ((e= strchr(s,';' )))
{
*e= '\0' ;
s= e + 1 ;
}
else
{
s+= strlen(s);
}
switch (fieldno)
{
case 0 : /* Code point */
codepoint= strtoul(tok, NULL, 16 );
if (codepoint > opt->max_char)
return 1 ;
break ;
case 1 : /* name */
break ;
case 2 : /* general category */
handle_general_category(opt, &unidata[codepoint],
tok, (my_wchar_t) codepoint);
break ;
case 3 : /* Canonical combining class */
break ;
case 4 : /* BiDi class */
break ;
case 5 : /* Decomposition type */
if (tok[0 ] && handle_decomposition(&unidata[codepoint], tok, str))
return -1 ;
break ;
case 6 : /* Numeric_Type, Numeric Value */
break ;
case 7 : /* Numeric_Type, Numeric Value */
break ;
case 8 : /* Numeric_Type, Numeric Value */
break ;
case 9 : /* BiDi mirrored */
break ;
case 10 : /* Unicode_1_Name */
break ;
case 11 : /* ISO_Comment */
break ;
case 12 : /*Simple_Uppercase_Mapping*/
if (tok[0 ])
unidata[codepoint].toupper= strtol(tok, NULL, 16 );
break ;
case 13 : /*Simple_Lowercase_Mapping*/
if (tok[0 ])
unidata[codepoint].tolower= strtol(tok, NULL, 16 );
break ;
case 14 : /* Simple_Titlecase_Mapping */
break ;
}
}
return 0 ;
}
static int
load_unidata_file(const UNIDATA_OPT *opt, FILE *f, UNIDATA_CHAR *unidata)
{
char str[1024 ];
while (fgets(str, sizeof (str), f))
{
if (parse_unidata_line(opt, str, unidata) < 0 )
return 1 ;
}
return 0 ;
}
static int
load_unidata(const UNIDATA_OPT *opt, UNIDATA_CHAR *unidata)
{
FILE *f;
int rc;
if (!(f= fopen(opt->filename, "r" )))
{
fprintf(stderr, "Could not open file '%s'\n" , opt->filename);
return 1 ;
}
rc= load_unidata_file(opt, f, unidata);
fclose(f);
return rc;
}
/************** Printing functions ********************/
static void
print_one_char(const UNIDATA_OPT *opt, UNIDATA_CHAR *data, int code)
{
UNIDATA_CHAR *ch= &data[code];
const char *comma= "" ;
if (opt->mode.print_curly_brackets_in_items)
printf("{" );
if (opt->mode.print_ctype)
{
printf("%s" , comma);
printf("%3d" , ch->ctype);
comma= "," ;
}
if (opt->mode.print_toupper)
{
printf("%s" , comma);
printf("0x%04X" , ch->toupper);
comma= "," ;
}
if (opt->mode.print_tolower)
{
printf("%s" , comma);
printf("0x%04X" , ch->tolower);
comma= "," ;
}
if (opt->mode.print_noaccent)
{
printf("%s" , comma);
printf("0x%04X" , ch->noaccent);
comma= "," ;
}
if (opt->mode.print_noaccent_tolower)
{
printf("%s" , comma);
printf("0x%04X" , ch->noaccent_tolower);
comma= "," ;
}
if (opt->mode.print_noaccent_toupper)
{
printf("%s" , comma);
printf("0x%04X" , ch->noaccent_toupper);
comma= "," ;
}
if (opt->mode.print_curly_brackets_in_items)
printf("}" );
if (opt->mode.single_array ||
(code & 0 xFF) != 0 xFF) /* Don't print comma for the last char in a page */
printf("," );
else
printf(" " );
}
static void
print_one_page(const UNIDATA_OPT *opt, UNIDATA_CHAR *data,
my_wchar_t pageno, const PAGE_STAT *pstat)
{
my_wchar_t charnum;
if (!opt->mode.single_array || pageno == 0 )
{
printf("%s%s%s %s%02X[256]={%s\n" ,
pageno == 0 ? "" : "static " ,
opt->mode.const_data ? "const " : "" ,
opt->mode.page_data_type_name, opt->mode.page_name,
(unsigned int ) pageno,
pstat[pageno].page_tab == PAGE_DATA_DUMMY ?
" /* This page is dummy */" : "");
}
for (charnum= 0 ; charnum < 256 ; charnum++)
{
my_wchar_t codepoint= (pageno << 8 ) + charnum;
my_wchar_t rem= charnum % opt->mode.chars_per_line;
if (!rem)
printf(" " );
print_one_char(opt, data, codepoint);
if (rem + 1 == opt->mode.chars_per_line)
{
printf(" /* %04X */", (codepoint + 1) - opt->mode.chars_per_line);
printf("\n" );
}
}
if (!opt->mode.single_array)
printf("};\n\n" );
}
static const char *page_name_in_index(const UNIDATA_OPT *opt,
const PAGE_STAT *pstat,
my_wchar_t pageno)
{
if (!opt->mode.page_name_derived)
return opt->mode.page_name;
return pstat[pageno].page_overridden ?
opt->mode.page_name :
opt->mode.page_name_derived;
}
static void print_page_index(const UNIDATA_OPT *opt,
const PAGE_STAT *pstat)
{
my_wchar_t page;
my_wchar_t npages= npages_by_opt(opt);
int printing_ctype= !strcmp(opt->mode.index_data_type_name, "MY_UNI_CTYPE" );
printf("%s%s %s[%d]={\n" ,
opt->mode.const_data ? "const " : "" ,
opt->mode.index_data_type_name, opt->mode.index_name,
(unsigned int ) npages);
for (page= 0 ; page < npages; page++)
{
my_wchar_t rem= page % opt->mode.pages_per_line_in_index;
if (!rem)
printf(" " );
if (opt->mode.print_curly_brackets_in_index)
printf("{" );
if (printing_ctype)
printf("%d," , pstat[page].page_ctype);
if (pstat[page].page_tab)
printf("%s%02X" , page_name_in_index(opt, pstat, page), page);
else
printf("NULL" );
if (opt->mode.print_curly_brackets_in_index)
printf("}" );
if (page + 1 < npages)
printf("," );
if (rem + 1 == opt->mode.pages_per_line_in_index)
printf("\n" );
else
printf(" " );
}
printf("};\n" );
}
static void print(UNIDATA_OPT *opt, UNIDATA_CHAR *unidata, const PAGE_STAT *pstat)
{
my_wchar_t npages= npages_by_opt(opt);
my_wchar_t page;
/* Print all pages */
for (page= 0 ; page < npages; page++)
{
if (opt->mode.page_name_derived && !pstat[page].page_overridden)
continue ;
if (opt->mode.single_array || pstat[page].page_tab)
print_one_page(opt, unidata, page, pstat);
}
/* Print index */
if (!opt->mode.single_array)
print_page_index(opt, pstat);
}
void print_command_line_options(int ac, char **av)
{
int i;
printf("/*\n");
printf(" Generated by:\n" );
for (i= 0 ; i < ac; i++)
{
printf(" %s%s%s\n" , i > 0 ? " " : "" , av[i], i+1 < ac ? " \\" :"" );
}
printf("\n" );
printf("*/\n" );
}
static void calc_page_parameters(const UNIDATA_OPT *opt, const UNIDATA_CHAR *code,
PAGE_STAT *pstat)
{
my_wchar_t npages= npages_by_opt(opt);
my_wchar_t page;
for (page= 0 ; page < npages; page++)
{
int ntype[CT_MAX + 1 ], t;
int character, done=0 ;
memset(ntype,0 ,sizeof (ntype));
for (character= 0 ;character < 256 ; character++)
{
size_t cod= (page << 8 ) + character;
const UNIDATA_CHAR *ch= &code[cod];
ntype[ch->ctype]++;
if ((ch->tolower != cod ||
ch->toupper != cod ||
ch->noaccent != cod ||
ch->noaccent_toupper != cod) &&
(opt->mode.print_tolower ||
opt->mode.print_toupper ||
opt->mode.print_noaccent ||
opt->mode.print_noaccent_toupper))
{
pstat[page].page_tab= PAGE_DATA_IMPORTANT;
}
}
if (opt->mode.print_ctype)
{
for (t= 0 ; t <= CT_MAX; t++)
{
if (ntype[t]==256 )
{
/* All ctypes are the same */
pstat[page].page_ctype= t;
done=1 ;
break ;
}
}
}
else
{
done= 1 ; /* Don't need ctype */
}
if (!done)
{
/* Mixed page, lets create the table */
pstat[page].page_ctype= CT_NONE;
pstat[page].page_tab= PAGE_DATA_IMPORTANT;
}
if (!pstat[page].page_tab &&
page <= (opt->dummy_pages_codepoint_max >> 8 ))
pstat[page].page_tab= PAGE_DATA_DUMMY;
}
}
static UNIDATA_CHAR code[MAX_UNI_CHAR + 1 ];
static PAGE_STAT pstat[MAX_UNI_PAGE + 1 ];
int usage(int ac, char **av)
{
fprintf(stderr, "Usage: %s filename\n" , av[0 ]);
return 1 ;
}
const char *one_opt(const char *option, const char *name, size_t length)
{
if (!strncmp(option, name, length))
return option + length;
return 0 ;
}
int get_option_bool(int *to, const char *name_and_value, const char *value)
{
if (!strcmp(value, "1" ))
*to= 1 ;
else if (!strcmp(value, "0" ))
*to= 0 ;
else
{
fprintf(stderr, "Bad option: %s\n" , name_and_value);
return 1 ;
}
return 0 ;
}
int get_option_codepoint(my_wchar_t *to, const char *name_and_value, const char *value)
{
unsigned long codepoint= value[0 ]=='0' && value[1 ]=='x' ?
strtoul(value + 2 , NULL, 16 ) :
strtoul(value, NULL, 10 );
if (codepoint > MAX_UNI_CHAR)
{
fprintf(stderr, "Too large --max-char: %s\n" , name_and_value);
return 1 ;
}
*to= (my_wchar_t) codepoint;
return 0 ;
}
int process_param(UNIDATA_OPT *opt, int ac, char **av)
{
int i;
if (ac < 2 )
return usage(ac, av);
for (i= 1 ; i < ac; i++)
{
const char *op;
if ((op= one_opt(av[i], STRING_WITH_LEN("--mode=" ))))
{
if (opt_set_mode(opt, av[i], op))
return 1 ;
}
else if ((op= one_opt(av[i], STRING_WITH_LEN("--max-char=" ))))
{
if (get_option_codepoint(&opt->max_char, av[i], op))
return 1 ;
}
else if ((op= one_opt(av[i], STRING_WITH_LEN("--print-toupper=" ))))
{
if (get_option_bool(&opt->mode.print_toupper, av[i], op))
return 1 ;
}
else if ((op= one_opt(av[i], STRING_WITH_LEN("--print-tolower=" ))))
{
if (get_option_bool(&opt->mode.print_tolower, av[i], op))
return 1 ;
}
else if ((op= one_opt(av[i], STRING_WITH_LEN("--print-noaccent-toupper=" ))))
{
if (get_option_bool(&opt->mode.print_noaccent_toupper, av[i], op))
return 1 ;
}
else if ((op= one_opt(av[i], STRING_WITH_LEN("--page-name=" ))))
{
opt->mode.page_name= op;
}
else if ((op= one_opt(av[i], STRING_WITH_LEN("--page-name-derived=" ))))
{
opt->mode.page_name_derived= op;
}
else if ((op= one_opt(av[i], STRING_WITH_LEN("--index-name=" ))))
{
opt->mode.index_name= op;
}
else
{
if (av[i][0 ] == '-' && av[i][1 ] == '-' )
{
fprintf(stderr, "Unknown option: %s\n" , av[i]);
return 1 ;
}
break ;
}
}
if (i + 1 != ac)
return usage(ac, av);
opt->filename= av[i];
return 0 ;
}
int main(int ac,char **av)
{
UNIDATA_OPT opt= opt_caseinfo;
if (process_param(&opt, ac, av))
return 1 ;
memset(code,0 ,sizeof (code));
memset(pstat,0 ,sizeof (pstat));
set_default_case_folding(&opt, code);
fill_cjk(code);
if (load_unidata(&opt, code))
return 1 ;
set_noaccent(&opt, code);
set_noaccent_tolower(&opt, code);
set_noaccent_toupper(&opt, code);
/*
Bug # 8385 : utf8_general_ci treats cyrillic letters I and SHORT I as the same
Because of decomposition applied , noaccent_toupper for the following letters :
U + 0419 CYRILLIC CAPITAL LETTER SHORT I
U + 0439 CYRILLIC SMALL LETTER SHORT I
was set to :
U + 418 CYRILLIC CAPITAL LETTER I
Reset it back to U + 0419 .
*/
code[0 x0419].noaccent_toupper= 0 x0419;
code[0 x0439].noaccent_toupper= 0 x0419;
/*
Bug # 27877 incorrect german order in utf8_general_ci
*/
if (strcmp(opt.mode.mode_name, "weight_general_mysql500_ci" ))
{
code[0 x00DF].noaccent_toupper= code['s' ].noaccent_toupper;
}
else
pstat[0 ].page_overridden= 1 ;
if (!strcmp(opt.mode.mode_name, "casefold-tr" ))
{
code[0 x49].tolower= 0 x0131;
code[0 x69].toupper= 0 x0130;
pstat[0 ].page_overridden= 1 ;
}
calc_page_parameters(&opt, code, pstat);
printf("%s\n" , COPYING);
print_command_line_options(ac, av);
print(&opt, code, pstat);
return 0 ;
}
Messung V0.5 in Prozent C=82 H=92 G=86
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland