Rob Sullivan writes: rewrite the regex handling to improve stability

This commit is contained in:
Mike Frysinger 2006-04-29 04:21:10 +00:00
parent 12ef09b818
commit f054be12de

View File

@ -104,10 +104,11 @@ static int num_marks;
#ifdef CONFIG_FEATURE_LESS_REGEXP #ifdef CONFIG_FEATURE_LESS_REGEXP
static int match_found; static int match_found;
static int match_lines[100]; static int *match_lines;
static int match_pos; static int match_pos;
static int num_matches; static int num_matches;
static int match_backwards; static int match_backwards;
static regex_t old_pattern;
#endif #endif
/* Needed termios structures */ /* Needed termios structures */
@ -235,14 +236,6 @@ static void data_readlines(void)
add_linenumbers(); add_linenumbers();
} }
/* Turn a percentage into a line number */
static int reverse_percent(int percentage)
{
double linenum = percentage;
linenum = ((linenum / 100) * num_flines) - 1;
return(linenum);
}
#ifdef CONFIG_FEATURE_LESS_FLAGS #ifdef CONFIG_FEATURE_LESS_FLAGS
/* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes /* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes
@ -463,12 +456,11 @@ static void buffer_up(int nlines)
static void buffer_line(int linenum) static void buffer_line(int linenum)
{ {
int i; int i;
past_eof = 0; past_eof = 0;
if (linenum < 1 || linenum > num_flines) { if (linenum < 0 || linenum > num_flines) {
clear_line(); clear_line();
printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum, NORMAL); printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum + 1, NORMAL);
} }
else if (linenum < (num_flines - height - 2)) { else if (linenum < (num_flines - height - 2)) {
for (i = 0; i < (height - 1); i++) { for (i = 0; i < (height - 1); i++) {
@ -476,6 +468,7 @@ static void buffer_line(int linenum)
buffer[i] = bb_xstrdup(flines[linenum + i]); buffer[i] = bb_xstrdup(flines[linenum + i]);
} }
line_pos = linenum; line_pos = linenum;
buffer_print();
} }
else { else {
for (i = 0; i < (height - 1); i++) { for (i = 0; i < (height - 1); i++) {
@ -488,6 +481,7 @@ static void buffer_line(int linenum)
line_pos = linenum; line_pos = linenum;
/* Set past_eof so buffer_down and buffer_up act differently */ /* Set past_eof so buffer_down and buffer_up act differently */
past_eof = 1; past_eof = 1;
buffer_print();
} }
} }
@ -610,46 +604,44 @@ static void colon_process(void)
/* Get a regular expression from the user, and then go through the current /* Get a regular expression from the user, and then go through the current
file line by line, running a processing regex function on each one. */ file line by line, running a processing regex function on each one. */
static char *insert_highlights(char *line, int start, int end) static char *process_regex_on_line(char *line, regex_t *pattern, int action)
{
return bb_xasprintf("%.*s%s%.*s%s%s", start, line, HIGHLIGHT,
end - start, line + start, NORMAL, line + end);
}
static char *process_regex_on_line(char *line, regex_t *pattern)
{ {
/* This function takes the regex and applies it to the line. /* This function takes the regex and applies it to the line.
Each part of the line that matches has the HIGHLIGHT Each part of the line that matches has the HIGHLIGHT
and NORMAL escape sequences placed around it by and NORMAL escape sequences placed around it by
insert_highlights, and then the line is returned. */ insert_highlights if action = 1, or has the escape sequences
removed if action = 0, and then the line is returned. */
int match_status; int match_status;
char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64); char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64);
char sub_line[256]; char *growline = "";
int prev_eo = 0;
regmatch_t match_structs; regmatch_t match_structs;
strcpy(line2, line); line2 = bb_xstrdup(line);
match_found = 0; match_found = 0;
match_status = regexec(pattern, line2, 1, &match_structs, 0); match_status = regexec(pattern, line2, 1, &match_structs, 0);
while (match_status == 0) { while (match_status == 0) {
memset(sub_line, 0, sizeof(sub_line));
if (match_found == 0) if (match_found == 0)
match_found = 1; match_found = 1;
line2 = insert_highlights(line2, match_structs.rm_so + prev_eo, match_structs.rm_eo + prev_eo); if (action) {
if ((size_t)match_structs.rm_eo + 11 + prev_eo < strlen(line2)) growline = bb_xasprintf("%s%.*s%s%.*s%s", growline, match_structs.rm_so, line2, HIGHLIGHT, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so, NORMAL);
strcat(sub_line, line2 + match_structs.rm_eo + 11 + prev_eo); }
else {
prev_eo += match_structs.rm_eo + 11; growline = bb_xasprintf("%s%.*s%.*s", growline, match_structs.rm_so - 4, line2, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so);
match_status = regexec(pattern, sub_line, 1, &match_structs, REG_NOTBOL); }
line2 += match_structs.rm_eo;
match_status = regexec(pattern, line2, 1, &match_structs, REG_NOTBOL);
} }
return line2; growline = bb_xasprintf("%s%s", growline, line2);
return (match_found ? growline : line);
free(growline);
free(line2);
} }
static void goto_match(int match) static void goto_match(int match)
@ -665,11 +657,10 @@ static void goto_match(int match)
static void regex_process(void) static void regex_process(void)
{ {
char uncomp_regex[100]; char uncomp_regex[100];
char current_line[256]; char *current_line;
int i; int i;
int j = 0; int j = 0;
regex_t pattern; regex_t pattern;
/* Get the uncompiled regular expression from the user */ /* Get the uncompiled regular expression from the user */
clear_line(); clear_line();
putchar((match_backwards) ? '?' : '/'); putchar((match_backwards) ? '?' : '/');
@ -677,32 +668,43 @@ static void regex_process(void)
fgets(uncomp_regex, sizeof(uncomp_regex), inp); fgets(uncomp_regex, sizeof(uncomp_regex), inp);
if (strlen(uncomp_regex) == 1) { if (strlen(uncomp_regex) == 1) {
goto_match(match_backwards ? match_pos - 1 : match_pos + 1); if (num_matches)
buffer_print(); goto_match(match_backwards ? match_pos - 1 : match_pos + 1);
else
buffer_print();
return; return;
} }
uncomp_regex[strlen(uncomp_regex) - 1] = '\0'; uncomp_regex[strlen(uncomp_regex) - 1] = '\0';
/* Compile the regex and check for errors */ /* Compile the regex and check for errors */
xregcomp(&pattern, uncomp_regex, 0); xregcomp(&pattern, uncomp_regex, 0);
if (num_matches) {
/* Get rid of all the highlights we added previously */
for (i = 0; i <= num_flines; i++) {
current_line = process_regex_on_line(flines[i], &old_pattern, 0);
flines[i] = bb_xstrdup(current_line);
}
}
old_pattern = pattern;
/* Reset variables */ /* Reset variables */
match_lines = xrealloc(match_lines, sizeof(int));
match_lines[0] = -1; match_lines[0] = -1;
match_pos = 0; match_pos = 0;
num_matches = 0; num_matches = 0;
match_found = 0; match_found = 0;
/* Run the regex on each line of the current file here */ /* Run the regex on each line of the current file here */
for (i = 0; i <= num_flines; i++) { for (i = 0; i <= num_flines; i++) {
strcpy(current_line, process_regex_on_line(flines[i], &pattern)); current_line = process_regex_on_line(flines[i], &pattern, 1);
flines[i] = bb_xstrdup(current_line); flines[i] = bb_xstrdup(current_line);
if (match_found) { if (match_found) {
match_lines = xrealloc(match_lines, (j + 1) * sizeof(int));
match_lines[j] = i; match_lines[j] = i;
j++; j++;
} }
} }
num_matches = j; num_matches = j;
if ((match_lines[0] != -1) && (num_flines > height - 2)) { if ((match_lines[0] != -1) && (num_flines > height - 2)) {
if (match_backwards) { if (match_backwards) {
@ -764,7 +766,7 @@ static void number_process(int first_digit)
buffer_line(num - 1); buffer_line(num - 1);
break; break;
case 'p': case '%': case 'p': case '%':
buffer_line(reverse_percent(num)); buffer_line(((num / 100) * num_flines) - 1);
break; break;
#ifdef CONFIG_FEATURE_LESS_REGEXP #ifdef CONFIG_FEATURE_LESS_REGEXP
case 'n': case 'n':
@ -852,7 +854,6 @@ static void full_repaint(void)
data_readlines(); data_readlines();
buffer_init(); buffer_init();
buffer_line(temp_line_pos); buffer_line(temp_line_pos);
buffer_print();
} }
@ -866,7 +867,7 @@ static void save_input_to_file(void)
printf("Log file: "); printf("Log file: ");
fgets(current_line, 256, inp); fgets(current_line, 256, inp);
current_line[strlen(current_line) - 1] = '\0'; current_line[strlen(current_line) - 1] = '\0';
if (strlen(current_line)) { if (strlen(current_line) > 1) {
fp = bb_xfopen(current_line, "w"); fp = bb_xfopen(current_line, "w");
for (i = 0; i < num_flines; i++) for (i = 0; i < num_flines; i++)
fprintf(fp, "%s", flines[i]); fprintf(fp, "%s", flines[i]);
@ -973,7 +974,6 @@ static void match_right_bracket(char bracket)
printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL);
buffer_line(bracket_line - height + 2); buffer_line(bracket_line - height + 2);
buffer_print();
} }
} }
@ -1001,7 +1001,6 @@ static void match_left_bracket(char bracket)
printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL);
buffer_line(bracket_line); buffer_line(bracket_line);
buffer_print();
} }
} }
@ -1035,12 +1034,10 @@ static void keypress_process(int keypress)
buffer_print(); buffer_print();
break; break;
case 'g': case 'p': case '<': case '%': case 'g': case 'p': case '<': case '%':
buffer_up(num_flines + 1); buffer_line(0);
buffer_print();
break; break;
case 'G': case '>': case 'G': case '>':
buffer_down(num_flines + 1); buffer_line(num_flines - height + 2);
buffer_print();
break; break;
case 'q': case 'Q': case 'q': case 'Q':
tless_exit(0); tless_exit(0);
@ -1078,20 +1075,16 @@ static void keypress_process(int keypress)
case '/': case '/':
match_backwards = 0; match_backwards = 0;
regex_process(); regex_process();
buffer_print();
break; break;
case 'n': case 'n':
goto_match(match_pos + 1); goto_match(match_pos + 1);
buffer_print();
break; break;
case 'N': case 'N':
goto_match(match_pos - 1); goto_match(match_pos - 1);
buffer_print();
break; break;
case '?': case '?':
match_backwards = 1; match_backwards = 1;
regex_process(); regex_process();
buffer_print();
break; break;
#endif #endif
#ifdef CONFIG_FEATURE_LESS_FLAGCS #ifdef CONFIG_FEATURE_LESS_FLAGCS