xref: /onnv-gate/usr/src/lib/libast/common/string/stropt.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.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
stropt(const char * as,const void * tab,int siz,int (* f)(void *,const void *,int,const char *),void * a)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