aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2014-04-22 20:37:35 +0300
committerEli Zaretskii2014-04-22 20:37:35 +0300
commit2f999d5275f7aab04d9e1aedc35d7c33eba94e2d (patch)
tree3fb9d81f5cc04de15d68203ee8431eb5582abf5d /src
parent30cb51f1bc9ce5976f492b5df5d30c6298f5a2aa (diff)
downloademacs-2f999d5275f7aab04d9e1aedc35d7c33eba94e2d.tar.gz
emacs-2f999d5275f7aab04d9e1aedc35d7c33eba94e2d.zip
Add debugging facility for the newline cache.
See the discussion in http://lists.gnu.org/archive/html/emacs-devel/2014-04/msg00295.html for more detail. src/search.c (find_newline1): New subroutine. (Fnewline_cache_check): New function. (syms_of_search): Defsubr it.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog6
-rw-r--r--src/search.c165
2 files changed, 171 insertions, 0 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index e8fb5f63203..98d607046c6 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
12014-04-22 Eli Zaretskii <eliz@gnu.org>
2
3 * search.c (find_newline1): New subroutine.
4 (Fnewline_cache_check): New function.
5 (syms_of_search): Defsubr it.
6
12014-04-21 Jarek Czekalski <jarekczek@poczta.onet.pl> 72014-04-21 Jarek Czekalski <jarekczek@poczta.onet.pl>
2 8
3 Fix freezing with scroll bars of GTK3 Toolkit (bug#15801). 9 Fix freezing with scroll bars of GTK3 Toolkit (bug#15801).
diff --git a/src/search.c b/src/search.c
index 3de194c5056..97087307be3 100644
--- a/src/search.c
+++ b/src/search.c
@@ -3108,6 +3108,170 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
3108 out - temp, 3108 out - temp,
3109 STRING_MULTIBYTE (string)); 3109 STRING_MULTIBYTE (string));
3110} 3110}
3111
3112/* Like find_newline, but doesn't use the cache, and only searches forward. */
3113static ptrdiff_t
3114find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
3115 ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *shortage,
3116 ptrdiff_t *bytepos, bool allow_quit)
3117{
3118 if (count > 0)
3119 {
3120 if (!end)
3121 end = ZV, end_byte = ZV_BYTE;
3122 }
3123 else
3124 {
3125 if (!end)
3126 end = BEGV, end_byte = BEGV_BYTE;
3127 }
3128 if (end_byte == -1)
3129 end_byte = CHAR_TO_BYTE (end);
3130
3131 if (shortage != 0)
3132 *shortage = 0;
3133
3134 immediate_quit = allow_quit;
3135
3136 if (count > 0)
3137 while (start != end)
3138 {
3139 /* Our innermost scanning loop is very simple; it doesn't know
3140 about gaps, buffer ends, or the newline cache. ceiling is
3141 the position of the last character before the next such
3142 obstacle --- the last character the dumb search loop should
3143 examine. */
3144 ptrdiff_t tem, ceiling_byte = end_byte - 1;
3145
3146 if (start_byte == -1)
3147 start_byte = CHAR_TO_BYTE (start);
3148
3149 /* The dumb loop can only scan text stored in contiguous
3150 bytes. BUFFER_CEILING_OF returns the last character
3151 position that is contiguous, so the ceiling is the
3152 position after that. */
3153 tem = BUFFER_CEILING_OF (start_byte);
3154 ceiling_byte = min (tem, ceiling_byte);
3155
3156 {
3157 /* The termination address of the dumb loop. */
3158 unsigned char *lim_addr = BYTE_POS_ADDR (ceiling_byte) + 1;
3159 ptrdiff_t lim_byte = ceiling_byte + 1;
3160
3161 /* Nonpositive offsets (relative to LIM_ADDR and LIM_BYTE)
3162 of the base, the cursor, and the next line. */
3163 ptrdiff_t base = start_byte - lim_byte;
3164 ptrdiff_t cursor, next;
3165
3166 for (cursor = base; cursor < 0; cursor = next)
3167 {
3168 /* The dumb loop. */
3169 unsigned char *nl = memchr (lim_addr + cursor, '\n', - cursor);
3170 next = nl ? nl - lim_addr : 0;
3171
3172 if (! nl)
3173 break;
3174 next++;
3175
3176 if (--count == 0)
3177 {
3178 immediate_quit = 0;
3179 if (bytepos)
3180 *bytepos = lim_byte + next;
3181 return BYTE_TO_CHAR (lim_byte + next);
3182 }
3183 }
3184
3185 start_byte = lim_byte;
3186 start = BYTE_TO_CHAR (start_byte);
3187 }
3188 }
3189
3190 immediate_quit = 0;
3191 if (shortage)
3192 *shortage = count;
3193 if (bytepos)
3194 {
3195 *bytepos = start_byte == -1 ? CHAR_TO_BYTE (start) : start_byte;
3196 eassert (*bytepos == CHAR_TO_BYTE (start));
3197 }
3198 return start;
3199}
3200
3201DEFUN ("newline-cache-check", Fnewline_cache_check, Snewline_cache_check,
3202 0, 1, 0,
3203 doc: /* Check the newline cache of BUFFER against buffer contents.
3204
3205BUFFER defaults to the current buffer.
3206
3207Value is an array of 2 sub-arrays of buffer positions for newlines,
3208the first based on the cache, the second based on actually scanning
3209the buffer. If the buffer doesn't have a cache, the value is nil. */)
3210 (Lisp_Object buffer)
3211{
3212 struct buffer *buf;
3213 struct region_cache *nlcache;
3214 ptrdiff_t shortage, nl_count_cache, nl_count_buf;
3215 Lisp_Object cache_newlines, buf_newlines, val;
3216 ptrdiff_t from, from_byte, found, i;
3217
3218 if (NILP (buffer))
3219 buf = current_buffer;
3220 else
3221 {
3222 CHECK_BUFFER (buffer);
3223 buf = XBUFFER (buffer);
3224 }
3225 if (buf->base_buffer)
3226 buf = buf->base_buffer;
3227
3228 /* If the buffer doesn't have a newline cache, return nil. */
3229 if (NILP (BVAR (buf, cache_long_scans))
3230 || buf->newline_cache == NULL)
3231 return Qnil;
3232
3233 /* How many newlines are there according to the cache? */
3234 find_newline (BUF_BEG (buf), BUF_BEG_BYTE (buf),
3235 BUF_Z (buf), BUF_Z_BYTE (buf),
3236 TYPE_MAXIMUM (ptrdiff_t), &shortage, NULL, true);
3237 nl_count_cache = TYPE_MAXIMUM (ptrdiff_t) - shortage;
3238
3239 /* Create vector and populate it. */
3240 cache_newlines = make_uninit_vector (nl_count_cache);
3241 for (from = BUF_BEG( buf), found = from, i = 0;
3242 from < BUF_Z (buf);
3243 from = found, i++)
3244 {
3245 ptrdiff_t from_byte = CHAR_TO_BYTE (from);
3246
3247 found = find_newline (from, from_byte, 0, -1, 1, &shortage, NULL, true);
3248 if (shortage == 0)
3249 ASET (cache_newlines, i, make_number (found - 1));
3250 }
3251
3252 /* Now do the same, but without using the cache. */
3253 find_newline1 (BUF_BEG (buf), BUF_BEG_BYTE (buf),
3254 BUF_Z (buf), BUF_Z_BYTE (buf),
3255 TYPE_MAXIMUM (ptrdiff_t), &shortage, NULL, true);
3256 nl_count_buf = TYPE_MAXIMUM (ptrdiff_t) - shortage;
3257 buf_newlines = make_uninit_vector (nl_count_buf);
3258 for (from = BUF_BEG( buf), found = from, i = 0;
3259 from < BUF_Z (buf);
3260 from = found, i++)
3261 {
3262 ptrdiff_t from_byte = CHAR_TO_BYTE (from);
3263
3264 found = find_newline1 (from, from_byte, 0, -1, 1, &shortage, NULL, true);
3265 if (shortage == 0)
3266 ASET (buf_newlines, i, make_number (found - 1));
3267 }
3268
3269 /* Construct the value and return it. */
3270 val = make_uninit_vector (2);
3271 ASET (val, 0, cache_newlines);
3272 ASET (val, 1, buf_newlines);
3273 return val;
3274}
3111 3275
3112void 3276void
3113syms_of_search (void) 3277syms_of_search (void)
@@ -3180,4 +3344,5 @@ is to bind it with `let' around a small expression. */);
3180 defsubr (&Smatch_data); 3344 defsubr (&Smatch_data);
3181 defsubr (&Sset_match_data); 3345 defsubr (&Sset_match_data);
3182 defsubr (&Sregexp_quote); 3346 defsubr (&Sregexp_quote);
3347 defsubr (&Snewline_cache_check);
3183} 3348}