55d5e2fe53efe82bec6b038fd0d6ebe83301e991
[chise/xemacs-chise.git.1] / src / fns.c
1 /* Random utility Lisp functions.
2    Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
3    Copyright (C) 1995, 1996 Ben Wing.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: Mule 2.0, FSF 19.30. */
23
24 /* This file has been Mule-ized. */
25
26 /* Note: FSF 19.30 has bool vectors.  We have bit vectors. */
27
28 /* Hacked on for Mule by Ben Wing, December 1994, January 1995. */
29
30 #include <config.h>
31
32 /* Note on some machines this defines `vector' as a typedef,
33    so make sure we don't use that name in this file.  */
34 #undef vector
35 #define vector *****
36
37 #include "lisp.h"
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 #include <errno.h>
43
44 #include "buffer.h"
45 #include "bytecode.h"
46 #include "device.h"
47 #include "events.h"
48 #include "extents.h"
49 #include "frame.h"
50 #include "systime.h"
51 #include "insdel.h"
52 #include "lstream.h"
53 #include "opaque.h"
54
55 /* NOTE: This symbol is also used in lread.c */
56 #define FEATUREP_SYNTAX
57
58 Lisp_Object Qstring_lessp;
59 Lisp_Object Qidentity;
60
61 static int internal_old_equal (Lisp_Object, Lisp_Object, int);
62
63 static Lisp_Object
64 mark_bit_vector (Lisp_Object obj, void (*markobj) (Lisp_Object))
65 {
66   return Qnil;
67 }
68
69 static void
70 print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
71 {
72   int i;
73   struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
74   int len = bit_vector_length (v);
75   int last = len;
76
77   if (INTP (Vprint_length))
78     last = min (len, XINT (Vprint_length));
79   write_c_string ("#*", printcharfun);
80   for (i = 0; i < last; i++)
81     {
82       if (bit_vector_bit (v, i))
83         write_c_string ("1", printcharfun);
84       else
85         write_c_string ("0", printcharfun);
86     }
87
88   if (last != len)
89     write_c_string ("...", printcharfun);
90 }
91
92 static int
93 bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
94 {
95   struct Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1);
96   struct Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2);
97
98   return ((bit_vector_length (v1) == bit_vector_length (v2)) &&
99           !memcmp (v1->bits, v2->bits,
100                    BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) *
101                    sizeof (long)));
102 }
103
104 static unsigned long
105 bit_vector_hash (Lisp_Object obj, int depth)
106 {
107   struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
108   return HASH2 (bit_vector_length (v),
109                 memory_hash (v->bits,
110                              BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) *
111                              sizeof (long)));
112 }
113
114 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("bit-vector", bit_vector,
115                                      mark_bit_vector, print_bit_vector, 0,
116                                      bit_vector_equal, bit_vector_hash, 0,
117                                      struct Lisp_Bit_Vector);
118 \f
119 DEFUN ("identity", Fidentity, 1, 1, 0, /*
120 Return the argument unchanged.
121 */
122        (arg))
123 {
124   return arg;
125 }
126
127 extern long get_random (void);
128 extern void seed_random (long arg);
129
130 DEFUN ("random", Frandom, 0, 1, 0, /*
131 Return a pseudo-random number.
132 All integers representable in Lisp are equally likely.
133   On most systems, this is 28 bits' worth.
134 With positive integer argument N, return random number in interval [0,N).
135 With argument t, set the random number seed from the current time and pid.
136 */
137        (limit))
138 {
139   EMACS_INT val;
140   unsigned long denominator;
141
142   if (EQ (limit, Qt))
143     seed_random (getpid () + time (NULL));
144   if (NATNUMP (limit) && !ZEROP (limit))
145     {
146       /* Try to take our random number from the higher bits of VAL,
147          not the lower, since (says Gentzel) the low bits of `random'
148          are less random than the higher ones.  We do this by using the
149          quotient rather than the remainder.  At the high end of the RNG
150          it's possible to get a quotient larger than limit; discarding
151          these values eliminates the bias that would otherwise appear
152          when using a large limit.  */
153       denominator = ((unsigned long)1 << VALBITS) / XINT (limit);
154       do
155         val = get_random () / denominator;
156       while (val >= XINT (limit));
157     }
158   else
159     val = get_random ();
160
161   return make_int (val);
162 }
163 \f
164 /* Random data-structure functions */
165
166 #ifdef LOSING_BYTECODE
167
168 /* #### Delete this shit */
169
170 /* Charcount is a misnomer here as we might be dealing with the
171    length of a vector or list, but emphasizes that we're not dealing
172    with Bytecounts in strings */
173 static Charcount
174 length_with_bytecode_hack (Lisp_Object seq)
175 {
176   if (!COMPILED_FUNCTIONP (seq))
177     return XINT (Flength (seq));
178   else
179     {
180       struct Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (seq);
181
182       return (f->flags.interactivep ? COMPILED_INTERACTIVE :
183               f->flags.domainp      ? COMPILED_DOMAIN :
184               COMPILED_DOC_STRING)
185         + 1;
186     }
187 }
188
189 #endif /* LOSING_BYTECODE */
190
191 void
192 check_losing_bytecode (CONST char *function, Lisp_Object seq)
193 {
194   if (COMPILED_FUNCTIONP (seq))
195     error_with_frob
196       (seq,
197        "As of 20.3, `%s' no longer works with compiled-function objects",
198        function);
199 }
200
201 DEFUN ("length", Flength, 1, 1, 0, /*
202 Return the length of vector, bit vector, list or string SEQUENCE.
203 */
204        (sequence))
205 {
206  retry:
207   if (STRINGP (sequence))
208     return make_int (XSTRING_CHAR_LENGTH (sequence));
209   else if (CONSP (sequence))
210     {
211       int len;
212       GET_EXTERNAL_LIST_LENGTH (sequence, len);
213       return make_int (len);
214     }
215   else if (VECTORP (sequence))
216     return make_int (XVECTOR_LENGTH (sequence));
217   else if (NILP (sequence))
218     return Qzero;
219   else if (BIT_VECTORP (sequence))
220     return make_int (bit_vector_length (XBIT_VECTOR (sequence)));
221   else
222     {
223       check_losing_bytecode ("length", sequence);
224       sequence = wrong_type_argument (Qsequencep, sequence);
225       goto retry;
226     }
227 }
228
229 DEFUN ("safe-length", Fsafe_length, 1, 1, 0, /*
230 Return the length of a list, but avoid error or infinite loop.
231 This function never gets an error.  If LIST is not really a list,
232 it returns 0.  If LIST is circular, it returns a finite value
233 which is at least the number of distinct elements.
234 */
235        (list))
236 {
237   Lisp_Object hare, tortoise;
238   int len;
239
240   for (hare = tortoise = list, len = 0;
241        CONSP (hare) && (! EQ (hare, tortoise) || len == 0);
242        hare = XCDR (hare), len++)
243     {
244       if (len & 1)
245         tortoise = XCDR (tortoise);
246     }
247
248   return make_int (len);
249 }
250
251 /*** string functions. ***/
252
253 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /*
254 Return t if two strings have identical contents.
255 Case is significant.  Text properties are ignored.
256 \(Under XEmacs, `equal' also ignores text properties and extents in
257 strings, but this is not the case under FSF Emacs 19.  In FSF Emacs 20
258 `equal' is the same as in XEmacs, in that respect.)
259 Symbols are also allowed; their print names are used instead.
260 */
261        (s1, s2))
262 {
263   Bytecount len;
264   struct Lisp_String *p1, *p2;
265
266   if (SYMBOLP (s1))
267     p1 = XSYMBOL (s1)->name;
268   else
269     {
270       CHECK_STRING (s1);
271       p1 = XSTRING (s1);
272     }
273
274   if (SYMBOLP (s2))
275     p2 = XSYMBOL (s2)->name;
276   else
277     {
278       CHECK_STRING (s2);
279       p2 = XSTRING (s2);
280     }
281
282   return (((len = string_length (p1)) == string_length (p2)) &&
283           !memcmp (string_data (p1), string_data (p2), len)) ? Qt : Qnil;
284 }
285
286
287 DEFUN ("string-lessp", Fstring_lessp, 2, 2, 0, /*
288 Return t if first arg string is less than second in lexicographic order.
289 If I18N2 support (but not Mule support) was compiled in, ordering is
290 determined by the locale. (Case is significant for the default C locale.)
291 In all other cases, comparison is simply done on a character-by-
292 character basis using the numeric value of a character. (Note that
293 this may not produce particularly meaningful results under Mule if
294 characters from different charsets are being compared.)
295
296 Symbols are also allowed; their print names are used instead.
297
298 The reason that the I18N2 locale-specific collation is not used under
299 Mule is that the locale model of internationalization does not handle
300 multiple charsets and thus has no hope of working properly under Mule.
301 What we really should do is create a collation table over all built-in
302 charsets.  This is extremely difficult to do from scratch, however.
303
304 Unicode is a good first step towards solving this problem.  In fact,
305 it is quite likely that a collation table exists (or will exist) for
306 Unicode.  When Unicode support is added to XEmacs/Mule, this problem
307 may be solved.
308 */
309        (s1, s2))
310 {
311   struct Lisp_String *p1, *p2;
312   Charcount end, len2;
313   int i;
314
315   if (SYMBOLP (s1))
316     p1 = XSYMBOL (s1)->name;
317   else
318     {
319       CHECK_STRING (s1);
320       p1 = XSTRING (s1);
321     }
322
323   if (SYMBOLP (s2))
324     p2 = XSYMBOL (s2)->name;
325   else
326     {
327       CHECK_STRING (s2);
328       p2 = XSTRING (s2);
329     }
330
331   end  = string_char_length (p1);
332   len2 = string_char_length (p2);
333   if (end > len2)
334     end = len2;
335
336 #if defined (I18N2) && !defined (MULE)
337   /* There is no hope of this working under Mule.  Even if we converted
338      the data into an external format so that strcoll() processed it
339      properly, it would still not work because strcoll() does not
340      handle multiple locales.  This is the fundamental flaw in the
341      locale model. */
342   {
343     Bytecount bcend = charcount_to_bytecount (string_data (p1), end);
344     /* Compare strings using collation order of locale. */
345     /* Need to be tricky to handle embedded nulls. */
346
347     for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1)
348       {
349         int val = strcoll ((char *) string_data (p1) + i,
350                            (char *) string_data (p2) + i);
351         if (val < 0)
352           return Qt;
353         if (val > 0)
354           return Qnil;
355       }
356   }
357 #else /* not I18N2, or MULE */
358   {
359     Bufbyte *ptr1 = string_data (p1);
360     Bufbyte *ptr2 = string_data (p2);
361
362     /* #### It is not really necessary to do this: We could compare
363        byte-by-byte and still get a reasonable comparison, since this
364        would compare characters with a charset in the same way.  With
365        a little rearrangement of the leading bytes, we could make most
366        inter-charset comparisons work out the same, too; even if some
367        don't, this is not a big deal because inter-charset comparisons
368        aren't really well-defined anyway. */
369     for (i = 0; i < end; i++)
370       {
371         if (charptr_emchar (ptr1) != charptr_emchar (ptr2))
372           return charptr_emchar (ptr1) < charptr_emchar (ptr2) ? Qt : Qnil;
373         INC_CHARPTR (ptr1);
374         INC_CHARPTR (ptr2);
375       }
376   }
377 #endif /* not I18N2, or MULE */
378   /* Can't do i < len2 because then comparison between "foo" and "foo^@"
379      won't work right in I18N2 case */
380   return end < len2 ? Qt : Qnil;
381 }
382
383 DEFUN ("string-modified-tick", Fstring_modified_tick, 1, 1, 0, /*
384 Return STRING's tick counter, incremented for each change to the string.
385 Each string has a tick counter which is incremented each time the contents
386 of the string are changed (e.g. with `aset').  It wraps around occasionally.
387 */
388        (string))
389 {
390   struct Lisp_String *s;
391
392   CHECK_STRING (string);
393   s = XSTRING (string);
394   if (CONSP (s->plist) && INTP (XCAR (s->plist)))
395     return XCAR (s->plist);
396   else
397     return Qzero;
398 }
399
400 void
401 bump_string_modiff (Lisp_Object str)
402 {
403   struct Lisp_String *s = XSTRING (str);
404   Lisp_Object *ptr = &s->plist;
405
406 #ifdef I18N3
407   /* #### remove the `string-translatable' property from the string,
408      if there is one. */
409 #endif
410   /* skip over extent info if it's there */
411   if (CONSP (*ptr) && EXTENT_INFOP (XCAR (*ptr)))
412     ptr = &XCDR (*ptr);
413   if (CONSP (*ptr) && INTP (XCAR (*ptr)))
414     XSETINT (XCAR (*ptr), 1+XINT (XCAR (*ptr)));
415   else
416     *ptr = Fcons (make_int (1), *ptr);
417 }
418
419 \f
420 enum  concat_target_type { c_cons, c_string, c_vector, c_bit_vector };
421 static Lisp_Object concat (int nargs, Lisp_Object *args,
422                            enum concat_target_type target_type,
423                            int last_special);
424
425 Lisp_Object
426 concat2 (Lisp_Object s1, Lisp_Object s2)
427 {
428   Lisp_Object args[2];
429   args[0] = s1;
430   args[1] = s2;
431   return concat (2, args, c_string, 0);
432 }
433
434 Lisp_Object
435 concat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3)
436 {
437   Lisp_Object args[3];
438   args[0] = s1;
439   args[1] = s2;
440   args[2] = s3;
441   return concat (3, args, c_string, 0);
442 }
443
444 Lisp_Object
445 vconcat2 (Lisp_Object s1, Lisp_Object s2)
446 {
447   Lisp_Object args[2];
448   args[0] = s1;
449   args[1] = s2;
450   return concat (2, args, c_vector, 0);
451 }
452
453 Lisp_Object
454 vconcat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3)
455 {
456   Lisp_Object args[3];
457   args[0] = s1;
458   args[1] = s2;
459   args[2] = s3;
460   return concat (3, args, c_vector, 0);
461 }
462
463 DEFUN ("append", Fappend, 0, MANY, 0, /*
464 Concatenate all the arguments and make the result a list.
465 The result is a list whose elements are the elements of all the arguments.
466 Each argument may be a list, vector, bit vector, or string.
467 The last argument is not copied, just used as the tail of the new list.
468 Also see: `nconc'.
469 */
470        (int nargs, Lisp_Object *args))
471 {
472   return concat (nargs, args, c_cons, 1);
473 }
474
475 DEFUN ("concat", Fconcat, 0, MANY, 0, /*
476 Concatenate all the arguments and make the result a string.
477 The result is a string whose elements are the elements of all the arguments.
478 Each argument may be a string or a list or vector of characters.
479
480 As of XEmacs 21.0, this function does NOT accept individual integers
481 as arguments.  Old code that relies on, for example, (concat "foo" 50)
482 returning "foo50" will fail.  To fix such code, either apply
483 `int-to-string' to the integer argument, or use `format'.
484 */
485        (int nargs, Lisp_Object *args))
486 {
487   return concat (nargs, args, c_string, 0);
488 }
489
490 DEFUN ("vconcat", Fvconcat, 0, MANY, 0, /*
491 Concatenate all the arguments and make the result a vector.
492 The result is a vector whose elements are the elements of all the arguments.
493 Each argument may be a list, vector, bit vector, or string.
494 */
495        (int nargs, Lisp_Object *args))
496 {
497   return concat (nargs, args, c_vector, 0);
498 }
499
500 DEFUN ("bvconcat", Fbvconcat, 0, MANY, 0, /*
501 Concatenate all the arguments and make the result a bit vector.
502 The result is a bit vector whose elements are the elements of all the
503 arguments.  Each argument may be a list, vector, bit vector, or string.
504 */
505        (int nargs, Lisp_Object *args))
506 {
507   return concat (nargs, args, c_bit_vector, 0);
508 }
509
510 /* Copy a (possibly dotted) list.  LIST must be a cons.
511    Can't use concat (1, &alist, c_cons, 0) - doesn't handle dotted lists. */
512 static Lisp_Object
513 copy_list (Lisp_Object list)
514 {
515   Lisp_Object list_copy = Fcons (XCAR (list), XCDR (list));
516   Lisp_Object last = list_copy;
517   Lisp_Object hare, tortoise;
518   int len;
519
520   for (tortoise = hare = XCDR (list), len = 1;
521        CONSP (hare);
522        hare = XCDR (hare), len++)
523     {
524       XCDR (last) = Fcons (XCAR (hare), XCDR (hare));
525       last = XCDR (last);
526
527       if (len < CIRCULAR_LIST_SUSPICION_LENGTH)
528         continue;
529       if (len & 1)
530         tortoise = XCDR (tortoise);
531       if (EQ (tortoise, hare))
532         signal_circular_list_error (list);
533     }
534
535   return list_copy;
536 }
537
538 DEFUN ("copy-list", Fcopy_list, 1, 1, 0, /*
539 Return a copy of list LIST, which may be a dotted list.
540 The elements of LIST are not copied; they are shared
541 with the original.
542 */
543        (list))
544 {
545  again:
546   if (NILP  (list)) return list;
547   if (CONSP (list)) return copy_list (list);
548
549   list = wrong_type_argument (Qlistp, list);
550   goto again;
551 }
552
553 DEFUN ("copy-sequence", Fcopy_sequence, 1, 1, 0, /*
554 Return a copy of list, vector, bit vector or string SEQUENCE.
555 The elements of a list or vector are not copied; they are shared
556 with the original. SEQUENCE may be a dotted list.
557 */
558        (sequence))
559 {
560  again:
561   if (NILP        (sequence)) return sequence;
562   if (CONSP       (sequence)) return copy_list (sequence);
563   if (STRINGP     (sequence)) return concat (1, &sequence, c_string,     0);
564   if (VECTORP     (sequence)) return concat (1, &sequence, c_vector,     0);
565   if (BIT_VECTORP (sequence)) return concat (1, &sequence, c_bit_vector, 0);
566
567   check_losing_bytecode ("copy-sequence", sequence);
568   sequence = wrong_type_argument (Qsequencep, sequence);
569   goto again;
570 }
571
572 struct merge_string_extents_struct
573 {
574   Lisp_Object string;
575   Bytecount entry_offset;
576   Bytecount entry_length;
577 };
578
579 static Lisp_Object
580 concat (int nargs, Lisp_Object *args,
581         enum concat_target_type target_type,
582         int last_special)
583 {
584   Lisp_Object val;
585   Lisp_Object tail = Qnil;
586   int toindex;
587   int argnum;
588   Lisp_Object last_tail;
589   Lisp_Object prev;
590   struct merge_string_extents_struct *args_mse = 0;
591   Bufbyte *string_result = 0;
592   Bufbyte *string_result_ptr = 0;
593   struct gcpro gcpro1;
594
595   /* The modus operandi in Emacs is "caller gc-protects args".
596      However, concat is called many times in Emacs on freshly
597      created stuff.  So we help those callers out by protecting
598      the args ourselves to save them a lot of temporary-variable
599      grief. */
600
601   GCPRO1 (args[0]);
602   gcpro1.nvars = nargs;
603
604 #ifdef I18N3
605   /* #### if the result is a string and any of the strings have a string
606      for the `string-translatable' property, then concat should also
607      concat the args but use the `string-translatable' strings, and store
608      the result in the returned string's `string-translatable' property. */
609 #endif
610   if (target_type == c_string)
611     args_mse = alloca_array (struct merge_string_extents_struct, nargs);
612
613   /* In append, the last arg isn't treated like the others */
614   if (last_special && nargs > 0)
615     {
616       nargs--;
617       last_tail = args[nargs];
618     }
619   else
620     last_tail = Qnil;
621
622   /* Check and coerce the arguments. */
623   for (argnum = 0; argnum < nargs; argnum++)
624     {
625       Lisp_Object seq = args[argnum];
626       if (LISTP (seq))
627         ;
628       else if (VECTORP (seq) || STRINGP (seq) || BIT_VECTORP (seq))
629         ;
630 #ifdef LOSING_BYTECODE
631       else if (COMPILED_FUNCTIONP (seq))
632         /* Urk!  We allow this, for "compatibility"... */
633         ;
634 #endif
635 #if 0                           /* removed for XEmacs 21 */
636       else if (INTP (seq))
637         /* This is too revolting to think about but maintains
638            compatibility with FSF (and lots and lots of old code). */
639         args[argnum] = Fnumber_to_string (seq);
640 #endif
641       else
642         {
643           check_losing_bytecode ("concat", seq);
644           args[argnum] = wrong_type_argument (Qsequencep, seq);
645         }
646
647       if (args_mse)
648         {
649           if (STRINGP (seq))
650             args_mse[argnum].string = seq;
651           else
652             args_mse[argnum].string = Qnil;
653         }
654     }
655
656   {
657     /* Charcount is a misnomer here as we might be dealing with the
658        length of a vector or list, but emphasizes that we're not dealing
659        with Bytecounts in strings */
660     Charcount total_length;
661
662     for (argnum = 0, total_length = 0; argnum < nargs; argnum++)
663       {
664 #ifdef LOSING_BYTECODE
665         Charcount thislen = length_with_bytecode_hack (args[argnum]);
666 #else
667         Charcount thislen = XINT (Flength (args[argnum]));
668 #endif
669         total_length += thislen;
670       }
671
672     switch (target_type)
673       {
674       case c_cons:
675         if (total_length == 0)
676           /* In append, if all but last arg are nil, return last arg */
677           RETURN_UNGCPRO (last_tail);
678         val = Fmake_list (make_int (total_length), Qnil);
679         break;
680       case c_vector:
681         val = make_vector (total_length, Qnil);
682         break;
683       case c_bit_vector:
684         val = make_bit_vector (total_length, Qzero);
685         break;
686       case c_string:
687         /* We don't make the string yet because we don't know the
688            actual number of bytes.  This loop was formerly written
689            to call Fmake_string() here and then call set_string_char()
690            for each char.  This seems logical enough but is waaaaaaaay
691            slow -- set_string_char() has to scan the whole string up
692            to the place where the substitution is called for in order
693            to find the place to change, and may have to do some
694            realloc()ing in order to make the char fit properly.
695            O(N^2) yuckage. */
696         val = Qnil;
697         string_result = (Bufbyte *) alloca (total_length * MAX_EMCHAR_LEN);
698         string_result_ptr = string_result;
699         break;
700       default:
701         abort ();
702       }
703   }
704
705
706   if (CONSP (val))
707     tail = val, toindex = -1;   /* -1 in toindex is flag we are
708                                     making a list */
709   else
710     toindex = 0;
711
712   prev = Qnil;
713
714   for (argnum = 0; argnum < nargs; argnum++)
715     {
716       Charcount thisleni = 0;
717       Charcount thisindex = 0;
718       Lisp_Object seq = args[argnum];
719       Bufbyte *string_source_ptr = 0;
720       Bufbyte *string_prev_result_ptr = string_result_ptr;
721
722       if (!CONSP (seq))
723         {
724 #ifdef LOSING_BYTECODE
725           thisleni = length_with_bytecode_hack (seq);
726 #else
727           thisleni = XINT (Flength (seq));
728 #endif
729         }
730       if (STRINGP (seq))
731         string_source_ptr = XSTRING_DATA (seq);
732
733       while (1)
734         {
735           Lisp_Object elt;
736
737           /* We've come to the end of this arg, so exit. */
738           if (NILP (seq))
739             break;
740
741           /* Fetch next element of `seq' arg into `elt' */
742           if (CONSP (seq))
743             {
744               elt = XCAR (seq);
745               seq = XCDR (seq);
746             }
747           else
748             {
749               if (thisindex >= thisleni)
750                 break;
751
752               if (STRINGP (seq))
753                 {
754                   elt = make_char (charptr_emchar (string_source_ptr));
755                   INC_CHARPTR (string_source_ptr);
756                 }
757               else if (VECTORP (seq))
758                 elt = XVECTOR_DATA (seq)[thisindex];
759               else if (BIT_VECTORP (seq))
760                 elt = make_int (bit_vector_bit (XBIT_VECTOR (seq),
761                                                 thisindex));
762               else
763                 elt = Felt (seq, make_int (thisindex));
764               thisindex++;
765             }
766
767           /* Store into result */
768           if (toindex < 0)
769             {
770               /* toindex negative means we are making a list */
771               XCAR (tail) = elt;
772               prev = tail;
773               tail = XCDR (tail);
774             }
775           else if (VECTORP (val))
776             XVECTOR_DATA (val)[toindex++] = elt;
777           else if (BIT_VECTORP (val))
778             {
779               CHECK_BIT (elt);
780               set_bit_vector_bit (XBIT_VECTOR (val), toindex++, XINT (elt));
781             }
782           else
783             {
784               CHECK_CHAR_COERCE_INT (elt);
785               string_result_ptr += set_charptr_emchar (string_result_ptr,
786                                                        XCHAR (elt));
787             }
788         }
789       if (args_mse)
790         {
791           args_mse[argnum].entry_offset =
792             string_prev_result_ptr - string_result;
793           args_mse[argnum].entry_length =
794             string_result_ptr - string_prev_result_ptr;
795         }
796     }
797
798   /* Now we finally make the string. */
799   if (target_type == c_string)
800     {
801       val = make_string (string_result, string_result_ptr - string_result);
802       for (argnum = 0; argnum < nargs; argnum++)
803         {
804           if (STRINGP (args_mse[argnum].string))
805             copy_string_extents (val, args_mse[argnum].string,
806                                  args_mse[argnum].entry_offset, 0,
807                                  args_mse[argnum].entry_length);
808         }
809     }
810
811   if (!NILP (prev))
812     XCDR (prev) = last_tail;
813
814   RETURN_UNGCPRO (val);
815 }
816 \f
817 DEFUN ("copy-alist", Fcopy_alist, 1, 1, 0, /*
818 Return a copy of ALIST.
819 This is an alist which represents the same mapping from objects to objects,
820 but does not share the alist structure with ALIST.
821 The objects mapped (cars and cdrs of elements of the alist)
822 are shared, however.
823 Elements of ALIST that are not conses are also shared.
824 */
825        (alist))
826 {
827   Lisp_Object tail;
828
829   if (NILP (alist))
830     return alist;
831   CHECK_CONS (alist);
832
833   alist = concat (1, &alist, c_cons, 0);
834   for (tail = alist; CONSP (tail); tail = XCDR (tail))
835     {
836       Lisp_Object car = XCAR (tail);
837
838       if (CONSP (car))
839         XCAR (tail) = Fcons (XCAR (car), XCDR (car));
840     }
841   return alist;
842 }
843
844 DEFUN ("copy-tree", Fcopy_tree, 1, 2, 0, /*
845 Return a copy of a list and substructures.
846 The argument is copied, and any lists contained within it are copied
847 recursively.  Circularities and shared substructures are not preserved.
848 Second arg VECP causes vectors to be copied, too.  Strings and bit vectors
849 are not copied.
850 */
851        (arg, vecp))
852 {
853   if (CONSP (arg))
854     {
855       Lisp_Object rest;
856       rest = arg = Fcopy_sequence (arg);
857       while (CONSP (rest))
858         {
859           Lisp_Object elt = XCAR (rest);
860           QUIT;
861           if (CONSP (elt) || VECTORP (elt))
862             XCAR (rest) = Fcopy_tree (elt, vecp);
863           if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */
864             XCDR (rest) = Fcopy_tree (XCDR (rest), vecp);
865           rest = XCDR (rest);
866         }
867     }
868   else if (VECTORP (arg) && ! NILP (vecp))
869     {
870       int i = XVECTOR_LENGTH (arg);
871       int j;
872       arg = Fcopy_sequence (arg);
873       for (j = 0; j < i; j++)
874         {
875           Lisp_Object elt = XVECTOR_DATA (arg) [j];
876           QUIT;
877           if (CONSP (elt) || VECTORP (elt))
878             XVECTOR_DATA (arg) [j] = Fcopy_tree (elt, vecp);
879         }
880     }
881   return arg;
882 }
883
884 DEFUN ("substring", Fsubstring, 2, 3, 0, /*
885 Return a substring of STRING, starting at index FROM and ending before TO.
886 TO may be nil or omitted; then the substring runs to the end of STRING.
887 If FROM or TO is negative, it counts from the end.
888 Relevant parts of the string-extent-data are copied in the new string.
889 */
890        (string, from, to))
891 {
892   Charcount ccfr, ccto;
893   Bytecount bfr, blen;
894   Lisp_Object val;
895
896   CHECK_STRING (string);
897   CHECK_INT (from);
898   get_string_range_char (string, from, to, &ccfr, &ccto,
899                          GB_HISTORICAL_STRING_BEHAVIOR);
900   bfr = charcount_to_bytecount (XSTRING_DATA (string), ccfr);
901   blen = charcount_to_bytecount (XSTRING_DATA (string) + bfr, ccto - ccfr);
902   val = make_string (XSTRING_DATA (string) + bfr, blen);
903   /* Copy any applicable extent information into the new string: */
904   copy_string_extents (val, string, 0, bfr, blen);
905   return val;
906 }
907
908 DEFUN ("subseq", Fsubseq, 2, 3, 0, /*
909 Return a subsequence of SEQ, starting at index FROM and ending before TO.
910 TO may be nil or omitted; then the subsequence runs to the end of SEQ.
911 If FROM or TO is negative, it counts from the end.
912 The resulting subsequence is always the same type as the original
913  sequence.
914 If SEQ is a string, relevant parts of the string-extent-data are copied
915  to the new string.
916 */
917        (seq, from, to))
918 {
919   int len, f, t;
920
921   if (STRINGP (seq))
922     return Fsubstring (seq, from, to);
923
924   if (!LISTP (seq) && !VECTORP (seq) && !BIT_VECTORP (seq))
925     {
926       check_losing_bytecode ("subseq", seq);
927       seq = wrong_type_argument (Qsequencep, seq);
928     }
929
930   len = XINT (Flength (seq));
931
932   CHECK_INT (from);
933   f = XINT (from);
934   if (f < 0)
935     f = len + f;
936
937   if (NILP (to))
938     t = len;
939   else
940     {
941       CHECK_INT (to);
942       t = XINT (to);
943       if (t < 0)
944         t = len + t;
945     }
946
947   if (!(0 <= f && f <= t && t <= len))
948     args_out_of_range_3 (seq, make_int (f), make_int (t));
949
950   if (VECTORP (seq))
951     {
952       Lisp_Object result = make_vector (t - f, Qnil);
953       int i;
954       Lisp_Object *in_elts  = XVECTOR_DATA (seq);
955       Lisp_Object *out_elts = XVECTOR_DATA (result);
956
957       for (i = f; i < t; i++)
958         out_elts[i - f] = in_elts[i];
959       return result;
960     }
961
962   if (LISTP (seq))
963     {
964       Lisp_Object result = Qnil;
965       int i;
966
967       seq = Fnthcdr (make_int (f), seq);
968
969       for (i = f; i < t; i++)
970         {
971           result = Fcons (Fcar (seq), result);
972           seq = Fcdr (seq);
973         }
974
975       return Fnreverse (result);
976     }
977
978   /* bit vector */
979   {
980     Lisp_Object result = make_bit_vector (t - f, Qzero);
981     int i;
982
983     for (i = f; i < t; i++)
984       set_bit_vector_bit (XBIT_VECTOR (result), i - f,
985                           bit_vector_bit (XBIT_VECTOR (seq), i));
986     return result;
987   }
988 }
989
990 \f
991 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /*
992 Take cdr N times on LIST, and return the result.
993 */
994        (n, list))
995 {
996   REGISTER int i;
997   REGISTER Lisp_Object tail = list;
998   CHECK_NATNUM (n);
999   for (i = XINT (n); i; i--)
1000     {
1001       if (CONSP (tail))
1002         tail = XCDR (tail);
1003       else if (NILP (tail))
1004         return Qnil;
1005       else
1006         {
1007           tail = wrong_type_argument (Qlistp, tail);
1008           i++;
1009         }
1010     }
1011   return tail;
1012 }
1013
1014 DEFUN ("nth", Fnth, 2, 2, 0, /*
1015 Return the Nth element of LIST.
1016 N counts from zero.  If LIST is not that long, nil is returned.
1017 */
1018        (n, list))
1019 {
1020   return Fcar (Fnthcdr (n, list));
1021 }
1022
1023 DEFUN ("elt", Felt, 2, 2, 0, /*
1024 Return element of SEQUENCE at index N.
1025 */
1026        (sequence, n))
1027 {
1028  retry:
1029   CHECK_INT_COERCE_CHAR (n); /* yuck! */
1030   if (LISTP (sequence))
1031     {
1032       Lisp_Object tem = Fnthcdr (n, sequence);
1033       /* #### Utterly, completely, fucking disgusting.
1034        * #### The whole point of "elt" is that it operates on
1035        * #### sequences, and does error- (bounds-) checking.
1036        */
1037       if (CONSP (tem))
1038         return XCAR (tem);
1039       else
1040 #if 1
1041         /* This is The Way It Has Always Been. */
1042         return Qnil;
1043 #else
1044         /* This is The Way Mly and Cltl2 say It Should Be. */
1045         args_out_of_range (sequence, n);
1046 #endif
1047     }
1048   else if (STRINGP     (sequence) ||
1049            VECTORP     (sequence) ||
1050            BIT_VECTORP (sequence))
1051     return Faref (sequence, n);
1052 #ifdef LOSING_BYTECODE
1053   else if (COMPILED_FUNCTIONP (sequence))
1054     {
1055       int idx = XINT (n);
1056       if (idx < 0)
1057         {
1058         lose:
1059           args_out_of_range (sequence, n);
1060         }
1061       /* Utter perversity */
1062       {
1063         Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (sequence);
1064         switch (idx)
1065           {
1066           case COMPILED_ARGLIST:
1067             return compiled_function_arglist (f);
1068           case COMPILED_INSTRUCTIONS:
1069             return compiled_function_instructions (f);
1070           case COMPILED_CONSTANTS:
1071             return compiled_function_constants (f);
1072           case COMPILED_STACK_DEPTH:
1073             return compiled_function_stack_depth (f);
1074           case COMPILED_DOC_STRING:
1075             return compiled_function_documentation (f);
1076           case COMPILED_DOMAIN:
1077             return compiled_function_domain (f);
1078           case COMPILED_INTERACTIVE:
1079             if (f->flags.interactivep)
1080               return compiled_function_interactive (f);
1081             /* if we return nil, can't tell interactive with no args
1082                from noninteractive. */
1083             goto lose;
1084           default:
1085             goto lose;
1086           }
1087       }
1088     }
1089 #endif /* LOSING_BYTECODE */
1090   else
1091     {
1092       check_losing_bytecode ("elt", sequence);
1093       sequence = wrong_type_argument (Qsequencep, sequence);
1094       goto retry;
1095     }
1096 }
1097
1098 DEFUN ("last", Flast, 1, 2, 0, /*
1099 Return the tail of list LIST, of length N (default 1).
1100 LIST may be a dotted list, but not a circular list.
1101 Optional argument N must be a non-negative integer.
1102 If N is zero, then the atom that terminates the list is returned.
1103 If N is greater than the length of LIST, then LIST itself is returned.
1104 */
1105        (list, n))
1106 {
1107   int int_n, count;
1108   Lisp_Object retval, tortoise, hare;
1109
1110   CHECK_LIST (list);
1111
1112   if (NILP (n))
1113     int_n = 1;
1114   else
1115     {
1116       CHECK_NATNUM (n);
1117       int_n = XINT (n);
1118     }
1119
1120   for (retval = tortoise = hare = list, count = 0;
1121        CONSP (hare);
1122        hare = XCDR (hare),
1123          (int_n-- <= 0 ? ((void) (retval = XCDR (retval))) : (void)0),
1124          count++)
1125     {
1126       if (count < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
1127
1128       if (count & 1)
1129         tortoise = XCDR (tortoise);
1130       if (EQ (hare, tortoise))
1131         signal_circular_list_error (list);
1132     }
1133
1134   return retval;
1135 }
1136
1137 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /*
1138 Modify LIST to remove the last N (default 1) elements.
1139 If LIST has N or fewer elements, nil is returned and LIST is unmodified.
1140 */
1141        (list, n))
1142 {
1143   int int_n;
1144
1145   CHECK_LIST (list);
1146
1147   if (NILP (n))
1148     int_n = 1;
1149   else
1150     {
1151       CHECK_NATNUM (n);
1152       int_n = XINT (n);
1153     }
1154
1155   {
1156     Lisp_Object last_cons = list;
1157
1158     EXTERNAL_LIST_LOOP_1 (list)
1159       {
1160         if (int_n-- < 0)
1161           last_cons = XCDR (last_cons);
1162       }
1163
1164     if (int_n >= 0)
1165       return Qnil;
1166
1167     XCDR (last_cons) = Qnil;
1168     return list;
1169   }
1170 }
1171
1172 DEFUN ("butlast", Fbutlast, 1, 2, 0, /*
1173 Return a copy of LIST with the last N (default 1) elements removed.
1174 If LIST has N or fewer elements, nil is returned.
1175 */
1176        (list, n))
1177 {
1178   int int_n;
1179
1180   CHECK_LIST (list);
1181
1182   if (NILP (n))
1183     int_n = 1;
1184   else
1185     {
1186       CHECK_NATNUM (n);
1187       int_n = XINT (n);
1188     }
1189
1190   {
1191     Lisp_Object retval = Qnil;
1192     Lisp_Object tail = list;
1193
1194     EXTERNAL_LIST_LOOP_1 (list)
1195       {
1196         if (--int_n < 0)
1197           {
1198             retval = Fcons (XCAR (tail), retval);
1199             tail = XCDR (tail);
1200           }
1201       }
1202
1203     return Fnreverse (retval);
1204   }
1205 }
1206
1207 DEFUN ("member", Fmember, 2, 2, 0, /*
1208 Return non-nil if ELT is an element of LIST.  Comparison done with `equal'.
1209 The value is actually the tail of LIST whose car is ELT.
1210 */
1211        (elt, list))
1212 {
1213   Lisp_Object list_elt, tail;
1214   EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
1215     {
1216       if (internal_equal (elt, list_elt, 0))
1217         return tail;
1218     }
1219   return Qnil;
1220 }
1221
1222 DEFUN ("old-member", Fold_member, 2, 2, 0, /*
1223 Return non-nil if ELT is an element of LIST.  Comparison done with `old-equal'.
1224 The value is actually the tail of LIST whose car is ELT.
1225 This function is provided only for byte-code compatibility with v19.
1226 Do not use it.
1227 */
1228        (elt, list))
1229 {
1230   Lisp_Object list_elt, tail;
1231   EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
1232     {
1233       if (internal_old_equal (elt, list_elt, 0))
1234         return tail;
1235     }
1236   return Qnil;
1237 }
1238
1239 DEFUN ("memq", Fmemq, 2, 2, 0, /*
1240 Return non-nil if ELT is an element of LIST.  Comparison done with `eq'.
1241 The value is actually the tail of LIST whose car is ELT.
1242 */
1243        (elt, list))
1244 {
1245   Lisp_Object list_elt, tail;
1246   EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
1247     {
1248       if (EQ_WITH_EBOLA_NOTICE (elt, list_elt))
1249         return tail;
1250     }
1251   return Qnil;
1252 }
1253
1254 DEFUN ("old-memq", Fold_memq, 2, 2, 0, /*
1255 Return non-nil if ELT is an element of LIST.  Comparison done with `old-eq'.
1256 The value is actually the tail of LIST whose car is ELT.
1257 This function is provided only for byte-code compatibility with v19.
1258 Do not use it.
1259 */
1260        (elt, list))
1261 {
1262   Lisp_Object list_elt, tail;
1263   EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
1264     {
1265       if (HACKEQ_UNSAFE (elt, list_elt))
1266         return tail;
1267     }
1268   return Qnil;
1269 }
1270
1271 Lisp_Object
1272 memq_no_quit (Lisp_Object elt, Lisp_Object list)
1273 {
1274   Lisp_Object list_elt, tail;
1275   LIST_LOOP_3 (list_elt, list, tail)
1276     {
1277       if (EQ_WITH_EBOLA_NOTICE (elt, list_elt))
1278         return tail;
1279     }
1280   return Qnil;
1281 }
1282
1283 DEFUN ("assoc", Fassoc, 2, 2, 0, /*
1284 Return non-nil if KEY is `equal' to the car of an element of LIST.
1285 The value is actually the element of LIST whose car equals KEY.
1286 */
1287        (key, list))
1288 {
1289   /* This function can GC. */
1290   Lisp_Object elt, elt_car, elt_cdr;
1291   EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
1292     {
1293       if (internal_equal (key, elt_car, 0))
1294         return elt;
1295     }
1296   return Qnil;
1297 }
1298
1299 DEFUN ("old-assoc", Fold_assoc, 2, 2, 0, /*
1300 Return non-nil if KEY is `old-equal' to the car of an element of LIST.
1301 The value is actually the element of LIST whose car equals KEY.
1302 */
1303        (key, list))
1304 {
1305   /* This function can GC. */
1306   Lisp_Object elt, elt_car, elt_cdr;
1307   EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
1308     {
1309       if (internal_old_equal (key, elt_car, 0))
1310         return elt;
1311     }
1312   return Qnil;
1313 }
1314
1315 Lisp_Object
1316 assoc_no_quit (Lisp_Object key, Lisp_Object list)
1317 {
1318   int speccount = specpdl_depth ();
1319   specbind (Qinhibit_quit, Qt);
1320   return unbind_to (speccount, Fassoc (key, list));
1321 }
1322
1323 DEFUN ("assq", Fassq, 2, 2, 0, /*
1324 Return non-nil if KEY is `eq' to the car of an element of LIST.
1325 The value is actually the element of LIST whose car is KEY.
1326 Elements of LIST that are not conses are ignored.
1327 */
1328        (key, list))
1329 {
1330   Lisp_Object elt, elt_car, elt_cdr;
1331   EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
1332     {
1333       if (EQ_WITH_EBOLA_NOTICE (key, elt_car))
1334         return elt;
1335     }
1336   return Qnil;
1337 }
1338
1339 DEFUN ("old-assq", Fold_assq, 2, 2, 0, /*
1340 Return non-nil if KEY is `old-eq' to the car of an element of LIST.
1341 The value is actually the element of LIST whose car is KEY.
1342 Elements of LIST that are not conses are ignored.
1343 This function is provided only for byte-code compatibility with v19.
1344 Do not use it.
1345 */
1346        (key, list))
1347 {
1348   Lisp_Object elt, elt_car, elt_cdr;
1349   EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
1350     {
1351       if (HACKEQ_UNSAFE (key, elt_car))
1352         return elt;
1353     }
1354   return Qnil;
1355 }
1356
1357 /* Like Fassq but never report an error and do not allow quits.
1358    Use only on lists known never to be circular.  */
1359
1360 Lisp_Object
1361 assq_no_quit (Lisp_Object key, Lisp_Object list)
1362 {
1363   /* This cannot GC. */
1364   Lisp_Object elt;
1365   LIST_LOOP_2 (elt, list)
1366     {
1367       Lisp_Object elt_car = XCAR (elt);
1368       if (EQ_WITH_EBOLA_NOTICE (key, elt_car))
1369         return elt;
1370     }
1371   return Qnil;
1372 }
1373
1374 DEFUN ("rassoc", Frassoc, 2, 2, 0, /*
1375 Return non-nil if KEY is `equal' to the cdr of an element of LIST.
1376 The value is actually the element of LIST whose cdr equals KEY.
1377 */
1378        (key, list))
1379 {
1380   Lisp_Object elt, elt_car, elt_cdr;
1381   EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
1382     {
1383       if (internal_equal (key, elt_cdr, 0))
1384         return elt;
1385     }
1386   return Qnil;
1387 }
1388
1389 DEFUN ("old-rassoc", Fold_rassoc, 2, 2, 0, /*
1390 Return non-nil if KEY is `old-equal' to the cdr of an element of LIST.
1391 The value is actually the element of LIST whose cdr equals KEY.
1392 */
1393        (key, list))
1394 {
1395   Lisp_Object elt, elt_car, elt_cdr;
1396   EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
1397     {
1398       if (internal_old_equal (key, elt_cdr, 0))
1399         return elt;
1400     }
1401   return Qnil;
1402 }
1403
1404 DEFUN ("rassq", Frassq, 2, 2, 0, /*
1405 Return non-nil if KEY is `eq' to the cdr of an element of LIST.
1406 The value is actually the element of LIST whose cdr is KEY.
1407 */
1408        (key, list))
1409 {
1410   Lisp_Object elt, elt_car, elt_cdr;
1411   EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
1412     {
1413       if (EQ_WITH_EBOLA_NOTICE (key, elt_cdr))
1414         return elt;
1415     }
1416   return Qnil;
1417 }
1418
1419 DEFUN ("old-rassq", Fold_rassq, 2, 2, 0, /*
1420 Return non-nil if KEY is `old-eq' to the cdr of an element of LIST.
1421 The value is actually the element of LIST whose cdr is KEY.
1422 */
1423        (key, list))
1424 {
1425   Lisp_Object elt, elt_car, elt_cdr;
1426   EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
1427     {
1428       if (HACKEQ_UNSAFE (key, elt_cdr))
1429         return elt;
1430     }
1431   return Qnil;
1432 }
1433
1434 /* Like Frassq, but caller must ensure that LIST is properly
1435    nil-terminated and ebola-free. */
1436 Lisp_Object
1437 rassq_no_quit (Lisp_Object key, Lisp_Object list)
1438 {
1439   Lisp_Object elt;
1440   LIST_LOOP_2 (elt, list)
1441     {
1442       Lisp_Object elt_cdr = XCDR (elt);
1443       if (EQ_WITH_EBOLA_NOTICE (key, elt_cdr))
1444         return elt;
1445     }
1446   return Qnil;
1447 }
1448
1449 \f
1450 DEFUN ("delete", Fdelete, 2, 2, 0, /*
1451 Delete by side effect any occurrences of ELT as a member of LIST.
1452 The modified LIST is returned.  Comparison is done with `equal'.
1453 If the first member of LIST is ELT, there is no way to remove it by side
1454 effect; therefore, write `(setq foo (delete element foo))' to be sure
1455 of changing the value of `foo'.
1456 Also see: `remove'.
1457 */
1458        (elt, list))
1459 {
1460   Lisp_Object list_elt;
1461   EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
1462                                 (internal_equal (elt, list_elt, 0)));
1463   return list;
1464 }
1465
1466 DEFUN ("old-delete", Fold_delete, 2, 2, 0, /*
1467 Delete by side effect any occurrences of ELT as a member of LIST.
1468 The modified LIST is returned.  Comparison is done with `old-equal'.
1469 If the first member of LIST is ELT, there is no way to remove it by side
1470 effect; therefore, write `(setq foo (old-delete element foo))' to be sure
1471 of changing the value of `foo'.
1472 */
1473        (elt, list))
1474 {
1475   Lisp_Object list_elt;
1476   EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
1477                                 (internal_old_equal (elt, list_elt, 0)));
1478   return list;
1479 }
1480
1481 DEFUN ("delq", Fdelq, 2, 2, 0, /*
1482 Delete by side effect any occurrences of ELT as a member of LIST.
1483 The modified LIST is returned.  Comparison is done with `eq'.
1484 If the first member of LIST is ELT, there is no way to remove it by side
1485 effect; therefore, write `(setq foo (delq element foo))' to be sure of
1486 changing the value of `foo'.
1487 */
1488        (elt, list))
1489 {
1490   Lisp_Object list_elt;
1491   EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
1492                                 (EQ_WITH_EBOLA_NOTICE (elt, list_elt)));
1493   return list;
1494 }
1495
1496 DEFUN ("old-delq", Fold_delq, 2, 2, 0, /*
1497 Delete by side effect any occurrences of ELT as a member of LIST.
1498 The modified LIST is returned.  Comparison is done with `old-eq'.
1499 If the first member of LIST is ELT, there is no way to remove it by side
1500 effect; therefore, write `(setq foo (old-delq element foo))' to be sure of
1501 changing the value of `foo'.
1502 */
1503        (elt, list))
1504 {
1505   Lisp_Object list_elt;
1506   EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
1507                                 (HACKEQ_UNSAFE (elt, list_elt)));
1508   return list;
1509 }
1510
1511 /* Like Fdelq, but caller must ensure that LIST is properly
1512    nil-terminated and ebola-free. */
1513
1514 Lisp_Object
1515 delq_no_quit (Lisp_Object elt, Lisp_Object list)
1516 {
1517   Lisp_Object list_elt;
1518   LIST_LOOP_DELETE_IF (list_elt, list,
1519                        (EQ_WITH_EBOLA_NOTICE (elt, list_elt)));
1520   return list;
1521 }
1522
1523 /* Be VERY careful with this.  This is like delq_no_quit() but
1524    also calls free_cons() on the removed conses.  You must be SURE
1525    that no pointers to the freed conses remain around (e.g.
1526    someone else is pointing to part of the list).  This function
1527    is useful on internal lists that are used frequently and where
1528    the actual list doesn't escape beyond known code bounds. */
1529
1530 Lisp_Object
1531 delq_no_quit_and_free_cons (Lisp_Object elt, Lisp_Object list)
1532 {
1533   REGISTER Lisp_Object tail = list;
1534   REGISTER Lisp_Object prev = Qnil;
1535
1536   while (!NILP (tail))
1537     {
1538       REGISTER Lisp_Object tem = XCAR (tail);
1539       if (EQ (elt, tem))
1540         {
1541           Lisp_Object cons_to_free = tail;
1542           if (NILP (prev))
1543             list = XCDR (tail);
1544           else
1545             XCDR (prev) = XCDR (tail);
1546           tail = XCDR (tail);
1547           free_cons (XCONS (cons_to_free));
1548         }
1549       else
1550         {
1551           prev = tail;
1552           tail = XCDR (tail);
1553         }
1554     }
1555   return list;
1556 }
1557
1558 DEFUN ("remassoc", Fremassoc, 2, 2, 0, /*
1559 Delete by side effect any elements of LIST whose car is `equal' to KEY.
1560 The modified LIST is returned.  If the first member of LIST has a car
1561 that is `equal' to KEY, there is no way to remove it by side effect;
1562 therefore, write `(setq foo (remassoc key foo))' to be sure of changing
1563 the value of `foo'.
1564 */
1565        (key, list))
1566 {
1567   Lisp_Object elt;
1568   EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
1569                                 (CONSP (elt) &&
1570                                  internal_equal (key, XCAR (elt), 0)));
1571   return list;
1572 }
1573
1574 Lisp_Object
1575 remassoc_no_quit (Lisp_Object key, Lisp_Object list)
1576 {
1577   int speccount = specpdl_depth ();
1578   specbind (Qinhibit_quit, Qt);
1579   return unbind_to (speccount, Fremassoc (key, list));
1580 }
1581
1582 DEFUN ("remassq", Fremassq, 2, 2, 0, /*
1583 Delete by side effect any elements of LIST whose car is `eq' to KEY.
1584 The modified LIST is returned.  If the first member of LIST has a car
1585 that is `eq' to KEY, there is no way to remove it by side effect;
1586 therefore, write `(setq foo (remassq key foo))' to be sure of changing
1587 the value of `foo'.
1588 */
1589        (key, list))
1590 {
1591   Lisp_Object elt;
1592   EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
1593                                 (CONSP (elt) &&
1594                                  EQ_WITH_EBOLA_NOTICE (key, XCAR (elt))));
1595   return list;
1596 }
1597
1598 /* no quit, no errors; be careful */
1599
1600 Lisp_Object
1601 remassq_no_quit (Lisp_Object key, Lisp_Object list)
1602 {
1603   Lisp_Object elt;
1604   LIST_LOOP_DELETE_IF (elt, list,
1605                        (CONSP (elt) &&
1606                         EQ_WITH_EBOLA_NOTICE (key, XCAR (elt))));
1607   return list;
1608 }
1609
1610 DEFUN ("remrassoc", Fremrassoc, 2, 2, 0, /*
1611 Delete by side effect any elements of LIST whose cdr is `equal' to VALUE.
1612 The modified LIST is returned.  If the first member of LIST has a car
1613 that is `equal' to VALUE, there is no way to remove it by side effect;
1614 therefore, write `(setq foo (remrassoc value foo))' to be sure of changing
1615 the value of `foo'.
1616 */
1617        (value, list))
1618 {
1619   Lisp_Object elt;
1620   EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
1621                                 (CONSP (elt) &&
1622                                  internal_equal (value, XCDR (elt), 0)));
1623   return list;
1624 }
1625
1626 DEFUN ("remrassq", Fremrassq, 2, 2, 0, /*
1627 Delete by side effect any elements of LIST whose cdr is `eq' to VALUE.
1628 The modified LIST is returned.  If the first member of LIST has a car
1629 that is `eq' to VALUE, there is no way to remove it by side effect;
1630 therefore, write `(setq foo (remrassq value foo))' to be sure of changing
1631 the value of `foo'.
1632 */
1633        (value, list))
1634 {
1635   Lisp_Object elt;
1636   EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
1637                                 (CONSP (elt) &&
1638                                  EQ_WITH_EBOLA_NOTICE (value, XCDR (elt))));
1639   return list;
1640 }
1641
1642 /* Like Fremrassq, fast and unsafe; be careful */
1643 Lisp_Object
1644 remrassq_no_quit (Lisp_Object value, Lisp_Object list)
1645 {
1646   Lisp_Object elt;
1647   LIST_LOOP_DELETE_IF (elt, list,
1648                        (CONSP (elt) &&
1649                         EQ_WITH_EBOLA_NOTICE (value, XCDR (elt))));
1650   return list;
1651 }
1652
1653 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /*
1654 Reverse LIST by destructively modifying cdr pointers.
1655 Return the beginning of the reversed list.
1656 Also see: `reverse'.
1657 */
1658        (list))
1659 {
1660   struct gcpro gcpro1, gcpro2;
1661   REGISTER Lisp_Object prev = Qnil;
1662   REGISTER Lisp_Object tail = list;
1663
1664   /* We gcpro our args; see `nconc' */
1665   GCPRO2 (prev, tail);
1666   while (!NILP (tail))
1667     {
1668       REGISTER Lisp_Object next;
1669       CONCHECK_CONS (tail);
1670       next = XCDR (tail);
1671       XCDR (tail) = prev;
1672       prev = tail;
1673       tail = next;
1674     }
1675   UNGCPRO;
1676   return prev;
1677 }
1678
1679 DEFUN ("reverse", Freverse, 1, 1, 0, /*
1680 Reverse LIST, copying.  Return the beginning of the reversed list.
1681 See also the function `nreverse', which is used more often.
1682 */
1683        (list))
1684 {
1685   Lisp_Object reversed_list = Qnil;
1686   Lisp_Object elt;
1687   EXTERNAL_LIST_LOOP_2 (elt, list)
1688     {
1689       reversed_list = Fcons (elt, reversed_list);
1690     }
1691   return reversed_list;
1692 }
1693 \f
1694 static Lisp_Object list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
1695                                Lisp_Object lisp_arg,
1696                                int (*pred_fn) (Lisp_Object, Lisp_Object,
1697                                                Lisp_Object lisp_arg));
1698
1699 Lisp_Object
1700 list_sort (Lisp_Object list,
1701            Lisp_Object lisp_arg,
1702            int (*pred_fn) (Lisp_Object, Lisp_Object,
1703                            Lisp_Object lisp_arg))
1704 {
1705   struct gcpro gcpro1, gcpro2, gcpro3;
1706   Lisp_Object back, tem;
1707   Lisp_Object front = list;
1708   Lisp_Object len = Flength (list);
1709   int length = XINT (len);
1710
1711   if (length < 2)
1712     return list;
1713
1714   XSETINT (len, (length / 2) - 1);
1715   tem = Fnthcdr (len, list);
1716   back = Fcdr (tem);
1717   Fsetcdr (tem, Qnil);
1718
1719   GCPRO3 (front, back, lisp_arg);
1720   front = list_sort (front, lisp_arg, pred_fn);
1721   back = list_sort (back, lisp_arg, pred_fn);
1722   UNGCPRO;
1723   return list_merge (front, back, lisp_arg, pred_fn);
1724 }
1725
1726 \f
1727 static int
1728 merge_pred_function (Lisp_Object obj1, Lisp_Object obj2,
1729                      Lisp_Object pred)
1730 {
1731   Lisp_Object tmp;
1732
1733   /* prevents the GC from happening in call2 */
1734   int speccount = specpdl_depth ();
1735 /* Emacs' GC doesn't actually relocate pointers, so this probably
1736    isn't strictly necessary */
1737   record_unwind_protect (restore_gc_inhibit,
1738                          make_int (gc_currently_forbidden));
1739   gc_currently_forbidden = 1;
1740   tmp = call2 (pred, obj1, obj2);
1741   unbind_to (speccount, Qnil);
1742
1743   if (NILP (tmp))
1744     return -1;
1745   else
1746     return 1;
1747 }
1748
1749 DEFUN ("sort", Fsort, 2, 2, 0, /*
1750 Sort LIST, stably, comparing elements using PREDICATE.
1751 Returns the sorted list.  LIST is modified by side effects.
1752 PREDICATE is called with two elements of LIST, and should return T
1753 if the first element is "less" than the second.
1754 */
1755        (list, pred))
1756 {
1757   return list_sort (list, pred, merge_pred_function);
1758 }
1759
1760 Lisp_Object
1761 merge (Lisp_Object org_l1, Lisp_Object org_l2,
1762        Lisp_Object pred)
1763 {
1764   return list_merge (org_l1, org_l2, pred, merge_pred_function);
1765 }
1766
1767
1768 static Lisp_Object
1769 list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
1770             Lisp_Object lisp_arg,
1771             int (*pred_fn) (Lisp_Object, Lisp_Object, Lisp_Object lisp_arg))
1772 {
1773   Lisp_Object value;
1774   Lisp_Object tail;
1775   Lisp_Object tem;
1776   Lisp_Object l1, l2;
1777   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1778
1779   l1 = org_l1;
1780   l2 = org_l2;
1781   tail = Qnil;
1782   value = Qnil;
1783
1784   /* It is sufficient to protect org_l1 and org_l2.
1785      When l1 and l2 are updated, we copy the new values
1786      back into the org_ vars.  */
1787
1788   GCPRO4 (org_l1, org_l2, lisp_arg, value);
1789
1790   while (1)
1791     {
1792       if (NILP (l1))
1793         {
1794           UNGCPRO;
1795           if (NILP (tail))
1796             return l2;
1797           Fsetcdr (tail, l2);
1798           return value;
1799         }
1800       if (NILP (l2))
1801         {
1802           UNGCPRO;
1803           if (NILP (tail))
1804             return l1;
1805           Fsetcdr (tail, l1);
1806           return value;
1807         }
1808
1809       if (((*pred_fn) (Fcar (l2), Fcar (l1), lisp_arg)) < 0)
1810         {
1811           tem = l1;
1812           l1 = Fcdr (l1);
1813           org_l1 = l1;
1814         }
1815       else
1816         {
1817           tem = l2;
1818           l2 = Fcdr (l2);
1819           org_l2 = l2;
1820         }
1821       if (NILP (tail))
1822         value = tem;
1823       else
1824         Fsetcdr (tail, tem);
1825       tail = tem;
1826     }
1827 }
1828
1829 \f
1830 /************************************************************************/
1831 /*                      property-list functions                         */
1832 /************************************************************************/
1833
1834 /* For properties of text, we need to do order-insensitive comparison of
1835    plists.  That is, we need to compare two plists such that they are the
1836    same if they have the same set of keys, and equivalent values.
1837    So (a 1 b 2) would be equal to (b 2 a 1).
1838
1839    NIL_MEANS_NOT_PRESENT is as in `plists-eq' etc.
1840    LAXP means use `equal' for comparisons.
1841  */
1842 int
1843 plists_differ (Lisp_Object a, Lisp_Object b, int nil_means_not_present,
1844                int laxp, int depth)
1845 {
1846   int eqp = (depth == -1);      /* -1 as depth means us eq, not equal. */
1847   int la, lb, m, i, fill;
1848   Lisp_Object *keys, *vals;
1849   char *flags;
1850   Lisp_Object rest;
1851
1852   if (NILP (a) && NILP (b))
1853     return 0;
1854
1855   Fcheck_valid_plist (a);
1856   Fcheck_valid_plist (b);
1857
1858   la = XINT (Flength (a));
1859   lb = XINT (Flength (b));
1860   m = (la > lb ? la : lb);
1861   fill = 0;
1862   keys  = alloca_array (Lisp_Object, m);
1863   vals  = alloca_array (Lisp_Object, m);
1864   flags = alloca_array (char, m);
1865
1866   /* First extract the pairs from A. */
1867   for (rest = a; !NILP (rest); rest = XCDR (XCDR (rest)))
1868     {
1869       Lisp_Object k = XCAR (rest);
1870       Lisp_Object v = XCAR (XCDR (rest));
1871       /* Maybe be Ebolified. */
1872       if (nil_means_not_present && NILP (v)) continue;
1873       keys [fill] = k;
1874       vals [fill] = v;
1875       flags[fill] = 0;
1876       fill++;
1877     }
1878   /* Now iterate over B, and stop if we find something that's not in A,
1879      or that doesn't match.  As we match, mark them. */
1880   for (rest = b; !NILP (rest); rest = XCDR (XCDR (rest)))
1881     {
1882       Lisp_Object k = XCAR (rest);
1883       Lisp_Object v = XCAR (XCDR (rest));
1884       /* Maybe be Ebolified. */
1885       if (nil_means_not_present && NILP (v)) continue;
1886       for (i = 0; i < fill; i++)
1887         {
1888           if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth))
1889             {
1890               if ((eqp
1891                    /* We narrowly escaped being Ebolified here. */
1892                    ? !EQ_WITH_EBOLA_NOTICE (v, vals [i])
1893                    : !internal_equal (v, vals [i], depth)))
1894                 /* a property in B has a different value than in A */
1895                 goto MISMATCH;
1896               flags [i] = 1;
1897               break;
1898             }
1899         }
1900       if (i == fill)
1901         /* there are some properties in B that are not in A */
1902         goto MISMATCH;
1903     }
1904   /* Now check to see that all the properties in A were also in B */
1905   for (i = 0; i < fill; i++)
1906     if (flags [i] == 0)
1907       goto MISMATCH;
1908
1909   /* Ok. */
1910   return 0;
1911
1912  MISMATCH:
1913   return 1;
1914 }
1915
1916 DEFUN ("plists-eq", Fplists_eq, 2, 3, 0, /*
1917 Return non-nil if property lists A and B are `eq'.
1918 A property list is an alternating list of keywords and values.
1919  This function does order-insensitive comparisons of the property lists:
1920  For example, the property lists '(a 1 b 2) and '(b 2 a 1) are equal.
1921  Comparison between values is done using `eq'.  See also `plists-equal'.
1922 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with
1923  a nil value is ignored.  This feature is a virus that has infected
1924  old Lisp implementations, but should not be used except for backward
1925  compatibility.
1926 */
1927        (a, b, nil_means_not_present))
1928 {
1929   return (plists_differ (a, b, !NILP (nil_means_not_present), 0, -1)
1930           ? Qnil : Qt);
1931 }
1932
1933 DEFUN ("plists-equal", Fplists_equal, 2, 3, 0, /*
1934 Return non-nil if property lists A and B are `equal'.
1935 A property list is an alternating list of keywords and values.  This
1936  function does order-insensitive comparisons of the property lists: For
1937  example, the property lists '(a 1 b 2) and '(b 2 a 1) are equal.
1938  Comparison between values is done using `equal'.  See also `plists-eq'.
1939 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with
1940  a nil value is ignored.  This feature is a virus that has infected
1941  old Lisp implementations, but should not be used except for backward
1942  compatibility.
1943 */
1944        (a, b, nil_means_not_present))
1945 {
1946   return (plists_differ (a, b, !NILP (nil_means_not_present), 0, 1)
1947           ? Qnil : Qt);
1948 }
1949
1950
1951 DEFUN ("lax-plists-eq", Flax_plists_eq, 2, 3, 0, /*
1952 Return non-nil if lax property lists A and B are `eq'.
1953 A property list is an alternating list of keywords and values.
1954  This function does order-insensitive comparisons of the property lists:
1955  For example, the property lists '(a 1 b 2) and '(b 2 a 1) are equal.
1956  Comparison between values is done using `eq'.  See also `plists-equal'.
1957 A lax property list is like a regular one except that comparisons between
1958  keywords is done using `equal' instead of `eq'.
1959 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with
1960  a nil value is ignored.  This feature is a virus that has infected
1961  old Lisp implementations, but should not be used except for backward
1962  compatibility.
1963 */
1964        (a, b, nil_means_not_present))
1965 {
1966   return (plists_differ (a, b, !NILP (nil_means_not_present), 1, -1)
1967           ? Qnil : Qt);
1968 }
1969
1970 DEFUN ("lax-plists-equal", Flax_plists_equal, 2, 3, 0, /*
1971 Return non-nil if lax property lists A and B are `equal'.
1972 A property list is an alternating list of keywords and values.  This
1973  function does order-insensitive comparisons of the property lists: For
1974  example, the property lists '(a 1 b 2) and '(b 2 a 1) are equal.
1975  Comparison between values is done using `equal'.  See also `plists-eq'.
1976 A lax property list is like a regular one except that comparisons between
1977  keywords is done using `equal' instead of `eq'.
1978 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with
1979  a nil value is ignored.  This feature is a virus that has infected
1980  old Lisp implementations, but should not be used except for backward
1981  compatibility.
1982 */
1983        (a, b, nil_means_not_present))
1984 {
1985   return (plists_differ (a, b, !NILP (nil_means_not_present), 1, 1)
1986           ? Qnil : Qt);
1987 }
1988
1989 /* Return the value associated with key PROPERTY in property list PLIST.
1990    Return nil if key not found.  This function is used for internal
1991    property lists that cannot be directly manipulated by the user.
1992    */
1993
1994 Lisp_Object
1995 internal_plist_get (Lisp_Object plist, Lisp_Object property)
1996 {
1997   Lisp_Object tail;
1998
1999   for (tail = plist; !NILP (tail); tail = XCDR (XCDR (tail)))
2000     {
2001       if (EQ (XCAR (tail), property))
2002         return XCAR (XCDR (tail));
2003     }
2004
2005   return Qunbound;
2006 }
2007
2008 /* Set PLIST's value for PROPERTY to VALUE.  Analogous to
2009    internal_plist_get(). */
2010
2011 void
2012 internal_plist_put (Lisp_Object *plist, Lisp_Object property,
2013                     Lisp_Object value)
2014 {
2015   Lisp_Object tail;
2016
2017   for (tail = *plist; !NILP (tail); tail = XCDR (XCDR (tail)))
2018     {
2019       if (EQ (XCAR (tail), property))
2020         {
2021           XCAR (XCDR (tail)) = value;
2022           return;
2023         }
2024     }
2025
2026   *plist = Fcons (property, Fcons (value, *plist));
2027 }
2028
2029 int
2030 internal_remprop (Lisp_Object *plist, Lisp_Object property)
2031 {
2032   Lisp_Object tail, prev;
2033
2034   for (tail = *plist, prev = Qnil;
2035        !NILP (tail);
2036        tail = XCDR (XCDR (tail)))
2037     {
2038       if (EQ (XCAR (tail), property))
2039         {
2040           if (NILP (prev))
2041             *plist = XCDR (XCDR (tail));
2042           else
2043             XCDR (XCDR (prev)) = XCDR (XCDR (tail));
2044           return 1;
2045         }
2046       else
2047         prev = tail;
2048     }
2049
2050   return 0;
2051 }
2052
2053 /* Called on a malformed property list.  BADPLACE should be some
2054    place where truncating will form a good list -- i.e. we shouldn't
2055    result in a list with an odd length. */
2056
2057 static Lisp_Object
2058 bad_bad_bunny (Lisp_Object *plist, Lisp_Object *badplace, Error_behavior errb)
2059 {
2060   if (ERRB_EQ (errb, ERROR_ME))
2061     return Fsignal (Qmalformed_property_list, list2 (*plist, *badplace));
2062   else
2063     {
2064       if (ERRB_EQ (errb, ERROR_ME_WARN))
2065         {
2066           warn_when_safe_lispobj
2067             (Qlist, Qwarning,
2068              list2 (build_string
2069                     ("Malformed property list -- list has been truncated"),
2070                     *plist));
2071           *badplace = Qnil;
2072         }
2073       return Qunbound;
2074     }
2075 }
2076
2077 /* Called on a circular property list.  BADPLACE should be some place
2078    where truncating will result in an even-length list, as above.
2079    If doesn't particularly matter where we truncate -- anywhere we
2080    truncate along the entire list will break the circularity, because
2081    it will create a terminus and the list currently doesn't have one.
2082 */
2083
2084 static Lisp_Object
2085 bad_bad_turtle (Lisp_Object *plist, Lisp_Object *badplace, Error_behavior errb)
2086 {
2087   if (ERRB_EQ (errb, ERROR_ME))
2088     /* #### Eek, this will probably result in another error
2089        when PLIST is printed out */
2090     return Fsignal (Qcircular_property_list, list1 (*plist));
2091   else
2092     {
2093       if (ERRB_EQ (errb, ERROR_ME_WARN))
2094         {
2095           warn_when_safe_lispobj
2096             (Qlist, Qwarning,
2097              list2 (build_string
2098                     ("Circular property list -- list has been truncated"),
2099                     *plist));
2100           *badplace = Qnil;
2101         }
2102       return Qunbound;
2103     }
2104 }
2105
2106 /* Advance the tortoise pointer by two (one iteration of a property-list
2107    loop) and the hare pointer by four and verify that no malformations
2108    or circularities exist.  If so, return zero and store a value into
2109    RETVAL that should be returned by the calling function.  Otherwise,
2110    return 1.  See external_plist_get().
2111  */
2112
2113 static int
2114 advance_plist_pointers (Lisp_Object *plist,
2115                         Lisp_Object **tortoise, Lisp_Object **hare,
2116                         Error_behavior errb, Lisp_Object *retval)
2117 {
2118   int i;
2119   Lisp_Object *tortsave = *tortoise;
2120
2121   /* Note that our "fixing" may be more brutal than necessary,
2122      but it's the user's own problem, not ours, if they went in and
2123      manually fucked up a plist. */
2124
2125   for (i = 0; i < 2; i++)
2126     {
2127       /* This is a standard iteration of a defensive-loop-checking
2128          loop.  We just do it twice because we want to advance past
2129          both the property and its value.
2130
2131          If the pointer indirection is confusing you, remember that
2132          one level of indirection on the hare and tortoise pointers
2133          is only due to pass-by-reference for this function.  The other
2134          level is so that the plist can be fixed in place. */
2135
2136       /* When we reach the end of a well-formed plist, **HARE is
2137          nil.  In that case, we don't do anything at all except
2138          advance TORTOISE by one.  Otherwise, we advance HARE
2139          by two (making sure it's OK to do so), then advance
2140          TORTOISE by one (it will always be OK to do so because
2141          the HARE is always ahead of the TORTOISE and will have
2142          already verified the path), then make sure TORTOISE and
2143          HARE don't contain the same non-nil object -- if the
2144          TORTOISE and the HARE ever meet, then obviously we're
2145          in a circularity, and if we're in a circularity, then
2146          the TORTOISE and the HARE can't cross paths without
2147          meeting, since the HARE only gains one step over the
2148          TORTOISE per iteration. */
2149
2150       if (!NILP (**hare))
2151         {
2152           Lisp_Object *haresave = *hare;
2153           if (!CONSP (**hare))
2154             {
2155               *retval = bad_bad_bunny (plist, haresave, errb);
2156               return 0;
2157             }
2158           *hare = &XCDR (**hare);
2159           /* In a non-plist, we'd check here for a nil value for
2160              **HARE, which is OK (it just means the list has an
2161              odd number of elements).  In a plist, it's not OK
2162              for the list to have an odd number of elements. */
2163           if (!CONSP (**hare))
2164             {
2165               *retval = bad_bad_bunny (plist, haresave, errb);
2166               return 0;
2167             }
2168           *hare = &XCDR (**hare);
2169         }
2170
2171       *tortoise = &XCDR (**tortoise);
2172       if (!NILP (**hare) && EQ (**tortoise, **hare))
2173         {
2174           *retval = bad_bad_turtle (plist, tortsave, errb);
2175           return 0;
2176         }
2177     }
2178
2179   return 1;
2180 }
2181
2182 /* Return the value of PROPERTY from PLIST, or Qunbound if
2183    property is not on the list.
2184
2185    PLIST is a Lisp-accessible property list, meaning that it
2186    has to be checked for malformations and circularities.
2187
2188    If ERRB is ERROR_ME, an error will be signalled.  Otherwise, the
2189    function will never signal an error; and if ERRB is ERROR_ME_WARN,
2190    on finding a malformation or a circularity, it issues a warning and
2191    attempts to silently fix the problem.
2192
2193    A pointer to PLIST is passed in so that PLIST can be successfully
2194    "fixed" even if the error is at the beginning of the plist. */
2195
2196 Lisp_Object
2197 external_plist_get (Lisp_Object *plist, Lisp_Object property,
2198                     int laxp, Error_behavior errb)
2199 {
2200   Lisp_Object *tortoise = plist;
2201   Lisp_Object *hare = plist;
2202
2203   while (!NILP (*tortoise))
2204     {
2205       Lisp_Object *tortsave = tortoise;
2206       Lisp_Object retval;
2207
2208       /* We do the standard tortoise/hare march.  We isolate the
2209          grungy stuff to do this in advance_plist_pointers(), though.
2210          To us, all this function does is advance the tortoise
2211          pointer by two and the hare pointer by four and make sure
2212          everything's OK.  We first advance the pointers and then
2213          check if a property matched; this ensures that our
2214          check for a matching property is safe. */
2215
2216       if (!advance_plist_pointers (plist, &tortoise, &hare, errb, &retval))
2217         return retval;
2218
2219       if (!laxp ? EQ (XCAR (*tortsave), property)
2220           : internal_equal (XCAR (*tortsave), property, 0))
2221         return XCAR (XCDR (*tortsave));
2222     }
2223
2224   return Qunbound;
2225 }
2226
2227 /* Set PLIST's value for PROPERTY to VALUE, given a possibly
2228    malformed or circular plist.  Analogous to external_plist_get(). */
2229
2230 void
2231 external_plist_put (Lisp_Object *plist, Lisp_Object property,
2232                     Lisp_Object value, int laxp, Error_behavior errb)
2233 {
2234   Lisp_Object *tortoise = plist;
2235   Lisp_Object *hare = plist;
2236
2237   while (!NILP (*tortoise))
2238     {
2239       Lisp_Object *tortsave = tortoise;
2240       Lisp_Object retval;
2241
2242       /* See above */
2243       if (!advance_plist_pointers (plist, &tortoise, &hare, errb, &retval))
2244         return;
2245
2246       if (!laxp ? EQ (XCAR (*tortsave), property)
2247           : internal_equal (XCAR (*tortsave), property, 0))
2248         {
2249           XCAR (XCDR (*tortsave)) = value;
2250           return;
2251         }
2252     }
2253
2254   *plist = Fcons (property, Fcons (value, *plist));
2255 }
2256
2257 int
2258 external_remprop (Lisp_Object *plist, Lisp_Object property,
2259                   int laxp, Error_behavior errb)
2260 {
2261   Lisp_Object *tortoise = plist;
2262   Lisp_Object *hare = plist;
2263
2264   while (!NILP (*tortoise))
2265     {
2266       Lisp_Object *tortsave = tortoise;
2267       Lisp_Object retval;
2268
2269       /* See above */
2270       if (!advance_plist_pointers (plist, &tortoise, &hare, errb, &retval))
2271         return 0;
2272
2273       if (!laxp ? EQ (XCAR (*tortsave), property)
2274           : internal_equal (XCAR (*tortsave), property, 0))
2275         {
2276           /* Now you see why it's so convenient to have that level
2277              of indirection. */
2278           *tortsave = XCDR (XCDR (*tortsave));
2279           return 1;
2280         }
2281     }
2282
2283   return 0;
2284 }
2285
2286 DEFUN ("plist-get", Fplist_get, 2, 3, 0, /*
2287 Extract a value from a property list.
2288 PLIST is a property list, which is a list of the form
2289 \(PROP1 VALUE1 PROP2 VALUE2...).  This function returns the value
2290 corresponding to the given PROP, or DEFAULT if PROP is not
2291 one of the properties on the list.
2292 */
2293        (plist, prop, default_))
2294 {
2295   Lisp_Object val = external_plist_get (&plist, prop, 0, ERROR_ME);
2296   return UNBOUNDP (val) ? default_ : val;
2297 }
2298
2299 DEFUN ("plist-put", Fplist_put, 3, 3, 0, /*
2300 Change value in PLIST of PROP to VAL.
2301 PLIST is a property list, which is a list of the form \(PROP1 VALUE1
2302 PROP2 VALUE2 ...).  PROP is usually a symbol and VAL is any object.
2303 If PROP is already a property on the list, its value is set to VAL,
2304 otherwise the new PROP VAL pair is added.  The new plist is returned;
2305 use `(setq x (plist-put x prop val))' to be sure to use the new value.
2306 The PLIST is modified by side effects.
2307 */
2308        (plist, prop, val))
2309 {
2310   external_plist_put (&plist, prop, val, 0, ERROR_ME);
2311   return plist;
2312 }
2313
2314 DEFUN ("plist-remprop", Fplist_remprop, 2, 2, 0, /*
2315 Remove from PLIST the property PROP and its value.
2316 PLIST is a property list, which is a list of the form \(PROP1 VALUE1
2317 PROP2 VALUE2 ...).  PROP is usually a symbol.  The new plist is
2318 returned; use `(setq x (plist-remprop x prop val))' to be sure to use
2319 the new value.  The PLIST is modified by side effects.
2320 */
2321        (plist, prop))
2322 {
2323   external_remprop (&plist, prop, 0, ERROR_ME);
2324   return plist;
2325 }
2326
2327 DEFUN ("plist-member", Fplist_member, 2, 2, 0, /*
2328 Return t if PROP has a value specified in PLIST.
2329 */
2330        (plist, prop))
2331 {
2332   Lisp_Object val = Fplist_get (plist, prop, Qunbound);
2333   return UNBOUNDP (val) ? Qnil : Qt;
2334 }
2335
2336 DEFUN ("check-valid-plist", Fcheck_valid_plist, 1, 1, 0, /*
2337 Given a plist, signal an error if there is anything wrong with it.
2338 This means that it's a malformed or circular plist.
2339 */
2340        (plist))
2341 {
2342   Lisp_Object *tortoise;
2343   Lisp_Object *hare;
2344
2345  start_over:
2346   tortoise = &plist;
2347   hare = &plist;
2348   while (!NILP (*tortoise))
2349     {
2350       Lisp_Object retval;
2351
2352       /* See above */
2353       if (!advance_plist_pointers (&plist, &tortoise, &hare, ERROR_ME,
2354                                    &retval))
2355         goto start_over;
2356     }
2357
2358   return Qnil;
2359 }
2360
2361 DEFUN ("valid-plist-p", Fvalid_plist_p, 1, 1, 0, /*
2362 Given a plist, return non-nil if its format is correct.
2363 If it returns nil, `check-valid-plist' will signal an error when given
2364 the plist; that means it's a malformed or circular plist or has non-symbols
2365 as keywords.
2366 */
2367        (plist))
2368 {
2369   Lisp_Object *tortoise;
2370   Lisp_Object *hare;
2371
2372   tortoise = &plist;
2373   hare = &plist;
2374   while (!NILP (*tortoise))
2375     {
2376       Lisp_Object retval;
2377
2378       /* See above */
2379       if (!advance_plist_pointers (&plist, &tortoise, &hare, ERROR_ME_NOT,
2380                                    &retval))
2381         return Qnil;
2382     }
2383
2384   return Qt;
2385 }
2386
2387 DEFUN ("canonicalize-plist", Fcanonicalize_plist, 1, 2, 0, /*
2388 Destructively remove any duplicate entries from a plist.
2389 In such cases, the first entry applies.
2390
2391 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with
2392  a nil value is removed.  This feature is a virus that has infected
2393  old Lisp implementations, but should not be used except for backward
2394  compatibility.
2395
2396 The new plist is returned.  If NIL-MEANS-NOT-PRESENT is given, the
2397  return value may not be EQ to the passed-in value, so make sure to
2398  `setq' the value back into where it came from.
2399 */
2400        (plist, nil_means_not_present))
2401 {
2402   Lisp_Object head = plist;
2403
2404   Fcheck_valid_plist (plist);
2405
2406   while (!NILP (plist))
2407     {
2408       Lisp_Object prop = Fcar (plist);
2409       Lisp_Object next = Fcdr (plist);
2410
2411       CHECK_CONS (next); /* just make doubly sure we catch any errors */
2412       if (!NILP (nil_means_not_present) && NILP (Fcar (next)))
2413         {
2414           if (EQ (head, plist))
2415             head = Fcdr (next);
2416           plist = Fcdr (next);
2417           continue;
2418         }
2419       /* external_remprop returns 1 if it removed any property.
2420          We have to loop till it didn't remove anything, in case
2421          the property occurs many times. */
2422       while (external_remprop (&XCDR (next), prop, 0, ERROR_ME))
2423         DO_NOTHING;
2424       plist = Fcdr (next);
2425     }
2426
2427   return head;
2428 }
2429
2430 DEFUN ("lax-plist-get", Flax_plist_get, 2, 3, 0, /*
2431 Extract a value from a lax property list.
2432
2433 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
2434 VALUE1 PROP2 VALUE2...), where comparisons between properties is done
2435 using `equal' instead of `eq'.  This function returns the value
2436 corresponding to the given PROP, or DEFAULT if PROP is not one of the
2437 properties on the list.
2438 */
2439        (lax_plist, prop, default_))
2440 {
2441   Lisp_Object val = external_plist_get (&lax_plist, prop, 1, ERROR_ME);
2442   if (UNBOUNDP (val))
2443     return default_;
2444   return val;
2445 }
2446
2447 DEFUN ("lax-plist-put", Flax_plist_put, 3, 3, 0, /*
2448 Change value in LAX-PLIST of PROP to VAL.
2449 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
2450 VALUE1 PROP2 VALUE2...), where comparisons between properties is done
2451 using `equal' instead of `eq'.  PROP is usually a symbol and VAL is
2452 any object.  If PROP is already a property on the list, its value is
2453 set to VAL, otherwise the new PROP VAL pair is added.  The new plist
2454 is returned; use `(setq x (lax-plist-put x prop val))' to be sure to
2455 use the new value.  The LAX-PLIST is modified by side effects.
2456 */
2457        (lax_plist, prop, val))
2458 {
2459   external_plist_put (&lax_plist, prop, val, 1, ERROR_ME);
2460   return lax_plist;
2461 }
2462
2463 DEFUN ("lax-plist-remprop", Flax_plist_remprop, 2, 2, 0, /*
2464 Remove from LAX-PLIST the property PROP and its value.
2465 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
2466 VALUE1 PROP2 VALUE2...), where comparisons between properties is done
2467 using `equal' instead of `eq'.  PROP is usually a symbol.  The new
2468 plist is returned; use `(setq x (lax-plist-remprop x prop val))' to be
2469 sure to use the new value.  The LAX-PLIST is modified by side effects.
2470 */
2471        (lax_plist, prop))
2472 {
2473   external_remprop (&lax_plist, prop, 1, ERROR_ME);
2474   return lax_plist;
2475 }
2476
2477 DEFUN ("lax-plist-member", Flax_plist_member, 2, 2, 0, /*
2478 Return t if PROP has a value specified in LAX-PLIST.
2479 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
2480 VALUE1 PROP2 VALUE2...), where comparisons between properties is done
2481 using `equal' instead of `eq'.
2482 */
2483        (lax_plist, prop))
2484 {
2485   return UNBOUNDP (Flax_plist_get (lax_plist, prop, Qunbound)) ? Qnil : Qt;
2486 }
2487
2488 DEFUN ("canonicalize-lax-plist", Fcanonicalize_lax_plist, 1, 2, 0, /*
2489 Destructively remove any duplicate entries from a lax plist.
2490 In such cases, the first entry applies.
2491
2492 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with
2493  a nil value is removed.  This feature is a virus that has infected
2494  old Lisp implementations, but should not be used except for backward
2495  compatibility.
2496
2497 The new plist is returned.  If NIL-MEANS-NOT-PRESENT is given, the
2498  return value may not be EQ to the passed-in value, so make sure to
2499  `setq' the value back into where it came from.
2500 */
2501        (lax_plist, nil_means_not_present))
2502 {
2503   Lisp_Object head = lax_plist;
2504
2505   Fcheck_valid_plist (lax_plist);
2506
2507   while (!NILP (lax_plist))
2508     {
2509       Lisp_Object prop = Fcar (lax_plist);
2510       Lisp_Object next = Fcdr (lax_plist);
2511
2512       CHECK_CONS (next); /* just make doubly sure we catch any errors */
2513       if (!NILP (nil_means_not_present) && NILP (Fcar (next)))
2514         {
2515           if (EQ (head, lax_plist))
2516             head = Fcdr (next);
2517           lax_plist = Fcdr (next);
2518           continue;
2519         }
2520       /* external_remprop returns 1 if it removed any property.
2521          We have to loop till it didn't remove anything, in case
2522          the property occurs many times. */
2523       while (external_remprop (&XCDR (next), prop, 1, ERROR_ME))
2524         DO_NOTHING;
2525       lax_plist = Fcdr (next);
2526     }
2527
2528   return head;
2529 }
2530
2531 /* In C because the frame props stuff uses it */
2532
2533 DEFUN ("destructive-alist-to-plist", Fdestructive_alist_to_plist, 1, 1, 0, /*
2534 Convert association list ALIST into the equivalent property-list form.
2535 The plist is returned.  This converts from
2536
2537 \((a . 1) (b . 2) (c . 3))
2538
2539 into
2540
2541 \(a 1 b 2 c 3)
2542
2543 The original alist is destroyed in the process of constructing the plist.
2544 See also `alist-to-plist'.
2545 */
2546        (alist))
2547 {
2548   Lisp_Object head = alist;
2549   while (!NILP (alist))
2550     {
2551       /* remember the alist element. */
2552       Lisp_Object el = Fcar (alist);
2553
2554       Fsetcar (alist, Fcar (el));
2555       Fsetcar (el, Fcdr (el));
2556       Fsetcdr (el, Fcdr (alist));
2557       Fsetcdr (alist, el);
2558       alist = Fcdr (Fcdr (alist));
2559     }
2560
2561   return head;
2562 }
2563
2564 /* Symbol plists are directly accessible, so we need to protect against
2565    invalid property list structure */
2566
2567 static Lisp_Object
2568 symbol_getprop (Lisp_Object sym, Lisp_Object propname, Lisp_Object default_)
2569 {
2570   Lisp_Object val = external_plist_get (&XSYMBOL (sym)->plist, propname,
2571                                         0, ERROR_ME);
2572   return UNBOUNDP (val) ? default_ : val;
2573 }
2574
2575 static void
2576 symbol_putprop (Lisp_Object sym, Lisp_Object propname, Lisp_Object value)
2577 {
2578   external_plist_put (&XSYMBOL (sym)->plist, propname, value, 0, ERROR_ME);
2579 }
2580
2581 static int
2582 symbol_remprop (Lisp_Object symbol, Lisp_Object propname)
2583 {
2584   return external_remprop (&XSYMBOL (symbol)->plist, propname, 0, ERROR_ME);
2585 }
2586
2587 /* We store the string's extent info as the first element of the string's
2588    property list; and the string's MODIFF as the first or second element
2589    of the string's property list (depending on whether the extent info
2590    is present), but only if the string has been modified.  This is ugly
2591    but it reduces the memory allocated for the string in the vast
2592    majority of cases, where the string is never modified and has no
2593    extent info. */
2594
2595
2596 static Lisp_Object *
2597 string_plist_ptr (struct Lisp_String *s)
2598 {
2599   Lisp_Object *ptr = &s->plist;
2600
2601   if (CONSP (*ptr) && EXTENT_INFOP (XCAR (*ptr)))
2602     ptr = &XCDR (*ptr);
2603   if (CONSP (*ptr) && INTP (XCAR (*ptr)))
2604     ptr = &XCDR (*ptr);
2605   return ptr;
2606 }
2607
2608 static Lisp_Object
2609 string_getprop (struct Lisp_String *s, Lisp_Object property,
2610                 Lisp_Object default_)
2611 {
2612   Lisp_Object val = external_plist_get (string_plist_ptr (s), property, 0,
2613                                         ERROR_ME);
2614   return UNBOUNDP (val) ? default_ : val;
2615 }
2616
2617 static void
2618 string_putprop (struct Lisp_String *s, Lisp_Object property,
2619                 Lisp_Object value)
2620 {
2621   external_plist_put (string_plist_ptr (s), property, value, 0, ERROR_ME);
2622 }
2623
2624 static int
2625 string_remprop (struct Lisp_String *s, Lisp_Object property)
2626 {
2627   return external_remprop (string_plist_ptr (s), property, 0, ERROR_ME);
2628 }
2629
2630 static Lisp_Object
2631 string_plist (struct Lisp_String *s)
2632 {
2633   return *string_plist_ptr (s);
2634 }
2635
2636 DEFUN ("get", Fget, 2, 3, 0, /*
2637 Return the value of OBJECT's PROPNAME property.
2638 This is the last VALUE stored with `(put OBJECT PROPNAME VALUE)'.
2639 If there is no such property, return optional third arg DEFAULT
2640 \(which defaults to `nil').  OBJECT can be a symbol, face, extent,
2641 or string.  See also `put', `remprop', and `object-plist'.
2642 */
2643        (object, propname, default_))
2644 {
2645   /* Various places in emacs call Fget() and expect it not to quit,
2646      so don't quit. */
2647
2648   /* It's easiest to treat symbols specially because they may not
2649      be an lrecord */
2650   if (SYMBOLP (object))
2651     return symbol_getprop (object, propname, default_);
2652   else if (STRINGP (object))
2653     return string_getprop (XSTRING (object), propname, default_);
2654   else if (LRECORDP (object))
2655     {
2656       CONST struct lrecord_implementation *imp
2657         = XRECORD_LHEADER_IMPLEMENTATION (object);
2658       if (!imp->getprop)
2659         goto noprops;
2660
2661       {
2662         Lisp_Object val = (imp->getprop) (object, propname);
2663         if (UNBOUNDP (val))
2664           val = default_;
2665         return val;
2666       }
2667     }
2668   else
2669     {
2670     noprops:
2671       signal_simple_error ("Object type has no properties", object);
2672       return Qnil;              /* Not reached */
2673     }
2674 }
2675
2676 DEFUN ("put", Fput, 3, 3, 0, /*
2677 Store OBJECT's PROPNAME property with value VALUE.
2678 It can be retrieved with `(get OBJECT PROPNAME)'.  OBJECT can be a
2679 symbol, face, extent, or string.
2680
2681 For a string, no properties currently have predefined meanings.
2682 For the predefined properties for extents, see `set-extent-property'.
2683 For the predefined properties for faces, see `set-face-property'.
2684
2685 See also `get', `remprop', and `object-plist'.
2686 */
2687        (object, propname, value))
2688 {
2689   CHECK_SYMBOL (propname);
2690   CHECK_LISP_WRITEABLE (object);
2691
2692   if (SYMBOLP (object))
2693     symbol_putprop (object, propname, value);
2694   else if (STRINGP (object))
2695     string_putprop (XSTRING (object), propname, value);
2696   else if (LRECORDP (object))
2697     {
2698       CONST struct lrecord_implementation
2699         *imp = XRECORD_LHEADER_IMPLEMENTATION (object);
2700       if (imp->putprop)
2701         {
2702           if (! (imp->putprop) (object, propname, value))
2703             signal_simple_error ("Can't set property on object", propname);
2704         }
2705       else
2706         goto noprops;
2707     }
2708   else
2709     {
2710     noprops:
2711       signal_simple_error ("Object type has no settable properties", object);
2712     }
2713
2714   return value;
2715 }
2716
2717 void
2718 pure_put (Lisp_Object sym, Lisp_Object prop, Lisp_Object val)
2719 {
2720   Fput (sym, prop, Fpurecopy (val));
2721 }
2722
2723 DEFUN ("remprop", Fremprop, 2, 2, 0, /*
2724 Remove from OBJECT's property list the property PROPNAME and its
2725 value.  OBJECT can be a symbol, face, extent, or string.  Returns
2726 non-nil if the property list was actually changed (i.e. if PROPNAME
2727 was present in the property list).  See also `get', `put', and
2728 `object-plist'.
2729 */
2730        (object, propname))
2731 {
2732   int retval = 0;
2733
2734   CHECK_SYMBOL (propname);
2735   CHECK_LISP_WRITEABLE (object);
2736
2737   if (SYMBOLP (object))
2738     retval = symbol_remprop (object, propname);
2739   else if (STRINGP (object))
2740     retval = string_remprop (XSTRING (object), propname);
2741   else if (LRECORDP (object))
2742     {
2743       CONST struct lrecord_implementation
2744         *imp = XRECORD_LHEADER_IMPLEMENTATION (object);
2745       if (imp->remprop)
2746         {
2747           retval = (imp->remprop) (object, propname);
2748           if (retval == -1)
2749             signal_simple_error ("Can't remove property from object",
2750                                  propname);
2751         }
2752       else
2753         goto noprops;
2754     }
2755   else
2756     {
2757     noprops:
2758       signal_simple_error ("Object type has no removable properties", object);
2759     }
2760
2761   return retval ? Qt : Qnil;
2762 }
2763
2764 DEFUN ("object-plist", Fobject_plist, 1, 1, 0, /*
2765 Return a property list of OBJECT's props.
2766 For a symbol this is equivalent to `symbol-plist'.
2767 Do not modify the property list directly; this may or may not have
2768 the desired effects. (In particular, for a property with a special
2769 interpretation, this will probably have no effect at all.)
2770 */
2771        (object))
2772 {
2773   if (SYMBOLP (object))
2774     return Fsymbol_plist (object);
2775   else if (STRINGP (object))
2776     return string_plist (XSTRING (object));
2777   else if (LRECORDP (object))
2778     {
2779       CONST struct lrecord_implementation
2780         *imp = XRECORD_LHEADER_IMPLEMENTATION (object);
2781       if (imp->plist)
2782         return (imp->plist) (object);
2783       else
2784         signal_simple_error ("Object type has no properties", object);
2785     }
2786   else
2787     signal_simple_error ("Object type has no properties", object);
2788
2789   return Qnil;
2790 }
2791
2792 \f
2793 int
2794 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
2795 {
2796   if (depth > 200)
2797     error ("Stack overflow in equal");
2798   QUIT;
2799   if (EQ_WITH_EBOLA_NOTICE (obj1, obj2))
2800     return 1;
2801   /* Note that (equal 20 20.0) should be nil */
2802   if (XTYPE (obj1) != XTYPE (obj2))
2803     return 0;
2804   if (LRECORDP (obj1))
2805     {
2806       CONST struct lrecord_implementation
2807         *imp1 = XRECORD_LHEADER_IMPLEMENTATION (obj1),
2808         *imp2 = XRECORD_LHEADER_IMPLEMENTATION (obj2);
2809
2810       return (imp1 == imp2) &&
2811         /* EQ-ness of the objects was noticed above */
2812         (imp1->equal && (imp1->equal) (obj1, obj2, depth));
2813     }
2814
2815   return 0;
2816 }
2817
2818 /* Note that we may be calling sub-objects that will use
2819    internal_equal() (instead of internal_old_equal()).  Oh well.
2820    We will get an Ebola note if there's any possibility of confusion,
2821    but that seems unlikely. */
2822
2823 static int
2824 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
2825 {
2826   if (depth > 200)
2827     error ("Stack overflow in equal");
2828   QUIT;
2829   if (HACKEQ_UNSAFE (obj1, obj2))
2830     return 1;
2831   /* Note that (equal 20 20.0) should be nil */
2832   if (XTYPE (obj1) != XTYPE (obj2))
2833     return 0;
2834
2835   return internal_equal (obj1, obj2, depth);
2836 }
2837
2838 DEFUN ("equal", Fequal, 2, 2, 0, /*
2839 Return t if two Lisp objects have similar structure and contents.
2840 They must have the same data type.
2841 Conses are compared by comparing the cars and the cdrs.
2842 Vectors and strings are compared element by element.
2843 Numbers are compared by value.  Symbols must match exactly.
2844 */
2845        (obj1, obj2))
2846 {
2847   return internal_equal (obj1, obj2, 0) ? Qt : Qnil;
2848 }
2849
2850 DEFUN ("old-equal", Fold_equal, 2, 2, 0, /*
2851 Return t if two Lisp objects have similar structure and contents.
2852 They must have the same data type.
2853 \(Note, however, that an exception is made for characters and integers;
2854 this is known as the "char-int confoundance disease." See `eq' and
2855 `old-eq'.)
2856 This function is provided only for byte-code compatibility with v19.
2857 Do not use it.
2858 */
2859        (obj1, obj2))
2860 {
2861   return internal_old_equal (obj1, obj2, 0) ? Qt : Qnil;
2862 }
2863
2864 \f
2865 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /*
2866 Store each element of ARRAY with ITEM.
2867 ARRAY is a vector, bit vector, or string.
2868 */
2869        (array, item))
2870 {
2871  retry:
2872   if (STRINGP (array))
2873     {
2874       Emchar charval;
2875       struct Lisp_String *s = XSTRING (array);
2876       Charcount len = string_char_length (s);
2877       Charcount i;
2878       CHECK_CHAR_COERCE_INT (item);
2879       CHECK_LISP_WRITEABLE (array);
2880       charval = XCHAR (item);
2881       for (i = 0; i < len; i++)
2882         set_string_char (s, i, charval);
2883       bump_string_modiff (array);
2884     }
2885   else if (VECTORP (array))
2886     {
2887       Lisp_Object *p = XVECTOR_DATA (array);
2888       int len = XVECTOR_LENGTH (array);
2889       CHECK_LISP_WRITEABLE (array);
2890       while (len--)
2891         *p++ = item;
2892     }
2893   else if (BIT_VECTORP (array))
2894     {
2895       struct Lisp_Bit_Vector *v = XBIT_VECTOR (array);
2896       int len = bit_vector_length (v);
2897       int bit;
2898       CHECK_BIT (item);
2899       CHECK_LISP_WRITEABLE (array);
2900       bit = XINT (item);
2901       while (len--)
2902         set_bit_vector_bit (v, len, bit);
2903     }
2904   else
2905     {
2906       array = wrong_type_argument (Qarrayp, array);
2907       goto retry;
2908     }
2909   return array;
2910 }
2911
2912 Lisp_Object
2913 nconc2 (Lisp_Object arg1, Lisp_Object arg2)
2914 {
2915   Lisp_Object args[2];
2916   struct gcpro gcpro1;
2917   args[0] = arg1;
2918   args[1] = arg2;
2919
2920   GCPRO1 (args[0]);
2921   gcpro1.nvars = 2;
2922
2923   RETURN_UNGCPRO (bytecode_nconc2 (args));
2924 }
2925
2926 Lisp_Object
2927 bytecode_nconc2 (Lisp_Object *args)
2928 {
2929  retry:
2930
2931   if (CONSP (args[0]))
2932     {
2933       /* (setcdr (last args[0]) args[1]) */
2934       Lisp_Object tortoise, hare;
2935       int count;
2936
2937       for (hare = tortoise = args[0], count = 0;
2938            CONSP (XCDR (hare));
2939            hare = XCDR (hare), count++)
2940         {
2941           if (count < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
2942
2943           if (count & 1)
2944             tortoise = XCDR (tortoise);
2945           if (EQ (hare, tortoise))
2946             signal_circular_list_error (args[0]);
2947         }
2948       XCDR (hare) = args[1];
2949       return args[0];
2950     }
2951   else if (NILP (args[0]))
2952     {
2953       return args[1];
2954     }
2955   else
2956     {
2957       args[0] = wrong_type_argument (args[0], Qlistp);
2958       goto retry;
2959     }
2960 }
2961
2962 DEFUN ("nconc", Fnconc, 0, MANY, 0, /*
2963 Concatenate any number of lists by altering them.
2964 Only the last argument is not altered, and need not be a list.
2965 Also see: `append'.
2966 If the first argument is nil, there is no way to modify it by side
2967 effect; therefore, write `(setq foo (nconc foo list))' to be sure of
2968 changing the value of `foo'.
2969 */
2970        (int nargs, Lisp_Object *args))
2971 {
2972   int argnum = 0;
2973   struct gcpro gcpro1;
2974
2975   /* The modus operandi in Emacs is "caller gc-protects args".
2976      However, nconc (particularly nconc2 ()) is called many times
2977      in Emacs on freshly created stuff (e.g. you see the idiom
2978      nconc2 (Fcopy_sequence (foo), bar) a lot).  So we help those
2979      callers out by protecting the args ourselves to save them
2980      a lot of temporary-variable grief. */
2981
2982   GCPRO1 (args[0]);
2983   gcpro1.nvars = nargs;
2984
2985   while (argnum < nargs)
2986     {
2987       Lisp_Object val;
2988     retry:
2989       val = args[argnum];
2990       if (CONSP (val))
2991         {
2992           /* `val' is the first cons, which will be our return value.  */
2993           /* `last_cons' will be the cons cell to mutate.  */
2994           Lisp_Object last_cons = val;
2995           Lisp_Object tortoise = val;
2996
2997           for (argnum++; argnum < nargs; argnum++)
2998             {
2999               Lisp_Object next = args[argnum];
3000             retry_next:
3001               if (CONSP (next) || argnum == nargs -1)
3002                 {
3003                   /* (setcdr (last val) next) */
3004                   int count;
3005
3006                   for (count = 0;
3007                        CONSP (XCDR (last_cons));
3008                        last_cons = XCDR (last_cons), count++)
3009                     {
3010                       if (count < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
3011
3012                       if (count & 1)
3013                         tortoise = XCDR (tortoise);
3014                       if (EQ (last_cons, tortoise))
3015                         signal_circular_list_error (args[argnum-1]);
3016                     }
3017                   XCDR (last_cons) = next;
3018                 }
3019               else if (NILP (next))
3020                 {
3021                   continue;
3022                 }
3023               else
3024                 {
3025                   next = wrong_type_argument (Qlistp, next);
3026                   goto retry_next;
3027                 }
3028             }
3029           RETURN_UNGCPRO (val);
3030         }
3031       else if (NILP (val))
3032         argnum++;
3033       else if (argnum == nargs - 1) /* last arg? */
3034         RETURN_UNGCPRO (val);
3035       else
3036         {
3037           args[argnum] = wrong_type_argument (Qlistp, val);
3038           goto retry;
3039         }
3040     }
3041   RETURN_UNGCPRO (Qnil);  /* No non-nil args provided. */
3042 }
3043
3044 \f
3045 /* This is the guts of all mapping functions.
3046    Apply fn to each element of seq, one by one,
3047    storing the results into elements of vals, a C vector of Lisp_Objects.
3048    leni is the length of vals, which should also be the length of seq.
3049
3050    If VALS is a null pointer, do not accumulate the results. */
3051
3052 static void
3053 mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
3054 {
3055   Lisp_Object result;
3056   Lisp_Object args[2];
3057   int i;
3058   struct gcpro gcpro1;
3059
3060   if (vals)
3061     {
3062       GCPRO1 (vals[0]);
3063       gcpro1.nvars = 0;
3064     }
3065
3066   args[0] = fn;
3067
3068   if (LISTP (seq))
3069     {
3070       for (i = 0; i < leni; i++)
3071         {
3072           args[1] = XCAR (seq);
3073           seq = XCDR (seq);
3074           result = Ffuncall (2, args);
3075           if (vals) vals[gcpro1.nvars++] = result;
3076         }
3077     }
3078   else if (VECTORP (seq))
3079     {
3080       Lisp_Object *objs = XVECTOR_DATA (seq);
3081       for (i = 0; i < leni; i++)
3082         {
3083           args[1] = *objs++;
3084           result = Ffuncall (2, args);
3085           if (vals) vals[gcpro1.nvars++] = result;
3086         }
3087     }
3088   else if (STRINGP (seq))
3089     {
3090       Bufbyte *p = XSTRING_DATA (seq);
3091       for (i = 0; i < leni; i++)
3092         {
3093           args[1] = make_char (charptr_emchar (p));
3094           INC_CHARPTR (p);
3095           result = Ffuncall (2, args);
3096           if (vals) vals[gcpro1.nvars++] = result;
3097         }
3098     }
3099   else if (BIT_VECTORP (seq))
3100     {
3101       struct Lisp_Bit_Vector *v = XBIT_VECTOR (seq);
3102       for (i = 0; i < leni; i++)
3103         {
3104           args[1] = make_int (bit_vector_bit (v, i));
3105           result = Ffuncall (2, args);
3106           if (vals) vals[gcpro1.nvars++] = result;
3107         }
3108     }
3109   else
3110     abort(); /* cannot get here since Flength(seq) did not get an error */
3111
3112   if (vals)
3113     UNGCPRO;
3114 }
3115
3116 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /*
3117 Apply FN to each element of SEQ, and concat the results as strings.
3118 In between each pair of results, stick in SEP.
3119 Thus, " " as SEP results in spaces between the values returned by FN.
3120 */
3121        (fn, seq, sep))
3122 {
3123   size_t len = XINT (Flength (seq));
3124   Lisp_Object *args;
3125   int i;
3126   struct gcpro gcpro1;
3127   int nargs = len + len - 1;
3128
3129   if (nargs < 0) return build_string ("");
3130
3131   args = alloca_array (Lisp_Object, nargs);
3132
3133   GCPRO1 (sep);
3134   mapcar1 (len, args, fn, seq);
3135   UNGCPRO;
3136
3137   for (i = len - 1; i >= 0; i--)
3138     args[i + i] = args[i];
3139
3140   for (i = 1; i < nargs; i += 2)
3141     args[i] = sep;
3142
3143   return Fconcat (nargs, args);
3144 }
3145
3146 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /*
3147 Apply FUNCTION to each element of SEQUENCE, and make a list of the results.
3148 The result is a list just as long as SEQUENCE.
3149 SEQUENCE may be a list, a vector, a bit vector, or a string.
3150 */
3151        (fn, seq))
3152 {
3153   size_t len = XINT (Flength (seq));
3154   Lisp_Object *args = alloca_array (Lisp_Object, len);
3155
3156   mapcar1 (len, args, fn, seq);
3157
3158   return Flist (len, args);
3159 }
3160
3161 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /*
3162 Apply FUNCTION to each element of SEQUENCE, making a vector of the results.
3163 The result is a vector of the same length as SEQUENCE.
3164 SEQUENCE may be a list, a vector or a string.
3165 */
3166        (fn, seq))
3167 {
3168   size_t len = XINT (Flength (seq));
3169   Lisp_Object result = make_vector (len, Qnil);
3170   struct gcpro gcpro1;
3171
3172   GCPRO1 (result);
3173   mapcar1 (len, XVECTOR_DATA (result), fn, seq);
3174   UNGCPRO;
3175
3176   return result;
3177 }
3178
3179 DEFUN ("mapc", Fmapc, 2, 2, 0, /*
3180 Apply FUNCTION to each element of SEQUENCE.
3181 SEQUENCE may be a list, a vector, a bit vector, or a string.
3182 This function is like `mapcar' but does not accumulate the results,
3183 which is more efficient if you do not use the results.
3184 */
3185        (fn, seq))
3186 {
3187   mapcar1 (XINT (Flength (seq)), 0, fn, seq);
3188
3189   return seq;
3190 }
3191
3192 \f
3193 /* #### this function doesn't belong in this file! */
3194
3195 DEFUN ("load-average", Fload_average, 0, 1, 0, /*
3196 Return list of 1 minute, 5 minute and 15 minute load averages.
3197 Each of the three load averages is multiplied by 100,
3198 then converted to integer.
3199
3200 When USE-FLOATS is non-nil, floats will be used instead of integers.
3201 These floats are not multiplied by 100.
3202
3203 If the 5-minute or 15-minute load averages are not available, return a
3204 shortened list, containing only those averages which are available.
3205
3206 On some systems, this won't work due to permissions on /dev/kmem,
3207 in which case you can't use this.
3208 */
3209        (use_floats))
3210 {
3211   double load_ave[3];
3212   int loads = getloadavg (load_ave, countof (load_ave));
3213   Lisp_Object ret = Qnil;
3214
3215   if (loads == -2)
3216     error ("load-average not implemented for this operating system");
3217   else if (loads < 0)
3218     signal_simple_error ("Could not get load-average",
3219                          lisp_strerror (errno));
3220
3221   while (loads-- > 0)
3222     {
3223       Lisp_Object load = (NILP (use_floats) ?
3224                           make_int ((int) (100.0 * load_ave[loads]))
3225                           : make_float (load_ave[loads]));
3226       ret = Fcons (load, ret);
3227     }
3228   return ret;
3229 }
3230
3231 \f
3232 Lisp_Object Vfeatures;
3233
3234 DEFUN ("featurep", Ffeaturep, 1, 1, 0, /*
3235 Return non-nil if feature FEXP is present in this Emacs.
3236 Use this to conditionalize execution of lisp code based on the
3237  presence or absence of emacs or environment extensions.
3238 FEXP can be a symbol, a number, or a list.
3239 If it is a symbol, that symbol is looked up in the `features' variable,
3240  and non-nil will be returned if found.
3241 If it is a number, the function will return non-nil if this Emacs
3242  has an equal or greater version number than FEXP.
3243 If it is a list whose car is the symbol `and', it will return
3244  non-nil if all the features in its cdr are non-nil.
3245 If it is a list whose car is the symbol `or', it will return non-nil
3246  if any of the features in its cdr are non-nil.
3247 If it is a list whose car is the symbol `not', it will return
3248  non-nil if the feature is not present.
3249
3250 Examples:
3251
3252   (featurep 'xemacs)
3253     => ; Non-nil on XEmacs.
3254
3255   (featurep '(and xemacs gnus))
3256     => ; Non-nil on XEmacs with Gnus loaded.
3257
3258   (featurep '(or tty-frames (and emacs 19.30)))
3259     => ; Non-nil if this Emacs supports TTY frames.
3260
3261   (featurep '(or (and xemacs 19.15) (and emacs 19.34)))
3262     => ; Non-nil on XEmacs 19.15 and later, or FSF Emacs 19.34 and later.
3263
3264 NOTE: The advanced arguments of this function (anything other than a
3265 symbol) are not yet supported by FSF Emacs.  If you feel they are useful
3266 for supporting multiple Emacs variants, lobby Richard Stallman at
3267 <bug-gnu-emacs@prep.ai.mit.edu>.
3268 */
3269        (fexp))
3270 {
3271 #ifndef FEATUREP_SYNTAX
3272   CHECK_SYMBOL (fexp);
3273   return NILP (Fmemq (fexp, Vfeatures)) ? Qnil : Qt;
3274 #else  /* FEATUREP_SYNTAX */
3275   static double featurep_emacs_version;
3276
3277   /* Brute force translation from Erik Naggum's lisp function. */
3278   if (SYMBOLP (fexp))
3279     {
3280       /* Original definition */
3281       return NILP (Fmemq (fexp, Vfeatures)) ? Qnil : Qt;
3282     }
3283   else if (INTP (fexp) || FLOATP (fexp))
3284     {
3285       double d = extract_float (fexp);
3286
3287       if (featurep_emacs_version == 0.0)
3288         {
3289           featurep_emacs_version = XINT (Vemacs_major_version) +
3290             (XINT (Vemacs_minor_version) / 100.0);
3291         }
3292       return featurep_emacs_version >= d ? Qt : Qnil;
3293     }
3294   else if (CONSP (fexp))
3295     {
3296       Lisp_Object tem = XCAR (fexp);
3297       if (EQ (tem, Qnot))
3298         {
3299           Lisp_Object negate;
3300
3301           tem = XCDR (fexp);
3302           negate = Fcar (tem);
3303           if (!NILP (tem))
3304             return NILP (call1 (Qfeaturep, negate)) ? Qt : Qnil;
3305           else
3306             return Fsignal (Qinvalid_read_syntax, list1 (tem));
3307         }
3308       else if (EQ (tem, Qand))
3309         {
3310           tem = XCDR (fexp);
3311           /* Use Fcar/Fcdr for error-checking. */
3312           while (!NILP (tem) && !NILP (call1 (Qfeaturep, Fcar (tem))))
3313             {
3314               tem = Fcdr (tem);
3315             }
3316           return NILP (tem) ? Qt : Qnil;
3317         }
3318       else if (EQ (tem, Qor))
3319         {
3320           tem = XCDR (fexp);
3321           /* Use Fcar/Fcdr for error-checking. */
3322           while (!NILP (tem) && NILP (call1 (Qfeaturep, Fcar (tem))))
3323             {
3324               tem = Fcdr (tem);
3325             }
3326           return NILP (tem) ? Qnil : Qt;
3327         }
3328       else
3329         {
3330           return Fsignal (Qinvalid_read_syntax, list1 (XCDR (fexp)));
3331         }
3332     }
3333   else
3334     {
3335       return Fsignal (Qinvalid_read_syntax, list1 (fexp));
3336     }
3337 }
3338 #endif /* FEATUREP_SYNTAX */
3339
3340 DEFUN ("provide", Fprovide, 1, 1, 0, /*
3341 Announce that FEATURE is a feature of the current Emacs.
3342 This function updates the value of the variable `features'.
3343 */
3344        (feature))
3345 {
3346   Lisp_Object tem;
3347   CHECK_SYMBOL (feature);
3348   if (!NILP (Vautoload_queue))
3349     Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
3350   tem = Fmemq (feature, Vfeatures);
3351   if (NILP (tem))
3352     Vfeatures = Fcons (feature, Vfeatures);
3353   LOADHIST_ATTACH (Fcons (Qprovide, feature));
3354   return feature;
3355 }
3356
3357 DEFUN ("require", Frequire, 1, 2, 0, /*
3358 If feature FEATURE is not loaded, load it from FILENAME.
3359 If FEATURE is not a member of the list `features', then the feature
3360 is not loaded; so load the file FILENAME.
3361 If FILENAME is omitted, the printname of FEATURE is used as the file name.
3362 */
3363        (feature, file_name))
3364 {
3365   Lisp_Object tem;
3366   CHECK_SYMBOL (feature);
3367   tem = Fmemq (feature, Vfeatures);
3368   LOADHIST_ATTACH (Fcons (Qrequire, feature));
3369   if (!NILP (tem))
3370     return feature;
3371   else
3372     {
3373       int speccount = specpdl_depth ();
3374
3375       /* Value saved here is to be restored into Vautoload_queue */
3376       record_unwind_protect (un_autoload, Vautoload_queue);
3377       Vautoload_queue = Qt;
3378
3379       call4 (Qload, NILP (file_name) ? Fsymbol_name (feature) : file_name,
3380              Qnil, Qt, Qnil);
3381
3382       tem = Fmemq (feature, Vfeatures);
3383       if (NILP (tem))
3384         error ("Required feature %s was not provided",
3385                string_data (XSYMBOL (feature)->name));
3386
3387       /* Once loading finishes, don't undo it.  */
3388       Vautoload_queue = Qt;
3389       return unbind_to (speccount, feature);
3390     }
3391 }
3392 \f
3393 /* base64 encode/decode functions.
3394
3395    Originally based on code from GNU recode.  Ported to FSF Emacs by
3396    Lars Magne Ingebrigtsen and Karl Heuer.  Ported to XEmacs and
3397    subsequently heavily hacked by Hrvoje Niksic.  */
3398
3399 #define MIME_LINE_LENGTH 72
3400
3401 #define IS_ASCII(Character) \
3402   ((Character) < 128)
3403 #define IS_BASE64(Character) \
3404   (IS_ASCII (Character) && base64_char_to_value[Character] >= 0)
3405
3406 /* Table of characters coding the 64 values.  */
3407 static char base64_value_to_char[64] =
3408 {
3409   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',     /*  0- 9 */
3410   'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',     /* 10-19 */
3411   'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',     /* 20-29 */
3412   'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',     /* 30-39 */
3413   'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',     /* 40-49 */
3414   'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',     /* 50-59 */
3415   '8', '9', '+', '/'                                    /* 60-63 */
3416 };
3417
3418 /* Table of base64 values for first 128 characters.  */
3419 static short base64_char_to_value[128] =
3420 {
3421   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,      /*   0-  9 */
3422   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,      /*  10- 19 */
3423   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,      /*  20- 29 */
3424   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,      /*  30- 39 */
3425   -1,  -1,  -1,  62,  -1,  -1,  -1,  63,  52,  53,      /*  40- 49 */
3426   54,  55,  56,  57,  58,  59,  60,  61,  -1,  -1,      /*  50- 59 */
3427   -1,  -1,  -1,  -1,  -1,  0,   1,   2,   3,   4,       /*  60- 69 */
3428   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,      /*  70- 79 */
3429   15,  16,  17,  18,  19,  20,  21,  22,  23,  24,      /*  80- 89 */
3430   25,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,      /*  90- 99 */
3431   29,  30,  31,  32,  33,  34,  35,  36,  37,  38,      /* 100-109 */
3432   39,  40,  41,  42,  43,  44,  45,  46,  47,  48,      /* 110-119 */
3433   49,  50,  51,  -1,  -1,  -1,  -1,  -1                 /* 120-127 */
3434 };
3435
3436 /* The following diagram shows the logical steps by which three octets
3437    get transformed into four base64 characters.
3438
3439                  .--------.  .--------.  .--------.
3440                  |aaaaaabb|  |bbbbcccc|  |ccdddddd|
3441                  `--------'  `--------'  `--------'
3442                     6   2      4   4       2   6
3443                .--------+--------+--------+--------.
3444                |00aaaaaa|00bbbbbb|00cccccc|00dddddd|
3445                `--------+--------+--------+--------'
3446
3447                .--------+--------+--------+--------.
3448                |AAAAAAAA|BBBBBBBB|CCCCCCCC|DDDDDDDD|
3449                `--------+--------+--------+--------'
3450
3451    The octets are divided into 6 bit chunks, which are then encoded into
3452    base64 characters.  */
3453
3454 #define ADVANCE_INPUT(c, stream)                                \
3455  ((ec = Lstream_get_emchar (stream)) == -1 ? 0 :                \
3456   ((ec > 255) ?                                                 \
3457    (signal_simple_error ("Non-ascii character in base64 input", \
3458                          make_char (ec)), 0)                    \
3459    : (c = (Bufbyte)ec), 1))
3460
3461 static Bytind
3462 base64_encode_1 (Lstream *istream, Bufbyte *to, int line_break)
3463 {
3464   EMACS_INT counter = 0;
3465   Bufbyte *e = to;
3466   Emchar ec;
3467   unsigned int value;
3468
3469   while (1)
3470     {
3471       Bufbyte c;
3472       if (!ADVANCE_INPUT (c, istream))
3473         break;
3474
3475       /* Wrap line every 76 characters.  */
3476       if (line_break)
3477         {
3478           if (counter < MIME_LINE_LENGTH / 4)
3479             counter++;
3480           else
3481             {
3482               *e++ = '\n';
3483               counter = 1;
3484             }
3485         }
3486
3487       /* Process first byte of a triplet.  */
3488       *e++ = base64_value_to_char[0x3f & c >> 2];
3489       value = (0x03 & c) << 4;
3490
3491       /* Process second byte of a triplet.  */
3492       if (!ADVANCE_INPUT (c, istream))
3493         {
3494           *e++ = base64_value_to_char[value];
3495           *e++ = '=';
3496           *e++ = '=';
3497           break;
3498         }
3499
3500       *e++ = base64_value_to_char[value | (0x0f & c >> 4)];
3501       value = (0x0f & c) << 2;
3502
3503       /* Process third byte of a triplet.  */
3504       if (!ADVANCE_INPUT (c, istream))
3505         {
3506           *e++ = base64_value_to_char[value];
3507           *e++ = '=';
3508           break;
3509         }
3510
3511       *e++ = base64_value_to_char[value | (0x03 & c >> 6)];
3512       *e++ = base64_value_to_char[0x3f & c];
3513     }
3514
3515   return e - to;
3516 }
3517 #undef ADVANCE_INPUT
3518
3519 /* Get next character from the stream, except that non-base64
3520    characters are ignored.  This is in accordance with rfc2045.  EC
3521    should be an Emchar, so that it can hold -1 as the value for EOF.  */
3522 #define ADVANCE_INPUT_IGNORE_NONBASE64(ec, stream, streampos) do {      \
3523   ec = Lstream_get_emchar (stream);                                     \
3524   ++streampos;                                                          \
3525   /* IS_BASE64 may not be called with negative arguments so check for   \
3526      EOF first. */                                                      \
3527   if (ec < 0 || IS_BASE64 (ec) || ec == '=')                            \
3528     break;                                                              \
3529 } while (1)
3530
3531 #define STORE_BYTE(pos, val, ccnt) do {                                 \
3532   pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val)));      \
3533   ++ccnt;                                                               \
3534 } while (0)
3535
3536 static Bytind
3537 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr)
3538 {
3539   Charcount ccnt = 0;
3540   Bufbyte *e = to;
3541   EMACS_INT streampos = 0;
3542
3543   while (1)
3544     {
3545       Emchar ec;
3546       unsigned long value;
3547
3548       /* Process first byte of a quadruplet.  */
3549       ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3550       if (ec < 0)
3551         break;
3552       if (ec == '=')
3553         signal_simple_error ("Illegal `=' character while decoding base64",
3554                              make_int (streampos));
3555       value = base64_char_to_value[ec] << 18;
3556
3557       /* Process second byte of a quadruplet.  */
3558       ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3559       if (ec < 0)
3560         error ("Premature EOF while decoding base64");
3561       if (ec == '=')
3562         signal_simple_error ("Illegal `=' character while decoding base64",
3563                              make_int (streampos));
3564       value |= base64_char_to_value[ec] << 12;
3565       STORE_BYTE (e, value >> 16, ccnt);
3566
3567       /* Process third byte of a quadruplet.  */
3568       ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3569       if (ec < 0)
3570         error ("Premature EOF while decoding base64");
3571
3572       if (ec == '=')
3573         {
3574           ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3575           if (ec < 0)
3576             error ("Premature EOF while decoding base64");
3577           if (ec != '=')
3578             signal_simple_error ("Padding `=' expected but not found while decoding base64",
3579                                  make_int (streampos));
3580           continue;
3581         }
3582
3583       value |= base64_char_to_value[ec] << 6;
3584       STORE_BYTE (e, 0xff & value >> 8, ccnt);
3585
3586       /* Process fourth byte of a quadruplet.  */
3587       ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3588       if (ec < 0)
3589         error ("Premature EOF while decoding base64");
3590       if (ec == '=')
3591         continue;
3592
3593       value |= base64_char_to_value[ec];
3594       STORE_BYTE (e, 0xff & value, ccnt);
3595     }
3596
3597   *ccptr = ccnt;
3598   return e - to;
3599 }
3600 #undef ADVANCE_INPUT
3601 #undef ADVANCE_INPUT_IGNORE_NONBASE64
3602 #undef STORE_BYTE
3603
3604 static Lisp_Object
3605 free_malloced_ptr (Lisp_Object unwind_obj)
3606 {
3607   void *ptr = (void *)get_opaque_ptr (unwind_obj);
3608   xfree (ptr);
3609   free_opaque_ptr (unwind_obj);
3610   return Qnil;
3611 }
3612
3613 /* Don't use alloca for regions larger than this, lest we overflow
3614    the stack.  */
3615 #define MAX_ALLOCA 65536
3616
3617 /* We need to setup proper unwinding, because there is a number of
3618    ways these functions can blow up, and we don't want to have memory
3619    leaks in those cases.  */
3620 #define XMALLOC_OR_ALLOCA(ptr, len, type) do {                  \
3621   size_t XOA_len = (len);                                       \
3622   if (XOA_len > MAX_ALLOCA)                                     \
3623     {                                                           \
3624       ptr = xnew_array (type, XOA_len);                         \
3625       record_unwind_protect (free_malloced_ptr,                 \
3626                              make_opaque_ptr ((void *)ptr));    \
3627     }                                                           \
3628   else                                                          \
3629     ptr = alloca_array (type, XOA_len);                         \
3630 } while (0)
3631
3632 #define XMALLOC_UNBIND(ptr, len, speccount) do {                \
3633   if ((len) > MAX_ALLOCA)                                       \
3634     unbind_to (speccount, Qnil);                                \
3635 } while (0)
3636
3637 DEFUN ("base64-encode-region", Fbase64_encode_region, 2, 3, "r", /*
3638 Base64-encode the region between BEG and END.
3639 Return the length of the encoded text.
3640 Optional third argument NO-LINE-BREAK means do not break long lines
3641 into shorter lines.
3642 */
3643        (beg, end, no_line_break))
3644 {
3645   Bufbyte *encoded;
3646   Bytind encoded_length;
3647   Charcount allength, length;
3648   struct buffer *buf = current_buffer;
3649   Bufpos begv, zv, old_pt = BUF_PT (buf);
3650   Lisp_Object input;
3651   int speccount = specpdl_depth();
3652
3653   get_buffer_range_char (buf, beg, end, &begv, &zv, 0);
3654   barf_if_buffer_read_only (buf, begv, zv);
3655
3656   /* We need to allocate enough room for encoding the text.
3657      We need 33 1/3% more space, plus a newline every 76
3658      characters, and then we round up. */
3659   length = zv - begv;
3660   allength = length + length/3 + 1;
3661   allength += allength / MIME_LINE_LENGTH + 1 + 6;
3662
3663   input = make_lisp_buffer_input_stream (buf, begv, zv, 0);
3664   /* We needn't multiply allength with MAX_EMCHAR_LEN because all the
3665      base64 characters will be single-byte.  */
3666   XMALLOC_OR_ALLOCA (encoded, allength, Bufbyte);
3667   encoded_length = base64_encode_1 (XLSTREAM (input), encoded,
3668                                     NILP (no_line_break));
3669   if (encoded_length > allength)
3670     abort ();
3671   Lstream_delete (XLSTREAM (input));
3672
3673   /* Now we have encoded the region, so we insert the new contents
3674      and delete the old.  (Insert first in order to preserve markers.)  */
3675   buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0);
3676   XMALLOC_UNBIND (encoded, allength, speccount);
3677   buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0);
3678
3679   /* Simulate FSF Emacs implementation of this function: if point was
3680      in the region, place it at the beginning.  */
3681   if (old_pt >= begv && old_pt < zv)
3682     BUF_SET_PT (buf, begv);
3683
3684   /* We return the length of the encoded text. */
3685   return make_int (encoded_length);
3686 }
3687
3688 DEFUN ("base64-encode-string", Fbase64_encode_string, 1, 2, 0, /*
3689 Base64 encode STRING and return the result.
3690 */
3691        (string, no_line_break))
3692 {
3693   Charcount allength, length;
3694   Bytind encoded_length;
3695   Bufbyte *encoded;
3696   Lisp_Object input, result;
3697   int speccount = specpdl_depth();
3698
3699   CHECK_STRING (string);
3700
3701   length = XSTRING_CHAR_LENGTH (string);
3702   allength = length + length/3 + 1;
3703   allength += allength / MIME_LINE_LENGTH + 1 + 6;
3704
3705   input = make_lisp_string_input_stream (string, 0, -1);
3706   XMALLOC_OR_ALLOCA (encoded, allength, Bufbyte);
3707   encoded_length = base64_encode_1 (XLSTREAM (input), encoded,
3708                                     NILP (no_line_break));
3709   if (encoded_length > allength)
3710     abort ();
3711   Lstream_delete (XLSTREAM (input));
3712   result = make_string (encoded, encoded_length);
3713   XMALLOC_UNBIND (encoded, allength, speccount);
3714   return result;
3715 }
3716
3717 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /*
3718 Base64-decode the region between BEG and END.
3719 Return the length of the decoded text.
3720 If the region can't be decoded, return nil and don't modify the buffer.
3721 Characters out of the base64 alphabet are ignored.
3722 */
3723        (beg, end))
3724 {
3725   struct buffer *buf = current_buffer;
3726   Bufpos begv, zv, old_pt = BUF_PT (buf);
3727   Bufbyte *decoded;
3728   Bytind decoded_length;
3729   Charcount length, cc_decoded_length;
3730   Lisp_Object input;
3731   int speccount = specpdl_depth();
3732
3733   get_buffer_range_char (buf, beg, end, &begv, &zv, 0);
3734   barf_if_buffer_read_only (buf, begv, zv);
3735
3736   length = zv - begv;
3737
3738   input = make_lisp_buffer_input_stream (buf, begv, zv, 0);
3739   /* We need to allocate enough room for decoding the text. */
3740   XMALLOC_OR_ALLOCA (decoded, length * MAX_EMCHAR_LEN, Bufbyte);
3741   decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length);
3742   if (decoded_length > length * MAX_EMCHAR_LEN)
3743     abort ();
3744   Lstream_delete (XLSTREAM (input));
3745
3746   /* Now we have decoded the region, so we insert the new contents
3747      and delete the old.  (Insert first in order to preserve markers.)  */
3748   BUF_SET_PT (buf, begv);
3749   buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0);
3750   XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3751   buffer_delete_range (buf, begv + cc_decoded_length,
3752                        zv + cc_decoded_length, 0);
3753
3754   /* Simulate FSF Emacs implementation of this function: if point was
3755      in the region, place it at the beginning.  */
3756   if (old_pt >= begv && old_pt < zv)
3757     BUF_SET_PT (buf, begv);
3758
3759   return make_int (cc_decoded_length);
3760 }
3761
3762 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /*
3763 Base64-decode STRING and return the result.
3764 Characters out of the base64 alphabet are ignored.
3765 */
3766        (string))
3767 {
3768   Bufbyte *decoded;
3769   Bytind decoded_length;
3770   Charcount length, cc_decoded_length;
3771   Lisp_Object input, result;
3772   int speccount = specpdl_depth();
3773
3774   CHECK_STRING (string);
3775
3776   length = XSTRING_CHAR_LENGTH (string);
3777   /* We need to allocate enough room for decoding the text. */
3778   XMALLOC_OR_ALLOCA (decoded, length * MAX_EMCHAR_LEN, Bufbyte);
3779
3780   input = make_lisp_string_input_stream (string, 0, -1);
3781   decoded_length = base64_decode_1 (XLSTREAM (input), decoded,
3782                                     &cc_decoded_length);
3783   if (decoded_length > length * MAX_EMCHAR_LEN)
3784     abort ();
3785   Lstream_delete (XLSTREAM (input));
3786
3787   result = make_string (decoded, decoded_length);
3788   XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3789   return result;
3790 }
3791 \f
3792 Lisp_Object Qyes_or_no_p;
3793
3794 void
3795 syms_of_fns (void)
3796 {
3797   defsymbol (&Qstring_lessp, "string-lessp");
3798   defsymbol (&Qidentity, "identity");
3799   defsymbol (&Qyes_or_no_p, "yes-or-no-p");
3800
3801   DEFSUBR (Fidentity);
3802   DEFSUBR (Frandom);
3803   DEFSUBR (Flength);
3804   DEFSUBR (Fsafe_length);
3805   DEFSUBR (Fstring_equal);
3806   DEFSUBR (Fstring_lessp);
3807   DEFSUBR (Fstring_modified_tick);
3808   DEFSUBR (Fappend);
3809   DEFSUBR (Fconcat);
3810   DEFSUBR (Fvconcat);
3811   DEFSUBR (Fbvconcat);
3812   DEFSUBR (Fcopy_list);
3813   DEFSUBR (Fcopy_sequence);
3814   DEFSUBR (Fcopy_alist);
3815   DEFSUBR (Fcopy_tree);
3816   DEFSUBR (Fsubstring);
3817   DEFSUBR (Fsubseq);
3818   DEFSUBR (Fnthcdr);
3819   DEFSUBR (Fnth);
3820   DEFSUBR (Felt);
3821   DEFSUBR (Flast);
3822   DEFSUBR (Fbutlast);
3823   DEFSUBR (Fnbutlast);
3824   DEFSUBR (Fmember);
3825   DEFSUBR (Fold_member);
3826   DEFSUBR (Fmemq);
3827   DEFSUBR (Fold_memq);
3828   DEFSUBR (Fassoc);
3829   DEFSUBR (Fold_assoc);
3830   DEFSUBR (Fassq);
3831   DEFSUBR (Fold_assq);
3832   DEFSUBR (Frassoc);
3833   DEFSUBR (Fold_rassoc);
3834   DEFSUBR (Frassq);
3835   DEFSUBR (Fold_rassq);
3836   DEFSUBR (Fdelete);
3837   DEFSUBR (Fold_delete);
3838   DEFSUBR (Fdelq);
3839   DEFSUBR (Fold_delq);
3840   DEFSUBR (Fremassoc);
3841   DEFSUBR (Fremassq);
3842   DEFSUBR (Fremrassoc);
3843   DEFSUBR (Fremrassq);
3844   DEFSUBR (Fnreverse);
3845   DEFSUBR (Freverse);
3846   DEFSUBR (Fsort);
3847   DEFSUBR (Fplists_eq);
3848   DEFSUBR (Fplists_equal);
3849   DEFSUBR (Flax_plists_eq);
3850   DEFSUBR (Flax_plists_equal);
3851   DEFSUBR (Fplist_get);
3852   DEFSUBR (Fplist_put);
3853   DEFSUBR (Fplist_remprop);
3854   DEFSUBR (Fplist_member);
3855   DEFSUBR (Fcheck_valid_plist);
3856   DEFSUBR (Fvalid_plist_p);
3857   DEFSUBR (Fcanonicalize_plist);
3858   DEFSUBR (Flax_plist_get);
3859   DEFSUBR (Flax_plist_put);
3860   DEFSUBR (Flax_plist_remprop);
3861   DEFSUBR (Flax_plist_member);
3862   DEFSUBR (Fcanonicalize_lax_plist);
3863   DEFSUBR (Fdestructive_alist_to_plist);
3864   DEFSUBR (Fget);
3865   DEFSUBR (Fput);
3866   DEFSUBR (Fremprop);
3867   DEFSUBR (Fobject_plist);
3868   DEFSUBR (Fequal);
3869   DEFSUBR (Fold_equal);
3870   DEFSUBR (Ffillarray);
3871   DEFSUBR (Fnconc);
3872   DEFSUBR (Fmapcar);
3873   DEFSUBR (Fmapvector);
3874   DEFSUBR (Fmapc);
3875   DEFSUBR (Fmapconcat);
3876   DEFSUBR (Fload_average);
3877   DEFSUBR (Ffeaturep);
3878   DEFSUBR (Frequire);
3879   DEFSUBR (Fprovide);
3880   DEFSUBR (Fbase64_encode_region);
3881   DEFSUBR (Fbase64_encode_string);
3882   DEFSUBR (Fbase64_decode_region);
3883   DEFSUBR (Fbase64_decode_string);
3884 }
3885
3886 void
3887 init_provide_once (void)
3888 {
3889   DEFVAR_LISP ("features", &Vfeatures /*
3890 A list of symbols which are the features of the executing emacs.
3891 Used by `featurep' and `require', and altered by `provide'.
3892 */ );
3893   Vfeatures = Qnil;
3894
3895   Fprovide (intern ("base64"));
3896 }