mirror of
https://github.com/sheumann/hush.git
synced 2025-01-03 00:31:16 +00:00
Rob Sullivan writes: rewrite the regex handling to improve stability
This commit is contained in:
parent
12ef09b818
commit
f054be12de
109
miscutils/less.c
109
miscutils/less.c
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user