1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 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
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)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
regsub(const regex_t * p,Sfio_t * dp,const char * op,const char * sp,size_t nmatch,regmatch_t * match,regflags_t flags)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