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 /* return an alist of BREGEXP or return NULL if it's not a
112 * where=!tmp!opt!ig,!temp!opt!i
114 alist *get_bregexps(const char *where)
116 char *p = (char *)where;
117 alist *list = New(alist(10, not_owned_by_alist));
120 reg = new_bregexp(p);
125 reg = new_bregexp(p);
136 bool BREGEXP::extract_regexp(const char *motif)
138 if (!motif || (*motif == '\0')) {
142 char *search = (char *) motif + 1;
144 int options = REG_EXTENDED | REG_NEWLINE;
146 bool found_motif = false;
148 /* extract 1st part */
149 char *dest = expr = bstrdup(motif);
151 while (*search && !ok) {
152 if (search[0] == '\\' && search[1] == sep) {
153 *dest++ = *++search; /* we skip separator */
155 } else if (*search == sep) { /* we found end of expression */
158 if (subst) { /* already have found motif */
162 *dest++ = *++search; /* we skip separator */
163 subst = dest; /* get replaced string */
170 *dest = '\0'; /* in case of */
179 while (*search && !ok) {
180 if (*search == 'i') {
181 options |= REG_ICASE;
183 } else if (*search == 'g') {
184 /* recherche multiple*/
186 } else if (*search == sep) {
189 } else { /* end of options */
195 int rc = regcomp(&preg, expr, options);
198 regerror(rc, &preg, prbuf, sizeof(prbuf));
199 Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
203 eor = search; /* useful to find the next regexp in where */
209 #define BREGEX_CAST unsigned
211 #define BREGEX_CAST const
214 /* return regexp->result */
215 char *BREGEXP::replace(const char *fname)
217 int flen = strlen(fname);
218 int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, ®s);
221 Dmsg0(100, "E: regex mismatch\n");
222 return return_fname(fname, flen);
225 int len = compute_dest_len(fname, ®s);
228 result = check_pool_memory_size(result, len);
229 edit_subst(fname, ®s);
231 } else { /* error in substitution */
232 Dmsg0(100, "E: error in substitution\n");
233 return return_fname(fname, flen);
239 char *BREGEXP::return_fname(const char *fname, int len)
241 result = check_pool_memory_size(result, len+1);
242 strcpy(result,fname);
246 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
250 char *psubst = subst;
253 if (!fname || !regs) {
258 if (regs->start[0] < 0) {
262 for (p = psubst++; *p ; p = psubst++) {
263 /* match $1 \1 back references */
264 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
265 no = *psubst++ - '0';
267 /* we check if the back reference exists */
268 /* references can not match if we are using (..)? */
270 if (regs->start[no] >= 0 && regs->end[no] >= 0) {
271 len += regs->end[no] - regs->start[no];
279 /* $0 is replaced by subst */
280 len -= regs->end[0] - regs->start[0];
281 len += strlen(fname) + 1;
286 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
290 char *psubst = subst;
294 /* il faut recopier fname dans dest
295 * on recopie le debut fname -> regs->start[0]
298 for (i = 0; i < regs->start[0] ; i++) {
299 result[i] = fname[i];
302 /* on recopie le motif de remplacement (avec tous les $x) */
304 for (p = psubst++; *p ; p = psubst++) {
305 /* match $1 \1 back references */
306 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
307 no = *psubst++ - '0';
309 /* have a back reference ? */
310 if (regs->start[no] >= 0 && regs->end[no] >= 0) {
311 len = regs->end[no] - regs->start[no];
312 bstrncpy(result + i, fname + regs->start[no], len + 1);
321 /* we copy what is out of the match */
322 strcpy(result + i, fname + regs->end[0]);
327 void BREGEXP::debug()
329 printf("expr=[%s]\n", expr);
330 printf("subst=[%s]\n", subst);
331 printf("result=%s\n", result?result:"(null)");