2 * Manipulation routines for BREGEXP list
4 * Eric Bollengier, March 2007
10 Bacula® - The Network Backup Solution
12 Copyright (C) 2006-2006 Free Software Foundation Europe e.V.
14 The main author of Bacula is Kern Sibbald, with contributions from
15 many others, a complete list can be found in the file AUTHORS.
16 This program is Free Software; you can redistribute it and/or
17 modify it under the terms of version two of the GNU General Public
18 License as published by the Free Software Foundation plus additions
19 that are listed in the file LICENSE.
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 Bacula® is a registered trademark of John Walker.
32 The licensor of Bacula is the Free Software Foundation Europe
33 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34 Switzerland, email:ftf@fsfeurope.org.
43 BREGEXP *new_bregexp(const char *motif)
45 Dmsg0(500, "bregexp: creating new bregexp object\n");
46 BREGEXP *self = (BREGEXP *)malloc(sizeof(BREGEXP));
47 memset(self, 0, sizeof(BREGEXP));
49 if (!self->extract_regexp(motif)) {
50 Dmsg0(100, "bregexp: extract_regexp error\n");
55 static int _start[RE_NREGS];
56 static int _end[RE_NREGS];
58 self->result = get_pool_memory(PM_FNAME);
59 self->result[0] = '\0';
62 /* TODO: que devient cette memoire... */
63 self->_regs_match = (int *) malloc (2*RE_NREGS * sizeof(int));
65 self->regs.num_regs = RE_NREGS;
66 self->regs.start = self->_regs_match;
67 self->regs.end = self->_regs_match+(RE_NREGS * sizeof(int));
73 void free_bregexp(BREGEXP *self)
75 Dmsg0(500, "bregexp: freeing BREGEXP object\n");
81 free_pool_memory(self->result);
83 if (self->_regs_match) {
84 free(self->_regs_match);
91 void free_bregexps(alist *bregexps)
93 Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
96 foreach_alist(elt, bregexps) {
101 char *apply_bregexps(const char *fname, alist *bregexps)
104 char *ret = (char *) fname;
105 foreach_alist(elt, bregexps) {
106 ret = elt->replace(ret);
111 char *get_next_bregexp(char *where)
117 if (!where && !*where) {
123 /* return an alist of BREGEXP or return NULL if it's not a
124 * where=!tmp!opt!ig,!temp!opt!i
126 alist *get_bregexps(const char *where)
128 char *p = (char *)where;
129 alist *list = New(alist(10, not_owned_by_alist));
132 reg = new_bregexp(p);
137 reg = new_bregexp(p);
148 bool BREGEXP::extract_regexp(const char *motif)
150 if (!motif || (*motif == '\0')) {
154 char *search = (char *) motif + 1;
156 int options = REG_EXTENDED | REG_NEWLINE;
158 bool found_motif = false;
160 /* extract 1st part */
161 char *dest = expr = bstrdup(motif);
163 while (*search && !ok) {
164 if (search[0] == '\\' && search[1] == sep) {
165 *dest++ = *++search; /* we skip separator */
167 } else if (*search == sep) { /* we found end of expression */
170 if (subst) { /* already have found motif */
174 *dest++ = *++search; /* we skip separator */
175 subst = dest; /* get replaced string */
182 *dest = '\0'; /* in case of */
191 while (*search && !ok) {
192 if (*search == 'i') {
193 options |= REG_ICASE;
195 } else if (*search == 'g') {
196 /* recherche multiple*/
198 } else if (*search == sep) {
201 } else { /* end of options */
207 int rc = regcomp(&preg, expr, options);
210 regerror(rc, &preg, prbuf, sizeof(prbuf));
211 Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
215 eor = search; /* useful to find the next regexp in where */
221 #define BREGEX_CAST unsigned
223 #define BREGEX_CAST const
226 /* return regexp->result */
227 char *BREGEXP::replace(const char *fname)
229 int flen = strlen(fname);
230 int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, ®s);
233 Dmsg0(100, "E: regex mismatch\n");
234 return return_fname(fname, flen);
237 int len = compute_dest_len(fname, ®s);
240 result = check_pool_memory_size(result, len);
241 edit_subst(fname, ®s);
243 } else { /* error in substitution */
244 Dmsg0(100, "E: error in substitution\n");
245 return return_fname(fname, flen);
251 char *BREGEXP::return_fname(const char *fname, int len)
253 result = check_pool_memory_size(result, len+1);
254 strcpy(result,fname);
258 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
262 char *psubst = subst;
265 if (!fname || !regs) {
270 if (regs->start[0] < 0) {
274 for (p = psubst++; *p ; p = psubst++) {
275 /* match $1 \1 back references */
276 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
277 no = *psubst++ - '0';
279 /* we check if the back reference exists */
280 /* references can not match if we are using (..)? */
282 if (regs->start[no] >= 0 && regs->end[no] >= 0) {
283 len += regs->end[no] - regs->start[no];
291 /* $0 is replaced by subst */
292 len -= regs->end[0] - regs->start[0];
293 len += strlen(fname) + 1;
298 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
302 char *psubst = subst;
306 /* il faut recopier fname dans dest
307 * on recopie le debut fname -> regs->start[0]
310 for (i = 0; i < regs->start[0] ; i++) {
311 result[i] = fname[i];
314 /* on recopie le motif de remplacement (avec tous les $x) */
316 for (p = psubst++; *p ; p = psubst++) {
317 /* match $1 \1 back references */
318 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
319 no = *psubst++ - '0';
321 /* have a back reference ? */
322 if (regs->start[no] >= 0 && regs->end[no] >= 0) {
323 len = regs->end[no] - regs->start[no];
324 bstrncpy(result + i, fname + regs->start[no], len + 1);
333 /* we copy what is out of the match */
334 strcpy(result + i, fname + regs->end[0]);
339 void BREGEXP::debug()
341 printf("expr=[%s]\n", expr);
342 printf("subst=[%s]\n", subst);
343 printf("result=%s\n", result?result:"(null)");
348 int main(int argc, char **argv)
352 reg = new_bregexp(argv[1]);
355 reg->replace(argv[2]);
357 printf("%s => %s\n", argv[1], reg->result);