aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-06-24 16:51:49 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-06-24 16:51:49 +0300
commitc735683258070b13ff221fabb81e1c24d7805174 (patch)
tree1e7e5ecf3ef99e5706f1632103812fcf743460e7
parent716d8fc8909b65613380c477942b05e750ef5db0 (diff)
downloadsmap-c735683258070b13ff221fabb81e1c24d7805174.tar.gz
smap-c735683258070b13ff221fabb81e1c24d7805174.tar.bz2
Improve help output.
* src/getopt.m4 (print_usage, print_help): Sort options prior to displaying them. (sort_opthelp, sort_options, optcmp) (cmpidx_short, cmpidx_long): New functions.
-rw-r--r--src/getopt.m4199
1 files changed, 159 insertions, 40 deletions
diff --git a/src/getopt.m4 b/src/getopt.m4
index c8de14d..3c19865 100644
--- a/src/getopt.m4
+++ b/src/getopt.m4
@@ -251,8 +251,63 @@ print_option_descr (const char *descr, size_t lmargin, size_t rmargin)
}
}
+#define NOPTHELP (sizeof (opthelp) / sizeof (opthelp[0]))
+
+static int
+optcmp (const void *a, const void *b)
+{
+ struct opthelp const *ap = (struct opthelp const *)a;
+ struct opthelp const *bp = (struct opthelp const *)b;
+ const char *opta, *optb;
+ size_t alen, blen;
+
+ for (opta = ap->opt; *opta == '-'; opta++)
+ ;
+ alen = strcspn (opta, ",");
+
+ for (optb = bp->opt; *optb == '-'; optb++)
+ ;
+ blen = strcspn (optb, ",");
+
+ if (alen > blen)
+ blen = alen;
+
+ return strncmp (opta, optb, blen);
+}
+
+static void
+sort_options (int start, int count)
+{
+ qsort (opthelp + start, count, sizeof (opthelp[0]), optcmp);
+}
+
+static int
+sort_group (int start)
+{
+ int i;
+
+ for (i = start; i < NOPTHELP && opthelp[i].opt; i++)
+ ;
+ sort_options (start, i - start);
+ return i + 1;
+}
+
+static void
+sort_opthelp (void)
+{
+ int start;
+
+ for (start = 0; start < NOPTHELP; )
+ {
+ if (!opthelp[start].opt)
+ start = sort_group (start + 1);
+ else
+ start = sort_group (start);
+ }
+}
+
void
-print_help(void)
+print_help (void)
{
unsigned i;
int argsused = 0;
@@ -263,7 +318,8 @@ print_help(void)
print_option_descr(gettext (doc), 0, RMARGIN);
putchar ('\n');
- for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++)
+ sort_opthelp ();
+ for (i = 0; i < NOPTHELP; i++)
{
unsigned n;
if (opthelp[i].opt)
@@ -328,6 +384,39 @@ dnl **************************************************************************
printf (_("Report bugs to %s.\n"), program_bug_address);
}
+static int
+cmpidx_short (const void *a, const void *b)
+{
+ unsigned const *ai = (unsigned const *)a;
+ unsigned const *bi = (unsigned const *)b;
+
+ return opthelp[*ai].opt[1] - opthelp[*bi].opt[1];
+}
+
+static int
+cmpidx_long (const void *a, const void *b)
+{
+ unsigned const *ai = (unsigned const *)a;
+ unsigned const *bi = (unsigned const *)b;
+ struct opthelp const *ap = opthelp + *ai;
+ struct opthelp const *bp = opthelp + *bi;
+ char const *opta, *optb;
+ size_t lena, lenb;
+
+ if (ap->opt[1] == '-')
+ opta = ap->opt;
+ else
+ opta = ap->opt + 4;
+ lena = strcspn (opta, ",");
+
+ if (bp->opt[1] == '-')
+ optb = bp->opt;
+ else
+ optb = bp->opt + 4;
+ lenb = strcspn (optb, ",");
+ return strncmp (opta, optb, lena > lenb ? lenb : lena);
+}
+
void
print_usage(void)
{
@@ -335,7 +424,9 @@ print_usage(void)
int f = 0;
unsigned n;
char buf[RMARGIN+1];
-
+ unsigned *idxbuf;
+ unsigned nidx;
+
#define FLUSH dnl
do dnl
{ dnl
@@ -348,94 +439,122 @@ print_usage(void)
#define ADDC(c) dnl
do { if (n == RMARGIN) FLUSH; buf[n++] = c; } while (0)
+ idxbuf = calloc (NOPTHELP, sizeof (idxbuf[0]));
+ if (!idxbuf)
+ {
+ fprintf (stderr, "not enough memory");
+ abort ();
+ }
+
n = snprintf (buf, sizeof buf, "%s %s ", _("Usage:"), [<$2>]);
/* Print a list of short options without arguments. */
- for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++)
- {
+ for (i = nidx = 0; i < NOPTHELP; i++)
if (opthelp[i].opt && opthelp[i].descr && opthelp[i].opt[1] != '-'
&& opthelp[i].arg == NULL)
+ idxbuf[nidx++] = i;
+
+ if (nidx)
+ {
+ qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short);
+
+ ADDC ('[');
+ ADDC ('-');
+ for (i = 0; i < nidx; i++)
{
- if (f == 0)
- {
- ADDC('[');
- ADDC('-');
- f = 1;
- }
- ADDC(opthelp[i].opt[1]);
+ ADDC (opthelp[idxbuf[i]].opt[1]);
}
+ ADDC (']');
}
- if (f)
- ADDC(']');
/* Print a list of short options with arguments. */
- for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++)
+ for (i = nidx = 0; i < NOPTHELP; i++)
{
if (opthelp[i].opt && opthelp[i].descr && opthelp[i].opt[1] != '-'
&& opthelp[i].arg)
+ idxbuf[nidx++] = i;
+ }
+
+ if (nidx)
+ {
+ qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short);
+
+ for (i = 0; i < nidx; i++)
{
- size_t len = 5
- + strlen (opthelp[i].arg)
- + (opthelp[i].is_optional ? 2 : 1);
+ struct opthelp *opt = opthelp + idxbuf[i];
+ size_t len = 5 + strlen (opt->arg)
+ + (opt->is_optional ? 2 : 1);
+
if (n + len > RMARGIN) FLUSH;
buf[n++] = ' ';
buf[n++] = '[';
buf[n++] = '-';
- buf[n++] = opthelp[i].opt[1];
- if (opthelp[i].is_optional)
+ buf[n++] = opt->opt[1];
+ if (opt->is_optional)
{
buf[n++] = '[';
- strcpy (&buf[n], opthelp[i].arg);
- n += strlen (opthelp[i].arg);
+ strcpy (&buf[n], opt->arg);
+ n += strlen (opt->arg);
buf[n++] = ']';
}
else
{
buf[n++] = ' ';
- strcpy (&buf[n], opthelp[i].arg);
- n += strlen (opthelp[i].arg);
+ strcpy (&buf[n], opt->arg);
+ n += strlen (opt->arg);
}
buf[n++] = ']';
}
}
+
#ifdef HAVE_GETOPT_LONG
/* Print a list of long options */
- for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++)
+ for (i = nidx = 0; i < NOPTHELP; i++)
{
- if (opthelp[i].opt && opthelp[i].descr)
+ if (opthelp[i].opt && opthelp[i].descr
+ && (opthelp[i].opt[1] == '-' || opthelp[i].opt[2] == ','))
+ idxbuf[nidx++] = i;
+ }
+
+ if (nidx)
+ {
+ qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_long);
+
+ for (i = 0; i < nidx; i++)
{
+ struct opthelp *opt = opthelp + idxbuf[i];
size_t len;
const char *longopt;
-
- if (opthelp[i].opt[1] == '-')
- longopt = opthelp[i].opt;
- else if (opthelp[i].opt[2] == ',')
- longopt = opthelp[i].opt + 4;
+
+ if (opt->opt[1] == '-')
+ longopt = opt->opt;
+ else if (opt->opt[2] == ',')
+ longopt = opt->opt + 4;
else
continue;
len = 3 + strlen (longopt)
- + (opthelp[i].arg ? 1 + strlen (opthelp[i].arg)
- + (opthelp[i].is_optional ? 2 : 0) : 0);
+ + (opt->arg ? 1 + strlen (opt->arg)
+ + (opt->is_optional ? 2 : 0) : 0);
if (n + len > RMARGIN) FLUSH;
buf[n++] = ' ';
buf[n++] = '[';
strcpy (&buf[n], longopt);
n += strlen (longopt);
- if (opthelp[i].arg)
+ if (opt->arg)
{
buf[n++] = '=';
- if (opthelp[i].is_optional)
+ if (opt->is_optional)
{
buf[n++] = '[';
- strcpy (&buf[n], opthelp[i].arg);
- n += strlen (opthelp[i].arg);
+ strcpy (&buf[n], opt->arg);
+ n += strlen (opt->arg);
buf[n++] = ']';
}
else
{
- strcpy (&buf[n], opthelp[i].arg);
- n += strlen (opthelp[i].arg);
+ strcpy (&buf[n], opt->arg);
+ n += strlen (opt->arg);
}
}
buf[n++] = ']';
@@ -443,7 +562,7 @@ print_usage(void)
}
#endif
FLUSH;
-
+ free (idxbuf);
}
const char version_etc_copyright[] =

Return to:

Send suggestions and report system problems to the System administrator.