1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2008 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 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 * OBSOLETE Sfio_t buffer interface -- use regsubcomp(),regsubexec() 26 */ 27 28 #include "reglib.h" 29 30 /* 31 * do a single substitution 32 */ 33 34 static int 35 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) 36 { 37 register int c; 38 char* s; 39 char* e; 40 const char* b; 41 regflags_t f; 42 43 f = flags &= (REG_SUB_LOWER|REG_SUB_UPPER); 44 for (;;) 45 { 46 switch (c = *sp++) 47 { 48 case 0: 49 return 0; 50 case '~': 51 if (!sre || *sp != '(') 52 { 53 sfputc(dp, c); 54 continue; 55 } 56 b = sp - 1; 57 sp++; 58 break; 59 case '\\': 60 if (sre) 61 { 62 sfputc(dp, chresc(sp - 1, &s)); 63 sp = (const char*)s; 64 continue; 65 } 66 if (*sp == '&') 67 { 68 c = *sp++; 69 sfputc(dp, c); 70 continue; 71 } 72 break; 73 case '&': 74 if (sre) 75 { 76 sfputc(dp, c); 77 continue; 78 } 79 sp--; 80 break; 81 default: 82 switch (flags) 83 { 84 case REG_SUB_UPPER: 85 if (islower(c)) 86 c = toupper(c); 87 break; 88 case REG_SUB_LOWER: 89 if (isupper(c)) 90 c = tolower(c); 91 break; 92 case REG_SUB_UPPER|REG_SUB_LOWER: 93 if (isupper(c)) 94 c = tolower(c); 95 else if (islower(c)) 96 c = toupper(c); 97 break; 98 } 99 sfputc(dp, c); 100 continue; 101 } 102 switch (c = *sp++) 103 { 104 case 0: 105 sp--; 106 continue; 107 case '&': 108 c = 0; 109 break; 110 case '0': case '1': case '2': case '3': case '4': 111 case '5': case '6': case '7': case '8': case '9': 112 c -= '0'; 113 if (sre) 114 while (isdigit(*sp)) 115 c = c * 10 + *sp++ - '0'; 116 break; 117 case 'l': 118 if (sre && *sp != ')') 119 { 120 c = -1; 121 break; 122 } 123 if (c = *sp) 124 { 125 sp++; 126 if (isupper(c)) 127 c = tolower(c); 128 sfputc(dp, c); 129 } 130 continue; 131 case 'u': 132 if (sre) 133 { 134 if (*sp != ')') 135 { 136 c = -1; 137 break; 138 } 139 sp++; 140 } 141 if (c = *sp) 142 { 143 sp++; 144 if (islower(c)) 145 c = toupper(c); 146 sfputc(dp, c); 147 } 148 continue; 149 case 'E': 150 if (sre) 151 { 152 if (*sp != ')') 153 { 154 c = -1; 155 break; 156 } 157 sp++; 158 } 159 flags = f; 160 continue; 161 case 'L': 162 if (sre) 163 { 164 if (*sp != ')') 165 { 166 c = -1; 167 break; 168 } 169 sp++; 170 } 171 f = flags; 172 flags = REG_SUB_LOWER; 173 continue; 174 case 'U': 175 if (sre) 176 { 177 if (*sp != ')') 178 { 179 c = -1; 180 break; 181 } 182 sp++; 183 } 184 f = flags; 185 flags = REG_SUB_UPPER; 186 continue; 187 default: 188 if (!sre) 189 { 190 sfputc(dp, chresc(sp - 2, &s)); 191 sp = (const char*)s; 192 continue; 193 } 194 sp--; 195 c = -1; 196 break; 197 } 198 if (sre) 199 { 200 if (c < 0 || *sp != ')') 201 { 202 for (; b < sp; b++) 203 sfputc(dp, *b); 204 continue; 205 } 206 sp++; 207 } 208 if (c >= nmatch) 209 return REG_ESUBREG; 210 s = (char*)op + match[c].rm_so; 211 e = (char*)op + match[c].rm_eo; 212 while (s < e) 213 { 214 c = *s++; 215 switch (flags) 216 { 217 case REG_SUB_UPPER: 218 if (islower(c)) 219 c = toupper(c); 220 break; 221 case REG_SUB_LOWER: 222 if (isupper(c)) 223 c = tolower(c); 224 break; 225 case REG_SUB_UPPER|REG_SUB_LOWER: 226 if (isupper(c)) 227 c = tolower(c); 228 else if (islower(c)) 229 c = toupper(c); 230 break; 231 } 232 sfputc(dp, c); 233 } 234 } 235 } 236 237 /* 238 * ed(1) style substitute using matches from last regexec() 239 */ 240 241 int 242 regsub(const regex_t* p, Sfio_t* dp, const char* op, const char* sp, size_t nmatch, regmatch_t* match, regflags_t flags) 243 { 244 int m; 245 int r; 246 int sre; 247 248 if ((p->env->flags & REG_NOSUB) || !nmatch) 249 return fatal(p->env->disc, REG_BADPAT, NiL); 250 m = (flags >> 16) & 0x3fff; 251 sre = !!(p->env->flags & REG_SHELL); 252 r = 0; 253 do 254 { 255 if (--m > 0) 256 sfwrite(dp, op, match->rm_eo); 257 else 258 { 259 sfwrite(dp, op, match->rm_so); 260 if (r = subold(dp, op, sp, nmatch, match, flags, sre)) 261 return fatal(p->env->disc, r, NiL); 262 } 263 op += match->rm_eo; 264 } 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)))); 265 if (r && r != REG_NOMATCH) 266 return fatal(p->env->disc, r, NiL); 267 sfputr(dp, op, -1); 268 return 0; 269 } 270