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