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
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).
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;
}
#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
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;
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;
#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 */
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++;
/* 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++;
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;
}
}
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++;
}
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
+ newcolor = (colortype *)nmalloc(sizeof(colortype));
+ fgstr = ptr;
+ ptr = parse_next_regex(ptr);
+ if (nregcomp(&newcolor->start, fgstr, 0)) {
+ free(newcolor);
+ cancelled = 1;
} else {
- for (tmpcolor = tmpsyntax->color;
- tmpcolor->next != NULL; tmpcolor = tmpcolor->next);
+ newcolor->fg = fg;
+ newcolor->bg = bg;
+ newcolor->bright = bright;
+ newcolor->next = NULL;
+ newcolor->end = NULL;
+
+ if (tmpsyntax->color == NULL) {
+ tmpsyntax->color = newcolor;
#ifdef DEBUG
- fprintf(stderr, _("Adding new entry for fg %d bg %d\n"), fg, bg);
+ fprintf(stderr, _("Starting a new colorstring 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;
- ptr = parse_next_regex(ptr);
- tmpcolor->start = mallocstrcpy(NULL, tmpcolor->start);
+ } else {
+ for (tmpcolor = tmpsyntax->color; tmpcolor->next != NULL;
+ tmpcolor = tmpcolor->next)
+ ;
#ifdef DEBUG
- fprintf(stderr, _("string val=%s\n"), tmpcolor->start);
+ fprintf(stderr, _("Adding new entry for fg %d bg %d\n"), fg, bg);
#endif
+ tmpcolor->next = newcolor;
+ }
+ }
- if (!expectend)
- tmpcolor->end = NULL;
- else {
+ if (expectend) {
if (ptr == NULL || strncasecmp(ptr, "end=", 4)) {
rcfile_error(_
("\"start=\" requires a corresponding \"end=\""));
}
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;
+ }
}
}
}
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));
* 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. */
* 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;
/* 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;
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. */
* 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. */
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. */
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
/* 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) {
}
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 */