1 #ifndef _LIBHX_OPTION_H 2 #define _LIBHX_OPTION_H 1 3 4 #ifdef __cplusplus 5 # include <cstddef> 6 # include <cstdio> 7 #else 8 # include <stddef.h> 9 # include <stdio.h> 10 #endif 11 12 #ifdef __cplusplus 13 extern "C" { 14 #endif 15 16 #ifndef __libhx_internal_hxmc_t_defined 17 #define __libhx_internal_hxmc_t_defined 1 18 typedef char hxmc_t; 19 #endif 20 21 struct HXoption; 22 23 /* 24 * FORMAT.C 25 */ 26 extern struct HXformat_map *HXformat_init(void); 27 extern void HXformat_free(struct HXformat_map *); 28 extern int HXformat_add(struct HXformat_map *, const char *, const void *, 29 unsigned int); 30 extern int HXformat_aprintf(const struct HXformat_map *, 31 hxmc_t **, const char *); 32 extern int HXformat_sprintf(const struct HXformat_map *, 33 char *, size_t, const char *); 34 extern int HXformat_fprintf(const struct HXformat_map *, 35 FILE *, const char *); 36 37 /* 38 * OPT.C 39 */ 40 41 /** 42 * Available types for struct HXoption.type. 43 * %HXTYPE_NONE: [-o] (int *) No argument; counts presence. 44 * %HXTYPE_VAL: [-o] (int *) Set to value in .val. 45 * %HXTYPE_SVAL: [-o] (const char *) Set to value in .uptr. 46 * %HXTYPE_BOOL: [fo] (int *) Parse argument as boolean 47 * ("yes", "no", "true", "false", 0 or non-zero) 48 * %HXTYPE_BYTE: [fo] (unsigned char *) Take first char of argument 49 * %HXTYPE_UCHAR: [fo] (unsigned char *) An integer. 50 * %HXTYPE_CHAR: [fo] (char *) An integer. 51 * %HXTYPE_USHORT: [fo] (unsigned short *) An integer. 52 * %HXTYPE_SHORT: [fo] (short *) An integer. 53 * %HXTYPE_UINT: [fo] (unsigned int *) An integer. 54 * %HXTYPE_INT: [fo] (int *) An integer. 55 * %HXTYPE_ULONG: [fo] (unsigned long *) An integer. 56 * %HXTYPE_LONG: [fo] (long *) An integer. 57 * %HXTYPE_ULLONG: [fo] (unsigned long long *) An integer. 58 * %HXTYPE_LLONG: [fo] (long long *) An integer. 59 * %HXTYPE_FLOAT: [fo] (float *) Read a floating point number 60 * %HXTYPE_DOUBLE: [fo] (double *) Read a floating point number 61 * %HXTYPE_STRING: [fo] (char **) Any string. 62 * %HXTYPE_STRP: [f-] (const char *const *) A string. 63 * %HXTYPE_STRDQ: [-o] (struct HXdeque *) A string. 64 * %HXTYPE_UINT8: [-o] (uint8_t *) An integer. 65 * %HXTYPE_UINT16: [-o] (uint8_t *) An integer. 66 * %HXTYPE_UINT32: [-o] (uint8_t *) An integer. 67 * %HXTYPE_UINT64: [-o] (uint8_t *) An integer. 68 * %HXTYPE_INT8: [-o] (uint8_t *) An integer. 69 * %HXTYPE_INT16: [-o] (uint8_t *) An integer. 70 * %HXTYPE_INT32: [-o] (uint8_t *) An integer. 71 * %HXTYPE_INT64: [-o] (uint8_t *) An integer. 72 * %HXTYPE_MCSTR: [-o] (hxmc_t *) A string. 73 * %HXTYPE_XSNTMARK: [-o] Internal sentinal marker (used in HXOPT_TABLEEND) 74 * %HXTYPE_XHELP: [-o] Internal helper marker (used in HXOPT_AUTOHELP) 75 * %HXTYPE_SIZE_T: [-o] (size_t *) An integer. 76 * 77 * Type expected of struct HXoption.ptr is given in (). 78 * HX_getopt (o) and HXformat_* (f) support different sets, marked with []. 79 */ 80 enum HX_option_type { 81 HXTYPE_NONE = 0, 82 HXTYPE_VAL, 83 HXTYPE_SVAL, 84 HXTYPE_BOOL, 85 HXTYPE_BYTE, 86 HXTYPE_UCHAR, /* 5 */ 87 HXTYPE_CHAR, 88 HXTYPE_USHORT, 89 HXTYPE_SHORT, 90 HXTYPE_UINT, 91 HXTYPE_INT, /* 10 */ 92 HXTYPE_ULONG, 93 HXTYPE_LONG, 94 HXTYPE_ULLONG, 95 HXTYPE_LLONG, 96 HXTYPE_FLOAT, /* 15 */ 97 HXTYPE_DOUBLE, 98 HXTYPE_STRING, 99 HXTYPE_STRP, /* (const char **) */ 100 HXTYPE_STRDQ, 101 HXTYPE_UINT8, /* 20 */ 102 HXTYPE_UINT16, 103 HXTYPE_UINT32, 104 HXTYPE_UINT64, 105 HXTYPE_INT8, 106 HXTYPE_INT16, /* 25 */ 107 HXTYPE_INT32, 108 HXTYPE_INT64, 109 HXTYPE_MCSTR, 110 HXTYPE_XSNTMARK, 111 HXTYPE_XHELP, /* 30 */ 112 HXTYPE_SIZE_T, 113 }; 114 115 /** 116 * Extra flags to be OR'ed into struct HXoption.type. 117 * %HXOPT_OPTIONAL: argument to option is optional 118 * (it's bad taste to use this) 119 * %HXOPT_INC: increase variable pointed to by .ptr. 120 * (only applies to %HXTYPE_NONE) 121 * %HXOPT_DEC: increase variable pointed to by .ptr. 122 * (only applies to %HXTYPE_NONE) 123 * %HXOPT_NOT: negate input (*ptr), this is done before OR/AND 124 * %HXOPT_OR: OR *ptr by argument 125 * %HXOPT_AND: AND *ptr by argument 126 * %HXOPT_XOR: XOR *ptr by argument 127 */ 128 enum { 129 HXOPT_OPTIONAL = 1 << 6, 130 HXOPT_INC = 1 << 7, 131 HXOPT_DEC = 1 << 8, 132 HXOPT_NOT = 1 << 9, 133 HXOPT_OR = 1 << 10, 134 HXOPT_AND = 1 << 11, 135 HXOPT_XOR = 1 << 12, 136 }; 137 138 /** 139 * Flags (4th arg) to HX_getopt. 140 * %HXOPT_PTHRU: pass-through unknown options to new argv 141 * %HXOPT_DESTROY_OLD: destroy old argv after parsing is successful 142 * %HXOPT_QUIET: do not output any warnings to stderr 143 * %HXOPT_HELPONERR: print out help when a parsing error occurs 144 * %HXOPT_USAGEONERR: print out short usage when a parsing error occurs 145 * %HXOPT_RQ_ORDER: require option order/POSIX mode: 146 * first non-option terminates option processing 147 */ 148 enum { 149 HXOPT_PTHRU = 1 << 0, 150 HXOPT_DESTROY_OLD = 1 << 1, 151 HXOPT_QUIET = 1 << 2, 152 HXOPT_HELPONERR = 1 << 3, 153 HXOPT_USAGEONERR = 1 << 4, 154 HXOPT_RQ_ORDER = 1 << 5, 155 }; 156 157 /** 158 * (Positive-ranged) return values for HX_getopt. 159 * %HXOPT_ERR_SUCCESS: success 160 * %HXOPT_ERR_UNKN: unknown option was encountered 161 * %HXOPT_ERR_VOID: long option takes no value 162 * %HXOPT_ERR_MIS: option requires a value argument 163 * %HXOPT_ERR_AMBIG: long option abbreviation was ambiguous 164 */ 165 enum { 166 HXOPT_ERR_SUCCESS = 0, 167 HXOPT_ERR_UNKN, 168 HXOPT_ERR_VOID, 169 HXOPT_ERR_MIS, 170 HXOPT_ERR_AMBIG, 171 }; 172 173 /** 174 * Extra flags to be OR'ed into HXformat_add()'s 4th arg. 175 * %HXFORMAT_IMMED: do not dereference the 4th arg to get at the value 176 */ 177 enum { 178 HXFORMAT_IMMED = 1 << 13, 179 }; 180 181 /** 182 * Flags for HX_shconfig_pv() 183 * %SHCONF_ONE: only read one configuration file 184 */ 185 enum { 186 SHCONF_ONE = 1 << 0, 187 }; 188 189 /** 190 * Flags in struct HXoptcb.flags 191 * %HXOPTCB_BY_LONG: cb was called by invocation of @current->ln 192 * %HXOPTCB_BY_SHORT: cb was called by invocation of @current->sh 193 */ 194 enum { 195 HXOPTCB_BY_LONG = 1 << 0, 196 HXOPTCB_BY_SHORT = 1 << 1, 197 }; 198 199 struct HXoptcb { 200 const struct HXoption *table, *current; 201 const char *data; 202 union { 203 double data_dbl; 204 long data_long; 205 }; 206 unsigned int flags; 207 }; 208 209 /** 210 * @ln: long option string (without "--"), or %NULL 211 * @sh: short option character, or '\0' 212 * @type: type of variable pointed to by .ptr 213 * @ptr: pointer to variable to set/update 214 * @uptr: freeform user-supplied pointer; 215 * in case of %HXTYPE_SVAL, this is the specific value to set 216 * @cb: callback function to invoke, or %NULL 217 * @val: specific value to set if type == HXTYPE_VAL 218 * @help: help string to display 219 * @htyp: type string to show in option's help 220 */ 221 struct HXoption { 222 const char *ln; 223 char sh; 224 unsigned int type; 225 void *ptr, *uptr; 226 void (*cb)(const struct HXoptcb *); 227 int val; 228 const char *help, *htyp; 229 }; 230 231 extern int HX_getopt(const struct HXoption *, int *, const char ***, 232 unsigned int); 233 extern void HX_getopt_help(const struct HXoptcb *, FILE *); 234 extern void HX_getopt_help_cb(const struct HXoptcb *); 235 extern void HX_getopt_usage(const struct HXoptcb *, FILE *); 236 extern void HX_getopt_usage_cb(const struct HXoptcb *); 237 extern int HX_shconfig(const char *, const struct HXoption *); 238 extern struct HXmap *HX_shconfig_map(const char *); 239 extern int HX_shconfig_pv(const char **, const char *, 240 const struct HXoption *, unsigned int); 241 extern void HX_shconfig_free(const struct HXoption *); 242 243 #ifdef __cplusplus 244 } /* extern "C" */ 245 #endif 246 247 #ifndef __cplusplus 248 # define HXOPT_AUTOHELP \ 249 {.ln = "help", .sh = '?', .type = HXTYPE_XHELP, \ 250 .cb = HX_getopt_help_cb, .help = "Show this help message"}, \ 251 {.ln = "usage", .type = HXTYPE_NONE, \ 252 .cb = HX_getopt_usage_cb, \ 253 .help = "Display brief usage message"} 254 # define HXOPT_TABLEEND {.type = HXTYPE_XSNTMARK} 255 #else 256 # define HXOPT_AUTOHELP \ 257 {"help", '?', HXTYPE_XHELP, NULL, NULL, HX_getopt_help_cb, \ 258 0, "Show this help message"}, \ 259 {"usage", 0, HXTYPE_NONE, NULL, NULL, HX_getopt_usage_cb, \ 260 0, "Display brief usage message"} 261 # define HXOPT_TABLEEND {NULL, 0, HXTYPE_XSNTMARK} 262 #endif 263 264 #endif /* _LIBHX_OPTION_H */ 265