1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00
* 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> 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. * iconv/gconv.h (__gconv_trans_fct): Add new parameter.
General namespace cleanup. General namespace cleanup.
(struct __gconv_trans_data): Add next field. (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 ("OSF00010105//", "ISO-10646/UCS4/") /* level 2 */
BUILTIN_ALIAS ("OSF00010106//", "ISO-10646/UCS4/") /* level 3 */ BUILTIN_ALIAS ("OSF00010106//", "ISO-10646/UCS4/") /* level 3 */
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
"ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
__gconv_transform_internal_ucs4, NULL, NULL, __gconv_transform_internal_ucs4, NULL, NULL,
4, 4, 4, 4) 4, 4, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15, BUILTIN_TRANSFORMATION ("ISO-10646/UCS4/", "INTERNAL", 1, "=ucs4->INTERNAL",
"INTERNAL", 1, "=ucs4->INTERNAL",
__gconv_transform_ucs4_internal, NULL, NULL, __gconv_transform_ucs4_internal, NULL, NULL,
4, 4, 4, 4) 4, 4, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, BUILTIN_TRANSFORMATION ("INTERNAL", "UCS-4LE//", 1, "=INTERNAL->ucs4le",
"UCS-4LE//", 1, "=INTERNAL->ucs4le",
__gconv_transform_internal_ucs4le, NULL, NULL, __gconv_transform_internal_ucs4le, NULL, NULL,
4, 4, 4, 4) 4, 4, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "UCS-4LE//", 15, BUILTIN_TRANSFORMATION ("UCS-4LE//", "INTERNAL", 1, "=ucs4le->INTERNAL",
"INTERNAL", 1, "=ucs4le->INTERNAL",
__gconv_transform_ucs4le_internal, NULL, NULL, __gconv_transform_ucs4le_internal, NULL, NULL,
4, 4, 4, 4) 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 ("ISO-IR-193//", "ISO-10646/UTF8/")
BUILTIN_ALIAS ("OSF05010001//", "ISO-10646/UTF8/") BUILTIN_ALIAS ("OSF05010001//", "ISO-10646/UTF8/")
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
"ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
__gconv_transform_internal_utf8, NULL, NULL, __gconv_transform_internal_utf8, NULL, NULL,
4, 4, 1, 6) 4, 4, 1, 6)
BUILTIN_TRANSFORMATION ("ISO-10646/UTF-?8/", "ISO-10646/UTF", 13, BUILTIN_TRANSFORMATION ("ISO-10646/UTF-8/", "INTERNAL", 1, "=utf8->INTERNAL",
"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, __gconv_transform_utf8_internal, NULL, NULL,
1, 6, 4, 4) 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 ("OSF00010101//", "ISO-10646/UCS2/") /* level 2 */
BUILTIN_ALIAS ("OSF00010102//", "ISO-10646/UCS2/") /* level 3 */ BUILTIN_ALIAS ("OSF00010102//", "ISO-10646/UCS2/") /* level 3 */
BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS2/", 15, "INTERNAL", BUILTIN_TRANSFORMATION ("ISO-10646/UCS2/", "INTERNAL", 1, "=ucs2->INTERNAL",
1, "=ucs2->INTERNAL",
__gconv_transform_ucs2_internal, NULL, NULL, __gconv_transform_ucs2_internal, NULL, NULL,
2, 2, 4, 4) 2, 2, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "ISO-10646/UCS2/", BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS2/", 1, "=INTERNAL->ucs2",
1, "=INTERNAL->ucs2",
__gconv_transform_internal_ucs2, NULL, NULL, __gconv_transform_internal_ucs2, NULL, NULL,
4, 4, 2, 2) 4, 4, 2, 2)
@ -85,13 +80,13 @@ BUILTIN_ALIAS ("UCS-2BE//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2LE//", "UNICODELITTLE//") BUILTIN_ALIAS ("UCS-2LE//", "UNICODELITTLE//")
BUILTIN_TRANSFORMATION (NULL, "UNICODELITTLE//", 15, "INTERNAL", BUILTIN_TRANSFORMATION ("UNICODELITTLE//", "INTERNAL", 1,
1, "=ucs2reverse->INTERNAL", "=ucs2reverse->INTERNAL",
__gconv_transform_ucs2reverse_internal, NULL, NULL, __gconv_transform_ucs2reverse_internal, NULL, NULL,
2, 2, 4, 4) 2, 2, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "UNICODELITTLE//", BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODELITTLE//", 1,
1, "=INTERNAL->ucs2reverse", "=INTERNAL->ucs2reverse",
__gconv_transform_internal_ucs2reverse, NULL, NULL, __gconv_transform_internal_ucs2reverse, NULL, NULL,
4, 4, 2, 2) 4, 4, 2, 2)
#else #else
@ -100,13 +95,13 @@ BUILTIN_ALIAS ("UCS-2LE//", "ISO-10646/UCS2/")
BUILTIN_ALIAS ("UCS-2BE//", "UNICODEBIG//") BUILTIN_ALIAS ("UCS-2BE//", "UNICODEBIG//")
BUILTIN_TRANSFORMATION (NULL, "UNICODEBIG//", 12, "INTERNAL", BUILTIN_TRANSFORMATION ("UNICODEBIG//", "INTERNAL", 1,
1, "=ucs2reverse->INTERNAL", "=ucs2reverse->INTERNAL",
__gconv_transform_ucs2reverse_internal, NULL, NULL, __gconv_transform_ucs2reverse_internal, NULL, NULL,
2, 2, 4, 4) 2, 2, 4, 4)
BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "UNICODEBIG//", BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODEBIG//", 1,
1, "=INTERNAL->ucs2reverse", "=INTERNAL->ucs2reverse",
__gconv_transform_internal_ucs2reverse, NULL, NULL, __gconv_transform_internal_ucs2reverse, NULL, NULL,
4, 4, 2, 2) 4, 4, 2, 2)
#endif #endif

View File

@ -56,13 +56,10 @@ 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, ConstPfx, ConstLen, To, Cost, Name, \ #define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
Fct, Init, End, MinF, MaxF, MinT, MaxT) \ MaxF, MinT, MaxT) \
{ \ { \
from_pattern: From, \ from_string: From, \
from_constpfx: ConstPfx, \
from_constpfx_len: ConstLen, \
from_regex: NULL, \
to_string: To, \ to_string: To, \
cost_hi: Cost, \ cost_hi: Cost, \
cost_lo: INT_MAX, \ cost_lo: INT_MAX, \
@ -78,8 +75,8 @@ static struct gconv_module builtin_modules[] =
static const char *builtin_aliases[] = static const char *builtin_aliases[] =
{ {
#define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \ #define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
Fct, Init, End, MinF, MaxF, MinT, MaxT) MaxF, MinT, MaxT)
#define BUILTIN_ALIAS(From, To) From " " To, #define BUILTIN_ALIAS(From, To) From " " To,
#include "gconv_builtin.h" #include "gconv_builtin.h"
@ -94,74 +91,17 @@ static const char *builtin_aliases[] =
/* 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
detect_conflict (const char *alias, size_t alias_len) detect_conflict (const char *alias)
{ {
struct gconv_module *node = __gconv_modules_db; struct gconv_module *node = __gconv_modules_db;
while (node != NULL) while (node != NULL)
{ {
int cmpres = strncmp (alias, node->from_constpfx, int cmpres = strcmp (alias, node->from_string);
MIN (alias_len, node->from_constpfx_len));
if (cmpres == 0) if (cmpres == 0)
{ /* We have a conflict. */
struct gconv_module *runp; return 1;
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;
}
else if (cmpres < 0) else if (cmpres < 0)
node = node->left; node = node->left;
else else
@ -201,7 +141,7 @@ add_alias (char *rp, void *modules)
*wp++ = '\0'; *wp++ = '\0';
/* Test whether this alias conflicts with any available module. */ /* 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. */ /* It does conflict, don't add the alias. */
return; return;
@ -235,49 +175,27 @@ insert_module (struct gconv_module *newp)
while (*rootp != NULL) while (*rootp != NULL)
{ {
struct gconv_module *root = *rootp; struct gconv_module *root = *rootp;
size_t minlen = MIN (newp->from_constpfx_len, root->from_constpfx_len);
int cmpres; int cmpres;
cmpres = strncmp (newp->from_constpfx, root->from_constpfx, minlen); cmpres = strcmp (newp->from_string, root->from_string);
if (cmpres == 0) if (cmpres == 0)
{ {
/* This can mean two things: the prefix is entirely the same or /* Both strings are identical. Insert the string at the
it matches only for the minimum length of both strings. */ end of the `same' list if it is not already there. */
if (newp->from_constpfx_len == root->from_constpfx_len) 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 rootp = &root->same;
end of the `same' list if it is not already there. */ root = *rootp;
const char *from_pattern = (newp->from_pattern if (root == NULL)
?: newp->from_constpfx); break;
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;
} }
/* The new element either has a prefix which is itself a if (root != NULL)
prefix for the prefix of the current node or vice verse. /* This is a no new conversion. */
In the first case we insert the node right here. Otherwise return;
we have to descent further. */
if (newp->from_constpfx_len < root->from_constpfx_len)
{
newp->matching = root;
break;
}
rootp = &root->matching; break;
} }
else if (cmpres < 0) else if (cmpres < 0)
rootp = &root->left; rootp = &root->left;
@ -291,7 +209,7 @@ insert_module (struct gconv_module *newp)
/* Add new module. */ /* Add new module. */
static inline void static void
internal_function internal_function
add_module (char *rp, const char *directory, size_t dir_len, void **modules, add_module (char *rp, const char *directory, size_t dir_len, void **modules,
size_t *nmodules, int modcounter) 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 3. filename of the module
4. an optional cost value 4. an optional cost value
*/ */
struct gconv_alias fake_alias;
struct gconv_module *new_module; struct gconv_module *new_module;
char *from, *to, *module, *wp; char *from, *to, *module, *wp;
size_t const_len;
int from_is_regex;
int need_ext; int need_ext;
int cost_hi; int cost_hi;
while (isspace (*rp)) while (isspace (*rp))
++rp; ++rp;
from = rp; from = rp;
from_is_regex = 0;
while (*rp != '\0' && !isspace (*rp)) while (*rp != '\0' && !isspace (*rp))
{ {
if (!isalnum (*rp) && *rp != '-' && *rp != '/' && *rp != '.'
&& *rp != '_' && *rp != '(' && *rp != ')')
from_is_regex = 1;
*rp = toupper (*rp); *rp = toupper (*rp);
++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. */ /* We must add the module extension. */
need_ext = sizeof (gconv_module_ext) - 1; 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) if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare) != NULL)
{ /* This module duplicates an alias. */
const_len = 0; return;
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 *) calloc (1, new_module = (struct gconv_module *) calloc (1,
sizeof (struct gconv_module) sizeof (struct gconv_module)
@ -394,15 +301,11 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
{ {
char *tmp; char *tmp;
new_module->from_constpfx = memcpy ((char *) new_module new_module->from_string = memcpy ((char *) new_module
+ sizeof (struct gconv_module), + sizeof (struct gconv_module),
from, to - from); from, to - from);
if (from_is_regex)
new_module->from_pattern = new_module->from_constpfx;
new_module->from_constpfx_len = const_len; new_module->to_string = memcpy ((char *) new_module->from_string
new_module->to_string = memcpy ((char *) new_module->from_constpfx
+ (to - from), to, module - to); + (to - from), to, module - to);
new_module->cost_hi = cost_hi; 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) if (need_ext)
memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_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. */ /* Now insert the new module data structure in our search tree. */
insert_module (new_module); insert_module (new_module);
} }
@ -643,17 +527,14 @@ __gconv_read_conf (void)
for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]); for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]);
++cnt) ++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) if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
!= NULL) != NULL)
/* It'll conflict so don't add it. */ /* It'll conflict so don't add it. */
continue; continue;
}
insert_module (&builtin_modules[cnt]); insert_module (&builtin_modules[cnt]);
} }

View File

@ -375,221 +375,111 @@ find_derivation (const char *toset, const char *toset_expand,
while (node != NULL) while (node != NULL)
{ {
int cmpres = strncmp (current->result_set, node->from_constpfx, int cmpres = strcmp (current->result_set, node->from_string);
MIN (current->result_set_len,
node->from_constpfx_len));
if (cmpres == 0) if (cmpres == 0)
{ {
/* Walk through the list of modules with this prefix and /* Walk through the list of modules with this prefix and
try to match the name. */ try to match the name. */
struct gconv_module *runp; struct gconv_module *runp;
if (current->result_set_len < node->from_constpfx_len)
/* Cannot possibly match. */
break;
/* Check all the modules with this prefix. */ /* Check all the modules with this prefix. */
runp = node; runp = node;
do 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 if (solution == NULL || cost_hi < best_cost_hi
found an matching entry if the strings are really || (cost_hi == best_cost_hi
equal. */ && cost_lo < best_cost_lo))
if (current->result_set_len == runp->from_constpfx_len)
{ {
if (strcmp (runp->to_string, "-") == 0) best_cost_hi = cost_hi;
result_set = toset_expand ?: toset; best_cost_lo = cost_lo;
else }
result_set = runp->to_string;
/* 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. */ /* Append at the end if there is no entry with
if (runp->from_regex == NULL) 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, *lastp = NEW_STEP (result_set,
runp->from_pattern, cost_hi, cost_lo,
REG_EXTENDED | REG_ICASE) != 0) runp, current);
/* Something is wrong. Remember this. */ lastp = &(*lastp)->next;
runp->from_regex = (regex_t *) -1L;
else
runp->from_regex = &runp->from_regex_mem;
} }
else if (step->cost_hi > cost_hi
if (runp->from_regex != (regex_t *) -1L) || (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. */ /* Update the cost for all steps. */
if (__regexec (runp->from_regex, current->result_set, for (step = first; step != NULL;
4, match, 0) == 0 step = step->next)
&& match[0].rm_so == 0
&& current->result_set[match[0].rm_eo] == '\0')
{ {
/* At least the whole <from> string is matched. struct derivation_step *back;
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;
while (*cp != '\0') if (step->code == NULL)
{ /* This is one of the entries we started
if (*cp != '\\') from. */
{ continue;
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;
ENSURE_LEN (match[idx].rm_eo step->cost_hi = step->code->cost_hi;
- match[idx].rm_so); step->cost_lo = step->code->cost_lo;
wp = __mempcpy (wp,
&current->result_set[match[idx].rm_so], for (back = step->last; back->code != NULL;
match[idx].rm_eo back = back->last)
- match[idx].rm_so);
++cp;
}
}
}
if (*cp == '\0' && wp != constr)
{ {
/* Terminate the constructed string. */ step->cost_hi += back->code->cost_hi;
*wp = '\0'; step->cost_lo += back->code->cost_lo;
result_set = constr;
} }
} }
}
}
if (result_set != NULL) for (step = solution; step != NULL;
{ step = step->next)
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))
{ {
best_cost_hi = cost_hi; step->cost_hi = (step->code->cost_hi
best_cost_lo = cost_lo; + step->last->cost_hi);
} step->cost_lo = (step->code->cost_lo
+ step->last->cost_lo);
/* Append this solution to list. */ if (step->cost_hi < best_cost_hi
if (solution == NULL) || (step->cost_hi == best_cost_hi
solution = NEW_STEP (result_set, 0, 0, runp, && step->cost_lo < best_cost_lo))
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)
{ {
struct derivation_step *back; solution = step;
best_cost_hi = step->cost_hi;
if (step->code == NULL) best_cost_lo = step->cost_lo;
/* 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;
}
} }
} }
} }
@ -599,10 +489,7 @@ find_derivation (const char *toset, const char *toset_expand,
} }
while (runp != NULL); while (runp != NULL);
if (current->result_set_len == node->from_constpfx_len) break;
break;
node = node->matching;
} }
else if (cmpres < 0) else if (cmpres < 0)
node = node->left; node = node->left;
@ -738,12 +625,10 @@ free_modules_db (struct gconv_module *node)
free_modules_db (node->left); free_modules_db (node->left);
if (node->right != NULL) if (node->right != NULL)
free_modules_db (node->right); free_modules_db (node->right);
if (node->same != NULL)
free_modules_db (node->same);
do do
{ {
struct gconv_module *act = node; struct gconv_module *act = node;
node = node->matching; node = node->same;
if (act->module_name[0] == '/') if (act->module_name[0] == '/')
free (act); free (act);
} }

View File

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

View File

@ -595,23 +595,15 @@ add_known_names (struct gconv_module *node)
add_known_names (node->left); add_known_names (node->left);
if (node->right != NULL) if (node->right != NULL)
add_known_names (node->right); add_known_names (node->right);
if (node->same != NULL)
add_known_names (node->same);
do do
{ {
if (node->from_pattern == NULL) if (strcmp (node->from_string, "INTERNAL"))
{ tsearch (node->from_string, &printlist,
if (strcmp (node->from_constpfx, "INTERNAL")) (__compar_fn_t) strverscmp);
tsearch (node->from_constpfx, &printlist, if (strcmp (node->to_string, "INTERNAL"))
(__compar_fn_t) strverscmp); tsearch (node->to_string, &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);
node = node->matching; node = node->same;
} }
while (node != NULL); while (node != NULL);
} }
@ -636,10 +628,7 @@ print_known_names (void)
The following list contain all the coded character sets known. This does\n\ 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\ 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\ the FROM and TO command line parameters. One coded character set can be\n\
listed with several different names (aliases).\n\ listed with several different names (aliases).\n\n "), stdout);
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);
/* Now print the collected names. */ /* Now print the collected names. */
column = 2; 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> 2000-06-14 Ulrich Drepper <drepper@redhat.com>
* shlib-versions: Add entry for SH. * shlib-versions: Add entry for SH.

View File

@ -59,9 +59,12 @@ struct timer_node
pthread_attr_t attr; pthread_attr_t attr;
unsigned int abstime; unsigned int abstime;
unsigned int armed; unsigned int armed;
unsigned int inuse; enum {
TIMER_FREE, TIMER_INUSE, TIMER_DELETED
} inuse;
struct thread_node *thread; struct thread_node *thread;
pid_t creator_pid; pid_t creator_pid;
int refcount;
}; };
@ -106,6 +109,28 @@ timer_ptr2id (struct timer_node *timer)
return timer - __timer_array; 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. */ /* Timespec helper routines. */
static inline int static inline int
@ -178,7 +203,6 @@ extern struct timer_node *__timer_alloc (void);
extern int __timer_thread_start (struct thread_node *thread); 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_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 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 void __timer_thread_dealloc (struct thread_node *thread);
extern int __timer_thread_queue_timer (struct thread_node *thread, extern int __timer_thread_queue_timer (struct thread_node *thread,
struct timer_node *insert); struct timer_node *insert);

View File

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

View File

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

View File

@ -181,7 +181,7 @@ init_module (void)
for (i = 0; i < TIMER_MAX; ++i) for (i = 0; i < TIMER_MAX; ++i)
{ {
list_append (&timer_free_list, &__timer_array[i].links); 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) for (i = 0; i < THREAD_MAXNODES; ++i)
@ -309,7 +309,7 @@ thread_cleanup (void *val)
static void static void
thread_expire_timer (struct thread_node *self, struct timer_node *timer) 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); pthread_mutex_unlock (&__timer_mutex);
@ -551,7 +551,8 @@ __timer_alloc (void)
{ {
struct timer_node *timer = timer_links2ptr (node); struct timer_node *timer = timer_links2ptr (node);
list_unlink_ip (node); list_unlink_ip (node);
timer->inuse = 1; timer->inuse = TIMER_INUSE;
timer->refcount = 1;
return timer; return timer;
} }
@ -564,8 +565,9 @@ __timer_alloc (void)
void void
__timer_dealloc (struct timer_node *timer) __timer_dealloc (struct timer_node *timer)
{ {
assert (timer->refcount == 0);
timer->thread = NULL; /* Break association between timer and thread. */ timer->thread = NULL; /* Break association between timer and thread. */
timer->inuse = 0; timer->inuse = TIMER_FREE;
list_append (&timer_free_list, &timer->links); list_append (&timer_free_list, &timer->links);
} }

View File

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