diff -ur nano-1.3.0-p0/src/color.c nano-1.3.0-p1/src/color.c --- nano-1.3.0-p0/src/color.c 2003-10-30 19:27:52.000000000 -0700 +++ nano-1.3.0-p1/src/color.c 2003-11-01 00:49:10.000000000 -0700 @@ -166,11 +166,9 @@ for (c = tmpsyntax->colors; c != NULL; c = c->next) { regcomp(&c->start, c->start_regex, (c->flags.insensitive ? REG_ICASE : 0) | REG_EXTENDED); - free(c->start_regex); if (c->end_regex != NULL) { c->end = (regex_t *)nmalloc(sizeof(regex_t)); regcomp(c->end, c->end_regex, (c->flags.insensitive ? REG_ICASE : 0) | REG_EXTENDED); - free(c->end_regex); } } @@ -180,4 +178,32 @@ do_colorinit(); } +int regexec_wrapper(const colortype *color, const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags) { + /* Each regex_t will be freed and recompiled every 100 calls */ + if (color->counter > 100) { + /* calls kB (maximum regexec leakage) + * ----------- + * 200 56 + * 150 40 + * 125 28 + * 100 20 + * 50 20 + */ + + regfree((regex_t *)&color->start); + regcomp((regex_t *)&color->start, color->start_regex, + (color->flags.insensitive ? REG_ICASE : 0) | REG_EXTENDED); + if(color->end_regex != NULL){ + regfree(color->end); + regcomp(color->end, color->end_regex, + (color->flags.insensitive ? REG_ICASE : 0) | REG_EXTENDED); + } + ((colortype *)color)->counter = 0; + } + + ((colortype *)color)->counter++; + return regexec(preg, string, nmatch, pmatch, eflags); +} + #endif /* ENABLE_COLOR */ diff -ur nano-1.3.0-p0/src/nano.h nano-1.3.0-p1/src/nano.h --- nano-1.3.0-p0/src/nano.h 2003-10-30 15:22:33.000000000 -0700 +++ nano-1.3.0-p1/src/nano.h 2003-10-31 22:20:30.000000000 -0700 @@ -211,6 +211,7 @@ regex_t start; /* Compiled regex string */ char *end_regex; /* End of the regex string */ regex_t *end; /* Compiled regex string */ + int counter; /* Number of times regexec() has been called */ struct colortype *next; } colortype; diff -ur nano-1.3.0-p0/src/proto.h nano-1.3.0-p1/src/proto.h --- nano-1.3.0-p0/src/proto.h 2003-10-30 15:25:40.000000000 -0700 +++ nano-1.3.0-p1/src/proto.h 2003-10-31 22:45:05.000000000 -0700 @@ -135,6 +135,8 @@ void set_colorpairs(void); void do_colorinit(void); void update_color(void); +int regexec_wrapper(const colortype *color, const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags); #endif /* ENABLE_COLOR */ /* Public functions in cut.c */ diff -ur nano-1.3.0-p0/src/rcfile.c nano-1.3.0-p1/src/rcfile.c --- nano-1.3.0-p0/src/rcfile.c 2003-10-30 19:33:38.000000000 -0700 +++ nano-1.3.0-p1/src/rcfile.c 2003-10-31 22:21:55.000000000 -0700 @@ -568,6 +568,7 @@ newcolor->next = NULL; newcolor->end_regex = NULL; newcolor->end = NULL; + newcolor->counter = 0; if (tmpsyntax->colors == NULL) { tmpsyntax->colors = newcolor; diff -ur nano-1.3.0-p0/src/winio.c nano-1.3.0-p1/src/winio.c --- nano-1.3.0-p0/src/winio.c 2003-10-23 18:14:42.000000000 -0600 +++ nano-1.3.0-p1/src/winio.c 2003-11-01 00:26:02.000000000 -0700 @@ -1035,38 +1035,39 @@ #ifdef ENABLE_COLOR if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) { - const colortype *tmpcolor = colorstrings; + const colortype *tmpcolor; - for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) { + for (tmpcolor = colorstrings; tmpcolor != NULL; tmpcolor = tmpcolor->next) { int x_start; /* Starting column for mvwaddnstr. Zero-based. */ int paintlen; - /* Number of chars to paint on this line. There are COLS - * characters on a whole line. */ - regmatch_t startmatch; /* match position for start_regexp */ - regmatch_t endmatch; /* match position for end_regexp */ + /* Number of chars to paint on this line. + * There are COLS characters on a whole line. */ + regmatch_t startmatch, endmatch; + /* match position for start_regexp and end_regexp */ if (tmpcolor->bright) wattron(edit, A_BOLD); wattron(edit, COLOR_PAIR(tmpcolor->pairnum)); + /* Two notes about regexec(). Return value 0 means there is * a match. Also, rm_eo is the first non-matching character * after the match. */ /* First case, tmpcolor is a single-line expression. */ if (tmpcolor->end == NULL) { - size_t k = 0; + size_t k; /* We increment k by rm_eo, to move past the end of the * last match. Even though two matches may overlap, we * want to ignore them, so that we can highlight * C-strings correctly. */ - while (k < endpos) { + for (k = 0; k < endpos; k = startmatch.rm_eo) { /* Note the fifth parameter to regexec(). It says * not to match the beginning-of-line character * unless k is 0. If regexec() returns REG_NOMATCH, * there are no more matches in the line. */ - if (regexec(&tmpcolor->start, &fileptr->data[k], 1, + if (regexec_wrapper(tmpcolor, &tmpcolor->start, &fileptr->data[k], 1, &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH) break; /* Translate the match to the beginning of the line. */ @@ -1087,15 +1088,15 @@ if (paintlen > COLS - x_start) paintlen = COLS - x_start; - assert(0 <= x_start && 0 < paintlen && - x_start + paintlen <= COLS); - mvwaddnstr(edit, yval, x_start, - converted + x_start, paintlen); + /* assert(0 <= x_start && 0 < paintlen && x_start + paintlen <= COLS); + * The above IF statement guarantees part of this test */ + assert(0 <= x_start && 0 < paintlen); + + mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen); } - k = startmatch.rm_eo; } } else { - /* This is a multi-line regexp. There are two steps. + /* This is a multi-line regexp. There are two steps. * First, we have to see if the beginning of the line is * colored by a start on an earlier line, and an end on * this line or later. @@ -1116,11 +1117,11 @@ * lines after fileptr? */ while (start_line != NULL && - regexec(&tmpcolor->start, start_line->data, 1, + regexec_wrapper(tmpcolor, &tmpcolor->start, start_line->data, 1, &startmatch, 0) == REG_NOMATCH) { /* If there is an end on this line, there is no need * to look for starts on earlier lines. */ - if (regexec(tmpcolor->end, start_line->data, 0, NULL, 0) + if (regexec_wrapper(tmpcolor, tmpcolor->end, start_line->data, 0, NULL, 0) == 0) goto step_two; start_line = start_line->prev; @@ -1136,14 +1137,14 @@ while (1) { start_col += startmatch.rm_so; startmatch.rm_eo -= startmatch.rm_so; - if (regexec(tmpcolor->end, + if (regexec_wrapper(tmpcolor, tmpcolor->end, start_line->data + start_col + startmatch.rm_eo, 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH) /* No end found after this start. */ break; start_col++; - if (regexec(&tmpcolor->start, + if (regexec_wrapper(tmpcolor, &tmpcolor->start, start_line->data + start_col, 1, &startmatch, REG_NOTBOL) == REG_NOMATCH) /* No later start on this line. */ @@ -1158,7 +1159,7 @@ * starts. */ end_line = fileptr; while (end_line != NULL && - regexec(tmpcolor->end, end_line->data, 1, &endmatch, 0)) + regexec_wrapper(tmpcolor, tmpcolor->end, end_line->data, 1, &endmatch, 0)) end_line = end_line->next; /* No end found, or it is too early. */ @@ -1172,7 +1173,10 @@ if (paintlen > COLS) paintlen = COLS; - assert(0 < paintlen && paintlen <= COLS); + /* assert(0 < paintlen && paintlen <= COLS); + * The above IF statement guarantees part of this test */ + assert(0 < paintlen); + mvwaddnstr(edit, yval, 0, converted, paintlen); /* We have already painted the whole line. */ @@ -1182,7 +1186,7 @@ step_two: /* Second step, we look for starts on this line. */ start_col = 0; while (start_col < endpos) { - if (regexec(&tmpcolor->start, fileptr->data + start_col, 1, + if (regexec_wrapper(tmpcolor, &tmpcolor->start, fileptr->data + start_col, 1, &startmatch, start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH || start_col + startmatch.rm_so >= endpos) @@ -1198,7 +1202,7 @@ else x_start = strnlenpt(fileptr->data, startmatch.rm_so) - start; - if (regexec(tmpcolor->end, fileptr->data + startmatch.rm_eo, + if (regexec_wrapper(tmpcolor, tmpcolor->end, fileptr->data + startmatch.rm_eo, 1, &endmatch, startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) { /* Translate the end match to be relative to the @@ -1215,10 +1219,11 @@ if (x_start + paintlen > COLS) paintlen = COLS - x_start; - assert(0 <= x_start && 0 < paintlen && - x_start + paintlen <= COLS); - mvwaddnstr(edit, yval, x_start, - converted + x_start, paintlen); + /* assert(0 <= x_start && 0 < paintlen && x_start + paintlen <= COLS); + * The above IF statement guarantees part of this test */ + assert(0 <= x_start && 0 < paintlen); + + mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen); } } else if (!searched_later_lines) { searched_later_lines = 1; @@ -1226,7 +1231,7 @@ * yet looked for one on later lines. */ end_line = fileptr->next; while (end_line != NULL && - regexec(tmpcolor->end, end_line->data, 0, + regexec_wrapper(tmpcolor, tmpcolor->end, end_line->data, 0, NULL, 0) == REG_NOMATCH) end_line = end_line->next; if (end_line != NULL) { @@ -1244,7 +1249,8 @@ } /* if (tmp_color->end != NULL) */ skip_step_two: - wattroff(edit, A_BOLD); + if (tmpcolor->bright) + wattroff(edit, A_BOLD); wattroff(edit, COLOR_PAIR(tmpcolor->pairnum)); } /* for tmpcolor in colorstrings */ } @@ -1305,7 +1311,9 @@ x_start = 0; } - assert(x_start >= 0 && x_start <= strlen(converted)); + /* assert(x_start >= 0 && x_start <= strlen(converted)); + * The above IF statement guarantees part of this test */ + assert(x_start <= strlen(converted)); wattron(edit, A_REVERSE); mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);