14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 compile 264887Schin */ 274887Schin 284887Schin #include "reglib.h" 294887Schin 304887Schin static const regflags_t submap[] = 314887Schin { 324887Schin 'g', REG_SUB_ALL, 334887Schin 'l', REG_SUB_LOWER, 344887Schin 'n', REG_SUB_NUMBER, 354887Schin 'p', REG_SUB_PRINT, 364887Schin 's', REG_SUB_STOP, 374887Schin 'u', REG_SUB_UPPER, 384887Schin 'w', REG_SUB_WRITE|REG_SUB_LAST, 394887Schin 0, 0 404887Schin }; 414887Schin 424887Schin int 434887Schin regsubflags(regex_t* p, register const char* s, char** e, int delim, register const regflags_t* map, int* pm, regflags_t* pf) 444887Schin { 454887Schin register int c; 464887Schin register const regflags_t* m; 474887Schin regflags_t flags; 484887Schin int minmatch; 494887Schin regdisc_t* disc; 504887Schin 514887Schin flags = pf ? *pf : 0; 524887Schin minmatch = pm ? *pm : 0; 534887Schin if (!map) 544887Schin map = submap; 554887Schin while (!(flags & REG_SUB_LAST)) 564887Schin { 574887Schin if (!(c = *s++) || c == delim) 584887Schin { 594887Schin s--; 604887Schin break; 614887Schin } 624887Schin else if (c >= '0' && c <= '9') 634887Schin { 644887Schin if (minmatch) 654887Schin { 664887Schin disc = p->env->disc; 674887Schin regfree(p); 684887Schin return fatal(disc, REG_EFLAGS, s - 1); 694887Schin } 704887Schin minmatch = c - '0'; 714887Schin while (*s >= '0' && *s <= '9') 724887Schin minmatch = minmatch * 10 + *s++ - '0'; 734887Schin } 744887Schin else 754887Schin { 764887Schin for (m = map; *m; m++) 774887Schin if (*m++ == c) 784887Schin { 794887Schin if (flags & *m) 804887Schin { 814887Schin disc = p->env->disc; 824887Schin regfree(p); 834887Schin return fatal(disc, REG_EFLAGS, s - 1); 844887Schin } 854887Schin flags |= *m--; 864887Schin break; 874887Schin } 884887Schin if (!*m) 894887Schin { 904887Schin s--; 914887Schin break; 924887Schin } 934887Schin } 944887Schin } 954887Schin if (pf) 964887Schin *pf = flags; 974887Schin if (pm) 984887Schin *pm = minmatch; 994887Schin if (e) 1004887Schin *e = (char*)s; 1014887Schin return 0; 1024887Schin } 1034887Schin 1044887Schin /* 1054887Schin * compile substitute rhs and optional flags 1064887Schin */ 1074887Schin 1084887Schin int 1094887Schin regsubcomp(regex_t* p, register const char* s, const regflags_t* map, int minmatch, regflags_t flags) 1104887Schin { 1114887Schin register regsub_t* sub; 1124887Schin register int c; 1134887Schin register int d; 1144887Schin register char* t; 1154887Schin register regsubop_t* op; 1164887Schin char* e; 1174887Schin const char* r; 1184887Schin int sre; 1194887Schin int f; 1204887Schin int g; 1214887Schin int n; 1224887Schin int nops; 1234887Schin const char* o; 1244887Schin regdisc_t* disc; 1254887Schin 1264887Schin disc = p->env->disc; 1274887Schin if (p->env->flags & REG_NOSUB) 1284887Schin { 1294887Schin regfree(p); 1304887Schin return fatal(disc, REG_BADPAT, NiL); 1314887Schin } 1324887Schin if (!(sub = (regsub_t*)alloc(p->env->disc, 0, sizeof(regsub_t) + strlen(s))) || !(sub->re_ops = (regsubop_t*)alloc(p->env->disc, 0, (nops = 8) * sizeof(regsubop_t)))) 1334887Schin { 1344887Schin if (sub) 1354887Schin alloc(p->env->disc, sub, 0); 1364887Schin regfree(p); 1374887Schin return fatal(disc, REG_ESPACE, s); 1384887Schin } 1394887Schin sub->re_buf = sub->re_end = 0; 1404887Schin p->re_sub = sub; 1414887Schin p->env->sub = 1; 1424887Schin op = sub->re_ops; 1434887Schin o = s; 1444887Schin if (!(p->env->flags & REG_DELIMITED)) 1454887Schin d = 0; 1464887Schin else 1474887Schin switch (d = *(s - 1)) 1484887Schin { 1494887Schin case '\\': 1504887Schin case '\n': 1514887Schin case '\r': 1524887Schin regfree(p); 1534887Schin return fatal(disc, REG_EDELIM, s); 1544887Schin } 1554887Schin sre = p->env->flags & REG_SHELL; 1564887Schin t = sub->re_rhs; 1574887Schin if (d) 1584887Schin { 1594887Schin r = s; 1604887Schin for (;;) 1614887Schin { 1624887Schin if (!*s) 1634887Schin { 1644887Schin if (p->env->flags & REG_MUSTDELIM) 1654887Schin { 1664887Schin regfree(p); 1674887Schin return fatal(disc, REG_EDELIM, r); 1684887Schin } 1694887Schin break; 1704887Schin } 1714887Schin else if (*s == d) 1724887Schin { 1734887Schin flags |= REG_SUB_FULL; 1744887Schin s++; 1754887Schin break; 1764887Schin } 1774887Schin else if (*s++ == '\\' && !*s++) 1784887Schin { 1794887Schin regfree(p); 1804887Schin return fatal(disc, REG_EESCAPE, r); 1814887Schin } 1824887Schin } 1834887Schin if (*s) 1844887Schin { 1854887Schin if (n = regsubflags(p, s, &e, d, map, &minmatch, &flags)) 1864887Schin return n; 1874887Schin s = (const char*)e; 1884887Schin } 1894887Schin p->re_npat = s - o; 1904887Schin s = r; 1914887Schin } 1924887Schin else 1934887Schin p->re_npat = 0; 1944887Schin op->op = f = g = flags & (REG_SUB_LOWER|REG_SUB_UPPER); 1954887Schin op->off = 0; 1964887Schin while ((c = *s++) != d) 1974887Schin { 1984887Schin again: 1994887Schin if (!c) 2004887Schin { 2014887Schin p->re_npat = s - o - 1; 2024887Schin break; 2034887Schin } 2044887Schin else if (c == '\\') 2054887Schin { 2064887Schin if (*s == c) 2074887Schin { 2084887Schin *t++ = *s++; 2094887Schin continue; 2104887Schin } 2114887Schin if ((c = *s++) == d) 2124887Schin goto again; 2134887Schin if (!c) 2144887Schin { 2154887Schin regfree(p); 2164887Schin return fatal(disc, REG_EESCAPE, s - 2); 2174887Schin } 2184887Schin if (c == '&') 2194887Schin { 2204887Schin *t++ = c; 2214887Schin continue; 2224887Schin } 2234887Schin } 2244887Schin else if (c == '&') 2254887Schin { 2264887Schin if (sre) 2274887Schin { 2284887Schin *t++ = c; 2294887Schin continue; 2304887Schin } 2314887Schin } 2324887Schin else 2334887Schin { 2344887Schin switch (op->op) 2354887Schin { 2364887Schin case REG_SUB_UPPER: 2374887Schin if (islower(c)) 2384887Schin c = toupper(c); 2394887Schin break; 2404887Schin case REG_SUB_LOWER: 2414887Schin if (isupper(c)) 2424887Schin c = tolower(c); 2434887Schin break; 2444887Schin case REG_SUB_UPPER|REG_SUB_LOWER: 2454887Schin if (isupper(c)) 2464887Schin c = tolower(c); 2474887Schin else if (islower(c)) 2484887Schin c = toupper(c); 2494887Schin break; 2504887Schin } 2514887Schin *t++ = c; 2524887Schin continue; 2534887Schin } 2544887Schin switch (c) 2554887Schin { 2564887Schin case 0: 2574887Schin s--; 2584887Schin continue; 2594887Schin case '&': 2604887Schin c = 0; 2614887Schin break; 2624887Schin case '0': case '1': case '2': case '3': case '4': 2634887Schin case '5': case '6': case '7': case '8': case '9': 2644887Schin c -= '0'; 265*8462SApril.Chin@Sun.COM if (isdigit(*s) && (p->env->flags & REG_MULTIREF)) 2664887Schin c = c * 10 + *s++ - '0'; 2674887Schin break; 2684887Schin case 'l': 2694887Schin if (c = *s) 2704887Schin { 2714887Schin s++; 2724887Schin if (isupper(c)) 2734887Schin c = tolower(c); 2744887Schin *t++ = c; 2754887Schin } 2764887Schin continue; 2774887Schin case 'u': 2784887Schin if (c = *s) 2794887Schin { 2804887Schin s++; 2814887Schin if (islower(c)) 2824887Schin c = toupper(c); 2834887Schin *t++ = c; 2844887Schin } 2854887Schin continue; 2864887Schin case 'E': 2874887Schin f = g; 2884887Schin set: 2894887Schin if ((op->len = (t - sub->re_rhs) - op->off) && (n = ++op - sub->re_ops) >= nops) 2904887Schin { 2914887Schin if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t)))) 2924887Schin { 2934887Schin regfree(p); 2944887Schin return fatal(disc, REG_ESPACE, NiL); 2954887Schin } 2964887Schin op = sub->re_ops + n; 2974887Schin } 2984887Schin op->op = f; 2994887Schin op->off = t - sub->re_rhs; 3004887Schin continue; 3014887Schin case 'L': 3024887Schin g = f; 3034887Schin f = REG_SUB_LOWER; 3044887Schin goto set; 3054887Schin case 'U': 3064887Schin g = f; 3074887Schin f = REG_SUB_UPPER; 3084887Schin goto set; 3094887Schin default: 3104887Schin if (!sre) 3114887Schin { 3124887Schin *t++ = chresc(s - 2, &e); 3134887Schin s = (const char*)e; 3144887Schin continue; 3154887Schin } 3164887Schin s--; 3174887Schin c = -1; 3184887Schin break; 3194887Schin } 3204887Schin if (c > p->re_nsub) 3214887Schin { 3224887Schin regfree(p); 3234887Schin return fatal(disc, REG_ESUBREG, s - 1); 3244887Schin } 3254887Schin if ((n = op - sub->re_ops) >= (nops - 2)) 3264887Schin { 3274887Schin if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t)))) 3284887Schin { 3294887Schin regfree(p); 3304887Schin return fatal(disc, REG_ESPACE, NiL); 3314887Schin } 3324887Schin op = sub->re_ops + n; 3334887Schin } 3344887Schin if (op->len = (t - sub->re_rhs) - op->off) 3354887Schin op++; 3364887Schin op->op = f; 3374887Schin op->off = c; 3384887Schin op->len = 0; 3394887Schin op++; 3404887Schin op->op = f; 3414887Schin op->off = t - sub->re_rhs; 3424887Schin } 3434887Schin if ((op->len = (t - sub->re_rhs) - op->off) && (n = ++op - sub->re_ops) >= nops) 3444887Schin { 3454887Schin if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t)))) 3464887Schin { 3474887Schin regfree(p); 3484887Schin return fatal(disc, REG_ESPACE, NiL); 3494887Schin } 3504887Schin op = sub->re_ops + n; 3514887Schin } 3524887Schin op->len = -1; 3534887Schin sub->re_flags = flags; 3544887Schin sub->re_min = minmatch; 3554887Schin return 0; 3564887Schin } 3574887Schin 3584887Schin void 3594887Schin regsubfree(regex_t* p) 3604887Schin { 3614887Schin Env_t* env; 3624887Schin regsub_t* sub; 3634887Schin 3644887Schin if (p && (env = p->env) && env->sub && (sub = p->re_sub)) 3654887Schin { 3664887Schin env->sub = 0; 3674887Schin p->re_sub = 0; 3684887Schin if (!(env->disc->re_flags & REG_NOFREE)) 3694887Schin { 3704887Schin if (sub->re_buf) 3714887Schin alloc(env->disc, sub->re_buf, 0); 3724887Schin if (sub->re_ops) 3734887Schin alloc(env->disc, sub->re_ops, 0); 3744887Schin alloc(env->disc, sub, 0); 3754887Schin } 3764887Schin } 3774887Schin } 378