1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-08 17:42:12 +03:00
1998-04-03 23:17  Ulrich Drepper  <drepper@cygnus.com>

	* 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.
This commit is contained in:
Ulrich Drepper
1998-04-04 07:25:25 +00:00
parent e62c19f12c
commit 0d9f67937f
20 changed files with 253 additions and 236 deletions

View File

@@ -1,3 +1,25 @@
1998-04-03 23:17 Ulrich Drepper <drepper@cygnus.com>
* 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 <drepper@cygnus.com> 1998-04-03 15:34 Ulrich Drepper <drepper@cygnus.com>
* iconv/gconv_int.h: New file. Internal header. * iconv/gconv_int.h: New file. Internal header.

View File

@@ -23,6 +23,7 @@
int int
internal_function
__gconv (gconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, __gconv (gconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
size_t *outbytesleft, size_t *converted) size_t *outbytesleft, size_t *converted)
{ {

View File

@@ -24,6 +24,7 @@
#define _GCONV_H 1 #define _GCONV_H 1
#include <features.h> #include <features.h>
#include <wchar.h>
#define __need_size_t #define __need_size_t
#include <stddef.h> #include <stddef.h>
@@ -51,6 +52,7 @@ enum
/* Forward declarations. */ /* Forward declarations. */
struct gconv_step; struct gconv_step;
struct gconv_step_data; struct gconv_step_data;
struct gconv_loaded_object;
/* Type of a conversion function. */ /* Type of a conversion function. */
@@ -59,15 +61,17 @@ typedef int (*gconv_fct) __P ((struct gconv_step *,
__const char *, size_t *, size_t *, int)); __const char *, size_t *, size_t *, int));
/* Constructor and destructor for local data for conversion step. */ /* Constructor and destructor for local data for conversion step. */
typedef int (*gconv_init_fct) __P ((struct gconv_step *, typedef int (*gconv_init_fct) __P ((struct gconv_step *));
struct gconv_step_data *)); typedef void (*gconv_end_fct) __P ((struct gconv_step *));
typedef void (*gconv_end_fct) __P ((struct gconv_step_data *));
/* Description of a conversion step. */ /* Description of a conversion step. */
struct gconv_step struct gconv_step
{ {
void *shlib_handle; struct gconv_loaded_object *shlib_handle;
const char *modname;
int counter;
__const char *from_name; __const char *from_name;
__const char *to_name; __const char *to_name;
@@ -75,6 +79,8 @@ struct gconv_step
gconv_fct fct; gconv_fct fct;
gconv_init_fct init_fct; gconv_init_fct init_fct;
gconv_end_fct end_fct; gconv_end_fct end_fct;
void *data; /* Pointer to step-local data. */
}; };
/* Additional data for steps in use of conversion descriptor. This is /* Additional data for steps in use of conversion descriptor. This is
@@ -87,7 +93,9 @@ struct gconv_step_data
int is_last; 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! */
}; };

View File

@@ -23,30 +23,22 @@ BUILTIN_ALIAS ("UTF-8//", "ISO-10646/UTF8/")
BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15, BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15,
"ISO-10646/UTF8/", 1, "=ucs4->utf8", "ISO-10646/UTF8/", 1, "=ucs4->utf8",
__gconv_transform_ucs4_utf8, __gconv_transform_ucs4_utf8, NULL, NULL)
__gconv_transform_init_rstate,
__gconv_transform_end_rstate)
BUILTIN_TRANSFORMATION ("ISO-10646/UTF-?8/", "ISO-10646/UTF", 13, BUILTIN_TRANSFORMATION ("ISO-10646/UTF-?8/", "ISO-10646/UTF", 13,
"ISO-10646/UCS4/", 1, "=utf8->ucs4", "ISO-10646/UCS4/", 1, "=utf8->ucs4",
__gconv_transform_utf8_ucs4, __gconv_transform_utf8_ucs4, NULL, NULL)
__gconv_transform_init_rstate,
__gconv_transform_end_rstate)
BUILTIN_ALIAS ("UCS2//", "ISO-10646/UCS2/") BUILTIN_ALIAS ("UCS2//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2//", "ISO-10646/UCS2/") BUILTIN_ALIAS ("UCS-2//", "ISO-10646/UCS2/")
BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS2/", 15, "ISO-10646/UCS4/", BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS2/", 15, "ISO-10646/UCS4/",
1, "=ucs2->ucs4", 1, "=ucs2->ucs4",
__gconv_transform_ucs2_ucs4, __gconv_transform_ucs2_ucs4, NULL, NULL)
__gconv_transform_init_rstate,
__gconv_transform_end_rstate)
BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15, "ISO-10646/UCS2/", BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15, "ISO-10646/UCS2/",
1, "=ucs4->ucs2", 1, "=ucs4->ucs2",
__gconv_transform_ucs4_ucs2, __gconv_transform_ucs4_ucs2, NULL, NULL)
__gconv_transform_init_rstate,
__gconv_transform_end_rstate)
BUILTIN_TRANSFORMATION ("(.*)", NULL, 0, "\\1", 1, "=dummy", BUILTIN_TRANSFORMATION ("(.*)", NULL, 0, "\\1", 1, "=dummy",
__gconv_transform_dummy, NULL, NULL) __gconv_transform_dummy, NULL, NULL)

View File

@@ -38,24 +38,11 @@ __gconv_close (gconv_t cd)
drunp = cd->data; drunp = cd->data;
do 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) if (!drunp->is_last && drunp->outbuf != NULL)
free (drunp->outbuf); free (drunp->outbuf);
/* Next step. */
++srunp;
} }
while (!(drunp++)->is_last); while (!(drunp++)->is_last);
/* Save the pointer, we need it below. */
srunp = cd->steps;
/* Free the data allocated for the descriptor. */ /* Free the data allocated for the descriptor. */
free (cd->data); free (cd->data);
free (cd); free (cd);

View File

@@ -34,6 +34,9 @@ void *__gconv_alias_db;
size_t __gconv_nmodules; size_t __gconv_nmodules;
struct gconv_module **__gconv_modules_db; struct gconv_module **__gconv_modules_db;
/* We modify global data. */
__libc_lock_define_initialized (static, lock)
/* Function for searching alias. */ /* Function for searching alias. */
int int
@@ -128,9 +131,7 @@ add_derivation (const char *fromset, const char *toset,
malloc (sizeof (struct known_derivation) + fromset_len + toset_len); malloc (sizeof (struct known_derivation) + fromset_len + toset_len);
if (new_deriv != NULL) if (new_deriv != NULL)
{ {
new_deriv->from = memcpy ((char *) new_deriv new_deriv->from = memcpy (new_deriv + 1, fromset, fromset_len);
+ sizeof (struct known_derivation),
fromset, fromset_len);
new_deriv->to = memcpy ((char *) new_deriv->from + fromset_len, new_deriv->to = memcpy ((char *) new_deriv->from + fromset_len,
toset, toset_len); toset, toset_len);
@@ -149,6 +150,11 @@ internal_function
free_derivation (void *p) free_derivation (void *p)
{ {
struct known_derivation *deriv = (struct known_derivation *) 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 ((struct gconv_step *) deriv->steps);
free (deriv); free (deriv);
@@ -189,7 +195,7 @@ gen_steps (struct derivation_step *best, const char *toset,
if (current->code->module_name[0] == '/') if (current->code->module_name[0] == '/')
{ {
/* Load the module, return handle for it. */ /* Load the module, return handle for it. */
void *shlib_handle = struct gconv_loaded_object *shlib_handle =
__gconv_find_shlib (current->code->module_name); __gconv_find_shlib (current->code->module_name);
if (shlib_handle == NULL) 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].shlib_handle = shlib_handle;
result[step_cnt].modname = shlib_handle->name;
result[step_cnt].fct = __gconv_find_func (shlib_handle, "gconv"); result[step_cnt].counter = 0;
if (result[step_cnt].fct == NULL) result[step_cnt].fct = shlib_handle->fct;
{ result[step_cnt].init_fct = shlib_handle->init_fct;
/* Argh, no conversion function. There is something result[step_cnt].end_fct = shlib_handle->end_fct;
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");
} }
else else
/* It's a builtin transformation. */ /* It's a builtin transformation. */
__gconv_get_builtin_trans (current->code->module_name, __gconv_get_builtin_trans (current->code->module_name,
&result[step_cnt]); &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; current = current->last;
} }
@@ -227,7 +227,11 @@ gen_steps (struct derivation_step *best, const char *toset,
{ {
/* Something went wrong while initializing the modules. */ /* Something went wrong while initializing the modules. */
while (++step_cnt < *nsteps) 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); free (result);
*nsteps = 0; *nsteps = 0;
status = GCONV_NOCONV; status = GCONV_NOCONV;
@@ -273,7 +277,8 @@ find_derivation (const char *toset, const char *toset_expand,
/* ### TODO /* ### TODO
For now we use a simple algorithm with quadratic runtime behaviour. 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) if (fromset_expand != NULL)
{ {
first = NEW_STEP (fromset_expand, NULL, 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. */ /* Ensure that the configuration data is read. */
__libc_once (once, __gconv_read_conf); __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 we don't have a module database return with an error. */
if (__gconv_modules_db == NULL) if (__gconv_modules_db == NULL)
return GCONV_NOCONV; 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, result = find_derivation (toset, toset_expand, fromset, fromset_expand,
handle, nsteps); 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 /* The following code is necessary since `find_derivation' will return
GCONV_OK even when no derivation was found but the same request GCONV_OK even when no derivation was found but the same request
was processed before. I.e., negative results will also be cached. */ 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; int result = GCONV_OK;
/* Acquire the lock. */
__libc_lock_lock (lock);
while (nsteps-- > 0) 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); result = __gconv_release_shlib (steps[nsteps].shlib_handle);
if (result != GCONV_OK) if (result != GCONV_OK)
break; break;
steps[nsteps].shlib_handle = NULL;
} }
/* Release the lock. */
__libc_lock_unlock (lock);
return result; return result;
} }

View File

@@ -40,27 +40,9 @@
#define TRIES_BEFORE_UNLOAD 2 #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 /* Array of loaded objects. This is shared by all threads so we have
to use semaphores to access it. */ to use semaphores to access it. */
static void *loaded; static void *loaded;
__libc_lock_define_initialized (static, lock)
@@ -68,8 +50,10 @@ __libc_lock_define_initialized (static, lock)
static int static int
known_compare (const void *p1, const void *p2) known_compare (const void *p1, const void *p2)
{ {
const struct loaded_object *s1 = (const struct loaded_object *) p1; const struct gconv_loaded_object *s1 =
const struct loaded_object *s2 = (const struct loaded_object *) p2; (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; return (intptr_t) s1->handle - (intptr_t) s2->handle;
} }
@@ -78,7 +62,7 @@ known_compare (const void *p1, const void *p2)
static void static void
do_open (void *a) 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. */ /* Open and relocate the shared object. */
args->handle = _dl_open (args->name, RTLD_LAZY); args->handle = _dl_open (args->name, RTLD_LAZY);
} }
@@ -124,9 +108,9 @@ get_sym (void *a)
} }
void * static void *
internal_function internal_function
__gconv_find_func (void *handle, const char *name) find_func (void *handle, const char *name)
{ {
struct get_sym_args args; 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 /* Open the gconv database if necessary. A non-negative return value
means success. */ means success. */
void * struct gconv_loaded_object *
internal_function internal_function
__gconv_find_shlib (const char *name) __gconv_find_shlib (const char *name)
{ {
void *result = NULL; struct gconv_loaded_object *found;
struct loaded_object *found;
/* Acquire the lock. */
__libc_lock_lock (lock);
/* Search the tree of shared objects previously requested. Data in /* Search the tree of shared objects previously requested. Data in
the tree are `loaded_object' structures, whose first member is a the tree are `loaded_object' structures, whose first member is a
@@ -164,7 +144,7 @@ __gconv_find_shlib (const char *name)
if (found == NULL) if (found == NULL)
{ {
/* This name was not known before. */ /* This name was not known before. */
found = malloc (sizeof (struct loaded_object)); found = malloc (sizeof (struct gconv_loaded_object));
if (found != NULL) if (found != NULL)
{ {
/* Point the tree node at this new structure. */ /* 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 (found->counter < -TRIES_BEFORE_UNLOAD)
{ {
if (dlerror_run (do_open, found) == 0) 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) else if (found->handle != NULL)
found->counter = MAX (found->counter + 1, 1); found->counter = MAX (found->counter + 1, 1);
result = found->handle;
} }
/* Release the lock. */ return found;
__libc_lock_unlock (lock);
return result;
} }
/* This is very ugly but the tsearch functions provide no way to pass /* This is very ugly but the tsearch functions provide no way to pass
information to the walker function. So we use a global variable. information to the walker function. So we use a global variable.
It is MT safe since we use a lock. */ It is MT safe since we use a lock. */
static void *release_handle; static struct gconv_loaded_object *release_handle;
static void static void
do_release_shlib (const void *nodep, VISIT value, int level) 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) if (value != preorder && value != leaf)
return; return;
if (obj->handle == release_handle) if (obj == release_handle)
/* This is the object we want to unload. Now set the release /* This is the object we want to unload. Now set the release
counter to zero. */ counter to zero. */
obj->counter = 0; 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 /* Unload the shared object. We don't use the trick to
catch errors since in the case an error is signalled catch errors since in the case an error is signalled
something is really wrong. */ something is really wrong. */
_dl_close ((struct link_map *) obj->handle); _dl_close (obj->handle);
obj->handle = NULL; 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. */ /* Notify system that a shared object is not longer needed. */
int int
internal_function 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. */ /* Urgh, this is ugly but we have no other possibility. */
release_handle = handle; release_handle = handle;
@@ -252,8 +244,5 @@ __gconv_release_shlib (void *handle)
if necessary. */ if necessary. */
__twalk (loaded, do_release_shlib); __twalk (loaded, do_release_shlib);
/* Release the lock. */
__libc_lock_unlock (lock);
return GCONV_OK; return GCONV_OK;
} }

View File

@@ -29,8 +29,8 @@ __BEGIN_DECLS
/* Structure for alias definition. Simply to strings. */ /* Structure for alias definition. Simply to strings. */
struct gconv_alias struct gconv_alias
{ {
__const char *fromname; const char *fromname;
__const char *toname; const char *toname;
}; };
@@ -38,19 +38,41 @@ struct gconv_alias
#define GCONV_DEFAULT_BUFSIZE 8160 #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. */ /* Description for an available conversion module. */
struct gconv_module struct gconv_module
{ {
__const char *from_pattern; const char *from_pattern;
__const char *from_constpfx; const char *from_constpfx;
size_t from_constpfx_len; 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; 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. */ /* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */
extern int __gconv_open __P ((__const char *__toset, __const char *__fromset, extern int __gconv_open (const char *__toset, const char *__fromset,
gconv_t *__handle)) gconv_t *__handle)
internal_function; internal_function;
/* Free resources associated with transformation descriptor CD. */ /* Free resources associated with transformation descriptor CD. */
extern int __gconv_close __P ((gconv_t cd)) extern int __gconv_close (gconv_t cd)
internal_function; internal_function;
/* Transform at most *INBYTESLEFT bytes from buffer starting at *INBUF /* Transform at most *INBYTESLEFT bytes from buffer starting at *INBUF
according to rules described by CD and place up to *OUTBYTESLEFT according to rules described by CD and place up to *OUTBYTESLEFT
bytes in buffer starting at *OUTBUF. Return number of written bytes in buffer starting at *OUTBUF. Return number of written
characters in *CONVERTED if this pointer is not null. */ characters in *CONVERTED if this pointer is not null. */
extern int __gconv __P ((gconv_t __cd, extern int __gconv (gconv_t __cd, const char **__inbuf, size_t *__inbytesleft,
__const char **__inbuf, size_t *__inbytesleft, char **__outbuf, size_t *__outbytesleft,
char **__outbuf, size_t *__outbytesleft, size_t *__converted)
size_t *__converted))
internal_function; internal_function;
/* Return in *HANDLE a pointer to an array with *NSTEPS elements describing /* Return in *HANDLE a pointer to an array with *NSTEPS elements describing
the single steps necessary for transformation from FROMSET to TOSET. */ the single steps necessary for transformation from FROMSET to TOSET. */
extern int __gconv_find_transform __P ((__const char *__toset, extern int __gconv_find_transform (const char *__toset, const char *__fromset,
__const char *__fromset, struct gconv_step **__handle,
struct gconv_step **__handle, size_t *__nsteps)
size_t *__nsteps))
internal_function; internal_function;
/* Read all the configuration data and cache it. */ /* Read all the configuration data and cache it. */
extern void __gconv_read_conf __P ((void)) extern void __gconv_read_conf (void)
internal_function; internal_function;
/* Comparison function to search alias. */ /* Comparison function to search alias. */
extern int __gconv_alias_compare __P ((__const void *__p1, extern int __gconv_alias_compare (const void *__p1, const void *__p2);
__const void *__p2));
/* Clear reference to transformation step implementations which might /* Clear reference to transformation step implementations which might
cause the code to be unloaded. */ cause the code to be unloaded. */
extern int __gconv_close_transform __P ((struct gconv_step *__steps, extern int __gconv_close_transform (struct gconv_step *__steps,
size_t __nsteps)) 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))
internal_function; internal_function;
/* Load shared object named by NAME. If already loaded increment reference /* Load shared object named by NAME. If already loaded increment reference
count. */ count. */
extern void *__gconv_find_shlib __P ((__const char *__name)) extern struct gconv_loaded_object *__gconv_find_shlib (const char *__name)
internal_function; internal_function;
/* Release shared object. If no further reference is available unload /* Release shared object. If no further reference is available unload
the object. */ the object. */
extern int __gconv_release_shlib __P ((void *__handle)) extern int __gconv_release_shlib (struct gconv_loaded_object *__handle)
internal_function; internal_function;
/* Fill STEP with information about builtin module with NAME. */ /* Fill STEP with information about builtin module with NAME. */
extern void __gconv_get_builtin_trans __P ((__const char *__name, extern void __gconv_get_builtin_trans (const char *__name,
struct gconv_step *__step)) struct gconv_step *__step)
internal_function; internal_function;
@@ -131,9 +144,9 @@ extern void __gconv_get_builtin_trans __P ((__const char *__name,
/* Builtin transformations. */ /* Builtin transformations. */
#ifdef _LIBC #ifdef _LIBC
# define __BUILTIN_TRANS(Name) \ # define __BUILTIN_TRANS(Name) \
extern int Name __P ((struct gconv_step *__step, \ extern int Name (struct gconv_step *__step, struct gconv_step_data *__data, \
struct gconv_step_data *__data, __const char *__inbuf,\ const char *__inbuf, size_t *__inlen, size_t *__written, \
size_t *__inlen, size_t *__written, int __do_flush)) int __do_flush)
__BUILTIN_TRANS (__gconv_transform_dummy); __BUILTIN_TRANS (__gconv_transform_dummy);
__BUILTIN_TRANS (__gconv_transform_ucs4_utf8); __BUILTIN_TRANS (__gconv_transform_ucs4_utf8);
@@ -142,10 +155,6 @@ __BUILTIN_TRANS (__gconv_transform_ucs2_ucs4);
__BUILTIN_TRANS (__gconv_transform_ucs4_ucs2); __BUILTIN_TRANS (__gconv_transform_ucs4_ucs2);
# undef __BUITLIN_TRANS # 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 #endif
__END_DECLS __END_DECLS

View File

@@ -65,25 +65,18 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle)
buffer. Signal this to the initializer. */ buffer. Signal this to the initializer. */
data[cnt].is_last = cnt == nsteps - 1; data[cnt].is_last = cnt == nsteps - 1;
if (steps[cnt].init_fct != NULL) /* We use the `mbstate_t' member in DATA. */
{ data[cnt].statep = &data[cnt].__state;
res = (steps[cnt].init_fct) (&steps[cnt], &data[cnt]);
if (res != GCONV_OK)
break;
}
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; res = GCONV_NOMEM;
data[cnt].outbuf = break;
(char *) malloc (data[cnt].outbufsize);
if (data[cnt].outbuf == NULL)
{
res = GCONV_NOMEM;
break;
}
data[cnt].outbufavail = 0;
} }
data[cnt].outbufavail = 0;
} }
} }
} }
@@ -99,14 +92,7 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle)
if (result->data != NULL) if (result->data != NULL)
{ {
while (cnt-- > 0) while (cnt-- > 0)
if (steps[cnt].end_fct != NULL) free (result->data[cnt].outbuf);
(*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); free (result->data);
} }

View File

@@ -58,26 +58,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 int
__gconv_transform_ucs4_utf8 (struct gconv_step *step, __gconv_transform_ucs4_utf8 (struct gconv_step *step,
struct gconv_step_data *data, const char *inbuf, struct gconv_step_data *data, const char *inbuf,
@@ -95,7 +75,7 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step,
if (do_flush) if (do_flush)
{ {
/* Clear the state. */ /* Clear the state. */
memset (data->data, '\0', sizeof (mbstate_t)); memset (data->statep, '\0', sizeof (mbstate_t));
do_write = 0; do_write = 0;
/* Call the steps down the chain if there are any. */ /* 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, (const wchar_t **) &newinbuf,
*inlen / sizeof (wchar_t), *inlen / sizeof (wchar_t),
data->outbufsize - data->outbufavail, data->outbufsize - data->outbufavail,
(mbstate_t *) data->data); data->statep);
/* Remember how much we converted. */ /* Remember how much we converted. */
do_write += newinbuf - inbuf; do_write += newinbuf - inbuf;
@@ -200,7 +180,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step,
if (do_flush) if (do_flush)
{ {
/* Clear the state. */ /* Clear the state. */
memset (data->data, '\0', sizeof (mbstate_t)); memset (data->statep, '\0', sizeof (mbstate_t));
do_write = 0; do_write = 0;
/* Call the steps down the chain if there are any. */ /* Call the steps down the chain if there are any. */
@@ -229,7 +209,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step,
&newinbuf, *inlen, &newinbuf, *inlen,
((data->outbufsize ((data->outbufsize
- data->outbufavail) / sizeof (wchar_t)), - data->outbufavail) / sizeof (wchar_t)),
(mbstate_t *) data->data); data->statep);
/* Remember how much we converted. */ /* Remember how much we converted. */
do_write += actually; do_write += actually;
@@ -244,7 +224,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step,
break; break;
} }
if (*inlen == 0 && !mbsinit ((mbstate_t *) data->data)) if (*inlen == 0 && !mbsinit (data->statep))
{ {
/* We have an incomplete character at the end. */ /* We have an incomplete character at the end. */
result = GCONV_INCOMPLETE_INPUT; result = GCONV_INCOMPLETE_INPUT;
@@ -309,7 +289,7 @@ __gconv_transform_ucs2_ucs4 (struct gconv_step *step,
if (do_flush) if (do_flush)
{ {
/* Clear the state. */ /* Clear the state. */
memset (data->data, '\0', sizeof (mbstate_t)); memset (data->statep, '\0', sizeof (mbstate_t));
do_write = 0; do_write = 0;
/* Call the steps down the chain if there are any. */ /* 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) if (*inlen != 1)
{ {
/* We have an incomplete input character. */ /* We have an incomplete input character. */
mbstate_t *state = (mbstate_t *) data->data; mbstate_t *state = data->statep;
state->count = 1; state->count = 1;
state->value = *(uint8_t *) newinbuf; state->value = *(uint8_t *) newinbuf;
--*inlen; --*inlen;
@@ -363,7 +343,7 @@ __gconv_transform_ucs2_ucs4 (struct gconv_step *step,
break; break;
} }
if (*inlen == 0 && !mbsinit ((mbstate_t *) data->data)) if (*inlen == 0 && !mbsinit (data->statep))
{ {
/* We have an incomplete character at the end. */ /* We have an incomplete character at the end. */
result = GCONV_INCOMPLETE_INPUT; result = GCONV_INCOMPLETE_INPUT;
@@ -428,7 +408,7 @@ __gconv_transform_ucs4_ucs2 (struct gconv_step *step,
if (do_flush) if (do_flush)
{ {
/* Clear the state. */ /* Clear the state. */
memset (data->data, '\0', sizeof (mbstate_t)); memset (data->statep, '\0', sizeof (mbstate_t));
do_write = 0; do_write = 0;
/* Call the steps down the chain if there are any. */ /* 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) if (*inlen < 4)
{ {
/* We have an incomplete input character. */ /* We have an incomplete input character. */
mbstate_t *state = (mbstate_t *) data->data; mbstate_t *state = data->statep;
state->count = *inlen; state->count = *inlen;
state->value = 0; state->value = 0;
while (*inlen > 0) while (*inlen > 0)
@@ -495,7 +475,7 @@ __gconv_transform_ucs4_ucs2 (struct gconv_step *step,
break; break;
} }
if (*inlen == 0 && !mbsinit ((mbstate_t *) data->data)) if (*inlen == 0 && !mbsinit (data->statep))
{ {
/* We have an incomplete character at the end. */ /* We have an incomplete character at the end. */
result = GCONV_INCOMPLETE_INPUT; result = GCONV_INCOMPLETE_INPUT;

View File

@@ -50,7 +50,7 @@ struct s_8bit_data
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct s_8bit_data *new_data; struct s_8bit_data *new_data;
@@ -71,7 +71,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
!= NULL)) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -80,7 +80,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -119,7 +119,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct s_8bit_data *) data->data)->dir; enum direction dir = ((struct s_8bit_data *) step->data)->dir;
do_write = 0; do_write = 0;

View File

@@ -37,7 +37,7 @@ struct s_8bit_data
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct s_8bit_data *new_data; struct s_8bit_data *new_data;
@@ -58,7 +58,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
!= NULL)) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -67,7 +67,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -106,7 +106,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct s_8bit_data *) data->data)->dir; enum direction dir = ((struct s_8bit_data *) step->data)->dir;
do_write = 0; do_write = 0;

View File

@@ -63,7 +63,7 @@ euckr_from_ucs4(wchar_t ch, unsigned char *cp)
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct euckr_data *new_data; struct euckr_data *new_data;
@@ -84,7 +84,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
!= NULL)) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -93,7 +93,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -132,7 +132,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct euckr_data *) data->data)->dir; enum direction dir = ((struct euckr_data *) step->data)->dir;
do_write = 0; do_write = 0;

View File

@@ -58,7 +58,7 @@ struct iso646_data
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct iso646_data *new_data; 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->dir = dir;
new_data->var = var; new_data->var = var;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -109,7 +109,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -148,8 +148,8 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct iso646_data *) data->data)->dir; enum direction dir = ((struct iso646_data *) step->data)->dir;
enum variant var = ((struct iso646_data *) data->data)->var; enum variant var = ((struct iso646_data *) step->data)->var;
do_write = 0; do_write = 0;

View File

@@ -387,7 +387,7 @@ struct iso6937_data
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct iso6937_data *new_data; struct iso6937_data *new_data;
@@ -408,7 +408,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
!= NULL)) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -417,7 +417,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -456,7 +456,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct iso6937_data *) data->data)->dir; enum direction dir = ((struct iso6937_data *) step->data)->dir;
do_write = 0; do_write = 0;

View File

@@ -37,7 +37,7 @@ struct iso88591_data
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct iso88591_data *new_data; struct iso88591_data *new_data;
@@ -58,7 +58,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
!= NULL)) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -67,7 +67,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -106,7 +106,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct iso88591_data *) data->data)->dir; enum direction dir = ((struct iso88591_data *) step->data)->dir;
do_write = 0; do_write = 0;

View File

@@ -239,7 +239,7 @@ johab_from_ucs4 (wchar_t ch, unsigned char *cp)
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct johab_data *new_data; struct johab_data *new_data;
@@ -260,7 +260,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
!= NULL)) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -269,7 +269,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -308,7 +308,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct johab_data *) data->data)->dir; enum direction dir = ((struct johab_data *) step->data)->dir;
do_write = 0; do_write = 0;

View File

@@ -3997,7 +3997,7 @@ struct sjis_data
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct sjis_data *new_data; struct sjis_data *new_data;
@@ -4018,7 +4018,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
!= NULL)) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -4027,7 +4027,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -4066,7 +4066,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct sjis_data *) data->data)->dir; enum direction dir = ((struct sjis_data *) step->data)->dir;
do_write = 0; do_write = 0;

View File

@@ -378,7 +378,7 @@ struct t61_data
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct t61_data *new_data; struct t61_data *new_data;
@@ -399,7 +399,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
!= NULL)) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -408,7 +408,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -447,7 +447,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct t61_data *) data->data)->dir; enum direction dir = ((struct t61_data *) step->data)->dir;
do_write = 0; do_write = 0;

View File

@@ -2623,7 +2623,7 @@ uhc_from_ucs4(wchar_t ch, unsigned char *cp)
int int
gconv_init (struct gconv_step *step, struct gconv_step_data *data) gconv_init (struct gconv_step *step)
{ {
/* Determine which direction. */ /* Determine which direction. */
struct uhc_data *new_data; 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)) = (struct uhc_data *) malloc (sizeof (struct uhc_data))) != NULL))
{ {
new_data->dir = dir; new_data->dir = dir;
data->data = new_data; step->data = new_data;
result = GCONV_OK; result = GCONV_OK;
} }
@@ -2652,7 +2652,7 @@ gconv_init (struct gconv_step *step, struct gconv_step_data *data)
void void
gconv_end (struct gconv_step_data *data) gconv_end (struct gconv_step *data)
{ {
free (data->data); free (data->data);
} }
@@ -2691,7 +2691,7 @@ gconv (struct gconv_step *step, struct gconv_step_data *data,
} }
else else
{ {
enum direction dir = ((struct uhc_data *) data->data)->dir; enum direction dir = ((struct uhc_data *) step->data)->dir;
do_write = 0; do_write = 0;