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