summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2016-11-05 20:18:05 +0200
committerSergey Poznyakoff <gray@gnu.org>2016-11-05 20:18:05 +0200
commitfd19deb4391f18e1a752ae5cfe4a9d3155e97705 (patch)
tree04fe4977ea9197ed4156498d3efc9c8bde0302ce
parente8f82804806e94f9b6e4fc072d785e29ea099827 (diff)
downloadmailutils-fd19deb4391f18e1a752ae5cfe4a9d3155e97705.tar.gz
mailutils-fd19deb4391f18e1a752ae5cfe4a9d3155e97705.tar.bz2
Fix option sorting.
* libmailutils/opt/opt.c (sort_group): Don't assume stability of the sort. Use auxiliary data structure to sort array of options that contain aliases. * libmailutils/tests/parseopt.c (set_prog_args): Fix delimiter. * libmailutils/tests/strtoc.c (v_cidr_format): Error checking. * maidag/Makefile.am (maidag_LDADD): Reorder libraries to make sure maidag uses freshly built libraries (not the ones already installed in the system). * mh/pick.c (options): Bugfix.
-rw-r--r--libmailutils/opt/opt.c76
-rw-r--r--libmailutils/tests/parseopt.c2
-rw-r--r--libmailutils/tests/strtoc.c18
-rw-r--r--maidag/Makefile.am8
-rw-r--r--mh/pick.c2
5 files changed, 83 insertions, 23 deletions
diff --git a/libmailutils/opt/opt.c b/libmailutils/opt/opt.c
index 0a436c563..7a992f231 100644
--- a/libmailutils/opt/opt.c
+++ b/libmailutils/opt/opt.c
@@ -29,6 +29,14 @@
#define EXIT_SUCCESS 0
#define EXIT_ERROR 1
+/* Option and its aliases form a contiguous array. Option slot is used
+ to preserve contiguity during sorting. */
+struct opt_slot
+{
+ struct mu_option **opt; /* Points to the option */
+ int count; /* Number of options in opt */
+};
+
/* Compare pointers to two option structs */
static int
optcmp (const void *a, const void *b)
@@ -36,11 +44,6 @@ optcmp (const void *a, const void *b)
struct mu_option const *ap = *(struct mu_option const **)a;
struct mu_option const *bp = *(struct mu_option const **)b;
- while (ap->opt_flags & MU_OPTION_ALIAS)
- ap--;
- while (bp->opt_flags & MU_OPTION_ALIAS)
- bp--;
-
if (!MU_OPTION_IS_VALID_SHORT_OPTION (ap)
&& MU_OPTION_IS_VALID_LONG_OPTION (ap)
&& !MU_OPTION_IS_VALID_SHORT_OPTION (bp)
@@ -60,18 +63,67 @@ optcmp (const void *a, const void *b)
}
}
+/* Compare pointers to two option slots */
+static int
+slotcmp (const void *a, const void *b)
+{
+ struct opt_slot const *ap = (struct opt_slot const *)a;
+ struct opt_slot const *bp = (struct opt_slot const *)b;
+ return optcmp (ap->opt, bp->opt);
+}
/* Sort a group of options in OPTBUF, starting at index START (first
option slot after a group header (if any). The group spans up to
next group header or end of options */
static size_t
sort_group (struct mu_option **optbuf, size_t start)
{
- size_t i;
-
+ size_t i, count = 0;
+
+ /* Make sure the first option in group is not an alias. */
+ optbuf[start]->opt_flags &= ~MU_OPTION_ALIAS;
for (i = start; optbuf[i] && !MU_OPTION_IS_GROUP_HEADER (optbuf[i]); i++)
- ;
-
- qsort (&optbuf[start], i - start, sizeof (optbuf[0]), optcmp);
+ {
+ if (!(optbuf[i]->opt_flags & MU_OPTION_ALIAS))
+ count++;
+ }
+ if (count == i - start)
+ /* Inplace sort */
+ qsort (&optbuf[start], count, sizeof (optbuf[0]), optcmp);
+ else
+ {
+ /* Option group contains aliases. Split it into option slots. */
+ struct mu_option **tmp;
+ struct opt_slot *slots;
+ size_t j, k, l;
+
+ slots = mu_calloc (count, sizeof (slots[0]));
+ j = 0;
+ slots[0].opt = optbuf + start;
+ slots[0].count = 1;
+ for (k = start + 1; k < i; k++)
+ {
+ if (optbuf[k]->opt_flags & MU_OPTION_ALIAS)
+ slots[j].count++;
+ else
+ {
+ j++;
+ slots[j].opt = optbuf + k;
+ slots[j].count = 1;
+ }
+ }
+ /* Sort the slots */
+ qsort (slots, count, sizeof (slots[0]), slotcmp);
+ /* Create ordered array of option pointers */
+ tmp = mu_calloc (i - start, sizeof (tmp[0]));
+ for (k = l = 0; k < count; k++)
+ for (j = 0; j < slots[k].count; j++)
+ tmp[l++] = slots[k].opt[j];
+ /* Copy ordered pointers back and free temporary memory */
+ memcpy (optbuf + start, tmp, (i - start) * sizeof tmp[0]);
+ free (tmp);
+ free (slots);
+ }
+
return i;
}
@@ -648,9 +700,7 @@ parseopt_init (struct mu_parseopt *po, struct mu_option **options,
po->po_optv[j] = NULL;
- /* Ensure sane start of options. This is necessary, in particular,
- because optcmp backs up until it finds an element with cleared
- MU_OPTION_ALIAS bit. */
+ /* Ensure sane start of options. */
po->po_optv[0]->opt_flags &= ~MU_OPTION_ALIAS;
if (!(flags & MU_PARSEOPT_NO_SORT))
{
diff --git a/libmailutils/tests/parseopt.c b/libmailutils/tests/parseopt.c
index 7b2aadea6..cefffdda3 100644
--- a/libmailutils/tests/parseopt.c
+++ b/libmailutils/tests/parseopt.c
@@ -90,7 +90,7 @@ set_prog_args (struct parseopt_param *param, char const *str, void *target)
size = 1;
for (i = 0; str[i]; i++)
- if (str[i] == '\n')
+ if (str[i] == '|')
size++;
args = mu_calloc (size + 1, sizeof (args[0]));
diff --git a/libmailutils/tests/strtoc.c b/libmailutils/tests/strtoc.c
index 64c3cb4f8..8ac863734 100644
--- a/libmailutils/tests/strtoc.c
+++ b/libmailutils/tests/strtoc.c
@@ -161,10 +161,17 @@ static void
v_cidr_format (union value *val, FILE *fp)
{
char *buf;
-
- mu_cidr_format (&val->v_cidr, 0, &buf);
- fprintf (fp, "%s", buf);
- free (buf);
+ int rc;
+ rc = mu_cidr_format (&val->v_cidr, 0, &buf);
+ if (rc)
+ {
+ fprintf (fp, "(can't convert value: %s)", mu_strerror (rc));
+ }
+ else
+ {
+ fprintf (fp, "%s", buf);
+ free (buf);
+ }
}
static int
@@ -259,6 +266,7 @@ struct testdata tests[] = {
.len = 4,
.address = { 127, 0, 0, 0 },
.netmask = { 255 } } } },
+#ifdef MAILUTILS_IPV6
{ mu_c_cidr, "fe80::4a5b:39ff:fe09:97f0/64", 0, { .v_cidr = {
.family = 10,
.len = 16,
@@ -266,7 +274,7 @@ struct testdata tests[] = {
0x4a, 0x5b, 0x39, 0xff, 0xfe, 0x9, 0x97, 0xf0 },
.netmask = { 255, 255, 255, 255, 255, 255, 255, 255,
0, 0, 0, 0, 0, 0, 0, 0 } } } },
-
+#endif
{ mu_c_incr, NULL, 0, { .v_int = 1 } },
{ mu_c_void }
};
diff --git a/maidag/Makefile.am b/maidag/Makefile.am
index 53c887eaf..d684f41f5 100644
--- a/maidag/Makefile.am
+++ b/maidag/Makefile.am
@@ -33,9 +33,6 @@ endif
maidag_LDADD = \
../lib/libmuscript.a\
- @LIBMU_SCM@ @GUILE_LIBS@\
- @LIBMU_SCM_DEPS@\
- @MU_LIB_PY@ @PYTHON_LIBS@\
${MU_APP_LIBRARIES}\
${MU_LIB_SIEVE}\
${MU_LIB_MBOX}\
@@ -49,7 +46,12 @@ maidag_LDADD = \
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS} \
@MU_COMMON_LIBRARIES@\
+ @LIBMU_SCM@\
+ @LIBMU_SCM_DEPS@\
+ @MU_LIB_PY@\
$(LIBMU_DBM)\
+ @GUILE_LIBS@\
+ @PYTHON_LIBS@\
@DBMLIBS@\
@MU_TCPWRAP_LIBRARIES@
diff --git a/mh/pick.c b/mh/pick.c
index 9a788660a..53e9d83b4 100644
--- a/mh/pick.c
+++ b/mh/pick.c
@@ -192,7 +192,7 @@ static struct mu_option options[] = {
{ ")", 0, NULL, MU_OPTION_ALIAS },
MU_OPTION_GROUP (N_("Operations over the selected messages")),
- { "list", 0, NULL, MU_OPTION_ALIAS,
+ { "list", 0, NULL, MU_OPTION_DEFAULT,
N_("list the numbers of the selected messages (default)"),
mu_c_bool, &list },
{ "sequence", 0, N_("NAME"), MU_OPTION_DEFAULT,

Return to:

Send suggestions and report system problems to the System administrator.