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