xref: /onnv-gate/usr/src/lib/libast/common/regex/regsubexec.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 /*
254887Schin  * posix regex ed(1) style substitute execute
264887Schin  */
274887Schin 
284887Schin #include "reglib.h"
294887Schin 
304887Schin #define NEED(p,b,n,r)	\
314887Schin 	do \
324887Schin 	{ \
334887Schin 		if (((b)->re_end - (b)->re_cur) < (n)) \
344887Schin 		{ \
354887Schin 			size_t	o = (b)->re_cur - (b)->re_buf; \
364887Schin 			size_t	a = ((b)->re_end - (b)->re_buf); \
374887Schin 			if (a < n) \
384887Schin 				a = roundof(n, 128); \
394887Schin 			a *= 2; \
404887Schin 			if (!((b)->re_buf = alloc(p->env->disc, (b)->re_buf, a))) \
414887Schin 			{ \
424887Schin 				(b)->re_buf = (b)->re_cur = (b)->re_end = 0; \
434887Schin 				c = REG_ESPACE; \
444887Schin 				r; \
454887Schin 			} \
464887Schin 			(b)->re_cur = (b)->re_buf + o; \
474887Schin 			(b)->re_end = (b)->re_buf + a; \
484887Schin 		} \
494887Schin 	} while (0)
504887Schin 
514887Schin #define PUTC(p,b,x,r)	\
524887Schin 	do \
534887Schin 	{ \
544887Schin 		NEED(p, b, 1, r); \
554887Schin 		*(b)->re_cur++ = (x); \
564887Schin 	} while (0)
574887Schin 
584887Schin #define PUTS(p,b,x,z,r)	\
594887Schin 	do if (z) \
604887Schin 	{ \
614887Schin 		NEED(p, b, z, r); \
624887Schin 		memcpy((b)->re_cur, x, z); \
634887Schin 		(b)->re_cur += (z); \
644887Schin 	} while (0)
654887Schin 
664887Schin /*
674887Schin  * do a single substitution
684887Schin  */
694887Schin 
704887Schin static int
sub(const regex_t * p,register regsub_t * b,const char * ss,register regsubop_t * op,size_t nmatch,register regmatch_t * match)714887Schin sub(const regex_t* p, register regsub_t* b, const char* ss, register regsubop_t* op, size_t nmatch, register regmatch_t* match)
724887Schin {
734887Schin 	register char*	s;
744887Schin 	register char*	e;
754887Schin 	register int	c;
764887Schin 
774887Schin 	for (;; op++)
784887Schin 	{
794887Schin 		switch (op->len)
804887Schin 		{
814887Schin 		case -1:
824887Schin 			break;
834887Schin 		case 0:
844887Schin 			if (op->off >= nmatch)
854887Schin 				return REG_ESUBREG;
864887Schin 			if ((c = match[op->off].rm_so) < 0)
874887Schin 				continue;
884887Schin 			s = (char*)ss + c;
894887Schin 			if ((c = match[op->off].rm_eo) < 0)
904887Schin 				continue;
914887Schin 			e = (char*)ss + c;
924887Schin 			NEED(p, b, e - s, return c);
934887Schin 			switch (op->op)
944887Schin 			{
954887Schin 			case REG_SUB_UPPER:
964887Schin 				while (s < e)
974887Schin 				{
984887Schin 					c = *s++;
994887Schin 					if (islower(c))
1004887Schin 						c = toupper(c);
1014887Schin 					*b->re_cur++ = c;
1024887Schin 				}
1034887Schin 				break;
1044887Schin 			case REG_SUB_LOWER:
1054887Schin 				while (s < e)
1064887Schin 				{
1074887Schin 					c = *s++;
1084887Schin 					if (isupper(c))
1094887Schin 						c = tolower(c);
1104887Schin 					*b->re_cur++ = c;
1114887Schin 				}
1124887Schin 				break;
1134887Schin 			case REG_SUB_UPPER|REG_SUB_LOWER:
1144887Schin 				while (s < e)
1154887Schin 				{
1164887Schin 					c = *s++;
1174887Schin 					if (isupper(c))
1184887Schin 						c = tolower(c);
1194887Schin 					else if (islower(c))
1204887Schin 						c = toupper(c);
1214887Schin 					*b->re_cur++ = c;
1224887Schin 				}
1234887Schin 				break;
1244887Schin 			default:
1254887Schin 				while (s < e)
1264887Schin 					*b->re_cur++ = *s++;
1274887Schin 				break;
1284887Schin 			}
1294887Schin 			continue;
1304887Schin 		default:
1314887Schin 			NEED(p, b, op->len, return c);
1324887Schin 			s = b->re_rhs + op->off;
1334887Schin 			e = s + op->len;
1344887Schin 			while (s < e)
1354887Schin 				*b->re_cur++ = *s++;
1364887Schin 			continue;
1374887Schin 		}
1384887Schin 		break;
1394887Schin 	}
1404887Schin 	return 0;
1414887Schin }
1424887Schin 
1434887Schin /*
1444887Schin  * ed(1) style substitute using matches from last regexec()
1454887Schin  */
1464887Schin 
1474887Schin int
regsubexec(const regex_t * p,const char * s,size_t nmatch,regmatch_t * match)1484887Schin regsubexec(const regex_t* p, const char* s, size_t nmatch, regmatch_t* match)
1494887Schin {
1504887Schin 	register int		c;
1514887Schin 	register regsub_t*	b;
1524887Schin 	const char*		e;
1534887Schin 	int			m;
1544887Schin 
1554887Schin 	if (!p->env->sub || (p->env->flags & REG_NOSUB) || !nmatch)
1564887Schin 		return fatal(p->env->disc, REG_BADPAT, NiL);
1574887Schin 	b = p->re_sub;
1584887Schin 	m = b->re_min;
1594887Schin 	b->re_cur = b->re_buf;
1604887Schin 	e = (const char*)p->env->end;
1618462SApril.Chin@Sun.COM 	c = 0;
1624887Schin 	for (;;)
1634887Schin 	{
1644887Schin 		if (--m > 0)
1654887Schin 			PUTS(p, b, s, match->rm_eo, return fatal(p->env->disc, c, NiL));
1664887Schin 		else
1674887Schin 		{
1684887Schin 			PUTS(p, b, s, match->rm_so, return fatal(p->env->disc, c, NiL));
1698462SApril.Chin@Sun.COM 			if (!c && (c = sub(p, b, s, b->re_ops, nmatch, match)))
1704887Schin 				return fatal(p->env->disc, c, NiL);
1714887Schin 		}
1724887Schin 		s += match->rm_eo;
1738462SApril.Chin@Sun.COM 		if (m <= 0 && !(b->re_flags & REG_SUB_ALL) || !*s)
1744887Schin 			break;
1754887Schin 		if (c = regnexec(p, s, e - s, nmatch, match, p->env->flags|(match->rm_so == match->rm_eo ? REG_ADVANCE : 0)))
1764887Schin 		{
1774887Schin 			if (c != REG_NOMATCH)
1784887Schin 				return fatal(p->env->disc, c, NiL);
1794887Schin 			break;
1804887Schin 		}
1818462SApril.Chin@Sun.COM 		if (!match->rm_so && !match->rm_eo && *s && m <= 1)
1828462SApril.Chin@Sun.COM 		{
1838462SApril.Chin@Sun.COM 			match->rm_so = match->rm_eo = 1;
1848462SApril.Chin@Sun.COM 			c = 1;
1858462SApril.Chin@Sun.COM 		}
1864887Schin 	}
1874887Schin 	while (s < e)
1884887Schin 	{
1894887Schin 		c = *s++;
1904887Schin 		PUTC(p, b, c, return fatal(p->env->disc, c, NiL));
1914887Schin 	}
1924887Schin 	NEED(p, b, 1, return fatal(p->env->disc, c, NiL));
1934887Schin 	*b->re_cur = 0;
1944887Schin 	b->re_len = b->re_cur - b->re_buf;
1954887Schin 	return 0;
1964887Schin }
197