1 /* String search routines for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #include <sys/types.h>
29 #define max(a, b) ((a) > (b) ? (a) : (b))
30 #define min(a, b) ((a) < (b) ? (a) : (b))
32 /* We compile regexps into this buffer and then use it for searching. */
34 struct re_pattern_buffer searchbuf
;
36 char search_fastmap
[0400];
38 /* Last regexp we compiled */
40 Lisp_Object last_regexp
;
42 /* Every call to re_match, etc., must pass &search_regs as the regs argument
43 unless you can show it is unnecessary (i.e., if re_match is certainly going
44 to be called again before region-around-match can be called). */
46 static struct re_registers search_regs
;
48 /* Nonzero if search_regs are indices in a string; 0 if in a buffer. */
50 static int search_regs_from_string
;
52 /* error condition signalled when regexp compile_pattern fails */
54 Lisp_Object Qinvalid_regexp
;
59 error ("Stack overflow in regexp matcher");
68 /* Compile a regexp and signal a Lisp error if anything goes wrong. */
70 compile_pattern (pattern
, bufp
, translate
)
72 struct re_pattern_buffer
*bufp
;
78 if (EQ (pattern
, last_regexp
)
79 && translate
== bufp
->translate
)
82 bufp
->translate
= translate
;
83 val
= re_compile_pattern ((char *) XSTRING (pattern
)->data
,
84 XSTRING (pattern
)->size
,
88 dummy
= build_string (val
);
90 Fsignal (Qinvalid_regexp
, Fcons (dummy
, Qnil
));
92 last_regexp
= pattern
;
96 /* Error condition used for failing searches */
97 Lisp_Object Qsearch_failed
;
103 Fsignal (Qsearch_failed
, Fcons (arg
, Qnil
));
107 DEFUN ("looking-at", Flooking_at
, Slooking_at
, 1, 1, 0,
108 "Return t if text after point matches regular expression PAT.")
113 unsigned char *p1
, *p2
;
117 CHECK_STRING (string
, 0);
118 compile_pattern (string
, &searchbuf
,
119 !NILP (current_buffer
->case_fold_search
) ? DOWNCASE_TABLE
: 0);
122 QUIT
; /* Do a pending quit right away, to avoid paradoxical behavior */
124 /* Get pointers and sizes of the two strings
125 that make up the visible portion of the buffer. */
143 i
= re_match_2 (&searchbuf
, (char *) p1
, s1
, (char *) p2
, s2
,
144 point
- BEGV
, &search_regs
,
149 val
= (0 <= i
? Qt
: Qnil
);
150 for (i
= 0; i
< RE_NREGS
; i
++)
151 if (search_regs
.start
[i
] >= 0)
153 search_regs
.start
[i
] += BEGV
;
154 search_regs
.end
[i
] += BEGV
;
156 search_regs_from_string
= 0;
161 DEFUN ("string-match", Fstring_match
, Sstring_match
, 2, 3, 0,
162 "Return index of start of first match for REGEXP in STRING, or nil.\n\
163 If third arg START is non-nil, start search at that index in STRING.\n\
164 For index of first char beyond the match, do (match-end 0).\n\
165 `match-end' and `match-beginning' also give indices of substrings\n\
166 matched by parenthesis constructs in the pattern.")
167 (regexp
, string
, start
)
168 Lisp_Object regexp
, string
, start
;
173 CHECK_STRING (regexp
, 0);
174 CHECK_STRING (string
, 1);
180 int len
= XSTRING (string
)->size
;
182 CHECK_NUMBER (start
, 2);
184 if (s
< 0 && -s
<= len
)
186 else if (0 > s
|| s
> len
)
187 args_out_of_range (string
, start
);
190 compile_pattern (regexp
, &searchbuf
,
191 !NILP (current_buffer
->case_fold_search
) ? DOWNCASE_TABLE
: 0);
193 val
= re_search (&searchbuf
, (char *) XSTRING (string
)->data
,
194 XSTRING (string
)->size
, s
, XSTRING (string
)->size
- s
,
197 search_regs_from_string
= 1;
200 if (val
< 0) return Qnil
;
201 return make_number (val
);
204 scan_buffer (target
, pos
, cnt
, shortage
)
206 register int cnt
, target
;
208 int lim
= ((cnt
> 0) ? ZV
- 1 : BEGV
);
209 int direction
= ((cnt
> 0) ? 1 : -1);
212 register unsigned char *cursor
, *limit
;
220 while (pos
!= lim
+ 1)
222 lim0
= BUFFER_CEILING_OF (pos
);
223 lim0
= min (lim
, lim0
);
224 limit
= &FETCH_CHAR (lim0
) + 1;
225 base
= (cursor
= &FETCH_CHAR (pos
));
228 while (*cursor
!= target
&& ++cursor
!= limit
)
235 return (pos
+ cursor
- base
+ 1);
238 if (++cursor
== limit
)
244 pos
+= cursor
- base
;
248 pos
--; /* first character we scan */
249 while (pos
> lim
- 1)
250 { /* we WILL scan under pos */
251 lim0
= BUFFER_FLOOR_OF (pos
);
252 lim0
= max (lim
, lim0
);
253 limit
= &FETCH_CHAR (lim0
) - 1;
254 base
= (cursor
= &FETCH_CHAR (pos
));
258 while (--cursor
!= limit
&& *cursor
!= target
)
265 return (pos
+ cursor
- base
+ 1);
271 pos
+= cursor
- base
;
276 *shortage
= cnt
* direction
;
277 return (pos
+ ((direction
== 1 ? 0 : 1)));
281 find_next_newline (from
, cnt
)
282 register int from
, cnt
;
284 return (scan_buffer ('\n', from
, cnt
, (int *) 0));
287 DEFUN ("skip-chars-forward", Fskip_chars_forward
, Sskip_chars_forward
, 1, 2, 0,
288 "Move point forward, stopping before a char not in CHARS, or at position LIM.\n\
289 CHARS is like the inside of a `[...]' in a regular expression\n\
290 except that `]' is never special and `\\' quotes `^', `-' or `\\'.\n\
291 Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\
292 With arg \"^a-zA-Z\", skips nonletters stopping before first letter.")
294 Lisp_Object string
, lim
;
296 skip_chars (1, string
, lim
);
300 DEFUN ("skip-chars-backward", Fskip_chars_backward
, Sskip_chars_backward
, 1, 2, 0,
301 "Move point backward, stopping after a char not in CHARS, or at position LIM.\n\
302 See `skip-chars-forward' for details.")
304 Lisp_Object string
, lim
;
306 skip_chars (0, string
, lim
);
310 skip_chars (forwardp
, string
, lim
)
312 Lisp_Object string
, lim
;
314 register unsigned char *p
, *pend
;
315 register unsigned char c
;
316 unsigned char fastmap
[0400];
320 CHECK_STRING (string
, 0);
323 XSET (lim
, Lisp_Int
, forwardp
? ZV
: BEGV
);
325 CHECK_NUMBER_COERCE_MARKER (lim
, 1);
327 #if 0 /* This breaks some things... jla. */
328 /* In any case, don't allow scan outside bounds of buffer. */
329 if (XFASTINT (lim
) > ZV
)
331 if (XFASTINT (lim
) < BEGV
)
332 XFASTINT (lim
) = BEGV
;
335 p
= XSTRING (string
)->data
;
336 pend
= p
+ XSTRING (string
)->size
;
337 bzero (fastmap
, sizeof fastmap
);
339 if (p
!= pend
&& *p
== '^')
344 /* Find the characters specified and set their elements of fastmap. */
351 if (p
== pend
) break;
354 if (p
!= pend
&& *p
== '-')
357 if (p
== pend
) break;
369 /* If ^ was the first character, complement the fastmap. */
372 for (i
= 0; i
< sizeof fastmap
; i
++)
378 while (point
< XINT (lim
) && fastmap
[FETCH_CHAR (point
)])
383 while (point
> XINT (lim
) && fastmap
[FETCH_CHAR (point
- 1)])
389 /* Subroutines of Lisp buffer search functions. */
392 search_command (string
, bound
, noerror
, count
, direction
, RE
)
393 Lisp_Object string
, bound
, noerror
, count
;
403 CHECK_NUMBER (count
, 3);
407 CHECK_STRING (string
, 0);
409 lim
= n
> 0 ? ZV
: BEGV
;
412 CHECK_NUMBER_COERCE_MARKER (bound
, 1);
414 if (n
> 0 ? lim
< point
: lim
> point
)
415 error ("Invalid search bound (wrong side of point)");
422 np
= search_buffer (string
, point
, lim
, n
, RE
,
423 (!NILP (current_buffer
->case_fold_search
)
424 ? XSTRING (current_buffer
->case_canon_table
)->data
: 0),
425 (!NILP (current_buffer
->case_fold_search
)
426 ? XSTRING (current_buffer
->case_eqv_table
)->data
: 0));
430 return signal_failure (string
);
431 if (!EQ (noerror
, Qt
))
433 if (lim
< BEGV
|| lim
> ZV
)
440 if (np
< BEGV
|| np
> ZV
)
445 return make_number (np
);
448 /* search for the n'th occurrence of STRING in the current buffer,
449 starting at position POS and stopping at position LIM,
450 treating PAT as a literal string if RE is false or as
451 a regular expression if RE is true.
453 If N is positive, searching is forward and LIM must be greater than POS.
454 If N is negative, searching is backward and LIM must be less than POS.
456 Returns -x if only N-x occurrences found (x > 0),
457 or else the position at the beginning of the Nth occurrence
458 (if searching backward) or the end (if searching forward). */
460 search_buffer (string
, pos
, lim
, n
, RE
, trt
, inverse_trt
)
466 register unsigned char *trt
;
467 register unsigned char *inverse_trt
;
469 int len
= XSTRING (string
)->size
;
470 unsigned char *base_pat
= XSTRING (string
)->data
;
471 register int *BM_tab
;
473 register int direction
= ((n
> 0) ? 1 : -1);
475 int infinity
, limit
, k
, stride_for_teases
;
476 register unsigned char *pat
, *cursor
, *p_limit
;
478 unsigned char *p1
, *p2
;
481 /* Null string is found at starting position. */
486 compile_pattern (string
, &searchbuf
, (char *) trt
);
488 if (RE
/* Here we detect whether the */
489 /* generality of an RE search is */
491 /* first item is "exact match" */
492 && *(searchbuf
.buffer
) == RE_EXACTN_VALUE
493 && searchbuf
.buffer
[1] + 2 == searchbuf
.used
) /*first is ONLY item */
495 RE
= 0; /* can do straight (non RE) search */
496 pat
= (base_pat
= (unsigned char *) searchbuf
.buffer
+ 2);
497 /* trt already applied */
498 len
= searchbuf
.used
- 2;
502 pat
= (unsigned char *) alloca (len
);
504 for (i
= len
; i
--;) /* Copy the pattern; apply trt */
505 *pat
++ = (((int) trt
) ? trt
[*base_pat
++] : *base_pat
++);
506 pat
-= len
; base_pat
= pat
;
511 immediate_quit
= 1; /* Quit immediately if user types ^G,
512 because letting this function finish
513 can take too long. */
514 QUIT
; /* Do a pending quit right away,
515 to avoid paradoxical behavior */
516 /* Get pointers and sizes of the two strings
517 that make up the visible portion of the buffer. */
536 int val
= re_search_2 (&searchbuf
, (char *) p1
, s1
, (char *) p2
, s2
,
537 pos
- BEGV
, lim
- pos
, &search_regs
,
538 /* Don't allow match past current point */
545 for (i
= 0; i
< RE_NREGS
; i
++)
546 if (search_regs
.start
[i
] >= 0)
548 search_regs
.start
[i
] += j
;
549 search_regs
.end
[i
] += j
;
551 search_regs_from_string
= 0;
552 /* Set pos to the new position. */
553 pos
= search_regs
.start
[0];
564 int val
= re_search_2 (&searchbuf
, (char *) p1
, s1
, (char *) p2
, s2
,
565 pos
- BEGV
, lim
- pos
, &search_regs
,
572 for (i
= 0; i
< RE_NREGS
; i
++)
573 if (search_regs
.start
[i
] >= 0)
575 search_regs
.start
[i
] += j
;
576 search_regs
.end
[i
] += j
;
578 search_regs_from_string
= 0;
579 pos
= search_regs
.end
[0];
591 else /* non-RE case */
594 int BM_tab_space
[0400];
595 BM_tab
= &BM_tab_space
[0];
597 BM_tab
= (int *) alloca (0400 * sizeof (int));
599 /* The general approach is that we are going to maintain that we know */
600 /* the first (closest to the present position, in whatever direction */
601 /* we're searching) character that could possibly be the last */
602 /* (furthest from present position) character of a valid match. We */
603 /* advance the state of our knowledge by looking at that character */
604 /* and seeing whether it indeed matches the last character of the */
605 /* pattern. If it does, we take a closer look. If it does not, we */
606 /* move our pointer (to putative last characters) as far as is */
607 /* logically possible. This amount of movement, which I call a */
608 /* stride, will be the length of the pattern if the actual character */
609 /* appears nowhere in the pattern, otherwise it will be the distance */
610 /* from the last occurrence of that character to the end of the */
612 /* As a coding trick, an enormous stride is coded into the table for */
613 /* characters that match the last character. This allows use of only */
614 /* a single test, a test for having gone past the end of the */
615 /* permissible match region, to test for both possible matches (when */
616 /* the stride goes past the end immediately) and failure to */
617 /* match (where you get nudged past the end one stride at a time). */
619 /* Here we make a "mickey mouse" BM table. The stride of the search */
620 /* is determined only by the last character of the putative match. */
621 /* If that character does not match, we will stride the proper */
622 /* distance to propose a match that superimposes it on the last */
623 /* instance of a character that matches it (per trt), or misses */
624 /* it entirely if there is none. */
626 dirlen
= len
* direction
;
627 infinity
= dirlen
- (lim
+ pos
+ len
+ len
) * direction
;
629 pat
= (base_pat
+= len
- 1);
630 BM_tab_base
= BM_tab
;
632 j
= dirlen
; /* to get it in a register */
633 /* A character that does not appear in the pattern induces a */
634 /* stride equal to the pattern length. */
635 while (BM_tab_base
!= BM_tab
)
643 while (i
!= infinity
)
645 j
= pat
[i
]; i
+= direction
;
646 if (i
== dirlen
) i
= infinity
;
651 stride_for_teases
= BM_tab
[j
];
652 BM_tab
[j
] = dirlen
- i
;
653 /* A translation table is accompanied by its inverse -- see */
654 /* comment following downcase_table for details */
655 while ((j
= inverse_trt
[j
]) != k
)
656 BM_tab
[j
] = dirlen
- i
;
661 stride_for_teases
= BM_tab
[j
];
662 BM_tab
[j
] = dirlen
- i
;
664 /* stride_for_teases tells how much to stride if we get a */
665 /* match on the far character but are subsequently */
666 /* disappointed, by recording what the stride would have been */
667 /* for that character if the last character had been */
670 infinity
= dirlen
- infinity
;
671 pos
+= dirlen
- ((direction
> 0) ? direction
: 0);
672 /* loop invariant - pos points at where last char (first char if reverse)
673 of pattern would align in a possible match. */
676 if ((lim
- pos
- (direction
> 0)) * direction
< 0)
677 return (n
* (0 - direction
));
678 /* First we do the part we can by pointers (maybe nothing) */
681 limit
= pos
- dirlen
+ direction
;
682 limit
= ((direction
> 0)
683 ? BUFFER_CEILING_OF (limit
)
684 : BUFFER_FLOOR_OF (limit
));
685 /* LIMIT is now the last (not beyond-last!) value
686 POS can take on without hitting edge of buffer or the gap. */
687 limit
= ((direction
> 0)
688 ? min (lim
- 1, min (limit
, pos
+ 20000))
689 : max (lim
, max (limit
, pos
- 20000)));
690 if ((limit
- pos
) * direction
> 20)
692 p_limit
= &FETCH_CHAR (limit
);
693 p2
= (cursor
= &FETCH_CHAR (pos
));
694 /* In this loop, pos + cursor - p2 is the surrogate for pos */
695 while (1) /* use one cursor setting as long as i can */
697 if (direction
> 0) /* worth duplicating */
699 /* Use signed comparison if appropriate
700 to make cursor+infinity sure to be > p_limit.
701 Assuming that the buffer lies in a range of addresses
702 that are all "positive" (as ints) or all "negative",
703 either kind of comparison will work as long
704 as we don't step by infinity. So pick the kind
705 that works when we do step by infinity. */
706 if ((int) (p_limit
+ infinity
) > (int) p_limit
)
707 while ((int) cursor
<= (int) p_limit
)
708 cursor
+= BM_tab
[*cursor
];
710 while ((unsigned int) cursor
<= (unsigned int) p_limit
)
711 cursor
+= BM_tab
[*cursor
];
715 if ((int) (p_limit
+ infinity
) < (int) p_limit
)
716 while ((int) cursor
>= (int) p_limit
)
717 cursor
+= BM_tab
[*cursor
];
719 while ((unsigned int) cursor
>= (unsigned int) p_limit
)
720 cursor
+= BM_tab
[*cursor
];
722 /* If you are here, cursor is beyond the end of the searched region. */
723 /* This can happen if you match on the far character of the pattern, */
724 /* because the "stride" of that character is infinity, a number able */
725 /* to throw you well beyond the end of the search. It can also */
726 /* happen if you fail to match within the permitted region and would */
727 /* otherwise try a character beyond that region */
728 if ((cursor
- p_limit
) * direction
<= len
)
729 break; /* a small overrun is genuine */
730 cursor
-= infinity
; /* large overrun = hit */
731 i
= dirlen
- direction
;
734 while ((i
-= direction
) + direction
!= 0)
735 if (pat
[i
] != trt
[*(cursor
-= direction
)])
740 while ((i
-= direction
) + direction
!= 0)
741 if (pat
[i
] != *(cursor
-= direction
))
744 cursor
+= dirlen
- i
- direction
; /* fix cursor */
745 if (i
+ direction
== 0)
749 = pos
+ cursor
- p2
+ ((direction
> 0)
751 search_regs
.end
[0] = len
+ search_regs
.start
[0];
752 search_regs_from_string
= 0;
753 if ((n
-= direction
) != 0)
754 cursor
+= dirlen
; /* to resume search */
756 return ((direction
> 0)
757 ? search_regs
.end
[0] : search_regs
.start
[0]);
760 cursor
+= stride_for_teases
; /* <sigh> we lose - */
765 /* Now we'll pick up a clump that has to be done the hard */
766 /* way because it covers a discontinuity */
768 limit
= ((direction
> 0)
769 ? BUFFER_CEILING_OF (pos
- dirlen
+ 1)
770 : BUFFER_FLOOR_OF (pos
- dirlen
- 1));
771 limit
= ((direction
> 0)
772 ? min (limit
+ len
, lim
- 1)
773 : max (limit
- len
, lim
));
774 /* LIMIT is now the last value POS can have
775 and still be valid for a possible match. */
778 /* This loop can be coded for space rather than */
779 /* speed because it will usually run only once. */
780 /* (the reach is at most len + 21, and typically */
781 /* does not exceed len) */
782 while ((limit
- pos
) * direction
>= 0)
783 pos
+= BM_tab
[FETCH_CHAR(pos
)];
784 /* now run the same tests to distinguish going off the */
785 /* end, a match or a phoney match. */
786 if ((pos
- limit
) * direction
<= len
)
787 break; /* ran off the end */
788 /* Found what might be a match.
789 Set POS back to last (first if reverse) char pos. */
791 i
= dirlen
- direction
;
792 while ((i
-= direction
) + direction
!= 0)
795 if (pat
[i
] != (((int) trt
)
796 ? trt
[FETCH_CHAR(pos
)]
800 /* Above loop has moved POS part or all the way
801 back to the first char pos (last char pos if reverse).
802 Set it once again at the last (first if reverse) char. */
803 pos
+= dirlen
- i
- direction
;
804 if (i
+ direction
== 0)
808 = pos
+ ((direction
> 0) ? 1 - len
: 0);
809 search_regs
.end
[0] = len
+ search_regs
.start
[0];
810 search_regs_from_string
= 0;
811 if ((n
-= direction
) != 0)
812 pos
+= dirlen
; /* to resume search */
814 return ((direction
> 0)
815 ? search_regs
.end
[0] : search_regs
.start
[0]);
818 pos
+= stride_for_teases
;
821 /* We have done one clump. Can we continue? */
822 if ((lim
- pos
) * direction
< 0)
823 return ((0 - n
) * direction
);
829 /* Given a string of words separated by word delimiters,
830 compute a regexp that matches those exact words
831 separated by arbitrary punctuation. */
837 register unsigned char *p
, *o
;
838 register int i
, len
, punct_count
= 0, word_count
= 0;
841 CHECK_STRING (string
, 0);
842 p
= XSTRING (string
)->data
;
843 len
= XSTRING (string
)->size
;
845 for (i
= 0; i
< len
; i
++)
846 if (SYNTAX (p
[i
]) != Sword
)
849 if (i
> 0 && SYNTAX (p
[i
-1]) == Sword
) word_count
++;
851 if (SYNTAX (p
[len
-1]) == Sword
) word_count
++;
852 if (!word_count
) return build_string ("");
854 val
= make_string (p
, len
- punct_count
+ 5 * (word_count
- 1) + 4);
856 o
= XSTRING (val
)->data
;
860 for (i
= 0; i
< len
; i
++)
861 if (SYNTAX (p
[i
]) == Sword
)
863 else if (i
> 0 && SYNTAX (p
[i
-1]) == Sword
&& --word_count
)
878 DEFUN ("search-backward", Fsearch_backward
, Ssearch_backward
, 1, 4,
879 "sSearch backward: ",
880 "Search backward from point for STRING.\n\
881 Set point to the beginning of the occurrence found, and return point.\n\
882 An optional second argument bounds the search; it is a buffer position.\n\
883 The match found must not extend before that position.\n\
884 Optional third argument, if t, means if fail just return nil (no error).\n\
885 If not nil and not t, position at limit of search and return nil.\n\
886 Optional fourth argument is repeat count--search for successive occurrences.\n\
887 See also the functions `match-beginning', `match-end' and `replace-match'.")
888 (string
, bound
, noerror
, count
)
889 Lisp_Object string
, bound
, noerror
, count
;
891 return search_command (string
, bound
, noerror
, count
, -1, 0);
894 DEFUN ("search-forward", Fsearch_forward
, Ssearch_forward
, 1, 4, "sSearch: ",
895 "Search forward from point for STRING.\n\
896 Set point to the end of the occurrence found, and return point.\n\
897 An optional second argument bounds the search; it is a buffer position.\n\
898 The match found must not extend after that position. nil is equivalent\n\
900 Optional third argument, if t, means if fail just return nil (no error).\n\
901 If not nil and not t, move to limit of search and return nil.\n\
902 Optional fourth argument is repeat count--search for successive occurrences.\n\
903 See also the functions `match-beginning', `match-end' and `replace-match'.")
904 (string
, bound
, noerror
, count
)
905 Lisp_Object string
, bound
, noerror
, count
;
907 return search_command (string
, bound
, noerror
, count
, 1, 0);
910 DEFUN ("word-search-backward", Fword_search_backward
, Sword_search_backward
, 1, 4,
911 "sWord search backward: ",
912 "Search backward from point for STRING, ignoring differences in punctuation.\n\
913 Set point to the beginning of the occurrence found, and return point.\n\
914 An optional second argument bounds the search; it is a buffer position.\n\
915 The match found must not extend before that position.\n\
916 Optional third argument, if t, means if fail just return nil (no error).\n\
917 If not nil and not t, move to limit of search and return nil.\n\
918 Optional fourth argument is repeat count--search for successive occurrences.")
919 (string
, bound
, noerror
, count
)
920 Lisp_Object string
, bound
, noerror
, count
;
922 return search_command (wordify (string
), bound
, noerror
, count
, -1, 1);
925 DEFUN ("word-search-forward", Fword_search_forward
, Sword_search_forward
, 1, 4,
927 "Search forward from point for STRING, ignoring differences in punctuation.\n\
928 Set point to the end of the occurrence found, and return point.\n\
929 An optional second argument bounds the search; it is a buffer position.\n\
930 The match found must not extend after that position.\n\
931 Optional third argument, if t, means if fail just return nil (no error).\n\
932 If not nil and not t, move to limit of search and return nil.\n\
933 Optional fourth argument is repeat count--search for successive occurrences.")
934 (string
, bound
, noerror
, count
)
935 Lisp_Object string
, bound
, noerror
, count
;
937 return search_command (wordify (string
), bound
, noerror
, count
, 1, 1);
940 DEFUN ("re-search-backward", Fre_search_backward
, Sre_search_backward
, 1, 4,
941 "sRE search backward: ",
942 "Search backward from point for match for regular expression REGEXP.\n\
943 Set point to the beginning of the match, and return point.\n\
944 The match found is the one starting last in the buffer\n\
945 and yet ending before the place the origin of the search.\n\
946 An optional second argument bounds the search; it is a buffer position.\n\
947 The match found must start at or after that position.\n\
948 Optional third argument, if t, means if fail just return nil (no error).\n\
949 If not nil and not t, move to limit of search and return nil.\n\
950 Optional fourth argument is repeat count--search for successive occurrences.\n\
951 See also the functions `match-beginning', `match-end' and `replace-match'.")
952 (string
, bound
, noerror
, count
)
953 Lisp_Object string
, bound
, noerror
, count
;
955 return search_command (string
, bound
, noerror
, count
, -1, 1);
958 DEFUN ("re-search-forward", Fre_search_forward
, Sre_search_forward
, 1, 4,
960 "Search forward from point for regular expression REGEXP.\n\
961 Set point to the end of the occurrence found, and return point.\n\
962 An optional second argument bounds the search; it is a buffer position.\n\
963 The match found must not extend after that position.\n\
964 Optional third argument, if t, means if fail just return nil (no error).\n\
965 If not nil and not t, move to limit of search and return nil.\n\
966 Optional fourth argument is repeat count--search for successive occurrences.\n\
967 See also the functions `match-beginning', `match-end' and `replace-match'.")
968 (string
, bound
, noerror
, count
)
969 Lisp_Object string
, bound
, noerror
, count
;
971 return search_command (string
, bound
, noerror
, count
, 1, 1);
974 DEFUN ("replace-match", Freplace_match
, Sreplace_match
, 1, 3, 0,
975 "Replace text matched by last search with NEWTEXT.\n\
976 If second arg FIXEDCASE is non-nil, do not alter case of replacement text.\n\
977 Otherwise convert to all caps or cap initials, like replaced text.\n\
978 If third arg LITERAL is non-nil, insert NEWTEXT literally.\n\
979 Otherwise treat `\\' as special:\n\
980 `\\&' in NEWTEXT means substitute original matched text.\n\
981 `\\N' means substitute what matched the Nth `\\(...\\)'.\n\
982 If Nth parens didn't match, substitute nothing.\n\
983 `\\\\' means insert one `\\'.\n\
984 Leaves point at end of replacement text.")
985 (string
, fixedcase
, literal
)
986 Lisp_Object string
, fixedcase
, literal
;
988 enum { nochange
, all_caps
, cap_initial
} case_action
;
989 register int pos
, last
;
990 int some_multiletter_word
;
992 register int c
, prevc
;
995 CHECK_STRING (string
, 0);
997 case_action
= nochange
; /* We tried an initialization */
998 /* but some C compilers blew it */
999 if (search_regs
.start
[0] < BEGV
1000 || search_regs
.start
[0] > search_regs
.end
[0]
1001 || search_regs
.end
[0] > ZV
)
1002 args_out_of_range(make_number (search_regs
.start
[0]),
1003 make_number (search_regs
.end
[0]));
1005 if (NILP (fixedcase
))
1007 /* Decide how to casify by examining the matched text. */
1009 last
= search_regs
.end
[0];
1011 case_action
= all_caps
;
1013 /* some_multiletter_word is set nonzero if any original word
1014 is more than one letter long. */
1015 some_multiletter_word
= 0;
1017 for (pos
= search_regs
.start
[0]; pos
< last
; pos
++)
1019 c
= FETCH_CHAR (pos
);
1022 /* Cannot be all caps if any original char is lower case */
1024 case_action
= cap_initial
;
1025 if (SYNTAX (prevc
) != Sword
)
1027 /* Cannot even be cap initials
1028 if some original initial is lower case */
1029 case_action
= nochange
;
1033 some_multiletter_word
= 1;
1035 else if (!NOCASEP (c
))
1038 if (!some_multiletter_word
&& SYNTAX (prevc
) == Sword
)
1039 some_multiletter_word
= 1;
1045 /* Do not make new text all caps
1046 if the original text contained only single letter words. */
1047 if (case_action
== all_caps
&& !some_multiletter_word
)
1048 case_action
= cap_initial
;
1050 if (!some_letter
) case_action
= nochange
;
1053 SET_PT (search_regs
.end
[0]);
1054 if (!NILP (literal
))
1055 Finsert (1, &string
);
1058 struct gcpro gcpro1
;
1061 for (pos
= 0; pos
< XSTRING (string
)->size
; pos
++)
1063 c
= XSTRING (string
)->data
[pos
];
1066 c
= XSTRING (string
)->data
[++pos
];
1068 Finsert_buffer_substring (Fcurrent_buffer (),
1069 make_number (search_regs
.start
[0]),
1070 make_number (search_regs
.end
[0]));
1071 else if (c
>= '1' && c
<= RE_NREGS
+ '0')
1073 if (search_regs
.start
[c
- '0'] >= 1)
1074 Finsert_buffer_substring (Fcurrent_buffer (),
1075 make_number (search_regs
.start
[c
- '0']),
1076 make_number (search_regs
.end
[c
- '0']));
1087 inslen
= point
- (search_regs
.end
[0]);
1088 del_range (search_regs
.start
[0], search_regs
.end
[0]);
1090 if (case_action
== all_caps
)
1091 Fupcase_region (make_number (point
- inslen
), make_number (point
));
1092 else if (case_action
== cap_initial
)
1093 upcase_initials_region (make_number (point
- inslen
), make_number (point
));
1098 match_limit (num
, beginningp
)
1104 CHECK_NUMBER (num
, 0);
1106 if (n
< 0 || n
>= RE_NREGS
)
1107 args_out_of_range (num
, make_number (RE_NREGS
));
1108 if (search_regs
.start
[n
] < 0)
1110 return (make_number ((beginningp
) ? search_regs
.start
[n
]
1111 : search_regs
.end
[n
]));
1114 DEFUN ("match-beginning", Fmatch_beginning
, Smatch_beginning
, 1, 1, 0,
1115 "Return position of start of text matched by last search.\n\
1116 ARG, a number, specifies which parenthesized expression in the last regexp.\n\
1117 Value is nil if ARGth pair didn't match, or there were less than ARG pairs.\n\
1118 Zero means the entire text matched by the whole regexp or whole string.")
1122 return match_limit (num
, 1);
1125 DEFUN ("match-end", Fmatch_end
, Smatch_end
, 1, 1, 0,
1126 "Return position of end of text matched by last search.\n\
1127 ARG, a number, specifies which parenthesized expression in the last regexp.\n\
1128 Value is nil if ARGth pair didn't match, or there were less than ARG pairs.\n\
1129 Zero means the entire text matched by the whole regexp or whole string.")
1133 return match_limit (num
, 0);
1136 DEFUN ("match-data", Fmatch_data
, Smatch_data
, 0, 0, 0,
1137 "Return a list containing all info on what the last search matched.\n\
1138 Element 2N is `(match-beginning N)'; element 2N + 1 is `(match-end N)'.\n\
1139 All the elements are markers or nil (nil if the Nth pair didn't match)\n\
1140 if the last match was on a buffer; integers or nil if a string was matched.\n\
1141 Use `store-match-data' to reinstate the data in this list.")
1144 Lisp_Object data
[2 * RE_NREGS
];
1148 for (i
= 0; i
< RE_NREGS
; i
++)
1150 int start
= search_regs
.start
[i
];
1153 if (search_regs_from_string
)
1155 XFASTINT (data
[2 * i
]) = start
;
1156 XFASTINT (data
[2 * i
+ 1]) = search_regs
.end
[i
];
1160 data
[2 * i
] = Fmake_marker ();
1161 Fset_marker (data
[2 * i
], make_number (start
), Qnil
);
1162 data
[2 * i
+ 1] = Fmake_marker ();
1163 Fset_marker (data
[2 * i
+ 1],
1164 make_number (search_regs
.end
[i
]), Qnil
);
1169 data
[2 * i
] = data
[2 * i
+ 1] = Qnil
;
1171 return Flist (2 * len
+ 2, data
);
1175 DEFUN ("store-match-data", Fstore_match_data
, Sstore_match_data
, 1, 1, 0,
1176 "Set internal data on last search match from elements of LIST.\n\
1177 LIST should have been created by calling `match-data' previously.")
1179 register Lisp_Object list
;
1182 register Lisp_Object marker
;
1184 if (!CONSP (list
) && !NILP (list
))
1185 list
= wrong_type_argument (Qconsp
, list
, 0);
1187 for (i
= 0; i
< RE_NREGS
; i
++)
1189 marker
= Fcar (list
);
1192 search_regs
.start
[i
] = -1;
1197 if (XTYPE (marker
) == Lisp_Marker
1198 && XMARKER (marker
)->buffer
== 0)
1199 XFASTINT (marker
) = 0;
1201 CHECK_NUMBER_COERCE_MARKER (marker
, 0);
1202 search_regs
.start
[i
] = XINT (marker
);
1205 marker
= Fcar (list
);
1206 if (XTYPE (marker
) == Lisp_Marker
1207 && XMARKER (marker
)->buffer
== 0)
1208 XFASTINT (marker
) = 0;
1210 CHECK_NUMBER_COERCE_MARKER (marker
, 0);
1211 search_regs
.end
[i
] = XINT (marker
);
1219 /* Quote a string to inactivate reg-expr chars */
1221 DEFUN ("regexp-quote", Fregexp_quote
, Sregexp_quote
, 1, 1, 0,
1222 "Return a regexp string which matches exactly STRING and nothing else.")
1226 register unsigned char *in
, *out
, *end
;
1227 register unsigned char *temp
;
1229 CHECK_STRING (str
, 0);
1231 temp
= (unsigned char *) alloca (XSTRING (str
)->size
* 2);
1233 /* Now copy the data into the new string, inserting escapes. */
1235 in
= XSTRING (str
)->data
;
1236 end
= in
+ XSTRING (str
)->size
;
1239 for (; in
!= end
; in
++)
1241 if (*in
== '[' || *in
== ']'
1242 || *in
== '*' || *in
== '.' || *in
== '\\'
1243 || *in
== '?' || *in
== '+'
1244 || *in
== '^' || *in
== '$')
1249 return make_string (temp
, out
- temp
);
1256 searchbuf
.allocated
= 100;
1257 searchbuf
.buffer
= (char *) malloc (searchbuf
.allocated
);
1258 searchbuf
.fastmap
= search_fastmap
;
1260 Qsearch_failed
= intern ("search-failed");
1261 staticpro (&Qsearch_failed
);
1262 Qinvalid_regexp
= intern ("invalid-regexp");
1263 staticpro (&Qinvalid_regexp
);
1265 Fput (Qsearch_failed
, Qerror_conditions
,
1266 Fcons (Qsearch_failed
, Fcons (Qerror
, Qnil
)));
1267 Fput (Qsearch_failed
, Qerror_message
,
1268 build_string ("Search failed"));
1270 Fput (Qinvalid_regexp
, Qerror_conditions
,
1271 Fcons (Qinvalid_regexp
, Fcons (Qerror
, Qnil
)));
1272 Fput (Qinvalid_regexp
, Qerror_message
,
1273 build_string ("Invalid regexp"));
1276 staticpro (&last_regexp
);
1278 defsubr (&Sstring_match
);
1279 defsubr (&Slooking_at
);
1280 defsubr (&Sskip_chars_forward
);
1281 defsubr (&Sskip_chars_backward
);
1282 defsubr (&Ssearch_forward
);
1283 defsubr (&Ssearch_backward
);
1284 defsubr (&Sword_search_forward
);
1285 defsubr (&Sword_search_backward
);
1286 defsubr (&Sre_search_forward
);
1287 defsubr (&Sre_search_backward
);
1288 defsubr (&Sreplace_match
);
1289 defsubr (&Smatch_beginning
);
1290 defsubr (&Smatch_end
);
1291 defsubr (&Smatch_data
);
1292 defsubr (&Sstore_match_data
);
1293 defsubr (&Sregexp_quote
);