aboutsummaryrefslogtreecommitdiff
path: root/locale/programs/ld-collate.c
diff options
context:
space:
mode:
Diffstat (limited to 'locale/programs/ld-collate.c')
-rw-r--r--locale/programs/ld-collate.c107
1 files changed, 63 insertions, 44 deletions
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index a9f42fe3fc..2e3707d78f 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -108,6 +108,7 @@ struct element_t
/* Next element in multibyte output list. */
struct element_t *mbnext;
+ struct element_t *mblast;
/* Next element in wide character output list. */
struct element_t *wcnext;
@@ -209,7 +210,6 @@ static const unsigned char encoding_byte[] =
static inline int
utf8_encode (char *buf, int val)
{
- char *startp = buf;
int retval;
if (val < 0x80)
@@ -237,7 +237,7 @@ utf8_encode (char *buf, int val)
*buf |= val;
}
- return buf - startp;
+ return retval;
}
@@ -309,6 +309,7 @@ new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen,
newp->next = NULL;
newp->mbnext = NULL;
+ newp->mblast = NULL;
return newp;
}
@@ -800,7 +801,10 @@ insert_weights (struct linereader *ldfile, struct element_t *elem,
{
elem->weights[weight_cnt].w = (struct element_t **)
obstack_alloc (&collate->mempool, sizeof (struct element_t *));
- elem->weights[weight_cnt].w[0] = elem;
+ if (ellipsis == tok_none)
+ elem->weights[weight_cnt].w[0] = elem;
+ else
+ elem->weights[weight_cnt].w[0] = ELEMENT_ELLIPSIS2;
elem->weights[weight_cnt].cnt = 1;
}
while (++weight_cnt < nrules);
@@ -1047,14 +1051,14 @@ sequence is not lower than that of the last character"), "LC_COLLATE");
struct element_t *elem;
size_t namelen;
- if (seq->ucs4 == UNINITIALIZED_CHAR_VALUE)
- seq->ucs4 = repertoire_find_value (repertoire, seq->name,
- strlen (seq->name));
-
/* I don't this this can ever happen. */
assert (seq->name != NULL);
namelen = strlen (seq->name);
+ if (seq->ucs4 == UNINITIALIZED_CHAR_VALUE)
+ seq->ucs4 = repertoire_find_value (repertoire, seq->name,
+ namelen);
+
/* Now we are ready to insert the new value in the
sequence. Find out whether the element is
already known. */
@@ -1089,7 +1093,7 @@ order for `%.*s' already defined at %s:%zu"),
/* Enqueue the new element. */
elem->last = collate->cursor;
- if (collate->cursor != NULL)
+ if (collate->cursor == NULL)
elem->next = NULL;
else
{
@@ -1123,7 +1127,7 @@ order for `%.*s' already defined at %s:%zu"),
}
else
{
- /* Simly use the weight from `ellipsis_weight'. */
+ /* Simply use the weight from `ellipsis_weight'. */
elem->weights[cnt].w =
collate->ellipsis_weight.weights[cnt].w;
elem->weights[cnt].cnt =
@@ -1496,6 +1500,7 @@ collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
if (runp->mbs != NULL)
{
struct element_t **eptr;
+ struct element_t *lastp = NULL;
/* Find the point where to insert in the list. */
eptr = &collate->mbheads[((unsigned char *) runp->mbs)[0]];
@@ -1526,11 +1531,15 @@ collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
}
/* To the next entry. */
+ lastp = *eptr;
eptr = &(*eptr)->mbnext;
}
/* Set the pointers. */
runp->mbnext = *eptr;
+ runp->mblast = lastp;
+ if (*eptr != NULL)
+ (*eptr)->mblast = runp;
*eptr = runp;
dont_insert:
}
@@ -2019,20 +2028,19 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
int32_t weightidx;
int added;
- /* Output the weight info. */
- weightidx = output_weight (&weightpool, collate, runp);
-
/* Find out wether this is a single entry or we have more than
one consecutive entry. */
if (runp->mbnext != NULL
&& runp->nmbs == runp->mbnext->nmbs
&& memcmp (runp->mbs, runp->mbnext->mbs, runp->nmbs - 1) == 0
- && (runp->mbs[runp->nmbs - 1] + 1
- == runp->mbnext->mbs[runp->nmbs - 1]))
+ && (runp->mbs[runp->nmbs - 1]
+ == runp->mbnext->mbs[runp->nmbs - 1] + 1))
{
int i;
+ struct element_t *series_startp = runp;
+ struct element_t *curp;
- /* Now add first the initial byte sequence. */
+ /* Compute how much space we will need. */
added = ((sizeof (int32_t) + 1 + 2 * (runp->nmbs - 1)
+ __alignof__ (int32_t) - 1)
& ~(__alignof__ (int32_t) - 1));
@@ -2042,50 +2050,58 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
a negative index into the indirect table. */
if (sizeof (int32_t) == sizeof (int))
obstack_int_grow_fast (&extrapool,
- obstack_object_size (&indirectpool)
- / sizeof (int32_t));
+ -(obstack_object_size (&indirectpool)
+ / sizeof (int32_t)));
else
{
- int32_t i = (obstack_object_size (&indirectpool)
- / sizeof (int32_t));
+ int32_t i = -(obstack_object_size (&indirectpool)
+ / sizeof (int32_t));
obstack_grow (&extrapool, &i, sizeof (int32_t));
}
- obstack_1grow_fast (&extrapool, runp->nmbs - 1);
- for (i = 1; i < runp->nmbs; ++i)
- obstack_1grow_fast (&extrapool, runp->mbs[i]);
+
+ /* Now search first the end of the series. */
+ do
+ runp = runp->mbnext;
+ while (runp->mbnext != NULL
+ && runp->nmbs == runp->mbnext->nmbs
+ && memcmp (runp->mbs, runp->mbnext->mbs,
+ runp->nmbs - 1) == 0
+ && (runp->mbs[runp->nmbs - 1]
+ == runp->mbnext->mbs[runp->nmbs - 1] + 1));
+
+ /* Now walk backward from here to the beginning. */
+ curp = runp;
+
+ obstack_1grow_fast (&extrapool, curp->nmbs - 1);
+ for (i = 1; i < curp->nmbs; ++i)
+ obstack_1grow_fast (&extrapool, curp->mbs[i]);
/* Now find the end of the consecutive sequence and
add all the indeces in the indirect pool. */
- while (1)
+ do
{
+ weightidx = output_weight (&weightpool, collate, curp);
if (sizeof (int32_t) == sizeof (int))
- obstack_int_grow (&extrapool, weightidx);
+ obstack_int_grow (&indirectpool, weightidx);
else
- obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
-
- runp = runp->next;
- if (runp->mbnext == NULL
- || runp->nmbs != runp->mbnext->nmbs
- || memcmp (runp->mbs, runp->mbnext->mbs,
- runp->nmbs - 1) != 0
- || (runp->mbs[runp->nmbs - 1] + 1
- != runp->mbnext->mbs[runp->nmbs - 1]))
- break;
+ obstack_grow (&indirectpool, &weightidx,
+ sizeof (int32_t));
- /* Insert the weight. */
- weightidx = output_weight (&weightpool, collate, runp);
+ curp = curp->mblast;
}
+ while (curp != series_startp);
- /* And add the end byte sequence. Without length this
- time. */
- for (i = 1; i < runp->nmbs; ++i)
- obstack_1grow_fast (&extrapool, runp->mbs[i]);
-
- weightidx = output_weight (&weightpool, collate, runp);
+ /* Add the final weight. */
+ weightidx = output_weight (&weightpool, collate, curp);
if (sizeof (int32_t) == sizeof (int))
- obstack_int_grow (&extrapool, weightidx);
+ obstack_int_grow (&indirectpool, weightidx);
else
- obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
+ obstack_grow (&indirectpool, &weightidx, sizeof (int32_t));
+
+ /* And add the end byte sequence. Without length this
+ time. */
+ for (i = 1; i < curp->nmbs; ++i)
+ obstack_1grow_fast (&extrapool, curp->mbs[i]);
}
else
{
@@ -2094,6 +2110,9 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
tested for). */
int i;
+ /* Output the weight info. */
+ weightidx = output_weight (&weightpool, collate, runp);
+
added = ((sizeof (int32_t) + 1 + runp->nmbs - 1
+ __alignof__ (int32_t) - 1)
& ~(__alignof__ (int32_t) - 1));