/src/ntp-dev/sntp/libopts/save-flags.c
Line | Count | Source |
1 | | /* -*- buffer-read-only: t -*- vi: set ro: |
2 | | * |
3 | | * DO NOT EDIT THIS FILE (save-flags.c) |
4 | | * |
5 | | * It has been AutoGen-ed |
6 | | * From the definitions /tmp/.ag-ufBbQe/save-flags.def |
7 | | * and the template file str2enum |
8 | | * |
9 | | * Redistribution and use in source and binary forms, with or without |
10 | | * modification, are permitted provided that the following conditions |
11 | | * are met: |
12 | | * 1. Redistributions of source code must retain the above copyright |
13 | | * notice, this list of conditions and the following disclaimer. |
14 | | * 2. Redistributions in binary form must reproduce the above copyright |
15 | | * notice, this list of conditions and the following disclaimer in the |
16 | | * documentation and/or other materials provided with the distribution. |
17 | | * 3. Neither the name ``Bruce Korb'' nor the name of any other |
18 | | * contributor may be used to endorse or promote products derived |
19 | | * from this software without specific prior written permission. |
20 | | * |
21 | | * str2enum IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS |
22 | | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
23 | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | | * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS |
25 | | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
28 | | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
29 | | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
30 | | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
31 | | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | | */ |
33 | | #include "save-flags.h" |
34 | | #include <sys/types.h> |
35 | | #ifndef MISSING_INTTYPES_H |
36 | | # include <inttypes.h> |
37 | | #endif |
38 | | |
39 | | typedef enum { |
40 | | SVFL_BNM_DEFAULT = 0, |
41 | | SVFL_BNM_USAGE = 1, |
42 | | SVFL_BNM_UPDATE = 2, |
43 | | SVFL_COUNT_BNM |
44 | | } save_flags_enum_t; |
45 | | |
46 | | static save_flags_enum_t |
47 | | find_save_flags_bnm(char const * str, size_t len); |
48 | | |
49 | | |
50 | | #include <sys/types.h> |
51 | | #include <string.h> |
52 | | #ifndef NUL |
53 | | #define NUL '\0' |
54 | | #endif |
55 | | |
56 | | /* ANSI-C code produced by gperf version 3.1 */ |
57 | | /* Command-line: gperf save-flags.gp */ |
58 | | /* Computed positions: -k'' */ |
59 | | |
60 | | |
61 | | # if 0 /* gperf build options: */ |
62 | | // %struct-type |
63 | | // %language=ANSI-C |
64 | | // %includes |
65 | | // %global-table |
66 | | // %omit-struct-type |
67 | | // %readonly-tables |
68 | | // %compare-strncmp |
69 | | // |
70 | | // %define slot-name svfl_name |
71 | | // %define hash-function-name save_flags_hash |
72 | | // %define lookup-function-name find_save_flags_name |
73 | | // %define word-array-name save_flags_table |
74 | | // %define initializer-suffix ,SVFL_COUNT_BNM |
75 | | // |
76 | | # endif |
77 | | |
78 | | #include "save-flags.h" |
79 | | typedef struct { |
80 | | char const * svfl_name; |
81 | | save_flags_enum_t svfl_id; |
82 | | } save_flags_map_t; |
83 | | #include <string.h> |
84 | | |
85 | | /* maximum key range = 3, duplicates = 0 */ |
86 | | |
87 | | static unsigned int |
88 | | save_flags_hash (register const char *str, register size_t len) |
89 | 0 | { |
90 | 0 | (void)str; |
91 | 0 | (void)len; |
92 | 0 | return len; |
93 | 0 | } |
94 | | |
95 | | static const save_flags_map_t save_flags_table[] = |
96 | | { |
97 | | {"",SVFL_COUNT_BNM}, {"",SVFL_COUNT_BNM}, |
98 | | {"",SVFL_COUNT_BNM}, {"",SVFL_COUNT_BNM}, |
99 | | {"",SVFL_COUNT_BNM}, |
100 | | {"usage", SVFL_BNM_USAGE}, |
101 | | {"update", SVFL_BNM_UPDATE}, |
102 | | {"default", SVFL_BNM_DEFAULT} |
103 | | }; |
104 | | |
105 | | static inline const save_flags_map_t * |
106 | | find_save_flags_name (register const char *str, register size_t len) |
107 | 0 | { |
108 | 0 | if (len <= 7 && len >= 5) |
109 | 0 | { |
110 | 0 | register unsigned int key = (int)save_flags_hash (str, len); |
111 | |
|
112 | 0 | if (key <= 7) |
113 | 0 | { |
114 | 0 | register const char *s = save_flags_table[key].svfl_name; |
115 | |
|
116 | 0 | if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') |
117 | 0 | return &save_flags_table[key]; |
118 | 0 | } |
119 | 0 | } |
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | | /** |
124 | | * Convert a command (keyword) to a save_flags_enum_t enumeration value. |
125 | | * |
126 | | * @param[in] str a string that should start with a known key word. |
127 | | * @param[in] len the provided length of the keyword at \a str. |
128 | | * @returns the enumeration value. |
129 | | * If not found, that value is SVFL_COUNT_BNM. |
130 | | */ |
131 | | static save_flags_enum_t |
132 | | find_save_flags_bnm(char const * str, size_t len) |
133 | 0 | { |
134 | 0 | save_flags_map_t const * map; |
135 | |
|
136 | 0 | map = find_save_flags_name(str, (unsigned int)len); |
137 | 0 | if (map != NULL) |
138 | 0 | return map->svfl_id; |
139 | | /* Check for a partial match */ |
140 | 0 | { |
141 | | /* |
142 | | * Indexes of valid save_flags_table entries in sorted order: |
143 | | */ |
144 | 0 | static unsigned int const ix_map[] = { |
145 | 0 | 7, 6, 5 }; |
146 | 0 | save_flags_enum_t res = SVFL_COUNT_BNM; |
147 | 0 | static int const HI = (sizeof(ix_map) / sizeof(ix_map[0])) - 1; |
148 | 0 | int lo = 0; |
149 | 0 | int hi = HI; |
150 | 0 | int av; |
151 | 0 | int cmp; |
152 | |
|
153 | 0 | for (;;) { |
154 | 0 | av = (hi + lo) / 2; |
155 | 0 | map = save_flags_table + ix_map[av]; |
156 | 0 | cmp = strncmp(map->svfl_name, str, len); |
157 | 0 | if (cmp == 0) break; |
158 | 0 | if (cmp > 0) |
159 | 0 | hi = av - 1; |
160 | 0 | else lo = av + 1; |
161 | 0 | if (lo > hi) |
162 | 0 | return SVFL_COUNT_BNM; |
163 | 0 | } |
164 | 0 | res = map->svfl_id; |
165 | | /* |
166 | | * If we have an exact match, accept it. |
167 | | */ |
168 | 0 | if (map->svfl_name[len] == NUL) |
169 | 0 | return res; |
170 | | /* |
171 | | * Check for a duplicate partial match (a partial match |
172 | | * with a higher or lower index than "av". |
173 | | */ |
174 | 0 | if (av < HI) { |
175 | 0 | map = save_flags_table + ix_map[av + 1]; |
176 | 0 | if (strncmp(map->svfl_name, str, len) == 0) |
177 | 0 | return SVFL_COUNT_BNM; |
178 | 0 | } |
179 | 0 | if (av > 0) { |
180 | 0 | map = save_flags_table + ix_map[av - 1]; |
181 | 0 | if (strncmp(map->svfl_name, str, len) == 0) |
182 | 0 | return SVFL_COUNT_BNM; |
183 | 0 | } |
184 | 0 | return res; |
185 | 0 | } |
186 | 0 | } |
187 | | |
188 | | /** |
189 | | * Convert a string to a save_flags_mask_t mask. |
190 | | * Bit names prefixed with a hyphen have the bit removed from the mask. |
191 | | * If the string starts with a '-', '+' or '|' character, then |
192 | | * the old value is used as a base, otherwise the result mask |
193 | | * is initialized to zero. Separating bit names with '+' or '|' |
194 | | * characters is optional. By default, the bits are "or"-ed into the |
195 | | * result. |
196 | | * |
197 | | * @param[in] str string with a list of bit names |
198 | | * @param[in] old previous value, used if \a str starts with a '+' or '-'. |
199 | | * |
200 | | * @returns an unsigned integer with the bits set. |
201 | | */ |
202 | | save_flags_mask_t |
203 | | save_flags_str2mask(char const * str, save_flags_mask_t old) |
204 | 0 | { |
205 | 0 | static char const white[] = ", \t\f"; |
206 | 0 | static char const name_chars[] = |
207 | 0 | "adefglpstu" |
208 | 0 | "ADEFGLPSTU"; |
209 | |
|
210 | 0 | save_flags_mask_t res = 0; |
211 | 0 | int have_data = 0; |
212 | |
|
213 | 0 | for (;;) { |
214 | 0 | save_flags_enum_t val; |
215 | 0 | unsigned int val_len; |
216 | 0 | unsigned int invert = 0; |
217 | |
|
218 | 0 | str += strspn(str, white); |
219 | 0 | switch (*str) { |
220 | 0 | case NUL: return res; |
221 | 0 | case '-': case '~': |
222 | 0 | invert = 1; |
223 | | /* FALLTHROUGH */ |
224 | |
|
225 | 0 | case '+': case '|': |
226 | 0 | if (have_data == 0) |
227 | 0 | res = old; |
228 | |
|
229 | 0 | str += 1 + strspn(str + 1, white); |
230 | 0 | if (*str == NUL) |
231 | 0 | return 0; |
232 | 0 | } |
233 | | |
234 | 0 | val_len = strspn(str, name_chars); |
235 | 0 | if (val_len == 0) |
236 | 0 | return 0; |
237 | 0 | val = find_save_flags_bnm(str, val_len); |
238 | 0 | if (val == SVFL_COUNT_BNM) |
239 | 0 | return 0; |
240 | 0 | if (invert) |
241 | 0 | res &= ~((save_flags_mask_t)1 << val); |
242 | 0 | else |
243 | 0 | res |= (save_flags_mask_t)1 << val; |
244 | 0 | have_data = 1; |
245 | 0 | str += val_len; |
246 | 0 | } |
247 | 0 | } |
248 | | /* end of save-flags.c */ |