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