diff options
| author | vapier <vapier@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-04-29 04:21:10 +0000 |
|---|---|---|
| committer | vapier <vapier@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-04-29 04:21:10 +0000 |
| commit | b396a4df03471f7731e2f7b681bbe103a7b702f1 (patch) | |
| tree | 0d8e32e0766a304e4b280e7a340586904123c3d7 /miscutils | |
| parent | 5c543216afed24ab66062c0d193497a2e5de0b96 (diff) | |
| download | busybox-w32-b396a4df03471f7731e2f7b681bbe103a7b702f1.tar.gz busybox-w32-b396a4df03471f7731e2f7b681bbe103a7b702f1.tar.bz2 busybox-w32-b396a4df03471f7731e2f7b681bbe103a7b702f1.zip | |
Rob Sullivan writes: rewrite the regex handling to improve stability
git-svn-id: svn://busybox.net/trunk/busybox@14961 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'miscutils')
| -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 |
