xref: /freebsd/contrib/ntp/sntp/libopts/save-flags.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
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