%% options copyright owner = Dirk Krause copyright year = 2015-xxxx SPDX-License-Identifier: BSD-3-Clause %% header /** @file dk4uc2l.h Text to LaTeX conversion. LaTeX sequences to represent a 32 bit character are found in lookup tables in the ${datarootdir}/dktools/charmap directory. The functions in this module read those lookup tables needed, cache the contents and provide LaTeX sequences. After finishing output you can write recommendations (i.e. LaTeX packages to include, font encoding to use) as comments to the file. The functions in this module use a dk4_er_t structure to report errors to the calling function as good as possible. The functions from the dk4uc2la module use a dk4_app_t structure to report errors immediately. Functions from the dk4uc2la and dk4uc2l module can be used combined. A typical scenario is to use the dk4uc2l_open_app_ex1() function with la set to 1 to open a conversion structure. This will read all the data files and store all contained LaTeX encodings in memory when opening the structure. Errors - i.e. failed memory allocations or syntax error in data files - are reported immediately. Later the dk4uc2l_find() function can be used. As problematic errors like failed memory allocations are already reported, a NULL return value can only indicate a missing encoding. */ #ifndef DK4CONF_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4conf.h" #else #include #endif #endif #ifndef DK4ERROR_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4error.h" #else #include #endif #endif #ifndef DK4STO_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4sto.h" #else #include #endif #endif #ifndef DK4STRM_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4strm.h" #else #include #endif #endif /** Information about a package. */ typedef struct { char *pn; /**< Package name. */ unsigned char used; /**< Flag: Package used. */ } dk4_uc2l_pkg_t; /** Pointer to a package or an array of packages. */ typedef dk4_uc2l_pkg_t *dk4_uc2l_pkg_p; /** Pointer to an array of package pointers. */ typedef dk4_uc2l_pkg_p *dk4_uc2l_pkg_pp; /** Data for contents of one file. The structure contains information about the character ranges covered by the file. */ typedef struct { dkChar *fn; /**< Short file name. */ unsigned char loaded; /**< Flag: File loaded. */ } dk4_uc2l_file_t; /** Range of characters. */ typedef struct { dk4_uc2l_file_t *file; /**< File containing data. */ char **both; /**< LaTeX text both modes. */ char **text; /**< LaTeX text text mode. */ char **math; /**< LaTeX text math mode. */ dk4_uc2l_pkg_t ***pkgs; /**< Packages for characters. */ unsigned char *fenc; /**< Required font encodings. */ dk4_um_t *lno; /**< Line numbers. */ dk4_c32_t start; /**< First character of range. */ dk4_c32_t end; /**< Final character of range. */ unsigned char ia; /**< Flag: Initialisation att. */ } dk4_uc2l_range_t; /** Text to LaTeX conversion structure. */ typedef struct { char buf[16]; /**< Buffer for direct output. */ dkChar *dname; /**< Directory name. */ dk4_sto_t *s_ranges; /**< Ranges container. */ dk4_sto_it_t *i_ranges; /**< Ranges container iterator. */ dk4_sto_t *s_files; /**< Files container. */ dk4_sto_it_t *i_files; /**< Files container iterator. */ dk4_sto_t *s_pkgs; /**< Package information container. */ dk4_sto_it_t *i_pkgs; /**< Package information iterator. */ int had_error; /**< Flag: Errors occured. */ unsigned char utf8allowed; /**< Flag: UTF-8 output allowed. */ unsigned char fallowed; /**< Allowed font encodings. */ } dk4_uc2l_t; /** Font encodings */ enum { /** OT1 font encoding. */ DK4_UC2L_FONT_ENCODING_OT1 = 1 , /** T1 font encoding. */ DK4_UC2L_FONT_ENCODING_T1 = 2 , /** T4 font encoding. */ DK4_UC2L_FONT_ENCODING_T4 = 4 , /** T5 font encoding. */ DK4_UC2L_FONT_ENCODING_T5 = 8 , /** All encodings mentioned above. */ DK4_UC2L_FONT_ENCODING_ALL = ( 0 | DK4_UC2L_FONT_ENCODING_OT1 | DK4_UC2L_FONT_ENCODING_T1 | DK4_UC2L_FONT_ENCODING_T4 | DK4_UC2L_FONT_ENCODING_T5 ) }; /** Errors from this module */ enum { /** Memory allocation failed. */ DK4_UC2L_ERROR_MEMORY = 1 , /** Syntax error in configuration file. */ DK4_UC2L_ERROR_SYNTAX = 2 , /** Decoding error in configuration file. */ DK4_UC2L_ERROR_DECODING = 4 , /** Other processing errors while reading data. */ DK4_UC2L_ERROR_PROCESSING = 8 , /** Failed to open one of the data files. */ DK4_UC2L_ERROR_FOPEN = 16 , }; #ifdef __cplusplus extern "C" { #endif /** Open conversion structure. @param dn Directory containing the data files. @param erp Error report, may be NULL. @return Valid pointer on success, NULL on error. */ dk4_uc2l_t * dk4uc2l_open(const dkChar *dn, dk4_er_t *erp); /** Close conversion structure, release memory. @param ulptr Conversion structure to close. */ void dk4uc2l_close(dk4_uc2l_t *ulptr); /** Find LaTeX encoding for one 32 bit character. @param ulptr Conversion structure. @param c Character to search encoding for. @param mm Flag: Math mode (1) or text mode (0). @param erp Error report, may be NULL. @return Pointer to encoding string on success, NULL on error. */ const char * dk4uc2l_find(dk4_uc2l_t *ulptr, dk4_c32_t c, int mm, dk4_er_t *erp); /** Enable or disable direct UTF-8 output. If you use usepackage[utf-8]{inputenc} you might want to enable UTF-8 output. @param ulptr Conversion structure to set up. @param enabled Flag: Enable UTF-8 output. */ void dk4uc2l_allow_utf8(dk4_uc2l_t *ulptr, int enabled); /** Reset information about used packages and allowed and denied font encodings. Typically you want to use this function only after finishing one output file and starting a new one. @param ulptr Conversion structure to reset. */ void dk4uc2l_clean_packages_and_fonts(dk4_uc2l_t *ulptr); /** Retrieve or-combination of all allowed font encodings. You should use this function after processing all characters. */ unsigned char dk4uc2l_retrieve_allowed_fe(dk4_uc2l_t *ulptr); /** Check whether a character can be written to a LaTeX file directly. @param c32 Character to check. @return 1 for yes, 0 for no. */ int dk4uc2lat_direct(dk4_c32_t c32); /** Issue recommendations about font encodings and packages. Use this function after processing all characters. @param ulptr Conversion structure. @param wstrm Destination stream to write to. @param erp Error report, may be NULL. */ void dk4uc2l_recommendations(dk4_uc2l_t *ulptr, dk4_stream_t *wstrm, dk4_er_t *erp); /** Retrieve internal error status from conversion structure. @param ulptr Conversion structure. @return Error status, 0 or combination of DK4_UC2L_ERROR_MEMORY, DK4_UC2L_ERROR_SYNTAX, DK4_UC2L_ERROR_DECODING, DK4_UC2L_ERROR_PROCESSING, and DK4_UC2L_ERROR_FOPEN. */ int dk4uc2l_retrieve_errors(dk4_uc2l_t *ulptr); /** Retrieve internal error status from conversion structure. @param ulptr Conversion structure. @return Error status, 0 or combination of DK4_UC2L_ERROR_MEMORY, DK4_UC2L_ERROR_SYNTAX, DK4_UC2L_ERROR_DECODING, DK4_UC2L_ERROR_PROCESSING, and DK4_UC2L_ERROR_FOPEN. */ void dk4uc2l_reset_errors(dk4_uc2l_t *ulptr); /** Write dkChar string LaTeX encoded to stream. The method is primarily selected by DK4_CHAR_SIZE. Use this function if you want to output a dkChar string. @param wstrm Stream to write to. @param ulptr Conversion structure. @param str String. @param ie Input encoding, only used if dkChar is char. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4uc2l_string_dk( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const dkChar *str, int ie, dk4_er_t *erp ); /** Write encoded string LaTeX encoded to stream. The method is selected by the ie parameter. Use this function if your string is not necessarily a dkChar string but you know the encoding. @param wstrm Stream to write to. @param ulptr Conversion structure. @param str String. @param ie Input encoding, only used if dkChar is char. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4uc2l_string_encoded( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const void *str, int ie, dk4_er_t *erp ); /** Write dk4_c32_t string LaTeX encoded to stream. @param wstrm Stream to write to. @param ulptr Conversion structure. @param str String to write. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4uc2l_string_c32( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const dk4_c32_t *str, dk4_er_t *erp ); /** Write UTF-16 encoded dk_c32_t string LaTeX encoded to stream. @param wstrm Stream to write to. @param ulptr Conversion structure. @param str String to write. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4uc2l_string_c16( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const dk4_c16_t *str, dk4_er_t *erp ); /** Write UTF-8 encoded char string LaTeX encoded to stream. @param wstrm Stream to write to. @param ulptr Conversion structure. @param str String to write. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4uc2l_string_utf8( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const char *str, dk4_er_t *erp ); /** Write ANSI encoded char string LaTeX encoded to stream. @param wstrm Stream to write to. @param ulptr Conversion structure. @param str String to write. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4uc2l_string_ansi( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const char *str, dk4_er_t *erp ); /** Write ASCII encoded char string LaTeX encoded to stream. @param wstrm Stream to write to. @param ulptr Conversion structure. @param str String to write. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4uc2l_string_ascii( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const char *str, dk4_er_t *erp ); /** Write char string LaTeX encoded to stream. @param wstrm Stream to write to. @param ulptr Conversion structure. @param str String to write. @param ie Input encoding. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4uc2l_string_c8( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const char *str, int ie, dk4_er_t *erp ); #ifdef __cplusplus } #endif %% module #include "dk4conf.h" #include #if DK4_HAVE_STRING_H #ifndef STRING_H_INCLUDED #include #define STRING_H_INCLUDED 1 #endif #endif #include "dk4const.h" #include "dk4uc2l.h" #include "dk4inst.h" #include "dk4mem.h" #include "dk4mema.h" #include "dk4str8.h" #include "dk4strd.h" #include "dk4utf16.h" #include "dk4utf8.h" #include "dk4ansi.h" #include "dk4maasz.h" #include "dk4maaul.h" #include "dk4maadu.h" #include "dk4filed.h" #include "dk4mpl.h" #include "dk4strm.h" #include "dk4strmr.h" #include "dk4dir.h" #include "dk4dira.h" #include "dk4pathd.h" #include "dk4tsp08.h" #include "dk4enc.h" #include "dk4mai8hul.h" #include "dk4maodh.h" #include "dk4maodd.h" #include "dk4unused.h" #include "dk4rec26.h" #include "dk4strmo08.h" #ifndef UC2L_H_INCLUDED #include "uc2l.h" #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif $!trace-include #define UL(x) ((unsigned long)(x)) /** Object to use and modify from line handler. */ typedef struct { dk4_uc2l_t *ulptr; /**< Conversion structure. */ dk4_sto_t *s_ra; /**< Local range storage. */ dk4_sto_it_t *i_ra; /**< Local range iterator. */ dk4_uc2l_file_t *file; /**< File structure. */ dk4_uc2l_range_t *rpc; /**< Range pointer cache, pass 2. */ } handler_object_t; /** File name suffixes to process. */ static const dkChar * const dk4uc2l_suffixes[] = { $!string-table macro=dkT .t2l .t2l.gz .t2l.bz2 $!end }; /** Keywords allowed in a data line. */ static const char * const dk4uc2l_keywords[] = { $!string-table # # 0 # b$oth # # 1 # t$ext # # 2 # m$ath # # 3 # e$ncoding # # 4 # p$ackages $!end }; /** Font encoding names. */ static const char * const dk4uc2l_font_encodings[] = { $!string-table ot1 t1 t4 t5 $!end }; /** Subdirectory names. */ static const dkChar * const dk4uc2l_kwnl[] = { $!string-table macro=dkT # # 0 1 2 Subdirectories to search # /dktools/charmap /dk4app/charmap /dk3app/charmap # # 3 File name separator # / # # # $!end }; /** Constant text strings for recommendations. */ static const char * const dk4uc2l_kw8[] = { $!string-table # # 0 Font encodings # % Font encodings: # # 1 Recommended package # % Recommended package: # # 2 3 4 5 Font encoding names # ot1 t1 t4 t5 # # # $!end }; /** Opening and closing tag for math mode. */ static const char * const dk4uc2l_mm[] = { "\\(", "\\)" }; /** Number of elements in dk4uc2l_suffixes array. */ static const size_t sz_suffixes = DK4_SIZEOF(dk4uc2l_suffixes,DK4_PDKCHAR) - 1; /** Compare two LaTeX package structures. @param l Left pointer, always a package structure. @param r Right pointer. @param cr Comparison criteria: 0 if r is a package pointer, 1 if r is just a package name string. @return Comparison result: 1 if l>r, 0 if l==r, -1 if lpn, (const char *)r); } break; default: { pr = (const dk4_uc2l_pkg_t *)r; back = strcmp(pl->pn, pr->pn); } break; } if (-1 > back) back = -1; if ( 1 < back) back = 1; } else { back = 1; } } else { if (NULL != r) { back = -1; } } return back; } /** Compare two file information structures. @param l Left pointer, always a file information structure. @param r Right pointer. @param cr Comparison criteria: 0 if the right pointer is a file information structure pointer, 1 if the right pointer is a file name string. @return Comparison result: 0 if file names are equal, -1 if lr. */ static int dk4uc2l_file_compare(const void *l, const void *r, int cr) { const dk4_uc2l_file_t *pl; const dk4_uc2l_file_t *pr; int back = 0; if (NULL != l) { if (NULL != r) { pl = (const dk4_uc2l_file_t *)l; switch (cr) { case 1: { back = dk4str_pathcmp(pl->fn, (const dkChar *)r); } break; default: { pr = (const dk4_uc2l_file_t *)r; back = dk4str_pathcmp(pl->fn, pr->fn); } break; } if (-1 > back) { back = -1; } if ( 1 < back) { back = 1; } } else { back = 1; } } else { if (NULL != r) { back = -1; } } return back; } /** Compare two range informations or a range information against a character. @param l Left pointer, always a range information structure. @param r Right pointer. @param cr Comparison criteria: 0 if the right pointer is a range information strucutre, 1 if the right pointer is a pointer to a dk4_c32_t. @return Comparison result: -1 if lr. */ int dk4uc2l_i_range_compare(const void *l, const void *r, int cr) { const dk4_uc2l_range_t *pl; const dk4_uc2l_range_t *pr; const dk4_c32_t *pc; int back = 0; if (NULL != l) { if (NULL != r) { pl = (const dk4_uc2l_range_t *)l; switch (cr) { case 1: { pc = (const dk4_c32_t *)r; if (pl->start > *pc) { back = 1; } else { if (pl->end < *pc) { back = -1; } } } break; default: { pr = (const dk4_uc2l_range_t *)r; if (pl->start < pr->start) { back = -1; } else { if (pl->start > pr->start) { back = 1; } } } break; } } else { back = 1; } } else { if (NULL != r) { back = -1; } } return back; } int dk4uc2l_i_suffix_index_supported(int i) { int back = 1; switch (i) { case 1: { #if !DK4_HAVE_ZLIB_H back = 0; #endif } break; case 2: { #if !DK4_HAVE_BZLIB_H back = 0; #endif } break; } return back; } int dk4uc2l_i_find_suffix_index(const dkChar *fn) { size_t sz = 0; size_t i = 0; size_t susz = 0; int back = -1; if (NULL != fn) { sz = dk4str_len(fn); for (i = 0; ((i < sz_suffixes) && (0 > back)); i++) { susz = dk4str_len(dk4uc2l_suffixes[i]); if (sz > susz) { if (0 == dk4str_pathcmp(&(fn[sz - susz]), dk4uc2l_suffixes[i])) { back = (int)i; i = sz_suffixes; } } } } return back; } void dk4uc2l_i_close_file(dk4_uc2l_file_t *fptr) { $? "+ dk4uc2l_i_close_file %d", TR_IPTR(fptr) if (NULL != fptr) { $? ". \"%!ds\"", TR_STR(fptr->fn) dk4mem_release(fptr->fn); fptr->loaded = 0x00; dk4mem_free(fptr); } $? "- dk4uc2l_i_close_file" } dk4_uc2l_file_t * dk4uc2l_i_open_file(const dkChar *fn, dk4_er_t *erp) { dk4_uc2l_file_t *back = NULL; $? "+ dk4uc2l_i_open_file \"%!ds\"", TR_STR(fn) if (NULL != fn) { back = dk4mem_new(dk4_uc2l_file_t,1,erp); if (NULL != back) { back->loaded = 0x00; back->fn = dk4str_dup(fn, erp); if (NULL == back->fn) { $? "! allocation fn" dk4mem_free(back); back = NULL; } } #if TRACE_DEBUG else { $? "! allocation back" } #endif } else { $? "! pn" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4uc2l_i_open_file %d", TR_IPTR(back) return back; } void dk4uc2l_i_close_pkg(dk4_uc2l_pkg_t *pptr) { $? "+ dk4uc2l_i_close_pkg %d", TR_IPTR(pptr) if (NULL != pptr) { $? ". \"%!8s\"", TR_8STR(pptr->pn) dk4mem_release(pptr->pn); pptr->used = 0x00; dk4mem_free(pptr); } $? "- dk4uc2l_i_close_pkg" } dk4_uc2l_pkg_t * dk4uc2l_i_open_pkg(const char *pn, dk4_er_t *erp) { dk4_uc2l_pkg_t *back = NULL; $? "+ dk4_uc2l_pkg_t \"%!8s\"", TR_8STR(pn) if (NULL != pn) { back = dk4mem_new(dk4_uc2l_pkg_t,1,erp); if (NULL != back) { back->used = 0x00; back->pn = dk4str8_dup(pn, erp); if (NULL == back->pn) { dk4mem_free(back); back = NULL; } #if TRACE_DEBUG else { $? "! allocation pn" } #endif } #if TRACE_DEBUG else { $? "! allocation back" } #endif } else { $? "! pn" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4_uc2l_pkg_t %d", TR_IPTR(back) return back; } void dk4uc2l_i_close_range(dk4_uc2l_range_t *rptr) { dk4_er_t er; /* Error report to detect numeric overflow */ unsigned long n; /* Number of elements in range */ size_t nn; /* Size_t version of n */ size_t i; /* Traverse all elements */ $? "+ dk4uc2l_i_close_range %d", TR_IPTR(rptr) if (NULL != rptr) { $? ". range %lu %lu",(unsigned long)(rptr->start),(unsigned long)(rptr->end) #if TRACE_DEBUG if (NULL != rptr->file) { if (NULL != rptr->file->fn) { $? ". \"%!ds\"", rptr->file->fn } } #endif dk4error_init(&er); n = dk4ma_ulong_sub(rptr->end, rptr->start, &er); n = dk4ma_ulong_add(n, 1UL, &er); #if 0 if ((DK4_E_NONE == er.ec) && ((dk4_um_t)n <= (dk4_um_t)(SIZE_MAX))) #endif if ((DK4_E_NONE == er.ec) && (dk4ma_um_isgeq(SIZE_MAX, n))) { nn = (size_t)n; if (NULL != rptr->both) { for (i = 0; i < nn; i++) { dk4mem_release((rptr->both)[i]); } dk4mem_free(rptr->both); rptr->both = NULL; } if (NULL != rptr->text) { for (i = 0; i < nn; i++) { dk4mem_release((rptr->text)[i]); } dk4mem_free(rptr->text); rptr->text = NULL; } if (NULL != rptr->math) { for (i = 0; i < nn; i++) { dk4mem_release((rptr->math)[i]); } dk4mem_free(rptr->math); rptr->math = NULL; } if (NULL != rptr->pkgs) { for (i = 0; i < nn; i++) { dk4mem_release((rptr->pkgs)[i]); } dk4mem_free(rptr->pkgs); rptr->pkgs = NULL; } if (NULL != rptr->fenc) { dk4mem_free(rptr->fenc); rptr->fenc = NULL; } if (NULL != rptr->lno) { dk4mem_free(rptr->lno); rptr->lno = NULL; } } rptr->file = NULL; rptr->start = (dk4_c32_t)0UL; rptr->end = (dk4_c32_t)0UL; rptr->ia = 0x00; dk4mem_free(rptr); } $? "- dk4uc2l_i_close_range" } int dk4uc2l_i_init_range( dk4_uc2l_range_t *rptr, dk4_er_t *erp ) { dk4_er_t er; char **ppchr; dk4_uc2l_pkg_pp *pppkg; unsigned char *puc; dk4_um_t *pum; size_t sznum = 0; size_t i = 0; unsigned long num = 0UL; int back = 0; $? "+ dk4uc2l_i_init_range 0x%lx...0x%lx", UL(rptr->start), UL(rptr->end) /* Avoid second initialization */ if (0x00 != rptr->ia) { $? ". already initialized" back = 1; goto finished; } /* Find number of elements */ dk4error_init(&er); num = dk4ma_ulong_add( dk4ma_ulong_sub( (unsigned long)(rptr->end), (unsigned long)(rptr->start), &er ), 1UL, &er ); if (DK4_E_NONE != er.ec) { $? "! math problem" dk4error_copy(erp, &er); goto finished; } #if 0 if ((dk4_um_t)(SIZE_MAX) >= (dk4_um_t)num) #endif if (0 != dk4ma_um_isgeq(SIZE_MAX, num)) { sznum = (size_t)num; } else { $? "! overflow" dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); goto finished; } /* both */ if (NULL == rptr->both) { rptr->both = dk4mem_new(DK4_PCHAR,sznum,erp); if (NULL != rptr->both) { ppchr = rptr->both; for (i = 0; i < sznum; i++) { *(ppchr++) = NULL; } } else { $? "! both" goto finished; } } /* text */ if (NULL == rptr->text) { rptr->text = dk4mem_new(DK4_PCHAR,sznum,erp); if (NULL != rptr->text) { ppchr = rptr->text; for (i = 0; i < sznum; i++) { *(ppchr++) = NULL; } } else { $? "! text" goto finished; } } /* math */ if (NULL == rptr->math) { rptr->math = dk4mem_new(DK4_PCHAR,sznum,erp); if (NULL != rptr->math) { ppchr = rptr->math; for (i = 0; i < sznum; i++) { *(ppchr++) = NULL; } } else { $? "! math" goto finished; } } /* pkgs */ if (NULL == rptr->pkgs) { rptr->pkgs = dk4mem_new(dk4_uc2l_pkg_pp,sznum,erp); if (NULL != rptr->pkgs) { pppkg = rptr->pkgs; for (i = 0; i < sznum; i++) { *(pppkg++) = NULL; } } else{ $? "! pkgs" goto finished; } } /* fenc */ if (NULL == rptr->fenc) { rptr->fenc = dk4mem_new(unsigned char,sznum,erp); if (NULL != rptr->fenc) { puc = rptr->fenc; for (i = 0; i < sznum; i++) { *(puc++) = 0xFF; } } else { $? "! fenc" goto finished; } } /* lno */ if (NULL == rptr->lno) { rptr->lno = dk4mem_new(dk4_um_t,sznum,erp); if (NULL != rptr->lno) { pum = rptr->lno; for (i = 0; i < sznum; i++) { *(pum++) = (dk4_um_t)0UL; } } else { $? "! lno" goto finished; } } /* Success */ back = 1; /* Return */ finished: $? "- dk4uc2l_i_init_range %d", back return back; } dk4_uc2l_range_t * dk4uc2l_i_open_range( dk4_c32_t c32, dk4_uc2l_file_t *fptr, dk4_er_t *erp ) { dk4_uc2l_range_t *back = NULL; $? "+ dk4uc2l_i_open_range %lu", (unsigned long)c32 if (NULL != fptr) { back = dk4mem_new(dk4_uc2l_range_t,1,erp); if (NULL != back) { back->file = fptr; back->both = NULL; back->text = NULL; back->math = NULL; back->pkgs = NULL; back->fenc = NULL; back->lno = NULL; back->start = back->end = c32; back->ia = 0x00; } #if TRACE_DEBUG else { $? "! allocation back" } #endif } else { $? "! fptr" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4uc2l_i_open_range %d", TR_IPTR(back) return back; } void dk4uc2l_close(dk4_uc2l_t *ulptr) { dk4_uc2l_pkg_t *pptr; dk4_uc2l_file_t *fptr; dk4_uc2l_range_t *rptr; $? "+ dk4uc2l_close %d", TR_IPTR(ulptr) #if DK4_USE_ASSERT assert(NULL != ulptr); #endif if (NULL != ulptr) { dk4mem_release(ulptr->dname); if (NULL != ulptr->s_ranges) { if (NULL != ulptr->i_ranges) { dk4sto_it_reset(ulptr->i_ranges); do { rptr = (dk4_uc2l_range_t *)dk4sto_it_next(ulptr->i_ranges); if (NULL != rptr) { dk4uc2l_i_close_range(rptr); } } while (NULL != rptr); dk4sto_it_close(ulptr->i_ranges); } dk4sto_close(ulptr->s_ranges); } ulptr->s_ranges = NULL; ulptr->i_ranges = NULL; if (NULL != ulptr->s_files) { if (NULL != ulptr->i_files) { dk4sto_it_reset(ulptr->i_files); do { fptr = (dk4_uc2l_file_t *)dk4sto_it_next(ulptr->i_files); if (NULL != fptr) { dk4uc2l_i_close_file(fptr); } } while (NULL != fptr); dk4sto_it_close(ulptr->i_files); } dk4sto_close(ulptr->s_files); } ulptr->s_files = NULL; ulptr->i_files = NULL; if (NULL != ulptr->s_pkgs) { if (NULL != ulptr->i_pkgs) { dk4sto_it_reset(ulptr->i_pkgs); do { pptr = (dk4_uc2l_pkg_t *)dk4sto_it_next(ulptr->i_pkgs); if (NULL != pptr) { dk4uc2l_i_close_pkg(pptr); } } while (NULL != pptr); dk4sto_it_close(ulptr->i_pkgs); } dk4sto_close(ulptr->s_pkgs); } ulptr->s_pkgs = NULL; ulptr->i_pkgs = NULL; dk4mem_free(ulptr); } $? "- dk4uc2l_close" } dk4_uc2l_t * dk4uc2l_i_new(const dkChar *dn, dk4_er_t *erp) { dk4_uc2l_t *back = NULL; int ok = 0; $? "+ dk4uc2l_i_new \"%!ds\"", TR_STR(dn) back = dk4mem_new(dk4_uc2l_t,1,erp); if (NULL != back) { $? ". allocation ok" back->buf[0] = '\0'; back->dname = NULL; back->s_ranges = NULL; back->i_ranges = NULL; back->s_files = NULL; back->i_files = NULL; back->s_pkgs = NULL; back->i_pkgs = NULL; back->had_error = 0; back->utf8allowed = 0; back->fallowed = 0xFF; back->dname = dk4str_dup(dn, erp); if (NULL != back->dname) { $? ". dname" back->s_ranges = dk4sto_open(erp); back->s_files = dk4sto_open(erp); back->s_pkgs = dk4sto_open(erp); if ( (NULL != back->s_ranges) && (NULL != back->s_files) && (NULL != back->s_pkgs) ) { $? ". storages ok" dk4sto_set_comp(back->s_ranges, dk4uc2l_i_range_compare, 0); dk4sto_set_comp(back->s_files, dk4uc2l_file_compare, 0); dk4sto_set_comp(back->s_pkgs, dk4uc2l_pkg_compare, 0); back->i_ranges = dk4sto_it_open(back->s_ranges, erp); back->i_files = dk4sto_it_open(back->s_files, erp); back->i_pkgs = dk4sto_it_open(back->s_pkgs, erp); if ( (NULL != back->i_ranges) && (NULL != back->i_files) && (NULL != back->i_pkgs) ) { $? ". iterators" ok = 1; } #if TRACE_DEBUG else { $? "! iterators" } #endif } #if TRACE_DEBUG else { $? "! storages" } #endif } #if TRACE_DEBUG else { $? "! dname" } #endif } #if TRACE_DEBUG else { $? "! allocation failed" } #endif if ((NULL != back) && (0 == ok)) { dk4uc2l_close(back); back = NULL; } $? "- dk4uc2l_i_new %d", TR_IPTR(back) return back; } /** Handler to process a line during pass 1. @param obj Object to use and modify during processing. @param line Current text line to process. @param lineno Current line number. @param erp Error report, may be NULL. @return DK4_TSP_RES_OK on success, DK4_TSP_RES_ERROR on recoverable errors, DK4_TSP_RES_FATAL on fatal errors requiring an abort. */ static int dk4uc2l_handler_pass1( void *obj, char *line, dk4_um_t DK4_ARG_UNUSED(lineno) , dk4_er_t *erp ) { handler_object_t *pho; char *p1; dk4_uc2l_range_t *rptr; dk4_uc2l_range_t *r2; const char *pe = NULL; unsigned long ul = 0UL; dk4_c32_t c32; dk4_c32_t rbo; int res; int back = DK4_TSP_RES_OK; DK4_UNUSED_ARG(lineno) #if TRACE_DEBUG dk4str8_delnl(line); #endif $? "+ dk4uc2l_handler_pass1 \"%!8s\"", TR_8STR(line) pho = (handler_object_t *)obj; /* Find start of line. */ p1 = dk4str8_start(line, NULL); /* Ignore empty lines and comment lines */ if (NULL == p1) { goto finished; } if ('#' == *p1) { goto finished; } /* Retrieve hexadecimal number */ (void)dk4str8_next(p1, NULL); res = dk4ma_input_c8_hex_ulong(&ul, p1, &pe, 1, erp); if (0 == res) { /* ERROR: Syntax, not a number */ goto finished; } c32 = (dk4_c32_t)ul; /* Check for number in global storage */ rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like( pho->ulptr->i_ranges, &c32, 1 ); if (NULL != rptr) { /* WARNING erp: Ignoring redefinition */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); goto finished; } /* Check for number in storage for file */ rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(pho->i_ra, &c32, 1); if (NULL != rptr) { /* WARNING erp: Ignoring redefinition */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); goto finished; } /* Check whether appending to existing range */ if (0UL < c32) { rbo = c32 - 1UL; rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(pho->i_ra, &rbo, 1); if (NULL != rptr) { rptr->end = c32; #if DK4_SIZEOF_LONG <= 4 if ((dk4_um_t)(ULONG_MAX) > (dk4_um_t)c32) { #endif rbo = c32 + 1UL; r2 = (dk4_uc2l_range_t *)dk4sto_it_find_like( pho->i_ra, &rbo, 1 ); if (NULL != r2) { dk4sto_remove(pho->s_ra, r2, NULL); rptr->end = r2->end; dk4uc2l_i_close_range(r2); } #if DK4_SIZEOF_LONG <= 4 } #endif goto finished; } } /* Check whether prepending to existing range */ #if DK4_SIZEOF_LONG <= 4 if ((dk4_um_t)(ULONG_MAX) > (dk4_um_t)c32) { #endif rbo = c32 + 1UL; rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(pho->i_ra, &rbo, 1); if (NULL != rptr) { rptr->start = c32; if ((dk4_c32_t)0UL < c32) { rbo = c32 - 1UL; r2 = (dk4_uc2l_range_t *)dk4sto_it_find_like( pho->i_ra, &rbo, 1 ); if (NULL != r2) { dk4sto_remove(pho->s_ra, r2, NULL); rptr->start = r2->start; dk4uc2l_i_close_range(r2); } } goto finished; } #if DK4_SIZEOF_LONG <= 4 } #endif /* Create range on its own */ rptr = dk4uc2l_i_open_range(c32, pho->file, erp); if (NULL == rptr) { back = DK4_TSP_RES_FATAL; goto finished; } if (0 == dk4sto_add(pho->ulptr->s_ranges, rptr, erp)) { dk4uc2l_i_close_range(rptr); back = DK4_TSP_RES_FATAL; } finished: $? "- dk4uc2l_handler_pass1 %d", back return back; } /** Process one file in pass 1 specified by absolute path name. @param ulptr Conversion structure to set up. @param rstrm Stream, opened for binary reading. @param puc2lf File structure. @param erp Error report, may be NULL. @param bptr Address of success variable to reset on errors. */ static 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 ) { char lnbuf[256]; /* Line buffer */ dk4_tsp08_t tsp08; /* Text stream processor */ handler_object_t ho; /* Handler object */ dk4_uc2l_range_t *rptr; /* Current range */ int res; /* Operation result */ int cc; /* Flag: Can continue */ char c; /* Current character to process */ $? "+ dk4uc2l_i_process_stream_pass1" /* Initialize handler object */ ho.file = puc2lf; ho.ulptr = ulptr; ho.s_ra = NULL; ho.i_ra = NULL; /* Create storage and iterator */ ho.s_ra = dk4sto_open(erp); if (NULL == ho.s_ra) { $? "! failed to create storage" *bptr = 0; ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; goto finished; } dk4sto_set_comp(ho.s_ra, dk4uc2l_i_range_compare, 0); ho.i_ra = dk4sto_it_open(ho.s_ra, erp); if (NULL == ho.i_ra) { $? "! failed to create iterator" *bptr = 0; ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; goto finished; } /* Initialize text stream processor */ res = dk4tsp08_setup_line( &tsp08, (void *)(&ho), dk4uc2l_handler_pass1, lnbuf, sizeof(lnbuf), DK4_ENCODING_PLAIN, DK4_ENCODING_PLAIN, erp ); if (0 == res) { $? "! failed to set up text processor" *bptr = 0; ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; goto finished; } /* Process file contents */ do { cc = 0; res = dk4stream_c8_read_byte(&c, rstrm, NULL); if (0 != res) { cc = 1; res = dk4tsp08_add_one_byte(&tsp08, (unsigned char)c); switch (res) { case DK4_TSP_RES_ERROR : { ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; *bptr = 0; } break; case DK4_TSP_RES_FATAL : { $? "! fatal error" ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; *bptr = 0; goto finished; } break; } } } while (0 < cc); /* Finalize text stream processor */ res = dk4tsp08_finish(&tsp08); switch (res) { case DK4_TSP_RES_ERROR : case DK4_TSP_RES_FATAL : { *bptr = 0; $? "! fatal error" ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; goto finished; } break; } /* Transfer ranges to global storage */ do { dk4sto_it_reset(ho.i_ra); rptr = (dk4_uc2l_range_t *)dk4sto_it_next(ho.i_ra); if (NULL != rptr) { dk4sto_remove(ho.s_ra, rptr, erp); if (0 == dk4sto_add(ulptr->s_ranges, rptr, erp)) { dk4uc2l_i_close_range(rptr); *bptr = 0; $? "! dk4sto_add" goto finished; } } } while (NULL != rptr); /* Release resources */ finished: if (NULL != ho.s_ra) { if (NULL != ho.i_ra) { dk4sto_it_reset(ho.i_ra); do { rptr = (dk4_uc2l_range_t *)dk4sto_it_next(ho.i_ra); if (NULL != rptr) { dk4uc2l_i_close_range(rptr); } } while (NULL != rptr); dk4sto_it_close(ho.i_ra); } dk4sto_close(ho.s_ra); } $? "- dk4uc2l_i_process_stream_pass1" } /** Process one file in pass 1 specified by absolute path name. @param ulptr Conversion structure to set up. @param fn Full (absolute) file name. @param sfn Short file name within given directory. @param erp Error report, may be NULL. @param bptr Address of success variable to reset on errors. */ static void dk4uc2l_i_process_one_full_file_pass1( dk4_uc2l_t *ulptr, const dkChar *fn, const dkChar *sfn, int *bptr, dk4_er_t *erp ) { dk4_stream_t *rstrm; dk4_uc2l_file_t *puc2lf; int fnsi; $? "+ dk4uc2l_i_process_one_full_file_pass1 \"%!ds\"", TR_STR(fn) puc2lf = (dk4_uc2l_file_t *)dk4sto_it_find_like(ulptr->i_files, sfn, 1); if (NULL == puc2lf) { puc2lf = dk4uc2l_i_open_file(sfn, erp); if (NULL != puc2lf) { if (0 != dk4sto_add(ulptr->s_files, puc2lf, erp)) { fnsi = dk4uc2l_i_find_suffix_index(fn); if (-1 < fnsi) { if (0 != dk4uc2l_i_suffix_index_supported(fnsi)) { rstrm = dk4stream_open_file_reader(fn, erp); if (NULL != rstrm) { /* Process stream */ dk4uc2l_i_process_stream_pass1( ulptr, rstrm, puc2lf, bptr, erp ); dk4stream_close(rstrm, NULL); } else { ulptr->had_error |= DK4_UC2L_ERROR_FOPEN; *bptr = 0; } } else { $? "! compression type not supported" ulptr->had_error |= DK4_UC2L_ERROR_FOPEN; *bptr = 0; /* ERROR erp: Compression type not supported */ dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED); } } else { $? "! file type not supported" /* Ignoring unsupported file */ } } else { $? "! failed to store" dk4uc2l_i_close_file(puc2lf); } } #if TRACE_DEBUG else { $? "! allocation failed" } #endif } #if TRACE_DEBUG else { $? "! bug, file already exists" } #endif $? "- dk4uc2l_i_process_one_full_file_pass1" } /** Process one file in pass 1. @param ulptr Conversion structure to set up. @param pth Directory path name, may be NULL. @param fn Short file name within given directory. @param erp Error report, may be NULL. @param bptr Address of success variable to reset on errors. */ static void dk4uc2l_i_process_one_file_pass1( dk4_uc2l_t *ulptr, const dkChar *pth, const dkChar *fn, int *bptr, dk4_er_t *erp ) { dkChar fnb[DK4_MAX_PATH]; size_t szfnb = DK4_SIZEOF(fnb,dkChar); $? "+ dk4uc2l_i_process_one_file_pass1 \"%!ds\" \"%!ds\"", TR_STR(pth), TR_STR(fn) if (NULL != pth) { if (0 != dk4str_cpy_s(fnb, szfnb, pth, erp)) { if (0 != dk4str_cat_s(fnb, szfnb, dk4uc2l_kwnl[3], erp)) { if (0 != dk4str_cat_s(fnb, szfnb, fn, erp)) { dk4path_correct_sep(fnb); dk4uc2l_i_process_one_full_file_pass1( ulptr, fnb, fn, bptr, erp ); } else { *bptr = 0; } } else { *bptr = 0; } } else { *bptr = 0; } } else { dk4uc2l_i_process_one_full_file_pass1(ulptr, fn, fn, bptr, erp); } $? "- dk4uc2l_i_process_one_file_pass1" } /** First pass to gather information which Unicode position is configured in which data file. This function is run while creating a new conversion structure to fill the range structures so we can later find a file for a Unicode position. If this function fails, the conversion structure is considered unusable. The function fails only on memory allocation failures, not on syntax errors in translation files. @param ulptr Conversion structure. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ static int dk4uc2l_i_pass1(dk4_uc2l_t *ulptr, dk4_er_t *erp) { const dkChar *fn = NULL; const dkChar *pth = NULL; dk4_dir_t *pdir = NULL; int back = 0; $? "+ dk4uc2l_i_pass1" pdir = dk4dir_open(ulptr->dname, DK4_DIR_OPEN_SORTED, erp); if (NULL != pdir) { pth = dk4dir_get_path(pdir); back = 1; do { fn = dk4dir_next_file(pdir); if (NULL != fn) { if (-1 < dk4uc2l_i_find_suffix_index(fn)) { dk4uc2l_i_process_one_file_pass1(ulptr,pth,fn,&back,erp); } } } while (NULL != fn); dk4dir_close(pdir); } else { $? "! failed to open dir" /* ERROR: Failed to open directory */ ulptr->had_error |= DK4_UC2L_ERROR_FOPEN; } $? "- dk4uc2l_i_pass1 %d", back return back; } /** Internal function to open a new conversion structure. @param dn Directory name (must be the name of an existing directory). @param erp Error report, may be NULL. @return Valid pointer on success, NULL on error. */ static dk4_uc2l_t * dk4uc2l_i_open(const dkChar *dn, dk4_er_t *erp) { dk4_uc2l_t *back = NULL; $? "+ dk4uc2l_i_open \"%!ds\"", dn back = dk4uc2l_i_new(dn, erp); if (NULL != back) { if (0 == dk4uc2l_i_pass1(back, erp)) { dk4uc2l_close(back); back = NULL; } #if TRACE_DEBUG else { $? "! pass 1" } #endif } #if TRACE_DEBUG else { $? "! mem" /* ERROR: Memory (already reported) */ } #endif $? "- dk4uc2l_i_open %d", TR_IPTR(back) return back; } dk4_uc2l_t * dk4uc2l_open(const dkChar *dn, dk4_er_t *erp) { dkChar fnb[DK4_MAX_PATH]; const dkChar *shdn = NULL; dk4_uc2l_t *back = NULL; const size_t szfnb = DK4_SIZEOF(fnb,dkChar); size_t i = 0; $? "+ dk4uc2l_open \"%!ds\"", TR_STR(dn) if (NULL != dn) { $? ". use specified directory name" if (0 != dk4file_is_directory(dn, erp)) { back = dk4uc2l_i_open(dn, erp); } } else { $? ". no directory name specified" shdn = dk4inst_get_directory(2); for (i = 0; ((i < 3) && (NULL == dn)); i++) { if (0 != dk4str_cpy_s(fnb, szfnb, shdn, NULL)) { if (0 != dk4str_cat_s(fnb, szfnb, dk4uc2l_kwnl[i], NULL)) { dk4path_correct_sep(fnb); if (0 != dk4file_is_directory(fnb, NULL)) { dn = fnb; } } } } if (NULL != dn) { $? ". directory name found" back = dk4uc2l_i_open(dn, erp); } else { $? "! no directory name found" /* ERROR: No directory found */ dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } } $? "- dk4uc2l_open %d", TR_IPTR(back) return back; } void dk4uc2l_allow_utf8(dk4_uc2l_t *ulptr, int enabled) { $? "+ dk4uc2l_allow_utf8" #if DK4_USE_ASSERT assert(NULL != ulptr); #endif if (NULL != ulptr) { ulptr->utf8allowed = ((0 != enabled) ? 0x01 : 0x00); } $? "- dk4uc2l_allow_utf8" } void dk4uc2l_clean_packages_and_fonts(dk4_uc2l_t *ulptr) { dk4_uc2l_pkg_t *pptr; $? "+ dk4uc2l_clean_packages_and_fonts" #if DK4_USE_ASSERT assert(NULL != ulptr); #endif if (NULL != ulptr) { ulptr->fallowed = DK4_UC2L_FONT_ENCODING_ALL; dk4sto_it_reset(ulptr->i_pkgs); do { pptr = (dk4_uc2l_pkg_t *)dk4sto_it_next(ulptr->i_pkgs); if (NULL != pptr) { pptr->used = 0x00; } } while (NULL != pptr); } $? "- dk4uc2l_clean_packages_and_fonts" } unsigned char dk4uc2l_retrieve_allowed_fe(dk4_uc2l_t *ulptr) { unsigned char back = 0x00; $? "+ dk4uc2l_retrieve_allowed_fe" #if DK4_USE_ASSERT assert(NULL != ulptr); #endif if (NULL != ulptr) { back = ulptr->fallowed; } $? "- dk4uc2l_retrieve_allowed_fe %u", (unsigned)back return back; } int dk4uc2lat_direct(dk4_c32_t c32) { int back = 0; char c; /* 8-bit character version of c32. */ $? "+ dk4uc2lat_direct %lx", dk4recode_dk_to_ul(c32) if(128UL > dk4recode_c32_to_ul(c32)) { c = (char)c32; switch(c) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ',': case '.': case ':': case ';': case '+': case '-': case '?': case '!': case '|': case '@': case '(': case ')': case '/': case '=': case ' ': { back = 1; } break; } } $? "- dk4uc2lat_direct %d", back return back; } int dk4uc2l_i_keyword_index(const char *pkey) { return (dk4str8_abbr_index(dk4uc2l_keywords, '$', pkey, 0)); } unsigned char dk4uc2l_font_encoding_from_name(const char *pname) { unsigned char back = 0x00; switch (dk4str8_array_index(dk4uc2l_font_encodings, pname, 0)) { case 0: { back = DK4_UC2L_FONT_ENCODING_OT1; } break; case 1: { back = DK4_UC2L_FONT_ENCODING_T1; } break; case 2: { back = DK4_UC2L_FONT_ENCODING_T4; } break; case 3: { back = DK4_UC2L_FONT_ENCODING_T5; } break; } return back; } dk4_uc2l_pkg_t * dk4uc2l_i_create_pkg( dk4_sto_t *s_pkgs, const char *pname ) { dk4_uc2l_pkg_t *back = NULL; back = dk4uc2l_i_open_pkg(pname, NULL); if (NULL != back) { if (0 == dk4sto_add(s_pkgs, back, NULL)) { dk4uc2l_i_close_pkg(back); back = NULL; } } return back; } /** Handler to process a line during pass 1. @param obj Object to use and modify during processing. @param line Current text line to process. @param lineno Current line number. @param erp Error report, may be NULL. @return DK4_TSP_RES_OK on success, DK4_TSP_RES_ERROR on recoverable errors, DK4_TSP_RES_FATAL on fatal errors requiring an abort. */ static int dk4uc2l_handler_pass2( void *obj, char *line, dk4_um_t lineno, dk4_er_t *erp ) { dk4_er_t er; char *pkgn[16]; handler_object_t *lho = NULL; const char *pe = NULL; char *p1 = NULL; char *p2 = NULL; char *p3 = NULL; char *p4 = NULL; dk4_uc2l_range_t *rptr = NULL; dk4_uc2l_pkg_t *pptr = NULL; size_t ind = 0; size_t numpkg = 0; size_t i = 0; unsigned long ul = 0UL; dk4_c32_t c32 = (dk4_c32_t)0UL; int back = DK4_TSP_RES_OK; int res = 0; int adding = 0; unsigned char fex = 0; unsigned char feval = 0; $? "+ dk4uc2l_handler_pass2" #if TRACE_DEBUG dk4str8_delnl(line); $? ". line=\"%!8s\"", line #endif /* Line handler object */ lho = (handler_object_t *)obj; /* Find start of line, ignore empty lines and comments */ p1 = dk4str8_start(line, NULL); if (NULL == p1) { $? ". ignore empty line" goto finished; } if ('#' == *p1) { $? ". ignore comment" goto finished; } /* Retrieve character number */ p2 = dk4str8_next(p1, NULL); res = dk4ma_input_c8_hex_ulong(&ul, p1, &pe, 1, erp); if (0 == res) { $? "! failed to retrieve character number" /* WARNING: Syntax, no number. Already reported in pass 1. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; goto finished; } c32 = (dk4_c32_t)ul; /* Find and check range structure, attempt cached range pointer first */ if (NULL != lho->rpc) { if ((lho->rpc->start <= c32) && (c32 <= lho->rpc->end)) { rptr = lho->rpc; } } if (NULL == rptr) { rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(lho->ulptr->i_ranges,&c32,1); } if (NULL == rptr) { $? "! rptr" /* ERROR: No range found. Already reported in pass 1. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; back = DK4_TSP_RES_FATAL; goto finished; } if (0 != dk4str_cmp(lho->file->fn, rptr->file->fn)) { /* ERROR: Not owned by current file. Already reported in pass 1. */ $? "! redefinition" lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; goto finished; } /* Initialize range structure (allocate memory) if not yet done */ if (0x00 == rptr->ia) { $? ". must initialize range" if (0 == dk4uc2l_i_init_range(rptr, erp)) { $? "! memory" lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; back = DK4_TSP_RES_FATAL; goto finished; } rptr->ia = 0x01; $? ". marking range as initialized" } else { $? ". range is already initialized" } /* Find index */ ind = (size_t)(c32 - rptr->start); /* Check whether character already defined */ if (NULL != rptr->lno) { if ((dk4_um_t)0UL != (rptr->lno)[ind]) { /* ERROR: Redefinition. Already reported in pass 1. */ $? "! redefinition" lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; goto finished; } else { (rptr->lno)[ind] = lineno; } } /* Traverse all strings in line */ p1 = p2; while (NULL != p1) { $? ". p1=\"%!8s\"", p1 p2 = dk4str8_next(p1, NULL); p3 = dk4str8_chr(p1, '='); if (NULL != p3) { *(p3++) = '\0'; p3 = dk4str8_start(p3, NULL); if (NULL != p3) { $? ". p1=\"%!8s\" p3=\"%!8s\"", p1, p3 res = dk4uc2l_i_keyword_index(p1); switch (res) { case 0 : { $? ". both=..." if (NULL != rptr->both) { if (NULL == (rptr->both)[ind]) { (rptr->both)[ind] = dk4str8_dup(p3, erp); if (NULL == (rptr->both)[ind]) { $? "! memory" lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } else { $? "! bug" /* ERROR: Already defined. Bug: Should not happen. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; } } else { $? "! rptr->both" /* ERROR: Memory. Already reported during range initialization. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } break; case 1 : { $? ". text=..." if (NULL != rptr->text) { if (NULL == (rptr->text)[ind]) { (rptr->text)[ind] = dk4str8_dup(p3, erp); if (NULL == (rptr->text)[ind]) { $? "! memory" lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } else { $? "! bug" /* ERROR: Already defined. Bug: Should not happen. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; } } else { $? "! rptr->text" /* ERROR: Memory Already reported during range initialization. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } break; case 2 : { $? ". math=..." if (NULL != rptr->math) { if (NULL == (rptr->math)[ind]) { (rptr->math)[ind] = dk4str8_dup(p3, erp); if (NULL == (rptr->math)[ind]) { $? "! memory" lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } else { $? "! bug" /* ERROR: Already defined. Bug: Should not happen. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; } } else { $? "! rptr->math" /* ERROR: Memory. Already reported during range initialization. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } break; case 3 : { $? ". encoding=..." if (NULL != rptr->fenc) { adding = 1; feval = 0x00; if ('!' == *p3) { adding = 0; p3++; feval = DK4_UC2L_FONT_ENCODING_ALL; } while (NULL != p3) { p4 = dk4str8_chr(p3, ','); if (NULL != p4) { *(p4++) = '\0'; } fex = dk4uc2l_font_encoding_from_name(p3); if (0x00 != fex) { if (0 != adding) { feval |= fex; } else { feval &= (~(fex)); } } else { $? "! illegal encoding \"%!8s\"", p3 /* ERROR: Illegal encoding name */ dk4error_set_simple_error_code( erp, DK4_E_SYNTAX ); lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; } p3 = p4; } (rptr->fenc)[ind] = feval; } else { /* ERROR: Memory. Already reported during range initialization. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } break; case 4 : { $? ". packages=..." if (NULL != rptr->pkgs) { if (NULL == (rptr->pkgs)[ind]) { dk4error_init(&er); numpkg = dk4str8_tokenize( pkgn, 16, p3, ",", &er ); if (0 < numpkg) { (rptr->pkgs)[ind] = dk4mem_new(dk4_uc2l_pkg_p,(numpkg+1),erp); if (NULL != (rptr->pkgs)[ind]) { for (i = 0; i <= numpkg; i++) { ((rptr->pkgs)[ind])[i] = NULL; } for (i = 0; i < numpkg; i++) { pptr = (dk4_uc2l_pkg_t *)dk4sto_it_find_like( lho->ulptr->i_pkgs, pkgn[i], 1 ); if (NULL != pptr) { ((rptr->pkgs)[ind])[i] = pptr; } else { pptr = dk4uc2l_i_create_pkg( lho->ulptr->s_pkgs, pkgn[i] ); if (NULL != pptr) { ((rptr->pkgs)[ind])[i] = pptr; } else { $? "! memory" dk4error_set_simple_error_code( erp, DK4_E_MEMORY_ALLOCATION_FAILED ); lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } } } else { $? "! memory" dk4error_set_simple_error_code( erp, DK4_E_MEMORY_ALLOCATION_FAILED ); lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } else { $? "! empty list" /* ERROR: Syntax, empty list */ dk4error_set_simple_error_code( erp, DK4_E_SYNTAX ); lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; } } else { $? "! bug" /* ERROR: Already defined. Bug: Should not happen. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; } } else { $? "! memory" /* ERROR: Memory. Already reported during range initalization. */ lho->ulptr->had_error |= DK4_UC2L_ERROR_MEMORY; } } break; default : { $? "! illegal key \"%!8s\"", p1 /* ERROR: Illegal key name */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; } break; } p1 = p2; } else { $? "! not key=value" /* ERROR: Syntax, not a key=value */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; p1 = NULL; } } else { $? "! not key=value" /* ERROR: Syntax, not a key=value */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); lho->ulptr->had_error |= DK4_UC2L_ERROR_SYNTAX; p1 = NULL; } } finished: $? "- dk4uc2l_handler_pass2 %d", back return back; } /** Load data file. @param ulptr Conversion structure. @param fptr File structure to load. @param erp Error report, may be NULL. */ static void dk4uc2l_load_data_file( dk4_uc2l_t *ulptr, dk4_uc2l_file_t *fptr, dk4_er_t *erp ) { dkChar fnb[DK4_MAX_PATH]; char lnb[256]; handler_object_t ho; dk4_tsp08_t tsp08; dk4_stream_t *rstrm = NULL; size_t fnbsz = DK4_SIZEOF(fnb,dkChar); size_t szlnb = sizeof(lnb); int res; int cc; char c; $? "+ dk4uc2l_load_data_file \"%!ds\"", fptr->fn /* Initialize handler object */ ho.ulptr = ulptr; ho.s_ra = NULL; ho.i_ra = NULL; ho.file = fptr; ho.rpc = NULL; /* Save source file name and line number */ /* Each file should be loaded only once */ if (0x00 != fptr->loaded) { goto finished; } fptr->loaded = 0x01; /* Construct full path name */ if (0 == dk4str_cpy_s(fnb, fnbsz, ulptr->dname, erp)) { /* ERROR: Directory name too long */ ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; goto finished; } if (0 == dk4str_cat_s(fnb, fnbsz, dk4uc2l_kwnl[3], erp)) { /* ERROR: Directory name too long */ ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; goto finished; } if (0 == dk4str_cat_s(fnb, fnbsz, fptr->fn, erp)) { /* ERROR: Directory name too long */ ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; goto finished; } dk4path_correct_sep(fnb); /* Open reader stream */ rstrm = dk4stream_open_file_reader(fnb, erp); if (NULL == rstrm) { /* ERROR: Failed to read file */ ulptr->had_error |= DK4_UC2L_ERROR_FOPEN; goto finished; } /* Initialize text processing */ res = dk4tsp08_setup_line( &tsp08, (void *)(&ho), dk4uc2l_handler_pass2, lnb, szlnb, DK4_ENCODING_PLAIN, DK4_ENCODING_PLAIN, erp ); if (0 == res) { ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; /* ERROR: Memory */ goto finished; } /* Process contents */ do { cc = 0; res = dk4stream_c8_read_byte(&c, rstrm, erp); if (0 < res) { cc = 1; res = dk4tsp08_add_one_byte(&tsp08, (unsigned char)c); switch (res) { case DK4_TSP_RES_ERROR : { ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; } break; case DK4_TSP_RES_FATAL : { ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; goto finished; } break; } } } while (0 < cc); /* Finish text processing */ res = dk4tsp08_finish(&tsp08); switch (res) { case DK4_TSP_RES_ERROR: case DK4_TSP_RES_FATAL: { ulptr->had_error |= DK4_UC2L_ERROR_PROCESSING; } break; } /* Clean up */ finished: if (NULL != rstrm) { dk4stream_close(rstrm, NULL); } $? "- dk4uc2l_load_data_file" } const char * dk4uc2l_find(dk4_uc2l_t *ulptr, dk4_c32_t c, int mm, dk4_er_t *erp) { dk4_uc2l_range_t *rptr; dk4_uc2l_pkg_t **pkgpp; dk4_uc2l_file_t *fptr; const char *back = NULL; size_t ind; size_t blgt; int res; $? "+ dk4uc2l_find 0x%lx", (unsigned long)c #if DK4_USE_ASSERT assert(NULL != ulptr); #endif /* Check ulptr usability */ if (NULL == ulptr) { $? "! args" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } /* Attempt direct output */ if (0 != dk4uc2lat_direct(c)) { $? ". direct output" ulptr->buf[0] = (char)c; ulptr->buf[1] = '\0'; back = &(ulptr->buf[0]); goto finished; } /* Attempt data loaded from files */ rptr = (dk4_uc2l_range_t *)dk4sto_it_find_like(ulptr->i_ranges, &c, 1); if (NULL != rptr) { $? ". found in overview data" fptr = rptr->file; if (0x00 == fptr->loaded) { $? ". must load data file" dk4uc2l_load_data_file(ulptr, fptr, erp); } ind = (size_t)(c - rptr->start); if (0 != mm) { $? ". search in math mode" if (NULL != rptr->math) { back = (rptr->math)[ind]; } } else { $? ". search in non-math mode" if (NULL != rptr->text) { back = (rptr->text)[ind]; } } if (NULL == back) { $? ". not yet found" if (NULL != rptr->both) { back = (rptr->both)[ind]; } } if (NULL != back) { $? ". found" if (NULL != rptr->pkgs) { $? ". modify package usage" pkgpp = (rptr->pkgs)[ind]; if (NULL != pkgpp) { while (NULL != *pkgpp) { (*(pkgpp++))->used = 0x01; } } } if (NULL != rptr->fenc) { $? ". modify encoding usage" ulptr->fallowed &= (rptr->fenc)[ind]; } goto finished; } } /* Attempt to use UTF-8 encoded data or ASCII data directly */ $? ". not yet found" if (0 == mm) { if (0x00 != ulptr->utf8allowed) { $? ". attempt utf-8" blgt = 15; res = dk4utf8_encode( (unsigned char *)(&(ulptr->buf[0])), &blgt, c, erp ); if (0 != res) { ulptr->buf[blgt] = '\0'; back = &(ulptr->buf[0]); } } else { $? ". attempt direct usage" if (dkC32(0x00000100) > c) { ulptr->buf[0] = (char)c; ulptr->buf[1] = '\0'; back = &(ulptr->buf[0]); } } } finished: $!trace-code if (NULL == back) { $? "! not found" $!trace-code } $? "- dk4uc2l_find \"%!8s\"", TR_8STR(back) return back; } static int dk4uc2l_i_encoding( unsigned char enclist, unsigned char oneenc ) { int back = 0; if (0x00 != (enclist & ((unsigned char)oneenc))) { back = 1; } return back; } void dk4uc2l_recommendations(dk4_uc2l_t *ulptr, dk4_stream_t *wstrm, dk4_er_t *erp) { dk4_uc2l_pkg_t *pptr; $? "+ dk4uc2l_recommendations" #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); #endif if ((NULL != ulptr) && (NULL != wstrm)) { dk4stream_write_char_string( wstrm, dk4uc2l_kw8[0], erp ); if (dk4uc2l_i_encoding(ulptr->fallowed,DK4_UC2L_FONT_ENCODING_T1)) { dk4stream_write_char_string( wstrm, dk4uc2l_kw8[3], erp ); } if (dk4uc2l_i_encoding(ulptr->fallowed,DK4_UC2L_FONT_ENCODING_OT1)) { dk4stream_write_char_string( wstrm, dk4uc2l_kw8[2], erp ); } if (dk4uc2l_i_encoding(ulptr->fallowed,DK4_UC2L_FONT_ENCODING_T4)) { dk4stream_write_char_string( wstrm, dk4uc2l_kw8[4], erp ); } if (dk4uc2l_i_encoding(ulptr->fallowed,DK4_UC2L_FONT_ENCODING_T5)) { dk4stream_write_char_string( wstrm, dk4uc2l_kw8[5], erp ); } dk4stream_write_byte(wstrm, '\n', erp); dk4sto_it_reset(ulptr->i_pkgs); do { pptr = (dk4_uc2l_pkg_t *)dk4sto_it_next(ulptr->i_pkgs); if (NULL != pptr) { if (0x00 != pptr->used) { dk4stream_write_char_string( wstrm, dk4uc2l_kw8[1], erp ); dk4stream_write_char_string( wstrm, pptr->pn, erp ); dk4stream_write_byte(wstrm, '\n', erp); } } } while (NULL != pptr); } $? "- dk4uc2l_recommendations" } int dk4uc2l_retrieve_errors(dk4_uc2l_t *ulptr) { int back = 0; $? "+ dk4uc2l_retrieve_errors" #if DK4_USE_ASSERT assert(NULL != ulptr); #endif if (NULL != ulptr) { back = ulptr->had_error; } $? "- dk4uc2l_retrieve_errors %d", back return back; } void dk4uc2l_reset_errors(dk4_uc2l_t *ulptr) { #if DK4_USE_ASSERT assert(NULL != ulptr); #endif if (NULL != ulptr) { ulptr->had_error = 0; } } /* ##### untested */ static void dk4uc2l_putc32( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, dk4_c32_t c32, int *pmm, int *pback, dk4_er_t *erp ) { dk4_er_t er; const char *le = NULL; $? "+ dk4uc2l_putc32 0x%08lx", UL(c32) #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); #endif dk4error_init(&er); le = dk4uc2l_find(ulptr, c32, 0, &er); if (NULL != le) { $? ". found char, no mm" if (0 != *pmm) { if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) { *pback = 0; $? "! end mm" } *pmm = 0; } if (0 == dk4stream_write_char_string(wstrm, le, erp)) { *pback = 0; $? "! le" } } else { le = dk4uc2l_find(ulptr, c32, 1, &er); if (NULL != le) { $? ". found char mm" if (0 == *pmm) { if (0 == dk4stream_write_char_string(wstrm,dk4uc2l_mm[0],erp)) { *pback = 0; $? "! start mm" } *pmm = 1; } if (0 == dk4stream_write_char_string(wstrm, le, erp)) { *pback = 0; $? "! le" } } else { $? "! not found" *pback = 0; dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } } $? "- dk4uc2l_putc32" } /* ##### untested */ int dk4uc2l_string_c32( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const dk4_c32_t *str, dk4_er_t *erp ) { int back = 0; int mm = 0; $? "+ dk4uc2l_string_c32" #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); assert(NULL != str); #endif /* Check arguments */ if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } /* Process all characters from string */ back = 1; while (dkC32(0) != *str) { dk4uc2l_putc32(wstrm, ulptr, *(str++), &mm, &back, erp); } /* Finalize math mode if necessary */ if (0 != mm) { if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) { back = 0; } } finished: $? "- dk4uc2l_string_c32 %d", back return back; } /* ##### untested */ int dk4uc2l_string_c16( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const dk4_c16_t *str, dk4_er_t *erp ) { dk4_utf16_decoder_t dec; dk4_c32_t c32; int mm = 0; int back = 0; int err = 0; $? "+ dk4uc2l_string_c16" #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); assert(NULL != str); #endif /* Check arguments */ if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) { $? "! arguments" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4utf16_init(&dec); while ((dkC16(0) != *str) && (0 == err)) { $? ". have char to add" switch (dk4utf16_add(&dec, *(str++))) { case DK4_EDSTM_FINISHED : { c32 = dk4utf16_get(&dec); dk4utf16_init(&dec); dk4uc2l_putc32(wstrm, ulptr, c32, &mm, &back, erp); $? ". back = %d, err = %d", back, err } break; case DK4_EDSTM_ERROR : { $? "! failed to add" err = 1; dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED); back = 0; } break; } } if (0 == err) { if (0 == dk4utf16_is_empty(&dec)) { $? "! decoder not empty" dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED); back = 0; } } if (0 != mm) { if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) { back = 0; $? "! failed to close mm" } } finished: $? "- dk4uc2l_string_c16 %d", back return back; } /* ##### untested */ int dk4uc2l_string_utf8( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const char *str, dk4_er_t *erp ) { dk4_utf8_decoder_t dec; dk4_c32_t c32; int back = 0; int mm = 0; int err = 0; $? "+ dk4uc2l_string_utf8" #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); assert(NULL != str); #endif if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4utf8_init(&dec); while(('\0' != *str) && (0 == err)) { switch (dk4utf8_add(&dec, (unsigned char)(*(str++)))) { case DK4_EDSTM_FINISHED : { c32 = dk4utf8_get(&dec); dk4utf8_init(&dec); dk4uc2l_putc32(wstrm, ulptr, c32, &mm, &back, erp); } break; case DK4_EDSTM_ERROR : { err = 1; dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED); back = 0; } break; } } if (0 == err) { if (0 == dk4utf8_is_empty(&dec)) { dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED); back = 0; } } if (0 != mm) { if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) { back = 0; } } finished: $? "- dk4uc2l_string_utf8 %d", back return back; } /* ##### untested */ int dk4uc2l_string_ansi( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const char *str, dk4_er_t *erp ) { dk4_c32_t c32; int back = 0; int mm = 0; $? "+ dk4uc2l_string_ansi" #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); assert(NULL != str); #endif if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; while ('\0' != *str) { if (0 != dk4ansi_decode(&c32, (unsigned char)(*(str++)))) { dk4uc2l_putc32(wstrm, ulptr, c32, &mm, &back, erp); } else { dk4error_set_simple_error_code(erp, DK4_E_DECODING_FAILED); back = 0; } } if (0 != mm) { if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) { back = 0; } } finished: $? "- dk4uc2l_string_ansi %d", back return back; } /* ##### untested */ int dk4uc2l_string_ascii( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const char *str, dk4_er_t *erp ) { dk4_c32_t c32; int back = 0; int mm = 0; $? "+ dk4uc2l_string_ascii" #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); assert(NULL != str); #endif if ((NULL == wstrm) || (NULL == ulptr) || (NULL == str)) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; while ('\0' != *str) { c32 = (dk4_c32_t)((unsigned char)(*(str++))); dk4uc2l_putc32(wstrm, ulptr, c32, &mm, &back, erp); } if (0 != mm) { if (0 == dk4stream_write_char_string(wstrm, dk4uc2l_mm[1], erp)) { back = 0; } } finished: $? "- dk4uc2l_string_ascii %d", back return back; } /* ##### untested */ int dk4uc2l_string_c8( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const char *str, int ie, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); assert(NULL != str); #endif switch (ie) { case DK4_ENCODING_UTF8 : { return (dk4uc2l_string_utf8(wstrm, ulptr, str, erp)); } break; case DK4_ENCODING_WIN1252 : { return (dk4uc2l_string_ansi(wstrm, ulptr, str, erp)); } break; default : { return (dk4uc2l_string_ascii(wstrm, ulptr, str, erp)); } break; } } /* ##### untested */ int dk4uc2l_string_dk( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const dkChar *str, #if 1 == DK4_CHAR_SIZE int ie, #else int DK4_ARG_UNUSED(ie), #endif dk4_er_t *erp ) { #if DK4_CHAR_SIZE > 1 DK4_UNUSED_ARG(ie) #endif #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); assert(NULL != str); #endif #if DK4_CHAR_SIZE > 1 #if DK4_CHAR_SIZE > 2 $? "= dk4uc2l_string_dk" return (dk4uc2l_string_c32(wstrm, ulptr, str, erp)); #else $? "= dk4uc2l_string_dk" return (dk4uc2l_string_c16(wstrm, ulptr, str, erp)); #endif #else $? "= dk4uc2l_string_dk" return (dk4uc2l_string_c8(wstrm, ulptr, str, ie, erp)); #endif } int dk4uc2l_string_encoded( dk4_stream_t *wstrm, dk4_uc2l_t *ulptr, const void *str, int ie, dk4_er_t *erp ) { int back = 0; #if DK4_CHAR_SIZE > 1 DK4_UNUSED_ARG(ie) #endif #if DK4_USE_ASSERT assert(NULL != wstrm); assert(NULL != ulptr); assert(NULL != str); #endif switch (ie) { case DK4_ENCODING_32 : { $? ". 32 bit encoding" back = dk4uc2l_string_c32(wstrm, ulptr, str, erp); } break; case DK4_ENCODING_UTF16 : { $? ". 16 bit encoding" back = dk4uc2l_string_c16(wstrm, ulptr, str, erp); } break; default : { $? ". 8 bit encoding" back = dk4uc2l_string_c8(wstrm, ulptr, str, ie, erp); } break; } return back; } /* vim: set ai sw=4 ts=4 : */