xref: /minix3/minix/lib/libsys/optset.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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