aboutsummaryrefslogtreecommitdiff
path: root/miscutils/less.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2006-04-29 04:21:10 +0000
committerMike Frysinger <vapier@gentoo.org>2006-04-29 04:21:10 +0000
commitf054be12de5b9121134d2f7ec790bd8853f9630c (patch)
tree0d8e32e0766a304e4b280e7a340586904123c3d7 /miscutils/less.c
parent12ef09b81829956d0c4f19fb45bd07cfb131235b (diff)
downloadbusybox-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.c109
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
106static int match_found; 106static int match_found;
107static int match_lines[100]; 107static int *match_lines;
108static int match_pos; 108static int match_pos;
109static int num_matches; 109static int num_matches;
110static int match_backwards; 110static int match_backwards;
111static 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 */
239static 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)
463static void buffer_line(int linenum) 456static 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
613static char *insert_highlights(char *line, int start, int end) 607static 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
619static 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
655static void goto_match(int match) 647static void goto_match(int match)
@@ -665,11 +657,10 @@ static void goto_match(int match)
665static void regex_process(void) 657static 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