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