/* opt.h -- general-purpose command line option parser
Copyright (C) 2016-2025 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 .
*/
#ifndef _MAILUTILS_OPT_H
#define _MAILUTILS_OPT_H
#include
#include
#include
#include
#include
extern char *mu_program_name;
extern char *mu_full_program_name;
void mu_set_program_name (char const *arg);
#define MU_OPTION_DEFAULT 0
#define MU_OPTION_ARG_OPTIONAL 0x01
#define MU_OPTION_HIDDEN 0x02
#define MU_OPTION_ALIAS 0x04
#define MU_OPTION_IMMEDIATE 0x08
struct mu_parseopt;
struct mu_option
{
char *opt_long; /* Long option name */
int opt_short; /* Short option character */
char *opt_arg; /* Argument name */
int opt_flags; /* Flags (see above) */
char *opt_doc; /* Human-readable documentation */
mu_c_type_t opt_type; /* Option type */
void *opt_ptr; /* Data pointer */
void (*opt_set) (struct mu_parseopt *, struct mu_option *, char const *);
/* Function to set the option */
char const *opt_default;/* Default value */
};
#define MU_OPTION_GROUP(text) { NULL, 0, NULL, 0, text }
#define MU_OPTION_END { NULL, 0, NULL, 0, NULL }
#define MU_OPTION_IS_END(opt) \
(!(opt)->opt_long && !(opt)->opt_short && !(opt)->opt_doc)
#define MU_OPTION_IS_OPTION(opt) \
((opt)->opt_short || (opt)->opt_long)
#define MU_OPTION_IS_GROUP_HEADER(opt) \
(!MU_OPTION_IS_OPTION(opt) && (opt)->opt_doc)
#define MU_OPTION_IS_VALID_SHORT_OPTION(opt) \
((opt)->opt_short > 0 && (opt)->opt_short < 127 && \
(mu_isalnum ((opt)->opt_short) || ((opt)->opt_short == '?')))
#define MU_OPTION_IS_VALID_LONG_OPTION(opt) \
((opt)->opt_long != NULL)
typedef struct mu_option_cache *mu_option_cache_ptr_t;
struct mu_option_cache
{
struct mu_option *cache_opt;
char const *cache_arg;
};
#define MU_PARSEOPT_DEFAULT 0
/* Don't ignore the first element of ARGV. By default it is the program
name */
#define MU_PARSEOPT_ARGV0 0x00000001
/* Ignore command line errors. */
#define MU_PARSEOPT_IGNORE_ERRORS 0x00000002
/* Don't order arguments so that options come first. */
#define MU_PARSEOPT_IN_ORDER 0x00000004
/* Don't provide standard options: -h, --help, --usage, --version */
#define MU_PARSEOPT_NO_STDOPT 0x00000008
/* Don't exit on errors */
#define MU_PARSEOPT_NO_ERREXIT 0x00000010
/* Apply all options immediately */
#define MU_PARSEOPT_IMMEDIATE 0x00000020
/* Don't sort options */
#define MU_PARSEOPT_NO_SORT 0x00001000
#define MU_PARSEOPT_PROG_NAME 0x00002000
#define MU_PARSEOPT_PROG_DOC 0x00004000
#define MU_PARSEOPT_PROG_ARGS 0x00008000
#define MU_PARSEOPT_BUG_ADDRESS 0x00010000
#define MU_PARSEOPT_PACKAGE_NAME 0x00020000
#define MU_PARSEOPT_PACKAGE_URL 0x00040000
#define MU_PARSEOPT_EXTRA_INFO 0x00080000
#define MU_PARSEOPT_EXIT_ERROR 0x00100000
#define MU_PARSEOPT_HELP_HOOK 0x00200000
#define MU_PARSEOPT_DATA 0x00400000
#define MU_PARSEOPT_VERSION_HOOK 0x00800000
#define MU_PARSEOPT_PROG_DOC_HOOK 0x01000000
/* Long options start with single dash. Disables recognition of traditional
short options */
#define MU_PARSEOPT_SINGLE_DASH 0x02000000
/* Negation prefix is set */
#define MU_PARSEOPT_NEGATION 0x04000000
/* po_special_args is set */
#define MU_PARSEOPT_SPECIAL_ARGS 0x08000000
/* Reuse mu_parseopt struct initialized previously */
#define MU_PARSEOPT_REUSE 0x80000000
/* Mask for immutable flag bits */
#define MU_PARSEOPT_IMMUTABLE_MASK 0xFFFFF000
struct mu_parseopt
{
/* Input data: */
int po_argc; /* Number of argiments */
char **po_argv; /* Array of arguments */
size_t po_optc; /* Number of elements in optv */
struct mu_option **po_optv; /* Array of ptrs to option structures */
int po_flags;
char *po_negation; /* Negation prefix for boolean options */
void *po_data; /* Call-specific data */
int po_exit_error; /* Exit on error with this code */
/* Informational: */
char const *po_prog_name;
char const *po_prog_doc;
char const **po_prog_args;
char const *po_special_args; /* Special option-like arguments */
char const *po_bug_address;
char const *po_package_name;
char const *po_package_url;
char const *po_extra_info;
void (*po_prog_doc_hook) (struct mu_parseopt *po, mu_stream_t stream);
void (*po_help_hook) (struct mu_parseopt *po, mu_stream_t stream);
void (*po_version_hook) (struct mu_parseopt *po, mu_stream_t stream);
/* Output data */
int po_ind; /* Index of the next option */
int po_opterr; /* Index of the element in po_argv that
caused last error, or -1 if no errors */
mu_list_t po_optlist;
/* Auxiliary data */
char *po_cur; /* Points to the next character */
int po_chr; /* Single-char option */
char *po_long_opt_start; /* Character sequence that starts
long option */
/* The following two keep the position of the first non-optional argument
and the number of contiguous non-optional arguments after it.
Obviously, the following holds true:
arg_start + arg_count == opt_ind
If permutation is not allowed (MU_OPTION_PARSE_IN_ORDER flag is set),
arg_count is always 0.
*/
int po_arg_start;
int po_arg_count;
unsigned po_permuted:1; /* Whether the arguments were permuted */
size_t po_longcnt; /* Number of long options */
size_t *po_longidx; /* Indices of long options in po_optv */
};
int mu_parseopt (struct mu_parseopt *p,
int argc, char **argv, struct mu_option **optv,
int flags);
void mu_parseopt_error (struct mu_parseopt *po, char const *fmt, ...);
int mu_parseopt_apply (struct mu_parseopt *p);
void mu_parseopt_free (struct mu_parseopt *p);
int mu_parseopt_help_stream_create (mu_stream_t *retstr,
struct mu_parseopt *po,
mu_stream_t outstr);
unsigned mu_parseopt_getcolumn (const char *name);
void mu_option_describe_options (mu_stream_t str, struct mu_parseopt *p);
void mu_program_help (struct mu_parseopt *p, mu_stream_t str);
void mu_program_usage (struct mu_parseopt *p, int optsummary, mu_stream_t str);
void mu_program_version (struct mu_parseopt *po, mu_stream_t str);
void mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt,
char const *arg);
int mu_option_possible_negation (struct mu_parseopt *po, struct mu_option *opt);
#endif