* iconv/gconv_int.h (strict gconv_module): Remove all members
	associated with regular expressions.  Use a simple string as the
	from name.
	* iconv/gconv_db.c: Remove code handling regular expressions.
	* iconv/gconv_conf.c: Likewise.
	* iconv/iconv_prog.c: Likewise.
	* iconv/gconv_builtin.h: Adjust for change in gconv_conf.c.
This commit is contained in:
Ulrich Drepper 2000-06-20 00:34:21 +00:00
parent d620426811
commit d2dfc5de01
12 changed files with 248 additions and 430 deletions

View file

@ -1,5 +1,13 @@
2000-06-19 Ulrich Drepper <drepper@redhat.com>
* iconv/gconv_int.h (strict gconv_module): Remove all members
associated with regular expressions. Use a simple string as the
from name.
* iconv/gconv_db.c: Remove code handling regular expressions.
* iconv/gconv_conf.c: Likewise.
* iconv/iconv_prog.c: Likewise.
* iconv/gconv_builtin.h: Adjust for change in gconv_conf.c.
* iconv/gconv.h (__gconv_trans_fct): Add new parameter.
General namespace cleanup.
(struct __gconv_trans_data): Add next field.

View file

@ -29,21 +29,17 @@ BUILTIN_ALIAS ("OSF00010104//", "ISO-10646/UCS4/") /* level 1 */
BUILTIN_ALIAS ("OSF00010105//", "ISO-10646/UCS4/") /* level 2 */
BUILTIN_ALIAS ("OSF00010106//", "ISO-10646/UCS4/") /* level 3 */
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8,
"ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
__gconv_transform_internal_ucs4, NULL, NULL,
4, 4, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15,
"INTERNAL", 1, "=ucs4->INTERNAL",
BUILTIN_TRANSFORMATION ("ISO-10646/UCS4/", "INTERNAL", 1, "=ucs4->INTERNAL",
__gconv_transform_ucs4_internal, NULL, NULL,
4, 4, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8,
"UCS-4LE//", 1, "=INTERNAL->ucs4le",
BUILTIN_TRANSFORMATION ("INTERNAL", "UCS-4LE//", 1, "=INTERNAL->ucs4le",
__gconv_transform_internal_ucs4le, NULL, NULL,
4, 4, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "UCS-4LE//", 15,
"INTERNAL", 1, "=ucs4le->INTERNAL",
BUILTIN_TRANSFORMATION ("UCS-4LE//", "INTERNAL", 1, "=ucs4le->INTERNAL",
__gconv_transform_ucs4le_internal, NULL, NULL,
4, 4, 4, 4)
@ -52,13 +48,14 @@ BUILTIN_ALIAS ("UTF-8//", "ISO-10646/UTF8/")
BUILTIN_ALIAS ("ISO-IR-193//", "ISO-10646/UTF8/")
BUILTIN_ALIAS ("OSF05010001//", "ISO-10646/UTF8/")
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8,
"ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
__gconv_transform_internal_utf8, NULL, NULL,
4, 4, 1, 6)
BUILTIN_TRANSFORMATION ("ISO-10646/UTF-?8/", "ISO-10646/UTF", 13,
"INTERNAL", 1, "=utf8->INTERNAL",
BUILTIN_TRANSFORMATION ("ISO-10646/UTF-8/", "INTERNAL", 1, "=utf8->INTERNAL",
__gconv_transform_utf8_internal, NULL, NULL,
1, 6, 4, 4)
BUILTIN_TRANSFORMATION ("ISO-10646/UTF8/", "INTERNAL", 1, "=utf8->INTERNAL",
__gconv_transform_utf8_internal, NULL, NULL,
1, 6, 4, 4)
@ -68,13 +65,11 @@ BUILTIN_ALIAS ("OSF00010100//", "ISO-10646/UCS2/") /* level 1 */
BUILTIN_ALIAS ("OSF00010101//", "ISO-10646/UCS2/") /* level 2 */
BUILTIN_ALIAS ("OSF00010102//", "ISO-10646/UCS2/") /* level 3 */
BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS2/", 15, "INTERNAL",
1, "=ucs2->INTERNAL",
BUILTIN_TRANSFORMATION ("ISO-10646/UCS2/", "INTERNAL", 1, "=ucs2->INTERNAL",
__gconv_transform_ucs2_internal, NULL, NULL,
2, 2, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "ISO-10646/UCS2/",
1, "=INTERNAL->ucs2",
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS2/", 1, "=INTERNAL->ucs2",
__gconv_transform_internal_ucs2, NULL, NULL,
4, 4, 2, 2)
@ -85,13 +80,13 @@ BUILTIN_ALIAS ("UCS-2BE//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2LE//", "UNICODELITTLE//")
BUILTIN_TRANSFORMATION (NULL, "UNICODELITTLE//", 15, "INTERNAL",
1, "=ucs2reverse->INTERNAL",
BUILTIN_TRANSFORMATION ("UNICODELITTLE//", "INTERNAL", 1,
"=ucs2reverse->INTERNAL",
__gconv_transform_ucs2reverse_internal, NULL, NULL,
2, 2, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "UNICODELITTLE//",
1, "=INTERNAL->ucs2reverse",
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODELITTLE//", 1,
"=INTERNAL->ucs2reverse",
__gconv_transform_internal_ucs2reverse, NULL, NULL,
4, 4, 2, 2)
#else
@ -100,13 +95,13 @@ BUILTIN_ALIAS ("UCS-2LE//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2BE//", "UNICODEBIG//")
BUILTIN_TRANSFORMATION (NULL, "UNICODEBIG//", 12, "INTERNAL",
1, "=ucs2reverse->INTERNAL",
BUILTIN_TRANSFORMATION ("UNICODEBIG//", "INTERNAL", 1,
"=ucs2reverse->INTERNAL",
__gconv_transform_ucs2reverse_internal, NULL, NULL,
2, 2, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "UNICODEBIG//",
1, "=INTERNAL->ucs2reverse",
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODEBIG//", 1,
"=INTERNAL->ucs2reverse",
__gconv_transform_internal_ucs2reverse, NULL, NULL,
4, 4, 2, 2)
#endif

View file

@ -56,13 +56,10 @@ static const char gconv_module_ext[] = MODULE_EXT;
/* We have a few builtin transformations. */
static struct gconv_module builtin_modules[] =
{
#define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \
Fct, Init, End, MinF, MaxF, MinT, MaxT) \
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
MaxF, MinT, MaxT) \
{ \
from_pattern: From, \
from_constpfx: ConstPfx, \
from_constpfx_len: ConstLen, \
from_regex: NULL, \
from_string: From, \
to_string: To, \
cost_hi: Cost, \
cost_lo: INT_MAX, \
@ -78,8 +75,8 @@ static struct gconv_module builtin_modules[] =
static const char *builtin_aliases[] =
{
#define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \
Fct, Init, End, MinF, MaxF, MinT, MaxT)
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
MaxF, MinT, MaxT)
#define BUILTIN_ALIAS(From, To) From " " To,
#include "gconv_builtin.h"
@ -94,74 +91,17 @@ static const char *builtin_aliases[] =
/* Test whether there is already a matching module known. */
static int
internal_function
detect_conflict (const char *alias, size_t alias_len)
detect_conflict (const char *alias)
{
struct gconv_module *node = __gconv_modules_db;
while (node != NULL)
{
int cmpres = strncmp (alias, node->from_constpfx,
MIN (alias_len, node->from_constpfx_len));
int cmpres = strcmp (alias, node->from_string);
if (cmpres == 0)
{
struct gconv_module *runp;
if (alias_len < node->from_constpfx_len)
/* Cannot possibly match. */
return 0;
/* This means the prefix and the alias are identical. If
there is now a simple extry or a regular expression
matching this name we have found a conflict. If there is
no conflict with the elements in the `same' list there
cannot be a conflict. */
runp = node;
do
{
if (runp->from_pattern == NULL)
{
/* This is a simple entry and therefore we have a
conflict if the strings are really the same. */
if (alias_len == node->from_constpfx_len)
return 1;
}
else
{
/* Compile the regular expression if necessary. */
if (runp->from_regex == NULL)
{
if (__regcomp (&runp->from_regex_mem,
runp->from_pattern,
REG_EXTENDED | REG_ICASE) != 0)
/* Something is wrong. Remember this. */
runp->from_regex = (regex_t *) -1L;
else
runp->from_regex = &runp->from_regex_mem;
}
if (runp->from_regex != (regex_t *) -1L)
{
regmatch_t match[1];
/* Try to match the regular expression. */
if (__regexec (runp->from_regex, alias, 1, match, 0) == 0
&& match[0].rm_so == 0
&& alias[match[0].rm_eo] == '\0')
/* They match, therefore it is a conflict. */
return 1;
}
}
runp = runp->same;
}
while (runp != NULL);
if (alias_len == node->from_constpfx_len)
return 0;
node = node->matching;
}
/* We have a conflict. */
return 1;
else if (cmpres < 0)
node = node->left;
else
@ -201,7 +141,7 @@ add_alias (char *rp, void *modules)
*wp++ = '\0';
/* Test whether this alias conflicts with any available module. */
if (detect_conflict (from, to - from - 1))
if (detect_conflict (from))
/* It does conflict, don't add the alias. */
return;
@ -235,49 +175,27 @@ insert_module (struct gconv_module *newp)
while (*rootp != NULL)
{
struct gconv_module *root = *rootp;
size_t minlen = MIN (newp->from_constpfx_len, root->from_constpfx_len);
int cmpres;
cmpres = strncmp (newp->from_constpfx, root->from_constpfx, minlen);
cmpres = strcmp (newp->from_string, root->from_string);
if (cmpres == 0)
{
/* This can mean two things: the prefix is entirely the same or
it matches only for the minimum length of both strings. */
if (newp->from_constpfx_len == root->from_constpfx_len)
/* Both strings are identical. Insert the string at the
end of the `same' list if it is not already there. */
while (strcmp (newp->from_string, root->from_string) != 0
|| strcmp (newp->to_string, root->to_string) != 0)
{
/* Both prefixes are identical. Insert the string at the
end of the `same' list if it is not already there. */
const char *from_pattern = (newp->from_pattern
?: newp->from_constpfx);
while (strcmp (from_pattern,
root->from_pattern ?: root->from_constpfx) != 0
|| strcmp (newp->to_string, root->to_string) != 0)
{
rootp = &root->same;
root = *rootp;
if (root == NULL)
break;
}
if (root != NULL)
/* This is a no new conversion. */
return;
break;
rootp = &root->same;
root = *rootp;
if (root == NULL)
break;
}
/* The new element either has a prefix which is itself a
prefix for the prefix of the current node or vice verse.
In the first case we insert the node right here. Otherwise
we have to descent further. */
if (newp->from_constpfx_len < root->from_constpfx_len)
{
newp->matching = root;
break;
}
if (root != NULL)
/* This is a no new conversion. */
return;
rootp = &root->matching;
break;
}
else if (cmpres < 0)
rootp = &root->left;
@ -291,7 +209,7 @@ insert_module (struct gconv_module *newp)
/* Add new module. */
static inline void
static void
internal_function
add_module (char *rp, const char *directory, size_t dir_len, void **modules,
size_t *nmodules, int modcounter)
@ -302,22 +220,17 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
3. filename of the module
4. an optional cost value
*/
struct gconv_alias fake_alias;
struct gconv_module *new_module;
char *from, *to, *module, *wp;
size_t const_len;
int from_is_regex;
int need_ext;
int cost_hi;
while (isspace (*rp))
++rp;
from = rp;
from_is_regex = 0;
while (*rp != '\0' && !isspace (*rp))
{
if (!isalnum (*rp) && *rp != '-' && *rp != '/' && *rp != '.'
&& *rp != '_' && *rp != '(' && *rp != ')')
from_is_regex = 1;
*rp = toupper (*rp);
++rp;
}
@ -373,18 +286,12 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
/* We must add the module extension. */
need_ext = sizeof (gconv_module_ext) - 1;
/* We've collected all the information, now create an entry. */
/* See whether we have already an alias with this name defined. */
fake_alias.fromname = strndupa (from, to - from);
if (from_is_regex)
{
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;
if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare) != NULL)
/* This module duplicates an alias. */
return;
new_module = (struct gconv_module *) calloc (1,
sizeof (struct gconv_module)
@ -394,15 +301,11 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
{
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 = new_module->from_constpfx;
new_module->from_string = memcpy ((char *) new_module
+ sizeof (struct gconv_module),
from, to - from);
new_module->from_constpfx_len = const_len;
new_module->to_string = memcpy ((char *) new_module->from_constpfx
new_module->to_string = memcpy ((char *) new_module->from_string
+ (to - from), to, module - to);
new_module->cost_hi = cost_hi;
@ -424,25 +327,6 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
if (need_ext)
memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
/* See whether we have already an alias with this name defined.
We do allow regular expressions matching this any alias since
this expression can also match other names and we test for aliases
before testing for modules. */
if (! from_is_regex)
{
struct gconv_alias fake_alias;
fake_alias.fromname = new_module->from_constpfx;
if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
!= NULL)
{
/* This module duplicates an alias. */
free (new_module);
return;
}
}
/* Now insert the new module data structure in our search tree. */
insert_module (new_module);
}
@ -643,17 +527,14 @@ __gconv_read_conf (void)
for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]);
++cnt)
{
if (builtin_modules[cnt].from_pattern == NULL)
{
struct gconv_alias fake_alias;
struct gconv_alias fake_alias;
fake_alias.fromname = builtin_modules[cnt].from_constpfx;
fake_alias.fromname = builtin_modules[cnt].from_string;
if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
!= NULL)
/* It'll conflict so don't add it. */
continue;
}
if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
!= NULL)
/* It'll conflict so don't add it. */
continue;
insert_module (&builtin_modules[cnt]);
}

View file

@ -375,221 +375,111 @@ find_derivation (const char *toset, const char *toset_expand,
while (node != NULL)
{
int cmpres = strncmp (current->result_set, node->from_constpfx,
MIN (current->result_set_len,
node->from_constpfx_len));
int cmpres = strcmp (current->result_set, node->from_string);
if (cmpres == 0)
{
/* Walk through the list of modules with this prefix and
try to match the name. */
struct gconv_module *runp;
if (current->result_set_len < node->from_constpfx_len)
/* Cannot possibly match. */
break;
/* Check all the modules with this prefix. */
runp = node;
do
{
const char *result_set = NULL;
const char *result_set = (strcmp (runp->to_string, "-") == 0
? (toset_expand ?: toset)
: runp->to_string);
int cost_hi = runp->cost_hi + current->cost_hi;
int cost_lo = runp->cost_lo + current->cost_lo;
struct derivation_step *step;
if (runp->from_pattern == NULL)
/* We managed to find a derivation. First see whether
this is what we are looking for. */
if (strcmp (result_set, toset) == 0
|| (toset_expand != NULL
&& strcmp (result_set, toset_expand) == 0))
{
/* This is a simple entry and therefore we have a
found an matching entry if the strings are really
equal. */
if (current->result_set_len == runp->from_constpfx_len)
if (solution == NULL || cost_hi < best_cost_hi
|| (cost_hi == best_cost_hi
&& cost_lo < best_cost_lo))
{
if (strcmp (runp->to_string, "-") == 0)
result_set = toset_expand ?: toset;
else
result_set = runp->to_string;
best_cost_hi = cost_hi;
best_cost_lo = cost_lo;
}
/* Append this solution to list. */
if (solution == NULL)
solution = NEW_STEP (result_set, 0, 0, runp, current);
else
{
while (solution->next != NULL)
solution = solution->next;
solution->next = NEW_STEP (result_set, 0, 0,
runp, current);
}
}
else
else if (cost_hi < best_cost_hi
|| (cost_hi == best_cost_hi
&& cost_lo < best_cost_lo))
{
/* Compile the regular expression if necessary. */
if (runp->from_regex == NULL)
/* Append at the end if there is no entry with
this name. */
for (step = first; step != NULL; step = step->next)
if (strcmp (result_set, step->result_set) == 0)
break;
if (step == NULL)
{
if (__regcomp (&runp->from_regex_mem,
runp->from_pattern,
REG_EXTENDED | REG_ICASE) != 0)
/* Something is wrong. Remember this. */
runp->from_regex = (regex_t *) -1L;
else
runp->from_regex = &runp->from_regex_mem;
*lastp = NEW_STEP (result_set,
cost_hi, cost_lo,
runp, current);
lastp = &(*lastp)->next;
}
if (runp->from_regex != (regex_t *) -1L)
else if (step->cost_hi > cost_hi
|| (step->cost_hi == cost_hi
&& step->cost_lo > cost_lo))
{
regmatch_t match[4];
step->code = runp;
step->last = current;
/* Try to match the regular expression. */
if (__regexec (runp->from_regex, current->result_set,
4, match, 0) == 0
&& match[0].rm_so == 0
&& current->result_set[match[0].rm_eo] == '\0')
/* Update the cost for all steps. */
for (step = first; step != NULL;
step = step->next)
{
/* At least the whole <from> string is matched.
We must now match sed-like possible
subexpressions from the match to the
toset expression. */
#define ENSURE_LEN(LEN) \
if (wp + (LEN) >= constr + len - 1) \
{ \
char *newp = alloca (len += 128); \
wp = __mempcpy (newp, constr, wp - constr); \
constr = newp; \
}
size_t len = 128;
char *constr = alloca (len);
char *wp = constr;
const char *cp = runp->to_string;
struct derivation_step *back;
while (*cp != '\0')
{
if (*cp != '\\')
{
ENSURE_LEN (1);
*wp++ = *cp++;
}
else if (cp[1] == '\0')
/* Backslash at end of string. */
break;
else
{
++cp;
if (*cp == '\\')
{
*wp++ = *cp++;
ENSURE_LEN (1);
}
else if (*cp < '1' || *cp > '3')
break;
else
{
int idx = *cp - '0';
if (match[idx].rm_so == -1)
/* No match. */
break;
if (step->code == NULL)
/* This is one of the entries we started
from. */
continue;
ENSURE_LEN (match[idx].rm_eo
- match[idx].rm_so);
wp = __mempcpy (wp,
&current->result_set[match[idx].rm_so],
match[idx].rm_eo
- match[idx].rm_so);
++cp;
}
}
}
if (*cp == '\0' && wp != constr)
step->cost_hi = step->code->cost_hi;
step->cost_lo = step->code->cost_lo;
for (back = step->last; back->code != NULL;
back = back->last)
{
/* Terminate the constructed string. */
*wp = '\0';
result_set = constr;
step->cost_hi += back->code->cost_hi;
step->cost_lo += back->code->cost_lo;
}
}
}
}
if (result_set != NULL)
{
int cost_hi = runp->cost_hi + current->cost_hi;
int cost_lo = runp->cost_lo + current->cost_lo;
struct derivation_step *step;
/* We managed to find a derivation. First see whether
this is what we are looking for. */
if (strcmp (result_set, toset) == 0
|| (toset_expand != NULL
&& strcmp (result_set, toset_expand) == 0))
{
if (solution == NULL || cost_hi < best_cost_hi
|| (cost_hi == best_cost_hi
&& cost_lo < best_cost_lo))
for (step = solution; step != NULL;
step = step->next)
{
best_cost_hi = cost_hi;
best_cost_lo = cost_lo;
}
step->cost_hi = (step->code->cost_hi
+ step->last->cost_hi);
step->cost_lo = (step->code->cost_lo
+ step->last->cost_lo);
/* Append this solution to list. */
if (solution == NULL)
solution = NEW_STEP (result_set, 0, 0, runp,
current);
else
{
while (solution->next != NULL)
solution = solution->next;
solution->next = NEW_STEP (result_set, 0, 0,
runp, current);
}
}
else if (cost_hi < best_cost_hi
|| (cost_hi == best_cost_hi
&& cost_lo < best_cost_lo))
{
/* Append at the end if there is no entry with
this name. */
for (step = first; step != NULL; step = step->next)
if (strcmp (result_set, step->result_set) == 0)
break;
if (step == NULL)
{
*lastp = NEW_STEP (result_set,
cost_hi, cost_lo,
runp, current);
lastp = &(*lastp)->next;
}
else if (step->cost_hi > cost_hi
|| (step->cost_hi == cost_hi
&& step->cost_lo > cost_lo))
{
step->code = runp;
step->last = current;
/* Update the cost for all steps. */
for (step = first; step != NULL;
step = step->next)
if (step->cost_hi < best_cost_hi
|| (step->cost_hi == best_cost_hi
&& step->cost_lo < best_cost_lo))
{
struct derivation_step *back;
if (step->code == NULL)
/* This is one of the entries we started
from. */
continue;
step->cost_hi = step->code->cost_hi;
step->cost_lo = step->code->cost_lo;
for (back = step->last; back->code != NULL;
back = back->last)
{
step->cost_hi += back->code->cost_hi;
step->cost_lo += back->code->cost_lo;
}
}
for (step = solution; step != NULL;
step = step->next)
{
step->cost_hi = (step->code->cost_hi
+ step->last->cost_hi);
step->cost_lo = (step->code->cost_lo
+ step->last->cost_lo);
if (step->cost_hi < best_cost_hi
|| (step->cost_hi == best_cost_hi
&& step->cost_lo < best_cost_lo))
{
solution = step;
best_cost_hi = step->cost_hi;
best_cost_lo = step->cost_lo;
}
solution = step;
best_cost_hi = step->cost_hi;
best_cost_lo = step->cost_lo;
}
}
}
@ -599,10 +489,7 @@ find_derivation (const char *toset, const char *toset_expand,
}
while (runp != NULL);
if (current->result_set_len == node->from_constpfx_len)
break;
node = node->matching;
break;
}
else if (cmpres < 0)
node = node->left;
@ -738,12 +625,10 @@ free_modules_db (struct gconv_module *node)
free_modules_db (node->left);
if (node->right != NULL)
free_modules_db (node->right);
if (node->same != NULL)
free_modules_db (node->same);
do
{
struct gconv_module *act = node;
node = node->matching;
node = node->same;
if (act->module_name[0] == '/')
free (act);
}

View file

@ -21,7 +21,6 @@
#define _GCONV_INT_H 1
#include "gconv.h"
#include <regex.h>
__BEGIN_DECLS
@ -76,12 +75,7 @@ struct __gconv_loaded_object
/* Description for an available conversion module. */
struct gconv_module
{
const char *from_pattern;
const char *from_constpfx;
size_t from_constpfx_len;
const regex_t *from_regex;
regex_t from_regex_mem;
const char *from_string;
const char *to_string;
int cost_hi;
@ -91,7 +85,6 @@ struct gconv_module
struct gconv_module *left; /* Prefix smaller. */
struct gconv_module *same; /* List of entries with identical prefix. */
struct gconv_module *matching;/* Next node with more specific prefix. */
struct gconv_module *right; /* Prefix larger. */
};

View file

@ -595,23 +595,15 @@ add_known_names (struct gconv_module *node)
add_known_names (node->left);
if (node->right != NULL)
add_known_names (node->right);
if (node->same != NULL)
add_known_names (node->same);
do
{
if (node->from_pattern == NULL)
{
if (strcmp (node->from_constpfx, "INTERNAL"))
tsearch (node->from_constpfx, &printlist,
(__compar_fn_t) strverscmp);
if (strcmp (node->to_string, "INTERNAL"))
tsearch (node->to_string, &printlist, (__compar_fn_t) strverscmp);
}
else
if (strcmp (node->from_pattern, "INTERNAL"))
tsearch (node->from_pattern, &printlist, (__compar_fn_t) strverscmp);
if (strcmp (node->from_string, "INTERNAL"))
tsearch (node->from_string, &printlist,
(__compar_fn_t) strverscmp);
if (strcmp (node->to_string, "INTERNAL"))
tsearch (node->to_string, &printlist, (__compar_fn_t) strverscmp);
node = node->matching;
node = node->same;
}
while (node != NULL);
}
@ -636,10 +628,7 @@ print_known_names (void)
The following list contain all the coded character sets known. This does\n\
not necessarily mean that all combinations of these names can be used for\n\
the FROM and TO command line parameters. One coded character set can be\n\
listed with several different names (aliases).\n\
Some of the names are no plain strings but instead regular expressions and\n\
they match a variety of names which can be given as parameters to the\n\
program.\n\n "), stdout);
listed with several different names (aliases).\n\n "), stdout);
/* Now print the collected names. */
column = 2;

View file

@ -1,3 +1,36 @@
2000-06-19 Ulrich Drepper <drepper@redhat.com>
* sysdeps/pthread/timer_create.c: Use _set_errno instead of assigning
to errno directly.
* sysdeps/pthread/timer_delete.c: Likewise.
* sysdeps/pthread/timer_getoverr.c: Likewise.
* sysdeps/pthread/timer_gettime.c: Likewise.
* sysdeps/pthread/timer_settime.c: Likewise.
2000-06-13 Kaz Kylheku <kaz@ashi.footprints.net>
Timer nodes are now reference counted, and can be marked
as deleted. This allows for the safe release of the global mutex
in the middle without losing the timer being operated on.
* sysdeps/pthread/posix-timer.h (struct timer_node): The inuse
member is now an enum with three values, so that an intermediate
state can be represented (deleted but not free for reuse yet).
New refcount member added.
* sysdeps/pthread/timer_routines.c: Likewise.
* sysdeps/pthread/posix-timer.h (timer_addref, timer_delref,
timer_valid): New inline functions added.
* sysdeps/pthread/timer_gettime.c (timer_gettime): Function
restructured, recursive deadlock bug fixed.
* sysdeps/pthread/timer_gettime.c (timer_gettime): Uses new
timer_addref to ensure that timer won't be deleted while mutex is not
held. Also uses timer_invalid to perform validation of timer handle.
* sysdeps/pthread/timer_settime.c (timer_settime): Likewise.
* sysdeps/pthread/timer_getoverr.c (timer_getoverrun): Likewise.
2000-06-14 Ulrich Drepper <drepper@redhat.com>
* shlib-versions: Add entry for SH.

View file

@ -59,9 +59,12 @@ struct timer_node
pthread_attr_t attr;
unsigned int abstime;
unsigned int armed;
unsigned int inuse;
enum {
TIMER_FREE, TIMER_INUSE, TIMER_DELETED
} inuse;
struct thread_node *thread;
pid_t creator_pid;
int refcount;
};
@ -106,6 +109,28 @@ timer_ptr2id (struct timer_node *timer)
return timer - __timer_array;
}
/* Check whether timer is valid; global mutex must be held. */
static inline int
timer_valid (struct timer_node *timer)
{
return timer && timer->inuse == TIMER_INUSE;
}
/* Timer refcount functions; need global mutex. */
extern void __timer_dealloc (struct timer_node *timer);
static inline void
timer_addref (struct timer_node *timer)
{
timer->refcount++;
}
static inline void
timer_delref (struct timer_node *timer)
{
if (--timer->refcount == 0)
__timer_dealloc (timer);
}
/* Timespec helper routines. */
static inline int
@ -178,7 +203,6 @@ extern struct timer_node *__timer_alloc (void);
extern int __timer_thread_start (struct thread_node *thread);
extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t);
extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t);
extern void __timer_dealloc (struct timer_node *timer);
extern void __timer_thread_dealloc (struct thread_node *thread);
extern int __timer_thread_queue_timer (struct thread_node *thread,
struct timer_node *insert);

View file

@ -34,8 +34,8 @@ timer_getoverrun (timerid)
pthread_mutex_lock (&__timer_mutex);
if ((timer = timer_id2ptr (timerid)) == NULL || !timer->inuse)
errno = EINVAL;
if (! timer_valid (timer = timer_id2ptr (timerid)))
__set_errno (EINVAL);
else
retval = 0; /* TODO: overrun counting not supported */

View file

@ -31,25 +31,30 @@ timer_gettime (timerid, value)
struct itimerspec *value;
{
struct timer_node *timer;
struct timespec now;
int retval = -1;
struct timespec now, expiry;
int retval = -1, armed = 0, valid;
clock_t clock = 0;
pthread_mutex_lock (&__timer_mutex);
timer = timer_id2ptr (timerid);
if (timer == NULL && !timer->inuse)
/* Invalid timer ID or the timer is not in use. */
errno = EINVAL;
else
{
value->it_interval = timer->value.it_interval;
valid = timer_valid (timer);
if (timer->armed)
if (valid) {
armed = timer->armed;
expiry = timer->expirytime;
clock = timer->clock;
value->it_interval = timer->value.it_interval;
}
pthread_mutex_unlock (&__timer_mutex);
if (valid)
{
if (armed)
{
pthread_mutex_unlock (&__timer_mutex);
clock_gettime (timer->clock, &now);
pthread_mutex_lock (&__timer_mutex);
timespec_sub (&value->it_value, &timer->expirytime, &now);
clock_gettime (clock, &now);
timespec_sub (&value->it_value, &expiry, &now);
}
else
{
@ -59,8 +64,8 @@ timer_gettime (timerid, value)
retval = 0;
}
pthread_mutex_lock (&__timer_mutex);
else
__set_errno (EINVAL);
return retval;
}

View file

@ -181,7 +181,7 @@ init_module (void)
for (i = 0; i < TIMER_MAX; ++i)
{
list_append (&timer_free_list, &__timer_array[i].links);
__timer_array[i].inuse = 0;
__timer_array[i].inuse = TIMER_FREE;
}
for (i = 0; i < THREAD_MAXNODES; ++i)
@ -309,7 +309,7 @@ thread_cleanup (void *val)
static void
thread_expire_timer (struct thread_node *self, struct timer_node *timer)
{
self->current_timer = timer;
self->current_timer = timer; /* Lets timer_delete know timer is running. */
pthread_mutex_unlock (&__timer_mutex);
@ -443,7 +443,7 @@ thread_func (void *arg)
}
/* Enqueue a timer in wakeup order in the thread's timer queue.
/* Enqueue a timer in wakeup order in the thread's timer queue.
Returns 1 if the timer was inserted at the head of the queue,
causing the queue's next wakeup time to change. */
@ -551,7 +551,8 @@ __timer_alloc (void)
{
struct timer_node *timer = timer_links2ptr (node);
list_unlink_ip (node);
timer->inuse = 1;
timer->inuse = TIMER_INUSE;
timer->refcount = 1;
return timer;
}
@ -564,8 +565,9 @@ __timer_alloc (void)
void
__timer_dealloc (struct timer_node *timer)
{
assert (timer->refcount == 0);
timer->thread = NULL; /* Break association between timer and thread. */
timer->inuse = 0;
timer->inuse = TIMER_FREE;
list_append (&timer_free_list, &timer->links);
}

View file

@ -41,7 +41,7 @@ timer_settime (timerid, flags, value, ovalue)
timer = timer_id2ptr (timerid);
if (timer == NULL)
{
errno = EINVAL;
__set_errno (EINVAL);
goto bail;
}
@ -50,7 +50,7 @@ timer_settime (timerid, flags, value, ovalue)
|| value->it_value.tv_nsec < 0
|| value->it_value.tv_nsec >= 1000000000)
{
errno = EINVAL;
__set_errno (EINVAL);
goto bail;
}
@ -64,13 +64,14 @@ timer_settime (timerid, flags, value, ovalue)
}
pthread_mutex_lock (&__timer_mutex);
timer_addref (timer);
/* One final check of timer validity; this one is possible only
until we have the mutex, which guards the inuse flag. */
until we have the mutex, because it accesses the inuse flag. */
if (!timer->inuse)
if (! timer_valid(timer))
{
errno = EINVAL;
__set_errno (EINVAL);
goto unlock_bail;
}
@ -86,6 +87,7 @@ timer_settime (timerid, flags, value, ovalue)
clock_gettime (timer->clock, &now);
have_now = 1;
pthread_mutex_lock (&__timer_mutex);
timer_addref (timer);
}
timespec_sub (&ovalue->it_value, &timer->expirytime, &now);
@ -123,6 +125,7 @@ timer_settime (timerid, flags, value, ovalue)
retval = 0;
unlock_bail:
timer_delref (timer);
pthread_mutex_unlock (&__timer_mutex);
bail: