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