XEmacs 21.2.28 "Hermes".
[chise/xemacs-chise.git.1] / src / fns.c
index 0b110e8..8a832a2 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -70,7 +70,7 @@ static void
 print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 {
   size_t i;
-  struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
+  Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
   size_t len = bit_vector_length (v);
   size_t last = len;
 
@@ -92,8 +92,8 @@ print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 static int
 bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
 {
-  struct Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1);
-  struct Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2);
+  Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1);
+  Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2);
 
   return ((bit_vector_length (v1) == bit_vector_length (v2)) &&
          !memcmp (v1->bits, v2->bits,
@@ -104,7 +104,7 @@ bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
 static unsigned long
 bit_vector_hash (Lisp_Object obj, int depth)
 {
-  struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
+  Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
   return HASH2 (bit_vector_length (v),
                memory_hash (v->bits,
                             BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) *
@@ -112,7 +112,7 @@ bit_vector_hash (Lisp_Object obj, int depth)
 }
 
 static const struct lrecord_description bit_vector_description[] = {
-  { XD_LISP_OBJECT, offsetof(Lisp_Bit_Vector, next), 1 },
+  { XD_LISP_OBJECT, offsetof (Lisp_Bit_Vector, next) },
   { XD_END }
 };
 
@@ -121,7 +121,7 @@ DEFINE_BASIC_LRECORD_IMPLEMENTATION ("bit-vector", bit_vector,
                                     mark_bit_vector, print_bit_vector, 0,
                                     bit_vector_equal, bit_vector_hash,
                                     bit_vector_description,
-                                    struct Lisp_Bit_Vector);
+                                    Lisp_Bit_Vector);
 \f
 DEFUN ("identity", Fidentity, 1, 1, 0, /*
 Return the argument unchanged.
@@ -184,7 +184,7 @@ length_with_bytecode_hack (Lisp_Object seq)
     return XINT (Flength (seq));
   else
     {
-      struct Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (seq);
+      Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (seq);
 
       return (f->flags.interactivep ? COMPILED_INTERACTIVE :
              f->flags.domainp      ? COMPILED_DOMAIN :
@@ -268,7 +268,7 @@ Symbols are also allowed; their print names are used instead.
        (s1, s2))
 {
   Bytecount len;
-  struct Lisp_String *p1, *p2;
+  Lisp_String *p1, *p2;
 
   if (SYMBOLP (s1))
     p1 = XSYMBOL (s1)->name;
@@ -315,7 +315,7 @@ may be solved.
 */
        (s1, s2))
 {
-  struct Lisp_String *p1, *p2;
+  Lisp_String *p1, *p2;
   Charcount end, len2;
   int i;
 
@@ -394,7 +394,7 @@ of the string are changed (e.g. with `aset').  It wraps around occasionally.
 */
        (string))
 {
-  struct Lisp_String *s;
+  Lisp_String *s;
 
   CHECK_STRING (string);
   s = XSTRING (string);
@@ -407,7 +407,7 @@ of the string are changed (e.g. with `aset').  It wraps around occasionally.
 void
 bump_string_modiff (Lisp_Object str)
 {
-  struct Lisp_String *s = XSTRING (str);
+  Lisp_String *s = XSTRING (str);
   Lisp_Object *ptr = &s->plist;
 
 #ifdef I18N3
@@ -1850,7 +1850,7 @@ int
 plists_differ (Lisp_Object a, Lisp_Object b, int nil_means_not_present,
               int laxp, int depth)
 {
-  int eqp = (depth == -1);     /* -1 as depth means us eq, not equal. */
+  int eqp = (depth == -1);     /* -1 as depth means use eq, not equal. */
   int la, lb, m, i, fill;
   Lisp_Object *keys, *vals;
   char *flags;
@@ -1894,10 +1894,10 @@ plists_differ (Lisp_Object a, Lisp_Object b, int nil_means_not_present,
        {
          if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth))
            {
-             if ((eqp
-                  /* We narrowly escaped being Ebolified here. */
-                  ? !EQ_WITH_EBOLA_NOTICE (v, vals [i])
-                  : !internal_equal (v, vals [i], depth)))
+             if (eqp
+                 /* We narrowly escaped being Ebolified here. */
+                 ? !EQ_WITH_EBOLA_NOTICE (v, vals [i])
+                 : !internal_equal (v, vals [i], depth))
                /* a property in B has a different value than in A */
                goto MISMATCH;
              flags [i] = 1;
@@ -2601,7 +2601,7 @@ symbol_remprop (Lisp_Object symbol, Lisp_Object propname)
 
 
 static Lisp_Object *
-string_plist_ptr (struct Lisp_String *s)
+string_plist_ptr (Lisp_String *s)
 {
   Lisp_Object *ptr = &s->plist;
 
@@ -2613,7 +2613,7 @@ string_plist_ptr (struct Lisp_String *s)
 }
 
 static Lisp_Object
-string_getprop (struct Lisp_String *s, Lisp_Object property,
+string_getprop (Lisp_String *s, Lisp_Object property,
                Lisp_Object default_)
 {
   Lisp_Object val = external_plist_get (string_plist_ptr (s), property, 0,
@@ -2622,20 +2622,20 @@ string_getprop (struct Lisp_String *s, Lisp_Object property,
 }
 
 static void
-string_putprop (struct Lisp_String *s, Lisp_Object property,
+string_putprop (Lisp_String *s, Lisp_Object property,
                Lisp_Object value)
 {
   external_plist_put (string_plist_ptr (s), property, value, 0, ERROR_ME);
 }
 
 static int
-string_remprop (struct Lisp_String *s, Lisp_Object property)
+string_remprop (Lisp_String *s, Lisp_Object property)
 {
   return external_remprop (string_plist_ptr (s), property, 0, ERROR_ME);
 }
 
 static Lisp_Object
-string_plist (struct Lisp_String *s)
+string_plist (Lisp_String *s)
 {
   return *string_plist_ptr (s);
 }
@@ -2864,7 +2864,7 @@ Do not use it.
 
 \f
 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /*
-Store each element of ARRAY with ITEM.
+Destructively modify ARRAY by replacing each element with ITEM.
 ARRAY is a vector, bit vector, or string.
 */
        (array, item))
@@ -2872,15 +2872,28 @@ ARRAY is a vector, bit vector, or string.
  retry:
   if (STRINGP (array))
     {
-      Emchar charval;
-      struct Lisp_String *s = XSTRING (array);
-      Charcount len = string_char_length (s);
-      Charcount i;
+      Lisp_String *s = XSTRING (array);
+      Bytecount old_bytecount = string_length (s);
+      Bytecount new_bytecount;
+      Bytecount item_bytecount;
+      Bufbyte item_buf[MAX_EMCHAR_LEN];
+      Bufbyte *p;
+      Bufbyte *end;
+
       CHECK_CHAR_COERCE_INT (item);
       CHECK_LISP_WRITEABLE (array);
-      charval = XCHAR (item);
-      for (i = 0; i < len; i++)
-       set_string_char (s, i, charval);
+
+      item_bytecount = set_charptr_emchar (item_buf, XCHAR (item));
+      new_bytecount = item_bytecount * string_char_length (s);
+
+      resize_string (s, -1, new_bytecount - old_bytecount);
+
+      for (p = string_data (s), end = p + new_bytecount;
+          p < end;
+          p += item_bytecount)
+       memcpy (p, item_buf, item_bytecount);
+      *p = '\0';
+
       bump_string_modiff (array);
     }
   else if (VECTORP (array))
@@ -2893,7 +2906,7 @@ ARRAY is a vector, bit vector, or string.
     }
   else if (BIT_VECTORP (array))
     {
-      struct Lisp_Bit_Vector *v = XBIT_VECTOR (array);
+      Lisp_Bit_Vector *v = XBIT_VECTOR (array);
       int len = bit_vector_length (v);
       int bit;
       CHECK_BIT (item);
@@ -3043,15 +3056,16 @@ changing the value of `foo'.
 }
 
 \f
-/* This is the guts of all mapping functions.
-   Apply fn to each element of seq, one by one,
-   storing the results into elements of vals, a C vector of Lisp_Objects.
-   leni is the length of vals, which should also be the length of seq.
+/* This is the guts of several mapping functions.
+   Apply FUNCTION to each element of SEQUENCE, one by one,
+   storing the results into elements of VALS, a C vector of Lisp_Objects.
+   LENI is the length of VALS, which should also be the length of SEQUENCE.
 
    If VALS is a null pointer, do not accumulate the results. */
 
 static void
-mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
+mapcar1 (size_t leni, Lisp_Object *vals,
+        Lisp_Object function, Lisp_Object sequence)
 {
   Lisp_Object result;
   Lisp_Object args[2];
@@ -3064,21 +3078,61 @@ mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
       gcpro1.nvars = 0;
     }
 
-  args[0] = fn;
+  args[0] = function;
 
-  if (LISTP (seq))
+  if (LISTP (sequence))
     {
-      for (i = 0; i < leni; i++)
+      /* A devious `function' could either:
+        - insert garbage into the list in front of us, causing XCDR to crash
+        - amputate the list behind us using (setcdr), causing the remaining
+          elts to lose their GCPRO status.
+
+        if (vals != 0) we avoid this by copying the elts into the
+        `vals' array.  By a stroke of luck, `vals' is exactly large
+        enough to hold the elts left to be traversed as well as the
+        results computed so far.
+
+        if (vals == 0) we don't have any free space available and
+        don't want to eat up any more stack with alloca().
+        So we use EXTERNAL_LIST_LOOP_3 and GCPRO the tail. */
+
+      if (vals)
        {
-         args[1] = XCAR (seq);
-         seq = XCDR (seq);
-         result = Ffuncall (2, args);
-         if (vals) vals[gcpro1.nvars++] = result;
+         Lisp_Object *val = vals;
+         Lisp_Object elt;
+
+         LIST_LOOP_2 (elt, sequence)
+             *val++ = elt;
+
+         gcpro1.nvars = leni;
+
+         for (i = 0; i < leni; i++)
+           {
+             args[1] = vals[i];
+             vals[i] = Ffuncall (2, args);
+           }
+       }
+      else
+       {
+         Lisp_Object elt, tail;
+         struct gcpro ngcpro1;
+
+         NGCPRO1 (tail);
+
+         {
+           EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
+             {
+               args[1] = elt;
+               Ffuncall (2, args);
+             }
+         }
+
+         NUNGCPRO;
        }
     }
-  else if (VECTORP (seq))
+  else if (VECTORP (sequence))
     {
-      Lisp_Object *objs = XVECTOR_DATA (seq);
+      Lisp_Object *objs = XVECTOR_DATA (sequence);
       for (i = 0; i < leni; i++)
        {
          args[1] = *objs++;
@@ -3086,10 +3140,16 @@ mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
          if (vals) vals[gcpro1.nvars++] = result;
        }
     }
-  else if (STRINGP (seq))
+  else if (STRINGP (sequence))
     {
-      Bufbyte *p = XSTRING_DATA (seq);
-      for (i = 0; i < leni; i++)
+      /* The string data of `sequence' might be relocated during GC. */
+      Bytecount slen = XSTRING_LENGTH (sequence);
+      Bufbyte *p = alloca_array (Bufbyte, slen);
+      Bufbyte *end = p + slen;
+
+      memcpy (p, XSTRING_DATA (sequence), slen);
+
+      while (p < end)
        {
          args[1] = make_char (charptr_emchar (p));
          INC_CHARPTR (p);
@@ -3097,9 +3157,9 @@ mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
          if (vals) vals[gcpro1.nvars++] = result;
        }
     }
-  else if (BIT_VECTORP (seq))
+  else if (BIT_VECTORP (sequence))
     {
-      struct Lisp_Bit_Vector *v = XBIT_VECTOR (seq);
+      Lisp_Bit_Vector *v = XBIT_VECTOR (sequence);
       for (i = 0; i < leni; i++)
        {
          args[1] = make_int (bit_vector_bit (v, i));
@@ -3108,20 +3168,21 @@ mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
        }
     }
   else
-    abort(); /* cannot get here since Flength(seq) did not get an error */
+    abort(); /* cannot get here since Flength(sequence) did not get an error */
 
   if (vals)
     UNGCPRO;
 }
 
 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /*
-Apply FN to each element of SEQ, and concat the results as strings.
-In between each pair of results, stick in SEP.
-Thus, " " as SEP results in spaces between the values returned by FN.
+Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.
+In between each pair of results, insert SEPARATOR.  Thus, using " " as
+SEPARATOR results in spaces between the values returned by FUNCTION.
+SEQUENCE may be a list, a vector, a bit vector, or a string.
 */
-       (fn, seq, sep))
+       (function, sequence, separator))
 {
-  size_t len = XINT (Flength (seq));
+  size_t len = XINT (Flength (sequence));
   Lisp_Object *args;
   int i;
   struct gcpro gcpro1;
@@ -3131,47 +3192,47 @@ Thus, " " as SEP results in spaces between the values returned by FN.
 
   args = alloca_array (Lisp_Object, nargs);
 
-  GCPRO1 (sep);
-  mapcar1 (len, args, fn, seq);
+  GCPRO1 (separator);
+  mapcar1 (len, args, function, sequence);
   UNGCPRO;
 
   for (i = len - 1; i >= 0; i--)
     args[i + i] = args[i];
 
   for (i = 1; i < nargs; i += 2)
-    args[i] = sep;
+    args[i] = separator;
 
   return Fconcat (nargs, args);
 }
 
 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /*
-Apply FUNCTION to each element of SEQUENCE, and make a list of the results.
-The result is a list just as long as SEQUENCE.
+Apply FUNCTION to each element of SEQUENCE; return a list of the results.
+The result is a list of the same length as SEQUENCE.
 SEQUENCE may be a list, a vector, a bit vector, or a string.
 */
-       (fn, seq))
+       (function, sequence))
 {
-  size_t len = XINT (Flength (seq));
+  size_t len = XINT (Flength (sequence));
   Lisp_Object *args = alloca_array (Lisp_Object, len);
 
-  mapcar1 (len, args, fn, seq);
+  mapcar1 (len, args, function, sequence);
 
   return Flist (len, args);
 }
 
 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /*
-Apply FUNCTION to each element of SEQUENCE, making a vector of the results.
+Apply FUNCTION to each element of SEQUENCE; return a vector of the results.
 The result is a vector of the same length as SEQUENCE.
-SEQUENCE may be a list, a vector or a string.
+SEQUENCE may be a list, a vector, a bit vector, or a string.
 */
-       (fn, seq))
+       (function, sequence))
 {
-  size_t len = XINT (Flength (seq));
+  size_t len = XINT (Flength (sequence));
   Lisp_Object result = make_vector (len, Qnil);
   struct gcpro gcpro1;
 
   GCPRO1 (result);
-  mapcar1 (len, XVECTOR_DATA (result), fn, seq);
+  mapcar1 (len, XVECTOR_DATA (result), function, sequence);
   UNGCPRO;
 
   return result;
@@ -3186,11 +3247,11 @@ which is more efficient if you do not use the results.
 The difference between this and `mapc' is that `mapc' supports all
 the spiffy Common Lisp arguments.  You should normally use `mapc'.
 */
-       (fn, seq))
+       (function, sequence))
 {
-  mapcar1 (XINT (Flength (seq)), 0, fn, seq);
+  mapcar1 (XINT (Flength (sequence)), 0, function, sequence);
 
-  return seq;
+  return sequence;
 }
 
 \f