diff options
| author | Paul Eggert | 2014-04-22 14:32:51 -0700 |
|---|---|---|
| committer | Paul Eggert | 2014-04-22 14:32:51 -0700 |
| commit | 42e910349d699ee3f8024371ca1e60e015fc6aa7 (patch) | |
| tree | ba589f3f7c278671f0ae9c5c8f15c241ae8dd674 /src/search.c | |
| parent | 4f96579371290b201a973072a1c2f237755bb954 (diff) | |
| parent | 34e856d5ac828753b7be20e2471f39fb613f7f40 (diff) | |
| download | emacs-42e910349d699ee3f8024371ca1e60e015fc6aa7.tar.gz emacs-42e910349d699ee3f8024371ca1e60e015fc6aa7.zip | |
Merge from emacs-24; up to 2014-04-22T20:19:17Z!eggert@cs.ucla.edu
Diffstat (limited to 'src/search.c')
| -rw-r--r-- | src/search.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/search.c b/src/search.c index 9bec825abcd..ee449213ace 100644 --- a/src/search.c +++ b/src/search.c | |||
| @@ -3098,6 +3098,169 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0, | |||
| 3098 | out - temp, | 3098 | out - temp, |
| 3099 | STRING_MULTIBYTE (string)); | 3099 | STRING_MULTIBYTE (string)); |
| 3100 | } | 3100 | } |
| 3101 | |||
| 3102 | /* Like find_newline, but doesn't use the cache, and only searches forward. */ | ||
| 3103 | static ptrdiff_t | ||
| 3104 | find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end, | ||
| 3105 | ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *shortage, | ||
| 3106 | ptrdiff_t *bytepos, bool allow_quit) | ||
| 3107 | { | ||
| 3108 | if (count > 0) | ||
| 3109 | { | ||
| 3110 | if (!end) | ||
| 3111 | end = ZV, end_byte = ZV_BYTE; | ||
| 3112 | } | ||
| 3113 | else | ||
| 3114 | { | ||
| 3115 | if (!end) | ||
| 3116 | end = BEGV, end_byte = BEGV_BYTE; | ||
| 3117 | } | ||
| 3118 | if (end_byte == -1) | ||
| 3119 | end_byte = CHAR_TO_BYTE (end); | ||
| 3120 | |||
| 3121 | if (shortage != 0) | ||
| 3122 | *shortage = 0; | ||
| 3123 | |||
| 3124 | immediate_quit = allow_quit; | ||
| 3125 | |||
| 3126 | if (count > 0) | ||
| 3127 | while (start != end) | ||
| 3128 | { | ||
| 3129 | /* Our innermost scanning loop is very simple; it doesn't know | ||
| 3130 | about gaps, buffer ends, or the newline cache. ceiling is | ||
| 3131 | the position of the last character before the next such | ||
| 3132 | obstacle --- the last character the dumb search loop should | ||
| 3133 | examine. */ | ||
| 3134 | ptrdiff_t tem, ceiling_byte = end_byte - 1; | ||
| 3135 | |||
| 3136 | if (start_byte == -1) | ||
| 3137 | start_byte = CHAR_TO_BYTE (start); | ||
| 3138 | |||
| 3139 | /* The dumb loop can only scan text stored in contiguous | ||
| 3140 | bytes. BUFFER_CEILING_OF returns the last character | ||
| 3141 | position that is contiguous, so the ceiling is the | ||
| 3142 | position after that. */ | ||
| 3143 | tem = BUFFER_CEILING_OF (start_byte); | ||
| 3144 | ceiling_byte = min (tem, ceiling_byte); | ||
| 3145 | |||
| 3146 | { | ||
| 3147 | /* The termination address of the dumb loop. */ | ||
| 3148 | unsigned char *lim_addr = BYTE_POS_ADDR (ceiling_byte) + 1; | ||
| 3149 | ptrdiff_t lim_byte = ceiling_byte + 1; | ||
| 3150 | |||
| 3151 | /* Nonpositive offsets (relative to LIM_ADDR and LIM_BYTE) | ||
| 3152 | of the base, the cursor, and the next line. */ | ||
| 3153 | ptrdiff_t base = start_byte - lim_byte; | ||
| 3154 | ptrdiff_t cursor, next; | ||
| 3155 | |||
| 3156 | for (cursor = base; cursor < 0; cursor = next) | ||
| 3157 | { | ||
| 3158 | /* The dumb loop. */ | ||
| 3159 | unsigned char *nl = memchr (lim_addr + cursor, '\n', - cursor); | ||
| 3160 | next = nl ? nl - lim_addr : 0; | ||
| 3161 | |||
| 3162 | if (! nl) | ||
| 3163 | break; | ||
| 3164 | next++; | ||
| 3165 | |||
| 3166 | if (--count == 0) | ||
| 3167 | { | ||
| 3168 | immediate_quit = 0; | ||
| 3169 | if (bytepos) | ||
| 3170 | *bytepos = lim_byte + next; | ||
| 3171 | return BYTE_TO_CHAR (lim_byte + next); | ||
| 3172 | } | ||
| 3173 | } | ||
| 3174 | |||
| 3175 | start_byte = lim_byte; | ||
| 3176 | start = BYTE_TO_CHAR (start_byte); | ||
| 3177 | } | ||
| 3178 | } | ||
| 3179 | |||
| 3180 | immediate_quit = 0; | ||
| 3181 | if (shortage) | ||
| 3182 | *shortage = count; | ||
| 3183 | if (bytepos) | ||
| 3184 | { | ||
| 3185 | *bytepos = start_byte == -1 ? CHAR_TO_BYTE (start) : start_byte; | ||
| 3186 | eassert (*bytepos == CHAR_TO_BYTE (start)); | ||
| 3187 | } | ||
| 3188 | return start; | ||
| 3189 | } | ||
| 3190 | |||
| 3191 | DEFUN ("newline-cache-check", Fnewline_cache_check, Snewline_cache_check, | ||
| 3192 | 0, 1, 0, | ||
| 3193 | doc: /* Check the newline cache of BUFFER against buffer contents. | ||
| 3194 | |||
| 3195 | BUFFER defaults to the current buffer. | ||
| 3196 | |||
| 3197 | Value is an array of 2 sub-arrays of buffer positions for newlines, | ||
| 3198 | the first based on the cache, the second based on actually scanning | ||
| 3199 | the buffer. If the buffer doesn't have a cache, the value is nil. */) | ||
| 3200 | (Lisp_Object buffer) | ||
| 3201 | { | ||
| 3202 | struct buffer *buf; | ||
| 3203 | ptrdiff_t shortage, nl_count_cache, nl_count_buf; | ||
| 3204 | Lisp_Object cache_newlines, buf_newlines, val; | ||
| 3205 | ptrdiff_t from, found, i; | ||
| 3206 | |||
| 3207 | if (NILP (buffer)) | ||
| 3208 | buf = current_buffer; | ||
| 3209 | else | ||
| 3210 | { | ||
| 3211 | CHECK_BUFFER (buffer); | ||
| 3212 | buf = XBUFFER (buffer); | ||
| 3213 | } | ||
| 3214 | if (buf->base_buffer) | ||
| 3215 | buf = buf->base_buffer; | ||
| 3216 | |||
| 3217 | /* If the buffer doesn't have a newline cache, return nil. */ | ||
| 3218 | if (NILP (BVAR (buf, cache_long_scans)) | ||
| 3219 | || buf->newline_cache == NULL) | ||
| 3220 | return Qnil; | ||
| 3221 | |||
| 3222 | /* How many newlines are there according to the cache? */ | ||
| 3223 | find_newline (BUF_BEG (buf), BUF_BEG_BYTE (buf), | ||
| 3224 | BUF_Z (buf), BUF_Z_BYTE (buf), | ||
| 3225 | TYPE_MAXIMUM (ptrdiff_t), &shortage, NULL, true); | ||
| 3226 | nl_count_cache = TYPE_MAXIMUM (ptrdiff_t) - shortage; | ||
| 3227 | |||
| 3228 | /* Create vector and populate it. */ | ||
| 3229 | cache_newlines = make_uninit_vector (nl_count_cache); | ||
| 3230 | for (from = BUF_BEG( buf), found = from, i = 0; | ||
| 3231 | from < BUF_Z (buf); | ||
| 3232 | from = found, i++) | ||
| 3233 | { | ||
| 3234 | ptrdiff_t from_byte = CHAR_TO_BYTE (from); | ||
| 3235 | |||
| 3236 | found = find_newline (from, from_byte, 0, -1, 1, &shortage, NULL, true); | ||
| 3237 | if (shortage == 0) | ||
| 3238 | ASET (cache_newlines, i, make_number (found - 1)); | ||
| 3239 | } | ||
| 3240 | |||
| 3241 | /* Now do the same, but without using the cache. */ | ||
| 3242 | find_newline1 (BUF_BEG (buf), BUF_BEG_BYTE (buf), | ||
| 3243 | BUF_Z (buf), BUF_Z_BYTE (buf), | ||
| 3244 | TYPE_MAXIMUM (ptrdiff_t), &shortage, NULL, true); | ||
| 3245 | nl_count_buf = TYPE_MAXIMUM (ptrdiff_t) - shortage; | ||
| 3246 | buf_newlines = make_uninit_vector (nl_count_buf); | ||
| 3247 | for (from = BUF_BEG( buf), found = from, i = 0; | ||
| 3248 | from < BUF_Z (buf); | ||
| 3249 | from = found, i++) | ||
| 3250 | { | ||
| 3251 | ptrdiff_t from_byte = CHAR_TO_BYTE (from); | ||
| 3252 | |||
| 3253 | found = find_newline1 (from, from_byte, 0, -1, 1, &shortage, NULL, true); | ||
| 3254 | if (shortage == 0) | ||
| 3255 | ASET (buf_newlines, i, make_number (found - 1)); | ||
| 3256 | } | ||
| 3257 | |||
| 3258 | /* Construct the value and return it. */ | ||
| 3259 | val = make_uninit_vector (2); | ||
| 3260 | ASET (val, 0, cache_newlines); | ||
| 3261 | ASET (val, 1, buf_newlines); | ||
| 3262 | return val; | ||
| 3263 | } | ||
| 3101 | 3264 | ||
| 3102 | void | 3265 | void |
| 3103 | syms_of_search (void) | 3266 | syms_of_search (void) |
| @@ -3170,4 +3333,5 @@ is to bind it with `let' around a small expression. */); | |||
| 3170 | defsubr (&Smatch_data); | 3333 | defsubr (&Smatch_data); |
| 3171 | defsubr (&Sset_match_data); | 3334 | defsubr (&Sset_match_data); |
| 3172 | defsubr (&Sregexp_quote); | 3335 | defsubr (&Sregexp_quote); |
| 3336 | defsubr (&Snewline_cache_check); | ||
| 3173 | } | 3337 | } |