xref: /onnv-gate/usr/src/lib/libast/common/string/fmtmatch.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  * return strmatch() expression given REG_AUGMENTED RE
284887Schin  * 0 returned for invalid RE
294887Schin  */
304887Schin 
314887Schin #include <ast.h>
324887Schin 
334887Schin char*
fmtmatch(const char * as)344887Schin fmtmatch(const char* as)
354887Schin {
364887Schin 	register char*	s = (char*)as;
374887Schin 	register int	c;
384887Schin 	register char*	t;
394887Schin 	register char**	p;
404887Schin 	register char*	b;
414887Schin 	char*		x;
424887Schin 	char*		y;
434887Schin 	char*		z;
444887Schin 	int		a;
454887Schin 	int		e;
464887Schin 	int		n;
474887Schin 	char*		buf;
484887Schin 	char*		stack[32];
494887Schin 
504887Schin 	c = 3 * (strlen(s) + 1);
514887Schin 	buf = fmtbuf(c);
524887Schin 	t = b = buf + 3;
534887Schin 	p = stack;
544887Schin 	if (a = *s == '^')
554887Schin 		s++;
564887Schin 	e = 0;
574887Schin 	for (;;)
584887Schin 	{
594887Schin 		switch (c = *s++)
604887Schin 		{
614887Schin 		case 0:
624887Schin 			break;
634887Schin 		case '\\':
644887Schin 			if (!(c = *s++))
654887Schin 				return 0;
664887Schin 			switch (*s)
674887Schin 			{
684887Schin 			case '*':
694887Schin 			case '+':
704887Schin 			case '?':
714887Schin 				*t++ = *s++;
724887Schin 				*t++ = '(';
734887Schin 				*t++ = '\\';
744887Schin 				*t++ = c;
754887Schin 				c = ')';
764887Schin 				break;
774887Schin 			case '|':
784887Schin 			case '&':
794887Schin 				if (c == '(')
804887Schin 				{
814887Schin 					*t++ = c;
824887Schin 					c = *s++;
834887Schin 					goto logical;
844887Schin 				}
854887Schin 				break;
864887Schin 			case '{':
874887Schin 			case '}':
884887Schin 				break;
894887Schin 			default:
904887Schin 				*t++ = '\\';
914887Schin 				break;
924887Schin 			}
934887Schin 			*t++ = c;
944887Schin 			continue;
954887Schin 		case '[':
964887Schin 			x = t;
974887Schin 			*t++ = c;
984887Schin 			if ((c = *s++) == '^')
994887Schin 			{
1004887Schin 				*t++ = '!';
1014887Schin 				c = *s++;
1024887Schin 			}
1034887Schin 			else if (c == '!')
1044887Schin 			{
1054887Schin 				*t++ = '\\';
1064887Schin 				*t++ = c;
1074887Schin 				c = *s++;
1084887Schin 			}
1094887Schin 			for (;;)
1104887Schin 			{
1114887Schin 				if (!(*t++ = c))
1124887Schin 					return 0;
1134887Schin 				if (c == '\\')
1144887Schin 					*t++ = c;
1154887Schin 				if ((c = *s++) == ']')
1164887Schin 				{
1174887Schin 					*t++ = c;
1184887Schin 					break;
1194887Schin 				}
1204887Schin 			}
1214887Schin 			switch (*s)
1224887Schin 			{
1234887Schin 			case '*':
1244887Schin 			case '+':
1254887Schin 			case '?':
1264887Schin 				for (y = t + 2, t--; t >= x; t--)
1274887Schin 					*(t + 2) = *t;
1284887Schin 				*++t = *s++;
1294887Schin 				*++t = '(';
1304887Schin 				t = y;
1314887Schin 				*t++ = ')';
1324887Schin 				break;
1334887Schin 			}
1344887Schin 			continue;
1354887Schin 		case '(':
1364887Schin 			if (p >= &stack[elementsof(stack)])
1374887Schin 				return 0;
1384887Schin 			*p++ = t;
1394887Schin 			if (*s == '?')
1404887Schin 			{
1414887Schin 				s++;
1424887Schin 				if (*s == 'K' && *(s + 1) == ')')
1434887Schin 				{
1444887Schin 					s += 2;
1454887Schin 					p--;
1464887Schin 					while (*t = *s)
1474887Schin 						t++, s++;
1484887Schin 					continue;
1494887Schin 				}
1504887Schin 				*t++ = '~';
1514887Schin 			}
1524887Schin 			else
1534887Schin 				*t++ = '@';
1544887Schin 			*t++ = '(';
1554887Schin 			continue;
1564887Schin 		case ')':
1574887Schin 			if (p == stack)
1584887Schin 				return 0;
1594887Schin 			p--;
1604887Schin 			*t++ = c;
1614887Schin 			switch (*s)
1624887Schin 			{
1634887Schin 			case 0:
1644887Schin 				break;
1654887Schin 			case '*':
1664887Schin 			case '+':
1674887Schin 			case '?':
1684887Schin 			case '!':
1694887Schin 				**p = *s++;
1704887Schin 				if (*s == '?')
1714887Schin 				{
1724887Schin 					s++;
1734887Schin 					x = *p + 1;
1744887Schin 					for (y = ++t; y > x; y--)
1754887Schin 						*y = *(y - 1);
1764887Schin 					*x = '-';
1774887Schin 				}
1784887Schin 				continue;
1794887Schin 			case '{':
1804887Schin 				for (z = s; *z != '}'; z++)
1814887Schin 					if (!*z)
1824887Schin 						return 0;
1834887Schin 				n = z - s;
1844887Schin 				if (*++z == '?')
1854887Schin 					n++;
1864887Schin 				x = *p + n;
1874887Schin 				for (y = t += n; y > x; y--)
1884887Schin 					*y = *(y - n);
1894887Schin 				for (x = *p; s < z; *x++ = *s++);
1904887Schin 				if (*s == '?')
1914887Schin 				{
1924887Schin 					s++;
1934887Schin 					*x++ = '-';
1944887Schin 				}
1954887Schin 				continue;
1964887Schin 			default:
1974887Schin 				continue;
1984887Schin 			}
1994887Schin 			break;
2004887Schin 		case '.':
2014887Schin 			switch (*s)
2024887Schin 			{
2034887Schin 			case 0:
2044887Schin 				*t++ = '?';
2054887Schin 				break;
2064887Schin 			case '*':
2074887Schin 				s++;
2084887Schin 				*t++ = '*';
2094887Schin 				e = !*s;
2104887Schin 				continue;
2114887Schin 			case '+':
2124887Schin 				s++;
2134887Schin 				*t++ = '?';
2144887Schin 				*t++ = '*';
2154887Schin 				continue;
2164887Schin 			case '?':
2174887Schin 				s++;
2184887Schin 				*t++ = '?';
2194887Schin 				*t++ = '(';
2204887Schin 				*t++ = '?';
2214887Schin 				*t++ = ')';
2224887Schin 				continue;
2234887Schin 			default:
2244887Schin 				*t++ = '?';
2254887Schin 				continue;
2264887Schin 			}
2274887Schin 			break;
2284887Schin 		case '*':
2294887Schin 		case '+':
2304887Schin 		case '?':
2314887Schin 		case '{':
2324887Schin 			n = *(t - 1);
2334887Schin 			if (t == b || n == '(' || n == '|')
2344887Schin 				return 0;
2354887Schin 			*(t - 1) = c;
2364887Schin 			if (c == '{')
2374887Schin 			{
2384887Schin 				for (z = s; *z != '}'; z++)
2394887Schin 					if (!*z)
2404887Schin 						return 0;
2414887Schin 				for (; s <= z; *t++ = *s++);
2424887Schin 			}
2434887Schin 			if (*s == '?')
2444887Schin 			{
2454887Schin 				s++;
2464887Schin 				*t++ = '-';
2474887Schin 			}
2484887Schin 			*t++ = '(';
2494887Schin 			*t++ = n;
2504887Schin 			*t++ = ')';
2514887Schin 			continue;
2524887Schin 		case '|':
2534887Schin 		case '&':
2544887Schin 			if (t == b || *(t - 1) == '(')
2554887Schin 				return 0;
2564887Schin 		logical:
2574887Schin 			if (!*s || *s == ')')
2584887Schin 				return 0;
2594887Schin 			if (p == stack && b == buf + 3)
2604887Schin 			{
2614887Schin 				*--b = '(';
2624887Schin 				*--b = '@';
2634887Schin 			}
2644887Schin 			*t++ = c;
2654887Schin 			continue;
2664887Schin 		case '$':
2674887Schin 			if (e = !*s)
2684887Schin 				break;
2694887Schin 			/*FALLTHROUGH*/
2704887Schin 		default:
2714887Schin 			*t++ = c;
2724887Schin 			continue;
2734887Schin 		}
2744887Schin 		break;
2754887Schin 	}
2764887Schin 	if (p != stack)
2774887Schin 		return 0;
2784887Schin 	if (b != buf + 3)
2794887Schin 		*t++ = ')';
2804887Schin 	if (!a && (*b != '*' || *(b + 1) == '(' || (*(b + 1) == '-' || *(b + 1) == '~') && *(b + 2) == '('))
2814887Schin 		*--b = '*';
2824887Schin 	if (!e)
2834887Schin 		*t++ = '*';
2844887Schin 	*t = 0;
2854887Schin 	return b;
2864887Schin }
287