From 716bbe96d47f61cf20ac9298d0911be522eefe98 Mon Sep 17 00:00:00 2001 From: "\"Vladimir N. Oleynik\"" Date: Tue, 28 Feb 2006 10:10:19 +0000 Subject: make grep faster (close bug 758), reduce small memory leak in CONFIG_FEATURE_CLEANUP mode --- findutils/grep.c | 78 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 16 deletions(-) (limited to 'findutils') diff --git a/findutils/grep.c b/findutils/grep.c index 3c5167e28..e1ce8e5fa 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -11,8 +11,9 @@ /* BB_AUDIT GNU defects - always acts as -a. */ /* http://www.opengroup.org/onlinepubs/007904975/utilities/grep.html */ /* - * Apr 2004 by Vladimir Oleynik - + * 2004,2006 (C) Vladimir Oleynik - * correction "-e pattern1 -e pattern2" logic and more optimizations. + * precompiled regex */ #include @@ -82,6 +83,13 @@ static int last_line_printed; static llist_t *pattern_head; /* growable list of patterns to match */ static char *cur_file; /* the current file we are reading */ +typedef struct GREP_LIST_DATA { + char *pattern; + regex_t preg; +#define PATTERN_MEM_A 1 +#define COMPILED 2 + int flg_mem_alocated_compiled; +} grep_list_data_t; static void print_line(const char *line, int linenum, char decoration) { @@ -115,12 +123,14 @@ static int grep_file(FILE *file) while ((line = bb_get_chomped_line_from_file(file)) != NULL) { llist_t *pattern_ptr = pattern_head; + grep_list_data_t * gl; linenum++; ret = 0; while (pattern_ptr) { + gl = (grep_list_data_t *)pattern_ptr->data; if (FGREP_FLAG) { - ret = strstr(line, pattern_ptr->data) != NULL; + ret = strstr(line, gl->pattern) != NULL; } else { /* * test for a postitive-assertion match (regexec returns success (0) @@ -128,10 +138,11 @@ static int grep_file(FILE *file) * match (regexec returns failure (REG_NOMATCH) and the user specified * invert search) */ - regex_t regex; - xregcomp(®ex, pattern_ptr->data, reflags); - ret |= regexec(®ex, line, 0, NULL, 0) == 0; - regfree(®ex); + if(!(gl->flg_mem_alocated_compiled & COMPILED)) { + gl->flg_mem_alocated_compiled |= COMPILED; + xregcomp(&(gl->preg), gl->pattern, reflags); + } + ret |= regexec(&(gl->preg), line, 0, NULL, 0) == 0; } pattern_ptr = pattern_ptr->link; } /* while (pattern_ptr) */ @@ -230,6 +241,25 @@ static int grep_file(FILE *file) return nmatches; } +#if ENABLE_FEATURE_CLEAN_UP +#define new_grep_list_data(p, m) add_grep_list_data(p, m) +static char * add_grep_list_data(char *pattern, int flg_used_mem) +#else +#define new_grep_list_data(p, m) add_grep_list_data(p) +static char * add_grep_list_data(char *pattern) +#endif +{ + grep_list_data_t *gl = xmalloc(sizeof(grep_list_data_t)); + gl->pattern = pattern; +#if ENABLE_FEATURE_CLEAN_UP + gl->flg_mem_alocated_compiled = flg_used_mem; +#else + gl->flg_mem_alocated_compiled = 0; +#endif + return (char *)gl; +} + + static void load_regexes_from_file(llist_t *fopt) { char *line; @@ -243,7 +273,8 @@ static void load_regexes_from_file(llist_t *fopt) free(cur); f = bb_xfopen(ffile, "r"); while ((line = bb_get_chomped_line_from_file(f)) != NULL) { - pattern_head = llist_add_to(pattern_head, line); + pattern_head = llist_add_to(pattern_head, + new_grep_list_data(line, PATTERN_MEM_A)); } } } @@ -296,7 +327,7 @@ extern int grep_main(int argc, char **argv) lines_after = 0; } else if(lines_before > 0) before_buf = (char **)xcalloc(lines_before, sizeof(char *)); - } + } #else /* with auto sanity checks */ bb_opt_complementally = "H-h:e::f::c-n:q-n:l-n"; @@ -309,6 +340,13 @@ extern int grep_main(int argc, char **argv) print_filename++; if(opt & GREP_OPT_h) print_filename--; + if (pattern_head != NULL) { + /* convert char *argv[] to grep_list_data_t */ + llist_t *cur; + + for(cur = pattern_head; cur; cur = cur->link) + cur->data = new_grep_list_data(cur->data, 0); + } if(opt & GREP_OPT_f) load_regexes_from_file(fopt); @@ -333,7 +371,9 @@ extern int grep_main(int argc, char **argv) if (*argv == NULL) bb_show_usage(); else { - pattern_head = llist_add_to(pattern_head, *argv++); + char *pattern = new_grep_list_data(*argv++, 0); + + pattern_head = llist_add_to(pattern_head, pattern); argc--; } } @@ -373,14 +413,20 @@ extern int grep_main(int argc, char **argv) } /* destroy all the elments in the pattern list */ - if (ENABLE_FEATURE_CLEAN_UP) - while (pattern_head) { - llist_t *pattern_head_ptr = pattern_head; - - pattern_head = pattern_head->link; - free(pattern_head_ptr); + if (ENABLE_FEATURE_CLEAN_UP) { + while (pattern_head) { + llist_t *pattern_head_ptr = pattern_head; + grep_list_data_t *gl = + (grep_list_data_t *)pattern_head_ptr->data; + + pattern_head = pattern_head->link; + if((gl->flg_mem_alocated_compiled & PATTERN_MEM_A)) + free(gl->pattern); + if((gl->flg_mem_alocated_compiled & COMPILED)) + regfree(&(gl->preg)); + free(pattern_head_ptr); + } } - /* 0 = success, 1 = failed, 2 = error */ /* If the -q option is specified, the exit status shall be zero * if an input line is selected, even if an error was detected. */ -- cgit v1.2.3