about summary refs log tree commit diff
path: root/locale
diff options
context:
space:
mode:
Diffstat (limited to 'locale')
-rw-r--r--locale/programs/locarchive.c54
1 files changed, 30 insertions, 24 deletions
diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c
index 057fab8d2e..ea2cf82792 100644
--- a/locale/programs/locarchive.c
+++ b/locale/programs/locarchive.c
@@ -168,6 +168,8 @@ create_archive (const char *archivefname, struct locarhandle *ah)
 }
 
 
+/* This structure and qsort comparator function are used below to sort an
+   old archive's locrec table in order of data position in the file.  */
 struct oldlocrecent
 {
   unsigned int cnt;
@@ -179,31 +181,35 @@ oldlocrecentcmp (const void *a, const void *b)
 {
   struct locrecent *la = ((const struct oldlocrecent *) a)->locrec;
   struct locrecent *lb = ((const struct oldlocrecent *) b)->locrec;
+  uint32_t start_a = -1, end_a = 0;
+  uint32_t start_b = -1, end_b = 0;
+  int cnt;
 
-  if (la->record[LC_ALL].offset < lb->record[LC_ALL].offset)
-    return -1;
-  if (la->record[LC_ALL].offset > lb->record[LC_ALL].offset)
-    return 1;
-
-  if (la->record[LC_CTYPE].offset < lb->record[LC_CTYPE].offset)
-    return -1;
-  if (la->record[LC_CTYPE].offset > lb->record[LC_CTYPE].offset)
-    return 1;
-
-  if (la->record[LC_COLLATE].offset < lb->record[LC_COLLATE].offset)
-    return -1;
-  if (la->record[LC_COLLATE].offset > lb->record[LC_COLLATE].offset)
-    return 1;
-
-  if (((const struct oldlocrecent *) a)->cnt
-      < ((const struct oldlocrecent *) b)->cnt)
-    return -1;
+  for (cnt = 0; cnt < __LC_LAST; ++cnt)
+    if (cnt != LC_ALL)
+      {
+	if (la->record[cnt].offset < start_a)
+	  start_a = la->record[cnt].offset;
+	if (la->record[cnt].offset + la->record[cnt].len > end_a)
+	  end_a = la->record[cnt].offset + la->record[cnt].len;
+      }
+  assert (start_a != (uint32_t)-1);
+  assert (end_a != 0);
 
-  if (((const struct oldlocrecent *) a)->cnt
-      > ((const struct oldlocrecent *) b)->cnt)
-    return 1;
+  for (cnt = 0; cnt < __LC_LAST; ++cnt)
+    if (cnt != LC_ALL)
+      {
+	if (lb->record[cnt].offset < start_b)
+	  start_b = lb->record[cnt].offset;
+	if (lb->record[cnt].offset + lb->record[cnt].len > end_b)
+	  end_b = lb->record[cnt].offset + lb->record[cnt].len;
+      }
+  assert (start_b != (uint32_t)-1);
+  assert (end_b != 0);
 
-  return 0;
+  if (start_a != start_b)
+    return (int)start_a - (int)start_b;
+  return (int)end_a - (int)end_b;
 }
 
 
@@ -323,10 +329,11 @@ enlarge_archive (struct locarhandle *ah, const struct locarhead *head)
 					   + head->namehash_offset);
   oldlocrectab = (struct locrecent *) ((char *) ah->addr
 				       + head->locrectab_offset);
+
+  /* Sort the old locrec table in order of data position.  */
   oldlocrecarray = (struct oldlocrecent *)
 		   alloca (head->namehash_size
 			   * sizeof (struct oldlocrecent));
-
   for (cnt = 0, loccnt = 0; cnt < head->namehash_size; ++cnt)
     if (oldnamehashtab[cnt].locrec_offset != 0)
       {
@@ -335,7 +342,6 @@ enlarge_archive (struct locarhandle *ah, const struct locarhead *head)
 	  = (struct locrecent *) ((char *) ah->addr
 				  + oldnamehashtab[cnt].locrec_offset);
       }
-
   qsort (oldlocrecarray, loccnt, sizeof (struct oldlocrecent),
 	 oldlocrecentcmp);