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