]> 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       printf("bregexp: extract_regexp error\n");
52       free_bregexp(self);
53       return NULL;
54    }
55
56    static int _start[RE_NREGS];
57    static int _end[RE_NREGS];
58
59    self->result = get_pool_memory(PM_FNAME);
60    self->result[0] = '\0';
61
62 #ifdef HAVE_REGEX_H
63    /* TODO: que devient cette memoire... */
64    self->_regs_match = (int *) malloc (2*RE_NREGS * sizeof(int));
65
66    self->regs.num_regs = RE_NREGS;
67    self->regs.start = self->_regs_match;
68    self->regs.end   = self->_regs_match+(RE_NREGS * sizeof(int));
69 #endif 
70
71    return self;
72 }
73
74 void free_bregexp(BREGEXP *self)
75 {
76    Dmsg0(500, "bregexp: freeing BREGEXP object\n");
77
78    if (self->expr) {
79       free(self->expr);
80    }
81    if (self->result) {
82       free_pool_memory(self->result);
83    }
84    if (self->_regs_match) {
85       free(self->_regs_match);
86    }
87
88    regfree(&self->preg);
89    free(self);
90 }
91
92 void free_bregexps(alist *bregexps)
93 {
94    Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
95
96    BREGEXP *elt;
97    foreach_alist(elt, bregexps) {
98       free_bregexp(elt);
99    }
100 }
101
102 char *apply_bregexps(const char *fname, alist *bregexps)
103 {
104    BREGEXP *elt;
105    char *ret = (char *) fname;
106    foreach_alist(elt, bregexps) {
107       ret = elt->replace(ret);
108    }
109    return ret;
110 }
111
112
113 bool BREGEXP::extract_regexp(const char *motif)
114 {
115    
116    if (!motif) {
117       return false;
118    }
119    char sep = motif[0];
120    char *search = (char *) motif + 1;
121    char *replace;
122    int options = REG_EXTENDED | REG_NEWLINE;
123    bool ok = false;
124    bool found_motif = false;
125
126    /* extract 1st part */
127    char *dest = expr = bstrdup(motif);
128
129    while (*search && !ok) {
130       if (*search == '\\' && *dest == sep) {
131          *dest++ = *++search;       /* we skip separator */ 
132       } else if (*search == sep) {
133          *dest++ = '\0';
134
135          if (subst) {   /* already have found motif */
136             ok = true;
137          } else {
138             *dest++ = *++search; /* we skip separator */ 
139             subst = dest;        /* get replaced string */
140          }
141       } else {
142          *dest++ = *search++;
143       }
144    }
145    *dest = '\0';                /* in case of */
146    
147    if (!ok || !subst) {
148       /* bad regexp */
149       return false;
150    }
151
152    /* find options */
153    while (*search) {
154       if (*search == 'i') {
155          options |= REG_ICASE;
156       }
157       if (*search == 'g') {
158               /* recherche multiple*/
159       }
160       search++;
161    }
162
163    int rc = regcomp(&preg, expr, options);
164    if (rc != 0) {
165       char prbuf[500];
166       regerror(rc, &preg, prbuf, sizeof(prbuf));
167       printf("bregexp: compile error: %s\n", prbuf);
168 //      Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
169       return false;
170    }
171
172    return true;
173 }
174
175 #ifndef HAVE_REGEX_H
176  #define BREGEX_CAST unsigned
177 #else
178  #define BREGEX_CAST const
179 #endif
180
181 /* return regexp->result */
182 char *BREGEXP::replace(const char *fname)
183 {
184    int flen = strlen(fname);
185    int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, &regs);
186
187    if (rc < 0) {
188       printf("E: regex mismatch\n");
189       return return_fname(fname, flen);
190    }
191
192    int len = compute_dest_len(fname, &regs);
193
194    if (len) {
195       result = check_pool_memory_size(result, len);
196       edit_subst(fname, &regs);
197
198    } else {                     /* error in substitution */
199       printf("E: error in substitution\n");
200       return return_fname(fname, flen);
201    }
202
203    return result;
204
205
206 char *BREGEXP::return_fname(const char *fname, int len)
207 {
208    result = check_pool_memory_size(result, len+1);
209    strcpy(result,fname);
210    return result;
211 }
212
213 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
214 {
215    int len=0;
216    char *p;
217    char *psubst = subst;
218    int no;
219
220    if (!fname || !regs) {
221       return 0;
222    }
223
224    /* match failed ? */
225    if (regs->start[0] < 0) {
226       return 0;
227    }
228
229    for (p = psubst++; *p ; p = psubst++) {
230       /* match $1 \1 back references */
231       if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
232          no = *psubst++ - '0';
233
234          /* we check if the back reference exists */
235          if (regs->start[no] >= 0 && regs->end[no] >= 0) { 
236             len += regs->end[no] - regs->start[no];
237          } else {
238             return 0; /* back reference missing */
239          }
240       } else {
241          len++;
242       }
243    }
244
245    /* $0 is replaced by subst */
246    len -= regs->end[0] - regs->start[0];
247    len += strlen(fname) + 1;
248
249    return len;
250 }
251
252 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
253 {
254    int i;
255    char *p;
256    char *psubst = subst;
257    int no;
258    int len;
259
260    /* il faut recopier fname dans dest
261     *  on recopie le debut fname -> regs->start[0]
262     */
263    
264    for (i = 0; i < regs->start[0] ; i++) {
265       result[i] = fname[i];
266    }
267
268    /* on recopie le motif de remplacement (avec tous les $x) */
269
270    for (p = psubst++; *p ; p = psubst++) {
271       /* match $1 \1 back references */
272       if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
273          no = *psubst++ - '0';
274
275          len = regs->end[no] - regs->start[no];
276          bstrncpy(result + i, fname + regs->start[no], len + 1);
277          i += len ;
278
279       } else {
280          result[i++] = *p;
281       }
282    }
283
284    /* we copy what is out of the match */
285    strcpy(result + i, fname + regs->end[0]);
286
287    return result;
288 }
289
290 void BREGEXP::debug()
291 {
292    printf("expr=[%s]\n", expr);
293    printf("subst=[%s]\n", subst);
294    printf("result=%s\n", result?result:"(null)");
295 }
296
297 #ifdef TEST
298
299 int main(int argc, char **argv)
300 {
301    BREGEXP *reg;
302    
303    reg = new_bregexp(argv[1]);
304
305    if (reg) {
306       reg->replace(argv[2]);
307       reg->debug();
308       printf("%s => %s\n", argv[1], reg->result);
309    }
310    exit(0);
311 }
312
313 #endif