1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 */ 27 28 #include <ast.h> 29 #include <ctype.h> 30 31 /* 32 * parse option expression in s using options in tab with element size siz 33 * first element in tab must be a char* 34 * options match 35 * 36 * [no]name[[:]=['"]value["']][, ]... 37 * 38 * f is called for each option 39 * 40 * (*f)(void* a, char* p, int n, char* v) 41 * 42 * a from stropt 43 * p matching tab entry, or name if no table 44 * n 0 if option had ``no'' prefix, -1 if :=, 1 otherwise 45 * v option value pointer 46 * 47 * for unmatched options p is 0 and v is the offending option 48 * 49 * names in s may be shorter than tab names 50 * longer names must have a prefix that matches a tab name 51 * the first match is returned 52 * \ escapes value using chresc() 53 */ 54 55 int 56 stropt(const char* as, const void* tab, int siz, int(*f)(void*, const void*, int, const char*), void* a) 57 { 58 register int c; 59 register char* s; 60 register char* v; 61 register char* t; 62 char** p; 63 char* u; 64 char* x; 65 char* e; 66 int n; 67 int ql; 68 int qr; 69 int qc; 70 71 if (!as) n = 0; 72 else if (!(x = s = strdup(as))) n = -1; 73 else 74 { 75 for (;;) 76 { 77 while (isspace(*s) || *s == ',') s++; 78 if (*s == 'n' && *(s + 1) == 'o') 79 { 80 s += 2; 81 n = 0; 82 } 83 else n = 1; 84 if (!*s) 85 { 86 n = 0; 87 break; 88 } 89 if (tab) 90 { 91 for (p = (char**)tab; t = *p; p = (char**)((char*)p + siz)) 92 { 93 for (v = s; *t && *t++ == *v; v++); 94 if (!*t || isspace(*v) || *v == ',' || *v == '=') 95 break; 96 if (*v == ':' && *(v + 1) == '=') 97 { 98 v++; 99 n = -1; 100 break; 101 } 102 } 103 if (!t) 104 { 105 u = v = s; 106 p = 0; 107 } 108 } 109 else 110 { 111 p = (char**)(v = s); 112 t = 0; 113 } 114 while (*v && !isspace(*v) && *v != '=' && *v != ',') 115 if (*v++ == ':' && *v == '=') 116 { 117 if (!t) 118 *(v - 1) = 0; 119 n = -n; 120 break; 121 } 122 if (*v == '=') 123 { 124 if (!t) 125 *v = 0; 126 t = s = ++v; 127 ql = qr = 0; 128 while (c = *s++) 129 { 130 if (c == '\\') 131 { 132 *t++ = chresc(s - 1, &e); 133 s = e; 134 } 135 else if (c == qr) 136 { 137 if (qr != ql) 138 *t++ = c; 139 if (--qc <= 0) 140 qr = ql = 0; 141 } 142 else if (c == ql) 143 { 144 *t++ = c; 145 qc++; 146 } 147 else if (qr) 148 *t++ = c; 149 else if (c == ',' || isspace(c)) 150 break; 151 else if (c == '"' || c == '\'') 152 { 153 ql = qr = c; 154 qc = 1; 155 } 156 else 157 { 158 *t++ = c; 159 if (c == '{') 160 { 161 ql = c; 162 qr = '}'; 163 qc = 1; 164 } 165 else if (c == '(') 166 { 167 ql = c; 168 qr = ')'; 169 qc = 1; 170 } 171 } 172 } 173 *t = 0; 174 } 175 else 176 { 177 s = v; 178 c = *s; 179 *s++ = 0; 180 } 181 n = p ? (*f)(a, p, n, v) : (*f)(a, p, v - u, u); 182 if (n || !c) 183 break; 184 } 185 free(x); 186 } 187 return n; 188 } 189