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