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