(mark_kboards): Mark all the Lisp_Object fields.
[bpt/emacs.git] / src / fns.c
1 /* Random utility Lisp functions.
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include <config.h>
23
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #include <time.h>
28
29 /* Note on some machines this defines `vector' as a typedef,
30 so make sure we don't use that name in this file. */
31 #undef vector
32 #define vector *****
33
34 #include "lisp.h"
35 #include "commands.h"
36 #include "charset.h"
37
38 #include "buffer.h"
39 #include "keyboard.h"
40 #include "intervals.h"
41 #include "frame.h"
42 #include "window.h"
43 #if defined (HAVE_MENUS) && defined (HAVE_X_WINDOWS)
44 #include "xterm.h"
45 #endif
46
47 #ifndef NULL
48 #define NULL (void *)0
49 #endif
50
51 /* Nonzero enables use of dialog boxes for questions
52 asked by mouse commands. */
53 int use_dialog_box;
54
55 extern int minibuffer_auto_raise;
56 extern Lisp_Object minibuf_window;
57
58 Lisp_Object Qstring_lessp, Qprovide, Qrequire;
59 Lisp_Object Qyes_or_no_p_history;
60 Lisp_Object Qcursor_in_echo_area;
61 Lisp_Object Qwidget_type;
62
63 static int internal_equal ();
64
65 extern long get_random ();
66 extern void seed_random ();
67
68 #ifndef HAVE_UNISTD_H
69 extern long time ();
70 #endif
71 \f
72 DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
73 "Return the argument unchanged.")
74 (arg)
75 Lisp_Object arg;
76 {
77 return arg;
78 }
79
80 DEFUN ("random", Frandom, Srandom, 0, 1, 0,
81 "Return a pseudo-random number.\n\
82 All integers representable in Lisp are equally likely.\n\
83 On most systems, this is 28 bits' worth.\n\
84 With positive integer argument N, return random number in interval [0,N).\n\
85 With argument t, set the random number seed from the current time and pid.")
86 (n)
87 Lisp_Object n;
88 {
89 EMACS_INT val;
90 Lisp_Object lispy_val;
91 unsigned long denominator;
92
93 if (EQ (n, Qt))
94 seed_random (getpid () + time (NULL));
95 if (NATNUMP (n) && XFASTINT (n) != 0)
96 {
97 /* Try to take our random number from the higher bits of VAL,
98 not the lower, since (says Gentzel) the low bits of `random'
99 are less random than the higher ones. We do this by using the
100 quotient rather than the remainder. At the high end of the RNG
101 it's possible to get a quotient larger than n; discarding
102 these values eliminates the bias that would otherwise appear
103 when using a large n. */
104 denominator = ((unsigned long)1 << VALBITS) / XFASTINT (n);
105 do
106 val = get_random () / denominator;
107 while (val >= XFASTINT (n));
108 }
109 else
110 val = get_random ();
111 XSETINT (lispy_val, val);
112 return lispy_val;
113 }
114 \f
115 /* Random data-structure functions */
116
117 DEFUN ("length", Flength, Slength, 1, 1, 0,
118 "Return the length of vector, list or string SEQUENCE.\n\
119 A byte-code function object is also allowed.\n\
120 If the string contains multibyte characters, this is not the necessarily\n\
121 the number of bytes in the string; it is the number of characters.\n\
122 To get the number of bytes, use `string-bytes'")
123 (sequence)
124 register Lisp_Object sequence;
125 {
126 register Lisp_Object tail, val;
127 register int i;
128
129 retry:
130 if (STRINGP (sequence))
131 XSETFASTINT (val, XSTRING (sequence)->size);
132 else if (VECTORP (sequence))
133 XSETFASTINT (val, XVECTOR (sequence)->size);
134 else if (CHAR_TABLE_P (sequence))
135 XSETFASTINT (val, (MIN_CHAR_COMPOSITION
136 + (CHAR_FIELD2_MASK | CHAR_FIELD3_MASK)
137 - 1));
138 else if (BOOL_VECTOR_P (sequence))
139 XSETFASTINT (val, XBOOL_VECTOR (sequence)->size);
140 else if (COMPILEDP (sequence))
141 XSETFASTINT (val, XVECTOR (sequence)->size & PSEUDOVECTOR_SIZE_MASK);
142 else if (CONSP (sequence))
143 {
144 for (i = 0, tail = sequence; !NILP (tail); i++)
145 {
146 QUIT;
147 tail = Fcdr (tail);
148 }
149
150 XSETFASTINT (val, i);
151 }
152 else if (NILP (sequence))
153 XSETFASTINT (val, 0);
154 else
155 {
156 sequence = wrong_type_argument (Qsequencep, sequence);
157 goto retry;
158 }
159 return val;
160 }
161
162 /* This does not check for quits. That is safe
163 since it must terminate. */
164
165 DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
166 "Return the length of a list, but avoid error or infinite loop.\n\
167 This function never gets an error. If LIST is not really a list,\n\
168 it returns 0. If LIST is circular, it returns a finite value\n\
169 which is at least the number of distinct elements.")
170 (list)
171 Lisp_Object list;
172 {
173 Lisp_Object tail, halftail, length;
174 int len = 0;
175
176 /* halftail is used to detect circular lists. */
177 halftail = list;
178 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
179 {
180 if (EQ (tail, halftail) && len != 0)
181 break;
182 len++;
183 if ((len & 1) == 0)
184 halftail = XCONS (halftail)->cdr;
185 }
186
187 XSETINT (length, len);
188 return length;
189 }
190
191 DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
192 "Return the number of bytes in STRING.\n\
193 If STRING is a multibyte string, this is greater than the length of STRING.")
194 (string)
195 Lisp_Object string;
196 {
197 CHECK_STRING (string, 1);
198 return make_number (STRING_BYTES (XSTRING (string)));
199 }
200
201 DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
202 "Return t if two strings have identical contents.\n\
203 Case is significant, but text properties are ignored.\n\
204 Symbols are also allowed; their print names are used instead.")
205 (s1, s2)
206 register Lisp_Object s1, s2;
207 {
208 if (SYMBOLP (s1))
209 XSETSTRING (s1, XSYMBOL (s1)->name);
210 if (SYMBOLP (s2))
211 XSETSTRING (s2, XSYMBOL (s2)->name);
212 CHECK_STRING (s1, 0);
213 CHECK_STRING (s2, 1);
214
215 if (XSTRING (s1)->size != XSTRING (s2)->size
216 || STRING_BYTES (XSTRING (s1)) != STRING_BYTES (XSTRING (s2))
217 || bcmp (XSTRING (s1)->data, XSTRING (s2)->data, STRING_BYTES (XSTRING (s1))))
218 return Qnil;
219 return Qt;
220 }
221
222 DEFUN ("compare-strings", Fcompare_strings,
223 Scompare_strings, 6, 7, 0,
224 "Compare the contents of two strings, converting to multibyte if needed.\n\
225 In string STR1, skip the first START1 characters and stop at END1.\n\
226 In string STR2, skip the first START2 characters and stop at END2.\n\
227 END1 and END2 default to the full lengths of the respective strings.\n\
228 \n\
229 Case is significant in this comparison if IGNORE-CASE is nil.\n\
230 Unibyte strings are converted to multibyte for comparison.\n\
231 \n\
232 The value is t if the strings (or specified portions) match.\n\
233 If string STR1 is less, the value is a negative number N;\n\
234 - 1 - N is the number of characters that match at the beginning.\n\
235 If string STR1 is greater, the value is a positive number N;\n\
236 N - 1 is the number of characters that match at the beginning.")
237 (str1, start1, end1, str2, start2, end2, ignore_case)
238 Lisp_Object str1, start1, end1, start2, str2, end2, ignore_case;
239 {
240 register int end1_char, end2_char;
241 register int i1, i1_byte, i2, i2_byte;
242
243 CHECK_STRING (str1, 0);
244 CHECK_STRING (str2, 1);
245 if (NILP (start1))
246 start1 = make_number (0);
247 if (NILP (start2))
248 start2 = make_number (0);
249 CHECK_NATNUM (start1, 2);
250 CHECK_NATNUM (start2, 3);
251 if (! NILP (end1))
252 CHECK_NATNUM (end1, 4);
253 if (! NILP (end2))
254 CHECK_NATNUM (end2, 4);
255
256 i1 = XINT (start1);
257 i2 = XINT (start2);
258
259 i1_byte = string_char_to_byte (str1, i1);
260 i2_byte = string_char_to_byte (str2, i2);
261
262 end1_char = XSTRING (str1)->size;
263 if (! NILP (end1) && end1_char > XINT (end1))
264 end1_char = XINT (end1);
265
266 end2_char = XSTRING (str2)->size;
267 if (! NILP (end2) && end2_char > XINT (end2))
268 end2_char = XINT (end2);
269
270 while (i1 < end1_char && i2 < end2_char)
271 {
272 /* When we find a mismatch, we must compare the
273 characters, not just the bytes. */
274 int c1, c2;
275
276 if (STRING_MULTIBYTE (str1))
277 FETCH_STRING_CHAR_ADVANCE (c1, str1, i1, i1_byte);
278 else
279 {
280 c1 = XSTRING (str1)->data[i1++];
281 c1 = unibyte_char_to_multibyte (c1);
282 }
283
284 if (STRING_MULTIBYTE (str2))
285 FETCH_STRING_CHAR_ADVANCE (c2, str2, i2, i2_byte);
286 else
287 {
288 c2 = XSTRING (str2)->data[i2++];
289 c2 = unibyte_char_to_multibyte (c2);
290 }
291
292 if (c1 == c2)
293 continue;
294
295 if (! NILP (ignore_case))
296 {
297 Lisp_Object tem;
298
299 tem = Fupcase (make_number (c1));
300 c1 = XINT (tem);
301 tem = Fupcase (make_number (c2));
302 c2 = XINT (tem);
303 }
304
305 if (c1 == c2)
306 continue;
307
308 /* Note that I1 has already been incremented
309 past the character that we are comparing;
310 hence we don't add or subtract 1 here. */
311 if (c1 < c2)
312 return make_number (- i1);
313 else
314 return make_number (i1);
315 }
316
317 if (i1 < end1_char)
318 return make_number (i1 - XINT (start1) + 1);
319 if (i2 < end2_char)
320 return make_number (- i1 + XINT (start1) - 1);
321
322 return Qt;
323 }
324
325 DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
326 "Return t if first arg string is less than second in lexicographic order.\n\
327 Case is significant.\n\
328 Symbols are also allowed; their print names are used instead.")
329 (s1, s2)
330 register Lisp_Object s1, s2;
331 {
332 register int end;
333 register int i1, i1_byte, i2, i2_byte;
334
335 if (SYMBOLP (s1))
336 XSETSTRING (s1, XSYMBOL (s1)->name);
337 if (SYMBOLP (s2))
338 XSETSTRING (s2, XSYMBOL (s2)->name);
339 CHECK_STRING (s1, 0);
340 CHECK_STRING (s2, 1);
341
342 i1 = i1_byte = i2 = i2_byte = 0;
343
344 end = XSTRING (s1)->size;
345 if (end > XSTRING (s2)->size)
346 end = XSTRING (s2)->size;
347
348 while (i1 < end)
349 {
350 /* When we find a mismatch, we must compare the
351 characters, not just the bytes. */
352 int c1, c2;
353
354 if (STRING_MULTIBYTE (s1))
355 FETCH_STRING_CHAR_ADVANCE (c1, s1, i1, i1_byte);
356 else
357 c1 = XSTRING (s1)->data[i1++];
358
359 if (STRING_MULTIBYTE (s2))
360 FETCH_STRING_CHAR_ADVANCE (c2, s2, i2, i2_byte);
361 else
362 c2 = XSTRING (s2)->data[i2++];
363
364 if (c1 != c2)
365 return c1 < c2 ? Qt : Qnil;
366 }
367 return i1 < XSTRING (s2)->size ? Qt : Qnil;
368 }
369 \f
370 static Lisp_Object concat ();
371
372 /* ARGSUSED */
373 Lisp_Object
374 concat2 (s1, s2)
375 Lisp_Object s1, s2;
376 {
377 #ifdef NO_ARG_ARRAY
378 Lisp_Object args[2];
379 args[0] = s1;
380 args[1] = s2;
381 return concat (2, args, Lisp_String, 0);
382 #else
383 return concat (2, &s1, Lisp_String, 0);
384 #endif /* NO_ARG_ARRAY */
385 }
386
387 /* ARGSUSED */
388 Lisp_Object
389 concat3 (s1, s2, s3)
390 Lisp_Object s1, s2, s3;
391 {
392 #ifdef NO_ARG_ARRAY
393 Lisp_Object args[3];
394 args[0] = s1;
395 args[1] = s2;
396 args[2] = s3;
397 return concat (3, args, Lisp_String, 0);
398 #else
399 return concat (3, &s1, Lisp_String, 0);
400 #endif /* NO_ARG_ARRAY */
401 }
402
403 DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
404 "Concatenate all the arguments and make the result a list.\n\
405 The result is a list whose elements are the elements of all the arguments.\n\
406 Each argument may be a list, vector or string.\n\
407 The last argument is not copied, just used as the tail of the new list.")
408 (nargs, args)
409 int nargs;
410 Lisp_Object *args;
411 {
412 return concat (nargs, args, Lisp_Cons, 1);
413 }
414
415 DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
416 "Concatenate all the arguments and make the result a string.\n\
417 The result is a string whose elements are the elements of all the arguments.\n\
418 Each argument may be a string or a list or vector of characters (integers).\n\
419 \n\
420 Do not use individual integers as arguments!\n\
421 The behavior of `concat' in that case will be changed later!\n\
422 If your program passes an integer as an argument to `concat',\n\
423 you should change it right away not to do so.")
424 (nargs, args)
425 int nargs;
426 Lisp_Object *args;
427 {
428 return concat (nargs, args, Lisp_String, 0);
429 }
430
431 DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
432 "Concatenate all the arguments and make the result a vector.\n\
433 The result is a vector whose elements are the elements of all the arguments.\n\
434 Each argument may be a list, vector or string.")
435 (nargs, args)
436 int nargs;
437 Lisp_Object *args;
438 {
439 return concat (nargs, args, Lisp_Vectorlike, 0);
440 }
441
442 /* Retrun a copy of a sub char table ARG. The elements except for a
443 nested sub char table are not copied. */
444 static Lisp_Object
445 copy_sub_char_table (arg)
446 Lisp_Object arg;
447 {
448 Lisp_Object copy = make_sub_char_table (XCHAR_TABLE (arg)->defalt);
449 int i;
450
451 /* Copy all the contents. */
452 bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
453 SUB_CHAR_TABLE_ORDINARY_SLOTS * sizeof (Lisp_Object));
454 /* Recursively copy any sub char-tables in the ordinary slots. */
455 for (i = 32; i < SUB_CHAR_TABLE_ORDINARY_SLOTS; i++)
456 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
457 XCHAR_TABLE (copy)->contents[i]
458 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
459
460 return copy;
461 }
462
463
464 DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
465 "Return a copy of a list, vector or string.\n\
466 The elements of a list or vector are not copied; they are shared\n\
467 with the original.")
468 (arg)
469 Lisp_Object arg;
470 {
471 if (NILP (arg)) return arg;
472
473 if (CHAR_TABLE_P (arg))
474 {
475 int i;
476 Lisp_Object copy;
477
478 copy = Fmake_char_table (XCHAR_TABLE (arg)->purpose, Qnil);
479 /* Copy all the slots, including the extra ones. */
480 bcopy (XVECTOR (arg)->contents, XVECTOR (copy)->contents,
481 ((XCHAR_TABLE (arg)->size & PSEUDOVECTOR_SIZE_MASK)
482 * sizeof (Lisp_Object)));
483
484 /* Recursively copy any sub char tables in the ordinary slots
485 for multibyte characters. */
486 for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS;
487 i < CHAR_TABLE_ORDINARY_SLOTS; i++)
488 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
489 XCHAR_TABLE (copy)->contents[i]
490 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
491
492 return copy;
493 }
494
495 if (BOOL_VECTOR_P (arg))
496 {
497 Lisp_Object val;
498 int size_in_chars
499 = (XBOOL_VECTOR (arg)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
500
501 val = Fmake_bool_vector (Flength (arg), Qnil);
502 bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
503 size_in_chars);
504 return val;
505 }
506
507 if (!CONSP (arg) && !VECTORP (arg) && !STRINGP (arg))
508 arg = wrong_type_argument (Qsequencep, arg);
509 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
510 }
511
512 static Lisp_Object
513 concat (nargs, args, target_type, last_special)
514 int nargs;
515 Lisp_Object *args;
516 enum Lisp_Type target_type;
517 int last_special;
518 {
519 Lisp_Object val;
520 register Lisp_Object tail;
521 register Lisp_Object this;
522 int toindex;
523 int toindex_byte;
524 register int result_len;
525 register int result_len_byte;
526 register int argnum;
527 Lisp_Object last_tail;
528 Lisp_Object prev;
529 int some_multibyte;
530
531 /* In append, the last arg isn't treated like the others */
532 if (last_special && nargs > 0)
533 {
534 nargs--;
535 last_tail = args[nargs];
536 }
537 else
538 last_tail = Qnil;
539
540 /* Canonicalize each argument. */
541 for (argnum = 0; argnum < nargs; argnum++)
542 {
543 this = args[argnum];
544 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
545 || COMPILEDP (this) || BOOL_VECTOR_P (this)))
546 {
547 if (INTEGERP (this))
548 args[argnum] = Fnumber_to_string (this);
549 else
550 args[argnum] = wrong_type_argument (Qsequencep, this);
551 }
552 }
553
554 /* Compute total length in chars of arguments in RESULT_LEN.
555 If desired output is a string, also compute length in bytes
556 in RESULT_LEN_BYTE, and determine in SOME_MULTIBYTE
557 whether the result should be a multibyte string. */
558 result_len_byte = 0;
559 result_len = 0;
560 some_multibyte = 0;
561 for (argnum = 0; argnum < nargs; argnum++)
562 {
563 int len;
564 this = args[argnum];
565 len = XFASTINT (Flength (this));
566 if (target_type == Lisp_String)
567 {
568 /* We must count the number of bytes needed in the string
569 as well as the number of characters. */
570 int i;
571 Lisp_Object ch;
572 int this_len_byte;
573
574 if (VECTORP (this))
575 for (i = 0; i < len; i++)
576 {
577 ch = XVECTOR (this)->contents[i];
578 if (! INTEGERP (ch))
579 wrong_type_argument (Qintegerp, ch);
580 this_len_byte = XFASTINT (Fchar_bytes (ch));
581 result_len_byte += this_len_byte;
582 if (this_len_byte > 1)
583 some_multibyte = 1;
584 }
585 else if (BOOL_VECTOR_P (this) && XBOOL_VECTOR (this)->size > 0)
586 wrong_type_argument (Qintegerp, Faref (this, make_number (0)));
587 else if (CONSP (this))
588 for (; CONSP (this); this = XCONS (this)->cdr)
589 {
590 ch = XCONS (this)->car;
591 if (! INTEGERP (ch))
592 wrong_type_argument (Qintegerp, ch);
593 this_len_byte = XFASTINT (Fchar_bytes (ch));
594 result_len_byte += this_len_byte;
595 if (this_len_byte > 1)
596 some_multibyte = 1;
597 }
598 else if (STRINGP (this))
599 {
600 if (STRING_MULTIBYTE (this))
601 {
602 some_multibyte = 1;
603 result_len_byte += STRING_BYTES (XSTRING (this));
604 }
605 else
606 result_len_byte += count_size_as_multibyte (XSTRING (this)->data,
607 XSTRING (this)->size);
608 }
609 }
610
611 result_len += len;
612 }
613
614 if (! some_multibyte)
615 result_len_byte = result_len;
616
617 /* Create the output object. */
618 if (target_type == Lisp_Cons)
619 val = Fmake_list (make_number (result_len), Qnil);
620 else if (target_type == Lisp_Vectorlike)
621 val = Fmake_vector (make_number (result_len), Qnil);
622 else if (some_multibyte)
623 val = make_uninit_multibyte_string (result_len, result_len_byte);
624 else
625 val = make_uninit_string (result_len);
626
627 /* In `append', if all but last arg are nil, return last arg. */
628 if (target_type == Lisp_Cons && EQ (val, Qnil))
629 return last_tail;
630
631 /* Copy the contents of the args into the result. */
632 if (CONSP (val))
633 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
634 else
635 toindex = 0, toindex_byte = 0;
636
637 prev = Qnil;
638
639 for (argnum = 0; argnum < nargs; argnum++)
640 {
641 Lisp_Object thislen;
642 int thisleni;
643 register unsigned int thisindex = 0;
644 register unsigned int thisindex_byte = 0;
645
646 this = args[argnum];
647 if (!CONSP (this))
648 thislen = Flength (this), thisleni = XINT (thislen);
649
650 if (STRINGP (this) && STRINGP (val)
651 && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
652 copy_text_properties (make_number (0), thislen, this,
653 make_number (toindex), val, Qnil);
654
655 /* Between strings of the same kind, copy fast. */
656 if (STRINGP (this) && STRINGP (val)
657 && STRING_MULTIBYTE (this) == some_multibyte)
658 {
659 int thislen_byte = STRING_BYTES (XSTRING (this));
660 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
661 STRING_BYTES (XSTRING (this)));
662 toindex_byte += thislen_byte;
663 toindex += thisleni;
664 }
665 /* Copy a single-byte string to a multibyte string. */
666 else if (STRINGP (this) && STRINGP (val))
667 {
668 toindex_byte += copy_text (XSTRING (this)->data,
669 XSTRING (val)->data + toindex_byte,
670 XSTRING (this)->size, 0, 1);
671 toindex += thisleni;
672 }
673 else
674 /* Copy element by element. */
675 while (1)
676 {
677 register Lisp_Object elt;
678
679 /* Fetch next element of `this' arg into `elt', or break if
680 `this' is exhausted. */
681 if (NILP (this)) break;
682 if (CONSP (this))
683 elt = XCONS (this)->car, this = XCONS (this)->cdr;
684 else if (thisindex >= thisleni)
685 break;
686 else if (STRINGP (this))
687 {
688 int c;
689 if (STRING_MULTIBYTE (this))
690 {
691 FETCH_STRING_CHAR_ADVANCE (c, this,
692 thisindex,
693 thisindex_byte);
694 XSETFASTINT (elt, c);
695 }
696 else
697 {
698 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
699 if (some_multibyte && XINT (elt) >= 0200
700 && XINT (elt) < 0400)
701 {
702 c = unibyte_char_to_multibyte (XINT (elt));
703 XSETINT (elt, c);
704 }
705 }
706 }
707 else if (BOOL_VECTOR_P (this))
708 {
709 int byte;
710 byte = XBOOL_VECTOR (this)->data[thisindex / BITS_PER_CHAR];
711 if (byte & (1 << (thisindex % BITS_PER_CHAR)))
712 elt = Qt;
713 else
714 elt = Qnil;
715 thisindex++;
716 }
717 else
718 elt = XVECTOR (this)->contents[thisindex++];
719
720 /* Store this element into the result. */
721 if (toindex < 0)
722 {
723 XCONS (tail)->car = elt;
724 prev = tail;
725 tail = XCONS (tail)->cdr;
726 }
727 else if (VECTORP (val))
728 XVECTOR (val)->contents[toindex++] = elt;
729 else
730 {
731 CHECK_NUMBER (elt, 0);
732 if (SINGLE_BYTE_CHAR_P (XINT (elt)))
733 {
734 XSTRING (val)->data[toindex_byte++] = XINT (elt);
735 toindex++;
736 }
737 else
738 /* If we have any multibyte characters,
739 we already decided to make a multibyte string. */
740 {
741 int c = XINT (elt);
742 unsigned char work[4], *str;
743 int i = CHAR_STRING (c, work, str);
744
745 /* P exists as a variable
746 to avoid a bug on the Masscomp C compiler. */
747 unsigned char *p = & XSTRING (val)->data[toindex_byte];
748 bcopy (str, p, i);
749 toindex_byte += i;
750 toindex++;
751 }
752 }
753 }
754 }
755 if (!NILP (prev))
756 XCONS (prev)->cdr = last_tail;
757
758 return val;
759 }
760 \f
761 static Lisp_Object string_char_byte_cache_string;
762 static int string_char_byte_cache_charpos;
763 static int string_char_byte_cache_bytepos;
764
765 /* Return the character index corresponding to CHAR_INDEX in STRING. */
766
767 int
768 string_char_to_byte (string, char_index)
769 Lisp_Object string;
770 int char_index;
771 {
772 int i, i_byte;
773 int best_below, best_below_byte;
774 int best_above, best_above_byte;
775
776 if (! STRING_MULTIBYTE (string))
777 return char_index;
778
779 best_below = best_below_byte = 0;
780 best_above = XSTRING (string)->size;
781 best_above_byte = STRING_BYTES (XSTRING (string));
782
783 if (EQ (string, string_char_byte_cache_string))
784 {
785 if (string_char_byte_cache_charpos < char_index)
786 {
787 best_below = string_char_byte_cache_charpos;
788 best_below_byte = string_char_byte_cache_bytepos;
789 }
790 else
791 {
792 best_above = string_char_byte_cache_charpos;
793 best_above_byte = string_char_byte_cache_bytepos;
794 }
795 }
796
797 if (char_index - best_below < best_above - char_index)
798 {
799 while (best_below < char_index)
800 {
801 int c;
802 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
803 }
804 i = best_below;
805 i_byte = best_below_byte;
806 }
807 else
808 {
809 while (best_above > char_index)
810 {
811 int best_above_byte_saved = --best_above_byte;
812
813 while (best_above_byte > 0
814 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
815 best_above_byte--;
816 if (XSTRING (string)->data[best_above_byte] < 0x80)
817 best_above_byte = best_above_byte_saved;
818 best_above--;
819 }
820 i = best_above;
821 i_byte = best_above_byte;
822 }
823
824 string_char_byte_cache_bytepos = i_byte;
825 string_char_byte_cache_charpos = i;
826 string_char_byte_cache_string = string;
827
828 return i_byte;
829 }
830 \f
831 /* Return the character index corresponding to BYTE_INDEX in STRING. */
832
833 int
834 string_byte_to_char (string, byte_index)
835 Lisp_Object string;
836 int byte_index;
837 {
838 int i, i_byte;
839 int best_below, best_below_byte;
840 int best_above, best_above_byte;
841
842 if (! STRING_MULTIBYTE (string))
843 return byte_index;
844
845 best_below = best_below_byte = 0;
846 best_above = XSTRING (string)->size;
847 best_above_byte = STRING_BYTES (XSTRING (string));
848
849 if (EQ (string, string_char_byte_cache_string))
850 {
851 if (string_char_byte_cache_bytepos < byte_index)
852 {
853 best_below = string_char_byte_cache_charpos;
854 best_below_byte = string_char_byte_cache_bytepos;
855 }
856 else
857 {
858 best_above = string_char_byte_cache_charpos;
859 best_above_byte = string_char_byte_cache_bytepos;
860 }
861 }
862
863 if (byte_index - best_below_byte < best_above_byte - byte_index)
864 {
865 while (best_below_byte < byte_index)
866 {
867 int c;
868 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
869 }
870 i = best_below;
871 i_byte = best_below_byte;
872 }
873 else
874 {
875 while (best_above_byte > byte_index)
876 {
877 int best_above_byte_saved = --best_above_byte;
878
879 while (best_above_byte > 0
880 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
881 best_above_byte--;
882 if (XSTRING (string)->data[best_above_byte] < 0x80)
883 best_above_byte = best_above_byte_saved;
884 best_above--;
885 }
886 i = best_above;
887 i_byte = best_above_byte;
888 }
889
890 string_char_byte_cache_bytepos = i_byte;
891 string_char_byte_cache_charpos = i;
892 string_char_byte_cache_string = string;
893
894 return i;
895 }
896 \f
897 /* Convert STRING to a multibyte string.
898 Single-byte characters 0240 through 0377 are converted
899 by adding nonascii_insert_offset to each. */
900
901 Lisp_Object
902 string_make_multibyte (string)
903 Lisp_Object string;
904 {
905 unsigned char *buf;
906 int nbytes;
907
908 if (STRING_MULTIBYTE (string))
909 return string;
910
911 nbytes = count_size_as_multibyte (XSTRING (string)->data,
912 XSTRING (string)->size);
913 /* If all the chars are ASCII, they won't need any more bytes
914 once converted. In that case, we can return STRING itself. */
915 if (nbytes == STRING_BYTES (XSTRING (string)))
916 return string;
917
918 buf = (unsigned char *) alloca (nbytes);
919 copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
920 0, 1);
921
922 return make_multibyte_string (buf, XSTRING (string)->size, nbytes);
923 }
924
925 /* Convert STRING to a single-byte string. */
926
927 Lisp_Object
928 string_make_unibyte (string)
929 Lisp_Object string;
930 {
931 unsigned char *buf;
932
933 if (! STRING_MULTIBYTE (string))
934 return string;
935
936 buf = (unsigned char *) alloca (XSTRING (string)->size);
937
938 copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
939 1, 0);
940
941 return make_unibyte_string (buf, XSTRING (string)->size);
942 }
943
944 DEFUN ("string-make-multibyte", Fstring_make_multibyte, Sstring_make_multibyte,
945 1, 1, 0,
946 "Return the multibyte equivalent of STRING.\n\
947 The function `unibyte-char-to-multibyte' is used to convert\n\
948 each unibyte character to a multibyte character.")
949 (string)
950 Lisp_Object string;
951 {
952 CHECK_STRING (string, 0);
953
954 return string_make_multibyte (string);
955 }
956
957 DEFUN ("string-make-unibyte", Fstring_make_unibyte, Sstring_make_unibyte,
958 1, 1, 0,
959 "Return the unibyte equivalent of STRING.\n\
960 Multibyte character codes are converted to unibyte\n\
961 by using just the low 8 bits.")
962 (string)
963 Lisp_Object string;
964 {
965 CHECK_STRING (string, 0);
966
967 return string_make_unibyte (string);
968 }
969
970 DEFUN ("string-as-unibyte", Fstring_as_unibyte, Sstring_as_unibyte,
971 1, 1, 0,
972 "Return a unibyte string with the same individual bytes as STRING.\n\
973 If STRING is unibyte, the result is STRING itself.")
974 (string)
975 Lisp_Object string;
976 {
977 CHECK_STRING (string, 0);
978
979 if (STRING_MULTIBYTE (string))
980 {
981 string = Fcopy_sequence (string);
982 XSTRING (string)->size = STRING_BYTES (XSTRING (string));
983 SET_STRING_BYTES (XSTRING (string), -1);
984 }
985 return string;
986 }
987
988 DEFUN ("string-as-multibyte", Fstring_as_multibyte, Sstring_as_multibyte,
989 1, 1, 0,
990 "Return a multibyte string with the same individual bytes as STRING.\n\
991 If STRING is multibyte, the result is STRING itself.")
992 (string)
993 Lisp_Object string;
994 {
995 CHECK_STRING (string, 0);
996
997 if (! STRING_MULTIBYTE (string))
998 {
999 int nbytes = STRING_BYTES (XSTRING (string));
1000 int newlen = multibyte_chars_in_text (XSTRING (string)->data, nbytes);
1001
1002 string = Fcopy_sequence (string);
1003 XSTRING (string)->size = newlen;
1004 XSTRING (string)->size_byte = nbytes;
1005 }
1006 return string;
1007 }
1008 \f
1009 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
1010 "Return a copy of ALIST.\n\
1011 This is an alist which represents the same mapping from objects to objects,\n\
1012 but does not share the alist structure with ALIST.\n\
1013 The objects mapped (cars and cdrs of elements of the alist)\n\
1014 are shared, however.\n\
1015 Elements of ALIST that are not conses are also shared.")
1016 (alist)
1017 Lisp_Object alist;
1018 {
1019 register Lisp_Object tem;
1020
1021 CHECK_LIST (alist, 0);
1022 if (NILP (alist))
1023 return alist;
1024 alist = concat (1, &alist, Lisp_Cons, 0);
1025 for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
1026 {
1027 register Lisp_Object car;
1028 car = XCONS (tem)->car;
1029
1030 if (CONSP (car))
1031 XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
1032 }
1033 return alist;
1034 }
1035
1036 DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
1037 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
1038 TO may be nil or omitted; then the substring runs to the end of STRING.\n\
1039 If FROM or TO is negative, it counts from the end.\n\
1040 \n\
1041 This function allows vectors as well as strings.")
1042 (string, from, to)
1043 Lisp_Object string;
1044 register Lisp_Object from, to;
1045 {
1046 Lisp_Object res;
1047 int size;
1048 int size_byte;
1049 int from_char, to_char;
1050 int from_byte, to_byte;
1051
1052 if (! (STRINGP (string) || VECTORP (string)))
1053 wrong_type_argument (Qarrayp, string);
1054
1055 CHECK_NUMBER (from, 1);
1056
1057 if (STRINGP (string))
1058 {
1059 size = XSTRING (string)->size;
1060 size_byte = STRING_BYTES (XSTRING (string));
1061 }
1062 else
1063 size = XVECTOR (string)->size;
1064
1065 if (NILP (to))
1066 {
1067 to_char = size;
1068 to_byte = size_byte;
1069 }
1070 else
1071 {
1072 CHECK_NUMBER (to, 2);
1073
1074 to_char = XINT (to);
1075 if (to_char < 0)
1076 to_char += size;
1077
1078 if (STRINGP (string))
1079 to_byte = string_char_to_byte (string, to_char);
1080 }
1081
1082 from_char = XINT (from);
1083 if (from_char < 0)
1084 from_char += size;
1085 if (STRINGP (string))
1086 from_byte = string_char_to_byte (string, from_char);
1087
1088 if (!(0 <= from_char && from_char <= to_char && to_char <= size))
1089 args_out_of_range_3 (string, make_number (from_char),
1090 make_number (to_char));
1091
1092 if (STRINGP (string))
1093 {
1094 res = make_specified_string (XSTRING (string)->data + from_byte,
1095 to_char - from_char, to_byte - from_byte,
1096 STRING_MULTIBYTE (string));
1097 copy_text_properties (make_number (from_char), make_number (to_char),
1098 string, make_number (0), res, Qnil);
1099 }
1100 else
1101 res = Fvector (to_char - from_char,
1102 XVECTOR (string)->contents + from_char);
1103
1104 return res;
1105 }
1106
1107 /* Extract a substring of STRING, giving start and end positions
1108 both in characters and in bytes. */
1109
1110 Lisp_Object
1111 substring_both (string, from, from_byte, to, to_byte)
1112 Lisp_Object string;
1113 int from, from_byte, to, to_byte;
1114 {
1115 Lisp_Object res;
1116 int size;
1117 int size_byte;
1118
1119 if (! (STRINGP (string) || VECTORP (string)))
1120 wrong_type_argument (Qarrayp, string);
1121
1122 if (STRINGP (string))
1123 {
1124 size = XSTRING (string)->size;
1125 size_byte = STRING_BYTES (XSTRING (string));
1126 }
1127 else
1128 size = XVECTOR (string)->size;
1129
1130 if (!(0 <= from && from <= to && to <= size))
1131 args_out_of_range_3 (string, make_number (from), make_number (to));
1132
1133 if (STRINGP (string))
1134 {
1135 res = make_specified_string (XSTRING (string)->data + from_byte,
1136 to - from, to_byte - from_byte,
1137 STRING_MULTIBYTE (string));
1138 copy_text_properties (make_number (from), make_number (to),
1139 string, make_number (0), res, Qnil);
1140 }
1141 else
1142 res = Fvector (to - from,
1143 XVECTOR (string)->contents + from);
1144
1145 return res;
1146 }
1147 \f
1148 DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1149 "Take cdr N times on LIST, returns the result.")
1150 (n, list)
1151 Lisp_Object n;
1152 register Lisp_Object list;
1153 {
1154 register int i, num;
1155 CHECK_NUMBER (n, 0);
1156 num = XINT (n);
1157 for (i = 0; i < num && !NILP (list); i++)
1158 {
1159 QUIT;
1160 list = Fcdr (list);
1161 }
1162 return list;
1163 }
1164
1165 DEFUN ("nth", Fnth, Snth, 2, 2, 0,
1166 "Return the Nth element of LIST.\n\
1167 N counts from zero. If LIST is not that long, nil is returned.")
1168 (n, list)
1169 Lisp_Object n, list;
1170 {
1171 return Fcar (Fnthcdr (n, list));
1172 }
1173
1174 DEFUN ("elt", Felt, Selt, 2, 2, 0,
1175 "Return element of SEQUENCE at index N.")
1176 (sequence, n)
1177 register Lisp_Object sequence, n;
1178 {
1179 CHECK_NUMBER (n, 0);
1180 while (1)
1181 {
1182 if (CONSP (sequence) || NILP (sequence))
1183 return Fcar (Fnthcdr (n, sequence));
1184 else if (STRINGP (sequence) || VECTORP (sequence)
1185 || BOOL_VECTOR_P (sequence) || CHAR_TABLE_P (sequence))
1186 return Faref (sequence, n);
1187 else
1188 sequence = wrong_type_argument (Qsequencep, sequence);
1189 }
1190 }
1191
1192 DEFUN ("member", Fmember, Smember, 2, 2, 0,
1193 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
1194 The value is actually the tail of LIST whose car is ELT.")
1195 (elt, list)
1196 register Lisp_Object elt;
1197 Lisp_Object list;
1198 {
1199 register Lisp_Object tail;
1200 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1201 {
1202 register Lisp_Object tem;
1203 tem = Fcar (tail);
1204 if (! NILP (Fequal (elt, tem)))
1205 return tail;
1206 QUIT;
1207 }
1208 return Qnil;
1209 }
1210
1211 DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
1212 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
1213 The value is actually the tail of LIST whose car is ELT.")
1214 (elt, list)
1215 register Lisp_Object elt;
1216 Lisp_Object list;
1217 {
1218 register Lisp_Object tail;
1219 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1220 {
1221 register Lisp_Object tem;
1222 tem = Fcar (tail);
1223 if (EQ (elt, tem)) return tail;
1224 QUIT;
1225 }
1226 return Qnil;
1227 }
1228
1229 DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
1230 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
1231 The value is actually the element of LIST whose car is KEY.\n\
1232 Elements of LIST that are not conses are ignored.")
1233 (key, list)
1234 register Lisp_Object key;
1235 Lisp_Object list;
1236 {
1237 register Lisp_Object tail;
1238 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1239 {
1240 register Lisp_Object elt, tem;
1241 elt = Fcar (tail);
1242 if (!CONSP (elt)) continue;
1243 tem = XCONS (elt)->car;
1244 if (EQ (key, tem)) return elt;
1245 QUIT;
1246 }
1247 return Qnil;
1248 }
1249
1250 /* Like Fassq but never report an error and do not allow quits.
1251 Use only on lists known never to be circular. */
1252
1253 Lisp_Object
1254 assq_no_quit (key, list)
1255 register Lisp_Object key;
1256 Lisp_Object list;
1257 {
1258 register Lisp_Object tail;
1259 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
1260 {
1261 register Lisp_Object elt, tem;
1262 elt = Fcar (tail);
1263 if (!CONSP (elt)) continue;
1264 tem = XCONS (elt)->car;
1265 if (EQ (key, tem)) return elt;
1266 }
1267 return Qnil;
1268 }
1269
1270 DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
1271 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
1272 The value is actually the element of LIST whose car equals KEY.")
1273 (key, list)
1274 register Lisp_Object key;
1275 Lisp_Object list;
1276 {
1277 register Lisp_Object tail;
1278 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1279 {
1280 register Lisp_Object elt, tem;
1281 elt = Fcar (tail);
1282 if (!CONSP (elt)) continue;
1283 tem = Fequal (XCONS (elt)->car, key);
1284 if (!NILP (tem)) return elt;
1285 QUIT;
1286 }
1287 return Qnil;
1288 }
1289
1290 DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
1291 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
1292 The value is actually the element of LIST whose cdr is ELT.")
1293 (key, list)
1294 register Lisp_Object key;
1295 Lisp_Object list;
1296 {
1297 register Lisp_Object tail;
1298 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1299 {
1300 register Lisp_Object elt, tem;
1301 elt = Fcar (tail);
1302 if (!CONSP (elt)) continue;
1303 tem = XCONS (elt)->cdr;
1304 if (EQ (key, tem)) return elt;
1305 QUIT;
1306 }
1307 return Qnil;
1308 }
1309
1310 DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
1311 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
1312 The value is actually the element of LIST whose cdr equals KEY.")
1313 (key, list)
1314 register Lisp_Object key;
1315 Lisp_Object list;
1316 {
1317 register Lisp_Object tail;
1318 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1319 {
1320 register Lisp_Object elt, tem;
1321 elt = Fcar (tail);
1322 if (!CONSP (elt)) continue;
1323 tem = Fequal (XCONS (elt)->cdr, key);
1324 if (!NILP (tem)) return elt;
1325 QUIT;
1326 }
1327 return Qnil;
1328 }
1329 \f
1330 DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
1331 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1332 The modified LIST is returned. Comparison is done with `eq'.\n\
1333 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
1334 therefore, write `(setq foo (delq element foo))'\n\
1335 to be sure of changing the value of `foo'.")
1336 (elt, list)
1337 register Lisp_Object elt;
1338 Lisp_Object list;
1339 {
1340 register Lisp_Object tail, prev;
1341 register Lisp_Object tem;
1342
1343 tail = list;
1344 prev = Qnil;
1345 while (!NILP (tail))
1346 {
1347 tem = Fcar (tail);
1348 if (EQ (elt, tem))
1349 {
1350 if (NILP (prev))
1351 list = XCONS (tail)->cdr;
1352 else
1353 Fsetcdr (prev, XCONS (tail)->cdr);
1354 }
1355 else
1356 prev = tail;
1357 tail = XCONS (tail)->cdr;
1358 QUIT;
1359 }
1360 return list;
1361 }
1362
1363 DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
1364 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1365 The modified LIST is returned. Comparison is done with `equal'.\n\
1366 If the first member of LIST is ELT, deleting it is not a side effect;\n\
1367 it is simply using a different list.\n\
1368 Therefore, write `(setq foo (delete element foo))'\n\
1369 to be sure of changing the value of `foo'.")
1370 (elt, list)
1371 register Lisp_Object elt;
1372 Lisp_Object list;
1373 {
1374 register Lisp_Object tail, prev;
1375 register Lisp_Object tem;
1376
1377 tail = list;
1378 prev = Qnil;
1379 while (!NILP (tail))
1380 {
1381 tem = Fcar (tail);
1382 if (! NILP (Fequal (elt, tem)))
1383 {
1384 if (NILP (prev))
1385 list = XCONS (tail)->cdr;
1386 else
1387 Fsetcdr (prev, XCONS (tail)->cdr);
1388 }
1389 else
1390 prev = tail;
1391 tail = XCONS (tail)->cdr;
1392 QUIT;
1393 }
1394 return list;
1395 }
1396
1397 DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
1398 "Reverse LIST by modifying cdr pointers.\n\
1399 Returns the beginning of the reversed list.")
1400 (list)
1401 Lisp_Object list;
1402 {
1403 register Lisp_Object prev, tail, next;
1404
1405 if (NILP (list)) return list;
1406 prev = Qnil;
1407 tail = list;
1408 while (!NILP (tail))
1409 {
1410 QUIT;
1411 next = Fcdr (tail);
1412 Fsetcdr (tail, prev);
1413 prev = tail;
1414 tail = next;
1415 }
1416 return prev;
1417 }
1418
1419 DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
1420 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
1421 See also the function `nreverse', which is used more often.")
1422 (list)
1423 Lisp_Object list;
1424 {
1425 Lisp_Object new;
1426
1427 for (new = Qnil; CONSP (list); list = XCONS (list)->cdr)
1428 new = Fcons (XCONS (list)->car, new);
1429 if (!NILP (list))
1430 wrong_type_argument (Qconsp, list);
1431 return new;
1432 }
1433 \f
1434 Lisp_Object merge ();
1435
1436 DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
1437 "Sort LIST, stably, comparing elements using PREDICATE.\n\
1438 Returns the sorted list. LIST is modified by side effects.\n\
1439 PREDICATE is called with two elements of LIST, and should return T\n\
1440 if the first element is \"less\" than the second.")
1441 (list, predicate)
1442 Lisp_Object list, predicate;
1443 {
1444 Lisp_Object front, back;
1445 register Lisp_Object len, tem;
1446 struct gcpro gcpro1, gcpro2;
1447 register int length;
1448
1449 front = list;
1450 len = Flength (list);
1451 length = XINT (len);
1452 if (length < 2)
1453 return list;
1454
1455 XSETINT (len, (length / 2) - 1);
1456 tem = Fnthcdr (len, list);
1457 back = Fcdr (tem);
1458 Fsetcdr (tem, Qnil);
1459
1460 GCPRO2 (front, back);
1461 front = Fsort (front, predicate);
1462 back = Fsort (back, predicate);
1463 UNGCPRO;
1464 return merge (front, back, predicate);
1465 }
1466
1467 Lisp_Object
1468 merge (org_l1, org_l2, pred)
1469 Lisp_Object org_l1, org_l2;
1470 Lisp_Object pred;
1471 {
1472 Lisp_Object value;
1473 register Lisp_Object tail;
1474 Lisp_Object tem;
1475 register Lisp_Object l1, l2;
1476 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1477
1478 l1 = org_l1;
1479 l2 = org_l2;
1480 tail = Qnil;
1481 value = Qnil;
1482
1483 /* It is sufficient to protect org_l1 and org_l2.
1484 When l1 and l2 are updated, we copy the new values
1485 back into the org_ vars. */
1486 GCPRO4 (org_l1, org_l2, pred, value);
1487
1488 while (1)
1489 {
1490 if (NILP (l1))
1491 {
1492 UNGCPRO;
1493 if (NILP (tail))
1494 return l2;
1495 Fsetcdr (tail, l2);
1496 return value;
1497 }
1498 if (NILP (l2))
1499 {
1500 UNGCPRO;
1501 if (NILP (tail))
1502 return l1;
1503 Fsetcdr (tail, l1);
1504 return value;
1505 }
1506 tem = call2 (pred, Fcar (l2), Fcar (l1));
1507 if (NILP (tem))
1508 {
1509 tem = l1;
1510 l1 = Fcdr (l1);
1511 org_l1 = l1;
1512 }
1513 else
1514 {
1515 tem = l2;
1516 l2 = Fcdr (l2);
1517 org_l2 = l2;
1518 }
1519 if (NILP (tail))
1520 value = tem;
1521 else
1522 Fsetcdr (tail, tem);
1523 tail = tem;
1524 }
1525 }
1526 \f
1527
1528 DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
1529 "Extract a value from a property list.\n\
1530 PLIST is a property list, which is a list of the form\n\
1531 \(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
1532 corresponding to the given PROP, or nil if PROP is not\n\
1533 one of the properties on the list.")
1534 (plist, prop)
1535 Lisp_Object plist;
1536 register Lisp_Object prop;
1537 {
1538 register Lisp_Object tail;
1539 for (tail = plist; !NILP (tail); tail = Fcdr (XCONS (tail)->cdr))
1540 {
1541 register Lisp_Object tem;
1542 tem = Fcar (tail);
1543 if (EQ (prop, tem))
1544 return Fcar (XCONS (tail)->cdr);
1545 }
1546 return Qnil;
1547 }
1548
1549 DEFUN ("get", Fget, Sget, 2, 2, 0,
1550 "Return the value of SYMBOL's PROPNAME property.\n\
1551 This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
1552 (symbol, propname)
1553 Lisp_Object symbol, propname;
1554 {
1555 CHECK_SYMBOL (symbol, 0);
1556 return Fplist_get (XSYMBOL (symbol)->plist, propname);
1557 }
1558
1559 DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
1560 "Change value in PLIST of PROP to VAL.\n\
1561 PLIST is a property list, which is a list of the form\n\
1562 \(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
1563 If PROP is already a property on the list, its value is set to VAL,\n\
1564 otherwise the new PROP VAL pair is added. The new plist is returned;\n\
1565 use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
1566 The PLIST is modified by side effects.")
1567 (plist, prop, val)
1568 Lisp_Object plist;
1569 register Lisp_Object prop;
1570 Lisp_Object val;
1571 {
1572 register Lisp_Object tail, prev;
1573 Lisp_Object newcell;
1574 prev = Qnil;
1575 for (tail = plist; CONSP (tail) && CONSP (XCONS (tail)->cdr);
1576 tail = XCONS (XCONS (tail)->cdr)->cdr)
1577 {
1578 if (EQ (prop, XCONS (tail)->car))
1579 {
1580 Fsetcar (XCONS (tail)->cdr, val);
1581 return plist;
1582 }
1583 prev = tail;
1584 }
1585 newcell = Fcons (prop, Fcons (val, Qnil));
1586 if (NILP (prev))
1587 return newcell;
1588 else
1589 Fsetcdr (XCONS (prev)->cdr, newcell);
1590 return plist;
1591 }
1592
1593 DEFUN ("put", Fput, Sput, 3, 3, 0,
1594 "Store SYMBOL's PROPNAME property with value VALUE.\n\
1595 It can be retrieved with `(get SYMBOL PROPNAME)'.")
1596 (symbol, propname, value)
1597 Lisp_Object symbol, propname, value;
1598 {
1599 CHECK_SYMBOL (symbol, 0);
1600 XSYMBOL (symbol)->plist
1601 = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
1602 return value;
1603 }
1604
1605 DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
1606 "Return t if two Lisp objects have similar structure and contents.\n\
1607 They must have the same data type.\n\
1608 Conses are compared by comparing the cars and the cdrs.\n\
1609 Vectors and strings are compared element by element.\n\
1610 Numbers are compared by value, but integers cannot equal floats.\n\
1611 (Use `=' if you want integers and floats to be able to be equal.)\n\
1612 Symbols must match exactly.")
1613 (o1, o2)
1614 register Lisp_Object o1, o2;
1615 {
1616 return internal_equal (o1, o2, 0) ? Qt : Qnil;
1617 }
1618
1619 static int
1620 internal_equal (o1, o2, depth)
1621 register Lisp_Object o1, o2;
1622 int depth;
1623 {
1624 if (depth > 200)
1625 error ("Stack overflow in equal");
1626
1627 tail_recurse:
1628 QUIT;
1629 if (EQ (o1, o2))
1630 return 1;
1631 if (XTYPE (o1) != XTYPE (o2))
1632 return 0;
1633
1634 switch (XTYPE (o1))
1635 {
1636 #ifdef LISP_FLOAT_TYPE
1637 case Lisp_Float:
1638 return (extract_float (o1) == extract_float (o2));
1639 #endif
1640
1641 case Lisp_Cons:
1642 if (!internal_equal (XCONS (o1)->car, XCONS (o2)->car, depth + 1))
1643 return 0;
1644 o1 = XCONS (o1)->cdr;
1645 o2 = XCONS (o2)->cdr;
1646 goto tail_recurse;
1647
1648 case Lisp_Misc:
1649 if (XMISCTYPE (o1) != XMISCTYPE (o2))
1650 return 0;
1651 if (OVERLAYP (o1))
1652 {
1653 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o1),
1654 depth + 1)
1655 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o1),
1656 depth + 1))
1657 return 0;
1658 o1 = XOVERLAY (o1)->plist;
1659 o2 = XOVERLAY (o2)->plist;
1660 goto tail_recurse;
1661 }
1662 if (MARKERP (o1))
1663 {
1664 return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
1665 && (XMARKER (o1)->buffer == 0
1666 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
1667 }
1668 break;
1669
1670 case Lisp_Vectorlike:
1671 {
1672 register int i, size;
1673 size = XVECTOR (o1)->size;
1674 /* Pseudovectors have the type encoded in the size field, so this test
1675 actually checks that the objects have the same type as well as the
1676 same size. */
1677 if (XVECTOR (o2)->size != size)
1678 return 0;
1679 /* Boolvectors are compared much like strings. */
1680 if (BOOL_VECTOR_P (o1))
1681 {
1682 int size_in_chars
1683 = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
1684
1685 if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
1686 return 0;
1687 if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
1688 size_in_chars))
1689 return 0;
1690 return 1;
1691 }
1692 if (WINDOW_CONFIGURATIONP (o1))
1693 return compare_window_configurations (o1, o2, 0);
1694
1695 /* Aside from them, only true vectors, char-tables, and compiled
1696 functions are sensible to compare, so eliminate the others now. */
1697 if (size & PSEUDOVECTOR_FLAG)
1698 {
1699 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
1700 return 0;
1701 size &= PSEUDOVECTOR_SIZE_MASK;
1702 }
1703 for (i = 0; i < size; i++)
1704 {
1705 Lisp_Object v1, v2;
1706 v1 = XVECTOR (o1)->contents [i];
1707 v2 = XVECTOR (o2)->contents [i];
1708 if (!internal_equal (v1, v2, depth + 1))
1709 return 0;
1710 }
1711 return 1;
1712 }
1713 break;
1714
1715 case Lisp_String:
1716 if (XSTRING (o1)->size != XSTRING (o2)->size)
1717 return 0;
1718 if (STRING_BYTES (XSTRING (o1)) != STRING_BYTES (XSTRING (o2)))
1719 return 0;
1720 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
1721 STRING_BYTES (XSTRING (o1))))
1722 return 0;
1723 return 1;
1724 }
1725 return 0;
1726 }
1727 \f
1728 extern Lisp_Object Fmake_char_internal ();
1729
1730 DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
1731 "Store each element of ARRAY with ITEM.\n\
1732 ARRAY is a vector, string, char-table, or bool-vector.")
1733 (array, item)
1734 Lisp_Object array, item;
1735 {
1736 register int size, index, charval;
1737 retry:
1738 if (VECTORP (array))
1739 {
1740 register Lisp_Object *p = XVECTOR (array)->contents;
1741 size = XVECTOR (array)->size;
1742 for (index = 0; index < size; index++)
1743 p[index] = item;
1744 }
1745 else if (CHAR_TABLE_P (array))
1746 {
1747 register Lisp_Object *p = XCHAR_TABLE (array)->contents;
1748 size = CHAR_TABLE_ORDINARY_SLOTS;
1749 for (index = 0; index < size; index++)
1750 p[index] = item;
1751 XCHAR_TABLE (array)->defalt = Qnil;
1752 }
1753 else if (STRINGP (array))
1754 {
1755 register unsigned char *p = XSTRING (array)->data;
1756 CHECK_NUMBER (item, 1);
1757 charval = XINT (item);
1758 size = XSTRING (array)->size;
1759 for (index = 0; index < size; index++)
1760 p[index] = charval;
1761 }
1762 else if (BOOL_VECTOR_P (array))
1763 {
1764 register unsigned char *p = XBOOL_VECTOR (array)->data;
1765 int size_in_chars
1766 = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
1767
1768 charval = (! NILP (item) ? -1 : 0);
1769 for (index = 0; index < size_in_chars; index++)
1770 p[index] = charval;
1771 }
1772 else
1773 {
1774 array = wrong_type_argument (Qarrayp, array);
1775 goto retry;
1776 }
1777 return array;
1778 }
1779 \f
1780 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
1781 1, 1, 0,
1782 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
1783 (char_table)
1784 Lisp_Object char_table;
1785 {
1786 CHECK_CHAR_TABLE (char_table, 0);
1787
1788 return XCHAR_TABLE (char_table)->purpose;
1789 }
1790
1791 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
1792 1, 1, 0,
1793 "Return the parent char-table of CHAR-TABLE.\n\
1794 The value is either nil or another char-table.\n\
1795 If CHAR-TABLE holds nil for a given character,\n\
1796 then the actual applicable value is inherited from the parent char-table\n\
1797 \(or from its parents, if necessary).")
1798 (char_table)
1799 Lisp_Object char_table;
1800 {
1801 CHECK_CHAR_TABLE (char_table, 0);
1802
1803 return XCHAR_TABLE (char_table)->parent;
1804 }
1805
1806 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
1807 2, 2, 0,
1808 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
1809 PARENT must be either nil or another char-table.")
1810 (char_table, parent)
1811 Lisp_Object char_table, parent;
1812 {
1813 Lisp_Object temp;
1814
1815 CHECK_CHAR_TABLE (char_table, 0);
1816
1817 if (!NILP (parent))
1818 {
1819 CHECK_CHAR_TABLE (parent, 0);
1820
1821 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
1822 if (EQ (temp, char_table))
1823 error ("Attempt to make a chartable be its own parent");
1824 }
1825
1826 XCHAR_TABLE (char_table)->parent = parent;
1827
1828 return parent;
1829 }
1830
1831 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
1832 2, 2, 0,
1833 "Return the value of CHAR-TABLE's extra-slot number N.")
1834 (char_table, n)
1835 Lisp_Object char_table, n;
1836 {
1837 CHECK_CHAR_TABLE (char_table, 1);
1838 CHECK_NUMBER (n, 2);
1839 if (XINT (n) < 0
1840 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1841 args_out_of_range (char_table, n);
1842
1843 return XCHAR_TABLE (char_table)->extras[XINT (n)];
1844 }
1845
1846 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
1847 Sset_char_table_extra_slot,
1848 3, 3, 0,
1849 "Set CHAR-TABLE's extra-slot number N to VALUE.")
1850 (char_table, n, value)
1851 Lisp_Object char_table, n, value;
1852 {
1853 CHECK_CHAR_TABLE (char_table, 1);
1854 CHECK_NUMBER (n, 2);
1855 if (XINT (n) < 0
1856 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1857 args_out_of_range (char_table, n);
1858
1859 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
1860 }
1861 \f
1862 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
1863 2, 2, 0,
1864 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
1865 RANGE should be nil (for the default value)\n\
1866 a vector which identifies a character set or a row of a character set,\n\
1867 a character set name, or a character code.")
1868 (char_table, range)
1869 Lisp_Object char_table, range;
1870 {
1871 int i;
1872
1873 CHECK_CHAR_TABLE (char_table, 0);
1874
1875 if (EQ (range, Qnil))
1876 return XCHAR_TABLE (char_table)->defalt;
1877 else if (INTEGERP (range))
1878 return Faref (char_table, range);
1879 else if (SYMBOLP (range))
1880 {
1881 Lisp_Object charset_info;
1882
1883 charset_info = Fget (range, Qcharset);
1884 CHECK_VECTOR (charset_info, 0);
1885
1886 return Faref (char_table,
1887 make_number (XINT (XVECTOR (charset_info)->contents[0])
1888 + 128));
1889 }
1890 else if (VECTORP (range))
1891 {
1892 if (XVECTOR (range)->size == 1)
1893 return Faref (char_table,
1894 make_number (XINT (XVECTOR (range)->contents[0]) + 128));
1895 else
1896 {
1897 int size = XVECTOR (range)->size;
1898 Lisp_Object *val = XVECTOR (range)->contents;
1899 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1900 size <= 1 ? Qnil : val[1],
1901 size <= 2 ? Qnil : val[2]);
1902 return Faref (char_table, ch);
1903 }
1904 }
1905 else
1906 error ("Invalid RANGE argument to `char-table-range'");
1907 }
1908
1909 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
1910 3, 3, 0,
1911 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
1912 RANGE should be t (for all characters), nil (for the default value)\n\
1913 a vector which identifies a character set or a row of a character set,\n\
1914 a coding system, or a character code.")
1915 (char_table, range, value)
1916 Lisp_Object char_table, range, value;
1917 {
1918 int i;
1919
1920 CHECK_CHAR_TABLE (char_table, 0);
1921
1922 if (EQ (range, Qt))
1923 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
1924 XCHAR_TABLE (char_table)->contents[i] = value;
1925 else if (EQ (range, Qnil))
1926 XCHAR_TABLE (char_table)->defalt = value;
1927 else if (SYMBOLP (range))
1928 {
1929 Lisp_Object charset_info;
1930
1931 charset_info = Fget (range, Qcharset);
1932 CHECK_VECTOR (charset_info, 0);
1933
1934 return Faset (char_table,
1935 make_number (XINT (XVECTOR (charset_info)->contents[0])
1936 + 128),
1937 value);
1938 }
1939 else if (INTEGERP (range))
1940 Faset (char_table, range, value);
1941 else if (VECTORP (range))
1942 {
1943 if (XVECTOR (range)->size == 1)
1944 return Faset (char_table,
1945 make_number (XINT (XVECTOR (range)->contents[0]) + 128),
1946 value);
1947 else
1948 {
1949 int size = XVECTOR (range)->size;
1950 Lisp_Object *val = XVECTOR (range)->contents;
1951 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1952 size <= 1 ? Qnil : val[1],
1953 size <= 2 ? Qnil : val[2]);
1954 return Faset (char_table, ch, value);
1955 }
1956 }
1957 else
1958 error ("Invalid RANGE argument to `set-char-table-range'");
1959
1960 return value;
1961 }
1962
1963 DEFUN ("set-char-table-default", Fset_char_table_default,
1964 Sset_char_table_default, 3, 3, 0,
1965 "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
1966 The generic character specifies the group of characters.\n\
1967 See also the documentation of make-char.")
1968 (char_table, ch, value)
1969 Lisp_Object char_table, ch, value;
1970 {
1971 int c, i, charset, code1, code2;
1972 Lisp_Object temp;
1973
1974 CHECK_CHAR_TABLE (char_table, 0);
1975 CHECK_NUMBER (ch, 1);
1976
1977 c = XINT (ch);
1978 SPLIT_NON_ASCII_CHAR (c, charset, code1, code2);
1979 if (! CHARSET_DEFINED_P (charset))
1980 invalid_character (c);
1981
1982 if (charset == CHARSET_ASCII)
1983 return (XCHAR_TABLE (char_table)->defalt = value);
1984
1985 /* Even if C is not a generic char, we had better behave as if a
1986 generic char is specified. */
1987 if (CHARSET_DIMENSION (charset) == 1)
1988 code1 = 0;
1989 temp = XCHAR_TABLE (char_table)->contents[charset + 128];
1990 if (!code1)
1991 {
1992 if (SUB_CHAR_TABLE_P (temp))
1993 XCHAR_TABLE (temp)->defalt = value;
1994 else
1995 XCHAR_TABLE (char_table)->contents[charset + 128] = value;
1996 return value;
1997 }
1998 char_table = temp;
1999 if (! SUB_CHAR_TABLE_P (char_table))
2000 char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
2001 = make_sub_char_table (temp));
2002 temp = XCHAR_TABLE (char_table)->contents[code1];
2003 if (SUB_CHAR_TABLE_P (temp))
2004 XCHAR_TABLE (temp)->defalt = value;
2005 else
2006 XCHAR_TABLE (char_table)->contents[code1] = value;
2007 return value;
2008 }
2009
2010 /* Look up the element in TABLE at index CH,
2011 and return it as an integer.
2012 If the element is nil, return CH itself.
2013 (Actually we do that for any non-integer.) */
2014
2015 int
2016 char_table_translate (table, ch)
2017 Lisp_Object table;
2018 int ch;
2019 {
2020 Lisp_Object value;
2021 value = Faref (table, make_number (ch));
2022 if (! INTEGERP (value))
2023 return ch;
2024 return XINT (value);
2025 }
2026 \f
2027 /* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
2028 character or group of characters that share a value.
2029 DEPTH is the current depth in the originally specified
2030 chartable, and INDICES contains the vector indices
2031 for the levels our callers have descended.
2032
2033 ARG is passed to C_FUNCTION when that is called. */
2034
2035 void
2036 map_char_table (c_function, function, subtable, arg, depth, indices)
2037 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
2038 Lisp_Object function, subtable, arg, *indices;
2039 int depth;
2040 {
2041 int i, to;
2042
2043 if (depth == 0)
2044 {
2045 /* At first, handle ASCII and 8-bit European characters. */
2046 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
2047 {
2048 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
2049 if (c_function)
2050 (*c_function) (arg, make_number (i), elt);
2051 else
2052 call2 (function, make_number (i), elt);
2053 }
2054 #if 0 /* If the char table has entries for higher characters,
2055 we should report them. */
2056 if (NILP (current_buffer->enable_multibyte_characters))
2057 return;
2058 #endif
2059 to = CHAR_TABLE_ORDINARY_SLOTS;
2060 }
2061 else
2062 {
2063 i = 32;
2064 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
2065 }
2066
2067 for (; i < to; i++)
2068 {
2069 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
2070
2071 XSETFASTINT (indices[depth], i);
2072
2073 if (SUB_CHAR_TABLE_P (elt))
2074 {
2075 if (depth >= 3)
2076 error ("Too deep char table");
2077 map_char_table (c_function, function, elt, arg, depth + 1, indices);
2078 }
2079 else
2080 {
2081 int charset = XFASTINT (indices[0]) - 128, c1, c2, c;
2082
2083 if (CHARSET_DEFINED_P (charset))
2084 {
2085 c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
2086 c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
2087 c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
2088 if (c_function)
2089 (*c_function) (arg, make_number (c), elt);
2090 else
2091 call2 (function, make_number (c), elt);
2092 }
2093 }
2094 }
2095 }
2096
2097 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
2098 2, 2, 0,
2099 "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
2100 FUNCTION is called with two arguments--a key and a value.\n\
2101 The key is always a possible IDX argument to `aref'.")
2102 (function, char_table)
2103 Lisp_Object function, char_table;
2104 {
2105 /* The depth of char table is at most 3. */
2106 Lisp_Object indices[3];
2107
2108 CHECK_CHAR_TABLE (char_table, 1);
2109
2110 map_char_table (NULL, function, char_table, char_table, 0, indices);
2111 return Qnil;
2112 }
2113 \f
2114 /* ARGSUSED */
2115 Lisp_Object
2116 nconc2 (s1, s2)
2117 Lisp_Object s1, s2;
2118 {
2119 #ifdef NO_ARG_ARRAY
2120 Lisp_Object args[2];
2121 args[0] = s1;
2122 args[1] = s2;
2123 return Fnconc (2, args);
2124 #else
2125 return Fnconc (2, &s1);
2126 #endif /* NO_ARG_ARRAY */
2127 }
2128
2129 DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
2130 "Concatenate any number of lists by altering them.\n\
2131 Only the last argument is not altered, and need not be a list.")
2132 (nargs, args)
2133 int nargs;
2134 Lisp_Object *args;
2135 {
2136 register int argnum;
2137 register Lisp_Object tail, tem, val;
2138
2139 val = Qnil;
2140
2141 for (argnum = 0; argnum < nargs; argnum++)
2142 {
2143 tem = args[argnum];
2144 if (NILP (tem)) continue;
2145
2146 if (NILP (val))
2147 val = tem;
2148
2149 if (argnum + 1 == nargs) break;
2150
2151 if (!CONSP (tem))
2152 tem = wrong_type_argument (Qlistp, tem);
2153
2154 while (CONSP (tem))
2155 {
2156 tail = tem;
2157 tem = Fcdr (tail);
2158 QUIT;
2159 }
2160
2161 tem = args[argnum + 1];
2162 Fsetcdr (tail, tem);
2163 if (NILP (tem))
2164 args[argnum + 1] = tail;
2165 }
2166
2167 return val;
2168 }
2169 \f
2170 /* This is the guts of all mapping functions.
2171 Apply FN to each element of SEQ, one by one,
2172 storing the results into elements of VALS, a C vector of Lisp_Objects.
2173 LENI is the length of VALS, which should also be the length of SEQ. */
2174
2175 static void
2176 mapcar1 (leni, vals, fn, seq)
2177 int leni;
2178 Lisp_Object *vals;
2179 Lisp_Object fn, seq;
2180 {
2181 register Lisp_Object tail;
2182 Lisp_Object dummy;
2183 register int i;
2184 struct gcpro gcpro1, gcpro2, gcpro3;
2185
2186 /* Don't let vals contain any garbage when GC happens. */
2187 for (i = 0; i < leni; i++)
2188 vals[i] = Qnil;
2189
2190 GCPRO3 (dummy, fn, seq);
2191 gcpro1.var = vals;
2192 gcpro1.nvars = leni;
2193 /* We need not explicitly protect `tail' because it is used only on lists, and
2194 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
2195
2196 if (VECTORP (seq))
2197 {
2198 for (i = 0; i < leni; i++)
2199 {
2200 dummy = XVECTOR (seq)->contents[i];
2201 vals[i] = call1 (fn, dummy);
2202 }
2203 }
2204 else if (BOOL_VECTOR_P (seq))
2205 {
2206 for (i = 0; i < leni; i++)
2207 {
2208 int byte;
2209 byte = XBOOL_VECTOR (seq)->data[i / BITS_PER_CHAR];
2210 if (byte & (1 << (i % BITS_PER_CHAR)))
2211 dummy = Qt;
2212 else
2213 dummy = Qnil;
2214
2215 vals[i] = call1 (fn, dummy);
2216 }
2217 }
2218 else if (STRINGP (seq) && ! STRING_MULTIBYTE (seq))
2219 {
2220 /* Single-byte string. */
2221 for (i = 0; i < leni; i++)
2222 {
2223 XSETFASTINT (dummy, XSTRING (seq)->data[i]);
2224 vals[i] = call1 (fn, dummy);
2225 }
2226 }
2227 else if (STRINGP (seq))
2228 {
2229 /* Multi-byte string. */
2230 int len_byte = STRING_BYTES (XSTRING (seq));
2231 int i_byte;
2232
2233 for (i = 0, i_byte = 0; i < leni;)
2234 {
2235 int c;
2236 int i_before = i;
2237
2238 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte);
2239 XSETFASTINT (dummy, c);
2240 vals[i_before] = call1 (fn, dummy);
2241 }
2242 }
2243 else /* Must be a list, since Flength did not get an error */
2244 {
2245 tail = seq;
2246 for (i = 0; i < leni; i++)
2247 {
2248 vals[i] = call1 (fn, Fcar (tail));
2249 tail = XCONS (tail)->cdr;
2250 }
2251 }
2252
2253 UNGCPRO;
2254 }
2255
2256 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
2257 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2258 In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
2259 SEPARATOR results in spaces between the values returned by FUNCTION.\n\
2260 SEQUENCE may be a list, a vector, a bool-vector, or a string.")
2261 (function, sequence, separator)
2262 Lisp_Object function, sequence, separator;
2263 {
2264 Lisp_Object len;
2265 register int leni;
2266 int nargs;
2267 register Lisp_Object *args;
2268 register int i;
2269 struct gcpro gcpro1;
2270
2271 len = Flength (sequence);
2272 leni = XINT (len);
2273 nargs = leni + leni - 1;
2274 if (nargs < 0) return build_string ("");
2275
2276 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2277
2278 GCPRO1 (separator);
2279 mapcar1 (leni, args, function, sequence);
2280 UNGCPRO;
2281
2282 for (i = leni - 1; i >= 0; i--)
2283 args[i + i] = args[i];
2284
2285 for (i = 1; i < nargs; i += 2)
2286 args[i] = separator;
2287
2288 return Fconcat (nargs, args);
2289 }
2290
2291 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2292 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2293 The result is a list just as long as SEQUENCE.\n\
2294 SEQUENCE may be a list, a vector, a bool-vector, or a string.")
2295 (function, sequence)
2296 Lisp_Object function, sequence;
2297 {
2298 register Lisp_Object len;
2299 register int leni;
2300 register Lisp_Object *args;
2301
2302 len = Flength (sequence);
2303 leni = XFASTINT (len);
2304 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2305
2306 mapcar1 (leni, args, function, sequence);
2307
2308 return Flist (leni, args);
2309 }
2310 \f
2311 /* Anything that calls this function must protect from GC! */
2312
2313 DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2314 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
2315 Takes one argument, which is the string to display to ask the question.\n\
2316 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
2317 No confirmation of the answer is requested; a single character is enough.\n\
2318 Also accepts Space to mean yes, or Delete to mean no.")
2319 (prompt)
2320 Lisp_Object prompt;
2321 {
2322 register Lisp_Object obj, key, def, answer_string, map;
2323 register int answer;
2324 Lisp_Object xprompt;
2325 Lisp_Object args[2];
2326 struct gcpro gcpro1, gcpro2;
2327 int count = specpdl_ptr - specpdl;
2328
2329 specbind (Qcursor_in_echo_area, Qt);
2330
2331 map = Fsymbol_value (intern ("query-replace-map"));
2332
2333 CHECK_STRING (prompt, 0);
2334 xprompt = prompt;
2335 GCPRO2 (prompt, xprompt);
2336
2337 while (1)
2338 {
2339
2340 #ifdef HAVE_MENUS
2341 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2342 && use_dialog_box
2343 && have_menus_p ())
2344 {
2345 Lisp_Object pane, menu;
2346 redisplay_preserve_echo_area ();
2347 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2348 Fcons (Fcons (build_string ("No"), Qnil),
2349 Qnil));
2350 menu = Fcons (prompt, pane);
2351 obj = Fx_popup_dialog (Qt, menu);
2352 answer = !NILP (obj);
2353 break;
2354 }
2355 #endif /* HAVE_MENUS */
2356 cursor_in_echo_area = 1;
2357 choose_minibuf_frame ();
2358 message_with_string ("%s(y or n) ", xprompt, 0);
2359
2360 if (minibuffer_auto_raise)
2361 {
2362 Lisp_Object mini_frame;
2363
2364 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2365
2366 Fraise_frame (mini_frame);
2367 }
2368
2369 obj = read_filtered_event (1, 0, 0);
2370 cursor_in_echo_area = 0;
2371 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2372 QUIT;
2373
2374 key = Fmake_vector (make_number (1), obj);
2375 def = Flookup_key (map, key, Qt);
2376 answer_string = Fsingle_key_description (obj);
2377
2378 if (EQ (def, intern ("skip")))
2379 {
2380 answer = 0;
2381 break;
2382 }
2383 else if (EQ (def, intern ("act")))
2384 {
2385 answer = 1;
2386 break;
2387 }
2388 else if (EQ (def, intern ("recenter")))
2389 {
2390 Frecenter (Qnil);
2391 xprompt = prompt;
2392 continue;
2393 }
2394 else if (EQ (def, intern ("quit")))
2395 Vquit_flag = Qt;
2396 /* We want to exit this command for exit-prefix,
2397 and this is the only way to do it. */
2398 else if (EQ (def, intern ("exit-prefix")))
2399 Vquit_flag = Qt;
2400
2401 QUIT;
2402
2403 /* If we don't clear this, then the next call to read_char will
2404 return quit_char again, and we'll enter an infinite loop. */
2405 Vquit_flag = Qnil;
2406
2407 Fding (Qnil);
2408 Fdiscard_input ();
2409 if (EQ (xprompt, prompt))
2410 {
2411 args[0] = build_string ("Please answer y or n. ");
2412 args[1] = prompt;
2413 xprompt = Fconcat (2, args);
2414 }
2415 }
2416 UNGCPRO;
2417
2418 if (! noninteractive)
2419 {
2420 cursor_in_echo_area = -1;
2421 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2422 xprompt, 0);
2423 }
2424
2425 unbind_to (count, Qnil);
2426 return answer ? Qt : Qnil;
2427 }
2428 \f
2429 /* This is how C code calls `yes-or-no-p' and allows the user
2430 to redefined it.
2431
2432 Anything that calls this function must protect from GC! */
2433
2434 Lisp_Object
2435 do_yes_or_no_p (prompt)
2436 Lisp_Object prompt;
2437 {
2438 return call1 (intern ("yes-or-no-p"), prompt);
2439 }
2440
2441 /* Anything that calls this function must protect from GC! */
2442
2443 DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
2444 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2445 Takes one argument, which is the string to display to ask the question.\n\
2446 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2447 The user must confirm the answer with RET,\n\
2448 and can edit it until it has been confirmed.")
2449 (prompt)
2450 Lisp_Object prompt;
2451 {
2452 register Lisp_Object ans;
2453 Lisp_Object args[2];
2454 struct gcpro gcpro1;
2455 Lisp_Object menu;
2456
2457 CHECK_STRING (prompt, 0);
2458
2459 #ifdef HAVE_MENUS
2460 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2461 && use_dialog_box
2462 && have_menus_p ())
2463 {
2464 Lisp_Object pane, menu, obj;
2465 redisplay_preserve_echo_area ();
2466 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2467 Fcons (Fcons (build_string ("No"), Qnil),
2468 Qnil));
2469 GCPRO1 (pane);
2470 menu = Fcons (prompt, pane);
2471 obj = Fx_popup_dialog (Qt, menu);
2472 UNGCPRO;
2473 return obj;
2474 }
2475 #endif /* HAVE_MENUS */
2476
2477 args[0] = prompt;
2478 args[1] = build_string ("(yes or no) ");
2479 prompt = Fconcat (2, args);
2480
2481 GCPRO1 (prompt);
2482
2483 while (1)
2484 {
2485 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
2486 Qyes_or_no_p_history, Qnil,
2487 Qnil));
2488 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2489 {
2490 UNGCPRO;
2491 return Qt;
2492 }
2493 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2494 {
2495 UNGCPRO;
2496 return Qnil;
2497 }
2498
2499 Fding (Qnil);
2500 Fdiscard_input ();
2501 message ("Please answer yes or no.");
2502 Fsleep_for (make_number (2), Qnil);
2503 }
2504 }
2505 \f
2506 DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
2507 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
2508 Each of the three load averages is multiplied by 100,\n\
2509 then converted to integer.\n\
2510 When USE-FLOATS is non-nil, floats will be used instead of integers.\n\
2511 These floats are not multiplied by 100.\n\n\
2512 If the 5-minute or 15-minute load averages are not available, return a\n\
2513 shortened list, containing only those averages which are available.")
2514 (use_floats)
2515 Lisp_Object use_floats;
2516 {
2517 double load_ave[3];
2518 int loads = getloadavg (load_ave, 3);
2519 Lisp_Object ret = Qnil;
2520
2521 if (loads < 0)
2522 error ("load-average not implemented for this operating system");
2523
2524 while (loads-- > 0)
2525 {
2526 Lisp_Object load = (NILP (use_floats) ?
2527 make_number ((int) (100.0 * load_ave[loads]))
2528 : make_float (load_ave[loads]));
2529 ret = Fcons (load, ret);
2530 }
2531
2532 return ret;
2533 }
2534 \f
2535 Lisp_Object Vfeatures;
2536
2537 DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
2538 "Returns t if FEATURE is present in this Emacs.\n\
2539 Use this to conditionalize execution of lisp code based on the presence or\n\
2540 absence of emacs or environment extensions.\n\
2541 Use `provide' to declare that a feature is available.\n\
2542 This function looks at the value of the variable `features'.")
2543 (feature)
2544 Lisp_Object feature;
2545 {
2546 register Lisp_Object tem;
2547 CHECK_SYMBOL (feature, 0);
2548 tem = Fmemq (feature, Vfeatures);
2549 return (NILP (tem)) ? Qnil : Qt;
2550 }
2551
2552 DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
2553 "Announce that FEATURE is a feature of the current Emacs.")
2554 (feature)
2555 Lisp_Object feature;
2556 {
2557 register Lisp_Object tem;
2558 CHECK_SYMBOL (feature, 0);
2559 if (!NILP (Vautoload_queue))
2560 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
2561 tem = Fmemq (feature, Vfeatures);
2562 if (NILP (tem))
2563 Vfeatures = Fcons (feature, Vfeatures);
2564 LOADHIST_ATTACH (Fcons (Qprovide, feature));
2565 return feature;
2566 }
2567
2568 DEFUN ("require", Frequire, Srequire, 1, 2, 0,
2569 "If feature FEATURE is not loaded, load it from FILENAME.\n\
2570 If FEATURE is not a member of the list `features', then the feature\n\
2571 is not loaded; so load the file FILENAME.\n\
2572 If FILENAME is omitted, the printname of FEATURE is used as the file name,\n\
2573 but in this case `load' insists on adding the suffix `.el' or `.elc'.")
2574 (feature, file_name)
2575 Lisp_Object feature, file_name;
2576 {
2577 register Lisp_Object tem;
2578 CHECK_SYMBOL (feature, 0);
2579 tem = Fmemq (feature, Vfeatures);
2580 LOADHIST_ATTACH (Fcons (Qrequire, feature));
2581 if (NILP (tem))
2582 {
2583 int count = specpdl_ptr - specpdl;
2584
2585 /* Value saved here is to be restored into Vautoload_queue */
2586 record_unwind_protect (un_autoload, Vautoload_queue);
2587 Vautoload_queue = Qt;
2588
2589 Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
2590 Qnil, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
2591
2592 tem = Fmemq (feature, Vfeatures);
2593 if (NILP (tem))
2594 error ("Required feature %s was not provided",
2595 XSYMBOL (feature)->name->data);
2596
2597 /* Once loading finishes, don't undo it. */
2598 Vautoload_queue = Qt;
2599 feature = unbind_to (count, feature);
2600 }
2601 return feature;
2602 }
2603 \f
2604 /* Primitives for work of the "widget" library.
2605 In an ideal world, this section would not have been necessary.
2606 However, lisp function calls being as slow as they are, it turns
2607 out that some functions in the widget library (wid-edit.el) are the
2608 bottleneck of Widget operation. Here is their translation to C,
2609 for the sole reason of efficiency. */
2610
2611 DEFUN ("widget-plist-member", Fwidget_plist_member, Swidget_plist_member, 2, 2, 0,
2612 "Return non-nil if PLIST has the property PROP.\n\
2613 PLIST is a property list, which is a list of the form\n\
2614 \(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
2615 Unlike `plist-get', this allows you to distinguish between a missing\n\
2616 property and a property with the value nil.\n\
2617 The value is actually the tail of PLIST whose car is PROP.")
2618 (plist, prop)
2619 Lisp_Object plist, prop;
2620 {
2621 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2622 {
2623 QUIT;
2624 plist = XCDR (plist);
2625 plist = CDR (plist);
2626 }
2627 return plist;
2628 }
2629
2630 DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
2631 "In WIDGET, set PROPERTY to VALUE.\n\
2632 The value can later be retrieved with `widget-get'.")
2633 (widget, property, value)
2634 Lisp_Object widget, property, value;
2635 {
2636 CHECK_CONS (widget, 1);
2637 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
2638 }
2639
2640 DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
2641 "In WIDGET, get the value of PROPERTY.\n\
2642 The value could either be specified when the widget was created, or\n\
2643 later with `widget-put'.")
2644 (widget, property)
2645 Lisp_Object widget, property;
2646 {
2647 Lisp_Object tmp;
2648
2649 while (1)
2650 {
2651 if (NILP (widget))
2652 return Qnil;
2653 CHECK_CONS (widget, 1);
2654 tmp = Fwidget_plist_member (XCDR (widget), property);
2655 if (CONSP (tmp))
2656 {
2657 tmp = XCDR (tmp);
2658 return CAR (tmp);
2659 }
2660 tmp = XCAR (widget);
2661 if (NILP (tmp))
2662 return Qnil;
2663 widget = Fget (tmp, Qwidget_type);
2664 }
2665 }
2666
2667 DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
2668 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
2669 ARGS are passed as extra arguments to the function.")
2670 (nargs, args)
2671 int nargs;
2672 Lisp_Object *args;
2673 {
2674 /* This function can GC. */
2675 Lisp_Object newargs[3];
2676 struct gcpro gcpro1, gcpro2;
2677 Lisp_Object result;
2678
2679 newargs[0] = Fwidget_get (args[0], args[1]);
2680 newargs[1] = args[0];
2681 newargs[2] = Flist (nargs - 2, args + 2);
2682 GCPRO2 (newargs[0], newargs[2]);
2683 result = Fapply (3, newargs);
2684 UNGCPRO;
2685 return result;
2686 }
2687 \f
2688 void
2689 syms_of_fns ()
2690 {
2691 Qstring_lessp = intern ("string-lessp");
2692 staticpro (&Qstring_lessp);
2693 Qprovide = intern ("provide");
2694 staticpro (&Qprovide);
2695 Qrequire = intern ("require");
2696 staticpro (&Qrequire);
2697 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
2698 staticpro (&Qyes_or_no_p_history);
2699 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
2700 staticpro (&Qcursor_in_echo_area);
2701 Qwidget_type = intern ("widget-type");
2702 staticpro (&Qwidget_type);
2703
2704 staticpro (&string_char_byte_cache_string);
2705 string_char_byte_cache_string = Qnil;
2706
2707 Fset (Qyes_or_no_p_history, Qnil);
2708
2709 DEFVAR_LISP ("features", &Vfeatures,
2710 "A list of symbols which are the features of the executing emacs.\n\
2711 Used by `featurep' and `require', and altered by `provide'.");
2712 Vfeatures = Qnil;
2713
2714 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
2715 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
2716 This applies to y-or-n and yes-or-no questions asked by commands\n\
2717 invoked by mouse clicks and mouse menu items.");
2718 use_dialog_box = 1;
2719
2720 defsubr (&Sidentity);
2721 defsubr (&Srandom);
2722 defsubr (&Slength);
2723 defsubr (&Ssafe_length);
2724 defsubr (&Sstring_bytes);
2725 defsubr (&Sstring_equal);
2726 defsubr (&Scompare_strings);
2727 defsubr (&Sstring_lessp);
2728 defsubr (&Sappend);
2729 defsubr (&Sconcat);
2730 defsubr (&Svconcat);
2731 defsubr (&Scopy_sequence);
2732 defsubr (&Sstring_make_multibyte);
2733 defsubr (&Sstring_make_unibyte);
2734 defsubr (&Sstring_as_multibyte);
2735 defsubr (&Sstring_as_unibyte);
2736 defsubr (&Scopy_alist);
2737 defsubr (&Ssubstring);
2738 defsubr (&Snthcdr);
2739 defsubr (&Snth);
2740 defsubr (&Selt);
2741 defsubr (&Smember);
2742 defsubr (&Smemq);
2743 defsubr (&Sassq);
2744 defsubr (&Sassoc);
2745 defsubr (&Srassq);
2746 defsubr (&Srassoc);
2747 defsubr (&Sdelq);
2748 defsubr (&Sdelete);
2749 defsubr (&Snreverse);
2750 defsubr (&Sreverse);
2751 defsubr (&Ssort);
2752 defsubr (&Splist_get);
2753 defsubr (&Sget);
2754 defsubr (&Splist_put);
2755 defsubr (&Sput);
2756 defsubr (&Sequal);
2757 defsubr (&Sfillarray);
2758 defsubr (&Schar_table_subtype);
2759 defsubr (&Schar_table_parent);
2760 defsubr (&Sset_char_table_parent);
2761 defsubr (&Schar_table_extra_slot);
2762 defsubr (&Sset_char_table_extra_slot);
2763 defsubr (&Schar_table_range);
2764 defsubr (&Sset_char_table_range);
2765 defsubr (&Sset_char_table_default);
2766 defsubr (&Smap_char_table);
2767 defsubr (&Snconc);
2768 defsubr (&Smapcar);
2769 defsubr (&Smapconcat);
2770 defsubr (&Sy_or_n_p);
2771 defsubr (&Syes_or_no_p);
2772 defsubr (&Sload_average);
2773 defsubr (&Sfeaturep);
2774 defsubr (&Srequire);
2775 defsubr (&Sprovide);
2776 defsubr (&Swidget_plist_member);
2777 defsubr (&Swidget_put);
2778 defsubr (&Swidget_get);
2779 defsubr (&Swidget_apply);
2780 }