summaryrefslogtreecommitdiff
path: root/iconv/gconv_conf.c
diff options
context:
space:
mode:
Diffstat (limited to 'iconv/gconv_conf.c')
-rw-r--r--iconv/gconv_conf.c158
1 files changed, 87 insertions, 71 deletions
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
index d3c13d75c9..8a72c7aac9 100644
--- a/iconv/gconv_conf.c
+++ b/iconv/gconv_conf.c
@@ -19,6 +19,7 @@
Boston, MA 02111-1307, USA. */
#include <ctype.h>
+#include <errno.h>
#include <gconv.h>
#include <search.h>
#include <stdio.h>
@@ -35,6 +36,12 @@ static const char default_gconv_path[] = GCONV_PATH;
along the path. */
static const char gconv_conf_filename[] = "gconv-modules";
+/* Filename extension for the modules. */
+#ifndef MODULE_EXT
+# define MODULE_EXT ".so"
+#endif
+static const char gconv_module_ext[] = MODULE_EXT;
+
/* We have a few builtin transformations. */
static struct gconv_module builtin_modules[] =
{
@@ -111,15 +118,18 @@ add_alias (char *rp)
new_alias = (struct gconv_alias *)
malloc (sizeof (struct gconv_alias) + (wp - from));
- new_alias->fromname = memcpy ((char *) new_alias
- + sizeof (struct gconv_alias),
- from, to - from);
- new_alias->toname = memcpy ((char *) new_alias + sizeof (struct gconv_alias)
- + (to - from), to, wp - to);
-
- if (__tsearch (new_alias, &__gconv_alias_db, __gconv_alias_compare) == NULL)
- /* Something went wrong, free this entry. */
- free (new_alias);
+ if (new_alias != NULL)
+ {
+ new_alias->fromname = memcpy ((char *) new_alias
+ + sizeof (struct gconv_alias),
+ from, wp - from);
+ new_alias->toname = new_alias->fromname + (to - from);
+
+ if (__tsearch (new_alias, &__gconv_alias_db, __gconv_alias_compare)
+ == NULL)
+ /* Something went wrong, free this entry. */
+ free (new_alias);
+ }
}
@@ -138,6 +148,7 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
char *from, *to, *module, *wp;
size_t const_len;
int from_is_regex;
+ int need_ext;
int cost;
while (isspace (*rp))
@@ -195,65 +206,68 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
/* Increment by one for the slash. */
++dir_len;
+ /* See whether we must add the ending. */
+ need_ext = 0;
+ if (wp - module < sizeof (gconv_module_ext)
+ || memcmp (wp - sizeof (gconv_module_ext), gconv_module_ext,
+ sizeof (gconv_module_ext)) != 0)
+ /* We must add the module extension. */
+ need_ext = sizeof (gconv_module_ext) - 1;
+
/* We've collected all the information, now create an entry. */
- const_len = 0;
if (from_is_regex)
- do
- ++const_len;
- while (isalnum (from[const_len]) || from[const_len] == '-'
- || from[const_len] == '/' || from[const_len] == '.'
- || from[const_len] == '_');
+ {
+ const_len = 0;
+ while (isalnum (from[const_len]) || from[const_len] == '-'
+ || from[const_len] == '/' || from[const_len] == '.'
+ || from[const_len] == '_')
+ ++const_len;
+ }
+ else
+ const_len = to - from - 1;
new_module = (struct gconv_module *) malloc (sizeof (struct gconv_module)
- + (wp - from) + const_len
- + dir_len);
+ + (wp - from)
+ + dir_len + need_ext);
if (new_module != NULL)
{
+ char *tmp;
+
+ new_module->from_constpfx = memcpy ((char *) new_module
+ + sizeof (struct gconv_module),
+ from, to - from);
if (from_is_regex)
- {
- new_module->from_pattern = memcpy ((char *) new_module
- + sizeof (struct gconv_module),
- from, to - from);
- new_module->from_constpfx = memcpy ((char *) new_module->from_pattern
- + (to - from),
- from, const_len);
- ((char *) new_module->from_constpfx)[const_len] = '\0';
- new_module->from_constpfx_len = const_len;
- ++const_len;
- }
+ new_module->from_pattern = new_module->from_constpfx;
else
- {
- new_module->from_pattern = NULL;
- new_module->from_constpfx = memcpy ((char *) new_module
- + sizeof (struct gconv_module),
- from, to - from);
- new_module->from_constpfx_len = to - from - 1;
- const_len = to - from;
- }
+ new_module->from_pattern = NULL;
+
+ new_module->from_constpfx_len = const_len;
+
new_module->from_regex = NULL;
new_module->to_string = memcpy ((char *) new_module->from_constpfx
- + const_len + 1, to, module - to);
+ + (to - from), to, module - to);
new_module->cost = cost;
+ new_module->module_name = (char *) new_module->to_string + (module - to);
+
if (dir_len == 0)
- new_module->module_name = memcpy ((char *) new_module->to_string
- + (module - to),
- module, wp - module);
+ tmp = (char *) new_module->module_name;
else
{
- char *tmp;
- new_module->module_name = ((char *) new_module->to_string
- + (module - to));
tmp = __mempcpy ((char *) new_module->module_name,
directory, dir_len - 1);
*tmp++ = '/';
- memcpy (tmp, module, wp - module);
}
- if (__tfind (new_module, *modules, module_compare) != NULL)
+ tmp = __mempcpy (tmp, module, wp - module);
+
+ if (need_ext)
+ memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
+
+ if (__tfind (new_module, modules, module_compare) == NULL)
if (__tsearch (new_module, modules, module_compare) == NULL)
/* Something went wrong while inserting the new module. */
free (new_module);
@@ -267,7 +281,7 @@ static void
insert_module (const void *nodep, VISIT value, int level)
{
if (value == preorder || value == leaf)
- __gconv_modules_db[__gconv_nmodules++] = (struct gconv_module *) nodep;
+ __gconv_modules_db[__gconv_nmodules++] = *(struct gconv_module **) nodep;
}
static void
@@ -302,8 +316,6 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
break;
rp = line;
- while (isspace (*rp))
- ++rp;
/* Terminate the line (excluding comments or newline) by an NUL byte
to simplify the following code. */
endp = strchr (rp, '#');
@@ -316,6 +328,9 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
*endp = '\0';
}
+ while (isspace (*rp))
+ ++rp;
+
/* If this is an empty line go on with the next one. */
if (rp == endp)
continue;
@@ -325,10 +340,10 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
++rp;
if (rp - word == sizeof ("alias") - 1
- && memcpy (word, "alias", sizeof ("alias") - 1) == 0)
+ && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
add_alias (rp);
else if (rp - word == sizeof ("module") - 1
- && memcpy (word, "module", sizeof ("module") - 1) == 0)
+ && memcmp (word, "module", sizeof ("module") - 1) == 0)
add_module (rp, directory, dir_len, modules, nmodules);
/* else */
/* Otherwise ignore the line. */
@@ -349,6 +364,7 @@ __gconv_read_conf (void)
char *gconv_path, *elem;
void *modules = NULL;
size_t nmodules = 0;
+ int save_errno = errno;
if (user_path == NULL)
/* No user-defined path. Make a modifiable copy of the default path. */
@@ -390,31 +406,31 @@ __gconv_read_conf (void)
/* If the configuration files do not contain any valid module specification
remember this by setting the pointer to the module array to NULL. */
- nmodules = sizeof (builtin_modules) / sizeof (struct gconv_module);
+ nmodules += sizeof (builtin_modules) / sizeof (builtin_modules[0]);
if (nmodules == 0)
+ __gconv_modules_db = NULL;
+ else
{
- __gconv_modules_db = NULL;
- return;
- }
+ __gconv_modules_db =
+ (struct gconv_module **) malloc (nmodules
+ * sizeof (struct gconv_module));
+ if (__gconv_modules_db != NULL)
+ {
+ size_t cnt;
- __gconv_modules_db =
- (struct gconv_module **) malloc (nmodules * sizeof (struct gconv_module));
- if (__gconv_modules_db == NULL)
- /* We cannot do anything. */
- return;
+ /* Insert all module entries into the array. */
+ __twalk (modules, insert_module);
- /* First insert the builtin transformations. */
- while (__gconv_nmodules < (sizeof (builtin_modules)
- / sizeof (struct gconv_module)))
- {
- __gconv_modules_db[__gconv_nmodules] =
- &builtin_modules[__gconv_nmodules];
- ++__gconv_nmodules;
- }
+ /* No remove the tree data structure. */
+ __tdestroy (modules, nothing);
- /* Insert all module entries into the array. */
- __twalk (modules, insert_module);
+ /* Finally insert the builtin transformations. */
+ for (cnt = 0; cnt < (sizeof (builtin_modules)
+ / sizeof (struct gconv_module)); ++cnt)
+ __gconv_modules_db[__gconv_nmodules++] = &builtin_modules[cnt];
+ }
+ }
- /* No remove the tree data structure. */
- __tdestroy (modules, nothing);
+ /* Restore the error number. */
+ __set_errno (save_errno);
}