autoopts.h revision 290001
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
132typedef 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 */
156typedef 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
180static 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 */
190typedef 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
204typedef enum {
205    ENV_ALL,
206    ENV_IMM,
207    ENV_NON_IMM
208} teEnvPresetType;
209
210typedef enum {
211    TOPT_UNDEFINED = 0,
212    TOPT_SHORT,
213    TOPT_LONG,
214    TOPT_DEFAULT
215} teOptType;
216
217typedef 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
233typedef 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 */
241typedef 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
264static void *
265ao_malloc(size_t sz);
266
267static void *
268ao_realloc(void *p, size_t sz);
269
270#define ao_free(_p) free(VOIDP(_p))
271
272static char *
273ao_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
382extern char * strchr(char const * s, int c);
383extern 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 */
407FILE * option_usage_fp;
408/**
409 *  If provided in the option structure
410 */
411static char const * program_pkgdatadir;
412/**
413 * privately exported functions
414 */
415extern 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
429typedef 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,
447typedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t;
448#undef  _aof_
449
450#define _aof_(_n, _f)   AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID),
451typedef enum { AOFLAG_TABLE } ao_flags_t;
452#undef  _aof_
453
454static char const   zNil[] = "";
455static arg_types_t  argTypes             = { NULL };
456static char         line_fmt_buf[32];
457static bool         displayEnum          = false;
458static char const   pkgdatadir_default[] = PKGDATADIR;
459static char const * program_pkgdatadir   = pkgdatadir_default;
460static tOptionLoadMode option_load_mode  = OPTION_LOAD_UNCOOKED;
461static tePagerState pagerState           = PAGER_STATE_INITIAL;
462
463       FILE *       option_usage_fp      = NULL;
464
465static char const * pz_enum_err_fmt;
466
467tOptions * optionParseShellOptions = NULL;
468
469static char const * shell_prog = NULL;
470static char * script_leader    = NULL;
471static char * script_trailer   = NULL;
472static char * script_text      = NULL;
473static 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