entered into RCS
[bpt/emacs.git] / src / search.c
CommitLineData
ca1d1d23
JB
1/* String search routines for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include "lisp.h"
23#include "syntax.h"
24#include "buffer.h"
25#include "commands.h"
4746118a 26
ca1d1d23
JB
27#include <sys/types.h>
28#include "regex.h"
29
30#define max(a, b) ((a) > (b) ? (a) : (b))
31#define min(a, b) ((a) < (b) ? (a) : (b))
32
33/* We compile regexps into this buffer and then use it for searching. */
34
35struct re_pattern_buffer searchbuf;
36
37char search_fastmap[0400];
38
39/* Last regexp we compiled */
40
41Lisp_Object last_regexp;
42
4746118a
JB
43/* Every call to re_match, etc., must pass &search_regs as the regs
44 argument unless you can show it is unnecessary (i.e., if re_match
45 is certainly going to be called again before region-around-match
46 can be called).
47
48 Since the registers are now dynamically allocated, we need to make
49 sure not to refer to the Nth register before checking that it has
1113d9db
JB
50 been allocated by checking search_regs.num_regs.
51
52 The regex code keeps track of whether it has allocated the search
53 buffer using bits in searchbuf. This means that whenever you
54 compile a new pattern, it completely forgets whether it has
55 allocated any registers, and will allocate new registers the next
56 time you call a searching or matching function. Therefore, we need
57 to call re_set_registers after compiling a new pattern or after
58 setting the match registers, so that the regex functions will be
59 able to free or re-allocate it properly. */
ca1d1d23
JB
60static struct re_registers search_regs;
61
daa37602
JB
62/* The buffer in which the last search was performed, or
63 Qt if the last search was done in a string;
64 Qnil if no searching has been done yet. */
65static Lisp_Object last_thing_searched;
ca1d1d23
JB
66
67/* error condition signalled when regexp compile_pattern fails */
68
69Lisp_Object Qinvalid_regexp;
70
71static void
72matcher_overflow ()
73{
74 error ("Stack overflow in regexp matcher");
75}
76
77#ifdef __STDC__
78#define CONST const
79#else
80#define CONST
81#endif
82
83/* Compile a regexp and signal a Lisp error if anything goes wrong. */
84
1113d9db 85compile_pattern (pattern, bufp, regp, translate)
ca1d1d23
JB
86 Lisp_Object pattern;
87 struct re_pattern_buffer *bufp;
1113d9db 88 struct re_registers *regp;
ca1d1d23
JB
89 char *translate;
90{
91 CONST char *val;
92 Lisp_Object dummy;
93
94 if (EQ (pattern, last_regexp)
95 && translate == bufp->translate)
96 return;
1113d9db 97
ca1d1d23
JB
98 last_regexp = Qnil;
99 bufp->translate = translate;
100 val = re_compile_pattern ((char *) XSTRING (pattern)->data,
101 XSTRING (pattern)->size,
102 bufp);
103 if (val)
104 {
105 dummy = build_string (val);
106 while (1)
107 Fsignal (Qinvalid_regexp, Fcons (dummy, Qnil));
108 }
1113d9db 109
ca1d1d23 110 last_regexp = pattern;
1113d9db
JB
111
112 /* Advise the searching functions about the space we have allocated
113 for register data. */
ebb9e16f
JB
114 if (regp)
115 re_set_registers (bufp, regp, regp->num_regs, regp->start, regp->end);
1113d9db 116
ca1d1d23
JB
117 return;
118}
119
120/* Error condition used for failing searches */
121Lisp_Object Qsearch_failed;
122
123Lisp_Object
124signal_failure (arg)
125 Lisp_Object arg;
126{
127 Fsignal (Qsearch_failed, Fcons (arg, Qnil));
128 return Qnil;
129}
130\f
131DEFUN ("looking-at", Flooking_at, Slooking_at, 1, 1, 0,
e065a56e
JB
132 "Return t if text after point matches regular expression PAT.\n\
133This function modifies the match data that `match-beginning',\n\
134`match-end' and `match-data' access; save and restore the match\n\
fe99283d 135data if you want to preserve them.")
ca1d1d23
JB
136 (string)
137 Lisp_Object string;
138{
139 Lisp_Object val;
140 unsigned char *p1, *p2;
141 int s1, s2;
142 register int i;
143
144 CHECK_STRING (string, 0);
1113d9db 145 compile_pattern (string, &searchbuf, &search_regs,
ca1d1d23
JB
146 !NILP (current_buffer->case_fold_search) ? DOWNCASE_TABLE : 0);
147
148 immediate_quit = 1;
149 QUIT; /* Do a pending quit right away, to avoid paradoxical behavior */
150
151 /* Get pointers and sizes of the two strings
152 that make up the visible portion of the buffer. */
153
154 p1 = BEGV_ADDR;
155 s1 = GPT - BEGV;
156 p2 = GAP_END_ADDR;
157 s2 = ZV - GPT;
158 if (s1 < 0)
159 {
160 p2 = p1;
161 s2 = ZV - BEGV;
162 s1 = 0;
163 }
164 if (s2 < 0)
165 {
166 s1 = ZV - BEGV;
167 s2 = 0;
168 }
169
170 i = re_match_2 (&searchbuf, (char *) p1, s1, (char *) p2, s2,
171 point - BEGV, &search_regs,
172 ZV - BEGV);
173 if (i == -2)
174 matcher_overflow ();
175
176 val = (0 <= i ? Qt : Qnil);
4746118a 177 for (i = 0; i < search_regs.num_regs; i++)
ca1d1d23
JB
178 if (search_regs.start[i] >= 0)
179 {
180 search_regs.start[i] += BEGV;
181 search_regs.end[i] += BEGV;
182 }
daa37602 183 XSET (last_thing_searched, Lisp_Buffer, current_buffer);
ca1d1d23
JB
184 immediate_quit = 0;
185 return val;
186}
187
188DEFUN ("string-match", Fstring_match, Sstring_match, 2, 3, 0,
189 "Return index of start of first match for REGEXP in STRING, or nil.\n\
190If third arg START is non-nil, start search at that index in STRING.\n\
191For index of first char beyond the match, do (match-end 0).\n\
192`match-end' and `match-beginning' also give indices of substrings\n\
193matched by parenthesis constructs in the pattern.")
194 (regexp, string, start)
195 Lisp_Object regexp, string, start;
196{
197 int val;
198 int s;
199
200 CHECK_STRING (regexp, 0);
201 CHECK_STRING (string, 1);
202
203 if (NILP (start))
204 s = 0;
205 else
206 {
207 int len = XSTRING (string)->size;
208
209 CHECK_NUMBER (start, 2);
210 s = XINT (start);
211 if (s < 0 && -s <= len)
212 s = len - s;
213 else if (0 > s || s > len)
214 args_out_of_range (string, start);
215 }
216
1113d9db 217 compile_pattern (regexp, &searchbuf, &search_regs,
ca1d1d23
JB
218 !NILP (current_buffer->case_fold_search) ? DOWNCASE_TABLE : 0);
219 immediate_quit = 1;
220 val = re_search (&searchbuf, (char *) XSTRING (string)->data,
221 XSTRING (string)->size, s, XSTRING (string)->size - s,
222 &search_regs);
223 immediate_quit = 0;
daa37602 224 last_thing_searched = Qt;
ca1d1d23
JB
225 if (val == -2)
226 matcher_overflow ();
227 if (val < 0) return Qnil;
228 return make_number (val);
229}
230\f
ffd56f97
JB
231/* Search for COUNT instances of the character TARGET, starting at START.
232 If COUNT is negative, search backwards.
233
234 If we find COUNT instances, set *SHORTAGE to zero, and return the
235 position of the COUNTth character.
236
237 If we don't find COUNT instances before reaching the end of the
238 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
239 the number of TARGETs left unfound, and return the end of the
240 buffer we bumped up against. */
241
242scan_buffer (target, start, count, shortage)
243 int *shortage, start;
244 register int count, target;
ca1d1d23 245{
ffd56f97
JB
246 int limit = ((count > 0) ? ZV - 1 : BEGV);
247 int direction = ((count > 0) ? 1 : -1);
248
249 register unsigned char *cursor;
ca1d1d23 250 unsigned char *base;
ffd56f97
JB
251
252 register int ceiling;
253 register unsigned char *ceiling_addr;
ca1d1d23
JB
254
255 if (shortage != 0)
256 *shortage = 0;
257
258 immediate_quit = 1;
259
ffd56f97
JB
260 if (count > 0)
261 while (start != limit + 1)
ca1d1d23 262 {
ffd56f97
JB
263 ceiling = BUFFER_CEILING_OF (start);
264 ceiling = min (limit, ceiling);
265 ceiling_addr = &FETCH_CHAR (ceiling) + 1;
266 base = (cursor = &FETCH_CHAR (start));
ca1d1d23
JB
267 while (1)
268 {
ffd56f97 269 while (*cursor != target && ++cursor != ceiling_addr)
ca1d1d23 270 ;
ffd56f97 271 if (cursor != ceiling_addr)
ca1d1d23 272 {
ffd56f97 273 if (--count == 0)
ca1d1d23
JB
274 {
275 immediate_quit = 0;
ffd56f97 276 return (start + cursor - base + 1);
ca1d1d23
JB
277 }
278 else
ffd56f97 279 if (++cursor == ceiling_addr)
ca1d1d23
JB
280 break;
281 }
282 else
283 break;
284 }
ffd56f97 285 start += cursor - base;
ca1d1d23
JB
286 }
287 else
288 {
ffd56f97
JB
289 start--; /* first character we scan */
290 while (start > limit - 1)
291 { /* we WILL scan under start */
292 ceiling = BUFFER_FLOOR_OF (start);
293 ceiling = max (limit, ceiling);
294 ceiling_addr = &FETCH_CHAR (ceiling) - 1;
295 base = (cursor = &FETCH_CHAR (start));
ca1d1d23
JB
296 cursor++;
297 while (1)
298 {
ffd56f97 299 while (--cursor != ceiling_addr && *cursor != target)
ca1d1d23 300 ;
ffd56f97 301 if (cursor != ceiling_addr)
ca1d1d23 302 {
ffd56f97 303 if (++count == 0)
ca1d1d23
JB
304 {
305 immediate_quit = 0;
ffd56f97 306 return (start + cursor - base + 1);
ca1d1d23
JB
307 }
308 }
309 else
310 break;
311 }
ffd56f97 312 start += cursor - base;
ca1d1d23
JB
313 }
314 }
315 immediate_quit = 0;
316 if (shortage != 0)
ffd56f97
JB
317 *shortage = count * direction;
318 return (start + ((direction == 1 ? 0 : 1)));
ca1d1d23
JB
319}
320
321int
322find_next_newline (from, cnt)
323 register int from, cnt;
324{
325 return (scan_buffer ('\n', from, cnt, (int *) 0));
326}
327\f
328DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0,
329 "Move point forward, stopping before a char not in CHARS, or at position LIM.\n\
330CHARS is like the inside of a `[...]' in a regular expression\n\
331except that `]' is never special and `\\' quotes `^', `-' or `\\'.\n\
332Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\
333With arg \"^a-zA-Z\", skips nonletters stopping before first letter.")
334 (string, lim)
335 Lisp_Object string, lim;
336{
337 skip_chars (1, string, lim);
338 return Qnil;
339}
340
341DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
342 "Move point backward, stopping after a char not in CHARS, or at position LIM.\n\
343See `skip-chars-forward' for details.")
344 (string, lim)
345 Lisp_Object string, lim;
346{
347 skip_chars (0, string, lim);
348 return Qnil;
349}
350
351skip_chars (forwardp, string, lim)
352 int forwardp;
353 Lisp_Object string, lim;
354{
355 register unsigned char *p, *pend;
356 register unsigned char c;
357 unsigned char fastmap[0400];
358 int negate = 0;
359 register int i;
360
361 CHECK_STRING (string, 0);
362
363 if (NILP (lim))
364 XSET (lim, Lisp_Int, forwardp ? ZV : BEGV);
365 else
366 CHECK_NUMBER_COERCE_MARKER (lim, 1);
367
368#if 0 /* This breaks some things... jla. */
369 /* In any case, don't allow scan outside bounds of buffer. */
370 if (XFASTINT (lim) > ZV)
371 XFASTINT (lim) = ZV;
372 if (XFASTINT (lim) < BEGV)
373 XFASTINT (lim) = BEGV;
374#endif
375
376 p = XSTRING (string)->data;
377 pend = p + XSTRING (string)->size;
378 bzero (fastmap, sizeof fastmap);
379
380 if (p != pend && *p == '^')
381 {
382 negate = 1; p++;
383 }
384
385 /* Find the characters specified and set their elements of fastmap. */
386
387 while (p != pend)
388 {
389 c = *p++;
390 if (c == '\\')
391 {
392 if (p == pend) break;
393 c = *p++;
394 }
395 if (p != pend && *p == '-')
396 {
397 p++;
398 if (p == pend) break;
399 while (c <= *p)
400 {
401 fastmap[c] = 1;
402 c++;
403 }
404 p++;
405 }
406 else
407 fastmap[c] = 1;
408 }
409
410 /* If ^ was the first character, complement the fastmap. */
411
412 if (negate)
413 for (i = 0; i < sizeof fastmap; i++)
414 fastmap[i] ^= 1;
415
416 immediate_quit = 1;
417 if (forwardp)
418 {
419 while (point < XINT (lim) && fastmap[FETCH_CHAR (point)])
420 SET_PT (point + 1);
421 }
422 else
423 {
424 while (point > XINT (lim) && fastmap[FETCH_CHAR (point - 1)])
425 SET_PT (point - 1);
426 }
427 immediate_quit = 0;
428}
429\f
430/* Subroutines of Lisp buffer search functions. */
431
432static Lisp_Object
433search_command (string, bound, noerror, count, direction, RE)
434 Lisp_Object string, bound, noerror, count;
435 int direction;
436 int RE;
437{
438 register int np;
439 int lim;
440 int n = direction;
441
442 if (!NILP (count))
443 {
444 CHECK_NUMBER (count, 3);
445 n *= XINT (count);
446 }
447
448 CHECK_STRING (string, 0);
449 if (NILP (bound))
450 lim = n > 0 ? ZV : BEGV;
451 else
452 {
453 CHECK_NUMBER_COERCE_MARKER (bound, 1);
454 lim = XINT (bound);
455 if (n > 0 ? lim < point : lim > point)
456 error ("Invalid search bound (wrong side of point)");
457 if (lim > ZV)
458 lim = ZV;
459 if (lim < BEGV)
460 lim = BEGV;
461 }
462
463 np = search_buffer (string, point, lim, n, RE,
464 (!NILP (current_buffer->case_fold_search)
465 ? XSTRING (current_buffer->case_canon_table)->data : 0),
466 (!NILP (current_buffer->case_fold_search)
467 ? XSTRING (current_buffer->case_eqv_table)->data : 0));
468 if (np <= 0)
469 {
470 if (NILP (noerror))
471 return signal_failure (string);
472 if (!EQ (noerror, Qt))
473 {
474 if (lim < BEGV || lim > ZV)
475 abort ();
476 SET_PT (lim);
477 }
478 return Qnil;
479 }
480
481 if (np < BEGV || np > ZV)
482 abort ();
483
484 SET_PT (np);
485
486 return make_number (np);
487}
488\f
489/* search for the n'th occurrence of STRING in the current buffer,
490 starting at position POS and stopping at position LIM,
491 treating PAT as a literal string if RE is false or as
492 a regular expression if RE is true.
493
494 If N is positive, searching is forward and LIM must be greater than POS.
495 If N is negative, searching is backward and LIM must be less than POS.
496
497 Returns -x if only N-x occurrences found (x > 0),
498 or else the position at the beginning of the Nth occurrence
499 (if searching backward) or the end (if searching forward). */
500
501search_buffer (string, pos, lim, n, RE, trt, inverse_trt)
502 Lisp_Object string;
503 int pos;
504 int lim;
505 int n;
506 int RE;
507 register unsigned char *trt;
508 register unsigned char *inverse_trt;
509{
510 int len = XSTRING (string)->size;
511 unsigned char *base_pat = XSTRING (string)->data;
512 register int *BM_tab;
513 int *BM_tab_base;
514 register int direction = ((n > 0) ? 1 : -1);
515 register int dirlen;
516 int infinity, limit, k, stride_for_teases;
517 register unsigned char *pat, *cursor, *p_limit;
518 register int i, j;
519 unsigned char *p1, *p2;
520 int s1, s2;
521
522 /* Null string is found at starting position. */
523 if (!len)
524 return pos;
525
526 if (RE)
1113d9db 527 compile_pattern (string, &searchbuf, &search_regs, (char *) trt);
ca1d1d23
JB
528
529 if (RE /* Here we detect whether the */
530 /* generality of an RE search is */
531 /* really needed. */
532 /* first item is "exact match" */
4746118a 533 && *(searchbuf.buffer) == (char) RE_EXACTN_VALUE
ca1d1d23
JB
534 && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */
535 {
536 RE = 0; /* can do straight (non RE) search */
537 pat = (base_pat = (unsigned char *) searchbuf.buffer + 2);
538 /* trt already applied */
539 len = searchbuf.used - 2;
540 }
541 else if (!RE)
542 {
543 pat = (unsigned char *) alloca (len);
544
545 for (i = len; i--;) /* Copy the pattern; apply trt */
546 *pat++ = (((int) trt) ? trt [*base_pat++] : *base_pat++);
547 pat -= len; base_pat = pat;
548 }
549
550 if (RE)
551 {
552 immediate_quit = 1; /* Quit immediately if user types ^G,
553 because letting this function finish
554 can take too long. */
555 QUIT; /* Do a pending quit right away,
556 to avoid paradoxical behavior */
557 /* Get pointers and sizes of the two strings
558 that make up the visible portion of the buffer. */
559
560 p1 = BEGV_ADDR;
561 s1 = GPT - BEGV;
562 p2 = GAP_END_ADDR;
563 s2 = ZV - GPT;
564 if (s1 < 0)
565 {
566 p2 = p1;
567 s2 = ZV - BEGV;
568 s1 = 0;
569 }
570 if (s2 < 0)
571 {
572 s1 = ZV - BEGV;
573 s2 = 0;
574 }
575 while (n < 0)
576 {
577 int val = re_search_2 (&searchbuf, (char *) p1, s1, (char *) p2, s2,
578 pos - BEGV, lim - pos, &search_regs,
579 /* Don't allow match past current point */
580 pos - BEGV);
581 if (val == -2)
582 matcher_overflow ();
583 if (val >= 0)
584 {
585 j = BEGV;
4746118a 586 for (i = 0; i < search_regs.num_regs; i++)
ca1d1d23
JB
587 if (search_regs.start[i] >= 0)
588 {
589 search_regs.start[i] += j;
590 search_regs.end[i] += j;
591 }
daa37602 592 XSET (last_thing_searched, Lisp_Buffer, current_buffer);
ca1d1d23
JB
593 /* Set pos to the new position. */
594 pos = search_regs.start[0];
595 }
596 else
597 {
598 immediate_quit = 0;
599 return (n);
600 }
601 n++;
602 }
603 while (n > 0)
604 {
605 int val = re_search_2 (&searchbuf, (char *) p1, s1, (char *) p2, s2,
606 pos - BEGV, lim - pos, &search_regs,
607 lim - BEGV);
608 if (val == -2)
609 matcher_overflow ();
610 if (val >= 0)
611 {
612 j = BEGV;
4746118a 613 for (i = 0; i < search_regs.num_regs; i++)
ca1d1d23
JB
614 if (search_regs.start[i] >= 0)
615 {
616 search_regs.start[i] += j;
617 search_regs.end[i] += j;
618 }
daa37602 619 XSET (last_thing_searched, Lisp_Buffer, current_buffer);
ca1d1d23
JB
620 pos = search_regs.end[0];
621 }
622 else
623 {
624 immediate_quit = 0;
625 return (0 - n);
626 }
627 n--;
628 }
629 immediate_quit = 0;
630 return (pos);
631 }
632 else /* non-RE case */
633 {
634#ifdef C_ALLOCA
635 int BM_tab_space[0400];
636 BM_tab = &BM_tab_space[0];
637#else
638 BM_tab = (int *) alloca (0400 * sizeof (int));
639#endif
640 /* The general approach is that we are going to maintain that we know */
641 /* the first (closest to the present position, in whatever direction */
642 /* we're searching) character that could possibly be the last */
643 /* (furthest from present position) character of a valid match. We */
644 /* advance the state of our knowledge by looking at that character */
645 /* and seeing whether it indeed matches the last character of the */
646 /* pattern. If it does, we take a closer look. If it does not, we */
647 /* move our pointer (to putative last characters) as far as is */
648 /* logically possible. This amount of movement, which I call a */
649 /* stride, will be the length of the pattern if the actual character */
650 /* appears nowhere in the pattern, otherwise it will be the distance */
651 /* from the last occurrence of that character to the end of the */
652 /* pattern. */
653 /* As a coding trick, an enormous stride is coded into the table for */
654 /* characters that match the last character. This allows use of only */
655 /* a single test, a test for having gone past the end of the */
656 /* permissible match region, to test for both possible matches (when */
657 /* the stride goes past the end immediately) and failure to */
658 /* match (where you get nudged past the end one stride at a time). */
659
660 /* Here we make a "mickey mouse" BM table. The stride of the search */
661 /* is determined only by the last character of the putative match. */
662 /* If that character does not match, we will stride the proper */
663 /* distance to propose a match that superimposes it on the last */
664 /* instance of a character that matches it (per trt), or misses */
665 /* it entirely if there is none. */
666
667 dirlen = len * direction;
668 infinity = dirlen - (lim + pos + len + len) * direction;
669 if (direction < 0)
670 pat = (base_pat += len - 1);
671 BM_tab_base = BM_tab;
672 BM_tab += 0400;
673 j = dirlen; /* to get it in a register */
674 /* A character that does not appear in the pattern induces a */
675 /* stride equal to the pattern length. */
676 while (BM_tab_base != BM_tab)
677 {
678 *--BM_tab = j;
679 *--BM_tab = j;
680 *--BM_tab = j;
681 *--BM_tab = j;
682 }
683 i = 0;
684 while (i != infinity)
685 {
686 j = pat[i]; i += direction;
687 if (i == dirlen) i = infinity;
688 if ((int) trt)
689 {
690 k = (j = trt[j]);
691 if (i == infinity)
692 stride_for_teases = BM_tab[j];
693 BM_tab[j] = dirlen - i;
694 /* A translation table is accompanied by its inverse -- see */
695 /* comment following downcase_table for details */
696 while ((j = inverse_trt[j]) != k)
697 BM_tab[j] = dirlen - i;
698 }
699 else
700 {
701 if (i == infinity)
702 stride_for_teases = BM_tab[j];
703 BM_tab[j] = dirlen - i;
704 }
705 /* stride_for_teases tells how much to stride if we get a */
706 /* match on the far character but are subsequently */
707 /* disappointed, by recording what the stride would have been */
708 /* for that character if the last character had been */
709 /* different. */
710 }
711 infinity = dirlen - infinity;
712 pos += dirlen - ((direction > 0) ? direction : 0);
713 /* loop invariant - pos points at where last char (first char if reverse)
714 of pattern would align in a possible match. */
715 while (n != 0)
716 {
717 if ((lim - pos - (direction > 0)) * direction < 0)
718 return (n * (0 - direction));
719 /* First we do the part we can by pointers (maybe nothing) */
720 QUIT;
721 pat = base_pat;
722 limit = pos - dirlen + direction;
723 limit = ((direction > 0)
724 ? BUFFER_CEILING_OF (limit)
725 : BUFFER_FLOOR_OF (limit));
726 /* LIMIT is now the last (not beyond-last!) value
727 POS can take on without hitting edge of buffer or the gap. */
728 limit = ((direction > 0)
729 ? min (lim - 1, min (limit, pos + 20000))
730 : max (lim, max (limit, pos - 20000)));
731 if ((limit - pos) * direction > 20)
732 {
733 p_limit = &FETCH_CHAR (limit);
734 p2 = (cursor = &FETCH_CHAR (pos));
735 /* In this loop, pos + cursor - p2 is the surrogate for pos */
736 while (1) /* use one cursor setting as long as i can */
737 {
738 if (direction > 0) /* worth duplicating */
739 {
740 /* Use signed comparison if appropriate
741 to make cursor+infinity sure to be > p_limit.
742 Assuming that the buffer lies in a range of addresses
743 that are all "positive" (as ints) or all "negative",
744 either kind of comparison will work as long
745 as we don't step by infinity. So pick the kind
746 that works when we do step by infinity. */
747 if ((int) (p_limit + infinity) > (int) p_limit)
748 while ((int) cursor <= (int) p_limit)
749 cursor += BM_tab[*cursor];
750 else
751 while ((unsigned int) cursor <= (unsigned int) p_limit)
752 cursor += BM_tab[*cursor];
753 }
754 else
755 {
756 if ((int) (p_limit + infinity) < (int) p_limit)
757 while ((int) cursor >= (int) p_limit)
758 cursor += BM_tab[*cursor];
759 else
760 while ((unsigned int) cursor >= (unsigned int) p_limit)
761 cursor += BM_tab[*cursor];
762 }
763/* If you are here, cursor is beyond the end of the searched region. */
764 /* This can happen if you match on the far character of the pattern, */
765 /* because the "stride" of that character is infinity, a number able */
766 /* to throw you well beyond the end of the search. It can also */
767 /* happen if you fail to match within the permitted region and would */
768 /* otherwise try a character beyond that region */
769 if ((cursor - p_limit) * direction <= len)
770 break; /* a small overrun is genuine */
771 cursor -= infinity; /* large overrun = hit */
772 i = dirlen - direction;
773 if ((int) trt)
774 {
775 while ((i -= direction) + direction != 0)
776 if (pat[i] != trt[*(cursor -= direction)])
777 break;
778 }
779 else
780 {
781 while ((i -= direction) + direction != 0)
782 if (pat[i] != *(cursor -= direction))
783 break;
784 }
785 cursor += dirlen - i - direction; /* fix cursor */
786 if (i + direction == 0)
787 {
788 cursor -= direction;
1113d9db
JB
789
790 /* Make sure we have registers in which to store
791 the match position. */
792 if (search_regs.num_regs == 0)
793 {
794 regoff_t *starts, *ends;
795
796 starts =
797 (regoff_t *) xmalloc (2 * sizeof (regoff_t));
798 ends =
799 (regoff_t *) xmalloc (2 * sizeof (regoff_t));
800 re_set_registers (&searchbuf,
801 &search_regs,
802 2, starts, ends);
803 }
804
ca1d1d23
JB
805 search_regs.start[0]
806 = pos + cursor - p2 + ((direction > 0)
807 ? 1 - len : 0);
808 search_regs.end[0] = len + search_regs.start[0];
daa37602 809 XSET (last_thing_searched, Lisp_Buffer, current_buffer);
ca1d1d23
JB
810 if ((n -= direction) != 0)
811 cursor += dirlen; /* to resume search */
812 else
813 return ((direction > 0)
814 ? search_regs.end[0] : search_regs.start[0]);
815 }
816 else
817 cursor += stride_for_teases; /* <sigh> we lose - */
818 }
819 pos += cursor - p2;
820 }
821 else
822 /* Now we'll pick up a clump that has to be done the hard */
823 /* way because it covers a discontinuity */
824 {
825 limit = ((direction > 0)
826 ? BUFFER_CEILING_OF (pos - dirlen + 1)
827 : BUFFER_FLOOR_OF (pos - dirlen - 1));
828 limit = ((direction > 0)
829 ? min (limit + len, lim - 1)
830 : max (limit - len, lim));
831 /* LIMIT is now the last value POS can have
832 and still be valid for a possible match. */
833 while (1)
834 {
835 /* This loop can be coded for space rather than */
836 /* speed because it will usually run only once. */
837 /* (the reach is at most len + 21, and typically */
838 /* does not exceed len) */
839 while ((limit - pos) * direction >= 0)
840 pos += BM_tab[FETCH_CHAR(pos)];
841 /* now run the same tests to distinguish going off the */
842 /* end, a match or a phoney match. */
843 if ((pos - limit) * direction <= len)
844 break; /* ran off the end */
845 /* Found what might be a match.
846 Set POS back to last (first if reverse) char pos. */
847 pos -= infinity;
848 i = dirlen - direction;
849 while ((i -= direction) + direction != 0)
850 {
851 pos -= direction;
852 if (pat[i] != (((int) trt)
853 ? trt[FETCH_CHAR(pos)]
854 : FETCH_CHAR (pos)))
855 break;
856 }
857 /* Above loop has moved POS part or all the way
858 back to the first char pos (last char pos if reverse).
859 Set it once again at the last (first if reverse) char. */
860 pos += dirlen - i- direction;
861 if (i + direction == 0)
862 {
863 pos -= direction;
1113d9db
JB
864
865 /* Make sure we have registers in which to store
866 the match position. */
867 if (search_regs.num_regs == 0)
868 {
869 regoff_t *starts, *ends;
870
871 starts =
872 (regoff_t *) xmalloc (2 * sizeof (regoff_t));
873 ends =
874 (regoff_t *) xmalloc (2 * sizeof (regoff_t));
875 re_set_registers (&searchbuf,
876 &search_regs,
877 2, starts, ends);
878 }
879
ca1d1d23
JB
880 search_regs.start[0]
881 = pos + ((direction > 0) ? 1 - len : 0);
882 search_regs.end[0] = len + search_regs.start[0];
daa37602 883 XSET (last_thing_searched, Lisp_Buffer, current_buffer);
ca1d1d23
JB
884 if ((n -= direction) != 0)
885 pos += dirlen; /* to resume search */
886 else
887 return ((direction > 0)
888 ? search_regs.end[0] : search_regs.start[0]);
889 }
890 else
891 pos += stride_for_teases;
892 }
893 }
894 /* We have done one clump. Can we continue? */
895 if ((lim - pos) * direction < 0)
896 return ((0 - n) * direction);
897 }
898 return pos;
899 }
900}
901\f
902/* Given a string of words separated by word delimiters,
903 compute a regexp that matches those exact words
904 separated by arbitrary punctuation. */
905
906static Lisp_Object
907wordify (string)
908 Lisp_Object string;
909{
910 register unsigned char *p, *o;
911 register int i, len, punct_count = 0, word_count = 0;
912 Lisp_Object val;
913
914 CHECK_STRING (string, 0);
915 p = XSTRING (string)->data;
916 len = XSTRING (string)->size;
917
918 for (i = 0; i < len; i++)
919 if (SYNTAX (p[i]) != Sword)
920 {
921 punct_count++;
922 if (i > 0 && SYNTAX (p[i-1]) == Sword) word_count++;
923 }
924 if (SYNTAX (p[len-1]) == Sword) word_count++;
925 if (!word_count) return build_string ("");
926
927 val = make_string (p, len - punct_count + 5 * (word_count - 1) + 4);
928
929 o = XSTRING (val)->data;
930 *o++ = '\\';
931 *o++ = 'b';
932
933 for (i = 0; i < len; i++)
934 if (SYNTAX (p[i]) == Sword)
935 *o++ = p[i];
936 else if (i > 0 && SYNTAX (p[i-1]) == Sword && --word_count)
937 {
938 *o++ = '\\';
939 *o++ = 'W';
940 *o++ = '\\';
941 *o++ = 'W';
942 *o++ = '*';
943 }
944
945 *o++ = '\\';
946 *o++ = 'b';
947
948 return val;
949}
950\f
951DEFUN ("search-backward", Fsearch_backward, Ssearch_backward, 1, 4,
952 "sSearch backward: ",
953 "Search backward from point for STRING.\n\
954Set point to the beginning of the occurrence found, and return point.\n\
955An optional second argument bounds the search; it is a buffer position.\n\
956The match found must not extend before that position.\n\
957Optional third argument, if t, means if fail just return nil (no error).\n\
958 If not nil and not t, position at limit of search and return nil.\n\
959Optional fourth argument is repeat count--search for successive occurrences.\n\
960See also the functions `match-beginning', `match-end' and `replace-match'.")
961 (string, bound, noerror, count)
962 Lisp_Object string, bound, noerror, count;
963{
964 return search_command (string, bound, noerror, count, -1, 0);
965}
966
967DEFUN ("search-forward", Fsearch_forward, Ssearch_forward, 1, 4, "sSearch: ",
968 "Search forward from point for STRING.\n\
969Set point to the end of the occurrence found, and return point.\n\
970An optional second argument bounds the search; it is a buffer position.\n\
971The match found must not extend after that position. nil is equivalent\n\
972 to (point-max).\n\
973Optional third argument, if t, means if fail just return nil (no error).\n\
974 If not nil and not t, move to limit of search and return nil.\n\
975Optional fourth argument is repeat count--search for successive occurrences.\n\
976See also the functions `match-beginning', `match-end' and `replace-match'.")
977 (string, bound, noerror, count)
978 Lisp_Object string, bound, noerror, count;
979{
980 return search_command (string, bound, noerror, count, 1, 0);
981}
982
983DEFUN ("word-search-backward", Fword_search_backward, Sword_search_backward, 1, 4,
984 "sWord search backward: ",
985 "Search backward from point for STRING, ignoring differences in punctuation.\n\
986Set point to the beginning of the occurrence found, and return point.\n\
987An optional second argument bounds the search; it is a buffer position.\n\
988The match found must not extend before that position.\n\
989Optional third argument, if t, means if fail just return nil (no error).\n\
990 If not nil and not t, move to limit of search and return nil.\n\
991Optional fourth argument is repeat count--search for successive occurrences.")
992 (string, bound, noerror, count)
993 Lisp_Object string, bound, noerror, count;
994{
995 return search_command (wordify (string), bound, noerror, count, -1, 1);
996}
997
998DEFUN ("word-search-forward", Fword_search_forward, Sword_search_forward, 1, 4,
999 "sWord search: ",
1000 "Search forward from point for STRING, ignoring differences in punctuation.\n\
1001Set point to the end of the occurrence found, and return point.\n\
1002An optional second argument bounds the search; it is a buffer position.\n\
1003The match found must not extend after that position.\n\
1004Optional third argument, if t, means if fail just return nil (no error).\n\
1005 If not nil and not t, move to limit of search and return nil.\n\
1006Optional fourth argument is repeat count--search for successive occurrences.")
1007 (string, bound, noerror, count)
1008 Lisp_Object string, bound, noerror, count;
1009{
1010 return search_command (wordify (string), bound, noerror, count, 1, 1);
1011}
1012
1013DEFUN ("re-search-backward", Fre_search_backward, Sre_search_backward, 1, 4,
1014 "sRE search backward: ",
1015 "Search backward from point for match for regular expression REGEXP.\n\
1016Set point to the beginning of the match, and return point.\n\
1017The match found is the one starting last in the buffer\n\
1018and yet ending before the place the origin of the search.\n\
1019An optional second argument bounds the search; it is a buffer position.\n\
1020The match found must start at or after that position.\n\
1021Optional third argument, if t, means if fail just return nil (no error).\n\
1022 If not nil and not t, move to limit of search and return nil.\n\
1023Optional fourth argument is repeat count--search for successive occurrences.\n\
1024See also the functions `match-beginning', `match-end' and `replace-match'.")
1025 (string, bound, noerror, count)
1026 Lisp_Object string, bound, noerror, count;
1027{
1028 return search_command (string, bound, noerror, count, -1, 1);
1029}
1030
1031DEFUN ("re-search-forward", Fre_search_forward, Sre_search_forward, 1, 4,
1032 "sRE search: ",
1033 "Search forward from point for regular expression REGEXP.\n\
1034Set point to the end of the occurrence found, and return point.\n\
1035An optional second argument bounds the search; it is a buffer position.\n\
1036The match found must not extend after that position.\n\
1037Optional third argument, if t, means if fail just return nil (no error).\n\
1038 If not nil and not t, move to limit of search and return nil.\n\
1039Optional fourth argument is repeat count--search for successive occurrences.\n\
1040See also the functions `match-beginning', `match-end' and `replace-match'.")
1041 (string, bound, noerror, count)
1042 Lisp_Object string, bound, noerror, count;
1043{
1044 return search_command (string, bound, noerror, count, 1, 1);
1045}
1046\f
1047DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 3, 0,
1048 "Replace text matched by last search with NEWTEXT.\n\
1049If second arg FIXEDCASE is non-nil, do not alter case of replacement text.\n\
1050Otherwise convert to all caps or cap initials, like replaced text.\n\
1051If third arg LITERAL is non-nil, insert NEWTEXT literally.\n\
1052Otherwise treat `\\' as special:\n\
1053 `\\&' in NEWTEXT means substitute original matched text.\n\
1054 `\\N' means substitute what matched the Nth `\\(...\\)'.\n\
1055 If Nth parens didn't match, substitute nothing.\n\
1056 `\\\\' means insert one `\\'.\n\
1113d9db 1057FIXEDCASE and LITERAL are optional arguments.\n\
ca1d1d23
JB
1058Leaves point at end of replacement text.")
1059 (string, fixedcase, literal)
1060 Lisp_Object string, fixedcase, literal;
1061{
1062 enum { nochange, all_caps, cap_initial } case_action;
1063 register int pos, last;
1064 int some_multiletter_word;
1065 int some_letter = 0;
1066 register int c, prevc;
1067 int inslen;
1068
1069 CHECK_STRING (string, 0);
1070
1071 case_action = nochange; /* We tried an initialization */
1072 /* but some C compilers blew it */
4746118a
JB
1073
1074 if (search_regs.num_regs <= 0)
1075 error ("replace-match called before any match found");
1076
ca1d1d23
JB
1077 if (search_regs.start[0] < BEGV
1078 || search_regs.start[0] > search_regs.end[0]
1079 || search_regs.end[0] > ZV)
1080 args_out_of_range(make_number (search_regs.start[0]),
1081 make_number (search_regs.end[0]));
1082
1083 if (NILP (fixedcase))
1084 {
1085 /* Decide how to casify by examining the matched text. */
1086
1087 last = search_regs.end[0];
1088 prevc = '\n';
1089 case_action = all_caps;
1090
1091 /* some_multiletter_word is set nonzero if any original word
1092 is more than one letter long. */
1093 some_multiletter_word = 0;
1094
1095 for (pos = search_regs.start[0]; pos < last; pos++)
1096 {
1097 c = FETCH_CHAR (pos);
1098 if (LOWERCASEP (c))
1099 {
1100 /* Cannot be all caps if any original char is lower case */
1101
1102 case_action = cap_initial;
1103 if (SYNTAX (prevc) != Sword)
1104 {
1105 /* Cannot even be cap initials
1106 if some original initial is lower case */
1107 case_action = nochange;
1108 break;
1109 }
1110 else
1111 some_multiletter_word = 1;
1112 }
1113 else if (!NOCASEP (c))
1114 {
1115 some_letter = 1;
1116 if (!some_multiletter_word && SYNTAX (prevc) == Sword)
1117 some_multiletter_word = 1;
1118 }
1119
1120 prevc = c;
1121 }
1122
1123 /* Do not make new text all caps
1124 if the original text contained only single letter words. */
1125 if (case_action == all_caps && !some_multiletter_word)
1126 case_action = cap_initial;
1127
1128 if (!some_letter) case_action = nochange;
1129 }
1130
1131 SET_PT (search_regs.end[0]);
1132 if (!NILP (literal))
1133 Finsert (1, &string);
1134 else
1135 {
1136 struct gcpro gcpro1;
1137 GCPRO1 (string);
1138
1139 for (pos = 0; pos < XSTRING (string)->size; pos++)
1140 {
1141 c = XSTRING (string)->data[pos];
1142 if (c == '\\')
1143 {
1144 c = XSTRING (string)->data[++pos];
1145 if (c == '&')
1146 Finsert_buffer_substring (Fcurrent_buffer (),
1147 make_number (search_regs.start[0]),
1148 make_number (search_regs.end[0]));
4746118a 1149 else if (c >= '1' && c <= search_regs.num_regs + '0')
ca1d1d23
JB
1150 {
1151 if (search_regs.start[c - '0'] >= 1)
1152 Finsert_buffer_substring (Fcurrent_buffer (),
1153 make_number (search_regs.start[c - '0']),
1154 make_number (search_regs.end[c - '0']));
1155 }
1156 else
1157 insert_char (c);
1158 }
1159 else
1160 insert_char (c);
1161 }
1162 UNGCPRO;
1163 }
1164
1165 inslen = point - (search_regs.end[0]);
1166 del_range (search_regs.start[0], search_regs.end[0]);
1167
1168 if (case_action == all_caps)
1169 Fupcase_region (make_number (point - inslen), make_number (point));
1170 else if (case_action == cap_initial)
1171 upcase_initials_region (make_number (point - inslen), make_number (point));
1172 return Qnil;
1173}
1174\f
1175static Lisp_Object
1176match_limit (num, beginningp)
1177 Lisp_Object num;
1178 int beginningp;
1179{
1180 register int n;
1181
1182 CHECK_NUMBER (num, 0);
1183 n = XINT (num);
4746118a
JB
1184 if (n < 0 || n >= search_regs.num_regs)
1185 args_out_of_range (num, make_number (search_regs.num_regs));
1186 if (search_regs.num_regs <= 0
1187 || search_regs.start[n] < 0)
ca1d1d23
JB
1188 return Qnil;
1189 return (make_number ((beginningp) ? search_regs.start[n]
1190 : search_regs.end[n]));
1191}
1192
1193DEFUN ("match-beginning", Fmatch_beginning, Smatch_beginning, 1, 1, 0,
1194 "Return position of start of text matched by last search.\n\
1195ARG, a number, specifies which parenthesized expression in the last regexp.\n\
1196 Value is nil if ARGth pair didn't match, or there were less than ARG pairs.\n\
1197Zero means the entire text matched by the whole regexp or whole string.")
1198 (num)
1199 Lisp_Object num;
1200{
1201 return match_limit (num, 1);
1202}
1203
1204DEFUN ("match-end", Fmatch_end, Smatch_end, 1, 1, 0,
1205 "Return position of end of text matched by last search.\n\
1206ARG, a number, specifies which parenthesized expression in the last regexp.\n\
1207 Value is nil if ARGth pair didn't match, or there were less than ARG pairs.\n\
1208Zero means the entire text matched by the whole regexp or whole string.")
1209 (num)
1210 Lisp_Object num;
1211{
1212 return match_limit (num, 0);
1213}
1214
1215DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 0, 0,
1216 "Return a list containing all info on what the last search matched.\n\
1217Element 2N is `(match-beginning N)'; element 2N + 1 is `(match-end N)'.\n\
1218All the elements are markers or nil (nil if the Nth pair didn't match)\n\
1219if the last match was on a buffer; integers or nil if a string was matched.\n\
1220Use `store-match-data' to reinstate the data in this list.")
1221 ()
1222{
4746118a 1223 Lisp_Object *data;
ca1d1d23
JB
1224 int i, len;
1225
daa37602
JB
1226 if (NILP (last_thing_searched))
1227 error ("match-data called before any match found");
1228
4746118a
JB
1229 data = (Lisp_Object *) alloca ((2 * search_regs.num_regs)
1230 * sizeof (Lisp_Object));
1231
ca1d1d23 1232 len = -1;
4746118a 1233 for (i = 0; i < search_regs.num_regs; i++)
ca1d1d23
JB
1234 {
1235 int start = search_regs.start[i];
1236 if (start >= 0)
1237 {
daa37602 1238 if (EQ (last_thing_searched, Qt))
ca1d1d23
JB
1239 {
1240 XFASTINT (data[2 * i]) = start;
1241 XFASTINT (data[2 * i + 1]) = search_regs.end[i];
1242 }
daa37602 1243 else if (XTYPE (last_thing_searched) == Lisp_Buffer)
ca1d1d23
JB
1244 {
1245 data[2 * i] = Fmake_marker ();
daa37602
JB
1246 Fset_marker (data[2 * i],
1247 make_number (start),
1248 last_thing_searched);
ca1d1d23
JB
1249 data[2 * i + 1] = Fmake_marker ();
1250 Fset_marker (data[2 * i + 1],
daa37602
JB
1251 make_number (search_regs.end[i]),
1252 last_thing_searched);
ca1d1d23 1253 }
daa37602
JB
1254 else
1255 /* last_thing_searched must always be Qt, a buffer, or Qnil. */
1256 abort ();
1257
ca1d1d23
JB
1258 len = i;
1259 }
1260 else
1261 data[2 * i] = data [2 * i + 1] = Qnil;
1262 }
1263 return Flist (2 * len + 2, data);
1264}
1265
1266
1267DEFUN ("store-match-data", Fstore_match_data, Sstore_match_data, 1, 1, 0,
1268 "Set internal data on last search match from elements of LIST.\n\
1269LIST should have been created by calling `match-data' previously.")
1270 (list)
1271 register Lisp_Object list;
1272{
1273 register int i;
1274 register Lisp_Object marker;
1275
1276 if (!CONSP (list) && !NILP (list))
1277 list = wrong_type_argument (Qconsp, list, 0);
1278
daa37602
JB
1279 /* Unless we find a marker with a buffer in LIST, assume that this
1280 match data came from a string. */
1281 last_thing_searched = Qt;
1282
4746118a
JB
1283 /* Allocate registers if they don't already exist. */
1284 {
1285 int length = Flength (list) / 2;
1286
1287 if (length > search_regs.num_regs)
1288 {
1113d9db
JB
1289 if (search_regs.num_regs == 0)
1290 {
1291 search_regs.start
1292 = (regoff_t *) xmalloc (length * sizeof (regoff_t));
1293 search_regs.end
1294 = (regoff_t *) xmalloc (length * sizeof (regoff_t));
1295 }
4746118a 1296 else
1113d9db
JB
1297 {
1298 search_regs.start
1299 = (regoff_t *) xrealloc (search_regs.start,
1300 length * sizeof (regoff_t));
1301 search_regs.end
1302 = (regoff_t *) xrealloc (search_regs.end,
1303 length * sizeof (regoff_t));
1304 }
4746118a 1305
1113d9db
JB
1306 re_set_registers (&searchbuf, &search_regs, length,
1307 search_regs.start, search_regs.end);
4746118a
JB
1308 }
1309 }
1310
1311 for (i = 0; i < search_regs.num_regs; i++)
ca1d1d23
JB
1312 {
1313 marker = Fcar (list);
1314 if (NILP (marker))
1315 {
1316 search_regs.start[i] = -1;
1317 list = Fcdr (list);
1318 }
1319 else
1320 {
daa37602
JB
1321 if (XTYPE (marker) == Lisp_Marker)
1322 {
1323 if (XMARKER (marker)->buffer == 0)
1324 XFASTINT (marker) = 0;
1325 else
1326 XSET (last_thing_searched, Lisp_Buffer,
1327 XMARKER (marker)->buffer);
1328 }
ca1d1d23
JB
1329
1330 CHECK_NUMBER_COERCE_MARKER (marker, 0);
1331 search_regs.start[i] = XINT (marker);
1332 list = Fcdr (list);
1333
1334 marker = Fcar (list);
1335 if (XTYPE (marker) == Lisp_Marker
1336 && XMARKER (marker)->buffer == 0)
1337 XFASTINT (marker) = 0;
1338
1339 CHECK_NUMBER_COERCE_MARKER (marker, 0);
1340 search_regs.end[i] = XINT (marker);
1341 }
1342 list = Fcdr (list);
1343 }
1344
1345 return Qnil;
1346}
1347
1348/* Quote a string to inactivate reg-expr chars */
1349
1350DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
1351 "Return a regexp string which matches exactly STRING and nothing else.")
1352 (str)
1353 Lisp_Object str;
1354{
1355 register unsigned char *in, *out, *end;
1356 register unsigned char *temp;
1357
1358 CHECK_STRING (str, 0);
1359
1360 temp = (unsigned char *) alloca (XSTRING (str)->size * 2);
1361
1362 /* Now copy the data into the new string, inserting escapes. */
1363
1364 in = XSTRING (str)->data;
1365 end = in + XSTRING (str)->size;
1366 out = temp;
1367
1368 for (; in != end; in++)
1369 {
1370 if (*in == '[' || *in == ']'
1371 || *in == '*' || *in == '.' || *in == '\\'
1372 || *in == '?' || *in == '+'
1373 || *in == '^' || *in == '$')
1374 *out++ = '\\';
1375 *out++ = *in;
1376 }
1377
1378 return make_string (temp, out - temp);
1379}
1380\f
1381syms_of_search ()
1382{
1383 register int i;
1384
1385 searchbuf.allocated = 100;
8c0e7b73 1386 searchbuf.buffer = (unsigned char *) malloc (searchbuf.allocated);
ca1d1d23
JB
1387 searchbuf.fastmap = search_fastmap;
1388
1389 Qsearch_failed = intern ("search-failed");
1390 staticpro (&Qsearch_failed);
1391 Qinvalid_regexp = intern ("invalid-regexp");
1392 staticpro (&Qinvalid_regexp);
1393
1394 Fput (Qsearch_failed, Qerror_conditions,
1395 Fcons (Qsearch_failed, Fcons (Qerror, Qnil)));
1396 Fput (Qsearch_failed, Qerror_message,
1397 build_string ("Search failed"));
1398
1399 Fput (Qinvalid_regexp, Qerror_conditions,
1400 Fcons (Qinvalid_regexp, Fcons (Qerror, Qnil)));
1401 Fput (Qinvalid_regexp, Qerror_message,
1402 build_string ("Invalid regexp"));
1403
1404 last_regexp = Qnil;
1405 staticpro (&last_regexp);
1406
daa37602
JB
1407 last_thing_searched = Qnil;
1408 staticpro (&last_thing_searched);
1409
ca1d1d23
JB
1410 defsubr (&Sstring_match);
1411 defsubr (&Slooking_at);
1412 defsubr (&Sskip_chars_forward);
1413 defsubr (&Sskip_chars_backward);
1414 defsubr (&Ssearch_forward);
1415 defsubr (&Ssearch_backward);
1416 defsubr (&Sword_search_forward);
1417 defsubr (&Sword_search_backward);
1418 defsubr (&Sre_search_forward);
1419 defsubr (&Sre_search_backward);
1420 defsubr (&Sreplace_match);
1421 defsubr (&Smatch_beginning);
1422 defsubr (&Smatch_end);
1423 defsubr (&Smatch_data);
1424 defsubr (&Sstore_match_data);
1425 defsubr (&Sregexp_quote);
1426}