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 bool BREGEXP::extract_regexp(const char *motif)
109 char *search = (char *) motif + 1;
111 int options = REG_EXTENDED | REG_NEWLINE;
113 bool found_motif = false;
115 /* extract 1st part */
116 char *dest = expr = bstrdup(motif);
118 while (*search && !ok) {
119 if (*search == '\\' && *dest == sep) {
120 *dest++ = *++search; /* we skip separator */
121 } else if (*search == sep) {
124 if (subst) { /* already have found motif */
127 *dest++ = *++search; /* we skip separator */
128 subst = dest; /* get replaced string */
134 *dest = '\0'; /* in case of */
143 if (*search == 'i') {
144 options |= REG_ICASE;
146 if (*search == 'g') {
147 /* recherche multiple*/
152 int rc = regcomp(&preg, expr, options);
155 regerror(rc, &preg, prbuf, sizeof(prbuf));
156 printf("bregexp: compile error: %s\n", prbuf);
157 // Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
165 #define BREGEX_CAST unsigned
167 #define BREGEX_CAST const
170 /* return regexp->result */
171 char *BREGEXP::replace(const char *fname)
173 int flen = strlen(fname);
174 int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, ®s);
177 printf("E: regex mismatch\n");
178 return return_fname(fname, flen);
181 int len = compute_dest_len(fname, ®s);
184 result = check_pool_memory_size(result, len);
185 edit_subst(fname, ®s);
187 } else { /* error in substitution */
188 printf("E: error in substitution\n");
189 return return_fname(fname, flen);
195 char *BREGEXP::return_fname(const char *fname, int len)
197 result = check_pool_memory_size(result, len+1);
198 strcpy(result,fname);
202 int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
206 char *psubst = subst;
209 if (!fname || !regs) {
214 if (regs->start[0] < 0) {
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';
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];
227 return 0; /* back reference missing */
234 /* $0 is replaced by subst */
235 len -= regs->end[0] - regs->start[0];
236 len += strlen(fname) + 1;
241 char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
245 char *psubst = subst;
249 /* il faut recopier fname dans dest
250 * on recopie le debut fname -> regs->start[0]
253 for (i = 0; i < regs->start[0] ; i++) {
254 result[i] = fname[i];
257 /* on recopie le motif de remplacement (avec tous les $x) */
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';
264 len = regs->end[no] - regs->start[no];
265 bstrncpy(result + i, fname + regs->start[no], len + 1);
273 /* we copy what is out of the match */
274 strcpy(result + i, fname + regs->end[0]);
279 void BREGEXP::debug()
281 printf("expr=[%s]\n", expr);
282 printf("subst=[%s]\n", subst);
283 printf("result=%s\n", result?result:"(null)");
288 int main(int argc, char **argv)
292 reg = new_bregexp(argv[1]);
295 reg->replace(argv[2]);
297 printf("%s => %s\n", argv[1], reg->result);