Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/regex/regsubcomp.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
24
/*
25
* posix regex ed(1) style substitute compile
26
*/
27
28
#include "reglib.h"
29
30
static const regflags_t submap[] =
31
{
32
'g', REG_SUB_ALL,
33
'l', REG_SUB_LOWER,
34
'n', REG_SUB_NUMBER,
35
'p', REG_SUB_PRINT,
36
's', REG_SUB_STOP,
37
'u', REG_SUB_UPPER,
38
'w', REG_SUB_WRITE|REG_SUB_LAST,
39
0, 0
40
};
41
42
int
43
regsubflags(regex_t* p, register const char* s, char** e, int delim, register const regflags_t* map, int* pm, regflags_t* pf)
44
{
45
register int c;
46
register const regflags_t* m;
47
regflags_t flags;
48
int minmatch;
49
regdisc_t* disc;
50
51
flags = pf ? *pf : 0;
52
minmatch = pm ? *pm : 0;
53
if (!map)
54
map = submap;
55
while (!(flags & REG_SUB_LAST))
56
{
57
if (!(c = *s++) || c == delim)
58
{
59
s--;
60
break;
61
}
62
else if (c >= '0' && c <= '9')
63
{
64
if (minmatch)
65
{
66
disc = p->env->disc;
67
regfree(p);
68
return fatal(disc, REG_EFLAGS, s - 1);
69
}
70
minmatch = c - '0';
71
while (*s >= '0' && *s <= '9')
72
minmatch = minmatch * 10 + *s++ - '0';
73
}
74
else
75
{
76
for (m = map; *m; m++)
77
if (*m++ == c)
78
{
79
if (flags & *m)
80
{
81
disc = p->env->disc;
82
regfree(p);
83
return fatal(disc, REG_EFLAGS, s - 1);
84
}
85
flags |= *m--;
86
break;
87
}
88
if (!*m)
89
{
90
s--;
91
break;
92
}
93
}
94
}
95
if (pf)
96
*pf = flags;
97
if (pm)
98
*pm = minmatch;
99
if (e)
100
*e = (char*)s;
101
return 0;
102
}
103
104
/*
105
* compile substitute rhs and optional flags
106
*/
107
108
int
109
regsubcomp(regex_t* p, register const char* s, const regflags_t* map, int minmatch, regflags_t flags)
110
{
111
register regsub_t* sub;
112
register int c;
113
register int d;
114
register char* t;
115
register regsubop_t* op;
116
char* e;
117
const char* r;
118
int sre;
119
int f;
120
int g;
121
int n;
122
int nops;
123
const char* o;
124
regdisc_t* disc;
125
126
disc = p->env->disc;
127
if (p->env->flags & REG_NOSUB)
128
{
129
regfree(p);
130
return fatal(disc, REG_BADPAT, NiL);
131
}
132
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))))
133
{
134
if (sub)
135
alloc(p->env->disc, sub, 0);
136
regfree(p);
137
return fatal(disc, REG_ESPACE, s);
138
}
139
sub->re_buf = sub->re_end = 0;
140
p->re_sub = sub;
141
p->env->sub = 1;
142
op = sub->re_ops;
143
o = s;
144
if (!(p->env->flags & REG_DELIMITED))
145
d = 0;
146
else
147
switch (d = *(s - 1))
148
{
149
case '\\':
150
case '\n':
151
case '\r':
152
regfree(p);
153
return fatal(disc, REG_EDELIM, s);
154
}
155
sre = p->env->flags & REG_SHELL;
156
t = sub->re_rhs;
157
if (d)
158
{
159
r = s;
160
for (;;)
161
{
162
if (!*s)
163
{
164
if (p->env->flags & REG_MUSTDELIM)
165
{
166
regfree(p);
167
return fatal(disc, REG_EDELIM, r);
168
}
169
break;
170
}
171
else if (*s == d)
172
{
173
flags |= REG_SUB_FULL;
174
s++;
175
break;
176
}
177
else if (*s++ == '\\' && !*s++)
178
{
179
regfree(p);
180
return fatal(disc, REG_EESCAPE, r);
181
}
182
}
183
if (*s)
184
{
185
if (n = regsubflags(p, s, &e, d, map, &minmatch, &flags))
186
return n;
187
s = (const char*)e;
188
}
189
p->re_npat = s - o;
190
s = r;
191
}
192
else
193
p->re_npat = 0;
194
op->op = f = g = flags & (REG_SUB_LOWER|REG_SUB_UPPER);
195
op->off = 0;
196
while ((c = *s++) != d)
197
{
198
again:
199
if (!c)
200
{
201
p->re_npat = s - o - 1;
202
break;
203
}
204
else if (c == '\\')
205
{
206
if (*s == c)
207
{
208
*t++ = *s++;
209
continue;
210
}
211
if ((c = *s++) == d)
212
goto again;
213
if (!c)
214
{
215
regfree(p);
216
return fatal(disc, REG_EESCAPE, s - 2);
217
}
218
if (c == '&')
219
{
220
*t++ = c;
221
continue;
222
}
223
}
224
else if (c == '&')
225
{
226
if (sre)
227
{
228
*t++ = c;
229
continue;
230
}
231
}
232
else
233
{
234
switch (op->op)
235
{
236
case REG_SUB_UPPER:
237
if (islower(c))
238
c = toupper(c);
239
break;
240
case REG_SUB_LOWER:
241
if (isupper(c))
242
c = tolower(c);
243
break;
244
case REG_SUB_UPPER|REG_SUB_LOWER:
245
if (isupper(c))
246
c = tolower(c);
247
else if (islower(c))
248
c = toupper(c);
249
break;
250
}
251
*t++ = c;
252
continue;
253
}
254
switch (c)
255
{
256
case 0:
257
s--;
258
continue;
259
case '&':
260
c = 0;
261
break;
262
case '0': case '1': case '2': case '3': case '4':
263
case '5': case '6': case '7': case '8': case '9':
264
c -= '0';
265
if (isdigit(*s) && (p->env->flags & REG_MULTIREF))
266
c = c * 10 + *s++ - '0';
267
break;
268
case 'l':
269
if (c = *s)
270
{
271
s++;
272
if (isupper(c))
273
c = tolower(c);
274
*t++ = c;
275
}
276
continue;
277
case 'u':
278
if (c = *s)
279
{
280
s++;
281
if (islower(c))
282
c = toupper(c);
283
*t++ = c;
284
}
285
continue;
286
case 'E':
287
f = g;
288
set:
289
if ((op->len = (t - sub->re_rhs) - op->off) && (n = ++op - sub->re_ops) >= nops)
290
{
291
if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t))))
292
{
293
regfree(p);
294
return fatal(disc, REG_ESPACE, NiL);
295
}
296
op = sub->re_ops + n;
297
}
298
op->op = f;
299
op->off = t - sub->re_rhs;
300
continue;
301
case 'L':
302
g = f;
303
f = REG_SUB_LOWER;
304
goto set;
305
case 'U':
306
g = f;
307
f = REG_SUB_UPPER;
308
goto set;
309
default:
310
if (!sre)
311
{
312
*t++ = chresc(s - 2, &e);
313
s = (const char*)e;
314
continue;
315
}
316
s--;
317
c = -1;
318
break;
319
}
320
if (c > p->re_nsub)
321
{
322
regfree(p);
323
return fatal(disc, REG_ESUBREG, s - 1);
324
}
325
if ((n = op - sub->re_ops) >= (nops - 2))
326
{
327
if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t))))
328
{
329
regfree(p);
330
return fatal(disc, REG_ESPACE, NiL);
331
}
332
op = sub->re_ops + n;
333
}
334
if (op->len = (t - sub->re_rhs) - op->off)
335
op++;
336
op->op = f;
337
op->off = c;
338
op->len = 0;
339
op++;
340
op->op = f;
341
op->off = t - sub->re_rhs;
342
}
343
if ((op->len = (t - sub->re_rhs) - op->off) && (n = ++op - sub->re_ops) >= nops)
344
{
345
if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t))))
346
{
347
regfree(p);
348
return fatal(disc, REG_ESPACE, NiL);
349
}
350
op = sub->re_ops + n;
351
}
352
op->len = -1;
353
sub->re_flags = flags;
354
sub->re_min = minmatch;
355
return 0;
356
}
357
358
void
359
regsubfree(regex_t* p)
360
{
361
Env_t* env;
362
regsub_t* sub;
363
364
if (p && (env = p->env) && env->sub && (sub = p->re_sub))
365
{
366
env->sub = 0;
367
p->re_sub = 0;
368
if (!(env->disc->re_flags & REG_NOFREE))
369
{
370
if (sub->re_buf)
371
alloc(env->disc, sub->re_buf, 0);
372
if (sub->re_ops)
373
alloc(env->disc, sub->re_ops, 0);
374
alloc(env->disc, sub, 0);
375
}
376
}
377
}
378
379