]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/breg.c
ebl update
[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 char *get_next_bregexp(char *where)
112 {
113    char sep;
114    char *after;
115    bool ok=false;
116
117    if (!where && !*where) {
118       return NULL;
119    }
120    
121 }
122
123 /* return an alist of BREGEXP or return NULL if it's not a 
124  * where=!tmp!opt!ig,!temp!opt!i
125  */
126 alist *get_bregexps(const char *where)
127 {
128    char *p = (char *)where;
129    alist *list = New(alist(10, not_owned_by_alist));
130    BREGEXP *reg;
131
132    reg = new_bregexp(p);
133
134    while(reg) {
135       p = reg->eor;
136       list->append(reg);
137       reg = new_bregexp(p);
138    }
139
140    if (list->size()) {
141       return list;      
142    } else {
143       delete list;
144       return NULL;
145    }
146 }
147
148 bool BREGEXP::extract_regexp(const char *motif)
149 {
150    if (!motif || (*motif == '\0')) {
151       return false;
152    }
153    char sep = motif[0];
154    char *search = (char *) motif + 1;
155    char *replace;
156    int options = REG_EXTENDED | REG_NEWLINE;
157    bool ok = false;
158    bool found_motif = false;
159
160    /* extract 1st part */
161    char *dest = expr = bstrdup(motif);
162
163    while (*search && !ok) {
164       if (search[0] == '\\' && search[1] == sep) {
165          *dest++ = *++search;       /* we skip separator */ 
166
167       } else if (*search == sep) {  /* we found end of expression */
168          *dest++ = '\0';
169
170          if (subst) {           /* already have found motif */
171             ok = true;
172
173          } else {
174             *dest++ = *++search; /* we skip separator */ 
175             subst = dest;        /* get replaced string */
176          }
177
178       } else {
179          *dest++ = *search++;
180       }
181    }
182    *dest = '\0';                /* in case of */
183    
184    if (!ok || !subst) {
185       /* bad regexp */
186       return false;
187    }
188
189    ok = false;
190    /* find options */
191    while (*search && !ok) {
192       if (*search == 'i') {
193          options |= REG_ICASE;
194
195       } else if (*search == 'g') {
196               /* recherche multiple*/
197
198       } else if (*search == sep) {
199          /* skip separator */
200
201       } else {                  /* end of options */
202          ok = true;
203       }
204       search++;
205    }
206
207    int rc = regcomp(&preg, expr, options);
208    if (rc != 0) {
209       char prbuf[500];
210       regerror(rc, &preg, prbuf, sizeof(prbuf));
211       Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
212       return false;
213    }
214
215    eor = search;                /* useful to find the next regexp in where */
216
217    return true;
218 }
219
220 #ifndef HAVE_REGEX_H
221  #define BREGEX_CAST unsigned
222 #else
223  #define BREGEX_CAST const
224 #endif
225
226 /* return regexp->result */
227 char *BREGEXP::replace(const char *fname)
228 {
229    int flen = strlen(fname);
230    int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, &regs);
231
232    if (rc < 0) {
233       Dmsg0(100, "E: regex mismatch\n");
234       return return_fname(fname, flen);
235    }
236
237    int len = compute_dest_len(fname, &regs);
238
239    if (len) {
240       result = check_pool_memory_size(result, len);
241       edit_subst(fname, &regs);
242
243    } else {                     /* error in substitution */
244       Dmsg0(100, "E: error in substitution\n");
245       return return_fname(fname, flen);
246    }
247
248    return result;
249
250
251 char *BREGEXP::return_fname(const char *fname, int len)
252 {
253    result = check_pool_memory_size(result, len+1);
254    strcpy(result,fname);
255    return result;
256 }
257
258 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
259 {
260    int len=0;
261    char *p;
262    char *psubst = subst;
263    int no;
264
265    if (!fname || !regs) {
266       return 0;
267    }
268
269    /* match failed ? */
270    if (regs->start[0] < 0) {
271       return 0;
272    }
273
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';
278
279          /* we check if the back reference exists */
280          /* references can not match if we are using (..)? */
281
282          if (regs->start[no] >= 0 && regs->end[no] >= 0) { 
283             len += regs->end[no] - regs->start[no];
284          }
285          
286       } else {
287          len++;
288       }
289    }
290
291    /* $0 is replaced by subst */
292    len -= regs->end[0] - regs->start[0];
293    len += strlen(fname) + 1;
294
295    return len;
296 }
297
298 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
299 {
300    int i;
301    char *p;
302    char *psubst = subst;
303    int no;
304    int len;
305
306    /* il faut recopier fname dans dest
307     *  on recopie le debut fname -> regs->start[0]
308     */
309    
310    for (i = 0; i < regs->start[0] ; i++) {
311       result[i] = fname[i];
312    }
313
314    /* on recopie le motif de remplacement (avec tous les $x) */
315
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';
320
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);
325             i += len ;
326          }
327
328       } else {
329          result[i++] = *p;
330       }
331    }
332
333    /* we copy what is out of the match */
334    strcpy(result + i, fname + regs->end[0]);
335
336    return result;
337 }
338
339 void BREGEXP::debug()
340 {
341    printf("expr=[%s]\n", expr);
342    printf("subst=[%s]\n", subst);
343    printf("result=%s\n", result?result:"(null)");
344 }
345
346 #ifdef TEST
347
348 int main(int argc, char **argv)
349 {
350    BREGEXP *reg;
351    
352    reg = new_bregexp(argv[1]);
353
354    if (reg) {
355       reg->replace(argv[2]);
356       reg->debug();
357       printf("%s => %s\n", argv[1], reg->result);
358    }
359    exit(0);
360 }
361
362 #endif