1 /*
2 Copyright (C) 2015-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 WARNING: This file was generated by the dkct program (see
8 http://dktools.sourceforge.net/ for details).
9 Changes you make here will be lost if dkct is run again!
10 You should modify the original source and run dkct on it.
11 Original source: dk4uc2l.ctr
12 */
13
14 /** @file dk4uc2l.c The dk4uc2l module.
15 */
16
17
18
19 #include "dk4conf.h"
20
21 #include <stdio.h>
22
23 #if DK4_HAVE_STRING_H
24 #ifndef STRING_H_INCLUDED
25 #include <string.h>
26 #define STRING_H_INCLUDED 1
27 #endif
28 #endif
29
30 #include <libdk4base/dk4const.h>
31 #include <libdk4lat/dk4uc2l.h>
32 #include <libdk4c/dk4inst.h>
33 #include <libdk4base/dk4mem.h>
34 #include <libdk4app/dk4mema.h>
35 #include <libdk4base/dk4str8.h>
36 #include <libdk4base/dk4strd.h>
37 #include <libdk4c/dk4utf16.h>
38 #include <libdk4c/dk4utf8.h>
39 #include <libdk4c/dk4ansi.h>
40 #include <libdk4ma/dk4maasz.h>
41 #include <libdk4ma/dk4maaul.h>
42 #include <libdk4ma/dk4maadu.h>
43 #include <libdk4c/dk4filed.h>
44 #include <libdk4base/dk4mpl.h>
45 #include <libdk4c/dk4strm.h>
46 #include <libdk4c/dk4strmr.h>
47 #include <libdk4c/dk4dir.h>
48 #include <libdk4app/dk4dira.h>
49 #include <libdk4c/dk4pathd.h>
50 #include <libdk4c/dk4tsp08.h>
51 #include <libdk4c/dk4enc.h>
52 #include <libdk4maio8h/dk4mai8hul.h>
53 #include <libdk4maiodh/dk4maodh.h>
54 #include <libdk4maiodd/dk4maodd.h>
55 #include <libdk4base/dk4unused.h>
56 #include <libdk4c/dk4rec26.h>
57 #include <libdk4c/dk4strmo08.h>
58
59 #ifndef UC2L_H_INCLUDED
60 #include <libdk4lat/uc2l.h>
61 #endif
62
63 #if DK4_HAVE_ASSERT_H
64 #ifndef ASSERT_H_INCLUDED
65 #include <assert.h>
66 #define ASSERT_H_INCLUDED 1
67 #endif
68 #endif
69
70
71
72
73
74
75 #define UL(x) ((unsigned long)(x))
76
77
78 /** Object to use and modify from line handler.
79 */
80 typedef struct {
81 dk4_uc2l_t *ulptr; /**< Conversion structure. */
82 dk4_sto_t *s_ra; /**< Local range storage. */
83 dk4_sto_it_t *i_ra; /**< Local range iterator. */
84 dk4_uc2l_file_t *file; /**< File structure. */
85 dk4_uc2l_range_t *rpc; /**< Range pointer cache, pass 2. */
86 } handler_object_t;
87
88
89
90 /** File name suffixes to process.
91 */
92 static const dkChar * const dk4uc2l_suffixes[] = {
93 /* 0 */
94 dkT(".t2l"),
95
96 /* 1 */
97 dkT(".t2l.gz"),
98
99 /* 2 */
100 dkT(".t2l.bz2"),
101
102 NULL
103
104 };
105
106
107
108 /** Keywords allowed in a data line.
109 */
110 static const char * const dk4uc2l_keywords[] = {
111 /* 0 */
112 "b$oth",
113
114 /* 1 */
115 "t$ext",
116
117 /* 2 */
118 "m$ath",
119
120 /* 3 */
121 "e$ncoding",
122
123 /* 4 */
124 "p$ackages",
125
126 NULL
127
128 };
129
130
131
132 /** Font encoding names.
133 */
134 static const char * const dk4uc2l_font_encodings[] = {
135 /* 0 */
136 "ot1",
137
138 /* 1 */
139 "t1",
140
141 /* 2 */
142 "t4",
143
144 /* 3 */
145 "t5",
146
147 NULL
148
149 };
150
151
152
153 /** Subdirectory names.
154 */
155 static const dkChar * const dk4uc2l_kwnl[] = {
156 /* 0 */
157 dkT("/dktools/charmap"),
158
159 /* 1 */
160 dkT("/dk4app/charmap"),
161
162 /* 2 */
163 dkT("/dk3app/charmap"),
164
165 /* 3 */
166 dkT("/"),
167
168 NULL
169
170 };
171
172
173
174 /** Constant text strings for recommendations.
175 */
176 static const char * const dk4uc2l_kw8[] = {
177 /* 0 */
178 "% Font encodings:",
179
180 /* 1 */
181 "% Recommended package: ",
182
183 /* 2 */
184 " ot1",
185
186 /* 3 */
187 " t1",
188
189 /* 4 */
190 " t4",
191
192 /* 5 */
193 " t5",
194
195 NULL
196
197 };
198
199
200
201 /** Opening and closing tag for math mode.
202 */
203 static const char * const dk4uc2l_mm[] = {
204 "\\(", "\\)"
205 };
206
207
208 /** Number of elements in dk4uc2l_suffixes array.
209 */
210 static const size_t sz_suffixes =
211 DK4_SIZEOF(dk4uc2l_suffixes,DK4_PDKCHAR) - 1;
212
213
214
215 /** Compare two LaTeX package structures.
216 @param l Left pointer, always a package structure.
217 @param r Right pointer.
218 @param cr Comparison criteria: 0 if r is a package pointer,
219 1 if r is just a package name string.
220 @return Comparison result: 1 if l>r, 0 if l==r, -1 if l<r.
221 */
222 static
223 int
dk4uc2l_pkg_compare(const void * l,const void * r,int cr)224 dk4uc2l_pkg_compare(const void *l, const void *r, int cr)
225 {
226
227 const dk4_uc2l_pkg_t *pl;
228 const dk4_uc2l_pkg_t *pr;
229 int back = 0;
230
231 if (NULL != l) {
232 if (NULL != r) {
233 pl = (const dk4_uc2l_pkg_t *)l;
234 switch (cr) {
235 case 1: {
236 back = strcmp(pl->pn, (const char *)r);
237 } break;
238 default: {
239 pr = (const dk4_uc2l_pkg_t *)r;
240 back = strcmp(pl->pn, pr->pn);
241 } break;
242 }
243 if (-1 > back) back = -1;
244 if ( 1 < back) back = 1;
245 }
246 else {
247 back = 1;
248 }
249 }
250 else {
251 if (NULL != r) { back = -1; }
252 }
253 return back;
254 }
255
256
257
258 /** Compare two file information structures.
259 @param l Left pointer, always a file information structure.
260 @param r Right pointer.
261 @param cr Comparison criteria:
262 0 if the right pointer is a file information structure
263 pointer,
264 1 if the right pointer is a file name string.
265 @return Comparison result: 0 if file names are equal, -1 if l<r,
266 1 if l>r.
267 */
268 static
269 int
dk4uc2l_file_compare(const void * l,const void * r,int cr)270 dk4uc2l_file_compare(const void *l, const void *r, int cr)
271 {
272 const dk4_uc2l_file_t *pl;
273 const dk4_uc2l_file_t *pr;
274 int back = 0;
275 if (NULL != l) {
276 if (NULL != r) {
277 pl = (const dk4_uc2l_file_t *)l;
278 switch (cr) {
279 case 1: {
280 back = dk4str_pathcmp(pl->fn, (const dkChar *)r);
281 } break;
282 default: {
283 pr = (const dk4_uc2l_file_t *)r;
284 back = dk4str_pathcmp(pl->fn, pr->fn);
285 } break;
286 }
287 if (-1 > back) { back = -1; }
288 if ( 1 < back) { back = 1; }
289 }
290 else {
291 back = 1;
292 }
293 }
294 else {
295 if (NULL != r) {
296 back = -1;
297 }
298 }
299 return back;
300 }
301
302
303
304 /** Compare two range informations or a range information against a
305 character.
306 @param l Left pointer, always a range information structure.
307 @param r Right pointer.
308 @param cr Comparison criteria:
309 0 if the right pointer is a range information strucutre,
310 1 if the right pointer is a pointer to a dk4_c32_t.
311 @return Comparison result: -1 if l<r, 0 if l=r, 1 if l>r.
312 */
313 int
dk4uc2l_i_range_compare(const void * l,const void * r,int cr)314 dk4uc2l_i_range_compare(const void *l, const void *r, int cr)
315 {
316 const dk4_uc2l_range_t *pl;
317 const dk4_uc2l_range_t *pr;
318 const dk4_c32_t *pc;
319 int back = 0;
320 if (NULL != l) {
321 if (NULL != r) {
322 pl = (const dk4_uc2l_range_t *)l;
323 switch (cr) {
324 case 1: {
325 pc = (const dk4_c32_t *)r;
326 if (pl->start > *pc) {
327 back = 1;
328 }
329 else {
330 if (pl->end < *pc) {
331 back = -1;
332 }
333 }
334 } break;
335 default: {
336 pr = (const dk4_uc2l_range_t *)r;
337 if (pl->start < pr->start) {
338 back = -1;
339 }
340 else {
341 if (pl->start > pr->start) {
342 back = 1;
343 }
344 }
345 } break;
346 }
347 }
348 else {
349 back = 1;
350 }
351 }
352 else {
353 if (NULL != r) {
354 back = -1;
355 }
356 }
357 return back;
358 }
359
360
361
362 int
dk4uc2l_i_suffix_index_supported(int i)363 dk4uc2l_i_suffix_index_supported(int i)
364 {
365 int back = 1;
366 switch (i) {
367 case 1: {
368 #if !DK4_HAVE_ZLIB_H
369 back = 0;
370 #endif
371 } break;
372 case 2: {
373 #if !DK4_HAVE_BZLIB_H
374 back = 0;
375 #endif
376 } break;
377 }
378 return back;
379 }
380
381
382
383 int
dk4uc2l_i_find_suffix_index(const dkChar * fn)384 dk4uc2l_i_find_suffix_index(const dkChar *fn)
385 {
386 size_t sz = 0;
387 size_t i = 0;
388 size_t susz = 0;
389 int back = -1;
390
391 if (NULL != fn) {
392 sz = dk4str_len(fn);
393 for (i = 0; ((i < sz_suffixes) && (0 > back)); i++) {
394 susz = dk4str_len(dk4uc2l_suffixes[i]);
395 if (sz > susz) {
396 if (0 == dk4str_pathcmp(&(fn[sz - susz]), dk4uc2l_suffixes[i])) {
397 back = (int)i; i = sz_suffixes;
398 }
399 }
400 }
401 }
402 return back;
403 }
404
405
406
407 void
dk4uc2l_i_close_file(dk4_uc2l_file_t * fptr)408 dk4uc2l_i_close_file(dk4_uc2l_file_t *fptr)
409 {
410
411 if (NULL != fptr) {
412
413 dk4mem_release(fptr->fn);
414 fptr->loaded = 0x00;
415 dk4mem_free(fptr);
416 }
417
418 }
419
420
421
422 dk4_uc2l_file_t *
dk4uc2l_i_open_file(const dkChar * fn,dk4_er_t * erp)423 dk4uc2l_i_open_file(const dkChar *fn, dk4_er_t *erp)
424 {
425 dk4_uc2l_file_t *back = NULL;
426
427 if (NULL != fn) {
428 back = dk4mem_new(dk4_uc2l_file_t,1,erp);
429 if (NULL != back) {
430 back->loaded = 0x00;
431 back->fn = dk4str_dup(fn, erp);
432 if (NULL == back->fn) {
433 dk4mem_free(back);
434 back = NULL;
435 }
436 }
437 #if TRACE_DEBUG
438 else {
439 }
440 #endif
441 }
442 else {
443 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
444 }
445
446 return back;
447 }
448
449
450
451 void
dk4uc2l_i_close_pkg(dk4_uc2l_pkg_t * pptr)452 dk4uc2l_i_close_pkg(dk4_uc2l_pkg_t *pptr)
453 {
454
455 if (NULL != pptr) {
456
457 dk4mem_release(pptr->pn);
458 pptr->used = 0x00;
459 dk4mem_free(pptr);
460 }
461
462 }
463
464
465
466 dk4_uc2l_pkg_t *
dk4uc2l_i_open_pkg(const char * pn,dk4_er_t * erp)467 dk4uc2l_i_open_pkg(const char *pn, dk4_er_t *erp)
468 {
469 dk4_uc2l_pkg_t *back = NULL;
470
471 if (NULL != pn) {
472 back = dk4mem_new(dk4_uc2l_pkg_t,1,erp);
473 if (NULL != back) {
474 back->used = 0x00;
475 back->pn = dk4str8_dup(pn, erp);
476 if (NULL == back->pn) {
477 dk4mem_free(back);
478 back = NULL;
479 }
480 #if TRACE_DEBUG
481 else {
482 }
483 #endif
484 }
485 #if TRACE_DEBUG
486 else {
487 }
488 #endif
489 }
490 else {
491 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
492 }
493
494 return back;
495 }
496
497
498
499
500 void
dk4uc2l_i_close_range(dk4_uc2l_range_t * rptr)501 dk4uc2l_i_close_range(dk4_uc2l_range_t *rptr)
502 {
503 dk4_er_t er; /* Error report to detect numeric overflow */
504 unsigned long n; /* Number of elements in range */
505 size_t nn; /* Size_t version of n */
506 size_t i; /* Traverse all elements */
507
508 if (NULL != rptr) {
509
510 #if TRACE_DEBUG
511 if (NULL != rptr->file) {
512 if (NULL != rptr->file->fn) {
513
514 }
515 }
516 #endif
517 dk4error_init(&er);
518 n = dk4ma_ulong_sub(rptr->end, rptr->start, &er);
519 n = dk4ma_ulong_add(n, 1UL, &er);
520 #if 0
521 if ((DK4_E_NONE == er.ec) && ((dk4_um_t)n <= (dk4_um_t)(SIZE_MAX)))
522 #endif
523 if ((DK4_E_NONE == er.ec) && (dk4ma_um_isgeq(SIZE_MAX, n))) {
524 nn = (size_t)n;
525 if (NULL != rptr->both) {
526 for (i = 0; i < nn; i++) {
527 dk4mem_release((rptr->both)[i]);
528 }
529 dk4mem_free(rptr->both); rptr->both = NULL;
530 }
531 if (NULL != rptr->text) {
532 for (i = 0; i < nn; i++) {
533 dk4mem_release((rptr->text)[i]);
534 }
535 dk4mem_free(rptr->text); rptr->text = NULL;
536 }
537 if (NULL != rptr->math) {
538 for (i = 0; i < nn; i++) {
539 dk4mem_release((rptr->math)[i]);
540 }
541 dk4mem_free(rptr->math); rptr->math = NULL;
542 }
543 if (NULL != rptr->pkgs) {
544 for (i = 0; i < nn; i++) {
545 dk4mem_release((rptr->pkgs)[i]);
546 }
547 dk4mem_free(rptr->pkgs); rptr->pkgs = NULL;
548 }
549 if (NULL != rptr->fenc) {
550 dk4mem_free(rptr->fenc); rptr->fenc = NULL;
551 }
552 if (NULL != rptr->lno) {
553 dk4mem_free(rptr->lno); rptr->lno = NULL;
554 }
555 }
556 rptr->file = NULL;
557 rptr->start = (dk4_c32_t)0UL;
558 rptr->end = (dk4_c32_t)0UL;
559 rptr->ia = 0x00;
560 dk4mem_free(rptr);
561 }
562
563 }
564
565
566
567 int
dk4uc2l_i_init_range(dk4_uc2l_range_t * rptr,dk4_er_t * erp)568 dk4uc2l_i_init_range(
569 dk4_uc2l_range_t *rptr,
570 dk4_er_t *erp
571 )
572 {
573 dk4_er_t er;
574 char **ppchr;
575 dk4_uc2l_pkg_pp *pppkg;
576 unsigned char *puc;
577 dk4_um_t *pum;
578 size_t sznum = 0;
579 size_t i = 0;
580 unsigned long num = 0UL;
581 int back = 0;
582
583
584 /* Avoid second initialization
585 */
586 if (0x00 != rptr->ia) {
587 back = 1;
588 goto finished;
589 }
590
591 /* Find number of elements
592 */
593 dk4error_init(&er);
594 num = dk4ma_ulong_add(
595 dk4ma_ulong_sub(
596 (unsigned long)(rptr->end), (unsigned long)(rptr->start), &er
597 ), 1UL, &er
598 );
599 if (DK4_E_NONE != er.ec) {
600 dk4error_copy(erp, &er);
601 goto finished;
602 }
603 #if 0
604 if ((dk4_um_t)(SIZE_MAX) >= (dk4_um_t)num)
605 #endif
606 if (0 != dk4ma_um_isgeq(SIZE_MAX, num)) {
607 sznum = (size_t)num;
608 }
609 else {
610 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
611 goto finished;
612 }
613
614 /* both
615 */
616 if (NULL == rptr->both) {
617 rptr->both = dk4mem_new(DK4_PCHAR,sznum,erp);
618 if (NULL != rptr->both) {
619 ppchr = rptr->both;
620 for (i = 0; i < sznum; i++) { *(ppchr++) = NULL; }
621 }
622 else {
623 goto finished;
624 }
625 }
626
627 /* text
628 */
629 if (NULL == rptr->text) {
630 rptr->text = dk4mem_new(DK4_PCHAR,sznum,erp);
631 if (NULL != rptr->text) {
632 ppchr = rptr->text;
633 for (i = 0; i < sznum; i++) { *(ppchr++) = NULL; }
634 }
635 else {
636 goto finished;
637 }
638 }
639
640 /* math
641 */
642 if (NULL == rptr->math) {
643 rptr->math = dk4mem_new(DK4_PCHAR,sznum,erp);
644 if (NULL != rptr->math) {
645 ppchr = rptr->math;
646 for (i = 0; i < sznum; i++) { *(ppchr++) = NULL; }
647 }
648 else {
649 goto finished;
650 }
651 }
652
653 /* pkgs
654 */
655 if (NULL == rptr->pkgs) {
656 rptr->pkgs = dk4mem_new(dk4_uc2l_pkg_pp,sznum,erp);
657 if (NULL != rptr->pkgs) {
658 pppkg = rptr->pkgs;
659 for (i = 0; i < sznum; i++) { *(pppkg++) = NULL; }
660 }
661 else{
662 goto finished;
663 }
664 }
665
666 /* fenc
667 */
668 if (NULL == rptr->fenc) {
669 rptr->fenc = dk4mem_new(unsigned char,sznum,erp);
670 if (NULL != rptr->fenc) {
671 puc = rptr->fenc;
672 for (i = 0; i < sznum; i++) { *(puc++) = 0xFF; }
673 }
674 else {
675 goto finished;
676 }
677 }
678
679 /* lno
680 */
681 if (NULL == rptr->lno) {
682 rptr->lno = dk4mem_new(dk4_um_t,sznum,erp);
683 if (NULL != rptr->lno) {
684 pum = rptr->lno;
685 for (i = 0; i < sznum; i++) { *(pum++) = (dk4_um_t)0UL; }
686 }
687 else {
688 goto finished;
689 }
690 }
691
692 /* Success
693 */
694 back = 1;
695
696 /* Return
697 */
698 finished:
699
700 return back;
701 }
702
703
704
705 dk4_uc2l_range_t *
dk4uc2l_i_open_range(dk4_c32_t c32,dk4_uc2l_file_t * fptr,dk4_er_t * erp)706 dk4uc2l_i_open_range(
707 dk4_c32_t c32,
708 dk4_uc2l_file_t *fptr,
709 dk4_er_t *erp
710 )
711 {
712 dk4_uc2l_range_t *back = NULL;
713
714 if (NULL != fptr) {
715 back = dk4mem_new(dk4_uc2l_range_t,1,erp);
716 if (NULL != back) {
717 back->file = fptr;
718 back->both = NULL;
719 back->text = NULL;
720 back->math = NULL;
721 back->pkgs = NULL;
722 back->fenc = NULL;
723 back->lno = NULL;
724 back->start = back->end = c32;
725 back->ia = 0x00;
726 }
727 #if TRACE_DEBUG
728 else {
729 }
730 #endif
731 }
732 else {
733 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
734 }
735
736 return back;
737 }
738
739
740
741 void
dk4uc2l_close(dk4_uc2l_t * ulptr)742 dk4uc2l_close(dk4_uc2l_t *ulptr)
743 {
744 dk4_uc2l_pkg_t *pptr;
745 dk4_uc2l_file_t *fptr;
746 dk4_uc2l_range_t *rptr;
747
748 #if DK4_USE_ASSERT
749 assert(NULL != ulptr);
750 #endif
751 if (NULL != ulptr) {
752 dk4mem_release(ulptr->dname);
753 if (NULL != ulptr->s_ranges) {
754 if (NULL != ulptr->i_ranges) {
755 dk4sto_it_reset(ulptr->i_ranges);
756 do {
757 rptr = (dk4_uc2l_range_t *)dk4sto_it_next(ulptr->i_ranges);
758 if (NULL != rptr) {
759 dk4uc2l_i_close_range(rptr);
760 }
761 } while (NULL != rptr);
762 dk4sto_it_close(ulptr->i_ranges);
763 }
764 dk4sto_close(ulptr->s_ranges);
765 }
766 ulptr->s_ranges = NULL;
767 ulptr->i_ranges = NULL;
768 if (NULL != ulptr->s_files) {
769 if (NULL != ulptr->i_files) {
770 dk4sto_it_reset(ulptr->i_files);
771 do {
772 fptr = (dk4_uc2l_file_t *)dk4sto_it_next(ulptr->i_files);
773 if (NULL != fptr) {
774 dk4uc2l_i_close_file(fptr);
775 }
776 } while (NULL != fptr);
777 dk4sto_it_close(ulptr->i_files);
778 }
779 dk4sto_close(ulptr->s_files);
780 }
781 ulptr->s_files = NULL;
782 ulptr->i_files = NULL;
783 if (NULL != ulptr->s_pkgs) {
784 if (NULL != ulptr->i_pkgs) {
785 dk4sto_it_reset(ulptr->i_pkgs);
786 do {
787 pptr = (dk4_uc2l_pkg_t *)dk4sto_it_next(ulptr->i_pkgs);
788 if (NULL != pptr) {
789 dk4uc2l_i_close_pkg(pptr);
790 }
791 } while (NULL != pptr);
792 dk4sto_it_close(ulptr->i_pkgs);
793 }
794 dk4sto_close(ulptr->s_pkgs);
795 }
796 ulptr->s_pkgs = NULL;
797 ulptr->i_pkgs = NULL;
798 dk4mem_free(ulptr);
799 }
800
801 }
802
803
804
805 dk4_uc2l_t *
dk4uc2l_i_new(const dkChar * dn,dk4_er_t * erp)806 dk4uc2l_i_new(const dkChar *dn, dk4_er_t *erp)
807 {
808 dk4_uc2l_t *back = NULL;
809 int ok = 0;
810
811 back = dk4mem_new(dk4_uc2l_t,1,erp);
812 if (NULL != back) {
813 back->buf[0] = '\0';
814 back->dname = NULL;
815 back->s_ranges = NULL;
816 back->i_ranges = NULL;
817 back->s_files = NULL;
818 back->i_files = NULL;
819 back->s_pkgs = NULL;
820 back->i_pkgs = NULL;
821 back->had_error = 0;
822 back->utf8allowed = 0;
823 back->fallowed = 0xFF;
824 back->dname = dk4str_dup(dn, erp);
825 if (NULL != back->dname) {
826 back->s_ranges = dk4sto_open(erp);
827 back->s_files = dk4sto_open(erp);
828 back->s_pkgs = dk4sto_open(erp);
829 if (
830 (NULL != back->s_ranges)
831 && (NULL != back->s_files)
832 && (NULL != back->s_pkgs)
833 ) {
834 dk4sto_set_comp(back->s_ranges, dk4uc2l_i_range_compare, 0);
835 dk4sto_set_comp(back->s_files, dk4uc2l_file_compare, 0);
836 dk4sto_set_comp(back->s_pkgs, dk4uc2l_pkg_compare, 0);
837 back->i_ranges = dk4sto_it_open(back->s_ranges, erp);
838 back->i_files = dk4sto_it_open(back->s_files, erp);
839 back->i_pkgs = dk4sto_it_open(back->s_pkgs, erp);
840 if (
841 (NULL != back->i_ranges)
842 && (NULL != back->i_files)
843 && (NULL != back->i_pkgs)
844 ) {
845 ok = 1;
846 }
847 #if TRACE_DEBUG
848 else {
849 }
850 #endif
851 }
852 #if TRACE_DEBUG
853 else {
854 }
855 #endif
856 }
857 #if TRACE_DEBUG
858 else {
859 }
860 #endif
861 }
862 #if TRACE_DEBUG
863 else {
864 }
865 #endif
866 if ((NULL != back) && (0 == ok)) {
867 dk4uc2l_close(back);
868 back = NULL;
869 }
870
871 return back;
872 }
873
874
875
876 /** Handler to process a line during pass 1.
877 @param obj Object to use and modify during processing.
878 @param line Current text line to process.
879 @param lineno Current line number.
880 @param erp Error report, may be NULL.
881 @return DK4_TSP_RES_OK on success, DK4_TSP_RES_ERROR on recoverable
882 errors, DK4_TSP_RES_FATAL on fatal errors requiring an abort.
883 */
884 static
885 int
dk4uc2l_handler_pass1(void * obj,char * line,dk4_um_t DK4_ARG_UNUSED (lineno),dk4_er_t * erp)886 dk4uc2l_handler_pass1(
887 void *obj,
888 char *line,
889 dk4_um_t DK4_ARG_UNUSED(lineno) ,
890 dk4_er_t *erp
891 )
892 {
893 handler_object_t *pho;
894 char *p1;
895 dk4_uc2l_range_t *rptr;
896 dk4_uc2l_range_t *r2;
897 const char *pe = NULL;
898 unsigned long ul = 0UL;
899 dk4_c32_t c32;
900 dk4_c32_t rbo;
901 int res;
902 int back = DK4_TSP_RES_OK;
903
904 DK4_UNUSED_ARG(lineno)
905 #if TRACE_DEBUG
906 dk4str8_delnl(line);
907 #endif
908
909 pho = (handler_object_t *)obj;
910
911 /* Find start of line.
912 */
913 p1 = dk4str8_start(line, NULL);
914
915 /* Ignore empty lines and comment lines
916 */
917 if (NULL == p1) {
918 goto finished;
919 }
920 if ('#' == *p1) {
921 goto finished;
922 }
923
924 /* Retrieve hexadecimal number
925 */
926 (void)dk4str8_next(p1, NULL);
927 res = dk4ma_input_c8_hex_ulong(&ul, p1, &pe, 1, erp);
928 if (0 == res) {
929 /* ERROR: Syntax, not a number */
930 goto finished;
931 }
932 c32 = (dk4_c32_t)ul;
933
934 /* Check for number in global storage
935 */
936 rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(
937 pho->ulptr->i_ranges, &c32, 1
938 );
939 if (NULL != rptr) {
940 /* WARNING erp: Ignoring redefinition */
941 dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
942 goto finished;
943 }
944
945 /* Check for number in storage for file
946 */
947 rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(pho->i_ra, &c32, 1);
948 if (NULL != rptr) {
949 /* WARNING erp: Ignoring redefinition */
950 dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
951 goto finished;
952 }
953
954 /* Check whether appending to existing range
955 */
956 if (0UL < c32) {
957 rbo = (dk4_c32_t)(c32 - 1UL);
958 rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(pho->i_ra, &rbo, 1);
959 if (NULL != rptr) {
960 rptr->end = c32;
961 #if DK4_SIZEOF_LONG <= 4
962 if ((dk4_um_t)(ULONG_MAX) > (dk4_um_t)c32) {
963 #endif
964 rbo = (dk4_c32_t)(c32 + 1UL);
965 r2 = (dk4_uc2l_range_t *)dk4sto_it_find_like(
966 pho->i_ra, &rbo, 1
967 );
968 if (NULL != r2) {
969 dk4sto_remove(pho->s_ra, r2, NULL);
970 rptr->end = r2->end;
971 dk4uc2l_i_close_range(r2);
972 }
973 #if DK4_SIZEOF_LONG <= 4
974 }
975 #endif
976 goto finished;
977 }
978 }
979
980 /* Check whether prepending to existing range
981 */
982 #if DK4_SIZEOF_LONG <= 4
983 if ((dk4_um_t)(ULONG_MAX) > (dk4_um_t)c32) {
984 #endif
985 rbo = (dk4_c32_t)(c32 + 1UL);
986 rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(pho->i_ra, &rbo, 1);
987 if (NULL != rptr) {
988 rptr->start = c32;
989 if ((dk4_c32_t)0UL < c32) {
990 rbo = (dk4_c32_t)(c32 - 1UL);
991 r2 = (dk4_uc2l_range_t *)dk4sto_it_find_like(
992 pho->i_ra, &rbo, 1
993 );
994 if (NULL != r2) {
995 dk4sto_remove(pho->s_ra, r2, NULL);
996 rptr->start = r2->start;
997 dk4uc2l_i_close_range(r2);
998 }
999 }
1000 goto finished;
1001 }
1002 #if DK4_SIZEOF_LONG <= 4
1003 }
1004 #endif
1005 /* Create range on its own
1006 */
1007 rptr = dk4uc2l_i_open_range(c32, pho->file, erp);
1008 if (NULL == rptr) {
1009 back = DK4_TSP_RES_FATAL;
1010 goto finished;
1011 }
1012 if (0 == dk4sto_add(pho->ulptr->s_ranges, rptr, erp)) {
1013 dk4uc2l_i_close_range(rptr);
1014 back = DK4_TSP_RES_FATAL;
1015 }
1016
1017 finished:
1018
1019 return back;
1020 }
1021
1022
1023
1024 /** Process one file in pass 1 specified by absolute path name.
1025 @param ulptr Conversion structure to set up.
1026 @param rstrm Stream, opened for binary reading.
1027 @param puc2lf File structure.
1028 @param erp Error report, may be NULL.
1029 @param bptr Address of success variable to reset on errors.
1030 */
1031 static
1032 void
dk4uc2l_i_process_stream_pass1(dk4_uc2l_t * ulptr,dk4_stream_t * rstrm,dk4_uc2l_file_t * puc2lf,int * bptr,dk4_er_t * erp)1033 dk4uc2l_i_process_stream_pass1(
1034 dk4_uc2l_t *ulptr,
1035 dk4_stream_t *rstrm,
1036 dk4_uc2l_file_t *puc2lf,
1037 int *bptr,
1038 dk4_er_t *erp
1039 )
1040 {
1041 char lnbuf[256]; /* Line buffer */
1042 dk4_tsp08_t tsp08; /* Text stream processor */
1043 handler_object_t ho; /* Handler object */
1044 dk4_uc2l_range_t *rptr; /* Current range */
1045 int res; /* Operation result */
1046 int cc; /* Flag: Can continue */
1047 char c; /* Current character to process */
1048
1049
1050 /* Initialize handler object
1051 */
1052 ho.file = puc2lf;
1053 ho.ulptr = ulptr;
1054 ho.s_ra = NULL;
1055 ho.i_ra = NULL;
1056
1057 /* Create storage and iterator
1058 */
1059 ho.s_ra = dk4sto_open(erp);
1060 if (NULL == ho.s_ra) {
1061 *bptr = 0;
1062 ulptr->had_error |= DK4_UC2L_ERROR_MEMORY;
1063 goto finished;
1064 }
1065 dk4sto_set_comp(ho.s_ra, dk4uc2l_i_range_compare, 0);
1066 ho.i_ra = dk4sto_it_open(ho.s_ra, erp);
1067 if (NULL == ho.i_ra) {
1068 *bptr = 0;
1069 ulptr->had_error |= DK4_UC2L_ERROR_MEMORY;
1070 goto finished;
1071 }
1072
1073 /* Initialize text stream processor
1074 */
1075 res = dk4tsp08_setup_line(
1076 &tsp08, (void *)(&ho), dk4uc2l_handler_pass1, lnbuf, sizeof(lnbuf),
1077 DK4_ENCODING_PLAIN, DK4_ENCODING_PLAIN, erp
1078 );
1079 if (0 == res) {
1080 *bptr = 0;
1081 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1082 goto finished;
1083 }
1084
1085 /* Process file contents
1086 */
1087 do {
1088 cc = 0;
1089 res = dk4stream_c8_read_byte(&c, rstrm, NULL);
1090 if (0 != res) {
1091 cc = 1;
1092 res = dk4tsp08_add_one_byte(&tsp08, (unsigned char)c);
1093 switch (res) {
1094 case DK4_TSP_RES_ERROR : {
1095 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1096 *bptr = 0;
1097 } break;
1098 case DK4_TSP_RES_FATAL : {
1099 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1100 *bptr = 0;
1101 goto finished;
1102 } break;
1103 }
1104 }
1105 } while (0 < cc);
1106
1107 /* Finalize text stream processor
1108 */
1109 res = dk4tsp08_finish(&tsp08);
1110 switch (res) {
1111 case DK4_TSP_RES_ERROR : case DK4_TSP_RES_FATAL : {
1112 *bptr = 0;
1113 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1114 goto finished;
1115 } break;
1116 }
1117
1118 /* Transfer ranges to global storage
1119 */
1120 do {
1121 dk4sto_it_reset(ho.i_ra);
1122 rptr = (dk4_uc2l_range_t *)dk4sto_it_next(ho.i_ra);
1123 if (NULL != rptr) {
1124 dk4sto_remove(ho.s_ra, rptr, erp);
1125 if (0 == dk4sto_add(ulptr->s_ranges, rptr, erp)) {
1126 dk4uc2l_i_close_range(rptr);
1127 *bptr = 0;
1128 goto finished;
1129 }
1130 }
1131 } while (NULL != rptr);
1132
1133 /* Release resources
1134 */
1135 finished:
1136 if (NULL != ho.s_ra) {
1137 if (NULL != ho.i_ra) {
1138 dk4sto_it_reset(ho.i_ra);
1139 do {
1140 rptr = (dk4_uc2l_range_t *)dk4sto_it_next(ho.i_ra);
1141 if (NULL != rptr) {
1142 dk4uc2l_i_close_range(rptr);
1143 }
1144 } while (NULL != rptr);
1145 dk4sto_it_close(ho.i_ra);
1146 }
1147 dk4sto_close(ho.s_ra);
1148 }
1149
1150
1151 }
1152
1153
1154 /** Process one file in pass 1 specified by absolute path name.
1155 @param ulptr Conversion structure to set up.
1156 @param fn Full (absolute) file name.
1157 @param sfn Short file name within given directory.
1158 @param erp Error report, may be NULL.
1159 @param bptr Address of success variable to reset on errors.
1160 */
1161 static
1162 void
dk4uc2l_i_process_one_full_file_pass1(dk4_uc2l_t * ulptr,const dkChar * fn,const dkChar * sfn,int * bptr,dk4_er_t * erp)1163 dk4uc2l_i_process_one_full_file_pass1(
1164 dk4_uc2l_t *ulptr,
1165 const dkChar *fn,
1166 const dkChar *sfn,
1167 int *bptr,
1168 dk4_er_t *erp
1169 )
1170 {
1171 dk4_stream_t *rstrm;
1172 dk4_uc2l_file_t *puc2lf;
1173 int fnsi;
1174
1175
1176 puc2lf = (dk4_uc2l_file_t *)dk4sto_it_find_like(ulptr->i_files, sfn, 1);
1177 if (NULL == puc2lf) {
1178 puc2lf = dk4uc2l_i_open_file(sfn, erp);
1179 if (NULL != puc2lf) {
1180 if (0 != dk4sto_add(ulptr->s_files, puc2lf, erp)) {
1181 fnsi = dk4uc2l_i_find_suffix_index(fn);
1182 if (-1 < fnsi) {
1183 if (0 != dk4uc2l_i_suffix_index_supported(fnsi)) {
1184 rstrm = dk4stream_open_file_reader(fn, erp);
1185 if (NULL != rstrm) {
1186 /* Process stream */
1187 dk4uc2l_i_process_stream_pass1(
1188 ulptr, rstrm, puc2lf, bptr, erp
1189 );
1190 dk4stream_close(rstrm, NULL);
1191 }
1192 else {
1193 ulptr->had_error |= DK4_UC2L_ERROR_FOPEN;
1194 *bptr = 0;
1195 }
1196 }
1197 else {
1198 ulptr->had_error |= DK4_UC2L_ERROR_FOPEN;
1199 *bptr = 0;
1200 /* ERROR erp: Compression type not supported */
1201 dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
1202 }
1203 }
1204 else {
1205 /* Ignoring unsupported file */
1206 }
1207 }
1208 else {
1209 dk4uc2l_i_close_file(puc2lf);
1210 }
1211 }
1212 #if TRACE_DEBUG
1213 else {
1214 }
1215 #endif
1216 }
1217 #if TRACE_DEBUG
1218 else {
1219 }
1220 #endif
1221
1222 }
1223
1224
1225
1226 /** Process one file in pass 1.
1227 @param ulptr Conversion structure to set up.
1228 @param pth Directory path name, may be NULL.
1229 @param fn Short file name within given directory.
1230 @param erp Error report, may be NULL.
1231 @param bptr Address of success variable to reset on errors.
1232 */
1233 static
1234 void
dk4uc2l_i_process_one_file_pass1(dk4_uc2l_t * ulptr,const dkChar * pth,const dkChar * fn,int * bptr,dk4_er_t * erp)1235 dk4uc2l_i_process_one_file_pass1(
1236 dk4_uc2l_t *ulptr,
1237 const dkChar *pth,
1238 const dkChar *fn,
1239 int *bptr,
1240 dk4_er_t *erp
1241 )
1242 {
1243 dkChar fnb[DK4_MAX_PATH];
1244 size_t szfnb = DK4_SIZEOF(fnb,dkChar);
1245
1246 if (NULL != pth) {
1247 if (0 != dk4str_cpy_s(fnb, szfnb, pth, erp)) {
1248 if (0 != dk4str_cat_s(fnb, szfnb, dk4uc2l_kwnl[3], erp)) {
1249 if (0 != dk4str_cat_s(fnb, szfnb, fn, erp)) {
1250 dk4path_correct_sep(fnb);
1251 dk4uc2l_i_process_one_full_file_pass1(
1252 ulptr, fnb, fn, bptr, erp
1253 );
1254 }
1255 else {
1256 *bptr = 0;
1257 }
1258 }
1259 else {
1260 *bptr = 0;
1261 }
1262 }
1263 else {
1264 *bptr = 0;
1265 }
1266 }
1267 else {
1268 dk4uc2l_i_process_one_full_file_pass1(ulptr, fn, fn, bptr, erp);
1269 }
1270
1271 }
1272
1273
1274
1275 /** First pass to gather information which Unicode position is configured
1276 in which data file.
1277 This function is run while creating a new conversion structure
1278 to fill the range structures so we can later find a file for a
1279 Unicode position.
1280 If this function fails, the conversion structure is considered
1281 unusable.
1282 The function fails only on memory allocation failures, not on
1283 syntax errors in translation files.
1284 @param ulptr Conversion structure.
1285 @param erp Error report, may be NULL.
1286 @return 1 on success, 0 on error.
1287 */
1288 static
1289 int
dk4uc2l_i_pass1(dk4_uc2l_t * ulptr,dk4_er_t * erp)1290 dk4uc2l_i_pass1(dk4_uc2l_t *ulptr, dk4_er_t *erp)
1291 {
1292 const dkChar *fn = NULL;
1293 const dkChar *pth = NULL;
1294 dk4_dir_t *pdir = NULL;
1295 int back = 0;
1296
1297 pdir = dk4dir_open(ulptr->dname, DK4_DIR_OPEN_SORTED, erp);
1298 if (NULL != pdir) {
1299 pth = dk4dir_get_path(pdir);
1300 back = 1;
1301 do {
1302 fn = dk4dir_next_file(pdir);
1303 if (NULL != fn) {
1304 if (-1 < dk4uc2l_i_find_suffix_index(fn)) {
1305 dk4uc2l_i_process_one_file_pass1(ulptr,pth,fn,&back,erp);
1306 }
1307 }
1308 } while (NULL != fn);
1309 dk4dir_close(pdir);
1310 }
1311 else {
1312 /* ERROR: Failed to open directory */
1313 ulptr->had_error |= DK4_UC2L_ERROR_FOPEN;
1314 }
1315
1316 return back;
1317 }
1318
1319
1320
1321 /** Internal function to open a new conversion structure.
1322 @param dn Directory name (must be the name of an existing directory).
1323 @param erp Error report, may be NULL.
1324 @return Valid pointer on success, NULL on error.
1325 */
1326 static
1327 dk4_uc2l_t *
dk4uc2l_i_open(const dkChar * dn,dk4_er_t * erp)1328 dk4uc2l_i_open(const dkChar *dn, dk4_er_t *erp)
1329 {
1330 dk4_uc2l_t *back = NULL;
1331
1332 back = dk4uc2l_i_new(dn, erp);
1333 if (NULL != back) {
1334 if (0 == dk4uc2l_i_pass1(back, erp)) {
1335 dk4uc2l_close(back);
1336 back = NULL;
1337 }
1338 #if TRACE_DEBUG
1339 else {
1340 }
1341 #endif
1342 }
1343 #if TRACE_DEBUG
1344 else {
1345 /* ERROR: Memory (already reported) */
1346 }
1347 #endif
1348
1349 return back;
1350 }
1351
1352
1353
1354 dk4_uc2l_t *
dk4uc2l_open(const dkChar * dn,dk4_er_t * erp)1355 dk4uc2l_open(const dkChar *dn, dk4_er_t *erp)
1356 {
1357 dkChar fnb[DK4_MAX_PATH];
1358 const dkChar *shdn = NULL;
1359 dk4_uc2l_t *back = NULL;
1360 const size_t szfnb = DK4_SIZEOF(fnb,dkChar);
1361 size_t i = 0;
1362
1363
1364 if (NULL != dn) {
1365 if (0 != dk4file_is_directory(dn, erp)) {
1366 back = dk4uc2l_i_open(dn, erp);
1367 }
1368 }
1369 else {
1370 shdn = dk4inst_get_directory(2);
1371 for (i = 0; ((i < 3) && (NULL == dn)); i++) {
1372 if (0 != dk4str_cpy_s(fnb, szfnb, shdn, NULL)) {
1373 if (0 != dk4str_cat_s(fnb, szfnb, dk4uc2l_kwnl[i], NULL)) {
1374 dk4path_correct_sep(fnb);
1375 if (0 != dk4file_is_directory(fnb, NULL)) {
1376 dn = fnb;
1377 }
1378 }
1379 }
1380 }
1381 if (NULL != dn) {
1382 back = dk4uc2l_i_open(dn, erp);
1383 }
1384 else {
1385 /* ERROR: No directory found */
1386 dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
1387 }
1388 }
1389
1390 return back;
1391 }
1392
1393
1394
1395 void
dk4uc2l_allow_utf8(dk4_uc2l_t * ulptr,int enabled)1396 dk4uc2l_allow_utf8(dk4_uc2l_t *ulptr, int enabled)
1397 {
1398
1399 #if DK4_USE_ASSERT
1400 assert(NULL != ulptr);
1401 #endif
1402 if (NULL != ulptr) {
1403 ulptr->utf8allowed = ((0 != enabled) ? 0x01 : 0x00);
1404 }
1405
1406 }
1407
1408
1409
1410 void
dk4uc2l_clean_packages_and_fonts(dk4_uc2l_t * ulptr)1411 dk4uc2l_clean_packages_and_fonts(dk4_uc2l_t *ulptr)
1412 {
1413 dk4_uc2l_pkg_t *pptr;
1414
1415 #if DK4_USE_ASSERT
1416 assert(NULL != ulptr);
1417 #endif
1418 if (NULL != ulptr) {
1419 ulptr->fallowed = DK4_UC2L_FONT_ENCODING_ALL;
1420 dk4sto_it_reset(ulptr->i_pkgs);
1421 do {
1422 pptr = (dk4_uc2l_pkg_t *)dk4sto_it_next(ulptr->i_pkgs);
1423 if (NULL != pptr) {
1424 pptr->used = 0x00;
1425 }
1426 } while (NULL != pptr);
1427 }
1428 }
1429
1430
1431
1432 unsigned char
dk4uc2l_retrieve_allowed_fe(dk4_uc2l_t * ulptr)1433 dk4uc2l_retrieve_allowed_fe(dk4_uc2l_t *ulptr)
1434 {
1435 unsigned char back = 0x00;
1436
1437 #if DK4_USE_ASSERT
1438 assert(NULL != ulptr);
1439 #endif
1440 if (NULL != ulptr) {
1441 back = ulptr->fallowed;
1442 }
1443
1444 return back;
1445 }
1446
1447
1448
1449 int
dk4uc2lat_direct(dk4_c32_t c32)1450 dk4uc2lat_direct(dk4_c32_t c32)
1451 {
1452 int back = 0;
1453 char c; /* 8-bit character version of c32. */
1454
1455 if(128UL > dk4recode_c32_to_ul(c32)) {
1456 c = (char)c32;
1457 switch(c) {
1458 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
1459 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
1460 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
1461 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
1462 case 'y': case 'z': case 'A': case 'B': case 'C': case 'D':
1463 case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
1464 case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
1465 case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V':
1466 case 'W': case 'X': case 'Y': case 'Z': case '0': case '1':
1467 case '2': case '3': case '4': case '5': case '6': case '7':
1468 case '8': case '9': case ',': case '.': case ':': case ';':
1469 case '+': case '-': case '?': case '!': case '|': case '@':
1470 case '(': case ')': case '/': case '=': case ' ':
1471 {
1472 back = 1;
1473 }
1474 break;
1475 }
1476 }
1477 return back;
1478 }
1479
1480
1481
1482 int
dk4uc2l_i_keyword_index(const char * pkey)1483 dk4uc2l_i_keyword_index(const char *pkey)
1484 {
1485 return (dk4str8_abbr_index(dk4uc2l_keywords, '$', pkey, 0));
1486 }
1487
1488
1489
1490
1491 unsigned char
dk4uc2l_font_encoding_from_name(const char * pname)1492 dk4uc2l_font_encoding_from_name(const char *pname)
1493 {
1494 unsigned char back = 0x00;
1495 switch (dk4str8_array_index(dk4uc2l_font_encodings, pname, 0)) {
1496 case 0: {
1497 back = DK4_UC2L_FONT_ENCODING_OT1;
1498 } break;
1499 case 1: {
1500 back = DK4_UC2L_FONT_ENCODING_T1;
1501 } break;
1502 case 2: {
1503 back = DK4_UC2L_FONT_ENCODING_T4;
1504 } break;
1505 case 3: {
1506 back = DK4_UC2L_FONT_ENCODING_T5;
1507 } break;
1508 }
1509 return back;
1510 }
1511
1512
1513
1514 dk4_uc2l_pkg_t *
dk4uc2l_i_create_pkg(dk4_sto_t * s_pkgs,const char * pname)1515 dk4uc2l_i_create_pkg(
1516 dk4_sto_t *s_pkgs,
1517 const char *pname
1518 )
1519 {
1520 dk4_uc2l_pkg_t *back = NULL;
1521 back = dk4uc2l_i_open_pkg(pname, NULL);
1522 if (NULL != back) {
1523 if (0 == dk4sto_add(s_pkgs, back, NULL)) {
1524 dk4uc2l_i_close_pkg(back);
1525 back = NULL;
1526 }
1527 }
1528 return back;
1529 }
1530
1531
1532
1533 /** Handler to process a line during pass 1.
1534 @param obj Object to use and modify during processing.
1535 @param line Current text line to process.
1536 @param lineno Current line number.
1537 @param erp Error report, may be NULL.
1538 @return DK4_TSP_RES_OK on success, DK4_TSP_RES_ERROR on recoverable
1539 errors, DK4_TSP_RES_FATAL on fatal errors requiring an abort.
1540 */
1541 static
1542 int
dk4uc2l_handler_pass2(void * obj,char * line,dk4_um_t lineno,dk4_er_t * erp)1543 dk4uc2l_handler_pass2(
1544 void *obj,
1545 char *line,
1546 dk4_um_t lineno,
1547 dk4_er_t *erp
1548 )
1549 {
1550 dk4_er_t er;
1551 char *pkgn[16];
1552 handler_object_t *lho = NULL;
1553 const char *pe = NULL;
1554 char *p1 = NULL;
1555 char *p2 = NULL;
1556 char *p3 = NULL;
1557 char *p4 = NULL;
1558 dk4_uc2l_range_t *rptr = NULL;
1559 dk4_uc2l_pkg_t *pptr = NULL;
1560 size_t ind = 0;
1561 size_t numpkg = 0;
1562 size_t i = 0;
1563 unsigned long ul = 0UL;
1564 dk4_c32_t c32 = (dk4_c32_t)0UL;
1565 int back = DK4_TSP_RES_OK;
1566 int res = 0;
1567 int adding = 0;
1568 unsigned char fex = 0;
1569 unsigned char feval = 0;
1570
1571 #if TRACE_DEBUG
1572 dk4str8_delnl(line);
1573
1574 #endif
1575
1576 /* Line handler object
1577 */
1578 lho = (handler_object_t *)obj;
1579
1580 /* Find start of line, ignore empty lines and comments
1581 */
1582 p1 = dk4str8_start(line, NULL);
1583 if (NULL == p1) {
1584 goto finished;
1585 }
1586 if ('#' == *p1) {
1587 goto finished;
1588 }
1589
1590 /* Retrieve character number
1591 */
1592 p2 = dk4str8_next(p1, NULL);
1593 res = dk4ma_input_c8_hex_ulong(&ul, p1, &pe, 1, erp);
1594 if (0 == res) {
1595 /* WARNING: Syntax, no number.
1596 Already reported in pass 1.
1597 */
1598 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1599 goto finished;
1600 }
1601 c32 = (dk4_c32_t)ul;
1602
1603 /* Find and check range structure, attempt cached range pointer first
1604 */
1605 if (NULL != lho->rpc) {
1606 if ((lho->rpc->start <= c32) && (c32 <= lho->rpc->end)) {
1607 rptr = lho->rpc;
1608 }
1609 }
1610 if (NULL == rptr) {
1611 rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(lho->ulptr->i_ranges,&c32,1);
1612 }
1613 if (NULL == rptr) {
1614 /* ERROR: No range found.
1615 Already reported in pass 1.
1616 */
1617 lho->ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1618 back = DK4_TSP_RES_FATAL;
1619 goto finished;
1620 }
1621 if (0 != dk4str_cmp(lho->file->fn, rptr->file->fn)) {
1622 /* ERROR: Not owned by current file.
1623 Already reported in pass 1.
1624 */
1625
1626 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1627 goto finished;
1628 }
1629
1630 /* Initialize range structure (allocate memory) if not yet done
1631 */
1632 if (0x00 == rptr->ia) {
1633 if (0 == dk4uc2l_i_init_range(rptr, erp)) {
1634
1635 lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY;
1636 back = DK4_TSP_RES_FATAL;
1637 goto finished;
1638 }
1639 rptr->ia = 0x01;
1640 }
1641 else {
1642 }
1643
1644 /* Find index
1645 */
1646 ind = (size_t)(c32 - rptr->start);
1647
1648 /* Check whether character already defined
1649 */
1650 if (NULL != rptr->lno) {
1651 if ((dk4_um_t)0UL != (rptr->lno)[ind]) {
1652 /* ERROR: Redefinition.
1653 Already reported in pass 1.
1654 */
1655
1656 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1657 goto finished;
1658 }
1659 else {
1660 (rptr->lno)[ind] = lineno;
1661 }
1662 }
1663
1664 /* Traverse all strings in line
1665 */
1666 p1 = p2;
1667 while (NULL != p1) {
1668 p2 = dk4str8_next(p1, NULL);
1669 p3 = dk4str8_chr(p1, '=');
1670 if (NULL != p3) {
1671 *(p3++) = '\0';
1672 p3 = dk4str8_start(p3, NULL);
1673 if (NULL != p3) {
1674
1675 res = dk4uc2l_i_keyword_index(p1);
1676 switch (res) {
1677 case 0 : {
1678 if (NULL != rptr->both) {
1679 if (NULL == (rptr->both)[ind]) {
1680 (rptr->both)[ind] = dk4str8_dup(p3, erp);
1681 if (NULL == (rptr->both)[ind]) {
1682
1683 lho->ulptr->had_error |=
1684 DK4_UC2L_ERROR_MEMORY;
1685 }
1686 }
1687 else {
1688 /* ERROR: Already defined.
1689 Bug: Should not happen.
1690 */
1691 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1692 }
1693 }
1694 else {
1695 /* ERROR: Memory.
1696 Already reported during range initialization.
1697 */
1698 lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY;
1699 }
1700 } break;
1701 case 1 : {
1702 if (NULL != rptr->text) {
1703 if (NULL == (rptr->text)[ind]) {
1704 (rptr->text)[ind] = dk4str8_dup(p3, erp);
1705 if (NULL == (rptr->text)[ind]) {
1706
1707 lho->ulptr->had_error |=
1708 DK4_UC2L_ERROR_MEMORY;
1709 }
1710 }
1711 else {
1712 /* ERROR: Already defined.
1713 Bug: Should not happen.
1714 */
1715 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1716 }
1717 }
1718 else {
1719 /* ERROR: Memory
1720 Already reported during range initialization.
1721 */
1722 lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY;
1723 }
1724 } break;
1725 case 2 : {
1726 if (NULL != rptr->math) {
1727 if (NULL == (rptr->math)[ind]) {
1728 (rptr->math)[ind] = dk4str8_dup(p3, erp);
1729 if (NULL == (rptr->math)[ind]) {
1730
1731 lho->ulptr->had_error |=
1732 DK4_UC2L_ERROR_MEMORY;
1733 }
1734 }
1735 else {
1736 /* ERROR: Already defined.
1737 Bug: Should not happen.
1738 */
1739 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1740 }
1741 }
1742 else {
1743 /* ERROR: Memory.
1744 Already reported during range initialization.
1745 */
1746 lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY;
1747 }
1748 } break;
1749 case 3 : {
1750 if (NULL != rptr->fenc) {
1751 adding = 1;
1752 feval = 0x00;
1753 if ('!' == *p3) {
1754 adding = 0;
1755 p3++;
1756 feval = DK4_UC2L_FONT_ENCODING_ALL;
1757 }
1758 while (NULL != p3) {
1759 p4 = dk4str8_chr(p3, ',');
1760 if (NULL != p4) {
1761 *(p4++) = '\0';
1762 }
1763 fex = dk4uc2l_font_encoding_from_name(p3);
1764 if (0x00 != fex) {
1765 if (0 != adding) {
1766 feval |= fex;
1767 }
1768 else {
1769 feval = (unsigned char)(feval & (~(fex)));
1770 }
1771 }
1772 else {
1773 /* ERROR: Illegal encoding name */
1774 dk4error_set_simple_error_code(
1775 erp, DK4_E_SYNTAX
1776 );
1777 lho->ulptr->had_error |=
1778 DK4_UC2L_ERROR_SYNTAX;
1779 }
1780 p3 = p4;
1781 }
1782 (rptr->fenc)[ind] = feval;
1783 }
1784 else {
1785 /* ERROR: Memory.
1786 Already reported during range initialization.
1787 */
1788 lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY;
1789 }
1790 } break;
1791 case 4 : {
1792 if (NULL != rptr->pkgs) {
1793 if (NULL == (rptr->pkgs)[ind]) {
1794 dk4error_init(&er);
1795 numpkg = dk4str8_tokenize(
1796 pkgn, 16, p3, ",", &er
1797 );
1798 if (0 < numpkg) {
1799 (rptr->pkgs)[ind] =
1800 dk4mem_new(dk4_uc2l_pkg_p,(numpkg+1),erp);
1801 if (NULL != (rptr->pkgs)[ind]) {
1802 for (i = 0; i <= numpkg; i++) {
1803 ((rptr->pkgs)[ind])[i] = NULL;
1804 }
1805 for (i = 0; i < numpkg; i++) {
1806 pptr =
1807 (dk4_uc2l_pkg_t *)dk4sto_it_find_like(
1808 lho->ulptr->i_pkgs, pkgn[i], 1
1809 );
1810 if (NULL != pptr) {
1811 ((rptr->pkgs)[ind])[i] = pptr;
1812 }
1813 else {
1814 pptr = dk4uc2l_i_create_pkg(
1815 lho->ulptr->s_pkgs, pkgn[i]
1816 );
1817 if (NULL != pptr) {
1818 ((rptr->pkgs)[ind])[i] =
1819 pptr;
1820 }
1821 else {
1822 dk4error_set_simple_error_code(
1823 erp,
1824 DK4_E_MEMORY_ALLOCATION_FAILED
1825 );
1826 lho->ulptr->had_error |=
1827 DK4_UC2L_ERROR_MEMORY;
1828 }
1829 }
1830 }
1831 }
1832 else {
1833 dk4error_set_simple_error_code(
1834 erp,
1835 DK4_E_MEMORY_ALLOCATION_FAILED
1836 );
1837 lho->ulptr->had_error |=
1838 DK4_UC2L_ERROR_MEMORY;
1839 }
1840 }
1841 else {
1842 /* ERROR: Syntax, empty list */
1843 dk4error_set_simple_error_code(
1844 erp, DK4_E_SYNTAX
1845 );
1846 lho->ulptr->had_error |=
1847 DK4_UC2L_ERROR_SYNTAX;
1848 }
1849 }
1850 else {
1851 /* ERROR: Already defined.
1852 Bug: Should not happen.
1853 */
1854 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1855 }
1856 }
1857 else {
1858 /* ERROR: Memory.
1859 Already reported during range initalization.
1860 */
1861 lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY;
1862 }
1863 } break;
1864 default : {
1865 /* ERROR: Illegal key name */
1866 dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
1867 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1868 } break;
1869 }
1870 p1 = p2;
1871 }
1872 else {
1873 /* ERROR: Syntax, not a key=value */
1874 dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
1875 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1876 p1 = NULL;
1877 }
1878 }
1879 else {
1880 /* ERROR: Syntax, not a key=value */
1881 dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
1882 lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX;
1883 p1 = NULL;
1884 }
1885 }
1886
1887 finished:
1888
1889 return back;
1890 }
1891
1892
1893
1894 /** Load data file.
1895 @param ulptr Conversion structure.
1896 @param fptr File structure to load.
1897 @param erp Error report, may be NULL.
1898 */
1899 static
1900 void
dk4uc2l_load_data_file(dk4_uc2l_t * ulptr,dk4_uc2l_file_t * fptr,dk4_er_t * erp)1901 dk4uc2l_load_data_file(
1902 dk4_uc2l_t *ulptr,
1903 dk4_uc2l_file_t *fptr,
1904 dk4_er_t *erp
1905 )
1906 {
1907 dkChar fnb[DK4_MAX_PATH];
1908 char lnb[256];
1909 handler_object_t ho;
1910 dk4_tsp08_t tsp08;
1911 dk4_stream_t *rstrm = NULL;
1912 size_t fnbsz = DK4_SIZEOF(fnb,dkChar);
1913 size_t szlnb = sizeof(lnb);
1914 int res;
1915 int cc;
1916 char c;
1917
1918
1919
1920 /* Initialize handler object
1921 */
1922 ho.ulptr = ulptr;
1923 ho.s_ra = NULL;
1924 ho.i_ra = NULL;
1925 ho.file = fptr;
1926 ho.rpc = NULL;
1927
1928 /* Save source file name and line number
1929 */
1930
1931 /* Each file should be loaded only once
1932 */
1933 if (0x00 != fptr->loaded) {
1934 goto finished;
1935 }
1936 fptr->loaded = 0x01;
1937
1938 /* Construct full path name
1939 */
1940 if (0 == dk4str_cpy_s(fnb, fnbsz, ulptr->dname, erp)) {
1941 /* ERROR: Directory name too long */
1942 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1943 goto finished;
1944 }
1945 if (0 == dk4str_cat_s(fnb, fnbsz, dk4uc2l_kwnl[3], erp)) {
1946 /* ERROR: Directory name too long */
1947 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1948 goto finished;
1949 }
1950 if (0 == dk4str_cat_s(fnb, fnbsz, fptr->fn, erp)) {
1951 /* ERROR: Directory name too long */
1952 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1953 goto finished;
1954 }
1955 dk4path_correct_sep(fnb);
1956
1957 /* Open reader stream
1958 */
1959 rstrm = dk4stream_open_file_reader(fnb, erp);
1960 if (NULL == rstrm) {
1961 /* ERROR: Failed to read file */
1962 ulptr->had_error |= DK4_UC2L_ERROR_FOPEN;
1963 goto finished;
1964 }
1965
1966 /* Initialize text processing
1967 */
1968 res = dk4tsp08_setup_line(
1969 &tsp08, (void *)(&ho), dk4uc2l_handler_pass2, lnb, szlnb,
1970 DK4_ENCODING_PLAIN, DK4_ENCODING_PLAIN, erp
1971 );
1972 if (0 == res) {
1973 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1974 /* ERROR: Memory */
1975 goto finished;
1976 }
1977
1978 /* Process contents
1979 */
1980 do {
1981 cc = 0;
1982 res = dk4stream_c8_read_byte(&c, rstrm, erp);
1983 if (0 < res) {
1984 cc = 1;
1985 res = dk4tsp08_add_one_byte(&tsp08, (unsigned char)c);
1986 switch (res) {
1987 case DK4_TSP_RES_ERROR : {
1988 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1989 } break;
1990 case DK4_TSP_RES_FATAL : {
1991 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
1992 goto finished;
1993 } break;
1994 }
1995 }
1996 } while (0 < cc);
1997
1998 /* Finish text processing
1999 */
2000 res = dk4tsp08_finish(&tsp08);
2001 switch (res) {
2002 case DK4_TSP_RES_ERROR: case DK4_TSP_RES_FATAL: {
2003 ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING;
2004 } break;
2005 }
2006
2007 /* Clean up
2008 */
2009 finished:
2010 if (NULL != rstrm) {
2011 dk4stream_close(rstrm, NULL);
2012 }
2013
2014 }
2015
2016
2017
2018 const char *
dk4uc2l_find(dk4_uc2l_t * ulptr,dk4_c32_t c,int mm,dk4_er_t * erp)2019 dk4uc2l_find(dk4_uc2l_t *ulptr, dk4_c32_t c, int mm, dk4_er_t *erp)
2020 {
2021 dk4_uc2l_range_t *rptr;
2022 dk4_uc2l_pkg_t **pkgpp;
2023 dk4_uc2l_file_t *fptr;
2024 const char *back = NULL;
2025 size_t ind;
2026 size_t blgt;
2027 int res;
2028
2029 #if DK4_USE_ASSERT
2030 assert(NULL != ulptr);
2031 #endif
2032 /* Check ulptr usability
2033 */
2034 if (NULL == ulptr) {
2035 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2036 goto finished;
2037 }
2038
2039 /* Attempt direct output
2040 */
2041 if (0 != dk4uc2lat_direct(c)) {
2042 ulptr->buf[0] = (char)c;
2043 ulptr->buf[1] = '\0';
2044 back = &(ulptr->buf[0]);
2045 goto finished;
2046 }
2047
2048 /* Attempt data loaded from files
2049 */
2050 rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(ulptr->i_ranges, &c, 1);
2051 if (NULL != rptr) {
2052 fptr = rptr->file;
2053 if (0x00 == fptr->loaded) {
2054 dk4uc2l_load_data_file(ulptr, fptr, erp);
2055 }
2056 ind = (size_t)(c - rptr->start);
2057 if (0 != mm) {
2058 if (NULL != rptr->math) {
2059 back = (rptr->math)[ind];
2060 }
2061 }
2062 else {
2063 if (NULL != rptr->text) {
2064 back = (rptr->text)[ind];
2065 }
2066 }
2067 if (NULL == back) {
2068 if (NULL != rptr->both) {
2069 back = (rptr->both)[ind];
2070 }
2071 }
2072 if (NULL != back) {
2073 if (NULL != rptr->pkgs) {
2074 pkgpp = (rptr->pkgs)[ind];
2075 if (NULL != pkgpp) {
2076 while (NULL != *pkgpp) {
2077 (*(pkgpp++))->used = 0x01;
2078 }
2079 }
2080 }
2081 if (NULL != rptr->fenc) {
2082 ulptr->fallowed &= (rptr->fenc)[ind];
2083 }
2084 goto finished;
2085 }
2086 }
2087
2088 /* Attempt to use UTF-8 encoded data or ASCII data directly
2089 */
2090
2091 if (0 == mm) {
2092 if (0x00 != ulptr->utf8allowed) {
2093 blgt = 15;
2094 res = dk4utf8_encode(
2095 (unsigned char *)(&(ulptr->buf[0])), &blgt, c, erp
2096 );
2097 if (0 != res) {
2098 ulptr->buf[blgt] = '\0';
2099 back = &(ulptr->buf[0]);
2100 }
2101 }
2102 else {
2103 if (dkC32(0x00000100) > c) {
2104 ulptr->buf[0] = (char)c;
2105 ulptr->buf[1] = '\0';
2106 back = &(ulptr->buf[0]);
2107 }
2108 }
2109 }
2110
2111 finished:
2112
2113
2114
2115
2116 return back;
2117 }
2118
2119
2120
2121 static
2122 int
dk4uc2l_i_encoding(unsigned char enclist,unsigned char oneenc)2123 dk4uc2l_i_encoding(
2124 unsigned char enclist,
2125 unsigned char oneenc
2126 )
2127 {
2128 int back = 0;
2129 if (0x00 != (enclist & ((unsigned char)oneenc))) {
2130 back = 1;
2131 }
2132 return back;
2133 }
2134
2135
2136
2137 void
dk4uc2l_recommendations(dk4_uc2l_t * ulptr,dk4_stream_t * wstrm,dk4_er_t * erp)2138 dk4uc2l_recommendations(dk4_uc2l_t *ulptr, dk4_stream_t *wstrm, dk4_er_t *erp)
2139 {
2140 dk4_uc2l_pkg_t *pptr;
2141
2142 #if DK4_USE_ASSERT
2143 assert(NULL != wstrm);
2144 assert(NULL != ulptr);
2145 #endif
2146 if ((NULL != ulptr) && (NULL != wstrm)) {
2147 dk4stream_write_char_string(
2148 wstrm, dk4uc2l_kw8[0], erp
2149 );
2150 if (dk4uc2l_i_encoding(ulptr->fallowed,DK4_UC2L_FONT_ENCODING_T1)) {
2151 dk4stream_write_char_string(
2152 wstrm, dk4uc2l_kw8[3], erp
2153 );
2154 }
2155 if (dk4uc2l_i_encoding(ulptr->fallowed,DK4_UC2L_FONT_ENCODING_OT1)) {
2156 dk4stream_write_char_string(
2157 wstrm, dk4uc2l_kw8[2], erp
2158 );
2159 }
2160 if (dk4uc2l_i_encoding(ulptr->fallowed,DK4_UC2L_FONT_ENCODING_T4)) {
2161 dk4stream_write_char_string(
2162 wstrm, dk4uc2l_kw8[4], erp
2163 );
2164 }
2165 if (dk4uc2l_i_encoding(ulptr->fallowed,DK4_UC2L_FONT_ENCODING_T5)) {
2166 dk4stream_write_char_string(
2167 wstrm, dk4uc2l_kw8[5], erp
2168 );
2169 }
2170 dk4stream_write_byte(wstrm, '\n', erp);
2171 dk4sto_it_reset(ulptr->i_pkgs);
2172 do {
2173 pptr = (dk4_uc2l_pkg_t *)dk4sto_it_next(ulptr->i_pkgs);
2174 if (NULL != pptr) {
2175 if (0x00 != pptr->used) {
2176 dk4stream_write_char_string(
2177 wstrm, dk4uc2l_kw8[1], erp
2178 );
2179 dk4stream_write_char_string(
2180 wstrm, pptr->pn, erp
2181 );
2182 dk4stream_write_byte(wstrm, '\n', erp);
2183 }
2184 }
2185 } while (NULL != pptr);
2186 }
2187
2188 }
2189
2190
2191
2192 int
dk4uc2l_retrieve_errors(dk4_uc2l_t * ulptr)2193 dk4uc2l_retrieve_errors(dk4_uc2l_t *ulptr)
2194 {
2195 int back = 0;
2196
2197 #if DK4_USE_ASSERT
2198 assert(NULL != ulptr);
2199 #endif
2200 if (NULL != ulptr) {
2201 back = ulptr->had_error;
2202 }
2203
2204 return back;
2205 }
2206
2207
2208
2209 void
dk4uc2l_reset_errors(dk4_uc2l_t * ulptr)2210 dk4uc2l_reset_errors(dk4_uc2l_t *ulptr)
2211 {
2212 #if DK4_USE_ASSERT
2213 assert(NULL != ulptr);
2214 #endif
2215 if (NULL != ulptr) {
2216 ulptr->had_error = 0;
2217 }
2218 }
2219
2220
2221
2222 /* ##### untested */
2223 static
2224 void
dk4uc2l_putc32(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,dk4_c32_t c32,int * pmm,int * pback,dk4_er_t * erp)2225 dk4uc2l_putc32(
2226 dk4_stream_t *wstrm,
2227 dk4_uc2l_t *ulptr,
2228 dk4_c32_t c32,
2229 int *pmm,
2230 int *pback,
2231 dk4_er_t *erp
2232 )
2233 {
2234 dk4_er_t er;
2235 const char *le = NULL;
2236
2237 #if DK4_USE_ASSERT
2238 assert(NULL != wstrm);
2239 assert(NULL != ulptr);
2240 #endif
2241 dk4error_init(&er);
2242 le = dk4uc2l_find(ulptr, c32, 0, &er);
2243 if (NULL != le) {
2244 if (0 != *pmm) {
2245 if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) {
2246 *pback = 0;
2247 }
2248 *pmm = 0;
2249 }
2250 if (0 == dk4stream_write_char_string(wstrm, le, erp)) {
2251 *pback = 0;
2252 }
2253 }
2254 else {
2255 le = dk4uc2l_find(ulptr, c32, 1, &er);
2256 if (NULL != le) {
2257 if (0 == *pmm) {
2258 if (0 == dk4stream_write_char_string(wstrm,dk4uc2l_mm[0],erp)) {
2259 *pback = 0;
2260 }
2261 *pmm = 1;
2262 }
2263 if (0 == dk4stream_write_char_string(wstrm, le, erp)) {
2264 *pback = 0;
2265 }
2266 }
2267 else {
2268 *pback = 0;
2269 dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
2270 }
2271 }
2272
2273 }
2274
2275
2276
2277 /* ##### untested */
2278 int
dk4uc2l_string_c32(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,const dk4_c32_t * str,dk4_er_t * erp)2279 dk4uc2l_string_c32(
2280 dk4_stream_t *wstrm,
2281 dk4_uc2l_t *ulptr,
2282 const dk4_c32_t *str,
2283 dk4_er_t *erp
2284 )
2285 {
2286 int back = 0;
2287 int mm = 0;
2288
2289
2290 #if DK4_USE_ASSERT
2291 assert(NULL != wstrm);
2292 assert(NULL != ulptr);
2293 assert(NULL != str);
2294 #endif
2295 /* Check arguments
2296 */
2297 if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) {
2298 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2299 goto finished;
2300 }
2301
2302 /* Process all characters from string
2303 */
2304 back = 1;
2305 while (dkC32(0) != *str) {
2306 dk4uc2l_putc32(wstrm, ulptr, *(str++), &mm, &back, erp);
2307 }
2308
2309 /* Finalize math mode if necessary
2310 */
2311 if (0 != mm) {
2312 if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) {
2313 back = 0;
2314 }
2315 }
2316
2317 finished:
2318
2319 return back;
2320 }
2321
2322
2323
2324 /* ##### untested */
2325 int
dk4uc2l_string_c16(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,const dk4_c16_t * str,dk4_er_t * erp)2326 dk4uc2l_string_c16(
2327 dk4_stream_t *wstrm,
2328 dk4_uc2l_t *ulptr,
2329 const dk4_c16_t *str,
2330 dk4_er_t *erp
2331 )
2332 {
2333 dk4_utf16_decoder_t dec;
2334 dk4_c32_t c32;
2335 int mm = 0;
2336 int back = 0;
2337 int err = 0;
2338
2339 #if DK4_USE_ASSERT
2340 assert(NULL != wstrm);
2341 assert(NULL != ulptr);
2342 assert(NULL != str);
2343 #endif
2344 /* Check arguments
2345 */
2346 if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) {
2347 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2348 goto finished;
2349 }
2350
2351 back = 1;
2352 dk4utf16_init(&dec);
2353 while ((dkC16(0) != *str) && (0 == err)) {
2354 switch (dk4utf16_add(&dec, *(str++))) {
2355 case DK4_EDSTM_FINISHED : {
2356 c32 = dk4utf16_get(&dec);
2357 dk4utf16_init(&dec);
2358 dk4uc2l_putc32(wstrm, ulptr, c32, &mm, &back, erp);
2359
2360 } break;
2361 case DK4_EDSTM_ERROR : {
2362 err = 1;
2363 dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED);
2364 back = 0;
2365 } break;
2366 }
2367 }
2368 if (0 == err) {
2369 if (0 == dk4utf16_is_empty(&dec)) {
2370 dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED);
2371 back = 0;
2372 }
2373 }
2374 if (0 != mm) {
2375 if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) {
2376 back = 0;
2377 }
2378 }
2379
2380 finished:
2381
2382 return back;
2383 }
2384
2385
2386
2387 /* ##### untested */
2388 int
dk4uc2l_string_utf8(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,const char * str,dk4_er_t * erp)2389 dk4uc2l_string_utf8(
2390 dk4_stream_t *wstrm,
2391 dk4_uc2l_t *ulptr,
2392 const char *str,
2393 dk4_er_t *erp
2394 )
2395 {
2396 dk4_utf8_decoder_t dec;
2397 dk4_c32_t c32;
2398 int back = 0;
2399 int mm = 0;
2400 int err = 0;
2401
2402 #if DK4_USE_ASSERT
2403 assert(NULL != wstrm);
2404 assert(NULL != ulptr);
2405 assert(NULL != str);
2406 #endif
2407 if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) {
2408 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2409 goto finished;
2410 }
2411
2412 back = 1;
2413 dk4utf8_init(&dec);
2414 while(('\0' != *str) && (0 == err)) {
2415 switch (dk4utf8_add(&dec, (unsigned char)(*(str++)))) {
2416 case DK4_EDSTM_FINISHED : {
2417 c32 = dk4utf8_get(&dec);
2418 dk4utf8_init(&dec);
2419 dk4uc2l_putc32(wstrm, ulptr, c32, &mm, &back, erp);
2420 } break;
2421 case DK4_EDSTM_ERROR : {
2422 err = 1;
2423 dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED);
2424 back = 0;
2425 } break;
2426 }
2427 }
2428 if (0 == err) {
2429 if (0 == dk4utf8_is_empty(&dec)) {
2430 dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED);
2431 back = 0;
2432 }
2433 }
2434 if (0 != mm) {
2435 if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) {
2436 back = 0;
2437 }
2438 }
2439
2440 finished:
2441
2442 return back;
2443 }
2444
2445
2446
2447 /* ##### untested */
2448 int
dk4uc2l_string_ansi(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,const char * str,dk4_er_t * erp)2449 dk4uc2l_string_ansi(
2450 dk4_stream_t *wstrm,
2451 dk4_uc2l_t *ulptr,
2452 const char *str,
2453 dk4_er_t *erp
2454 )
2455 {
2456 dk4_c32_t c32;
2457 int back = 0;
2458 int mm = 0;
2459
2460 #if DK4_USE_ASSERT
2461 assert(NULL != wstrm);
2462 assert(NULL != ulptr);
2463 assert(NULL != str);
2464 #endif
2465 if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) {
2466 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2467 goto finished;
2468 }
2469 back = 1;
2470 while ('\0' != *str) {
2471 if (0 != dk4ansi_decode(&c32, (unsigned char)(*(str++)))) {
2472 dk4uc2l_putc32(wstrm, ulptr, c32, &mm, &back, erp);
2473 }
2474 else {
2475 dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED);
2476 back = 0;
2477 }
2478 }
2479 if (0 != mm) {
2480 if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) {
2481 back = 0;
2482 }
2483 }
2484
2485 finished:
2486
2487 return back;
2488 }
2489
2490
2491
2492 /* ##### untested */
2493 int
dk4uc2l_string_ascii(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,const char * str,dk4_er_t * erp)2494 dk4uc2l_string_ascii(
2495 dk4_stream_t *wstrm,
2496 dk4_uc2l_t *ulptr,
2497 const char *str,
2498 dk4_er_t *erp
2499 )
2500 {
2501 dk4_c32_t c32;
2502 int back = 0;
2503 int mm = 0;
2504
2505 #if DK4_USE_ASSERT
2506 assert(NULL != wstrm);
2507 assert(NULL != ulptr);
2508 assert(NULL != str);
2509 #endif
2510 if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) {
2511 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2512 goto finished;
2513 }
2514
2515 back = 1;
2516 while ('\0' != *str) {
2517 c32 = (dk4_c32_t)((unsigned char)(*(str++)));
2518 dk4uc2l_putc32(wstrm, ulptr, c32, &mm, &back, erp);
2519 }
2520 if (0 != mm) {
2521 if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) {
2522 back = 0;
2523 }
2524 }
2525
2526 finished:
2527
2528 return back;
2529 }
2530
2531
2532
2533 /* ##### untested */
2534 int
dk4uc2l_string_c8(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,const char * str,int ie,dk4_er_t * erp)2535 dk4uc2l_string_c8(
2536 dk4_stream_t *wstrm,
2537 dk4_uc2l_t *ulptr,
2538 const char *str,
2539 int ie,
2540 dk4_er_t *erp
2541 )
2542 {
2543 #if DK4_USE_ASSERT
2544 assert(NULL != wstrm);
2545 assert(NULL != ulptr);
2546 assert(NULL != str);
2547 #endif
2548 switch (ie) {
2549 case DK4_ENCODING_UTF8 : {
2550 return (dk4uc2l_string_utf8(wstrm, ulptr, str, erp));
2551 } break;
2552 case DK4_ENCODING_WIN1252 : {
2553 return (dk4uc2l_string_ansi(wstrm, ulptr, str, erp));
2554 } break;
2555 default : {
2556 return (dk4uc2l_string_ascii(wstrm, ulptr, str, erp));
2557 } break;
2558 }
2559 }
2560
2561
2562
2563 /* ##### untested */
2564 int
dk4uc2l_string_dk(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,const dkChar * str,int ie,dk4_er_t * erp)2565 dk4uc2l_string_dk(
2566 dk4_stream_t *wstrm,
2567 dk4_uc2l_t *ulptr,
2568 const dkChar *str,
2569 #if 1 == DK4_CHAR_SIZE
2570 int ie,
2571 #else
2572 int DK4_ARG_UNUSED(ie),
2573 #endif
2574 dk4_er_t *erp
2575 )
2576 {
2577 #if DK4_CHAR_SIZE > 1
2578 DK4_UNUSED_ARG(ie)
2579 #endif
2580 #if DK4_USE_ASSERT
2581 assert(NULL != wstrm);
2582 assert(NULL != ulptr);
2583 assert(NULL != str);
2584 #endif
2585 #if DK4_CHAR_SIZE > 1
2586 #if DK4_CHAR_SIZE > 2
2587
2588 return (dk4uc2l_string_c32(wstrm, ulptr, str, erp));
2589 #else
2590
2591 return (dk4uc2l_string_c16(wstrm, ulptr, str, erp));
2592 #endif
2593 #else
2594
2595 return (dk4uc2l_string_c8(wstrm, ulptr, str, ie, erp));
2596 #endif
2597 }
2598
2599
2600
2601 int
dk4uc2l_string_encoded(dk4_stream_t * wstrm,dk4_uc2l_t * ulptr,const void * str,int ie,dk4_er_t * erp)2602 dk4uc2l_string_encoded(
2603 dk4_stream_t *wstrm,
2604 dk4_uc2l_t *ulptr,
2605 const void *str,
2606 int ie,
2607 dk4_er_t *erp
2608 )
2609 {
2610 int back = 0;
2611 #if DK4_CHAR_SIZE > 1
2612 DK4_UNUSED_ARG(ie)
2613 #endif
2614 #if DK4_USE_ASSERT
2615 assert(NULL != wstrm);
2616 assert(NULL != ulptr);
2617 assert(NULL != str);
2618 #endif
2619 switch (ie) {
2620 case DK4_ENCODING_32 : {
2621 back = dk4uc2l_string_c32(wstrm, ulptr, str, erp);
2622 } break;
2623 case DK4_ENCODING_UTF16 : {
2624 back = dk4uc2l_string_c16(wstrm, ulptr, str, erp);
2625 } break;
2626 default : {
2627 back = dk4uc2l_string_c8(wstrm, ulptr, str, ie, erp);
2628 } break;
2629 }
2630 return back;
2631 }
2632
2633
2634 /* vim: set ai sw=4 ts=4 : */
2635
2636