diff options
author | Ulrich Drepper <drepper@redhat.com> | 2000-06-19 21:12:06 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2000-06-19 21:12:06 +0000 |
commit | d620426811688301eb1cbe6e63773d6430b2706e (patch) | |
tree | 555eb9182298ec1e56db8a5de4f62daa2e654321 /iconv/gconv_trans.c | |
parent | 01da56ba764e6abc52bfe9a1feeb79d3d67346d1 (diff) | |
download | glibc-d620426811688301eb1cbe6e63773d6430b2706e.tar.gz glibc-d620426811688301eb1cbe6e63773d6430b2706e.tar.xz glibc-d620426811688301eb1cbe6e63773d6430b2706e.zip |
Update.
2000-06-19 Ulrich Drepper <drepper@redhat.com> * iconv/gconv.h (__gconv_trans_fct): Add new parameter. General namespace cleanup. (struct __gconv_trans_data): Add next field. (struct __gconv_step_data): Make __trans a pointer. * iconv/gconv_conf.c: Split out code to find gconv directories from __gconv_read_conf in new functions. * iconv/gconv_int.h: Define new data structure and declare new functions for handling of gconv directory list. * iconv/gconv_open.c: Allow more than one error handling step being used. Call function to load error handling module if it is none of the builtin transformations. * iconv/gconv_close.c: Add code to free transliteration data. * iconv/gconv_trans.c: Add functions to load and unload modules implementing transliteration etc. * iconv/skeleton.c: Call all context functions now that more than one module is allowed. * iconv/loop.c (STANDARD_ERR_HANDLING): New macro. * iconv/gconv_simple.c: Use STANDARD_ERR_HANDLING macro for places where the full error handling using transliteration is needed. * iconvdata/8bit-gap.c: Likewise. * iconvdata/8bit-generic.c: Likewise. * iconvdata/ansi_x3.110.c: Likewise. * iconvdata/big5.c: Likewise. * iconvdata/big5hkscs.c: Likewise. * iconvdata/euc-cn.c: Likewise. * iconvdata/euc-jp.c: Likewise. * iconvdata/euc-kr.c: Likewise. * iconvdata/euc-tw.c: Likewise. * iconvdata/gbgbk.c: Likewise. * iconvdata/gbk.c: Likewise. * iconvdata/iso-2022-cn.c: Likewise. * iconvdata/iso-2022-jp.c: Likewise. * iconvdata/iso-2022-kr.c: Likewise. * iconvdata/iso646.c: Likewise. * iconvdata/iso8859-1.c: Likewise. * iconvdata/iso_6937-2.c: Likewise. * iconvdata/iso_6937.c: Likewise. * iconvdata/johab.c: Likewise. * iconvdata/sjis.c: Likewise. * iconvdata/t.61.c: Likewise. * iconvdata/uhc.c: Likewise. * iconvdata/unicode.c: Likewise. * iconvdata/utf-16.c: Likewise. * libio/iofwide.c: Reset __trans member of __gconv_trans_data structure correctly after last change. * wcsmbs/btowc.c: Likewise. * wcsmbs/mbrtowc.c: Likewise. * wcsmbs/mbsnrtowcs.c: Likewise. * wcsmbs/mbsrtowcs.c: Likewise. * wcsmbs/wcrtomb.c: Likewise. * wcsmbs/wcsnrtombs.c: Likewise. * wcsmbs/wcsrtombs.c: Likewise. * wcsmbs/wctob.c: Likewise. * localedata/Makefile: Set -Wno-format for some files since gcc does not know all the format specifiers. 2000-06-18 Ulrich Drepper <drepper@redhat.com> * locale/loadlocale.c (_nl_unload_locale): Remove a bit of unneeded code. * locale/lc-time.c (_nl_init_era_entries): Likewise.
Diffstat (limited to 'iconv/gconv_trans.c')
-rw-r--r-- | iconv/gconv_trans.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c index 269917b531..4d6e7766fd 100644 --- a/iconv/gconv_trans.c +++ b/iconv/gconv_trans.c @@ -18,9 +18,13 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <assert.h> #include <dlfcn.h> +#include <search.h> #include <stdint.h> +#include <string.h> +#include <bits/libc-lock.h> #include "gconv_int.h" #include "../locale/localeinfo.h" @@ -28,6 +32,7 @@ int __gconv_transliterate (struct __gconv_step *step, struct __gconv_step_data *step_data, + void *trans_data __attribute__ ((unused)), const unsigned char *inbufstart, const unsigned char **inbufp, const unsigned char *inbufend, @@ -218,3 +223,178 @@ __gconv_transliterate (struct __gconv_step *step, /* Haven't found a match. */ return __GCONV_ILLEGAL_INPUT; } + + +/* Structure to represent results of found (or not) transliteration + modules. */ +struct known_trans +{ + /* This structure must remain the first member. */ + struct trans_struct info; + + const char *fname; + void *handle; + int open_count; +}; + + +/* Tree with results of previous calls to __gconv_translit_find. */ +static void *search_tree; + +/* We modify global data. */ +__libc_lock_define_initialized (static, lock); + + +/* Compare two transliteration entries. */ +static int +trans_compare (const void *p1, const void *p2) +{ + struct known_trans *s1 = (struct known_trans *) p1; + struct known_trans *s2 = (struct known_trans *) p2; + + return strcmp (s1->info.name, s2->info.name); +} + + +/* Open (maybe reopen) the module named in the struct. Get the function + and data structure pointers we need. */ +static int +open_translit (struct known_trans *trans) +{ + __gconv_trans_query_fct queryfct; + + trans->handle = __libc_dlopen (trans->fname); + if (trans->handle == NULL) + /* Not available. */ + return 1; + + /* Find the required symbol. */ + queryfct = __libc_dlsym (trans->handle, "gconv_trans_context"); + if (queryfct == NULL) + { + /* We cannot live with that. */ + close_and_out: + __libc_dlclose (trans->handle); + trans->handle = NULL; + return 1; + } + + /* Get the context. */ + if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames) + != 0) + goto close_and_out; + + /* Of course we also have to have the actual function. */ + trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans"); + if (trans->info.trans_fct == NULL) + goto close_and_out; + + /* Now the optional functions. */ + trans->info.trans_init_fct = + __libc_dlsym (trans->handle, "gconv_trans_init"); + trans->info.trans_context_fct = + __libc_dlsym (trans->handle, "gconv_trans_context"); + trans->info.trans_end_fct = + __libc_dlsym (trans->handle, "gconv_trans_end"); + + trans->open_count = 1; + + return 0; +} + + +int +internal_function +__gconv_translit_find (struct trans_struct *trans) +{ + struct known_trans **found; + const struct path_elem *runp; + int res = 1; + + /* We have to have a name. */ + assert (trans->name != NULL); + + /* Acquire the lock. */ + __libc_lock_lock (lock); + + /* See whether we know this module already. */ + found = __tfind (trans, &search_tree, trans_compare); + if (found != NULL) + { + /* Is this module available? */ + if ((*found)->handle != NULL) + { + /* Maybe we have to reopen the file. */ + if ((*found)->handle != (void *) -1) + /* The object is not unloaded. */ + res = 0; + else if (open_translit (*found) == 0) + { + /* Copy the data. */ + *trans = (*found)->info; + res = 0; + } + } + } + else + { + size_t name_len = strlen (trans->name) + 1; + int need_so = 0; + struct known_trans *newp; + + /* We have to continue looking for the module. */ + if (__gconv_path_elem == NULL) + __gconv_get_path (); + + /* See whether we have to append .so. */ + if (name_len <= 3 || memcmp (&trans->name[name_len - 3], ".so", 3) != 0) + need_so = 1; + + /* Create a new entry. */ + newp = (struct known_trans *) malloc (sizeof (struct known_trans) + + (__gconv_max_path_elem_len + + name_len + 3) + + name_len); + if (newp != NULL) + { + char *cp; + + /* Clear the struct. */ + memset (newp, '\0', sizeof (struct known_trans)); + + /* Store a copy of the module name. */ + newp->info.name = (char *) (newp + 1); + cp = __mempcpy ((char *) newp->info.name, trans->name, name_len); + + newp->fname = cp; + + /* Seach in all the directories. */ + for (runp = __gconv_path_elem; runp->name != NULL; ++runp) + { + cp = __mempcpy (__stpcpy ((char *) newp->fname, runp->name), + trans->name, name_len); + if (need_so) + memcpy (cp, ".so", sizeof (".so")); + + if (open_translit (newp) == 0) + { + /* We found a module. */ + res = 0; + break; + } + } + + /* In any case we'll add the entry to our search tree. */ + if (__tsearch (newp, &search_tree, trans_compare) == NULL) + { + /* Yickes, this should not happen. Unload the object. */ + res = 1; + /* XXX unload here. */ + } + } + } + + __libc_lock_unlock (lock); + + return res; +} |