]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/breg.c
ebl cleanup
[bacula/bacula] / bacula / patches / testing / breg.c
1 /*
2  * Manipulation routines for BREGEXP list
3  *
4  *  Eric Bollengier, March 2007
5  *
6  *  Version $Id$
7  *
8  */
9 /*
10    Bacula® - The Network Backup Solution
11
12    Copyright (C) 2006-2006 Free Software Foundation Europe e.V.
13
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.
20
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.
25
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
29    02110-1301, USA.
30
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.
35 */
36
37
38 #include "bacula.h"
39
40 #include "breg.h"
41 #include "mem_pool.h"
42
43 BREGEXP *new_bregexp(const char *motif)
44 {
45    Dmsg0(500, "bregexp: creating new bregexp object\n");
46    BREGEXP *self = (BREGEXP *)malloc(sizeof(BREGEXP));
47    memset(self, 0, sizeof(BREGEXP));
48    
49    if (!self->extract_regexp(motif)) {
50       Dmsg0(100, "bregexp: extract_regexp error\n");
51       free_bregexp(self);
52       return NULL;
53    }
54
55    static int _start[RE_NREGS];
56    static int _end[RE_NREGS];
57
58    self->result = get_pool_memory(PM_FNAME);
59    self->result[0] = '\0';
60
61 #ifdef HAVE_REGEX_H
62    /* TODO: que devient cette memoire... */
63    self->_regs_match = (int *) malloc (2*RE_NREGS * sizeof(int));
64
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));
68 #endif 
69
70    return self;
71 }
72
73 void free_bregexp(BREGEXP *self)
74 {
75    Dmsg0(500, "bregexp: freeing BREGEXP object\n");
76
77    if (self->expr) {
78       free(self->expr);
79    }
80    if (self->result) {
81       free_pool_memory(self->result);
82    }
83    if (self->_regs_match) {
84       free(self->_regs_match);
85    }
86
87    regfree(&self->preg);
88    free(self);
89 }
90
91 void free_bregexps(alist *bregexps)
92 {
93    Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
94
95    BREGEXP *elt;
96    foreach_alist(elt, bregexps) {
97       free_bregexp(elt);
98    }
99 }
100
101 char *apply_bregexps(const char *fname, alist *bregexps)
102 {
103    BREGEXP *elt;
104    char *ret = (char *) fname;
105    foreach_alist(elt, bregexps) {
106       ret = elt->replace(ret);
107    }
108    return ret;
109 }
110
111 /* return an alist of BREGEXP or return NULL if it's not a 
112  * where=!tmp!opt!ig,!temp!opt!i
113  */
114 alist *get_bregexps(const char *where)
115 {
116    char *p = (char *)where;
117    alist *list = New(alist(10, not_owned_by_alist));
118    BREGEXP *reg;
119
120    reg = new_bregexp(p);
121
122    while(reg) {
123       p = reg->eor;
124       list->append(reg);
125       reg = new_bregexp(p);
126    }
127
128    if (list->size()) {
129       return list;      
130    } else {
131       delete list;
132       return NULL;
133    }
134 }
135
136 bool BREGEXP::extract_regexp(const char *motif)
137 {
138    if (!motif || (*motif == '\0')) {
139       return false;
140    }
141    char sep = motif[0];
142    char *search = (char *) motif + 1;
143    char *replace;
144    int options = REG_EXTENDED | REG_NEWLINE;
145    bool ok = false;
146    bool found_motif = false;
147
148    /* extract 1st part */
149    char *dest = expr = bstrdup(motif);
150
151    while (*search && !ok) {
152       if (search[0] == '\\' && search[1] == sep) {
153          *dest++ = *++search;       /* we skip separator */ 
154
155       } else if (*search == sep) {  /* we found end of expression */
156          *dest++ = '\0';
157
158          if (subst) {           /* already have found motif */
159             ok = true;
160
161          } else {
162             *dest++ = *++search; /* we skip separator */ 
163             subst = dest;        /* get replaced string */
164          }
165
166       } else {
167          *dest++ = *search++;
168       }
169    }
170    *dest = '\0';                /* in case of */
171    
172    if (!ok || !subst) {
173       /* bad regexp */
174       return false;
175    }
176
177    ok = false;
178    /* find options */
179    while (*search && !ok) {
180       if (*search == 'i') {
181          options |= REG_ICASE;
182
183       } else if (*search == 'g') {
184               /* recherche multiple*/
185
186       } else if (*search == sep) {
187          /* skip separator */
188
189       } else {                  /* end of options */
190          ok = true;
191       }
192       search++;
193    }
194
195    int rc = regcomp(&preg, expr, options);
196    if (rc != 0) {
197       char prbuf[500];
198       regerror(rc, &preg, prbuf, sizeof(prbuf));
199       Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
200       return false;
201    }
202
203    eor = search;                /* useful to find the next regexp in where */
204
205    return true;
206 }
207
208 #ifndef HAVE_REGEX_H
209  #define BREGEX_CAST unsigned
210 #else
211  #define BREGEX_CAST const
212 #endif
213
214 /* return regexp->result */
215 char *BREGEXP::replace(const char *fname)
216 {
217    int flen = strlen(fname);
218    int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, &regs);
219
220    if (rc < 0) {
221       Dmsg0(100, "E: regex mismatch\n");
222       return return_fname(fname, flen);
223    }
224
225    int len = compute_dest_len(fname, &regs);
226
227    if (len) {
228       result = check_pool_memory_size(result, len);
229       edit_subst(fname, &regs);
230
231    } else {                     /* error in substitution */
232       Dmsg0(100, "E: error in substitution\n");
233       return return_fname(fname, flen);
234    }
235
236    return result;
237
238
239 char *BREGEXP::return_fname(const char *fname, int len)
240 {
241    result = check_pool_memory_size(result, len+1);
242    strcpy(result,fname);
243    return result;
244 }
245
246 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
247 {
248    int len=0;
249    char *p;
250    char *psubst = subst;
251    int no;
252
253    if (!fname || !regs) {
254       return 0;
255    }
256
257    /* match failed ? */
258    if (regs->start[0] < 0) {
259       return 0;
260    }
261
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';
266
267          /* we check if the back reference exists */
268          /* references can not match if we are using (..)? */
269
270          if (regs->start[no] >= 0 && regs->end[no] >= 0) { 
271             len += regs->end[no] - regs->start[no];
272          }
273          
274       } else {
275          len++;
276       }
277    }
278
279    /* $0 is replaced by subst */
280    len -= regs->end[0] - regs->start[0];
281    len += strlen(fname) + 1;
282
283    return len;
284 }
285
286 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
287 {
288    int i;
289    char *p;
290    char *psubst = subst;
291    int no;
292    int len;
293
294    /* il faut recopier fname dans dest
295     *  on recopie le debut fname -> regs->start[0]
296     */
297    
298    for (i = 0; i < regs->start[0] ; i++) {
299       result[i] = fname[i];
300    }
301
302    /* on recopie le motif de remplacement (avec tous les $x) */
303
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';
308
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);
313             i += len ;
314          }
315
316       } else {
317          result[i++] = *p;
318       }
319    }
320
321    /* we copy what is out of the match */
322    strcpy(result + i, fname + regs->end[0]);
323
324    return result;
325 }
326
327 void BREGEXP::debug()
328 {
329    printf("expr=[%s]\n", expr);
330    printf("subst=[%s]\n", subst);
331    printf("result=%s\n", result?result:"(null)");
332 }