comparison lib/argp-help.c @ 8764:b675774a0b22

(hol_entry_cmp): Option sorting algorithm assumes the sorting is stable, while most qsort implementations are not. Use argument addresses to ensure they never compare as equal.
author Sergey Poznyakoff <gray@gnu.org.ua>
date Mon, 30 Apr 2007 08:25:46 +0000
parents 8a62dff89d5a
children 0d10c63d2bd3
comparison
equal deleted inserted replaced
8763:39bb5430fc0e 8764:b675774a0b22
731 (*name)++; 731 (*name)++;
732 } 732 }
733 return non_opt; 733 return non_opt;
734 } 734 }
735 735
736 #define HOL_ENTRY_PTRCMP(a,b) ((a) < (b) ? -1 : 1)
737
736 /* Order ENTRY1 & ENTRY2 by the order which they should appear in a help 738 /* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
737 listing. */ 739 listing. */
738 static int 740 static int
739 hol_entry_cmp (const struct hol_entry *entry1, 741 hol_entry_cmp (const struct hol_entry *entry1,
740 const struct hol_entry *entry2) 742 const struct hol_entry *entry2)
741 { 743 {
742 /* The group numbers by which the entries should be ordered; if either is 744 /* The group numbers by which the entries should be ordered; if either is
743 in a cluster, then this is just the group within the cluster. */ 745 in a cluster, then this is just the group within the cluster. */
744 int group1 = entry1->group, group2 = entry2->group; 746 int group1 = entry1->group, group2 = entry2->group;
747 int rc;
745 748
746 if (entry1->cluster != entry2->cluster) 749 if (entry1->cluster != entry2->cluster)
747 { 750 {
748 /* The entries are not within the same cluster, so we can't compare them 751 /* The entries are not within the same cluster, so we can't compare them
749 directly, we have to use the appropiate clustering level too. */ 752 directly, we have to use the appropiate clustering level too. */
756 else if (! entry2->cluster) 759 else if (! entry2->cluster)
757 /* Likewise, but ENTRY2's not in a cluster. */ 760 /* Likewise, but ENTRY2's not in a cluster. */
758 return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); 761 return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
759 else 762 else
760 /* Both entries are in clusters, we can just compare the clusters. */ 763 /* Both entries are in clusters, we can just compare the clusters. */
761 return hol_cluster_cmp (entry1->cluster, entry2->cluster); 764 return (rc = hol_cluster_cmp (entry1->cluster, entry2->cluster)) ?
765 rc : HOL_ENTRY_PTRCMP(entry1, entry2);
762 } 766 }
763 else if (group1 == group2) 767 else if (group1 == group2)
764 /* The entries are both in the same cluster and group, so compare them 768 /* The entries are both in the same cluster and group, so compare them
765 alphabetically. */ 769 alphabetically. */
766 { 770 {
780 /* `documentation' options always follow normal options (or 784 /* `documentation' options always follow normal options (or
781 documentation options that *look* like normal options). */ 785 documentation options that *look* like normal options). */
782 return doc1 - doc2; 786 return doc1 - doc2;
783 else if (!short1 && !short2 && long1 && long2) 787 else if (!short1 && !short2 && long1 && long2)
784 /* Only long options. */ 788 /* Only long options. */
785 return __strcasecmp (long1, long2); 789 return (rc = __strcasecmp (long1, long2)) ?
790 rc : HOL_ENTRY_PTRCMP(entry1, entry2);
786 else 791 else
787 /* Compare short/short, long/short, short/long, using the first 792 /* Compare short/short, long/short, short/long, using the first
788 character of long options. Entries without *any* valid 793 character of long options. Entries without *any* valid
789 options (such as options with OPTION_HIDDEN set) will be put 794 options (such as options with OPTION_HIDDEN set) will be put
790 first, but as they're not displayed, it doesn't matter where 795 first, but as they're not displayed, it doesn't matter where
797 #else 802 #else
798 int lower_cmp = tolower (first1) - tolower (first2); 803 int lower_cmp = tolower (first1) - tolower (first2);
799 #endif 804 #endif
800 /* Compare ignoring case, except when the options are both the 805 /* Compare ignoring case, except when the options are both the
801 same letter, in which case lower-case always comes first. */ 806 same letter, in which case lower-case always comes first. */
802 return lower_cmp ? lower_cmp : first2 - first1; 807 return lower_cmp ? lower_cmp :
808 (rc = first2 - first1) ?
809 rc : HOL_ENTRY_PTRCMP(entry1, entry2);
803 } 810 }
804 } 811 }
805 else 812 else
806 /* Within the same cluster, but not the same group, so just compare 813 /* Within the same cluster, but not the same group, so just compare
807 groups. */ 814 groups. */
808 return group_cmp (group1, group2, 0); 815 return group_cmp (group1, group2, HOL_ENTRY_PTRCMP(entry1, entry2));
809 } 816 }
810 817
811 /* Version of hol_entry_cmp with correct signature for qsort. */ 818 /* Version of hol_entry_cmp with correct signature for qsort. */
812 static int 819 static int
813 hol_entry_qcmp (const void *entry1_v, const void *entry2_v) 820 hol_entry_qcmp (const void *entry1_v, const void *entry2_v)