1 /* This file provides functionality to parse strings of comma-separated 2 * options, each being either a single key name or a key=value pair, where the 3 * value may be enclosed in quotes. A table of optset entries is provided to 4 * determine which options are recognized, how to parse their values, and where 5 * to store those. Unrecognized options are silently ignored; improperly 6 * formatted options are silently set to reasonably acceptable values. 7 * 8 * The entry points into this file are: 9 * optset_parse parse the given options string using the given table 10 * 11 * Created: 12 * May 2009 (D.C. van Moolenbroek) 13 */ 14 15 #include <stdlib.h> 16 #include <string.h> 17 #include <minix/config.h> 18 #include <minix/const.h> 19 #include <minix/optset.h> 20 21 static void optset_parse_entry(struct optset *entry, char *ptr, int len); 22 23 /*===========================================================================* 24 * optset_parse_entry * 25 *===========================================================================*/ 26 static void optset_parse_entry(struct optset *entry, char *ptr, int len) 27 { 28 /* Parse and store the value of a single option. 29 */ 30 char *dst; 31 int val; 32 33 switch (entry->os_type) { 34 case OPT_BOOL: 35 *((int *) entry->os_ptr) = entry->os_val; 36 37 break; 38 39 case OPT_STRING: 40 if (len >= entry->os_val) 41 len = entry->os_val - 1; 42 43 dst = (char *) entry->os_ptr; 44 45 if (len > 0) 46 memcpy(dst, ptr, len); 47 dst[len] = 0; 48 49 break; 50 51 case OPT_INT: 52 if (len > 0) 53 val = (int) strtoul(ptr, NULL, entry->os_val); 54 else 55 val = 0; 56 57 *((int *) entry->os_ptr) = val; 58 59 break; 60 } 61 } 62 63 /*===========================================================================* 64 * optset_parse * 65 *===========================================================================*/ 66 void optset_parse(struct optset *table, char *string) 67 { 68 /* Parse a string of options, using the provided table of optset entries. 69 */ 70 char *p, *kptr, *vptr; 71 int i, klen, vlen; 72 73 for (p = string; *p; ) { 74 /* Get the key name for the field. */ 75 for (kptr = p, klen = 0; *p && *p != '=' && *p != ','; p++, klen++); 76 77 if (*p == '=') { 78 /* The field has an associated value. */ 79 vptr = ++p; 80 81 /* If the first character after the '=' is a quote character, 82 * find a matching quote character followed by either a comma 83 * or the terminating null character, and use the string in 84 * between. Otherwise, use the string up to the next comma or 85 * the terminating null character. 86 */ 87 if (*p == '\'' || *p == '"') { 88 p++; 89 90 for (vlen = 0; *p && (*p != *vptr || 91 (p[1] && p[1] != ',')); p++, vlen++); 92 93 if (*p) p++; 94 vptr++; 95 } 96 else 97 for (vlen = 0; *p && *p != ','; p++, vlen++); 98 } 99 else { 100 vptr = NULL; 101 vlen = 0; 102 } 103 104 if (*p == ',') p++; 105 106 /* Find a matching entry for this key in the given table. If found, 107 * call optset_parse_entry() on it. Silently ignore the option 108 * otherwise. 109 */ 110 for (i = 0; table[i].os_name != NULL; i++) { 111 if ((int) strlen(table[i].os_name) == klen && 112 !strncasecmp(table[i].os_name, kptr, klen)) { 113 114 optset_parse_entry(&table[i], vptr, vlen); 115 116 break; 117 } 118 } 119 } 120 } 121