changeset 63145:73d9b884e8c8

(Fmatch_data): Add optional RESEAT arg. Unchain markers in REUSE list if non-nil; free them if equal to evaporate. (Fset_match_data): Add optional RESEAT arg. Unchain markers in LIST if non-nil; free them if equal to evaporate. Use XCAR/XCDR. (restore_search_regs): Rename from restore_match_data. Uses changed. (unwind_set_match_data): New function. (record_unwind_save_match_data): New function like save-match-data.
author Kim F. Storm <storm@cua.dk>
date Wed, 08 Jun 2005 22:32:20 +0000
parents e8b95d8eb45a
children 7dced3c64549
files src/search.c
diffstat 1 files changed, 78 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/search.c	Wed Jun 08 19:41:19 2005 +0000
+++ b/src/search.c	Wed Jun 08 22:32:20 2005 +0000
@@ -2739,7 +2739,7 @@
   return match_limit (subexp, 0);
 }
 
-DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 2, 0,
+DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 3, 0,
        doc: /* Return a list containing all info on what the last search matched.
 Element 2N is `(match-beginning N)'; element 2N + 1 is `(match-end N)'.
 All the elements are markers or nil (nil if the Nth pair didn't match)
@@ -2751,17 +2751,35 @@
 this case, and if the last match was in a buffer, the buffer will get
 stored as one additional element at the end of the list.
 
-If REUSE is a list, reuse it as part of the value.  If REUSE is long enough
-to hold all the values, and if INTEGERS is non-nil, no consing is done.
+If REUSE is a list, reuse it as part of the value.  If REUSE is long
+enough to hold all the values, and if INTEGERS is non-nil, no consing
+is done.
+
+If optional third arg RESEAT is non-nil, any previous markers on the
+REUSE list will be modified to point to nowhere.
+
+If RESEAT is `evaporate', put markers back on the free list.
+Note: No other references to the markers must exist if you use this.
 
 Return value is undefined if the last search failed.  */)
-     (integers, reuse)
-     Lisp_Object integers, reuse;
+  (integers, reuse, reseat)
+     Lisp_Object integers, reuse, reseat;
 {
   Lisp_Object tail, prev;
   Lisp_Object *data;
   int i, len;
 
+  if (!NILP (reseat))
+    for (tail = reuse; CONSP (tail); tail = XCDR (tail))
+      if (MARKERP (XCAR (tail)))
+	{
+	  if (EQ (reseat, Qevaporate))
+	    free_marker (XCAR (tail));
+	  else
+	    unchain_marker (XMARKER (XCAR (tail)));
+	  XSETCAR (tail, Qnil);
+	}
+
   if (NILP (last_thing_searched))
     return Qnil;
 
@@ -2797,10 +2815,10 @@
 	    /* last_thing_searched must always be Qt, a buffer, or Qnil.  */
 	    abort ();
 
-	  len = 2*(i+1);
+	  len = 2 * i + 2;
 	}
       else
-	data[2 * i] = data [2 * i + 1] = Qnil;
+	data[2 * i] = data[2 * i + 1] = Qnil;
     }
 
   if (BUFFERP (last_thing_searched) && !NILP (integers))
@@ -2834,11 +2852,15 @@
 }
 
 
-DEFUN ("set-match-data", Fset_match_data, Sset_match_data, 1, 1, 0,
+DEFUN ("set-match-data", Fset_match_data, Sset_match_data, 1, 2, 0,
        doc: /* Set internal data on last search match from elements of LIST.
-LIST should have been created by calling `match-data' previously.  */)
-     (list)
-     register Lisp_Object list;
+LIST should have been created by calling `match-data' previously.
+
+If optional arg RESEAT is non-nil, make markers on LIST point nowhere.
+If RESEAT is `evaporate', put the markers back on the free list.
+Note: No other references to the markers must exist if you use this.  */)
+    (list, reseat)
+     register Lisp_Object list, reseat;
 {
   register int i;
   register Lisp_Object marker;
@@ -2882,9 +2904,9 @@
 	search_regs.num_regs = length;
       }
 
-    for (i = 0;; i++)
+    for (i = 0; CONSP (list); i++)
       {
-	marker = Fcar (list);
+	marker = XCAR (list);
 	if (BUFFERP (marker))
 	  {
 	    last_thing_searched = marker;
@@ -2895,12 +2917,14 @@
 	if (NILP (marker))
 	  {
 	    search_regs.start[i] = -1;
-	    list = Fcdr (list);
+	    list = XCDR (list);
 	  }
 	else
 	  {
 	    int from;
-
+	    Lisp_Object m;
+
+	    m = marker;
 	    if (MARKERP (marker))
 	      {
 		if (XMARKER (marker)->buffer == 0)
@@ -2911,17 +2935,36 @@
 
 	    CHECK_NUMBER_COERCE_MARKER (marker);
 	    from = XINT (marker);
-	    list = Fcdr (list);
-
-	    marker = Fcar (list);
+
+	    if (!NILP (reseat) && MARKERP (m))
+	      {
+		if (EQ (reseat, Qevaporate))
+		  free_marker (m);
+		else
+		  unchain_marker (XMARKER (m));
+	      }
+
+	    if ((list = XCDR (list), !CONSP (list)))
+	      break;
+
+	    m = marker = XCAR (list);
+
 	    if (MARKERP (marker) && XMARKER (marker)->buffer == 0)
 	      XSETFASTINT (marker, 0);
 
 	    CHECK_NUMBER_COERCE_MARKER (marker);
 	    search_regs.start[i] = from;
 	    search_regs.end[i] = XINT (marker);
+
+	    if (!NILP (reseat) && MARKERP (m))
+	      {
+		if (EQ (reseat, Qevaporate))
+		  free_marker (m);
+		else
+		  unchain_marker (XMARKER (m));
+	      }
 	  }
-	list = Fcdr (list);
+	list = XCDR (list);
       }
 
     for (; i < search_regs.num_regs; i++)
@@ -2959,7 +3002,7 @@
 
 /* Called upon exit from filters and sentinels. */
 void
-restore_match_data ()
+restore_search_regs ()
 {
   if (search_regs_saved)
     {
@@ -2977,6 +3020,21 @@
     }
 }
 
+static Lisp_Object
+unwind_set_match_data (list)
+     Lisp_Object list;
+{
+  return Fset_match_data (list, Qevaporate);
+}
+
+/* Called to unwind protect the match data.  */
+void
+record_unwind_save_match_data ()
+{
+  record_unwind_protect (unwind_set_match_data,
+			 Fmatch_data (Qnil, Qnil, Qnil));
+}
+
 /* Quote a string to inactivate reg-expr chars */
 
 DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,