1181834Sroberto
2181834Sroberto/*
3290001Sglebius *  \file autoopts.h
4181834Sroberto *
5181834Sroberto *  This file defines all the global structures and special values
6181834Sroberto *  used in the automated option processing library.
7290001Sglebius *
8290001Sglebius * @group autoopts
9290001Sglebius * @{
10181834Sroberto */
11181834Sroberto/*
12290001Sglebius *  This file is part of AutoOpts, a companion to AutoGen.
13290001Sglebius *  AutoOpts is free software.
14290001Sglebius *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
15181834Sroberto *
16290001Sglebius *  AutoOpts is available under any one of two licenses.  The license
17290001Sglebius *  in use must be one of these two and the choice is under the control
18290001Sglebius *  of the user of the license.
19181834Sroberto *
20290001Sglebius *   The GNU Lesser General Public License, version 3 or later
21290001Sglebius *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
22181834Sroberto *
23290001Sglebius *   The Modified Berkeley Software Distribution License
24290001Sglebius *      See the file "COPYING.mbsd"
25181834Sroberto *
26290001Sglebius *  These files have the following sha256 sums:
27181834Sroberto *
28290001Sglebius *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
29290001Sglebius *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
30290001Sglebius *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
31181834Sroberto */
32181834Sroberto
33181834Sroberto#ifndef AUTOGEN_AUTOOPTS_H
34181834Sroberto#define AUTOGEN_AUTOOPTS_H
35290001Sglebius#include <stdnoreturn.h>
36181834Sroberto
37181834Sroberto#define AO_NAME_LIMIT           127
38181834Sroberto#define AO_NAME_SIZE            ((size_t)(AO_NAME_LIMIT + 1))
39181834Sroberto
40181834Sroberto#ifndef AG_PATH_MAX
41181834Sroberto#  ifdef PATH_MAX
42181834Sroberto#    define AG_PATH_MAX         ((size_t)PATH_MAX)
43181834Sroberto#  else
44181834Sroberto#    define AG_PATH_MAX         ((size_t)4096)
45181834Sroberto#  endif
46181834Sroberto#else
47181834Sroberto#  if defined(PATH_MAX) && (PATH_MAX > MAXPATHLEN)
48181834Sroberto#     undef  AG_PATH_MAX
49181834Sroberto#     define AG_PATH_MAX        ((size_t)PATH_MAX)
50181834Sroberto#  endif
51181834Sroberto#endif
52181834Sroberto
53181834Sroberto#undef  EXPORT
54181834Sroberto#define EXPORT
55181834Sroberto
56290001Sglebius#ifndef NUL
57290001Sglebius#define NUL                     '\0'
58290001Sglebius#endif
59290001Sglebius#define BEL                     '\a'
60290001Sglebius#define BS                      '\b'
61290001Sglebius#define HT                      '\t'
62290001Sglebius#define LF                      '\n'
63290001Sglebius#define VT                      '\v'
64290001Sglebius#define FF                      '\f'
65290001Sglebius#define CR                      '\r'
66290001Sglebius
67181834Sroberto#if defined(_WIN32) && !defined(__CYGWIN__)
68181834Sroberto# define DIRCH                  '\\'
69181834Sroberto#else
70181834Sroberto# define DIRCH                  '/'
71181834Sroberto#endif
72181834Sroberto
73290001Sglebius#ifndef EX_USAGE
74290001Sglebius   /**
75290001Sglebius    *  Command line usage problem
76290001Sglebius    */
77290001Sglebius#  define EX_USAGE              64
78290001Sglebius#endif
79290001Sglebius#ifndef EX_DATAERR
80290001Sglebius   /**
81290001Sglebius    *  The input data was incorrect in some way.
82290001Sglebius    */
83290001Sglebius#  define EX_DATAERR            64
84290001Sglebius#endif
85181834Sroberto#ifndef EX_NOINPUT
86290001Sglebius   /**
87290001Sglebius    *  option state was requested from a file that cannot be loaded.
88290001Sglebius    */
89181834Sroberto#  define EX_NOINPUT            66
90181834Sroberto#endif
91181834Sroberto#ifndef EX_SOFTWARE
92290001Sglebius   /**
93290001Sglebius    *  AutoOpts Software failure.
94290001Sglebius    */
95181834Sroberto#  define EX_SOFTWARE           70
96181834Sroberto#endif
97290001Sglebius#ifndef EX_OSERR
98290001Sglebius   /**
99290001Sglebius    *  Command line usage problem
100290001Sglebius    */
101290001Sglebius#  define EX_OSERR              71
102181834Sroberto#endif
103181834Sroberto
104290001Sglebius#define NL '\n'
105290001Sglebius#ifndef C
106290001Sglebius/**
107290001Sglebius *  Coercive cast.  Compel an address to be interpreted as the type
108290001Sglebius *  of the first argument.  No complaints, just do it.
109290001Sglebius */
110290001Sglebius#define C(_t,_p)  ((_t)VOIDP(_p))
111290001Sglebius#endif
112290001Sglebius
113290001Sglebius/* The __attribute__((__warn_unused_result__)) feature
114290001Sglebius   is available in gcc versions 3.4 and newer,
115290001Sglebius   while the typeof feature has been available since 2.7 at least.  */
116290001Sglebius# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
117290001Sglebius#  define ignore_val(x) ((void) (x))
118290001Sglebius# else
119290001Sglebius#  define ignore_val(x) (({ __typeof__ (x) __x = (x); (void) __x; }))
120290001Sglebius# endif
121290001Sglebius
122181834Sroberto/*
123181834Sroberto *  Convert the number to a list usable in a printf call
124181834Sroberto */
125181834Sroberto#define NUM_TO_VER(n)           ((n) >> 12), ((n) >> 7) & 0x001F, (n) & 0x007F
126181834Sroberto
127181834Sroberto#define NAMED_OPTS(po) \
128181834Sroberto        (((po)->fOptSet & (OPTPROC_SHORTOPT | OPTPROC_LONGOPT)) == 0)
129181834Sroberto
130290001Sglebius#define SKIP_OPT(p)  (((p)->fOptState & OPTST_IMMUTABLE_MASK) != 0)
131181834Sroberto
132181834Srobertotypedef int tDirection;
133290001Sglebius/**
134290001Sglebius * handling option presets.  Start with command line and work through
135290001Sglebius * config settings in reverse order.
136290001Sglebius */
137181834Sroberto#define DIRECTION_PRESET        -1
138290001Sglebius/**
139290001Sglebius * handling normal options.  Start with first config file, then environment
140290001Sglebius * variables and finally the command line.
141290001Sglebius */
142181834Sroberto#define DIRECTION_PROCESS       1
143290001Sglebius/**
144290001Sglebius * An initialzation phase or an option being loaded from program sources.
145290001Sglebius */
146181834Sroberto#define DIRECTION_CALLED        0
147181834Sroberto
148181834Sroberto#define PROCESSING(d)           ((d)>0)
149181834Sroberto#define PRESETTING(d)           ((d)<0)
150290001Sglebius#define CALLED(d)               ((d)==0)
151181834Sroberto
152290001Sglebius/**
153181834Sroberto *  When loading a line (or block) of text as an option, the value can
154290001Sglebius *  be processed in any of several modes.
155181834Sroberto */
156181834Srobertotypedef enum {
157290001Sglebius    /**
158290001Sglebius     *  If the value looks like a quoted string, then process it.  Double
159290001Sglebius     *  quoted strings are processed the way strings are in "C" programs,
160290001Sglebius     *  except they are treated as regular characters if the following
161290001Sglebius     *  character is not a well-established escape sequence.  Single quoted
162290001Sglebius     *  strings (quoted with apostrophies) are handled the way strings are
163290001Sglebius     *  handled in shell scripts, *except* that backslash escapes are
164290001Sglebius     *  honored before backslash escapes and apostrophies.
165290001Sglebius     */
166181834Sroberto    OPTION_LOAD_COOKED,
167290001Sglebius
168290001Sglebius    /**
169290001Sglebius     * Even if the value begins with quote characters, do not do quote
170290001Sglebius     * processing.  Strip leading and trailing white space.
171290001Sglebius     */
172181834Sroberto    OPTION_LOAD_UNCOOKED,
173290001Sglebius
174290001Sglebius    /**
175290001Sglebius     * Keep every part of the value between the delimiters.
176290001Sglebius     */
177181834Sroberto    OPTION_LOAD_KEEP
178181834Sroberto} tOptionLoadMode;
179181834Sroberto
180290001Sglebiusstatic tOptionLoadMode option_load_mode;
181181834Sroberto
182290001Sglebius/**
183181834Sroberto *  The pager state is used by optionPagedUsage() procedure.
184181834Sroberto *  When it runs, it sets itself up to be called again on exit.
185181834Sroberto *  If, however, a routine needs a child process to do some work
186181834Sroberto *  before it is done, then 'pagerState' must be set to
187181834Sroberto *  'PAGER_STATE_CHILD' so that optionPagedUsage() will not try
188181834Sroberto *  to run the pager program before its time.
189181834Sroberto */
190181834Srobertotypedef enum {
191290001Sglebius    PAGER_STATE_INITIAL, //@< initial option paging state
192290001Sglebius
193290001Sglebius    /**
194290001Sglebius     * temp file created and optionPagedUsage is scheduled to run at exit
195290001Sglebius     */
196181834Sroberto    PAGER_STATE_READY,
197290001Sglebius
198290001Sglebius    /**
199290001Sglebius     *  This is a child process used in creating shell script usage.
200290001Sglebius     */
201181834Sroberto    PAGER_STATE_CHILD
202181834Sroberto} tePagerState;
203181834Sroberto
204181834Srobertotypedef enum {
205181834Sroberto    ENV_ALL,
206181834Sroberto    ENV_IMM,
207181834Sroberto    ENV_NON_IMM
208181834Sroberto} teEnvPresetType;
209181834Sroberto
210181834Srobertotypedef enum {
211181834Sroberto    TOPT_UNDEFINED = 0,
212181834Sroberto    TOPT_SHORT,
213181834Sroberto    TOPT_LONG,
214181834Sroberto    TOPT_DEFAULT
215181834Sroberto} teOptType;
216181834Sroberto
217181834Srobertotypedef struct {
218290001Sglebius    tOptDesc *          pOD;
219290001Sglebius    char const *        pzOptArg;
220290001Sglebius    opt_state_mask_t    flags;
221290001Sglebius    teOptType           optType;
222181834Sroberto} tOptState;
223181834Sroberto#define OPTSTATE_INITIALIZER(st) \
224181834Sroberto    { NULL, NULL, OPTST_ ## st, TOPT_UNDEFINED }
225181834Sroberto
226181834Sroberto#define TEXTTO_TABLE \
227290001Sglebius        _TT_(LONGUSAGE) \
228290001Sglebius        _TT_(USAGE) \
229290001Sglebius        _TT_(VERSION)
230181834Sroberto#define _TT_(n) \
231181834Sroberto        TT_ ## n ,
232181834Sroberto
233181834Srobertotypedef enum { TEXTTO_TABLE COUNT_TT } teTextTo;
234181834Sroberto
235181834Sroberto#undef _TT_
236181834Sroberto
237290001Sglebius/**
238290001Sglebius * option argument types.  Used to create usage information for
239290001Sglebius * particular options.
240290001Sglebius */
241181834Srobertotypedef struct {
242290001Sglebius    char const * pzStr;
243290001Sglebius    char const * pzReq;
244290001Sglebius    char const * pzNum;
245290001Sglebius    char const * pzFile;
246290001Sglebius    char const * pzKey;
247290001Sglebius    char const * pzKeyL;
248290001Sglebius    char const * pzBool;
249290001Sglebius    char const * pzNest;
250290001Sglebius    char const * pzOpt;
251290001Sglebius    char const * pzNo;
252290001Sglebius    char const * pzBrk;
253290001Sglebius    char const * pzNoF;
254290001Sglebius    char const * pzSpc;
255290001Sglebius    char const * pzOptFmt;
256290001Sglebius    char const * pzTime;
257181834Sroberto} arg_types_t;
258181834Sroberto
259290001Sglebius#define AGALOC(_c, _w)        ao_malloc((size_t)_c)
260290001Sglebius#define AGREALOC(_p, _c, _w)  ao_realloc(VOIDP(_p), (size_t)_c)
261290001Sglebius#define AGFREE(_p)            free(VOIDP(_p))
262290001Sglebius#define AGDUPSTR(_p, _s, _w)  (_p = ao_strdup(_s))
263181834Sroberto
264181834Srobertostatic void *
265290001Sglebiusao_malloc(size_t sz);
266181834Sroberto
267181834Srobertostatic void *
268290001Sglebiusao_realloc(void *p, size_t sz);
269181834Sroberto
270290001Sglebius#define ao_free(_p) free(VOIDP(_p))
271181834Sroberto
272181834Srobertostatic char *
273290001Sglebiusao_strdup(char const * str);
274181834Sroberto
275290001Sglebius/**
276181834Sroberto *  DO option handling?
277181834Sroberto *
278181834Sroberto *  Options are examined at two times:  at immediate handling time and at
279181834Sroberto *  normal handling time.  If an option is disabled, the timing may be
280181834Sroberto *  different from the handling of the undisabled option.  The OPTST_DIABLED
281181834Sroberto *  bit indicates the state of the currently discovered option.
282181834Sroberto *  So, here's how it works:
283181834Sroberto *
284181834Sroberto *  A) handling at "immediate" time, either 1 or 2:
285181834Sroberto *
286181834Sroberto *  1.  OPTST_DISABLED is not set:
287181834Sroberto *      IMM           must be set
288181834Sroberto *      DISABLE_IMM   don't care
289181834Sroberto *      TWICE         don't care
290181834Sroberto *      DISABLE_TWICE don't care
291181834Sroberto *      0 -and-  1 x x x
292181834Sroberto *
293181834Sroberto *  2.  OPTST_DISABLED is set:
294181834Sroberto *      IMM           don't care
295181834Sroberto *      DISABLE_IMM   must be set
296181834Sroberto *      TWICE         don't care
297181834Sroberto *      DISABLE_TWICE don't care
298181834Sroberto *      1 -and-  x 1 x x
299181834Sroberto */
300181834Sroberto#define DO_IMMEDIATELY(_flg) \
301181834Sroberto    (  (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == OPTST_IMM) \
302181834Sroberto    || (   ((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM))    \
303181834Sroberto        == (OPTST_DISABLED|OPTST_DISABLE_IMM)  ))
304181834Sroberto
305290001Sglebius/**
306290001Sglebius *  B) handling at "regular" time because it was not immediate
307181834Sroberto *
308181834Sroberto *  1.  OPTST_DISABLED is not set:
309181834Sroberto *      IMM           must *NOT* be set
310181834Sroberto *      DISABLE_IMM   don't care
311181834Sroberto *      TWICE         don't care
312181834Sroberto *      DISABLE_TWICE don't care
313181834Sroberto *      0 -and-  0 x x x
314181834Sroberto *
315181834Sroberto *  2.  OPTST_DISABLED is set:
316181834Sroberto *      IMM           don't care
317181834Sroberto *      DISABLE_IMM   don't care
318181834Sroberto *      TWICE         must be set
319181834Sroberto *      DISABLE_TWICE don't care
320181834Sroberto *      1 -and-  x x 1 x
321181834Sroberto */
322181834Sroberto#define DO_NORMALLY(_flg) ( \
323181834Sroberto       (((_flg) & (OPTST_DISABLED|OPTST_IMM))            == 0)  \
324181834Sroberto    || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM))    ==     \
325181834Sroberto                  OPTST_DISABLED)  )
326181834Sroberto
327290001Sglebius/**
328290001Sglebius *  C)  handling at "regular" time because it is to be handled twice.
329181834Sroberto *      The immediate bit was already tested and found to be set:
330181834Sroberto *
331181834Sroberto *  3.  OPTST_DISABLED is not set:
332181834Sroberto *      IMM           is set (but don't care)
333181834Sroberto *      DISABLE_IMM   don't care
334181834Sroberto *      TWICE         must be set
335181834Sroberto *      DISABLE_TWICE don't care
336181834Sroberto *      0 -and-  ? x 1 x
337181834Sroberto *
338181834Sroberto *  4.  OPTST_DISABLED is set:
339181834Sroberto *      IMM           don't care
340181834Sroberto *      DISABLE_IMM   is set (but don't care)
341181834Sroberto *      TWICE         don't care
342181834Sroberto *      DISABLE_TWICE must be set
343181834Sroberto *      1 -and-  x ? x 1
344181834Sroberto */
345181834Sroberto#define DO_SECOND_TIME(_flg) ( \
346181834Sroberto       (((_flg) & (OPTST_DISABLED|OPTST_TWICE))          ==     \
347181834Sroberto                  OPTST_TWICE)                                  \
348181834Sroberto    || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_TWICE))  ==     \
349181834Sroberto                  (OPTST_DISABLED|OPTST_DISABLE_TWICE)  ))
350181834Sroberto
351181834Sroberto/*
352181834Sroberto *  text_mmap structure.  Only active on platforms with mmap(2).
353181834Sroberto */
354181834Sroberto#ifdef HAVE_SYS_MMAN_H
355181834Sroberto#  include <sys/mman.h>
356181834Sroberto#else
357181834Sroberto#  ifndef  PROT_READ
358181834Sroberto#   define PROT_READ            0x01
359181834Sroberto#  endif
360181834Sroberto#  ifndef  PROT_WRITE
361181834Sroberto#   define PROT_WRITE           0x02
362181834Sroberto#  endif
363181834Sroberto#  ifndef  MAP_SHARED
364181834Sroberto#   define MAP_SHARED           0x01
365181834Sroberto#  endif
366181834Sroberto#  ifndef  MAP_PRIVATE
367181834Sroberto#   define MAP_PRIVATE          0x02
368181834Sroberto#  endif
369181834Sroberto#endif
370181834Sroberto
371181834Sroberto#ifndef MAP_FAILED
372290001Sglebius#  define  MAP_FAILED           VOIDP(-1)
373181834Sroberto#endif
374181834Sroberto
375181834Sroberto#ifndef  _SC_PAGESIZE
376181834Sroberto# ifdef  _SC_PAGE_SIZE
377181834Sroberto#  define _SC_PAGESIZE          _SC_PAGE_SIZE
378181834Sroberto# endif
379181834Sroberto#endif
380181834Sroberto
381181834Sroberto#ifndef HAVE_STRCHR
382290001Sglebiusextern char * strchr(char const * s, int c);
383290001Sglebiusextern char * strrchr(char const * s, int c);
384181834Sroberto#endif
385181834Sroberto
386290001Sglebius/**
387290001Sglebius * INQUERY_CALL() tests whether the option handling function has been
388290001Sglebius * called by an inquery (help text needed, or option being reset),
389290001Sglebius * or called by a set-the-option operation.
390290001Sglebius */
391290001Sglebius#define INQUERY_CALL(_o, _d) (                  \
392290001Sglebius    ((_o) <= OPTPROC_EMIT_LIMIT)                \
393290001Sglebius    || ((_d) == NULL)                           \
394290001Sglebius    || (((_d)->fOptState & OPTST_RESET) != 0) )
395290001Sglebius
396290001Sglebius/**
397181834Sroberto *  Define and initialize all the user visible strings.
398181834Sroberto *  We do not do translations.  If translations are to be done, then
399181834Sroberto *  the client will provide a callback for that purpose.
400181834Sroberto */
401181834Sroberto#undef DO_TRANSLATIONS
402181834Sroberto#include "autoopts/usage-txt.h"
403181834Sroberto
404290001Sglebius/**
405181834Sroberto *  File pointer for usage output
406181834Sroberto */
407290001SglebiusFILE * option_usage_fp;
408290001Sglebius/**
409290001Sglebius *  If provided in the option structure
410290001Sglebius */
411290001Sglebiusstatic char const * program_pkgdatadir;
412290001Sglebius/**
413290001Sglebius * privately exported functions
414290001Sglebius */
415181834Srobertoextern tOptProc optionPrintVersion, optionPagedUsage, optionLoadOpt;
416181834Sroberto
417290001Sglebius#ifdef AUTOOPTS_INTERNAL
418290001Sglebius
419290001Sglebius#ifndef PKGDATADIR
420290001Sglebius#  define PKGDATADIR ""
421290001Sglebius#endif
422290001Sglebius#define APOSTROPHE '\''
423290001Sglebius
424290001Sglebius#define OPTPROC_L_N_S  (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
425290001Sglebius#if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H)
426290001Sglebius# include <libintl.h>
427290001Sglebius#endif
428290001Sglebius
429290001Sglebiustypedef struct {
430290001Sglebius    size_t          fnm_len;
431290001Sglebius    uint32_t        fnm_mask;
432290001Sglebius    char const *    fnm_name;
433290001Sglebius} ao_flag_names_t;
434290001Sglebius
435290001Sglebius/**
436290001Sglebius * Automated Options Usage Flags.
437290001Sglebius * NB: no entry may be a prefix of another entry
438290001Sglebius */
439290001Sglebius#define AOFLAG_TABLE                            \
440290001Sglebius    _aof_(gnu,             OPTPROC_GNUUSAGE )   \
441290001Sglebius    _aof_(autoopts,        ~OPTPROC_GNUUSAGE)   \
442290001Sglebius    _aof_(no_misuse_usage, OPTPROC_MISUSE   )   \
443290001Sglebius    _aof_(misuse_usage,    ~OPTPROC_MISUSE  )   \
444290001Sglebius    _aof_(compute,         OPTPROC_COMPUTE  )
445290001Sglebius
446290001Sglebius#define _aof_(_n, _f)   AOUF_ ## _n ## _ID,
447290001Sglebiustypedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t;
448290001Sglebius#undef  _aof_
449290001Sglebius
450290001Sglebius#define _aof_(_n, _f)   AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID),
451290001Sglebiustypedef enum { AOFLAG_TABLE } ao_flags_t;
452290001Sglebius#undef  _aof_
453290001Sglebius
454290001Sglebiusstatic char const   zNil[] = "";
455290001Sglebiusstatic arg_types_t  argTypes             = { NULL };
456290001Sglebiusstatic char         line_fmt_buf[32];
457290001Sglebiusstatic bool         displayEnum          = false;
458290001Sglebiusstatic char const   pkgdatadir_default[] = PKGDATADIR;
459290001Sglebiusstatic char const * program_pkgdatadir   = pkgdatadir_default;
460290001Sglebiusstatic tOptionLoadMode option_load_mode  = OPTION_LOAD_UNCOOKED;
461290001Sglebiusstatic tePagerState pagerState           = PAGER_STATE_INITIAL;
462290001Sglebius
463290001Sglebius       FILE *       option_usage_fp      = NULL;
464290001Sglebius
465290001Sglebiusstatic char const * pz_enum_err_fmt;
466290001Sglebius
467290001SglebiustOptions * optionParseShellOptions = NULL;
468290001Sglebius
469290001Sglebiusstatic char const * shell_prog = NULL;
470290001Sglebiusstatic char * script_leader    = NULL;
471290001Sglebiusstatic char * script_trailer   = NULL;
472290001Sglebiusstatic char * script_text      = NULL;
473290001Sglebiusstatic bool   print_exit       = false;
474290001Sglebius#endif /* AUTOOPTS_INTERNAL */
475290001Sglebius
476181834Sroberto#endif /* AUTOGEN_AUTOOPTS_H */
477290001Sglebius/**
478290001Sglebius * @}
479181834Sroberto * Local Variables:
480181834Sroberto * mode: C
481181834Sroberto * c-file-style: "stroustrup"
482181834Sroberto * indent-tabs-mode: nil
483181834Sroberto * End:
484181834Sroberto * end of autoopts/autoopts.h */
485