From 0d9f67937f0c9329c35c2c0d15848ab8316dc520 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 4 Apr 1998 07:25:25 +0000 Subject: [PATCH] Update. 1998-04-03 23:17 Ulrich Drepper * iconv/gconv.c: Rewrite of the low-level of gconv. * iconv/gconv.h: Likewise. * iconv/gconv_builtin.h: Likewise. * iconv/gconv_close.c: Likewise. * iconv/gconv_db.: Likewise. * iconv/gconv_dl.c: Likewise. * iconv/gconv_int.h: Likewise. * iconv/gconv_open.c: Likewise. * iconv/gconv_simple.c: Likewise. * iconvdata/8bit-gap.c: Adapt for rewrite. * iconvdata/8bit-generic.c: Likewise. * iconvdata/euckr.c: Likewise. * iconvdata/iso646.c: Likewise. * iconvdata/iso6937.c: Likewise. * iconvdata/iso8859-1.c: Likewise. * iconvdata/johab.c: Likewise. * iconvdata/sjis.c: Likewise. * iconvdata/t61.c: Likewise. * iconvdata/uhc.c: Likewise. --- ChangeLog | 22 ++++++++++++ iconv/gconv.c | 1 + iconv/gconv.h | 18 +++++++--- iconv/gconv_builtin.h | 16 +++------ iconv/gconv_close.c | 13 ------- iconv/gconv_db.c | 87 ++++++++++++++++++++++++++++++++++------------ iconv/gconv_dl.c | 85 ++++++++++++++++++++------------------------- iconv/gconv_int.h | 89 ++++++++++++++++++++++++++---------------------- iconv/gconv_open.c | 34 ++++++------------ iconv/gconv_simple.c | 42 ++++++----------------- iconvdata/8bit-gap.c | 8 ++--- iconvdata/8bit-generic.c | 8 ++--- iconvdata/euckr.c | 8 ++--- iconvdata/iso646.c | 10 +++--- iconvdata/iso6937.c | 8 ++--- iconvdata/iso8859-1.c | 8 ++--- iconvdata/johab.c | 8 ++--- iconvdata/sjis.c | 8 ++--- iconvdata/t61.c | 8 ++--- iconvdata/uhc.c | 8 ++--- 20 files changed, 253 insertions(+), 236 deletions(-) diff --git a/ChangeLog b/ChangeLog index 98ead12..3a2eed7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +1998-04-03 23:17 Ulrich Drepper + + * iconv/gconv.c: Rewrite of the low-level of gconv. + * iconv/gconv.h: Likewise. + * iconv/gconv_builtin.h: Likewise. + * iconv/gconv_close.c: Likewise. + * iconv/gconv_db.: Likewise. + * iconv/gconv_dl.c: Likewise. + * iconv/gconv_int.h: Likewise. + * iconv/gconv_open.c: Likewise. + * iconv/gconv_simple.c: Likewise. + * iconvdata/8bit-gap.c: Adapt for rewrite. + * iconvdata/8bit-generic.c: Likewise. + * iconvdata/euckr.c: Likewise. + * iconvdata/iso646.c: Likewise. + * iconvdata/iso6937.c: Likewise. + * iconvdata/iso8859-1.c: Likewise. + * iconvdata/johab.c: Likewise. + * iconvdata/sjis.c: Likewise. + * iconvdata/t61.c: Likewise. + * iconvdata/uhc.c: Likewise. + 1998-04-03 15:34 Ulrich Drepper * iconv/gconv_int.h: New file. Internal header. diff --git a/iconv/gconv.c b/iconv/gconv.c index 5df1635..71d87ae 100644 --- a/iconv/gconv.c +++ b/iconv/gconv.c @@ -23,6 +23,7 @@ int +internal_function __gconv (gconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft, size_t *converted) { diff --git a/iconv/gconv.h b/iconv/gconv.h index 76a7197..f3f80f4 100644 --- a/iconv/gconv.h +++ b/iconv/gconv.h @@ -24,6 +24,7 @@ #define _GCONV_H 1 #include +#include #define __need_size_t #include @@ -51,6 +52,7 @@ enum /* Forward declarations. */ struct gconv_step; struct gconv_step_data; +struct gconv_loaded_object; /* Type of a conversion function. */ @@ -59,15 +61,17 @@ typedef int (*gconv_fct) __P ((struct gconv_step *, __const char *, size_t *, size_t *, int)); /* Constructor and destructor for local data for conversion step. */ -typedef int (*gconv_init_fct) __P ((struct gconv_step *, - struct gconv_step_data *)); -typedef void (*gconv_end_fct) __P ((struct gconv_step_data *)); +typedef int (*gconv_init_fct) __P ((struct gconv_step *)); +typedef void (*gconv_end_fct) __P ((struct gconv_step *)); /* Description of a conversion step. */ struct gconv_step { - void *shlib_handle; + struct gconv_loaded_object *shlib_handle; + const char *modname; + + int counter; __const char *from_name; __const char *to_name; @@ -75,6 +79,8 @@ struct gconv_step gconv_fct fct; gconv_init_fct init_fct; gconv_end_fct end_fct; + + void *data; /* Pointer to step-local data. */ }; /* Additional data for steps in use of conversion descriptor. This is @@ -87,7 +93,9 @@ struct gconv_step_data int is_last; - void *data; /* Pointer to step-local data. */ + mbstate_t *statep; + mbstate_t __state; /* This element should not be used directly by + any module; always use STATEP! */ }; diff --git a/iconv/gconv_builtin.h b/iconv/gconv_builtin.h index 8e5d692..9c98c35 100644 --- a/iconv/gconv_builtin.h +++ b/iconv/gconv_builtin.h @@ -23,30 +23,22 @@ BUILTIN_ALIAS ("UTF-8//", "ISO-10646/UTF8/") BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15, "ISO-10646/UTF8/", 1, "=ucs4->utf8", - __gconv_transform_ucs4_utf8, - __gconv_transform_init_rstate, - __gconv_transform_end_rstate) + __gconv_transform_ucs4_utf8, NULL, NULL) BUILTIN_TRANSFORMATION ("ISO-10646/UTF-?8/", "ISO-10646/UTF", 13, "ISO-10646/UCS4/", 1, "=utf8->ucs4", - __gconv_transform_utf8_ucs4, - __gconv_transform_init_rstate, - __gconv_transform_end_rstate) + __gconv_transform_utf8_ucs4, NULL, NULL) BUILTIN_ALIAS ("UCS2//", "ISO-10646/UCS2/") BUILTIN_ALIAS ("UCS-2//", "ISO-10646/UCS2/") BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS2/", 15, "ISO-10646/UCS4/", 1, "=ucs2->ucs4", - __gconv_transform_ucs2_ucs4, - __gconv_transform_init_rstate, - __gconv_transform_end_rstate) + __gconv_transform_ucs2_ucs4, NULL, NULL) BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15, "ISO-10646/UCS2/", 1, "=ucs4->ucs2", - __gconv_transform_ucs4_ucs2, - __gconv_transform_init_rstate, - __gconv_transform_end_rstate) + __gconv_transform_ucs4_ucs2, NULL, NULL) BUILTIN_TRANSFORMATION ("(.*)", NULL, 0, "\\1", 1, "=dummy", __gconv_transform_dummy, NULL, NULL) diff --git a/iconv/gconv_close.c b/iconv/gconv_close.c index b6d5fbc..de0937d 100644 --- a/iconv/gconv_close.c +++ b/iconv/gconv_close.c @@ -38,24 +38,11 @@ __gconv_close (gconv_t cd) drunp = cd->data; do { - /* Call destructor. */ - if (srunp->end_fct != NULL) - (*srunp->end_fct) (drunp); - else - if (drunp->data != NULL) - free (drunp->data); - if (!drunp->is_last && drunp->outbuf != NULL) free (drunp->outbuf); - - /* Next step. */ - ++srunp; } while (!(drunp++)->is_last); - /* Save the pointer, we need it below. */ - srunp = cd->steps; - /* Free the data allocated for the descriptor. */ free (cd->data); free (cd); diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c index 5a3932c..e0a94e4 100644 --- a/iconv/gconv_db.c +++ b/iconv/gconv_db.c @@ -34,6 +34,9 @@ void *__gconv_alias_db; size_t __gconv_nmodules; struct gconv_module **__gconv_modules_db; +/* We modify global data. */ +__libc_lock_define_initialized (static, lock) + /* Function for searching alias. */ int @@ -128,9 +131,7 @@ add_derivation (const char *fromset, const char *toset, malloc (sizeof (struct known_derivation) + fromset_len + toset_len); if (new_deriv != NULL) { - new_deriv->from = memcpy ((char *) new_deriv - + sizeof (struct known_derivation), - fromset, fromset_len); + new_deriv->from = memcpy (new_deriv + 1, fromset, fromset_len); new_deriv->to = memcpy ((char *) new_deriv->from + fromset_len, toset, toset_len); @@ -149,6 +150,11 @@ internal_function free_derivation (void *p) { struct known_derivation *deriv = (struct known_derivation *) p; + size_t cnt; + + for (cnt = 0; cnt < deriv->nsteps; ++cnt) + if (deriv->steps[cnt].end_fct) + (*deriv->steps[cnt].end_fct) (&deriv->steps[cnt]); free ((struct gconv_step *) deriv->steps); free (deriv); @@ -189,7 +195,7 @@ gen_steps (struct derivation_step *best, const char *toset, if (current->code->module_name[0] == '/') { /* Load the module, return handle for it. */ - void *shlib_handle = + struct gconv_loaded_object *shlib_handle = __gconv_find_shlib (current->code->module_name); if (shlib_handle == NULL) @@ -199,27 +205,21 @@ gen_steps (struct derivation_step *best, const char *toset, } result[step_cnt].shlib_handle = shlib_handle; - - result[step_cnt].fct = __gconv_find_func (shlib_handle, "gconv"); - if (result[step_cnt].fct == NULL) - { - /* Argh, no conversion function. There is something - wrong here. */ - __gconv_release_shlib (result[step_cnt].shlib_handle); - failed = 1; - break; - } - - result[step_cnt].init_fct = __gconv_find_func (shlib_handle, - "gconv_init"); - result[step_cnt].end_fct = __gconv_find_func (shlib_handle, - "gconv_end"); + result[step_cnt].modname = shlib_handle->name; + result[step_cnt].counter = 0; + result[step_cnt].fct = shlib_handle->fct; + result[step_cnt].init_fct = shlib_handle->init_fct; + result[step_cnt].end_fct = shlib_handle->end_fct; } else /* It's a builtin transformation. */ __gconv_get_builtin_trans (current->code->module_name, &result[step_cnt]); + /* Call the init function. */ + if (result[step_cnt].init_fct != NULL) + (*result[step_cnt].init_fct) (&result[step_cnt]); + current = current->last; } @@ -227,7 +227,11 @@ gen_steps (struct derivation_step *best, const char *toset, { /* Something went wrong while initializing the modules. */ while (++step_cnt < *nsteps) - __gconv_release_shlib (result[step_cnt].shlib_handle); + { + if (result[step_cnt].end_fct != NULL) + (*result[step_cnt].end_fct) (&result[step_cnt]); + __gconv_release_shlib (result[step_cnt].shlib_handle); + } free (result); *nsteps = 0; status = GCONV_NOCONV; @@ -273,7 +277,8 @@ find_derivation (const char *toset, const char *toset_expand, /* ### TODO For now we use a simple algorithm with quadratic runtime behaviour. - The task is to match the `toset' with any of the available. */ + The task is to match the `toset' with any of the available rules, + starting from FROMSET. */ if (fromset_expand != NULL) { first = NEW_STEP (fromset_expand, NULL, NULL); @@ -495,6 +500,9 @@ __gconv_find_transform (const char *toset, const char *fromset, /* Ensure that the configuration data is read. */ __libc_once (once, __gconv_read_conf); + /* Acquire the lock. */ + __libc_lock_lock (lock); + /* If we don't have a module database return with an error. */ if (__gconv_modules_db == NULL) return GCONV_NOCONV; @@ -517,6 +525,33 @@ __gconv_find_transform (const char *toset, const char *fromset, result = find_derivation (toset, toset_expand, fromset, fromset_expand, handle, nsteps); + /* Increment the user counter. */ + if (result == GCONV_OK) + { + size_t cnt = *nsteps; + struct gconv_step *steps = *handle; + + do + if (steps[--cnt].counter++ == 0) + { + steps[--cnt].shlib_handle = + __gconv_find_shlib (steps[--cnt].modname); + if (steps[--cnt].shlib_handle == NULL) + { + /* Oops, this is the second time we use this module (after + unloading) and this time loading failed!? */ + while (++cnt < *nsteps) + __gconv_release_shlib (steps[cnt].shlib_handle); + result = GCONV_NOCONV; + break; + } + } + while (cnt > 0); + } + + /* Release the lock. */ + __libc_lock_unlock (lock); + /* The following code is necessary since `find_derivation' will return GCONV_OK even when no derivation was found but the same request was processed before. I.e., negative results will also be cached. */ @@ -533,14 +568,22 @@ __gconv_close_transform (struct gconv_step *steps, size_t nsteps) { int result = GCONV_OK; + /* Acquire the lock. */ + __libc_lock_lock (lock); + while (nsteps-- > 0) - if (steps[nsteps].shlib_handle != NULL) + if (steps[nsteps].shlib_handle != NULL + && --steps[nsteps].counter == 0) { result = __gconv_release_shlib (steps[nsteps].shlib_handle); if (result != GCONV_OK) break; + steps[nsteps].shlib_handle = NULL; } + /* Release the lock. */ + __libc_lock_unlock (lock); + return result; } diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c index 2a7cc92..b11e156 100644 --- a/iconv/gconv_dl.c +++ b/iconv/gconv_dl.c @@ -40,27 +40,9 @@ #define TRIES_BEFORE_UNLOAD 2 -/* Structure describing one loaded shared object. This normally are - objects to perform conversation but as a special case the db shared - object is also handled. */ -struct loaded_object -{ - /* Name of the object. */ - const char *name; - - /* Reference counter for the db functionality. If no conversion is - needed we unload the db library. */ - int counter; - - /* The handle for the shared object. */ - void *handle; -}; - - /* Array of loaded objects. This is shared by all threads so we have to use semaphores to access it. */ static void *loaded; -__libc_lock_define_initialized (static, lock) @@ -68,8 +50,10 @@ __libc_lock_define_initialized (static, lock) static int known_compare (const void *p1, const void *p2) { - const struct loaded_object *s1 = (const struct loaded_object *) p1; - const struct loaded_object *s2 = (const struct loaded_object *) p2; + const struct gconv_loaded_object *s1 = + (const struct gconv_loaded_object *) p1; + const struct gconv_loaded_object *s2 = + (const struct gconv_loaded_object *) p2; return (intptr_t) s1->handle - (intptr_t) s2->handle; } @@ -78,7 +62,7 @@ known_compare (const void *p1, const void *p2) static void do_open (void *a) { - struct loaded_object *args = (struct loaded_object *) a; + struct gconv_loaded_object *args = (struct gconv_loaded_object *) a; /* Open and relocate the shared object. */ args->handle = _dl_open (args->name, RTLD_LAZY); } @@ -124,9 +108,9 @@ get_sym (void *a) } -void * +static void * internal_function -__gconv_find_func (void *handle, const char *name) +find_func (void *handle, const char *name) { struct get_sym_args args; @@ -141,15 +125,11 @@ __gconv_find_func (void *handle, const char *name) /* Open the gconv database if necessary. A non-negative return value means success. */ -void * +struct gconv_loaded_object * internal_function __gconv_find_shlib (const char *name) { - void *result = NULL; - struct loaded_object *found; - - /* Acquire the lock. */ - __libc_lock_lock (lock); + struct gconv_loaded_object *found; /* Search the tree of shared objects previously requested. Data in the tree are `loaded_object' structures, whose first member is a @@ -164,7 +144,7 @@ __gconv_find_shlib (const char *name) if (found == NULL) { /* This name was not known before. */ - found = malloc (sizeof (struct loaded_object)); + found = malloc (sizeof (struct gconv_loaded_object)); if (found != NULL) { /* Point the tree node at this new structure. */ @@ -189,35 +169,50 @@ __gconv_find_shlib (const char *name) if (found->counter < -TRIES_BEFORE_UNLOAD) { if (dlerror_run (do_open, found) == 0) - found->counter = 1; + { + found->fct = find_func (found->handle, "gconv"); + if (found->fct == NULL) + { + /* Argh, no conversion function. There is something + wrong here. */ + __gconv_release_shlib (found); + found = NULL; + } + else + { + found->init_fct = find_func (found->handle, "gconv_init"); + found->end_fct = find_func (found->handle, "gconv_end"); + + /* We have succeeded in loading the shared object. */ + found->counter = 1; + } + } + else + /* Error while loading the shared object. */ + found = NULL; } else if (found->handle != NULL) found->counter = MAX (found->counter + 1, 1); - - result = found->handle; } - /* Release the lock. */ - __libc_lock_unlock (lock); - - return result; + return found; } /* This is very ugly but the tsearch functions provide no way to pass information to the walker function. So we use a global variable. It is MT safe since we use a lock. */ -static void *release_handle; +static struct gconv_loaded_object *release_handle; static void do_release_shlib (const void *nodep, VISIT value, int level) { - struct loaded_object *obj = *(struct loaded_object **) nodep; + struct gconv_loaded_object *obj = *(struct gconv_loaded_object **) nodep; if (value != preorder && value != leaf) return; - if (obj->handle == release_handle) + if (obj == release_handle) /* This is the object we want to unload. Now set the release counter to zero. */ obj->counter = 0; @@ -228,7 +223,7 @@ do_release_shlib (const void *nodep, VISIT value, int level) /* Unload the shared object. We don't use the trick to catch errors since in the case an error is signalled something is really wrong. */ - _dl_close ((struct link_map *) obj->handle); + _dl_close (obj->handle); obj->handle = NULL; } @@ -239,11 +234,8 @@ do_release_shlib (const void *nodep, VISIT value, int level) /* Notify system that a shared object is not longer needed. */ int internal_function -__gconv_release_shlib (void *handle) +__gconv_release_shlib (struct gconv_loaded_object *handle) { - /* Acquire the lock. */ - __libc_lock_lock (lock); - /* Urgh, this is ugly but we have no other possibility. */ release_handle = handle; @@ -252,8 +244,5 @@ __gconv_release_shlib (void *handle) if necessary. */ __twalk (loaded, do_release_shlib); - /* Release the lock. */ - __libc_lock_unlock (lock); - return GCONV_OK; } diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h index 5261284..5e0723e 100644 --- a/iconv/gconv_int.h +++ b/iconv/gconv_int.h @@ -29,8 +29,8 @@ __BEGIN_DECLS /* Structure for alias definition. Simply to strings. */ struct gconv_alias { - __const char *fromname; - __const char *toname; + const char *fromname; + const char *toname; }; @@ -38,19 +38,41 @@ struct gconv_alias #define GCONV_DEFAULT_BUFSIZE 8160 +/* Structure describing one loaded shared object. This normally are + objects to perform conversation but as a special case the db shared + object is also handled. */ +struct gconv_loaded_object +{ + /* Name of the object. */ + const char *name; + + /* Reference counter for the db functionality. If no conversion is + needed we unload the db library. */ + int counter; + + /* The handle for the shared object. */ + struct link_map *handle; + + /* Pointer to the functions the module defines. */ + gconv_fct fct; + gconv_init_fct init_fct; + gconv_end_fct end_fct; +}; + + /* Description for an available conversion module. */ struct gconv_module { - __const char *from_pattern; - __const char *from_constpfx; + const char *from_pattern; + const char *from_constpfx; size_t from_constpfx_len; - __const regex_t *from_regex; + const regex_t *from_regex; - __const char *to_string; + const char *to_string; int cost; - __const char *module_name; + const char *module_name; }; @@ -65,65 +87,56 @@ extern struct gconv_module **__gconv_modules_db; /* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */ -extern int __gconv_open __P ((__const char *__toset, __const char *__fromset, - gconv_t *__handle)) +extern int __gconv_open (const char *__toset, const char *__fromset, + gconv_t *__handle) internal_function; /* Free resources associated with transformation descriptor CD. */ -extern int __gconv_close __P ((gconv_t cd)) +extern int __gconv_close (gconv_t cd) internal_function; /* Transform at most *INBYTESLEFT bytes from buffer starting at *INBUF according to rules described by CD and place up to *OUTBYTESLEFT bytes in buffer starting at *OUTBUF. Return number of written characters in *CONVERTED if this pointer is not null. */ -extern int __gconv __P ((gconv_t __cd, - __const char **__inbuf, size_t *__inbytesleft, - char **__outbuf, size_t *__outbytesleft, - size_t *__converted)) +extern int __gconv (gconv_t __cd, const char **__inbuf, size_t *__inbytesleft, + char **__outbuf, size_t *__outbytesleft, + size_t *__converted) internal_function; /* Return in *HANDLE a pointer to an array with *NSTEPS elements describing the single steps necessary for transformation from FROMSET to TOSET. */ -extern int __gconv_find_transform __P ((__const char *__toset, - __const char *__fromset, - struct gconv_step **__handle, - size_t *__nsteps)) +extern int __gconv_find_transform (const char *__toset, const char *__fromset, + struct gconv_step **__handle, + size_t *__nsteps) internal_function; /* Read all the configuration data and cache it. */ -extern void __gconv_read_conf __P ((void)) +extern void __gconv_read_conf (void) internal_function; /* Comparison function to search alias. */ -extern int __gconv_alias_compare __P ((__const void *__p1, - __const void *__p2)); +extern int __gconv_alias_compare (const void *__p1, const void *__p2); /* Clear reference to transformation step implementations which might cause the code to be unloaded. */ -extern int __gconv_close_transform __P ((struct gconv_step *__steps, - size_t __nsteps)) - internal_function; - - -/* Find in the shared object associated with HANDLE for a function with - name NAME. Return function pointer or NULL. */ -extern void *__gconv_find_func __P ((void *__handle, __const char *__name)) +extern int __gconv_close_transform (struct gconv_step *__steps, + size_t __nsteps) internal_function; /* Load shared object named by NAME. If already loaded increment reference count. */ -extern void *__gconv_find_shlib __P ((__const char *__name)) +extern struct gconv_loaded_object *__gconv_find_shlib (const char *__name) internal_function; /* Release shared object. If no further reference is available unload the object. */ -extern int __gconv_release_shlib __P ((void *__handle)) +extern int __gconv_release_shlib (struct gconv_loaded_object *__handle) internal_function; /* Fill STEP with information about builtin module with NAME. */ -extern void __gconv_get_builtin_trans __P ((__const char *__name, - struct gconv_step *__step)) +extern void __gconv_get_builtin_trans (const char *__name, + struct gconv_step *__step) internal_function; @@ -131,9 +144,9 @@ extern void __gconv_get_builtin_trans __P ((__const char *__name, /* Builtin transformations. */ #ifdef _LIBC # define __BUILTIN_TRANS(Name) \ - extern int Name __P ((struct gconv_step *__step, \ - struct gconv_step_data *__data, __const char *__inbuf,\ - size_t *__inlen, size_t *__written, int __do_flush)) + extern int Name (struct gconv_step *__step, struct gconv_step_data *__data, \ + const char *__inbuf, size_t *__inlen, size_t *__written, \ + int __do_flush) __BUILTIN_TRANS (__gconv_transform_dummy); __BUILTIN_TRANS (__gconv_transform_ucs4_utf8); @@ -142,10 +155,6 @@ __BUILTIN_TRANS (__gconv_transform_ucs2_ucs4); __BUILTIN_TRANS (__gconv_transform_ucs4_ucs2); # undef __BUITLIN_TRANS -extern int __gconv_transform_init_rstate __P ((struct gconv_step *__step, - struct gconv_step_data *__data)); -extern void __gconv_transform_end_rstate __P ((struct gconv_step_data *__data)); - #endif __END_DECLS diff --git a/iconv/gconv_open.c b/iconv/gconv_open.c index ea7b365..d82dcfe 100644 --- a/iconv/gconv_open.c +++ b/iconv/gconv_open.c @@ -65,25 +65,18 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle) buffer. Signal this to the initializer. */ data[cnt].is_last = cnt == nsteps - 1; - if (steps[cnt].init_fct != NULL) - { - res = (steps[cnt].init_fct) (&steps[cnt], &data[cnt]); - if (res != GCONV_OK) - break; - } + /* We use the `mbstate_t' member in DATA. */ + data[cnt].statep = &data[cnt].__state; - if (!data[cnt].is_last && data[cnt].outbuf == NULL) + /* Allocate the buffer. */ + data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE; + data[cnt].outbuf = (char *) malloc (data[cnt].outbufsize); + if (data[cnt].outbuf == NULL) { - data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE; - data[cnt].outbuf = - (char *) malloc (data[cnt].outbufsize); - if (data[cnt].outbuf == NULL) - { - res = GCONV_NOMEM; - break; - } - data[cnt].outbufavail = 0; + res = GCONV_NOMEM; + break; } + data[cnt].outbufavail = 0; } } } @@ -99,14 +92,7 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle) if (result->data != NULL) { while (cnt-- > 0) - if (steps[cnt].end_fct != NULL) - (*steps[cnt].end_fct) (&result->data[cnt]); - else - { - free (result->data[cnt].outbuf); - if (result->data[cnt].data != NULL) - free (result->data[cnt].data); - } + free (result->data[cnt].outbuf); free (result->data); } diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c index 280ecf5..7fbdfba 100644 --- a/iconv/gconv_simple.c +++ b/iconv/gconv_simple.c @@ -59,26 +59,6 @@ __gconv_transform_dummy (struct gconv_step *step, struct gconv_step_data *data, int -__gconv_transform_init_rstate (struct gconv_step *step, - struct gconv_step_data *data) -{ - /* We have to provide the transformation function an correctly initialized - object of type `mbstate_t'. This must be dynamically allocated. */ - data->data = calloc (1, sizeof (mbstate_t)); - - return data->data == NULL ? GCONV_NOMEM : GCONV_OK; -} - - -void -__gconv_transform_end_rstate (struct gconv_step_data *data) -{ - if (data->data != NULL) - free (data->data); -} - - -int __gconv_transform_ucs4_utf8 (struct gconv_step *step, struct gconv_step_data *data, const char *inbuf, size_t *inlen, size_t *written, int do_flush) @@ -95,7 +75,7 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step, if (do_flush) { /* Clear the state. */ - memset (data->data, '\0', sizeof (mbstate_t)); + memset (data->statep, '\0', sizeof (mbstate_t)); do_write = 0; /* Call the steps down the chain if there are any. */ @@ -127,7 +107,7 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step, (const wchar_t **) &newinbuf, *inlen / sizeof (wchar_t), data->outbufsize - data->outbufavail, - (mbstate_t *) data->data); + data->statep); /* Remember how much we converted. */ do_write += newinbuf - inbuf; @@ -200,7 +180,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step, if (do_flush) { /* Clear the state. */ - memset (data->data, '\0', sizeof (mbstate_t)); + memset (data->statep, '\0', sizeof (mbstate_t)); do_write = 0; /* Call the steps down the chain if there are any. */ @@ -229,7 +209,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step, &newinbuf, *inlen, ((data->outbufsize - data->outbufavail) / sizeof (wchar_t)), - (mbstate_t *) data->data); + data->statep); /* Remember how much we converted. */ do_write += actually; @@ -244,7 +224,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step, break; } - if (*inlen == 0 && !mbsinit ((mbstate_t *) data->data)) + if (*inlen == 0 && !mbsinit (data->statep)) { /* We have an incomplete character at the end. */ result = GCONV_INCOMPLETE_INPUT; @@ -309,7 +289,7 @@ __gconv_transform_ucs2_ucs4 (struct gconv_step *step, if (do_flush) { /* Clear the state. */ - memset (data->data, '\0', sizeof (mbstate_t)); + memset (data->statep, '\0', sizeof (mbstate_t)); do_write = 0; /* Call the steps down the chain if there are any. */ @@ -347,7 +327,7 @@ __gconv_transform_ucs2_ucs4 (struct gconv_step *step, if (*inlen != 1) { /* We have an incomplete input character. */ - mbstate_t *state = (mbstate_t *) data->data; + mbstate_t *state = data->statep; state->count = 1; state->value = *(uint8_t *) newinbuf; --*inlen; @@ -363,7 +343,7 @@ __gconv_transform_ucs2_ucs4 (struct gconv_step *step, break; } - if (*inlen == 0 && !mbsinit ((mbstate_t *) data->data)) + if (*inlen == 0 && !mbsinit (data->statep)) { /* We have an incomplete character at the end. */ result = GCONV_INCOMPLETE_INPUT; @@ -428,7 +408,7 @@ __gconv_transform_ucs4_ucs2 (struct gconv_step *step, if (do_flush) { /* Clear the state. */ - memset (data->data, '\0', sizeof (mbstate_t)); + memset (data->statep, '\0', sizeof (mbstate_t)); do_write = 0; /* Call the steps down the chain if there are any. */ @@ -474,7 +454,7 @@ __gconv_transform_ucs4_ucs2 (struct gconv_step *step, if (*inlen < 4) { /* We have an incomplete input character. */ - mbstate_t *state = (mbstate_t *) data->data; + mbstate_t *state = data->statep; state->count = *inlen; state->value = 0; while (*inlen > 0) @@ -495,7 +475,7 @@ __gconv_transform_ucs4_ucs2 (struct gconv_step *step, break; } - if (*inlen == 0 && !mbsinit ((mbstate_t *) data->data)) + if (*inlen == 0 && !mbsinit (data->statep)) { /* We have an incomplete character at the end. */ result = GCONV_INCOMPLETE_INPUT; diff --git a/iconvdata/8bit-gap.c b/iconvdata/8bit-gap.c index 301bd6b..1528cb6 100644 --- a/iconvdata/8bit-gap.c +++ b/iconvdata/8bit-gap.c @@ -50,7 +50,7 @@ struct s_8bit_data int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct s_8bit_data *new_data; @@ -71,7 +71,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -80,7 +80,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -119,7 +119,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct s_8bit_data *) data->data)->dir; + enum direction dir = ((struct s_8bit_data *) step->data)->dir; do_write = 0; diff --git a/iconvdata/8bit-generic.c b/iconvdata/8bit-generic.c index e8493fc..7f0bbae 100644 --- a/iconvdata/8bit-generic.c +++ b/iconvdata/8bit-generic.c @@ -37,7 +37,7 @@ struct s_8bit_data int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct s_8bit_data *new_data; @@ -58,7 +58,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -67,7 +67,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -106,7 +106,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct s_8bit_data *) data->data)->dir; + enum direction dir = ((struct s_8bit_data *) step->data)->dir; do_write = 0; diff --git a/iconvdata/euckr.c b/iconvdata/euckr.c index ba58034..9789e88 100644 --- a/iconvdata/euckr.c +++ b/iconvdata/euckr.c @@ -63,7 +63,7 @@ euckr_from_ucs4(wchar_t ch, unsigned char *cp) int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct euckr_data *new_data; @@ -84,7 +84,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -93,7 +93,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -132,7 +132,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct euckr_data *) data->data)->dir; + enum direction dir = ((struct euckr_data *) step->data)->dir; do_write = 0; diff --git a/iconvdata/iso646.c b/iconvdata/iso646.c index 3b4864e..a9705f0 100644 --- a/iconvdata/iso646.c +++ b/iconvdata/iso646.c @@ -58,7 +58,7 @@ struct iso646_data int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct iso646_data *new_data; @@ -100,7 +100,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) { new_data->dir = dir; new_data->var = var; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -109,7 +109,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -148,8 +148,8 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct iso646_data *) data->data)->dir; - enum variant var = ((struct iso646_data *) data->data)->var; + enum direction dir = ((struct iso646_data *) step->data)->dir; + enum variant var = ((struct iso646_data *) step->data)->var; do_write = 0; diff --git a/iconvdata/iso6937.c b/iconvdata/iso6937.c index 0108036..377eef5 100644 --- a/iconvdata/iso6937.c +++ b/iconvdata/iso6937.c @@ -387,7 +387,7 @@ struct iso6937_data int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct iso6937_data *new_data; @@ -408,7 +408,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -417,7 +417,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -456,7 +456,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct iso6937_data *) data->data)->dir; + enum direction dir = ((struct iso6937_data *) step->data)->dir; do_write = 0; diff --git a/iconvdata/iso8859-1.c b/iconvdata/iso8859-1.c index 5f98adc..cdeb526 100644 --- a/iconvdata/iso8859-1.c +++ b/iconvdata/iso8859-1.c @@ -37,7 +37,7 @@ struct iso88591_data int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct iso88591_data *new_data; @@ -58,7 +58,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -67,7 +67,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -106,7 +106,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct iso88591_data *) data->data)->dir; + enum direction dir = ((struct iso88591_data *) step->data)->dir; do_write = 0; diff --git a/iconvdata/johab.c b/iconvdata/johab.c index 3acd5fc..bde56ce 100644 --- a/iconvdata/johab.c +++ b/iconvdata/johab.c @@ -239,7 +239,7 @@ johab_from_ucs4 (wchar_t ch, unsigned char *cp) int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct johab_data *new_data; @@ -260,7 +260,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -269,7 +269,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -308,7 +308,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct johab_data *) data->data)->dir; + enum direction dir = ((struct johab_data *) step->data)->dir; do_write = 0; diff --git a/iconvdata/sjis.c b/iconvdata/sjis.c index 492bbd7..f713db1 100644 --- a/iconvdata/sjis.c +++ b/iconvdata/sjis.c @@ -3997,7 +3997,7 @@ struct sjis_data int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct sjis_data *new_data; @@ -4018,7 +4018,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -4027,7 +4027,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -4066,7 +4066,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct sjis_data *) data->data)->dir; + enum direction dir = ((struct sjis_data *) step->data)->dir; do_write = 0; diff --git a/iconvdata/t61.c b/iconvdata/t61.c index a8de21c..7d4314d 100644 --- a/iconvdata/t61.c +++ b/iconvdata/t61.c @@ -378,7 +378,7 @@ struct t61_data int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct t61_data *new_data; @@ -399,7 +399,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -408,7 +408,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -447,7 +447,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct t61_data *) data->data)->dir; + enum direction dir = ((struct t61_data *) step->data)->dir; do_write = 0; diff --git a/iconvdata/uhc.c b/iconvdata/uhc.c index c64ff1b..9e5f009 100644 --- a/iconvdata/uhc.c +++ b/iconvdata/uhc.c @@ -2623,7 +2623,7 @@ uhc_from_ucs4(wchar_t ch, unsigned char *cp) int -gconv_init (struct gconv_step *step, struct gconv_step_data *data) +gconv_init (struct gconv_step *step) { /* Determine which direction. */ struct uhc_data *new_data; @@ -2643,7 +2643,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) = (struct uhc_data *) malloc (sizeof (struct uhc_data))) != NULL)) { new_data->dir = dir; - data->data = new_data; + step->data = new_data; result = GCONV_OK; } @@ -2652,7 +2652,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data) void -gconv_end (struct gconv_step_data *data) +gconv_end (struct gconv_step *data) { free (data->data); } @@ -2691,7 +2691,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data, } else { - enum direction dir = ((struct uhc_data *) data->data)->dir; + enum direction dir = ((struct uhc_data *) step->data)->dir; do_write = 0; -- 2.7.4