+ first_list = list;
+ first_length = (length + 1) / 2;
+ second_length = length / 2;
+ for (cursor = list, counter = first_length - 1;
+ counter;
+ cursor = SUCCESSOR (cursor), counter--)
+ continue;
+ second_list = SUCCESSOR (cursor);
+ SUCCESSOR (cursor) = 0;
+
+ first_list = merge_sort_sll (first_list, first_length, compare);
+ second_list = merge_sort_sll (second_list, second_length, compare);
+
+ merge_point = &result;
+ while (first_list && second_list)
+ if ((*compare) (first_list, second_list) < 0)
+ {
+ cursor = SUCCESSOR (first_list);
+ *merge_point = first_list;
+ merge_point = &SUCCESSOR (first_list);
+ first_list = cursor;
+ }
+ else
+ {
+ cursor = SUCCESSOR (second_list);
+ *merge_point = second_list;
+ merge_point = &SUCCESSOR (second_list);
+ second_list = cursor;
+ }
+ if (first_list)
+ *merge_point = first_list;
+ else
+ *merge_point = second_list;
+
+ return result;
+
+#undef SUCCESSOR
+}
+
+/* Sort doubly linked LIST of names, of given LENGTH, using COMPARE
+ to order names. Return the sorted list. */
+static struct name *
+merge_sort (struct name *list, int length,
+ int (*compare) (struct name const*, struct name const*))
+{
+ struct name *head, *p, *prev;
+ head = merge_sort_sll (list, length, compare);
+ /* Fixup prev pointers */
+ for (prev = NULL, p = head; p; prev = p, p = p->next)
+ p->prev = prev;
+ return head;
+}
+
+/* A comparison function for sorting names. Put found names last;
+ break ties by string comparison. */