Mercurial > hg > octave-kai > gnulib-hg
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) |