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