aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJim Blandy1994-10-08 22:15:15 +0000
committerJim Blandy1994-10-08 22:15:15 +0000
commit9169c321e5e6b1fc3d8e88b53d845d7791d0454b (patch)
treeb0f980a90c3595393b805408330e4351920f871d /src
parent56e1065ec396c40e81518e603444edecae4320f2 (diff)
downloademacs-9169c321e5e6b1fc3d8e88b53d845d7791d0454b.tar.gz
emacs-9169c321e5e6b1fc3d8e88b53d845d7791d0454b.zip
* search.c: #include "region-cache.h".
(max, min): Make these functions, not macros; we'd like to pass them arguments that would be bad to evaluate more than once. (newline_cache_on_off): New function. (scan_buffer): New argument END. Call newline_cache_on_off. If this buffer's newline cache is enabled, consult it to see if we need to scan a region for newlines, and store information in the cache after doing so. (find_next_newline): Pass new arg to scan_buffer. (find_before_next_newline): New function.
Diffstat (limited to 'src')
-rw-r--r--src/search.c299
1 files changed, 227 insertions, 72 deletions
diff --git a/src/search.c b/src/search.c
index c0a778697ad..bb871395b74 100644
--- a/src/search.c
+++ b/src/search.c
@@ -22,15 +22,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22#include "lisp.h" 22#include "lisp.h"
23#include "syntax.h" 23#include "syntax.h"
24#include "buffer.h" 24#include "buffer.h"
25#include "region-cache.h"
25#include "commands.h" 26#include "commands.h"
26#include "blockinput.h" 27#include "blockinput.h"
27 28
28#include <sys/types.h> 29#include <sys/types.h>
29#include "regex.h" 30#include "regex.h"
30 31
31#define max(a, b) ((a) > (b) ? (a) : (b))
32#define min(a, b) ((a) < (b) ? (a) : (b))
33
34/* We compile regexps into this buffer and then use it for searching. */ 32/* We compile regexps into this buffer and then use it for searching. */
35 33
36struct re_pattern_buffer searchbuf; 34struct re_pattern_buffer searchbuf;
@@ -253,34 +251,94 @@ fast_string_match (regexp, string)
253 return val; 251 return val;
254} 252}
255 253
256/* Search for COUNT instances of the character TARGET, starting at START. 254/* max and min. */
257 If COUNT is negative, search backwards. 255
256static int
257max (a, b)
258 int a, b;
259{
260 return ((a > b) ? a : b);
261}
262
263static int
264min (a, b)
265 int a, b;
266{
267 return ((a < b) ? a : b);
268}
269
270
271/* The newline cache: remembering which sections of text have no newlines. */
272
273/* If the user has requested newline caching, make sure it's on.
274 Otherwise, make sure it's off.
275 This is our cheezy way of associating an action with the change of
276 state of a buffer-local variable. */
277static void
278newline_cache_on_off (buf)
279 struct buffer *buf;
280{
281 if (NILP (buf->cache_long_line_scans))
282 {
283 /* It should be off. */
284 if (buf->newline_cache)
285 {
286 free_region_cache (buf->newline_cache);
287 buf->newline_cache = 0;
288 }
289 }
290 else
291 {
292 /* It should be on. */
293 if (buf->newline_cache == 0)
294 buf->newline_cache = new_region_cache ();
295 }
296}
297
298
299/* Search for COUNT instances of the character TARGET between START and END.
300
301 If COUNT is positive, search forwards; END must be >= START.
302 If COUNT is negative, search backwards for the -COUNTth instance;
303 END must be <= START.
304 If COUNT is zero, do anything you please; run rogue, for all I care.
305
306 If END is zero, use BEGV or ZV instead, as appropriate for the
307 direction indicated by COUNT.
258 308
259 If we find COUNT instances, set *SHORTAGE to zero, and return the 309 If we find COUNT instances, set *SHORTAGE to zero, and return the
260 position after the COUNTth match. Note that for reverse motion 310 position after the COUNTth match. Note that for reverse motion
261 this is not the same as the usual convention for Emacs motion commands. 311 this is not the same as the usual convention for Emacs motion commands.
262 312
263 If we don't find COUNT instances before reaching the end of the 313 If we don't find COUNT instances before reaching END, set *SHORTAGE
264 buffer (or the beginning, if scanning backwards), set *SHORTAGE to 314 to the number of TARGETs left unfound, and return END.
265 the number of TARGETs left unfound, and return the end of the
266 buffer we bumped up against.
267 315
268 If ALLOW_QUIT is non-zero, set immediate_quit. That's good to do 316 If ALLOW_QUIT is non-zero, set immediate_quit. That's good to do
269 except when inside redisplay. */ 317 except when inside redisplay. */
270 318
271scan_buffer (target, start, count, shortage, allow_quit) 319scan_buffer (target, start, end, count, shortage, allow_quit)
272 int *shortage, start; 320 register int target;
273 register int count, target; 321 int start, end;
322 int count;
323 int *shortage;
274 int allow_quit; 324 int allow_quit;
275{ 325{
276 int limit = ((count > 0) ? ZV - 1 : BEGV); 326 struct region_cache *newline_cache;
277 int direction = ((count > 0) ? 1 : -1); 327 int direction;
278 328
279 register unsigned char *cursor; 329 if (count > 0)
280 unsigned char *base; 330 {
331 direction = 1;
332 if (! end) end = ZV;
333 }
334 else
335 {
336 direction = -1;
337 if (! end) end = BEGV;
338 }
281 339
282 register int ceiling; 340 newline_cache_on_off (current_buffer);
283 register unsigned char *ceiling_addr; 341 newline_cache = current_buffer->newline_cache;
284 342
285 if (shortage != 0) 343 if (shortage != 0)
286 *shortage = 0; 344 *shortage = 0;
@@ -288,78 +346,175 @@ scan_buffer (target, start, count, shortage, allow_quit)
288 immediate_quit = allow_quit; 346 immediate_quit = allow_quit;
289 347
290 if (count > 0) 348 if (count > 0)
291 while (start != limit + 1) 349 while (start != end)
292 { 350 {
293 ceiling = BUFFER_CEILING_OF (start); 351 /* Our innermost scanning loop is very simple; it doesn't know
294 ceiling = min (limit, ceiling); 352 about gaps, buffer ends, or the newline cache. ceiling is
295 ceiling_addr = &FETCH_CHAR (ceiling) + 1; 353 the position of the last character before the next such
296 base = (cursor = &FETCH_CHAR (start)); 354 obstacle --- the last character the dumb search loop should
297 while (1) 355 examine. */
298 { 356 register int ceiling = end - 1;
299 while (*cursor != target && ++cursor != ceiling_addr) 357
300 ; 358 /* If we're looking for a newline, consult the newline cache
301 if (cursor != ceiling_addr) 359 to see where we can avoid some scanning. */
302 { 360 if (target == '\n' && newline_cache)
303 if (--count == 0) 361 {
304 { 362 int next_change;
305 immediate_quit = 0; 363 immediate_quit = 0;
306 return (start + cursor - base + 1); 364 while (region_cache_forward
307 } 365 (current_buffer, newline_cache, start, &next_change))
308 else 366 start = next_change;
309 if (++cursor == ceiling_addr) 367 immediate_quit = 1;
310 break; 368
311 } 369 /* start should never be after end. */
312 else 370 if (start >= end)
313 break; 371 start = end - 1;
314 } 372
315 start += cursor - base; 373 /* Now the text after start is an unknown region, and
374 next_change is the position of the next known region. */
375 ceiling = min (next_change - 1, ceiling);
376 }
377
378 /* The dumb loop can only scan text stored in contiguous
379 bytes. BUFFER_CEILING_OF returns the last character
380 position that is contiguous, so the ceiling is the
381 position after that. */
382 ceiling = min (BUFFER_CEILING_OF (start), ceiling);
383
384 {
385 /* The termination address of the dumb loop. */
386 register unsigned char *ceiling_addr = &FETCH_CHAR (ceiling) + 1;
387 register unsigned char *cursor = &FETCH_CHAR (start);
388 unsigned char *base = cursor;
389
390 while (cursor < ceiling_addr)
391 {
392 unsigned char *scan_start = cursor;
393
394 /* The dumb loop. */
395 while (*cursor != target && ++cursor < ceiling_addr)
396 ;
397
398 /* If we're looking for newlines, cache the fact that
399 the region from start to cursor is free of them. */
400 if (target == '\n' && newline_cache)
401 know_region_cache (current_buffer, newline_cache,
402 start + scan_start - base,
403 start + cursor - base);
404
405 /* Did we find the target character? */
406 if (cursor < ceiling_addr)
407 {
408 if (--count == 0)
409 {
410 immediate_quit = 0;
411 return (start + cursor - base + 1);
412 }
413 cursor++;
414 }
415 }
416
417 start += cursor - base;
418 }
316 } 419 }
317 else 420 else
318 { 421 while (start > end)
319 start--; /* first character we scan */ 422 {
320 while (start > limit - 1) 423 /* The last character to check before the next obstacle. */
321 { /* we WILL scan under start */ 424 register int ceiling = end;
322 ceiling = BUFFER_FLOOR_OF (start); 425
323 ceiling = max (limit, ceiling); 426 /* Consult the newline cache, if appropriate. */
324 ceiling_addr = &FETCH_CHAR (ceiling) - 1; 427 if (target == '\n' && newline_cache)
325 base = (cursor = &FETCH_CHAR (start)); 428 {
326 cursor++; 429 int next_change;
327 while (1) 430 immediate_quit = 0;
328 { 431 while (region_cache_backward
329 while (--cursor != ceiling_addr && *cursor != target) 432 (current_buffer, newline_cache, start, &next_change))
330 ; 433 start = next_change;
331 if (cursor != ceiling_addr) 434 immediate_quit = 1;
332 { 435
333 if (++count == 0) 436 /* Start should never be at or before end. */
334 { 437 if (start <= end)
335 immediate_quit = 0; 438 start = end + 1;
336 return (start + cursor - base + 1); 439
337 } 440 /* Now the text before start is an unknown region, and
338 } 441 next_change is the position of the next known region. */
339 else 442 ceiling = max (next_change, ceiling);
340 break; 443 }
341 } 444
342 start += cursor - base; 445 /* Stop scanning before the gap. */
343 } 446 ceiling = max (BUFFER_FLOOR_OF (start - 1), ceiling);
344 } 447
448 {
449 /* The termination address of the dumb loop. */
450 register unsigned char *ceiling_addr = &FETCH_CHAR (ceiling);
451 register unsigned char *cursor = &FETCH_CHAR (start - 1);
452 unsigned char *base = cursor;
453
454 while (cursor >= ceiling_addr)
455 {
456 unsigned char *scan_start = cursor;
457
458 while (*cursor != target && --cursor >= ceiling_addr)
459 ;
460
461 /* If we're looking for newlines, cache the fact that
462 the region from after the cursor to start is free of them. */
463 if (target == '\n' && newline_cache)
464 know_region_cache (current_buffer, newline_cache,
465 start + cursor - base,
466 start + scan_start - base);
467
468 /* Did we find the target character? */
469 if (cursor >= ceiling_addr)
470 {
471 if (++count >= 0)
472 {
473 immediate_quit = 0;
474 return (start + cursor - base);
475 }
476 cursor--;
477 }
478 }
479
480 start += cursor - base;
481 }
482 }
483
345 immediate_quit = 0; 484 immediate_quit = 0;
346 if (shortage != 0) 485 if (shortage != 0)
347 *shortage = count * direction; 486 *shortage = count * direction;
348 return (start + ((direction == 1 ? 0 : 1))); 487 return start;
349} 488}
350 489
351int 490int
352find_next_newline_no_quit (from, cnt) 491find_next_newline_no_quit (from, cnt)
353 register int from, cnt; 492 register int from, cnt;
354{ 493{
355 return scan_buffer ('\n', from, cnt, (int *) 0, 0); 494 return scan_buffer ('\n', from, 0, cnt, (int *) 0, 0);
356} 495}
357 496
358int 497int
359find_next_newline (from, cnt) 498find_next_newline (from, cnt)
360 register int from, cnt; 499 register int from, cnt;
361{ 500{
362 return scan_buffer ('\n', from, cnt, (int *) 0, 1); 501 return scan_buffer ('\n', from, 0, cnt, (int *) 0, 1);
502}
503
504
505/* Like find_next_newline, but returns position before the newline,
506 not after, and only search up to TO. This isn't just
507 find_next_newline (...)-1, because you might hit TO. */
508int
509find_before_next_newline (from, to, cnt)
510{
511 int shortage;
512 int pos = scan_buffer ('\n', from, to, cnt, &shortage, 1);
513
514 if (shortage == 0)
515 pos--;
516
517 return pos;
363} 518}
364 519
365Lisp_Object skip_chars (); 520Lisp_Object skip_chars ();