mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 19:00:07 +00:00
Update.
2001-07-22 Ulrich Drepper <drepper@redhat.com> * iconv/gconv_builtin.c (struct builtin_map): Remove init and end elements. (BUILTIN_TRANSFORMATION): Remove Init and End parameters. (__gconv_get_builtin_trans): Initialize __init_fct and __end_fct to NULL. * iconv/gconv_builtin.h: Remove NULL parameters for Init and End in all BUILTIN_TRANSFORMATION calls. * iconv/gconv_conf.c (BUILTIN_TRANSFORMATION): Remove Init and End parameters. * iconv/gconv_simple.c: Likewise. * iconv/gconv_db.c (gen_steps): Internal converters don't have initializers, move the code accordingly. * iconv/gconv_conf.c (__gconv_read_conf): Don't read configuration file if STATIC_GCONV is defined. * iconv/gconv_conf.c (__gconv_path_envvar): New global variable. (__gconv_get_path): Use it instead of call getenv. (__gconv_read_conf): First see whether cache can be used. If yes, don't do any work here. * iconv/gconv_db.c (__gconv_release_step): Renamed from release_step and exported. Change callers. (__gconv_find_transform): First call __gconv_lookup_cache and only continue if it signals no cache available. Remove some unnecessary tests. * iconv/gconv_int.h: Declare __gconv_path_envvar, __gconv_lookup_cache, __gconv_release_step, and __gconv_loaded_cache. * iconv/gconv_cache.c: New file. * iconv/iconvconfig.c: New file. * iconv/iconvconfig.h: New file. * iconv/strtab.c: New file. * iconv/Makefile: Add rules to build new files and programs.
This commit is contained in:
parent
2c42236695
commit
6b98979fc9
35
ChangeLog
35
ChangeLog
@ -1,3 +1,38 @@
|
|||||||
|
2001-07-22 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* iconv/gconv_builtin.c (struct builtin_map): Remove init and end
|
||||||
|
elements.
|
||||||
|
(BUILTIN_TRANSFORMATION): Remove Init and End parameters.
|
||||||
|
(__gconv_get_builtin_trans): Initialize __init_fct and __end_fct to
|
||||||
|
NULL.
|
||||||
|
* iconv/gconv_builtin.h: Remove NULL parameters for Init and End in
|
||||||
|
all BUILTIN_TRANSFORMATION calls.
|
||||||
|
* iconv/gconv_conf.c (BUILTIN_TRANSFORMATION): Remove Init and End
|
||||||
|
parameters.
|
||||||
|
* iconv/gconv_simple.c: Likewise.
|
||||||
|
* iconv/gconv_db.c (gen_steps): Internal converters don't have
|
||||||
|
initializers, move the code accordingly.
|
||||||
|
|
||||||
|
* iconv/gconv_conf.c (__gconv_read_conf): Don't read configuration
|
||||||
|
file if STATIC_GCONV is defined.
|
||||||
|
|
||||||
|
* iconv/gconv_conf.c (__gconv_path_envvar): New global variable.
|
||||||
|
(__gconv_get_path): Use it instead of call getenv.
|
||||||
|
(__gconv_read_conf): First see whether cache can be used. If yes,
|
||||||
|
don't do any work here.
|
||||||
|
* iconv/gconv_db.c (__gconv_release_step): Renamed from release_step
|
||||||
|
and exported. Change callers.
|
||||||
|
(__gconv_find_transform): First call __gconv_lookup_cache and only
|
||||||
|
continue if it signals no cache available. Remove some unnecessary
|
||||||
|
tests.
|
||||||
|
* iconv/gconv_int.h: Declare __gconv_path_envvar, __gconv_lookup_cache,
|
||||||
|
__gconv_release_step, and __gconv_loaded_cache.
|
||||||
|
* iconv/gconv_cache.c: New file.
|
||||||
|
* iconv/iconvconfig.c: New file.
|
||||||
|
* iconv/iconvconfig.h: New file.
|
||||||
|
* iconv/strtab.c: New file.
|
||||||
|
* iconv/Makefile: Add rules to build new files and programs.
|
||||||
|
|
||||||
2001-07-20 Roland McGrath <roland@frob.com>
|
2001-07-20 Roland McGrath <roland@frob.com>
|
||||||
|
|
||||||
* sysdeps/generic/device-nrs.h (DEV_TTY_P): Change argument type
|
* sysdeps/generic/device-nrs.h (DEV_TTY_P): Change argument type
|
||||||
|
19
PROJECTS
19
PROJECTS
@ -156,24 +156,7 @@ contact <bug-glibc@gnu.org>.
|
|||||||
the currently implemented methods.
|
the currently implemented methods.
|
||||||
|
|
||||||
|
|
||||||
[22] It should be possible to have the information gconv-modules in
|
[22] Done.
|
||||||
a simple cache which is faster to access. Using libdb is probably
|
|
||||||
overkill and loading it would probably be slower than reading the
|
|
||||||
plain text file. But a file format with a simple hash table and
|
|
||||||
some data it points to should be fine. Probably it should be
|
|
||||||
two tables, one for the aliases, one for the mappings. The code
|
|
||||||
should start similar to this:
|
|
||||||
|
|
||||||
if (stat ("gconv-modules", &stp) == 0
|
|
||||||
&& stat ("gconv-modules.db", &std) == 0
|
|
||||||
&& stp.st_mtime < std.st_mtime)
|
|
||||||
{
|
|
||||||
... use the cache ...
|
|
||||||
{
|
|
||||||
else
|
|
||||||
{
|
|
||||||
... use the plain file if it exists, otherwise the db ...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[23] The `strptime' function needs to be completed. This includes among
|
[23] The `strptime' function needs to be completed. This includes among
|
||||||
|
@ -26,11 +26,12 @@ include ../Makeconfig
|
|||||||
headers = iconv.h gconv.h
|
headers = iconv.h gconv.h
|
||||||
routines = iconv_open iconv iconv_close \
|
routines = iconv_open iconv iconv_close \
|
||||||
gconv_open gconv gconv_close gconv_db gconv_conf \
|
gconv_open gconv gconv_close gconv_db gconv_conf \
|
||||||
gconv_builtin gconv_simple gconv_trans
|
gconv_builtin gconv_simple gconv_trans gconv_cache
|
||||||
ifeq ($(elf),yes)
|
ifeq ($(elf),yes)
|
||||||
routines += gconv_dl
|
routines += gconv_dl
|
||||||
else
|
else
|
||||||
CFLAGS-gconv_db.c = -DSTATIC_GCONV
|
CFLAGS-gconv_db.c = -DSTATIC_GCONV
|
||||||
|
CFLAGS-gconv_cache.c = -DSTATIC_GCONV
|
||||||
CFLAGS-gconv_simple.c = -DSTATIC_GCONV
|
CFLAGS-gconv_simple.c = -DSTATIC_GCONV
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ vpath %.c ../locale/programs
|
|||||||
|
|
||||||
iconv_prog-modules = iconv_charmap charmap charmap-dir linereader \
|
iconv_prog-modules = iconv_charmap charmap charmap-dir linereader \
|
||||||
dummy-repertoire simple-hash xstrdup xmalloc
|
dummy-repertoire simple-hash xstrdup xmalloc
|
||||||
|
iconvconfig-modules = strtab xmalloc
|
||||||
extra-objs = $(iconv_prog-modules:=.o)
|
extra-objs = $(iconv_prog-modules:=.o)
|
||||||
CFLAGS-iconv_prog.c = -I../locale/programs
|
CFLAGS-iconv_prog.c = -I../locale/programs
|
||||||
CFLAGS-iconv_charmap.c = -I../locale/programs
|
CFLAGS-iconv_charmap.c = -I../locale/programs
|
||||||
@ -50,10 +52,12 @@ tests = tst-iconv1 tst-iconv2 tst-iconv3
|
|||||||
distribute = gconv_builtin.h gconv_int.h loop.c skeleton.c iconv_prog.h \
|
distribute = gconv_builtin.h gconv_int.h loop.c skeleton.c iconv_prog.h \
|
||||||
iconv_charmap.c dummy-repertoire.c gconv_charset.h
|
iconv_charmap.c dummy-repertoire.c gconv_charset.h
|
||||||
|
|
||||||
others = iconv_prog
|
others = iconv_prog iconvconfig
|
||||||
install-others = $(inst_bindir)/iconv
|
install-others = $(inst_bindir)/iconv
|
||||||
|
|
||||||
|
CFLAGS-gconv_cache.c = -DGCONV_DIR='"$(gconvdir)"'
|
||||||
CFLAGS-gconv_conf.c = -DGCONV_PATH='"$(gconvdir)"'
|
CFLAGS-gconv_conf.c = -DGCONV_PATH='"$(gconvdir)"'
|
||||||
|
CFLAGS-iconvconfig.c = -DGCONV_PATH='"$(gconvdir)"' -DGCONV_DIR='"$(gconvdir)"'
|
||||||
|
|
||||||
include ../Rules
|
include ../Rules
|
||||||
|
|
||||||
@ -61,3 +65,4 @@ $(inst_bindir)/iconv: $(objpfx)iconv_prog $(+force)
|
|||||||
$(do-install-program)
|
$(do-install-program)
|
||||||
|
|
||||||
$(objpfx)iconv_prog: $(iconv_prog-modules:%=$(objpfx)%.o)
|
$(objpfx)iconv_prog: $(iconv_prog-modules:%=$(objpfx)%.o)
|
||||||
|
$(objpfx)iconvconfig: $(iconvconfig-modules:%=$(objpfx)%.o)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Builtin transformations.
|
/* Builtin transformations.
|
||||||
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||||
|
|
||||||
@ -30,18 +30,14 @@ BUILTIN_ALIAS ("OSF00010105//", "ISO-10646/UCS4/") /* level 2 */
|
|||||||
BUILTIN_ALIAS ("OSF00010106//", "ISO-10646/UCS4/") /* level 3 */
|
BUILTIN_ALIAS ("OSF00010106//", "ISO-10646/UCS4/") /* level 3 */
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
|
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
|
||||||
__gconv_transform_internal_ucs4, NULL, NULL,
|
__gconv_transform_internal_ucs4, 4, 4, 4, 4)
|
||||||
4, 4, 4, 4)
|
|
||||||
BUILTIN_TRANSFORMATION ("ISO-10646/UCS4/", "INTERNAL", 1, "=ucs4->INTERNAL",
|
BUILTIN_TRANSFORMATION ("ISO-10646/UCS4/", "INTERNAL", 1, "=ucs4->INTERNAL",
|
||||||
__gconv_transform_ucs4_internal, NULL, NULL,
|
__gconv_transform_ucs4_internal, 4, 4, 4, 4)
|
||||||
4, 4, 4, 4)
|
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("INTERNAL", "UCS-4LE//", 1, "=INTERNAL->ucs4le",
|
BUILTIN_TRANSFORMATION ("INTERNAL", "UCS-4LE//", 1, "=INTERNAL->ucs4le",
|
||||||
__gconv_transform_internal_ucs4le, NULL, NULL,
|
__gconv_transform_internal_ucs4le, 4, 4, 4, 4)
|
||||||
4, 4, 4, 4)
|
|
||||||
BUILTIN_TRANSFORMATION ("UCS-4LE//", "INTERNAL", 1, "=ucs4le->INTERNAL",
|
BUILTIN_TRANSFORMATION ("UCS-4LE//", "INTERNAL", 1, "=ucs4le->INTERNAL",
|
||||||
__gconv_transform_ucs4le_internal, NULL, NULL,
|
__gconv_transform_ucs4le_internal, 4, 4, 4, 4)
|
||||||
4, 4, 4, 4)
|
|
||||||
|
|
||||||
BUILTIN_ALIAS ("WCHAR_T//", "INTERNAL")
|
BUILTIN_ALIAS ("WCHAR_T//", "INTERNAL")
|
||||||
|
|
||||||
@ -51,15 +47,12 @@ BUILTIN_ALIAS ("ISO-IR-193//", "ISO-10646/UTF8/")
|
|||||||
BUILTIN_ALIAS ("OSF05010001//", "ISO-10646/UTF8/")
|
BUILTIN_ALIAS ("OSF05010001//", "ISO-10646/UTF8/")
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
|
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
|
||||||
__gconv_transform_internal_utf8, NULL, NULL,
|
__gconv_transform_internal_utf8, 4, 4, 1, 6)
|
||||||
4, 4, 1, 6)
|
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("ISO-10646/UTF-8/", "INTERNAL", 1, "=utf8->INTERNAL",
|
BUILTIN_TRANSFORMATION ("ISO-10646/UTF-8/", "INTERNAL", 1, "=utf8->INTERNAL",
|
||||||
__gconv_transform_utf8_internal, NULL, NULL,
|
__gconv_transform_utf8_internal, 1, 6, 4, 4)
|
||||||
1, 6, 4, 4)
|
|
||||||
BUILTIN_TRANSFORMATION ("ISO-10646/UTF8/", "INTERNAL", 1, "=utf8->INTERNAL",
|
BUILTIN_TRANSFORMATION ("ISO-10646/UTF8/", "INTERNAL", 1, "=utf8->INTERNAL",
|
||||||
__gconv_transform_utf8_internal, NULL, NULL,
|
__gconv_transform_utf8_internal, 1, 6, 4, 4)
|
||||||
1, 6, 4, 4)
|
|
||||||
|
|
||||||
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/")
|
||||||
@ -68,12 +61,10 @@ BUILTIN_ALIAS ("OSF00010101//", "ISO-10646/UCS2/") /* level 2 */
|
|||||||
BUILTIN_ALIAS ("OSF00010102//", "ISO-10646/UCS2/") /* level 3 */
|
BUILTIN_ALIAS ("OSF00010102//", "ISO-10646/UCS2/") /* level 3 */
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("ISO-10646/UCS2/", "INTERNAL", 1, "=ucs2->INTERNAL",
|
BUILTIN_TRANSFORMATION ("ISO-10646/UCS2/", "INTERNAL", 1, "=ucs2->INTERNAL",
|
||||||
__gconv_transform_ucs2_internal, NULL, NULL,
|
__gconv_transform_ucs2_internal, 2, 2, 4, 4)
|
||||||
2, 2, 4, 4)
|
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS2/", 1, "=INTERNAL->ucs2",
|
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS2/", 1, "=INTERNAL->ucs2",
|
||||||
__gconv_transform_internal_ucs2, NULL, NULL,
|
__gconv_transform_internal_ucs2, 4, 4, 2, 2)
|
||||||
4, 4, 2, 2)
|
|
||||||
|
|
||||||
|
|
||||||
BUILTIN_ALIAS ("ANSI_X3.4//", "ANSI_X3.4-1968//")
|
BUILTIN_ALIAS ("ANSI_X3.4//", "ANSI_X3.4-1968//")
|
||||||
@ -90,12 +81,10 @@ BUILTIN_ALIAS ("CSASCII//", "ANSI_X3.4-1968//")
|
|||||||
BUILTIN_ALIAS ("OSF00010020//", "ANSI_X3.4-1968//")
|
BUILTIN_ALIAS ("OSF00010020//", "ANSI_X3.4-1968//")
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("ANSI_X3.4-1968//", "INTERNAL", 1, "=ascii->INTERNAL",
|
BUILTIN_TRANSFORMATION ("ANSI_X3.4-1968//", "INTERNAL", 1, "=ascii->INTERNAL",
|
||||||
__gconv_transform_ascii_internal, NULL, NULL,
|
__gconv_transform_ascii_internal, 4, 4, 1, 1)
|
||||||
4, 4, 1, 1)
|
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("INTERNAL", "ANSI_X3.4-1968//", 1, "=INTERNAL->ascii",
|
BUILTIN_TRANSFORMATION ("INTERNAL", "ANSI_X3.4-1968//", 1, "=INTERNAL->ascii",
|
||||||
__gconv_transform_internal_ascii, NULL, NULL,
|
__gconv_transform_internal_ascii, 4, 4, 1, 1)
|
||||||
4, 4, 1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
@ -106,13 +95,11 @@ BUILTIN_ALIAS ("UCS-2LE//", "UNICODELITTLE//")
|
|||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("UNICODELITTLE//", "INTERNAL", 1,
|
BUILTIN_TRANSFORMATION ("UNICODELITTLE//", "INTERNAL", 1,
|
||||||
"=ucs2reverse->INTERNAL",
|
"=ucs2reverse->INTERNAL",
|
||||||
__gconv_transform_ucs2reverse_internal, NULL, NULL,
|
__gconv_transform_ucs2reverse_internal, 2, 2, 4, 4)
|
||||||
2, 2, 4, 4)
|
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODELITTLE//", 1,
|
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODELITTLE//", 1,
|
||||||
"=INTERNAL->ucs2reverse",
|
"=INTERNAL->ucs2reverse",
|
||||||
__gconv_transform_internal_ucs2reverse, NULL, NULL,
|
__gconv_transform_internal_ucs2reverse, 4, 4, 2, 2)
|
||||||
4, 4, 2, 2)
|
|
||||||
#else
|
#else
|
||||||
BUILTIN_ALIAS ("UNICODELITTLE//", "ISO-10646/UCS2/")
|
BUILTIN_ALIAS ("UNICODELITTLE//", "ISO-10646/UCS2/")
|
||||||
BUILTIN_ALIAS ("UCS-2LE//", "ISO-10646/UCS2/")
|
BUILTIN_ALIAS ("UCS-2LE//", "ISO-10646/UCS2/")
|
||||||
@ -121,11 +108,9 @@ BUILTIN_ALIAS ("UCS-2BE//", "UNICODEBIG//")
|
|||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("UNICODEBIG//", "INTERNAL", 1,
|
BUILTIN_TRANSFORMATION ("UNICODEBIG//", "INTERNAL", 1,
|
||||||
"=ucs2reverse->INTERNAL",
|
"=ucs2reverse->INTERNAL",
|
||||||
__gconv_transform_ucs2reverse_internal, NULL, NULL,
|
__gconv_transform_ucs2reverse_internal, 2, 2, 4, 4)
|
||||||
2, 2, 4, 4)
|
|
||||||
|
|
||||||
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODEBIG//", 1,
|
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODEBIG//", 1,
|
||||||
"=INTERNAL->ucs2reverse",
|
"=INTERNAL->ucs2reverse",
|
||||||
__gconv_transform_internal_ucs2reverse, NULL, NULL,
|
__gconv_transform_internal_ucs2reverse, 4, 4, 2, 2)
|
||||||
4, 4, 2, 2)
|
|
||||||
#endif
|
#endif
|
||||||
|
395
iconv/gconv_cache.c
Normal file
395
iconv/gconv_cache.c
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
/* Cache handling for iconv modules.
|
||||||
|
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <gconv_int.h>
|
||||||
|
#include <iconvconfig.h>
|
||||||
|
|
||||||
|
#include "../intl/hash-string.h"
|
||||||
|
|
||||||
|
static void *cache;
|
||||||
|
static size_t cache_size;
|
||||||
|
static int cache_malloced;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
internal_function
|
||||||
|
__gconv_load_cache (void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct stat64 st;
|
||||||
|
struct gconvcache_header *header;
|
||||||
|
|
||||||
|
/* We cannot use the cache if the GCONV_PATH environment variable is
|
||||||
|
set. */
|
||||||
|
__gconv_path_envvar = getenv ("GCONV_PATH");
|
||||||
|
if (__gconv_path_envvar != NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* See whether the cache file exists. */
|
||||||
|
fd = __open (GCONV_MODULES_CACHE, O_RDONLY);
|
||||||
|
if (__builtin_expect (fd, 0) == -1)
|
||||||
|
/* Not available. */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Get information about the file. */
|
||||||
|
if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0
|
||||||
|
/* We do not have to start looking at the file if it cannot contain
|
||||||
|
at least the cache header. */
|
||||||
|
|| st.st_size < sizeof (struct gconvcache_header))
|
||||||
|
{
|
||||||
|
close_and_exit:
|
||||||
|
close (fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make the file content available. */
|
||||||
|
cache_size = st.st_size;
|
||||||
|
#ifdef _POSIX_MAPPED_FILES
|
||||||
|
cache = __mmap (NULL, cache_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
if (__builtin_expect (cache == MAP_FAILED, 0))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
size_t already_read;
|
||||||
|
|
||||||
|
cache = malloc (cache_size);
|
||||||
|
if (cache == NULL)
|
||||||
|
goto close_and_exit;
|
||||||
|
|
||||||
|
already_read = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ssize_t n = __read (fd, (char *) cache + already_read,
|
||||||
|
cache_size - already_read);
|
||||||
|
if (__builtin_expect (n, 0) == -1)
|
||||||
|
{
|
||||||
|
free (cache);
|
||||||
|
cache = NULL;
|
||||||
|
goto close_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_read += n;
|
||||||
|
}
|
||||||
|
while (already_read < cache_size);
|
||||||
|
|
||||||
|
cache_malloced = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't need the file descriptor anymore. */
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
/* Check the consistency. */
|
||||||
|
header = (struct gconvcache_header *) cache;
|
||||||
|
if (__builtin_expect (header->magic, GCONVCACHE_MAGIC) != GCONVCACHE_MAGIC
|
||||||
|
|| __builtin_expect (header->string_offset >= cache_size, 0)
|
||||||
|
|| __builtin_expect (header->hash_offset >= cache_size, 0)
|
||||||
|
|| __builtin_expect (header->hash_size == 0, 0)
|
||||||
|
|| __builtin_expect ((header->hash_offset
|
||||||
|
+ header->hash_size * sizeof (struct hash_entry))
|
||||||
|
> cache_size, 0)
|
||||||
|
|| __builtin_expect (header->module_offset >= cache_size, 0)
|
||||||
|
|| __builtin_expect (header->otherconv_offset > cache_size, 0))
|
||||||
|
{
|
||||||
|
if (cache_malloced)
|
||||||
|
{
|
||||||
|
free (cache);
|
||||||
|
cache_malloced = 0;
|
||||||
|
}
|
||||||
|
#ifdef _POSIX_MAPPED_FILES
|
||||||
|
else
|
||||||
|
munmap (cache, cache_size);
|
||||||
|
#endif
|
||||||
|
cache = NULL;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* That worked. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
internal_function
|
||||||
|
find_module_idx (const char *str, size_t *idxp)
|
||||||
|
{
|
||||||
|
unsigned int idx;
|
||||||
|
unsigned int hval;
|
||||||
|
unsigned int hval2;
|
||||||
|
const struct gconvcache_header *header;
|
||||||
|
const char *strtab;
|
||||||
|
const struct hash_entry *hashtab;
|
||||||
|
unsigned int limit;
|
||||||
|
|
||||||
|
header = (const struct gconvcache_header *) cache;
|
||||||
|
strtab = (char *) cache + header->string_offset;
|
||||||
|
hashtab = (struct hash_entry *) ((char *) cache + header->hash_offset);
|
||||||
|
|
||||||
|
hval = hash_string (str);
|
||||||
|
idx = hval % header->hash_size;
|
||||||
|
hval2 = 1 + hval % (header->hash_size - 2);
|
||||||
|
|
||||||
|
limit = cache_size - header->string_offset;
|
||||||
|
while (hashtab[idx].string_offset != 0)
|
||||||
|
if (hashtab[idx].string_offset < limit
|
||||||
|
&& strcmp (str, strtab + hashtab[idx].string_offset) == 0)
|
||||||
|
{
|
||||||
|
*idxp = hashtab[idx].module_idx;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((idx += hval2) >= header->hash_size)
|
||||||
|
idx -= header->hash_size;
|
||||||
|
|
||||||
|
/* Nothing found. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
internal_function
|
||||||
|
find_module (const char *directory, const char *filename,
|
||||||
|
struct __gconv_step *result)
|
||||||
|
{
|
||||||
|
size_t dirlen = strlen (directory);
|
||||||
|
size_t fnamelen = strlen (filename) + 1;
|
||||||
|
char *fullname;
|
||||||
|
int status = __GCONV_OK;
|
||||||
|
|
||||||
|
fullname = (char *) malloc (dirlen + fnamelen);
|
||||||
|
if (fullname == NULL)
|
||||||
|
return __GCONV_NOMEM;
|
||||||
|
|
||||||
|
memcpy (__mempcpy (fullname, directory, dirlen), filename, fnamelen);
|
||||||
|
|
||||||
|
result->__shlib_handle = __gconv_find_shlib (fullname);
|
||||||
|
if (result->__shlib_handle == NULL)
|
||||||
|
return __GCONV_NOCONV;
|
||||||
|
|
||||||
|
result->__modname = fullname;
|
||||||
|
result->__fct = result->__shlib_handle->fct;
|
||||||
|
result->__init_fct = result->__shlib_handle->init_fct;
|
||||||
|
result->__end_fct = result->__shlib_handle->end_fct;
|
||||||
|
result->__counter = 1;
|
||||||
|
|
||||||
|
result->__data = NULL;
|
||||||
|
if (result->__init_fct != NULL)
|
||||||
|
status = DL_CALL_FCT (result->__init_fct, (result));
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
internal_function
|
||||||
|
__gconv_lookup_cache (const char *toset, const char *fromset,
|
||||||
|
struct __gconv_step **handle, size_t *nsteps, int flags)
|
||||||
|
{
|
||||||
|
const struct gconvcache_header *header;
|
||||||
|
const char *strtab;
|
||||||
|
size_t fromidx;
|
||||||
|
size_t toidx;
|
||||||
|
const struct module_entry *modtab;
|
||||||
|
const struct module_entry *from_module;
|
||||||
|
const struct module_entry *to_module;
|
||||||
|
struct __gconv_step *result;
|
||||||
|
|
||||||
|
if (cache == NULL)
|
||||||
|
/* We have no cache available. */
|
||||||
|
return __GCONV_NODB;
|
||||||
|
|
||||||
|
header = (const struct gconvcache_header *) cache;
|
||||||
|
strtab = (char *) cache + header->string_offset;
|
||||||
|
modtab = (const struct module_entry *) ((char *) cache
|
||||||
|
+ header->module_offset);
|
||||||
|
|
||||||
|
if (find_module_idx (fromset, &fromidx) != 0
|
||||||
|
|| (header->module_offset + (fromidx + 1) * sizeof (struct module_entry)
|
||||||
|
> cache_size))
|
||||||
|
return __GCONV_NOCONV;
|
||||||
|
from_module = &modtab[fromidx];
|
||||||
|
|
||||||
|
if (find_module_idx (toset, &toidx) != 0
|
||||||
|
|| (header->module_offset + (toidx + 1) * sizeof (struct module_entry)
|
||||||
|
> cache_size))
|
||||||
|
return __GCONV_NOCONV;
|
||||||
|
to_module = &modtab[toidx];
|
||||||
|
|
||||||
|
/* Avoid copy-only transformations if the user requests. */
|
||||||
|
if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0) && fromidx == toidx)
|
||||||
|
return __GCONV_NOCONV;
|
||||||
|
|
||||||
|
/* If there are special conversions available examine them first. */
|
||||||
|
if (__builtin_expect (from_module->extra_offset, 0) != 0)
|
||||||
|
{
|
||||||
|
/* Search through the list to see whether there is a module
|
||||||
|
matching the destination character set. */
|
||||||
|
const struct extra_entry *extra;
|
||||||
|
|
||||||
|
/* Note the -1. This is due to the offset added in iconvconfig.
|
||||||
|
See there for more explanations. */
|
||||||
|
extra = (const struct extra_entry *) ((char *) cache
|
||||||
|
+ header->otherconv_offset
|
||||||
|
+ from_module->extra_offset - 1);
|
||||||
|
while (extra->module_cnt != 0
|
||||||
|
&& extra->module[extra->module_cnt - 1].outname_offset != toidx)
|
||||||
|
extra = (const struct extra_entry *) ((char *) extra
|
||||||
|
+ sizeof (struct extra_entry)
|
||||||
|
+ (extra->module_cnt
|
||||||
|
* sizeof (struct extra_entry_module)));
|
||||||
|
|
||||||
|
if (extra->module_cnt != 0)
|
||||||
|
{
|
||||||
|
/* Use the extra module. First determine how many steps. */
|
||||||
|
char *fromname;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
*nsteps = extra->module_cnt;
|
||||||
|
*handle = result =
|
||||||
|
(struct __gconv_step *) malloc (extra->module_cnt
|
||||||
|
* sizeof (struct __gconv_step));
|
||||||
|
if (result == NULL)
|
||||||
|
return __GCONV_NOMEM;
|
||||||
|
|
||||||
|
fromname = (char *) strtab + from_module->canonname_offset;
|
||||||
|
idx = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
result[idx].__from_name = fromname;
|
||||||
|
fromname = result[idx].__to_name =
|
||||||
|
(char *) strtab + modtab[extra->module[idx].outname_offset].canonname_offset;
|
||||||
|
|
||||||
|
#ifndef STATIC_GCONV
|
||||||
|
if (strtab[extra->module[idx].dir_offset] != '\0')
|
||||||
|
{
|
||||||
|
/* Load the module, return handle for it. */
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = find_module (strtab + extra->module[idx].dir_offset,
|
||||||
|
strtab + extra->module[idx].name_offset,
|
||||||
|
&result[idx]);
|
||||||
|
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||||
|
{
|
||||||
|
/* Something went wrong. */
|
||||||
|
free (result);
|
||||||
|
goto try_internal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
/* It's a builtin transformation. */
|
||||||
|
__gconv_get_builtin_trans (strtab
|
||||||
|
+ extra->module[idx].name_offset,
|
||||||
|
&result[idx]);
|
||||||
|
|
||||||
|
}
|
||||||
|
while (++idx < extra->module_cnt);
|
||||||
|
|
||||||
|
return __GCONV_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try_internal:
|
||||||
|
/* See whether we can convert via the INTERNAL charset. */
|
||||||
|
if (__builtin_expect (from_module->fromname_offset, 1) == 0
|
||||||
|
|| __builtin_expect (to_module->toname_offset, 1) == 0)
|
||||||
|
/* Not possible. Nothing we can do. */
|
||||||
|
return __GCONV_NOCONV;
|
||||||
|
|
||||||
|
/* Use the two modules. */
|
||||||
|
result = (struct __gconv_step *) malloc (2 * sizeof (struct __gconv_step));
|
||||||
|
if (result == NULL)
|
||||||
|
return __GCONV_NOMEM;
|
||||||
|
|
||||||
|
*handle = result;
|
||||||
|
*nsteps = 2;
|
||||||
|
|
||||||
|
/* Generate data structure for conversion to INTERNAL. */
|
||||||
|
result[0].__from_name = (char *) strtab + from_module->canonname_offset;
|
||||||
|
result[0].__to_name = (char *) "INTERNAL";
|
||||||
|
|
||||||
|
#ifndef STATIC_GCONV
|
||||||
|
if (strtab[from_module->fromdir_offset] != '\0')
|
||||||
|
{
|
||||||
|
/* Load the module, return handle for it. */
|
||||||
|
int res = find_module (strtab + from_module->fromdir_offset,
|
||||||
|
strtab + from_module->fromname_offset,
|
||||||
|
&result[0]);
|
||||||
|
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||||
|
{
|
||||||
|
/* Something went wrong. */
|
||||||
|
free (result);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
/* It's a builtin transformation. */
|
||||||
|
__gconv_get_builtin_trans (strtab + from_module->fromname_offset,
|
||||||
|
&result[0]);
|
||||||
|
|
||||||
|
/* Generate data structure for conversion from INTERNAL. */
|
||||||
|
result[1].__from_name = (char *) "INTERNAL";
|
||||||
|
result[1].__to_name = (char *) strtab + to_module->canonname_offset;
|
||||||
|
|
||||||
|
#ifndef STATIC_GCONV
|
||||||
|
if (strtab[to_module->todir_offset] != '\0')
|
||||||
|
{
|
||||||
|
/* Load the module, return handle for it. */
|
||||||
|
int res = find_module (strtab + to_module->todir_offset,
|
||||||
|
strtab + to_module->toname_offset,
|
||||||
|
&result[1]);
|
||||||
|
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||||
|
{
|
||||||
|
/* Something went wrong. */
|
||||||
|
__gconv_release_step (&result[0]);
|
||||||
|
free (result);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
/* It's a builtin transformation. */
|
||||||
|
__gconv_get_builtin_trans (strtab + to_module->toname_offset, &result[1]);
|
||||||
|
|
||||||
|
return __GCONV_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Free all resources if necessary. */
|
||||||
|
static void __attribute__ ((unused))
|
||||||
|
free_mem (void)
|
||||||
|
{
|
||||||
|
if (cache_malloced)
|
||||||
|
free (cache);
|
||||||
|
#ifdef _POSIX_MAPPED_FILES
|
||||||
|
else
|
||||||
|
munmap (cache, cache_size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
text_set_element (__libc_subfreeres, free_mem);
|
@ -60,8 +60,8 @@ static const char gconv_module_ext[] = MODULE_EXT;
|
|||||||
/* We have a few builtin transformations. */
|
/* We have a few builtin transformations. */
|
||||||
static struct gconv_module builtin_modules[] =
|
static struct gconv_module builtin_modules[] =
|
||||||
{
|
{
|
||||||
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
|
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
|
||||||
MaxF, MinT, MaxT) \
|
MinT, MaxT) \
|
||||||
{ \
|
{ \
|
||||||
from_string: From, \
|
from_string: From, \
|
||||||
to_string: To, \
|
to_string: To, \
|
||||||
@ -79,8 +79,8 @@ static struct gconv_module builtin_modules[] =
|
|||||||
|
|
||||||
static const char *builtin_aliases[] =
|
static const char *builtin_aliases[] =
|
||||||
{
|
{
|
||||||
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
|
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
|
||||||
MaxF, MinT, MaxT)
|
MinT, MaxT)
|
||||||
#define BUILTIN_ALIAS(From, To) From " " To,
|
#define BUILTIN_ALIAS(From, To) From " " To,
|
||||||
|
|
||||||
#include "gconv_builtin.h"
|
#include "gconv_builtin.h"
|
||||||
@ -92,6 +92,10 @@ static const char *builtin_aliases[] =
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Value of the GCONV_PATH environment variable. */
|
||||||
|
const char *__gconv_path_envvar;
|
||||||
|
|
||||||
|
|
||||||
/* Test whether there is already a matching module known. */
|
/* Test whether there is already a matching module known. */
|
||||||
static int
|
static int
|
||||||
internal_function
|
internal_function
|
||||||
@ -423,7 +427,6 @@ __gconv_get_path (void)
|
|||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
{
|
{
|
||||||
/* Determine the complete path first. */
|
/* Determine the complete path first. */
|
||||||
const char *user_path;
|
|
||||||
char *gconv_path;
|
char *gconv_path;
|
||||||
size_t gconv_path_len;
|
size_t gconv_path_len;
|
||||||
char *elem;
|
char *elem;
|
||||||
@ -433,8 +436,7 @@ __gconv_get_path (void)
|
|||||||
char *cwd;
|
char *cwd;
|
||||||
size_t cwdlen;
|
size_t cwdlen;
|
||||||
|
|
||||||
user_path = getenv ("GCONV_PATH");
|
if (__gconv_path_envvar == NULL)
|
||||||
if (user_path == NULL)
|
|
||||||
{
|
{
|
||||||
/* No user-defined path. Make a modifiable copy of the
|
/* No user-defined path. Make a modifiable copy of the
|
||||||
default path. */
|
default path. */
|
||||||
@ -446,11 +448,12 @@ __gconv_get_path (void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Append the default path to the user-defined path. */
|
/* Append the default path to the user-defined path. */
|
||||||
size_t user_len = strlen (user_path);
|
size_t user_len = strlen (__gconv_path_envvar);
|
||||||
|
|
||||||
gconv_path_len = user_len + 1 + sizeof (default_gconv_path);
|
gconv_path_len = user_len + 1 + sizeof (default_gconv_path);
|
||||||
gconv_path = alloca (gconv_path_len);
|
gconv_path = alloca (gconv_path_len);
|
||||||
__mempcpy (__mempcpy (__mempcpy (gconv_path, user_path, user_len),
|
__mempcpy (__mempcpy (__mempcpy (gconv_path, __gconv_path_envvar,
|
||||||
|
user_len),
|
||||||
":", 1),
|
":", 1),
|
||||||
default_gconv_path, sizeof (default_gconv_path));
|
default_gconv_path, sizeof (default_gconv_path));
|
||||||
cwd = __getcwd (NULL, 0);
|
cwd = __getcwd (NULL, 0);
|
||||||
@ -530,6 +533,15 @@ __gconv_read_conf (void)
|
|||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
size_t cnt;
|
size_t cnt;
|
||||||
|
|
||||||
|
/* First see whether we should use the cache. */
|
||||||
|
if (__gconv_load_cache () == 0)
|
||||||
|
{
|
||||||
|
/* Yes, we are done. */
|
||||||
|
__set_errno (save_errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef STATIC_GCONV
|
||||||
/* Find out where we have to look. */
|
/* Find out where we have to look. */
|
||||||
if (__gconv_path_elem == NULL)
|
if (__gconv_path_elem == NULL)
|
||||||
__gconv_get_path ();
|
__gconv_get_path ();
|
||||||
@ -549,6 +561,7 @@ __gconv_read_conf (void)
|
|||||||
/* Read the next configuration file. */
|
/* Read the next configuration file. */
|
||||||
read_conf_file (filename, elem, elem_len, &modules, &nmodules);
|
read_conf_file (filename, elem, elem_len, &modules, &nmodules);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Add the internal modules. */
|
/* Add the internal modules. */
|
||||||
for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]);
|
for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]);
|
||||||
|
@ -178,8 +178,9 @@ free_derivation (void *p)
|
|||||||
|
|
||||||
|
|
||||||
/* Decrement the reference count for a single step in a steps array. */
|
/* Decrement the reference count for a single step in a steps array. */
|
||||||
static inline void
|
void
|
||||||
release_step (struct __gconv_step *step)
|
internal_function
|
||||||
|
__gconv_release_step (struct __gconv_step *step)
|
||||||
{
|
{
|
||||||
if (--step->__counter == 0)
|
if (--step->__counter == 0)
|
||||||
{
|
{
|
||||||
@ -231,6 +232,9 @@ gen_steps (struct derivation_step *best, const char *toset,
|
|||||||
? __strdup (current->result_set)
|
? __strdup (current->result_set)
|
||||||
: result[step_cnt + 1].__from_name);
|
: result[step_cnt + 1].__from_name);
|
||||||
|
|
||||||
|
result[step_cnt].__counter = 1;
|
||||||
|
result[step_cnt].__data = NULL;
|
||||||
|
|
||||||
#ifndef STATIC_GCONV
|
#ifndef STATIC_GCONV
|
||||||
if (current->code->module_name[0] == '/')
|
if (current->code->module_name[0] == '/')
|
||||||
{
|
{
|
||||||
@ -249,6 +253,22 @@ gen_steps (struct derivation_step *best, const char *toset,
|
|||||||
result[step_cnt].__fct = shlib_handle->fct;
|
result[step_cnt].__fct = shlib_handle->fct;
|
||||||
result[step_cnt].__init_fct = shlib_handle->init_fct;
|
result[step_cnt].__init_fct = shlib_handle->init_fct;
|
||||||
result[step_cnt].__end_fct = shlib_handle->end_fct;
|
result[step_cnt].__end_fct = shlib_handle->end_fct;
|
||||||
|
|
||||||
|
/* Call the init function. */
|
||||||
|
if (result[step_cnt].__init_fct != NULL)
|
||||||
|
{
|
||||||
|
status = DL_CALL_FCT (result[step_cnt].__init_fct,
|
||||||
|
(&result[step_cnt]));
|
||||||
|
|
||||||
|
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
|
||||||
|
{
|
||||||
|
failed = 1;
|
||||||
|
/* Make sure we unload this modules. */
|
||||||
|
--step_cnt;
|
||||||
|
result[step_cnt].__end_fct = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -256,25 +276,6 @@ gen_steps (struct derivation_step *best, const char *toset,
|
|||||||
__gconv_get_builtin_trans (current->code->module_name,
|
__gconv_get_builtin_trans (current->code->module_name,
|
||||||
&result[step_cnt]);
|
&result[step_cnt]);
|
||||||
|
|
||||||
result[step_cnt].__counter = 1;
|
|
||||||
|
|
||||||
/* Call the init function. */
|
|
||||||
result[step_cnt].__data = NULL;
|
|
||||||
if (result[step_cnt].__init_fct != NULL)
|
|
||||||
{
|
|
||||||
status = DL_CALL_FCT (result[step_cnt].__init_fct,
|
|
||||||
(&result[step_cnt]));
|
|
||||||
|
|
||||||
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
|
|
||||||
{
|
|
||||||
failed = 1;
|
|
||||||
/* Make sure we unload this modules. */
|
|
||||||
--step_cnt;
|
|
||||||
result[step_cnt].__end_fct = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
current = current->last;
|
current = current->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +283,7 @@ 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)
|
||||||
release_step (&result[step_cnt]);
|
__gconv_release_step (&result[step_cnt]);
|
||||||
free (result);
|
free (result);
|
||||||
*nsteps = 0;
|
*nsteps = 0;
|
||||||
*handle = NULL;
|
*handle = NULL;
|
||||||
@ -328,7 +329,7 @@ increment_counter (struct __gconv_step *steps, size_t nsteps)
|
|||||||
(after unloading) and this time loading failed!? */
|
(after unloading) and this time loading failed!? */
|
||||||
--step->__counter;
|
--step->__counter;
|
||||||
while (++cnt < nsteps)
|
while (++cnt < nsteps)
|
||||||
release_step (&steps[cnt]);
|
__gconv_release_step (&steps[cnt]);
|
||||||
result = __GCONV_NOCONV;
|
result = __GCONV_NOCONV;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -647,8 +648,8 @@ __gconv_find_transform (const char *toset, const char *fromset,
|
|||||||
struct __gconv_step **handle, size_t *nsteps,
|
struct __gconv_step **handle, size_t *nsteps,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
const char *fromset_expand = NULL;
|
const char *fromset_expand;
|
||||||
const char *toset_expand = NULL;
|
const char *toset_expand;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
/* Ensure that the configuration data is read. */
|
/* Ensure that the configuration data is read. */
|
||||||
@ -657,6 +658,14 @@ __gconv_find_transform (const char *toset, const char *fromset,
|
|||||||
/* Acquire the lock. */
|
/* Acquire the lock. */
|
||||||
__libc_lock_lock (lock);
|
__libc_lock_lock (lock);
|
||||||
|
|
||||||
|
result = __gconv_lookup_cache (toset, fromset, handle, nsteps, flags);
|
||||||
|
if (result != __GCONV_NODB)
|
||||||
|
{
|
||||||
|
/* We have a cache and could resolve the request, successful or not. */
|
||||||
|
__libc_lock_unlock (lock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
@ -665,11 +674,8 @@ __gconv_find_transform (const char *toset, const char *fromset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* See whether the names are aliases. */
|
/* See whether the names are aliases. */
|
||||||
if (__gconv_alias_db != NULL)
|
fromset_expand = do_lookup_alias (fromset);
|
||||||
{
|
toset_expand = do_lookup_alias (toset);
|
||||||
fromset_expand = do_lookup_alias (fromset);
|
|
||||||
toset_expand = do_lookup_alias (toset);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0)
|
if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0)
|
||||||
/* We are not supposed to create a pseudo transformation (means
|
/* We are not supposed to create a pseudo transformation (means
|
||||||
@ -713,7 +719,7 @@ __gconv_close_transform (struct __gconv_step *steps, size_t nsteps)
|
|||||||
__libc_lock_lock (lock);
|
__libc_lock_lock (lock);
|
||||||
|
|
||||||
while (nsteps-- > 0)
|
while (nsteps-- > 0)
|
||||||
release_step (&steps[nsteps]);
|
__gconv_release_step (&steps[nsteps]);
|
||||||
|
|
||||||
/* Release the lock. */
|
/* Release the lock. */
|
||||||
__libc_lock_unlock (lock);
|
__libc_lock_unlock (lock);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||||
|
|
||||||
@ -120,6 +120,9 @@ extern void *__gconv_alias_db;
|
|||||||
extern size_t __gconv_nmodules;
|
extern size_t __gconv_nmodules;
|
||||||
extern struct gconv_module *__gconv_modules_db;
|
extern struct gconv_module *__gconv_modules_db;
|
||||||
|
|
||||||
|
/* Value of the GCONV_PATH environment variable. */
|
||||||
|
extern const char *__gconv_path_envvar;
|
||||||
|
|
||||||
|
|
||||||
/* The gconv functions expects the name to be in upper case and complete,
|
/* The gconv functions expects the name to be in upper case and complete,
|
||||||
including the trailing slashes if necessary. */
|
including the trailing slashes if necessary. */
|
||||||
@ -179,9 +182,22 @@ extern int __gconv_find_transform (const char *toset, const char *fromset,
|
|||||||
size_t *nsteps, int flags)
|
size_t *nsteps, int flags)
|
||||||
internal_function;
|
internal_function;
|
||||||
|
|
||||||
|
/* Search for transformation in cache data. */
|
||||||
|
extern int __gconv_lookup_cache (const char *toset, const char *fromset,
|
||||||
|
struct __gconv_step **handle, size_t *nsteps,
|
||||||
|
int flags)
|
||||||
|
internal_function;
|
||||||
|
|
||||||
|
/* Free data associated with a step's structure. */
|
||||||
|
extern void __gconv_release_step (struct __gconv_step *step)
|
||||||
|
internal_function;
|
||||||
|
|
||||||
/* Read all the configuration data and cache it. */
|
/* Read all the configuration data and cache it. */
|
||||||
extern void __gconv_read_conf (void);
|
extern void __gconv_read_conf (void);
|
||||||
|
|
||||||
|
/* Try to read module cache file. */
|
||||||
|
extern int __gconv_load_cache (void) internal_function;
|
||||||
|
|
||||||
/* Determine the directories we are looking in. */
|
/* Determine the directories we are looking in. */
|
||||||
extern void __gconv_get_path (void);
|
extern void __gconv_get_path (void);
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
#define BUILTIN_ALIAS(s1, s2) /* nothing */
|
#define BUILTIN_ALIAS(s1, s2) /* nothing */
|
||||||
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
|
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
|
||||||
MaxF, MinT, MaxT) \
|
MinT, MaxT) \
|
||||||
extern int Fct (struct __gconv_step *, struct __gconv_step_data *, \
|
extern int Fct (struct __gconv_step *, struct __gconv_step_data *, \
|
||||||
__const unsigned char **, __const unsigned char *, \
|
__const unsigned char **, __const unsigned char *, \
|
||||||
unsigned char **, size_t *, int, int);
|
unsigned char **, size_t *, int, int);
|
||||||
|
1165
iconv/iconvconfig.c
Normal file
1165
iconv/iconvconfig.c
Normal file
File diff suppressed because it is too large
Load Diff
67
iconv/iconvconfig.h
Normal file
67
iconv/iconvconfig.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef uint16_t gidx_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct gconvcache_header
|
||||||
|
{
|
||||||
|
uint32_t magic;
|
||||||
|
gidx_t string_offset;
|
||||||
|
gidx_t hash_offset;
|
||||||
|
gidx_t hash_size;
|
||||||
|
gidx_t module_offset;
|
||||||
|
gidx_t otherconv_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hash_entry
|
||||||
|
{
|
||||||
|
gidx_t string_offset;
|
||||||
|
gidx_t module_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct module_entry
|
||||||
|
{
|
||||||
|
gidx_t canonname_offset;
|
||||||
|
gidx_t fromdir_offset;
|
||||||
|
gidx_t fromname_offset;
|
||||||
|
gidx_t todir_offset;
|
||||||
|
gidx_t toname_offset;
|
||||||
|
gidx_t extra_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct extra_entry
|
||||||
|
{
|
||||||
|
gidx_t module_cnt;
|
||||||
|
struct extra_entry_module
|
||||||
|
{
|
||||||
|
gidx_t outname_offset;
|
||||||
|
gidx_t dir_offset;
|
||||||
|
gidx_t name_offset;
|
||||||
|
} module[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define GCONVCACHE_MAGIC 0x20010324
|
||||||
|
|
||||||
|
|
||||||
|
#define GCONV_MODULES_CACHE GCONV_DIR "/gconv-modules.cache"
|
294
iconv/strtab.c
Normal file
294
iconv/strtab.c
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
/* C string table handling.
|
||||||
|
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct Strent
|
||||||
|
{
|
||||||
|
const char *string;
|
||||||
|
size_t len;
|
||||||
|
struct Strent *next;
|
||||||
|
struct Strent *left;
|
||||||
|
struct Strent *right;
|
||||||
|
size_t offset;
|
||||||
|
char reverse[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct memoryblock
|
||||||
|
{
|
||||||
|
struct memoryblock *next;
|
||||||
|
char memory[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Strtab
|
||||||
|
{
|
||||||
|
struct Strent *root;
|
||||||
|
struct memoryblock *memory;
|
||||||
|
char *backp;
|
||||||
|
size_t left;
|
||||||
|
size_t total;
|
||||||
|
|
||||||
|
struct Strent null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Cache for the pagesize. We correct this value a bit so that `malloc'
|
||||||
|
is not allocating more than a page. */
|
||||||
|
static size_t ps;
|
||||||
|
|
||||||
|
|
||||||
|
extern void *xmalloc (size_t n) __attribute__ ((__malloc__));
|
||||||
|
|
||||||
|
|
||||||
|
struct Strtab *
|
||||||
|
strtabinit (void)
|
||||||
|
{
|
||||||
|
if (ps == 0)
|
||||||
|
{
|
||||||
|
ps = sysconf (_SC_PAGESIZE) - 2 * sizeof (void);
|
||||||
|
assert (sizeof (struct memoryblock) < ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (struct Strtab *) calloc (1, sizeof (struct Strtab));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
morememory (struct Strtab *st, size_t len)
|
||||||
|
{
|
||||||
|
struct memoryblock *newmem;
|
||||||
|
|
||||||
|
if (len < ps)
|
||||||
|
len = ps;
|
||||||
|
newmem = (struct memoryblock *) malloc (len);
|
||||||
|
if (newmem == NULL)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
newmem->next = st->memory;
|
||||||
|
st->memory = newmem;
|
||||||
|
st->backp = newmem->memory;
|
||||||
|
st->left = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
strtabfree (struct Strtab *st)
|
||||||
|
{
|
||||||
|
struct memoryblock *mb = st->memory;
|
||||||
|
|
||||||
|
while (mb != NULL)
|
||||||
|
{
|
||||||
|
void *old = mb;
|
||||||
|
mb = mb->next;
|
||||||
|
free (old);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (st);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct Strent *
|
||||||
|
newstring (struct Strtab *st, const char *str, size_t len)
|
||||||
|
{
|
||||||
|
struct Strent *newstr;
|
||||||
|
size_t align;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Compute the string length if the caller doesn't know it. */
|
||||||
|
if (len == 0)
|
||||||
|
len = strlen (str) + 1;
|
||||||
|
|
||||||
|
/* Compute the amount of padding needed to make the structure aligned. */
|
||||||
|
align = ((__alignof__ (struct Strent)
|
||||||
|
- (((uintptr_t) st->backp)
|
||||||
|
& (__alignof__ (struct Strent) - 1)))
|
||||||
|
& (__alignof__ (struct Strent) - 1));
|
||||||
|
|
||||||
|
/* Make sure there is enough room in the memory block. */
|
||||||
|
if (st->left < align + sizeof (struct Strent) + len)
|
||||||
|
{
|
||||||
|
morememory (st, sizeof (struct Strent) + len);
|
||||||
|
align = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the reserved string. */
|
||||||
|
newstr = (struct Strent *) (st->backp + align);
|
||||||
|
newstr->string = str;
|
||||||
|
newstr->len = len;
|
||||||
|
newstr->next = NULL;
|
||||||
|
newstr->left = NULL;
|
||||||
|
newstr->right = NULL;
|
||||||
|
newstr->offset = 0;
|
||||||
|
for (i = len - 2; i >= 0; --i)
|
||||||
|
newstr->reverse[i] = str[len - 2 - i];
|
||||||
|
newstr->reverse[len - 1] = '\0';
|
||||||
|
st->backp += align + sizeof (struct Strent) + len;
|
||||||
|
st->left -= align + sizeof (struct Strent) + len;
|
||||||
|
|
||||||
|
return newstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX This function should definitely be rewritten to use a balancing
|
||||||
|
tree algorith (AVL, red-black trees). For now a simple, correct
|
||||||
|
implementation is enough. */
|
||||||
|
static struct Strent **
|
||||||
|
searchstring (struct Strent **sep, struct Strent *newstr)
|
||||||
|
{
|
||||||
|
int cmpres;
|
||||||
|
|
||||||
|
/* More strings? */
|
||||||
|
if (*sep == NULL)
|
||||||
|
{
|
||||||
|
*sep = newstr;
|
||||||
|
return sep;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare the strings. */
|
||||||
|
cmpres = memcmp ((*sep)->reverse, newstr->reverse,
|
||||||
|
MIN ((*sep)->len, newstr->len));
|
||||||
|
if (cmpres == 0)
|
||||||
|
/* We found a matching string. */
|
||||||
|
return sep;
|
||||||
|
else if (cmpres > 0)
|
||||||
|
return searchstring (&(*sep)->left, newstr);
|
||||||
|
else
|
||||||
|
return searchstring (&(*sep)->right, newstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Add new string. The actual string is assumed to be permanent. */
|
||||||
|
struct Strent *
|
||||||
|
strtabadd (struct Strtab *st, const char *str, size_t len)
|
||||||
|
{
|
||||||
|
struct Strent *newstr;
|
||||||
|
struct Strent **sep;
|
||||||
|
|
||||||
|
/* Allocate memory for the new string and its associated information. */
|
||||||
|
newstr = newstring (st, str, len);
|
||||||
|
|
||||||
|
/* Search in the array for the place to insert the string. If there
|
||||||
|
is no string with matching prefix and no string with matching
|
||||||
|
leading substring, create a new entry. */
|
||||||
|
sep = searchstring (&st->root, newstr);
|
||||||
|
if (*sep != newstr)
|
||||||
|
{
|
||||||
|
/* This is not the same entry. This means we have a prefix match. */
|
||||||
|
if ((*sep)->len > newstr->len)
|
||||||
|
{
|
||||||
|
/* We have a new substring. This means we don't need the reverse
|
||||||
|
string of this entry anymore. */
|
||||||
|
st->backp -= newstr->len;
|
||||||
|
st->left += newstr->len;
|
||||||
|
|
||||||
|
newstr->next = (*sep)->next;
|
||||||
|
(*sep)->next = newstr;
|
||||||
|
}
|
||||||
|
else if ((*sep)->len != newstr->len)
|
||||||
|
{
|
||||||
|
/* When we get here it means that the string we are about to
|
||||||
|
add has a common prefix with a string we already have but
|
||||||
|
it is longer. In this case we have to put it first. */
|
||||||
|
newstr->next = *sep;
|
||||||
|
*sep = newstr;
|
||||||
|
|
||||||
|
st->total += newstr->len - (*sep)->len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We have an exact match. Free the memory we allocated. */
|
||||||
|
st->left += st->backp - (char *) newstr;
|
||||||
|
st->backp = (char *) newstr;
|
||||||
|
|
||||||
|
newstr = *sep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
st->total += newstr->len;
|
||||||
|
|
||||||
|
return newstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
copystrings (struct Strent *nodep, char **freep, size_t *offsetp)
|
||||||
|
{
|
||||||
|
struct Strent *subs;
|
||||||
|
|
||||||
|
if (nodep->left != NULL)
|
||||||
|
copystrings (nodep->left, freep, offsetp);
|
||||||
|
|
||||||
|
/* Process the current node. */
|
||||||
|
nodep->offset = *offsetp;
|
||||||
|
*freep = (char *) mempcpy (*freep, nodep->string, nodep->len);
|
||||||
|
*offsetp += nodep->len;
|
||||||
|
|
||||||
|
for (subs = nodep->next; subs != NULL; subs = subs->next)
|
||||||
|
{
|
||||||
|
assert (subs->len < nodep->len);
|
||||||
|
subs->offset = nodep->offset + nodep->len - subs->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodep->right != NULL)
|
||||||
|
copystrings (nodep->right, freep, offsetp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
strtabfinalize (struct Strtab *st, size_t *size)
|
||||||
|
{
|
||||||
|
size_t copylen;
|
||||||
|
char *endp;
|
||||||
|
char *retval;
|
||||||
|
|
||||||
|
/* Fill in the information. */
|
||||||
|
endp = retval = (char *) xmalloc (st->total + 1);
|
||||||
|
|
||||||
|
/* Always put an empty string at the beginning so that a zero offset
|
||||||
|
can mean error. */
|
||||||
|
*endp++ = '\0';
|
||||||
|
|
||||||
|
/* Now run through the tree and add all the string while also updating
|
||||||
|
the offset members of the elfstrent records. */
|
||||||
|
copylen = 1;
|
||||||
|
copystrings (st->root, &endp, ©len);
|
||||||
|
assert (copylen == st->total + 1);
|
||||||
|
assert (endp = retval + st->total + 1);
|
||||||
|
*size = copylen;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
strtaboffset (struct Strent *se)
|
||||||
|
{
|
||||||
|
return se->offset;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user