Commit 7717d6fa 7717d6fab8dd9168864990714574a82aa85f7229 by Sergey Poznyakoff

mh: improve traditional option parser and help output.

* mh/mh_getopt.h (mh_option): Move match_len to the end of the
structure.  It should not be initialized.
(mh_option_init): New prototype.

* mh/mh_getopt.c (mh_option_init): New function.
* mh/mh_argp.c (mh_argp_parse): Call mh_option_init.

* mh/ali.c: Update mh_option declaration.
* mh/anno.c: Likewise.
* mh/burst.c: Likewise.
* mh/comp.c: Likewise.
* mh/fmtcheck.c: Likewise.
* mh/folder.c: Likewise.
* mh/forw.c: Likewise.
* mh/inc.c: Likewise.
* mh/install-mh.c: Likewise.
* mh/mark.c: Likewise.
* mh/mhl.c: Likewise.
* mh/mhn.c: Likewise.
* mh/mhparam.c: Likewise.
* mh/mhpath.c: Likewise.
* mh/pick.c: Likewise.
* mh/refile.c: Likewise.
* mh/repl.c: Likewise.
* mh/rmf.c: Likewise.
* mh/rmm.c: Likewise.
* mh/scan.c: Likewise.
* mh/send.c: Likewise.
* mh/sortm.c: Likewise.
* mh/whatnow.c: Likewise.
* mh/whom.c: Likewise.
1 parent d4582ca1
......@@ -45,12 +45,12 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{ "alias", 1, MH_OPT_ARG, "aliasfile" },
{ "noalias", 3, },
{ "list", 1, MH_OPT_BOOL },
{ "normalize", 3, MH_OPT_BOOL },
{ "user", 1, MH_OPT_BOOL },
{ 0 }
{ "alias", MH_OPT_ARG, "aliasfile" },
{ "noalias", },
{ "list", MH_OPT_BOOL },
{ "normalize", MH_OPT_BOOL },
{ "user", MH_OPT_BOOL },
{ NULL }
};
static int list_mode;
......
......@@ -42,10 +42,10 @@ static struct argp_option options[] = {
};
struct mh_option mh_option[] = {
{"inplace", 1, MH_OPT_BOOL },
{"date", 1, MH_OPT_BOOL },
{"component", 1, MH_OPT_ARG, "field"},
{"text", 1, MH_OPT_ARG, "body"},
{ "inplace", MH_OPT_BOOL },
{ "date", MH_OPT_BOOL },
{ "component", MH_OPT_ARG, "field" },
{ "text", MH_OPT_ARG, "body" },
{ NULL }
};
......
......@@ -50,10 +50,10 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"inplace", 1, MH_OPT_BOOL },
{"quiet", 1, MH_OPT_BOOL },
{"verbose", 1, MH_OPT_BOOL },
{NULL}
{ "inplace", MH_OPT_BOOL },
{ "quiet", MH_OPT_BOOL },
{ "verbose", MH_OPT_BOOL },
{ NULL }
};
/* Command line switches */
......
......@@ -58,17 +58,17 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"build", 1, },
{"file", 2, MH_OPT_ARG, "draftfile"},
{"form", 2, MH_OPT_ARG, "formatfile"},
{"draftfolder", 6, MH_OPT_ARG, "folder"},
{"nodraftfolder", 3, },
{"draftmessage", 6, },
{"editor", 1, MH_OPT_ARG, "program"},
{"noedit", 3, },
{"whatnowproc", 2, MH_OPT_ARG, "program"},
{"nowhatnowproc", 3, },
{ 0 }
{ "build" },
{ "file", MH_OPT_ARG, "draftfile" },
{ "form", MH_OPT_ARG, "formatfile" },
{ "draftfolder", MH_OPT_ARG, "folder" },
{ "nodraftfolder" },
{ "draftmessage" },
{ "editor", MH_OPT_ARG, "program" },
{ "noedit" },
{ "whatnowproc", MH_OPT_ARG, "program" },
{ "nowhatnowproc" },
{ NULL }
};
struct mh_whatnow_env wh_env = { 0 };
......
......@@ -39,9 +39,9 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"form", 4, MH_OPT_ARG, "formatfile"},
{"format", 5, MH_OPT_ARG, "string"},
{ 0 }
{ "form", MH_OPT_ARG, "formatfile" },
{ "format", MH_OPT_ARG, "string" },
{ NULL }
};
char *format_str;
......
......@@ -83,18 +83,18 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"print", 2, 0, NULL },
{"list", 1, 0, NULL },
{"push", 2, 0, NULL },
{"pop", 2, 0, NULL },
{"all", 1, 0, NULL },
{"pack", 2, 0, NULL },
{"create", 1, MH_OPT_BOOL, NULL},
{"fast", 1, MH_OPT_BOOL, NULL},
{"header", 1, MH_OPT_BOOL, NULL},
{"recurse", 1, MH_OPT_BOOL, NULL},
{"total", 1, MH_OPT_BOOL, NULL},
{NULL},
{ "print" },
{ "list" },
{ "push" },
{ "pop" },
{ "all" },
{ "pack" },
{ "create", MH_OPT_BOOL },
{ "fast", MH_OPT_BOOL },
{ "header", MH_OPT_BOOL },
{ "recurse", MH_OPT_BOOL },
{ "total", MH_OPT_BOOL },
{ NULL }
};
typedef int (*folder_action) ();
......
......@@ -72,21 +72,21 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"annotate", 1, MH_OPT_BOOL },
{"build", 1, },
{"form", 4, MH_OPT_ARG, "formatfile"},
{"format", 5, MH_OPT_ARG, "string"},
{"draftfolder", 6, MH_OPT_ARG, "folder"},
{"nodraftfolder", 3 },
{"draftmessage", 6, },
{"editor", 1, MH_OPT_ARG, "program"},
{"noedit", 3, },
{"filter", 2, MH_OPT_ARG, "program"},
{"inplace", 1, MH_OPT_BOOL },
{"whatnowproc", 2, MH_OPT_ARG, "program"},
{"nowhatnowproc", 3 },
{"mime", 2, MH_OPT_BOOL, NULL},
{NULL}
{ "annotate", MH_OPT_BOOL },
{ "build" },
{ "form", MH_OPT_ARG, "formatfile"},
{ "format", MH_OPT_ARG, "string"},
{ "draftfolder", MH_OPT_ARG, "folder"},
{ "nodraftfolder" },
{ "draftmessage" },
{ "editor", MH_OPT_ARG, "program"},
{ "noedit" },
{ "filter", MH_OPT_ARG, "program"},
{ "inplace", MH_OPT_BOOL },
{ "whatnowproc", MH_OPT_ARG, "program"},
{ "nowhatnowproc" },
{ "mime", MH_OPT_BOOL },
{ NULL }
};
enum encap_type {
......
......@@ -52,16 +52,16 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"audit", 5, MH_OPT_ARG, "audit-file" },
{"noaudit", 3, 0, },
{"changecur", 1, MH_OPT_BOOL},
{"file", 2, MH_OPT_ARG, "input-file"},
{"form", 4, MH_OPT_ARG, "format-file"},
{"format", 5, MH_OPT_ARG, "string"},
{"truncate", 2, MH_OPT_BOOL, },
{"width", 1, MH_OPT_ARG, "number"},
{"quiet", 1, 0, },
{ 0 }
{ "audit", MH_OPT_ARG, "audit-file" },
{ "noaudit" },
{ "changecur", MH_OPT_BOOL },
{ "file", MH_OPT_ARG, "input-file" },
{ "form", MH_OPT_ARG, "format-file" },
{ "format", MH_OPT_ARG, "string" },
{ "truncate", MH_OPT_BOOL },
{ "width", MH_OPT_ARG, "number" },
{ "quiet" },
{ NULL }
};
static char *format_str = mh_list_format;
......
......@@ -29,8 +29,8 @@ static struct argp_option options[] = {
};
struct mh_option mh_option[] = {
{"auto", 1, 0, },
{"compat", 1, 0, },
{ "auto" },
{ "compat" },
{ NULL }
};
......
......@@ -43,12 +43,12 @@ static struct argp_option options[] = {
};
struct mh_option mh_option[] = {
{"sequence", 1, },
{"add", 1, },
{"delete", 1, },
{"list", 1, },
{"public", 1, MH_OPT_BOOL },
{"zero", 1, MH_OPT_BOOL },
{ "sequence" },
{ "add" },
{ "delete" },
{ "list" },
{ "public", MH_OPT_BOOL },
{ "zero", MH_OPT_BOOL },
{ NULL }
};
......
......@@ -202,6 +202,7 @@ mh_argp_parse (int *pargc, char **pargv[],
mu_set_program_name ((*pargv)[0]);
mh_init ();
mh_option_init (mh_option);
memset (&argp, 0, sizeof (argp));
argp.options = option;
argp.parser = parse_opt;
......
......@@ -153,6 +153,52 @@ mh_help (struct mh_option *mh_opt, const char *doc)
mu_program_name);
}
static int
optcmp (const void *a, const void *b)
{
struct mh_option const *opta = a, *optb = b;
return strcmp (opta->opt, optb->opt);
}
void
mh_option_init (struct mh_option *opt)
{
size_t count, i;
/* Count number of elements and initialize minimum abbreviation
lengths to 1. */
for (count = 0; opt[count].opt; count++)
opt[count].match_len = 1;
/* Sort them alphabetically */
qsort (opt, count, sizeof (opt[0]), optcmp);
/* Determine minimum abbreviations */
for (i = 0; i < count; i++)
{
const char *sample = opt[i].opt;
size_t sample_len = strlen (sample);
size_t minlen = opt[i].match_len;
size_t j;
for (j = i + 1; j < count; j++)
{
size_t len = strlen (opt[j].opt);
if (len >= minlen && memcmp (opt[j].opt, sample, minlen) == 0)
do
{
minlen++;
opt[j].match_len = minlen;
if (minlen == sample_len)
break;
}
while (len >= minlen && memcmp (opt[j].opt, sample, minlen) == 0);
else
break;
}
opt[i].match_len = minlen;
}
}
void
mh_opt_notimpl (const char *name)
{
......
......@@ -25,9 +25,9 @@
struct mh_option
{
char *opt;
int match_len;
int flags;
char *arg;
size_t match_len;
};
struct mh_argp_data
......@@ -183,6 +183,8 @@ enum mh_arg {
extern void (*mh_help_hook) (void);
void mh_option_init (struct mh_option *opt);
void mh_argp_init (void);
void mh_argv_preproc (int argc, char **argv, struct mh_argp_data *data);
int mh_getopt (int argc, char **argv, struct mh_option *mh_opt, const char *doc);
......
......@@ -50,13 +50,13 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{ "bell", 1, MH_OPT_BOOL },
{ "clear", 1, MH_OPT_BOOL },
{ "form", 1, MH_OPT_ARG, "formatfile"},
{ "width", 1, MH_OPT_ARG, "number"},
{ "length", 1, MH_OPT_ARG, "number"},
{ "moreproc", 1, MH_OPT_ARG, "program"},
{ "nomoreproc", 3, },
{ "bell", MH_OPT_BOOL },
{ "clear", MH_OPT_BOOL },
{ "form", MH_OPT_ARG, "formatfile"},
{ "width", MH_OPT_ARG, "number"},
{ "length", MH_OPT_ARG, "number"},
{ "moreproc", MH_OPT_ARG, "program"},
{ "nomoreproc" },
{ NULL }
};
......
......@@ -89,20 +89,20 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"file", 2, 0, "filename"},
{"list", 1, MH_OPT_BOOL, NULL},
{"headers", 1, MH_OPT_BOOL, NULL},
{"realsize", 1, MH_OPT_BOOL, NULL},
{"show", 2, MH_OPT_BOOL, NULL},
{"serialonly", 2, MH_OPT_BOOL, NULL},
{"form", 2, 0, "formfile"},
{"pause", 3, MH_OPT_BOOL, NULL},
{"store", 1, MH_OPT_BOOL, NULL},
{"auto", 1, MH_OPT_BOOL, NULL},
{"part", 3, 0, "part"},
{"type", 1, 0, "type"},
{"verbose", 1, MH_OPT_BOOL, NULL},
{NULL}
{ "file", MH_OPT_ARG, "filename" },
{ "list", MH_OPT_BOOL },
{ "headers", MH_OPT_BOOL },
{ "realsize", MH_OPT_BOOL },
{ "show", MH_OPT_BOOL },
{ "serialonly", MH_OPT_BOOL },
{ "form", MH_OPT_ARG, "formfile" },
{ "pause", MH_OPT_BOOL },
{ "store", MH_OPT_BOOL },
{ "auto", MH_OPT_BOOL },
{ "part", MH_OPT_ARG, "part" },
{ "type", MH_OPT_ARG, "type" },
{ "verbose", MH_OPT_BOOL },
{ NULL }
};
typedef struct _msg_part *msg_part_t;
......
......@@ -34,9 +34,9 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{ "all", 1, 0 },
{ "component", 1, MH_OPT_BOOL},
{ 0 }
{ "all" },
{ "component", MH_OPT_BOOL },
{ NULL }
};
static int display_all;
......
......@@ -32,7 +32,7 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{ 0 }
{ NULL }
};
static error_t
......
......@@ -102,28 +102,28 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"component", 1, 0, "field" },
{"pattern", 1, 0, "pattern" },
{"search", 1, 0, "pattern" },
{"cc", 1, 0, "pattern" },
{"date", 1, 0, "pattern" },
{"from", 1, 0, "pattern" },
{"subject", 1, 0, "pattern" },
{"to", 1, 0, "pattern" },
{"datefield", 1, 0, "field" },
{"after", 1, 0, "date" },
{"before", 1, 0, "date"},
{"and", 1, 0, NULL },
{"or", 1, 0, NULL },
{"not", 1, 0, NULL },
{"lbrace", 1, 0, NULL },
{"rbrace", 1, 0, NULL },
{"list", 1, MH_OPT_BOOL, },
{"sequence", 1, 0, NULL },
{"public", 1, MH_OPT_BOOL },
{"zero", 1, MH_OPT_BOOL },
{NULL}
{ "component", MH_OPT_ARG, "field" },
{ "pattern", MH_OPT_ARG, "pattern" },
{ "search", MH_OPT_ARG, "pattern" },
{ "cc", MH_OPT_ARG, "pattern" },
{ "date", MH_OPT_ARG, "pattern" },
{ "from", MH_OPT_ARG, "pattern" },
{ "subject", MH_OPT_ARG, "pattern" },
{ "to", MH_OPT_ARG, "pattern" },
{ "datefield", MH_OPT_ARG, "field" },
{ "after", MH_OPT_ARG, "date" },
{ "before", MH_OPT_ARG, "date" },
{ "and" },
{ "or" },
{ "not" },
{ "lbrace" },
{ "rbrace" },
{ "list", MH_OPT_BOOL },
{ "sequence", MH_OPT_ARG, "name" },
{ "public", MH_OPT_BOOL },
{ "zero", MH_OPT_BOOL },
{ NULL }
};
static int list = 1;
......
......@@ -49,12 +49,12 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"file", 2, 0, "input-file"},
{"draft", 1, 0, NULL },
{"link", 1, MH_OPT_BOOL, NULL },
{"preserve", 1, MH_OPT_BOOL, NULL },
{"src", 1, 0, "+folder" },
{ 0 }
{ "file", MH_OPT_ARG, "input-file"},
{ "draft" },
{ "link", MH_OPT_BOOL },
{ "preserve", MH_OPT_BOOL },
{ "src", MH_OPT_ARG, "folder" },
{ NULL }
};
int link_flag = 0;
......
......@@ -70,26 +70,26 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"annotate", 1, MH_OPT_BOOL },
{"build", 1, },
{"cc", 1, MH_OPT_ARG, "all/to/cc/me"},
{"nocc", 3, MH_OPT_ARG, "all/to/cc/me"},
{"form", 4, MH_OPT_ARG, "formatfile"},
{"width", 1, MH_OPT_ARG, "number"},
{"draftfolder", 6, MH_OPT_ARG, "folder"},
{"nodraftfolder", 3 },
{"draftmessage", 6, },
{"editor", 1, MH_OPT_ARG, "program"},
{"noedit", 3, },
{"fcc", 1, MH_OPT_ARG, "folder"},
{"filter", 2, MH_OPT_ARG, "program"},
{"format", 2, MH_OPT_BOOL },
{"group", 1, MH_OPT_BOOL },
{"inplace", 1, MH_OPT_BOOL },
{"query", 1, MH_OPT_BOOL },
{"whatnowproc", 2, MH_OPT_ARG, "program"},
{"nowhatnowproc", 3 },
{ 0 }
{ "annotate", MH_OPT_BOOL },
{ "build" },
{ "cc", MH_OPT_ARG, "all/to/cc/me"},
{ "nocc", MH_OPT_ARG, "all/to/cc/me"},
{ "form", MH_OPT_ARG, "formatfile"},
{ "width", MH_OPT_ARG, "number"},
{ "draftfolder", MH_OPT_ARG, "folder"},
{ "nodraftfolder" },
{ "draftmessage" },
{ "editor", MH_OPT_ARG, "program"},
{ "noedit" },
{ "fcc", MH_OPT_ARG, "folder"},
{ "filter", MH_OPT_ARG, "program"},
{ "format", MH_OPT_BOOL },
{ "group", MH_OPT_BOOL },
{ "inplace", MH_OPT_BOOL },
{ "query", MH_OPT_BOOL },
{ "whatnowproc", MH_OPT_ARG, "program"},
{ "nowhatnowproc" },
{ NULL }
};
static char default_format_str[] =
......
......@@ -47,7 +47,7 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"interactive", 1, MH_OPT_BOOL, NULL},
{ "interactive", MH_OPT_BOOL },
{ 0 }
};
......
......@@ -32,7 +32,7 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{ 0 }
{ NULL }
};
static error_t
......
......@@ -56,14 +56,14 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"clear", 1, MH_OPT_BOOL},
{"form", 4, MH_OPT_ARG, "formatfile"},
{"format", 5, MH_OPT_ARG, "string"},
{"header", 3, MH_OPT_BOOL},
{"width", 1, MH_OPT_ARG, "number"},
{"reverse", 1, MH_OPT_BOOL},
{"file", 4, MH_OPT_ARG, "file"},
{ 0 }
{ "clear", MH_OPT_BOOL },
{ "form", MH_OPT_ARG, "formatfile" },
{ "format", MH_OPT_ARG, "string" },
{ "header", MH_OPT_BOOL },
{ "width", MH_OPT_ARG, "number" },
{ "reverse", MH_OPT_BOOL },
{ "file", MH_OPT_ARG, "file" },
{ NULL }
};
static int clear;
......
......@@ -79,25 +79,25 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"alias", 1, 0, "aliasfile" },
{"draft", 5, 0, NULL },
{"draftfolder", 6, 0, "folder" },
{"draftmessage", 6, 0, "message"},
{"nodraftfolder", 3, 0, NULL },
{"filter", 2, 0, "filterfile"},
{"nofilter", 3, 0, NULL },
{"format", 4, MH_OPT_BOOL, NULL},
{"forward", 4, MH_OPT_BOOL, NULL},
{"mime", 2, MH_OPT_BOOL, NULL},
{"msgid", 2, MH_OPT_BOOL, NULL},
{"push", 2, MH_OPT_BOOL, NULL},
{"preserve", 2, MH_OPT_BOOL, NULL},
{"keep", 1, MH_OPT_BOOL, NULL},
{"split", 1, 0, "seconds"},
{"verbose", 1, MH_OPT_BOOL, NULL},
{"watch", 2, MH_OPT_BOOL, NULL},
{"width", 2, 0, NULL },
{ 0 }
{ "alias", MH_OPT_ARG, "aliasfile" },
{ "draft" },
{ "draftfolder", MH_OPT_ARG, "folder" },
{ "draftmessage", MH_OPT_ARG, "message" },
{ "nodraftfolder" },
{ "filter", MH_OPT_ARG, "filterfile" },
{ "nofilter" },
{ "format", MH_OPT_BOOL },
{ "forward", MH_OPT_BOOL },
{ "mime", MH_OPT_BOOL },
{ "msgid", MH_OPT_BOOL },
{ "push", MH_OPT_BOOL },
{ "preserve", MH_OPT_BOOL },
{ "keep", MH_OPT_BOOL },
{ "split", MH_OPT_ARG, "seconds" },
{ "verbose", MH_OPT_BOOL },
{ "watch", MH_OPT_BOOL },
{ "width" },
{ NULL }
};
static int use_draft; /* Use the prepared draft */
......
......@@ -78,13 +78,13 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"datefield", 1, 0, "field" },
{"nodatefield", 3, 0, 0 },
{"textfield", 1, 0, "field" },
{"notextfield", 3, 0, 0 },
{"limit", 1, 0, "days" },
{"nolimit", 3, 0, 0 },
{"verbose", 1, MH_OPT_BOOL, NULL},
{ "datefield", MH_OPT_ARG, "field" },
{ "nodatefield" },
{ "textfield", MH_OPT_ARG, "field" },
{ "notextfield" },
{ "limit", MH_OPT_ARG, "days" },
{ "nolimit" },
{ "verbose", MH_OPT_BOOL },
{ NULL },
};
......
......@@ -38,13 +38,13 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"draftfolder", 6, MH_OPT_ARG, "folder"},
{"nodraftfolder", 3, },
{"draftmessage", 6, },
{"editor", 1, MH_OPT_ARG, "program"},
{"noedit", 3, },
{"prompt", 1 },
{ 0 }
{ "draftfolder", MH_OPT_ARG, "folder" },
{ "nodraftfolder" },
{ "draftmessage" },
{ "editor", MH_OPT_ARG, "program" },
{ "noedit" },
{ "prompt" },
{ NULL }
};
struct mh_whatnow_env wh_env = { 0 };
......
......@@ -42,12 +42,12 @@ static struct argp_option options[] = {
/* Traditional MH options */
struct mh_option mh_option[] = {
{"alias", 1, 0, "aliasfile" },
{"draft", 5, 0, NULL },
{"draftfolder", 6, 0, "folder" },
{"draftmessage", 6, 0, "message"},
{"nodraftfolder", 3, 0, NULL },
{"check", 1, MH_OPT_BOOL, NULL},
{ "alias", MH_OPT_ARG, "aliasfile" },
{ "draft" },
{ "draftfolder", MH_OPT_ARG, "folder" },
{ "draftmessage", MH_OPT_ARG, "message" },
{ "nodraftfolder" },
{ "check", MH_OPT_BOOL },
{NULL}
};
......