File: getopt.h

package info (click to toggle)
scrypt 1.2.0%2Bgit.3.c1a9826-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 456 kB
  • ctags: 328
  • sloc: ansic: 3,307; sh: 391; makefile: 103
file content (175 lines) | stat: -rw-r--r-- 5,919 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#ifndef _GETOPT_H_
#define _GETOPT_H_

#include <setjmp.h>
#include <stddef.h>

/**
 * This getopt implementation parses options of the following forms:
 * -a -b -c foo		(single-character options)
 * -abc foo		(packed single-character options)
 * -abcfoo		(packed single-character options and an argument)
 * --foo bar		(long option)
 * --foo=bar		(long option and argument separated by '=')
 *
 * It does not support abbreviated options (e.g., interpreting --foo as
 * --foobar when there are no other --foo* options) since that misfeature
 * results in breakage when new options are added.  It also does not support
 * options appearing after non-options (e.g., "cp foo bar -R") since that is
 * a horrible GNU perversion.
 */

/* Work around LLVM bug. */
#ifdef __clang__
#warning Working around bug in LLVM optimizer
#warning For more details see https://llvm.org/bugs/show_bug.cgi?id=27190
#define DO_SETJMP _DO_SETJMP(__LINE__)
#define _DO_SETJMP(x) __DO_SETJMP(x)
#define __DO_SETJMP(x)							\
	void * getopt_initloop = && getopt_initloop_ ## x;		\
	getopt_initloop_ ## x:
#define DO_LONGJMP							\
	goto *getopt_initloop
#else
#define DO_SETJMP							\
	sigjmp_buf getopt_initloop;					\
	if (!getopt_initialized)					\
		sigsetjmp(getopt_initloop, 0)
#define DO_LONGJMP							\
	siglongjmp(getopt_initloop, 1)
#endif

/* Avoid namespace collisions with libc getopt. */
#define getopt	libcperciva_getopt
#define optarg	libcperciva_optarg
#define optind	libcperciva_optind
#define opterr	libcperciva_opterr
#define optreset	libcperciva_optreset

/* Standard getopt global variables. */
extern const char * optarg;
extern int optind, opterr, optreset;

/* Dummy option string, equal to "(dummy)". */
#define GETOPT_DUMMY getopt_dummy

/**
 * GETOPT(argc, argv):
 * When called for the first time (or the first time after optreset is set to
 * a nonzero value), return GETOPT_DUMMY, aka. "(dummy)".  Thereafter, return
 * the next option string and set optarg / optind appropriately; abort if not
 * properly initialized when not being called for the first time.
 */
#define GETOPT(argc, argv) getopt(argc, argv)

/**
 * GETOPT_SWITCH(ch):
 * Jump to the appropriate GETOPT_OPT, GETOPT_OPTARG, GETOPT_MISSING_ARG, or
 * GETOPT_DEFAULT based on the option string ${ch}.  When called for the first
 * time, perform magic to index the options.
 *
 * GETOPT_SWITCH(ch) is equivalent to "switch (ch)" in a standard getopt loop.
 */
#define GETOPT_SWITCH(ch)						\
	volatile size_t getopt_ln_min = __LINE__;			\
	volatile size_t getopt_ln = getopt_ln_min - 1;		\
	volatile int getopt_default_missing = 0;			\
	DO_SETJMP;						\
	switch (getopt_initialized ? getopt_lookup(ch) + getopt_ln_min : getopt_ln++)

/**
 * GETOPT_OPT(os):
 * Jump to this point when the option string ${os} is passed to GETOPT_SWITCH.
 *
 * GETOPT_OPT("-x") is equivalent to "case 'x'" in a standard getopt loop
 * which has an optstring containing "x".
 */
#define GETOPT_OPT(os)	_GETOPT_OPT(os, __LINE__)
#define _GETOPT_OPT(os, ln)	__GETOPT_OPT(os, ln)
#define __GETOPT_OPT(os, ln)						\
	case ln:							\
		if (getopt_initialized)					\
			goto getopt_skip_ ## ln;			\
		getopt_register_opt(os, ln - getopt_ln_min, 0);		\
		DO_LONGJMP;						\
	getopt_skip_ ## ln

/**
 * GETOPT_OPTARG(os):
 * Jump to this point when the option string ${os} is passed to GETOPT_SWITCH,
 * unless no argument is available, in which case jump to GETOPT_MISSING_ARG
 * (if present) or GETOPT_DEFAULT (if not).
 *
 * GETOPT_OPTARG("-x") is equivalent to "case 'x'" in a standard getopt loop
 * which has an optstring containing "x:".
 */
#define GETOPT_OPTARG(os)	_GETOPT_OPTARG(os, __LINE__)
#define _GETOPT_OPTARG(os, ln)	__GETOPT_OPTARG(os, ln)
#define __GETOPT_OPTARG(os, ln)						\
	case ln:							\
		if (getopt_initialized)					\
			goto getopt_skip_ ## ln;			\
		getopt_register_opt(os, ln - getopt_ln_min, 1);		\
		DO_LONGJMP;						\
	getopt_skip_ ## ln

/**
 * GETOPT_MISSING_ARG:
 * Jump to this point if an option string specified in GETOPT_OPTARG is seen
 * but no argument is available.
 *
 * GETOPT_MISSING_ARG is equivalent to "case ':'" in a standard getopt loop
 * which has an optstring starting with ":".  As such, it also has the effect
 * of disabling warnings about invalid options, as if opterr had been zeroed.
 */
#define GETOPT_MISSING_ARG	_GETOPT_MISSING_ARG(__LINE__)
#define _GETOPT_MISSING_ARG(ln)	__GETOPT_MISSING_ARG(ln)
#define __GETOPT_MISSING_ARG(ln)					\
	case ln:							\
		if (getopt_initialized)					\
			goto getopt_skip_ ## ln;			\
		getopt_register_missing(ln - getopt_ln_min);		\
		DO_LONGJMP;						\
	getopt_skip_ ## ln

/**
 * GETOPT_DEFAULT:
 * Jump to this point if an unrecognized option is seen or if an option
 * specified in GETOPT_OPTARG is seen, no argument is available, and there is
 * no GETOPT_MISSING_ARG label.
 *
 * GETOPT_DEFAULT is equivalent to "case '?'" in a standard getopt loop.
 *
 * NOTE: This MUST be present in the GETOPT_SWITCH statement, and MUST occur
 * after all other GETOPT_* labels.
 */
#define GETOPT_DEFAULT		_GETOPT_DEFAULT(__LINE__)
#define _GETOPT_DEFAULT(ln)	__GETOPT_DEFAULT(ln)
#define __GETOPT_DEFAULT(ln)						\
		goto getopt_skip_ ## ln;				\
	case ln:							\
		getopt_initialized = 1;					\
		break;							\
	default:							\
		if (getopt_initialized)					\
			goto getopt_skip_ ## ln;			\
		if (!getopt_default_missing) {				\
			getopt_setrange(ln - getopt_ln_min);		\
			getopt_default_missing = 1;			\
		}							\
		DO_LONGJMP;						\
	getopt_skip_ ## ln

/*
 * The back-end implementation.  These should be considered internal
 * interfaces and not used directly.
 */
const char * getopt(int, char * const []);
size_t getopt_lookup(const char *);
void getopt_register_opt(const char *, size_t, int);
void getopt_register_missing(size_t);
void getopt_setrange(size_t);
extern const char * getopt_dummy;
extern int getopt_initialized;

#endif /* !_GETOPT_H_ */