14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin /* 244887Schin * Glenn Fowler 254887Schin * AT&T Research 264887Schin */ 274887Schin 284887Schin #include <ast.h> 294887Schin #include <ctype.h> 304887Schin 314887Schin /* 324887Schin * parse option expression in s using options in tab with element size siz 334887Schin * first element in tab must be a char* 344887Schin * options match 354887Schin * 364887Schin * [no]name[[:]=['"]value["']][, ]... 374887Schin * 384887Schin * f is called for each option 394887Schin * 404887Schin * (*f)(void* a, char* p, int n, char* v) 414887Schin * 424887Schin * a from stropt 434887Schin * p matching tab entry, or name if no table 444887Schin * n 0 if option had ``no'' prefix, -1 if :=, 1 otherwise 454887Schin * v option value pointer 464887Schin * 474887Schin * for unmatched options p is 0 and v is the offending option 484887Schin * 494887Schin * names in s may be shorter than tab names 504887Schin * longer names must have a prefix that matches a tab name 514887Schin * the first match is returned 524887Schin * \ escapes value using chresc() 534887Schin */ 544887Schin 554887Schin int 564887Schin stropt(const char* as, const void* tab, int siz, int(*f)(void*, const void*, int, const char*), void* a) 574887Schin { 584887Schin register int c; 594887Schin register char* s; 604887Schin register char* v; 614887Schin register char* t; 624887Schin char** p; 634887Schin char* u; 644887Schin char* x; 654887Schin char* e; 664887Schin int n; 674887Schin int ql; 684887Schin int qr; 694887Schin int qc; 704887Schin 714887Schin if (!as) n = 0; 724887Schin else if (!(x = s = strdup(as))) n = -1; 734887Schin else 744887Schin { 754887Schin for (;;) 764887Schin { 774887Schin while (isspace(*s) || *s == ',') s++; 784887Schin if (*s == 'n' && *(s + 1) == 'o') 794887Schin { 804887Schin s += 2; 814887Schin n = 0; 824887Schin } 834887Schin else n = 1; 844887Schin if (!*s) 854887Schin { 864887Schin n = 0; 874887Schin break; 884887Schin } 894887Schin if (tab) 904887Schin { 914887Schin for (p = (char**)tab; t = *p; p = (char**)((char*)p + siz)) 924887Schin { 934887Schin for (v = s; *t && *t++ == *v; v++); 944887Schin if (!*t || isspace(*v) || *v == ',' || *v == '=') 954887Schin break; 964887Schin if (*v == ':' && *(v + 1) == '=') 974887Schin { 984887Schin v++; 994887Schin n = -1; 1004887Schin break; 1014887Schin } 1024887Schin } 1034887Schin if (!t) 1044887Schin { 1054887Schin u = v = s; 1064887Schin p = 0; 1074887Schin } 1084887Schin } 1094887Schin else 1104887Schin { 1114887Schin p = (char**)(v = s); 1124887Schin t = 0; 1134887Schin } 1144887Schin while (*v && !isspace(*v) && *v != '=' && *v != ',') 1154887Schin if (*v++ == ':' && *v == '=') 1164887Schin { 1174887Schin if (!t) 1184887Schin *(v - 1) = 0; 1194887Schin n = -n; 1204887Schin break; 1214887Schin } 1224887Schin if (*v == '=') 1234887Schin { 1244887Schin if (!t) 1254887Schin *v = 0; 1264887Schin t = s = ++v; 1274887Schin ql = qr = 0; 1284887Schin while (c = *s++) 1294887Schin { 1304887Schin if (c == '\\') 1314887Schin { 1324887Schin *t++ = chresc(s - 1, &e); 1334887Schin s = e; 1344887Schin } 1354887Schin else if (c == qr) 1364887Schin { 1374887Schin if (qr != ql) 1384887Schin *t++ = c; 1394887Schin if (--qc <= 0) 1404887Schin qr = ql = 0; 1414887Schin } 1424887Schin else if (c == ql) 1434887Schin { 1444887Schin *t++ = c; 1454887Schin qc++; 1464887Schin } 1474887Schin else if (qr) 1484887Schin *t++ = c; 1494887Schin else if (c == ',' || isspace(c)) 1504887Schin break; 1514887Schin else if (c == '"' || c == '\'') 1524887Schin { 1534887Schin ql = qr = c; 1544887Schin qc = 1; 1554887Schin } 1564887Schin else 1574887Schin { 1584887Schin *t++ = c; 1594887Schin if (c == '{') 1604887Schin { 1614887Schin ql = c; 1624887Schin qr = '}'; 1634887Schin qc = 1; 1644887Schin } 1654887Schin else if (c == '(') 1664887Schin { 1674887Schin ql = c; 1684887Schin qr = ')'; 1694887Schin qc = 1; 1704887Schin } 1714887Schin } 1724887Schin } 1734887Schin *t = 0; 1744887Schin } 1754887Schin else 1764887Schin { 1774887Schin s = v; 1784887Schin c = *s; 1794887Schin *s++ = 0; 1804887Schin } 1814887Schin n = p ? (*f)(a, p, n, v) : (*f)(a, p, v - u, u); 1824887Schin if (n || !c) 1834887Schin break; 1844887Schin } 1854887Schin free(x); 1864887Schin } 1874887Schin return n; 1884887Schin } 189