xref: /freebsd/contrib/ntp/sntp/libopts/save-flags.c (revision bdd1243d)
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 {
90   (void)str;
91   (void)len;
92   return len;
93 }
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 {
108   if (len <= 7 && len >= 5)
109     {
110       register unsigned int key = (int)save_flags_hash (str, len);
111 
112       if (key <= 7)
113         {
114           register const char *s = save_flags_table[key].svfl_name;
115 
116           if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
117             return &save_flags_table[key];
118         }
119     }
120   return 0;
121 }
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 {
134     save_flags_map_t const * map;
135 
136     map = find_save_flags_name(str, (unsigned int)len);
137     if (map != NULL)
138         return map->svfl_id;
139     /* Check for a partial match */
140     {
141         /*
142          * Indexes of valid save_flags_table entries in sorted order:
143          */
144         static unsigned int const ix_map[] = {
145             7, 6, 5 };
146         save_flags_enum_t res = SVFL_COUNT_BNM;
147         static int const HI = (sizeof(ix_map) / sizeof(ix_map[0])) - 1;
148         int lo = 0;
149         int hi = HI;
150         int av;
151         int cmp;
152 
153         for (;;) {
154             av  = (hi + lo) / 2;
155             map = save_flags_table + ix_map[av];
156             cmp = strncmp(map->svfl_name, str, len);
157             if (cmp == 0) break;
158             if (cmp > 0)
159                  hi = av - 1;
160             else lo = av + 1;
161             if (lo > hi)
162                 return SVFL_COUNT_BNM;
163         }
164         res = map->svfl_id;
165         /*
166          * If we have an exact match, accept it.
167          */
168         if (map->svfl_name[len] == NUL)
169             return res;
170         /*
171          * Check for a duplicate partial match (a partial match
172          * with a higher or lower index than "av".
173          */
174         if (av < HI) {
175             map = save_flags_table + ix_map[av + 1];
176             if (strncmp(map->svfl_name, str, len) == 0)
177                 return SVFL_COUNT_BNM;
178         }
179         if (av > 0) {
180             map = save_flags_table + ix_map[av - 1];
181             if (strncmp(map->svfl_name, str, len) == 0)
182                 return SVFL_COUNT_BNM;
183         }
184         return res;
185     }
186 }
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 {
205     static char const white[] = ", \t\f";
206     static char const name_chars[] =
207         "adefglpstu"
208         "ADEFGLPSTU";
209 
210     save_flags_mask_t res = 0;
211     int have_data = 0;
212 
213     for (;;) {
214         save_flags_enum_t val;
215         unsigned int val_len;
216         unsigned int invert = 0;
217 
218         str += strspn(str, white);
219         switch (*str) {
220         case NUL: return res;
221         case '-': case '~':
222             invert = 1;
223             /* FALLTHROUGH */
224 
225         case '+': case '|':
226             if (have_data == 0)
227                 res = old;
228 
229             str += 1 + strspn(str + 1, white);
230             if (*str == NUL)
231                 return 0;
232         }
233 
234         val_len = strspn(str, name_chars);
235         if (val_len == 0)
236             return 0;
237         val = find_save_flags_bnm(str, val_len);
238         if (val == SVFL_COUNT_BNM)
239             return 0;
240         if (invert)
241             res &= ~((save_flags_mask_t)1 << val);
242         else
243             res |= (save_flags_mask_t)1 << val;
244         have_data = 1;
245         str += val_len;
246     }
247 }
248 /* end of save-flags.c */
249