diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-10-21 17:48:26 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-10-21 17:57:59 +0300 |
commit | f434857b8318b05b7036025605ab18cdf3e7c238 (patch) | |
tree | 28223e6cc500a5f82f561ce0677d30a266ad8f8d /mh/mh_getopt.c | |
parent | 53eb68133eeede20c49445cd4ff58ad6e4becc07 (diff) | |
download | mailutils-f434857b8318b05b7036025605ab18cdf3e7c238.tar.gz mailutils-f434857b8318b05b7036025605ab18cdf3e7c238.tar.bz2 |
Begin rewriting MH to get rid of argp stuff.
MH utilities will use only single-dash long options.
* include/mailutils/opt.h (mu_option) <opt_default>: New member.
* libmailutils/opt/opt.c (find_long_option): Improve detection
of ambiguous options.
(mu_option_set_value): Use default value (opt_default), if
supplied.
* mh/mh_argp.c: Delete.
* mh/Makefile.am (libmh_a_SOURCES): Remove mh_argp.c
* mh/mh_getopt.c: Rewrite from scratch using mailutils/opt
* mh/mh_getopt.h: Likewise.
* mh/mh.h: Add missing includes
(mh_read_formfile, mh_alias_read): Change signatures.
* mh/mh_alias.l (mh_alias_read): Name is const
* mh/mh_init.c (mh_read_formfile): Name is const.
* mh/ali.c: Convert to mh_getopt.
* 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/scan.c: Likewise.
* mh/tests/burst.at: Don't use double-dash options
* mh/tests/folder.at: Likewise.
Diffstat (limited to 'mh/mh_getopt.c')
-rw-r--r-- | mh/mh_getopt.c | 335 |
1 files changed, 180 insertions, 155 deletions
diff --git a/mh/mh_getopt.c b/mh/mh_getopt.c index 217261fcb..b4d92fb19 100644 --- a/mh/mh_getopt.c +++ b/mh/mh_getopt.c @@ -15,8 +15,6 @@ You should have received a copy of the GNU General Public License along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ -/* Parse traditional MH options. */ - #ifdef HAVE_CONFIG_H # include <config.h> #endif @@ -24,197 +22,224 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <mh_getopt.h> +#include "mh.h" +#include <mailutils/stream.h> +#include <mailutils/wordsplit.h> #include <mailutils/io.h> -static int mh_optind = 1; -static char *mh_optarg; -static char *mh_optptr; - -void (*mh_help_hook) (); +struct getopt_data +{ + char *extra_doc; +}; -int -mh_getopt (int argc, char **argv, struct mh_option *mh_opt, const char *doc) +static void +mh_extra_help_hook (struct mu_parseopt *po, mu_stream_t stream) { - struct mh_option *p; - int optlen; - - if (mh_optind >= argc || argv[mh_optind] == NULL) - return EOF; - mh_optptr = argv[mh_optind]; + struct getopt_data *data = po->po_data; + mu_stream_printf (stream, "%s\n", _(data->extra_doc)); +} - if (mh_optptr[0] == '+') +static void +augment_argv (int *pargc, char ***pargv) +{ + int argc; + char **argv; + int i, j; + struct mu_wordsplit ws; + char const *val = mh_global_profile_get (mu_program_name, NULL); + + if (!val) + return; + + if (mu_wordsplit (val, &ws, MU_WRDSF_DEFFLAGS)) { - mh_optarg = mh_optptr + 1; - mh_optind++; - return '+'; + mu_error (_("cannot split line `%s': %s"), val, + mu_wordsplit_strerror (&ws)); + exit (1); } + + argc = *pargc + ws.ws_wordc; + argv = calloc (argc + 1, sizeof *argv); + if (!argv) + mh_err_memory (1); + + i = 0; + argv[i++] = (*pargv)[0]; + for (j = 0; j < ws.ws_wordc; i++, j++) + argv[i] = ws.ws_wordv[j]; + for (j = 1; i < argc; i++, j++) + argv[i] = (*pargv)[j]; + argv[i] = NULL; - if (mh_optptr[0] != '-' || mh_optptr[1] == '-') + ws.ws_wordc = 0; + mu_wordsplit_free (&ws); + + *pargc = argc; + *pargv = argv; +} + +static void +process_folder_arg (int *pargc, char **argv, struct mu_parseopt *po) +{ + int i, j; + int argc = *pargc; + struct mu_option *opt; + + /* Find folder option */ + for (i = 0; ; i++) { - mh_optind++; - return 0; + if (!po->po_optv[i]) + return; /* Nothing to do */ + if (MU_OPTION_IS_VALID_LONG_OPTION (po->po_optv[i]) + && strcmp (po->po_optv[i]->opt_long, "folder") == 0) + break; } - - if (strcmp (mh_optptr, "-version") == 0) - mu_asprintf (&argv[mh_optind], "--version"); - else + opt = po->po_optv[i]; + + for (i = j = 0; i < argc; i++) { - int negation = 0; - - optlen = strlen (mh_optptr+1); - for (p = mh_opt; p->opt; p++) + if (argv[i][0] == '+') { - if (p->match_len <= optlen - && memcmp (mh_optptr+1, p->opt, optlen) == 0) - break; - if (p->flags == MH_OPT_BOOL - && optlen > 2 - && memcmp (mh_optptr+1, "no", 2) == 0 - && strlen (p->opt) >= optlen-2 - && memcmp (mh_optptr+3, p->opt, optlen-2) == 0) - { - negation = 1; - break; - } - } - - if (p->opt) - { - char *longopt = p->opt; - switch (p->flags) - { - case MH_OPT_BOOL: - mh_optarg = negation ? "no" : "yes"; - mu_asprintf (&argv[mh_optind], "--%s=%s", longopt, mh_optarg); - break; - - case MH_OPT_ARG: - mu_asprintf (&argv[mh_optind], "--%s", longopt); - mh_optarg = argv[++mh_optind]; - break; - - default: - mu_asprintf (&argv[mh_optind], "--%s", longopt); - mh_optarg = NULL; - } - mh_optind++; - return 1; - } - else if (!strcmp (mh_optptr+1, "help")) - { - mh_help (mh_opt, doc); - exit (1); + opt->opt_set (po, opt, argv[i] + 1); } else - mh_optind++; + argv[j++] = argv[i]; } - return '?'; + argv[j] = NULL; + *pargc = j; } - -void -mh_argv_preproc (int argc, char **argv, struct mh_argp_data *data) + +static void +set_folder (struct mu_parseopt *po, struct mu_option *opt, char const *arg) { - mh_optind = 1; - while (mh_getopt (argc, argv, data->mh_option, data->doc) != EOF) - ; + mh_set_current_folder (arg); } +static struct mu_option folder_option[] = { + { "folder", 0, NULL, MU_OPTION_DEFAULT, + N_("set current folder"), + mu_c_string, NULL, set_folder }, + MU_OPTION_END +}; + void -mh_help (struct mh_option *mh_opt, const char *doc) +mh_getopt (int *pargc, char ***pargv, struct mu_option *options, + int mhflags, + char *argdoc, char *progdoc, char *extradoc) { - struct mh_option *p; + int argc = *pargc; + char **argv = *pargv; + struct mu_parseopt po; + struct mu_option *optv[3]; + struct getopt_data getopt_data; + char const *args[2]; + int flags = MU_PARSEOPT_SINGLE_DASH | MU_PARSEOPT_IMMEDIATE; + int i; + + po.po_negation = "no"; + flags |= MU_PARSEOPT_NEGATION; - printf (_("Compatibility syntax:\n")); - printf (_("%s [switches] %s\n"), mu_program_name, doc); - printf (_(" switches are:\n")); + if (argdoc) + { + args[0] = argdoc; + args[1] = NULL; + po.po_prog_args = args; + flags |= MU_PARSEOPT_PROG_ARGS; + } + if (progdoc) + { + po.po_prog_doc = progdoc; + flags |= MU_PARSEOPT_PROG_DOC; + } + + getopt_data.extra_doc = extradoc; + if (extradoc) + { + po.po_help_hook = mh_extra_help_hook; + flags |= MU_PARSEOPT_HELP_HOOK; + } + + po.po_data = &getopt_data; + flags |= MU_PARSEOPT_DATA; - for (p = mh_opt; p->opt; p++) + po.po_exit_error = 1; + flags |= MU_PARSEOPT_EXIT_ERROR; + + po.po_package_name = PACKAGE_NAME; + flags |= MU_PARSEOPT_PACKAGE_NAME; + + po.po_package_url = PACKAGE_URL; + flags |= MU_PARSEOPT_PACKAGE_URL; + + po.po_bug_address = PACKAGE_BUGREPORT; + flags |= MU_PARSEOPT_BUG_ADDRESS; + + //po.po_extra_info = gnu_general_help_url; + //flags |= MU_PARSEOPT_EXTRA_INFO; + + mu_set_program_name (argv[0]); + mh_init (); + augment_argv (&argc, &argv); + + i = 0; + if (mhflags & MH_GETOPT_DEFAULT_FOLDER) + optv[i++] = folder_option; + optv[i++] = options; + optv[i] = NULL; + + if (mu_parseopt (&po, argc, argv, optv, flags)) + exit (po.po_exit_error); + + argc -= po.po_arg_start; + argv += po.po_arg_start; + + process_folder_arg (&argc, argv, &po); + + if (!argdoc && argc) { - int len = strlen (p->opt); - - printf (" -"); - if (p->flags == MH_OPT_BOOL) - printf ("[no]"); - if (len > p->match_len) - printf ("(%*.*s)%s", - (int) p->match_len, (int) p->match_len, p->opt, - p->opt + p->match_len); - else - printf ("%s", p->opt); - - if (p->flags == MH_OPT_ARG) - printf (" %s", p->arg); - printf ("\n"); + mu_error (_("Extra arguments")); + exit (1); } - if (mh_help_hook) - mh_help_hook (); - printf (" -help\n"); - printf (" -version\n"); - printf (_("\nPlease use GNU long options instead.\n" - "Run %s --help for more info on these.\n"), - mu_program_name); + + *pargc = argc; + *pargv = argv; + + mh_init2 (); } - -static int -optcmp (const void *a, const void *b) +void +mh_opt_notimpl (struct mu_parseopt *po, struct mu_option *opt, char const *arg) { - struct mh_option const *opta = a, *optb = b; - return strcmp (opta->opt, optb->opt); + mu_error (_("option is not yet implemented: %s"), opt->opt_long); + exit (1); } void -mh_option_init (struct mh_option *opt) +mh_opt_notimpl_warning (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) { - 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++; - if (minlen <= strlen (opt[j].opt)) - opt[j].match_len = minlen; - if (minlen == sample_len) - break; - } - while (len >= minlen && memcmp (opt[j].opt, sample, minlen) == 0); - else if (opt[j].opt[0] == sample[0]) - opt[j].match_len = minlen; - else - break; - } - if (minlen <= sample_len) - opt[i].match_len = minlen; - } + mu_error (_("ignoring not implemented option %s"), opt->opt_long); } void -mh_opt_notimpl (const char *name) +mh_opt_clear_string (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) { - mu_error (_("option is not yet implemented: %s"), name); - exit (1); + char **sptr = opt->opt_ptr; + free (*sptr); + *sptr = NULL; +} + +void +mh_opt_find_file (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) +{ + mh_find_file (arg, opt->opt_ptr); } void -mh_opt_notimpl_warning (const char *name) +mh_opt_read_formfile (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) { - mu_error (_("ignoring not implemented option %s"), name); + mh_read_formfile (arg, opt->opt_ptr); } |