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