summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-07-20 19:56:14 +0300
committerSergey Poznyakoff <gray@gnu.org>2020-07-20 19:56:14 +0300
commit5f4189763ed01c32035701c0c198181456b1f3c3 (patch)
tree5ae2423d7241311b1fd0f5d488865d9f27fccf60
parent81d07acbbfbc7ebb897edef9aa7c1b2f24272ae4 (diff)
downloadmailutils-5f4189763ed01c32035701c0c198181456b1f3c3.tar.gz
mailutils-5f4189763ed01c32035701c0c198181456b1f3c3.tar.bz2
New simplified interface to command line option parser.
* include/mailutils/cli.h (MU_CLI_OPTION_): New constants. (mu_cli_simple): New proto. * libmailutils/cli/simple.c: New file. * libmailutils/cli/Makefile.am: Add new source. * libmailutils/cli/cli.c (mu_cli_ext): Take into account po_special_flags in hints. Honor MU_PARSEOPT_HELP_HOOK and MU_PARSEOPT_EXIT_ERROR set in hints. * libmailutils/opt/opt.c (parseopt_init): Fix improper use of MU_PARSEOPT_PACKAGE_URL instead of MU_PARSEOPT_DATA.
-rw-r--r--include/mailutils/cli.h219
-rw-r--r--libmailutils/cli/Makefile.am1
-rw-r--r--libmailutils/cli/cli.c27
-rw-r--r--libmailutils/cli/simple.c226
-rw-r--r--libmailutils/opt/opt.c2
5 files changed, 469 insertions, 6 deletions
diff --git a/include/mailutils/cli.h b/include/mailutils/cli.h
index 06c864464..9d2afc806 100644
--- a/include/mailutils/cli.h
+++ b/include/mailutils/cli.h
@@ -74,5 +74,224 @@ void mu_cli_ext (int argc, char **argv,
char *mu_site_config_file (void);
void mu_acl_cfg_init (void);
+
+/* Simplified interface */
+enum
+ {
+ MU_CLI_OPTION_END = -1, /* End of options */
+
+ /* Argument: struct mu_option *
+ * Description: Supplies the array of options. Can be given mupliple
+ * times.
+ * Ref: optv in struct mu_cli_setup.
+ */
+ MU_CLI_OPTION_OPTIONS,
+
+ /* Argument: struct mu_cfg_param *
+ * Description: Supplies configuration definitions.
+ * Ref: cfg in struct mu_cli_setup
+ */
+ MU_CLI_OPTION_CONFIG,
+
+ /* Argument: char **
+ * Description: NULL-terminated array of capability strings.
+ * Ref: capa argument to mu_cli and mu_cli_ext.
+ */
+ MU_CLI_OPTION_CAPABILITIES,
+
+ /* Argument: int
+ * Description: Exit code to use on usage errors (default: EX_USAGE).
+ * Ref: ex_usage member of struct mu_cli_setup.
+ */
+ MU_CLI_OPTION_EX_USAGE,
+
+ /* Argument: int
+ * Description: Exit code to use on configuration errors (default:
+ * EX_CONFIG).
+ * Ref: ex_config member of struct mu_cli_setup.
+ */
+ MU_CLI_OPTION_EX_CONFIG,
+
+ /* Argument: none
+ * Description: Ignore usage errors.
+ * Ref: MU_PARSEOPT_IGNORE_ERRORS flag in opt.h
+ */
+ MU_CLI_OPTION_IGNORE_ERRORS,
+
+ /* Argument: int *
+ * Description: A pointer to store the number of command line
+ * arguments in.
+ * Ref: ret_argc argument in mu_cli and mu_cli_ext.
+ */
+ MU_CLI_OPTION_RETURN_ARGC,
+
+ /* Argument: char ***
+ * Description: A pointer to store the address of the array of
+ * command line arguments.
+ * Ref: ret_argv argument in mu_cli and mu_cli_ext.
+ */
+ MU_CLI_OPTION_RETURN_ARGV,
+
+ /* Argument: none
+ * Description: Do not reorder options and arguments.
+ * Ref: The inorder member of struct mu_cli_setup and
+ * MU_PARSEOPT_IN_ORDER flag in opt.h
+ */
+ MU_CLI_OPTION_IN_ORDER,
+
+ /* Argument: none
+ * Description: Don't provide standard options: -h, --help, --usage,
+ * --version.
+ * Ref: MU_PARSEOPT_NO_STDOPT flag in opt.h
+ */
+ MU_CLI_OPTION_NO_STDOPT,
+
+ /* Argument: none
+ * Description: Don't exit on errors
+ * Ref: MU_PARSEOPT_NO_ERREXIT flag in opt.h
+ */
+ MU_CLI_OPTION_NO_ERREXIT,
+
+ /* Argument: none
+ * Description: Apply all options immediately.
+ * Ref: MU_PARSEOPT_IMMEDIATE
+ */
+ MU_CLI_OPTION_IMMEDIATE,
+
+ /* Argument: none
+ * Description: Don't sort options in help output.
+ * Ref: MU_PARSEOPT_NO_SORT flag in opt.h.
+ */
+ MU_CLI_OPTION_NO_SORT,
+
+ /* Argument: char const *
+ * Description: Override the name of the program to use in error
+ * messages.
+ * Ref: MU_PARSEOPT_PROG_NAME flag in opt.h
+ */
+ MU_CLI_OPTION_PROG_NAME,
+
+ /* Argument: char const *
+ * Description: Documentation string for the program. It will be
+ * displayed on the line following the usage summary.
+ * Ref: MU_PARSEOPT_PROG_DOC
+ */
+ MU_CLI_OPTION_PROG_DOC,
+
+ /* Argument: char const *
+ * Description: Names of arguments for the program. These are
+ * displayed in the constructed usage summary. For example, if
+ * this keyword is set tp "A B" and the program name is "foo", then
+ * the help output will begin with
+ * Usage: foo A B
+ *
+ * Multiple instances are allowed.
+ * Ref: MU_PARSEOPT_PROG_ARGS flag in opt.h
+ */
+ MU_CLI_OPTION_PROG_ARGS,
+
+ /* Argument: char const *
+ * Description: Bug address for the package.
+ * Ref: MU_PARSEOPT_BUG_ADDRESS in opt.h
+ */
+ MU_CLI_OPTION_BUG_ADDRESS,
+
+ /* Argument: char const *
+ * Description: Sets the PACKAGE_NAME.
+ * Ref: MU_PARSEOPT_PACKAGE_NAME in opt.h
+ */
+ MU_CLI_OPTION_PACKAGE_NAME,
+
+ /* Argument: char const *
+ * Description: URL of the package.
+ * Ref: MU_PARSEOPT_PACKAGE_URL in opt.h
+ */
+ MU_CLI_OPTION_PACKAGE_URL,
+
+ /* Argument: char const *
+ * Description: Extra help information. This will be displayed after
+ * the option list.
+ * Ref: MU_PARSEOPT_EXTRA_INFO in opt.h
+ */
+ MU_CLI_OPTION_EXTRA_INFO,
+
+ /* Argument: void (*) (struct mu_parseopt *, mu_stream_t)
+ * Description: Pointer to a function to be called as a part of the
+ * --help option handling, after outputting the option list.
+ * Ref: po_help_hook member of struct mu_parseopt and the
+ * MU_PARSEOPT_HELP_HOOK flag in opt.h
+ */
+ MU_CLI_OPTION_HELP_HOOK,
+
+ /* Argument: void *
+ * Description: Call-specific configuration data. This will be passed
+ * as the last argument to mu_cfg_tree_reduce.
+ *
+ * Ref: mu_cfg_tree_reduce
+ */
+ MU_CLI_OPTION_DATA,
+
+ /* Argument: void (*) (struct mu_parseopt *, mu_stream_t)
+ * Description: User function to be called on --version.
+ * Ref: po_version_hook member of struct mu_parseopt and the
+ * MU_PARSEOPT_VERSION_HOOK flag in opt.h
+ */
+ MU_CLI_OPTION_VERSION_HOOK,
+
+ /* Argument: void (*) (struct mu_parseopt *, mu_stream_t)
+ * Description: Pointer to a function to be called as a part of the
+ * --help option handling. This function will be called after printing
+ * initial program description (see MU_CLI_OPTION_PROG_DOC) and before
+ * printing the option summary.
+ * Ref:
+ */
+ MU_CLI_OPTION_PROG_DOC_HOOK,
+
+ /* Argument: none
+ * Description: Long options start with single dash (a la find). Thid
+ * Disables recognition of traditional short options.
+ * Ref: MU_PARSEOPT_SINGLE_DASH flag in opt.h
+ */
+ MU_CLI_OPTION_SINGLE_DASH,
+
+ /* Argument: char const *
+ * Description: Prefix that negates the value of a boolean option.
+ * Ref: po_negation member of struct mu_parseopt and the
+ * MU_PARSEOPT_NEGATION flag in opt.h
+ */
+ MU_CLI_OPTION_NEGATION,
+
+ /* Argument: char const *
+ * Description: Descriptive names of special arguments. If given, this
+ * will be printed in short usage summary after the regular options.
+ * Ref: The po_special_args member of struct mu_parseopt and the
+ * MU_PARSEOPT_SPECIAL_ARGS flag in opt.h
+ */
+ MU_CLI_OPTION_SPECIAL_ARGS,
+
+
+ /* Argument: char const *
+ * Description: Name of site-wide configuration file to parse. If NULL,
+ * the default site-wide configuration is assumed.
+ * Ref: The site_file member of struct mu_cfg_parse_hints and the
+ * MU_CFHINT_SITE_FILE flag in cfg.h
+ */
+ MU_CLI_OPTION_CONF_SITE_FILE,
+
+ /* Argument: none
+ * Description: Enable the use of per-user configuration files.
+ * Ref: MU_CFHINT_PER_USER_FILE flag in cfg.h
+ */
+ MU_CLI_OPTION_CONF_PER_USER_FILE,
+
+ /* Argument: none
+ * Description: Don't allow users to overide configuration settings
+ * from the command line.
+ * Ref: MU_CFHINT_NO_CONFIG_OVERRIDE flag in cfg.h
+ */
+ MU_CLI_OPTION_CONF_NO_OVERRIDE
+ };
+
+void mu_cli_simple (int argc, char **argv, ...);
#endif
diff --git a/libmailutils/cli/Makefile.am b/libmailutils/cli/Makefile.am
index d600c1ae2..17b2384ef 100644
--- a/libmailutils/cli/Makefile.am
+++ b/libmailutils/cli/Makefile.am
@@ -21,6 +21,7 @@ libcli_la_SOURCES = \
acl.c\
capa.c\
cli.c\
+ simple.c\
stdcapa.c
AM_CPPFLAGS = \
diff --git a/libmailutils/cli/cli.c b/libmailutils/cli/cli.c
index a4c54edf8..e048995f6 100644
--- a/libmailutils/cli/cli.c
+++ b/libmailutils/cli/cli.c
@@ -488,7 +488,8 @@ run_commit (void *item, void *data)
| MU_PARSEOPT_EXTRA_INFO \
| MU_PARSEOPT_VERSION_HOOK \
| MU_PARSEOPT_PROG_NAME \
- | MU_PARSEOPT_NEGATION)
+ | MU_PARSEOPT_NEGATION \
+ | MU_PARSEOPT_SPECIAL_ARGS )
void
mu_cli_ext (int argc, char **argv,
@@ -591,7 +592,12 @@ mu_cli_ext (int argc, char **argv,
po.po_help_hook = extra_help_hook;
flags |= MU_PARSEOPT_HELP_HOOK;
}
-
+ else if (pohint->po_flags & MU_PARSEOPT_HELP_HOOK)
+ {
+ po.po_help_hook = pohint->po_help_hook;
+ flags |= MU_PARSEOPT_HELP_HOOK;
+ }
+
if (setup->prog_doc_hook)
{
po.po_prog_doc_hook = prog_doc_hook;
@@ -622,7 +628,20 @@ mu_cli_ext (int argc, char **argv,
po.po_negation = pohint->po_negation;
if (flags & MU_PARSEOPT_PROG_NAME)
po.po_prog_name = pohint->po_prog_name;
-
+ if (flags & MU_PARSEOPT_SPECIAL_ARGS)
+ po.po_special_args = pohint->po_special_args;
+
+ if (setup->ex_usage)
+ {
+ po.po_exit_error = setup->ex_usage;
+ flags |= MU_PARSEOPT_EXIT_ERROR;
+ }
+ else if (pohint->po_flags & MU_PARSEOPT_EXIT_ERROR)
+ {
+ po.po_exit_error = pohint->po_exit_error;
+ flags |= MU_PARSEOPT_EXIT_ERROR;
+ }
+
appd.setup = setup;
appd.hints = &hints;
appd.append_tree = NULL;
@@ -630,8 +649,6 @@ mu_cli_ext (int argc, char **argv,
po.po_data = &appd;
flags |= MU_PARSEOPT_DATA;
- po.po_exit_error = setup->ex_usage;
-
mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
optv = init_options (pool, capa, setup, &hints, &com_list);
diff --git a/libmailutils/cli/simple.c b/libmailutils/cli/simple.c
new file mode 100644
index 000000000..0daef170d
--- /dev/null
+++ b/libmailutils/cli/simple.c
@@ -0,0 +1,226 @@
+/* cli.c -- Command line interface for GNU Mailutils
+ Copyright (C) 2016-2020 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or (at
+ your option) any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <mailutils/cfg.h>
+#include <mailutils/opt.h>
+#include <mailutils/cli.h>
+#include <mailutils/nls.h>
+
+void
+mu_cli_simple (int argc, char **argv, ...)
+{
+ struct mu_cli_setup setup;
+ struct mu_parseopt pohint;
+ struct mu_cfg_parse_hints cfhint;
+ char **capa = NULL;
+ void *data = NULL;
+ int *ret_argc = NULL;
+ char ***ret_argv = NULL;
+
+ mu_opool_t args_pool = NULL, optv_pool = NULL;
+
+ va_list ap;
+ int opt;
+
+ memset (&setup, 0, sizeof (setup));
+ memset (&pohint, 0, sizeof (pohint));
+ memset (&cfhint, 0, sizeof (cfhint));
+
+ va_start (ap, argv);
+ while ((opt = va_arg (ap, int)) != MU_CLI_OPTION_END)
+ {
+ switch (opt)
+ {
+ case MU_CLI_OPTION_OPTIONS:
+ {
+ struct mu_option *p;
+ if (!optv_pool)
+ mu_opool_create (&optv_pool, MU_OPOOL_ENOMEMABRT);
+ p = va_arg (ap, struct mu_option *);
+ mu_opool_append (optv_pool, &p, sizeof p);
+ }
+ break;
+
+ case MU_CLI_OPTION_CONFIG:
+ setup.cfg = va_arg (ap, struct mu_cfg_param *);
+ break;
+
+ case MU_CLI_OPTION_CAPABILITIES:
+ capa = va_arg (ap, char **);
+ break;
+
+ case MU_CLI_OPTION_EX_USAGE:
+ setup.ex_usage = va_arg (ap, int);
+ break;
+
+ case MU_CLI_OPTION_EX_CONFIG:
+ setup.ex_config = va_arg (ap, int);
+ break;
+
+ case MU_CLI_OPTION_DATA:
+ data = va_arg (ap, void *);
+ break;
+
+ case MU_CLI_OPTION_IN_ORDER:
+ setup.inorder = 1;
+ break;
+
+ case MU_CLI_OPTION_RETURN_ARGC:
+ ret_argc = va_arg (ap, int *);
+ break;
+
+ case MU_CLI_OPTION_RETURN_ARGV:
+ ret_argv = va_arg (ap, char ***);
+ break;
+
+ case MU_CLI_OPTION_IGNORE_ERRORS:
+ pohint.po_flags |= MU_PARSEOPT_IGNORE_ERRORS;
+ break;
+
+ case MU_CLI_OPTION_NO_STDOPT:
+ pohint.po_flags |= MU_PARSEOPT_NO_STDOPT;
+ break;
+
+ case MU_CLI_OPTION_NO_ERREXIT:
+ pohint.po_flags |= MU_PARSEOPT_NO_ERREXIT;
+ break;
+
+ case MU_CLI_OPTION_IMMEDIATE:
+ pohint.po_flags |= MU_PARSEOPT_IMMEDIATE;
+ break;
+
+ case MU_CLI_OPTION_NO_SORT:
+ pohint.po_flags |= MU_PARSEOPT_NO_SORT;
+ break;
+
+ case MU_CLI_OPTION_SINGLE_DASH:
+ pohint.po_flags |= MU_PARSEOPT_SINGLE_DASH;
+ break;
+
+ case MU_CLI_OPTION_PROG_NAME:
+ pohint.po_flags |= MU_PARSEOPT_PROG_NAME;
+ pohint.po_prog_name = va_arg (ap, char *);
+ break;
+
+ case MU_CLI_OPTION_PROG_DOC:
+ pohint.po_flags |= MU_PARSEOPT_PROG_DOC;
+ pohint.po_prog_doc = va_arg (ap, char *);
+ break;
+
+ case MU_CLI_OPTION_PROG_ARGS:
+ {
+ char *p;
+ if (!args_pool)
+ mu_opool_create (&args_pool, MU_OPOOL_ENOMEMABRT);
+ p = va_arg (ap, char *);
+ mu_opool_append (args_pool, &p, sizeof p);
+ }
+ break;
+
+ case MU_CLI_OPTION_BUG_ADDRESS:
+ pohint.po_flags |= MU_PARSEOPT_BUG_ADDRESS;
+ pohint.po_bug_address = va_arg (ap, char *);
+ break;
+
+ case MU_CLI_OPTION_PACKAGE_NAME:
+ pohint.po_flags |= MU_PARSEOPT_PACKAGE_NAME;
+ pohint.po_package_name = va_arg (ap, char *);
+ break;
+
+ case MU_CLI_OPTION_PACKAGE_URL:
+ pohint.po_flags |= MU_PARSEOPT_PACKAGE_URL;
+ pohint.po_package_url = va_arg (ap, char *);
+ break;
+
+ case MU_CLI_OPTION_EXTRA_INFO:
+ pohint.po_flags |= MU_PARSEOPT_EXTRA_INFO;
+ pohint.po_extra_info = va_arg (ap, char *);
+ break;
+
+ case MU_CLI_OPTION_HELP_HOOK:
+ pohint.po_flags |= MU_PARSEOPT_HELP_HOOK;
+ pohint.po_help_hook =
+ va_arg (ap, void (*) (struct mu_parseopt *, mu_stream_t));
+ break;
+
+ case MU_CLI_OPTION_VERSION_HOOK:
+ pohint.po_flags |= MU_PARSEOPT_VERSION_HOOK;
+ pohint.po_version_hook =
+ va_arg (ap, void (*) (struct mu_parseopt *, mu_stream_t));
+ break;
+
+ case MU_CLI_OPTION_PROG_DOC_HOOK:
+ pohint.po_flags |= MU_PARSEOPT_PROG_DOC_HOOK;
+ pohint.po_prog_doc_hook =
+ va_arg (ap, void (*) (struct mu_parseopt *, mu_stream_t));
+ break;
+
+ case MU_CLI_OPTION_NEGATION:
+ pohint.po_flags |= MU_PARSEOPT_NEGATION;
+ pohint.po_negation = va_arg (ap, char *);
+ break;
+
+ case MU_CLI_OPTION_SPECIAL_ARGS:
+ pohint.po_flags |= MU_PARSEOPT_SPECIAL_ARGS;
+ pohint.po_special_args = va_arg (ap, char *);
+ break;
+
+ case MU_CLI_OPTION_CONF_SITE_FILE:
+ if ((cfhint.site_file = va_arg (ap, char *)) == NULL)
+ cfhint.site_file = mu_site_config_file ();
+ cfhint.flags = MU_CFHINT_SITE_FILE;
+ break;
+
+ case MU_CLI_OPTION_CONF_PER_USER_FILE:
+ cfhint.flags |= MU_CFHINT_PER_USER_FILE;
+ break;
+
+ case MU_CLI_OPTION_CONF_NO_OVERRIDE:
+ cfhint.flags |= MU_CFHINT_NO_CONFIG_OVERRIDE;
+ break;
+
+ default:
+ mu_diag_output (MU_DIAG_CRIT,
+ _("%s:%d: INTERNAL ERROR: unrecognized mu_cli_simple option"),
+ __FILE__, __LINE__);
+ abort ();
+ }
+ }
+ if (optv_pool)
+ {
+ struct mu_option *p = NULL;
+ mu_opool_append (optv_pool, &p, sizeof p);
+ setup.optv = mu_opool_finish (optv_pool, NULL);
+ }
+ if (args_pool)
+ {
+ char *p = NULL;
+ mu_opool_append (args_pool, &p, sizeof p);
+ pohint.po_prog_args = mu_opool_finish (args_pool, NULL);
+ pohint.po_flags |= MU_PARSEOPT_PROG_ARGS;
+ }
+ mu_cli_ext (argc, argv, &setup, &pohint, &cfhint, capa, data,
+ ret_argc, ret_argv);
+ mu_opool_destroy (&args_pool);
+ mu_opool_destroy (&optv_pool);
+ va_end (ap);
+}
diff --git a/libmailutils/opt/opt.c b/libmailutils/opt/opt.c
index ab598bbbf..8f5be3b9b 100644
--- a/libmailutils/opt/opt.c
+++ b/libmailutils/opt/opt.c
@@ -659,7 +659,7 @@ parseopt_init (struct mu_parseopt *po, struct mu_option **options,
po->po_package_name = NULL;
if (!(flags & MU_PARSEOPT_PACKAGE_URL))
po->po_package_url = NULL;
- if (!(flags & MU_PARSEOPT_PACKAGE_URL))
+ if (!(flags & MU_PARSEOPT_DATA))
po->po_data = NULL;
if (!(flags & MU_PARSEOPT_EXTRA_INFO))
po->po_extra_info = NULL;

Return to:

Send suggestions and report system problems to the System administrator.