mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-18 06:30:05 +00:00
Update.
* 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:
parent
d620426811
commit
d2dfc5de01
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
}
|
||||
|
269
iconv/gconv_db.c
269
iconv/gconv_db.c
@ -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,
|
||||
¤t->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);
|
||||
}
|
||||
|
@ -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. */
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user