]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/breg.c
ebl works with bregex.h and regex.h
[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 bool BREGEXP::extract_regexp(const char *motif)
103 {
104    
105    if (!motif) {
106       return false;
107    }
108    char sep = motif[0];
109    char *search = (char *) motif + 1;
110    char *replace;
111    int options = REG_EXTENDED | REG_NEWLINE;
112    bool ok = false;
113    bool found_motif = false;
114
115    /* extract 1st part */
116    char *dest = expr = bstrdup(motif);
117
118    while (*search && !ok) {
119       if (*search == '\\' && *dest == sep) {
120          *dest++ = *++search;       /* we skip separator */ 
121       } else if (*search == sep) {
122          *dest++ = '\0';
123
124          if (subst) {   /* already have found motif */
125             ok = true;
126          } else {
127             *dest++ = *++search; /* we skip separator */ 
128             subst = dest;        /* get replaced string */
129          }
130       } else {
131          *dest++ = *search++;
132       }
133    }
134    *dest = '\0';                /* in case of */
135    
136    if (!ok || !subst) {
137       /* bad regexp */
138       return false;
139    }
140
141    /* find options */
142    while (*search) {
143       if (*search == 'i') {
144          options |= REG_ICASE;
145       }
146       if (*search == 'g') {
147               /* recherche multiple*/
148       }
149       search++;
150    }
151
152    int rc = regcomp(&preg, expr, options);
153    if (rc != 0) {
154       char prbuf[500];
155       regerror(rc, &preg, prbuf, sizeof(prbuf));
156       printf("bregexp: compile error: %s\n", prbuf);
157 //      Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
158       return false;
159    }
160
161    return true;
162 }
163
164 #ifndef HAVE_REGEX_H
165  #define BREGEX_CAST unsigned
166 #else
167  #define BREGEX_CAST const
168 #endif
169
170 /* return regexp->result */
171 char *BREGEXP::replace(const char *fname)
172 {
173    int flen = strlen(fname);
174    int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, &regs);
175
176    if (rc < 0) {
177       printf("E: regex mismatch\n");
178       return return_fname(fname, flen);
179    }
180
181    int len = compute_dest_len(fname, &regs);
182
183    if (len) {
184       result = check_pool_memory_size(result, len);
185       edit_subst(fname, &regs);
186
187    } else {                     /* error in substitution */
188       printf("E: error in substitution\n");
189       return return_fname(fname, flen);
190    }
191
192    return result;
193
194
195 char *BREGEXP::return_fname(const char *fname, int len)
196 {
197    result = check_pool_memory_size(result, len+1);
198    strcpy(result,fname);
199    return result;
200 }
201
202 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
203 {
204    int len=0;
205    char *p;
206    char *psubst = subst;
207    int no;
208
209    if (!fname || !regs) {
210       return 0;
211    }
212
213    /* match failed ? */
214    if (regs->start[0] < 0) {
215       return 0;
216    }
217
218    for (p = psubst++; *p ; p = psubst++) {
219       /* match $1 \1 back references */
220       if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
221          no = *psubst++ - '0';
222
223          /* we check if the back reference exists */
224          if (regs->start[no] >= 0 && regs->end[no] >= 0) { 
225             len += regs->end[no] - regs->start[no];
226          } else {
227             return 0; /* back reference missing */
228          }
229       } else {
230          len++;
231       }
232    }
233
234    /* $0 is replaced by subst */
235    len -= regs->end[0] - regs->start[0];
236    len += strlen(fname) + 1;
237
238    return len;
239 }
240
241 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
242 {
243    int i;
244    char *p;
245    char *psubst = subst;
246    int no;
247    int len;
248
249    /* il faut recopier fname dans dest
250     *  on recopie le debut fname -> regs->start[0]
251     */
252    
253    for (i = 0; i < regs->start[0] ; i++) {
254       result[i] = fname[i];
255    }
256
257    /* on recopie le motif de remplacement (avec tous les $x) */
258
259    for (p = psubst++; *p ; p = psubst++) {
260       /* match $1 \1 back references */
261       if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
262          no = *psubst++ - '0';
263
264          len = regs->end[no] - regs->start[no];
265          bstrncpy(result + i, fname + regs->start[no], len + 1);
266          i += len ;
267
268       } else {
269          result[i++] = *p;
270       }
271    }
272
273    /* we copy what is out of the match */
274    strcpy(result + i, fname + regs->end[0]);
275
276    return result;
277 }
278
279 void BREGEXP::debug()
280 {
281    printf("expr=[%s]\n", expr);
282    printf("subst=[%s]\n", subst);
283    printf("result=%s\n", result?result:"(null)");
284 }
285
286 #ifdef TEST
287
288 int main(int argc, char **argv)
289 {
290    BREGEXP *reg;
291    
292    reg = new_bregexp(argv[1]);
293
294    if (reg) {
295       reg->replace(argv[2]);
296       reg->debug();
297       printf("%s => %s\n", argv[1], reg->result);
298    }
299    exit(0);
300 }
301
302 #endif