diff options
author | Mike Frysinger <vapier@gentoo.org> | 2006-04-29 04:21:10 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2006-04-29 04:21:10 +0000 |
commit | f054be12de5b9121134d2f7ec790bd8853f9630c (patch) | |
tree | 0d8e32e0766a304e4b280e7a340586904123c3d7 /miscutils/less.c | |
parent | 12ef09b81829956d0c4f19fb45bd07cfb131235b (diff) | |
download | busybox-w32-f054be12de5b9121134d2f7ec790bd8853f9630c.tar.gz busybox-w32-f054be12de5b9121134d2f7ec790bd8853f9630c.tar.bz2 busybox-w32-f054be12de5b9121134d2f7ec790bd8853f9630c.zip |
Rob Sullivan writes: rewrite the regex handling to improve stability
Diffstat (limited to 'miscutils/less.c')
-rw-r--r-- | miscutils/less.c | 109 |
1 files changed, 51 insertions, 58 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index eee960821..84e4b612d 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -104,10 +104,11 @@ static int num_marks; | |||
104 | 104 | ||
105 | #ifdef CONFIG_FEATURE_LESS_REGEXP | 105 | #ifdef CONFIG_FEATURE_LESS_REGEXP |
106 | static int match_found; | 106 | static int match_found; |
107 | static int match_lines[100]; | 107 | static int *match_lines; |
108 | static int match_pos; | 108 | static int match_pos; |
109 | static int num_matches; | 109 | static int num_matches; |
110 | static int match_backwards; | 110 | static int match_backwards; |
111 | static regex_t old_pattern; | ||
111 | #endif | 112 | #endif |
112 | 113 | ||
113 | /* Needed termios structures */ | 114 | /* Needed termios structures */ |
@@ -235,14 +236,6 @@ static void data_readlines(void) | |||
235 | add_linenumbers(); | 236 | add_linenumbers(); |
236 | } | 237 | } |
237 | 238 | ||
238 | /* Turn a percentage into a line number */ | ||
239 | static int reverse_percent(int percentage) | ||
240 | { | ||
241 | double linenum = percentage; | ||
242 | linenum = ((linenum / 100) * num_flines) - 1; | ||
243 | return(linenum); | ||
244 | } | ||
245 | |||
246 | #ifdef CONFIG_FEATURE_LESS_FLAGS | 239 | #ifdef CONFIG_FEATURE_LESS_FLAGS |
247 | 240 | ||
248 | /* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes | 241 | /* 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) | |||
463 | static void buffer_line(int linenum) | 456 | static void buffer_line(int linenum) |
464 | { | 457 | { |
465 | int i; | 458 | int i; |
466 | |||
467 | past_eof = 0; | 459 | past_eof = 0; |
468 | 460 | ||
469 | if (linenum < 1 || linenum > num_flines) { | 461 | if (linenum < 0 || linenum > num_flines) { |
470 | clear_line(); | 462 | clear_line(); |
471 | printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum, NORMAL); | 463 | printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum + 1, NORMAL); |
472 | } | 464 | } |
473 | else if (linenum < (num_flines - height - 2)) { | 465 | else if (linenum < (num_flines - height - 2)) { |
474 | for (i = 0; i < (height - 1); i++) { | 466 | for (i = 0; i < (height - 1); i++) { |
@@ -476,6 +468,7 @@ static void buffer_line(int linenum) | |||
476 | buffer[i] = bb_xstrdup(flines[linenum + i]); | 468 | buffer[i] = bb_xstrdup(flines[linenum + i]); |
477 | } | 469 | } |
478 | line_pos = linenum; | 470 | line_pos = linenum; |
471 | buffer_print(); | ||
479 | } | 472 | } |
480 | else { | 473 | else { |
481 | for (i = 0; i < (height - 1); i++) { | 474 | for (i = 0; i < (height - 1); i++) { |
@@ -488,6 +481,7 @@ static void buffer_line(int linenum) | |||
488 | line_pos = linenum; | 481 | line_pos = linenum; |
489 | /* Set past_eof so buffer_down and buffer_up act differently */ | 482 | /* Set past_eof so buffer_down and buffer_up act differently */ |
490 | past_eof = 1; | 483 | past_eof = 1; |
484 | buffer_print(); | ||
491 | } | 485 | } |
492 | } | 486 | } |
493 | 487 | ||
@@ -610,46 +604,44 @@ static void colon_process(void) | |||
610 | /* Get a regular expression from the user, and then go through the current | 604 | /* Get a regular expression from the user, and then go through the current |
611 | file line by line, running a processing regex function on each one. */ | 605 | file line by line, running a processing regex function on each one. */ |
612 | 606 | ||
613 | static char *insert_highlights(char *line, int start, int end) | 607 | static char *process_regex_on_line(char *line, regex_t *pattern, int action) |
614 | { | ||
615 | return bb_xasprintf("%.*s%s%.*s%s%s", start, line, HIGHLIGHT, | ||
616 | end - start, line + start, NORMAL, line + end); | ||
617 | } | ||
618 | |||
619 | static char *process_regex_on_line(char *line, regex_t *pattern) | ||
620 | { | 608 | { |
621 | /* This function takes the regex and applies it to the line. | 609 | /* This function takes the regex and applies it to the line. |
622 | Each part of the line that matches has the HIGHLIGHT | 610 | Each part of the line that matches has the HIGHLIGHT |
623 | and NORMAL escape sequences placed around it by | 611 | and NORMAL escape sequences placed around it by |
624 | insert_highlights, and then the line is returned. */ | 612 | insert_highlights if action = 1, or has the escape sequences |
625 | 613 | removed if action = 0, and then the line is returned. */ | |
626 | int match_status; | 614 | int match_status; |
627 | char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64); | 615 | char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64); |
628 | char sub_line[256]; | 616 | char *growline = ""; |
629 | int prev_eo = 0; | ||
630 | regmatch_t match_structs; | 617 | regmatch_t match_structs; |
631 | 618 | ||
632 | strcpy(line2, line); | 619 | line2 = bb_xstrdup(line); |
633 | 620 | ||
634 | match_found = 0; | 621 | match_found = 0; |
635 | match_status = regexec(pattern, line2, 1, &match_structs, 0); | 622 | match_status = regexec(pattern, line2, 1, &match_structs, 0); |
636 | 623 | ||
637 | while (match_status == 0) { | 624 | while (match_status == 0) { |
638 | |||
639 | memset(sub_line, 0, sizeof(sub_line)); | ||
640 | |||
641 | if (match_found == 0) | 625 | if (match_found == 0) |
642 | match_found = 1; | 626 | match_found = 1; |
643 | 627 | ||
644 | line2 = insert_highlights(line2, match_structs.rm_so + prev_eo, match_structs.rm_eo + prev_eo); | 628 | if (action) { |
645 | if ((size_t)match_structs.rm_eo + 11 + prev_eo < strlen(line2)) | 629 | 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); |
646 | strcat(sub_line, line2 + match_structs.rm_eo + 11 + prev_eo); | 630 | } |
647 | 631 | else { | |
648 | prev_eo += match_structs.rm_eo + 11; | 632 | 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); |
649 | match_status = regexec(pattern, sub_line, 1, &match_structs, REG_NOTBOL); | 633 | } |
634 | |||
635 | line2 += match_structs.rm_eo; | ||
636 | match_status = regexec(pattern, line2, 1, &match_structs, REG_NOTBOL); | ||
650 | } | 637 | } |
651 | 638 | ||
652 | return line2; | 639 | growline = bb_xasprintf("%s%s", growline, line2); |
640 | |||
641 | return (match_found ? growline : line); | ||
642 | |||
643 | free(growline); | ||
644 | free(line2); | ||
653 | } | 645 | } |
654 | 646 | ||
655 | static void goto_match(int match) | 647 | static void goto_match(int match) |
@@ -665,11 +657,10 @@ static void goto_match(int match) | |||
665 | static void regex_process(void) | 657 | static void regex_process(void) |
666 | { | 658 | { |
667 | char uncomp_regex[100]; | 659 | char uncomp_regex[100]; |
668 | char current_line[256]; | 660 | char *current_line; |
669 | int i; | 661 | int i; |
670 | int j = 0; | 662 | int j = 0; |
671 | regex_t pattern; | 663 | regex_t pattern; |
672 | |||
673 | /* Get the uncompiled regular expression from the user */ | 664 | /* Get the uncompiled regular expression from the user */ |
674 | clear_line(); | 665 | clear_line(); |
675 | putchar((match_backwards) ? '?' : '/'); | 666 | putchar((match_backwards) ? '?' : '/'); |
@@ -677,32 +668,43 @@ static void regex_process(void) | |||
677 | fgets(uncomp_regex, sizeof(uncomp_regex), inp); | 668 | fgets(uncomp_regex, sizeof(uncomp_regex), inp); |
678 | 669 | ||
679 | if (strlen(uncomp_regex) == 1) { | 670 | if (strlen(uncomp_regex) == 1) { |
680 | goto_match(match_backwards ? match_pos - 1 : match_pos + 1); | 671 | if (num_matches) |
681 | buffer_print(); | 672 | goto_match(match_backwards ? match_pos - 1 : match_pos + 1); |
673 | else | ||
674 | buffer_print(); | ||
682 | return; | 675 | return; |
683 | } | 676 | } |
684 | |||
685 | uncomp_regex[strlen(uncomp_regex) - 1] = '\0'; | 677 | uncomp_regex[strlen(uncomp_regex) - 1] = '\0'; |
686 | 678 | ||
687 | /* Compile the regex and check for errors */ | 679 | /* Compile the regex and check for errors */ |
688 | xregcomp(&pattern, uncomp_regex, 0); | 680 | xregcomp(&pattern, uncomp_regex, 0); |
689 | 681 | ||
682 | if (num_matches) { | ||
683 | /* Get rid of all the highlights we added previously */ | ||
684 | for (i = 0; i <= num_flines; i++) { | ||
685 | current_line = process_regex_on_line(flines[i], &old_pattern, 0); | ||
686 | flines[i] = bb_xstrdup(current_line); | ||
687 | } | ||
688 | } | ||
689 | old_pattern = pattern; | ||
690 | |||
690 | /* Reset variables */ | 691 | /* Reset variables */ |
692 | match_lines = xrealloc(match_lines, sizeof(int)); | ||
691 | match_lines[0] = -1; | 693 | match_lines[0] = -1; |
692 | match_pos = 0; | 694 | match_pos = 0; |
693 | num_matches = 0; | 695 | num_matches = 0; |
694 | match_found = 0; | 696 | match_found = 0; |
695 | |||
696 | /* Run the regex on each line of the current file here */ | 697 | /* Run the regex on each line of the current file here */ |
697 | for (i = 0; i <= num_flines; i++) { | 698 | for (i = 0; i <= num_flines; i++) { |
698 | strcpy(current_line, process_regex_on_line(flines[i], &pattern)); | 699 | current_line = process_regex_on_line(flines[i], &pattern, 1); |
699 | flines[i] = bb_xstrdup(current_line); | 700 | flines[i] = bb_xstrdup(current_line); |
700 | if (match_found) { | 701 | if (match_found) { |
702 | match_lines = xrealloc(match_lines, (j + 1) * sizeof(int)); | ||
701 | match_lines[j] = i; | 703 | match_lines[j] = i; |
702 | j++; | 704 | j++; |
703 | } | 705 | } |
704 | } | 706 | } |
705 | 707 | ||
706 | num_matches = j; | 708 | num_matches = j; |
707 | if ((match_lines[0] != -1) && (num_flines > height - 2)) { | 709 | if ((match_lines[0] != -1) && (num_flines > height - 2)) { |
708 | if (match_backwards) { | 710 | if (match_backwards) { |
@@ -764,7 +766,7 @@ static void number_process(int first_digit) | |||
764 | buffer_line(num - 1); | 766 | buffer_line(num - 1); |
765 | break; | 767 | break; |
766 | case 'p': case '%': | 768 | case 'p': case '%': |
767 | buffer_line(reverse_percent(num)); | 769 | buffer_line(((num / 100) * num_flines) - 1); |
768 | break; | 770 | break; |
769 | #ifdef CONFIG_FEATURE_LESS_REGEXP | 771 | #ifdef CONFIG_FEATURE_LESS_REGEXP |
770 | case 'n': | 772 | case 'n': |
@@ -852,7 +854,6 @@ static void full_repaint(void) | |||
852 | data_readlines(); | 854 | data_readlines(); |
853 | buffer_init(); | 855 | buffer_init(); |
854 | buffer_line(temp_line_pos); | 856 | buffer_line(temp_line_pos); |
855 | buffer_print(); | ||
856 | } | 857 | } |
857 | 858 | ||
858 | 859 | ||
@@ -866,7 +867,7 @@ static void save_input_to_file(void) | |||
866 | printf("Log file: "); | 867 | printf("Log file: "); |
867 | fgets(current_line, 256, inp); | 868 | fgets(current_line, 256, inp); |
868 | current_line[strlen(current_line) - 1] = '\0'; | 869 | current_line[strlen(current_line) - 1] = '\0'; |
869 | if (strlen(current_line)) { | 870 | if (strlen(current_line) > 1) { |
870 | fp = bb_xfopen(current_line, "w"); | 871 | fp = bb_xfopen(current_line, "w"); |
871 | for (i = 0; i < num_flines; i++) | 872 | for (i = 0; i < num_flines; i++) |
872 | fprintf(fp, "%s", flines[i]); | 873 | fprintf(fp, "%s", flines[i]); |
@@ -973,7 +974,6 @@ static void match_right_bracket(char bracket) | |||
973 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); | 974 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); |
974 | 975 | ||
975 | buffer_line(bracket_line - height + 2); | 976 | buffer_line(bracket_line - height + 2); |
976 | buffer_print(); | ||
977 | } | 977 | } |
978 | } | 978 | } |
979 | 979 | ||
@@ -1001,7 +1001,6 @@ static void match_left_bracket(char bracket) | |||
1001 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); | 1001 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); |
1002 | 1002 | ||
1003 | buffer_line(bracket_line); | 1003 | buffer_line(bracket_line); |
1004 | buffer_print(); | ||
1005 | } | 1004 | } |
1006 | } | 1005 | } |
1007 | 1006 | ||
@@ -1035,12 +1034,10 @@ static void keypress_process(int keypress) | |||
1035 | buffer_print(); | 1034 | buffer_print(); |
1036 | break; | 1035 | break; |
1037 | case 'g': case 'p': case '<': case '%': | 1036 | case 'g': case 'p': case '<': case '%': |
1038 | buffer_up(num_flines + 1); | 1037 | buffer_line(0); |
1039 | buffer_print(); | ||
1040 | break; | 1038 | break; |
1041 | case 'G': case '>': | 1039 | case 'G': case '>': |
1042 | buffer_down(num_flines + 1); | 1040 | buffer_line(num_flines - height + 2); |
1043 | buffer_print(); | ||
1044 | break; | 1041 | break; |
1045 | case 'q': case 'Q': | 1042 | case 'q': case 'Q': |
1046 | tless_exit(0); | 1043 | tless_exit(0); |
@@ -1078,20 +1075,16 @@ static void keypress_process(int keypress) | |||
1078 | case '/': | 1075 | case '/': |
1079 | match_backwards = 0; | 1076 | match_backwards = 0; |
1080 | regex_process(); | 1077 | regex_process(); |
1081 | buffer_print(); | ||
1082 | break; | 1078 | break; |
1083 | case 'n': | 1079 | case 'n': |
1084 | goto_match(match_pos + 1); | 1080 | goto_match(match_pos + 1); |
1085 | buffer_print(); | ||
1086 | break; | 1081 | break; |
1087 | case 'N': | 1082 | case 'N': |
1088 | goto_match(match_pos - 1); | 1083 | goto_match(match_pos - 1); |
1089 | buffer_print(); | ||
1090 | break; | 1084 | break; |
1091 | case '?': | 1085 | case '?': |
1092 | match_backwards = 1; | 1086 | match_backwards = 1; |
1093 | regex_process(); | 1087 | regex_process(); |
1094 | buffer_print(); | ||
1095 | break; | 1088 | break; |
1096 | #endif | 1089 | #endif |
1097 | #ifdef CONFIG_FEATURE_LESS_FLAGCS | 1090 | #ifdef CONFIG_FEATURE_LESS_FLAGCS |