1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * Phong Vo <kpv@research.att.com> * 20*4887Schin * * 21*4887Schin ***********************************************************************/ 22*4887Schin #pragma prototyped 23*4887Schin 24*4887Schin /* 25*4887Schin * posix regex ed(1) style substitute execute 26*4887Schin */ 27*4887Schin 28*4887Schin #include "reglib.h" 29*4887Schin 30*4887Schin #define NEED(p,b,n,r) \ 31*4887Schin do \ 32*4887Schin { \ 33*4887Schin if (((b)->re_end - (b)->re_cur) < (n)) \ 34*4887Schin { \ 35*4887Schin size_t o = (b)->re_cur - (b)->re_buf; \ 36*4887Schin size_t a = ((b)->re_end - (b)->re_buf); \ 37*4887Schin if (a < n) \ 38*4887Schin a = roundof(n, 128); \ 39*4887Schin a *= 2; \ 40*4887Schin if (!((b)->re_buf = alloc(p->env->disc, (b)->re_buf, a))) \ 41*4887Schin { \ 42*4887Schin (b)->re_buf = (b)->re_cur = (b)->re_end = 0; \ 43*4887Schin c = REG_ESPACE; \ 44*4887Schin r; \ 45*4887Schin } \ 46*4887Schin (b)->re_cur = (b)->re_buf + o; \ 47*4887Schin (b)->re_end = (b)->re_buf + a; \ 48*4887Schin } \ 49*4887Schin } while (0) 50*4887Schin 51*4887Schin #define PUTC(p,b,x,r) \ 52*4887Schin do \ 53*4887Schin { \ 54*4887Schin NEED(p, b, 1, r); \ 55*4887Schin *(b)->re_cur++ = (x); \ 56*4887Schin } while (0) 57*4887Schin 58*4887Schin #define PUTS(p,b,x,z,r) \ 59*4887Schin do if (z) \ 60*4887Schin { \ 61*4887Schin NEED(p, b, z, r); \ 62*4887Schin memcpy((b)->re_cur, x, z); \ 63*4887Schin (b)->re_cur += (z); \ 64*4887Schin } while (0) 65*4887Schin 66*4887Schin /* 67*4887Schin * do a single substitution 68*4887Schin */ 69*4887Schin 70*4887Schin static int 71*4887Schin sub(const regex_t* p, register regsub_t* b, const char* ss, register regsubop_t* op, size_t nmatch, register regmatch_t* match) 72*4887Schin { 73*4887Schin register char* s; 74*4887Schin register char* e; 75*4887Schin register int c; 76*4887Schin 77*4887Schin for (;; op++) 78*4887Schin { 79*4887Schin switch (op->len) 80*4887Schin { 81*4887Schin case -1: 82*4887Schin break; 83*4887Schin case 0: 84*4887Schin if (op->off >= nmatch) 85*4887Schin return REG_ESUBREG; 86*4887Schin if ((c = match[op->off].rm_so) < 0) 87*4887Schin continue; 88*4887Schin s = (char*)ss + c; 89*4887Schin if ((c = match[op->off].rm_eo) < 0) 90*4887Schin continue; 91*4887Schin e = (char*)ss + c; 92*4887Schin NEED(p, b, e - s, return c); 93*4887Schin switch (op->op) 94*4887Schin { 95*4887Schin case REG_SUB_UPPER: 96*4887Schin while (s < e) 97*4887Schin { 98*4887Schin c = *s++; 99*4887Schin if (islower(c)) 100*4887Schin c = toupper(c); 101*4887Schin *b->re_cur++ = c; 102*4887Schin } 103*4887Schin break; 104*4887Schin case REG_SUB_LOWER: 105*4887Schin while (s < e) 106*4887Schin { 107*4887Schin c = *s++; 108*4887Schin if (isupper(c)) 109*4887Schin c = tolower(c); 110*4887Schin *b->re_cur++ = c; 111*4887Schin } 112*4887Schin break; 113*4887Schin case REG_SUB_UPPER|REG_SUB_LOWER: 114*4887Schin while (s < e) 115*4887Schin { 116*4887Schin c = *s++; 117*4887Schin if (isupper(c)) 118*4887Schin c = tolower(c); 119*4887Schin else if (islower(c)) 120*4887Schin c = toupper(c); 121*4887Schin *b->re_cur++ = c; 122*4887Schin } 123*4887Schin break; 124*4887Schin default: 125*4887Schin while (s < e) 126*4887Schin *b->re_cur++ = *s++; 127*4887Schin break; 128*4887Schin } 129*4887Schin continue; 130*4887Schin default: 131*4887Schin NEED(p, b, op->len, return c); 132*4887Schin s = b->re_rhs + op->off; 133*4887Schin e = s + op->len; 134*4887Schin while (s < e) 135*4887Schin *b->re_cur++ = *s++; 136*4887Schin continue; 137*4887Schin } 138*4887Schin break; 139*4887Schin } 140*4887Schin return 0; 141*4887Schin } 142*4887Schin 143*4887Schin /* 144*4887Schin * ed(1) style substitute using matches from last regexec() 145*4887Schin */ 146*4887Schin 147*4887Schin int 148*4887Schin regsubexec(const regex_t* p, const char* s, size_t nmatch, regmatch_t* match) 149*4887Schin { 150*4887Schin register int c; 151*4887Schin register regsub_t* b; 152*4887Schin const char* e; 153*4887Schin int m; 154*4887Schin 155*4887Schin if (!p->env->sub || (p->env->flags & REG_NOSUB) || !nmatch) 156*4887Schin return fatal(p->env->disc, REG_BADPAT, NiL); 157*4887Schin b = p->re_sub; 158*4887Schin m = b->re_min; 159*4887Schin b->re_cur = b->re_buf; 160*4887Schin e = (const char*)p->env->end; 161*4887Schin for (;;) 162*4887Schin { 163*4887Schin if (--m > 0) 164*4887Schin PUTS(p, b, s, match->rm_eo, return fatal(p->env->disc, c, NiL)); 165*4887Schin else 166*4887Schin { 167*4887Schin PUTS(p, b, s, match->rm_so, return fatal(p->env->disc, c, NiL)); 168*4887Schin if (c = sub(p, b, s, b->re_ops, nmatch, match)) 169*4887Schin return fatal(p->env->disc, c, NiL); 170*4887Schin } 171*4887Schin s += match->rm_eo; 172*4887Schin if (m <= 0 && !(b->re_flags & REG_SUB_ALL)) 173*4887Schin break; 174*4887Schin if (c = regnexec(p, s, e - s, nmatch, match, p->env->flags|(match->rm_so == match->rm_eo ? REG_ADVANCE : 0))) 175*4887Schin { 176*4887Schin if (c != REG_NOMATCH) 177*4887Schin return fatal(p->env->disc, c, NiL); 178*4887Schin break; 179*4887Schin } 180*4887Schin } 181*4887Schin while (s < e) 182*4887Schin { 183*4887Schin c = *s++; 184*4887Schin PUTC(p, b, c, return fatal(p->env->disc, c, NiL)); 185*4887Schin } 186*4887Schin NEED(p, b, 1, return fatal(p->env->disc, c, NiL)); 187*4887Schin *b->re_cur = 0; 188*4887Schin b->re_len = b->re_cur - b->re_buf; 189*4887Schin return 0; 190*4887Schin } 191