1 /* opt.h -- general-purpose command line option parser 2 Copyright (C) 2016-2021 Free Software Foundation, Inc. 3 4 GNU Mailutils is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License as 6 published by the Free Software Foundation; either version 3, or (at 7 your option) any later version. 8 9 GNU Mailutils is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef _MAILUTILS_OPT_H 19 #define _MAILUTILS_OPT_H 20 #include <stdio.h> 21 #include <mailutils/types.h> 22 #include <mailutils/list.h> 23 #include <mailutils/util.h> 24 #include <mailutils/cctype.h> 25 26 extern char *mu_program_name; 27 extern char *mu_full_program_name; 28 29 void mu_set_program_name (char const *arg); 30 31 #define MU_OPTION_DEFAULT 0 32 #define MU_OPTION_ARG_OPTIONAL 0x01 33 #define MU_OPTION_HIDDEN 0x02 34 #define MU_OPTION_ALIAS 0x04 35 #define MU_OPTION_IMMEDIATE 0x08 36 37 struct mu_parseopt; 38 39 struct mu_option 40 { 41 char *opt_long; /* Long option name */ 42 int opt_short; /* Short option character */ 43 char *opt_arg; /* Argument name */ 44 int opt_flags; /* Flags (see above) */ 45 char *opt_doc; /* Human-readable documentation */ 46 mu_c_type_t opt_type; /* Option type */ 47 void *opt_ptr; /* Data pointer */ 48 void (*opt_set) (struct mu_parseopt *, struct mu_option *, char const *); 49 /* Function to set the option */ 50 char const *opt_default;/* Default value */ 51 }; 52 53 #define MU_OPTION_GROUP(text) { NULL, 0, NULL, 0, text } 54 #define MU_OPTION_END { NULL, 0, NULL, 0, NULL } 55 56 #define MU_OPTION_IS_END(opt) \ 57 (!(opt)->opt_long && !(opt)->opt_short && !(opt)->opt_doc) 58 59 #define MU_OPTION_IS_OPTION(opt) \ 60 ((opt)->opt_short || (opt)->opt_long) 61 #define MU_OPTION_IS_GROUP_HEADER(opt) \ 62 (!MU_OPTION_IS_OPTION(opt) && (opt)->opt_doc) 63 #define MU_OPTION_IS_VALID_SHORT_OPTION(opt) \ 64 ((opt)->opt_short > 0 && (opt)->opt_short < 127 && \ 65 (mu_isalnum ((opt)->opt_short) || ((opt)->opt_short == '?'))) 66 #define MU_OPTION_IS_VALID_LONG_OPTION(opt) \ 67 ((opt)->opt_long != NULL) 68 69 typedef struct mu_option_cache *mu_option_cache_ptr_t; 70 71 struct mu_option_cache 72 { 73 struct mu_option *cache_opt; 74 char const *cache_arg; 75 }; 76 77 #define MU_PARSEOPT_DEFAULT 0 78 /* Don't ignore the first element of ARGV. By default it is the program 79 name */ 80 #define MU_PARSEOPT_ARGV0 0x00000001 81 /* Ignore command line errors. */ 82 #define MU_PARSEOPT_IGNORE_ERRORS 0x00000002 83 /* Don't order arguments so that options come first. */ 84 #define MU_PARSEOPT_IN_ORDER 0x00000004 85 /* Don't provide standard options: -h, --help, --usage, --version */ 86 #define MU_PARSEOPT_NO_STDOPT 0x00000008 87 /* Don't exit on errors */ 88 #define MU_PARSEOPT_NO_ERREXIT 0x00000010 89 /* Apply all options immediately */ 90 #define MU_PARSEOPT_IMMEDIATE 0x00000020 91 92 /* Don't sort options */ 93 #define MU_PARSEOPT_NO_SORT 0x00001000 94 95 #define MU_PARSEOPT_PROG_NAME 0x00002000 96 #define MU_PARSEOPT_PROG_DOC 0x00004000 97 #define MU_PARSEOPT_PROG_ARGS 0x00008000 98 #define MU_PARSEOPT_BUG_ADDRESS 0x00010000 99 #define MU_PARSEOPT_PACKAGE_NAME 0x00020000 100 #define MU_PARSEOPT_PACKAGE_URL 0x00040000 101 #define MU_PARSEOPT_EXTRA_INFO 0x00080000 102 #define MU_PARSEOPT_EXIT_ERROR 0x00100000 103 #define MU_PARSEOPT_HELP_HOOK 0x00200000 104 #define MU_PARSEOPT_DATA 0x00400000 105 #define MU_PARSEOPT_VERSION_HOOK 0x00800000 106 #define MU_PARSEOPT_PROG_DOC_HOOK 0x01000000 107 /* Long options start with single dash. Disables recognition of traditional 108 short options */ 109 #define MU_PARSEOPT_SINGLE_DASH 0x02000000 110 /* Negation prefix is set */ 111 #define MU_PARSEOPT_NEGATION 0x04000000 112 /* po_special_args is set */ 113 #define MU_PARSEOPT_SPECIAL_ARGS 0x08000000 114 115 /* Reuse mu_parseopt struct initialized previously */ 116 #define MU_PARSEOPT_REUSE 0x80000000 117 /* Mask for immutable flag bits */ 118 #define MU_PARSEOPT_IMMUTABLE_MASK 0xFFFFF000 119 120 struct mu_parseopt 121 { 122 /* Input data: */ 123 int po_argc; /* Number of argiments */ 124 char **po_argv; /* Array of arguments */ 125 size_t po_optc; /* Number of elements in optv */ 126 struct mu_option **po_optv; /* Array of ptrs to option structures */ 127 int po_flags; 128 129 char *po_negation; /* Negation prefix for boolean options */ 130 void *po_data; /* Call-specific data */ 131 132 int po_exit_error; /* Exit on error with this code */ 133 134 /* Informational: */ 135 char const *po_prog_name; 136 char const *po_prog_doc; 137 char const **po_prog_args; 138 char const *po_special_args; /* Special option-like arguments */ 139 char const *po_bug_address; 140 char const *po_package_name; 141 char const *po_package_url; 142 char const *po_extra_info; 143 144 void (*po_prog_doc_hook) (struct mu_parseopt *po, mu_stream_t stream); 145 void (*po_help_hook) (struct mu_parseopt *po, mu_stream_t stream); 146 void (*po_version_hook) (struct mu_parseopt *po, mu_stream_t stream); 147 148 /* Output data */ 149 int po_ind; /* Index of the next option */ 150 int po_opterr; /* Index of the element in po_argv that 151 caused last error, or -1 if no errors */ 152 mu_list_t po_optlist; 153 154 /* Auxiliary data */ 155 char *po_cur; /* Points to the next character */ 156 int po_chr; /* Single-char option */ 157 158 char *po_long_opt_start; /* Character sequence that starts 159 long option */ 160 161 /* The following two keep the position of the first non-optional argument 162 and the number of contiguous non-optional arguments after it. 163 Obviously, the following holds true: 164 165 arg_start + arg_count == opt_ind 166 167 If permutation is not allowed (MU_OPTION_PARSE_IN_ORDER flag is set), 168 arg_count is always 0. 169 */ 170 int po_arg_start; 171 int po_arg_count; 172 173 unsigned po_permuted:1; /* Whether the arguments were permuted */ 174 175 size_t po_longcnt; /* Number of long options */ 176 size_t *po_longidx; /* Indices of long options in po_optv */ 177 }; 178 179 180 int mu_parseopt (struct mu_parseopt *p, 181 int argc, char **argv, struct mu_option **optv, 182 int flags); 183 void mu_parseopt_error (struct mu_parseopt *po, char const *fmt, ...); 184 185 int mu_parseopt_apply (struct mu_parseopt *p); 186 void mu_parseopt_free (struct mu_parseopt *p); 187 188 int mu_parseopt_help_stream_create (mu_stream_t *retstr, 189 struct mu_parseopt *po, 190 mu_stream_t outstr); 191 unsigned mu_parseopt_getcolumn (const char *name); 192 193 void mu_option_describe_options (mu_stream_t str, struct mu_parseopt *p); 194 void mu_program_help (struct mu_parseopt *p, mu_stream_t str); 195 void mu_program_usage (struct mu_parseopt *p, int optsummary, mu_stream_t str); 196 void mu_program_version (struct mu_parseopt *po, mu_stream_t str); 197 198 void mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt, 199 char const *arg); 200 201 int mu_option_possible_negation (struct mu_parseopt *po, struct mu_option *opt); 202 203 #endif 204