DB's debug and multibuffer and regcomp fix to make nano less of a complete cpu hog


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1411 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
diff --git a/ChangeLog b/ChangeLog
index e8a6673..612c7a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -21,6 +21,10 @@
 	  regex (try "^*").  Changed regexp_init() to return 
 	  1 or 0 based on regcomp()'s return value and search_init 
 	  to exit with an error message (sorry Jordi!)
+	- Move regcomp into rcfile.c rather than each display refresh
+	  of winio.c.  New function rcfile.c:nregcomp().
+	  This fixes much of nano's resource hogging behavior
+	  in syntax higlighting. (David Benbennick).
 - cut.c:
   do_cut_text()
 	- Fix incorrect cursor location when cutting long lines
@@ -46,6 +50,9 @@
 	  mode on. (DLR; found by David Benbennick)
   save_history()
 	- Fix nrealloc return value being ignored (David Benbennick).
+- global.c:
+  thanks_for_all_the_fish()
+	- Fix compiling with DEBUG and multibuffer (David Benbennick).
 - nano.c:
   do_char()
 	- Remove unneeded check_statblank() (David Benbennick).
diff --git a/color.c b/color.c
index e118889..c2d0daa 100644
--- a/color.c
+++ b/color.c
@@ -108,15 +108,10 @@
 	const exttype *e;
 
 	for (e = tmpsyntax->extensions; e != NULL; e = e->next) {
-	    regex_t syntaxfile_regexp;
-
-	    regcomp(&syntaxfile_regexp, e->val, REG_EXTENDED | REG_NOSUB);
-
 	    /* Set colorstrings if we matched the extension regex */
-            if (!regexec(&syntaxfile_regexp, filename, 0, NULL, 0))
+	    if (!regexec(&e->val, filename, 0, NULL, 0))
 		colorstrings = tmpsyntax->color;
 
-	    regfree(&syntaxfile_regexp);
 	    if (colorstrings != NULL)
 		break;
 	}
diff --git a/global.c b/global.c
index 8fdd288..9cda438 100644
--- a/global.c
+++ b/global.c
@@ -856,10 +856,12 @@
 #ifdef ENABLE_MULTIBUFFER
     if (open_files != NULL) {
 	/* We free the memory associated with each open file. */
+	while (open_files->prev != NULL)
+	    open_files = open_files->prev;
 	free_openfilestruct(open_files);
+    }
 #else
-    if (fileage != NULL)
-	free_filestruct(fileage);
+    free_filestruct(fileage);
 #endif
 
 #ifdef ENABLE_COLOR
@@ -881,7 +883,8 @@
 	    syntaxes->color = bob->next;
 	    regfree(&bob->start);
 	    if (bob->end != NULL)
-		regfree(&bob->end);
+		regfree(bob->end);
+	    free(bob->end);
 	    free(bob);
 	}
 	syntaxes = syntaxes->next;
diff --git a/nano.h b/nano.h
index c85743e..de0fe7c 100644
--- a/nano.h
+++ b/nano.h
@@ -182,13 +182,13 @@
     int bg;			/* bg color */
     int bright;			/* Is this color A_BOLD? */
     int pairnum;		/* Color pair number used for this fg/bg */
-    char *start;		/* Start (or all) of the regex string */
-    char *end;			/* End of the regex string */
+    regex_t start;		/* Start (or all) of the regex string */
+    regex_t *end;		/* End of the regex string */
     struct colortype *next;
 } colortype;
 
 typedef struct exttype {
-    char *val;
+    regex_t val;		/* The extensions that match this syntax. */
     struct exttype *next;
 } exttype;
 
diff --git a/proto.h b/proto.h
index 530f552..9809362 100644
--- a/proto.h
+++ b/proto.h
@@ -326,6 +326,7 @@
 #ifdef ENABLE_COLOR
 int colortoint(const char *colorname, int *bright);
 char *parse_next_regex(char *ptr);
+int nregcomp(regex_t *preg, const char *regex, int flags);
 void parse_syntax(char *ptr);
 void parse_colors(char *ptr);
 #endif /* ENABLE_COLOR */
diff --git a/rcfile.c b/rcfile.c
index ac37ac8..0c43b50 100644
--- a/rcfile.c
+++ b/rcfile.c
@@ -240,11 +240,29 @@
     return ptr;
 }
 
+/* Compile the regular expression regex to preg.  Returns FALSE on success,
+   TRUE if the expression is invalid. */
+int nregcomp(regex_t *preg, const char *regex, int flags)
+{
+    int rc = regcomp(preg, regex, REG_EXTENDED | flags);
+
+    if (rc != 0) {
+	size_t len = regerror(rc, preg, NULL, 0);
+	char *str = charalloc(len);
+
+	regerror(rc, preg, str, len);
+	rcfile_error(_("Bad regex \"%s\": %s"), regex, str);
+	free(str);
+    }
+    return rc != 0;
+}
+
 void parse_syntax(char *ptr)
 {
     syntaxtype *tmpsyntax = NULL;
     const char *fileregptr = NULL, *nameptr = NULL;
-    exttype *exttmp = NULL;
+    exttype *endext = NULL;
+	/* The end of the extensions list for this syntax. */
 
     while (*ptr == ' ')
 	ptr++;
@@ -291,6 +309,9 @@
 
     /* Now load in the extensions to their part of the struct */
     while (*ptr != '\n' && *ptr != '\0') {
+	exttype *newext;
+	    /* The new extension structure. */
+
 	while (*ptr != '"' && *ptr != '\n' && *ptr != '\0')
 	    ptr++;
 
@@ -301,17 +322,17 @@
 	fileregptr = ptr;
 	ptr = parse_next_regex(ptr);
 
-	if (tmpsyntax->extensions == NULL) {
-	    tmpsyntax->extensions = (exttype *)nmalloc(sizeof(exttype));
-	    exttmp = tmpsyntax->extensions;
-	} else {
-	    for (exttmp = tmpsyntax->extensions; exttmp->next != NULL;
-		 exttmp = exttmp->next);
-	    exttmp->next = (exttype *)nmalloc(sizeof(exttype));
-	    exttmp = exttmp->next;
+	newext = (exttype *)nmalloc(sizeof(exttype));
+	if (nregcomp(&newext->val, fileregptr, REG_NOSUB))
+	    free(newext);
+	else {
+	    if (endext == NULL)
+		tmpsyntax->extensions = newext;
+	    else
+		endext->next = newext;
+	    endext = newext;
+	    endext->next = NULL;
 	}
-	exttmp->val = mallocstrcpy(NULL, fileregptr);
-	exttmp->next = NULL;
     }
 }
 
@@ -353,6 +374,11 @@
        in the colorstrings array, woo! */
 
     while (*ptr != '\0') {
+	colortype *newcolor;
+	    /* The new color structure. */
+	int cancelled = 0;
+	    /* The start expression was bad. */
+
 	while (*ptr == ' ')
 	    ptr++;
 
@@ -371,37 +397,37 @@
 	}
 	ptr++;
 
-	if (tmpsyntax->color == NULL) {
-	    tmpsyntax->color = nmalloc(sizeof(colortype));
-	    tmpcolor = tmpsyntax->color;
-#ifdef DEBUG
-	    fprintf(stderr, _("Starting a new colorstring for fg %d bg %d\n"),
-		    fg, bg);
-#endif
-	} else {
-	    for (tmpcolor = tmpsyntax->color;
-		 tmpcolor->next != NULL; tmpcolor = tmpcolor->next);
-#ifdef DEBUG
-	    fprintf(stderr, _("Adding new entry for fg %d bg %d\n"), fg, bg);
-#endif
-	    tmpcolor->next = nmalloc(sizeof(colortype));
-	    tmpcolor = tmpcolor->next;
-	}
-	tmpcolor->fg = fg;
-	tmpcolor->bg = bg;
-	tmpcolor->bright = bright;
-	tmpcolor->next = NULL;
-
-	tmpcolor->start = ptr;
+	newcolor = (colortype *)nmalloc(sizeof(colortype));
+	fgstr = ptr;
 	ptr = parse_next_regex(ptr);
-	tmpcolor->start = mallocstrcpy(NULL, tmpcolor->start);
-#ifdef DEBUG
-	fprintf(stderr, _("string val=%s\n"), tmpcolor->start);
-#endif
+	if (nregcomp(&newcolor->start, fgstr, 0)) {
+	    free(newcolor);
+	    cancelled = 1;
+	} else {
+	    newcolor->fg = fg;
+	    newcolor->bg = bg;
+	    newcolor->bright = bright;
+	    newcolor->next = NULL;
+	    newcolor->end = NULL;
 
-	if (!expectend)
-	    tmpcolor->end = NULL;
-	else {
+	    if (tmpsyntax->color == NULL) {
+		tmpsyntax->color = newcolor;
+#ifdef DEBUG
+		fprintf(stderr, _("Starting a new colorstring for fg %d bg %d\n"),
+			fg, bg);
+#endif
+	    } else {
+		for (tmpcolor = tmpsyntax->color; tmpcolor->next != NULL;
+			tmpcolor = tmpcolor->next)
+		    ;
+#ifdef DEBUG
+		fprintf(stderr, _("Adding new entry for fg %d bg %d\n"), fg, bg);
+#endif
+		tmpcolor->next = newcolor;
+	    }
+	}
+
+	if (expectend) {
 	    if (ptr == NULL || strncasecmp(ptr, "end=", 4)) {
 		rcfile_error(_
 			     ("\"start=\" requires a corresponding \"end=\""));
@@ -417,13 +443,18 @@
 	    }
 	    ptr++;
 
-	    tmpcolor->end = ptr;
+	    fgstr = ptr;
 	    ptr = parse_next_regex(ptr);
-	    tmpcolor->end = mallocstrcpy(NULL, tmpcolor->end);
-#ifdef DEBUG
-	    fprintf(stderr, _("For end part, beginning = \"%s\"\n"),
-		    tmpcolor->end);
-#endif
+
+	    /* If the start regex was invalid, skip past the end regex to
+	     * stay in sync. */
+	    if (cancelled)
+		continue;
+	    newcolor->end = (regex_t *)nmalloc(sizeof(regex_t));
+	    if (nregcomp(newcolor->end, fgstr, 0)) {
+		free(newcolor->end);
+		newcolor->end = NULL;
+	    }
 	}
     }
 }
diff --git a/winio.c b/winio.c
index e2afb3d..740cf98 100644
--- a/winio.c
+++ b/winio.c
@@ -708,12 +708,9 @@
 	    int paintlen;
 		/* number of chars to paint on this line.  There are COLS
 		 * characters on a whole line. */
-	    regex_t start_regexp;	/* Compiled search regexp */
 	    regmatch_t startmatch;	/* match position for start_regexp*/
 	    regmatch_t endmatch;	/* match position for end_regexp*/
 
-	    regcomp(&start_regexp, tmpcolor->start, REG_EXTENDED);
-
 	    if (tmpcolor->bright)
 		wattron(edit, A_BOLD);
 	    wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
@@ -734,7 +731,7 @@
 		     * match the beginning-of-line character unless
 		     * k == 0.  If regexec returns nonzero, there are no
 		     * more matches in the line. */
-		    if (regexec(&start_regexp, &fileptr->data[k], 1,
+		    if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
 				&startmatch, k == 0 ? 0 : REG_NOTBOL))
 			break;
 		    /* Translate the match to the beginning of the line. */
@@ -771,7 +768,6 @@
 		 * after start_line matching the end.  If that line is not
 		 * before fileptr, then paint the beginning of this line. */
 
-		regex_t end_regexp;	/* Compiled search regexp */
 		const filestruct *start_line = fileptr->prev;
 		    /* the first line before fileptr matching start*/
 		regoff_t start_col;
@@ -781,14 +777,12 @@
 		    /* Used in step 2.  Have we looked for an end on
 		     * lines after fileptr? */
 
-		regcomp(&end_regexp, tmpcolor->end, REG_EXTENDED);
-
 		while (start_line != NULL &&
-			regexec(&start_regexp, start_line->data, 1,
+			regexec(&tmpcolor->start, start_line->data, 1,
 				&startmatch, 0)) {
 		    /* If there is an end on this line, there is no need
 		     * to look for starts on earlier lines. */
-		    if (!regexec(&end_regexp, start_line->data, 1,
+		    if (!regexec(tmpcolor->end, start_line->data, 1,
 				&endmatch, 0))
 			goto step_two;
 		    start_line = start_line->prev;
@@ -804,14 +798,14 @@
 		while (1) {
 		    start_col += startmatch.rm_so;
 		    startmatch.rm_eo -= startmatch.rm_so;
-		    if (regexec(&end_regexp,
+		    if (regexec(tmpcolor->end,
 			    start_line->data + start_col + startmatch.rm_eo,
 			    1, &endmatch,
 			    start_col + startmatch.rm_eo == 0 ? 0 : REG_NOTBOL))
 			/* No end found after this start */
 			break;
 		    start_col++;
-		    if (regexec(&start_regexp,
+		    if (regexec(&tmpcolor->start,
 			    start_line->data + start_col, 1, &startmatch,
 			    REG_NOTBOL))
 			/* No later start on this line. */
@@ -824,8 +818,8 @@
 		 * fileptr and after the start.  Is there an end after
 		 * the start at all?  We don't paint unterminated starts. */
 		end_line = fileptr;
-		while (end_line != NULL && regexec(&end_regexp, end_line->data,
-				1, &endmatch, 0))
+		while (end_line != NULL &&
+			regexec(tmpcolor->end, end_line->data, 1, &endmatch, 0))
 		    end_line = end_line->next;
 
 		/* No end found, or it is too early. */
@@ -850,7 +844,7 @@
   step_two:	/* Second step, we look for starts on this line. */
 		start_col = 0;
 		while (start_col < start + COLS) {
-		    if (regexec(&start_regexp, fileptr->data + start_col, 1,
+		    if (regexec(&tmpcolor->start, fileptr->data + start_col, 1,
 				&startmatch, start_col == 0 ? 0 : REG_NOTBOL)
 			    || start_col + startmatch.rm_so >= start + COLS)
 			/* No more starts on this line. */
@@ -865,7 +859,7 @@
 			x_start = 0;
 			startmatch.rm_so = start;
 		    }
-		    if (!regexec(&end_regexp, fileptr->data + startmatch.rm_eo,
+		    if (!regexec(tmpcolor->end, fileptr->data + startmatch.rm_eo,
 				1, &endmatch,
 				startmatch.rm_eo == 0 ? 0 : REG_NOTBOL)) {
 			/* Translate the end match to be relative to the
@@ -891,7 +885,7 @@
 			/* There is no end on this line.  But we haven't
 			 * yet looked for one on later lines. */
 			end_line = fileptr->next;
-			while (end_line != NULL && regexec(&end_regexp,
+			while (end_line != NULL && regexec(tmpcolor->end,
 				end_line->data, 1, &endmatch, 0))
 			    end_line = end_line->next;
 			if (end_line != NULL) {
@@ -906,12 +900,9 @@
 		    }
 		    start_col = startmatch.rm_so + 1;
 		} /* while start_col < start + COLS */
-
-  skip_step_two:
-		regfree(&end_regexp);
 	    } /* if (tmp_color->end != NULL) */
 
-	    regfree(&start_regexp);
+  skip_step_two:
 	    wattroff(edit, A_BOLD);
 	    wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
 	} /* for tmpcolor in colorstrings */