Home | History | Annotate | Line # | Download | only in libopts
      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