CUBRID Engine  latest
locale_support.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * locale_support.c : Locale support using LDML (XML) files
21  */
22 
23 #ident "$Id$"
24 
25 
26 #include "config.h"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <assert.h>
31 
32 #include "porting.h"
33 #include "environment_variable.h"
34 #include "utility.h"
35 #include "xml_parser.h"
36 #include "chartype.h"
37 #include "error_manager.h"
38 #include "release_string.h"
39 #include "uca_support.h"
40 #include "unicode_support.h"
41 #include "message_catalog.h"
42 #include "language_support.h"
43 #include "system_parameter.h"
44 #include "crypt_opfunc.h"
45 #if !defined(WINDOWS)
46 #include <netinet/in.h>
47 #endif /* !WINDOWS */
48 #include "locale_support.h"
49 
50 #if defined (SUPPRESS_STRLEN_WARNING)
51 #define strlen(s1) ((int) strlen(s1))
52 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
53 
54 #define TXT_CONV_LINE_SIZE 512
55 #define TXT_CONV_ITEM_GROW_COUNT 128
56 
57 #define LOC_CURRENT_COLL_TAIL(ld) (&(ld->collations[ld->coll_cnt].tail_coll))
58 const char *ldml_ref_day_names[] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
59 
60 /* this must map to 'Am_Pm_name' from string_opfunc.c */
61 const char *ldml_ref_am_pm_names[] = { "am", "pm", "Am", "Pm", "AM", "PM",
62  "a.m.", "p.m.", "A.m.", "P.m.", "A.M.", "P.M."
63 };
64 
65 typedef struct
66 {
67  unsigned int text_cp;
68  unsigned int unicode_cp;
70 
71 /* shared data : this is used during genlocale process
72  * data shared by several locales are centralized here; and saved only once
73  * in the generated libray */
74 typedef enum
75 {
80 
81 typedef struct
82 {
84  char lsd_key[COLL_NAME_SIZE];
85 
86 /* print size of an integer */
87 #define COLL_SHARED_DATA_SIZE (10 + 2)
88  void *data;
91 
93 static int count_shared_data = 0;
94 static int alloced_shared_data = 0;
95 
96 
97 static int start_element_ok (void *data, const char **attr);
98 static int end_element_ok (void *data, const char *el_name);
99 static int start_calendar (void *data, const char **attr);
100 static int end_dateFormatCUBRID (void *data, const char *el_name);
101 static int end_timeFormatCUBRID (void *data, const char *el_name);
102 static int end_datetimeFormatCUBRID (void *data, const char *el_name);
103 static int end_timestampFormatCUBRID (void *data, const char *el_name);
104 static int end_timetzFormatCUBRID (void *data, const char *el_name);
105 static int end_datetimetzFormatCUBRID (void *data, const char *el_name);
106 static int end_timestamptzFormatCUBRID (void *data, const char *el_name);
107 static int start_calendar_name_context (void *data, const char **attr);
108 static int start_month_day_Width (void *data, const char **attr);
109 static int end_month_day_Width (void *data, const char *el_name);
110 static int start_month (void *data, const char **attr);
111 static int end_month (void *data, const char *el_name);
112 static int start_day (void *data, const char **attr);
113 static int end_day (void *data, const char *el_name);
114 static int start_dayPeriodWidth (void *data, const char **attr);
115 static int start_dayPeriod (void *data, const char **attr);
116 static int end_dayPeriod (void *data, const char *el_name);
117 static int start_numbers_symbols (void *data, const char **attr);
118 static int start_currency (void *data, const char **attr);
119 static int end_number_symbol (void *data, const char *el_name);
120 static int start_collations (void *data, const char **attr);
121 static int start_one_collation (void *data, const char **attr);
122 static int end_one_collation (void *data, const char *el_name);
123 static int start_collation_settings (void *data, const char **attr);
124 static int start_collation_reset (void *data, const char **attr);
125 static int end_collation_reset (void *data, const char *el_name);
126 static int start_collation_rule (void *data, const char **attr);
127 static int start_collation_cubrid_rule (void *data, const char **attr);
128 static int start_collation_cubrid_rule_set_wr (void *data, const char **attr);
129 static int end_collation_cubrid_rule_set (void *data, const char *el_name);
130 static int end_collation_cubrid_rule_set_cp_ch (void *data, const char *el_name);
131 static int end_collation_cubrid_rule_set_ech_ecp (void *data, const char *el_name);
132 static int end_collation_cubrid_rule_set_w_wr (void *data, const char *el_name);
133 static int handle_data_collation_rule (void *data, const char *s, int len);
134 static int end_collation_rule (void *data, const char *el_name);
135 static int start_collation_x (void *data, const char **attr);
136 static int end_collation_x (void *data, const char *el_name);
137 static int end_collation_x_rule (void *data, const char *el_name);
138 static int end_collation_x_extend (void *data, const char *el_name);
139 static int end_collation_x_context (void *data, const char *el_name);
140 static int start_collation_logical_pos (void *data, const char **attr);
141 static int end_collation_logical_pos (void *data, const char *el_name);
142 static int start_one_alphabet (void *data, const char **attr);
143 static int start_upper_case_rule (void *data, const char **attr);
144 static int end_case_rule (void *data, const char *el_name);
145 static int start_lower_case_rule (void *data, const char **attr);
146 static int end_transform_buffer (void *data, const char *el_name);
147 static int start_include_collation (void *data, const char **attr);
148 
149 static int start_unicode_file (void *data, const char **attr);
150 
151 static int start_consoleconversion (void *data, const char **attr);
152 
153 static int handle_data (void *data, const char *s, int len);
154 
155 
156 static void clear_data_buffer (XML_PARSER_DATA * pd);
161 static void locale_alloc_collation_id (COLL_TAILORING * coll_tail);
162 static int locale_check_collation_id (const COLL_TAILORING * coll_tail);
163 
164 static void print_debug_start_el (void *data, const char **attrs, const char *msg, const int status);
165 static void print_debug_end_el (void *data, const char *msg, const int status);
166 static void print_debug_data_content (void *data, const char *msg, const int status);
167 static int load_console_conv_data (LOCALE_DATA * ld, bool is_verbose);
168 
169 static int locale_save_to_C_file (LOCALE_FILE lf, LOCALE_DATA * ld);
170 static int locale_save_calendar_to_C_file (FILE * fp, LOCALE_DATA * ld);
171 static int locale_save_alphabets_to_C_file (FILE * fp, LOCALE_DATA * ld);
172 static int locale_save_one_alphabet_to_C_file (FILE * fp, ALPHABET_DATA * a, bool save_w_identier_name,
173  const char *alpha_suffix);
174 static int locale_save_collation_data_to_C_file (FILE * fp, LOCALE_COLLATION * lc);
175 static int locale_save_console_conv_to_C_file (FILE * fp, LOCALE_DATA * ld);
176 static int locale_save_normalization_to_C_file (FILE * fp, LOCALE_DATA * ld);
177 
178 static void locale_destroy_collation_tailorings (const COLL_TAILORING * ct);
179 static void locale_destroy_collation_data (const COLL_DATA * cd);
181 static void locale_destroy_console_conversion (const TEXT_CONVERSION * tc);
182 static int str_pop_token (char *str_p, char **token_p, char **next_p);
183 static int dump_locale_alphabet (ALPHABET_DATA * ad, int dl_settings, int lower_bound, int upper_bound);
184 
185 static void dump_collation_key (COLL_DATA * coll, const unsigned int key, bool print_weight, bool print_key);
186 static void dump_collation_contr (COLL_DATA * coll, const COLL_CONTRACTION * contr, bool print_weight,
187  bool print_contr);
188 static void dump_collation_codepoint (COLL_DATA * coll, const unsigned int cp, bool print_weight, bool print_cp);
190 static void dump_unicode_mapping (UNICODE_MAPPING * um, const int mode);
191 static int dump_console_conversion (TEXT_CONVERSION * tc);
192 
193 static int comp_func_coll_uca_exp_fo (const void *arg1, const void *arg2);
194 static int comp_func_coll_uca_exp (const void *arg1, const void *arg2);
195 
196 static int comp_func_coll_uca_simple_weights_fo (const void *arg1, const void *arg2);
197 static int comp_func_coll_uca_simple_weights (const void *arg1, const void *arg2);
198 static int comp_func_parse_order_index (const void *arg1, const void *arg2);
200 static int locale_check_and_set_shared_data (const LOC_SHARED_DATA_TYPE lsd_type, const char *lsd_key, const void *data,
201  LDML_CONTEXT * ldml_context, LOC_SHARED_DATA ** found_entry);
202 static int locale_compute_coll_checksum (COLL_DATA * cd);
204 static int locale_alphabet_data_to_buf (ALPHABET_DATA * a, char *buf);
206 static int common_collation_end_rule (void *data, LOCALE_DATA * ld, const int rule_id, TAILOR_RULE * t_rule);
207 static int common_collation_start_rule (void *data, const char **attr, LOCALE_DATA * ld, TAILOR_RULE * t_rule);
208 
209 #define PRINT_DEBUG_START(d, a, m, s) \
210  do { \
211  print_debug_start_el (d, a, m, s); \
212  } while (0);
213 
214 #define PRINT_DEBUG_END(d, m, s) \
215  do { \
216  print_debug_end_el (d, m, s); \
217  } while (0);
218 
219 #define PRINT_DEBUG_DATA(d, m, s) \
220  do { \
221  print_debug_data_content (d, m, s); \
222  } while (0);
223 
224 #define PRINT_TO_C_FILE_MAX_INT_LINE 10
225 
226 #if defined(_WIN32) || defined(WINDOWS) || defined(WIN64)
227 #define DLL_EXPORT_PREFIX "__declspec(dllexport) "
228 #define LOCLIB_FILE_EXT "dll"
229 #else
230 #define DLL_EXPORT_PREFIX ""
231 #define LOCLIB_FILE_EXT "so"
232 #endif
233 
234 #define PRINT_STRING_TO_C_FILE(fp, val, len) \
235  do { \
236  int istr; \
237  fprintf (fp, "\""); \
238  for (istr = 0; istr < len; istr++) \
239  { \
240  fprintf (fp, "\\x%02X", (unsigned char) val[istr]); \
241  } \
242  fprintf (fp, "\""); \
243  } while (0);
244 
245 #define PRINT_VAR_TO_C_FILE(fp, type, valname, val, format, d) \
246  do { \
247  fprintf (fp, "\n" DLL_EXPORT_PREFIX "const " \
248  type " " valname "_%s = " format ";\n", d, val); \
249  } while (0);
250 
251 #define PRINT_STRING_VAR_TO_C_FILE(fp, valname, val, d) \
252  do { \
253  fprintf (fp, "\n" DLL_EXPORT_PREFIX "const char " valname "_%s[] = ", d); \
254  PRINT_STRING_TO_C_FILE (fp, val, strlen (val)); \
255  fprintf (fp, ";\n"); \
256  } while (0);
257 
258 #define PRINT_STRING_ARRAY_TO_C_FILE(fp, valname, arrcount, val, d) \
259  do { \
260  int istrarr; \
261  fprintf(fp, "\n" DLL_EXPORT_PREFIX"const char* " valname "_%s[] = {\n", d);\
262  for (istrarr = 0; istrarr < arrcount; istrarr++) \
263  { \
264  fprintf(fp, "\t"); \
265  PRINT_STRING_TO_C_FILE (fp, val[istrarr], strlen(val[istrarr])); \
266  if (istrarr < arrcount - 1) \
267  { \
268  fprintf(fp, ",\n"); \
269  } \
270  else \
271  { \
272  fprintf(fp, "\n"); \
273  } \
274  } \
275  fprintf(fp, "};\n"); \
276  } while (0);
277 
278 
279 #define PRINT_NUM_ARRAY_TO_C_FILE(fp, vname, vtype, intf, arrcount, val, d) \
280  do { \
281  int i_arr, j_arr; \
282  fprintf(fp, \
283  "\n" DLL_EXPORT_PREFIX "const " vtype " " vname "_%s[] = {\n", d); \
284  j_arr = 1; \
285  for (i_arr = 0; i_arr < arrcount; i_arr++) \
286  { \
287  fprintf(fp, "\t"); \
288  fprintf(fp, intf, val[i_arr]); \
289  if (i_arr < arrcount - 1) \
290  { \
291  fprintf(fp, ","); \
292  } \
293  j_arr++; \
294  if (j_arr > PRINT_TO_C_FILE_MAX_INT_LINE) \
295  { \
296  j_arr = 1; \
297  fprintf(fp, "\n"); \
298  } \
299  } \
300  fprintf(fp, "};\n"); \
301  } while (0);
302 
303 
304 #define PRINT_UNNAMED_NUM_ARRAY_TO_C_FILE(fp, intf, tab, arrcount, val) \
305  do { \
306  int i_uarr, j_uarr; \
307  fprintf(fp, tab"{\n"); \
308  j_uarr = 1; \
309  for (i_uarr = 0; i_uarr < arrcount; i_uarr++) \
310  { \
311  fprintf(fp, intf, val[i_uarr]); \
312  if (i_uarr < arrcount - 1) \
313  { \
314  fprintf(fp, ","); \
315  } \
316  j_uarr++; \
317  if (j_uarr > PRINT_TO_C_FILE_MAX_INT_LINE) \
318  { \
319  j_uarr = 1; \
320  fprintf(fp, "\n" tab); \
321  } \
322  } \
323  fprintf(fp, "\n" tab "}"); \
324  } while (0);
325 
326 
327 #define XML_COMMENT_START "<!-- "
328 #define XML_COMMENT_END " -->"
329 
331 
332 static char *cmp_token_name_array = NULL;
333 static char cmp_token_name_size = 0;
334 
335 /*
336  * LDML element definition (XML schema)
337  * full name is the "path" - the names of all parent elements down to
338  * the element
339  */
342 };
343 
346 };
347 
350 };
351 
352 XML_ELEMENT_DEF ldml_elem_calendar = { "ldml dates calendars calendar", 4, (ELEM_START_FUNC) (&start_calendar),
354 };
355 
356 XML_ELEMENT_DEF ldml_elem_dateFormatCUBRID = { "ldml dates calendars calendar dateFormatCUBRID", 5,
359 };
360 
361 XML_ELEMENT_DEF ldml_timeFormatCUBRID = { "ldml dates calendars calendar timeFormatCUBRID", 5,
364 };
365 
366 XML_ELEMENT_DEF ldml_datetimeFormatCUBRID = { "ldml dates calendars calendar datetimeFormatCUBRID", 5,
369 };
370 
371 XML_ELEMENT_DEF ldml_timestampFormatCUBRID = { "ldml dates calendars calendar timestampFormatCUBRID", 5,
375 };
376 
377 XML_ELEMENT_DEF ldml_timetzFormatCUBRID = { "ldml dates calendars calendar timetzFormatCUBRID", 5,
381 };
382 
383 XML_ELEMENT_DEF ldml_datetimetzFormatCUBRID = { "ldml dates calendars calendar datetimetzFormatCUBRID", 5,
387 };
388 
389 XML_ELEMENT_DEF ldml_timestamptzFormatCUBRID = { "ldml dates calendars calendar timestamptzFormatCUBRID", 5,
393 };
394 
395 XML_ELEMENT_DEF ldml_elem_months = { "ldml dates calendars calendar months", 5,
397  NULL
398 };
399 
400 XML_ELEMENT_DEF ldml_elem_monthContext = { "ldml dates calendars calendar months monthContext", 6,
403 };
404 
405 XML_ELEMENT_DEF ldml_elem_monthWidth = { "ldml dates calendars calendar months monthContext monthWidth", 7,
408 };
409 
410 XML_ELEMENT_DEF ldml_elem_month = { "ldml dates calendars calendar months monthContext monthWidth month", 8,
413 };
414 
415 XML_ELEMENT_DEF ldml_elem_days = { "ldml dates calendars calendar days", 5,
417  NULL
418 };
419 
420 XML_ELEMENT_DEF ldml_elem_dayContext = { "ldml dates calendars calendar days dayContext", 6,
423 };
424 
425 XML_ELEMENT_DEF ldml_elem_dayWidth = { "ldml dates calendars calendar days dayContext dayWidth", 7,
428 };
429 
430 XML_ELEMENT_DEF ldml_elem_day = { "ldml dates calendars calendar days dayContext dayWidth day", 8,
433 };
434 
435 XML_ELEMENT_DEF ldml_elem_dayPeriods = { "ldml dates calendars calendar dayPeriods", 5,
437  NULL
438 };
439 
440 XML_ELEMENT_DEF ldml_elem_dayPeriodContext = { "ldml dates calendars calendar dayPeriods dayPeriodContext", 6,
443 };
444 
446  "ldml dates calendars calendar dayPeriods dayPeriodContext dayPeriodWidth",
447  7,
450  NULL
451 };
452 
454  "ldml dates calendars calendar dayPeriods dayPeriodContext dayPeriodWidth dayPeriod",
455  8,
458 };
459 
462 };
463 
466 };
467 
468 XML_ELEMENT_DEF ldml_elem_symbol_decimal = { "ldml numbers symbols decimal", 4, (ELEM_START_FUNC) (&start_element_ok),
470 };
471 
472 XML_ELEMENT_DEF ldml_elem_symbol_group = { "ldml numbers symbols group", 4, (ELEM_START_FUNC) (&start_element_ok),
474 };
475 
478 };
479 
480 XML_ELEMENT_DEF ldml_elem_currency = { "ldml numbers currencies currency", 4,
483 };
484 
487 };
488 
491 };
492 
493 XML_ELEMENT_DEF ldml_elem_collation_rules = { "ldml collations collation rules", 4,
495  NULL
496 };
497 
498 XML_ELEMENT_DEF ldml_elem_collation_settings = { "ldml collations collation settings", 4,
501 };
502 
503 XML_ELEMENT_DEF ldml_elem_collation_reset = { "ldml collations collation rules reset", 5,
506 };
507 
508 XML_ELEMENT_DEF ldml_elem_collation_p = { "ldml collations collation rules p", 5,
512 };
513 
514 XML_ELEMENT_DEF ldml_elem_collation_s = { "ldml collations collation rules s", 5,
518 };
519 
520 XML_ELEMENT_DEF ldml_elem_collation_t = { "ldml collations collation rules t", 5,
524 };
525 
526 XML_ELEMENT_DEF ldml_elem_collation_i = { "ldml collations collation rules i", 5,
530 };
531 
532 XML_ELEMENT_DEF ldml_elem_collation_pc = { "ldml collations collation rules pc", 5,
536 };
537 
538 XML_ELEMENT_DEF ldml_elem_collation_sc = { "ldml collations collation rules sc", 5,
542 };
543 
544 XML_ELEMENT_DEF ldml_elem_collation_tc = { "ldml collations collation rules tc", 5,
548 };
549 
550 XML_ELEMENT_DEF ldml_elem_collation_ic = { "ldml collations collation rules ic", 5,
554 };
555 
556 XML_ELEMENT_DEF ldml_elem_collation_x = { "ldml collations collation rules x", 5,
558  NULL
559 };
560 
561 XML_ELEMENT_DEF ldml_elem_collation_x_p = { "ldml collations collation rules x p", 6,
565 };
566 
567 XML_ELEMENT_DEF ldml_elem_collation_x_s = { "ldml collations collation rules x s", 6,
571 };
572 
573 XML_ELEMENT_DEF ldml_elem_collation_x_t = { "ldml collations collation rules x t", 6,
577 };
578 
579 XML_ELEMENT_DEF ldml_elem_collation_x_i = { "ldml collations collation rules x i", 6,
583 };
584 
585 XML_ELEMENT_DEF ldml_elem_collation_x_extend = { "ldml collations collation rules x extend", 6,
588 };
589 
590 XML_ELEMENT_DEF ldml_elem_collation_x_context = { "ldml collations collation rules x context", 6,
593 };
594 
595 XML_ELEMENT_DEF ldml_elem_collation_reset_first_variable = { "ldml collations collation rules reset first_variable", 6,
598 };
599 
600 XML_ELEMENT_DEF ldml_elem_collation_reset_last_variable = { "ldml collations collation rules reset last_variable", 6,
603 };
604 
606  { "ldml collations collation rules reset first_primary_ignorable", 6,
609 };
610 
612  { "ldml collations collation rules reset last_primary_ignorable", 6,
615 };
616 
618  { "ldml collations collation rules reset first_secondary_ignorable", 6,
621 };
622 
624  { "ldml collations collation rules reset last_secondary_ignorable", 6,
627 };
628 
630  { "ldml collations collation rules reset first_tertiary_ignorable", 6,
633 };
634 
636  { "ldml collations collation rules reset last_tertiary_ignorable", 6,
639 };
640 
642  { "ldml collations collation rules reset first_non_ignorable", 6,
645 };
646 
648  { "ldml collations collation rules reset last_non_ignorable", 6,
651 };
652 
653 XML_ELEMENT_DEF ldml_elem_collation_reset_first_trailing = { "ldml collations collation rules reset first_trailing", 6,
656 };
657 
658 XML_ELEMENT_DEF ldml_elem_collation_reset_last_trailing = { "ldml collations collation rules reset last_trailing", 6,
661 };
662 
664  "ldml collations collation cubridrules", 4,
666  NULL
667 };
668 
669 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set = { "ldml collations collation cubridrules set", 5,
672 };
673 
674 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_ch = { "ldml collations collation cubridrules set ch", 6,
678 };
679 
680 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_sch = { "ldml collations collation cubridrules set sch", 6,
684 };
685 
686 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_ech = { "ldml collations collation cubridrules set ech", 6,
690 };
691 
692 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_cp = { "ldml collations collation cubridrules set cp", 6,
696 };
697 
698 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_scp = { "ldml collations collation cubridrules set scp", 6,
702 };
703 
704 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_ecp = { "ldml collations collation cubridrules set ecp", 6,
708 };
709 
710 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_w = { "ldml collations collation cubridrules set w", 6,
714 };
715 
716 XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_wr = { "ldml collations collation cubridrules set wr", 6,
720 };
721 
724 };
725 
726 XML_ELEMENT_DEF ldml_elem_include_collation = { "ldml collations include", 3,
729  NULL
730 };
731 
734 };
735 
736 XML_ELEMENT_DEF ldml_elem_alphabet_upper = { "ldml alphabets alphabet u", 4,
739 };
740 
742  { "ldml alphabets alphabet u s", 5, (ELEM_START_FUNC) (&start_element_ok),
744 };
745 
747  { "ldml alphabets alphabet u d", 5, (ELEM_START_FUNC) (&start_element_ok),
749 };
750 
751 XML_ELEMENT_DEF ldml_elem_alphabet_lower = { "ldml alphabets alphabet l", 4,
754 };
755 
757  { "ldml alphabets alphabet l s", 5, (ELEM_START_FUNC) (&start_element_ok),
759 };
760 
762  { "ldml alphabets alphabet l d", 5, (ELEM_START_FUNC) (&start_element_ok),
764 };
765 
768 };
769 
771  { "ldml consoleconversion", 2, (ELEM_START_FUNC) (&start_consoleconversion),
773 };
774 
775 /*
776  * LDML elements list - KEEP the order in this list !
777  * it is mandatory to put in schema all parent elements, before adding a new
778  * element */
784 
789 
794 
798  &ldml_elem_day,
799 
804 
811 
826 
834 
847 
858 
867 
869 
871 
875 };
876 
877 /*
878  * start_element_ok() - Dummy XML element start function
879  * Used just for verbose purpose.
880  *
881  * return: always 0 (validation OK)
882  * data: user data
883  * attr: attribute/value pair array
884  *
885  * Note : this function is registered by XML elements that normally do not
886  * require any validation for element start, but is used only for
887  * debug purpose, in order to properly display each parsed XML element
888  */
889 static int
890 start_element_ok (void *data, const char **attr)
891 {
892  PRINT_DEBUG_START (data, attr, "", 0);
893  return 0;
894 }
895 
896 /*
897  * end_element_ok() - Dummy XML element end function
898  * Used just for verbose purpose.
899  *
900  *
901  * return: always 0 (OK)
902  * data: user data
903  * el_name: element name
904  *
905  * Note : this function is registered by XML elements that normally do not
906  * require any action for element end, but is used only for
907  * debug purpose, in order to properly display each parsed XML element
908  */
909 static int
910 end_element_ok (void *data, const char *el_name)
911 {
912  PRINT_DEBUG_END (data, "", 0);
913  return 0;
914 }
915 
916 /*
917  * start_calendar() - XML element start function
918  * "ldml dates calendars calendar"
919  *
920  * return: 0 validation OK enter this element , 1 validation NOK do not enter
921  * -1 error abort parsing
922  * data: user data
923  * attr: attribute/value pair array
924  */
925 static int
926 start_calendar (void *data, const char **attr)
927 {
928  if (xml_check_att_value (attr, "type", "gregorian") != 0)
929  {
930  PRINT_DEBUG_START (data, attr, "", 1);
931  return 1;
932  }
933 
934  PRINT_DEBUG_START (data, attr, "", 0);
935  return 0;
936 }
937 
938 /*
939  * end_dateFormatCUBRID() - XML element end function
940  * "ldml dates calendars calendar dateFormatCUBRID"
941  *
942  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
943  * data: user data
944  * el_name: element name
945  */
946 static int
947 end_dateFormatCUBRID (void *data, const char *el_name)
948 {
949  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
950  LOCALE_DATA *ld = NULL;
951 
952  assert (data != NULL);
953 
954  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
955 
956  /* copy data buffer to locale */
957  assert (ld->data_buf_count < (int) sizeof (ld->dateFormat));
958 
959  if (ld->data_buf_count < (int) sizeof (ld->dateFormat))
960  {
961  strcpy (ld->dateFormat, ld->data_buffer);
962  }
963  else
964  {
965  PRINT_DEBUG_END (data, "Too much data", -1);
966  return -1;
967  }
968 
970 
971  PRINT_DEBUG_END (data, "", 0);
972 
973  return 0;
974 }
975 
976 /*
977  * end_timeFormatCUBRID() - XML element end function
978  * "ldml dates calendars calendar timeFormatCUBRID"
979  *
980  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
981  * data: user data
982  * el_name: element name
983  */
984 static int
985 end_timeFormatCUBRID (void *data, const char *el_name)
986 {
987  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
988  LOCALE_DATA *ld = NULL;
989 
990  assert (data != NULL);
991 
992  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
993 
994  /* copy data buffer to locale */
995  assert (ld->data_buf_count < (int) sizeof (ld->timeFormat));
996 
997  if (ld->data_buf_count < (int) sizeof (ld->timeFormat))
998  {
999  strcpy (ld->timeFormat, ld->data_buffer);
1000  }
1001  else
1002  {
1003  PRINT_DEBUG_END (data, "Too much data", -1);
1004  return -1;
1005  }
1006 
1008 
1009  PRINT_DEBUG_END (data, "", 0);
1010 
1011  return 0;
1012 }
1013 
1014 /*
1015  * end_datetimeFormatCUBRID() - XML element end function
1016  * "ldml dates calendars calendar datetimeFormatCUBRID"
1017  *
1018  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1019  * data: user data
1020  * el_name: element name
1021  */
1022 static int
1023 end_datetimeFormatCUBRID (void *data, const char *el_name)
1024 {
1025  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1026  LOCALE_DATA *ld = NULL;
1027 
1028  assert (data != NULL);
1029 
1030  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1031 
1032  /* copy data buffer to locale */
1033  assert (ld->data_buf_count < (int) sizeof (ld->datetimeFormat));
1034 
1035  if (ld->data_buf_count < (int) sizeof (ld->datetimeFormat))
1036  {
1037  strcpy (ld->datetimeFormat, ld->data_buffer);
1038  }
1039  else
1040  {
1041  PRINT_DEBUG_END (data, "Too much data", -1);
1042  return -1;
1043  }
1044 
1046 
1047  PRINT_DEBUG_END (data, "", 0);
1048 
1049  return 0;
1050 }
1051 
1052 /*
1053  * end_timestampFormatCUBRID() - XML element end function
1054  * "ldml dates calendars calendar timestampFormatCUBRID"
1055  *
1056  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1057  * data: user data
1058  * el_name: element name
1059  */
1060 static int
1061 end_timestampFormatCUBRID (void *data, const char *el_name)
1062 {
1063  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1064  LOCALE_DATA *ld = NULL;
1065 
1066  assert (data != NULL);
1067 
1068  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1069 
1070  /* copy data buffer to locale */
1071  assert (ld->data_buf_count < (int) sizeof (ld->timestampFormat));
1072 
1073  if (ld->data_buf_count < (int) sizeof (ld->timestampFormat))
1074  {
1075  strcpy (ld->timestampFormat, ld->data_buffer);
1076  }
1077  else
1078  {
1079  PRINT_DEBUG_END (data, "Too much data", -1);
1080  return -1;
1081  }
1082 
1084 
1085  PRINT_DEBUG_END (data, "", 0);
1086 
1087  return 0;
1088 }
1089 
1090 /*
1091  * end_timetzFormatCUBRID() - XML element end function
1092  * "ldml dates calendars calendar timetzFormatCUBRID"
1093  *
1094  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1095  * data: user data
1096  * el_name: element name
1097  */
1098 static int
1099 end_timetzFormatCUBRID (void *data, const char *el_name)
1100 {
1101  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1102  LOCALE_DATA *ld = NULL;
1103 
1104  assert (data != NULL);
1105 
1106  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1107 
1108  /* copy data buffer to locale */
1109  assert (ld->data_buf_count < (int) sizeof (ld->timetzFormat));
1110 
1111  if (ld->data_buf_count < (int) sizeof (ld->timetzFormat))
1112  {
1113  strcpy (ld->timetzFormat, ld->data_buffer);
1114  }
1115  else
1116  {
1117  PRINT_DEBUG_END (data, "Too much data", -1);
1118  return -1;
1119  }
1120 
1122 
1123  PRINT_DEBUG_END (data, "", 0);
1124 
1125  return 0;
1126 }
1127 
1128 /*
1129  * end_datetimetzFormatCUBRID() - XML element end function
1130  * "ldml dates calendars calendar datetimetzFormatCUBRID"
1131  *
1132  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1133  * data: user data
1134  * el_name: element name
1135  */
1136 static int
1137 end_datetimetzFormatCUBRID (void *data, const char *el_name)
1138 {
1139  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1140  LOCALE_DATA *ld = NULL;
1141 
1142  assert (data != NULL);
1143 
1144  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1145 
1146  /* copy data buffer to locale */
1147  assert (ld->data_buf_count < (int) sizeof (ld->datetimetzFormat));
1148 
1149  if (ld->data_buf_count < (int) sizeof (ld->datetimetzFormat))
1150  {
1151  strcpy (ld->datetimetzFormat, ld->data_buffer);
1152  }
1153  else
1154  {
1155  PRINT_DEBUG_END (data, "Too much data", -1);
1156  return -1;
1157  }
1158 
1160 
1161  PRINT_DEBUG_END (data, "", 0);
1162 
1163  return 0;
1164 }
1165 
1166 /*
1167  * end_timestamptzFormatCUBRID() - XML element end function
1168  * "ldml dates calendars calendar timestamptzFormatCUBRID"
1169  *
1170  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1171  * data: user data
1172  * el_name: element name
1173  */
1174 static int
1175 end_timestamptzFormatCUBRID (void *data, const char *el_name)
1176 {
1177  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1178  LOCALE_DATA *ld = NULL;
1179 
1180  assert (data != NULL);
1181 
1182  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1183 
1184  /* copy data buffer to locale */
1185  assert (ld->data_buf_count < (int) sizeof (ld->timestamptzFormat));
1186 
1187  if (ld->data_buf_count < (int) sizeof (ld->timestamptzFormat))
1188  {
1189  strcpy (ld->timestamptzFormat, ld->data_buffer);
1190  }
1191  else
1192  {
1193  PRINT_DEBUG_END (data, "Too much data", -1);
1194  return -1;
1195  }
1196 
1198 
1199  PRINT_DEBUG_END (data, "", 0);
1200 
1201  return 0;
1202 }
1203 
1204 /*
1205  * start_calendar_name_context() - XML element start function
1206  * "ldml dates calendars calendar months monthContext"
1207  *
1208  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1209  * -1 error abort parsing
1210  * data: user data
1211  * attr: attribute/value pair array
1212  */
1213 static int
1214 start_calendar_name_context (void *data, const char **attr)
1215 {
1216  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1217  LOCALE_DATA *ld = NULL;
1218 
1219  assert (data != NULL);
1220 
1221  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1222 
1223  if (xml_check_att_value (attr, "type", "format") == 0)
1224  {
1225  PRINT_DEBUG_START (data, attr, "", 0);
1226  return 0;
1227  }
1228 
1229  PRINT_DEBUG_START (data, attr, "", 1);
1230  return 1;
1231 }
1232 
1233 /*
1234  * start_month_day_Width() - XML element start function
1235  * "ldml dates calendars calendar months monthContext monthWidth"
1236  *
1237  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1238  * -1 error abort parsing
1239  * data: user data
1240  * attr: attribute/value pair array
1241  */
1242 static int
1243 start_month_day_Width (void *data, const char **attr)
1244 {
1245  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1246  LOCALE_DATA *ld = NULL;
1247 
1248  assert (data != NULL);
1249 
1250  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1251 
1252  assert (ld->name_type == 0);
1253 
1254  if (xml_check_att_value (attr, "type", "abbreviated") == 0)
1255  {
1256  ld->name_type = 1;
1257  PRINT_DEBUG_START (data, attr, "", 0);
1258  return 0;
1259  }
1260  else if (xml_check_att_value (attr, "type", "wide") == 0)
1261  {
1262  ld->name_type = 2;
1263  PRINT_DEBUG_START (data, attr, "", 0);
1264  return 0;
1265  }
1266 
1267  PRINT_DEBUG_START (data, attr, "", 1);
1268  return 1;
1269 }
1270 
1271 /*
1272  * end_month_day_Width() - XML element end function
1273  * "ldml dates calendars calendar months monthContext monthWidth"
1274  *
1275  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1276  * data: user data
1277  * el_name: element name
1278  */
1279 static int
1280 end_month_day_Width (void *data, const char *el_name)
1281 {
1282  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1283  LOCALE_DATA *ld = NULL;
1284 
1285  assert (data != NULL);
1286 
1287  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1288 
1289  assert (ld->name_type != 0);
1290 
1291  ld->name_type = 0;
1292 
1293  PRINT_DEBUG_END (data, "", 0);
1294  return 0;
1295 }
1296 
1297 /*
1298  * start_month() - XML element start function
1299  * "ldml dates calendars calendar months monthContext monthWidth month"
1300  *
1301  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1302  * -1 error abort parsing
1303  * data: user data
1304  * attr: attribute/value pair array
1305  */
1306 static int
1307 start_month (void *data, const char **attr)
1308 {
1309  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1310  LOCALE_DATA *ld = NULL;
1311  char *month_count = NULL;
1312 
1313  assert (data != NULL);
1314 
1315  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1316 
1317  if (xml_get_att_value (attr, "type", &month_count) == 0)
1318  {
1319  assert (month_count != NULL);
1320  ld->curr_period = atoi (month_count);
1321 
1322  assert (ld->curr_period > 0 && ld->curr_period <= CAL_MONTH_COUNT);
1323 
1324  if (ld->curr_period > 0 && ld->curr_period <= CAL_MONTH_COUNT)
1325  {
1326  ld->curr_period = ld->curr_period - 1;
1327  }
1328  else
1329  {
1330  PRINT_DEBUG_START (data, attr, "Invalid month", -1);
1331  return -1;
1332  }
1333 
1334  PRINT_DEBUG_START (data, attr, "", 0);
1335  return 0;
1336  }
1337 
1338  PRINT_DEBUG_START (data, attr, "", 1);
1339  return 1;
1340 }
1341 
1342 /*
1343  * end_month() - XML element end function
1344  * "ldml dates calendars calendar months monthContext monthWidth month"
1345  *
1346  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1347  * data: user data
1348  * el_name: element name
1349  */
1350 static int
1351 end_month (void *data, const char *el_name)
1352 {
1353  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1354  LOCALE_DATA *ld = NULL;
1355 
1356  assert (data != NULL);
1357 
1358  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1359 
1360  /* copy data buffer to locale */
1361  assert (ld->curr_period >= 0 && ld->curr_period < CAL_MONTH_COUNT);
1362 
1363  assert (ld->name_type == 2 || ld->name_type == 1);
1364 
1365  if (ld->name_type == 1)
1366  {
1368 
1370  {
1371  strcpy (ld->month_names_abbreviated[ld->curr_period], ld->data_buffer);
1372  }
1373  else
1374  {
1375  PRINT_DEBUG_END (data, "Too much data", -1);
1376  return -1;
1377  }
1378  }
1379  else if (ld->name_type == 2)
1380  {
1383  {
1384  strcpy (ld->month_names_wide[ld->curr_period], ld->data_buffer);
1385  }
1386  else
1387  {
1388  PRINT_DEBUG_END (data, "Too much data", -1);
1389  return -1;
1390  }
1391  }
1392 
1393  ld->curr_period = -1;
1394 
1396 
1397  PRINT_DEBUG_END (data, "", 0);
1398  return 0;
1399 }
1400 
1401 /*
1402  * start_day() - XML element start function
1403  * "ldml dates calendars calendar days dayContext dayWidth day"
1404  *
1405  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1406  * -1 error abort parsing
1407  * data: user data
1408  * attr: attribute/value pair array
1409  */
1410 static int
1411 start_day (void *data, const char **attr)
1412 {
1413  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1414  LOCALE_DATA *ld = NULL;
1415  char *day_ref_name = NULL;
1416  int i;
1417 
1418  assert (data != NULL);
1419 
1420  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1421 
1422  if (xml_get_att_value (attr, "type", &day_ref_name) != 0)
1423  {
1424  PRINT_DEBUG_START (data, attr, "", 1);
1425  return 1;
1426  }
1427 
1428  assert (day_ref_name != NULL);
1429 
1430  for (i = 0; i < 7; i++)
1431  {
1432  if (strcmp (ldml_ref_day_names[i], day_ref_name) == 0)
1433  {
1434  break;
1435  }
1436  }
1437 
1438  assert (i >= 0 && i < CAL_DAY_COUNT);
1439 
1440  if (i >= 0 && i < CAL_DAY_COUNT)
1441  {
1442  ld->curr_period = i;
1443  }
1444  else
1445  {
1446  PRINT_DEBUG_START (data, attr, "Invalid day", -1);
1447  return -1;
1448  }
1449 
1450  PRINT_DEBUG_START (data, attr, "", 0);
1451  return 0;
1452 }
1453 
1454 /*
1455  * end_day() - XML element end function
1456  * "ldml dates calendars calendar days dayContext dayWidth day"
1457  *
1458  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1459  * data: user data
1460  * el_name: element name
1461  */
1462 static int
1463 end_day (void *data, const char *el_name)
1464 {
1465  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1466  LOCALE_DATA *ld = NULL;
1467 
1468  assert (data != NULL);
1469 
1470  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1471 
1472  /* copy data buffer to locale */
1473  assert (ld->curr_period >= 0 && ld->curr_period < CAL_DAY_COUNT);
1474 
1475  assert (ld->name_type == 2 || ld->name_type == 1);
1476 
1477  if (ld->name_type == 1)
1478  {
1481  {
1482  strcpy (ld->day_names_abbreviated[ld->curr_period], ld->data_buffer);
1483  }
1484  else
1485  {
1486  PRINT_DEBUG_END (data, "Too much data", -1);
1487  return -1;
1488  }
1489  }
1490  else if (ld->name_type == 2)
1491  {
1494  {
1495  strcpy (ld->day_names_wide[ld->curr_period], ld->data_buffer);
1496  }
1497  else
1498  {
1499  PRINT_DEBUG_END (data, "Too much data", -1);
1500  return -1;
1501  }
1502  }
1503 
1504  ld->curr_period = -1;
1505 
1507 
1508  PRINT_DEBUG_END (data, "", 0);
1509  return 0;
1510 }
1511 
1512 /*
1513  * start_dayPeriodWidth() - XML element start function
1514  * "ldml dates calendars calendar dayPeriods dayPeriodContext dayPeriodWidth"
1515  *
1516  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1517  * -1 error abort parsing
1518  * data: user data
1519  * attr: attribute/value pair array
1520  */
1521 static int
1522 start_dayPeriodWidth (void *data, const char **attr)
1523 {
1524  if (xml_check_att_value (attr, "type", "wide") == 0)
1525  {
1526  PRINT_DEBUG_START (data, attr, "", 0);
1527  return 0;
1528  }
1529 
1530  PRINT_DEBUG_START (data, attr, "", 1);
1531  return 1;
1532 }
1533 
1534 /*
1535  * start_dayPeriod() - XML element start function
1536  * "ldml dates calendars calendar dayPeriods dayPeriodContext dayPeriodWidth dayPeriod"
1537  *
1538  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1539  * -1 error abort parsing
1540  * data: user data
1541  * attr: attribute/value pair array
1542  */
1543 static int
1544 start_dayPeriod (void *data, const char **attr)
1545 {
1546  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1547  LOCALE_DATA *ld = NULL;
1548  char *am_pm_ref_name = NULL;
1549  int i;
1550 
1551  assert (data != NULL);
1552 
1553  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1554 
1555  if (xml_get_att_value (attr, "type", &am_pm_ref_name) != 0)
1556  {
1557  PRINT_DEBUG_START (data, attr, "", 1);
1558  return 1;
1559  }
1560 
1561  assert (am_pm_ref_name != NULL);
1562 
1563  for (i = 0; i < CAL_AM_PM_COUNT; i++)
1564  {
1565  if (strcmp (ldml_ref_am_pm_names[i], am_pm_ref_name) == 0)
1566  {
1567  break;
1568  }
1569  }
1570 
1571  assert (i >= 0 && i < CAL_AM_PM_COUNT);
1572 
1573  if (i >= 0 && i < CAL_AM_PM_COUNT)
1574  {
1575  ld->curr_period = i;
1576  }
1577  else
1578  {
1579  PRINT_DEBUG_START (data, attr, "Invalid dayPeriod", -1);
1580  return -1;
1581  }
1582 
1583  PRINT_DEBUG_START (data, attr, "", 0);
1584  return 0;
1585 }
1586 
1587 /*
1588  * end_dayPeriod() - XML element end function
1589  * "ldml dates calendars calendar dayPeriods dayPeriodContext dayPeriodWidth dayPeriod"
1590  *
1591  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1592  * data: user data
1593  * el_name: element name
1594  */
1595 static int
1596 end_dayPeriod (void *data, const char *el_name)
1597 {
1598  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1599  LOCALE_DATA *ld = NULL;
1600 
1601  assert (data != NULL);
1602 
1603  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1604 
1605  /* copy data buffer to locale */
1606  assert (ld->curr_period >= 0 && ld->curr_period < CAL_AM_PM_COUNT);
1607 
1610  {
1611  strcpy (ld->am_pm[ld->curr_period], ld->data_buffer);
1612  }
1613  else
1614  {
1615  PRINT_DEBUG_END (data, "Too much data", -1);
1616  return -1;
1617  }
1618 
1619  ld->curr_period = -1;
1620 
1622 
1623  PRINT_DEBUG_END (data, "", 0);
1624  return 0;
1625 }
1626 
1627 /*
1628  * start_numbers_symbols() - XML element start function
1629  * "ldml numbers symbols"
1630  *
1631  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1632  * -1 error abort parsing
1633  * data: user data
1634  * attr: attribute/value pair array
1635  */
1636 static int
1637 start_numbers_symbols (void *data, const char **attr)
1638 {
1639  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1640  LOCALE_DATA *ld = NULL;
1641 
1642  assert (data != NULL);
1643 
1644  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1645 
1646  if (xml_check_att_value (attr, "numberSystem", "latn") != 0)
1647  {
1648  PRINT_DEBUG_START (data, attr, "", 1);
1649  return 1;
1650  }
1651 
1652  PRINT_DEBUG_START (data, attr, "", 0);
1653  return 0;
1654 }
1655 
1656 /*
1657  * end_number_symbol() - XML element end function
1658  * "ldml numbers symbols decimal"
1659  *
1660  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1661  * data: user data
1662  * el_name: element name
1663  */
1664 static int
1665 end_number_symbol (void *data, const char *el_name)
1666 {
1667  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1668  LOCALE_DATA *ld = NULL;
1669 
1670  assert (data != NULL);
1671 
1672  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1673 
1674  /* number symbol is exactly one character (ASCII compatible) */
1675  if (ld->data_buf_count == 1 && (*(ld->data_buffer) >= ' ' && (unsigned char) *(ld->data_buffer) < 0x80))
1676  {
1677  if (strcmp (el_name, "decimal") == 0)
1678  {
1679  ld->number_decimal_sym = *(ld->data_buffer);
1680  }
1681  else
1682  {
1683  ld->number_group_sym = *(ld->data_buffer);
1684  }
1685  }
1686  else
1687  {
1688  PRINT_DEBUG_END (data, "Invalid numeric symbol", -1);
1689  return -1;
1690  }
1691 
1693 
1694  PRINT_DEBUG_END (data, "", 0);
1695  return 0;
1696 }
1697 
1698 /*
1699  * start_currency() - XML element start function
1700  * "ldml numbers currencies currency"
1701  *
1702  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1703  * -1 error abort parsing
1704  * data: user data
1705  * attr: attribute/value pair array
1706  */
1707 static int
1708 start_currency (void *data, const char **attr)
1709 {
1710  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1711  LOCALE_DATA *ld = NULL;
1712  char *att_val = NULL;
1713  int currency_size = 0;
1714 
1715  assert (data != NULL);
1716 
1717  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1718 
1719  /* all setting are optional */
1720  if (xml_get_att_value (attr, "type", &att_val) == 0)
1721  {
1722  /* Type attribute found, store it. */
1723  if (strlen (att_val) != LOC_DATA_CURRENCY_ISO_CODE_LEN)
1724  {
1725  PRINT_DEBUG_START (data, attr, "Currency ISO code invalid, " "it must be 3 chars long.", -1);
1726  return -1;
1727  }
1729  {
1730  PRINT_DEBUG_START (data, attr, "Currency ISO code already set.", -1);
1731  return -1;
1732  }
1733  if (!intl_is_currency_symbol (att_val, &(ld->default_currency_code), &currency_size, CURRENCY_CHECK_MODE_ISO))
1734  {
1735  PRINT_DEBUG_START (data, attr, "Currency ISO code not supported", -1);
1736  return -1;
1737  }
1738  }
1739  else
1740  {
1741  /* If <currency> does not have a type attribute, parsing fails. */
1742  PRINT_DEBUG_START (data, attr, "Currency tag does not have an ISO code type " "attribute.", -1);
1743  return -1;
1744  }
1745 
1746  PRINT_DEBUG_START (data, attr, "", 0);
1747  return 0;
1748 }
1749 
1750 
1751 /* LDML collation */
1752 /*
1753  * start_collations() - XML element start function
1754  * "ldml collations"
1755  *
1756  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1757  * -1 error abort parsing
1758  * data: user data
1759  * attr: attribute/value pair array
1760  */
1761 static int
1762 start_collations (void *data, const char **attr)
1763 {
1764  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1765  LOCALE_DATA *ld = NULL;
1766  char *valid_locales = NULL;
1767  int check_loc_len;
1768  char *t_start;
1769  char *t_end;
1770  char *att_val_end;
1771  bool locale_found = false;
1772  bool search_end = false;
1773 
1774  assert (data != NULL);
1775 
1776  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1777 
1778  if (xml_get_att_value (attr, "validSubLocales", &valid_locales) != 0)
1779  {
1780  PRINT_DEBUG_START (data, attr, "", 1);
1781  return 1;
1782  }
1783 
1784  assert (ld->locale_name != NULL);
1785 
1786  check_loc_len = strlen (ld->locale_name);
1787  att_val_end = valid_locales + strlen (valid_locales);
1788 
1789  /* separate the locales_name into tokens */
1790  t_start = t_end = valid_locales;
1791 
1792  do
1793  {
1794  if (*t_end == '\0' || char_isspace ((int) *t_end))
1795  {
1796  /* token ended, check locale name */
1797  if ((t_end - t_start == 3 && memcmp (t_start, "all", 3) == 0) || (t_end - t_start == 1 && *t_start == '*')
1798  || (t_end - t_start == check_loc_len && memcmp (ld->locale_name, t_start, t_end - t_start) == 0))
1799  {
1800  locale_found = true;
1801  break;
1802  }
1803 
1804  if (*t_end == '\0')
1805  {
1806  search_end = true;
1807  }
1808 
1809  t_end++;
1810  t_start = t_end;
1811  }
1812  else
1813  {
1814  t_end++;
1815  }
1816  }
1817  while (!search_end);
1818 
1819  if (!locale_found)
1820  {
1821  PRINT_DEBUG_START (data, attr, "", 1);
1822  return 1;
1823  }
1824 
1825  PRINT_DEBUG_START (data, attr, "", 0);
1826  return 0;
1827 }
1828 
1829 /*
1830  * start_one_collation() - XML element start function
1831  * "ldml collations collation"
1832  *
1833  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1834  * -1 error abort parsing
1835  * data: user data
1836  * attr: attribute/value pair array
1837  */
1838 static int
1839 start_one_collation (void *data, const char **attr)
1840 {
1841  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1842  LOCALE_DATA *ld = NULL;
1843  LOCALE_COLLATION *locale_coll = NULL;
1844  char *att_val = NULL;
1845 
1846  assert (data != NULL);
1847 
1848  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1849 
1850  locale_coll = new_locale_collation (ld);
1851  if (locale_coll == NULL)
1852  {
1854  PRINT_DEBUG_START (data, attr, "memory allocation failed", -1);
1855  return -1;
1856  }
1857 
1858  if (xml_get_att_value (attr, "type", &att_val) != 0)
1859  {
1860  PRINT_DEBUG_START (data, attr, "", 1);
1861  return 1;
1862  }
1863 
1864  assert (att_val != NULL);
1865 
1866  strncpy (locale_coll->tail_coll.coll_name, att_val, COLL_NAME_SIZE - 1);
1867  locale_coll->tail_coll.coll_name[COLL_NAME_SIZE - 1] = '\0';
1868 
1869  /* initialize default value for settings */
1871  locale_coll->tail_coll.uca_opt.sett_caseFirst = 1;
1872 
1874  locale_coll->tail_coll.ldml_context.line_no = XML_GetCurrentLineNumber (pd->xml_parser);
1875 
1876  PRINT_DEBUG_START (data, attr, "", 0);
1877  return 0;
1878 }
1879 
1880 /*
1881  * end_one_collation() - XML element end function
1882  * "ldml collations collation"
1883  *
1884  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
1885  * data: user data
1886  * el_name: element name
1887  */
1888 static int
1889 end_one_collation (void *data, const char *el_name)
1890 {
1891  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1892  LOCALE_DATA *ld = NULL;
1893 
1894  assert (data != NULL);
1895 
1896  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1897 
1898  ld->coll_cnt++;
1899 
1900  PRINT_DEBUG_END (data, "", 0);
1901  return 0;
1902 }
1903 
1904 /*
1905  * start_collation_settings() - XML element start function
1906  * "ldml collations collation settings"
1907  *
1908  * return: 0 validation OK enter this element , 1 validation NOK do not enter
1909  * -1 error abort parsing
1910  * data: user data
1911  * attr: attribute/value pair array
1912  */
1913 static int
1914 start_collation_settings (void *data, const char **attr)
1915 {
1916  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
1917  LOCALE_DATA *ld = NULL;
1918  char *att_val = NULL;
1919  char err_msg[ERR_MSG_SIZE + PATH_MAX];
1920  COLL_TAILORING *curr_coll_tail = NULL;
1921 
1922  assert (data != NULL);
1923 
1924  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
1925  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
1926 
1927  att_val = NULL;
1928  if (xml_get_att_value (attr, "id", &att_val) == 0)
1929  {
1930  assert (att_val != NULL);
1931  curr_coll_tail->coll_id = atoi (att_val);
1932 
1933  if (curr_coll_tail->coll_id < LANG_MAX_BUILTIN_COLLATIONS || curr_coll_tail->coll_id >= LANG_MAX_COLLATIONS)
1934  {
1935  snprintf (err_msg, sizeof (err_msg) - 1,
1936  "File %s, line: %lu : " "Invalid collation numeric identifier : %d"
1937  " for collation '%s'. Valid range is from %d to %d", ld->ldml_context.ldml_file,
1938  XML_GetCurrentLineNumber (pd->xml_parser), curr_coll_tail->coll_id, curr_coll_tail->coll_name,
1940  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
1941  return -1;
1942  }
1943  }
1944 
1945  att_val = NULL;
1946  /* all setting are optional */
1947  if (xml_get_att_value (attr, "strength", &att_val) == 0)
1948  {
1949  T_LEVEL coll_strength = TAILOR_QUATERNARY;
1950  if (strcasecmp (att_val, "primary") == 0 || strcmp (att_val, "1") == 0)
1951  {
1952  coll_strength = TAILOR_PRIMARY;
1953  }
1954  else if ((strcasecmp (att_val, "secondary") == 0) || (strcmp (att_val, "2") == 0))
1955  {
1956  coll_strength = TAILOR_SECONDARY;
1957  }
1958  else if ((strcasecmp (att_val, "tertiary") == 0) || (strcmp (att_val, "3") == 0))
1959  {
1960  coll_strength = TAILOR_TERTIARY;
1961  }
1962  else if ((strcasecmp (att_val, "quaternary") == 0) || (strcmp (att_val, "4") == 0))
1963  {
1964  coll_strength = TAILOR_QUATERNARY;
1965  }
1966  else if ((strcasecmp (att_val, "identical") == 0) || (strcmp (att_val, "5") == 0))
1967  {
1968  coll_strength = TAILOR_IDENTITY;
1969  }
1970  else
1971  {
1972  snprintf (err_msg, sizeof (err_msg) - 1,
1973  "File %s, line: %lu : " "Invalid collation strength : '%s'" " for collation '%s'",
1974  ld->ldml_context.ldml_file, XML_GetCurrentLineNumber (pd->xml_parser), att_val,
1975  curr_coll_tail->coll_name);
1976  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
1977  return -1;
1978  }
1979 
1980  curr_coll_tail->uca_opt.sett_strength = coll_strength;
1981  }
1982 
1983  att_val = NULL;
1984 
1985  if (xml_get_att_value (attr, "backwards", &att_val) == 0)
1986  {
1987  if (strcasecmp (att_val, "on") == 0)
1988  {
1989  curr_coll_tail->uca_opt.sett_backwards = true;
1990  }
1991  }
1992 
1993  att_val = NULL;
1994 
1995  if (xml_get_att_value (attr, "caseLevel", &att_val) == 0)
1996  {
1997  if (strcasecmp (att_val, "on") == 0)
1998  {
1999  curr_coll_tail->uca_opt.sett_caseLevel = true;
2000  }
2001  }
2002 
2003  att_val = NULL;
2004 
2005  if (xml_get_att_value (attr, "caseFirst", &att_val) == 0)
2006  {
2007  if (strcasecmp (att_val, "off") == 0)
2008  {
2009  curr_coll_tail->uca_opt.sett_caseFirst = 0;
2010  }
2011  else if (strcasecmp (att_val, "upper") == 0)
2012  {
2013  curr_coll_tail->uca_opt.sett_caseFirst = 1;
2014  }
2015  else if (strcasecmp (att_val, "lower") == 0)
2016  {
2017  curr_coll_tail->uca_opt.sett_caseFirst = 2;
2018  }
2019  }
2020 
2021  /* CUBRID specific collation settings */
2022  att_val = NULL;
2023  if (xml_get_att_value (attr, "CUBRIDMaxWeights", &att_val) == 0)
2024  {
2025  assert (att_val != NULL);
2026  curr_coll_tail->sett_max_cp = atoi (att_val);
2027  }
2028 
2029  att_val = NULL;
2030  if (xml_get_att_value (attr, "DUCETContractions", &att_val) == 0)
2031  {
2032  assert (att_val != NULL);
2033  if (strcasecmp (att_val, "use") == 0)
2034  {
2035  curr_coll_tail->uca_opt.sett_contr_policy |= CONTR_DUCET_USE;
2036  }
2037  }
2038 
2039  att_val = NULL;
2040  if (xml_get_att_value (attr, "TailoringContractions", &att_val) == 0)
2041  {
2042  assert (att_val != NULL);
2043  if (strcasecmp (att_val, "use") == 0)
2044  {
2045  curr_coll_tail->uca_opt.sett_contr_policy |= CONTR_TAILORING_USE;
2046  }
2047  }
2048 
2049  att_val = NULL;
2050  if (xml_get_att_value (attr, "CUBRIDExpansions", &att_val) == 0)
2051  {
2052  assert (att_val != NULL);
2053  if (strcasecmp (att_val, "use") == 0)
2054  {
2055  curr_coll_tail->uca_opt.sett_expansions = true;
2056  }
2057  }
2058 
2059  att_val = NULL;
2060  if (xml_get_att_value (attr, "MatchContractionBoundary", &att_val) == 0)
2061  {
2062  assert (att_val != NULL);
2063  if (strcasecmp (att_val, "true") == 0)
2064  {
2066  }
2067  }
2068 
2069  PRINT_DEBUG_START (data, attr, "", 0);
2070  return 0;
2071 }
2072 
2073 /*
2074  * start_collation_reset() - XML element start function
2075  * "ldml collations collation rules reset"
2076  *
2077  * return: 0 validation OK enter this element , 1 validation NOK do not enter
2078  * -1 error abort parsing
2079  * data: user data
2080  * attr: attribute/value pair array
2081  */
2082 static int
2083 start_collation_reset (void *data, const char **attr)
2084 {
2085  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2086  LOCALE_DATA *ld = NULL;
2087  char *att_val = NULL;
2088 
2089  assert (data != NULL);
2090 
2091  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2092 
2093  *(ld->last_anchor_buf) = '\0';
2094 
2098 
2099  if (xml_get_att_value (attr, "before", &att_val) == 0)
2100  {
2101  if (strcmp (att_val, "primary") == 0)
2102  {
2104  }
2105  else if (strcmp (att_val, "secondary") == 0)
2106  {
2108  }
2109  else if (strcmp (att_val, "tertiary") == 0)
2110  {
2112  }
2113  else if (strcmp (att_val, "quaternary") == 0)
2114  {
2116  }
2117  else
2118  {
2119  assert (false);
2120  PRINT_DEBUG_START (data, attr, "Invalid value for before", -1);
2121  return -1;
2122  }
2123 
2125  }
2126 
2127  ld->last_r_buf_p = NULL;
2128  ld->last_r_buf_size = 0;
2129 
2130  PRINT_DEBUG_START (data, attr, "", 0);
2131  return 0;
2132 }
2133 
2134 /*
2135  * end_collation_reset() - XML element end function
2136  * "ldml collations collation rules reset"
2137  *
2138  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
2139  * data: user data
2140  * el_name: element name
2141  */
2142 static int
2143 end_collation_reset (void *data, const char *el_name)
2144 {
2145  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2146  LOCALE_DATA *ld = NULL;
2147 
2148  assert (data != NULL);
2149 
2150  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2151 
2153 
2155  {
2156  strcpy (ld->last_anchor_buf, ld->data_buffer);
2158  PRINT_DEBUG_END (data, "", 0);
2159  return 0;
2160  }
2161 
2163 
2164  PRINT_DEBUG_END (data, "Too much data", -1);
2165  return -1;
2166 }
2167 
2168 /*
2169  * start_collation_rule() - XML element start function
2170  * "ldml collations collation rules p"
2171  *
2172  * return: 0 validation OK enter this element , 1 validation NOK do not enter
2173  * -1 error abort parsing
2174  * data: user data
2175  * attr: attribute/value pair array
2176  */
2177 static int
2178 start_collation_rule (void *data, const char **attr)
2179 {
2180  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2181  LOCALE_DATA *ld = NULL;
2182  TAILOR_RULE *t_rule = NULL;
2183  int status;
2184 
2185  assert (data != NULL);
2186 
2187  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2188 
2189  t_rule = new_collation_rule (ld);
2190 
2191  if (t_rule == NULL)
2192  {
2194  PRINT_DEBUG_START (data, attr, "memory allocation failed", -1);
2195  return -1;
2196  }
2197 
2199  {
2200  /* nothing do to for logical position reference */
2201  assert (t_rule->r_buf == NULL);
2202  assert (t_rule->r_buf_size == 0);
2203 
2204  PRINT_DEBUG_START (data, attr, "", 0);
2205  return 0;
2206  }
2207 
2208  status = common_collation_start_rule (data, attr, ld, t_rule);
2209  if (status != 0)
2210  {
2211  return status;
2212  }
2213 
2214  PRINT_DEBUG_START (data, attr, "", 0);
2215  return 0;
2216 }
2217 
2218 /*
2219  * start_collation_cubrid_rule() - XML element start function
2220  * "ldml collations collation cubridrules set"
2221  *
2222  * return: 0 validation OK enter this element , 1 validation NOK do not enter
2223  * -1 error abort parsing
2224  * data: user data
2225  * attr: attribute/value pair array
2226  */
2227 static int
2228 start_collation_cubrid_rule (void *data, const char **attr)
2229 {
2230  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2231  LOCALE_DATA *ld = NULL;
2232  CUBRID_TAILOR_RULE *ct_rule = NULL;
2233 
2234  assert (data != NULL);
2235 
2236  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2237 
2238  ct_rule = new_collation_cubrid_rule (ld);
2239 
2240  if (ct_rule == NULL)
2241  {
2243  PRINT_DEBUG_START (data, attr, "OUT OF MEMORY", -1);
2244  return -1;
2245  }
2246 
2247  PRINT_DEBUG_START (data, attr, "", 0);
2248  clear_data_buffer (pd);
2249  return 0;
2250 }
2251 
2252 /*
2253  * start_collation_cubrid_rule_set_wr - XML element start function
2254  * "ldml collations collation cubridrules set wr"
2255  *
2256  * return: NO_ERROR if it's OK to enter this element,
2257  * ER_LOC_GEN if STEP attribute is a string exceeding the max size.
2258  * data(in/out): user data
2259  * attr(in): attribute/value pair array
2260  */
2261 static int
2262 start_collation_cubrid_rule_set_wr (void *data, const char **attr)
2263 {
2264  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2265  LOCALE_DATA *ld = NULL;
2266  char *att_val = NULL;
2267  CUBRID_TAILOR_RULE *ct_rule;
2268  COLL_TAILORING *curr_coll_tail = NULL;
2269  int rule_id;
2270  int err_status = NO_ERROR;
2271 
2272  assert (data != NULL);
2273 
2274  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2275 
2276  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2277 
2278  rule_id = curr_coll_tail->cub_count_rules;
2279  ct_rule = &(curr_coll_tail->cub_rules[rule_id]);
2280 
2281  if (xml_get_att_value (attr, "step", &att_val) == 0)
2282  {
2283  if (strlen (att_val) > MAX_STRLEN_FOR_COLLATION_ELEMENT)
2284  {
2285  err_status = ER_LOC_GEN;
2286  LOG_LOCALE_ERROR ("Data buffer too big in <wr> attribute STEP.", ER_LOC_GEN, true);
2287  goto exit;
2288  }
2289  strcpy (ct_rule->step, att_val);
2290  ct_rule->step[strlen (att_val)] = '\0';
2291  }
2292 
2293 exit:
2294  PRINT_DEBUG_START (data, attr, "", 0);
2295  return err_status;
2296 }
2297 
2298 /*
2299  * end_collation_cubrid_rule_set() - XML element end function
2300  * "ldml collations collation cubridrules ..."
2301  *
2302  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
2303  * data: user data
2304  * el_name: element name
2305  */
2306 static int
2307 end_collation_cubrid_rule_set (void *data, const char *el_name)
2308 {
2309  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2310  LOCALE_DATA *ld = NULL;
2311  COLL_TAILORING *curr_coll_tail = NULL;
2312  int rule_id;
2313 
2314  assert (data != NULL);
2315 
2316  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2317  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2318 
2319  rule_id = curr_coll_tail->cub_count_rules;
2320 
2321  /* rule finished, increase count */
2322  curr_coll_tail->cub_count_rules++;
2323 
2324  if (pd->verbose)
2325  {
2326  char msg[ERR_MSG_SIZE];
2327 
2328  snprintf (msg, sizeof (msg) - 1, " * SET Rule no. %d, tag name :%s *", (rule_id + 1), el_name);
2329  PRINT_DEBUG_END (data, msg, 0);
2330  }
2331 
2332  return 0;
2333 }
2334 
2335 /*
2336  * end_collation_cubrid_rule_set_end_cp_ch - XML element end function for
2337  * cp, ch, scp, sch
2338  * "ldml collations collation cubridrules ..."
2339  *
2340  * return: NO_ERROR(0) if parser OK,
2341  * ER_LOC_GEN if data buffer for codepoint is too big.
2342  * data(in/out): user data
2343  * el_name(in): element name
2344  */
2345 static int
2346 end_collation_cubrid_rule_set_cp_ch (void *data, const char *el_name)
2347 {
2348  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2349  LOCALE_DATA *ld = NULL;
2350  CUBRID_TAILOR_RULE *ct_rule = NULL;
2351  COLL_TAILORING *curr_coll_tail = NULL;
2352  int rule_id;
2353  int err_status = NO_ERROR;
2354 
2355  assert (data != NULL);
2356 
2357  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2358  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2359 
2360  rule_id = curr_coll_tail->cub_count_rules;
2361  ct_rule = &(curr_coll_tail->cub_rules[rule_id]);
2362 
2364  {
2365  err_status = ER_LOC_GEN;
2366  LOG_LOCALE_ERROR ("Data buffer too large in codepoint starting label.", ER_LOC_GEN, true);
2367  goto exit;
2368  }
2369 
2370  memcpy (ct_rule->start_cp_buf, ld->data_buffer, ld->data_buf_count * sizeof (char));
2371  ct_rule->start_cp_buf[ld->data_buf_count] = '\0';
2372 
2373  memcpy (ct_rule->end_cp_buf, ld->data_buffer, ld->data_buf_count * sizeof (char));
2374  ct_rule->end_cp_buf[ld->data_buf_count] = '\0';
2375 
2376  if (strcmp (el_name, "ch") == 0 || strcmp (el_name, "sch") == 0)
2377  {
2378  ct_rule->start_cp_buf_type = BUF_TYPE_CHAR;
2379  ct_rule->end_cp_buf_type = BUF_TYPE_CHAR;
2380  }
2381  else if (strcmp (el_name, "cp") == 0 || strcmp (el_name, "scp") == 0)
2382  {
2383  ct_rule->start_cp_buf_type = BUF_TYPE_CODE;
2384  ct_rule->end_cp_buf_type = BUF_TYPE_CODE;
2385  }
2386 
2387  if (pd->verbose)
2388  {
2389  char msg[ERR_MSG_SIZE];
2390 
2391  snprintf (msg, sizeof (msg) - 1, " * SET Rule no. %d, tag name :%s *", (rule_id + 1), el_name);
2392  PRINT_DEBUG_END (data, msg, 0);
2393  }
2394 
2395 exit:
2396  clear_data_buffer (pd);
2397  return err_status;
2398 }
2399 
2400 /*
2401  * end_collation_cubrid_rule_set_end_ecp - XML element end function
2402  * for ech/ecp.
2403  * "ldml collations collation cubridrules ..."
2404  *
2405  * return: NO_ERROR if parser OK
2406  * ER_LOC_GEN if buffer data too big
2407  * data(in/out): user data
2408  * el_name(in): element name
2409  */
2410 static int
2411 end_collation_cubrid_rule_set_ech_ecp (void *data, const char *el_name)
2412 {
2413  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2414  LOCALE_DATA *ld = NULL;
2415  CUBRID_TAILOR_RULE *ct_rule = NULL;
2416  COLL_TAILORING *curr_coll_tail = NULL;
2417  int rule_id;
2418  int err_status = NO_ERROR;
2419 
2420  assert (data != NULL);
2421 
2422  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2423  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2424 
2426  {
2427  err_status = ER_LOC_GEN;
2428  LOG_LOCALE_ERROR ("Data buffer too large in codepoint end label.", ER_LOC_GEN, true);
2429  goto exit;
2430  }
2431  rule_id = curr_coll_tail->cub_count_rules;
2432  ct_rule = &(curr_coll_tail->cub_rules[rule_id]);
2433 
2434  memcpy (ct_rule->end_cp_buf, ld->data_buffer, ld->data_buf_count * sizeof (char));
2435  ct_rule->end_cp_buf[ld->data_buf_count] = '\0';
2436 
2437  if (strcmp (el_name, "ech") == 0)
2438  {
2439  ct_rule->end_cp_buf_type = BUF_TYPE_CHAR;
2440  }
2441  else if (strcmp (el_name, "ecp") == 0)
2442  {
2443  ct_rule->end_cp_buf_type = BUF_TYPE_CODE;
2444  }
2445 
2446  if (pd->verbose)
2447  {
2448  char msg[ERR_MSG_SIZE];
2449 
2450  snprintf (msg, sizeof (msg) - 1, "* SET Rule no. %d, tag name :%s *", (rule_id + 1), el_name);
2451  PRINT_DEBUG_END (data, msg, 0);
2452  }
2453 
2454 exit:
2455  clear_data_buffer (pd);
2456  return err_status;
2457 }
2458 
2459 /*
2460  * end_collation_cubrid_rule_set_w_wr() - XML element end function for w / wr.
2461  * "ldml collations collation cubridrules ..."
2462  *
2463  * return: NO_ERROR if parser OK,
2464  * ER_LOC_GEN if parser NOK and stop parsing.
2465  * data(in/out): user data
2466  * el_name(in): element name
2467  */
2468 static int
2469 end_collation_cubrid_rule_set_w_wr (void *data, const char *el_name)
2470 {
2471  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2472  LOCALE_DATA *ld = NULL;
2473  CUBRID_TAILOR_RULE *ct_rule = NULL;
2474  COLL_TAILORING *curr_coll_tail = NULL;
2475  int rule_id;
2476  int err_status = NO_ERROR;
2477 
2478  assert (data != NULL);
2479 
2480  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2481  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2482 
2483  rule_id = curr_coll_tail->cub_count_rules;
2484  ct_rule = &(curr_coll_tail->cub_rules[rule_id]);
2485 
2487  {
2488  err_status = ER_LOC_GEN;
2489  LOG_LOCALE_ERROR ("Data buffer too large in weight label.", ER_LOC_GEN, true);
2490  goto exit;
2491  }
2492 
2493  memcpy (ct_rule->start_weight, ld->data_buffer, ld->data_buf_count * sizeof (char));
2494  ct_rule->start_weight[ld->data_buf_count] = '\0';
2495 
2496  if (pd->verbose)
2497  {
2498  char msg[ERR_MSG_SIZE];
2499 
2500  snprintf (msg, sizeof (msg) - 1, "* SET Rule no. %d, tag name :%s *", (rule_id + 1), el_name);
2501  PRINT_DEBUG_END (data, msg, 0);
2502  }
2503 
2504 exit:
2505  clear_data_buffer (pd);
2506  return err_status;
2507 }
2508 
2509 /*
2510  * handle_data_collation_rule() - XML element data content handle function
2511  * "ldml collations collation rules p"
2512  *
2513  * return: 0 handling OK, non-zero if handling NOK and stop parsing
2514  * (data): user data
2515  * (s): content buffer
2516  * (len): length of buffer
2517  */
2518 static int
2519 handle_data_collation_rule (void *data, const char *s, int len)
2520 {
2521  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2522  LOCALE_DATA *ld = NULL;
2523  TAILOR_RULE *t_rule = NULL;
2524  COLL_TAILORING *curr_coll_tail = NULL;
2525 
2526  assert (data != NULL);
2527 
2528  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2529  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2530 
2531  assert (len >= 0);
2532 
2533  t_rule = &(curr_coll_tail->rules[curr_coll_tail->count_rules]);
2534  char *const realloc_t_buf = (char *) realloc (t_rule->t_buf, t_rule->t_buf_size + len);
2535  if (realloc_t_buf == NULL)
2536  {
2538  PRINT_DEBUG_DATA (data, "memory allocation failed", -1);
2539  return -1;
2540  }
2541  else
2542  {
2543  t_rule->t_buf = realloc_t_buf;
2544  }
2545 
2546  /* copy partial data to data buffer */
2547  memcpy (t_rule->t_buf + t_rule->t_buf_size, s, len);
2548  t_rule->t_buf_size += len;
2549 
2550  if (pd->verbose)
2551  {
2552  char msg[ERR_MSG_SIZE];
2553 
2554  if (len < 32 && len < ERR_MSG_SIZE)
2555  {
2556  memcpy (msg, s, len);
2557  msg[len] = '\0';
2558  }
2559  else
2560  {
2561  char msg2[33];
2562 
2563  memcpy (msg2, s, 32);
2564  msg2[32] = '\0';
2565  snprintf (msg, sizeof (msg) - 1, "%s | %d bytes", msg2, len);
2566  }
2567  PRINT_DEBUG_DATA (data, msg, 0);
2568  }
2569 
2570  return 0;
2571 }
2572 
2573 /*
2574  * end_collation_rule() - XML element end function
2575  * "ldml collations collation rules p"
2576  *
2577  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
2578  * data: user data
2579  * el_name: element name
2580  */
2581 static int
2582 end_collation_rule (void *data, const char *el_name)
2583 {
2584  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2585  LOCALE_DATA *ld = NULL;
2586  TAILOR_RULE *t_rule = NULL;
2587  COLL_TAILORING *curr_coll_tail = NULL;
2588  int rule_id;
2589  int status;
2590 
2591  assert (data != NULL);
2592 
2593  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2594  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2595 
2596  /* rule finished, increase count */
2597  rule_id = curr_coll_tail->count_rules++;
2598  t_rule = &(curr_coll_tail->rules[rule_id]);
2599 
2600  if (strcmp (el_name, "p") == 0)
2601  {
2602  t_rule->level = TAILOR_PRIMARY;
2603  }
2604  else if (strcmp (el_name, "s") == 0)
2605  {
2606  t_rule->level = TAILOR_SECONDARY;
2607  }
2608  else if (strcmp (el_name, "t") == 0)
2609  {
2610  t_rule->level = TAILOR_TERTIARY;
2611  }
2612  else if (strcmp (el_name, "i") == 0)
2613  {
2614  t_rule->level = TAILOR_IDENTITY;
2615  }
2616  else if (strcmp (el_name, "pc") == 0)
2617  {
2618  t_rule->level = TAILOR_PRIMARY;
2619  t_rule->multiple_chars = true;
2620  }
2621  else if (strcmp (el_name, "sc") == 0)
2622  {
2623  t_rule->level = TAILOR_SECONDARY;
2624  t_rule->multiple_chars = true;
2625  }
2626  else if (strcmp (el_name, "tc") == 0)
2627  {
2628  t_rule->level = TAILOR_TERTIARY;
2629  t_rule->multiple_chars = true;
2630  }
2631  else if (strcmp (el_name, "ic") == 0)
2632  {
2633  t_rule->level = TAILOR_IDENTITY;
2634  t_rule->multiple_chars = true;
2635  }
2636  else
2637  {
2638  assert (false);
2640  PRINT_DEBUG_END (data, "Invalid element name", -1);
2641  return -1;
2642  }
2643 
2644  status = common_collation_end_rule (data, ld, rule_id, t_rule);
2645  if (status != 0)
2646  {
2647  return status;
2648  }
2649 
2650  return 0;
2651 }
2652 
2653 /*
2654  * start_collation_x() - XML element start function
2655  * "ldml collations collation rules x"
2656  *
2657  * return: 0 validation OK enter this element , 1 validation NOK do not enter
2658  * -1 error abort parsing
2659  * data: user data
2660  * attr: attribute/value pair array
2661  */
2662 static int
2663 start_collation_x (void *data, const char **attr)
2664 {
2665  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2666  LOCALE_DATA *ld = NULL;
2667  TAILOR_RULE *t_rule = NULL;
2668  int status;
2669 
2670  assert (data != NULL);
2671 
2672  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2673 
2674  t_rule = new_collation_rule (ld);
2675 
2676  if (t_rule == NULL)
2677  {
2679  PRINT_DEBUG_START (data, attr, "memory allocation failed", -1);
2680  return -1;
2681  }
2682 
2684  {
2686  PRINT_DEBUG_START (data, attr, "Last <reset> tag is invalid", -1);
2687  return -1;
2688  }
2689 
2690  status = common_collation_start_rule (data, attr, ld, t_rule);
2691  if (status != 0)
2692  {
2693  return status;
2694  }
2695 
2696  PRINT_DEBUG_START (data, attr, "", 0);
2697  return 0;
2698 }
2699 
2700 /*
2701  * end_collation_x - XML element end function
2702  * "ldml collations collation rules x"
2703  *
2704  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
2705  * data: user data
2706  * el_name: element name
2707  */
2708 static int
2709 end_collation_x (void *data, const char *el_name)
2710 {
2711  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2712  LOCALE_DATA *ld = NULL;
2713  TAILOR_RULE *t_rule = NULL;
2714  COLL_TAILORING *curr_coll_tail = NULL;
2715  int rule_id;
2716 
2717  assert (data != NULL);
2718 
2719  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2720  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2721 
2722  /* rule finished, increase count */
2723  rule_id = curr_coll_tail->count_rules++;
2724  t_rule = &(curr_coll_tail->rules[rule_id]);
2725  /* BEFORE applies only for the first rule after <reset> */
2727 
2728  if (pd->verbose)
2729  {
2730  char msg[ERR_MSG_SIZE];
2731 
2732  snprintf (msg, sizeof (msg) - 1, " * X_Rule %d, L :%d, Dir:%d, PosType:%d, Mc:%d *", rule_id, t_rule->level,
2733  t_rule->direction, t_rule->r_pos_type, t_rule->multiple_chars);
2734  PRINT_DEBUG_END (data, msg, 0);
2735  }
2736 
2737  return 0;
2738 }
2739 
2740 /*
2741  * end_collation_x_rule - XML element end function
2742  * "ldml collations collation rules x p"
2743  *
2744  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
2745  * data: user data
2746  * el_name: element name
2747  */
2748 static int
2749 end_collation_x_rule (void *data, const char *el_name)
2750 {
2751  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2752  LOCALE_DATA *ld = NULL;
2753  TAILOR_RULE *t_rule = NULL;
2754  COLL_TAILORING *curr_coll_tail = NULL;
2755  int rule_id;
2756  int status;
2757 
2758  assert (data != NULL);
2759 
2760  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2761  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2762 
2763  rule_id = curr_coll_tail->count_rules;
2764  t_rule = &(curr_coll_tail->rules[rule_id]);
2765 
2766  assert (strlen (ld->data_buffer) == ld->data_buf_count);
2767 
2768  char *const realloc_t_buf = (char *) realloc (t_rule->t_buf, t_rule->t_buf_size + ld->data_buf_count);
2769  if (realloc_t_buf == NULL)
2770  {
2772  PRINT_DEBUG_END (data, "memory allocation failed", -1);
2773  return -1;
2774  }
2775  else
2776  {
2777  t_rule->t_buf = realloc_t_buf;
2778  }
2779 
2780  /* copy partial data to rule tailoring buffer (character to be modified) */
2781  memcpy (t_rule->t_buf + t_rule->t_buf_size, ld->data_buffer, ld->data_buf_count);
2782  t_rule->t_buf_size += ld->data_buf_count;
2783 
2784  if (strcmp (el_name, "p") == 0)
2785  {
2786  t_rule->level = TAILOR_PRIMARY;
2787  }
2788  else if (strcmp (el_name, "s") == 0)
2789  {
2790  t_rule->level = TAILOR_SECONDARY;
2791  }
2792  else if (strcmp (el_name, "t") == 0)
2793  {
2794  t_rule->level = TAILOR_TERTIARY;
2795  }
2796  else if (strcmp (el_name, "i") == 0)
2797  {
2798  t_rule->level = TAILOR_IDENTITY;
2799  }
2800  else
2801  {
2802  assert (false);
2804  PRINT_DEBUG_END (data, "Invalid element name", -1);
2805  return -1;
2806  }
2807 
2808  status = common_collation_end_rule (data, ld, rule_id, t_rule);
2809  if (status != 0)
2810  {
2811  return status;
2812  }
2813 
2815 
2816  return 0;
2817 }
2818 
2819 /*
2820  * end_collation_x_extend - XML element end function
2821  * "ldml collations collation rules x extend"
2822  *
2823  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
2824  * data: user data
2825  * el_name: element name
2826  */
2827 static int
2828 end_collation_x_extend (void *data, const char *el_name)
2829 {
2830  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2831  LOCALE_DATA *ld = NULL;
2832  TAILOR_RULE *t_rule = NULL;
2833  COLL_TAILORING *curr_coll_tail = NULL;
2834  int rule_id;
2835 
2836  assert (data != NULL);
2837 
2838  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2839  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2840 
2841  rule_id = curr_coll_tail->count_rules;
2842  t_rule = &(curr_coll_tail->rules[rule_id]);
2843 
2844  assert (t_rule->r_buf != NULL);
2845  assert (ld->data_buf_count > 0);
2846 
2847  char *const realloc_r_buf = (char *) realloc (t_rule->r_buf, t_rule->r_buf_size + ld->data_buf_count);
2848  if (realloc_r_buf == NULL)
2849  {
2851  PRINT_DEBUG_END (data, "memory allocation failed", -1);
2852  return -1;
2853  }
2854  else
2855  {
2856  t_rule->r_buf = realloc_r_buf;
2857  }
2858 
2859  memcpy (t_rule->r_buf + t_rule->r_buf_size, ld->data_buffer, ld->data_buf_count);
2860 
2861  t_rule->r_buf_size += ld->data_buf_count;
2862 
2864 
2865  PRINT_DEBUG_END (data, "", 0);
2866 
2867  return 0;
2868 }
2869 
2870 /*
2871  * end_collation_x_context - XML element end function
2872  * "ldml collations collation rules x context"
2873  *
2874  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
2875  * data: user data
2876  * el_name: element name
2877  */
2878 static int
2879 end_collation_x_context (void *data, const char *el_name)
2880 {
2881  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2882  LOCALE_DATA *ld = NULL;
2883  TAILOR_RULE *t_rule = NULL;
2884  COLL_TAILORING *curr_coll_tail = NULL;
2885  int rule_id;
2886 
2887  assert (data != NULL);
2888 
2889  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2890  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
2891 
2892  rule_id = curr_coll_tail->count_rules;
2893  t_rule = &(curr_coll_tail->rules[rule_id]);
2894 
2897  {
2899  PRINT_DEBUG_END (data, "Too much data", -1);
2900  return -1;
2901  }
2902 
2903  if (t_rule->t_buf_size < ld->data_buf_count)
2904  {
2905  char *const realloc_t_buf = (char *) realloc (t_rule->t_buf, ld->data_buf_count);
2906  if (realloc_t_buf == NULL)
2907  {
2909  PRINT_DEBUG_END (data, "memory allocation failed", -1);
2910  return -1;
2911  }
2912  else
2913  {
2914  t_rule->t_buf = realloc_t_buf;
2915  }
2916  }
2917 
2918  memcpy (t_rule->t_buf, ld->data_buffer, ld->data_buf_count);
2919  t_rule->t_buf_size = ld->data_buf_count;
2920 
2922  if (pd->verbose)
2923  {
2924  char msg[ERR_MSG_SIZE];
2925  int rule_id = curr_coll_tail->count_rules;
2926 
2927  snprintf (msg, sizeof (msg) - 1, "* Rule %d *", rule_id);
2928  PRINT_DEBUG_END (data, msg, 0);
2929  }
2930  else
2931  {
2932  PRINT_DEBUG_END (data, "", 0);
2933  }
2934 
2935  return 0;
2936 }
2937 
2938 /*
2939  * start_collation_logical_pos() - XML element start function
2940  * "ldml collations collation rules reset first_variable"
2941  *
2942  * return: 0 validation OK enter this element , 1 validation NOK do not enter
2943  * -1 error abort parsing
2944  * data: user data
2945  * attr: attribute/value pair array
2946  */
2947 static int
2948 start_collation_logical_pos (void *data, const char **attr)
2949 {
2950  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2951  LOCALE_DATA *ld = NULL;
2952 
2953  assert (data != NULL);
2954 
2955  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2956 
2957  PRINT_DEBUG_START (data, attr, "", 0);
2958  return 0;
2959 }
2960 
2961 /*
2962  * end_collation_logical_pos() - XML element end function
2963  * "ldml collations collation rules reset first_variable"
2964  *
2965  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
2966  * data: user data
2967  * el_name: element name
2968  */
2969 static int
2970 end_collation_logical_pos (void *data, const char *el_name)
2971 {
2972  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
2973  LOCALE_DATA *ld = NULL;
2974 
2975  assert (data != NULL);
2976 
2977  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
2978 
2979  if (strcmp (el_name, "first_variable") == 0)
2980  {
2982  }
2983  else if (strcmp (el_name, "last_variable") == 0)
2984  {
2986  }
2987  else if (strcmp (el_name, "first_primary_ignorable") == 0)
2988  {
2990  }
2991  else if (strcmp (el_name, "last_primary_ignorable") == 0)
2992  {
2994  }
2995  else if (strcmp (el_name, "first_secondary_ignorable") == 0)
2996  {
2998  }
2999  else if (strcmp (el_name, "last_secondary_ignorable") == 0)
3000  {
3002  }
3003  else if (strcmp (el_name, "first_tertiary_ignorable") == 0)
3004  {
3006  }
3007  else if (strcmp (el_name, "last_tertiary_ignorable") == 0)
3008  {
3010  }
3011  else if (strcmp (el_name, "first_non_ignorable") == 0)
3012  {
3014  }
3015  else if (strcmp (el_name, "last_non_ignorable") == 0)
3016  {
3018  }
3019  else if (strcmp (el_name, "first_trailing") == 0)
3020  {
3022  }
3023  else if (strcmp (el_name, "last_trailing") == 0)
3024  {
3026  }
3027  else
3028  {
3029  assert (false);
3031  PRINT_DEBUG_END (data, "Internal LDML parser error", -1);
3032  return -1;
3033  }
3034 
3035  PRINT_DEBUG_END (data, "", 0);
3036 
3037  return 0;
3038 }
3039 
3040 /* Alphabet XML elements handling */
3041 /*
3042  * start_one_alphabet() - XML element start function
3043  * "ldml alphabets alphabet"
3044  *
3045  * return: 0 validation OK enter this element , 1 validation NOK do not enter
3046  * -1 error abort parsing
3047  * data: user data
3048  * attr: attribute/value pair array
3049  */
3050 static int
3051 start_one_alphabet (void *data, const char **attr)
3052 {
3053  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3054  LOCALE_DATA *ld = NULL;
3055  char *att_val = NULL;
3056 
3057  assert (data != NULL);
3058 
3059  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
3060 
3061  if (ld->alpha_tailoring.alphabet_mode != 0 || ld->alpha_tailoring.count_rules != 0
3062  || ld->alpha_tailoring.sett_max_letters != -1)
3063  {
3064  PRINT_DEBUG_START (data, attr, "Only one alphabet is allowed", -1);
3065  return -1;
3066  }
3067 
3068  att_val = NULL;
3069  if (xml_get_att_value (attr, "CUBRIDMaxLetters", &att_val) == 0)
3070  {
3071  assert (att_val != NULL);
3072  ld->alpha_tailoring.sett_max_letters = atoi (att_val);
3073  }
3074 
3075  att_val = NULL;
3076  if (xml_get_att_value (attr, "CUBRIDAlphabetMode", &att_val) == 0)
3077  {
3078  assert (att_val != NULL);
3079  if (strcasecmp (att_val, "ASCII") == 0)
3080  {
3082  }
3083  else if (strcasecmp (att_val, "UNICODEDATAFILE") == 0)
3084  {
3086  }
3087  else
3088  {
3089  PRINT_DEBUG_START (data, attr, "Invalid value for CUBRIDAlphabetMode." "Expected ASCII or UNICODEDATAFILE",
3090  -1);
3091  return -1;
3092  }
3093  }
3094 
3096  ld->alpha_tailoring.ldml_context.line_no = XML_GetCurrentLineNumber (pd->xml_parser);
3097 
3098  PRINT_DEBUG_START (data, attr, "", 0);
3099  return 0;
3100 }
3101 
3102 /*
3103  * start_upper_case_rule() - XML element start function
3104  * "ldml alphabets alphabet u"
3105  *
3106  * return: 0 validation OK enter this element , 1 validation NOK do not enter
3107  * -1 error abort parsing
3108  * data: user data
3109  * attr: attribute/value pair array
3110  */
3111 static int
3112 start_upper_case_rule (void *data, const char **attr)
3113 {
3114  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3115  LOCALE_DATA *ld = NULL;
3116  TRANSFORM_RULE *tf_rule = NULL;
3117 
3118  assert (data != NULL);
3119 
3120  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
3121 
3122  tf_rule = new_transform_rule (ld);
3123 
3124  if (tf_rule == NULL)
3125  {
3127  PRINT_DEBUG_START (data, attr, "OUT OF MEMORY", -1);
3128  return -1;
3129  }
3130 
3131  tf_rule->type = TR_UPPER;
3132 
3133  PRINT_DEBUG_START (data, attr, "", 0);
3134  return 0;
3135 }
3136 
3137 /*
3138  * end_case_rule() - XML element end function
3139  * "ldml alphabets alphabet u"
3140  *
3141  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
3142  * data: user data
3143  * el_name: element name
3144  */
3145 static int
3146 end_case_rule (void *data, const char *el_name)
3147 {
3148  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3149  LOCALE_DATA *ld = NULL;
3150  TRANSFORM_RULE *tf_rule = NULL;
3151  int rule_id;
3152 
3153  assert (data != NULL);
3154 
3155  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
3156 
3157  /* rule finished, increase count */
3158  rule_id = ld->alpha_tailoring.count_rules++;
3159  tf_rule = &(ld->alpha_tailoring.rules[rule_id]);
3160 
3161  if (pd->verbose)
3162  {
3163  char msg[64];
3164  unsigned char *dummy = NULL;
3165  unsigned int cp_src = intl_utf8_to_cp ((unsigned char *) tf_rule->src, tf_rule->src_size,
3166  &dummy);
3167  unsigned int cp_dest = intl_utf8_to_cp ((unsigned char *) tf_rule->dest, tf_rule->dest_size,
3168  &dummy);
3169 
3170  sprintf (msg, " * Case Rule %d, Src :%0X, Dest:%0X *", rule_id, cp_src, cp_dest);
3171  PRINT_DEBUG_END (data, msg, 0);
3172  }
3173  else
3174  {
3175  PRINT_DEBUG_END (data, "", 0);
3176  }
3177 
3178  return 0;
3179 }
3180 
3181 /*
3182  * start_lower_case_rule() - XML element start function
3183  * "ldml alphabets alphabet l"
3184  *
3185  * return: 0 validation OK enter this element , 1 validation NOK do not enter
3186  * -1 error abort parsing
3187  * data: user data
3188  * attr: attribute/value pair array
3189  */
3190 static int
3191 start_lower_case_rule (void *data, const char **attr)
3192 {
3193  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3194  LOCALE_DATA *ld = NULL;
3195  TRANSFORM_RULE *tf_rule = NULL;
3196 
3197  assert (data != NULL);
3198 
3199  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
3200 
3201  tf_rule = new_transform_rule (ld);
3202 
3203  if (tf_rule == NULL)
3204  {
3206  PRINT_DEBUG_START (data, attr, "OUT OF MEMORY", -1);
3207  return -1;
3208  }
3209 
3210  tf_rule->type = TR_LOWER;
3211 
3212  PRINT_DEBUG_START (data, attr, "", 0);
3213  return 0;
3214 }
3215 
3216 /*
3217  * end_transform_buffer() - XML element end function
3218  * "ldml alphabets alphabet u s"
3219  *
3220  * return: 0 parser OK, non-zero value if parser NOK and stop parsing
3221  * data: user data
3222  * el_name: element name
3223  */
3224 static int
3225 end_transform_buffer (void *data, const char *el_name)
3226 {
3227  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3228  LOCALE_DATA *ld = NULL;
3229  TRANSFORM_RULE *tf_rule = NULL;
3230  char *tf_buf = NULL;
3231 
3232  assert (data != NULL);
3233 
3234  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
3235 
3237  tf_rule = &(ld->alpha_tailoring.rules[ld->alpha_tailoring.count_rules]);
3238 
3239  if (ld->data_buf_count <= 0)
3240  {
3241  PRINT_DEBUG_END (data, "Expecting non-empty string", -1);
3243  goto error_exit;
3244  }
3245 
3246  tf_buf = (char *) malloc (ld->data_buf_count);
3247  if (tf_buf == NULL)
3248  {
3250  PRINT_DEBUG_END (data, "memory allocation failed", -1);
3251  goto error_exit;
3252  }
3253 
3254  memcpy (tf_buf, ld->data_buffer, ld->data_buf_count);
3255 
3256  assert (tf_rule->type == TR_LOWER || tf_rule->type == TR_UPPER);
3257 
3258  if (strcmp (el_name, "s") == 0)
3259  {
3260  if (tf_rule->src != NULL || tf_rule->src_size != 0)
3261  {
3262  PRINT_DEBUG_END (data, "duplicate source for case rule", -1);
3264  goto error_exit;
3265  }
3266 
3267  tf_rule->src = tf_buf;
3268  tf_rule->src_size = ld->data_buf_count;
3269  }
3270  else if (strcmp (el_name, "d") == 0)
3271  {
3272  if (tf_rule->dest != NULL || tf_rule->dest_size != 0)
3273  {
3274  PRINT_DEBUG_END (data, "duplicate destination for case rule", -1);
3276  goto error_exit;
3277  }
3278 
3279  tf_rule->dest = tf_buf;
3280  tf_rule->dest_size = ld->data_buf_count;
3281  }
3282  else
3283  {
3284  assert (false);
3285  PRINT_DEBUG_END (data, "Internal LDML parser error", -1);
3287  goto error_exit;
3288  }
3289 
3290  PRINT_DEBUG_END (data, "", 0);
3291 
3293 
3294  return 0;
3295 
3296 error_exit:
3297 
3299 
3300  return -1;
3301 }
3302 
3303 /*
3304  * start_consoleconversion() - XML element start function
3305  * "ldml consoleconversion"
3306  *
3307  * return: 0 validation OK enter this element , 1 validation NOK do not enter
3308  * -1 error abort parsing
3309  * data: user data
3310  * attr: attribute/value pair array
3311  */
3312 static int
3313 start_consoleconversion (void *data, const char **attr)
3314 {
3315  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3316  LOCALE_DATA *ld = NULL;
3317  char *att_val = NULL;
3318 
3319  assert (data != NULL);
3320 
3321  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
3322 
3323  if (*(ld->txt_conv_prm.nl_lang_str) != '\0' || *(ld->txt_conv_prm.conv_file) != '\0'
3324  || *(ld->txt_conv_prm.win_codepages) != '\0')
3325  {
3326  PRINT_DEBUG_START (data, attr, "Only one console conversion is allowed", -1);
3327  return -1;
3328  }
3329 
3330  att_val = NULL;
3331  if (xml_get_att_value (attr, "type", &att_val) == 0)
3332  {
3333  assert (att_val != NULL);
3334  if (strcasecmp (att_val, "ISO") == 0)
3335  {
3337  }
3338  else if (strcasecmp (att_val, "DBCS") == 0)
3339  {
3341  }
3342  else if (strcasecmp (att_val, "ISO88591") == 0)
3343  {
3345  }
3346  else if (strcasecmp (att_val, "ISO88599") == 0)
3347  {
3349  }
3350  else
3351  {
3352  PRINT_DEBUG_START (data, attr, "Invalid value for type." "Expecting ISO88591 or ISO or EUC", -1);
3353  return -1;
3354  }
3355  }
3356 
3357  att_val = NULL;
3358  if (xml_get_att_value (attr, "windows_codepage", &att_val) == 0)
3359  {
3360  assert (att_val != NULL);
3361 
3362  if (strlen (att_val) > (int) sizeof (ld->txt_conv_prm.win_codepages) - 1)
3363  {
3364  PRINT_DEBUG_START (data, attr, "Invalid attribute value", -1);
3365  return -1;
3366  }
3367 
3368  strcpy (ld->txt_conv_prm.win_codepages, att_val);
3369  }
3370 
3371  att_val = NULL;
3372  if (xml_get_att_value (attr, "linux_charset", &att_val) == 0)
3373  {
3374  assert (att_val != NULL);
3375 
3376  if (strlen (att_val) > (int) sizeof (ld->txt_conv_prm.nl_lang_str) - 1)
3377  {
3378  PRINT_DEBUG_START (data, attr, "Invalid attribute value", -1);
3379  return -1;
3380  }
3381 
3382  strcpy (ld->txt_conv_prm.nl_lang_str, att_val);
3383  }
3384 
3385  att_val = NULL;
3386  if (xml_get_att_value (attr, "file", &att_val) == 0)
3387  {
3388  assert (att_val != NULL);
3389 
3390  if (strlen (att_val) > (int) sizeof (ld->txt_conv_prm.conv_file) - 1)
3391  {
3392  PRINT_DEBUG_START (data, attr, "Invalid attribute value", -1);
3393  return -1;
3394  }
3395 
3396  strcpy (ld->txt_conv_prm.conv_file, att_val);
3397  }
3398 
3399  PRINT_DEBUG_START (data, attr, "", 0);
3400  return 0;
3401 }
3402 
3403 /* General LDML handling functions */
3404 /*
3405  * handle_data() - XML element data content handle function
3406  * generic data handling function
3407  *
3408  * return: 0 handling OK, non-zero if handling NOK and stop parsing
3409  * (data): user data
3410  * (s): content buffer
3411  * (len): length of buffer
3412  */
3413 static int
3414 handle_data (void *data, const char *s, int len)
3415 {
3416  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3417  LOCALE_DATA *ld = NULL;
3418  char msg[64];
3419 
3420  assert (data != NULL);
3421 
3422  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
3423 
3424  assert (len >= 0);
3425 
3426  if (ld->data_buf_count + len >= LOC_DATA_BUFF_SIZE)
3427  {
3429  sprintf (msg, "Too much data : %d + %d bytes", ld->data_buf_count, len);
3430  PRINT_DEBUG_DATA (data, msg, -1);
3431  return -1;
3432  }
3433 
3434  /* copy partial data to data buffer */
3435  memcpy (ld->data_buffer + ld->data_buf_count, s, len);
3436  ld->data_buf_count += len;
3437  ld->data_buffer[ld->data_buf_count] = '\0';
3438 
3439  if (pd->verbose)
3440  {
3441  char msg[64];
3442 
3443  if (len < 64)
3444  {
3445  memcpy (msg, s, len);
3446  msg[len] = '\0';
3447  }
3448  else
3449  {
3450  char msg2[33];
3451 
3452  memcpy (msg2, s, 32);
3453  msg2[32] = '\0';
3454  sprintf (msg, "%s | %d bytes", msg2, len);
3455  }
3456  PRINT_DEBUG_DATA (data, msg, 0);
3457  }
3458 
3459  return 0;
3460 }
3461 
3462 /*
3463  * clear_data_buffer() - clears the data content buffer
3464  *
3465  * return:
3466  * pd(in): parser data
3467  */
3468 static void
3470 {
3471  LOCALE_DATA *ld = NULL;
3472 
3473  assert (pd != NULL);
3474 
3475  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
3476 
3477  ld->data_buf_count = 0;
3478  *(ld->data_buffer) = '\0';
3479 }
3480 
3481 /*
3482  * new_locale_collation() - creates new collation in the locale struct
3483  *
3484  * return: rule
3485  * ld(in): locale data
3486  */
3487 static LOCALE_COLLATION *
3489 {
3490  LOCALE_COLLATION *loc_collation = NULL;
3491 
3492  assert (ld != NULL);
3493 
3494  /* check number of rules, increase array if necessary */
3495  LOCALE_COLLATION *const realloc_collations
3496  = (LOCALE_COLLATION *) realloc (ld->collations, sizeof (LOCALE_COLLATION) * (ld->coll_cnt + 1));
3497  if (realloc_collations == NULL)
3498  {
3499  return NULL;
3500  }
3501  else
3502  {
3503  ld->collations = realloc_collations;
3504  }
3505 
3506  loc_collation = &(ld->collations[ld->coll_cnt]);
3507  memset (loc_collation, 0, sizeof (LOCALE_COLLATION));
3508 
3509  loc_collation->tail_coll.sett_max_cp = -1;
3511 
3512  return loc_collation;
3513 }
3514 
3515 /*
3516  * new_collation_rule() - creates new collation tailoring rule
3517  *
3518  * return: rule
3519  * ld(in): locale data
3520  */
3521 static TAILOR_RULE *
3523 {
3524  TAILOR_RULE *t_rule = NULL;
3525  COLL_TAILORING *curr_coll_tail = NULL;
3526 
3527  assert (ld != NULL);
3528 
3529  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
3530 
3531  /* check number of rules, increase array if necessary */
3532  if (curr_coll_tail->count_rules + 1 >= curr_coll_tail->max_rules)
3533  {
3534  TAILOR_RULE *const realloc_rules = (TAILOR_RULE *) realloc (curr_coll_tail->rules,
3535  sizeof (TAILOR_RULE) * (curr_coll_tail->max_rules +
3537  if (realloc_rules == NULL)
3538  {
3539  return NULL;
3540  }
3541  else
3542  {
3543  curr_coll_tail->rules = realloc_rules;
3544  }
3545 
3546  curr_coll_tail->max_rules += LOC_DATA_TAILOR_RULES_COUNT_GROW;
3547  }
3548 
3549  /* will use slot indicated by 'coll->count_rules' */
3550  t_rule = &(curr_coll_tail->rules[curr_coll_tail->count_rules]);
3551  memset (t_rule, 0, sizeof (TAILOR_RULE));
3552 
3553  return t_rule;
3554 }
3555 
3556 /*
3557  * new_transform_rule() - creates new transform rule
3558  *
3559  * return: rule
3560  * ld(in): locale data
3561  */
3562 static TRANSFORM_RULE *
3564 {
3565  TRANSFORM_RULE *tf_rule = NULL;
3566 
3567  assert (ld != NULL);
3568 
3569  /* check number of rules, increase array if necessary */
3571  {
3572  TRANSFORM_RULE *const realloc_alpha_tailoring_rules = (TRANSFORM_RULE *) realloc (ld->alpha_tailoring.rules,
3573  sizeof (TRANSFORM_RULE) *
3574  (ld->alpha_tailoring.max_rules +
3576  if (realloc_alpha_tailoring_rules == NULL)
3577  {
3578  return NULL;
3579  }
3580  else
3581  {
3582  ld->alpha_tailoring.rules = realloc_alpha_tailoring_rules;
3583  }
3584 
3586  }
3587 
3588  /* will use slot indicated by 'alpha_tailoring->count_rules' */
3589  tf_rule = &(ld->alpha_tailoring.rules[ld->alpha_tailoring.count_rules]);
3590  memset (tf_rule, 0, sizeof (TRANSFORM_RULE));
3591 
3592  return tf_rule;
3593 }
3594 
3595 /*
3596  * new_collation_cubrid_rule - creates new collation tailoring rule
3597  *
3598  * return: rule
3599  * ld(in): locale data
3600  */
3601 static CUBRID_TAILOR_RULE *
3603 {
3604  CUBRID_TAILOR_RULE *ct_rule = NULL;
3605  COLL_TAILORING *curr_coll_tail = NULL;
3606 
3607  assert (ld != NULL);
3608  curr_coll_tail = LOC_CURRENT_COLL_TAIL (ld);
3609 
3610  /* check number of absolute rules, increase array if necessary */
3611  if (curr_coll_tail->cub_count_rules + 1 >= curr_coll_tail->cub_max_rules)
3612  {
3613  CUBRID_TAILOR_RULE *const realloc_cub_rules = (CUBRID_TAILOR_RULE *) realloc (curr_coll_tail->cub_rules,
3614  sizeof (CUBRID_TAILOR_RULE) *
3615  (curr_coll_tail->max_rules +
3617  if (realloc_cub_rules == NULL)
3618  {
3619  return NULL;
3620  }
3621  else
3622  {
3623  curr_coll_tail->cub_rules = realloc_cub_rules;
3624  }
3625 
3627  }
3628 
3629  /* will use slot indicated by 'coll->cub_count_rules' */
3630  ct_rule = &(curr_coll_tail->cub_rules[curr_coll_tail->cub_count_rules]);
3631  memset (ct_rule, 0, sizeof (CUBRID_TAILOR_RULE));
3632 
3633  return ct_rule;
3634 }
3635 
3636 /*
3637  * print_debug_start_el() - print debug info for start of XML element
3638  *
3639  * return:
3640  * data(in):
3641  * attrs(in):
3642  * status(in): status returned from start function
3643  */
3644 static void
3645 print_debug_start_el (void *data, const char **attrs, const char *msg, const int status)
3646 {
3647  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3648  const char **curr_att;
3649 
3650  assert (data != NULL);
3651  assert (attrs != NULL);
3652 
3653  if (pd->verbose)
3654  {
3655  int i;
3656 
3657  assert (pd->ce != NULL);
3658  assert (pd->ce->def != NULL);
3659 
3660  for (i = 0; i < pd->ce->def->depth; i++)
3661  {
3662  printf (" ");
3663  }
3664  printf ("<%s", pd->ce->short_name);
3665 
3666  for (curr_att = attrs; *curr_att != NULL; curr_att++, curr_att++)
3667  {
3668  printf (" %s=\"%s\"", curr_att[0], curr_att[1]);
3669  }
3670 
3671  if (*msg == '\0' && status == 0)
3672  {
3673  printf (">\n");
3674  }
3675  else
3676  {
3677  printf ("> " XML_COMMENT_START " %s ", msg);
3678 
3679  if (status == 0)
3680  {
3681  printf (XML_COMMENT_END "\n");
3682  }
3683  else if (status == -1)
3684  {
3685  printf (" * NOK, Aborting ! *" XML_COMMENT_END "\n");
3686  }
3687  else
3688  {
3689  printf (" * Ignore *" XML_COMMENT_END "\n");
3690  }
3691  }
3692  }
3693 }
3694 
3695 /*
3696  * print_debug_end_el() - print debug info for end of XML element
3697  *
3698  * return:
3699  * data(in):
3700  * status(in): status returned from start function
3701  */
3702 static void
3703 print_debug_end_el (void *data, const char *msg, const int status)
3704 {
3705  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3706 
3707  assert (data != NULL);
3708 
3709  if (pd->verbose)
3710  {
3711  int i;
3712 
3713  assert (pd->ce != NULL);
3714  assert (pd->ce->def != NULL);
3715 
3716  for (i = 0; i < pd->ce->def->depth; i++)
3717  {
3718  printf (" ");
3719  }
3720 
3721  printf ("<\\%s> ", pd->ce->short_name);
3722 
3723  if (*msg == '\0' && status == 0)
3724  {
3725  printf ("\n");
3726  }
3727  else
3728  {
3729  printf (XML_COMMENT_START " %s ", msg);
3730 
3731  if (status != 0)
3732  {
3733  printf (" * NOK, Aborting ! *" XML_COMMENT_END "\n");
3734  }
3735  else
3736  {
3737  printf (XML_COMMENT_END "\n");
3738  }
3739  }
3740  }
3741 }
3742 
3743 /*
3744  * print_debug_data_content() - print debug info data content of XML element
3745  *
3746  * return:
3747  * data(in):
3748  * status(in): status returned from start function
3749  */
3750 static void
3751 print_debug_data_content (void *data, const char *msg, const int status)
3752 {
3753  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
3754 
3755  assert (data != NULL);
3756 
3757  if (pd->verbose)
3758  {
3759  int i;
3760 
3761  assert (pd->ce != NULL);
3762  assert (pd->ce->def != NULL);
3763 
3764  for (i = 0; i < pd->ce->def->depth + 1; i++)
3765  {
3766  printf (" ");
3767  }
3768 
3769  assert (msg != NULL);
3770 
3771  printf ("%s ", msg);
3772 
3773  if (status != 0)
3774  {
3775  printf (XML_COMMENT_START "* NOK, Aborting ! *" XML_COMMENT_END);
3776  }
3777 
3778  printf ("\n");
3779  }
3780 }
3781 
3782 /*
3783  * locale_alloc_collation_id() - allocates collation id
3784  *
3785  * return:
3786  *
3787  * Note : Ranges of collation id:
3788  * 0 - 31(*) : built-in collations (32)
3789  * 32(*) - 46 : generic collations (language independent) (15)
3790  * 47 - 255 : language dependent collations (208 = 26 * 8)
3791  * Collation is name is in format: charset_lang_desc1_desc2_..
3792  * utf8_de_exp : Collation specific to de (German) with expansions
3793  * utf8_gen_ai_ci : Generic collation, accent and case insensitive
3794  *
3795  */
3796 static void
3798 {
3799 #define ID_PER_RANGE 8
3800 #define START_GENERIC_RANGE LANG_MAX_BUILTIN_COLLATIONS
3801 #define START_LANG_RANGE 47
3802 
3803  int coll_id = 0;
3804  char coll_name[COLL_NAME_SIZE];
3805  const char *charset_part, *lang_part, *desc_part;
3806  int range_start, range_size;
3807 
3808  strcpy (coll_name, coll_tail->coll_name);
3809 
3810  charset_part = coll_name;
3811  lang_part = strchr (coll_name, '_');
3812  if (lang_part != NULL)
3813  {
3814  lang_part++;
3815  desc_part = strchr (lang_part, '_');
3816  if (desc_part != NULL)
3817  {
3818  desc_part++;
3819  }
3820  }
3821  else
3822  {
3823  desc_part = NULL;
3824  }
3825 
3826  if (lang_part != NULL)
3827  {
3828  if (strncasecmp (lang_part, "gen", 3) == 0)
3829  {
3830  range_start = START_GENERIC_RANGE;
3831  range_size = (START_LANG_RANGE - START_GENERIC_RANGE) + 1;
3832  }
3833  else
3834  {
3835  int s = (int) *lang_part;
3836  s = (char_isupper (s)) ? (s + ('a' - 'A')) : s;
3837  s = (s > 'z') ? 'z' : ((s < 'a') ? 'a' : s);
3838  s -= 'a';
3839  range_start = START_LANG_RANGE + s * ID_PER_RANGE;
3840  range_size = ID_PER_RANGE;
3841  }
3842 
3843  if (desc_part != NULL)
3844  {
3845  while (desc_part < coll_name + strlen (coll_name))
3846  {
3847  coll_id += *desc_part++;
3848  }
3849  }
3850 
3851  coll_id %= range_size;
3852  coll_id += range_start;
3853  }
3854 
3855  coll_tail->coll_id = coll_id;
3856 
3857 #undef ID_PER_RANGE
3858 #undef START_GENERIC_RANGE
3859 #undef START_LANG_RANGE
3860 }
3861 
3862 /*
3863  * locale_check_collation_id() - checks a collation id
3864  *
3865  * return:
3866  *
3867  *
3868  */
3869 static int
3871 {
3872  char err_msg[ERR_MSG_SIZE];
3873  static int taken_collations[LANG_MAX_COLLATIONS] = { 0 };
3874 
3875  assert (coll_tail->coll_id >= LANG_MAX_BUILTIN_COLLATIONS && coll_tail->coll_id < LANG_MAX_COLLATIONS);
3876 
3877  if (taken_collations[coll_tail->coll_id] != 0)
3878  {
3879  snprintf (err_msg, sizeof (err_msg) - 1,
3880  "Invalid collation numeric identifier : %d" " for collation '%s'. Id is already taken.",
3881  coll_tail->coll_id, coll_tail->coll_name);
3882  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
3883  return ER_LOC_GEN;
3884  }
3885 
3886  taken_collations[coll_tail->coll_id] = 1;
3887  return NO_ERROR;
3888 }
3889 
3890 /*
3891  * load_console_conv_data() - Loads the console conversion file (standardised
3892  * and availabe at Unicode.org).
3893  * Returns: error code
3894  * ld(in/out) : locale data
3895  * is_verbose(in) :
3896  */
3897 static int
3898 load_console_conv_data (LOCALE_DATA * ld, bool is_verbose)
3899 {
3900  TXT_CONV_ITEM *txt_conv_array = NULL;
3901  FILE *fp = NULL;
3902  char *end_p;
3903  char err_msg[ERR_MSG_SIZE];
3904  char str[TXT_CONV_LINE_SIZE];
3905  char conv_file_name[PATH_MAX];
3906  int status = NO_ERROR;
3907  int line_count = 0;
3908  int txt_conv_max_items = 0;
3909  int txt_conv_count_items = 0;
3910  unsigned int i;
3911  unsigned int cp_text = 0;
3912  unsigned int cp_unicode = 0;
3913  TXT_CONV_ITEM min_values = { 0xffff, 0xffff };
3914  TXT_CONV_ITEM max_values = { 0, 0 };
3915 
3916  assert (ld != NULL);
3917 
3919  {
3920  if (is_verbose)
3921  {
3922  printf ("No console conversion data\n");
3923  }
3924  return status;
3925  }
3926 
3929  {
3930  if (is_verbose)
3931  {
3932  printf ("Built-in console conversion\n");
3933  }
3935  return status;
3936  }
3937 
3938  strncpy (conv_file_name, ld->txt_conv_prm.conv_file, sizeof (conv_file_name) - 1);
3939  conv_file_name[sizeof (conv_file_name) - 1] = '\0';
3940 
3941  fp = fopen_ex (conv_file_name, "rt");
3942  if (fp == NULL)
3943  {
3944  envvar_codepagedir_file (conv_file_name, sizeof (conv_file_name), ld->txt_conv_prm.conv_file);
3945  fp = fopen_ex (conv_file_name, "rt");
3946  }
3947 
3948  if (fp == NULL)
3949  {
3950  snprintf_dots_truncate (err_msg, sizeof (err_msg) - 1, "Cannot open file %s", ld->txt_conv_prm.conv_file);
3951  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
3952  status = ER_LOC_GEN;
3953  goto error;
3954  }
3955 
3956  if (is_verbose)
3957  {
3958  printf ("Using file: %s\n", conv_file_name);
3959  }
3960 
3961  memset (ld->txt_conv.byte_flag, 0, sizeof (ld->txt_conv.byte_flag));
3962  while (fgets (str, sizeof (str), fp))
3963  {
3964  char *s;
3965 
3966  line_count++;
3967 
3968  s = str;
3969  /* skip white spaces */
3970  while (char_isspace (*s))
3971  {
3972  s++;
3973  }
3974 
3975  if (*s == '\0' || *s == '#')
3976  {
3977  continue;
3978  }
3979 
3980  str_to_uint32 (&cp_text, &end_p, s, 16);
3981 
3982  /* skip codepoints values above 0xFFFF */
3983  if (cp_text > 0xffff || (cp_text > 0xff && ld->txt_conv_prm.conv_type == TEXT_CONV_GENERIC_1BYTE))
3984  {
3985  snprintf_dots_truncate (err_msg, sizeof (err_msg) - 1, "Codepoint value too big" " in file :%s at line %d",
3986  ld->txt_conv_prm.conv_file, line_count);
3987  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
3988  status = ER_LOC_GEN;
3989  goto error;
3990  }
3991 
3992  /* skip first token */
3993  while (!char_isspace (*s))
3994  {
3995  s++;
3996  }
3997  /* skip white spaces */
3998  while (char_isspace (*s))
3999  {
4000  s++;
4001  }
4002 
4003  if (*s == '\0' || *s == '#')
4004  {
4006  {
4007  assert (cp_text <= 0xff);
4008  if (strncasecmp (s, "#DBCS", 5) == 0)
4009  {
4010  ld->txt_conv.byte_flag[cp_text] = 1;
4011  }
4012  else
4013  {
4014  ld->txt_conv.byte_flag[cp_text] = 2;
4015  }
4016  }
4017  continue;
4018  }
4019 
4020  str_to_uint32 (&cp_unicode, &end_p, s, 16);
4021 
4022  /* first codepoints which maps the same character are not included */
4023  if (((ld->txt_conv_prm.conv_type == TEXT_CONV_GENERIC_1BYTE && cp_text < 0x80)
4024  || ld->txt_conv_prm.conv_type == TEXT_CONV_GENERIC_2BYTE) && (cp_text == cp_unicode
4025  && min_values.text_cp == 0xffff
4026  && min_values.unicode_cp == 0xffff))
4027  {
4028  continue;
4029  }
4030 
4031  if (cp_unicode > 0xffff)
4032  {
4033  snprintf_dots_truncate (err_msg, sizeof (err_msg) - 1, "Codepoint value too big" " in file :%s at line %d",
4034  ld->txt_conv_prm.conv_file, line_count);
4035  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
4036  status = ER_LOC_GEN;
4037  goto error;
4038  }
4039 
4040  if (txt_conv_count_items >= txt_conv_max_items)
4041  {
4042  TXT_CONV_ITEM *const realloc_txt_conv_array = (TXT_CONV_ITEM *) realloc (txt_conv_array,
4043  sizeof (TXT_CONV_ITEM) *
4044  (txt_conv_max_items +
4046  if (realloc_txt_conv_array == NULL)
4047  {
4048  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_GEN, true);
4049  status = ER_LOC_GEN;
4050  goto error;
4051  }
4052  else
4053  {
4054  txt_conv_array = realloc_txt_conv_array;
4055  }
4056 
4057  txt_conv_max_items += TXT_CONV_ITEM_GROW_COUNT;
4058  }
4059 
4060  txt_conv_array[txt_conv_count_items].text_cp = cp_text;
4061  txt_conv_array[txt_conv_count_items].unicode_cp = cp_unicode;
4062 
4063  min_values.text_cp = MIN (min_values.text_cp, cp_text);
4064  min_values.unicode_cp = MIN (min_values.unicode_cp, cp_unicode);
4065 
4066  max_values.text_cp = MAX (max_values.text_cp, cp_text);
4067  max_values.unicode_cp = MAX (max_values.unicode_cp, cp_unicode);
4068 
4069  txt_conv_count_items++;
4070  }
4071 
4072  if (is_verbose)
4073  {
4074  printf ("Building %d console conversion rules\n", txt_conv_count_items);
4075  }
4076 
4077  /* build conversions */
4078  ld->txt_conv.text_first_cp = min_values.text_cp;
4079  ld->txt_conv.text_last_cp = max_values.text_cp;
4080 
4081  ld->txt_conv.utf8_first_cp = min_values.unicode_cp;
4082  ld->txt_conv.utf8_last_cp = max_values.unicode_cp;
4083 
4086 
4087  if (ld->txt_conv.text_last_cp == 0 || ld->txt_conv.utf8_last_cp == 0)
4088  {
4089  LOG_LOCALE_ERROR ("Invalid console mapping", ER_LOC_GEN, true);
4090  status = ER_LOC_GEN;
4091  goto error;
4092  }
4093 
4094  ld->txt_conv.text_to_utf8 =
4095  (CONV_CP_TO_BYTES *) malloc (sizeof (CONV_CP_TO_BYTES) *
4096  (ld->txt_conv.text_last_cp - ld->txt_conv.text_first_cp + 1));
4097  memset (ld->txt_conv.text_to_utf8, 0,
4098  sizeof (CONV_CP_TO_BYTES) * (ld->txt_conv.text_last_cp - ld->txt_conv.text_first_cp + 1));
4099 
4100  ld->txt_conv.utf8_to_text =
4101  (CONV_CP_TO_BYTES *) malloc (sizeof (CONV_CP_TO_BYTES) *
4102  (ld->txt_conv.utf8_last_cp - ld->txt_conv.utf8_first_cp + 1));
4103  memset (ld->txt_conv.utf8_to_text, 0,
4104  sizeof (CONV_CP_TO_BYTES) * (ld->txt_conv.utf8_last_cp - ld->txt_conv.utf8_first_cp + 1));
4105 
4106  if (ld->txt_conv.text_to_utf8 == NULL || ld->txt_conv.utf8_to_text == NULL)
4107  {
4108  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_GEN, true);
4109  status = ER_LOC_GEN;
4110  goto error;
4111  }
4112 
4113  for (i = 0; i < ld->txt_conv.text_last_cp - ld->txt_conv.text_first_cp + 1; i++)
4114  {
4115  ld->txt_conv.text_to_utf8[i].size = 1;
4116  *(ld->txt_conv.text_to_utf8[i].bytes) = '?';
4117  }
4118 
4119  for (i = 0; i < ld->txt_conv.utf8_last_cp - ld->txt_conv.utf8_first_cp + 1; i++)
4120  {
4121  ld->txt_conv.utf8_to_text[i].size = 1;
4122  *(ld->txt_conv.utf8_to_text[i].bytes) = '?';
4123  }
4124 
4125  for (i = 0; (int) i < txt_conv_count_items; i++)
4126  {
4127  CONV_CP_TO_BYTES *text_to_utf8_item = NULL;
4128  CONV_CP_TO_BYTES *utf8_to_text_item = NULL;
4129 
4130  cp_text = txt_conv_array[i].text_cp;
4131  cp_unicode = txt_conv_array[i].unicode_cp;
4132 
4133  assert (cp_text >= ld->txt_conv.text_first_cp && cp_text <= ld->txt_conv.text_last_cp);
4134 
4135  assert (cp_unicode >= ld->txt_conv.utf8_first_cp && cp_unicode <= ld->txt_conv.utf8_last_cp);
4136 
4137  text_to_utf8_item = &(ld->txt_conv.text_to_utf8[cp_text - ld->txt_conv.text_first_cp]);
4138  utf8_to_text_item = &(ld->txt_conv.utf8_to_text[cp_unicode - ld->txt_conv.utf8_first_cp]);
4139 
4140  text_to_utf8_item->size = intl_cp_to_utf8 (cp_unicode, text_to_utf8_item->bytes);
4141 
4143  {
4144  utf8_to_text_item->size = 1;
4145  utf8_to_text_item->bytes[0] = cp_text;
4146  }
4147  else
4148  {
4150  utf8_to_text_item->size = intl_cp_to_dbcs (cp_text, ld->txt_conv.byte_flag, utf8_to_text_item->bytes);
4151  }
4152  }
4153 
4154  assert (fp != NULL);
4155  fclose (fp);
4156 
4157  assert (txt_conv_array != NULL);
4158  free (txt_conv_array);
4159 
4163  if (ld->txt_conv.nl_lang_str == NULL)
4164  {
4165  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_GEN, true);
4166  status = ER_LOC_GEN;
4167  goto error;
4168  }
4169 
4170  return status;
4171 
4172 error:
4173 
4174  if (fp != NULL)
4175  {
4176  fclose (fp);
4177  }
4178 
4179  if (txt_conv_array != NULL)
4180  {
4181  free (txt_conv_array);
4182  }
4183 
4184  return status;
4185 }
4186 
4187 /*
4188  * comp_func_parse_order_index - compare function for sorting parse order
4189  * indexes for month and weekday names, based on the reversed
4190  * binary order of the LDML tokens
4191  *
4192  * Note: this function is used by the genlocale tool
4193  * The elements in the arrays should be NUL-terminated strings, stored
4194  * in fixed length char arrays. Encoding is not relevant, the purpose
4195  * of this comparison is to make sure that the tokenizer first tries
4196  * to match some tokens before others which can be prefixes for them.
4197  * E.g. In Vietnamese(vi_VN), the October translation followed by
4198  * a space is a prefix for the translations of November and December.
4199  */
4200 static int
4201 comp_func_parse_order_index (const void *arg1, const void *arg2)
4202 {
4203  char *s1;
4204  char *s2;
4205  char pos1;
4206  char pos2;
4207  int cmp;
4208 
4209  pos1 = *((char *) arg1);
4210  pos2 = *((char *) arg2);
4211  s1 = (char *) (cmp_token_name_array + pos1 * cmp_token_name_size);
4212  s2 = (char *) (cmp_token_name_array + pos2 * cmp_token_name_size);
4213 
4214  cmp = strcmp (s2, s1);
4215 
4216  return (cmp == 0) ? (pos1 - pos2) : cmp;
4217 }
4218 
4219 /*
4220  * locale_make_calendar_parse_order() - computes the order in which the
4221  * string tokenizer should search for matches with
4222  * weekday and month names, both wide and abbreviated.
4223  *
4224  * return:
4225  * ld(in/out): LOCALE_DATA for which to do the processing
4226  */
4227 static void
4229 {
4230  int i;
4231  for (i = 0; i < CAL_MONTH_COUNT; i++)
4232  {
4235  }
4236  for (i = 0; i < CAL_DAY_COUNT; i++)
4237  {
4240  }
4241  for (i = 0; i < CAL_AM_PM_COUNT; i++)
4242  {
4243  ld->am_pm_parse_order[i] = i;
4244  }
4245 
4248  qsort (ld->month_names_abbr_parse_order, CAL_MONTH_COUNT, sizeof (char), comp_func_parse_order_index);
4249 
4250  cmp_token_name_array = (char *) (ld->month_names_wide);
4252  qsort (ld->month_names_wide_parse_order, CAL_MONTH_COUNT, sizeof (char), comp_func_parse_order_index);
4253 
4256  qsort (ld->day_names_abbr_parse_order, CAL_DAY_COUNT, sizeof (char), comp_func_parse_order_index);
4257 
4258  cmp_token_name_array = (char *) (ld->day_names_wide);
4260  qsort (ld->day_names_wide_parse_order, CAL_DAY_COUNT, sizeof (char), comp_func_parse_order_index);
4261 
4262  cmp_token_name_array = (char *) (ld->am_pm);
4264  qsort (ld->am_pm_parse_order, CAL_AM_PM_COUNT, sizeof (char), comp_func_parse_order_index);
4265 }
4266 
4267 /*
4268  * locale_init_data() - initializes one locale data
4269  *
4270  * return:
4271  * ld(in/out):
4272  * locale_name(in):
4273  */
4274 void
4275 locale_init_data (LOCALE_DATA * ld, const char *locale_name)
4276 {
4277  memset (ld, 0, sizeof (LOCALE_DATA));
4278  ld->curr_period = -1;
4279 
4280  assert (strlen (locale_name) < (int) sizeof (ld->locale_name));
4281  strcpy (ld->locale_name, locale_name);
4282 
4283  /* default number symbols */
4284  ld->number_decimal_sym = ',';
4285  ld->number_group_sym = '.';
4287 
4289 }
4290 
4291 /*
4292  * locale_destroy_data() - frees memory allocated for one locale data
4293  *
4294  * return:
4295  * ld(in/out):
4296  */
4297 void
4299 {
4300  int i;
4301 
4302  assert (ld != NULL);
4303 
4304  /* collations */
4305  for (i = 0; i < ld->coll_cnt; i++)
4306  {
4309  }
4310 
4311  free (ld->collations);
4312  ld->collations = NULL;
4313  ld->coll_cnt = 0;
4314 
4315  /* alphabet tailoring */
4317 
4318  /* alphabets */
4321 
4323 
4325 
4326  /* ldml context file path */
4327  if (ld->ldml_context.ldml_file != NULL)
4328  {
4329  free (ld->ldml_context.ldml_file);
4330  }
4331 }
4332 
4333 /*
4334  * locale_destroy_alphabet_data() - frees memory for one locale alphabet
4335  * return:
4336  * a(in/out):
4337  *
4338  * Note : Alphabets that are common are not freed
4339  */
4340 void
4342 {
4343  assert (a != NULL);
4344 
4345  if (a->lower_cp != NULL)
4346  {
4347  free (a->lower_cp);
4348  }
4349 
4350  if (a->upper_cp != NULL)
4351  {
4352  free (a->upper_cp);
4353  }
4354 
4355  memset ((void *) a, 0, sizeof (ALPHABET_DATA));
4356 }
4357 
4358 /*
4359  * locale_destroy_collation_tailorings() - frees memory for one locale
4360  * collation tailorings
4361  * return:
4362  * ct(in/out):
4363  */
4364 static void
4366 {
4367  int i;
4368 
4369  assert (ct != NULL);
4370 
4371  /* collation tailorings */
4372  for (i = 0; i < ct->count_rules; i++)
4373  {
4374  TAILOR_RULE *t_rule = &(ct->rules[i]);
4375 
4376  assert (t_rule != NULL);
4377  assert (t_rule->t_buf != NULL);
4378 
4379  if (t_rule->t_buf != NULL)
4380  {
4381  assert (t_rule->t_buf_size > 0);
4382  free (t_rule->t_buf);
4383  }
4384 
4385  if (t_rule->r_buf != NULL)
4386  {
4387  assert (t_rule->r_buf_size > 0);
4388  free (t_rule->r_buf);
4389  }
4390 
4391  memset (t_rule, 0, sizeof (TAILOR_RULE));
4392  }
4393 
4394  if (ct->rules != NULL)
4395  {
4396  assert (ct->max_rules > 0);
4397  free (ct->rules);
4398  }
4399 
4400  if (ct->cub_rules != NULL)
4401  {
4402  assert (ct->cub_max_rules > 0);
4403  free (ct->cub_rules);
4404  }
4405 
4406  if (ct->ldml_context.ldml_file != NULL)
4407  {
4408  free (ct->ldml_context.ldml_file);
4409  }
4410 
4411  memset ((void *) ct, 0, sizeof (COLL_TAILORING));
4412 }
4413 
4414 /*
4415  * locale_destroy_collation_data() - frees memory for collation data
4416  * return:
4417  * cd(in/out):
4418  */
4419 static void
4421 {
4422  assert (cd != NULL);
4423 
4424  /* collation data */
4425  if (cd->weights != NULL)
4426  {
4427  free (cd->weights);
4428  }
4429 
4430  if (cd->next_cp != NULL)
4431  {
4432  free (cd->next_cp);
4433  }
4434 
4435  /* contractions */
4436  if (cd->uca_num != NULL)
4437  {
4438  free (cd->uca_num);
4439  }
4440 
4441  if (cd->uca_w_l13 != NULL)
4442  {
4443  free (cd->uca_w_l13);
4444  }
4445 
4446  if (cd->uca_w_l4 != NULL)
4447  {
4448  free (cd->uca_w_l4);
4449  }
4450 
4451  if (cd->cp_first_contr_array != NULL)
4452  {
4453  free (cd->cp_first_contr_array);
4454  }
4455 
4456  if (cd->contr_list != NULL)
4457  {
4458  free (cd->contr_list);
4459  }
4460 
4461  memset ((void *) cd, 0, sizeof (COLL_DATA));
4462 }
4463 
4464 /*
4465  * locale_destroy_alphabet_tailoring() - frees memory for alphabet tailorings
4466  * return:
4467  * at(in/out):
4468  */
4469 static void
4471 {
4472  int i;
4473 
4474  assert (at != 0);
4475 
4476  /* case tailoring */
4477  for (i = 0; i < at->count_rules; i++)
4478  {
4479  TRANSFORM_RULE *tf_rule = &(at->rules[i]);
4480 
4481  assert (tf_rule != NULL);
4482  assert (tf_rule->src != NULL);
4483  assert (tf_rule->dest != NULL);
4484 
4485  if (tf_rule->src != NULL)
4486  {
4487  assert (tf_rule->src_size > 0);
4488  free (tf_rule->src);
4489  }
4490 
4491  if (tf_rule->dest != NULL)
4492  {
4493  assert (tf_rule->dest_size > 0);
4494  free (tf_rule->dest);
4495  }
4496 
4497  memset (tf_rule, 0, sizeof (TRANSFORM_RULE));
4498  }
4499 
4500  if (at->rules != NULL)
4501  {
4502  assert (at->max_rules > 0);
4503  free (at->rules);
4504  }
4505 
4506  if (at->ldml_context.ldml_file != NULL)
4507  {
4508  free (at->ldml_context.ldml_file);
4509  }
4510 
4511  memset ((void *) at, 0, sizeof (ALPHABET_TAILORING));
4512 }
4513 
4514 /*
4515  * locale_destroy_console_conversion() - frees memory for console conversion
4516  * return:
4517  * tc(in/out):
4518  */
4519 static void
4521 {
4522  assert (tc != 0);
4523 
4524  /* console conversion */
4525  if (tc->nl_lang_str != NULL)
4526  {
4527  free (tc->nl_lang_str);
4528  }
4529 
4530  if (tc->win_codepages != NULL)
4531  {
4532  free (tc->win_codepages);
4533  }
4534 
4535  if (tc->text_to_utf8 != NULL)
4536  {
4537  free (tc->text_to_utf8);
4538  }
4539 
4540  if (tc->utf8_to_text != NULL)
4541  {
4542  free (tc->utf8_to_text);
4543  }
4544 
4545  memset ((void *) tc, 0, sizeof (TEXT_CONVERSION));
4546 }
4547 
4548 /*
4549  * locale_compile_locale() - process locale data loaded from LDML file(s)
4550  *
4551  * return: error code
4552  * lf(in): structure containing file paths
4553  * ld(in): locale data to be processed
4554  * is_verbose(in):
4555  */
4556 int
4557 locale_compile_locale (LOCALE_FILE * lf, LOCALE_DATA * ld, bool is_verbose)
4558 {
4559  XML_PARSER_DATA ldml_parser;
4560  LOC_SHARED_DATA *norm_sh_entry = NULL;
4561  char *locale_str = NULL;
4562  int er_status = NO_ERROR;
4563  int i;
4564 
4565  assert (lf != NULL);
4566  locale_str = lf->locale_name;
4567 
4568  if (is_verbose)
4569  {
4570  printf ("\n*** Parsing LDML\n");
4571  }
4572 
4573  locale_init_data (ld, locale_str);
4574  ldml_parser.ud = ld;
4575  ldml_parser.verbose = is_verbose;
4576 
4577  ld->ldml_context.ldml_file = strdup (lf->ldml_file);
4578  ld->ldml_context.line_no = 1;
4579 
4580  ldml_parser.xml_parser =
4581  xml_init_parser (&ldml_parser, lf->ldml_file, "UTF-8", ldml_elements,
4582  sizeof (ldml_elements) / sizeof (XML_ELEMENT_DEF *));
4583 
4584  if (ldml_parser.xml_parser == NULL)
4585  {
4586  LOG_LOCALE_ERROR ("Cannot init XML parser", ER_LOC_GEN, true);
4587 
4588  er_status = ER_LOC_GEN;
4589  goto exit;
4590  }
4591 
4592  xml_parser_exec (&ldml_parser);
4593 
4594  if (ldml_parser.xml_error == XML_CUB_NO_ERROR)
4595  {
4596  if (is_verbose)
4597  {
4598  printf ("Parsing finished.\n");
4599  printf ("Date format: %s\n", ld->dateFormat);
4600  printf ("Time format: %s\n", ld->timeFormat);
4601  printf ("Datetime format: %s\n", ld->datetimeFormat);
4602  printf ("Timestamp format: %s\n", ld->timestampFormat);
4603  printf ("Timetz format: %s\n", ld->timetzFormat);
4604  printf ("Datetimetz format: %s\n", ld->datetimetzFormat);
4605  printf ("Timestamptz format: %s\n", ld->timestamptzFormat);
4606  }
4607  }
4608  else
4609  {
4610  char msg[ERR_MSG_SIZE];
4611  const char *xml_err_text = (char *) XML_ErrorString (XML_GetErrorCode (ldml_parser.xml_parser));
4612 
4613  snprintf_dots_truncate (msg, sizeof (msg) - 1,
4614  "Error parsing file %s, " "line : %d, column : %d. Internal XML: %s",
4615  ldml_parser.filepath, ldml_parser.xml_error_line, ldml_parser.xml_error_column,
4616  xml_err_text);
4617 
4618  LOG_LOCALE_ERROR (msg, ER_LOC_GEN, true);
4619  er_status = ER_LOC_GEN;
4620  goto exit;
4621  }
4622 
4624 
4625  if (ld->alpha_tailoring.sett_max_letters == -1)
4626  {
4628  }
4629 
4630  if (is_verbose)
4631  {
4632  printf ("\n*** Processing alphabet ***\nNumber of letters = %d\n", ld->alpha_tailoring.sett_max_letters);
4633  }
4634 
4635  if (ld->alpha_tailoring.sett_max_letters == 0)
4636  {
4638  }
4639  else
4640  {
4641  LOC_SHARED_DATA *alphabet_sh_entry = NULL;
4643 
4644  er_status = unicode_process_alphabet (ld, is_verbose);
4645  if (er_status != NO_ERROR)
4646  {
4647  goto exit;
4648  }
4649 
4650  if (ld->alphabet.a_type == ALPHABET_UNICODE)
4651  {
4652  er_status =
4653  locale_check_and_set_shared_data (LOC_SHARED_ALPHABET, "unicode", NULL, ldml_context, &alphabet_sh_entry);
4654  }
4655  else if (ld->alphabet.a_type == ALPHABET_ASCII)
4656  {
4657  er_status =
4658  locale_check_and_set_shared_data (LOC_SHARED_ALPHABET, "ascii", NULL, ldml_context, &alphabet_sh_entry);
4659  }
4660 
4661  if (er_status != NO_ERROR)
4662  {
4663  goto exit;
4664  }
4665 
4666  ld->alphabet.do_not_save = (alphabet_sh_entry != NULL) ? true : false;
4667 
4668  alphabet_sh_entry = NULL;
4670  {
4671  er_status =
4672  locale_check_and_set_shared_data (LOC_SHARED_ALPHABET, "unicode", NULL, ldml_context, &alphabet_sh_entry);
4673  }
4674  else if (ld->identif_alphabet.a_type == ALPHABET_ASCII)
4675  {
4676  er_status =
4677  locale_check_and_set_shared_data (LOC_SHARED_ALPHABET, "ascii", NULL, ldml_context, &alphabet_sh_entry);
4678  }
4679 
4680  if (er_status != NO_ERROR)
4681  {
4682  goto exit;
4683  }
4684 
4685  ld->identif_alphabet.do_not_save = (alphabet_sh_entry != NULL) ? true : false;
4686  if (ld->identif_alphabet.do_not_save == false)
4687  {
4688  /* check that casing data matches the rule of INTL_IDENTIFIER_CASING_SIZE_MULTIPLIER: the ratio between the
4689  * size in bytes of lower (or upper) case character (or sequence of characters) and the size in bytes of
4690  * original character is less than INTL_IDENTIFIER_CASING_SIZE_MULTIPLIER */
4691  unsigned int cp;
4692  ALPHABET_DATA *a = &(ld->identif_alphabet);
4693  unsigned char dummy[INTL_UTF8_MAX_CHAR_SIZE];
4694 
4695  for (cp = 0; (int) cp < a->l_count; cp++)
4696  {
4697  int case_cnt, case_size, cp_size;
4698  unsigned int *lower_cp = &(a->lower_cp[cp * a->lower_multiplier]);
4699  unsigned int *upper_cp = &(a->upper_cp[cp * a->upper_multiplier]);
4700 
4701  for (case_size = 0, case_cnt = 0; case_cnt < a->lower_multiplier && *lower_cp != 0;
4702  case_cnt++, lower_cp++)
4703  {
4704  if (*lower_cp == cp)
4705  {
4706  /* character does not have lower case */
4707  case_size = 0;
4708  break;
4709  }
4710  case_size += intl_cp_to_utf8 (*lower_cp, dummy);
4711  }
4712 
4713  if (case_size > 0)
4714  {
4715  cp_size = intl_cp_to_utf8 (cp, dummy);
4716  if (case_size > cp_size * INTL_IDENTIFIER_CASING_SIZE_MULTIPLIER)
4717  {
4718  char msg[ERR_MSG_SIZE];
4719 
4720  snprintf (msg, sizeof (msg) - 1,
4721  "Lower case " "sequence for codepoint Ux%04X is too "
4722  "big: %d bytes; expecting at most %d", cp, case_size,
4723  cp_size * INTL_IDENTIFIER_CASING_SIZE_MULTIPLIER);
4724  LOG_LOCALE_ERROR (msg, ER_LOC_GEN, true);
4725  er_status = ER_LOC_GEN;
4726  goto exit;
4727  }
4728  }
4729 
4730  for (case_size = 0, case_cnt = 0; case_cnt < a->upper_multiplier && *upper_cp != 0;
4731  case_cnt++, upper_cp++)
4732  {
4733  if (*upper_cp == cp)
4734  {
4735  /* character does not have upper case */
4736  case_size = 0;
4737  break;
4738  }
4739  case_size += intl_cp_to_utf8 (*upper_cp, dummy);
4740  }
4741 
4742  if (case_size > 0)
4743  {
4744  cp_size = intl_cp_to_utf8 (cp, dummy);
4745  if (case_size > cp_size * INTL_IDENTIFIER_CASING_SIZE_MULTIPLIER)
4746  {
4747  char msg[ERR_MSG_SIZE];
4748 
4749  snprintf (msg, sizeof (msg) - 1,
4750  "Upper case " "sequence for codepoint Ux%04X is too "
4751  "big: %d bytes; expecting at most %d", cp, case_size,
4752  cp_size * INTL_IDENTIFIER_CASING_SIZE_MULTIPLIER);
4753  LOG_LOCALE_ERROR (msg, ER_LOC_GEN, true);
4754  er_status = ER_LOC_GEN;
4755  goto exit;
4756  }
4757  }
4758  }
4759  }
4760  }
4761 
4762  if (is_verbose)
4763  {
4764  printf ("\n*** Processing Unicode normalization data ***\n");
4765  }
4766 
4767  er_status = locale_check_and_set_shared_data (LOC_SHARED_NORMALIZATION, "normalization", NULL, NULL, &norm_sh_entry);
4768 
4769  ld->unicode_normalization.do_not_save = (norm_sh_entry != NULL) ? true : false;
4770 
4771  if (norm_sh_entry == NULL)
4772  {
4773  /* not shared, process normalization */
4774  er_status = unicode_process_normalization (ld, is_verbose);
4775  if (er_status != NO_ERROR)
4776  {
4777  goto exit;
4778  }
4779  }
4780 
4781  if (is_verbose)
4782  {
4783  printf ("\n*** Processing console conversion data ***\n");
4784  }
4785 
4786  er_status = load_console_conv_data (ld, is_verbose);
4787  if (er_status != NO_ERROR)
4788  {
4789  goto exit;
4790  }
4791 
4792  if (ld->coll_cnt == 0 && is_verbose)
4793  {
4794  printf ("\n*** No collation defined ***\n");
4795  }
4796 
4797  for (i = 0; i < ld->coll_cnt; i++)
4798  {
4799  LOC_SHARED_DATA *coll_sh_entry = NULL;
4800  LOCALE_COLLATION *lc = &(ld->collations[i]);
4801  char shared_coll_data[COLL_SHARED_DATA_SIZE];
4802 
4803 
4804  strncpy (lc->opt_coll.coll_name, lc->tail_coll.coll_name, COLL_NAME_SIZE);
4805  lc->opt_coll.coll_name[COLL_NAME_SIZE - 1] = '\0';
4806 
4808  {
4809  char msg[ERR_MSG_SIZE];
4810 
4811  snprintf (msg, sizeof (msg) - 1,
4812  "Collation name %s " "not allowed. It cannot contain white-spaces "
4813  "or have same name as a built-in collation", lc->opt_coll.coll_name);
4814 
4815  LOG_LOCALE_ERROR (msg, ER_LOC_GEN, true);
4816  er_status = ER_LOC_GEN;
4817  goto exit;
4818  }
4819 
4820  snprintf (shared_coll_data, sizeof (shared_coll_data) - 1, "%d", lc->tail_coll.coll_id);
4821 
4822  er_status =
4824  &(lc->tail_coll.ldml_context), &coll_sh_entry);
4825  if (er_status != NO_ERROR)
4826  {
4827  goto exit;
4828  }
4829 
4830  lc->do_not_save = (coll_sh_entry != NULL) ? true : false;
4831 
4832  if (coll_sh_entry != NULL)
4833  {
4834  /* check found entry */
4835  const char *coll_sh_data = (const char *) coll_sh_entry->data;
4836 
4837  assert (coll_sh_data != NULL);
4838 
4839  if (strcmp (shared_coll_data, coll_sh_data) != 0)
4840  {
4841  /* found collation with same name buf different collation shared data (collation id) */
4842  char msg[ERR_MSG_SIZE + 2 * PATH_MAX];
4843 
4844  snprintf (msg, sizeof (msg) - 1,
4845  "File: %s, line: %d : " "collation name %s (id:%d) already defined in "
4846  "file: %s, line: %d with id: %s", lc->tail_coll.ldml_context.ldml_file,
4848  coll_sh_entry->ldml_context.ldml_file, coll_sh_entry->ldml_context.line_no, coll_sh_data);
4849 
4850  LOG_LOCALE_ERROR (msg, ER_LOC_GEN, true);
4851  er_status = ER_LOC_GEN;
4852  goto exit;
4853  }
4854  else if (strcmp (lc->tail_coll.ldml_context.ldml_file, coll_sh_entry->ldml_context.ldml_file) != 0
4855  || lc->tail_coll.ldml_context.line_no != coll_sh_entry->ldml_context.line_no)
4856  {
4857  /* same collation, just put an debug info */
4858  printf ("Warning : Definition of collation %s (id: %d) " "ignored in file: %s, line: %d. "
4859  "Using the definition from file: %s, line: %d.\n", lc->tail_coll.coll_name, lc->tail_coll.coll_id,
4861  coll_sh_entry->ldml_context.ldml_file, coll_sh_entry->ldml_context.line_no);
4862  }
4863 
4864  continue;
4865  }
4866 
4867  if (lc->tail_coll.sett_max_cp == -1)
4868  {
4870  }
4871 
4872  if (is_verbose)
4873  {
4874  printf ("\n*** Processing collation : %s ***\n" "Number of weights = %d\n", lc->tail_coll.coll_name,
4875  lc->tail_coll.sett_max_cp);
4876  }
4877 
4878  if (lc->tail_coll.sett_max_cp == 0)
4879  {
4881  }
4882  else
4883  {
4884  er_status = uca_process_collation (lc, is_verbose);
4885  if (er_status != NO_ERROR)
4886  {
4887  goto exit;
4888  }
4889 
4890  if (lc->tail_coll.coll_id <= 0)
4891  {
4893  }
4894 
4895  er_status = locale_check_collation_id (&lc->tail_coll);
4896  if (er_status != NO_ERROR)
4897  {
4898  goto exit;
4899  }
4900  lc->opt_coll.coll_id = lc->tail_coll.coll_id;
4901  }
4902 
4903  er_status = locale_compute_coll_checksum (&(lc->opt_coll));
4904  if (er_status != NO_ERROR)
4905  {
4906  goto exit;
4907  }
4908  if (is_verbose)
4909  {
4910  printf ("ID : %d | Checksum : %s\n", lc->opt_coll.coll_id, lc->opt_coll.checksum);
4911  }
4912  }
4913 
4914  er_status = locale_compute_locale_checksum (ld);
4915  if (er_status != NO_ERROR)
4916  {
4917  goto exit;
4918  }
4919 
4920  if (is_verbose)
4921  {
4922  printf ("\n Locale checksum :%s\n", ld->checksum);
4923  }
4924 
4925 exit:
4926  xml_destroy_parser (&ldml_parser);
4927  uca_free_data ();
4928  unicode_free_data ();
4929 
4930  if (is_verbose)
4931  {
4932  printf ("\n\nLocale finished\n\n\n");
4933  }
4934 
4935  return er_status;
4936 }
4937 
4938 /*
4939  * locale_mark_duplicate_collations - finds duplicate arrays within all
4940  * collations and uses string identifiers from
4941  * LOCALE_DATA structure to mark the arrays which will
4942  * not be exported to the shared library, but another
4943  * identical array will be loaded instead.
4944  *
4945  * return: error status
4946  *
4947  * ld(in): all locale data loaded from LDML and compiled
4948  * start_index(in): index of the first working locale (in ld)
4949  * end_index(in): index of the last working locale stored in the ld array
4950  */
4951 void
4952 locale_mark_duplicate_collations (LOCALE_DATA ** ld, int start_index, int end_index, bool is_verbose)
4953 {
4954 #define PRINT_DUPLICATE_SYMBOL_NAME(symbol, dupl_coll, orig_coll, do_print) \
4955  if (do_print) \
4956  { \
4957  printf ("\n *** Duplicate array: %s in collation %s is a duplicate " \
4958  "of %s from collation %s", (symbol), \
4959  (dupl_coll)->opt_coll.coll_name, \
4960  (symbol), (orig_coll)->opt_coll.coll_name); \
4961  }
4962 
4963  int i1, i2, j1, j2;
4964  LOCALE_COLLATION *cur_coll, *comp_coll;
4965  LOCALE_DATA *cur_ld, *comp_ld;
4966 
4967  /* Search for duplicate arrays. In order to avoid errors, search must be done backwards for the cursor collation,
4968  * while searching forward in the locales; the rule of determining the identifier to be stored is that the first
4969  * occurence is considered as the original, and all identical arrays that follow are duplicates */
4970  for (i1 = end_index - 1; i1 >= start_index; i1--)
4971  {
4972  cur_ld = ld[i1];
4973  for (j1 = cur_ld->coll_cnt - 1; j1 >= 0; j1--)
4974  {
4975  cur_coll = &(cur_ld->collations[j1]);
4976 
4977  for (i2 = start_index; i2 <= i1; i2++)
4978  {
4979  comp_ld = ld[i2];
4980  for (j2 = 0; (i1 == i2 && j2 < j1) || (i1 > i2 && j2 < comp_ld->coll_cnt); j2++)
4981  {
4982  comp_coll = &(comp_ld->collations[j2]);
4983  /* Two COLL_INFO structures are refferenced.Compare them. */
4984 
4985  if (cur_coll->opt_coll.w_count != comp_coll->opt_coll.w_count)
4986  {
4987  continue;
4988  }
4989 
4990  if (cur_coll->opt_coll.uca_opt.sett_expansions == comp_coll->opt_coll.uca_opt.sett_expansions)
4991  {
4992  if (!cur_coll->opt_coll.uca_opt.sett_expansions)
4993  {
4994  if (*(cur_coll->coll_ref.coll_weights_ref) == '\0'
4995  && memcmp (cur_coll->opt_coll.weights, comp_coll->opt_coll.weights,
4996  sizeof (comp_coll->opt_coll.weights[0]) * cur_coll->opt_coll.w_count) == 0)
4997  {
4998  sprintf (cur_coll->coll_ref.coll_weights_ref, "%s_%s", "coll_weights",
4999  comp_coll->opt_coll.coll_name);
5000  PRINT_DUPLICATE_SYMBOL_NAME ("coll_weights", cur_coll, comp_coll, is_verbose);
5001  }
5002  }
5003  else
5004  {
5005  if (cur_coll->opt_coll.uca_exp_num != comp_coll->opt_coll.uca_exp_num)
5006  {
5007  continue;
5008  }
5009 
5010  if (*(cur_coll->coll_ref.coll_uca_num_ref) == '\0'
5011  && memcmp (cur_coll->opt_coll.uca_num, comp_coll->opt_coll.uca_num,
5012  sizeof (comp_coll->opt_coll.uca_num[0]) * comp_coll->opt_coll.w_count) == 0)
5013  {
5014  sprintf (cur_coll->coll_ref.coll_uca_num_ref, "%s_%s", "coll_uca_num",
5015  comp_coll->opt_coll.coll_name);
5016  PRINT_DUPLICATE_SYMBOL_NAME ("coll_uca_num", cur_coll, comp_coll, is_verbose);
5017  }
5018 
5019  if (*(cur_coll->coll_ref.coll_uca_w_l13_ref) == '\0'
5020  && memcmp (cur_coll->opt_coll.uca_w_l13, comp_coll->opt_coll.uca_w_l13,
5021  sizeof (UCA_L13_W) * cur_coll->opt_coll.uca_exp_num *
5022  cur_coll->opt_coll.w_count) == 0)
5023  {
5024  sprintf (cur_coll->coll_ref.coll_uca_w_l13_ref, "%s_%s", "coll_uca_w_l13",
5025  comp_coll->opt_coll.coll_name);
5026  PRINT_DUPLICATE_SYMBOL_NAME ("coll_uca_w_l13", cur_coll, comp_coll, is_verbose);
5027  }
5030  && *(cur_coll->coll_ref.coll_uca_w_l4_ref) == '\0'
5031  && memcmp (cur_coll->opt_coll.uca_w_l4, comp_coll->opt_coll.uca_w_l4,
5032  sizeof (UCA_L4_W) * cur_coll->opt_coll.uca_exp_num *
5033  cur_coll->opt_coll.w_count) == 0)
5034  {
5035  sprintf (cur_coll->coll_ref.coll_uca_w_l4_ref, "%s_%s", "coll_uca_w_l4",
5036  comp_coll->opt_coll.coll_name);
5037  PRINT_DUPLICATE_SYMBOL_NAME ("coll_uca_w_l4", cur_coll, comp_coll, is_verbose);
5038  }
5039  }
5040  } /* endif equal sett_expansions */
5041 
5042  if (*(cur_coll->coll_ref.coll_next_cp_ref) == '\0'
5043  && memcmp (cur_coll->opt_coll.next_cp, comp_coll->opt_coll.next_cp,
5044  sizeof (comp_coll->opt_coll.next_cp[0]) * comp_coll->opt_coll.w_count) == 0)
5045  {
5046  sprintf (cur_coll->coll_ref.coll_next_cp_ref, "%s_%s", "coll_next_cp",
5047  comp_coll->opt_coll.coll_name);
5048  PRINT_DUPLICATE_SYMBOL_NAME ("coll_next_cp", cur_coll, comp_coll, is_verbose);
5049  }
5050 
5051  /* compare contraction data */
5052  if (cur_coll->opt_coll.count_contr > 0
5053  && cur_coll->opt_coll.count_contr == comp_coll->opt_coll.count_contr)
5054  {
5055  if (cur_coll->opt_coll.contr_min_size == comp_coll->opt_coll.contr_min_size
5056  && *(cur_coll->coll_ref.coll_contr_list_ref) == '\0'
5057  && memcmp (cur_coll->opt_coll.contr_list, comp_coll->opt_coll.contr_list,
5058  sizeof (COLL_CONTRACTION) * comp_coll->opt_coll.count_contr) == 0)
5059  {
5060  sprintf (cur_coll->coll_ref.coll_contr_list_ref, "%s_%s", "coll_contr_list",
5061  comp_coll->opt_coll.coll_name);
5062  PRINT_DUPLICATE_SYMBOL_NAME ("coll_contr_list", cur_coll, comp_coll, is_verbose);
5063  }
5064 
5065  if (cur_coll->opt_coll.cp_first_contr_offset == comp_coll->opt_coll.cp_first_contr_offset
5066  && cur_coll->opt_coll.cp_first_contr_count == comp_coll->opt_coll.cp_first_contr_count
5067  && *(cur_coll->coll_ref.coll_cp_first_contr_array_ref) == '\0'
5068  && memcmp (cur_coll->opt_coll.cp_first_contr_array, comp_coll->opt_coll.cp_first_contr_array,
5069  sizeof (comp_coll->opt_coll.cp_first_contr_array[0]) *
5070  comp_coll->opt_coll.w_count) == 0)
5071  {
5072  sprintf (cur_coll->coll_ref.coll_cp_first_contr_array_ref, "%s_%s",
5073  "coll_cp_first_contr_array", comp_coll->opt_coll.coll_name);
5074  PRINT_DUPLICATE_SYMBOL_NAME ("coll_cp_first_" "contr_array", cur_coll, comp_coll, is_verbose);
5075  }
5076  }
5077  }
5078  }
5079  }
5080  }
5081 #undef PRINT_DUPLICATE_SYMBOL_NAME
5082 }
5083 
5084 /*
5085  * locale_save_all_to_C_file - saves all locale data to C source file, for
5086  * later use when compiling them into a locale shared
5087  * library.
5088  *
5089  * return: error code
5090  * ld(in): locale data
5091  * start_index(in): starting index inside ld array for locales to export
5092  * loc_count(in): number of locales stored in the ld array
5093  * lf(in): locale file info
5094  */
5095 int
5096 locale_save_all_to_C_file (LOCALE_DATA ** ld, int start_index, int end_index, LOCALE_FILE * lf)
5097 {
5098  int er_status = NO_ERROR;
5099  int i;
5100 
5101  for (i = start_index; i < end_index; i++)
5102  {
5103  er_status = locale_save_to_C_file (lf[i], ld[i]);
5104  if (er_status != NO_ERROR)
5105  {
5106  break;
5107  }
5108  }
5109 
5110  return er_status;
5111 }
5112 
5113 /*
5114  * locale_get_cfg_locales() - reads the locale strings and file paths configured
5115  *
5116  * return: error code
5117  * locale_files(in/out):
5118  * p_num_locales(out): number of user defined locales
5119  * is_lang_init(in): true if this is called in context of lang initialization
5120  *
5121  * Note : This funtion is called in two contexts :
5122  * - language initialization (no error is set in this case)
5123  * - locale generation admin tool (error is generated)
5124  */
5125 int
5126 locale_get_cfg_locales (LOCALE_FILE ** p_locale_files, int *p_num_locales, bool is_lang_init)
5127 {
5128  char locale_cfg_file[PATH_MAX];
5129  char line[1024];
5130  FILE *fp = NULL;
5131  LOCALE_FILE *locale_files = NULL;
5132  int num_locales;
5133  int max_locales = 10;
5134  char msg[ERR_MSG_SIZE];
5135  int err_status = NO_ERROR;
5136 
5137  assert (p_locale_files != NULL);
5138  assert (p_num_locales != NULL);
5139 
5140  envvar_confdir_file (locale_cfg_file, sizeof (locale_cfg_file), "cubrid_locales.txt");
5141 
5142  fp = fopen_ex (locale_cfg_file, "rt");
5143  if (fp == NULL)
5144  {
5145  if (is_lang_init)
5146  {
5147  /* no error is recorded, 'cubrid_locales.txt' is optional */
5148  goto exit;
5149  }
5150  else
5151  {
5152  snprintf_dots_truncate (msg, sizeof (msg) - 1, "Cannot open file %s", locale_cfg_file);
5153  LOG_LOCALE_ERROR (msg, ER_LOC_GEN, true);
5154  err_status = ER_LOC_GEN;
5155  goto exit;
5156  }
5157  }
5158 
5159  locale_files = NULL;
5160  num_locales = 0;
5161 
5162  locale_files = (LOCALE_FILE *) malloc (max_locales * sizeof (LOCALE_FILE));
5163  if (locale_files == NULL)
5164  {
5165  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_INIT, true);
5166  err_status = ER_LOC_INIT;
5167  goto exit;
5168  }
5169 
5170  while (fgets (line, sizeof (line) - 1, fp) != NULL)
5171  {
5172  char *str, *next;
5173  LOCALE_FILE *loc;
5174 
5175  if (*line == '\0' || *line == '#' || char_isspace ((int) *line))
5176  {
5177  continue;
5178  }
5179 
5180  num_locales++;
5181 
5182  if (num_locales >= max_locales)
5183  {
5184  max_locales *= 2;
5185  LOCALE_FILE *const realloc_locale_files
5186  = (LOCALE_FILE *) realloc (locale_files, max_locales * sizeof (LOCALE_FILE));
5187  if (realloc_locale_files == NULL)
5188  {
5189  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_INIT, true);
5190  err_status = ER_LOC_INIT;
5191  goto exit;
5192  }
5193  else
5194  {
5195  locale_files = realloc_locale_files;
5196  }
5197  }
5198 
5199  loc = &(locale_files[num_locales - 1]);
5200  memset (loc, 0, sizeof (LOCALE_FILE));
5201 
5202  str = line;
5203  err_status = str_pop_token (str, &(loc->locale_name), &next);
5204  if (err_status != NO_ERROR)
5205  {
5206  goto exit;
5207  }
5208 
5209  if (next == NULL)
5210  {
5211  continue;
5212  }
5213 
5214  str = next;
5215  err_status = str_pop_token (str, &(loc->ldml_file), &next);
5216  if (err_status != NO_ERROR)
5217  {
5218  goto exit;
5219  }
5220 
5221  if (next == NULL)
5222  {
5223  continue;
5224  }
5225 
5226  str = next;
5227  err_status = str_pop_token (str, &(loc->lib_file), &next);
5228  if (err_status != NO_ERROR)
5229  {
5230  goto exit;
5231  }
5232  }
5233 
5234  *p_locale_files = locale_files;
5235  *p_num_locales = num_locales;
5236 
5237 exit:
5238  if (fp != NULL)
5239  {
5240  fclose (fp);
5241  }
5242 
5243  return err_status;
5244 }
5245 
5246 /*
5247  * locale_check_and_set_default_files() - checks if the files for locale is set
5248  * if not set, the default file paths are
5249  * computed
5250  *
5251  * return:
5252  * lf(in/out):
5253  * is_lang_init(in): true if this is called in context of lang initialization
5254  *
5255  * Note : This funtion is called in two contexts :
5256  * - language initialization (no error is set in this case)
5257  * - locale generation admin tool (error is generated)
5258  */
5259 int
5261 {
5262  bool is_alloc_ldml_file = false;
5263  bool is_alloc_lib_file = false;
5264  int er_status = NO_ERROR;
5265 
5266  assert (lf != NULL);
5267 
5268  if (lf->locale_name == NULL || strlen (lf->locale_name) > LOC_LOCALE_STR_SIZE)
5269  {
5270  er_status = is_lang_init ? ER_LOC_INIT : ER_LOC_GEN;
5271  LOG_LOCALE_ERROR ("invalid locale name in 'cubrid_locales.txt'", er_status, true);
5272  goto error;
5273  }
5274 
5275  if (lf->ldml_file == NULL || *(lf->ldml_file) == '\0' || *(lf->ldml_file) == '*')
5276  {
5277  /* generate name for LDML file */
5278  char ldml_short_file[LOC_LOCALE_STR_SIZE + 13];
5279 
5280  snprintf (ldml_short_file, sizeof (ldml_short_file) - 1, "cubrid_%s.xml", lf->locale_name);
5281  ldml_short_file[sizeof (ldml_short_file) - 1] = '\0';
5282 
5283  if (lf->ldml_file != NULL)
5284  {
5285  free (lf->ldml_file);
5286  }
5287 
5288  lf->ldml_file = (char *) malloc (PATH_MAX + 1);
5289  if (lf->ldml_file == NULL)
5290  {
5291  er_status = is_lang_init ? ER_LOC_INIT : ER_LOC_GEN;
5292  LOG_LOCALE_ERROR ("memory allocation failed", er_status, true);
5293  goto error;
5294  }
5295 
5296  is_alloc_ldml_file = true;
5297  envvar_ldmldir_file (lf->ldml_file, PATH_MAX, ldml_short_file);
5298  }
5299 
5300  if (lf->lib_file == NULL || *(lf->lib_file) == '\0' || *(lf->lib_file) == '*')
5301  {
5302  /* generate name for locale lib file */
5303  char lib_short_file[PATH_MAX];
5304 
5305  snprintf (lib_short_file, sizeof (lib_short_file) - 1, "libcubrid_%s.%s", lf->locale_name, LOCLIB_FILE_EXT);
5306  lib_short_file[sizeof (lib_short_file) - 1] = '\0';
5307 
5308  if (lf->lib_file != NULL)
5309  {
5310  free (lf->lib_file);
5311  }
5312 
5313  lf->lib_file = (char *) malloc (PATH_MAX + 1);
5314  if (lf->lib_file == NULL)
5315  {
5316  er_status = is_lang_init ? ER_LOC_INIT : ER_LOC_GEN;
5317  LOG_LOCALE_ERROR ("memory allocation failed", er_status, true);
5318  goto error;
5319  }
5320 
5321  is_alloc_lib_file = true;
5322  envvar_libdir_file (lf->lib_file, PATH_MAX, lib_short_file);
5323 
5324  if (is_lang_init)
5325  {
5326  FILE *fp;
5327 
5328  /* check that default lib file exists, otherwise switch to the common libray locale */
5329  fp = fopen_ex (lf->lib_file, "rb");
5330  if (fp == NULL)
5331  {
5332  snprintf (lib_short_file, sizeof (lib_short_file) - 1, "libcubrid_all_locales.%s", LOCLIB_FILE_EXT);
5333  lib_short_file[sizeof (lib_short_file) - 1] = '\0';
5334 
5335  assert (lf->lib_file != NULL);
5336 
5337  envvar_libdir_file (lf->lib_file, PATH_MAX, lib_short_file);
5338  }
5339  else
5340  {
5341  fclose (fp);
5342  }
5343  }
5344  }
5345 
5346  return NO_ERROR;
5347 
5348 error:
5349 
5350  if (is_alloc_ldml_file)
5351  {
5352  free (lf->ldml_file);
5353  lf->ldml_file = NULL;
5354  }
5355 
5356  if (is_alloc_lib_file)
5357  {
5358  free (lf->lib_file);
5359  lf->lib_file = NULL;
5360  }
5361  return er_status;
5362 }
5363 
5364 /*
5365  * save_contraction_to_C_file() - saves collation contraction data to C file
5366  *
5367  * return: zero if save is successful, non-zero otherwise
5368  * fp(in): file descriptor
5369  * c(in): contraction to save
5370  * use_expansion(in):
5371  * use_level_4(in):
5372  */
5373 static int
5374 save_contraction_to_C_file (FILE * fp, COLL_CONTRACTION * c, bool use_expansion, bool use_level_4)
5375 {
5376  assert (c != NULL);
5377  assert (fp != NULL);
5378 
5379  fprintf (fp, "\t{\n");
5380  fprintf (fp, "\t\t%u, \n", c->next);
5381  fprintf (fp, "\t\t%u, \n", c->wv);
5382 
5383  if (use_expansion)
5384  {
5385  assert (c->uca_num > 0 || c->uca_num <= MAX_UCA_EXP_CE);
5386 
5387  PRINT_UNNAMED_NUM_ARRAY_TO_C_FILE (fp, "%uu", "\t\t", c->uca_num, c->uca_w_l13);
5388  fprintf (fp, ",\n");
5389 
5390  if (use_level_4)
5391  {
5392  PRINT_UNNAMED_NUM_ARRAY_TO_C_FILE (fp, "%u", "\t\t", c->uca_num, c->uca_w_l4);
5393  }
5394  else
5395  {
5396  fprintf (fp, "\t\t{ 0 }");
5397  }
5398  }
5399  else
5400  {
5401  fprintf (fp, "\t\t{ 0 },\n\t\t{ 0 }");
5402  }
5403 
5404  fprintf (fp, ",\n\t\t");
5405  PRINT_STRING_TO_C_FILE (fp, c->c_buf, strlen (c->c_buf));
5406  fprintf (fp, ", \n");
5407  fprintf (fp, "\t\t%u, \n", c->cp_count);
5408  fprintf (fp, "\t\t%u, \n", c->size);
5409  fprintf (fp, "\t\t%u \n", c->uca_num);
5410 
5411  fprintf (fp, "} \n");
5412 
5413  return 0;
5414 }
5415 
5416 /*
5417  * locale_prepare_C_file() - saves locale data to C source file, for
5418  * later use when generating the locale shared
5419  * library.
5420  *
5421  * return: error code
5422  * lf(in): locale file info
5423  * ld(in): locale data
5424  * c_file_path(in): the path to where to write the C file
5425  */
5426 int
5428 {
5429  FILE *fp;
5430  char c_file_path[PATH_MAX];
5431  char err_msg[ERR_MSG_SIZE];
5432 
5433  envvar_loclib_dir_file (c_file_path, sizeof (c_file_path), "locale.c");
5434 
5435  fp = fopen_ex (c_file_path, "w");
5436  if (fp == NULL)
5437  {
5438  goto error;
5439  }
5440  fprintf (fp, "/* GENERATED FILE - DO NOT EDIT */\n");
5441 
5442 #if defined(WINDOWS)
5443  fprintf (fp, "#include <stdio.h>\n");
5444 #else
5445  fprintf (fp, "#include <stddef.h>\n");
5446 #endif
5447  fprintf (fp, "#include \"locale_lib_common.h\"\n\n");
5448  fclose (fp);
5449  return 0;
5450 error:
5451  snprintf_dots_truncate (err_msg, sizeof (err_msg) - 1, "Error opening file %s for rewrite.", c_file_path);
5452  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
5453  return ER_GENERIC_ERROR;
5454 }
5455 
5456 /*
5457  * locale_save_to_C_file() - saves locale data to C source file, for
5458  * later use when generating the locale shared
5459  * library.
5460  *
5461  * return: error code
5462  * lf(in): locale file info
5463  * ld(in): locale data
5464  */
5465 static int
5467 {
5468  FILE *fp;
5469  char c_file_path[PATH_MAX];
5470  char err_msg[ERR_MSG_SIZE];
5471  int i;
5472 
5473  assert (ld != NULL);
5474 
5475  envvar_loclib_dir_file (c_file_path, sizeof (c_file_path), "locale.c");
5476 
5477  fp = fopen_ex (c_file_path, "a");
5478  if (fp == NULL)
5479  {
5480  goto error;
5481  }
5482  fprintf (fp, "/*\n * %s - generated from %s \n *\n */\n", ld->locale_name, lf.ldml_file);
5483 
5484  PRINT_STRING_VAR_TO_C_FILE (fp, "locale_name", ld->locale_name, ld->locale_name);
5485 
5487 
5488  PRINT_VAR_TO_C_FILE (fp, "char", "number_decimal_sym", ld->number_decimal_sym, "'%c'", ld->locale_name);
5489  PRINT_VAR_TO_C_FILE (fp, "char", "number_group_sym", ld->number_group_sym, "'%c'", ld->locale_name);
5490  PRINT_VAR_TO_C_FILE (fp, "int", "default_currency_code", ld->default_currency_code, "%d", ld->locale_name);
5491 
5493 
5494  /* number of collation associated with this locale */
5495  PRINT_VAR_TO_C_FILE (fp, "int", "count_coll", ld->coll_cnt, "%d", ld->locale_name);
5496 
5497  for (i = 0; i < ld->coll_cnt; i++)
5498  {
5499  char coll_suffix[ERR_MSG_SIZE];
5500 
5501  /* Collation names are user defined: first save fixed name variables containing collations name included in the
5502  * LDML: collation_1_es_ES = "utf8_es_ES"; collation_2_es_ES = "utf8_es_ES_ci"; */
5503  snprintf (coll_suffix, sizeof (coll_suffix) - 1, "%d_%s", i, ld->locale_name);
5504  PRINT_STRING_VAR_TO_C_FILE (fp, "collation", ld->collations[i].opt_coll.coll_name, coll_suffix);
5505 
5506  if (ld->collations[i].do_not_save)
5507  {
5508  continue;
5509  }
5510 
5511  /* the collation data is decorated with the user defined name of the collation : coll_weights_utf8_es_ES = { ..
5512  * }; coll_weights_utf8_es_ES_ci = { .. }; */
5514  }
5515 
5517 
5519 
5520  PRINT_STRING_VAR_TO_C_FILE (fp, "locale_checksum", ld->checksum, ld->locale_name);
5521 
5522  fclose (fp);
5523  return 0;
5524 
5525 error:
5526  snprintf_dots_truncate (err_msg, sizeof (err_msg) - 1, "Error opening file %s for append.", c_file_path);
5527  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
5528  return ER_GENERIC_ERROR;
5529 }
5530 
5531 /*
5532  * locale_save_calendar_to_C_file() - saves calendar data to C source file,
5533  * as variables, for later use when generating the
5534  * locale shared library.
5535  *
5536  * return: error code
5537  * fp(in): file pointer where to write the data
5538  * ld(in): locale data
5539  */
5540 static int
5542 {
5543  assert (ld != NULL);
5544  assert (fp != NULL);
5545 
5546  /* calendar format strings */
5547  PRINT_STRING_VAR_TO_C_FILE (fp, "date_format", ld->dateFormat, ld->locale_name);
5548  PRINT_STRING_VAR_TO_C_FILE (fp, "time_format", ld->timeFormat, ld->locale_name);
5549  PRINT_STRING_VAR_TO_C_FILE (fp, "datetime_format", ld->datetimeFormat, ld->locale_name);
5550  PRINT_STRING_VAR_TO_C_FILE (fp, "timestamp_format", ld->timestampFormat, ld->locale_name);
5551  PRINT_STRING_VAR_TO_C_FILE (fp, "timetz_format", ld->timetzFormat, ld->locale_name);
5552  PRINT_STRING_VAR_TO_C_FILE (fp, "datetimetz_format", ld->datetimetzFormat, ld->locale_name);
5553  PRINT_STRING_VAR_TO_C_FILE (fp, "timestamptz_format", ld->timestamptzFormat, ld->locale_name);
5554 
5555  /* calendar data arrays */
5556  PRINT_STRING_ARRAY_TO_C_FILE (fp, "month_names_abbreviated", CAL_MONTH_COUNT, ld->month_names_abbreviated,
5557  ld->locale_name);
5558  PRINT_STRING_ARRAY_TO_C_FILE (fp, "month_names_wide", CAL_MONTH_COUNT, ld->month_names_wide, ld->locale_name);
5559  PRINT_STRING_ARRAY_TO_C_FILE (fp, "day_names_abbreviated", CAL_DAY_COUNT, ld->day_names_abbreviated, ld->locale_name);
5560  PRINT_STRING_ARRAY_TO_C_FILE (fp, "day_names_wide", CAL_DAY_COUNT, ld->day_names_wide, ld->locale_name);
5562 
5563  /* calendar parse order arrays */
5564  PRINT_NUM_ARRAY_TO_C_FILE (fp, "day_names_abbr_parse_order", "char", "%u", CAL_DAY_COUNT,
5566  PRINT_NUM_ARRAY_TO_C_FILE (fp, "day_names_wide_parse_order", "char", "%u", CAL_DAY_COUNT,
5568  PRINT_NUM_ARRAY_TO_C_FILE (fp, "month_names_abbr_parse_order", "char", "%u", CAL_MONTH_COUNT,
5570  PRINT_NUM_ARRAY_TO_C_FILE (fp, "month_names_wide_parse_order", "char", "%u", CAL_MONTH_COUNT,
5572  PRINT_NUM_ARRAY_TO_C_FILE (fp, "am_pm_parse_order", "char", "%u", CAL_AM_PM_COUNT, ld->am_pm_parse_order,
5573  ld->locale_name);
5574 
5575  return 0;
5576 }
5577 
5578 /*
5579  * locale_save_alphabets_to_C_file() - saves alphabet and identifier alphabet
5580  * to C source file as variables, for later use
5581  * when generating the locale shared library.
5582  *
5583  * return: error code
5584  * fp(in): file pointer where to write the data
5585  * a(in): alphabet data
5586  * save_w_identier_name(in): true if alphabet is to be saved as "identifier"
5587  * name
5588  * alpha_suffix(in): suffix to be applied to variables names
5589  */
5590 static int
5591 locale_save_one_alphabet_to_C_file (FILE * fp, ALPHABET_DATA * a, bool save_w_identier_name, const char *alpha_suffix)
5592 {
5593  assert (a != NULL);
5594  assert (fp != NULL);
5595 
5596  if (save_w_identier_name)
5597  {
5598  PRINT_VAR_TO_C_FILE (fp, "int", "ident_alphabet_l_count", a->l_count, "%d", alpha_suffix);
5599 
5600  PRINT_VAR_TO_C_FILE (fp, "int", "ident_alphabet_lower_multiplier", a->lower_multiplier, "%d", alpha_suffix);
5601  PRINT_VAR_TO_C_FILE (fp, "int", "ident_alphabet_upper_multiplier", a->upper_multiplier, "%d", alpha_suffix);
5602  PRINT_NUM_ARRAY_TO_C_FILE (fp, "ident_alphabet_lower_cp", "unsigned int", "%u", a->l_count * a->lower_multiplier,
5603  a->lower_cp, alpha_suffix);
5604  PRINT_NUM_ARRAY_TO_C_FILE (fp, "ident_alphabet_upper_cp", "unsigned int", "%u", a->l_count * a->upper_multiplier,
5605  a->upper_cp, alpha_suffix);
5606  }
5607  else
5608  {
5609  PRINT_VAR_TO_C_FILE (fp, "int", "alphabet_l_count", a->l_count, "%d", alpha_suffix);
5610  PRINT_VAR_TO_C_FILE (fp, "int", "alphabet_lower_multiplier", a->lower_multiplier, "%d", alpha_suffix);
5611  PRINT_VAR_TO_C_FILE (fp, "int", "alphabet_upper_multiplier", a->upper_multiplier, "%d", alpha_suffix);
5612  PRINT_NUM_ARRAY_TO_C_FILE (fp, "alphabet_lower_cp", "unsigned int", "%u", a->l_count * a->lower_multiplier,
5613  a->lower_cp, alpha_suffix);
5614  PRINT_NUM_ARRAY_TO_C_FILE (fp, "alphabet_upper_cp", "unsigned int", "%u", a->l_count * a->upper_multiplier,
5615  a->upper_cp, alpha_suffix);
5616  }
5617 
5618  return 0;
5619 }
5620 
5621 /*
5622  * locale_save_alphabets_to_C_file() - saves alphabet and identifier alphabet
5623  * to C source file as variables, for later use
5624  * when generating the locale shared library.
5625  *
5626  * return: error code
5627  * fp(in): file pointer where to write the data
5628  * ld(in): locale data
5629  */
5630 static int
5632 {
5633  assert (ld != NULL);
5634  assert (fp != NULL);
5635 
5636  /* alphabet data */
5637  PRINT_VAR_TO_C_FILE (fp, "int", "alphabet_a_type", ld->alphabet.a_type, "%d", ld->locale_name);
5638 
5639  if (!(ld->alphabet.do_not_save))
5640  {
5641  const char *alpha_suffix;
5642 
5643  if (ld->alphabet.a_type == ALPHABET_UNICODE)
5644  {
5645  alpha_suffix = "unicode";
5646  }
5647  else if (ld->alphabet.a_type == ALPHABET_ASCII)
5648  {
5649  alpha_suffix = "ascii";
5650  }
5651  else
5652  {
5653  alpha_suffix = (const char *) (ld->locale_name);
5654  }
5655 
5656  (void) locale_save_one_alphabet_to_C_file (fp, &(ld->alphabet), false, alpha_suffix);
5657  }
5658 
5659  /* identifier alphabet data */
5660  PRINT_VAR_TO_C_FILE (fp, "int", "ident_alphabet_a_type", ld->identif_alphabet.a_type, "%d", ld->locale_name);
5661 
5662  if (!(ld->identif_alphabet.do_not_save))
5663  {
5664  const char *alpha_suffix;
5665  bool save_w_identif = false;
5666 
5668  {
5669  alpha_suffix = "unicode";
5670  }
5671  else if (ld->identif_alphabet.a_type == ALPHABET_ASCII)
5672  {
5673  alpha_suffix = "ascii";
5674  }
5675  else
5676  {
5677  alpha_suffix = (const char *) (ld->locale_name);
5678  save_w_identif = true;
5679  }
5680 
5681  (void) locale_save_one_alphabet_to_C_file (fp, &(ld->identif_alphabet), save_w_identif, alpha_suffix);
5682  }
5683 
5684  return 0;
5685 }
5686 
5687 /*
5688  * locale_save_collation_data_to_C_file() - saves collation data to C source
5689  * file as variables, for later use when generating
5690  * the locale shared library.
5691  *
5692  * return: error code
5693  * fp(in): file pointer where to write the data
5694  * cd(in): collation data
5695  */
5696 static int
5698 {
5699  int i;
5700  COLL_DATA *cd = NULL;
5701 
5702  assert (lc != NULL);
5703  assert (fp != NULL);
5704 
5705  cd = &(lc->opt_coll);
5706 
5707  /* collation constants */
5708  PRINT_VAR_TO_C_FILE (fp, "int", "coll_id", cd->coll_id, "%d", cd->coll_name);
5709  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_name", cd->coll_name, cd->coll_name);
5710 
5711  /* OPT_COLL.UCA_OPT members */
5712  PRINT_VAR_TO_C_FILE (fp, "int", "coll_sett_strength", cd->uca_opt.sett_strength, "%d", cd->coll_name);
5713  PRINT_VAR_TO_C_FILE (fp, "int", "coll_sett_backwards", cd->uca_opt.sett_backwards ? 1 : 0, "%d", cd->coll_name);
5714  PRINT_VAR_TO_C_FILE (fp, "int", "coll_sett_caseLevel", cd->uca_opt.sett_caseLevel ? 1 : 0, "%d", cd->coll_name);
5715  PRINT_VAR_TO_C_FILE (fp, "int", "coll_sett_caseFirst", cd->uca_opt.sett_caseFirst, "%d", cd->coll_name);
5716  PRINT_VAR_TO_C_FILE (fp, "int", "coll_sett_expansions", cd->uca_opt.sett_expansions ? 1 : 0, "%d", cd->coll_name);
5717  PRINT_VAR_TO_C_FILE (fp, "int", "coll_sett_contr_policy", cd->uca_opt.sett_contr_policy, "%d", cd->coll_name);
5718  PRINT_VAR_TO_C_FILE (fp, "int", "coll_match_contr", cd->uca_opt.sett_match_contr, "%d", cd->coll_name);
5719 
5720  /* other OPT_COLL members */
5721  PRINT_VAR_TO_C_FILE (fp, "int", "coll_w_count", cd->w_count, "%d", cd->coll_name);
5722  PRINT_VAR_TO_C_FILE (fp, "int", "coll_uca_exp_num", cd->uca_exp_num, "%d", cd->coll_name);
5723  PRINT_VAR_TO_C_FILE (fp, "int", "coll_count_contr", cd->count_contr, "%d", cd->coll_name);
5724 
5725  /* OPT_COLL pointer and array members */
5726  if (cd->w_count > 0)
5727  {
5728  if (!(cd->uca_opt.sett_expansions))
5729  {
5730  if (*(lc->coll_ref.coll_weights_ref) == '\0')
5731  {
5732  sprintf (lc->coll_ref.coll_weights_ref, "coll_weights_%s", cd->coll_name);
5733  PRINT_NUM_ARRAY_TO_C_FILE (fp, "coll_weights", "unsigned int", "%u", cd->w_count, cd->weights,
5734  cd->coll_name);
5735  }
5736  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_weights_ref", lc->coll_ref.coll_weights_ref, cd->coll_name);
5737  }
5738  else
5739  {
5740  assert (cd->uca_exp_num > 1);
5741 
5742  if (*(lc->coll_ref.coll_uca_w_l13_ref) == '\0')
5743  {
5744  sprintf (lc->coll_ref.coll_uca_w_l13_ref, "coll_uca_w_l13_%s", cd->coll_name);
5745  PRINT_NUM_ARRAY_TO_C_FILE (fp, "coll_uca_w_l13", "unsigned int", "%u", cd->uca_exp_num * cd->w_count,
5746  cd->uca_w_l13, cd->coll_name);
5747  }
5748  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_uca_w_l13_ref", lc->coll_ref.coll_uca_w_l13_ref, cd->coll_name);
5749 
5751  {
5752  if (*(lc->coll_ref.coll_uca_w_l4_ref) == '\0')
5753  {
5754  sprintf (lc->coll_ref.coll_uca_w_l4_ref, "coll_uca_w_l4_%s", cd->coll_name);
5755  PRINT_NUM_ARRAY_TO_C_FILE (fp, "coll_uca_w_l4", "unsigned short", "%u", cd->uca_exp_num * cd->w_count,
5756  cd->uca_w_l4, cd->coll_name);
5757  }
5758  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_uca_w_l4_ref", lc->coll_ref.coll_uca_w_l4_ref, cd->coll_name);
5759  }
5760 
5761  if (*(lc->coll_ref.coll_uca_num_ref) == '\0')
5762  {
5763  sprintf (lc->coll_ref.coll_uca_num_ref, "coll_uca_num_%s", cd->coll_name);
5764  PRINT_NUM_ARRAY_TO_C_FILE (fp, "coll_uca_num", "char", "%d", cd->w_count, cd->uca_num, cd->coll_name);
5765  }
5766  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_uca_num_ref", lc->coll_ref.coll_uca_num_ref, cd->coll_name);
5767  }
5768 
5769  if (*(lc->coll_ref.coll_next_cp_ref) == '\0')
5770  {
5771  sprintf (lc->coll_ref.coll_next_cp_ref, "coll_next_cp_%s", cd->coll_name);
5772  PRINT_NUM_ARRAY_TO_C_FILE (fp, "coll_next_cp", "unsigned int", "%u", cd->w_count, cd->next_cp, cd->coll_name);
5773  }
5774  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_next_cp_ref", lc->coll_ref.coll_next_cp_ref, cd->coll_name);
5775  }
5776 
5777  if (cd->count_contr > 0)
5778  {
5779  PRINT_VAR_TO_C_FILE (fp, "int", "coll_contr_min_size", cd->contr_min_size, "%d", cd->coll_name);
5780  PRINT_VAR_TO_C_FILE (fp, "unsigned int", "coll_cp_first_contr_offset", cd->cp_first_contr_offset, "%u",
5781  cd->coll_name);
5782  PRINT_VAR_TO_C_FILE (fp, "unsigned int", "coll_cp_first_contr_count", cd->cp_first_contr_count, "%u",
5783  cd->coll_name);
5784 
5785  if (*(lc->coll_ref.coll_contr_list_ref) == '\0')
5786  {
5787  sprintf (lc->coll_ref.coll_contr_list_ref, "coll_contr_list_%s", cd->coll_name);
5788  fprintf (fp, "" DLL_EXPORT_PREFIX "const COLL_CONTRACTION coll_contr_list_%s[] = {", cd->coll_name);
5789  for (i = 0; i < cd->count_contr; i++)
5790  {
5791  fprintf (fp, "\n");
5794  if (i < cd->count_contr - 1)
5795  {
5796  fprintf (fp, ", ");
5797  }
5798  }
5799  fprintf (fp, "};\n");
5800  }
5801  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_contr_list_ref", lc->coll_ref.coll_contr_list_ref, cd->coll_name);
5802 
5803  if (*(lc->coll_ref.coll_cp_first_contr_array_ref) == '\0')
5804  {
5805  sprintf (lc->coll_ref.coll_cp_first_contr_array_ref, "coll_cp_first_contr_array_%s", cd->coll_name);
5806  PRINT_NUM_ARRAY_TO_C_FILE (fp, "coll_cp_first_contr_array", "int", "%d", (int) cd->cp_first_contr_count,
5807  cd->cp_first_contr_array, cd->coll_name);
5808  }
5809  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_cp_first_contr_array_ref", lc->coll_ref.coll_cp_first_contr_array_ref,
5810  cd->coll_name);
5811 
5812  }
5813 
5814  PRINT_STRING_VAR_TO_C_FILE (fp, "coll_checksum", cd->checksum, cd->coll_name);
5815  return 0;
5816 }
5817 
5818 /*
5819  * locale_save_console_conv_to_C_file() - saves console conversion data to
5820  * binary file
5821  *
5822  * return: zero if save is successful, non-zero otherwise
5823  * fp(in): file descriptor
5824  * tc(in): console conversion info
5825  */
5826 static int
5828 {
5829  int i;
5830 
5831  TEXT_CONVERSION *tc;
5832 
5833  assert (ld != NULL);
5834  assert (fp != NULL);
5835 
5836  tc = &(ld->txt_conv);
5837 
5838  /* TEXT_CONVERSION non-array members */
5839  PRINT_VAR_TO_C_FILE (fp, "int", "tc_conv_type", tc->conv_type, "%d", ld->locale_name);
5840 
5842  {
5843  return 0;
5844  }
5845 
5846  PRINT_NUM_ARRAY_TO_C_FILE (fp, "tc_is_lead_byte", "unsigned char", "%u", 256, tc->byte_flag, ld->locale_name);
5847  PRINT_VAR_TO_C_FILE (fp, "unsigned int", "tc_utf8_first_cp", tc->utf8_first_cp, "%u", ld->locale_name);
5848  PRINT_VAR_TO_C_FILE (fp, "unsigned int", "tc_utf8_last_cp", tc->utf8_last_cp, "%u", ld->locale_name);
5849  PRINT_VAR_TO_C_FILE (fp, "unsigned int", "tc_text_first_cp", tc->text_first_cp, "%u", ld->locale_name);
5850  PRINT_VAR_TO_C_FILE (fp, "unsigned int", "tc_text_last_cp", tc->text_last_cp, "%u", ld->locale_name);
5851 
5852  assert (tc->win_codepages != NULL);
5853  PRINT_STRING_VAR_TO_C_FILE (fp, "tc_win_codepages", tc->win_codepages, ld->locale_name);
5854 
5855  assert (tc->nl_lang_str != NULL);
5856  PRINT_STRING_VAR_TO_C_FILE (fp, "tc_nl_lang_str", tc->nl_lang_str, ld->locale_name);
5857 
5858  assert (tc->utf8_last_cp > tc->utf8_first_cp);
5859  assert (tc->utf8_to_text != NULL);
5860 
5861  fprintf (fp, "" DLL_EXPORT_PREFIX "const CONV_CP_TO_BYTES tc_utf8_to_text_%s[] = { \n", ld->locale_name);
5862  for (i = 0; i < (int) (tc->utf8_last_cp - tc->utf8_first_cp + 1); i++)
5863  {
5864  fprintf (fp, "{ %u, ", tc->utf8_to_text[i].size);
5866  fprintf (fp, "},\n");
5867  }
5868  fprintf (fp, "};\n");
5869 
5870  assert (tc->text_last_cp > tc->text_first_cp);
5871  assert (tc->text_to_utf8 != NULL);
5872 
5873  fprintf (fp, "" DLL_EXPORT_PREFIX "const CONV_CP_TO_BYTES tc_text_to_utf8_%s[] = { \n", ld->locale_name);
5874  for (i = 0; i < (int) (tc->text_last_cp - tc->text_first_cp + 1); i++)
5875  {
5876  fprintf (fp, "{ %u, ", tc->text_to_utf8[i].size);
5878  fprintf (fp, "},\n");
5879  }
5880  fprintf (fp, "};\n");
5881 
5882  return 0;
5883 }
5884 
5885 /*
5886  * str_pop_token() - Extracts a token from a string;
5887  * A token is a sub-string surrounded by whitespaces.
5888  * return: string token
5889  * str_p(in): buffer with tokens
5890  * token_p(in/out): returned token string
5891  * next_p(in/out): pointer to next token or NULL if no more tokens
5892  *
5893  * Note : When found the token characters are copied into a new string
5894  * and returned.
5895  * The pointer to the first character following the new token in
5896  * the buffer is returned.
5897  */
5898 static int
5899 str_pop_token (char *str_p, char **token_p, char **next_p)
5900 {
5901  char *p, *end, *token = NULL;
5902  int length;
5903 
5904  assert (str_p != NULL);
5905  assert (token_p != NULL);
5906  assert (next_p != NULL);
5907 
5908  p = str_p;
5909  while (char_isspace ((int) *p) && *p != '\0')
5910  {
5911  p++;
5912  }
5913  end = p;
5914  while (!char_isspace ((int) *end) && *end != '\0')
5915  {
5916  end++;
5917  }
5918 
5919  length = (int) (end - p);
5920  if (length > 0)
5921  {
5922  token = (char *) malloc (length + 1);
5923  if (token == NULL)
5924  {
5925  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_INIT, true);
5926  return ER_LOC_INIT;
5927  }
5928  assert (token != NULL);
5929 
5930  strncpy (token, p, length);
5931  token[length] = '\0';
5932  }
5933  else
5934  {
5935  /* no more tokens */
5936  end = NULL;
5937  }
5938 
5939  *token_p = token;
5940  *next_p = end;
5941  return NO_ERROR;
5942 }
5943 
5944 /*
5945  * dump_locale_alphabet - dump the selected ALPHABET_DATA structure
5946  * in human-readable text format.
5947  * Returns : NO_ERROR.
5948  * ad(in) : the ALPHABET_DATA to be dumped in text format.
5949  * dl_settings(in): the commmand line options encoded intoa binary masked int.
5950  * lower_bound(in): the starting codepoint for the range of items which
5951  * -w or -c will dump.
5952  * upper_bound(in) : the ending codepoint for the range of items which
5953  * -w or -c will dump.
5954  */
5955 static int
5956 dump_locale_alphabet (ALPHABET_DATA * ad, int dl_settings, int lower_bound, int upper_bound)
5957 {
5958 #define DUMP_CP_BUF_SIZE 128
5959  int i, cp;
5960  unsigned char utf8_buf[INTL_UTF8_MAX_CHAR_SIZE + 1];
5961  unsigned int *case_buf;
5962  char out_case[DUMP_CP_BUF_SIZE];
5963  char out_cp[DUMP_CP_BUF_SIZE];
5964 
5965  assert (ad != NULL);
5966  assert (lower_bound <= upper_bound);
5967 
5968  printf ("Alphabet type: ");
5969  if (ad->a_type == ALPHABET_UNICODE)
5970  {
5971  printf ("Unicode\n");
5972  }
5973  else if (ad->a_type == ALPHABET_ASCII)
5974  {
5975  printf ("ASCII\n");
5976  }
5977  else
5978  {
5979  assert (ad->a_type == ALPHABET_TAILORED);
5980  printf ("Tailored\n");
5981  }
5982 
5983  printf ("Letter count: %d\n", ad->l_count);
5984  if (ad->l_count > 0)
5985  {
5986  printf ("Lower multiplier: %d\n", ad->lower_multiplier);
5987  printf ("Upper multiplier: %d\n", ad->upper_multiplier);
5988  }
5989 
5990  for (cp = lower_bound; cp < upper_bound; cp++)
5991  {
5992  memset (utf8_buf, 0, INTL_UTF8_MAX_CHAR_SIZE + 1);
5993  intl_cp_to_utf8 (cp, utf8_buf);
5994  printf ("CP: Ux%04X | %-4s", cp, (cp > 0x0020 ? utf8_buf : (unsigned char *) ""));
5995  if ((dl_settings & DUMPLOCALE_IS_ALPHABET_LOWER) != 0)
5996  {
5997  bool print_case = true;
5998  memset (out_cp, 0, sizeof (out_cp));
5999  memset (out_case, 0, sizeof (out_case));
6000 
6001  case_buf = &(ad->lower_cp[cp * ad->lower_multiplier]);
6002 
6003  for (i = 0; i < ad->lower_multiplier; i++)
6004  {
6005  char temp_cp[8];
6006 
6007  if (case_buf[i] == 0)
6008  {
6009  break;
6010  }
6011 
6012  if (case_buf[i] < 0x20)
6013  {
6014  print_case = false;
6015  }
6016  memset (utf8_buf, 0, sizeof (utf8_buf));
6017  intl_cp_to_utf8 (case_buf[i], utf8_buf);
6018  strcat (out_case, (char *) utf8_buf);
6019  snprintf (temp_cp, sizeof (temp_cp) - 1, "Ux%04X", case_buf[i]);
6020  strcat (out_cp, temp_cp);
6021  }
6022  printf (" | Lower : CP(s): %-12s, lower char(s): %-12s", out_cp, (print_case ? out_case : ""));
6023  }
6024  if ((dl_settings & DUMPLOCALE_IS_ALPHABET_UPPER) != 0)
6025  {
6026  bool print_case = true;
6027  memset (out_cp, 0, sizeof (out_cp));
6028  memset (out_case, 0, sizeof (out_case));
6029 
6030  case_buf = &(ad->upper_cp[cp * ad->upper_multiplier]);
6031 
6032  for (i = 0; i < ad->upper_multiplier; i++)
6033  {
6034  char temp_cp[8];
6035 
6036  if (case_buf[i] == 0)
6037  {
6038  break;
6039  }
6040 
6041  if (case_buf[i] < 0x20)
6042  {
6043  print_case = false;
6044  }
6045 
6046  memset (utf8_buf, 0, sizeof (utf8_buf));
6047  intl_cp_to_utf8 (case_buf[i], utf8_buf);
6048  strcat (out_case, (char *) utf8_buf);
6049  snprintf (temp_cp, sizeof (temp_cp) - 1, "Ux%04X", case_buf[i]);
6050  strcat (out_cp, temp_cp);
6051  }
6052  printf (" | Upper : CP(s): %-12s, upper char(s): %-12s", out_cp, (print_case ? out_case : ""));
6053  }
6054  printf ("\n");
6055  }
6056  return NO_ERROR;
6057 }
6058 
6059 /*
6060  * dump_locale_collation - dump the selected COLL_DATA structure
6061  * in human-readable text format.
6062  * Returns : NO_ERROR.
6063  * coll(in) : the COLL_DATA to be dumped in text format.
6064  * dl_settings(in): the commmand line options encoded intoa binary masked int.
6065  * lower_bound(in): the starting codepoint for the range of items which
6066  * -w or -c will dump.
6067  * upper_bound(in) : the ending codepoint for the range of items which
6068  * -w or -c will dump.
6069  */
6070 static int
6071 dump_locale_collation (COLL_DATA * coll, int dl_settings, int start_value, int end_value)
6072 {
6073  unsigned int *coll_key_list = NULL;
6074  int coll_key_list_cnt = 0;
6075  int lower_bound = 0;
6076  int upper_bound = 0;
6077  int err_status = NO_ERROR;
6078  int cp, i;
6079 
6080  assert (coll != NULL);
6081 
6082  lower_bound = 0;
6083  upper_bound = coll->w_count;
6084  if (start_value > lower_bound)
6085  {
6086  lower_bound = start_value;
6087  }
6088  if (end_value > 0 && end_value < upper_bound)
6089  {
6090  /* if an upper bound is specified, use the "+1" to make sure that the upper bound codepoint is included in the
6091  * dump file. */
6092  upper_bound = end_value + 1;
6093  }
6094 
6095  printf ("\n");
6096  printf ("* Collation: %s | id: %d | checksum: %s *\n", coll->coll_name, coll->coll_id, coll->checksum);
6097  printf ("Max codepoints: %d\n", coll->w_count);
6098  printf ("Level: %d\n", coll->uca_opt.sett_strength);
6099  printf ("Expansions: %s\n", coll->uca_opt.sett_expansions ? "yes" : "no");
6100  if (coll->uca_opt.sett_expansions)
6101  {
6102  printf ("Expansion CE num: %d\n", coll->uca_exp_num);
6103  }
6104  printf ("Contractions: %d\n", coll->count_contr);
6105  if (coll->count_contr > 0)
6106  {
6107  printf ("Contraction min size: %d\n", coll->contr_min_size);
6108  }
6109 
6110  assert (coll->w_count > 0);
6111 
6112  if (upper_bound < lower_bound)
6113  {
6114  err_status = ER_LOC_GEN;
6117  true);
6118  goto exit;
6119  }
6120 
6121  /* Dump collation information, cp and next_cp info, ordered by cp. */
6122  if ((dl_settings & DUMPLOCALE_IS_COLLATION_CP_ORDER) != 0)
6123  {
6124  printf ("\n");
6125  printf ("* Codepoint collation info (codepoint order) *\n");
6126  for (cp = lower_bound; cp < upper_bound; cp++)
6127  {
6128  unsigned int next_id;
6129 
6130  assert (cp >= 0 && cp < coll->w_count);
6131 
6132  dump_collation_codepoint (coll, cp, true, true);
6133 
6134  next_id = coll->next_cp[cp];
6135  printf (" | Next : ");
6136 
6137  dump_collation_key (coll, next_id, true, true);
6138 
6139  printf ("\n");
6140  }
6141  }
6142 
6143  if (coll->count_contr > 0 && (dl_settings & DUMPLOCALE_IS_COLLATION_CP_ORDER) != 0)
6144  {
6145  printf ("\n");
6146  printf ("* Contraction collation info (contraction order) *\n");
6147  for (i = 0; i < coll->count_contr; i++)
6148  {
6149  COLL_CONTRACTION *contr = &(coll->contr_list[i]);
6150 
6151  dump_collation_contr (coll, contr, true, true);
6152  printf (" | Next :");
6153 
6154  dump_collation_key (coll, contr->next, true, true);
6155 
6156  printf ("\n");
6157  }
6158  }
6159 
6160  /* Dump weight list and corresponding codepoints, ordered by weight. */
6161  if ((dl_settings & DUMPLOCALE_IS_COLLATION_WEIGHT_ORDER) != 0)
6162  {
6163  int keys_same_weight = 1;
6164  int cp_count = upper_bound - lower_bound;
6165  bool use_expansions;
6166 
6167  printf ("\n");
6168  printf ("* Collation info (weight order) *\n");
6169  coll_key_list_cnt = cp_count + coll->count_contr;
6170  coll_key_list = (unsigned int *) malloc (coll_key_list_cnt * sizeof (unsigned int));
6171  if (coll_key_list == NULL)
6172  {
6173  err_status = ER_LOC_INIT;
6174  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_INIT, true);
6175  goto exit;
6176  }
6177 
6178  for (cp = lower_bound; cp < upper_bound; cp++)
6179  {
6180  coll_key_list[cp - lower_bound] = cp;
6181  }
6182 
6183  for (i = 0; i < coll->count_contr; i++)
6184  {
6185  coll_key_list[i + cp_count] = i | INTL_MASK_CONTR;
6186  }
6187 
6188  /* Order by weight. */
6189  use_expansions = coll->uca_opt.sett_expansions;
6190 
6191  dump_coll_data = coll;
6192  if (use_expansions)
6193  {
6194  qsort (coll_key_list, coll_key_list_cnt, sizeof (unsigned int), comp_func_coll_uca_exp_fo);
6195  }
6196  else
6197  {
6198  qsort (coll_key_list, coll_key_list_cnt, sizeof (unsigned int), comp_func_coll_uca_simple_weights_fo);
6199  }
6200 
6201  /* Dump ordered (weight, key id) tuples. */
6202  for (i = 0; i < coll_key_list_cnt; i++)
6203  {
6204  bool same_weights = false;
6205 
6206  if (i > 0)
6207  {
6208  if (use_expansions)
6209  {
6210  same_weights =
6211  (comp_func_coll_uca_exp (&(coll_key_list[i]), &(coll_key_list[i - 1])) == 0) ? true : false;
6212  }
6213  else
6214  {
6215  same_weights =
6216  (comp_func_coll_uca_simple_weights (&(coll_key_list[i]), &(coll_key_list[i - 1])) ==
6217  0) ? true : false;
6218  }
6219  }
6220 
6221  if (i > 0 && !same_weights)
6222  {
6223  if (keys_same_weight > 1)
6224  {
6225  printf (" Keys same weight : %d\n", keys_same_weight);
6226  }
6227  else
6228  {
6229  printf ("\n");
6230  }
6231 
6232  dump_collation_key (coll, coll_key_list[i], true, false);
6233  keys_same_weight = 1;
6234  }
6235  else
6236  {
6237  printf ("\n");
6238  dump_collation_key (coll, coll_key_list[i], true, false);
6239  keys_same_weight++;
6240  }
6241 
6242  printf (" | ");
6243 
6244  dump_collation_key (coll, coll_key_list[i], false, true);
6245  }
6246  }
6247 exit:
6248  if (coll_key_list != NULL)
6249  {
6250  free (coll_key_list);
6251  }
6252 
6253  return err_status;
6254 }
6255 
6256 /*
6257  * locale_dump - output the selected information on locale data in
6258  * human-readable text format.
6259  * Returns : error status.
6260  * data(in): the locale data to be dumped in text format.
6261  * lf(in) : the LOCALE_FILE i.e. binary file from which ld was imported.
6262  * dl_settings(in): the commmand line options encoded intoa binary masked int.
6263  * start_value(in): the starting codepoint for the range of items which
6264  * -w or -c will dump.
6265  * end_value(in) : the ending codepoint for the range of items which
6266  * -w or -c will dump.
6267  */
6268 int
6269 locale_dump (void *data, LOCALE_FILE * lf, int dl_settings, int start_value, int end_value)
6270 {
6271  int i;
6272  int lower_bound = 0;
6273  int upper_bound = 0;
6274  int alphabet_settings;
6275  int err_status = NO_ERROR;
6276  LANG_LOCALE_DATA *lld = NULL;
6277 
6278  assert (data != NULL);
6279  assert (lf != NULL);
6280  assert (start_value <= end_value);
6281 
6282  lld = (LANG_LOCALE_DATA *) data;
6283 
6284  printf ("*************************************************\n");
6285  printf ("Locale data for: %s\nLibrary file: %s\n", lf->locale_name, lf->lib_file);
6286  printf ("Locale string: %s\n", lld->lang_name);
6287  printf ("Locale checksum: %s\n", lld->checksum);
6288 
6289  if ((dl_settings & DUMPLOCALE_IS_CALENDAR) != 0)
6290  {
6291  printf ("\n * Calendar *\n");
6292  printf ("Date format: %s\n", lld->date_format);
6293  printf ("Time format: %s\n", lld->time_format);
6294  printf ("Datetime format: %s\n", lld->datetime_format);
6295  printf ("Timestamp format: %s\n", lld->timestamp_format);
6296  printf ("Datetime_tz format: %s\n", lld->datetimetz_format);
6297  printf ("Timestamp_tz format: %s\n", lld->timestamptz_format);
6298 
6299  printf ("\nAbbreviated month names:\n");
6300  for (i = 0; i < CAL_MONTH_COUNT; i++)
6301  {
6302  printf ("%d. %s\n", (i + 1), lld->month_short_name[i]);
6303  }
6304  printf ("\nAbbreviated month names, sorted for tokenizer:\n");
6305  for (i = 0; i < CAL_MONTH_COUNT; i++)
6306  {
6307  printf ("%d. %s = month %d\n", (i + 1), lld->month_short_name[(int) (lld->month_short_parse_order[i])],
6308  (int) (lld->month_short_parse_order[i]) + 1);
6309  }
6310 
6311  printf ("\nWide month names:\n");
6312  for (i = 0; i < CAL_MONTH_COUNT; i++)
6313  {
6314  printf ("%d. %s\n", (i + 1), lld->month_name[i]);
6315  }
6316  printf ("\nWide month names, sorted for tokenizer:\n");
6317  for (i = 0; i < CAL_MONTH_COUNT; i++)
6318  {
6319  printf ("%d. %s = month %d\n", (i + 1), lld->month_name[(int) (lld->month_parse_order[i])],
6320  (int) (lld->month_parse_order[i]) + 1);
6321  }
6322 
6323  printf ("\nAbbreviated weekday names:\n");
6324  for (i = 0; i < CAL_DAY_COUNT; i++)
6325  {
6326  printf ("%d. %s\n", (i + 1), lld->day_short_name[i]);
6327  }
6328  printf ("\nAbbreviated weekday names, sorted for parse order:\n");
6329  for (i = 0; i < CAL_DAY_COUNT; i++)
6330  {
6331  printf ("%d. %s = weekday %d\n", (i + 1), lld->day_short_name[(int) (lld->day_short_parse_order[i])],
6332  (int) (lld->day_short_parse_order[i]) + 1);
6333  }
6334 
6335  printf ("\nWide weekday names:\n");
6336  for (i = 0; i < CAL_DAY_COUNT; i++)
6337  {
6338  printf ("%d. %s\n", (i + 1), lld->day_name[i]);
6339  }
6340  printf ("\nWide weekday names, sorted for tokenizer:\n");
6341  for (i = 0; i < CAL_DAY_COUNT; i++)
6342  {
6343  printf ("%d. %s = weekday %d\n", (i + 1), lld->day_name[(int) (lld->day_parse_order[i])],
6344  (int) (lld->day_parse_order[i]) + 1);
6345  }
6346 
6347  printf ("\nDay periods:\n");
6348  for (i = 0; i < CAL_AM_PM_COUNT; i++)
6349  {
6350  printf ("%d. %s\n", (i + 1), lld->am_pm[i]);
6351  }
6352  printf ("\nDay periods, sorted for tokenizer:\n");
6353  for (i = 0; i < CAL_AM_PM_COUNT; i++)
6354  {
6355  printf ("%d. %s = day period %d\n", (i + 1), lld->am_pm[(int) (lld->am_pm_parse_order[i])],
6356  (int) (lld->am_pm_parse_order[i]) + 1);
6357  }
6358  }
6359 
6360  /* Display numbering information. */
6361  if ((dl_settings & DUMPLOCALE_IS_NUMBERING) != 0)
6362  {
6363  printf ("\n * Numbers *\n");
6364  printf ("Decimal separator: <%c>\n", lld->number_decimal_sym);
6365  printf ("Separator for digit grouping: <%c>\n", lld->number_group_sym);
6366  printf ("Default currency ISO code: %s\n", intl_get_money_ISO_symbol (lld->default_currency_code));
6367  }
6368 
6369  if ((dl_settings & DUMPLOCALE_IS_ALPHABET) != 0)
6370  {
6371  lower_bound = 0;
6372  upper_bound = lld->alphabet.l_count;
6373  if (start_value > lower_bound)
6374  {
6375  lower_bound = start_value;
6376  }
6377  if (end_value > 0 && end_value < upper_bound)
6378  {
6379  /* if an upper bound is specified, use the "+1" to make sure that the upper bound codepoint is included in
6380  * the dump file. */
6381  upper_bound = end_value + 1;
6382  }
6383  }
6384 
6385  if (upper_bound < lower_bound)
6386  {
6387  err_status = ER_LOC_GEN;
6390  true);
6391  goto exit;
6392  }
6393 
6394  /* Dump alphabet data. */
6395  if ((dl_settings & DUMPLOCALE_IS_ALPHABET) != 0)
6396  {
6397  alphabet_settings = 0;
6398  alphabet_settings |= (dl_settings & DUMPLOCALE_IS_ALPHABET_LOWER);
6399  alphabet_settings |= (dl_settings & DUMPLOCALE_IS_ALPHABET_UPPER);
6400  printf ("\n * Alphabet data *\n");
6401  dump_locale_alphabet (&(lld->alphabet), alphabet_settings, lower_bound, upper_bound);
6402  }
6403 
6404  /* Dump identifier alphabet data. */
6405  if ((dl_settings & DUMPLOCALE_IS_IDENTIFIER_ALPHABET) != 0)
6406  {
6407  alphabet_settings = 0;
6408  if ((dl_settings & DUMPLOCALE_IS_IDENTIFIER_ALPHABET_LOWER) != 0)
6409  {
6410  alphabet_settings |= DUMPLOCALE_IS_ALPHABET_LOWER;
6411  }
6412  if ((dl_settings & DUMPLOCALE_IS_IDENTIFIER_ALPHABET_UPPER) != 0)
6413  {
6414  alphabet_settings |= DUMPLOCALE_IS_ALPHABET_UPPER;
6415  }
6416 
6417  printf ("\n");
6418  printf ("* Identifier alphabet data *\n");
6419  dump_locale_alphabet (&(lld->ident_alphabet), alphabet_settings, lower_bound, upper_bound);
6420  }
6421 
6422  /* Dump normalization data. */
6423  if ((dl_settings & DUMPLOCALE_IS_NORMALIZATION) != 0)
6424  {
6425  printf ("\n");
6426  printf ("* Normalization data *\n");
6428  }
6429 
6430  /* Dump normalization data. */
6431  if ((dl_settings & DUMPLOCALE_IS_TEXT_CONV) != 0)
6432  {
6433  printf ("\n");
6434  printf ("* Console conversion data *\n");
6436  }
6437 
6438 exit:
6439  return err_status;
6440 }
6441 
6442 /*
6443  * locale_dump_lib_collations() - output the selected information on
6444  * collations data in human-readable text
6445  * format.
6446  * return: error code
6447  * lib_handle(in):
6448  * lf(in): locale file info
6449  * dl_settings(in):
6450  * lower_bound(in):
6451  * upper_bound(in):
6452  */
6453 int
6454 locale_dump_lib_collations (void *lib_handle, const LOCALE_FILE * lf, int dl_settings, int start_value, int end_value)
6455 {
6456  int err_status = NO_ERROR;
6457  int i, count_coll_to_load;
6458  COLL_DATA coll;
6459 
6460  assert (lib_handle != NULL);
6461  assert (lf != NULL);
6462  assert (lf->locale_name != NULL);
6463 
6464  /* collation data */
6465  err_status = lang_load_count_coll_from_lib (&count_coll_to_load, lib_handle, lf);
6466  if (err_status != NO_ERROR)
6467  {
6468  goto exit;
6469  }
6470 
6471  printf ("\n\n* Collations: %d collations found *\n", count_coll_to_load);
6472 
6473  for (i = 0; i < count_coll_to_load; i++)
6474  {
6475  /* get name of collation */
6476  char *coll_name = NULL;
6477 
6478  memset (&coll, 0, sizeof (COLL_DATA));
6479 
6480  err_status = lang_load_get_coll_name_from_lib (i, &coll_name, lib_handle, lf);
6481  if (err_status != NO_ERROR)
6482  {
6483  goto exit;
6484  }
6485 
6486  assert (strlen (coll_name) < (int) sizeof (coll.coll_name));
6487  strncpy (coll.coll_name, coll_name, sizeof (coll.coll_name) - 1);
6488 
6489  err_status = lang_load_coll_from_lib (&coll, lib_handle, lf);
6490  if (err_status != NO_ERROR)
6491  {
6492  goto exit;
6493  }
6494 
6495  err_status = dump_locale_collation (&coll, dl_settings, start_value, end_value);
6496  if (err_status != NO_ERROR)
6497  {
6498  goto exit;
6499  }
6500  printf ("\n\n\n");
6501  }
6502 
6503 exit:
6504  return err_status;
6505 }
6506 
6507 /*
6508  * comp_func_coll_uca_simple_weights_fo - compare function for sorting
6509  * collatable elements according to simple weights order
6510  * but applies full order
6511  *
6512  * Note: This function uses 'comp_func_coll_uca_simple_weights' but applies
6513  * a full order.
6514  * The purpose is to provide a 'deterministic comparison' to eliminate
6515  * unpredictable results of sort algorithm (qsort).
6516  */
6517 static int
6518 comp_func_coll_uca_simple_weights_fo (const void *arg1, const void *arg2)
6519 {
6520  unsigned int pos1;
6521  unsigned int pos2;
6522  int cmp;
6523 
6524  pos1 = *((unsigned int *) arg1);
6525  pos2 = *((unsigned int *) arg2);
6526 
6527  cmp = comp_func_coll_uca_simple_weights (arg1, arg2);
6528 
6529  return (cmp == 0) ? (int) (pos1 - pos2) : cmp;
6530 }
6531 
6532 /*
6533  * comp_func_coll_uca_simple_weights - compare function for sorting collatable
6534  * elements according to simple weights order
6535  *
6536  * Note: this function is used by dump_locale tool
6537  * The elements in array are 32 bit unsigned integers, keys which
6538  * may be Unicode points or contractions (when highest bit is set)
6539  *
6540  */
6541 static int
6542 comp_func_coll_uca_simple_weights (const void *arg1, const void *arg2)
6543 {
6544  unsigned int pos1;
6545  unsigned int pos2;
6546  unsigned int wv1, wv2;
6547  COLL_DATA *coll = dump_coll_data;
6548 
6549  pos1 = *((unsigned int *) arg1);
6550  pos2 = *((unsigned int *) arg2);
6551 
6552  assert (coll != NULL);
6553 
6554  if (INTL_IS_NEXT_CONTR (pos1))
6555  {
6556  wv1 = coll->contr_list[INTL_GET_NEXT_CONTR_ID (pos1)].wv;
6557  }
6558  else
6559  {
6560  wv1 = coll->weights[pos1];
6561  }
6562 
6563  if (INTL_IS_NEXT_CONTR (pos2))
6564  {
6565  wv2 = coll->contr_list[INTL_GET_NEXT_CONTR_ID (pos2)].wv;
6566  }
6567  else
6568  {
6569  wv2 = coll->weights[pos2];
6570  }
6571 
6572  return wv1 - wv2;
6573 }
6574 
6575 /*
6576  * comp_func_coll_uca_exp_fo - compare function for sorting collatable
6577  * elements according to UCA algorithm,
6578  * with full order
6579  *
6580  * Note: This function uses 'comp_func_coll_uca_exp' but applies a full order
6581  * The purpose is to provide a 'deterministic comparison' to eliminate
6582  * unpredictable results of sort algorithm (qsort).
6583  */
6584 static int
6585 comp_func_coll_uca_exp_fo (const void *arg1, const void *arg2)
6586 {
6587  unsigned int pos1;
6588  unsigned int pos2;
6589  int cmp;
6590 
6591  pos1 = *((unsigned int *) arg1);
6592  pos2 = *((unsigned int *) arg2);
6593 
6594  cmp = comp_func_coll_uca_exp (arg1, arg2);
6595 
6596  return (cmp == 0) ? (int) (pos1 - pos2) : cmp;
6597 }
6598 
6599 /*
6600  * comp_func_coll_uca_exp - compare function for sorting collatable elements
6601  * according to UCA algorithm
6602  *
6603  * Note: this function is used by dump_locale tool
6604  * The elements in array are 32 bit unsigned integers, keys which
6605  * may be Unicode points or contractions (when highest bit is set)
6606  *
6607  */
6608 static int
6609 comp_func_coll_uca_exp (const void *arg1, const void *arg2)
6610 {
6611  unsigned int pos1;
6612  unsigned int pos2;
6613  COLL_DATA *coll = dump_coll_data;
6614  unsigned char utf8_buf_1[INTL_UTF8_MAX_CHAR_SIZE + 1];
6615  unsigned char utf8_buf_2[INTL_UTF8_MAX_CHAR_SIZE + 1];
6616  char *str1;
6617  char *str2;
6618  int size1, size2;
6619 
6620  pos1 = *((unsigned int *) arg1);
6621  pos2 = *((unsigned int *) arg2);
6622 
6623  assert (coll != NULL);
6624 
6625  /* build strings from the two keys and use the UCA collation function */
6626  if (INTL_IS_NEXT_CONTR (pos1))
6627  {
6628  str1 = coll->contr_list[INTL_GET_NEXT_CONTR_ID (pos1)].c_buf;
6629  size1 = coll->contr_list[INTL_GET_NEXT_CONTR_ID (pos1)].size;
6630  }
6631  else
6632  {
6633  size1 = intl_cp_to_utf8 (pos1, utf8_buf_1);
6634  utf8_buf_1[size1] = '\0';
6635  str1 = (char *) utf8_buf_1;
6636  }
6637 
6638  if (INTL_IS_NEXT_CONTR (pos2))
6639  {
6640  str2 = coll->contr_list[INTL_GET_NEXT_CONTR_ID (pos2)].c_buf;
6641  size2 = coll->contr_list[INTL_GET_NEXT_CONTR_ID (pos2)].size;
6642  }
6643  else
6644  {
6645  size2 = intl_cp_to_utf8 (pos2, utf8_buf_2);
6646  utf8_buf_2[size2] = '\0';
6647  str2 = (char *) utf8_buf_2;
6648  }
6649 
6650  return lang_strmatch_utf8_uca_w_coll_data (coll, false, (const unsigned char *) str1, size1,
6651  (const unsigned char *) str2, size2, NULL, false, NULL, false);
6652 }
6653 
6654 /*
6655  * dump_collation_key - prints information on collation key
6656  * (codepoint or contraction)
6657  * Returns :
6658  * coll(in) : collation data
6659  * key(in) : key to print
6660  * print_weight(in): true if weight should be printed
6661  * print_contr(in): true if contraction info should be printed
6662  */
6663 static void
6664 dump_collation_key (COLL_DATA * coll, const unsigned int key, bool print_weight, bool print_key)
6665 {
6666  if (INTL_IS_NEXT_CONTR (key))
6667  {
6668  unsigned int contr_id = INTL_GET_NEXT_CONTR_ID (key);
6669  COLL_CONTRACTION *contr = &(coll->contr_list[contr_id]);
6670 
6671  dump_collation_contr (coll, contr, print_weight, print_key);
6672  }
6673  else
6674  {
6675  dump_collation_codepoint (coll, key, print_weight, print_key);
6676  }
6677 }
6678 
6679 /*
6680  * dump_collation_contr - prints information on collation contraction
6681  * Returns :
6682  * coll(in) : collation data
6683  * contr(in) : contraction
6684  * print_weight(in): true if weight should be printed
6685  * print_contr(in): true if contraction info should be printed
6686  */
6687 static void
6688 dump_collation_contr (COLL_DATA * coll, const COLL_CONTRACTION * contr, bool print_weight, bool print_contr)
6689 {
6690  int i;
6691 
6692  assert (contr != NULL);
6693 
6695 
6696  if (print_contr)
6697  {
6698  unsigned int cp_list[LOC_MAX_UCA_CHARS_SEQ];
6699  bool print_utf8 = true;
6700  int cp_count;
6701 
6702  intl_utf8_to_cp_list ((const unsigned char *) contr->c_buf, strlen (contr->c_buf), cp_list, sizeof (cp_list),
6703  &cp_count);
6704 
6705  assert (cp_count == contr->cp_count);
6706 
6707  printf ("Contr: ");
6708  for (i = 0; i < cp_count; i++)
6709  {
6710  printf ("Ux%04X ", cp_list[i]);
6711  if (cp_list[i] < 0x20)
6712  {
6713  print_utf8 = false;
6714  }
6715  }
6716 
6717  if (print_utf8)
6718  {
6719  printf (" | %s", contr->c_buf);
6720  }
6721  }
6722 
6723  if (!print_weight)
6724  {
6725  return;
6726  }
6727 
6728  if (coll->uca_exp_num <= 1)
6729  {
6730  printf (" | Weight : %04x", contr->wv);
6731  return;
6732  }
6733 
6734  assert (contr->uca_num > 0 && contr->uca_num <= MAX_UCA_EXP_CE);
6735 
6736  printf (" | Weight : ");
6737  for (i = 0; i < (int) contr->uca_num; i++)
6738  {
6739  printf ("[%04X.", UCA_GET_L1_W (contr->uca_w_l13[i]));
6740  printf ("%04X.", UCA_GET_L2_W (contr->uca_w_l13[i]));
6741  printf ("%04X.", UCA_GET_L3_W (contr->uca_w_l13[i]));
6743  {
6744  printf ("%04X]", contr->uca_w_l4[i]);
6745  }
6746  else
6747  {
6748  printf ("]");
6749  }
6750  }
6751 }
6752 
6753 /*
6754  * dump_collation_codepoint - prints information on collation codepoint
6755  * Returns :
6756  * coll(in) : collation data
6757  * cp(in) : codepoint
6758  * print_weight(in): true if weight should be printed
6759  */
6760 static void
6761 dump_collation_codepoint (COLL_DATA * coll, const unsigned int cp, bool print_weight, bool print_cp)
6762 {
6764 
6765  if (print_cp)
6766  {
6767  unsigned char utf8_buf[INTL_UTF8_MAX_CHAR_SIZE + 1];
6768 
6769  memset (utf8_buf, 0, INTL_UTF8_MAX_CHAR_SIZE + 1);
6770 
6771  intl_cp_to_utf8 (cp, utf8_buf);
6772 
6773  printf ("CP: Ux%04X | %-4s", cp, ((cp > 0x20) ? utf8_buf : (unsigned char *) ""));
6774  }
6775 
6776  if (!print_weight)
6777  {
6778  return;
6779  }
6780 
6781  if (coll->uca_exp_num <= 1)
6782  {
6783  printf (" | Weight%s: %04x", ((int) cp < coll->w_count) ? "" : "(Computed)",
6784  (((int) cp < coll->w_count) ? (coll->weights[cp]) : (cp + 1)));
6785  return;
6786  }
6787 
6788  assert (coll->uca_exp_num > 1);
6789  assert (coll->uca_exp_num <= MAX_UCA_EXP_CE);
6790 
6791  if ((int) cp < coll->w_count)
6792  {
6793  int i;
6794  UCA_L13_W *uca_w_l13 = &(coll->uca_w_l13[cp * coll->uca_exp_num]);
6795 
6796  printf (" | Weight : ");
6797 
6798  assert (coll->uca_num[cp] >= 1);
6799  assert (coll->uca_num[cp] <= MAX_UCA_EXP_CE);
6800 
6801  for (i = 0; i < coll->uca_num[cp]; i++)
6802  {
6803  printf ("[%04X.", UCA_GET_L1_W (uca_w_l13[i]));
6804  printf ("%04X.", UCA_GET_L2_W (uca_w_l13[i]));
6805  printf ("%04X.", UCA_GET_L3_W (uca_w_l13[i]));
6807  {
6808  printf ("%04X]", coll->uca_w_l4[cp * coll->uca_exp_num + i]);
6809  }
6810  else
6811  {
6812  printf ("]");
6813  }
6814  }
6815  }
6816  else
6817  {
6818  printf (" | Weight(Computed) : %04X", cp + 1);
6819  }
6820 }
6821 
6822 /*
6823  * locale_check_and_set_shared_data - checks if data has already been taken
6824  * into account as shared data, otherwise
6825  * adds the new key as shared data
6826  * Returns : error status
6827  * lsd_type(in): shared data type
6828  * lsd_key(in) : key (name) of data
6829  * data(in) : data to be stored for key
6830  * ldml_context(in): context of LDML file
6831  * found_entry(out): shread data entry if found
6832  *
6833  * Note : this is used in context of genlocale tool, to check for duplicate
6834  * collations, normalization or alphabet data
6835  */
6836 static int
6837 locale_check_and_set_shared_data (const LOC_SHARED_DATA_TYPE lsd_type, const char *lsd_key, const void *data,
6838  LDML_CONTEXT * ldml_context, LOC_SHARED_DATA ** found_entry)
6839 {
6840 #define SHARED_DATA_INCR_SIZE 32
6841 
6842  int status = NO_ERROR;
6843  int i;
6844 
6845  assert (lsd_key != NULL);
6846  assert (found_entry != NULL);
6847 
6848  *found_entry = NULL;
6849 
6850  for (i = 0; i < count_shared_data; i++)
6851  {
6852  if (lsd_type == shared_data[i].lsd_type && strcmp (lsd_key, shared_data[i].lsd_key) == 0)
6853  {
6854  *found_entry = &(shared_data[i]);
6855  goto exit;
6856  }
6857  }
6858 
6859  /* set new shared data */
6860  if (alloced_shared_data <= count_shared_data)
6861  {
6862  LOC_SHARED_DATA *const realloc_shared_data = (LOC_SHARED_DATA *) realloc (shared_data,
6863  sizeof (LOC_SHARED_DATA) *
6866  if (realloc_shared_data == NULL)
6867  {
6868  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_GEN, true);
6869  status = ER_LOC_GEN;
6870  goto exit;
6871  }
6872  else
6873  {
6874  shared_data = realloc_shared_data;
6875  }
6877  }
6878 
6879  memset (&(shared_data[count_shared_data]), 0, sizeof (LOC_SHARED_DATA));
6880  shared_data[count_shared_data].lsd_type = lsd_type;
6881  strncpy (shared_data[count_shared_data].lsd_key, lsd_key, COLL_NAME_SIZE - 1);
6882  shared_data[count_shared_data].lsd_key[COLL_NAME_SIZE - 1] = '\0';
6883 
6884  if (data != NULL)
6885  {
6886  shared_data[count_shared_data].data = strdup ((const char *) data);
6887  if (shared_data[count_shared_data].data == NULL)
6888  {
6889  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_GEN, true);
6890  status = ER_LOC_GEN;
6891  goto exit;
6892  }
6893  }
6894 
6895  if (ldml_context != NULL)
6896  {
6897  shared_data[count_shared_data].ldml_context.ldml_file = strdup (ldml_context->ldml_file);
6898  if (shared_data[count_shared_data].ldml_context.ldml_file == NULL)
6899  {
6900  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_GEN, true);
6901  status = ER_LOC_GEN;
6902  goto exit;
6903  }
6904  shared_data[count_shared_data].ldml_context.line_no = ldml_context->line_no;
6905  }
6906 
6907  count_shared_data++;
6908 
6909 exit:
6910  return status;
6911 
6912 #undef SHARED_DATA_INCR_SIZE
6913 }
6914 
6915 /*
6916  * locale_free_shared_data -
6917  *
6918  * Note : this is used in context of genlocale tool.
6919  */
6920 void
6922 {
6923  if (shared_data != NULL)
6924  {
6925  int i;
6926  assert (count_shared_data > 0);
6928 
6929  for (i = 0; i < count_shared_data; i++)
6930  {
6931  if (shared_data[i].data != NULL)
6932  {
6933  free (shared_data[i].data);
6934  shared_data[i].data = NULL;
6935  }
6936  if (shared_data[i].ldml_context.ldml_file != NULL)
6937  {
6938  free (shared_data[i].ldml_context.ldml_file);
6939  shared_data[i].ldml_context.ldml_file = NULL;
6940  }
6941  }
6942 
6943  free (shared_data);
6944  shared_data = NULL;
6945  }
6946 
6947  alloced_shared_data = 0;
6948  count_shared_data = 0;
6949 }
6950 
6951 /*
6952  * start_unicode_file() - XML element start function
6953  * "ldml unicodefile"
6954  *
6955  * return: 0 validation OK enter this element , 1 validation NOK do not enter
6956  * -1 error abort parsing
6957  * data: user data
6958  * attr: attribute/value pair array
6959  */
6960 static int
6961 start_unicode_file (void *data, const char **attr)
6962 {
6963  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
6964  LOCALE_DATA *ld = NULL;
6965  char *att_val = NULL;
6966 
6967  assert (data != NULL);
6968 
6969  ld = (LOCALE_DATA *) XML_USER_DATA (pd);
6970 
6971  if (strlen (ld->unicode_data_file) != 0)
6972  {
6973  PRINT_DEBUG_START (data, attr, "Only one unicodefile tag is allowed", -1);
6974  return -1;
6975  }
6976 
6977  att_val = NULL;
6978  if (xml_get_att_value (attr, "CUBRIDUnicodeDataFilePath", &att_val) == 0)
6979  {
6980  assert (att_val != NULL);
6981 
6982  strncpy (ld->unicode_data_file, att_val, sizeof (ld->unicode_data_file) - 1);
6983  ld->unicode_data_file[sizeof (ld->unicode_data_file) - 1] = '\0';
6985  ld->unicode_mode = 1;
6986  }
6987 
6988  PRINT_DEBUG_START (data, attr, "", 0);
6989 
6990  return 0;
6991 }
6992 
6993 /*
6994  * locale_destroy_normalization_data() - frees memory used by the specified
6995  * locale for storing its computed normalization data.
6996  * return:
6997  * ld(in/out): locale to use
6998  */
6999 void
7001 {
7002  if (norm == NULL)
7003  {
7004  return;
7005  }
7006  if (norm->unicode_mappings != NULL)
7007  {
7008  free (norm->unicode_mappings);
7009  norm->unicode_mappings = NULL;
7010  }
7011 
7012  if (norm->list_full_decomp != NULL)
7013  {
7014  free (norm->list_full_decomp);
7015  norm->list_full_decomp = NULL;
7016  }
7017 
7018  if (norm->unicode_mapping_index != NULL)
7019  {
7020  free (norm->unicode_mapping_index);
7021  norm->unicode_mapping_index = NULL;
7022  }
7023 }
7024 
7025 /*
7026  * locale_save_normalization_to_C_file() - saves normalization data
7027  * to C source file as variables, for later use
7028  * when generating the locale shared library.
7029  *
7030  * return: error code
7031  * fp(in): file pointer where to write the data
7032  * ld(in): locale data
7033  */
7034 static int
7036 {
7037  int i;
7038  UNICODE_MAPPING *um;
7039  UNICODE_NORMALIZATION *norm;
7040 
7041  assert (ld != NULL);
7042  assert (fp != NULL);
7043 
7044  norm = &(ld->unicode_normalization);
7045 
7046  if (norm->do_not_save)
7047  {
7048  goto exit;
7049  }
7050 
7051  PRINT_VAR_TO_C_FILE (fp, "int", "unicode_mappings_count", norm->unicode_mappings_count, "%d",
7053 
7054  PRINT_NUM_ARRAY_TO_C_FILE (fp, "unicode_mapping_index", "int", "%d", MAX_UNICODE_CHARS, norm->unicode_mapping_index,
7056  PRINT_NUM_ARRAY_TO_C_FILE (fp, "list_full_decomp", "int", "%d", MAX_UNICODE_CHARS, norm->list_full_decomp,
7058 
7059  fprintf (fp, "" DLL_EXPORT_PREFIX "const UNICODE_MAPPING unicode_mappings_%s[] = {", UNICODE_NORMALIZATION_DECORATOR);
7060  for (i = 0; i < norm->unicode_mappings_count; i++)
7061  {
7062  um = &(norm->unicode_mappings[i]);
7063  fprintf (fp, "\t{%u, %d, ", um->cp, um->size);
7064  PRINT_STRING_TO_C_FILE (fp, um->buffer, um->size);
7065  fprintf (fp, "}%s\n", (i < norm->unicode_mappings_count - 1) ? "," : "");
7066  }
7067  fprintf (fp, "};");
7068 
7069 exit:
7070 
7071  return 0;
7072 }
7073 
7074 #define NORM_MAPPING_DUMP_MODE_FULL 0
7075 #define NORM_MAPPING_DUMP_MODE_COMP 1
7076 #define NORM_MAPPING_DUMP_MODE_DECOMP 2
7077 /*
7078  * dump_locale_normalization - dump the selected UNICODE_NORMALIZATION
7079  * structure in human-readable text format.
7080  * Returns : NO_ERROR.
7081  * norm(in) : the UNICODE_NORMALIZATION to be dumped in text format.
7082  */
7083 static void
7085 {
7086  int i;
7087 
7088  printf ("Sorted list of unicode mappings: \n");
7089  for (i = 0; i < norm->unicode_mappings_count; i++)
7090  {
7091  printf ("%d.\t ", i + 1);
7093  printf ("\n");
7094  }
7095 
7096  printf ("\n Unicode composition mappings \n");
7097  for (i = 0; i < MAX_UNICODE_CHARS; i++)
7098  {
7099  int j, comp_start, comp_end;
7100 
7101  printf ("CP: %04X | \t Comp: ", i);
7102 
7103  if (!CP_HAS_MAPPINGS (norm->unicode_mapping_index[i]))
7104  {
7105  printf ("NO\n");
7106  continue;
7107  }
7108 
7109  comp_start = GET_MAPPING_OFFSET (norm->unicode_mapping_index[i]);
7110  comp_end = GET_MAPPING_OFFSET (norm->unicode_mapping_index[i + 1]);
7111 
7112  printf ("(%2d) From: %d To: %d | \t", comp_end - comp_start, comp_start, comp_end);
7113 
7114  for (j = comp_start; j < comp_end; j++)
7115  {
7117  printf (" | ");
7118  }
7119  printf ("\n");
7120  }
7121 
7122  printf ("\n Unicode decomposition mappings\n");
7123  for (i = 0; i < MAX_UNICODE_CHARS; i++)
7124  {
7125  int decomp_idx = norm->list_full_decomp[i];
7126 
7127  printf ("CP: %04X | Decomp : ", i);
7128 
7129  if (decomp_idx < 0)
7130  {
7131  printf ("NO\n");
7132  continue;
7133  }
7134 
7135  assert (decomp_idx >= 0);
7136 
7138 
7139  printf ("\n");
7140  }
7141 }
7142 
7143 /*
7144  * dump_unicode_mapping() - Dump a UNICODE_MAPPING to the console.
7145  *
7146  * Returns:
7147  * um(in) : unicode mapping to dump
7148  */
7149 static void
7151 {
7152  unsigned int cp;
7153  unsigned char *next;
7154  unsigned char *cur_str;
7155 
7156  if (um == NULL)
7157  {
7158  printf ("Null mapping.\n");
7159  return;
7160  }
7161 
7162  if (mode == NORM_MAPPING_DUMP_MODE_FULL)
7163  {
7164  printf ("CP: %04X", um->cp);
7165  if (um->size > 0)
7166  {
7167  printf (" ->");
7168  }
7169  }
7170 
7171  cur_str = um->buffer;
7172  next = cur_str;
7173  while (next < um->buffer + um->size)
7174  {
7175  cp = intl_utf8_to_cp (cur_str, (int) INTL_UTF8_MAX_CHAR_SIZE, &next);
7176  printf ("%04X ", cp);
7177  cur_str = next;
7178  }
7179 
7180  if (mode == NORM_MAPPING_DUMP_MODE_COMP)
7181  {
7182  printf (" -> CP: %04X", um->cp);
7183  }
7184 }
7185 
7186 /*
7187  * dump_console_conversion - dump Console text conversion data structure
7188  * in human-readable text format.
7189  * Returns : NO_ERROR.
7190  * tc(in): the TEXT_CONVERSION to be dumped in text format.
7191  */
7192 static int
7194 {
7195  unsigned char utf8_seq[INTL_UTF8_MAX_CHAR_SIZE + 1];
7196  unsigned char cnv_utf8_buf[2 * 3 + 1];
7197  unsigned char *cnv_utf8;
7198  CONV_CP_TO_BYTES *c_item;
7199  unsigned int utf8_cp, con_cp;
7200  unsigned char *next;
7201  int utf8_size;
7202  unsigned char *char_to_print = NULL;
7203  int err;
7204 
7205  if (tc == NULL || tc->conv_type == TEXT_CONV_NO_CONVERSION)
7206  {
7207  printf ("\nNo console conversion for this locale.\n\n");
7208  goto exit;
7209  }
7210 
7211  printf ("\nType: ");
7213  {
7214  printf ("built-in %s console to UTF-8 encoding \n",
7215  (tc->conv_type == TEXT_CONV_ISO_88591_BUILTIN) ? "ISO 8859-1" : "ISO 8859-9");
7216  }
7217  else
7218  {
7219  printf ("%s byte console to UTF-8 encoding \n", (tc->conv_type == TEXT_CONV_GENERIC_1BYTE) ? "single" : "double");
7220  }
7221 
7222  printf ("Windows codepages: %s\n", tc->win_codepages);
7223  printf ("Linux LANG charset values: %s\n", tc->nl_lang_str);
7224 
7226  {
7227  goto exit;
7228  }
7229 
7230  printf ("\nConsole to UTF-8 conversion:\n");
7231  printf ("Console codepoint -> Unicode codepoint | Character (UTF-8) \n");
7232  for (con_cp = 0; con_cp <= tc->text_last_cp; con_cp++)
7233  {
7234  unsigned char dbcs_seq[2 + 1];
7235  int dbcs_size;
7236 
7237  if (tc->conv_type == TEXT_CONV_GENERIC_2BYTE && con_cp <= 0xff && tc->byte_flag[con_cp] != 0)
7238  {
7239  printf ("%02X -> Undefined or leading byte\n", con_cp);
7240  continue;
7241  }
7242  utf8_cp = con_cp;
7243 
7244  if (con_cp >= tc->text_first_cp)
7245  {
7246  c_item = &(tc->text_to_utf8[con_cp - tc->text_first_cp]);
7247  utf8_cp = intl_utf8_to_cp (c_item->bytes, c_item->size, &next);
7248  assert ((unsigned char *) next - c_item->bytes == c_item->size);
7249 
7250  if (utf8_cp == 0x3f)
7251  {
7252  assert (con_cp != 0x3f);
7253  printf ("%04X -> Undefined codepoint\n", con_cp);
7254  continue;
7255  }
7256 
7257  utf8_size = intl_cp_to_utf8 (utf8_cp, utf8_seq);
7258  assert ((unsigned int) utf8_size < sizeof (utf8_seq));
7259  utf8_seq[utf8_size] = '\0';
7260 
7261  char_to_print = (utf8_cp > 0x20) ? utf8_seq : (unsigned char *) "";
7262 
7263  dbcs_size = intl_cp_to_dbcs (con_cp, tc->byte_flag, dbcs_seq);
7264  dbcs_seq[dbcs_size] = '\0';
7265 
7266  cnv_utf8 = cnv_utf8_buf;
7267  utf8_size = sizeof (cnv_utf8_buf);
7268 
7270  {
7271  err = intl_text_single_byte_to_utf8_ext (tc, dbcs_seq, dbcs_size, &cnv_utf8, &utf8_size);
7272  assert (err == NO_ERROR);
7273  }
7274  else
7275  {
7276  if (dbcs_size == 2 && tc->byte_flag[dbcs_seq[0]] != 1)
7277  {
7278  /* invalid console codepoint */
7279  cnv_utf8 = NULL;
7280  }
7281  else
7282  {
7283  err = intl_text_dbcs_to_utf8_ext (tc, dbcs_seq, dbcs_size, &cnv_utf8, &utf8_size);
7284  assert (err == NO_ERROR);
7285  }
7286  }
7287 
7288  if (cnv_utf8 != NULL)
7289  {
7290  assert ((unsigned int) utf8_size <= sizeof (cnv_utf8_buf));
7291  char_to_print = cnv_utf8;
7292  }
7293  }
7294  else
7295  {
7296  utf8_size = intl_cp_to_utf8 (utf8_cp, utf8_seq);
7297  assert ((unsigned int) utf8_size < sizeof (utf8_seq));
7298  utf8_seq[utf8_size] = '\0';
7299 
7300  char_to_print = (utf8_cp > 0x20) ? utf8_seq : (unsigned char *) "";
7301  }
7302 
7303  if (con_cp <= 0xff)
7304  {
7305  printf ("%02X -> Ux%04X | %s\n", con_cp, utf8_cp, char_to_print);
7306  }
7307  else
7308  {
7309  printf ("%04X -> Ux%04X | %s\n", con_cp, utf8_cp, char_to_print);
7310  }
7311  }
7312 
7313  if (tc->text_last_cp < ((tc->conv_type == TEXT_CONV_GENERIC_1BYTE) ? (unsigned int) 0xff : (unsigned int) 0xffff))
7314  {
7316  {
7317  printf ("Range %02X - FF is not mapped\n", tc->text_last_cp + 1);
7318  }
7319  else
7320  {
7321  printf ("Range %04X - FFFF is not mapped\n", tc->text_last_cp + 1);
7322  }
7323  }
7324 
7325  printf ("\n\nUTF-8 to console conversion:\n");
7326  printf ("Unicode codepoint [Unicode character] ->" " Console codepoint | Character (UTF-8 encoding)\n");
7327  for (utf8_cp = 0; utf8_cp <= tc->utf8_last_cp; utf8_cp++)
7328  {
7329  if (utf8_cp > 0x20)
7330  {
7331  utf8_size = intl_cp_to_utf8 (utf8_cp, utf8_seq);
7332  assert ((unsigned int) utf8_size < sizeof (utf8_seq));
7333  utf8_seq[utf8_size] = '\0';
7334  }
7335  else
7336  {
7337  utf8_seq[0] = ' ';
7338  utf8_seq[1] = '\0';
7339  }
7340 
7341  con_cp = utf8_cp;
7342  char_to_print = utf8_seq;
7343 
7344  if (utf8_cp >= tc->utf8_first_cp)
7345  {
7346  c_item = &(tc->utf8_to_text[utf8_cp - tc->utf8_first_cp]);
7347 
7348  con_cp = intl_dbcs_to_cp (c_item->bytes, c_item->size, tc->byte_flag, &next);
7349  assert (next - c_item->bytes == c_item->size);
7350 
7351  if (con_cp == 0x3f)
7352  {
7353  assert (utf8_cp != 0x3f);
7354  printf ("Ux%04X [%s] -> Not mapped\n", utf8_cp, utf8_seq);
7355  continue;
7356  }
7357 
7358  cnv_utf8 = cnv_utf8_buf;
7359  utf8_size = sizeof (cnv_utf8_buf);
7360 
7362  {
7363  err = intl_text_single_byte_to_utf8_ext (tc, c_item->bytes, c_item->size, &cnv_utf8, &utf8_size);
7364  assert (err == NO_ERROR);
7365  }
7366  else
7367  {
7368  err = intl_text_dbcs_to_utf8_ext (tc, c_item->bytes, c_item->size, &cnv_utf8, &utf8_size);
7369  assert (err == NO_ERROR);
7370  }
7371  assert ((unsigned int) utf8_size <= sizeof (cnv_utf8_buf));
7372  char_to_print = cnv_utf8 ? cnv_utf8 : utf8_seq;
7373  }
7374 
7376  {
7377  printf ("Ux%04X [%s] -> %02X | %s\n", utf8_cp, utf8_seq, con_cp, char_to_print);
7378  }
7379  else
7380  {
7381  printf ("Ux%04X [%s] -> %04X | %s\n", utf8_cp, utf8_seq, con_cp, char_to_print);
7382  }
7383  }
7384 
7385  printf ("Codepoints above Ux%04X are not mapped\n", tc->utf8_last_cp);
7386 
7387 exit:
7388  return 0;
7389 }
7390 
7391 #define BUF_PUT_INT16(buf,v) \
7392  do { \
7393  unsigned short nv = htons(v); \
7394  *((unsigned char *) (buf)) = ((unsigned char *) &nv)[1]; \
7395  buf = (char *) (buf) + 1; \
7396  *((unsigned char *) (buf)) = ((unsigned char *) &nv)[0]; \
7397  buf = (char *) (buf) + 1; \
7398  } while (0)
7399 
7400 #define BUF_PUT_INT32(buf,v) \
7401  do { \
7402  unsigned int nv = htonl(v); \
7403  *((unsigned char *) (buf)) = ((unsigned char *) &nv)[3]; \
7404  buf = (char *) (buf) + 1; \
7405  *((unsigned char *) (buf)) = ((unsigned char *) &nv)[2]; \
7406  buf = (char *) (buf) + 1; \
7407  *((unsigned char *) (buf)) = ((unsigned char *) &nv)[1]; \
7408  buf = (char *) (buf) + 1; \
7409  *((unsigned char *) (buf)) = ((unsigned char *) &nv)[0]; \
7410  buf = (char *) (buf) + 1; \
7411  } while (0)
7412 
7413 #define BUF_ALIGN(buf, align) \
7414  ((char *)((((UINTPTR)(buf) + ((UINTPTR)((align)-1)))) \
7415  & ~((UINTPTR)((align)-1))))
7416 
7417 /*
7418  * locale_compute_coll_checksum() - Computes the MD5 checksum of collation
7419  *
7420  * Returns: error status
7421  * coll_data(in/out):
7422  */
7423 static int
7425 {
7426  int input_size = 0;
7427  char *input_buf = NULL;
7428  char *buf_pos;
7429  int error_code = NO_ERROR;
7430  int cp, w;
7431 
7432  if (cd->uca_opt.sett_expansions)
7433  {
7434  /* Weights L1-L3 */
7435  input_size += cd->uca_exp_num * cd->w_count * sizeof (cd->uca_w_l13[0]);
7437  {
7438  /* Weights L4 */
7439  input_size += cd->uca_exp_num * cd->w_count * sizeof (cd->uca_w_l4[0]);
7440  }
7441  }
7442  else
7443  {
7444  /* single level weights */
7445  input_size += cd->w_count * sizeof (cd->weights[0]);
7446  }
7447 
7448  /* next_cp */
7449  input_size += cd->w_count * sizeof (cd->next_cp[0]);
7450 
7451  if (cd->count_contr > 0)
7452  {
7453  /* contractions list */
7454  input_size += cd->count_contr * sizeof (COLL_CONTRACTION);
7455 
7456  input_size += sizeof (cd->contr_min_size);
7457  input_size += sizeof (cd->cp_first_contr_offset);
7458  input_size += sizeof (cd->cp_first_contr_count);
7459  }
7460 
7461  input_size += sizeof (UCA_OPTIONS);
7462 
7463  /* build buffer */
7464  input_buf = (char *) malloc (input_size);
7465  if (input_buf == NULL)
7466  {
7467  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_GEN, true);
7468  return ER_LOC_GEN;
7469  }
7470 
7471  memset (input_buf, 0, input_size);
7472  buf_pos = input_buf;
7473 
7474  if (cd->uca_opt.sett_expansions)
7475  {
7476  for (cp = 0; cp < cd->w_count; cp++)
7477  {
7478  for (w = 0; w < cd->uca_exp_num; w++)
7479  {
7480  BUF_PUT_INT32 (buf_pos, cd->uca_w_l13[cp * cd->uca_exp_num + w]);
7481  }
7482  }
7483 
7485  {
7486  /* Weights L4 */
7487  for (cp = 0; cp < cd->w_count; cp++)
7488  {
7489  for (w = 0; w < cd->uca_exp_num; w++)
7490  {
7491  BUF_PUT_INT16 (buf_pos, cd->uca_w_l4[cp * cd->uca_exp_num + w]);
7492  }
7493  }
7494  }
7495  }
7496  else
7497  {
7498  for (cp = 0; cp < cd->w_count; cp++)
7499  {
7500  BUF_PUT_INT32 (buf_pos, cd->weights[cp]);
7501  }
7502  }
7503 
7504  for (cp = 0; cp < cd->w_count; cp++)
7505  {
7506  BUF_PUT_INT32 (buf_pos, cd->next_cp[cp]);
7507  }
7508 
7509  if (cd->count_contr > 0)
7510  {
7511  /* contractions list */
7512  for (cp = 0; cp < cd->count_contr; cp++)
7513  {
7514  COLL_CONTRACTION *c = &(cd->contr_list[cp]);
7515 
7516  BUF_PUT_INT32 (buf_pos, c->next);
7517  BUF_PUT_INT32 (buf_pos, c->wv);
7518  for (w = 0; w < MAX_UCA_EXP_CE; w++)
7519  {
7520  BUF_PUT_INT32 (buf_pos, c->uca_w_l13[w]);
7521  }
7522  for (w = 0; w < MAX_UCA_EXP_CE; w++)
7523  {
7524  BUF_PUT_INT16 (buf_pos, c->uca_w_l4[w]);
7525  }
7526 
7527  memcpy (buf_pos, c->c_buf, sizeof (c->c_buf));
7528  buf_pos += sizeof (c->c_buf);
7529 
7530  *buf_pos++ = c->cp_count;
7531  *buf_pos++ = c->size;
7532  *buf_pos++ = c->uca_num;
7533 
7534  buf_pos +=
7535  sizeof (COLL_CONTRACTION) - (2 * sizeof (int) + MAX_UCA_EXP_CE * sizeof (int) +
7536  MAX_UCA_EXP_CE * sizeof (short) + sizeof (c->c_buf) + 3 * sizeof (char));
7537  }
7538 
7539  BUF_PUT_INT32 (buf_pos, cd->contr_min_size);
7540 
7541  BUF_PUT_INT32 (buf_pos, cd->cp_first_contr_offset);
7542 
7543  BUF_PUT_INT32 (buf_pos, cd->cp_first_contr_count);
7544  }
7545 
7546  BUF_PUT_INT32 (buf_pos, cd->uca_opt.sett_strength);
7547  *buf_pos++ = (unsigned char) (cd->uca_opt.sett_backwards);
7548  *buf_pos++ = (unsigned char) (cd->uca_opt.sett_caseLevel);
7549  buf_pos = BUF_ALIGN (buf_pos, sizeof (int));
7550  BUF_PUT_INT32 (buf_pos, cd->uca_opt.sett_caseFirst);
7551  *buf_pos++ = (unsigned char) (cd->uca_opt.sett_expansions);
7552  buf_pos = BUF_ALIGN (buf_pos, sizeof (int));
7553  BUF_PUT_INT32 (buf_pos, cd->uca_opt.sett_contr_policy);
7554  *buf_pos++ = (unsigned char) (cd->uca_opt.use_only_first_ce);
7555  buf_pos = BUF_ALIGN (buf_pos, sizeof (int));
7556  BUF_PUT_INT32 (buf_pos, cd->uca_opt.sett_match_contr);
7557 
7558  if (buf_pos - input_buf != input_size)
7559  {
7560  LOG_LOCALE_ERROR ("Error on collation checksum", ER_LOC_GEN, true);
7561  free (input_buf);
7562  return ER_LOC_GEN;
7563  }
7564  assert (buf_pos - input_buf == input_size);
7565 
7566  memset (cd->checksum, 0, sizeof (cd->checksum));
7567  error_code = crypt_md5_buffer_hex (input_buf, input_size, cd->checksum);
7568 
7569  free (input_buf);
7570  return error_code;
7571 }
7572 
7573 /*
7574  * locale_alphabet_data_size() - Computes the size required by alphabet data
7575  *
7576  * Returns: size in bytes
7577  * a(in):
7578  */
7579 static int
7581 {
7582  int input_size = 0;
7583 
7584  input_size += sizeof (a->a_type);
7585  input_size += a->l_count * a->lower_multiplier * sizeof (a->lower_cp[0]);
7586  input_size += a->l_count * a->upper_multiplier * sizeof (a->upper_cp[0]);
7587 
7588  return input_size;
7589 }
7590 
7591 /*
7592  * locale_alphabet_data_to_buf() - Saves alphabet data to a buffer
7593  *
7594  * Returns: size in bytes
7595  * a(in):
7596  * buf(out):
7597  *
7598  * Note : this is used in for data checksum purpose
7599  */
7600 static int
7602 {
7603  char *buf_pos = buf;
7604  int cp, m;
7605 
7606  BUF_PUT_INT32 (buf_pos, a->a_type);
7607 
7608  for (cp = 0; cp < a->l_count; cp++)
7609  {
7610  for (m = 0; m < a->lower_multiplier; m++)
7611  {
7612  BUF_PUT_INT32 (buf_pos, a->lower_cp[cp * a->lower_multiplier + m]);
7613  }
7614  }
7615 
7616  for (cp = 0; cp < a->l_count; cp++)
7617  {
7618  for (m = 0; m < a->upper_multiplier; m++)
7619  {
7620  BUF_PUT_INT32 (buf_pos, a->upper_cp[cp * a->upper_multiplier + m]);
7621  }
7622  }
7623 
7624  return CAST_BUFLEN (buf_pos - buf);
7625 }
7626 
7627 /*
7628  * locale_compute_locale_checksum() - Computes the MD5 checksum of locale data
7629  *
7630  * Returns: error status
7631  * ld(in/out):
7632  */
7633 static int
7635 {
7636  int input_size = 0;
7637  char *input_buf = NULL;
7638  char *buf_pos;
7639  int error_code = NO_ERROR;
7640  int cp;
7641 
7642  input_size += sizeof (ld->dateFormat);
7643  input_size += sizeof (ld->timeFormat);
7644  input_size += sizeof (ld->datetimeFormat);
7645  input_size += sizeof (ld->timestampFormat);
7646  input_size += sizeof (ld->timetzFormat);
7647  input_size += sizeof (ld->datetimetzFormat);
7648  input_size += sizeof (ld->timestamptzFormat);
7649 
7650  input_size += sizeof (ld->month_names_abbreviated);
7651  input_size += sizeof (ld->month_names_wide);
7652  input_size += sizeof (ld->day_names_abbreviated);
7653  input_size += sizeof (ld->day_names_wide);
7654  input_size += sizeof (ld->am_pm);
7655 
7656  input_size += sizeof (ld->day_names_abbr_parse_order);
7657  input_size += sizeof (ld->day_names_wide_parse_order);
7658  input_size += sizeof (ld->month_names_abbr_parse_order);
7659  input_size += sizeof (ld->month_names_wide_parse_order);
7660  input_size += sizeof (ld->am_pm_parse_order);
7661 
7662  input_size += sizeof (ld->number_decimal_sym);
7663  input_size += sizeof (ld->number_group_sym);
7664  input_size += sizeof (ld->default_currency_code);
7665 
7666  input_size += locale_alphabet_data_size (&(ld->alphabet));
7667  input_size += locale_alphabet_data_size (&(ld->identif_alphabet));
7668 
7669  input_size += sizeof (ld->txt_conv.conv_type);
7671  {
7672  TEXT_CONVERSION *tc = &(ld->txt_conv);
7673 
7674  input_size += sizeof (tc->byte_flag);
7675  input_size += sizeof (tc->utf8_first_cp);
7676  input_size += sizeof (tc->utf8_last_cp);
7677  input_size += sizeof (tc->text_first_cp);
7678  input_size += sizeof (tc->text_last_cp);
7679 
7680  input_size += strlen (tc->nl_lang_str);
7681  input_size += strlen (tc->win_codepages);
7682 
7683  input_size += (tc->utf8_last_cp - tc->utf8_first_cp + 1) * sizeof (CONV_CP_TO_BYTES);
7684  input_size += (tc->text_last_cp - tc->text_first_cp + 1) * sizeof (CONV_CP_TO_BYTES);
7685  }
7686 
7688  {
7690 
7691  input_size += MAX_UNICODE_CHARS * sizeof (un->unicode_mapping_index[0]);
7692  input_size += MAX_UNICODE_CHARS * sizeof (un->list_full_decomp[0]);
7693 
7694  input_size += un->unicode_mappings_count * sizeof (UNICODE_MAPPING);
7695  }
7696 
7697  /* build buffer */
7698  input_buf = (char *) malloc (input_size);
7699  if (input_buf == NULL)
7700  {
7701  LOG_LOCALE_ERROR ("memory allocation failed", ER_LOC_GEN, true);
7702  return ER_LOC_GEN;
7703  }
7704 
7705  buf_pos = input_buf;
7706  memset (input_buf, 0, input_size);
7707 
7708  /* formats */
7709  memcpy (buf_pos, ld->dateFormat, sizeof (ld->dateFormat));
7710  buf_pos += sizeof (ld->dateFormat);
7711 
7712  memcpy (buf_pos, ld->timeFormat, sizeof (ld->timeFormat));
7713  buf_pos += sizeof (ld->timeFormat);
7714 
7715  memcpy (buf_pos, ld->datetimeFormat, sizeof (ld->datetimeFormat));
7716  buf_pos += sizeof (ld->datetimeFormat);
7717 
7718  memcpy (buf_pos, ld->timestampFormat, sizeof (ld->timestampFormat));
7719  buf_pos += sizeof (ld->timestampFormat);
7720 
7721  memcpy (buf_pos, ld->timetzFormat, sizeof (ld->timetzFormat));
7722  buf_pos += sizeof (ld->timetzFormat);
7723 
7724  memcpy (buf_pos, ld->datetimetzFormat, sizeof (ld->datetimetzFormat));
7725  buf_pos += sizeof (ld->datetimetzFormat);
7726 
7727  memcpy (buf_pos, ld->timestamptzFormat, sizeof (ld->timestamptzFormat));
7728  buf_pos += sizeof (ld->timestamptzFormat);
7729 
7730  /* calendar names */
7731  memcpy (buf_pos, ld->month_names_abbreviated, sizeof (ld->month_names_abbreviated));
7732  buf_pos += sizeof (ld->month_names_abbreviated);
7733 
7734  memcpy (buf_pos, ld->month_names_wide, sizeof (ld->month_names_wide));
7735  buf_pos += sizeof (ld->month_names_wide);
7736 
7737  memcpy (buf_pos, ld->day_names_abbreviated, sizeof (ld->day_names_abbreviated));
7738  buf_pos += sizeof (ld->day_names_abbreviated);
7739 
7740  memcpy (buf_pos, ld->day_names_wide, sizeof (ld->day_names_wide));
7741  buf_pos += sizeof (ld->day_names_wide);
7742 
7743  memcpy (buf_pos, ld->am_pm, sizeof (ld->am_pm));
7744  buf_pos += sizeof (ld->am_pm);
7745 
7746  /* calendar parsing order */
7747  memcpy (buf_pos, ld->day_names_abbr_parse_order, sizeof (ld->day_names_abbr_parse_order));
7748  buf_pos += sizeof (ld->day_names_abbr_parse_order);
7749 
7750  memcpy (buf_pos, ld->day_names_wide_parse_order, sizeof (ld->day_names_wide_parse_order));
7751  buf_pos += sizeof (ld->day_names_wide_parse_order);
7752 
7753  memcpy (buf_pos, ld->month_names_abbr_parse_order, sizeof (ld->month_names_abbr_parse_order));
7754  buf_pos += sizeof (ld->month_names_abbr_parse_order);
7755 
7756  memcpy (buf_pos, ld->month_names_wide_parse_order, sizeof (ld->month_names_wide_parse_order));
7757  buf_pos += sizeof (ld->month_names_wide_parse_order);
7758 
7759  memcpy (buf_pos, ld->am_pm_parse_order, sizeof (ld->am_pm_parse_order));
7760  buf_pos += sizeof (ld->am_pm_parse_order);
7761 
7762  /* number symbols */
7763  memcpy (buf_pos, &(ld->number_decimal_sym), sizeof (ld->number_decimal_sym));
7764  buf_pos += sizeof (ld->number_decimal_sym);
7765 
7766  memcpy (buf_pos, &(ld->number_group_sym), sizeof (ld->number_group_sym));
7767  buf_pos += sizeof (ld->number_group_sym);
7768 
7769  BUF_PUT_INT32 (buf_pos, ld->default_currency_code);
7770 
7771  /* alphabets */
7772  buf_pos += locale_alphabet_data_to_buf (&(ld->alphabet), buf_pos);
7773  buf_pos += locale_alphabet_data_to_buf (&(ld->identif_alphabet), buf_pos);
7774 
7775  /* text conversion */
7776  BUF_PUT_INT32 (buf_pos, ld->txt_conv.conv_type);
7777 
7779  {
7780  TEXT_CONVERSION *tc = &(ld->txt_conv);
7781 
7782  memcpy (buf_pos, tc->byte_flag, sizeof (tc->byte_flag));
7783  buf_pos += sizeof (tc->byte_flag);
7784 
7785  BUF_PUT_INT32 (buf_pos, tc->utf8_first_cp);
7786  BUF_PUT_INT32 (buf_pos, tc->utf8_last_cp);
7787  BUF_PUT_INT32 (buf_pos, tc->text_first_cp);
7788  BUF_PUT_INT32 (buf_pos, tc->text_last_cp);
7789 
7790  memcpy (buf_pos, tc->nl_lang_str, strlen (tc->nl_lang_str));
7791  buf_pos += strlen (tc->nl_lang_str);
7792 
7793  memcpy (buf_pos, tc->win_codepages, strlen (tc->win_codepages));
7794  buf_pos += strlen (tc->win_codepages);
7795 
7796  memcpy (buf_pos, tc->utf8_to_text, (tc->utf8_last_cp - tc->utf8_first_cp + 1) * sizeof (CONV_CP_TO_BYTES));
7797  buf_pos += (tc->utf8_last_cp - tc->utf8_first_cp + 1) * sizeof (CONV_CP_TO_BYTES);
7798 
7799  memcpy (buf_pos, tc->text_to_utf8, (tc->text_last_cp - tc->text_first_cp + 1) * sizeof (CONV_CP_TO_BYTES));
7800  buf_pos += (tc->text_last_cp - tc->text_first_cp + 1) * sizeof (CONV_CP_TO_BYTES);
7801  }
7802 
7804  {
7806 
7807  for (cp = 0; cp < MAX_UNICODE_CHARS; cp++)
7808  {
7809  BUF_PUT_INT32 (buf_pos, un->unicode_mapping_index[cp]);
7810  }
7811 
7812  for (cp = 0; cp < MAX_UNICODE_CHARS; cp++)
7813  {
7814  BUF_PUT_INT32 (buf_pos, un->list_full_decomp[cp]);
7815  }
7816 
7817  for (cp = 0; cp < un->unicode_mappings_count; cp++)
7818  {
7819  UNICODE_MAPPING *um = &(un->unicode_mappings[cp]);
7820  BUF_PUT_INT32 (buf_pos, um->cp);
7821  BUF_PUT_INT32 (buf_pos, um->size);
7822  memcpy (buf_pos, um->buffer, sizeof (um->buffer));
7823  buf_pos += sizeof (um->buffer);
7824 
7825  buf_pos += sizeof (UNICODE_MAPPING) - (sizeof (um->buffer) + 2 * sizeof (int));
7826  }
7827  }
7828 
7829  if (buf_pos - input_buf != input_size)
7830  {
7831  LOG_LOCALE_ERROR ("Error on locale checksum", ER_LOC_GEN, true);
7832  free (input_buf);
7833  return ER_LOC_GEN;
7834  }
7835  assert (buf_pos - input_buf == input_size);
7836 
7837  memset (ld->checksum, 0, sizeof (ld->checksum));
7838  error_code = crypt_md5_buffer_hex (input_buf, input_size, ld->checksum);
7839 
7840  free (input_buf);
7841  return error_code;
7842 }
7843 
7844 /*
7845  * common_collation_end_rule() - finishes a collation rule
7846  *
7847  * Returns: error status
7848  * data(in/out): user data
7849  * ld(in/out): locale data
7850  * rule_id(in): collation rule id (position in rule list)
7851  * t_rule(in/out): collation rule
7852  */
7853 static int
7854 common_collation_end_rule (void *data, LOCALE_DATA * ld, const int rule_id, TAILOR_RULE * t_rule)
7855 {
7856  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
7857 
7858  assert (data != NULL);
7859  assert (ld != NULL);
7860  assert (t_rule != NULL);
7861 
7862  if (ld->last_rule_level != TAILOR_UNDEFINED)
7863  {
7864  if (ld->last_rule_level != t_rule->level)
7865  {
7866  /* first rule must match the level of anchor */
7868  PRINT_DEBUG_END (data, "Rule level doesn't match reset level", -1);
7869  return -1;
7870  }
7871 
7872  /* reset level of anchor : don't need to check for following rules */
7874  }
7875 
7876  t_rule->direction = ld->last_rule_dir;
7877  t_rule->r_pos_type = ld->last_rule_pos_type;
7878 
7879  /* last tailor character is the new reference */
7880  if (!(t_rule->multiple_chars))
7881  {
7882  /* reset rule position */
7884 
7885  assert (t_rule->t_buf_size > 0);
7886 
7887  ld->last_r_buf_size = t_rule->t_buf_size;
7888  ld->last_r_buf_p = t_rule->t_buf;
7889 
7890  memcpy (ld->last_anchor_buf, t_rule->t_buf, t_rule->t_buf_size);
7891  ld->last_anchor_buf[t_rule->t_buf_size] = '\0';
7892  }
7893 
7894  /* BEFORE applies only for the first rule after <reset> */
7896 
7897  if (pd->verbose)
7898  {
7899  char msg[ERR_MSG_SIZE];
7900  int xml_line_no = XML_GetCurrentLineNumber (pd->xml_parser);
7901  int xml_col_no = XML_GetCurrentColumnNumber (pd->xml_parser);
7902 
7903  snprintf (msg, sizeof (msg) - 1, "* Rule %d, L :%d, Dir:%d, PosType:%d, Mc:%d ;" " XML: line: %d , col:%d *",
7904  rule_id, t_rule->level, t_rule->direction, t_rule->r_pos_type, t_rule->multiple_chars, xml_line_no,
7905  xml_col_no);
7906  PRINT_DEBUG_END (data, msg, 0);
7907  }
7908 
7909  return 0;
7910 }
7911 
7912 /*
7913  * common_collation_start_rule() - starts a collation rule
7914  *
7915  * Returns: error status
7916  * data(in/out): user data
7917  * attr(in): element name
7918  * ld(in/out): locale data
7919  * t_rule(in/out): collation rule
7920  */
7921 static int
7922 common_collation_start_rule (void *data, const char **attr, LOCALE_DATA * ld, TAILOR_RULE * t_rule)
7923 {
7924  char *ref_buf_p = NULL;
7925  int ref_buf_size = 0;
7926  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
7927 
7928  assert (data != NULL);
7929  assert (ld != NULL);
7930  assert (t_rule != NULL);
7931 
7933 
7934  strcpy (t_rule->anchor_buf, ld->last_anchor_buf);
7935 
7936  /* reference is last reference or anchor if no last refence is available */
7937  if (ld->last_r_buf_p == NULL)
7938  {
7939  ref_buf_p = ld->last_anchor_buf;
7940  ref_buf_size = strlen (ld->last_anchor_buf);
7941  }
7942  else
7943  {
7944  ref_buf_p = ld->last_r_buf_p;
7945  ref_buf_size = ld->last_r_buf_size;
7946  }
7947 
7948  assert (ref_buf_size > 0);
7949  assert (ref_buf_p != NULL);
7950 
7951  t_rule->r_buf = (char *) malloc (ref_buf_size);
7952  if (t_rule->r_buf == NULL)
7953  {
7955  PRINT_DEBUG_START (data, attr, "memory allocation failed", -1);
7956  return -1;
7957  }
7958  memcpy (t_rule->r_buf, ref_buf_p, ref_buf_size);
7959  t_rule->r_buf_size = ref_buf_size;
7960 
7961  return 0;
7962 }
7963 
7964 /*
7965  * start_include_collation() - XML element start function
7966  * "ldml collations include"
7967  *
7968  * return: 0 validation OK enter this element , 1 validation NOK do not enter
7969  * -1 error abort parsing
7970  * data: user data
7971  * attr: attribute/value pair array
7972  */
7973 static int
7974 start_include_collation (void *data, const char **attr)
7975 {
7976  XML_PARSER_DATA *pd = (XML_PARSER_DATA *) data;
7977  LOCALE_DATA *ld = NULL;
7978  XML_PARSER_DATA *new_pd = NULL;
7979  char *att_val = NULL;
7980  char include_file_path[PATH_MAX] = { 0 };
7981  char *prev_ldml_file = NULL;
7982  int prev_line_no = 0;
7983  LDML_CONTEXT *context = NULL;
7984 
7985  assert (data != NULL);
7986 
7987  if (xml_get_att_value (attr, "file", &att_val) != 0)
7988  {
7989  LOG_LOCALE_ERROR ("<include> tag requires a valid FILE attribute.", ER_LOC_GEN, true);
7990  PRINT_DEBUG_START (data, attr, "<include> tag requires a valid " "FILE attribute.", -1);
7991 
7992  return -1;
7993  }
7994 
7995  /* build a path and check if the file exists/is accessible */
7996  envvar_ldmldir_file (include_file_path, PATH_MAX, att_val);
7997  new_pd = xml_create_subparser (pd, include_file_path);
7998 
7999  ld = (LOCALE_DATA *) XML_USER_DATA (new_pd);
8000  assert (ld != NULL);
8001 
8002  context = &(ld->ldml_context);
8003  prev_ldml_file = context->ldml_file;
8004  prev_line_no = context->line_no;
8005  context->ldml_file = strdup (include_file_path);
8006  context->line_no = 0;
8007 
8008  int ret;
8009  if (new_pd == NULL)
8010  {
8011  char err_msg[ERR_MSG_SIZE] = { 0 };
8012 
8013  switch (pd->xml_error)
8014  {
8016  ret = snprintf (err_msg, sizeof (err_msg) - 1, "Inclusion loop found for file %s.", include_file_path);
8017  break;
8019  ret = snprintf (err_msg, sizeof (err_msg) - 1, "Failed to initialize subparser for file path %s.",
8020  include_file_path);
8021  break;
8022  case XML_CUB_OUT_OF_MEMORY:
8023  ret = snprintf (err_msg, sizeof (err_msg) - 1, "Memory exhausted when creating subparser for file %s.",
8024  include_file_path);
8025  break;
8026  }
8027  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
8028  PRINT_DEBUG_START (data, attr, err_msg, -1);
8029 
8030  return -1;
8031  }
8032 
8033  xml_parser_exec (new_pd);
8034 
8035  if (new_pd->xml_error == XML_CUB_ERR_FILE_MISSING)
8036  {
8037  char err_msg[ERR_MSG_SIZE] = { 0 };
8038 
8039  snprintf_dots_truncate (err_msg, sizeof (err_msg) - 1, "Included file %s does not exist or " "is not accessible.",
8040  include_file_path);
8041  PRINT_DEBUG_START (data, attr, err_msg, -1);
8042  LOG_LOCALE_ERROR (err_msg, ER_LOC_GEN, true);
8043 
8044  return -1;
8045  }
8046  else if (new_pd->xml_error != XML_CUB_NO_ERROR)
8047  {
8048  char msg[ERR_MSG_SIZE] = { 0 };
8049  const char *xml_err_text = (char *) XML_ErrorString (XML_GetErrorCode (new_pd->xml_parser));
8050 
8051  snprintf_dots_truncate (msg, sizeof (msg) - 1, "Error parsing file %s, " "line: %d, column: %d. Internal XML: %s",
8052  new_pd->filepath, new_pd->xml_error_line, new_pd->xml_error_column, xml_err_text);
8053  LOG_LOCALE_ERROR (msg, ER_LOC_GEN, true);
8054 
8055  return -1;
8056  }
8057  free (context->ldml_file);
8058  context->ldml_file = prev_ldml_file;
8059  context->line_no = prev_line_no;
8060 
8061  pd->next = new_pd->next;
8062  xml_destroy_parser_data (new_pd);
8063  free (new_pd);
8064 
8065  return 0;
8066 }
XML_ELEMENT_DEF ldml_timetzFormatCUBRID
static int end_day(void *data, const char *el_name)
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_cp
static int start_collation_x(void *data, const char **attr)
const int depth
Definition: xml_parser.h:87
int char_isspace(int c)
Definition: chartype.c:109
const char * month_short_parse_order
int uca_process_collation(LOCALE_COLLATION *lc, bool is_verbose)
Definition: uca_support.c:810
unsigned char bytes[TEXT_CONV_MAX_BYTES]
#define LANG_MAX_COLLATIONS
#define INTL_IS_NEXT_CONTR(v)
XML_ELEMENT_DEF ldml_elem_collation_x_p
#define CAL_AM_PM_COUNT
XML_ELEMENT_DEF ldml_elem_collation_reset_first_non_ignorable
const char * month_name[CAL_MONTH_COUNT]
char nl_lang_str[TXT_CONV_SYSTEM_STR_SIZE]
XML_ELEMENT_DEF ldml_elem_collation_reset_first_secondary_ignorable
static int end_collation_x(void *data, const char *el_name)
XML_ELEMENT_DEF ldml_elem_collation_reset_last_non_ignorable
#define NO_ERROR
Definition: error_code.h:46
char coll_next_cp_ref[LOC_LIB_SYMBOL_NAME_SIZE]
static int common_collation_end_rule(void *data, LOCALE_DATA *ld, const int rule_id, TAILOR_RULE *t_rule)
#define TXT_CONV_ITEM_GROW_COUNT
static int locale_save_calendar_to_C_file(FILE *fp, LOCALE_DATA *ld)
static int end_datetimetzFormatCUBRID(void *data, const char *el_name)
CONV_CP_TO_BYTES * utf8_to_text
const char * date_format
XML_ELEMENT_DEF ldml_elem_collation_reset_last_trailing
XML_ELEMENT_DEF ldml_elem_calendars
#define BUF_PUT_INT32(buf, v)
char coll_cp_first_contr_array_ref[LOC_LIB_SYMBOL_NAME_SIZE]
#define ER_LOC_GEN
Definition: error_code.h:1371
XML_ELEMENT_DEF ldml_elem_dayPeriodContext
UCA_OPTIONS uca_opt
int lang_load_coll_from_lib(COLL_DATA *cd, void *lib_handle, const LOCALE_FILE *lf)
int locale_dump_lib_collations(void *lib_handle, const LOCALE_FILE *lf, int dl_settings, int start_value, int end_value)
#define XML_COMMENT_START
#define XML_CUB_ERR_FILE_MISSING
Definition: xml_parser.h:43
static int end_collation_cubrid_rule_set_cp_ch(void *data, const char *el_name)
bool sett_expansions
unsigned char buffer[NORMALIZATION_MAX_BUF_SIZE]
XML_ELEMENT_DEF ldml_elem_collation_reset_first_tertiary_ignorable
static int end_timestampFormatCUBRID(void *data, const char *el_name)
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_w
#define LOC_DATA_MONTH_ABBR_SIZE
LDML_CONTEXT ldml_context
char month_names_wide_parse_order[CAL_MONTH_COUNT]
#define CAL_MONTH_COUNT
char * locale_name
void uca_free_data(void)
Definition: uca_support.c:2119
static int start_consoleconversion(void *data, const char **attr)
XML_ELEMENT_DEF ldml_elem_collation_settings
CP_BUF_TYPE start_cp_buf_type
char end_cp_buf[LOC_DATA_BUFF_SIZE]
ALPHABET_DATA identif_alphabet
TEXT_CONV_TYPE conv_type
#define START_LANG_RANGE
int locale_compile_locale(LOCALE_FILE *lf, LOCALE_DATA *ld, bool is_verbose)
unsigned char size
XML_ELEMENT_DEF ldml_elem_days
XML_ELEMENT_DEF ldml_elem_collation_s
void locale_free_shared_data(void)
#define UCA_GET_L1_W(v)
COLL_MATCH_CONTR sett_match_contr
char month_names_abbr_parse_order[CAL_MONTH_COUNT]
#define LOC_MAX_UCA_CHARS_SEQ
char filepath[PATH_MAX]
Definition: xml_parser.h:124
XML_ELEMENT_DEF ldml_elem_dayWidth
static int start_upper_case_rule(void *data, const char **attr)
static int end_collation_logical_pos(void *data, const char *el_name)
char last_anchor_buf[LOC_DATA_COLL_TWO_CHARS]
static int start_one_alphabet(void *data, const char **attr)
XML_ELEMENT_DEF ldml_elem_day
char timestampFormat[CAL_COMP_DATE_FORMAT_SIZE]
static int start_dayPeriodWidth(void *data, const char **attr)
static int start_unicode_file(void *data, const char **attr)
XML_ELEMENT_DEF ldml_elem_months
char * last_r_buf_p
static void dump_collation_key(COLL_DATA *coll, const unsigned int key, bool print_weight, bool print_key)
LDML_CONTEXT ldml_context
static int comp_func_coll_uca_simple_weights(const void *arg1, const void *arg2)
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_scp
UCA_L13_W uca_w_l13[MAX_UCA_EXP_CE]
int str_to_uint32(unsigned int *ret_p, char **end_p, const char *str_p, int base)
Definition: porting.c:2382
static int locale_check_and_set_shared_data(const LOC_SHARED_DATA_TYPE lsd_type, const char *lsd_key, const void *data, LDML_CONTEXT *ldml_context, LOC_SHARED_DATA **found_entry)
char start_cp_buf[LOC_DATA_BUFF_SIZE]
ALPHABET_DATA alphabet
XML_PARSER_DATA * xml_create_subparser(XML_PARSER_DATA *pd, char *new_file)
Definition: xml_parser.c:1002
static int end_collation_cubrid_rule_set_w_wr(void *data, const char *el_name)
static TAILOR_RULE * new_collation_rule(LOCALE_DATA *ld)
const char * am_pm[CAL_AM_PM_COUNT]
char * envvar_libdir_file(char *path, size_t size, const char *filename)
static int start_collation_reset(void *data, const char **attr)
XML_ELEMENT_DEF ldml_timestampFormatCUBRID
XML_ELEMENT_DEF ldml_elem_alphabet_upper
XML_ELEMENT_DEF ldml_elem_dayContext
int locale_save_all_to_C_file(LOCALE_DATA **ld, int start_index, int end_index, LOCALE_FILE *lf)
#define PRINT_STRING_ARRAY_TO_C_FILE(fp, valname, arrcount, val, d)
RULE_POS_TYPE last_rule_pos_type
ALPHABET_TYPE a_type
XML_ELEMENT_DEF ldml_elem_numbers
#define TXT_CONV_LINE_SIZE
#define SHARED_DATA_INCR_SIZE
static void clear_data_buffer(XML_PARSER_DATA *pd)
static int start_calendar(void *data, const char **attr)
static int end_dayPeriod(void *data, const char *el_name)
#define LOCLIB_FILE_EXT
void locale_destroy_alphabet_data(const ALPHABET_DATA *a)
T_LEVEL
static int start_one_collation(void *data, const char **attr)
static int start_currency(void *data, const char **attr)
#define DUMPLOCALE_IS_COLLATION_WEIGHT_ORDER
XML_ELEMENT_DEF ldml_elem_alphabet_lower
RULE_POS_TYPE r_pos_type
int(* ELEM_START_FUNC)(void *, const char **)
Definition: xml_parser.h:60
static int locale_alphabet_data_to_buf(ALPHABET_DATA *a, char *buf)
const char * month_short_name[CAL_MONTH_COUNT]
static int handle_data_collation_rule(void *data, const char *s, int len)
static char cmp_token_name_size
static int locale_save_alphabets_to_C_file(FILE *fp, LOCALE_DATA *ld)
XML_Parser xml_init_parser(void *data, const char *xml_file, const char *encoding, XML_ELEMENT_DEF **element_array, const int count)
Definition: xml_parser.c:939
#define XML_CUB_OUT_OF_MEMORY
Definition: xml_parser.h:39
static int end_collation_reset(void *data, const char *el_name)
static int end_month_day_Width(void *data, const char *el_name)
const char * datetime_format
#define XML_CUB_ERR_PARSER
Definition: xml_parser.h:42
int intl_cp_to_utf8(const unsigned int codepoint, unsigned char *utf8_seq)
#define NORM_MAPPING_DUMP_MODE_DECOMP
static int end_timestamptzFormatCUBRID(void *data, const char *el_name)
static int end_datetimeFormatCUBRID(void *data, const char *el_name)
#define BUF_PUT_INT16(buf, v)
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_ch
static int end_collation_cubrid_rule_set(void *data, const char *el_name)
static int locale_save_collation_data_to_C_file(FILE *fp, LOCALE_COLLATION *lc)
XML_ELEMENT_DEF ldml_elem_alphabet_lower_dest
static CUBRID_TAILOR_RULE * new_collation_cubrid_rule(LOCALE_DATA *ld)
XML_ELEMENT_DEF ldml_datetimetzFormatCUBRID
ALPHABET_DATA alphabet
#define NORM_MAPPING_DUMP_MODE_COMP
static int end_collation_x_rule(void *data, const char *el_name)
const char * timestamptz_format
#define XML_USER_DATA(xml)
Definition: xml_parser.h:109
static void locale_make_calendar_parse_order(LOCALE_DATA *ld)
static void locale_destroy_collation_data(const COLL_DATA *cd)
XML_ELEMENT_DEF ldml_elem_alphabet_upper_dest
#define LOC_DATA_DAY_ABBR_SIZE
UCA_OPTIONS uca_opt
char timetzFormat[CAL_SIMPLE_DATE_TZ_FORMAT_SIZE]
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_ech
XML_ELEMENT_DEF ldml_elem_collation_x_s
XML_ELEMENT_DEF ldml_elem_collation_x_t
static int start_numbers_symbols(void *data, const char **attr)
static int end_collation_cubrid_rule_set_ech_ecp(void *data, const char *el_name)
#define LOC_DATA_AM_PM_SIZE
TEXT_CONV_TYPE conv_type
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_ecp
static int locale_check_collation_id(const COLL_TAILORING *coll_tail)
#define COLL_NAME_SIZE
XML_ELEMENT_DEF * def
Definition: xml_parser.h:96
XML_ELEMENT_DEF ldml_elem_consoleconversion
bool use_only_first_ce
char * ldml_file
#define MAX_UNICODE_CHARS
unsigned char uca_num
static int end_element_ok(void *data, const char *el_name)
XML_ELEMENT_DEF ldml_elem_alphabet
char number_group_sym
COLL_DATA_REF coll_ref
XML_Parser xml_parser
Definition: xml_parser.h:114
XML_ELEMENT_DEF ldml_elem_collation
#define XML_CUB_NO_ERROR
Definition: xml_parser.h:36
char month_names_wide[CAL_MONTH_COUNT][LOC_DATA_MONTH_WIDE_SIZE]
struct unicode_mapping UNICODE_MAPPING
LOC_SHARED_DATA_TYPE lsd_type
UNICODE_MAPPING * unicode_mappings
static int end_one_collation(void *data, const char *el_name)
char win_codepages[TXT_CONV_SYSTEM_STR_SIZE]
CONV_CP_TO_BYTES * text_to_utf8
static int end_dateFormatCUBRID(void *data, const char *el_name)
#define DUMPLOCALE_IS_CALENDAR
#define PRINT_STRING_TO_C_FILE(fp, val, len)
LOCALE_COLLATION * collations
ALPHABET_DATA ident_alphabet
static int locale_compute_coll_checksum(COLL_DATA *cd)
int lang_strmatch_utf8_uca_w_coll_data(const COLL_DATA *coll_data, bool is_match, const unsigned char *str1, const int size1, const unsigned char *str2, const int size2, const unsigned char *escape, const bool has_last_escape, int *str1_match_size, bool ignore_trailing_space)
static int locale_save_to_C_file(LOCALE_FILE lf, LOCALE_DATA *ld)
#define assert(x)
static int end_timetzFormatCUBRID(void *data, const char *el_name)
#define DUMPLOCALE_IS_IDENTIFIER_ALPHABET_LOWER
#define START_GENERIC_RANGE
#define ER_GENERIC_ERROR
Definition: error_code.h:49
static int save_contraction_to_C_file(FILE *fp, COLL_CONTRACTION *c, bool use_expansion, bool use_level_4)
static int start_month(void *data, const char **attr)
char am_pm_parse_order[CAL_AM_PM_COUNT]
#define DUMPLOCALE_IS_NORMALIZATION
unsigned int text_first_cp
static int locale_compute_locale_checksum(LOCALE_DATA *ld)
#define UCA_GET_L2_W(v)
char coll_uca_w_l4_ref[LOC_LIB_SYMBOL_NAME_SIZE]
#define PRINT_DUPLICATE_SYMBOL_NAME(symbol, dupl_coll, orig_coll, do_print)
#define COLL_SHARED_DATA_SIZE
XML_ELEMENT_DEF ldml_elem_calendar
#define MAX_STRLEN_FOR_COLLATION_ELEMENT
bool intl_is_currency_symbol(const char *src, DB_CURRENCY *currency, int *symbol_size, const CURRENCY_CHECK_MODE check_mode)
unsigned int text_cp
XML_ELEMENT_DEF ldml_elem_currency
void xml_parser_exec(XML_PARSER_DATA *pd)
Definition: xml_parser.c:1240
#define LANG_MAX_BUILTIN_COLLATIONS
XML_ELEMENT_DEF ldml_elem_collation_t
const char * timestamp_format
const char * day_parse_order
static int handle_data(void *data, const char *s, int len)
unsigned int intl_dbcs_to_cp(const unsigned char *seq, const int size, const unsigned char *byte_flag, unsigned char **next_char)
XML_ELEMENT_DEF ldml_elem_monthContext
UCA_L4_W uca_w_l4[MAX_UCA_EXP_CE]
unsigned int utf8_first_cp
XML_ELEMENT_DEF ldml_elem_collation_sc
XML_ELEMENT_DEF ldml_timeFormatCUBRID
static enum scanner_mode mode
static int start_collation_settings(void *data, const char **attr)
static int end_number_symbol(void *data, const char *el_name)
const char * day_short_parse_order
#define DUMPLOCALE_IS_IDENTIFIER_ALPHABET_UPPER
static int start_day(void *data, const char **attr)
const char * am_pm_parse_order
#define PRINT_DEBUG_START(d, a, m, s)
int locale_dump(void *data, LOCALE_FILE *lf, int dl_settings, int start_value, int end_value)
COLL_TAILORING tail_coll
#define PRINT_DEBUG_END(d, m, s)
static void locale_alloc_collation_id(COLL_TAILORING *coll_tail)
int locale_get_cfg_locales(LOCALE_FILE **p_locale_files, int *p_num_locales, bool is_lang_init)
static LOC_SHARED_DATA * shared_data
static int start_collation_rule(void *data, const char **attr)
#define LOC_DATA_MONTH_WIDE_SIZE
static void print_debug_data_content(void *data, const char *msg, const int status)
static int end_month(void *data, const char *el_name)
#define CAL_DAY_COUNT
const char * time_format
void unicode_free_data(void)
CUBRID_TAILOR_RULE * cub_rules
unsigned int cp_first_contr_count
#define DUMPLOCALE_IS_ALPHABET
static void locale_destroy_alphabet_tailoring(const ALPHABET_TAILORING *cd)
XML_ELEMENT_DEF ldml_elem_collation_i
struct coll_contraction COLL_CONTRACTION
XML_ELEMENT_DEF ldml_elem_collation_reset_first_trailing
XML_ELEMENT_DEF ldml_elem_collation_rules
#define DUMPLOCALE_IS_NUMBERING
char coll_uca_w_l13_ref[LOC_LIB_SYMBOL_NAME_SIZE]
#define NULL
Definition: freelistheap.h:34
char am_pm[CAL_AM_PM_COUNT][LOC_DATA_AM_PM_SIZE]
char checksum[32+1]
unsigned int intl_utf8_to_cp(const unsigned char *utf8, const int size, unsigned char **next_char)
XML_ELEMENT_DEF ldml_elem_dateFormatCUBRID
struct uca_options UCA_OPTIONS
unsigned int * lower_cp
char timestamptzFormat[CAL_COMP_DATE_TZ_FORMAT_SIZE]
static int end_case_rule(void *data, const char *el_name)
int char_isupper(int c)
Definition: chartype.c:49
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_wr
static int start_include_collation(void *data, const char **attr)
#define ER_LOC_INIT
Definition: error_code.h:1370
CP_BUF_TYPE end_cp_buf_type
static int locale_save_one_alphabet_to_C_file(FILE *fp, ALPHABET_DATA *a, bool save_w_identier_name, const char *alpha_suffix)
char number_decimal_sym
static int start_lower_case_rule(void *data, const char **attr)
#define INTL_MAX_UNICODE_CP_ALLOWED
const char * day_name[CAL_DAY_COUNT]
#define err(fd,...)
Definition: porting.h:431
#define MAX_UCA_EXP_CE
int crypt_md5_buffer_hex(const char *buffer, size_t len, char *resblock)
Definition: crypt_opfunc.c:646
char unicode_data_file[PATH_MAX]
int * cp_first_contr_array
#define DUMP_CP_BUF_SIZE
char day_names_wide_parse_order[CAL_DAY_COUNT]
unsigned int utf8_last_cp
#define ID_PER_RANGE
int unicode_process_alphabet(LOCALE_DATA *ld, bool is_verbose)
TAILOR_RULE * rules
XML_ELEMENT_DEF ldml_elem_collation_reset_last_primary_ignorable
char anchor_buf[LOC_DATA_COLL_TWO_CHARS]
XML_ELEMENT_DEF ldml_elem_collation_ic
T_LEVEL last_rule_level
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set_sch
#define PRINT_DEBUG_DATA(d, m, s)
const char * month_parse_order
static int str_pop_token(char *str_p, char **token_p, char **next_p)
#define cmp
Definition: mprec.h:351
#define UNICODE_NORMALIZATION_DECORATOR
static char * cmp_token_name_array
void locale_init_data(LOCALE_DATA *ld, const char *locale_name)
TRANSFORM_TYPE type
#define PRINT_STRING_VAR_TO_C_FILE(fp, valname, val, d)
XML_ELEMENT_DEF ldml_elem_dayPeriodWidth
#define strlen(s1)
char c_buf[LOC_MAX_UCA_CHARS_SEQ *INTL_UTF8_MAX_CHAR_SIZE]
const char * lang_name
#define PRINT_UNNAMED_NUM_ARRAY_TO_C_FILE(fp, intf, tab, arrcount, val)
FILE * fopen_ex(const char *filename, const char *type)
Definition: util_common.c:322
int intl_text_dbcs_to_utf8_ext(void *t, const unsigned char *in_buf, const int in_size, unsigned char **out_buf, int *out_size)
#define XML_COMMENT_END
UNICODE_NORMALIZATION unicode_norm
static int start_dayPeriod(void *data, const char **attr)
char day_names_wide[CAL_DAY_COUNT][LOC_DATA_DAY_WIDE_SIZE]
static int alloced_shared_data
#define LOC_CURRENT_COLL_TAIL(ld)
#define LOC_DATA_COLL_CUBRID_TAILOR_COUNT_GROW
#define CAST_BUFLEN
Definition: porting.h:471
static TRANSFORM_RULE * new_transform_rule(LOCALE_DATA *ld)
#define INTL_UTF8_MAX_CHAR_SIZE
int unicode_process_normalization(LOCALE_DATA *ld, bool is_verbose)
#define DUMPLOCALE_IS_TEXT_CONV
static void dump_collation_contr(COLL_DATA *coll, const COLL_CONTRACTION *contr, bool print_weight, bool print_contr)
static void print_debug_end_el(void *data, const char *msg, const int status)
XML_ELEMENT_DEF ldml_elem_currencies
static void error(const char *msg)
Definition: gencat.c:331
char conv_file[PATH_MAX]
static int start_collation_cubrid_rule_set_wr(void *data, const char **attr)
char checksum[32+1]
static int dump_locale_alphabet(ALPHABET_DATA *ad, int dl_settings, int lower_bound, int upper_bound)
unsigned char byte_flag[256]
char day_names_abbr_parse_order[CAL_DAY_COUNT]
void locale_destroy_data(LOCALE_DATA *ld)
static int locale_alphabet_data_size(ALPHABET_DATA *a)
int intl_utf8_to_cp_list(const unsigned char *utf8, const int size, unsigned int *cp_array, const int max_array_size, int *array_count)
XML_ELEMENT_DEF ldml_elem_collation_pc
XML_ELEMENT_DEF ldml_elem_collation_x_extend
UNICODE_NORMALIZATION unicode_normalization
const char * ldml_ref_day_names[]
static int start_collation_cubrid_rule(void *data, const char **attr)
COLL_CONTRACTION * contr_list
XML_ELEMENT_DEF ldml_elem_dayPeriods
XML_ELEMENT_DEF ldml_elem_dayPeriod
XML_ELEMENT_DEF ldml_elem_collation_reset
#define snprintf_dots_truncate(dest, max_len,...)
Definition: porting.h:323
static int locale_save_normalization_to_C_file(FILE *fp, LOCALE_DATA *ld)
UCA_L13_W * uca_w_l13
XML_ELEMENT_DEF ldml_elem_collation_p
XML_ELEMENT_DEF ldml_elem_alphabet_lower_src
static void dump_collation_codepoint(COLL_DATA *coll, const unsigned int cp, bool print_weight, bool print_cp)
XML_ELEMENT_DEF ldml_elem_collations
static int start_collation_logical_pos(void *data, const char **attr)
char coll_weights_ref[LOC_LIB_SYMBOL_NAME_SIZE]
static int start_element_ok(void *data, const char **attr)
TEXT_CONVERSION * txt_conv
void locale_mark_duplicate_collations(LOCALE_DATA **ld, int start_index, int end_index, bool is_verbose)
XML_ELEMENT_DEF ldml_elem_unicodefile
UCA_L4_W * uca_w_l4
static int locale_save_console_conv_to_C_file(FILE *fp, LOCALE_DATA *ld)
int intl_cp_to_dbcs(const unsigned int codepoint, const unsigned char *byte_flag, unsigned char *seq)
static void locale_destroy_collation_tailorings(const COLL_TAILORING *ct)
#define INTL_MASK_CONTR
static void print_debug_start_el(void *data, const char **attrs, const char *msg, const int status)
int(* ELEM_DATA_FUNC)(void *, const char *, int)
Definition: xml_parser.h:81
char datetimetzFormat[CAL_COMP_DATE_TZ_FORMAT_SIZE]
XML_ELEMENT_DEF ldml_elem_dates
#define LOC_LOCALE_STR_SIZE
int(* ELEM_END_FUNC)(void *, const char *)
Definition: xml_parser.h:70
#define BUF_ALIGN(buf, align)
#define CP_HAS_MAPPINGS(val)
unsigned int unicode_cp
TAILOR_DIR direction
char step[MAX_STRLEN_FOR_COLLATION_ELEMENT]
char day_names_abbreviated[CAL_DAY_COUNT][LOC_DATA_DAY_ABBR_SIZE]
static int dump_console_conversion(TEXT_CONVERSION *tc)
void xml_destroy_parser_data(void *data)
Definition: xml_parser.c:1067
char start_weight[MAX_STRLEN_FOR_COLLATION_ELEMENT]
unsigned int * next_cp
TRANSFORM_RULE * rules
#define LOC_DATA_TAILOR_RULES_COUNT_GROW
void xml_destroy_parser(void *data)
Definition: xml_parser.c:977
DB_CURRENCY default_currency_code
static void locale_destroy_console_conversion(const TEXT_CONVERSION *tc)
XML_PARSER_DATA * next
Definition: xml_parser.h:127
int xml_check_att_value(const char **attrs, const char *att_name, const char *att_value)
Definition: xml_parser.c:1152
TEXT_CONVERSION_PRM txt_conv_prm
XML_ELEMENT_DEF ldml_elem_ldml
#define PRINT_VAR_TO_C_FILE(fp, type, valname, val, format, d)
char * intl_get_money_ISO_symbol(const DB_CURRENCY currency)
XML_ELEMENT_DEF ldml_elem_collation_reset_last_secondary_ignorable
char * envvar_codepagedir_file(char *path, size_t size, const char *filename)
static int comp_func_coll_uca_exp_fo(const void *arg1, const void *arg2)
LDML_CONTEXT ldml_context
const char * datetimetz_format
XML_ELEMENT_DEF ldml_elem_include_collation
char * envvar_loclib_dir_file(char *path, size_t size, const char *filename)
char month_names_abbreviated[CAL_MONTH_COUNT][LOC_DATA_MONTH_ABBR_SIZE]
T_LEVEL sett_strength
int i
Definition: dynamic_load.c:954
XML_ELEMENT_DEF * ldml_elements[]
char * msgcat_message(int cat_id, int set_id, int msg_id)
LOC_SHARED_DATA_TYPE
char dateFormat[CAL_SIMPLE_DATE_FORMAT_SIZE]
#define PRINT_NUM_ARRAY_TO_C_FILE(fp, vname, vtype, intf, arrcount, val, d)
#define LOG_LOCALE_ERROR(msg, er_status, do_print)
XML_ELEMENT_DEF ldml_elem_alphabet_upper_src
unsigned int UCA_L13_W
#define XML_CUB_ERR_PARSER_INIT_FAIL
Definition: xml_parser.h:45
static int start_collations(void *data, const char **attr)
static int end_collation_x_context(void *data, const char *el_name)
#define DUMPLOCALE_IS_IDENTIFIER_ALPHABET
unsigned short int UCA_L4_W
char * strdup(const char *str)
Definition: porting.c:901
#define GET_MAPPING_OFFSET(val)
static int start_calendar_name_context(void *data, const char **attr)
char coll_contr_list_ref[LOC_LIB_SYMBOL_NAME_SIZE]
unsigned char size
XML_ELEMENT_DEF ldml_timestamptzFormatCUBRID
XML_ELEMENT_DEF ldml_elem_symbol_decimal
static LOCALE_COLLATION * new_locale_collation(LOCALE_DATA *ld)
static int comp_func_parse_order_index(const void *arg1, const void *arg2)
LDML_CONTEXT ldml_context
char coll_name[COLL_NAME_SIZE]
char timeFormat[CAL_SIMPLE_DATE_FORMAT_SIZE]
#define DUMPLOCALE_IS_COLLATION_CP_ORDER
const char * ldml_ref_am_pm_names[]
XML_ELEMENT_DEF ldml_elem_collation_reset_first_variable
XML_ELEMENT_DEF ldml_elem_symbol_group
void locale_destroy_normalization_data(UNICODE_NORMALIZATION *norm)
#define LOC_DATA_DAY_WIDE_SIZE
const char * short_name
Definition: xml_parser.h:97
#define NORM_MAPPING_DUMP_MODE_FULL
XML_ELEMENT_DEF ldml_datetimeFormatCUBRID
int xml_get_att_value(const char **attrs, const char *att_name, char **p_att_value)
Definition: xml_parser.c:1180
char lsd_key[COLL_NAME_SIZE]
int lang_load_count_coll_from_lib(int *count_coll, void *lib_handle, const LOCALE_FILE *lf)
unsigned int text_last_cp
XML_ELEMENT_DEF ldml_elem_month
static int load_console_conv_data(LOCALE_DATA *ld, bool is_verbose)
XML_ELEMENT_DEF ldml_elem_collation_x_i
XML_ELEMENT_DEF ldml_elem_alphabets
int locale_prepare_C_file(void)
ALPHABET_TAILORING alpha_tailoring
char coll_name[COLL_NAME_SIZE]
#define XML_CUB_ERR_INCLUDE_LOOP
Definition: xml_parser.h:44
XML_ELEMENT_DEF ldml_elem_collation_reset_last_tertiary_ignorable
#define UCA_GET_L3_W(v)
XML_ELEMENT_DEF ldml_elem_collation_x_context
unsigned int * weights
XML_ELEMENT_DEF ldml_elem_collation_tc
char datetimeFormat[CAL_COMP_DATE_FORMAT_SIZE]
XML_ELEMENT_DEF ldml_elem_numbers_symbols
TAILOR_DIR last_rule_dir
XML_ELEMENT_DEF ldml_elem_monthWidth
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules
DB_CURRENCY default_currency_code
char data_buffer[LOC_DATA_BUFF_SIZE]
#define INTL_GET_NEXT_CONTR_ID(v)
#define DLL_EXPORT_PREFIX
static int comp_func_coll_uca_simple_weights_fo(const void *arg1, const void *arg2)
static int end_timeFormatCUBRID(void *data, const char *el_name)
TEXT_CONVERSION txt_conv
static void dump_locale_normalization(UNICODE_NORMALIZATION *norm)
bool lang_is_coll_name_allowed(const char *name)
#define LOC_DATA_BUFF_SIZE
char * envvar_ldmldir_file(char *path, size_t size, const char *filename)
XML_ELEMENT_DEF ldml_elem_collation_reset_first_primary_ignorable
const char ** p
Definition: dynamic_load.c:945
int locale_check_and_set_default_files(LOCALE_FILE *lf, bool is_lang_init)
#define LOC_DATA_COLL_TWO_CHARS
int contr_min_size
char coll_uca_num_ref[LOC_LIB_SYMBOL_NAME_SIZE]
static COLL_DATA * dump_coll_data
XML_ELEMENT_DEF ldml_elem_collation_cubrid_rules_set
static int end_collation_x_extend(void *data, const char *el_name)
char * uca_num
#define ERR_MSG_SIZE
static void dump_unicode_mapping(UNICODE_MAPPING *um, const int mode)
static int comp_func_coll_uca_exp(const void *arg1, const void *arg2)
static int end_transform_buffer(void *data, const char *el_name)
static int end_collation_rule(void *data, const char *el_name)
static int dump_locale_collation(COLL_DATA *coll, int dl_settings, int start_value, int end_value)
XML_ELEMENT_DEF ldml_elem_collation_x
static int common_collation_start_rule(void *data, const char **attr, LOCALE_DATA *ld, TAILOR_RULE *t_rule)
unsigned int cp_first_contr_offset
unsigned char cp_count
XML_ELEMENT * ce
Definition: xml_parser.h:117
static int start_month_day_Width(void *data, const char **attr)
#define DUMPLOCALE_IS_ALPHABET_LOWER
char * envvar_confdir_file(char *path, size_t size, const char *filename)
#define LOC_DATA_CURRENCY_ISO_CODE_LEN
#define INTL_IDENTIFIER_CASING_SIZE_MULTIPLIER
char locale_name[LOC_LOCALE_STR_SIZE]
int intl_text_single_byte_to_utf8_ext(void *t, const unsigned char *in_buf, const int in_size, unsigned char **out_buf, int *out_size)
const char * day_short_name[CAL_DAY_COUNT]
XML_ELEMENT_DEF ldml_elem_collation_reset_last_variable
unsigned int * upper_cp
static int count_shared_data
int lang_load_get_coll_name_from_lib(const int coll_pos, char **coll_name, void *lib_handle, const LOCALE_FILE *lf)
#define DUMPLOCALE_IS_ALPHABET_UPPER
#define MSGCAT_CATALOG_UTILS