Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
collate.cpp
Go to the documentation of this file.
1
29#include "def.h" // for Def
30#include "diagnostic.h" // for issue_diag()
31#include "path.h" // for get_pathname()
32#include "scanner.h" // for scanner
33
34#include <fstream> // for ofstream
35#include <iostream> // for cout
36#include <string> // for string
37#include <vector> // for vector
38
39#include <cassert> // for assert()
40#include <cctype> // for toupper()
41#include <cstdio> // for sprintf()
42#include <cstdlib> // for strtoul()
43#include <cstring> // for strchr()
44
45
46void Def::
47create_wchar_utf8_table ()
48{
49 if (!wchar_utf8_to_ext_.empty())
50 return;
51
52 typedef std::map<std::string, wchar_t>::const_iterator n_cmap_citer2;
53
54 const n_cmap_citer2 n_cmap_end = charmap_.get_mb_cmap ().end ();
55
56 for (n_cmap_citer2 n_cmap_it = charmap_.get_mb_cmap ().begin ();
57 n_cmap_it != n_cmap_end; ++n_cmap_it) {
58
59 const std::string wchar_utf8 = utf8_encode (n_cmap_it->second);
60
61 wchar_utf8_to_ext_.insert (std::make_pair (wchar_utf8,
62 n_cmap_it->first));
63 }
64}
65
66
67void Def::process_weights (collate_entry_t& entry)
68{
69 // iterator of weights tokens
70 token_list_t::iterator w_it = entry.second.begin ();
71
72 w_cmap_iter wcmap_it;
73 ce_map_iter ce_map_it;
74 coll_map_iter coll_map_it;
75
76 Weights_t* weights = new Weights_t[collate_out_.num_weights];
77
78 int i = 0;
79 for (i = 0; i < collate_out_.num_weights && w_it != entry.second.end ();
80 ++i, ++w_it){
81 get_weight (*w_it, weights, i);
82 }
83
84 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
85
86 // the remaining weights - see above - are given as weight the
87 // collating value of the symbol at start of line
88 while (i < collate_out_.num_weights) {
89 weights[i].size = 1;
90 wcmap_it = w_cmap.find (entry.first.name);
91 if (wcmap_it != w_cmap.end()) {
92 coll_map_it = coll_map_.find (wcmap_it->second);
93 weights[i].weight[0] = coll_map_it->second.coll_val;
94 }
95 else if ((ce_map_it = ce_map_.find (entry.first.name)) !=
96 ce_map_.end()) {
97 weights[i].weight[0] = ce_map_it->second.coll_val;
98 }
99 else {
101 issue_diag (W_COLSYM, false, &entry.first,
102 "symbolic name %s not defined as character or "
103 "collating-element, ignoring\n",
104 entry.first.name.c_str()) || warnings_occurred_;
105 }
106 i++;
107 }
108
109 wcmap_it = w_cmap.find (entry.first.name);
110 if (wcmap_it != w_cmap.end()) {
111 coll_map_it = coll_map_.find (wcmap_it->second);
112 coll_map_it->second.weights = weights;
113 } else if ((ce_map_it = ce_map_.find (entry.first.name)) != ce_map_.end()) {
114 ce_map_it->second.weights = weights;
115 } else {
117 issue_diag (W_COLSYM, false, &entry.first,
118 "symbolic name %s not defined as character or "
119 "collating-element, ignoring\n",
120 entry.first.name.c_str()) || warnings_occurred_;
121 }
122}
123
124
125unsigned int Def::process_order_stmt (collate_section_t& section)
126{
127 // number of orders in the section
128 collate_out_.num_weights = unsigned (section.order.size ());
129 if (collate_out_.num_weights == 0) {
130 collate_out_.num_weights = 1;
131 collate_out_.weight_type[0] = 0;
132 } else {
133 collate_out_.num_weights = 0;
134 token_list_t::iterator ord_it = section.order.begin ();
135 for (; ord_it != section.order.end ();
136 ++ord_it, ++collate_out_.num_weights) {
137 if (ord_it->token == Scanner::tok_forward) {
138 collate_out_.weight_type[collate_out_.num_weights] = 0;
139 } else if (ord_it->token == Scanner::tok_backward) {
140 collate_out_.weight_type[collate_out_.num_weights] = 1;
141 } else if (ord_it->token == Scanner::tok_position) {
142 // this is equivalent to "forward,position"
143 if (no_position_)
144 collate_out_.weight_type[collate_out_.num_weights] = 0;
145 else
146 collate_out_.weight_type[collate_out_.num_weights] = 2;
147 } else {
148 std::string::size_type comma_pos = ord_it->name.find (',');
149 if (comma_pos != std::string::npos) {
150 std::string first = ord_it->name.substr (0, comma_pos);
151 std::string second = ord_it->name.substr (comma_pos + 1);
152
153 // verify a valid weight ordering
154 if ( (first == "forward" && second != "position")
155 || (first == "backward" && second != "position")) {
156 issue_diag (E_COLORD, true,
157 &*ord_it, "unrecognized collating order\n");
158 break;
159 } else if (first == "forward") {
160 if (no_position_)
161 collate_out_.weight_type
162 [collate_out_.num_weights] = 0;
163 else
164 collate_out_.weight_type
165 [collate_out_.num_weights] = 2;
166 }
167 else
168 collate_out_.weight_type[collate_out_.num_weights] = 3;
169 }
170 else {
171 issue_diag (E_COLORD, true,
172 &*ord_it, "unrecognized collating order\n");
173 }
174 }
175 }
176 }
177
178 // build the order value;
179 unsigned int order = 0;
180 for (int i = 0; i < collate_out_.num_weights; ++i) {
181 order <<= 2;
182 order |= collate_out_.weight_type[i];
183 }
184
185 return order;
186}
187
188
189// decimally increment the symbolic name, turning something like
190// <U1234> into <U1245>, or <jis234> to <jis235>
191static std::string
192dec_increment (const std::string &sym)
193{
194 const char *pdig = sym.c_str ();
195
196 for (; !(std::isdigit (*pdig)); ++pdig);
197
198 char *end;
199
200 const unsigned long sym_val = std::strtoul (pdig, &end, 10);
201
202 char numstr [64];
203 std::sprintf (numstr, "%lu", sym_val + 1);
204
205 std::string next_sym = sym.substr (0, pdig - sym.c_str ());
206 next_sym.append (numstr);
207 next_sym.append (end);
208
209 return next_sym;
210}
211
212
213// hexadecimally increment the symbolic name
214static std::string
215hex_increment (const std::string& sym)
216{
217 const char *pdig = sym.c_str ();
218
219 for (; !(std::isxdigit (*pdig)); ++pdig);
220
221 char *end;
222
223 const unsigned long sym_val = std::strtoul (pdig, &end, 16);
224
225 char numstr [64];
226 std::sprintf (numstr, "%lx", sym_val + 1);
227
228 std::string next_sym = sym.substr (0, pdig - sym.c_str ());
229 next_sym.append (numstr);
230 next_sym.append (end);
231
232 return next_sym;
233}
234
235
236// scanning ahead and adding all symbols to the collating symbols map
237void Def::preprocess_collation_definitions()
238{
239 // start with collation values from 2
240 unsigned int coll_value = 2;
241
242 // previous_elm and next_elm are used for processing ellipsis.
243 std::string prev_elm;
244 std::string next_elm;
245
246 token_list_t::iterator cs_it = sym_list_.begin ();
247 for (; cs_it != sym_list_.end (); ++cs_it) {
248 cs_map_iter csm_it = cs_map_.find (cs_it->name);
249 if (csm_it != cs_map_.end ())
250 csm_it->second = coll_value++;
251 }
252
253 static token_list_t::size_type max_orders = 0;
254
255 std::list<collate_section_t>::iterator s_it = section_list_.begin ();
256
257 if (s_it != section_list_.end()) {
258 // get maximum weights count
259 max_orders = s_it->order.size ();
260 }
261
262 for (; s_it != section_list_.end (); ++s_it) {
263 if (max_orders != s_it->order.size ())
264 issue_diag (E_COLNUM, true, &*s_it->order.begin (),
265 "number of collation orders "
266 "different for this section\n");
267 }
268
269 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
270
271 // preprocess sections' collation definitions
272 for (s_it = section_list_.begin ();
273 s_it != section_list_.end (); ++s_it) {
274
275 // process the order statement and get the weight
276 unsigned int order = process_order_stmt (*s_it);
277
278 std::list<collate_entry_t>::iterator e_it =
279 s_it->entries.begin ();
280
281 for (; e_it != s_it->entries.end (); ++e_it) {
282 switch (e_it->first.token) {
284 // store the previous name
285 prev_elm = e_it->first.name;
286
287 // process each of the collation definitions
288 process_collation_definition (false, *e_it,
289 coll_value++, order);
290
291 break;
292
293 case Scanner::tok_abs_ellipsis: // "<FOO>...<BAR>"
294 case Scanner::tok_hex_ellipsis: // "<FOO>..<BAR>"
295 case Scanner::tok_dec_ellipsis: // "<FOO>....<BAR>"
296 {
297
298 if (++e_it != s_it->entries.end ())
299 next_elm = e_it->first.name;
300 else {
301 issue_diag (E_SYNTAX, true, &e_it->first,
302 "unexpected end of collation section while"
303 " processing ellipsis during scan_ahead\n");
304 }
305
306 if (e_it->first.token == Scanner::tok_abs_ellipsis) {
307 wchar_t w_cmap_cur_val
308 = w_cmap.find(prev_elm)->second;
309 wchar_t w_cmap_end_val
310 = w_cmap.find(next_elm)->second;
311
312 // the first value has already been
313 // added so don't add it again
314 w_cmap_cur_val = charmap_.increment_wchar (w_cmap_cur_val);
315 while (w_cmap_cur_val != w_cmap_end_val) {
316 // process iteration
317 collate_info_t ci = {UINT_MAX, UINT_MAX, 0, 0};
318 ci.coll_val = coll_value++;
319 ci.order = order;
320
321 coll_map_.insert (std::make_pair (w_cmap_cur_val, ci));
322 w_cmap_cur_val =
323 charmap_.increment_wchar (w_cmap_cur_val);
324 }
325
326 // add last element "next_elm" to array
327 collate_info_t ci = {UINT_MAX, UINT_MAX, 0, 0};
328 ci.coll_val = coll_value++;
329 ci.order = order;
330 coll_map_.insert (std::make_pair (w_cmap_cur_val, ci));
331
332 }
333 else {
334 // we are incrementing the symbolic names
335 std::string next_name = prev_elm;
336 do {
337 if (e_it->first.token == Scanner::tok_hex_ellipsis)
338 next_name = hex_increment (next_name);
339 else
340 next_name = dec_increment (next_name);
341
342 w_cmap_iter it = w_cmap.find (next_name);
343 if (it != w_cmap.end()) {
344 // process iteration
345 collate_info_t ci = {UINT_MAX, UINT_MAX, 0, 0};
346 ci.coll_val = coll_value++;
347 ci.order = order;
348 coll_map_.insert (
349 std::make_pair (it->second, ci));
350 }
351 } while (next_name != next_elm);
352 }
353
354 prev_elm = next_elm;
355 break;
356 }
357
359 issue_diag (W_NOTSUP, true, &e_it->first,
360 "ellipsis not supported"
361 " processing ellipsis during scan_ahead\n");
362 default:
363 break;
364 }
365 }
366 }
367}
368
369
370void Def::process_collation_definition ( bool do_weights,
371 collate_entry_t& entry,
372 unsigned int coll_value,
373 unsigned int order)
374{
375 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
376
377 // iterators
378 w_cmap_iter w_cmap_pos =
379 w_cmap.find(entry.first.name);
380 ce_map_iter ce_map_pos =
381 ce_map_.find(entry.first.name);
382
383 // look up the symbolic name in the wide character map
384 if (w_cmap_pos != w_cmap.end()) {
385
386 wchar_t wval = w_cmap_pos->second;
387 coll_map_iter coll_map_pos = coll_map_.find (wval);
388
389 coll_map_pos->second.coll_val = coll_value;
390 coll_map_pos->second.order = order;
391
392 // process the weights
393 if (do_weights) {
394 unsigned int offset = next_offset_++;
395 coll_map_pos->second.offset = offset;
396 off_mapr_.insert(std::make_pair(offset, entry.first.name));
397
398 process_weights (entry);
399 }
400
401 }
402 else if (ce_map_pos != ce_map_.end()) {
403
404 ce_map_pos->second.coll_val = coll_value;
405 ce_map_pos->second.order = order;
406
407 // process the weights
408 if (do_weights) {
409 unsigned int offset = next_offset_++;
410 ce_map_pos->second.offset = offset;
411 off_mapr_.insert(std::make_pair(offset, entry.first.name));
412
413 process_weights (entry);
414 }
415
416 }
417 else if (cs_map_.find(entry.first.name) != cs_map_.end()) {
418
419 cs_map_.find(entry.first.name)->second = coll_value;
420
421 }
422 else {
423 // the symbol is missing from all three maps;
424 // add it in cs map as "sym <-> collating_value" pair
425 cs_map_.insert (std::make_pair(entry.first.name, coll_value));
426
428 issue_diag (W_COLSYM, false, &entry.first,
429 "unknown symbol name %s found in "
430 "LC_COLLATE definition\n",
431 entry.first.name.c_str()) || warnings_occurred_;
432 }
433}
434
435void Def::process_order(collate_section_t& section,
436 unsigned int& coll_value)
437{
438 std::string sym;
439
440 // get the orders
441 unsigned int section_order = process_order_stmt (section);
442
443 // current element
444 std::string curr_elm;
445
446 // previous_elm and next_elm are used for processing ellipsis.
447 std::string prev_elm;
448 std::string next_elm;
449
450 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
451
452 // iterate thru section's entries
453 std::list<collate_entry_t>::iterator e_it = section.entries.begin ();
454 for (; e_it != section.entries.end (); ++e_it) {
455 if (e_it->first.token == Scanner::tok_sym_name) {
456 prev_elm = e_it->first.name;
457 process_collation_definition (true, *e_it,
458 coll_value++, section_order);
459
460 }
461 else if ( e_it->first.token == Scanner::tok_abs_ellipsis
462 || e_it->first.token == Scanner::tok_dec_ellipsis
463 || e_it->first.token == Scanner::tok_hex_ellipsis) {
464
465 // process line with ellipsis
466 Weights_t* weights_template =
467 new Weights_t[collate_out_.num_weights];
468 std::vector<bool> ordinal_weights;
469
470 token_list_t::iterator w_it = e_it->second.begin ();
471 for (int i = 0; i < collate_out_.num_weights
472 && w_it != e_it->second.end (); ++i, ++w_it) {
473 ordinal_weights.push_back (
474 get_weight (*w_it,weights_template, i));
475 }
476 while (ordinal_weights.size() < collate_out_.num_weights)
477 ordinal_weights.push_back (true);
478
479 // next line
480 if (++e_it != section.entries.end ())
481 next_elm = e_it->first.name;
482 else {
483 issue_diag (E_SYNTAX, true, &e_it->first,
484 "unexpected end of collation section while"
485 " processing ellipsis\n");
486 }
487
488 if (e_it->first.token == Scanner::tok_abs_ellipsis) {
489 wchar_t w_cmap_cur_val
490 = w_cmap.find(prev_elm)->second;
491 wchar_t w_cmap_end_val
492 = w_cmap.find(next_elm)->second;
493
494 // the first value has already been added so don't add it again
495 w_cmap_cur_val = charmap_.increment_wchar (w_cmap_cur_val);
496
497 while (w_cmap_cur_val != w_cmap_end_val) {
498
499 add_to_coll (w_cmap_cur_val, weights_template,
500 coll_value++, ordinal_weights, false);
501
502 w_cmap_cur_val = charmap_.increment_wchar (w_cmap_cur_val);
503 }
504
505 // add the end element to the collation array.
506 add_to_coll (w_cmap_end_val, weights_template, coll_value++,
507 ordinal_weights, false);
508
509 } else {
510
511 // we are incrementing the symbolic names
512 std::string next_name = prev_elm;
513 do {
514 if (e_it->first.token == Scanner::tok_hex_ellipsis)
515 next_name = hex_increment (next_name);
516 else
517 next_name = dec_increment (next_name);
518
519 w_cmap_iter it = w_cmap.find (next_name);
520 if (it != w_cmap.end()) {
521 add_to_coll (it->second, weights_template,
522 coll_value++, ordinal_weights, false);
523 }
524 } while (next_name != next_elm);
525 }
526
527 // store current left-hand symbol
528 next_elm = prev_elm;
529
530 delete[] weights_template;
531
532 } else if (e_it->first.token == Scanner::tok_undefined) {
533
534 // add all characters that were not explicitely given a collation
535 // value in increasing order based on their encoded values
536 undefined_keyword_found_ = true;
537 collate_out_.undefined_optimization = true;
538 undef_char_info_.order = section_order;
539 Weights_t* weights_template
540 = new Weights_t[collate_out_.num_weights];
541 std::vector<bool> ordinal_weights;
542
543 token_list_t::iterator w_it = e_it->second.begin ();
544 for (int i = 0; i < collate_out_.num_weights
545 && w_it != e_it->second.end(); ++i, ++w_it) {
546
547 if (w_it->token == Scanner::tok_abs_ellipsis)
548 collate_out_.undefined_optimization = false;
549
550 ordinal_weights.push_back (
551 !get_weight (*w_it, weights_template, i));
552 }
553
554 while (ordinal_weights.size() < collate_out_.num_weights)
555 ordinal_weights.push_back (false);
556
557 add_missing_values (ordinal_weights, weights_template,
558 coll_value, false);
559
560 delete[] weights_template;
561 }
562 }
563}
564
565void Def::add_missing_values (const std::vector<bool> &ordinal_weights,
566 const Weights_t* weights_template,
567 unsigned int &coll_value, bool give_warning)
568{
569 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
570
571 // we want to print a warning message once if there are characters that
572 // were not given collation values.
573 bool warning_issued = false;
574
575 symnames_list_iter symnames_it;
576 for (symnames_it = charmap_.get_symnames_list ().begin ();
577 symnames_it != charmap_.get_symnames_list ().end ();
578 ++symnames_it) {
579
580 std::map<std::string, wchar_t>::const_iterator w_cmap_it;
581 if ((w_cmap_it = w_cmap.find(*symnames_it)) != w_cmap.end()) {
582 wchar_t wchar_val = (*w_cmap_it).second;
583
584 coll_map_iter coll_map_it;
585 if ((coll_map_it = coll_map_.find(wchar_val)) != coll_map_.end()) {
586 if (coll_map_it->second.offset == UINT_MAX) {
587 if (give_warning && !warning_issued) {
588 warning_issued = true;
590 issue_diag (W_MISSING, false,
591 0, "some characters in the codeset "
592 "were not explicitly given a "
593 "collation value\n")
595 }
596 if (!collate_out_.undefined_optimization) {
597 add_to_coll (wchar_val, weights_template,
598 coll_value++, ordinal_weights, true);
599 }
600 }
601 }
602 }
603 }
604 if (collate_out_.undefined_optimization){
605 collate_out_.undefined_weight_idx = next_offset_++;
606 undef_char_info_.offset = collate_out_.undefined_weight_idx;
607 undef_char_info_.coll_val = coll_value++;
608 // initialize the weight template with the undefined collation info
609 Weights_t* weights = new Weights_t[collate_out_.num_weights];
610
611 if (0 != weights_template) {
612 for (int k = 0; k < collate_out_.num_weights; ++k) {
613 weights[k].size = weights_template[k].size;
614 for (int j = 0; j < 256; ++j)
615 weights[k].weight[j] = weights_template[k].weight[j];
616 }
617 }
618
619
620 std::vector<bool>::const_iterator it;
621
622 // now go through the vector that tells us if a particular
623 // weight is based on the ordinal position of the element
624 // and place the correct ordinal value in the weight vector
625 // if it is.
626 int i = 0;
627 for (it = ordinal_weights.begin();
628 it != ordinal_weights.end(); ++it, ++i)
629 {
630 // FIXME: this may not be correct
631 if (!*it){
632 weights[i].size = 1;
633 weights[i].weight[0] = undef_char_info_.coll_val;
634 }
635 }
636 undef_char_info_.weights = weights;
637
638
639 }
640}
641
642void Def::add_to_coll (const wchar_t w_cmap_cur_val,
643 const Weights_t* weights_template,
644 const unsigned int coll_value,
645 const std::vector<bool>& ordinal_weights,
646 bool undefined_value)
647{
648 Weights_t* weights = new Weights_t[collate_out_.num_weights];
649
650 if (0 != weights_template) {
651 for (int k = 0; k < collate_out_.num_weights; ++k) {
652 weights[k].size = weights_template[k].size;
653 for (int j = 0; j < 256; ++j)
654 weights[k].weight[j] = weights_template[k].weight[j];
655 }
656 }
657
658 // get the symbolic name from the value
659 std::string name
660 = charmap_.get_rw_cmap().find (w_cmap_cur_val)->second;
661 coll_map_.find (w_cmap_cur_val)->second.coll_val = coll_value;
662
663 unsigned int offset;
664 if (undefined_value && collate_out_.undefined_optimization)
665 offset = next_offset_;
666 else
667 offset = next_offset_++;
668
669 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
670
671 w_cmap_iter w_cmap_pos = w_cmap.find(name);
672 coll_map_iter coll_it = coll_map_.find (w_cmap_pos->second);
673 coll_it->second.offset = offset;
674
675 off_mapr_.insert(std::make_pair(offset, name));
676
677 std::vector<bool>::const_iterator it;
678
679 // now go through the vector that tells us if a particular
680 // weight is based on the ordinal position of the element
681 // and place the correct ordinal value in the weight vector
682 // if it is.
683 int i = 0;
684 for (it = ordinal_weights.begin();
685 it != ordinal_weights.end(); ++it, ++i)
686 {
687 if (*it){
688 weights[i].size = 1;
689 weights[i].weight[0] = coll_value;
690 }
691 }
692 coll_it->second.weights = weights;
693}
694
695// if undefined optimization is on then only those characters that have
696// been defined should go into the valid set, otherwise all characters go
697// into the set.
698void Def::gen_valid_coll_mb_set ()
699{
700 if (!valid_coll_mb_set_.empty())
701 return;
702
703 for (coll_map_iter coll_it = coll_map_.begin();
704 coll_it != coll_map_.end(); ++coll_it) {
705 if (coll_it->second.offset != UINT_MAX
706 || !collate_out_.undefined_optimization){
707 rmb_cmap_iter rn_cmap_it
708 = charmap_.get_rmb_cmap().find (coll_it->first);
709 std::string valid = rn_cmap_it->second.substr
710 (0, rn_cmap_it->second.size() - 1);
711
712 while (valid.size() > 0){
713 valid_coll_mb_set_.insert (valid);
714 valid = valid.substr(0, valid.size() - 1);
715 }
716 }
717 }
718}
719
720
721// In processing the collate section of the locale definition file
722// we will filter out the characters that are not present in the
723// charmap file; these characters when encountered on the left-hand side
724// of a weight definition for a symbolic name will be left in place
725// and used as a mere collating symbol for the rest of the parsing -
726// i.e. its weights ignored and assigned the weight corresponding to
727// its position in the collate section.
728void Def::process_collate()
729{
730 issue_diag (I_STAGE, false, 0, "processing LC_COLLATE section\n");
731
732 // update flags
733 collate_def_found_ = true;
734 // initialization
735 init_coll_map ();
736
737 // first preprocess the collate section
738 preprocess_collate ();
739
740 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
741
742 // process the collating symbols list
743 token_list_t::iterator cs_it = cs_list_.begin ();
744 for (;cs_it != cs_list_.end (); ++cs_it) {
745 if (w_cmap.find (cs_it->name) !=
746 w_cmap.end())
747 issue_diag (E_SYNTAX, true, &*cs_it,
748 "collating-symbol %s found in character map\n",
749 cs_it->name.c_str ());
750 else if (ce_map_.find (cs_it->name) != ce_map_.end())
751 issue_diag (E_SYNTAX, true, &*cs_it,
752 "collating-symbol %s has already been defined as "
753 "a collating-element\n", cs_it->name.c_str ());
754
755 cs_map_.insert (std::make_pair (cs_it->name, 0));
756 }
757
758 // process the collating elements list
759 std::list<collate_elem_t>::iterator ce_it =
760 ce_list_.begin ();
761 for (; ce_it != ce_list_.end (); ++ce_it) {
762 if (w_cmap.find (ce_it->first.name) !=
763 w_cmap.end()) {
764 issue_diag (E_SYNTAX, true, &ce_it->first,
765 "collating element %s found in charmap\n",
766 ce_it->first.name.c_str());
767 }
768
769 // collating element info to be stored
770 ce_info_t ce_tmp;
771 ce_tmp.offset = UINT_MAX;
772 ce_tmp.coll_val = UINT_MAX;
773 ce_tmp.order = 0;
774 ce_tmp.weights = 0;
775
776 // array of symbolic names
777 std::vector<std::string> ce_sym_array;
778
779 // get the definition of this collating element
780 token_list_t& ce_def_list = ce_it->second;
781 token_list_t::iterator ce_def_it = ce_def_list.begin ();
782 bool invalid = false;
783
784 if (ce_def_it->token == Scanner::tok_string) {
785 if ((ce_tmp.ce_wstr = convert_wstring (*ce_def_it)).empty())
786 invalid = true;
787 } else if (ce_def_it->token == Scanner::tok_sym_name) {
788 for (; ce_def_it != ce_def_list.end (); ++ce_def_it)
789 ce_sym_array.push_back (ce_def_it->name);
790 if ((ce_tmp.ce_wstr = convert_wstring (ce_sym_array)).empty())
791 invalid = true;
792 } else {
793 issue_diag (E_SYNTAX, true, &*ce_def_it,
794 "illegal collating-element expression: %s\n",
795 ce_def_it->name.c_str ());
796 }
797 if (invalid)
798 issue_diag (W_SYNTAX, false, &*ce_def_it,
799 "character in collating element definition "
800 "not found in character map\n");
801
802 if (!invalid) {
803 ce_map_.insert (std::make_pair(ce_it->first.name, ce_tmp));
804
805 std::string ce_str;
806 std::string ce_utf8_wstr;
807 for (unsigned int i = 0; i < ce_tmp.ce_wstr.size(); ++i){
808 ce_str += convert_to_ext(ce_tmp.ce_wstr[i]);
809 ce_utf8_wstr += utf8_encode (ce_tmp.ce_wstr[i]);
810 }
811 ce_sym_map_.insert (std::make_pair(ce_str, ce_it->first.name));
812 ce_wsym_map_.insert (std::make_pair (ce_utf8_wstr,
813 ce_it->first.name));
814 }
815 }
816
817 // preprocess the collation definitions and make known all
818 // the symbolic names available
819 preprocess_collation_definitions();
820
821 // collation values 0 and 1 are reserved
822 unsigned int coll_value = 2;
823
824 // FIXME: assign values to the collating-elements AGAIN
825 cs_it = sym_list_.begin ();
826 for (; cs_it != sym_list_.end (); ++cs_it) {
827 cs_map_iter csm_it = cs_map_.find (cs_it->name);
828 if (csm_it != cs_map_.end ())
829 csm_it->second = coll_value++;
830 }
831
832 // process the sections
833 std::list<collate_section_t>::iterator sect_it =
834 section_list_.begin ();
835 for (; sect_it != section_list_.end (); ++sect_it)
836 process_order (*sect_it, coll_value);
837
838 // check to make sure that all the elements in the codeset were added
839 if (!undefined_keyword_found_) {
840 std::vector<bool> ordinal_weights;
841 for (int i = 0; i < collate_out_.num_weights; ++i)
842 ordinal_weights.push_back (false);
843 collate_out_.undefined_optimization = true;
844 add_missing_values (ordinal_weights, 0, coll_value, true);
845 }
846
847}
848
849
850void Def::gen_n_to_w_coll_tables (const std::string &charp,
851 unsigned int tab_num)
852{
853 gen_valid_coll_mb_set();
854 offset_tab_t tab;
855 for (unsigned int k = 0; k <= UCHAR_MAX; ++k) {
856 tab.off[k] = UINT_MAX;
857 }
858
859 tab.first_offset = -1;
860 mb_cmap_iter n_cmap_it;
861
862 for (unsigned int i = 0; i <= UCHAR_MAX; ++i){
863 unsigned char cur_char = (unsigned char)i;
864 std::string mb_char = charp;
865 mb_char += (char)cur_char;
866 if ((n_cmap_it = charmap_.get_mb_cmap().find (mb_char))
867 != charmap_.get_mb_cmap().end()) {
868 coll_map_iter coll_map_it = coll_map_.find (n_cmap_it->second);
869 if (coll_map_it->second.offset != UINT_MAX
870 || !collate_out_.undefined_optimization) {
871 tab.off[cur_char] = coll_map_it->second.offset;
872 if (tab.first_offset == -1)
873 tab.first_offset = cur_char;
874 }
875 }
876 else {
877 if (valid_coll_mb_set_.find (mb_char) != valid_coll_mb_set_.end()){
878 ++next_tab_num_;
879 tab.off[cur_char] = next_tab_num_ | 0x80000000;
880 gen_n_to_w_coll_tables (mb_char, next_tab_num_);
881 if (tab.first_offset == -1)
882 tab.first_offset = cur_char;
883
884 }
885 else {
886 tab.off[cur_char] = UINT_MAX;
887 }
888 }
889 }
890 char_offs_.insert (std::make_pair (tab_num, tab));
891}
892
893
894void Def::gen_w_to_n_coll_tables (const std::string &charp,
895 unsigned int tab_num)
896{
897 // initialize a table used in ctype and collate
898 create_wchar_utf8_table();
899 gen_valid_coll_wchar_set();
900
901 offset_tab_t tab;
902 for (unsigned int k = 0; k <= UCHAR_MAX; ++k)
903 tab.off[k] = UINT_MAX;
904
905 tab.first_offset = -1;
906 wchar_utf8_iter wu_it;
907 mb_cmap_iter n_cmap_it;
908
909 for (unsigned int i = 0; i <= UCHAR_MAX; ++i) {
910 unsigned char cur_char = (unsigned char)i;
911 std::string mb_char = (charp);
912
913 mb_char += (char)cur_char;
914
915 wu_it = wchar_utf8_to_ext_.find (mb_char);
916 if (wu_it != wchar_utf8_to_ext_.end()) {
917 n_cmap_it = charmap_.get_mb_cmap().find (wu_it->second);
918 if (n_cmap_it != charmap_.get_mb_cmap().end ()) {
919
920 coll_map_iter coll_map_it = coll_map_.find (n_cmap_it->second);
921 if (coll_map_it->second.offset != UINT_MAX ||
922 !collate_out_.undefined_optimization) {
923 tab.off[cur_char] = coll_map_it->second.offset;
924 if (tab.first_offset == -1)
925 tab.first_offset = cur_char;
926 }
927 }
928 }
929 else
930 if (valid_coll_wchar_set_.find (mb_char) !=
931 valid_coll_wchar_set_.end()) {
932
933 ++next_wchar_coll_tab_num_;
934 tab.off[cur_char] = next_wchar_coll_tab_num_ | 0x80000000;
935 gen_w_to_n_coll_tables (mb_char,
936 next_wchar_coll_tab_num_);
937 if (tab.first_offset == -1)
938 tab.first_offset = cur_char;
939 }
940 else
941 tab.off[cur_char] = UINT_MAX;
942 }
943
944 w_to_n_coll_.insert (std::make_pair (tab_num, tab));
945}
946
947
948void Def::gen_n_ce_tables (const std::set<std::string>ce_elms,
949 unsigned int idx, unsigned int tab_num)
950{
951 if (ce_elms.size() > 0) {
952 ce_offset_tab_t tab;
953 for (unsigned int k = 0; k <= UCHAR_MAX; ++k) {
954 tab.off[k] = UINT_MAX;
955 }
956 tab.first_offset = -1;
957 tab.last_offset = 0;
958 ce_sym_map_iter ce_sym_map_it;
959 ce_map_iter ce_map_it;
960
961 std::set<std::string>::const_iterator ce_elms_it;
962 std::set<std::string> next_elms;
963
964 for (unsigned int i = 0; i <= UCHAR_MAX; ++i) {
965 next_elms.clear();
966 for (ce_elms_it = ce_elms.begin(); ce_elms_it != ce_elms.end();
967 ce_elms_it ++) {
968
969 if ((unsigned char)i == (unsigned char)((*ce_elms_it)[idx])) {
970 if ((*ce_elms_it).size() == idx + 1) {
971 if ((ce_sym_map_it = ce_sym_map_.find (*ce_elms_it))
972 != ce_sym_map_.end()) {
973 ce_map_it = ce_map_.find(ce_sym_map_it->second);
974 tab.off[i] = ce_map_it->second.offset;
975 if (tab.first_offset == -1)
976 tab.first_offset = i;
977 if ((unsigned int)tab.last_offset < i)
978 tab.last_offset = i;
979 }
980 }
981 else {
982
983 next_elms.insert (*ce_elms_it);
984 if (tab.off[i] == UINT_MAX) {
985 ++ next_n_ce_tab_num_;
986 tab.off[i] = next_n_ce_tab_num_ | 0x80000000;
987 }
988 if (tab.first_offset == -1)
989 tab.first_offset = i;
990 if ((unsigned int)tab.last_offset < i)
991 tab.last_offset = i;
992 }
993 }
994 }
995 // now recursively call gen_n_ce_tables if any collating
996 // elements with this character were found;
997 if (next_elms.size() != 0)
998 gen_n_ce_tables (next_elms, idx + 1, next_n_ce_tab_num_);
999 }
1000 n_ce_offs_.insert(std::make_pair(tab_num, tab));
1001
1002 }
1003}
1004
1005
1006void Def::gen_w_ce_tables (const std::set<std::string>ce_elms,
1007 unsigned int idx, unsigned int tab_num)
1008{
1009 if (ce_elms.size() > 0) {
1010 ce_offset_tab_t tab;
1011 for (unsigned int k = 0; k <= UCHAR_MAX; ++k) {
1012 tab.off[k] = UINT_MAX;
1013 }
1014 tab.first_offset = -1;
1015 tab.last_offset = 0;
1016 ce_sym_map_iter ce_sym_map_it;
1017 ce_map_iter ce_map_it;
1018
1019 std::set<std::string>::const_iterator ce_elms_it;
1020 std::set<std::string> next_elms;
1021
1022 for (unsigned int i = 0; i <= UCHAR_MAX; ++i) {
1023 next_elms.clear();
1024 for (ce_elms_it = ce_elms.begin(); ce_elms_it != ce_elms.end();
1025 ce_elms_it ++) {
1026
1027 if ((unsigned char)i == (unsigned char)(*ce_elms_it)[idx]) {
1028 if ((*ce_elms_it).size() == idx + 1) {
1029 if ((ce_sym_map_it = ce_wsym_map_.find (*ce_elms_it))
1030 != ce_wsym_map_.end()) {
1031 ce_map_it = ce_map_.find(ce_sym_map_it->second);
1032 tab.off[i] = ce_map_it->second.offset;
1033 if (tab.first_offset == -1)
1034 tab.first_offset = i;
1035 if ((unsigned int)tab.last_offset < i)
1036 tab.last_offset = i;
1037 }
1038 }
1039 else {
1040 next_elms.insert (*ce_elms_it);
1041 if (tab.off[i] == UINT_MAX) {
1042 ++ next_w_ce_tab_num_;
1043 tab.off[i] = next_w_ce_tab_num_ | 0x80000000;
1044 }
1045 if (tab.first_offset == -1)
1046 tab.first_offset = i;
1047 if ((unsigned int)tab.last_offset < i)
1048 tab.last_offset = i;
1049 }
1050 }
1051 }
1052 // now recursively call gen_w_ce_tables if any collating
1053 // elements with this character were found;
1054 if (next_elms.size() != 0)
1055 gen_w_ce_tables (next_elms, idx + 1, next_w_ce_tab_num_);
1056 }
1057 w_ce_offs_.insert(std::make_pair(tab_num, tab));
1058 }
1059}
1060
1061
1063{
1064 std::cout << "LC_COLLATE\n";
1065
1066 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
1067
1068 token_list_t::iterator sl_it = sym_list_.begin ();
1069 for (; sl_it != sym_list_.end (); ++sl_it) {
1070 std::cout << sl_it->name << " % ";
1071 cs_map_iter cs_it = cs_map_.find (sl_it->name);
1072 if (cs_it != cs_map_.end ()) {
1073 std::cout << cs_it->second << '\n';
1074 continue;
1075 }
1076
1077 ce_map_iter ce_it = ce_map_.find (sl_it->name);
1078 if (ce_it != ce_map_.end ()) {
1079 std::cout << ce_it->second.coll_val << '\n';
1080 continue;
1081 }
1082
1083 std::map<std::string, wchar_t >::const_iterator cw_it =
1084 w_cmap.find (sl_it->name);
1085 if (cw_it != w_cmap.end ()) {
1086 coll_map_iter cm_it =
1087 coll_map_.find (cw_it->second);
1088 if (cm_it != coll_map_.end ()) {
1089 std::cout << cm_it->second.coll_val << '\n';
1090 continue;
1091 }
1092 }
1093 std::cout << '\n';
1094 }
1095
1096 std::cout << "\n\n";
1097
1098 std::list<collate_section_t>::iterator sect_it =
1099 section_list_.begin ();
1100 while (sect_it != section_list_.end ()) {
1101
1102 // dump the orders
1103 std::cout << "order_start " << sect_it->name;
1104 token_list_t::iterator o_it = sect_it->order.begin ();
1105 for (; o_it != sect_it->order.end (); ++o_it)
1106 std::cout << ";" << o_it->name;
1107 std::cout << '\n';
1108
1109 // for each entry in the entries list
1110 collate_entry_list_t::iterator e_it = sect_it->entries.begin ();
1111 for (; e_it != sect_it->entries.end (); ++e_it) {
1112
1113 // dump the collation definition (weights included)
1114 std::cout << e_it->first.name << " ";
1115 if (!e_it->second.empty ()) {
1116 token_list_t::iterator w_it = e_it->second.begin ();
1117 std::cout << (w_it++)->name;
1118 for (; w_it != e_it->second.end (); ++w_it)
1119 std::cout << ";" << w_it->name;
1120 }
1121
1122 // lookup the value associated with this collation symbol
1123 cs_map_iter cs_it = cs_map_.find (e_it->first.name);
1124 if (cs_it != cs_map_.end ()) {
1125 std::cout << " % " << cs_it->second << '\n';
1126 continue;
1127 }
1128
1129 ce_map_iter ce_it = ce_map_.find (e_it->first.name);
1130 if (ce_it != ce_map_.end ()) {
1131 std::cout << " % " << ce_it->second.coll_val << '\n';
1132 continue;
1133 }
1134
1135 std::map<std::string, wchar_t >::const_iterator cw_it =
1136 w_cmap.find (e_it->first.name);
1137 if (cw_it != w_cmap.end ()) {
1138 coll_map_iter cm_it =
1139 coll_map_.find (cw_it->second);
1140 if (cm_it != coll_map_.end ()) {
1141 std::cout << " % " << cm_it->second.coll_val << '\n';
1142 continue;
1143 }
1144
1145 }
1146 std::cout << '\n';
1147 }
1148
1149 std::cout << "order_end\n";
1150 ++sect_it;
1151 }
1152 std::cout << "END LC_COLLATE\n";
1153}
1154
1155
1156void Def::write_collate (std::string dir_name)
1157{
1158 assert (!dir_name.empty());
1159
1160 static const char lc_name[] = "LC_COLLATE";
1161
1162 if (collate_written_)
1163 return;
1164
1165 if (!collate_def_found_) {
1166 issue_diag (I_SKIP, false, 0,
1167 "%s section not found, skipping\n", lc_name);
1168 return;
1169 }
1170
1171 next_tab_num_ = 0;
1172 next_wchar_coll_tab_num_ = 0;
1173 std::set<std::string> ce_strs;
1174 ce_sym_map_iter it;
1175 ce_map_iter ce_mit;
1176 for (it = ce_sym_map_.begin (); it != ce_sym_map_.end (); ++it) {
1177 if ((ce_mit = ce_map_.find (it->second))->second.coll_val
1178 != UINT_MAX) {
1179 // check to see of the largest_ce needs to be changed
1180 if (ce_mit->second.ce_wstr.size() + 1
1181 > collate_out_.largest_ce)
1182 collate_out_.largest_ce =
1183 unsigned (ce_mit->second.ce_wstr.size());
1184
1185 ce_strs.insert (it->first);
1186 }
1187 }
1188 next_n_ce_tab_num_ = 0;
1189 gen_n_ce_tables(ce_strs, 0, 0);
1190 ce_strs.clear();
1191 for (it = ce_wsym_map_.begin (); it != ce_wsym_map_.end (); ++it) {
1192 if (ce_map_.find (it->second)->second.coll_val != UINT_MAX)
1193 ce_strs.insert (it->first);
1194 }
1195 next_w_ce_tab_num_ = 0;
1196 gen_w_ce_tables (ce_strs, 0, 0);
1197
1198 gen_n_to_w_coll_tables ("", next_tab_num_);
1199 gen_w_to_n_coll_tables ("", next_wchar_coll_tab_num_);
1200
1201 (dir_name += _RWSTD_PATH_SEP) += lc_name;
1202
1203 issue_diag (I_OPENWR, false, 0, "writing %s\n", dir_name.c_str ());
1204
1205 std::ofstream out (dir_name.c_str(), std::ios::binary);
1206 out.exceptions (std::ios::failbit | std::ios::badbit);
1207
1208 // calculate the size of an individual weight element
1209 collate_out_.elm_size = collate_out_.num_weights
1210 * collate_out_.longest_weight * unsigned (sizeof (unsigned int)) +
1211 unsigned (sizeof (unsigned int));
1212
1213 // the first section of the collate database is the collating
1214 // element information
1215 collate_out_.n_ce_tab_off = 0;
1216 collate_out_.w_ce_tab_off = collate_out_.n_ce_tab_off;
1217 n_ce_offs_iter n_ce_offs_it;
1218 for (n_ce_offs_it = n_ce_offs_.begin();
1219 n_ce_offs_it != n_ce_offs_.end (); ++n_ce_offs_it) {
1220 collate_out_.w_ce_tab_off += (n_ce_offs_it->second.last_offset
1221 - n_ce_offs_it->second.first_offset + 1)
1222 * unsigned (sizeof (int));
1223 }
1224
1225 // next comes the weight information
1226 collate_out_.weight_tab_off = collate_out_.w_ce_tab_off;
1227 w_ce_offs_iter w_ce_offs_it;
1228 for (w_ce_offs_it = w_ce_offs_.begin();
1229 w_ce_offs_it != w_ce_offs_.end(); ++w_ce_offs_it) {
1230 collate_out_.weight_tab_off += (w_ce_offs_it->second.last_offset
1231 - w_ce_offs_it->second.first_offset + 1)
1232 * unsigned (sizeof (int));
1233 }
1234
1235 coll_map_iter coll_map_pos;
1236
1237 collate_out_.num_elms = unsigned (off_mapr_.size());
1238 if (collate_out_.undefined_optimization)
1239 ++collate_out_.num_elms;
1240
1241 // now calculate the offset for the first narrow character table
1242 collate_out_.n_char_tab_off = collate_out_.weight_tab_off
1243 + collate_out_.num_elms * collate_out_.elm_size;
1244
1245 // now calculate the offset fo the fist wide character table
1246 // but first we need the size of the narrow tables
1247 char_offs_iter char_offs_it;
1248 unsigned int char_offs_size = 0;
1249 for (char_offs_it = char_offs_.begin();
1250 char_offs_it != char_offs_.end(); ++char_offs_it) {
1251 char_offs_size += (UCHAR_MAX + 1
1252 - char_offs_it->second.first_offset)
1253 * unsigned (sizeof (unsigned int));
1254 }
1255
1256 collate_out_.w_char_tab_off = collate_out_.n_char_tab_off
1257 + char_offs_size;
1258
1259 // now calculate the offset for the narrow character offset table
1260 // but first we need the size of the wide tables
1261 w_to_n_coll_iter w_to_n_coll_it;
1262 unsigned int w_to_n_size = 0;
1263 for (w_to_n_coll_it = w_to_n_coll_.begin();
1264 w_to_n_coll_it != w_to_n_coll_.end(); ++w_to_n_coll_it) {
1265 w_to_n_size += (UCHAR_MAX + 1
1266 - w_to_n_coll_it->second.first_offset)
1267 * unsigned (sizeof (unsigned int));
1268 }
1269
1270 collate_out_.n_char_off_tab_off = collate_out_.w_char_tab_off
1271 + w_to_n_size;
1272
1273 // now calculate the offset for the wide character offset table
1274 collate_out_.w_char_off_tab_off = collate_out_.n_char_off_tab_off
1275 + unsigned (char_offs_.size() * sizeof (unsigned int));
1276
1277 // calculate the offset for the narrow collating element offset table
1278 collate_out_.n_ce_off_tab_off = collate_out_.w_char_off_tab_off
1279 + unsigned (w_to_n_coll_.size() * sizeof (unsigned int));
1280
1281 // calculate the offset for the wide collating element offset table
1282 collate_out_.w_ce_off_tab_off = collate_out_.n_ce_off_tab_off
1283 + unsigned (n_ce_offs_.size() * sizeof (unsigned int));
1284
1285 // now calculate the offset of the first character information
1286 collate_out_.n_char_first_char_off = collate_out_.w_ce_off_tab_off
1287 + unsigned (w_ce_offs_.size() * sizeof (unsigned int));
1288
1289 // now calculate the offset of the wide table first char info
1290 collate_out_.w_char_first_char_off = collate_out_.n_char_first_char_off
1291 + unsigned (char_offs_.size() * sizeof (unsigned char));
1292
1293 // now calculate the offset of the narrow ce first character info
1294 collate_out_.n_ce_first_char_off = collate_out_.w_char_first_char_off
1295 + unsigned (w_to_n_coll_.size() * sizeof (unsigned char));
1296
1297 // now calculate the offset of the wide ce first character info
1298 collate_out_.w_ce_first_char_off = collate_out_.n_ce_first_char_off
1299 + unsigned (n_ce_offs_.size() * sizeof (unsigned char));
1300
1301 // now calculate the offset of the narrow ce last character info
1302 collate_out_.n_ce_last_char_off = collate_out_.w_ce_first_char_off
1303 + unsigned (w_ce_offs_.size() * sizeof (unsigned char));
1304
1305 // now calculate the offset of the wide ce last character info
1306 collate_out_.w_ce_last_char_off = collate_out_.n_ce_last_char_off
1307 + unsigned (n_ce_offs_.size() * sizeof (unsigned char));
1308
1309 // now calculate the offset of the codeset name
1310 collate_out_.codeset_off = collate_out_.w_ce_last_char_off
1311 + unsigned (w_ce_offs_.size() * sizeof (unsigned char));
1312
1313 // finally calculate the offset of the charmap name
1314 collate_out_.charmap_off = collate_out_.codeset_off
1315 + unsigned (charmap_.get_code_set_name().size()) + 1;
1316
1317
1318
1319 // print out the collate struct
1320 out.write ((char*)&collate_out_, sizeof(collate_out_));
1321
1322 unsigned int i;
1323 for (n_ce_offs_it = n_ce_offs_.begin();
1324 n_ce_offs_it != n_ce_offs_.end(); ++n_ce_offs_it) {
1325 for (i = (unsigned int)n_ce_offs_it->second.first_offset;
1326 i <= (unsigned int)n_ce_offs_it->second.last_offset; ++i)
1327 out.write ((char*)&n_ce_offs_it->second.off[i],
1328 sizeof (n_ce_offs_it->second.off[i]));
1329 }
1330
1331 for (w_ce_offs_it = w_ce_offs_.begin();
1332 w_ce_offs_it != w_ce_offs_.end(); ++w_ce_offs_it) {
1333 for (i = (unsigned int)w_ce_offs_it->second.first_offset;
1334 i <= (unsigned int)w_ce_offs_it->second.last_offset; ++i)
1335 out.write ((char*)&w_ce_offs_it->second.off[i],
1336 sizeof (w_ce_offs_it->second.off[i]));
1337 }
1338
1339
1340 // now print out the weight array
1341 unsigned int maxw = UINT_MAX;
1342 Weights_t* weights;
1343 bool undefined_written = false;
1344
1345 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
1346
1347 std::size_t off_idx = 0;
1348 off_mapr_iter current_off = off_mapr_.begin();
1349 for (; current_off != off_mapr_.end(); ++off_idx) {
1350
1351 // check the current offset
1352 if (current_off->first != off_idx
1353 && off_idx != undef_char_info_.offset)
1354 issue_diag (E_RANGE, true, 0,
1355 "current_off : %d, index : %d, giving up\n",
1356 current_off->first, off_idx);
1357
1358 if (collate_out_.undefined_optimization
1359 && off_idx == undef_char_info_.offset) {
1360 undefined_written = true;
1361 weights = undef_char_info_.weights;
1362 out.write ((char*)&undef_char_info_.order,
1363 sizeof (undef_char_info_.order));
1364 for (int j = 0; j < collate_out_.num_weights; ++j) {
1365 for (int k = 0; k < weights[j].size; ++k) {
1366 out.write ((char*)&weights[j].weight[k],
1367 sizeof (weights[j].weight[k]));
1368 }
1369 for (int c = weights[j].size;
1370 c < collate_out_.longest_weight; ++c)
1371 out.write ((char*)&maxw, sizeof (maxw));
1372 }
1373 continue;
1374 }
1375
1376 w_cmap_iter w_cmap_pos = w_cmap.find
1377 (current_off->second);
1378 if (w_cmap_pos != w_cmap.end()) {
1379 coll_map_pos = coll_map_.find (w_cmap_pos->second);
1380 out.write ((char*)&coll_map_pos->second.order,
1381 sizeof (coll_map_pos->second.order));
1382 weights = coll_map_pos->second.weights;
1383 for (int j = 0; j < collate_out_.num_weights; ++j) {
1384 for (int k = 0; k < weights[j].size; ++k) {
1385 out.write ((char*)&weights[j].weight[k],
1386 sizeof (weights[j].weight[k]));
1387 }
1388 for (int c = weights[j].size;
1389 c < collate_out_.longest_weight; ++c)
1390 out.write ((char*)&maxw, sizeof (maxw));
1391 }
1392 ++current_off;
1393 }
1394
1395 else {
1396 ce_map_iter ce_map_it = ce_map_.find (current_off->second);
1397 if (ce_map_it != ce_map_.end()
1398 && ce_map_it->second.coll_val != UINT_MAX) {
1399 out.write ((char*)&ce_map_it->second.order,
1400 sizeof (ce_map_it->second.order));
1401 weights = ce_map_it->second.weights;
1402 for (int j = 0; j < collate_out_.num_weights; ++j) {
1403 for (int k = 0; k < weights[j].size; ++k) {
1404 out.write ((char*)&weights[j].weight[k],
1405 sizeof (weights[j].weight[k]));
1406 }
1407 for (int c = weights[j].size;
1408 c < collate_out_.longest_weight; ++c)
1409 out.write ((char*)&maxw, sizeof (maxw));
1410 }
1411
1412 }
1413 ++current_off;
1414 }
1415 }
1416
1417 // maske sure that we got to the undefined value
1418 if (!undefined_written && collate_out_.undefined_optimization) {
1419 if (off_idx != undef_char_info_.offset)
1420 issue_diag (E_RANGE, true, 0,
1421 "current_off : %d, index : %d, giving up\n",
1422 undef_char_info_.offset, off_idx);
1423
1424 weights = undef_char_info_.weights;
1425 out.write ((char*)&undef_char_info_.order,
1426 sizeof (undef_char_info_.order));
1427 for (int j = 0; j < collate_out_.num_weights; ++j) {
1428 for (int k = 0; k < weights[j].size; ++k) {
1429 out.write ((char*)&weights[j].weight[k],
1430 sizeof (weights[j].weight[k]));
1431 }
1432 for (int c = weights[j].size;
1433 c < collate_out_.longest_weight; ++c)
1434 out.write ((char*)&maxw, sizeof (maxw));
1435 }
1436 }
1437
1438 // now print out the narrow character tables
1439 for (char_offs_it = char_offs_.begin();
1440 char_offs_it != char_offs_.end(); ++char_offs_it) {
1441 for (unsigned int c = char_offs_it->second.first_offset;
1442 c <= UCHAR_MAX; ++c) {
1443 out.write ((const char*)&char_offs_it->second.off[c],
1444 sizeof (char_offs_it->second.off[c]));
1445 }
1446 }
1447
1448 // now print out the wide character tables
1449 for (w_to_n_coll_it = w_to_n_coll_.begin();
1450 w_to_n_coll_it != w_to_n_coll_.end(); ++w_to_n_coll_it) {
1451 for (unsigned int c = w_to_n_coll_it->second.first_offset;
1452 c <= UCHAR_MAX; ++c) {
1453 out.write ((const char*)&w_to_n_coll_it->second.off[c],
1454 sizeof (w_to_n_coll_it->second.off[c]));
1455 }
1456 }
1457
1458 // now print the narrow character table offsets
1459 unsigned int current_offset = 0;
1460 for (char_offs_it = char_offs_.begin();
1461 char_offs_it != char_offs_.end(); ++char_offs_it) {
1462 out.write ((const char*)&current_offset, sizeof (current_offset));
1463 current_offset += (UCHAR_MAX + 1
1464 - char_offs_it->second.first_offset);
1465 }
1466
1467 // now print the wide character table offsets
1468 current_offset = 0;
1469 for (w_to_n_coll_it = w_to_n_coll_.begin();
1470 w_to_n_coll_it != w_to_n_coll_.end(); ++w_to_n_coll_it) {
1471 out.write ((const char*)&current_offset, sizeof (current_offset));
1472 current_offset += (UCHAR_MAX + 1
1473 - w_to_n_coll_it->second.first_offset);
1474 }
1475
1476 // now print the narrow ce table offsets
1477 current_offset = 0;
1478 for (n_ce_offs_it = n_ce_offs_.begin();
1479 n_ce_offs_it != n_ce_offs_.end(); ++n_ce_offs_it) {
1480 out.write ((const char*)&current_offset, sizeof (current_offset));
1481 current_offset += (n_ce_offs_it->second.last_offset
1482 - n_ce_offs_it->second.first_offset + 1);
1483 }
1484
1485 // now print the wide ce table offsets
1486 current_offset = 0;
1487 for (w_ce_offs_it = w_ce_offs_.begin();
1488 w_ce_offs_it != w_ce_offs_.end(); ++w_ce_offs_it) {
1489 out.write ((const char*)&current_offset, sizeof (current_offset));
1490 current_offset += (w_ce_offs_it->second.last_offset
1491 - w_ce_offs_it->second.first_offset + 1);
1492 }
1493
1494
1495 // now print out the narrow character tables starting character
1496 for (char_offs_it = char_offs_.begin();
1497 char_offs_it != char_offs_.end(); ++char_offs_it) {
1498 const char off = char ((char_offs_it->second).first_offset);
1499 out << off;
1500 }
1501
1502 // now print out the wide character tables starting character
1503 for (w_to_n_coll_it = w_to_n_coll_.begin();
1504 w_to_n_coll_it != w_to_n_coll_.end(); ++w_to_n_coll_it) {
1505 const char off = char ((w_to_n_coll_it->second).first_offset);
1506 out << off;
1507 }
1508
1509 // now print out the narrow ce tables starting character
1510 for (n_ce_offs_it = n_ce_offs_.begin();
1511 n_ce_offs_it != n_ce_offs_.end(); ++n_ce_offs_it) {
1512 const char off = char ((n_ce_offs_it->second).first_offset);
1513 out << off;
1514 }
1515
1516 // now print out the wide ce tables starting character
1517 for (w_ce_offs_it = w_ce_offs_.begin();
1518 w_ce_offs_it != w_ce_offs_.end(); ++w_ce_offs_it) {
1519 const char off = char ((w_ce_offs_it->second).first_offset);
1520 out << off;
1521 }
1522
1523 // now print out the narrow ce tables ending character
1524 for (n_ce_offs_it = n_ce_offs_.begin();
1525 n_ce_offs_it != n_ce_offs_.end(); ++n_ce_offs_it) {
1526 const char off = char ((n_ce_offs_it->second).last_offset);
1527 out << off;
1528 }
1529
1530 // now print out the wide ce tables ending character
1531 for (w_ce_offs_it = w_ce_offs_.begin();
1532 w_ce_offs_it != w_ce_offs_.end(); ++w_ce_offs_it) {
1533 const char off = char ((w_ce_offs_it->second).last_offset);
1534 out << off;
1535 }
1536
1537 // finally write the codeset and charmap names
1538 out << charmap_.get_code_set_name() << std::ends
1539 << charmap_.get_charmap_name() << std::ends;
1540}
1541
1542
1543void Def::init_coll_map() {
1544
1545 rw_cmap_iter rw_cmap_pos;
1546 collate_info_t tmp = {UINT_MAX, UINT_MAX, 0, 0};
1547
1548 for (rw_cmap_pos = charmap_.get_rw_cmap().begin();
1549 rw_cmap_pos != charmap_.get_rw_cmap().end();
1550 ++rw_cmap_pos) {
1551 coll_map_.insert (std::make_pair (rw_cmap_pos->first, tmp));
1552 }
1553}
1554
1555
1556// In the preprocess_collate member function the collate section is
1557// preprocessed and the result of the preprocessing is stored in-memory
1558// as a number of lists; the content of these lists is then preprocessed
1559// acoording to the reorder statements; the result is then passed
1560// on to process_collate.
1561void Def::preprocess_collate ()
1562{
1563 int nesting_level = 0;
1564
1565 do {
1566 // fetch next token
1567 next = scanner_.next_token();
1568
1569 switch (next.token) {
1570 case Scanner::tok_end:
1571 next = scanner_.next_token();
1572 if (next.token == Scanner::tok_collate) {
1573 // end of collation block
1574 if (nesting_level == 0)
1575 return;
1576
1577 nesting_level--;
1578 scanner_.close ();
1579 } else
1580 issue_diag (E_SYNTAX, true, &next,
1581 "wrong section name in END directive\n");
1582
1583 break;
1584 case Scanner::tok_copy: {
1585 next = scanner_.next_token();
1586 if (next.token != Scanner::tok_string)
1587 issue_diag (E_SYNTAX, true, &next,
1588 "expected string following \"copy\" directive\n");
1589
1590 // bump up the nesting level
1591 ++nesting_level;
1592
1593 issue_diag (I_STAGE, false, 0, "processing copy directive\n");
1594
1595 // open the file
1596 scanner_.open (get_pathname (strip_quotes (next.name), next.file));
1597
1598 // get comment char and escape char;
1599 // these informations are stored by the scanner
1600 while ((next = scanner_.next_token ()).token
1602 // the LC_IDENTIFICATION section may also have a
1603 // LC_COLLATE token that will mess up the parsing
1604 if (next.token == Scanner::tok_ident) {
1605 while ((next = scanner_.next_token()).token
1606 != Scanner::tok_end );
1607 next = scanner_.next_token();
1608 }
1609 }
1610
1611 break;
1612 }
1613
1614 // a collating element definition defines a symbolic name that
1615 // represents symbolically the congregation of two other symbolic
1616 // names which have to be present in the character map;
1617 // the form of the phrase is:
1618 // collating-element sym from ("string" | (sym sym+))
1620 next = scanner_.next_token();
1621 // we expect a symbolic name
1622 if (next.token != Scanner::tok_sym_name)
1623 issue_diag (E_SYNTAX, true, &next,
1624 "symbolic name expected following "
1625 "collating-element\n");
1626 // symbolic name
1627 token_t sym (next);
1628
1629 next = scanner_.next_token ();
1630 if (next.token != Scanner::tok_from)
1631 issue_diag (E_SYNTAX, true, &next,
1632 "illegal collating-element expression\n");
1633
1634 token_list_t ce_def_list;
1635 next = scanner_.next_token ();
1636 if (next.token == Scanner::tok_string) {
1637 ce_def_list.push_back (next);
1638 ce_list_.push_back (std::make_pair(sym,ce_def_list));
1639 } else if (next.token == Scanner::tok_sym_name) {
1640 do {
1641 ce_def_list.push_back (next);
1642 next = scanner_.next_token();
1643 } while (next.token != Scanner::tok_nl);
1644 ce_list_.push_back (std::make_pair(sym,ce_def_list));
1645 } else
1646 issue_diag (E_SYNTAX, true, &next,
1647 "illegal collating-element expression\n");
1648 break;
1649 }
1651 next = scanner_.next_token();
1652 if (next.token != Scanner::tok_sym_name)
1653 issue_diag (E_SYNTAX, true, &next,
1654 "symbolic name expected following "
1655 "collating-symbol\n");
1656 cs_list_.push_back (next);
1657 break;
1659 next = scanner_.next_token ();
1660 if (next.token != Scanner::tok_sym_name)
1661 issue_diag (W_SYNTAX, false, &next,
1662 "expecting script name, got %s\n",
1663 next.name.c_str ());
1664 script_list_.push_back(next);
1665 break;
1667 sym_list_.push_back (next);
1668 break;
1670 preprocess_order();
1671 break;
1672
1674 preprocess_reorder ();
1675 break;
1676
1678 preprocess_reorder_section ();
1679 break;
1680
1681 default:
1682 break;
1683 }
1684 }
1685 while (Scanner::tok_end_tokens != next.token);
1686}
1687
1688
1689// The task of preprocess_order is to parse and model the content of the
1690// order sections in the input files
1691void Def::preprocess_order ()
1692{
1693 // one order-start keyword has been encountered;
1694 // push a collate_section down the list and use it
1695 while (next.token != Scanner::tok_order_end) {
1696 section_list_.push_back (collate_section_t());
1697 collate_section_t& section = section_list_.back ();
1698
1699 next = scanner_.next_token ();
1700
1701 // store the orders
1702 while (next.token != Scanner::tok_nl) {
1703 if (next.token == Scanner::tok_sym_name) {
1704 // symbolic name, has to be a section name
1705 section.name = next.name;
1706 } else {
1707 // might be a combination of order and position
1708 // do the same until a better way is found
1709 section.order.push_back (next);
1710 }
1711
1712 // fetch next token
1713 next = scanner_.next_token ();
1714 }
1715
1716 // unnamed sections
1717 if (section.name == "")
1718 section.name = "unnamed";
1719
1720 issue_diag (I_STAGE, false, 0,
1721 "processing %s order\n", section.name.c_str ());
1722
1723 // store the collation statements
1724 while (!(next.token == Scanner::tok_order_end ||
1725 next.token == Scanner::tok_order_start )) {
1726
1727 next = scanner_.next_token ();
1728 switch (next.token) {
1729 case Scanner::tok_end:
1730 issue_diag (E_SYNTAX, true, &next,
1731 "unexpected END directive while "
1732 "parsing collate section\n");
1733 case Scanner::tok_nl:
1734 continue;
1736 scanner_.ignore_line ();
1737 break;
1740 {
1741 token_t sym (next);
1742 section.entries.push_back (
1743 std::make_pair(sym,token_list_t()));
1744 collate_entry_t& entry = section.entries.back ();
1745
1746 next = scanner_.next_token ();
1747 while (next.token != Scanner::tok_nl) {
1748 entry.second.push_back (next);
1749 next = scanner_.next_token ();
1750 }
1751 break;
1752 }
1753 default:
1754 break;
1755 }
1756 }
1757 }
1758}
1759
1760
1761// Handles the reorder statements in the form:
1762// reorder-after <sym>
1763// <sym> <sym><sym>...
1764// OR
1765// reorder-after <sym>
1766// .. <sym><sym>.....
1767// followed by reorder-end statement or another reorder-after
1768void Def::preprocess_reorder ()
1769{
1770 while (true) {
1771 // process one or more statements grouped
1772 // under a reorder section
1773
1774 // retrieve the symbol
1775 next = scanner_.next_token ();
1776 if (next.token != Scanner::tok_sym_name)
1777 issue_diag (E_SYNTAX, true, &next,
1778 "expecting symbolic name, got %s\n",
1779 next.name.c_str ());
1780
1781 // store the symbolic name
1782 token_t sym (next);
1783 collate_entry_list_t entries_list;
1784 while (true) {
1785
1786 // process the statements
1787 next = scanner_.next_token ();
1788
1789 if (next.token == Scanner::tok_nl )
1790 continue;
1791 else if ( next.token == Scanner::tok_sym_name
1792 || next.token == Scanner::tok_hex_ellipsis) {
1793 // the line will contain one single symbolic name
1794 // or a complete collation statement
1795 collate_entry_t entry;
1796 entry.first = next;
1797
1798 next = scanner_.next_token ();
1799 while (next.token != Scanner::tok_nl) {
1800 entry.second.push_back (next);
1801 next = scanner_.next_token ();
1802 }
1803
1804 // add the entry to the list
1805 entries_list.push_back (entry);
1806 } else if (next.token == Scanner::tok_reorder) {
1807 // call insert_entry
1808 if (!entries_list.empty ())
1809 insert_entries (sym, entries_list);
1810 entries_list.clear ();
1811 break;
1812 } else if (next.token == Scanner::tok_reorder_end ) {
1813 // call insert_entry
1814 // call insert_entry
1815 if (!entries_list.empty ())
1816 insert_entries (sym, entries_list);
1817 return;
1818 } else {
1819 issue_diag (E_SYNTAX, true, &next,
1820 "unexpected token : %s in a reorder block\n",
1821 next.name.c_str ());
1822 }
1823 }
1824 }
1825}
1826
1827
1828void Def::preprocess_reorder_section ()
1829{
1830 while (next.token != Scanner::tok_reorder_section_end) {
1831 // process one or more statements grouped
1832 // under a reorder section
1833
1834 // retrieve the symbol
1835 next = scanner_.next_token ();
1836 token_t sym (next);
1837
1838 // process the statements
1839 while (!(next.token == Scanner::tok_reorder_section ||
1841
1842 next = scanner_.next_token ();
1843 switch (next.token) {
1844 case Scanner::tok_nl:
1845 continue;
1846 case Scanner::tok_sym_name: {
1847 // the line will contain one single symbolic name
1848 // which is the name of a section
1849 next = scanner_.next_token ();
1850 if (next.token != Scanner::tok_sym_name) {
1851 issue_diag (E_SYNTAX, true, &next,
1852 "expecting section name, got %s\n",
1853 next.name.c_str ());
1854 }
1855
1856 std::list<collate_section_t>::iterator beg =
1857 section_list_.begin ();
1858 std::list<collate_section_t>::iterator end =
1859 section_list_.end ();
1860 std::list<collate_section_t>::iterator ref_it, mov_it;
1861 for (ref_it = beg;
1862 ref_it->name != sym.name && ref_it != end;
1863 ++ref_it);
1864 for (mov_it = beg;
1865 mov_it->name != next.name && mov_it != end;
1866 ++mov_it);
1867
1868 if (ref_it == end || mov_it == end)
1869 issue_diag (E_SYNTAX, true, &next,
1870 "missing sections %s %s requested\n",
1871 sym.name.c_str (), next.name.c_str ());
1872
1873 // replace it
1874 section_list_.splice (++ref_it, section_list_,
1875 mov_it, mov_it);
1876
1877 // replace the insertion point
1878 sym = next;
1879 break;
1880 }
1881 default:
1882 issue_diag (E_SYNTAX, true, &next,
1883 "unexpected token : %s in a "
1884 "reorder section block\n",
1885 next.name.c_str ());
1886 break;
1887 }
1888
1889 }
1890 }
1891}
1892
1893
1894void Def::list_collate ()
1895{
1896 // print the script list
1897 token_list_t::iterator script_it = script_list_.begin ();
1898 while (script_it != script_list_.end ()) {
1899 std::cout << "script " << (script_it++)->name << '\n';
1900 }
1901 std::cout << '\n';
1902
1903 // print the collating symbols' list
1904 token_list_t::iterator cs_it = cs_list_.begin ();
1905 while (cs_it != cs_list_.end ()) {
1906 std::cout << "collating-symbol " << (cs_it++)->name << '\n';
1907 }
1908 std::cout << '\n';
1909
1910 // print the collating elements list
1911 std::list<collate_elem_t>::iterator ce_it = ce_list_.begin ();
1912 while (ce_it != ce_list_.end ()) {
1913 std::cout << "collating-element " << ce_it->first.name
1914 << " from ";
1915 token_list_t::iterator ce_def_it = ce_it->second.begin ();
1916 for (;ce_def_it != ce_it->second.end (); ce_def_it++) {
1917 std::cout << ce_def_it->name << ";";
1918 }
1919 std::cout << '\n';
1920 }
1921 std::cout << '\n';
1922
1923 // print out general/global symbols' list
1924 token_list_t::iterator sym_it = sym_list_.begin ();
1925 while (sym_it != sym_list_.end ()) {
1926 std::cout << (sym_it++)->name << '\n';
1927 }
1928 std::cout << '\n';
1929
1930 // print out sections
1931 std::list<collate_section_t>::iterator sc_it =
1932 section_list_.begin ();
1933 while (sc_it != section_list_.end ()) {
1934 // print prolog
1935 std::cout << "order_start ";
1936 if (sc_it->name != "unnamed")
1937 std::cout << sc_it->name << ";";
1938
1939 token_list_t::iterator it = sc_it->order.begin ();
1940 while (it != sc_it->order.end ())
1941 std::cout << (it++)->name << ";";
1942 std::cout << '\n';
1943
1944 std::list<collate_entry_t>::iterator e_it =
1945 sc_it->entries.begin ();
1946 while (e_it != sc_it->entries.end ()) {
1947 std::cout << e_it->first.name << " ";
1948 token_list_t::iterator w_it = e_it->second.begin ();
1949 while (w_it != e_it->second.end ())
1950 std::cout << (w_it++)->name << ";";
1951 std::cout << '\n';
1952 ++e_it;
1953 }
1954
1955 ++sc_it;
1956 }
1957 std::cout << '\n' << "order_end\n";
1958}
1959
1960
1961// FIXME - modify the algorithm to get log(N) complexity
1962// Inserts an entry inside the section information;
1963// searching for the appropriate entry in the list is
1964// done in linear time
1965bool Def::insert_entries (token_t& s, collate_entry_list_t& e)
1966{
1967 // first remove these entries if found
1968 collate_entry_list_t::iterator r_it = e.begin ();
1969 for (; r_it != e.end (); ++r_it)
1970 remove_entry (*r_it);
1971
1972 // first search through the symbols list; if found check
1973 // the collate_entry object; it should not have weights
1974 token_list_t::iterator it = sym_list_.begin ();
1975 for (; it != sym_list_.end (); ++it) {
1976 if (it->name != s.name)
1977 continue;
1978
1979 // FIXME - all statements have to have no weights if they are
1980 // to be inserted after collation symbols outside section boundaries;
1981 // found it; check one collate_entry_t object
1982 if (!e.begin ()->second.empty ()) {
1983 issue_diag (E_REORD, true, &s,
1984 "requested reorder-after: reference "
1985 "symbol %s was found outside section boundaries "
1986 "and the objects to be reordered are collation "
1987 "definitions\n", s.name.c_str ());
1988 }
1989
1990 // insert the symbolic name there
1991 collate_entry_list_t::iterator e_it = e.begin ();
1992 for (; e_it != e.end (); ++e_it)
1993 it = sym_list_.insert (++it, e_it->first);
1994
1995 return true;
1996 }
1997
1998 // if not successful then search in each section
1999 std::list<collate_section_t>::iterator sect_it = section_list_.begin ();
2000 while (sect_it != section_list_.end ()) {
2001 collate_entry_list_t::iterator e_it = sect_it->entries.begin ();
2002 for (; e_it != sect_it->entries.end (); ++e_it) {
2003 if (e_it->first.name != s.name)
2004 continue;
2005
2006 // found it; insert entry
2007 sect_it->entries.insert (++e_it, e.begin (), e.end ());
2008 return true;
2009 }
2010 ++sect_it;
2011 }
2012
2013 issue_diag (W_REORD, false, &s,
2014 "requested reorder-after: reference "
2015 "symbol %s was not found \n", s.name.c_str ());
2016
2017 return false;
2018}
2019
2020
2021// FIXME - modify the algorithm to get log(N) complexity
2022void Def::remove_entry (collate_entry_t& e)
2023{
2024 // search in the sym_list_ and in the sections
2025 if (e.second.empty ()) {
2026 token_list_t::iterator it = sym_list_.begin ();
2027 for (; it != sym_list_.end (); ++it) {
2028 if (it->name != e.first.name)
2029 continue;
2030
2031 sym_list_.erase (it);
2032 return;
2033 }
2034 }
2035
2036 // search in the sections
2037 std::list<collate_section_t>::iterator sect_it = section_list_.begin ();
2038 while (sect_it != section_list_.end ()) {
2039 std::list<collate_entry_t>::iterator e_it = sect_it->entries.begin ();
2040 for (; e_it != sect_it->entries.end (); ++e_it) {
2041 if (e_it->first.name != e.first.name)
2042 continue;
2043
2044 sect_it->entries.erase (e_it);
2045 return;
2046 }
2047 ++sect_it;
2048 }
2049 return ;
2050}
2051
2052
2053
2054bool Def::get_weight ( token_t& w,
2055 Weights_t* weights,
2056 int weight_num)
2057{
2058 const std::map<std::string, wchar_t>& w_cmap = charmap_.get_w_cmap ();
2059
2060 bool ret = false;
2061 weights[weight_num].size = 1;
2062 ce_map_iter ce_map_it;
2063 if(w.token == Scanner::tok_sym_name) {
2064 w_cmap_iter w_cmap_pos = w_cmap.find (w.name);
2065 if (w_cmap_pos != w_cmap.end()){
2066 coll_map_iter coll_map_pos = coll_map_.find(w_cmap_pos->second);
2067
2068 if (coll_map_pos->second.coll_val == UINT_MAX)
2069 issue_diag (E_SYMUSED, true,
2070 &w, "symbolic name %s "
2071 "used as weight before being assigned a "
2072 "collation value\n", w.name.c_str());
2073
2074 // store weight
2075 weights[weight_num].weight[0] = coll_map_pos->second.coll_val;
2076 }
2077 else if ((ce_map_it = ce_map_.find (w.name))
2078 != ce_map_.end())
2079 weights[weight_num].weight[0] = ce_map_it->second.coll_val;
2080 else {
2081 cs_map_iter cs_it = cs_map_.find (w.name);
2082 if (cs_it == cs_map_.end ())
2083 issue_diag (E_SYNTAX, true,
2084 &w, "symbolic name %s not found\n",
2085 w.name.c_str());
2086
2087 weights[weight_num].weight[0] = cs_it->second;
2088 }
2089 }
2090 else if (w.token == Scanner::tok_char_value) {
2091 // the weight is given in numerical form
2092 const char* next_val =
2093 std::strchr (w.name.c_str (), scanner_.escape_char ());
2094
2095 assert (0 != next_val);
2096
2097 const char* next_wt = std::strchr (w.name.c_str (), ';');
2098
2099 while (weight_num < collate_out_.num_weights) {
2100
2101 unsigned c;
2102
2103 for (c = 0; *next_val && (!next_wt || next_val < next_wt); ++c) {
2104
2105 const char* end = 0;
2106
2107 weights [weight_num].weight [c] =
2108 unsigned (scanner_.convert_escape (next_val, &end, true));
2109
2110 assert (0 != end);
2111
2112 next_val = end;
2113 }
2114
2115 weights [weight_num++].size = c;
2116
2117 if (next_wt)
2118 next_wt = std::strchr (next_val, ';');
2119
2120 }
2121
2122 }
2123 else if(w.token == Scanner::tok_ignore) {
2124 // use the special weight 0 for IGNORE weights
2125 weights[weight_num].size = 1;
2126 weights[weight_num].weight[0] = 0;
2127 }
2128 else if (w.token == Scanner::tok_string) {
2129 // the weights are given either in symbolic name form (e.g.,
2130 // "<symbolic-name>" or in the form of a quoted multibyte
2131 // character string (e.g., "\001\d010\x16\")
2132 const std::string tmp (w.name.substr (1, w.name.size() - 2));
2133
2134 // keeps track of the length of the weight
2135 unsigned char k = 0;
2136
2137 // iterate thru the string content and retrieve the symbols
2138 std::string::const_iterator it = tmp.begin ();
2139
2140 const char escape = scanner_.escape_char ();
2141
2142 while (it != tmp.end ()) {
2143 // weight in string form
2144 std::string wsym;
2145
2146 // next comes a symbolic name
2147 if (*it == '<') {
2148 while (*it != '>') {
2149 if (*it == escape)
2150 ++it;
2151
2152 wsym += *it++;
2153 }
2154 wsym += *it++;
2155
2156 // wsym has the symbolic name, lookup for it in
2157 // the character map, collating-symbol map,
2158 // and collating-element map
2159 w_cmap_iter w_cm_pos = w_cmap.find(wsym);
2160 cs_map_iter cs_it = cs_map_.find (wsym);
2161 ce_map_iter ce_it = ce_map_.find (wsym);
2162
2163 if (w_cm_pos != w_cmap.end()) {
2164 // is in the character map, check its associated
2165 // collation value
2166 coll_map_iter coll_it = coll_map_.find(w_cm_pos->second);
2167 if (coll_it == coll_map_.end())
2168 issue_diag (E_SYMUSED, true, &w,
2169 "weight %s not defined\n",
2170 wsym.c_str());
2171 if (coll_it->second.coll_val == UINT_MAX)
2172 issue_diag (E_SYMUSED, true,
2173 &w, "symbolic name %s "
2174 "used as weight before being assigned a "
2175 "collation value\n", wsym.c_str());
2176
2177 weights[weight_num].weight[k++] = coll_it->second.coll_val;
2178 }
2179 else if (ce_it != ce_map_.end()) {
2180 // it is in the collating-element map
2181 weights[weight_num].weight[k++] = ce_it->second.coll_val;
2182 }
2183 else if (cs_it != cs_map_.end()) {
2184 // it is in the collating-symbol map
2185 weights[weight_num].weight[k++] = cs_it->second;
2186 }
2187 else {
2188 // it is not in any of the maps, that's an error
2189 issue_diag (E_SYNTAX, true, &w,
2190 "symbolic name %s not found\n",
2191 wsym.c_str());
2192 }
2193 }
2194 else if (*it == escape) {
2195
2196 // weight is given in a quoted escape form
2197 const char* const beg = tmp.c_str () + (it - tmp.begin ());
2198 const char* end = 0;
2199
2200 weights [weight_num].weight [k++] =
2201 unsigned (scanner_.convert_escape (beg, &end, true));
2202
2203 assert (0 != end);
2204
2205 it += end - beg;
2206
2207 break;
2208 }
2209 else
2210 issue_diag (E_SYNTAX, true, &w,
2211 "illegal string content as a weight");
2212 }
2213
2214 weights[weight_num].size = k;
2215 if (k > collate_out_.longest_weight)
2216 collate_out_.longest_weight = k;
2217
2218 }
2219 else if (w.token == Scanner::tok_abs_ellipsis)
2220 // return true if ellipsis are embedded in the weight
2221 ret = true;
2222 else
2224 issue_diag (W_SYNTAX, false, &w,
2225 "illegal token %s found in collation definition\n",
2226 w.name.c_str()) || warnings_occurred_;
2227
2228 return ret;
2229}
2230
2231
2232// if undefined optimization is on then only those characters that have
2233// been defined should go into the valid set, otherwise all characters go
2234// into the set.
2235void Def::gen_valid_coll_wchar_set () {
2236
2237 if (!valid_coll_wchar_set_.empty())
2238 return;
2239
2240 create_wchar_utf8_table();
2241
2242 for (coll_map_iter coll_it = coll_map_.begin();
2243 coll_it != coll_map_.end(); ++coll_it) {
2244 if (coll_it->second.offset != UINT_MAX
2245 || !collate_out_.undefined_optimization){
2246
2247 std::string valid = utf8_encode (coll_it->first);
2248 valid = valid.substr (0, valid.size() - 1);
2249
2250 while (valid.size() > 0){
2251 valid_coll_wchar_set_.insert (valid);
2252 valid = valid.substr(0, valid.size() - 1);
2253 }
2254 }
2255 }
2256}
#define i
Definition 17.names.cpp:126
#define k
Definition 17.names.cpp:128
#define e
Definition 17.names.cpp:118
#define w
Definition 17.names.cpp:139
#define j
Definition 17.names.cpp:127
#define off
Definition 17.names.cpp:507
#define offset
Definition 17.names.cpp:508
#define c
Definition 17.names.cpp:111
#define tmp
Definition 17.names.cpp:553
#define s
const int end
const int out
#define assert(expr)
Definition _cassert.h:40
#define _RWSTD_PATH_SEP
Definition _config.h:297
const std::list< std::string > & get_symnames_list() const
Definition charmap.h:94
const std::map< wchar_t, std::string > & get_rmb_cmap() const
Definition charmap.h:89
const std::string & get_code_set_name() const
Definition charmap.h:112
std::string get_charmap_name() const
Definition charmap.cpp:475
const std::map< wchar_t, std::string > & get_rw_cmap() const
Definition charmap.h:77
const std::map< std::string, wchar_t > & get_w_cmap() const
Definition charmap.h:71
const std::map< std::string, wchar_t > & get_mb_cmap() const
Definition charmap.h:83
wchar_t increment_wchar(wchar_t) const
Definition charmap.cpp:486
void dump_collate()
Definition collate.cpp:1062
std::pair< token_t, token_list_t > collate_entry_t
Definition def.h:98
void write_collate(std::string dir_name)
Definition collate.cpp:1156
std::list< collate_entry_t > collate_entry_list_t
Definition def.h:100
friend struct ce_info_t
Definition def.h:112
Scanner::token_t token_t
Definition def.h:95
friend struct collate_info_t
Definition def.h:113
std::list< token_t > token_list_t
Definition def.h:97
bool warnings_occurred_
Definition def.h:90
void open(std::string, char='#', char='\\')
Definition scanner.cpp:142
char escape_char() const
Definition scanner.cpp:129
void close()
Definition scanner.cpp:169
void ignore_line()
Definition scanner.cpp:135
unsigned long convert_escape(const char *, const char **=0, bool=false) const
Definition scanner.cpp:705
token_t next_token()
Definition scanner.cpp:352
@ tok_backward
Definition scanner.h:95
@ tok_end
Definition scanner.h:66
@ tok_script
Definition scanner.h:82
@ tok_reorder_section_end
Definition scanner.h:91
@ tok_sym_name
Definition scanner.h:161
@ tok_reorder_end
Definition scanner.h:89
@ tok_comment
Definition scanner.h:163
@ tok_string
Definition scanner.h:99
@ tok_ignore
Definition scanner.h:100
@ tok_coll_sym
Definition scanner.h:84
@ tok_forward
Definition scanner.h:94
@ tok_undefined
Definition scanner.h:97
@ tok_collate
Definition scanner.h:52
@ tok_coll_elem
Definition scanner.h:83
@ tok_reorder
Definition scanner.h:88
@ tok_order_start
Definition scanner.h:92
@ tok_copy
Definition scanner.h:166
@ tok_abs_ellipsis
Definition scanner.h:103
@ tok_nl
Definition scanner.h:168
@ tok_position
Definition scanner.h:96
@ tok_reorder_section
Definition scanner.h:90
@ tok_char_value
Definition scanner.h:162
@ tok_from
Definition scanner.h:85
@ tok_order_end
Definition scanner.h:93
@ tok_ident
Definition scanner.h:60
@ tok_end_tokens
Definition scanner.h:170
@ tok_dec_ellipsis
Definition scanner.h:105
@ tok_dbl_ellipsis
Definition scanner.h:106
@ tok_hex_ellipsis
Definition scanner.h:104
const char * name
Definition codecvt1.cpp:72
std::string strip_quotes(const std::string &str)
Definition def.h:604
bool issue_diag(int type, bool, const Scanner::token_t *token, const char *fmt,...)
@ W_REORD
Definition diagnostic.h:67
@ E_SYMUSED
Definition diagnostic.h:36
@ I_OPENWR
Definition diagnostic.h:83
@ W_MISSING
Definition diagnostic.h:66
@ W_NOTSUP
Definition diagnostic.h:76
@ E_COLNUM
Definition diagnostic.h:40
@ W_COLSYM
Definition diagnostic.h:65
@ E_COLORD
Definition diagnostic.h:50
@ I_SKIP
Definition diagnostic.h:86
@ W_SYNTAX
Definition diagnostic.h:72
@ E_RANGE
Definition diagnostic.h:48
@ E_REORD
Definition diagnostic.h:51
@ I_STAGE
Definition diagnostic.h:81
@ E_SYNTAX
Definition diagnostic.h:49
#define UCHAR_MAX
Definition limits.h:60
#define UINT_MAX
Definition limits.h:84
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.h:2990
std::string get_pathname(const std::string &fname, const std::string &other)
Definition path.cpp:129
std::string name
Definition scanner.h:178
token_id token
Definition scanner.h:179
const char * file
Definition scanner.h:186
std::map< std::string, wchar_t >::const_iterator n_cmap_citer2
Definition codecvt.cpp:41