diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2013-11-11 08:37:54 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2013-11-11 08:37:54 -0800 |
commit | 5389db9e7160a85080078a1cf26dbc46ace55c21 (patch) | |
tree | ae2ac2575245de6b24fa24f95d2f364f95d46649 /src/search.c | |
parent | 8ee0219ffe51c77293ded1633c9edff816c151d7 (diff) | |
download | emacs-5389db9e7160a85080078a1cf26dbc46ace55c21.tar.gz |
* search.c (find_newline): Rewrite to prefer offsets to pointers.
This avoids undefined behavior when subtracting pointers into
different aways. On my platform it also makes the code a tad
smaller and presumably faster.
Diffstat (limited to 'src/search.c')
-rw-r--r-- | src/search.c | 98 |
1 files changed, 38 insertions, 60 deletions
diff --git a/src/search.c b/src/search.c index 1d0740428d7..c9e27627cd1 100644 --- a/src/search.c +++ b/src/search.c @@ -720,58 +720,45 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end, { /* The termination address of the dumb loop. */ - register unsigned char *ceiling_addr - = BYTE_POS_ADDR (ceiling_byte) + 1; - register unsigned char *cursor - = BYTE_POS_ADDR (start_byte); - unsigned char *base = cursor; + unsigned char *lim_addr = BYTE_POS_ADDR (ceiling_byte) + 1; + ptrdiff_t lim_byte = ceiling_byte + 1; - while (cursor < ceiling_addr) - { + /* Nonpositive offsets (relative to LIM_ADDR and LIM_BYTE) + of the base, the cursor, and the next line. */ + ptrdiff_t base = start_byte - lim_byte; + ptrdiff_t cursor, next; + + for (cursor = base; cursor < 0; cursor = next) + { /* The dumb loop. */ - unsigned char *nl = memchr (cursor, '\n', ceiling_addr - cursor); + unsigned char *nl = memchr (lim_addr + cursor, '\n', - cursor); + next = nl ? nl - lim_addr : 0; /* If we're looking for newlines, cache the fact that - the region from start to cursor is free of them. */ + this line's region is free of them. */ if (newline_cache) { - unsigned char *low = cursor; - unsigned char *lim = nl ? nl : ceiling_addr; know_region_cache (current_buffer, newline_cache, - BYTE_TO_CHAR (low - base + start_byte), - BYTE_TO_CHAR (lim - base + start_byte)); + BYTE_TO_CHAR (lim_byte + cursor), + BYTE_TO_CHAR (lim_byte + next)); + /* know_region_cache can relocate buffer text. */ + lim_addr = BYTE_POS_ADDR (ceiling_byte) + 1; } if (! nl) break; + next++; if (--count == 0) { immediate_quit = 0; if (bytepos) - *bytepos = nl + 1 - base + start_byte; - return BYTE_TO_CHAR (nl + 1 - base + start_byte); - } - if (newline_cache) - { - /* The call to know_region_cache could have - allocated memory and caused relocation of buffer - text. If it did, adjust pointers into buffer - text. */ - ptrdiff_t offset = BYTE_POS_ADDR (start_byte) - base; - - if (offset != 0) - { - cursor += offset; - base += offset; - ceiling_addr += offset; - nl += offset; - } + *bytepos = lim_byte + next; + return BYTE_TO_CHAR (lim_byte + next); } - cursor = nl + 1; } - start_byte += ceiling_addr - base; + start_byte = lim_byte; start = BYTE_TO_CHAR (start_byte); } } @@ -810,24 +797,28 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end, { /* The termination address of the dumb loop. */ - register unsigned char *ceiling_addr = BYTE_POS_ADDR (ceiling_byte); - register unsigned char *cursor = BYTE_POS_ADDR (start_byte - 1); - unsigned char *base = cursor; + unsigned char *ceiling_addr = BYTE_POS_ADDR (ceiling_byte); + + /* Offsets (relative to CEILING_ADDR and CEILING_BYTE) of + the base, the cursor, and the previous line. These + offsets are at least -1. */ + ptrdiff_t base = start_byte - ceiling_byte; + ptrdiff_t cursor, prev; - while (cursor >= ceiling_addr) + for (cursor = base; 0 < cursor; cursor = prev) { - unsigned char *nl = memrchr (ceiling_addr, '\n', - cursor + 1 - ceiling_addr); + unsigned char *nl = memrchr (ceiling_addr, '\n', cursor); + prev = nl ? nl - ceiling_addr : -1; /* If we're looking for newlines, cache the fact that - the region from after the cursor to start is free of them. */ + this line's region is free of them. */ if (newline_cache) { - unsigned char *low = nl ? nl : ceiling_addr - 1; - unsigned char *lim = cursor; know_region_cache (current_buffer, newline_cache, - BYTE_TO_CHAR (low - base + start_byte), - BYTE_TO_CHAR (lim - base + start_byte)); + BYTE_TO_CHAR (ceiling_byte + prev + 1), + BYTE_TO_CHAR (ceiling_byte + cursor)); + /* know_region_cache can relocate buffer text. */ + ceiling_addr = BYTE_POS_ADDR (ceiling_byte); } if (! nl) @@ -837,25 +828,12 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end, { immediate_quit = 0; if (bytepos) - *bytepos = nl - base + start_byte; - return BYTE_TO_CHAR (nl - base + start_byte); - } - if (newline_cache) - { - ptrdiff_t offset = BYTE_POS_ADDR (start_byte - 1) - base; - - if (offset != 0) - { - cursor += offset; - base += offset; - ceiling_addr += offset; - nl += offset; - } + *bytepos = ceiling_byte + prev + 1; + return BYTE_TO_CHAR (ceiling_byte + prev + 1); } - cursor = nl - 1; } - start_byte += ceiling_addr - 1 - base; + start_byte = ceiling_byte; start = BYTE_TO_CHAR (start_byte); } } |