2 * Manipulation routines for BREGEXP list
4 * Eric Bollengier, March 2007
10 Bacula® - The Network Backup Solution
12 Copyright (C) 2006-2006 Free Software Foundation Europe e.V.
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.
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.
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
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.
43 BREGEXP *new_bregexp(const char *motif)
45 Dmsg0(500, "bregexp: creating new bregexp object\n");
46 BREGEXP *self = (BREGEXP *)malloc(sizeof(BREGEXP));
47 memset(self, 0, sizeof(BREGEXP));
49 if (!self->extract_regexp(motif)) {
50 // Dmsg0(100, "bregexp: extract_regexp error\n");
51 printf("bregexp: extract_regexp error\n");
56 static int _start[RE_NREGS];
57 static int _end[RE_NREGS];
59 self->result = get_pool_memory(PM_FNAME);
60 self->result[0] = '\0';
63 /* TODO: que devient cette memoire... */
64 self->_regs_match = (int *) malloc (2*RE_NREGS * sizeof(int));
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));
74 void free_bregexp(BREGEXP *self)
76 Dmsg0(500, "bregexp: freeing BREGEXP object\n");
82 free_pool_memory(self->result);
84 if (self->_regs_match) {
85 free(self->_regs_match);
92 void free_bregexps(alist *bregexps)
94 Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
97 foreach_alist(elt, bregexps) {
102 char *apply_bregexps(const char *fname, alist *bregexps)
105 char *ret = (char *) fname;
106 foreach_alist(elt, bregexps) {
107 ret = elt->replace(ret);
113 bool BREGEXP::extract_regexp(const char *motif)
120 char *search = (char *) motif + 1;
122 int options = REG_EXTENDED | REG_NEWLINE;
124 bool found_motif = false;
126 /* extract 1st part */
127 char *dest = expr = bstrdup(motif);
129 while (*search && !ok) {
130 if (*search == '\\' && *dest == sep) {
131 *dest++ = *++search; /* we skip separator */
132 } else if (*search == sep) {
135 if (subst) { /* already have found motif */
138 *dest++ = *++search; /* we skip separator */
139 subst = dest; /* get replaced string */
145 *dest = '\0'; /* in case of */
154 if (*search == 'i') {
155 options |= REG_ICASE;
157 if (*search == 'g') {
158 /* recherche multiple*/
163 int rc = regcomp(&preg, expr, options);
166 regerror(rc, &preg, prbuf, sizeof(prbuf));
167 printf("bregexp: compile error: %s\n", prbuf);
168 // Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
176 #define BREGEX_CAST unsigned
178 #define BREGEX_CAST const
181 /* return regexp->result */
182 char *BREGEXP::replace(const char *fname)
184 int flen = strlen(fname);
185 int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, ®s);
188 printf("E: regex mismatch\n");
189 return return_fname(fname, flen);
192 int len = compute_dest_len(fname, ®s);
195 result = check_pool_memory_size(result, len);
196 edit_subst(fname, ®s);
198 } else { /* error in substitution */
199 printf("E: error in substitution\n");
200 return return_fname(fname, flen);
206 char *BREGEXP::return_fname(const char *fname, int len)
208 result = check_pool_memory_size(result, len+1);
209 strcpy(result,fname);
213 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
217 char *psubst = subst;
220 if (!fname || !regs) {
225 if (regs->start[0] < 0) {
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';
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];
238 return 0; /* back reference missing */
245 /* $0 is replaced by subst */
246 len -= regs->end[0] - regs->start[0];
247 len += strlen(fname) + 1;
252 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
256 char *psubst = subst;
260 /* il faut recopier fname dans dest
261 * on recopie le debut fname -> regs->start[0]
264 for (i = 0; i < regs->start[0] ; i++) {
265 result[i] = fname[i];
268 /* on recopie le motif de remplacement (avec tous les $x) */
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';
275 len = regs->end[no] - regs->start[no];
276 bstrncpy(result + i, fname + regs->start[no], len + 1);
284 /* we copy what is out of the match */
285 strcpy(result + i, fname + regs->end[0]);
290 void BREGEXP::debug()
292 printf("expr=[%s]\n", expr);
293 printf("subst=[%s]\n", subst);
294 printf("result=%s\n", result?result:"(null)");
299 int main(int argc, char **argv)
303 reg = new_bregexp(argv[1]);
306 reg->replace(argv[2]);
308 printf("%s => %s\n", argv[1], reg->result);