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