bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* Initial Travis testing results look great. One failed self test on OS X 10.10
@ 2020-03-28 23:14 Jeffrey Walton
  2020-03-29  0:32 ` Jeffrey Walton
  0 siblings, 1 reply; 5+ messages in thread
From: Jeffrey Walton @ 2020-03-28 23:14 UTC (permalink / raw)
  To: bug-gnulib

The initial Travis testing results look great.

The .travis.yml file needs some tuning, so ignore the UBsan and Asan
failures at the moment.

OS X 10.10 is reporting a failure in the argp test
(https://travis-ci.org/github/noloader/gnulib/jobs/668196414). It is
not present in OS X 10.14 testing. Search for 'error:' in the wall of
text:

PASS: test-accept
PASS: test-alloca-opt
PASS: test-argp
FAIL: test-argp-2.sh
...

I've got an OS X 10.9 machine I may be able to duplicate it on.

Jeff


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Initial Travis testing results look great. One failed self test on OS X 10.10
  2020-03-28 23:14 Initial Travis testing results look great. One failed self test on OS X 10.10 Jeffrey Walton
@ 2020-03-29  0:32 ` Jeffrey Walton
  2020-03-29 12:19   ` argp failure on macOS Bruno Haible
  2020-12-08 20:48   ` Initial Travis testing results look great. One failed self test on OS X 10.10 Bruno Haible
  0 siblings, 2 replies; 5+ messages in thread
From: Jeffrey Walton @ 2020-03-29  0:32 UTC (permalink / raw)
  To: bug-gnulib

On Sat, Mar 28, 2020 at 7:14 PM Jeffrey Walton <noloader@gmail.com> wrote:
>
> The initial Travis testing results look great.
>
> The .travis.yml file needs some tuning, so ignore the UBsan and Asan
> failures at the moment.
>
> OS X 10.10 is reporting a failure in the argp test
> (https://travis-ci.org/github/noloader/gnulib/jobs/668196414). It is
> not present in OS X 10.14 testing. Search for 'error:' in the wall of
> text:
>
> PASS: test-accept
> PASS: test-alloca-opt
> PASS: test-argp
> FAIL: test-argp-2.sh
> ...

FAIL: test-argp-2.sh
====================

*** argp.61477  2020-03-28 20:12:34.000000000 -0400
--- -   2020-03-28 20:12:34.583510000 -0400
***************
*** 1,4 ****
! Usage: test-argp [-tvCSOlp?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
!             [--file=FILE] [--input=FILE] [--read=FILE] [--verbose] [--cantiga]
!             [--sonet] [--option] [--optional[=ARG]] [--many] [--one] [--two]
!             [--limerick] [--poem] [--help] [--usage] [--version] ARGS...
--- 1,4 ----
! Usage: test-argp [-tCSvOpl?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
!             [--cantiga] [--sonet] [--file=FILE] [--input=FILE] [--read=FILE]
!             [--verbose] [--option] [--optional[=ARG]] [--poem] [--limerick]
!             [--many] [--one] [--two] [--help] [--usage] [--version] ARGS...
*** argp.61477  2020-03-28 20:12:34.000000000 -0400
--- -   2020-03-28 20:12:34.626794000 -0400
***************
*** 1,4 ****
! Usage: test-argp [-tvCSOlp?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
! [--file=FILE] [--input=FILE] [--read=FILE] [--verbose] [--cantiga] [--sonet]
! [--option] [--optional[=ARG]] [--many] [--one] [--two] [--limerick] [--poem]
  [--help] [--usage] [--version] ARGS...
--- 1,4 ----
! Usage: test-argp [-tCSvOpl?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
! [--cantiga] [--sonet] [--file=FILE] [--input=FILE] [--read=FILE] [--verbose]
! [--option] [--optional[=ARG]] [--poem] [--limerick] [--many] [--one] [--two]
  [--help] [--usage] [--version] ARGS...
*** argp.61477  2020-03-28 20:12:34.000000000 -0400
--- -   2020-03-28 20:12:34.657116000 -0400
***************
*** 5,17 ****
    -t, --test

   Option Group 1
-   -f, -r, --file=FILE, --input=FILE, --read=FILE
-                              Option with a mandatory argument
-   -v, --verbose              Simple option without arguments

   Option Group 1.1
    -C, --cantiga              create a cantiga
    -S, --sonet                create a sonet

   Option Group 2
    -O, --option               An option
--- 5,17 ----
    -t, --test

   Option Group 1

   Option Group 1.1
    -C, --cantiga              create a cantiga
    -S, --sonet                create a sonet
+   -f, -r, --file=FILE, --input=FILE, --read=FILE
+                              Option with a mandatory argument
+   -v, --verbose              Simple option without arguments

   Option Group 2
    -O, --option               An option
***************
*** 19,32 ****
    -o, --optional[=ARG]       Option with an optional argument. ARG is one of
                               the following:

    many                       many units
    one                        one unit
    two                        two units

-  Option Group 2.1
-   -l, --limerick             create a limerick
-   -p, --poem                 create a poem
-
    -?, --help                 give this help list
        --usage                give a short usage message
    -V, --version              print program version
--- 19,32 ----
    -o, --optional[=ARG]       Option with an optional argument. ARG is one of
                               the following:

+  Option Group 2.1
+   -p, --poem                 create a poem
+   -l, --limerick             create a limerick
+
    many                       many units
    one                        one unit
    two                        two units

    -?, --help                 give this help list
        --usage                give a short usage message
    -V, --version              print program version
FAIL test-argp-2.sh (exit status: 1)


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: argp failure on macOS
  2020-03-29  0:32 ` Jeffrey Walton
@ 2020-03-29 12:19   ` Bruno Haible
  2020-03-29 21:05     ` Sergey Poznyakoff
  2020-12-08 20:48   ` Initial Travis testing results look great. One failed self test on OS X 10.10 Bruno Haible
  1 sibling, 1 reply; 5+ messages in thread
From: Bruno Haible @ 2020-03-29 12:19 UTC (permalink / raw)
  To: Sergey Poznyakoff; +Cc: noloader, bug-gnulib

Hi Sergey,

Do you have time to look into this?

> > OS X 10.10 is reporting a failure in the argp test
> > (https://travis-ci.org/github/noloader/gnulib/jobs/668196414). It is
> > not present in OS X 10.14 testing. Search for 'error:' in the wall of
> > text:
> >
> > PASS: test-accept
> > PASS: test-alloca-opt
> > PASS: test-argp
> > FAIL: test-argp-2.sh
> > ...
> 
> FAIL: test-argp-2.sh
> ====================
> 
> *** argp.61477  2020-03-28 20:12:34.000000000 -0400
> --- -   2020-03-28 20:12:34.583510000 -0400
> ***************
> *** 1,4 ****
> ! Usage: test-argp [-tvCSOlp?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
> !             [--file=FILE] [--input=FILE] [--read=FILE] [--verbose] [--cantiga]
> !             [--sonet] [--option] [--optional[=ARG]] [--many] [--one] [--two]
> !             [--limerick] [--poem] [--help] [--usage] [--version] ARGS...
> --- 1,4 ----
> ! Usage: test-argp [-tCSvOpl?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
> !             [--cantiga] [--sonet] [--file=FILE] [--input=FILE] [--read=FILE]
> !             [--verbose] [--option] [--optional[=ARG]] [--poem] [--limerick]
> !             [--many] [--one] [--two] [--help] [--usage] [--version] ARGS...
> *** argp.61477  2020-03-28 20:12:34.000000000 -0400
> --- -   2020-03-28 20:12:34.626794000 -0400
> ***************
> *** 1,4 ****
> ! Usage: test-argp [-tvCSOlp?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
> ! [--file=FILE] [--input=FILE] [--read=FILE] [--verbose] [--cantiga] [--sonet]
> ! [--option] [--optional[=ARG]] [--many] [--one] [--two] [--limerick] [--poem]
>   [--help] [--usage] [--version] ARGS...
> --- 1,4 ----
> ! Usage: test-argp [-tCSvOpl?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
> ! [--cantiga] [--sonet] [--file=FILE] [--input=FILE] [--read=FILE] [--verbose]
> ! [--option] [--optional[=ARG]] [--poem] [--limerick] [--many] [--one] [--two]
>   [--help] [--usage] [--version] ARGS...
> *** argp.61477  2020-03-28 20:12:34.000000000 -0400
> --- -   2020-03-28 20:12:34.657116000 -0400
> ***************
> *** 5,17 ****
>     -t, --test
> 
>    Option Group 1
> -   -f, -r, --file=FILE, --input=FILE, --read=FILE
> -                              Option with a mandatory argument
> -   -v, --verbose              Simple option without arguments
> 
>    Option Group 1.1
>     -C, --cantiga              create a cantiga
>     -S, --sonet                create a sonet
> 
>    Option Group 2
>     -O, --option               An option
> --- 5,17 ----
>     -t, --test
> 
>    Option Group 1
> 
>    Option Group 1.1
>     -C, --cantiga              create a cantiga
>     -S, --sonet                create a sonet
> +   -f, -r, --file=FILE, --input=FILE, --read=FILE
> +                              Option with a mandatory argument
> +   -v, --verbose              Simple option without arguments
> 
>    Option Group 2
>     -O, --option               An option
> ***************
> *** 19,32 ****
>     -o, --optional[=ARG]       Option with an optional argument. ARG is one of
>                                the following:
> 
>     many                       many units
>     one                        one unit
>     two                        two units
> 
> -  Option Group 2.1
> -   -l, --limerick             create a limerick
> -   -p, --poem                 create a poem
> -
>     -?, --help                 give this help list
>         --usage                give a short usage message
>     -V, --version              print program version
> --- 19,32 ----
>     -o, --optional[=ARG]       Option with an optional argument. ARG is one of
>                                the following:
> 
> +  Option Group 2.1
> +   -p, --poem                 create a poem
> +   -l, --limerick             create a limerick
> +
>     many                       many units
>     one                        one unit
>     two                        two units
> 
>     -?, --help                 give this help list
>         --usage                give a short usage message
>     -V, --version              print program version
> FAIL test-argp-2.sh (exit status: 1)
> 
> 




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: argp failure on macOS
  2020-03-29 12:19   ` argp failure on macOS Bruno Haible
@ 2020-03-29 21:05     ` Sergey Poznyakoff
  0 siblings, 0 replies; 5+ messages in thread
From: Sergey Poznyakoff @ 2020-03-29 21:05 UTC (permalink / raw)
  To: Bruno Haible; +Cc: noloader, bug-gnulib

Hi Bruno,

> Do you have time to look into this?

Sure. I'll take a look.

Regards,
Sergey



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Initial Travis testing results look great. One failed self test on OS X 10.10
  2020-03-29  0:32 ` Jeffrey Walton
  2020-03-29 12:19   ` argp failure on macOS Bruno Haible
@ 2020-12-08 20:48   ` Bruno Haible
  1 sibling, 0 replies; 5+ messages in thread
From: Bruno Haible @ 2020-12-08 20:48 UTC (permalink / raw)
  To: bug-gnulib, noloader

[-- Attachment #1: Type: text/plain, Size: 17665 bytes --]

Jeffrey Walton wrote in
<https://lists.gnu.org/archive/html/bug-gnulib/2020-03/msg00085.html>:
> FAIL: test-argp-2.sh
> ====================
> 
> *** argp.61477  2020-03-28 20:12:34.000000000 -0400
> --- -   2020-03-28 20:12:34.583510000 -0400
> ***************
> *** 1,4 ****
> ! Usage: test-argp [-tvCSOlp?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
> !             [--file=FILE] [--input=FILE] [--read=FILE] [--verbose] [--cantiga]
> !             [--sonet] [--option] [--optional[=ARG]] [--many] [--one] [--two]
> !             [--limerick] [--poem] [--help] [--usage] [--version] ARGS...
> --- 1,4 ----
> ! Usage: test-argp [-tCSvOpl?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
> !             [--cantiga] [--sonet] [--file=FILE] [--input=FILE] [--read=FILE]
> !             [--verbose] [--option] [--optional[=ARG]] [--poem] [--limerick]
> !             [--many] [--one] [--two] [--help] [--usage] [--version] ARGS...
> *** argp.61477  2020-03-28 20:12:34.000000000 -0400
> --- -   2020-03-28 20:12:34.626794000 -0400
> ***************
> *** 1,4 ****
> ! Usage: test-argp [-tvCSOlp?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
> ! [--file=FILE] [--input=FILE] [--read=FILE] [--verbose] [--cantiga] [--sonet]
> ! [--option] [--optional[=ARG]] [--many] [--one] [--two] [--limerick] [--poem]
>   [--help] [--usage] [--version] ARGS...
> --- 1,4 ----
> ! Usage: test-argp [-tCSvOpl?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
> ! [--cantiga] [--sonet] [--file=FILE] [--input=FILE] [--read=FILE] [--verbose]
> ! [--option] [--optional[=ARG]] [--poem] [--limerick] [--many] [--one] [--two]
>   [--help] [--usage] [--version] ARGS...
> *** argp.61477  2020-03-28 20:12:34.000000000 -0400
> --- -   2020-03-28 20:12:34.657116000 -0400
> ***************
> *** 5,17 ****
>     -t, --test
> 
>    Option Group 1
> -   -f, -r, --file=FILE, --input=FILE, --read=FILE
> -                              Option with a mandatory argument
> -   -v, --verbose              Simple option without arguments
> 
>    Option Group 1.1
>     -C, --cantiga              create a cantiga
>     -S, --sonet                create a sonet
> 
>    Option Group 2
>     -O, --option               An option
> --- 5,17 ----
>     -t, --test
> 
>    Option Group 1
> 
>    Option Group 1.1
>     -C, --cantiga              create a cantiga
>     -S, --sonet                create a sonet
> +   -f, -r, --file=FILE, --input=FILE, --read=FILE
> +                              Option with a mandatory argument
> +   -v, --verbose              Simple option without arguments
> 
>    Option Group 2
>     -O, --option               An option
> ***************
> *** 19,32 ****
>     -o, --optional[=ARG]       Option with an optional argument. ARG is one of
>                                the following:
> 
>     many                       many units
>     one                        one unit
>     two                        two units
> 
> -  Option Group 2.1
> -   -l, --limerick             create a limerick
> -   -p, --poem                 create a poem
> -
>     -?, --help                 give this help list
>         --usage                give a short usage message
>     -V, --version              print program version
> --- 19,32 ----
>     -o, --optional[=ARG]       Option with an optional argument. ARG is one of
>                                the following:
> 
> +  Option Group 2.1
> +   -p, --poem                 create a poem
> +   -l, --limerick             create a limerick
> +
>     many                       many units
>     one                        one unit
>     two                        two units
> 
>     -?, --help                 give this help list
>         --usage                give a short usage message
>     -V, --version              print program version
> FAIL test-argp-2.sh (exit status: 1)

As I observe this failure also on FreeBSD, and it makes the '--help' output
produce really nonsensical output, I decided to dig deeper.

In 2009, we had a case where the suspicion that qsort() is used in an invalid
manner, but that was not the cause of the bug, back then:
<https://lists.gnu.org/archive/html/bug-gnulib/2009-09/msg00287.html>.

But now it is. Recall the requirements that a comparison function passed to
qsort() must fulfil:
<https://pubs.opengroup.org/onlinepubs/9699919799/functions/qsort.html>

  "When the same objects (consisting of width bytes, irrespective of their
   current positions in the array) are passed more than once to the comparison
   function, the results shall be consistent with one another. That is, they
   shall define a total ordering on the array."

I added debugging code to print the contents of the argument array passed to
qsort(), as well as a matrix of all the cmp(entry[i], entry[j]) results, and
a verification of the "total ordering" property, and found:

  * The argument arrary is the same on glibc and on macOS,
  * The matrix of cmp(entry[i], entry[j]) results is the same on glibc and
    on macOS,
  * The verification of the "total ordering" property prints many failures.

This means that qsort() has undefined behaviour, the way it is invoked.

And it is not surprising that different qsort implementations (in glibc
vs. macOS/FreeBSD) produce different results.

This patch fixes the test failure by rewriting the comparison function in
a way that it is a total ordering. Recall that the easiest way to guarantee
a total ordering is to use lexicographic ordering
<https://en.wikipedia.org/wiki/Lexicographic_order>. All functions defined as

int foo_cmp (const foo *foo1, const foo *foo2)
{
  int cmp = prop1_compare (prop1 (foo1), prop1 (foo2));
  if (cmp != 0)
    return cmp;

  cmp = prop2_compare (prop2 (foo1), prop2 (foo2));
  if (cmp != 0)
    return cmp;

  ...

  cmp = propN_compare (propN (foo1), propN (foo2));
  if (cmp != 0)
    return cmp;

  return 0;
}

(with prop1_compare, ..., propN_compare being total order functions) are
total orderings.

I will soon submit a glibc bug to get this fixed in glibc as well.


2020-12-08  Bruno Haible  <bruno@clisp.org>

	argp: Avoid undefined behaviour when invoking qsort().
	This fixes a test-argp-2.sh test failure on macOS and FreeBSD.
	Reported by Jeffrey Walton <noloader@gmail.com> in
	<https://lists.gnu.org/archive/html/bug-gnulib/2020-03/msg00085.html>.
	* lib/argp-help.c (group_cmp): Remove third argument.
	(hol_sibling_cluster_cmp, hol_cousin_cluster_cmp): New functions, based
	upon hol_cluster_cmp.
	(hol_cluster_cmp): Use hol_cousin_cluster_cmp.
	(hol_entry_cmp): Rewritten to implement a total order.

diff --git a/lib/argp-help.c b/lib/argp-help.c
index 29d0f03..1cb0b84 100644
--- a/lib/argp-help.c
+++ b/lib/argp-help.c
@@ -672,37 +672,93 @@ hol_set_group (struct hol *hol, const char *name, int group)
     entry->group = group;
 }
 \f
-/* Order by group:  0, 1, 2, ..., n, -m, ..., -2, -1.
-   EQ is what to return if GROUP1 and GROUP2 are the same.  */
+/* -------------------------------------------------------------------------- */
+/* Sorting the entries in a HOL.                                              */
+
+/* Order by group:  0, 1, 2, ..., n, -m, ..., -2, -1.  */
 static int
-group_cmp (int group1, int group2, int eq)
+group_cmp (int group1, int group2)
 {
-  if (group1 == group2)
-    return eq;
-  else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
+  if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
     return group1 - group2;
   else
+    /* Return > 0 if group1 < 0 <= group2.
+       Return < 0 if group2 < 0 <= group1.  */
     return group2 - group1;
 }
 
-/* Compare clusters CL1 & CL2 by the order that they should appear in
+/* Compare clusters CL1 and CL2 by the order that they should appear in
+   output.  Assume CL1 and CL2 have the same parent.  */
+static int
+hol_sibling_cluster_cmp (const struct hol_cluster *cl1,
+                         const struct hol_cluster *cl2)
+{
+  /* Compare by group first.  */
+  int cmp = group_cmp (cl1->group, cl2->group);
+  if (cmp != 0)
+    return cmp;
+
+  /* Within a group, compare by index within the group.  */
+  return cl2->index - cl1->index;
+}
+
+/* Compare clusters CL1 and CL2 by the order that they should appear in
+   output.  Assume CL1 and CL2 are at the same depth.  */
+static int
+hol_cousin_cluster_cmp (const struct hol_cluster *cl1,
+                        const struct hol_cluster *cl2)
+{
+  if (cl1->parent == cl2->parent)
+    return hol_sibling_cluster_cmp (cl1, cl2);
+  else
+    {
+      /* Compare the parent clusters first.  */
+      int cmp = hol_cousin_cluster_cmp (cl1->parent, cl2->parent);
+      if (cmp != 0)
+        return cmp;
+
+      /* Next, compare by group.  */
+      cmp = group_cmp (cl1->group, cl2->group);
+      if (cmp != 0)
+        return cmp;
+
+      /* Next, within a group, compare by index within the group.  */
+      return cl2->index - cl1->index;
+    }
+}
+
+/* Compare clusters CL1 and CL2 by the order that they should appear in
    output.  */
 static int
 hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
 {
   /* If one cluster is deeper than the other, use its ancestor at the same
-     level, so that finding the common ancestor is straightforward.  */
-  while (cl1->depth > cl2->depth)
-    cl1 = cl1->parent;
-  while (cl2->depth > cl1->depth)
-    cl2 = cl2->parent;
+     level.  Then, go by the rule that entries that are not in a sub-cluster
+     come before entries in a sub-cluster.  */
+  if (cl1->depth > cl2->depth)
+    {
+      do
+        cl1 = cl1->parent;
+      while (cl1->depth > cl2->depth);
+      int cmp = hol_cousin_cluster_cmp (cl1, cl2);
+      if (cmp != 0)
+        return cmp;
 
-  /* Now reduce both clusters to their ancestors at the point where both have
-     a common parent; these can be directly compared.  */
-  while (cl1->parent != cl2->parent)
-    cl1 = cl1->parent, cl2 = cl2->parent;
+      return 1;
+    }
+  else if (cl1->depth < cl2->depth)
+    {
+      do
+        cl2 = cl2->parent;
+      while (cl1->depth < cl2->depth);
+      int cmp = hol_cousin_cluster_cmp (cl1, cl2);
+      if (cmp != 0)
+        return cmp;
 
-  return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index);
+      return -1;
+    }
+  else
+    return hol_cousin_cluster_cmp (cl1, cl2);
 }
 
 /* Return the ancestor of CL that's just below the root (i.e., has a parent
@@ -733,77 +789,116 @@ canon_doc_option (const char **name)
   return non_opt;
 }
 
-/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
-   listing.  */
+/* Order ENTRY1 and ENTRY2 by the order which they should appear in a help
+   listing.
+   This function implements a total order, that is:
+     - if cmp (entry1, entry2) < 0 and cmp (entry2, entry3) < 0,
+       then cmp (entry1, entry3) < 0.
+     - if cmp (entry1, entry2) < 0 and cmp (entry2, entry3) == 0,
+       then cmp (entry1, entry3) < 0.
+     - if cmp (entry1, entry2) == 0 and cmp (entry2, entry3) < 0,
+       then cmp (entry1, entry3) < 0.
+     - if cmp (entry1, entry2) == 0 and cmp (entry2, entry3) == 0,
+       then cmp (entry1, entry3) == 0.  */
 static int
 hol_entry_cmp (const struct hol_entry *entry1,
                const struct hol_entry *entry2)
 {
-  /* The group numbers by which the entries should be ordered; if either is
-     in a cluster, then this is just the group within the cluster.  */
-  int group1 = entry1->group, group2 = entry2->group;
-
-  if (entry1->cluster != entry2->cluster)
+  /* First, compare the group numbers.  For entries within a cluster, what
+     matters is the group number of the base cluster in which the entry
+     resides.  */
+  int group1 = (entry1->cluster
+                ? hol_cluster_base (entry1->cluster)->group
+                : entry1->group);
+  int group2 = (entry2->cluster
+                ? hol_cluster_base (entry2->cluster)->group
+                : entry2->group);
+  int cmp = group_cmp (group1, group2);
+  if (cmp != 0)
+    return cmp;
+
+  /* The group numbers are the same.  */
+
+  /* Entries that are not in a cluster come before entries in a cluster.  */
+  cmp = (entry1->cluster != NULL) - (entry2->cluster != NULL);
+  if (cmp != 0)
+    return cmp;
+
+  /* Compare the clusters.  */
+  if (entry1->cluster != NULL)
     {
-      /* The entries are not within the same cluster, so we can't compare them
-         directly, we have to use the appropriate clustering level too.  */
-      if (! entry1->cluster)
-        /* ENTRY1 is at the 'base level', not in a cluster, so we have to
-           compare it's group number with that of the base cluster in which
-           ENTRY2 resides.  Note that if they're in the same group, the
-           clustered option always comes last.  */
-        return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1);
-      else if (! entry2->cluster)
-        /* Likewise, but ENTRY2's not in a cluster.  */
-        return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
-      else
-        /* Both entries are in clusters, we can just compare the clusters.  */
-        return hol_cluster_cmp (entry1->cluster, entry2->cluster);
+      cmp = hol_cluster_cmp (entry1->cluster, entry2->cluster);
+      if (cmp != 0)
+        return cmp;
     }
-  else if (group1 == group2)
-    /* The entries are both in the same cluster and group, so compare them
-       alphabetically.  */
+
+  /* For entries in the same cluster, compare also the group numbers
+     within the cluster.  */
+  cmp = group_cmp (entry1->group, entry2->group);
+  if (cmp != 0)
+    return cmp;
+
+  /* The entries are both in the same group and the same cluster.  */
+
+  /* 'documentation' options always follow normal options (or documentation
+     options that *look* like normal options).  */
+  const char *long1 = hol_entry_first_long (entry1);
+  const char *long2 = hol_entry_first_long (entry2);
+  int doc1 =
+    (odoc (entry1->opt) ? long1 != NULL && canon_doc_option (&long1) : 0);
+  int doc2 =
+    (odoc (entry2->opt) ? long2 != NULL && canon_doc_option (&long2) : 0);
+  cmp = doc1 - doc2;
+  if (cmp != 0)
+    return cmp;
+
+  /* Compare the entries alphabetically.  */
+
+  /* First, compare the first character of the options.
+     Put entries without *any* valid options (such as options with
+     OPTION_HIDDEN set) first.  But as they're not displayed, it doesn't
+     matter where they are.  */
+  int short1 = hol_entry_first_short (entry1);
+  int short2 = hol_entry_first_short (entry2);
+  unsigned char first1 = short1 ? short1 : long1 != NULL ? *long1 : 0;
+  unsigned char first2 = short2 ? short2 : long2 != NULL ? *long2 : 0;
+  /* Compare ignoring case.  */
+  /* Use tolower, not _tolower, since the latter has undefined behaviour
+     for characters that are not uppercase letters.  */
+  cmp = tolower (first1) - tolower (first2);
+  if (cmp != 0)
+    return cmp;
+  /* When the options start with the same letter (ignoring case), lower-case
+     comes first.  */
+  cmp = first2 - first1;
+  if (cmp != 0)
+    return cmp;
+
+  /* The first character of the options agree.  */
+
+  /* Put entries with a short option before entries without a short option.  */
+  cmp = (short1 != 0) - (short2 != 0);
+  if (cmp != 0)
+    return cmp;
+
+  /* Compare entries without a short option by comparing the long option.  */
+  if (short1 == 0)
     {
-      int short1 = hol_entry_first_short (entry1);
-      int short2 = hol_entry_first_short (entry2);
-      int doc1 = odoc (entry1->opt);
-      int doc2 = odoc (entry2->opt);
-      const char *long1 = hol_entry_first_long (entry1);
-      const char *long2 = hol_entry_first_long (entry2);
-
-      if (doc1)
-        doc1 = long1 != NULL && canon_doc_option (&long1);
-      if (doc2)
-        doc2 = long2 != NULL && canon_doc_option (&long2);
-
-      if (doc1 != doc2)
-        /* 'documentation' options always follow normal options (or
-           documentation options that *look* like normal options).  */
-        return doc1 - doc2;
-      else if (!short1 && !short2 && long1 && long2)
-        /* Only long options.  */
-        return __strcasecmp (long1, long2);
-      else
-        /* Compare short/short, long/short, short/long, using the first
-           character of long options.  Entries without *any* valid
-           options (such as options with OPTION_HIDDEN set) will be put
-           first, but as they're not displayed, it doesn't matter where
-           they are.  */
+      cmp = (long1 != NULL) - (long2 != NULL);
+      if (cmp != 0)
+        return cmp;
+
+      if (long1 != NULL)
         {
-          unsigned char first1 = short1 ? short1 : long1 ? *long1 : 0;
-          unsigned char first2 = short2 ? short2 : long2 ? *long2 : 0;
-          /* Use tolower, not _tolower, since the latter has undefined
-             behaviour for characters that are not uppercase letters.  */
-          int lower_cmp = tolower (first1) - tolower (first2);
-          /* Compare ignoring case, except when the options are both the
-             same letter, in which case lower-case always comes first.  */
-          return lower_cmp ? lower_cmp : first2 - first1;
+          cmp = __strcasecmp (long1, long2);
+          if (cmp != 0)
+            return cmp;
         }
     }
-  else
-    /* Within the same cluster, but not the same group, so just compare
-       groups.  */
-    return group_cmp (group1, group2, 0);
+
+  /* We're out of comparison criteria.  At this point, if ENTRY1 != ENTRY2,
+     the order of these entries will be unpredictable.  */
+  return 0;
 }
 
 /* Variant of hol_entry_cmp with correct signature for qsort.  */

[-- Attachment #2: argp-debug.diff --]
[-- Type: text/x-patch, Size: 2279 bytes --]

diff --git a/lib/argp-help.c b/lib/argp-help.c
index 52260f3..ca5f397 100644
--- a/lib/argp-help.c
+++ b/lib/argp-help.c
@@ -822,12 +822,50 @@ hol_sort (struct hol *hol)
 {
   if (hol->num_entries > 0)
     {
-      unsigned i;
+      unsigned i, j, k;
       struct hol_entry *e;
       for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++)
         e->ord = i;
+
+      fprintf (stderr, "hol_sort: entries = {\n");
+      for (i = 0; i < hol->num_entries; i++)
+        {
+          e = hol->entries + i;
+          fprintf (stderr, "  [%u] = [%s] [%s]\n", i, e->opt->name != NULL ? e->opt->name : "", e->opt->doc != NULL ? e->opt->doc : "");
+        }
+      fprintf (stderr, "}\n");
+      fprintf (stderr, "hol_sort: comparisons =\n");
+      for (i = 0; i < hol->num_entries; i++)
+        {
+          fprintf (stderr, "  ");
+          for (j = 0; j < hol->num_entries; j++)
+            {
+              int cmp = hol_entry_cmp (hol->entries + i, hol->entries + j);
+              fprintf (stderr, cmp > 0 ? " +" : cmp < 0 ? " -" : " .");
+            }
+          fprintf (stderr, "\n");
+        }
+      for (i = 0; i < hol->num_entries; i++)
+        for (j = 0; j < hol->num_entries; j++)
+          for (k = 0; k < hol->num_entries; k++) {
+            int cmp1 = hol_entry_cmp (hol->entries + i, hol->entries + j);
+            int cmp2 = hol_entry_cmp (hol->entries + j, hol->entries + k);
+            int cmp3 = hol_entry_cmp (hol->entries + i, hol->entries + k);
+            if (((cmp1 < 0 && cmp2 <= 0) || (cmp1 <= 0 && cmp2 < 0)) && !(cmp3 < 0))
+              fprintf (stderr, "hol_sort: transitivity violated for [%u] [%u] [%u]\n", i, j, k);
+          }
       qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
              hol_entry_qcmp);
+      fprintf (stderr, "hol_sort: sort result:\n");
+      for (i = 0; i < hol->num_entries; i++)
+        fprintf (stderr, "  [%u] <- [%u]\n", i, hol->entries[i].ord);
+      fprintf (stderr, "hol_sort: compare after sort:\n");
+      for (i = 1; i < hol->num_entries; i++)
+        {
+          int cmp = hol_entry_cmp (hol->entries + i-1, hol->entries + i);
+          fprintf (stderr, cmp > 0 ? " +" : cmp < 0 ? " -" : " .");
+        }
+      fprintf (stderr, "\n");
     }
 }
 \f

[-- Attachment #3: argp-glibc.out --]
[-- Type: text/plain, Size: 12527 bytes --]

hol_sort: entries = {
  [0] = [] [Main options]
  [1] = [test] []
  [2] = [] [Option Group 1]
  [3] = [verbose] [Simple option without arguments]
  [4] = [file] [Option with a mandatory argument]
  [5] = [hidden] [Hidden option]
  [6] = [] [Option Group 1.1]
  [7] = [cantiga] [create a cantiga]
  [8] = [sonet] [create a sonet]
  [9] = [] [Option Group 2]
  [10] = [option] [An option]
  [11] = [optional] [Option with an optional argument. ARG is one of the following:]
  [12] = [one] [one unit]
  [13] = [two] [two units]
  [14] = [many] [many units]
  [15] = [] [Option Group 2.1]
  [16] = [poem] [create a poem]
  [17] = [limerick] [create a limerick]
  [18] = [help] [give this help list]
  [19] = [usage] [give a short usage message]
  [20] = [program-name] [set the program name]
  [21] = [HANG] [hang for SECS seconds (default 3600)]
  [22] = [version] [print program version]
}
hol_sort: comparisons =
   . - - - - - - - - - - - - - - - - - - - - - -
   + . - - - - - - - - - - - - - - - - - - - - -
   + + . - - . . . . - - - - - - - - - - - - - -
   + + + . + + . . . - - - - - - - - - - - - - -
   + + + - . + . . . - - - - - - - - - - - - - -
   + + . - - . . . . - - - - - - - - - - - - - -
   + + . . . . . - - - - - - - - - - - - - - - -
   + + . . . . + . - - - - - - - - - - - - - - -
   + + . . . . + + . - - - - - - - - - - - - - -
   + + + + + + + + + . - - - - - . . . - - - - -
   + + + + + + + + + + . - - - - . . . - - - - -
   + + + + + + + + + + + . - - - . . . - - - - -
   + + + + + + + + + + + + . - + . . . - - - - -
   + + + + + + + + + + + + + . + . . . - - - - -
   + + + + + + + + + + + + - - . . . . - - - - -
   + + + + + + + + + . . . . . . . - - - - - - -
   + + + + + + + + + . . . . . . + . + - - - - -
   + + + + + + + + + . . . . . . + - . - - - - -
   + + + + + + + + + + + + + + + + + + . - + + -
   + + + + + + + + + + + + + + + + + + + . + + -
   + + + + + + + + + + + + + + + + + + - - . . -
   + + + + + + + + + + + + + + + + + + - - . . -
   + + + + + + + + + + + + + + + + + + + + + + .
hol_sort: transitivity violated for [2] [3] [6]
hol_sort: transitivity violated for [2] [3] [7]
hol_sort: transitivity violated for [2] [3] [8]
hol_sort: transitivity violated for [2] [4] [6]
hol_sort: transitivity violated for [2] [4] [7]
hol_sort: transitivity violated for [2] [4] [8]
hol_sort: transitivity violated for [2] [6] [7]
hol_sort: transitivity violated for [2] [6] [8]
hol_sort: transitivity violated for [2] [7] [8]
hol_sort: transitivity violated for [3] [6] [7]
hol_sort: transitivity violated for [3] [6] [8]
hol_sort: transitivity violated for [3] [7] [8]
hol_sort: transitivity violated for [4] [3] [6]
hol_sort: transitivity violated for [4] [3] [7]
hol_sort: transitivity violated for [4] [3] [8]
hol_sort: transitivity violated for [4] [6] [7]
hol_sort: transitivity violated for [4] [6] [8]
hol_sort: transitivity violated for [4] [7] [8]
hol_sort: transitivity violated for [5] [3] [6]
hol_sort: transitivity violated for [5] [3] [7]
hol_sort: transitivity violated for [5] [3] [8]
hol_sort: transitivity violated for [5] [4] [6]
hol_sort: transitivity violated for [5] [4] [7]
hol_sort: transitivity violated for [5] [4] [8]
hol_sort: transitivity violated for [5] [6] [7]
hol_sort: transitivity violated for [5] [6] [8]
hol_sort: transitivity violated for [5] [7] [8]
hol_sort: transitivity violated for [6] [2] [3]
hol_sort: transitivity violated for [6] [2] [4]
hol_sort: transitivity violated for [6] [4] [3]
hol_sort: transitivity violated for [6] [5] [3]
hol_sort: transitivity violated for [6] [5] [4]
hol_sort: transitivity violated for [6] [7] [2]
hol_sort: transitivity violated for [6] [7] [3]
hol_sort: transitivity violated for [6] [7] [4]
hol_sort: transitivity violated for [6] [7] [5]
hol_sort: transitivity violated for [6] [8] [2]
hol_sort: transitivity violated for [6] [8] [3]
hol_sort: transitivity violated for [6] [8] [4]
hol_sort: transitivity violated for [6] [8] [5]
hol_sort: transitivity violated for [7] [2] [3]
hol_sort: transitivity violated for [7] [2] [4]
hol_sort: transitivity violated for [7] [4] [3]
hol_sort: transitivity violated for [7] [5] [3]
hol_sort: transitivity violated for [7] [5] [4]
hol_sort: transitivity violated for [7] [8] [2]
hol_sort: transitivity violated for [7] [8] [3]
hol_sort: transitivity violated for [7] [8] [4]
hol_sort: transitivity violated for [7] [8] [5]
hol_sort: transitivity violated for [8] [2] [3]
hol_sort: transitivity violated for [8] [2] [4]
hol_sort: transitivity violated for [8] [4] [3]
hol_sort: transitivity violated for [8] [5] [3]
hol_sort: transitivity violated for [8] [5] [4]
hol_sort: transitivity violated for [9] [10] [15]
hol_sort: transitivity violated for [9] [10] [16]
hol_sort: transitivity violated for [9] [10] [17]
hol_sort: transitivity violated for [9] [11] [15]
hol_sort: transitivity violated for [9] [11] [16]
hol_sort: transitivity violated for [9] [11] [17]
hol_sort: transitivity violated for [9] [12] [15]
hol_sort: transitivity violated for [9] [12] [16]
hol_sort: transitivity violated for [9] [12] [17]
hol_sort: transitivity violated for [9] [13] [15]
hol_sort: transitivity violated for [9] [13] [16]
hol_sort: transitivity violated for [9] [13] [17]
hol_sort: transitivity violated for [9] [14] [15]
hol_sort: transitivity violated for [9] [14] [16]
hol_sort: transitivity violated for [9] [14] [17]
hol_sort: transitivity violated for [9] [15] [16]
hol_sort: transitivity violated for [9] [15] [17]
hol_sort: transitivity violated for [9] [17] [16]
hol_sort: transitivity violated for [10] [11] [15]
hol_sort: transitivity violated for [10] [11] [16]
hol_sort: transitivity violated for [10] [11] [17]
hol_sort: transitivity violated for [10] [12] [15]
hol_sort: transitivity violated for [10] [12] [16]
hol_sort: transitivity violated for [10] [12] [17]
hol_sort: transitivity violated for [10] [13] [15]
hol_sort: transitivity violated for [10] [13] [16]
hol_sort: transitivity violated for [10] [13] [17]
hol_sort: transitivity violated for [10] [14] [15]
hol_sort: transitivity violated for [10] [14] [16]
hol_sort: transitivity violated for [10] [14] [17]
hol_sort: transitivity violated for [10] [15] [16]
hol_sort: transitivity violated for [10] [15] [17]
hol_sort: transitivity violated for [10] [17] [16]
hol_sort: transitivity violated for [11] [12] [15]
hol_sort: transitivity violated for [11] [12] [16]
hol_sort: transitivity violated for [11] [12] [17]
hol_sort: transitivity violated for [11] [13] [15]
hol_sort: transitivity violated for [11] [13] [16]
hol_sort: transitivity violated for [11] [13] [17]
hol_sort: transitivity violated for [11] [14] [15]
hol_sort: transitivity violated for [11] [14] [16]
hol_sort: transitivity violated for [11] [14] [17]
hol_sort: transitivity violated for [11] [15] [16]
hol_sort: transitivity violated for [11] [15] [17]
hol_sort: transitivity violated for [11] [17] [16]
hol_sort: transitivity violated for [12] [13] [15]
hol_sort: transitivity violated for [12] [13] [16]
hol_sort: transitivity violated for [12] [13] [17]
hol_sort: transitivity violated for [12] [15] [16]
hol_sort: transitivity violated for [12] [15] [17]
hol_sort: transitivity violated for [12] [17] [16]
hol_sort: transitivity violated for [13] [15] [16]
hol_sort: transitivity violated for [13] [15] [17]
hol_sort: transitivity violated for [13] [17] [16]
hol_sort: transitivity violated for [14] [12] [15]
hol_sort: transitivity violated for [14] [12] [16]
hol_sort: transitivity violated for [14] [12] [17]
hol_sort: transitivity violated for [14] [13] [15]
hol_sort: transitivity violated for [14] [13] [16]
hol_sort: transitivity violated for [14] [13] [17]
hol_sort: transitivity violated for [14] [15] [16]
hol_sort: transitivity violated for [14] [15] [17]
hol_sort: transitivity violated for [14] [17] [16]
hol_sort: transitivity violated for [15] [9] [10]
hol_sort: transitivity violated for [15] [9] [11]
hol_sort: transitivity violated for [15] [9] [12]
hol_sort: transitivity violated for [15] [9] [13]
hol_sort: transitivity violated for [15] [9] [14]
hol_sort: transitivity violated for [15] [10] [11]
hol_sort: transitivity violated for [15] [10] [12]
hol_sort: transitivity violated for [15] [10] [13]
hol_sort: transitivity violated for [15] [10] [14]
hol_sort: transitivity violated for [15] [11] [12]
hol_sort: transitivity violated for [15] [11] [13]
hol_sort: transitivity violated for [15] [11] [14]
hol_sort: transitivity violated for [15] [12] [13]
hol_sort: transitivity violated for [15] [14] [12]
hol_sort: transitivity violated for [15] [14] [13]
hol_sort: transitivity violated for [15] [16] [9]
hol_sort: transitivity violated for [15] [16] [10]
hol_sort: transitivity violated for [15] [16] [11]
hol_sort: transitivity violated for [15] [16] [12]
hol_sort: transitivity violated for [15] [16] [13]
hol_sort: transitivity violated for [15] [16] [14]
hol_sort: transitivity violated for [15] [17] [9]
hol_sort: transitivity violated for [15] [17] [10]
hol_sort: transitivity violated for [15] [17] [11]
hol_sort: transitivity violated for [15] [17] [12]
hol_sort: transitivity violated for [15] [17] [13]
hol_sort: transitivity violated for [15] [17] [14]
hol_sort: transitivity violated for [16] [9] [10]
hol_sort: transitivity violated for [16] [9] [11]
hol_sort: transitivity violated for [16] [9] [12]
hol_sort: transitivity violated for [16] [9] [13]
hol_sort: transitivity violated for [16] [9] [14]
hol_sort: transitivity violated for [16] [10] [11]
hol_sort: transitivity violated for [16] [10] [12]
hol_sort: transitivity violated for [16] [10] [13]
hol_sort: transitivity violated for [16] [10] [14]
hol_sort: transitivity violated for [16] [11] [12]
hol_sort: transitivity violated for [16] [11] [13]
hol_sort: transitivity violated for [16] [11] [14]
hol_sort: transitivity violated for [16] [12] [13]
hol_sort: transitivity violated for [16] [14] [12]
hol_sort: transitivity violated for [16] [14] [13]
hol_sort: transitivity violated for [17] [9] [10]
hol_sort: transitivity violated for [17] [9] [11]
hol_sort: transitivity violated for [17] [9] [12]
hol_sort: transitivity violated for [17] [9] [13]
hol_sort: transitivity violated for [17] [9] [14]
hol_sort: transitivity violated for [17] [10] [11]
hol_sort: transitivity violated for [17] [10] [12]
hol_sort: transitivity violated for [17] [10] [13]
hol_sort: transitivity violated for [17] [10] [14]
hol_sort: transitivity violated for [17] [11] [12]
hol_sort: transitivity violated for [17] [11] [13]
hol_sort: transitivity violated for [17] [11] [14]
hol_sort: transitivity violated for [17] [12] [13]
hol_sort: transitivity violated for [17] [14] [12]
hol_sort: transitivity violated for [17] [14] [13]
hol_sort: transitivity violated for [17] [16] [9]
hol_sort: transitivity violated for [17] [16] [10]
hol_sort: transitivity violated for [17] [16] [11]
hol_sort: transitivity violated for [17] [16] [12]
hol_sort: transitivity violated for [17] [16] [13]
hol_sort: transitivity violated for [17] [16] [14]
hol_sort: sort result:
  [0] <- [0]
  [1] <- [1]
  [2] <- [2]
  [3] <- [5]
  [4] <- [4]
  [5] <- [3]
  [6] <- [6]
  [7] <- [7]
  [8] <- [8]
  [9] <- [9]
  [10] <- [10]
  [11] <- [11]
  [12] <- [14]
  [13] <- [12]
  [14] <- [13]
  [15] <- [15]
  [16] <- [17]
  [17] <- [16]
  [18] <- [20]
  [19] <- [21]
  [20] <- [18]
  [21] <- [19]
  [22] <- [22]
hol_sort: compare after sort:
 - - . - - . - - - - - - - - . - - - . - - -
Usage: test-argp [OPTION...] ARGS...
documentation string

 Main options
  -t, --test

 Option Group 1
  -f, -r, --file=FILE, --input=FILE, --read=FILE
                             Option with a mandatory argument
  -v, --verbose              Simple option without arguments

 Option Group 1.1
  -C, --cantiga              create a cantiga
  -S, --sonet                create a sonet

 Option Group 2
  -O, --option               An option

  -o, --optional[=ARG]       Option with an optional argument. ARG is one of
                             the following:

  many                       many units
  one                        one unit
  two                        two units

 Option Group 2.1
  -l, --limerick             create a limerick
  -p, --poem                 create a poem

  -?, --help                 give this help list
      --usage                give a short usage message
  -V, --version              print program version

Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.

Report bugs to <>.

[-- Attachment #4: argp-macos.out --]
[-- Type: text/plain, Size: 12527 bytes --]

hol_sort: entries = {
  [0] = [] [Main options]
  [1] = [test] []
  [2] = [] [Option Group 1]
  [3] = [verbose] [Simple option without arguments]
  [4] = [file] [Option with a mandatory argument]
  [5] = [hidden] [Hidden option]
  [6] = [] [Option Group 1.1]
  [7] = [cantiga] [create a cantiga]
  [8] = [sonet] [create a sonet]
  [9] = [] [Option Group 2]
  [10] = [option] [An option]
  [11] = [optional] [Option with an optional argument. ARG is one of the following:]
  [12] = [one] [one unit]
  [13] = [two] [two units]
  [14] = [many] [many units]
  [15] = [] [Option Group 2.1]
  [16] = [poem] [create a poem]
  [17] = [limerick] [create a limerick]
  [18] = [help] [give this help list]
  [19] = [usage] [give a short usage message]
  [20] = [program-name] [set the program name]
  [21] = [HANG] [hang for SECS seconds (default 3600)]
  [22] = [version] [print program version]
}
hol_sort: comparisons =
   . - - - - - - - - - - - - - - - - - - - - - -
   + . - - - - - - - - - - - - - - - - - - - - -
   + + . - - . . . . - - - - - - - - - - - - - -
   + + + . + + . . . - - - - - - - - - - - - - -
   + + + - . + . . . - - - - - - - - - - - - - -
   + + . - - . . . . - - - - - - - - - - - - - -
   + + . . . . . - - - - - - - - - - - - - - - -
   + + . . . . + . - - - - - - - - - - - - - - -
   + + . . . . + + . - - - - - - - - - - - - - -
   + + + + + + + + + . - - - - - . . . - - - - -
   + + + + + + + + + + . - - - - . . . - - - - -
   + + + + + + + + + + + . - - - . . . - - - - -
   + + + + + + + + + + + + . - + . . . - - - - -
   + + + + + + + + + + + + + . + . . . - - - - -
   + + + + + + + + + + + + - - . . . . - - - - -
   + + + + + + + + + . . . . . . . - - - - - - -
   + + + + + + + + + . . . . . . + . + - - - - -
   + + + + + + + + + . . . . . . + - . - - - - -
   + + + + + + + + + + + + + + + + + + . - + + -
   + + + + + + + + + + + + + + + + + + + . + + -
   + + + + + + + + + + + + + + + + + + - - . . -
   + + + + + + + + + + + + + + + + + + - - . . -
   + + + + + + + + + + + + + + + + + + + + + + .
hol_sort: transitivity violated for [2] [3] [6]
hol_sort: transitivity violated for [2] [3] [7]
hol_sort: transitivity violated for [2] [3] [8]
hol_sort: transitivity violated for [2] [4] [6]
hol_sort: transitivity violated for [2] [4] [7]
hol_sort: transitivity violated for [2] [4] [8]
hol_sort: transitivity violated for [2] [6] [7]
hol_sort: transitivity violated for [2] [6] [8]
hol_sort: transitivity violated for [2] [7] [8]
hol_sort: transitivity violated for [3] [6] [7]
hol_sort: transitivity violated for [3] [6] [8]
hol_sort: transitivity violated for [3] [7] [8]
hol_sort: transitivity violated for [4] [3] [6]
hol_sort: transitivity violated for [4] [3] [7]
hol_sort: transitivity violated for [4] [3] [8]
hol_sort: transitivity violated for [4] [6] [7]
hol_sort: transitivity violated for [4] [6] [8]
hol_sort: transitivity violated for [4] [7] [8]
hol_sort: transitivity violated for [5] [3] [6]
hol_sort: transitivity violated for [5] [3] [7]
hol_sort: transitivity violated for [5] [3] [8]
hol_sort: transitivity violated for [5] [4] [6]
hol_sort: transitivity violated for [5] [4] [7]
hol_sort: transitivity violated for [5] [4] [8]
hol_sort: transitivity violated for [5] [6] [7]
hol_sort: transitivity violated for [5] [6] [8]
hol_sort: transitivity violated for [5] [7] [8]
hol_sort: transitivity violated for [6] [2] [3]
hol_sort: transitivity violated for [6] [2] [4]
hol_sort: transitivity violated for [6] [4] [3]
hol_sort: transitivity violated for [6] [5] [3]
hol_sort: transitivity violated for [6] [5] [4]
hol_sort: transitivity violated for [6] [7] [2]
hol_sort: transitivity violated for [6] [7] [3]
hol_sort: transitivity violated for [6] [7] [4]
hol_sort: transitivity violated for [6] [7] [5]
hol_sort: transitivity violated for [6] [8] [2]
hol_sort: transitivity violated for [6] [8] [3]
hol_sort: transitivity violated for [6] [8] [4]
hol_sort: transitivity violated for [6] [8] [5]
hol_sort: transitivity violated for [7] [2] [3]
hol_sort: transitivity violated for [7] [2] [4]
hol_sort: transitivity violated for [7] [4] [3]
hol_sort: transitivity violated for [7] [5] [3]
hol_sort: transitivity violated for [7] [5] [4]
hol_sort: transitivity violated for [7] [8] [2]
hol_sort: transitivity violated for [7] [8] [3]
hol_sort: transitivity violated for [7] [8] [4]
hol_sort: transitivity violated for [7] [8] [5]
hol_sort: transitivity violated for [8] [2] [3]
hol_sort: transitivity violated for [8] [2] [4]
hol_sort: transitivity violated for [8] [4] [3]
hol_sort: transitivity violated for [8] [5] [3]
hol_sort: transitivity violated for [8] [5] [4]
hol_sort: transitivity violated for [9] [10] [15]
hol_sort: transitivity violated for [9] [10] [16]
hol_sort: transitivity violated for [9] [10] [17]
hol_sort: transitivity violated for [9] [11] [15]
hol_sort: transitivity violated for [9] [11] [16]
hol_sort: transitivity violated for [9] [11] [17]
hol_sort: transitivity violated for [9] [12] [15]
hol_sort: transitivity violated for [9] [12] [16]
hol_sort: transitivity violated for [9] [12] [17]
hol_sort: transitivity violated for [9] [13] [15]
hol_sort: transitivity violated for [9] [13] [16]
hol_sort: transitivity violated for [9] [13] [17]
hol_sort: transitivity violated for [9] [14] [15]
hol_sort: transitivity violated for [9] [14] [16]
hol_sort: transitivity violated for [9] [14] [17]
hol_sort: transitivity violated for [9] [15] [16]
hol_sort: transitivity violated for [9] [15] [17]
hol_sort: transitivity violated for [9] [17] [16]
hol_sort: transitivity violated for [10] [11] [15]
hol_sort: transitivity violated for [10] [11] [16]
hol_sort: transitivity violated for [10] [11] [17]
hol_sort: transitivity violated for [10] [12] [15]
hol_sort: transitivity violated for [10] [12] [16]
hol_sort: transitivity violated for [10] [12] [17]
hol_sort: transitivity violated for [10] [13] [15]
hol_sort: transitivity violated for [10] [13] [16]
hol_sort: transitivity violated for [10] [13] [17]
hol_sort: transitivity violated for [10] [14] [15]
hol_sort: transitivity violated for [10] [14] [16]
hol_sort: transitivity violated for [10] [14] [17]
hol_sort: transitivity violated for [10] [15] [16]
hol_sort: transitivity violated for [10] [15] [17]
hol_sort: transitivity violated for [10] [17] [16]
hol_sort: transitivity violated for [11] [12] [15]
hol_sort: transitivity violated for [11] [12] [16]
hol_sort: transitivity violated for [11] [12] [17]
hol_sort: transitivity violated for [11] [13] [15]
hol_sort: transitivity violated for [11] [13] [16]
hol_sort: transitivity violated for [11] [13] [17]
hol_sort: transitivity violated for [11] [14] [15]
hol_sort: transitivity violated for [11] [14] [16]
hol_sort: transitivity violated for [11] [14] [17]
hol_sort: transitivity violated for [11] [15] [16]
hol_sort: transitivity violated for [11] [15] [17]
hol_sort: transitivity violated for [11] [17] [16]
hol_sort: transitivity violated for [12] [13] [15]
hol_sort: transitivity violated for [12] [13] [16]
hol_sort: transitivity violated for [12] [13] [17]
hol_sort: transitivity violated for [12] [15] [16]
hol_sort: transitivity violated for [12] [15] [17]
hol_sort: transitivity violated for [12] [17] [16]
hol_sort: transitivity violated for [13] [15] [16]
hol_sort: transitivity violated for [13] [15] [17]
hol_sort: transitivity violated for [13] [17] [16]
hol_sort: transitivity violated for [14] [12] [15]
hol_sort: transitivity violated for [14] [12] [16]
hol_sort: transitivity violated for [14] [12] [17]
hol_sort: transitivity violated for [14] [13] [15]
hol_sort: transitivity violated for [14] [13] [16]
hol_sort: transitivity violated for [14] [13] [17]
hol_sort: transitivity violated for [14] [15] [16]
hol_sort: transitivity violated for [14] [15] [17]
hol_sort: transitivity violated for [14] [17] [16]
hol_sort: transitivity violated for [15] [9] [10]
hol_sort: transitivity violated for [15] [9] [11]
hol_sort: transitivity violated for [15] [9] [12]
hol_sort: transitivity violated for [15] [9] [13]
hol_sort: transitivity violated for [15] [9] [14]
hol_sort: transitivity violated for [15] [10] [11]
hol_sort: transitivity violated for [15] [10] [12]
hol_sort: transitivity violated for [15] [10] [13]
hol_sort: transitivity violated for [15] [10] [14]
hol_sort: transitivity violated for [15] [11] [12]
hol_sort: transitivity violated for [15] [11] [13]
hol_sort: transitivity violated for [15] [11] [14]
hol_sort: transitivity violated for [15] [12] [13]
hol_sort: transitivity violated for [15] [14] [12]
hol_sort: transitivity violated for [15] [14] [13]
hol_sort: transitivity violated for [15] [16] [9]
hol_sort: transitivity violated for [15] [16] [10]
hol_sort: transitivity violated for [15] [16] [11]
hol_sort: transitivity violated for [15] [16] [12]
hol_sort: transitivity violated for [15] [16] [13]
hol_sort: transitivity violated for [15] [16] [14]
hol_sort: transitivity violated for [15] [17] [9]
hol_sort: transitivity violated for [15] [17] [10]
hol_sort: transitivity violated for [15] [17] [11]
hol_sort: transitivity violated for [15] [17] [12]
hol_sort: transitivity violated for [15] [17] [13]
hol_sort: transitivity violated for [15] [17] [14]
hol_sort: transitivity violated for [16] [9] [10]
hol_sort: transitivity violated for [16] [9] [11]
hol_sort: transitivity violated for [16] [9] [12]
hol_sort: transitivity violated for [16] [9] [13]
hol_sort: transitivity violated for [16] [9] [14]
hol_sort: transitivity violated for [16] [10] [11]
hol_sort: transitivity violated for [16] [10] [12]
hol_sort: transitivity violated for [16] [10] [13]
hol_sort: transitivity violated for [16] [10] [14]
hol_sort: transitivity violated for [16] [11] [12]
hol_sort: transitivity violated for [16] [11] [13]
hol_sort: transitivity violated for [16] [11] [14]
hol_sort: transitivity violated for [16] [12] [13]
hol_sort: transitivity violated for [16] [14] [12]
hol_sort: transitivity violated for [16] [14] [13]
hol_sort: transitivity violated for [17] [9] [10]
hol_sort: transitivity violated for [17] [9] [11]
hol_sort: transitivity violated for [17] [9] [12]
hol_sort: transitivity violated for [17] [9] [13]
hol_sort: transitivity violated for [17] [9] [14]
hol_sort: transitivity violated for [17] [10] [11]
hol_sort: transitivity violated for [17] [10] [12]
hol_sort: transitivity violated for [17] [10] [13]
hol_sort: transitivity violated for [17] [10] [14]
hol_sort: transitivity violated for [17] [11] [12]
hol_sort: transitivity violated for [17] [11] [13]
hol_sort: transitivity violated for [17] [11] [14]
hol_sort: transitivity violated for [17] [12] [13]
hol_sort: transitivity violated for [17] [14] [12]
hol_sort: transitivity violated for [17] [14] [13]
hol_sort: transitivity violated for [17] [16] [9]
hol_sort: transitivity violated for [17] [16] [10]
hol_sort: transitivity violated for [17] [16] [11]
hol_sort: transitivity violated for [17] [16] [12]
hol_sort: transitivity violated for [17] [16] [13]
hol_sort: transitivity violated for [17] [16] [14]
hol_sort: sort result:
  [0] <- [0]
  [1] <- [1]
  [2] <- [5]
  [3] <- [2]
  [4] <- [6]
  [5] <- [7]
  [6] <- [8]
  [7] <- [4]
  [8] <- [3]
  [9] <- [9]
  [10] <- [10]
  [11] <- [11]
  [12] <- [15]
  [13] <- [16]
  [14] <- [17]
  [15] <- [14]
  [16] <- [12]
  [17] <- [13]
  [18] <- [20]
  [19] <- [21]
  [20] <- [18]
  [21] <- [19]
  [22] <- [22]
hol_sort: compare after sort:
 - - . . - - . - - - - . - + . - - - . - - -
Usage: test-argp [OPTION...] ARGS...
documentation string

 Main options
  -t, --test

 Option Group 1

 Option Group 1.1
  -C, --cantiga              create a cantiga
  -S, --sonet                create a sonet
  -f, -r, --file=FILE, --input=FILE, --read=FILE
                             Option with a mandatory argument
  -v, --verbose              Simple option without arguments

 Option Group 2
  -O, --option               An option

  -o, --optional[=ARG]       Option with an optional argument. ARG is one of
                             the following:

 Option Group 2.1
  -p, --poem                 create a poem
  -l, --limerick             create a limerick

  many                       many units
  one                        one unit
  two                        two units

  -?, --help                 give this help list
      --usage                give a short usage message
  -V, --version              print program version

Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.

Report bugs to <>.

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-12-08 22:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-28 23:14 Initial Travis testing results look great. One failed self test on OS X 10.10 Jeffrey Walton
2020-03-29  0:32 ` Jeffrey Walton
2020-03-29 12:19   ` argp failure on macOS Bruno Haible
2020-03-29 21:05     ` Sergey Poznyakoff
2020-12-08 20:48   ` Initial Travis testing results look great. One failed self test on OS X 10.10 Bruno Haible

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).