diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-11-05 20:18:05 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-11-05 20:18:05 +0200 |
commit | fd19deb4391f18e1a752ae5cfe4a9d3155e97705 (patch) | |
tree | 04fe4977ea9197ed4156498d3efc9c8bde0302ce | |
parent | e8f82804806e94f9b6e4fc072d785e29ea099827 (diff) | |
download | mailutils-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.c | 76 | ||||
-rw-r--r-- | libmailutils/tests/parseopt.c | 2 | ||||
-rw-r--r-- | libmailutils/tests/strtoc.c | 18 | ||||
-rw-r--r-- | maidag/Makefile.am | 8 | ||||
-rw-r--r-- | mh/pick.c | 2 |
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@ @@ -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, |