grep: free expressions and patterns when done.
authorJunio C Hamano <junkio@cox.net>
Wed, 27 Sep 2006 23:27:10 +0000 (16:27 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 27 Sep 2006 23:27:10 +0000 (16:27 -0700)
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-grep.c
grep.c
grep.h

index 6718788..4205e5d 100644 (file)
@@ -325,6 +325,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
                else
                        hit |= grep_file(opt, ce->name);
        }
+       free_grep_patterns(opt);
        return hit;
 }
 
@@ -694,5 +695,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                if (grep_object(&opt, paths, real_obj, list.objects[i].name))
                        hit = 1;
        }
+       free_grep_patterns(&opt);
        return !hit;
 }
diff --git a/grep.c b/grep.c
index cc8d684..2c740bd 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -167,6 +167,46 @@ void compile_grep_patterns(struct grep_opt *opt)
                die("incomplete pattern expression: %s", p->pattern);
 }
 
+static void free_pattern_expr(struct grep_expr *x)
+{
+       switch (x->node) {
+       case GREP_NODE_ATOM:
+               break;
+       case GREP_NODE_NOT:
+               free_pattern_expr(x->u.unary);
+               break;
+       case GREP_NODE_AND:
+       case GREP_NODE_OR:
+               free_pattern_expr(x->u.binary.left);
+               free_pattern_expr(x->u.binary.right);
+               break;
+       }
+       free(x);
+}
+
+void free_grep_patterns(struct grep_opt *opt)
+{
+       struct grep_pat *p, *n;
+
+       for (p = opt->pattern_list; p; p = n) {
+               n = p->next;
+               switch (p->token) {
+               case GREP_PATTERN: /* atom */
+               case GREP_PATTERN_HEAD:
+               case GREP_PATTERN_BODY:
+                       regfree(&p->regexp);
+                       break;
+               default:
+                       break;
+               }
+               free(p);
+       }
+
+       if (!opt->extended)
+               return;
+       free_pattern_expr(opt->pattern_expression);
+}
+
 static char *end_of_line(char *cp, unsigned long *left)
 {
        unsigned long l = *left;
@@ -439,6 +479,8 @@ int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long
                lno++;
        }
 
+       free(prev);
+
        if (opt->status_only)
                return 0;
        if (opt->unmatch_name_only) {
diff --git a/grep.h b/grep.h
index 0b503ea..af9098c 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -73,6 +73,7 @@ struct grep_opt {
 
 extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
 extern void compile_grep_patterns(struct grep_opt *opt);
+extern void free_grep_patterns(struct grep_opt *opt);
 extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
 
 #endif