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