xref: /onnv-gate/usr/src/lib/libast/common/regex/regsub.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  * OBSOLETE Sfio_t buffer interface -- use regsubcomp(),regsubexec()
264887Schin  */
274887Schin 
284887Schin #include "reglib.h"
294887Schin 
304887Schin /*
314887Schin  * do a single substitution
324887Schin  */
334887Schin 
344887Schin static int
subold(register Sfio_t * dp,const char * op,register const char * sp,size_t nmatch,register regmatch_t * match,register regflags_t flags,int sre)354887Schin subold(register Sfio_t* dp, const char* op, register const char* sp, size_t nmatch, register regmatch_t* match, register regflags_t flags, int sre)
364887Schin {
374887Schin 	register int	c;
384887Schin 	char*		s;
394887Schin 	char*		e;
404887Schin 	const char*	b;
414887Schin 	regflags_t	f;
424887Schin 
434887Schin 	f = flags &= (REG_SUB_LOWER|REG_SUB_UPPER);
444887Schin 	for (;;)
454887Schin 	{
464887Schin 		switch (c = *sp++)
474887Schin 		{
484887Schin 		case 0:
494887Schin 			return 0;
504887Schin 		case '~':
514887Schin 			if (!sre || *sp != '(')
524887Schin 			{
534887Schin 				sfputc(dp, c);
544887Schin 				continue;
554887Schin 			}
564887Schin 			b = sp - 1;
574887Schin 			sp++;
584887Schin 			break;
594887Schin 		case '\\':
604887Schin 			if (sre)
614887Schin 			{
624887Schin 				sfputc(dp, chresc(sp - 1, &s));
634887Schin 				sp = (const char*)s;
644887Schin 				continue;
654887Schin 			}
664887Schin 			if (*sp == '&')
674887Schin 			{
684887Schin 				c = *sp++;
694887Schin 				sfputc(dp, c);
704887Schin 				continue;
714887Schin 			}
724887Schin 			break;
734887Schin 		case '&':
744887Schin 			if (sre)
754887Schin 			{
764887Schin 				sfputc(dp, c);
774887Schin 				continue;
784887Schin 			}
794887Schin 			sp--;
804887Schin 			break;
814887Schin 		default:
824887Schin 			switch (flags)
834887Schin 			{
844887Schin 			case REG_SUB_UPPER:
854887Schin 				if (islower(c))
864887Schin 					c = toupper(c);
874887Schin 				break;
884887Schin 			case REG_SUB_LOWER:
894887Schin 				if (isupper(c))
904887Schin 					c = tolower(c);
914887Schin 				break;
924887Schin 			case REG_SUB_UPPER|REG_SUB_LOWER:
934887Schin 				if (isupper(c))
944887Schin 					c = tolower(c);
954887Schin 				else if (islower(c))
964887Schin 					c = toupper(c);
974887Schin 				break;
984887Schin 			}
994887Schin 			sfputc(dp, c);
1004887Schin 			continue;
1014887Schin 		}
1024887Schin 		switch (c = *sp++)
1034887Schin 		{
1044887Schin 		case 0:
1054887Schin 			sp--;
1064887Schin 			continue;
1074887Schin 		case '&':
1084887Schin 			c = 0;
1094887Schin 			break;
1104887Schin 		case '0': case '1': case '2': case '3': case '4':
1114887Schin 		case '5': case '6': case '7': case '8': case '9':
1124887Schin 			c -= '0';
1134887Schin 			if (sre)
1144887Schin 				while (isdigit(*sp))
1154887Schin 					c = c * 10 + *sp++ - '0';
1164887Schin 			break;
1174887Schin 		case 'l':
1184887Schin 			if (sre && *sp != ')')
1194887Schin 			{
1204887Schin 				c = -1;
1214887Schin 				break;
1224887Schin 			}
1234887Schin 			if (c = *sp)
1244887Schin 			{
1254887Schin 				sp++;
1264887Schin 				if (isupper(c))
1274887Schin 					c = tolower(c);
1284887Schin 				sfputc(dp, c);
1294887Schin 			}
1304887Schin 			continue;
1314887Schin 		case 'u':
1324887Schin 			if (sre)
1334887Schin 			{
1344887Schin 				if (*sp != ')')
1354887Schin 				{
1364887Schin 					c = -1;
1374887Schin 					break;
1384887Schin 				}
1394887Schin 				sp++;
1404887Schin 			}
1414887Schin 			if (c = *sp)
1424887Schin 			{
1434887Schin 				sp++;
1444887Schin 				if (islower(c))
1454887Schin 					c = toupper(c);
1464887Schin 				sfputc(dp, c);
1474887Schin 			}
1484887Schin 			continue;
1494887Schin 		case 'E':
1504887Schin 			if (sre)
1514887Schin 			{
1524887Schin 				if (*sp != ')')
1534887Schin 				{
1544887Schin 					c = -1;
1554887Schin 					break;
1564887Schin 				}
1574887Schin 				sp++;
1584887Schin 			}
1594887Schin 			flags = f;
1604887Schin 			continue;
1614887Schin 		case 'L':
1624887Schin 			if (sre)
1634887Schin 			{
1644887Schin 				if (*sp != ')')
1654887Schin 				{
1664887Schin 					c = -1;
1674887Schin 					break;
1684887Schin 				}
1694887Schin 				sp++;
1704887Schin 			}
1714887Schin 			f = flags;
1724887Schin 			flags = REG_SUB_LOWER;
1734887Schin 			continue;
1744887Schin 		case 'U':
1754887Schin 			if (sre)
1764887Schin 			{
1774887Schin 				if (*sp != ')')
1784887Schin 				{
1794887Schin 					c = -1;
1804887Schin 					break;
1814887Schin 				}
1824887Schin 				sp++;
1834887Schin 			}
1844887Schin 			f = flags;
1854887Schin 			flags = REG_SUB_UPPER;
1864887Schin 			continue;
1874887Schin 		default:
1884887Schin 			if (!sre)
1894887Schin 			{
1904887Schin 				sfputc(dp, chresc(sp - 2, &s));
1914887Schin 				sp = (const char*)s;
1924887Schin 				continue;
1934887Schin 			}
1944887Schin 			sp--;
1954887Schin 			c = -1;
1964887Schin 			break;
1974887Schin 		}
1984887Schin 		if (sre)
1994887Schin 		{
2004887Schin 			if (c < 0 || *sp != ')')
2014887Schin 			{
2024887Schin 				for (; b < sp; b++)
2034887Schin 					sfputc(dp, *b);
2044887Schin 				continue;
2054887Schin 			}
2064887Schin 			sp++;
2074887Schin 		}
2084887Schin 		if (c >= nmatch)
2094887Schin 			return REG_ESUBREG;
2104887Schin 		s = (char*)op + match[c].rm_so;
2114887Schin 		e = (char*)op + match[c].rm_eo;
2124887Schin 		while (s < e)
2134887Schin 		{
2144887Schin 			c = *s++;
2154887Schin 			switch (flags)
2164887Schin 			{
2174887Schin 			case REG_SUB_UPPER:
2184887Schin 				if (islower(c))
2194887Schin 					c = toupper(c);
2204887Schin 				break;
2214887Schin 			case REG_SUB_LOWER:
2224887Schin 				if (isupper(c))
2234887Schin 					c = tolower(c);
2244887Schin 				break;
2254887Schin 			case REG_SUB_UPPER|REG_SUB_LOWER:
2264887Schin 				if (isupper(c))
2274887Schin 					c = tolower(c);
2284887Schin 				else if (islower(c))
2294887Schin 					c = toupper(c);
2304887Schin 				break;
2314887Schin 			}
2324887Schin 			sfputc(dp, c);
2334887Schin 		}
2344887Schin 	}
2354887Schin }
2364887Schin 
2374887Schin /*
2384887Schin  * ed(1) style substitute using matches from last regexec()
2394887Schin  */
2404887Schin 
2414887Schin int
regsub(const regex_t * p,Sfio_t * dp,const char * op,const char * sp,size_t nmatch,regmatch_t * match,regflags_t flags)2424887Schin regsub(const regex_t* p, Sfio_t* dp, const char* op, const char* sp, size_t nmatch, regmatch_t* match, regflags_t flags)
2434887Schin {
2444887Schin 	int	m;
2454887Schin 	int	r;
2464887Schin 	int	sre;
2474887Schin 
2484887Schin 	if ((p->env->flags & REG_NOSUB) || !nmatch)
2494887Schin 		return fatal(p->env->disc, REG_BADPAT, NiL);
2504887Schin 	m = (flags >> 16) & 0x3fff;
2514887Schin 	sre = !!(p->env->flags & REG_SHELL);
2528462SApril.Chin@Sun.COM 	r = 0;
2534887Schin 	do
2544887Schin 	{
2554887Schin 		if (--m > 0)
2564887Schin 			sfwrite(dp, op, match->rm_eo);
2574887Schin 		else
2584887Schin 		{
2594887Schin 			sfwrite(dp, op, match->rm_so);
2604887Schin 			if (r = subold(dp, op, sp, nmatch, match, flags, sre))
2614887Schin 				return fatal(p->env->disc, r, NiL);
2624887Schin 		}
2634887Schin 		op += match->rm_eo;
2644887Schin 	} while ((m > 0 || (flags & REG_SUB_ALL)) && !(r = regexec(p, op, nmatch, match, p->env->flags|(match->rm_so == match->rm_eo ? REG_ADVANCE : 0))));
2654887Schin 	if (r && r != REG_NOMATCH)
2664887Schin 		return fatal(p->env->disc, r, NiL);
2674887Schin 	sfputr(dp, op, -1);
2684887Schin 	return 0;
2694887Schin }
270