1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
25 * posix regex ed(1) style substitute compile
30 static const regflags_t submap
[] =
38 'w', REG_SUB_WRITE
|REG_SUB_LAST
,
43 regsubflags(regex_t
* p
, register const char* s
, char** e
, int delim
, register const regflags_t
* map
, int* pm
, regflags_t
* pf
)
46 register const regflags_t
* m
;
52 minmatch
= pm
? *pm
: 0;
55 while (!(flags
& REG_SUB_LAST
))
57 if (!(c
= *s
++) || c
== delim
)
62 else if (c
>= '0' && c
<= '9')
68 return fatal(disc
, REG_EFLAGS
, s
- 1);
71 while (*s
>= '0' && *s
<= '9')
72 minmatch
= minmatch
* 10 + *s
++ - '0';
76 for (m
= map
; *m
; m
++)
83 return fatal(disc
, REG_EFLAGS
, s
- 1);
105 * compile substitute rhs and optional flags
109 regsubcomp(regex_t
* p
, register const char* s
, const regflags_t
* map
, int minmatch
, regflags_t flags
)
111 register regsub_t
* sub
;
115 register regsubop_t
* op
;
127 if (p
->env
->flags
& REG_NOSUB
)
130 return fatal(disc
, REG_BADPAT
, NiL
);
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
))))
135 alloc(p
->env
->disc
, sub
, 0);
137 return fatal(disc
, REG_ESPACE
, s
);
139 sub
->re_buf
= sub
->re_end
= 0;
144 if (!(p
->env
->flags
& REG_DELIMITED
))
147 switch (d
= *(s
- 1))
153 return fatal(disc
, REG_EDELIM
, s
);
155 sre
= p
->env
->flags
& REG_SHELL
;
164 if (p
->env
->flags
& REG_MUSTDELIM
)
167 return fatal(disc
, REG_EDELIM
, r
);
173 flags
|= REG_SUB_FULL
;
177 else if (*s
++ == '\\' && !*s
++)
180 return fatal(disc
, REG_EESCAPE
, r
);
185 if (n
= regsubflags(p
, s
, &e
, d
, map
, &minmatch
, &flags
))
194 op
->op
= f
= g
= flags
& (REG_SUB_LOWER
|REG_SUB_UPPER
);
196 while ((c
= *s
++) != d
)
201 p
->re_npat
= s
- o
- 1;
216 return fatal(disc
, REG_EESCAPE
, s
- 2);
244 case REG_SUB_UPPER
|REG_SUB_LOWER
:
262 case '0': case '1': case '2': case '3': case '4':
263 case '5': case '6': case '7': case '8': case '9':
265 if (isdigit(*s
) && (p
->env
->flags
& REG_MULTIREF
))
266 c
= c
* 10 + *s
++ - '0';
289 if ((op
->len
= (t
- sub
->re_rhs
) - op
->off
) && (n
= ++op
- sub
->re_ops
) >= nops
)
291 if (!(sub
->re_ops
= (regsubop_t
*)alloc(p
->env
->disc
, sub
->re_ops
, (nops
*= 2) * sizeof(regsubop_t
))))
294 return fatal(disc
, REG_ESPACE
, NiL
);
296 op
= sub
->re_ops
+ n
;
299 op
->off
= t
- sub
->re_rhs
;
312 *t
++ = chresc(s
- 2, &e
);
323 return fatal(disc
, REG_ESUBREG
, s
- 1);
325 if ((n
= op
- sub
->re_ops
) >= (nops
- 2))
327 if (!(sub
->re_ops
= (regsubop_t
*)alloc(p
->env
->disc
, sub
->re_ops
, (nops
*= 2) * sizeof(regsubop_t
))))
330 return fatal(disc
, REG_ESPACE
, NiL
);
332 op
= sub
->re_ops
+ n
;
334 if (op
->len
= (t
- sub
->re_rhs
) - op
->off
)
341 op
->off
= t
- sub
->re_rhs
;
343 if ((op
->len
= (t
- sub
->re_rhs
) - op
->off
) && (n
= ++op
- sub
->re_ops
) >= nops
)
345 if (!(sub
->re_ops
= (regsubop_t
*)alloc(p
->env
->disc
, sub
->re_ops
, (nops
*= 2) * sizeof(regsubop_t
))))
348 return fatal(disc
, REG_ESPACE
, NiL
);
350 op
= sub
->re_ops
+ n
;
353 sub
->re_flags
= flags
;
354 sub
->re_min
= minmatch
;
359 regsubfree(regex_t
* p
)
364 if (p
&& (env
= p
->env
) && env
->sub
&& (sub
= p
->re_sub
))
368 if (!(env
->disc
->re_flags
& REG_NOFREE
))
371 alloc(env
->disc
, sub
->re_buf
, 0);
373 alloc(env
->disc
, sub
->re_ops
, 0);
374 alloc(env
->disc
, sub
, 0);