diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/search.c | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/src/search.c b/src/search.c index 7f006883270..f3835ff0743 100644 --- a/src/search.c +++ b/src/search.c | |||
| @@ -592,6 +592,35 @@ search_command (string, bound, noerror, count, direction, RE) | |||
| 592 | return make_number (np); | 592 | return make_number (np); |
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | static int | ||
| 596 | trivial_regexp_p (regexp) | ||
| 597 | Lisp_Object regexp; | ||
| 598 | { | ||
| 599 | int len = XSTRING (regexp)->size; | ||
| 600 | unsigned char *s = XSTRING (regexp)->data; | ||
| 601 | unsigned char c; | ||
| 602 | while (--len >= 0) | ||
| 603 | { | ||
| 604 | switch (*s++) | ||
| 605 | { | ||
| 606 | case '.': case '*': case '+': case '?': case '[': case '^': case '$': | ||
| 607 | return 0; | ||
| 608 | case '\\': | ||
| 609 | if (--len < 0) | ||
| 610 | return 0; | ||
| 611 | switch (*s++) | ||
| 612 | { | ||
| 613 | case '|': case '(': case ')': case '`': case '\'': case 'b': | ||
| 614 | case 'B': case '<': case '>': case 'w': case 'W': case 's': | ||
| 615 | case 'S': case '1': case '2': case '3': case '4': case '5': | ||
| 616 | case '6': case '7': case '8': case '9': | ||
| 617 | return 0; | ||
| 618 | } | ||
| 619 | } | ||
| 620 | } | ||
| 621 | return 1; | ||
| 622 | } | ||
| 623 | |||
| 595 | /* Search for the n'th occurrence of STRING in the current buffer, | 624 | /* Search for the n'th occurrence of STRING in the current buffer, |
| 596 | starting at position POS and stopping at position LIM, | 625 | starting at position POS and stopping at position LIM, |
| 597 | treating PAT as a literal string if RE is false or as | 626 | treating PAT as a literal string if RE is false or as |
| @@ -636,32 +665,10 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt) | |||
| 636 | if (n == 0) | 665 | if (n == 0) |
| 637 | return pos; | 666 | return pos; |
| 638 | 667 | ||
| 639 | if (RE) | 668 | if (RE && !trivial_regexp_p (string)) |
| 640 | compile_pattern (string, &searchbuf, &search_regs, (char *) trt); | ||
| 641 | |||
| 642 | if (RE /* Here we detect whether the */ | ||
| 643 | /* generality of an RE search is */ | ||
| 644 | /* really needed. */ | ||
| 645 | /* first item is "exact match" */ | ||
| 646 | && *(searchbuf.buffer) == (char) RE_EXACTN_VALUE | ||
| 647 | && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */ | ||
| 648 | { | 669 | { |
| 649 | RE = 0; /* can do straight (non RE) search */ | 670 | compile_pattern (string, &searchbuf, &search_regs, (char *) trt); |
| 650 | pat = (base_pat = (unsigned char *) searchbuf.buffer + 2); | ||
| 651 | /* trt already applied */ | ||
| 652 | len = searchbuf.used - 2; | ||
| 653 | } | ||
| 654 | else if (!RE) | ||
| 655 | { | ||
| 656 | pat = (unsigned char *) alloca (len); | ||
| 657 | 671 | ||
| 658 | for (i = len; i--;) /* Copy the pattern; apply trt */ | ||
| 659 | *pat++ = (((int) trt) ? trt [*base_pat++] : *base_pat++); | ||
| 660 | pat -= len; base_pat = pat; | ||
| 661 | } | ||
| 662 | |||
| 663 | if (RE) | ||
| 664 | { | ||
| 665 | immediate_quit = 1; /* Quit immediately if user types ^G, | 672 | immediate_quit = 1; /* Quit immediately if user types ^G, |
| 666 | because letting this function finish | 673 | because letting this function finish |
| 667 | can take too long. */ | 674 | can take too long. */ |
| @@ -693,7 +700,9 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt) | |||
| 693 | /* Don't allow match past current point */ | 700 | /* Don't allow match past current point */ |
| 694 | pos - BEGV); | 701 | pos - BEGV); |
| 695 | if (val == -2) | 702 | if (val == -2) |
| 696 | matcher_overflow (); | 703 | { |
| 704 | matcher_overflow (); | ||
| 705 | } | ||
| 697 | if (val >= 0) | 706 | if (val >= 0) |
| 698 | { | 707 | { |
| 699 | j = BEGV; | 708 | j = BEGV; |
| @@ -721,7 +730,9 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt) | |||
| 721 | pos - BEGV, lim - pos, &search_regs, | 730 | pos - BEGV, lim - pos, &search_regs, |
| 722 | lim - BEGV); | 731 | lim - BEGV); |
| 723 | if (val == -2) | 732 | if (val == -2) |
| 724 | matcher_overflow (); | 733 | { |
| 734 | matcher_overflow (); | ||
| 735 | } | ||
| 725 | if (val >= 0) | 736 | if (val >= 0) |
| 726 | { | 737 | { |
| 727 | j = BEGV; | 738 | j = BEGV; |
| @@ -752,6 +763,24 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt) | |||
| 752 | #else | 763 | #else |
| 753 | BM_tab = (int *) alloca (0400 * sizeof (int)); | 764 | BM_tab = (int *) alloca (0400 * sizeof (int)); |
| 754 | #endif | 765 | #endif |
| 766 | { | ||
| 767 | unsigned char *patbuf = (unsigned char *) alloca (len); | ||
| 768 | pat = patbuf; | ||
| 769 | while (--len >= 0) | ||
| 770 | { | ||
| 771 | /* If we got here and the RE flag is set, it's because we're | ||
| 772 | dealing with a regexp known to be trivial, so the backslash | ||
| 773 | just quotes the next character. */ | ||
| 774 | if (RE && *base_pat == '\\') | ||
| 775 | { | ||
| 776 | len--; | ||
| 777 | base_pat++; | ||
| 778 | } | ||
| 779 | *pat++ = (trt ? trt[*base_pat++] : *base_pat++); | ||
| 780 | } | ||
| 781 | len = pat - patbuf; | ||
| 782 | pat = base_pat = patbuf; | ||
| 783 | } | ||
| 755 | /* The general approach is that we are going to maintain that we know */ | 784 | /* The general approach is that we are going to maintain that we know */ |
| 756 | /* the first (closest to the present position, in whatever direction */ | 785 | /* the first (closest to the present position, in whatever direction */ |
| 757 | /* we're searching) character that could possibly be the last */ | 786 | /* we're searching) character that could possibly be the last */ |