mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-30 22:43:12 +03: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:
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
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)
|
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,
|
|
||||||
¤t->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);
|
||||||
}
|
}
|
||||||
|
@ -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. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
Reference in New Issue
Block a user