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 /* Free a bregexps alist
93 void free_bregexps(alist *bregexps)
95 Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
98 foreach_alist(elt, bregexps) {
103 /* Apply all regexps to fname
105 char *apply_bregexps(const char *fname, alist *bregexps)
108 char *ret = (char *) fname;
109 foreach_alist(elt, bregexps) {
110 ret = elt->replace(ret);
112 Dmsg2(500, "bregexp: fname=%s ret=%s\n", fname, ret);
116 /* return an alist of BREGEXP or return NULL if it's not a
117 * where=!tmp!opt!ig,!temp!opt!i
119 alist *get_bregexps(const char *where)
121 char *p = (char *)where;
122 alist *list = New(alist(10, not_owned_by_alist));
125 reg = new_bregexp(p);
130 reg = new_bregexp(p);
141 bool BREGEXP::extract_regexp(const char *motif)
163 char *search = (char *) motif + 1;
164 int options = REG_EXTENDED | REG_NEWLINE;
166 bool found_motif = false;
168 /* extract 1st part */
169 char *dest = expr = bstrdup(motif);
171 while (*search && !ok) {
172 if (search[0] == '\\' && search[1] == sep) {
173 *dest++ = *++search; /* we skip separator */
175 } else if (*search == sep) { /* we found end of expression */
178 if (subst) { /* already have found motif */
182 *dest++ = *++search; /* we skip separator */
183 subst = dest; /* get replaced string */
190 *dest = '\0'; /* in case of */
199 while (*search && !ok) {
200 if (*search == 'i') {
201 options |= REG_ICASE;
203 } else if (*search == 'g') {
204 /* recherche multiple*/
206 } else if (*search == sep) {
209 } else { /* end of options */
215 int rc = regcomp(&preg, expr, options);
218 regerror(rc, &preg, prbuf, sizeof(prbuf));
219 Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
223 eor = search; /* useful to find the next regexp in where */
229 #define BREGEX_CAST unsigned
231 #define BREGEX_CAST const
234 /* return regexp->result */
235 char *BREGEXP::replace(const char *fname)
237 int flen = strlen(fname);
238 int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, ®s);
241 Dmsg0(500, "bregexp: regex mismatch\n");
242 return return_fname(fname, flen);
245 int len = compute_dest_len(fname, ®s);
248 result = check_pool_memory_size(result, len);
249 edit_subst(fname, ®s);
251 Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
253 } else { /* error in substitution */
254 Dmsg0(100, "bregexp: error in substitution\n");
255 return return_fname(fname, flen);
261 char *BREGEXP::return_fname(const char *fname, int len)
263 result = check_pool_memory_size(result, len+1);
264 strcpy(result,fname);
268 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
272 char *psubst = subst;
275 if (!fname || !regs) {
280 if (regs->start[0] < 0) {
284 for (p = psubst++; *p ; p = psubst++) {
285 /* match $1 \1 back references */
286 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
287 no = *psubst++ - '0';
289 /* we check if the back reference exists */
290 /* references can not match if we are using (..)? */
292 if (regs->start[no] >= 0 && regs->end[no] >= 0) {
293 len += regs->end[no] - regs->start[no];
301 /* $0 is replaced by subst */
302 len -= regs->end[0] - regs->start[0];
303 len += strlen(fname) + 1;
308 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
312 char *psubst = subst;
316 /* il faut recopier fname dans dest
317 * on recopie le debut fname -> regs->start[0]
320 for (i = 0; i < regs->start[0] ; i++) {
321 result[i] = fname[i];
324 /* on recopie le motif de remplacement (avec tous les $x) */
326 for (p = psubst++; *p ; p = psubst++) {
327 /* match $1 \1 back references */
328 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
329 no = *psubst++ - '0';
331 /* have a back reference ? */
332 if (regs->start[no] >= 0 && regs->end[no] >= 0) {
333 len = regs->end[no] - regs->start[no];
334 bstrncpy(result + i, fname + regs->start[no], len + 1);
343 /* we copy what is out of the match */
344 strcpy(result + i, fname + regs->end[0]);
349 void BREGEXP::debug()
351 printf("expr=[%s]\n", expr);
352 printf("subst=[%s]\n", subst);
353 printf("result=%s\n", result?result:"(null)");