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