- (funcall search-function search-string nil t)
- ;; If the search string matches immediately after
- ;; the previous match, but it did not match there
- ;; before the replacement was done, ignore the match.
- (if (or (eq lastrepl (point))
- (and regexp-flag
- (eq lastrepl (match-beginning 0))
- (not match-again)))
- (if (eobp)
- nil
- ;; Don't replace the null string
- ;; right after end of previous replacement.
- (forward-char 1)
- (funcall search-function search-string nil t))
- t))
-
- ;; Save the data associated with the real match.
- ;; For speed, use only integers and reuse the list used last time.
- (setq real-match-data (match-data t real-match-data))
-
- ;; Before we make the replacement, decide whether the search string
- ;; can match again just after this match.
- (if regexp-flag
- (setq match-again (looking-at search-string)))
- ;; If time for a change, advance to next replacement string.
- (if (and (listp replacements)
- (= next-rotate-count replace-count))
- (progn
- (setq next-rotate-count
- (+ next-rotate-count repeat-count))
- (setq next-replacement (nth replacement-index replacements))
- (setq replacement-index (% (1+ replacement-index) (length replacements)))))
+ ;; Use the next match if it is already known;
+ ;; otherwise, search for a match after moving forward
+ ;; one char if progress is required.
+ (setq real-match-data
+ (if (consp match-again)
+ (progn (goto-char (nth 1 match-again))
+ match-again)
+ (and (or match-again
+ ;; MATCH-AGAIN nil means in the
+ ;; regexp case that there's no
+ ;; match adjacent to the last
+ ;; one. So, we could move
+ ;; forward, but we don't want to
+ ;; because that moves point 1
+ ;; position after the last
+ ;; replacement when everything
+ ;; has been done.
+ regexp-flag
+ (progn (forward-char 1) (not (eobp))))
+ (funcall search-function search-string limit t)
+ ;; For speed, use only integers and
+ ;; reuse the list used last time.
+ (match-data t real-match-data)))))
+
+ ;; Record whether the match is nonempty, to avoid an infinite loop
+ ;; repeatedly matching the same empty string.
+ (setq nonempty-match
+ (/= (nth 0 real-match-data) (nth 1 real-match-data)))
+
+ ;; If the match is empty, record that the next one can't be adjacent.
+ ;; Otherwise, if matching a regular expression, do the next
+ ;; match now, since the replacement for this match may
+ ;; affect whether the next match is adjacent to this one.
+ (setq match-again
+ (and nonempty-match
+ (or (not regexp-flag)
+ (and (looking-at search-string)
+ (match-data)))))
+
+ ;; Calculate the replacement string, if necessary.
+ (when replacements
+ (set-match-data real-match-data)
+ (setq next-replacement
+ (funcall (car replacements) (cdr replacements)
+ replace-count)))