1 2 /* 3 * \file autoopts.h 4 * 5 * This file defines all the global structures and special values 6 * used in the automated option processing library. 7 * 8 * @group autoopts 9 * @{ 10 */ 11 /* 12 * This file is part of AutoOpts, a companion to AutoGen. 13 * AutoOpts is free software. 14 * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved 15 * 16 * AutoOpts is available under any one of two licenses. The license 17 * in use must be one of these two and the choice is under the control 18 * of the user of the license. 19 * 20 * The GNU Lesser General Public License, version 3 or later 21 * See the files "COPYING.lgplv3" and "COPYING.gplv3" 22 * 23 * The Modified Berkeley Software Distribution License 24 * See the file "COPYING.mbsd" 25 * 26 * These files have the following sha256 sums: 27 * 28 * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 29 * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 30 * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd 31 */ 32 33 #ifndef AUTOGEN_AUTOOPTS_H 34 #define AUTOGEN_AUTOOPTS_H 35 #include <stdnoreturn.h> 36 37 #define AO_NAME_LIMIT 127 38 #define AO_NAME_SIZE ((size_t)(AO_NAME_LIMIT + 1)) 39 40 #ifndef AG_PATH_MAX 41 # ifdef PATH_MAX 42 # define AG_PATH_MAX ((size_t)PATH_MAX) 43 # else 44 # define AG_PATH_MAX ((size_t)4096) 45 # endif 46 #else 47 # if defined(PATH_MAX) && (PATH_MAX > MAXPATHLEN) 48 # undef AG_PATH_MAX 49 # define AG_PATH_MAX ((size_t)PATH_MAX) 50 # endif 51 #endif 52 53 #undef EXPORT 54 #define EXPORT 55 56 #ifndef NUL 57 #define NUL '\0' 58 #endif 59 #define BEL '\a' 60 #define BS '\b' 61 #define HT '\t' 62 #define LF '\n' 63 #define VT '\v' 64 #define FF '\f' 65 #define CR '\r' 66 67 #if defined(_WIN32) && !defined(__CYGWIN__) 68 # define DIRCH '\\' 69 #else 70 # define DIRCH '/' 71 #endif 72 73 #ifndef EX_USAGE 74 /** 75 * Command line usage problem 76 */ 77 # define EX_USAGE 64 78 #endif 79 #ifndef EX_DATAERR 80 /** 81 * The input data was incorrect in some way. 82 */ 83 # define EX_DATAERR 64 84 #endif 85 #ifndef EX_NOINPUT 86 /** 87 * option state was requested from a file that cannot be loaded. 88 */ 89 # define EX_NOINPUT 66 90 #endif 91 #ifndef EX_SOFTWARE 92 /** 93 * AutoOpts Software failure. 94 */ 95 # define EX_SOFTWARE 70 96 #endif 97 #ifndef EX_OSERR 98 /** 99 * Command line usage problem 100 */ 101 # define EX_OSERR 71 102 #endif 103 104 #define NL '\n' 105 #ifndef C 106 /** 107 * Coercive cast. Compel an address to be interpreted as the type 108 * of the first argument. No complaints, just do it. 109 */ 110 #define C(_t,_p) ((_t)VOIDP(_p)) 111 #endif 112 113 /* The __attribute__((__warn_unused_result__)) feature 114 is available in gcc versions 3.4 and newer, 115 while the typeof feature has been available since 2.7 at least. */ 116 # if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) 117 # define ignore_val(x) ((void) (x)) 118 # else 119 # define ignore_val(x) (({ __typeof__ (x) __x = (x); (void) __x; })) 120 # endif 121 122 /* 123 * Convert the number to a list usable in a printf call 124 */ 125 #define NUM_TO_VER(n) ((n) >> 12), ((n) >> 7) & 0x001F, (n) & 0x007F 126 127 #define NAMED_OPTS(po) \ 128 (((po)->fOptSet & (OPTPROC_SHORTOPT | OPTPROC_LONGOPT)) == 0) 129 130 #define SKIP_OPT(p) (((p)->fOptState & OPTST_IMMUTABLE_MASK) != 0) 131 132 typedef int tDirection; 133 /** 134 * handling option presets. Start with command line and work through 135 * config settings in reverse order. 136 */ 137 #define DIRECTION_PRESET -1 138 /** 139 * handling normal options. Start with first config file, then environment 140 * variables and finally the command line. 141 */ 142 #define DIRECTION_PROCESS 1 143 /** 144 * An initialzation phase or an option being loaded from program sources. 145 */ 146 #define DIRECTION_CALLED 0 147 148 #define PROCESSING(d) ((d)>0) 149 #define PRESETTING(d) ((d)<0) 150 #define CALLED(d) ((d)==0) 151 152 /** 153 * When loading a line (or block) of text as an option, the value can 154 * be processed in any of several modes. 155 */ 156 typedef enum { 157 /** 158 * If the value looks like a quoted string, then process it. Double 159 * quoted strings are processed the way strings are in "C" programs, 160 * except they are treated as regular characters if the following 161 * character is not a well-established escape sequence. Single quoted 162 * strings (quoted with apostrophies) are handled the way strings are 163 * handled in shell scripts, *except* that backslash escapes are 164 * honored before backslash escapes and apostrophies. 165 */ 166 OPTION_LOAD_COOKED, 167 168 /** 169 * Even if the value begins with quote characters, do not do quote 170 * processing. Strip leading and trailing white space. 171 */ 172 OPTION_LOAD_UNCOOKED, 173 174 /** 175 * Keep every part of the value between the delimiters. 176 */ 177 OPTION_LOAD_KEEP 178 } tOptionLoadMode; 179 180 static tOptionLoadMode option_load_mode; 181 182 /** 183 * The pager state is used by optionPagedUsage() procedure. 184 * When it runs, it sets itself up to be called again on exit. 185 * If, however, a routine needs a child process to do some work 186 * before it is done, then 'pagerState' must be set to 187 * 'PAGER_STATE_CHILD' so that optionPagedUsage() will not try 188 * to run the pager program before its time. 189 */ 190 typedef enum { 191 PAGER_STATE_INITIAL, //@< initial option paging state 192 193 /** 194 * temp file created and optionPagedUsage is scheduled to run at exit 195 */ 196 PAGER_STATE_READY, 197 198 /** 199 * This is a child process used in creating shell script usage. 200 */ 201 PAGER_STATE_CHILD 202 } tePagerState; 203 204 typedef enum { 205 ENV_ALL, 206 ENV_IMM, 207 ENV_NON_IMM 208 } teEnvPresetType; 209 210 typedef enum { 211 TOPT_UNDEFINED = 0, 212 TOPT_SHORT, 213 TOPT_LONG, 214 TOPT_DEFAULT 215 } teOptType; 216 217 typedef struct { 218 tOptDesc * pOD; 219 char const * pzOptArg; 220 opt_state_mask_t flags; 221 teOptType optType; 222 } tOptState; 223 #define OPTSTATE_INITIALIZER(st) \ 224 { NULL, NULL, OPTST_ ## st, TOPT_UNDEFINED } 225 226 #define TEXTTO_TABLE \ 227 _TT_(LONGUSAGE) \ 228 _TT_(USAGE) \ 229 _TT_(VERSION) 230 #define _TT_(n) \ 231 TT_ ## n , 232 233 typedef enum { TEXTTO_TABLE COUNT_TT } teTextTo; 234 235 #undef _TT_ 236 237 /** 238 * option argument types. Used to create usage information for 239 * particular options. 240 */ 241 typedef struct { 242 char const * pzStr; 243 char const * pzReq; 244 char const * pzNum; 245 char const * pzFile; 246 char const * pzKey; 247 char const * pzKeyL; 248 char const * pzBool; 249 char const * pzNest; 250 char const * pzOpt; 251 char const * pzNo; 252 char const * pzBrk; 253 char const * pzNoF; 254 char const * pzSpc; 255 char const * pzOptFmt; 256 char const * pzTime; 257 } arg_types_t; 258 259 #define AGALOC(_c, _w) ao_malloc((size_t)_c) 260 #define AGREALOC(_p, _c, _w) ao_realloc(VOIDP(_p), (size_t)_c) 261 #define AGFREE(_p) free(VOIDP(_p)) 262 #define AGDUPSTR(_p, _s, _w) (_p = ao_strdup(_s)) 263 264 static void * 265 ao_malloc(size_t sz); 266 267 static void * 268 ao_realloc(void *p, size_t sz); 269 270 #define ao_free(_p) free(VOIDP(_p)) 271 272 static char * 273 ao_strdup(char const * str); 274 275 /** 276 * DO option handling? 277 * 278 * Options are examined at two times: at immediate handling time and at 279 * normal handling time. If an option is disabled, the timing may be 280 * different from the handling of the undisabled option. The OPTST_DIABLED 281 * bit indicates the state of the currently discovered option. 282 * So, here's how it works: 283 * 284 * A) handling at "immediate" time, either 1 or 2: 285 * 286 * 1. OPTST_DISABLED is not set: 287 * IMM must be set 288 * DISABLE_IMM don't care 289 * TWICE don't care 290 * DISABLE_TWICE don't care 291 * 0 -and- 1 x x x 292 * 293 * 2. OPTST_DISABLED is set: 294 * IMM don't care 295 * DISABLE_IMM must be set 296 * TWICE don't care 297 * DISABLE_TWICE don't care 298 * 1 -and- x 1 x x 299 */ 300 #define DO_IMMEDIATELY(_flg) \ 301 ( (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == OPTST_IMM) \ 302 || ( ((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM)) \ 303 == (OPTST_DISABLED|OPTST_DISABLE_IMM) )) 304 305 /** 306 * B) handling at "regular" time because it was not immediate 307 * 308 * 1. OPTST_DISABLED is not set: 309 * IMM must *NOT* be set 310 * DISABLE_IMM don't care 311 * TWICE don't care 312 * DISABLE_TWICE don't care 313 * 0 -and- 0 x x x 314 * 315 * 2. OPTST_DISABLED is set: 316 * IMM don't care 317 * DISABLE_IMM don't care 318 * TWICE must be set 319 * DISABLE_TWICE don't care 320 * 1 -and- x x 1 x 321 */ 322 #define DO_NORMALLY(_flg) ( \ 323 (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == 0) \ 324 || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM)) == \ 325 OPTST_DISABLED) ) 326 327 /** 328 * C) handling at "regular" time because it is to be handled twice. 329 * The immediate bit was already tested and found to be set: 330 * 331 * 3. OPTST_DISABLED is not set: 332 * IMM is set (but don't care) 333 * DISABLE_IMM don't care 334 * TWICE must be set 335 * DISABLE_TWICE don't care 336 * 0 -and- ? x 1 x 337 * 338 * 4. OPTST_DISABLED is set: 339 * IMM don't care 340 * DISABLE_IMM is set (but don't care) 341 * TWICE don't care 342 * DISABLE_TWICE must be set 343 * 1 -and- x ? x 1 344 */ 345 #define DO_SECOND_TIME(_flg) ( \ 346 (((_flg) & (OPTST_DISABLED|OPTST_TWICE)) == \ 347 OPTST_TWICE) \ 348 || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_TWICE)) == \ 349 (OPTST_DISABLED|OPTST_DISABLE_TWICE) )) 350 351 /* 352 * text_mmap structure. Only active on platforms with mmap(2). 353 */ 354 #ifdef HAVE_SYS_MMAN_H 355 # include <sys/mman.h> 356 #else 357 # ifndef PROT_READ 358 # define PROT_READ 0x01 359 # endif 360 # ifndef PROT_WRITE 361 # define PROT_WRITE 0x02 362 # endif 363 # ifndef MAP_SHARED 364 # define MAP_SHARED 0x01 365 # endif 366 # ifndef MAP_PRIVATE 367 # define MAP_PRIVATE 0x02 368 # endif 369 #endif 370 371 #ifndef MAP_FAILED 372 # define MAP_FAILED VOIDP(-1) 373 #endif 374 375 #ifndef _SC_PAGESIZE 376 # ifdef _SC_PAGE_SIZE 377 # define _SC_PAGESIZE _SC_PAGE_SIZE 378 # endif 379 #endif 380 381 #ifndef HAVE_STRCHR 382 extern char * strchr(char const * s, int c); 383 extern char * strrchr(char const * s, int c); 384 #endif 385 386 /** 387 * INQUERY_CALL() tests whether the option handling function has been 388 * called by an inquery (help text needed, or option being reset), 389 * or called by a set-the-option operation. 390 */ 391 #define INQUERY_CALL(_o, _d) ( \ 392 ((_o) <= OPTPROC_EMIT_LIMIT) \ 393 || ((_d) == NULL) \ 394 || (((_d)->fOptState & OPTST_RESET) != 0) ) 395 396 /** 397 * Define and initialize all the user visible strings. 398 * We do not do translations. If translations are to be done, then 399 * the client will provide a callback for that purpose. 400 */ 401 #undef DO_TRANSLATIONS 402 #include "autoopts/usage-txt.h" 403 404 /** 405 * File pointer for usage output 406 */ 407 FILE * option_usage_fp; 408 /** 409 * If provided in the option structure 410 */ 411 static char const * program_pkgdatadir; 412 /** 413 * privately exported functions 414 */ 415 extern tOptProc optionPrintVersion, optionPagedUsage, optionLoadOpt; 416 417 #ifdef AUTOOPTS_INTERNAL 418 419 #ifndef PKGDATADIR 420 # define PKGDATADIR "" 421 #endif 422 #define APOSTROPHE '\'' 423 424 #define OPTPROC_L_N_S (OPTPROC_LONGOPT | OPTPROC_SHORTOPT) 425 #if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H) 426 # include <libintl.h> 427 #endif 428 429 typedef struct { 430 size_t fnm_len; 431 uint32_t fnm_mask; 432 char const * fnm_name; 433 } ao_flag_names_t; 434 435 /** 436 * Automated Options Usage Flags. 437 * NB: no entry may be a prefix of another entry 438 */ 439 #define AOFLAG_TABLE \ 440 _aof_(gnu, OPTPROC_GNUUSAGE ) \ 441 _aof_(autoopts, ~OPTPROC_GNUUSAGE) \ 442 _aof_(no_misuse_usage, OPTPROC_MISUSE ) \ 443 _aof_(misuse_usage, ~OPTPROC_MISUSE ) \ 444 _aof_(compute, OPTPROC_COMPUTE ) 445 446 #define _aof_(_n, _f) AOUF_ ## _n ## _ID, 447 typedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t; 448 #undef _aof_ 449 450 #define _aof_(_n, _f) AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID), 451 typedef enum { AOFLAG_TABLE } ao_flags_t; 452 #undef _aof_ 453 454 static char const zNil[] = ""; 455 static arg_types_t argTypes = { NULL }; 456 static char line_fmt_buf[32]; 457 static bool displayEnum = false; 458 static char const pkgdatadir_default[] = PKGDATADIR; 459 static char const * program_pkgdatadir = pkgdatadir_default; 460 static tOptionLoadMode option_load_mode = OPTION_LOAD_UNCOOKED; 461 static tePagerState pagerState = PAGER_STATE_INITIAL; 462 463 FILE * option_usage_fp = NULL; 464 465 static char const * pz_enum_err_fmt; 466 467 tOptions * optionParseShellOptions = NULL; 468 469 static char const * shell_prog = NULL; 470 static char * script_leader = NULL; 471 static char * script_trailer = NULL; 472 static char * script_text = NULL; 473 static bool print_exit = false; 474 #endif /* AUTOOPTS_INTERNAL */ 475 476 #endif /* AUTOGEN_AUTOOPTS_H */ 477 /** 478 * @} 479 * Local Variables: 480 * mode: C 481 * c-file-style: "stroustrup" 482 * indent-tabs-mode: nil 483 * End: 484 * end of autoopts/autoopts.h */ 485