xref: /netbsd-src/external/bsd/ntp/dist/sntp/libopts/save-flags.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: save-flags.c,v 1.2 2024/08/18 20:47:25 christos Exp $	*/
2897be3a4Schristos 
3897be3a4Schristos /*   -*- buffer-read-only: t -*- vi: set ro:
4897be3a4Schristos  *
5897be3a4Schristos  *  DO NOT EDIT THIS FILE   (save-flags.c)
6897be3a4Schristos  *
7897be3a4Schristos  *  It has been AutoGen-ed
8897be3a4Schristos  *  From the definitions    /tmp/.ag-ufBbQe/save-flags.def
9897be3a4Schristos  *  and the template file   str2enum
10897be3a4Schristos  *
11897be3a4Schristos  * Redistribution and use in source and binary forms, with or without
12897be3a4Schristos  * modification, are permitted provided that the following conditions
13897be3a4Schristos  * are met:
14897be3a4Schristos  * 1. Redistributions of source code must retain the above copyright
15897be3a4Schristos  *    notice, this list of conditions and the following disclaimer.
16897be3a4Schristos  * 2. Redistributions in binary form must reproduce the above copyright
17897be3a4Schristos  *    notice, this list of conditions and the following disclaimer in the
18897be3a4Schristos  *    documentation and/or other materials provided with the distribution.
19897be3a4Schristos  * 3. Neither the name ``Bruce Korb'' nor the name of any other
20897be3a4Schristos  *    contributor may be used to endorse or promote products derived
21897be3a4Schristos  *    from this software without specific prior written permission.
22897be3a4Schristos  *
23897be3a4Schristos  * str2enum IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS
24897be3a4Schristos  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25897be3a4Schristos  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26897be3a4Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS
27897be3a4Schristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28897be3a4Schristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29897be3a4Schristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30897be3a4Schristos  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31897be3a4Schristos  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32897be3a4Schristos  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33897be3a4Schristos  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34897be3a4Schristos  */
35897be3a4Schristos #include "save-flags.h"
36897be3a4Schristos #include <sys/types.h>
37897be3a4Schristos #ifndef MISSING_INTTYPES_H
38897be3a4Schristos # include <inttypes.h>
39897be3a4Schristos #endif
40897be3a4Schristos 
41897be3a4Schristos typedef enum {
42897be3a4Schristos     SVFL_BNM_DEFAULT  = 0,
43897be3a4Schristos     SVFL_BNM_USAGE    = 1,
44897be3a4Schristos     SVFL_BNM_UPDATE   = 2,
45897be3a4Schristos     SVFL_COUNT_BNM
46897be3a4Schristos } save_flags_enum_t;
47897be3a4Schristos 
48897be3a4Schristos static save_flags_enum_t
49897be3a4Schristos find_save_flags_bnm(char const * str, size_t len);
50897be3a4Schristos 
51897be3a4Schristos 
52897be3a4Schristos #include <sys/types.h>
53897be3a4Schristos #include <string.h>
54897be3a4Schristos #ifndef NUL
55897be3a4Schristos #define NUL '\0'
56897be3a4Schristos #endif
57897be3a4Schristos 
58897be3a4Schristos /* ANSI-C code produced by gperf version 3.1 */
59897be3a4Schristos /* Command-line: gperf save-flags.gp  */
60897be3a4Schristos /* Computed positions: -k'' */
61897be3a4Schristos 
62897be3a4Schristos 
63897be3a4Schristos # if 0 /* gperf build options: */
64897be3a4Schristos // %struct-type
65897be3a4Schristos // %language=ANSI-C
66897be3a4Schristos // %includes
67897be3a4Schristos // %global-table
68897be3a4Schristos // %omit-struct-type
69897be3a4Schristos // %readonly-tables
70897be3a4Schristos // %compare-strncmp
71897be3a4Schristos //
72897be3a4Schristos // %define slot-name               svfl_name
73897be3a4Schristos // %define hash-function-name      save_flags_hash
74897be3a4Schristos // %define lookup-function-name    find_save_flags_name
75897be3a4Schristos // %define word-array-name         save_flags_table
76897be3a4Schristos // %define initializer-suffix      ,SVFL_COUNT_BNM
77897be3a4Schristos //
78897be3a4Schristos # endif
79897be3a4Schristos 
80897be3a4Schristos #include "save-flags.h"
81897be3a4Schristos typedef struct {
82897be3a4Schristos     char const *    svfl_name;
83897be3a4Schristos     save_flags_enum_t svfl_id;
84897be3a4Schristos } save_flags_map_t;
85897be3a4Schristos #include <string.h>
86897be3a4Schristos 
87897be3a4Schristos /* maximum key range = 3, duplicates = 0 */
88897be3a4Schristos 
89897be3a4Schristos static unsigned int
90897be3a4Schristos save_flags_hash (register const char *str, register size_t len)
91897be3a4Schristos {
92897be3a4Schristos   (void)str;
93897be3a4Schristos   (void)len;
94897be3a4Schristos   return len;
95897be3a4Schristos }
96897be3a4Schristos 
97897be3a4Schristos static const save_flags_map_t save_flags_table[] =
98897be3a4Schristos   {
99897be3a4Schristos     {"",SVFL_COUNT_BNM}, {"",SVFL_COUNT_BNM},
100897be3a4Schristos     {"",SVFL_COUNT_BNM}, {"",SVFL_COUNT_BNM},
101897be3a4Schristos     {"",SVFL_COUNT_BNM},
102897be3a4Schristos     {"usage",    SVFL_BNM_USAGE},
103897be3a4Schristos     {"update",   SVFL_BNM_UPDATE},
104897be3a4Schristos     {"default",  SVFL_BNM_DEFAULT}
105897be3a4Schristos   };
106897be3a4Schristos 
107897be3a4Schristos static inline const save_flags_map_t *
108897be3a4Schristos find_save_flags_name (register const char *str, register size_t len)
109897be3a4Schristos {
110897be3a4Schristos   if (len <= 7 && len >= 5)
111897be3a4Schristos     {
112897be3a4Schristos       register unsigned int key = (int)save_flags_hash (str, len);
113897be3a4Schristos 
114897be3a4Schristos       if (key <= 7)
115897be3a4Schristos         {
116897be3a4Schristos           register const char *s = save_flags_table[key].svfl_name;
117897be3a4Schristos 
118897be3a4Schristos           if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
119897be3a4Schristos             return &save_flags_table[key];
120897be3a4Schristos         }
121897be3a4Schristos     }
122897be3a4Schristos   return 0;
123897be3a4Schristos }
124897be3a4Schristos 
125897be3a4Schristos /**
126897be3a4Schristos  * Convert a command (keyword) to a save_flags_enum_t enumeration value.
127897be3a4Schristos  *
128897be3a4Schristos  * @param[in] str   a string that should start with a known key word.
129897be3a4Schristos  * @param[in] len   the provided length of the keyword at \a str.
130897be3a4Schristos  * @returns the enumeration value.
131897be3a4Schristos  * If not found, that value is SVFL_COUNT_BNM.
132897be3a4Schristos  */
133897be3a4Schristos static save_flags_enum_t
134897be3a4Schristos find_save_flags_bnm(char const * str, size_t len)
135897be3a4Schristos {
136897be3a4Schristos     save_flags_map_t const * map;
137897be3a4Schristos 
138897be3a4Schristos     map = find_save_flags_name(str, (unsigned int)len);
139897be3a4Schristos     if (map != NULL)
140897be3a4Schristos         return map->svfl_id;
141897be3a4Schristos     /* Check for a partial match */
142897be3a4Schristos     {
143897be3a4Schristos         /*
144897be3a4Schristos          * Indexes of valid save_flags_table entries in sorted order:
145897be3a4Schristos          */
146897be3a4Schristos         static unsigned int const ix_map[] = {
147897be3a4Schristos             7, 6, 5 };
148897be3a4Schristos         save_flags_enum_t res = SVFL_COUNT_BNM;
149897be3a4Schristos         static int const HI = (sizeof(ix_map) / sizeof(ix_map[0])) - 1;
150897be3a4Schristos         int lo = 0;
151897be3a4Schristos         int hi = HI;
152897be3a4Schristos         int av;
153897be3a4Schristos         int cmp;
154897be3a4Schristos 
155897be3a4Schristos         for (;;) {
156897be3a4Schristos             av  = (hi + lo) / 2;
157897be3a4Schristos             map = save_flags_table + ix_map[av];
158897be3a4Schristos             cmp = strncmp(map->svfl_name, str, len);
159897be3a4Schristos             if (cmp == 0) break;
160897be3a4Schristos             if (cmp > 0)
161897be3a4Schristos                  hi = av - 1;
162897be3a4Schristos             else lo = av + 1;
163897be3a4Schristos             if (lo > hi)
164897be3a4Schristos                 return SVFL_COUNT_BNM;
165897be3a4Schristos         }
166897be3a4Schristos         res = map->svfl_id;
167897be3a4Schristos         /*
168897be3a4Schristos          * If we have an exact match, accept it.
169897be3a4Schristos          */
170897be3a4Schristos         if (map->svfl_name[len] == NUL)
171897be3a4Schristos             return res;
172897be3a4Schristos         /*
173897be3a4Schristos          * Check for a duplicate partial match (a partial match
174897be3a4Schristos          * with a higher or lower index than "av".
175897be3a4Schristos          */
176897be3a4Schristos         if (av < HI) {
177897be3a4Schristos             map = save_flags_table + ix_map[av + 1];
178897be3a4Schristos             if (strncmp(map->svfl_name, str, len) == 0)
179897be3a4Schristos                 return SVFL_COUNT_BNM;
180897be3a4Schristos         }
181897be3a4Schristos         if (av > 0) {
182897be3a4Schristos             map = save_flags_table + ix_map[av - 1];
183897be3a4Schristos             if (strncmp(map->svfl_name, str, len) == 0)
184897be3a4Schristos                 return SVFL_COUNT_BNM;
185897be3a4Schristos         }
186897be3a4Schristos         return res;
187897be3a4Schristos     }
188897be3a4Schristos }
189897be3a4Schristos 
190897be3a4Schristos /**
191897be3a4Schristos  * Convert a string to a save_flags_mask_t mask.
192897be3a4Schristos  * Bit names prefixed with a hyphen have the bit removed from the mask.
193897be3a4Schristos  * If the string starts with a '-', '+' or '|' character, then
194897be3a4Schristos  * the old value is used as a base, otherwise the result mask
195897be3a4Schristos  * is initialized to zero.  Separating bit names with '+' or '|'
196897be3a4Schristos  * characters is optional.  By default, the bits are "or"-ed into the
197897be3a4Schristos  * result.
198897be3a4Schristos  *
199897be3a4Schristos  * @param[in] str string with a list of bit names
200897be3a4Schristos  * @param[in] old previous value, used if \a str starts with a '+' or '-'.
201897be3a4Schristos  *
202897be3a4Schristos  * @returns an unsigned integer with the bits set.
203897be3a4Schristos  */
204897be3a4Schristos save_flags_mask_t
205897be3a4Schristos save_flags_str2mask(char const * str, save_flags_mask_t old)
206897be3a4Schristos {
207897be3a4Schristos     static char const white[] = ", \t\f";
208897be3a4Schristos     static char const name_chars[] =
209897be3a4Schristos         "adefglpstu"
210897be3a4Schristos         "ADEFGLPSTU";
211897be3a4Schristos 
212897be3a4Schristos     save_flags_mask_t res = 0;
213897be3a4Schristos     int have_data = 0;
214897be3a4Schristos 
215897be3a4Schristos     for (;;) {
216897be3a4Schristos         save_flags_enum_t val;
217897be3a4Schristos         unsigned int val_len;
218897be3a4Schristos         unsigned int invert = 0;
219897be3a4Schristos 
220897be3a4Schristos         str += strspn(str, white);
221897be3a4Schristos         switch (*str) {
222897be3a4Schristos         case NUL: return res;
223897be3a4Schristos         case '-': case '~':
224897be3a4Schristos             invert = 1;
225897be3a4Schristos             /* FALLTHROUGH */
226897be3a4Schristos 
227897be3a4Schristos         case '+': case '|':
228897be3a4Schristos             if (have_data == 0)
229897be3a4Schristos                 res = old;
230897be3a4Schristos 
231897be3a4Schristos             str += 1 + strspn(str + 1, white);
232897be3a4Schristos             if (*str == NUL)
233897be3a4Schristos                 return 0;
234897be3a4Schristos         }
235897be3a4Schristos 
236897be3a4Schristos         val_len = strspn(str, name_chars);
237897be3a4Schristos         if (val_len == 0)
238897be3a4Schristos             return 0;
239897be3a4Schristos         val = find_save_flags_bnm(str, val_len);
240897be3a4Schristos         if (val == SVFL_COUNT_BNM)
241897be3a4Schristos             return 0;
242897be3a4Schristos         if (invert)
243897be3a4Schristos             res &= ~((save_flags_mask_t)1 << val);
244897be3a4Schristos         else
245897be3a4Schristos             res |= (save_flags_mask_t)1 << val;
246897be3a4Schristos         have_data = 1;
247897be3a4Schristos         str += val_len;
248897be3a4Schristos     }
249897be3a4Schristos }
250897be3a4Schristos /* end of save-flags.c */
251