xref: /freebsd/contrib/ntp/sntp/libopts/autoopts.h (revision a0ee8cc636cd5c2374ec44ca71226564ea0bca95)
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