/[vps]/baselayout-vserver/trunk/src/core/simple-regex.c
Gentoo

Diff of /baselayout-vserver/trunk/src/core/simple-regex.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 126 Revision 127
1/*
2 * simple_regex.c
3 *
4 * Simle regex library.
5 *
6 * Copyright (C) 2004,2005 Martin Schlemmer <azarah@nosferatu.za.org>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * $Header$
23 */
24
25/*
26 * Some notes:
27 *
28 * - This is a very simple regex library (read: return a match if some string
29 * matches some regex). It is probably not POSIX (if there are a POSIX or
30 * other standard) compatible.
31 *
32 * - I primarily wrote it to _not_ use glibc type regex functions, in case we
33 * might want to use it in code that have to be linked agaist klibc, etc.
34 *
35 * - It really is not optimized in any way yet.
36 *
37 * - Supported operators are:
38 *
39 * '.', '?', '*', '+' - So called 'wildcards'
40 * '[a-z]', '[^a-z]' - Basic 'lists'. Note that 'a-z' just specify that
41 * it supports basic lists as well as sequences ..
42 * The '^' is for an inverted list of course.
43 * '^', '$' - The 'from start' and 'to end' operators. If these
44 * are not used at the start ('^') or end ('$') of the
45 * regex, they will be treated as normal characters
46 * (this of course exclude the use of '^' in a 'list').
47 *
48 * - If an invalid argument was passed, the functions returns 0 with
49 * 'regex_data-match == 0' (no error with no match) rather than -1. It may
50 * not be consistant with other practices, but I personally do not feel it is
51 * a critical error for these types of functions, and there are debugging you
52 * can enable to verify that there are no such issues.
53 *
54 * - __somefunction() is usually a helper function for somefunction(). I guess
55 * recursion might be an alternative, but I try to avoid it.
56 *
57 * - In general if we are matching a 'wildcard' ('*', '+' or '?'), a 'word'
58 * (read: some part of the regex that do not contain a 'wildcard' or 'list')
59 * will have a greater 'weight' than the 'wildcard'. This means that we
60 * will only continue to evaluate the 'wildcard' until the following 'word'
61 * (if any) matches. Currently this do not hold true for a 'list' not
62 * followed by a 'wildcard' - I might fix this in future.
63 *
64 */
65
66#include <errno.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70
71#include "debug.h"
72#include "misc.h"
73#include "simple-regex.h"
74
75/* Macro to check if a regex_data_t pointer is valid */
76#define CHECK_REGEX_DATA_P(_regex_data, _on_error) \
77 do { \
78 if ((NULL == _regex_data) \
79 || (NULL == _regex_data->data) \
80 /* We do not check for this, as it might still \
81 * provide a match ('*' or '?' wildcard) */ \
82 /* || (0 == strlen(_regex_data->data)) */ \
83 || (NULL == _regex_data->regex) \
84 || (0 == strlen(_regex_data->regex))) {\
85 DBG_MSG("Invalid argument passed!\n"); \
86 goto _on_error; \
87 } \
88 } while (0)
89
90size_t get_word(const char *regex, char **r_word);
91int match_word(regex_data_t *regex_data);
92size_t get_list_size(const char *regex);
93size_t get_list(const char *regex, char **r_list);
94int __match_list(regex_data_t *regex_data);
95int match_list(regex_data_t *regex_data);
96size_t get_wildcard(const char *regex, char *r_wildcard);
97int __match_wildcard(regex_data_t *regex_data,
98int (*match_func)(regex_data_t *regex_data), const char *regex);
99int match_wildcard(regex_data_t *regex_data);
100int __match(regex_data_t *regex_data);
101
102/*
103 * Return values for match_* functions
104 *
105 * 0 - There was no error. If there was a match, regex_data->match
106 * - will be > 0 (this is the definitive check - if not true, the
107 * - other values of the struct may be bogus), regex_data->count
108 * - will be the amount of data that was matched (might be 0 for
109 * - some wildcards), and regex_data->r_count will be > 0.
110 *
111 * -1 - An error occured. Check errno for more info.
112 *
113 */
114
115size_t get_word(const char *regex, char **r_word)
116{
117 char *r_list;
118 char *tmp_p;
119 size_t count = 0;
120 size_t tmp_count;
121
122 /* NULL string means we do not have a word */
123 if ((NULL == regex) || (0 == strlen(regex))) {
124 DBG_MSG("Invalid argument passed!\n");
125 return 0;
126 }
127
128 *r_word = malloc(strlen(regex) + 1);
129 if (NULL == r_word) {
130 DBG_MSG("Failed to allocate buffer!\n");
131 return 0;
132 }
133 tmp_p = *r_word;
134
135 while (strlen(regex) > 0) {
136 switch (regex[0]) {
137 case '*':
138 case '+':
139 case '?':
140 /* If its a wildcard, backup one step */
141 *(--tmp_p) = '\0';
142 count--;
143 return count;
144 case '[':
145 tmp_count = get_list(regex, &r_list);
146 free(r_list);
147 /* In theory should not happen, but you never know
148 * what may happen in future ... */
149 if (-1 == tmp_count)
150 goto error;
151
152 /* Bail if we have a list */
153 if (tmp_count > 0) {
154 tmp_p[0] = '\0';
155 return count;
156 }
157 default:
158 *tmp_p++ = *regex++;
159 count++;
160 break;
161 }
162 }
163
164 tmp_p[0] = '\0';
165
166 return count;
167
168error:
169 free(*r_word);
170
171 return -1;
172}
173
174int match_word(regex_data_t *regex_data)
175{
176 char *data_p = regex_data->data;
177 char *r_word = NULL, *r_word_p;
178 size_t count = 0;
179
180 CHECK_REGEX_DATA_P(regex_data, exit);
181
182 count = get_word(regex_data->regex, &r_word);
183 if (-1 == count)
184 goto error;
185 if (0 == count)
186 goto exit;
187 r_word_p = r_word;
188
189 while ((strlen(data_p) > 0) && (strlen(r_word_p) > 0 )) {
190 /* If 'r_word' is not 100% part of 'string', we do not have
191 * a match. If its a '.', it matches no matter what. */
192 if ((data_p[0] != r_word_p[0]) && ('.' != r_word_p[0])) {
193 count = 0;
194 goto exit;
195 }
196
197 data_p++;
198 r_word_p++;
199 }
200
201 /* If 'string' is shorter than 'r_word', we do not have a match */
202 if ((0 == strlen(data_p)) && (0 < strlen(r_word_p))) {
203 count = 0;
204 goto exit;
205 }
206
207exit:
208 /* Fill in our structure */
209 if (0 == count)
210 regex_data->match = REGEX_NO_MATCH;
211 else if (strlen(regex_data->data) == count)
212 regex_data->match = REGEX_FULL_MATCH;
213 else
214 regex_data->match = REGEX_PARTIAL_MATCH;
215 if (regex_data->match != REGEX_NO_MATCH)
216 regex_data->where = regex_data->data;
217 else
218 regex_data->where = NULL;
219 regex_data->count = count;
220 regex_data->r_count = count;
221
222 free(r_word);
223 return 0;
224
225error:
226 regex_data->match = REGEX_NO_MATCH;
227
228 free(r_word);
229 return -1;
230}
231
232size_t get_list_size(const char *regex)
233{
234 size_t count = 0;
235
236 /* NULL string means we do not have a list */
237 if ((NULL == regex)
238 || (0 == strlen(regex))
239 || ('[' != regex[0])) {
240 DBG_MSG("Invalid argument passed!\n");
241 return 0;
242 }
243
244 regex++;
245
246 while ((strlen(regex) > 0) && (']' != regex[0])) {
247 /* We have a sequence (x-y) */
248 if (('-' == regex[0])
249 && (']' != regex[1])
250 && (strlen(regex) >= 2)
251 && (regex[-1] < regex[1]))
252 {
253 /* Add current + diff in sequence */
254 count += regex[1] - regex[-1];
255 /* Take care of '-' and next char */
256 regex += 2;
257 } else {
258 regex++;
259 count++;
260 }
261 }
262
263 return count;
264}
265
266size_t get_list(const char *regex, char **r_list)
267{
268 char *tmp_buf = NULL;
269 size_t count = 0;
270 size_t size;
271
272 /* NULL string means we do not have a list */
273 if ((NULL == regex) || (0 == strlen(regex))) {
274 DBG_MSG("Invalid argument passed!\n");
275 return 0;
276 }
277
278 /* Bail if we do not have a list. Do not add debugging, as
279 * it is very noisy (used a lot when we call match_list() in
280 * __match() and match() to test for list matching) */
281 if ('[' != regex[0])
282 return 0;
283
284 size = get_list_size(regex);
285 if (0 == size) {
286 /* Should not be an issue, but just in case */
287 DBG_MSG("0 returned by get_list_size.\n");
288 return 0;
289 }
290
291 *r_list = malloc(size + 1);
292 if (NULL == *r_list) {
293 DBG_MSG("Failed to allocate buffer!\n");
294 return -1;
295 }
296 tmp_buf = *r_list;
297
298 /* Take care of '[' */
299 regex++;
300 count++;
301
302 while ((strlen(regex) > 0) && (']' != regex[0])) {
303 /* We have a sequence (x-y) */
304 if (('-' == regex[0])
305 && (']' != regex[1])
306 && (strlen(regex) >= 2)
307 && (regex[-1] < regex[1])) {
308 /* Fill in missing chars in sequence */
309 while (tmp_buf[-1] < regex[1]) {
310 tmp_buf[0] = (char)(tmp_buf[-1] + 1);
311 tmp_buf++;
312 /* We do not increase count */
313 }
314 /* Take care of '-' and next char */
315 count += 2;
316 regex += 2;
317 } else {
318 *tmp_buf++ = *regex++;
319 count++;
320 }
321 }
322
323 tmp_buf[0] = '\0';
324 /* Take care of ']' */
325 count++;
326
327 /* We do not have a list as it does not end in ']' */
328 if (']' != regex[0]) {
329 count = 0;
330 free(*r_list);
331 }
332
333 return count;
334}
335
336/* If the first is the '^' character, everything but the list is matched
337 * NOTE: We only evaluate _ONE_ data character at a time!! */
338int __match_list(regex_data_t *regex_data)
339{
340 regex_data_t tmp_data;
341 char *data_p = regex_data->data;
342 char *list_p = regex_data->regex;
343 char test_regex[2] = { '\0', '\0' };
344 int invert = 0;
345 int match;
346 int retval;
347
348 CHECK_REGEX_DATA_P(regex_data, failed);
349
350 if ('^' == list_p[0]) {
351 /* We need to invert the match */
352 invert = 1;
353 /* Make sure '^' is not part of our list */
354 list_p++;
355 }
356
357 if (invert)
358 /* All should be a match if not in the list */
359 match = 1;
360 else
361 /* We only have a match if in the list */
362 match = 0;
363
364 while (strlen(list_p) > 0) {
365 test_regex[0] = list_p[0];
366
367 FILL_REGEX_DATA(tmp_data, data_p, test_regex);
368 retval = match_word(&tmp_data);
369 if (-1 == retval)
370 goto error;
371
372 if (REGEX_MATCH(tmp_data)) {
373 if (invert)
374 /* If we exclude the list from
375 * characters we try to match, we
376 * have a match until one of the
377 * list is found. */
378 match = 0;
379 else
380 /* If not, we have to keep looking
381 * until one from the list match
382 * before we have a match */
383 match = 1;
384 break;
385 }
386 list_p++;
387 }
388
389 /* Fill in our structure */
390 if (match) {
391 regex_data->match = REGEX_PARTIAL_MATCH;
392 regex_data->where = regex_data->data;
393 regex_data->count = 1;
394 /* This one is more cosmetic, as match_list() will
395 * do the right thing */
396 regex_data->r_count = 0; /* strlen(regex_data->regex); */
397 } else {
398failed:
399 regex_data->match = REGEX_NO_MATCH;
400 regex_data->where = NULL;
401 regex_data->count = 0;
402 regex_data->r_count = 0;
403 }
404
405 return 0;
406
407error:
408 regex_data->match = REGEX_NO_MATCH;
409
410 return -1;
411}
412
413int match_list(regex_data_t *regex_data)
414{
415 regex_data_t tmp_data;
416 char *data_p = regex_data->data;
417 char *list_p = regex_data->regex;
418 char *r_list = NULL;
419 size_t r_count = 0;
420 int retval;
421
422 CHECK_REGEX_DATA_P(regex_data, failed);
423
424 r_count = get_list(list_p, &r_list);
425 if (-1 == r_count)
426 goto error;
427 if (0 == r_count)
428 goto failed;
429
430 FILL_REGEX_DATA(tmp_data, data_p, &list_p[r_count-1]);
431 retval = __match_wildcard(&tmp_data, __match_list, r_list);
432 if (-1 == retval)
433 goto error;
434 if (REGEX_MATCH(tmp_data)) {
435 /* This should be 2 ('word' + 'wildcard'), so just remove
436 * the wildcard */
437 tmp_data.r_count--;
438 goto exit;
439 }
440
441 FILL_REGEX_DATA(tmp_data, data_p, r_list);
442 retval = __match_list(&tmp_data);
443 if (-1 == retval)
444 goto error;
445 if (REGEX_MATCH(tmp_data))
446 goto exit;
447
448failed:
449 /* We will fill in regex_data below */
450 tmp_data.match = REGEX_NO_MATCH;
451 tmp_data.where = NULL;
452 tmp_data.count = 0;
453 tmp_data.r_count = 0;
454
455exit:
456 /* Fill in our structure */
457 regex_data->match = tmp_data.match;
458 regex_data->where = tmp_data.where;
459 regex_data->count = tmp_data.count;
460 if (regex_data->match != REGEX_NO_MATCH)
461 /* tmp_data.r_count for __match_wildcard will take care of the
462 * wildcard, and tmp_data.r_count for __match_list will be 0 */
463 regex_data->r_count = r_count + tmp_data.r_count;
464 else
465 regex_data->r_count = 0;
466
467 free(r_list);
468 return 0;
469
470error:
471 regex_data->match = REGEX_NO_MATCH;
472
473 free(r_list);
474 return -1;
475}
476
477size_t get_wildcard(const char *regex, char *r_wildcard)
478{
479 /* NULL regex means we do not have a wildcard */
480 if ((NULL == regex) || (0 == strlen(regex))) {
481 DBG_MSG("Invalid argument passed!\n");
482 return 0;
483 }
484
485 r_wildcard[0] = regex[0];
486 r_wildcard[2] = '\0';
487
488 switch (regex[1]) {
489 case '*':
490 case '+':
491 case '?':
492 r_wildcard[1] = regex[1];
493 break;
494 default:
495 r_wildcard[0] = '\0';
496 return 0;
497 }
498
499 return strlen(r_wildcard);
500}
501
502int __match_wildcard(regex_data_t *regex_data, int (*match_func)(regex_data_t *regex_data), const char *regex)
503{
504 regex_data_t tmp_data;
505 char *data_p = regex_data->data;
506 char *wildcard_p = regex_data->regex;
507 char r_wildcard[3];
508 size_t count = 0;
509 size_t r_count = 0;
510 int is_match = 0;
511 int retval;
512
513 CHECK_REGEX_DATA_P(regex_data, exit);
514
515 if (NULL == match_func) {
516 DBG_MSG("NULL match_func was passed!\n");
517 goto exit;
518 }
519
520 r_count = get_wildcard(wildcard_p, r_wildcard);
521 if (0 == r_count)
522 goto exit;
523
524 FILL_REGEX_DATA(tmp_data, data_p, (char *)regex);
525 retval = match_func(&tmp_data);
526 if (-1 == retval)
527 goto error;
528
529 switch (r_wildcard[1]) {
530 case '*':
531 case '?':
532 /* '*' and '?' always matches */
533 is_match = 1;
534 case '+':
535 /* We need to match all of them */
536 do {
537 /* If we have at least one match for '+', or none
538 * for '*' or '?', check if we have a word or list match.
539 * We do this because a word weights more than a wildcard */
540 if ((strlen(wildcard_p) > 2)
541 && ((count > 0)
542 || ('*' == r_wildcard[1])
543 || ('?' == r_wildcard[1]))) {
544 regex_data_t tmp_data2;
545#if 0
546 printf("data_p = %s, wildcard_p = %s\n", data_p, wildcard_p);
547#endif
548
549 FILL_REGEX_DATA(tmp_data2, data_p, &wildcard_p[2]);
550 retval = match(&tmp_data2);
551 if (-1 == retval)
552 goto error;
553
554 if (/* '.' might be a special case ... */
555 /* ('.' != wildcard_p[2]) && */
556 ((REGEX_MATCH(tmp_data2))
557 && (REGEX_FULL_MATCH == tmp_data2.match))) {
558 goto exit;
559 }
560 }
561
562 if (REGEX_MATCH(tmp_data)) {
563 data_p += tmp_data.count;
564 count += tmp_data.count;
565 is_match = 1;
566
567 FILL_REGEX_DATA(tmp_data, data_p, (char *)regex);
568 retval = match_func(&tmp_data);
569 if (-1 == retval)
570 goto error;
571 }
572 /* Only once for '?' */
573 } while ((REGEX_MATCH(tmp_data)) && ('?' != r_wildcard[1]));
574
575 break;
576 default:
577 /* No wildcard */
578 break;
579 }
580
581exit:
582 /* Fill in our structure */
583 /* We can still have a match ('*' and '?'), although count == 0 */
584 if ((0 == count) && (0 == is_match))
585 regex_data->match = REGEX_NO_MATCH;
586 else if (strlen(regex_data->data) == count)
587 regex_data->match = REGEX_FULL_MATCH;
588 else
589 regex_data->match = REGEX_PARTIAL_MATCH;
590 if (regex_data->match != REGEX_NO_MATCH)
591 regex_data->where = regex_data->data;
592 else
593 regex_data->where = NULL;
594 regex_data->count = count;
595 regex_data->r_count = r_count;
596
597 return 0;
598
599error:
600 regex_data->match = REGEX_NO_MATCH;
601
602 return -1;
603}
604
605int match_wildcard(regex_data_t *regex_data)
606{
607 regex_data_t tmp_data;
608 char *data_p = regex_data->data;
609 char *wildcard_p = regex_data->regex;
610 char r_wildcard[3];
611 size_t r_count;
612 int retval;
613
614 CHECK_REGEX_DATA_P(regex_data, failed);
615
616 /* Invalid wildcard - we need a character + a regex operator */
617 if (strlen(wildcard_p) < 2)
618 goto failed;
619
620 r_count = get_wildcard(wildcard_p, r_wildcard);
621 if (0 == r_count)
622 goto failed;
623
624 /* Needed so that match_word() will not bail if it sees the wildcard */
625 r_wildcard[1] = '\0';
626
627 FILL_REGEX_DATA(tmp_data, data_p, wildcard_p);
628 retval = __match_wildcard(&tmp_data, match_word, r_wildcard);
629 if (-1 == retval)
630 goto error;
631 if (REGEX_MATCH(tmp_data))
632 goto exit;
633
634failed:
635 /* We will fill in regex_data below */
636 tmp_data.match = REGEX_NO_MATCH;
637 tmp_data.where = NULL;
638 tmp_data.count = 0;
639 tmp_data.r_count = 0;
640
641exit:
642 /* Fill in our structure */
643 regex_data->match = tmp_data.match;
644 regex_data->where = tmp_data.where;
645 regex_data->count = tmp_data.count;
646 regex_data->r_count = tmp_data.r_count;
647
648 return 0;
649
650error:
651 regex_data->match = REGEX_NO_MATCH;
652
653 return -1;
654}
655
656int __match(regex_data_t *regex_data)
657{
658 regex_data_t tmp_data;
659 char *data_p = regex_data->data;
660 char *regex_p = regex_data->regex;
661 size_t count = 0;
662 size_t r_count = 0;
663 int match = 0;
664 int retval;
665
666 CHECK_REGEX_DATA_P(regex_data, failed);
667
668 while (strlen(regex_p) > 0) {
669#if 0
670 printf("data_p = '%s', regex_p = '%s'\n", data_p, regex_p);
671#endif
672
673 FILL_REGEX_DATA(tmp_data, data_p, regex_p);
674 retval = match_list(&tmp_data);
675 if (-1 == retval)
676 goto error;
677 if (REGEX_MATCH(tmp_data))
678 goto match;
679
680 FILL_REGEX_DATA(tmp_data, data_p, regex_p);
681 retval = match_wildcard(&tmp_data);
682 if (-1 == retval)
683 goto error;
684 if (REGEX_MATCH(tmp_data))
685 goto match;
686
687 FILL_REGEX_DATA(tmp_data, data_p, regex_p);
688 retval = match_word(&tmp_data);
689 if (-1 == retval)
690 goto error;
691 if (REGEX_MATCH(tmp_data))
692 goto match;
693
694 break;
695
696match:
697 data_p += tmp_data.count;
698 count += tmp_data.count;
699 regex_p += tmp_data.r_count;
700 r_count += tmp_data.r_count;
701 match = 1;
702
703 /* Check that we do not go out of bounds */
704 if (((data_p - regex_data->data) > strlen(regex_data->data))
705 || ((regex_p - regex_data->regex) > strlen(regex_data->regex)))
706 goto failed;
707 }
708
709 /* We could not match the whole regex (data too short?) */
710 if (0 != strlen(regex_p))
711 goto failed;
712
713 goto exit;
714
715failed:
716 /* We will fill in regex_data below */
717 count = 0;
718 r_count = 0;
719 match = 0;
720
721exit:
722 /* Fill in our structure */
723 /* We can still have a match ('*' and '?'), although count == 0 */
724 if ((0 == count) && (0 == match))
725 regex_data->match = REGEX_NO_MATCH;
726 else if (strlen(regex_data->data) == count)
727 regex_data->match = REGEX_FULL_MATCH;
728 else
729 regex_data->match = REGEX_PARTIAL_MATCH;
730 if (regex_data->match != REGEX_NO_MATCH)
731 regex_data->where = regex_data->data;
732 else
733 regex_data->where = NULL;
734 regex_data->count = count;
735 regex_data->r_count = r_count;
736
737 return 0;
738
739error:
740 regex_data->match = REGEX_NO_MATCH;
741
742 return -1;
743}
744
745int match(regex_data_t *regex_data)
746{
747 regex_data_t tmp_data;
748 char *data_p = regex_data->data;
749 char *regex_p;
750 char *tmp_buf = NULL;
751 int from_start = 0;
752 int to_end = 0;
753 int retval;
754
755 CHECK_REGEX_DATA_P(regex_data, failed);
756
757 /* We might be modifying regex_p, so make a copy */
758 tmp_buf = strndup(regex_data->regex, strlen(regex_data->regex));
759 if (NULL == tmp_buf) {
760 DBG_MSG("Failed to allocate temporary buffer!\n");
761 goto error;
762 }
763 regex_p = tmp_buf;
764
765 /* Should we only match from the start? */
766 if ('^' == regex_p[0]) {
767 regex_p++;
768 from_start = 1;
769 }
770
771 /* Should we match up to the end? */
772 if ('$' == regex_p[strlen(regex_p) - 1]) {
773 regex_p[strlen(regex_p) - 1] = '\0';
774 to_end = 1;
775 }
776
777 do {
778 FILL_REGEX_DATA(tmp_data, data_p, regex_p);
779 retval = __match(&tmp_data);
780 if (-1 == retval)
781 goto error;
782 } while ((strlen(data_p++) > 0)
783 && (!REGEX_MATCH(tmp_data))
784 && (0 == from_start));
785
786 /* Compensate for above extra inc */
787 data_p--;
788
789 /* Fill in our structure */
790 if (REGEX_MATCH(tmp_data)) {
791 /* Check if we had an '$' at the end of the regex, and
792 * verify that we still have a match */
793 if ((1 == to_end) && (tmp_data.count != strlen(data_p))) {
794 goto failed;
795 }
796
797 if ((data_p == regex_data->data)
798 && (tmp_data.match == REGEX_FULL_MATCH))
799 regex_data->match = REGEX_FULL_MATCH;
800 else
801 regex_data->match = REGEX_PARTIAL_MATCH;
802 regex_data->where = data_p;
803 regex_data->count = tmp_data.count;
804 regex_data->r_count = tmp_data.r_count;
805 if (1 == from_start)
806 regex_data->r_count++;
807 if (1 == to_end)
808 regex_data->r_count++;
809 } else {
810failed:
811 regex_data->match = REGEX_NO_MATCH;
812 regex_data->where = NULL;
813 regex_data->count = 0;
814 regex_data->r_count = 0;
815 }
816
817 free(tmp_buf);
818
819 return 0;
820
821error:
822 regex_data->match = REGEX_NO_MATCH;
823 free(tmp_buf);
824
825 return -1;
826}
827

Legend:
Removed from v.126  
changed lines
  Added in v.127

  ViewVC Help
Powered by ViewVC 1.1.20