1 | // =============================================================== // |
---|
2 | // // |
---|
3 | // File : admatch.cxx // |
---|
4 | // Purpose : functions related to string match/replace // |
---|
5 | // // |
---|
6 | // ReCoded for POSIX ERE // |
---|
7 | // by Ralf Westram (coder@reallysoft.de) in April 2009 // |
---|
8 | // Institute of Microbiology (Technical University Munich) // |
---|
9 | // http://www.arb-home.de/ // |
---|
10 | // // |
---|
11 | // =============================================================== // |
---|
12 | |
---|
13 | #include "gb_local.h" |
---|
14 | |
---|
15 | #include <arb_strbuf.h> |
---|
16 | #include <arb_match.h> |
---|
17 | |
---|
18 | #include <cctype> |
---|
19 | |
---|
20 | // ------------------------ |
---|
21 | // string matcher |
---|
22 | |
---|
23 | enum string_matcher_type { |
---|
24 | SM_INVALID = -1, |
---|
25 | SM_ANY = 0, // matches any string |
---|
26 | SM_WILDCARDED, // match with wildcards (GBS_string_matches) |
---|
27 | SM_REGEXPR, // match using regexpr |
---|
28 | }; |
---|
29 | |
---|
30 | struct GBS_string_matcher { |
---|
31 | string_matcher_type type; |
---|
32 | GB_CASE case_flag; |
---|
33 | char *wildexpr; |
---|
34 | GBS_regex *regexpr; |
---|
35 | }; |
---|
36 | |
---|
37 | GBS_string_matcher *GBS_compile_matcher(const char *search_expr, GB_CASE case_flag) { |
---|
38 | /* returns a valid string matcher (to be used with GBS_string_matches_regexp) |
---|
39 | * or NULL (in which case an error was exported) |
---|
40 | */ |
---|
41 | |
---|
42 | GBS_string_matcher *matcher = ARB_alloc<GBS_string_matcher>(1); |
---|
43 | GB_ERROR error = 0; |
---|
44 | |
---|
45 | matcher->type = SM_INVALID; |
---|
46 | matcher->case_flag = case_flag; |
---|
47 | matcher->wildexpr = NULL; |
---|
48 | matcher->regexpr = NULL; |
---|
49 | |
---|
50 | if (search_expr[0] == '/') { |
---|
51 | const char *end = strchr(search_expr, 0)-1; |
---|
52 | if (end>search_expr && end[0] == '/') { |
---|
53 | GB_CASE expr_attached_case; |
---|
54 | const char *unwrapped_expr = GBS_unwrap_regexpr(search_expr, &expr_attached_case, &error); |
---|
55 | |
---|
56 | if (unwrapped_expr) { |
---|
57 | if (expr_attached_case != GB_MIND_CASE) error = "format '/../i' not allowed here"; |
---|
58 | else { |
---|
59 | matcher->regexpr = GBS_compile_regexpr(unwrapped_expr, case_flag, &error); |
---|
60 | if (matcher->regexpr) { |
---|
61 | matcher->type = SM_REGEXPR; |
---|
62 | } |
---|
63 | } |
---|
64 | } |
---|
65 | } |
---|
66 | } |
---|
67 | |
---|
68 | if (matcher->regexpr == NULL && !error) { |
---|
69 | if (strcmp(search_expr, "*") == 0) { |
---|
70 | matcher->type = SM_ANY; |
---|
71 | } |
---|
72 | else { |
---|
73 | matcher->type = SM_WILDCARDED; |
---|
74 | matcher->wildexpr = ARB_strdup(search_expr); |
---|
75 | } |
---|
76 | } |
---|
77 | |
---|
78 | if (matcher->type == SM_INVALID) { |
---|
79 | error = GBS_global_string("Failed to create GBS_string_matcher from '%s'", search_expr); |
---|
80 | } |
---|
81 | |
---|
82 | if (error) { |
---|
83 | GBS_free_matcher(matcher); |
---|
84 | matcher = 0; |
---|
85 | GB_export_error(error); |
---|
86 | } |
---|
87 | return matcher; |
---|
88 | } |
---|
89 | |
---|
90 | void GBS_free_matcher(GBS_string_matcher *matcher) { |
---|
91 | free(matcher->wildexpr); |
---|
92 | if (matcher->regexpr) GBS_free_regexpr(matcher->regexpr); |
---|
93 | free(matcher); |
---|
94 | } |
---|
95 | |
---|
96 | // ------------------------- |
---|
97 | // wildcard search |
---|
98 | |
---|
99 | GB_CSTR GBS_find_string(GB_CSTR cont, GB_CSTR substr, int match_mode) { |
---|
100 | /* search a substring in another string |
---|
101 | * match_mode == 0 -> exact match |
---|
102 | * match_mode == 1 -> a==A |
---|
103 | * match_mode == 2 -> a==a && a==? |
---|
104 | * match_mode == else -> a==A && a==? |
---|
105 | */ |
---|
106 | const char *p1, *p2; |
---|
107 | char b; |
---|
108 | |
---|
109 | switch (match_mode) { |
---|
110 | |
---|
111 | case 0: // exact match |
---|
112 | for (p1 = cont, p2 = substr; *p1;) { |
---|
113 | if (!(b = *p2)) { |
---|
114 | return (char *)cont; |
---|
115 | } |
---|
116 | else { |
---|
117 | if (b == *p1) { |
---|
118 | p1++; |
---|
119 | p2++; |
---|
120 | } |
---|
121 | else { |
---|
122 | p2 = substr; |
---|
123 | p1 = (++cont); |
---|
124 | } |
---|
125 | } |
---|
126 | } |
---|
127 | if (!*p2) return (char *)cont; |
---|
128 | break; |
---|
129 | |
---|
130 | case 1: // a==A |
---|
131 | for (p1 = cont, p2 = substr; *p1;) { |
---|
132 | if (!(b = *p2)) { |
---|
133 | return (char *)cont; |
---|
134 | } |
---|
135 | else { |
---|
136 | if (toupper(*p1) == toupper(b)) { |
---|
137 | p1++; |
---|
138 | p2++; |
---|
139 | } |
---|
140 | else { |
---|
141 | p2 = substr; |
---|
142 | p1 = (++cont); |
---|
143 | } |
---|
144 | } |
---|
145 | } |
---|
146 | if (!*p2) return (char *)cont; |
---|
147 | break; |
---|
148 | case 2: // a==a && a==? |
---|
149 | for (p1 = cont, p2 = substr; *p1;) { |
---|
150 | if (!(b = *p2)) { |
---|
151 | return (char *)cont; |
---|
152 | } |
---|
153 | else { |
---|
154 | if (b == *p1 || (b=='?')) { |
---|
155 | p1++; |
---|
156 | p2++; |
---|
157 | } |
---|
158 | else { |
---|
159 | p2 = substr; |
---|
160 | p1 = (++cont); |
---|
161 | } |
---|
162 | } |
---|
163 | } |
---|
164 | if (!*p2) return (char *)cont; |
---|
165 | break; |
---|
166 | |
---|
167 | default: // a==A && a==? |
---|
168 | for (p1 = cont, p2 = substr; *p1;) { |
---|
169 | if (!(b = *p2)) { |
---|
170 | return (char *)cont; |
---|
171 | } |
---|
172 | else { |
---|
173 | if (toupper(*p1) == toupper(b) || (b=='?')) { |
---|
174 | p1++; |
---|
175 | p2++; |
---|
176 | } |
---|
177 | else { |
---|
178 | p2 = substr; |
---|
179 | p1 = (++cont); |
---|
180 | } |
---|
181 | } |
---|
182 | } |
---|
183 | if (!*p2) return (char *)cont; |
---|
184 | break; |
---|
185 | } |
---|
186 | return 0; |
---|
187 | } |
---|
188 | |
---|
189 | bool GBS_string_matches(const char *str, const char *search, GB_CASE case_sens) |
---|
190 | /* Wildcards in 'search' string: |
---|
191 | * ? one character |
---|
192 | * * several characters |
---|
193 | * |
---|
194 | * if 'case_sens' == GB_IGNORE_CASE -> change all letters to uppercase |
---|
195 | * |
---|
196 | * returns true if strings are equal, false otherwise |
---|
197 | */ |
---|
198 | { |
---|
199 | const char *p1, *p2; |
---|
200 | char a, b, *d; |
---|
201 | long i; |
---|
202 | char fsbuf[256]; |
---|
203 | |
---|
204 | p1 = str; |
---|
205 | p2 = search; |
---|
206 | while (1) { |
---|
207 | a = *p1; |
---|
208 | b = *p2; |
---|
209 | if (b == '*') { |
---|
210 | if (!p2[1]) break; // '*' also matches nothing |
---|
211 | i = 0; |
---|
212 | d = fsbuf; |
---|
213 | for (p2++; (b=*p2)&&(b!='*');) { |
---|
214 | *(d++) = b; |
---|
215 | p2++; |
---|
216 | i++; |
---|
217 | if (i > 250) break; |
---|
218 | } |
---|
219 | if (*p2 != '*') { |
---|
220 | p1 += strlen(p1)-i; // check the end of the string |
---|
221 | if (p1 < str) return false; |
---|
222 | p2 -= i; |
---|
223 | } |
---|
224 | else { |
---|
225 | *d = 0; |
---|
226 | p1 = GBS_find_string(p1, fsbuf, 2+(case_sens == GB_IGNORE_CASE)); // match with '?' wildcard |
---|
227 | if (!p1) return false; |
---|
228 | p1 += i; |
---|
229 | } |
---|
230 | continue; |
---|
231 | } |
---|
232 | |
---|
233 | if (!a) return !b; |
---|
234 | if (a != b) { |
---|
235 | if (b != '?') { |
---|
236 | if (!b) return !a; |
---|
237 | if (case_sens == GB_IGNORE_CASE) { |
---|
238 | a = toupper(a); |
---|
239 | b = toupper(b); |
---|
240 | if (a != b) return false; |
---|
241 | } |
---|
242 | else { |
---|
243 | return false; |
---|
244 | } |
---|
245 | } |
---|
246 | } |
---|
247 | p1++; |
---|
248 | p2++; |
---|
249 | } |
---|
250 | return true; |
---|
251 | } |
---|
252 | |
---|
253 | bool GBS_string_matches_regexp(const char *str, const GBS_string_matcher *expr) { |
---|
254 | /* Wildcard or regular expression match |
---|
255 | * Returns true if match |
---|
256 | * |
---|
257 | * Use GBS_compile_matcher() and GBS_free_matcher() to maintain 'expr' |
---|
258 | */ |
---|
259 | bool matches = false; |
---|
260 | |
---|
261 | switch (expr->type) { |
---|
262 | case SM_ANY: { |
---|
263 | matches = true; |
---|
264 | break; |
---|
265 | } |
---|
266 | case SM_WILDCARDED: { |
---|
267 | matches = GBS_string_matches(str, expr->wildexpr, expr->case_flag); |
---|
268 | break; |
---|
269 | } |
---|
270 | case SM_REGEXPR: { |
---|
271 | matches = GBS_regmatch_compiled(str, expr->regexpr, NULL) != NULL; |
---|
272 | break; |
---|
273 | } |
---|
274 | case SM_INVALID: { |
---|
275 | gb_assert(0); |
---|
276 | break; |
---|
277 | } |
---|
278 | } |
---|
279 | |
---|
280 | return matches; |
---|
281 | } |
---|
282 | |
---|
283 | // ----------------------------------- |
---|
284 | // Search replace tool (SRT) |
---|
285 | |
---|
286 | #define GBS_SET ((char)1) |
---|
287 | #define GBS_SEP ((char)2) |
---|
288 | #define GBS_MWILD ((char)3) |
---|
289 | #define GBS_WILD ((char)4) |
---|
290 | |
---|
291 | __ATTR__USERESULT_TODO static GB_ERROR gbs_build_replace_string(GBS_strstruct *strstruct, |
---|
292 | char *bar, char *wildcards, long max_wildcard, |
---|
293 | char **mwildcards, long max_mwildcard, GBDATA *gb_container) |
---|
294 | { |
---|
295 | int wildcardcnt = 0; |
---|
296 | int mwildcardcnt = 0; |
---|
297 | |
---|
298 | char *p = bar; |
---|
299 | char c; |
---|
300 | while ((c=*(p++))) { |
---|
301 | switch (c) { |
---|
302 | case GBS_MWILD: |
---|
303 | case GBS_WILD: { |
---|
304 | char d = *(p++); |
---|
305 | if (gb_container && (d=='(')) { // if a gbcont then replace till ')' |
---|
306 | char *klz = gbs_search_second_bracket(p); |
---|
307 | if (klz) { // reference found: $(gbd) |
---|
308 | int separator = 0; |
---|
309 | *klz = 0; |
---|
310 | char *psym = strpbrk(p, "#|:"); |
---|
311 | if (psym) { |
---|
312 | separator = *psym; |
---|
313 | *psym = 0; |
---|
314 | } |
---|
315 | |
---|
316 | GBDATA *gb_entry = *p |
---|
317 | ? GB_search(gb_container, p, GB_FIND) |
---|
318 | : gb_container; |
---|
319 | |
---|
320 | if (psym) *psym = separator; |
---|
321 | |
---|
322 | char *entry = (gb_entry && gb_entry != gb_container) |
---|
323 | ? GB_read_as_string(gb_entry) |
---|
324 | : ARB_strdup(""); |
---|
325 | |
---|
326 | if (entry) { |
---|
327 | char *h; |
---|
328 | switch (separator) { |
---|
329 | case ':': |
---|
330 | h = GBS_string_eval(entry, psym+1, gb_container); |
---|
331 | if (!h) return GB_await_error(); |
---|
332 | |
---|
333 | GBS_strcat(strstruct, h); |
---|
334 | free(h); |
---|
335 | break; |
---|
336 | |
---|
337 | case '|': |
---|
338 | h = GB_command_interpreter(GB_get_root(gb_container), entry, psym+1, gb_container, 0); |
---|
339 | if (!h) return GB_await_error(); |
---|
340 | |
---|
341 | GBS_strcat(strstruct, h); |
---|
342 | free(h); |
---|
343 | break; |
---|
344 | |
---|
345 | case '#': |
---|
346 | if (!gb_entry) { |
---|
347 | GBS_strcat(strstruct, psym+1); |
---|
348 | break; |
---|
349 | } |
---|
350 | // fall-through |
---|
351 | default: |
---|
352 | GBS_strcat(strstruct, entry); |
---|
353 | break; |
---|
354 | } |
---|
355 | free(entry); |
---|
356 | } |
---|
357 | *klz = ')'; |
---|
358 | p = klz+1; |
---|
359 | break; |
---|
360 | } |
---|
361 | c = '*'; |
---|
362 | GBS_chrcat(strstruct, c); |
---|
363 | GBS_chrcat(strstruct, d); |
---|
364 | } |
---|
365 | else { |
---|
366 | int wildcard_num = d - '1'; |
---|
367 | if (c == GBS_WILD) { |
---|
368 | c = '?'; |
---|
369 | if ((wildcard_num<0)||(wildcard_num>9)) { |
---|
370 | p--; // use this character |
---|
371 | wildcard_num = wildcardcnt++; |
---|
372 | } |
---|
373 | if (wildcard_num>=max_wildcard) { |
---|
374 | GBS_chrcat(strstruct, c); |
---|
375 | } |
---|
376 | else { |
---|
377 | GBS_chrcat(strstruct, wildcards[wildcard_num]); |
---|
378 | } |
---|
379 | } |
---|
380 | else { |
---|
381 | c = '*'; |
---|
382 | if ((wildcard_num<0)||(wildcard_num>9)) { |
---|
383 | p--; // use this character |
---|
384 | wildcard_num = mwildcardcnt++; |
---|
385 | } |
---|
386 | if (wildcard_num>=max_mwildcard) { |
---|
387 | GBS_chrcat(strstruct, c); |
---|
388 | } |
---|
389 | else { |
---|
390 | GBS_strcat(strstruct, mwildcards[wildcard_num]); |
---|
391 | } |
---|
392 | } |
---|
393 | } |
---|
394 | break; |
---|
395 | } |
---|
396 | default: |
---|
397 | GBS_chrcat(strstruct, c); |
---|
398 | break; |
---|
399 | } |
---|
400 | } |
---|
401 | return 0; |
---|
402 | } |
---|
403 | |
---|
404 | static char *gbs_compress_command(const char *com) { |
---|
405 | /* Prepare SRT. |
---|
406 | * |
---|
407 | * Replaces all |
---|
408 | * '=' by GBS_SET |
---|
409 | * ':' by GBS_SEP |
---|
410 | * '?' by GBS_WILD if followed by a number or '?' |
---|
411 | * '*' by GBS_MWILD or '(' |
---|
412 | * \ is the escape character |
---|
413 | */ |
---|
414 | char *result, *s, *d; |
---|
415 | int ch; |
---|
416 | |
---|
417 | s = d = result = ARB_strdup(com); |
---|
418 | while ((ch = *(s++))) { |
---|
419 | switch (ch) { |
---|
420 | case '=': *(d++) = GBS_SET; break; |
---|
421 | case ':': *(d++) = GBS_SEP; break; |
---|
422 | case '?': |
---|
423 | ch = *s; // @@@ unused |
---|
424 | *(d++) = GBS_WILD; |
---|
425 | break; |
---|
426 | case '*': |
---|
427 | ch = *s; // @@@ unused |
---|
428 | *(d++) = GBS_MWILD; |
---|
429 | break; |
---|
430 | case '\\': |
---|
431 | ch = *(s++); if (!ch) { s--; break; }; |
---|
432 | switch (ch) { |
---|
433 | case 'n': *(d++) = '\n'; break; |
---|
434 | case 't': *(d++) = '\t'; break; |
---|
435 | case '0': *(d++) = '\0'; break; |
---|
436 | default: *(d++) = ch; break; |
---|
437 | } |
---|
438 | break; |
---|
439 | default: |
---|
440 | *(d++) = ch; |
---|
441 | } |
---|
442 | } |
---|
443 | *d = 0; |
---|
444 | return result; |
---|
445 | } |
---|
446 | |
---|
447 | |
---|
448 | char *GBS_string_eval(const char *insource, const char *icommand, GBDATA *gb_container) |
---|
449 | /* GBS_string_eval replaces substrings in source |
---|
450 | * Syntax: command = "oliver=olli:peter=peti" |
---|
451 | * |
---|
452 | * Returns a heapcopy of result of replacement. |
---|
453 | * |
---|
454 | * * is a wildcard for any number of character |
---|
455 | * ? is a wildcard for exactly one character |
---|
456 | * |
---|
457 | * To reference to the wildcards on the left side of the '=' |
---|
458 | * use ? and *, to reference in a different order use: |
---|
459 | * *0 to reference to the first occurrence of * |
---|
460 | * *1 second |
---|
461 | * ... |
---|
462 | * *9 |
---|
463 | * |
---|
464 | * if the last and first characters of the search string are no '*' wildcards then |
---|
465 | * the replace is repeated as many times as possible |
---|
466 | * '\' is the escape character: e.g. \n is newline; '\\' is '\'; '\=' is '='; .... |
---|
467 | * |
---|
468 | * eg: |
---|
469 | * print first three characters of first word and the whole second word: |
---|
470 | * |
---|
471 | * *(arb_key) is the value of the a database entry arb key |
---|
472 | * *(arb_key#string) value of the database entry or 'string' if the entry does not exist |
---|
473 | * *(arb_key\:SRT) runs SRT recursively on the value of the database entry |
---|
474 | * *([arb_key]|ACI) runs the ACI command interpreter on the value of the database entry (or on an empty string) |
---|
475 | * |
---|
476 | * If an error occurs it returns NULL - in this case the error was exported. |
---|
477 | */ |
---|
478 | { |
---|
479 | GB_CSTR source; // pointer into the current string when parsed |
---|
480 | char *search; // pointer into the current command when parsed |
---|
481 | GB_CSTR p; // short live pointer |
---|
482 | char c; |
---|
483 | GB_CSTR already_transferred; // point into 'in' string to non parsed position |
---|
484 | |
---|
485 | char wildcard[40]; |
---|
486 | char *mwildcard[10]; |
---|
487 | GB_ERROR error; |
---|
488 | |
---|
489 | long i; |
---|
490 | long max_wildcard; |
---|
491 | long max_mwildcard; |
---|
492 | |
---|
493 | char *start_of_wildcard; |
---|
494 | char what_wild_card; |
---|
495 | |
---|
496 | GB_CSTR start_match; |
---|
497 | |
---|
498 | char *doppelpunkt; |
---|
499 | |
---|
500 | char *bar; |
---|
501 | char *in; |
---|
502 | char *nextdp; |
---|
503 | GBS_strstruct *strstruct; |
---|
504 | char *command; |
---|
505 | |
---|
506 | if (!icommand || !icommand[0]) return ARB_strdup(insource); |
---|
507 | |
---|
508 | command = gbs_compress_command(icommand); |
---|
509 | in = ARB_strdup(insource); // copy insource to allow to destroy it |
---|
510 | |
---|
511 | for (doppelpunkt = command; doppelpunkt; doppelpunkt = nextdp) { // loop over command string |
---|
512 | // in is in , strstruct is out |
---|
513 | max_wildcard = 0; |
---|
514 | max_mwildcard = 0; |
---|
515 | nextdp = strchr(doppelpunkt, GBS_SEP); |
---|
516 | if (nextdp) { |
---|
517 | *(nextdp++) = 0; |
---|
518 | } |
---|
519 | if (!doppelpunkt[0]) { // empty command -> search next |
---|
520 | continue; |
---|
521 | } |
---|
522 | |
---|
523 | bar = strchr(doppelpunkt+1, GBS_SET); // Parse the command string !!!! |
---|
524 | if (bar) { |
---|
525 | *(bar++) = 0; |
---|
526 | } |
---|
527 | else { |
---|
528 | GB_export_errorf("SRT ERROR: no '=' found in command '%s' (position > %zi)", icommand, doppelpunkt-command+1); |
---|
529 | free(command); |
---|
530 | free(in); |
---|
531 | return 0; |
---|
532 | } |
---|
533 | |
---|
534 | already_transferred = in; |
---|
535 | strstruct = GBS_stropen(1000); // create output stream |
---|
536 | |
---|
537 | if ((!*in) && doppelpunkt[0] == GBS_MWILD && doppelpunkt[1] == 0) { // empty string -> pars myself |
---|
538 | // * matches empty string !!!! |
---|
539 | mwildcard[max_mwildcard++] = ARB_strdup(""); |
---|
540 | gbs_build_replace_string(strstruct, bar, wildcard, max_wildcard, mwildcard, max_mwildcard, gb_container); |
---|
541 | goto gbs_pars_unsuccessfull; // successfull search |
---|
542 | } |
---|
543 | |
---|
544 | for (source = in; *source;) { // loop over string |
---|
545 | search = doppelpunkt; |
---|
546 | |
---|
547 | start_match = 0; // match string for '*' |
---|
548 | while ((c = *(search++))) { // search matching command |
---|
549 | switch (c) { |
---|
550 | case GBS_MWILD: |
---|
551 | if (!start_match) start_match = source; |
---|
552 | |
---|
553 | start_of_wildcard = search; |
---|
554 | if (!(c = *(search++))) { // last character is a wildcard -> that was it |
---|
555 | mwildcard[max_mwildcard++] = ARB_strdup(source); |
---|
556 | source += strlen(source); |
---|
557 | goto gbs_pars_successfull; // successfull search and end wildcard |
---|
558 | } |
---|
559 | while ((c=*(search++)) && c!=GBS_MWILD && c!=GBS_WILD) ; // search the next wildcardstring |
---|
560 | search--; // back one character |
---|
561 | *search = 0; |
---|
562 | what_wild_card = c; |
---|
563 | p = GBS_find_string(source, start_of_wildcard, 0); |
---|
564 | if (!p) { // string not found -> unsuccessful search |
---|
565 | goto gbs_pars_unsuccessfull; |
---|
566 | } |
---|
567 | c = *p; // set wildcard // @@@ unused |
---|
568 | mwildcard[max_mwildcard++] = ARB_strpartdup(source, p-1); |
---|
569 | source = p + strlen(start_of_wildcard); // we parsed it |
---|
570 | *search = what_wild_card; |
---|
571 | break; |
---|
572 | |
---|
573 | case GBS_WILD: |
---|
574 | if (!source[0]) { |
---|
575 | goto gbs_pars_unsuccessfull; |
---|
576 | } |
---|
577 | if (!start_match) start_match = source; |
---|
578 | wildcard[max_wildcard++] = *(source++); |
---|
579 | break; |
---|
580 | default: |
---|
581 | if (start_match) { |
---|
582 | if (c != *(source++)) { |
---|
583 | goto gbs_pars_unsuccessfull; |
---|
584 | } |
---|
585 | break; |
---|
586 | } |
---|
587 | else { |
---|
588 | char *buf1; |
---|
589 | buf1 = search-1; |
---|
590 | while ((c=*(search++)) && c!=GBS_MWILD && c!=GBS_WILD) ; // search the next wildcardstring |
---|
591 | search--; // back one character |
---|
592 | *search = 0; |
---|
593 | what_wild_card = c; |
---|
594 | p = GBS_find_string(source, buf1, 0); |
---|
595 | if (!p) { // string not found -> unsuccessful search |
---|
596 | goto gbs_pars_unsuccessfull; |
---|
597 | } |
---|
598 | start_match = p; |
---|
599 | source = p + strlen(buf1); // we parsed it |
---|
600 | *search = what_wild_card; |
---|
601 | } |
---|
602 | break; |
---|
603 | } |
---|
604 | } |
---|
605 | |
---|
606 | gbs_pars_successfull : |
---|
607 | /* now we got |
---|
608 | * source: pointer to end of match |
---|
609 | * start_match: pointer to start of match |
---|
610 | * in: pointer to the entire string |
---|
611 | * already_transferred: pointer to the start of the unparsed string |
---|
612 | * bar: the replace string |
---|
613 | */ |
---|
614 | |
---|
615 | // now look for the replace string |
---|
616 | GBS_strncat(strstruct, already_transferred, start_match-already_transferred); // cat old data |
---|
617 | error = gbs_build_replace_string(strstruct, bar, wildcard, max_wildcard, // do the command |
---|
618 | mwildcard, max_mwildcard, gb_container); |
---|
619 | already_transferred = source; |
---|
620 | |
---|
621 | for (i = 0; i < max_mwildcard; i++) { |
---|
622 | freenull(mwildcard[i]); |
---|
623 | } |
---|
624 | max_wildcard = 0; |
---|
625 | max_mwildcard = 0; |
---|
626 | |
---|
627 | if (error) { |
---|
628 | GBS_strforget(strstruct); |
---|
629 | free(command); |
---|
630 | free(in); |
---|
631 | GB_export_error(error); |
---|
632 | return 0; |
---|
633 | } |
---|
634 | } |
---|
635 | gbs_pars_unsuccessfull : |
---|
636 | GBS_strcat(strstruct, already_transferred); // cat the rest data |
---|
637 | |
---|
638 | for (i = 0; i < max_mwildcard; i++) { |
---|
639 | freenull(mwildcard[i]); |
---|
640 | } |
---|
641 | max_wildcard = 0; |
---|
642 | max_mwildcard = 0; |
---|
643 | |
---|
644 | freeset(in, GBS_strclose(strstruct)); |
---|
645 | } |
---|
646 | free(command); |
---|
647 | return in; |
---|
648 | } |
---|
649 | |
---|