(lisp_data_to_selection_data): Call
[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 return string_make_multibyte (string);
953 }
954
955 DEFUN ("string-make-unibyte", Fstring_make_unibyte, Sstring_make_unibyte,
956 1, 1, 0,
957 "Return the unibyte equivalent of STRING.\n\
958 Multibyte character codes are converted to unibyte\n\
959 by using just the low 8 bits.")
960 (string)
961 Lisp_Object string;
962 {
963 return string_make_unibyte (string);
964 }
965
966 DEFUN ("string-as-unibyte", Fstring_as_unibyte, Sstring_as_unibyte,
967 1, 1, 0,
968 "Return a unibyte string with the same individual bytes as STRING.\n\
969 If STRING is unibyte, the result is STRING itself.")
970 (string)
971 Lisp_Object string;
972 {
973 if (STRING_MULTIBYTE (string))
974 {
975 string = Fcopy_sequence (string);
976 XSTRING (string)->size = STRING_BYTES (XSTRING (string));
977 SET_STRING_BYTES (XSTRING (string), -1);
978 }
979 return string;
980 }
981
982 DEFUN ("string-as-multibyte", Fstring_as_multibyte, Sstring_as_multibyte,
983 1, 1, 0,
984 "Return a multibyte string with the same individual bytes as STRING.\n\
985 If STRING is multibyte, the result is STRING itself.")
986 (string)
987 Lisp_Object string;
988 {
989 if (! STRING_MULTIBYTE (string))
990 {
991 int nbytes = STRING_BYTES (XSTRING (string));
992 int newlen = multibyte_chars_in_text (XSTRING (string)->data, nbytes);
993
994 string = Fcopy_sequence (string);
995 XSTRING (string)->size = newlen;
996 XSTRING (string)->size_byte = nbytes;
997 }
998 return string;
999 }
1000 \f
1001 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
1002 "Return a copy of ALIST.\n\
1003 This is an alist which represents the same mapping from objects to objects,\n\
1004 but does not share the alist structure with ALIST.\n\
1005 The objects mapped (cars and cdrs of elements of the alist)\n\
1006 are shared, however.\n\
1007 Elements of ALIST that are not conses are also shared.")
1008 (alist)
1009 Lisp_Object alist;
1010 {
1011 register Lisp_Object tem;
1012
1013 CHECK_LIST (alist, 0);
1014 if (NILP (alist))
1015 return alist;
1016 alist = concat (1, &alist, Lisp_Cons, 0);
1017 for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
1018 {
1019 register Lisp_Object car;
1020 car = XCONS (tem)->car;
1021
1022 if (CONSP (car))
1023 XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
1024 }
1025 return alist;
1026 }
1027
1028 DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
1029 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
1030 TO may be nil or omitted; then the substring runs to the end of STRING.\n\
1031 If FROM or TO is negative, it counts from the end.\n\
1032 \n\
1033 This function allows vectors as well as strings.")
1034 (string, from, to)
1035 Lisp_Object string;
1036 register Lisp_Object from, to;
1037 {
1038 Lisp_Object res;
1039 int size;
1040 int size_byte;
1041 int from_char, to_char;
1042 int from_byte, to_byte;
1043
1044 if (! (STRINGP (string) || VECTORP (string)))
1045 wrong_type_argument (Qarrayp, string);
1046
1047 CHECK_NUMBER (from, 1);
1048
1049 if (STRINGP (string))
1050 {
1051 size = XSTRING (string)->size;
1052 size_byte = STRING_BYTES (XSTRING (string));
1053 }
1054 else
1055 size = XVECTOR (string)->size;
1056
1057 if (NILP (to))
1058 {
1059 to_char = size;
1060 to_byte = size_byte;
1061 }
1062 else
1063 {
1064 CHECK_NUMBER (to, 2);
1065
1066 to_char = XINT (to);
1067 if (to_char < 0)
1068 to_char += size;
1069
1070 if (STRINGP (string))
1071 to_byte = string_char_to_byte (string, to_char);
1072 }
1073
1074 from_char = XINT (from);
1075 if (from_char < 0)
1076 from_char += size;
1077 if (STRINGP (string))
1078 from_byte = string_char_to_byte (string, from_char);
1079
1080 if (!(0 <= from_char && from_char <= to_char && to_char <= size))
1081 args_out_of_range_3 (string, make_number (from_char),
1082 make_number (to_char));
1083
1084 if (STRINGP (string))
1085 {
1086 res = make_specified_string (XSTRING (string)->data + from_byte,
1087 to_char - from_char, to_byte - from_byte,
1088 STRING_MULTIBYTE (string));
1089 copy_text_properties (make_number (from_char), make_number (to_char),
1090 string, make_number (0), res, Qnil);
1091 }
1092 else
1093 res = Fvector (to_char - from_char,
1094 XVECTOR (string)->contents + from_char);
1095
1096 return res;
1097 }
1098
1099 /* Extract a substring of STRING, giving start and end positions
1100 both in characters and in bytes. */
1101
1102 Lisp_Object
1103 substring_both (string, from, from_byte, to, to_byte)
1104 Lisp_Object string;
1105 int from, from_byte, to, to_byte;
1106 {
1107 Lisp_Object res;
1108 int size;
1109 int size_byte;
1110
1111 if (! (STRINGP (string) || VECTORP (string)))
1112 wrong_type_argument (Qarrayp, string);
1113
1114 if (STRINGP (string))
1115 {
1116 size = XSTRING (string)->size;
1117 size_byte = STRING_BYTES (XSTRING (string));
1118 }
1119 else
1120 size = XVECTOR (string)->size;
1121
1122 if (!(0 <= from && from <= to && to <= size))
1123 args_out_of_range_3 (string, make_number (from), make_number (to));
1124
1125 if (STRINGP (string))
1126 {
1127 res = make_specified_string (XSTRING (string)->data + from_byte,
1128 to - from, to_byte - from_byte,
1129 STRING_MULTIBYTE (string));
1130 copy_text_properties (make_number (from), make_number (to),
1131 string, make_number (0), res, Qnil);
1132 }
1133 else
1134 res = Fvector (to - from,
1135 XVECTOR (string)->contents + from);
1136
1137 return res;
1138 }
1139 \f
1140 DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1141 "Take cdr N times on LIST, returns the result.")
1142 (n, list)
1143 Lisp_Object n;
1144 register Lisp_Object list;
1145 {
1146 register int i, num;
1147 CHECK_NUMBER (n, 0);
1148 num = XINT (n);
1149 for (i = 0; i < num && !NILP (list); i++)
1150 {
1151 QUIT;
1152 list = Fcdr (list);
1153 }
1154 return list;
1155 }
1156
1157 DEFUN ("nth", Fnth, Snth, 2, 2, 0,
1158 "Return the Nth element of LIST.\n\
1159 N counts from zero. If LIST is not that long, nil is returned.")
1160 (n, list)
1161 Lisp_Object n, list;
1162 {
1163 return Fcar (Fnthcdr (n, list));
1164 }
1165
1166 DEFUN ("elt", Felt, Selt, 2, 2, 0,
1167 "Return element of SEQUENCE at index N.")
1168 (sequence, n)
1169 register Lisp_Object sequence, n;
1170 {
1171 CHECK_NUMBER (n, 0);
1172 while (1)
1173 {
1174 if (CONSP (sequence) || NILP (sequence))
1175 return Fcar (Fnthcdr (n, sequence));
1176 else if (STRINGP (sequence) || VECTORP (sequence)
1177 || BOOL_VECTOR_P (sequence) || CHAR_TABLE_P (sequence))
1178 return Faref (sequence, n);
1179 else
1180 sequence = wrong_type_argument (Qsequencep, sequence);
1181 }
1182 }
1183
1184 DEFUN ("member", Fmember, Smember, 2, 2, 0,
1185 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
1186 The value is actually the tail of LIST whose car is ELT.")
1187 (elt, list)
1188 register Lisp_Object elt;
1189 Lisp_Object list;
1190 {
1191 register Lisp_Object tail;
1192 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1193 {
1194 register Lisp_Object tem;
1195 tem = Fcar (tail);
1196 if (! NILP (Fequal (elt, tem)))
1197 return tail;
1198 QUIT;
1199 }
1200 return Qnil;
1201 }
1202
1203 DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
1204 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
1205 The value is actually the tail of LIST whose car is ELT.")
1206 (elt, list)
1207 register Lisp_Object elt;
1208 Lisp_Object list;
1209 {
1210 register Lisp_Object tail;
1211 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1212 {
1213 register Lisp_Object tem;
1214 tem = Fcar (tail);
1215 if (EQ (elt, tem)) return tail;
1216 QUIT;
1217 }
1218 return Qnil;
1219 }
1220
1221 DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
1222 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
1223 The value is actually the element of LIST whose car is KEY.\n\
1224 Elements of LIST that are not conses are ignored.")
1225 (key, list)
1226 register Lisp_Object key;
1227 Lisp_Object list;
1228 {
1229 register Lisp_Object tail;
1230 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1231 {
1232 register Lisp_Object elt, tem;
1233 elt = Fcar (tail);
1234 if (!CONSP (elt)) continue;
1235 tem = XCONS (elt)->car;
1236 if (EQ (key, tem)) return elt;
1237 QUIT;
1238 }
1239 return Qnil;
1240 }
1241
1242 /* Like Fassq but never report an error and do not allow quits.
1243 Use only on lists known never to be circular. */
1244
1245 Lisp_Object
1246 assq_no_quit (key, list)
1247 register Lisp_Object key;
1248 Lisp_Object list;
1249 {
1250 register Lisp_Object tail;
1251 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
1252 {
1253 register Lisp_Object elt, tem;
1254 elt = Fcar (tail);
1255 if (!CONSP (elt)) continue;
1256 tem = XCONS (elt)->car;
1257 if (EQ (key, tem)) return elt;
1258 }
1259 return Qnil;
1260 }
1261
1262 DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
1263 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
1264 The value is actually the element of LIST whose car equals KEY.")
1265 (key, list)
1266 register Lisp_Object key;
1267 Lisp_Object list;
1268 {
1269 register Lisp_Object tail;
1270 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1271 {
1272 register Lisp_Object elt, tem;
1273 elt = Fcar (tail);
1274 if (!CONSP (elt)) continue;
1275 tem = Fequal (XCONS (elt)->car, key);
1276 if (!NILP (tem)) return elt;
1277 QUIT;
1278 }
1279 return Qnil;
1280 }
1281
1282 DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
1283 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
1284 The value is actually the element of LIST whose cdr is ELT.")
1285 (key, list)
1286 register Lisp_Object key;
1287 Lisp_Object list;
1288 {
1289 register Lisp_Object tail;
1290 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1291 {
1292 register Lisp_Object elt, tem;
1293 elt = Fcar (tail);
1294 if (!CONSP (elt)) continue;
1295 tem = XCONS (elt)->cdr;
1296 if (EQ (key, tem)) return elt;
1297 QUIT;
1298 }
1299 return Qnil;
1300 }
1301
1302 DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
1303 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
1304 The value is actually the element of LIST whose cdr equals KEY.")
1305 (key, list)
1306 register Lisp_Object key;
1307 Lisp_Object list;
1308 {
1309 register Lisp_Object tail;
1310 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1311 {
1312 register Lisp_Object elt, tem;
1313 elt = Fcar (tail);
1314 if (!CONSP (elt)) continue;
1315 tem = Fequal (XCONS (elt)->cdr, key);
1316 if (!NILP (tem)) return elt;
1317 QUIT;
1318 }
1319 return Qnil;
1320 }
1321 \f
1322 DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
1323 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1324 The modified LIST is returned. Comparison is done with `eq'.\n\
1325 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
1326 therefore, write `(setq foo (delq element foo))'\n\
1327 to be sure of changing the value of `foo'.")
1328 (elt, list)
1329 register Lisp_Object elt;
1330 Lisp_Object list;
1331 {
1332 register Lisp_Object tail, prev;
1333 register Lisp_Object tem;
1334
1335 tail = list;
1336 prev = Qnil;
1337 while (!NILP (tail))
1338 {
1339 tem = Fcar (tail);
1340 if (EQ (elt, tem))
1341 {
1342 if (NILP (prev))
1343 list = XCONS (tail)->cdr;
1344 else
1345 Fsetcdr (prev, XCONS (tail)->cdr);
1346 }
1347 else
1348 prev = tail;
1349 tail = XCONS (tail)->cdr;
1350 QUIT;
1351 }
1352 return list;
1353 }
1354
1355 DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
1356 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1357 The modified LIST is returned. Comparison is done with `equal'.\n\
1358 If the first member of LIST is ELT, deleting it is not a side effect;\n\
1359 it is simply using a different list.\n\
1360 Therefore, write `(setq foo (delete element foo))'\n\
1361 to be sure of changing the value of `foo'.")
1362 (elt, list)
1363 register Lisp_Object elt;
1364 Lisp_Object list;
1365 {
1366 register Lisp_Object tail, prev;
1367 register Lisp_Object tem;
1368
1369 tail = list;
1370 prev = Qnil;
1371 while (!NILP (tail))
1372 {
1373 tem = Fcar (tail);
1374 if (! NILP (Fequal (elt, tem)))
1375 {
1376 if (NILP (prev))
1377 list = XCONS (tail)->cdr;
1378 else
1379 Fsetcdr (prev, XCONS (tail)->cdr);
1380 }
1381 else
1382 prev = tail;
1383 tail = XCONS (tail)->cdr;
1384 QUIT;
1385 }
1386 return list;
1387 }
1388
1389 DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
1390 "Reverse LIST by modifying cdr pointers.\n\
1391 Returns the beginning of the reversed list.")
1392 (list)
1393 Lisp_Object list;
1394 {
1395 register Lisp_Object prev, tail, next;
1396
1397 if (NILP (list)) return list;
1398 prev = Qnil;
1399 tail = list;
1400 while (!NILP (tail))
1401 {
1402 QUIT;
1403 next = Fcdr (tail);
1404 Fsetcdr (tail, prev);
1405 prev = tail;
1406 tail = next;
1407 }
1408 return prev;
1409 }
1410
1411 DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
1412 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
1413 See also the function `nreverse', which is used more often.")
1414 (list)
1415 Lisp_Object list;
1416 {
1417 Lisp_Object new;
1418
1419 for (new = Qnil; CONSP (list); list = XCONS (list)->cdr)
1420 new = Fcons (XCONS (list)->car, new);
1421 if (!NILP (list))
1422 wrong_type_argument (Qconsp, list);
1423 return new;
1424 }
1425 \f
1426 Lisp_Object merge ();
1427
1428 DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
1429 "Sort LIST, stably, comparing elements using PREDICATE.\n\
1430 Returns the sorted list. LIST is modified by side effects.\n\
1431 PREDICATE is called with two elements of LIST, and should return T\n\
1432 if the first element is \"less\" than the second.")
1433 (list, predicate)
1434 Lisp_Object list, predicate;
1435 {
1436 Lisp_Object front, back;
1437 register Lisp_Object len, tem;
1438 struct gcpro gcpro1, gcpro2;
1439 register int length;
1440
1441 front = list;
1442 len = Flength (list);
1443 length = XINT (len);
1444 if (length < 2)
1445 return list;
1446
1447 XSETINT (len, (length / 2) - 1);
1448 tem = Fnthcdr (len, list);
1449 back = Fcdr (tem);
1450 Fsetcdr (tem, Qnil);
1451
1452 GCPRO2 (front, back);
1453 front = Fsort (front, predicate);
1454 back = Fsort (back, predicate);
1455 UNGCPRO;
1456 return merge (front, back, predicate);
1457 }
1458
1459 Lisp_Object
1460 merge (org_l1, org_l2, pred)
1461 Lisp_Object org_l1, org_l2;
1462 Lisp_Object pred;
1463 {
1464 Lisp_Object value;
1465 register Lisp_Object tail;
1466 Lisp_Object tem;
1467 register Lisp_Object l1, l2;
1468 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1469
1470 l1 = org_l1;
1471 l2 = org_l2;
1472 tail = Qnil;
1473 value = Qnil;
1474
1475 /* It is sufficient to protect org_l1 and org_l2.
1476 When l1 and l2 are updated, we copy the new values
1477 back into the org_ vars. */
1478 GCPRO4 (org_l1, org_l2, pred, value);
1479
1480 while (1)
1481 {
1482 if (NILP (l1))
1483 {
1484 UNGCPRO;
1485 if (NILP (tail))
1486 return l2;
1487 Fsetcdr (tail, l2);
1488 return value;
1489 }
1490 if (NILP (l2))
1491 {
1492 UNGCPRO;
1493 if (NILP (tail))
1494 return l1;
1495 Fsetcdr (tail, l1);
1496 return value;
1497 }
1498 tem = call2 (pred, Fcar (l2), Fcar (l1));
1499 if (NILP (tem))
1500 {
1501 tem = l1;
1502 l1 = Fcdr (l1);
1503 org_l1 = l1;
1504 }
1505 else
1506 {
1507 tem = l2;
1508 l2 = Fcdr (l2);
1509 org_l2 = l2;
1510 }
1511 if (NILP (tail))
1512 value = tem;
1513 else
1514 Fsetcdr (tail, tem);
1515 tail = tem;
1516 }
1517 }
1518 \f
1519
1520 DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
1521 "Extract a value from a property list.\n\
1522 PLIST is a property list, which is a list of the form\n\
1523 \(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
1524 corresponding to the given PROP, or nil if PROP is not\n\
1525 one of the properties on the list.")
1526 (plist, prop)
1527 Lisp_Object plist;
1528 register Lisp_Object prop;
1529 {
1530 register Lisp_Object tail;
1531 for (tail = plist; !NILP (tail); tail = Fcdr (XCONS (tail)->cdr))
1532 {
1533 register Lisp_Object tem;
1534 tem = Fcar (tail);
1535 if (EQ (prop, tem))
1536 return Fcar (XCONS (tail)->cdr);
1537 }
1538 return Qnil;
1539 }
1540
1541 DEFUN ("get", Fget, Sget, 2, 2, 0,
1542 "Return the value of SYMBOL's PROPNAME property.\n\
1543 This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
1544 (symbol, propname)
1545 Lisp_Object symbol, propname;
1546 {
1547 CHECK_SYMBOL (symbol, 0);
1548 return Fplist_get (XSYMBOL (symbol)->plist, propname);
1549 }
1550
1551 DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
1552 "Change value in PLIST of PROP to VAL.\n\
1553 PLIST is a property list, which is a list of the form\n\
1554 \(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
1555 If PROP is already a property on the list, its value is set to VAL,\n\
1556 otherwise the new PROP VAL pair is added. The new plist is returned;\n\
1557 use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
1558 The PLIST is modified by side effects.")
1559 (plist, prop, val)
1560 Lisp_Object plist;
1561 register Lisp_Object prop;
1562 Lisp_Object val;
1563 {
1564 register Lisp_Object tail, prev;
1565 Lisp_Object newcell;
1566 prev = Qnil;
1567 for (tail = plist; CONSP (tail) && CONSP (XCONS (tail)->cdr);
1568 tail = XCONS (XCONS (tail)->cdr)->cdr)
1569 {
1570 if (EQ (prop, XCONS (tail)->car))
1571 {
1572 Fsetcar (XCONS (tail)->cdr, val);
1573 return plist;
1574 }
1575 prev = tail;
1576 }
1577 newcell = Fcons (prop, Fcons (val, Qnil));
1578 if (NILP (prev))
1579 return newcell;
1580 else
1581 Fsetcdr (XCONS (prev)->cdr, newcell);
1582 return plist;
1583 }
1584
1585 DEFUN ("put", Fput, Sput, 3, 3, 0,
1586 "Store SYMBOL's PROPNAME property with value VALUE.\n\
1587 It can be retrieved with `(get SYMBOL PROPNAME)'.")
1588 (symbol, propname, value)
1589 Lisp_Object symbol, propname, value;
1590 {
1591 CHECK_SYMBOL (symbol, 0);
1592 XSYMBOL (symbol)->plist
1593 = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
1594 return value;
1595 }
1596
1597 DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
1598 "Return t if two Lisp objects have similar structure and contents.\n\
1599 They must have the same data type.\n\
1600 Conses are compared by comparing the cars and the cdrs.\n\
1601 Vectors and strings are compared element by element.\n\
1602 Numbers are compared by value, but integers cannot equal floats.\n\
1603 (Use `=' if you want integers and floats to be able to be equal.)\n\
1604 Symbols must match exactly.")
1605 (o1, o2)
1606 register Lisp_Object o1, o2;
1607 {
1608 return internal_equal (o1, o2, 0) ? Qt : Qnil;
1609 }
1610
1611 static int
1612 internal_equal (o1, o2, depth)
1613 register Lisp_Object o1, o2;
1614 int depth;
1615 {
1616 if (depth > 200)
1617 error ("Stack overflow in equal");
1618
1619 tail_recurse:
1620 QUIT;
1621 if (EQ (o1, o2))
1622 return 1;
1623 if (XTYPE (o1) != XTYPE (o2))
1624 return 0;
1625
1626 switch (XTYPE (o1))
1627 {
1628 #ifdef LISP_FLOAT_TYPE
1629 case Lisp_Float:
1630 return (extract_float (o1) == extract_float (o2));
1631 #endif
1632
1633 case Lisp_Cons:
1634 if (!internal_equal (XCONS (o1)->car, XCONS (o2)->car, depth + 1))
1635 return 0;
1636 o1 = XCONS (o1)->cdr;
1637 o2 = XCONS (o2)->cdr;
1638 goto tail_recurse;
1639
1640 case Lisp_Misc:
1641 if (XMISCTYPE (o1) != XMISCTYPE (o2))
1642 return 0;
1643 if (OVERLAYP (o1))
1644 {
1645 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o1),
1646 depth + 1)
1647 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o1),
1648 depth + 1))
1649 return 0;
1650 o1 = XOVERLAY (o1)->plist;
1651 o2 = XOVERLAY (o2)->plist;
1652 goto tail_recurse;
1653 }
1654 if (MARKERP (o1))
1655 {
1656 return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
1657 && (XMARKER (o1)->buffer == 0
1658 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
1659 }
1660 break;
1661
1662 case Lisp_Vectorlike:
1663 {
1664 register int i, size;
1665 size = XVECTOR (o1)->size;
1666 /* Pseudovectors have the type encoded in the size field, so this test
1667 actually checks that the objects have the same type as well as the
1668 same size. */
1669 if (XVECTOR (o2)->size != size)
1670 return 0;
1671 /* Boolvectors are compared much like strings. */
1672 if (BOOL_VECTOR_P (o1))
1673 {
1674 int size_in_chars
1675 = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
1676
1677 if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
1678 return 0;
1679 if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
1680 size_in_chars))
1681 return 0;
1682 return 1;
1683 }
1684 if (WINDOW_CONFIGURATIONP (o1))
1685 return compare_window_configurations (o1, o2, 0);
1686
1687 /* Aside from them, only true vectors, char-tables, and compiled
1688 functions are sensible to compare, so eliminate the others now. */
1689 if (size & PSEUDOVECTOR_FLAG)
1690 {
1691 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
1692 return 0;
1693 size &= PSEUDOVECTOR_SIZE_MASK;
1694 }
1695 for (i = 0; i < size; i++)
1696 {
1697 Lisp_Object v1, v2;
1698 v1 = XVECTOR (o1)->contents [i];
1699 v2 = XVECTOR (o2)->contents [i];
1700 if (!internal_equal (v1, v2, depth + 1))
1701 return 0;
1702 }
1703 return 1;
1704 }
1705 break;
1706
1707 case Lisp_String:
1708 if (XSTRING (o1)->size != XSTRING (o2)->size)
1709 return 0;
1710 if (STRING_BYTES (XSTRING (o1)) != STRING_BYTES (XSTRING (o2)))
1711 return 0;
1712 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
1713 STRING_BYTES (XSTRING (o1))))
1714 return 0;
1715 return 1;
1716 }
1717 return 0;
1718 }
1719 \f
1720 extern Lisp_Object Fmake_char_internal ();
1721
1722 DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
1723 "Store each element of ARRAY with ITEM.\n\
1724 ARRAY is a vector, string, char-table, or bool-vector.")
1725 (array, item)
1726 Lisp_Object array, item;
1727 {
1728 register int size, index, charval;
1729 retry:
1730 if (VECTORP (array))
1731 {
1732 register Lisp_Object *p = XVECTOR (array)->contents;
1733 size = XVECTOR (array)->size;
1734 for (index = 0; index < size; index++)
1735 p[index] = item;
1736 }
1737 else if (CHAR_TABLE_P (array))
1738 {
1739 register Lisp_Object *p = XCHAR_TABLE (array)->contents;
1740 size = CHAR_TABLE_ORDINARY_SLOTS;
1741 for (index = 0; index < size; index++)
1742 p[index] = item;
1743 XCHAR_TABLE (array)->defalt = Qnil;
1744 }
1745 else if (STRINGP (array))
1746 {
1747 register unsigned char *p = XSTRING (array)->data;
1748 CHECK_NUMBER (item, 1);
1749 charval = XINT (item);
1750 size = XSTRING (array)->size;
1751 for (index = 0; index < size; index++)
1752 p[index] = charval;
1753 }
1754 else if (BOOL_VECTOR_P (array))
1755 {
1756 register unsigned char *p = XBOOL_VECTOR (array)->data;
1757 int size_in_chars
1758 = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
1759
1760 charval = (! NILP (item) ? -1 : 0);
1761 for (index = 0; index < size_in_chars; index++)
1762 p[index] = charval;
1763 }
1764 else
1765 {
1766 array = wrong_type_argument (Qarrayp, array);
1767 goto retry;
1768 }
1769 return array;
1770 }
1771 \f
1772 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
1773 1, 1, 0,
1774 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
1775 (char_table)
1776 Lisp_Object char_table;
1777 {
1778 CHECK_CHAR_TABLE (char_table, 0);
1779
1780 return XCHAR_TABLE (char_table)->purpose;
1781 }
1782
1783 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
1784 1, 1, 0,
1785 "Return the parent char-table of CHAR-TABLE.\n\
1786 The value is either nil or another char-table.\n\
1787 If CHAR-TABLE holds nil for a given character,\n\
1788 then the actual applicable value is inherited from the parent char-table\n\
1789 \(or from its parents, if necessary).")
1790 (char_table)
1791 Lisp_Object char_table;
1792 {
1793 CHECK_CHAR_TABLE (char_table, 0);
1794
1795 return XCHAR_TABLE (char_table)->parent;
1796 }
1797
1798 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
1799 2, 2, 0,
1800 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
1801 PARENT must be either nil or another char-table.")
1802 (char_table, parent)
1803 Lisp_Object char_table, parent;
1804 {
1805 Lisp_Object temp;
1806
1807 CHECK_CHAR_TABLE (char_table, 0);
1808
1809 if (!NILP (parent))
1810 {
1811 CHECK_CHAR_TABLE (parent, 0);
1812
1813 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
1814 if (EQ (temp, char_table))
1815 error ("Attempt to make a chartable be its own parent");
1816 }
1817
1818 XCHAR_TABLE (char_table)->parent = parent;
1819
1820 return parent;
1821 }
1822
1823 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
1824 2, 2, 0,
1825 "Return the value of CHAR-TABLE's extra-slot number N.")
1826 (char_table, n)
1827 Lisp_Object char_table, n;
1828 {
1829 CHECK_CHAR_TABLE (char_table, 1);
1830 CHECK_NUMBER (n, 2);
1831 if (XINT (n) < 0
1832 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1833 args_out_of_range (char_table, n);
1834
1835 return XCHAR_TABLE (char_table)->extras[XINT (n)];
1836 }
1837
1838 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
1839 Sset_char_table_extra_slot,
1840 3, 3, 0,
1841 "Set CHAR-TABLE's extra-slot number N to VALUE.")
1842 (char_table, n, value)
1843 Lisp_Object char_table, n, value;
1844 {
1845 CHECK_CHAR_TABLE (char_table, 1);
1846 CHECK_NUMBER (n, 2);
1847 if (XINT (n) < 0
1848 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1849 args_out_of_range (char_table, n);
1850
1851 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
1852 }
1853 \f
1854 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
1855 2, 2, 0,
1856 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
1857 RANGE should be nil (for the default value)\n\
1858 a vector which identifies a character set or a row of a character set,\n\
1859 a character set name, or a character code.")
1860 (char_table, range)
1861 Lisp_Object char_table, range;
1862 {
1863 int i;
1864
1865 CHECK_CHAR_TABLE (char_table, 0);
1866
1867 if (EQ (range, Qnil))
1868 return XCHAR_TABLE (char_table)->defalt;
1869 else if (INTEGERP (range))
1870 return Faref (char_table, range);
1871 else if (SYMBOLP (range))
1872 {
1873 Lisp_Object charset_info;
1874
1875 charset_info = Fget (range, Qcharset);
1876 CHECK_VECTOR (charset_info, 0);
1877
1878 return Faref (char_table,
1879 make_number (XINT (XVECTOR (charset_info)->contents[0])
1880 + 128));
1881 }
1882 else if (VECTORP (range))
1883 {
1884 if (XVECTOR (range)->size == 1)
1885 return Faref (char_table,
1886 make_number (XINT (XVECTOR (range)->contents[0]) + 128));
1887 else
1888 {
1889 int size = XVECTOR (range)->size;
1890 Lisp_Object *val = XVECTOR (range)->contents;
1891 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1892 size <= 1 ? Qnil : val[1],
1893 size <= 2 ? Qnil : val[2]);
1894 return Faref (char_table, ch);
1895 }
1896 }
1897 else
1898 error ("Invalid RANGE argument to `char-table-range'");
1899 }
1900
1901 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
1902 3, 3, 0,
1903 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
1904 RANGE should be t (for all characters), nil (for the default value)\n\
1905 a vector which identifies a character set or a row of a character set,\n\
1906 a coding system, or a character code.")
1907 (char_table, range, value)
1908 Lisp_Object char_table, range, value;
1909 {
1910 int i;
1911
1912 CHECK_CHAR_TABLE (char_table, 0);
1913
1914 if (EQ (range, Qt))
1915 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
1916 XCHAR_TABLE (char_table)->contents[i] = value;
1917 else if (EQ (range, Qnil))
1918 XCHAR_TABLE (char_table)->defalt = value;
1919 else if (SYMBOLP (range))
1920 {
1921 Lisp_Object charset_info;
1922
1923 charset_info = Fget (range, Qcharset);
1924 CHECK_VECTOR (charset_info, 0);
1925
1926 return Faset (char_table,
1927 make_number (XINT (XVECTOR (charset_info)->contents[0])
1928 + 128),
1929 value);
1930 }
1931 else if (INTEGERP (range))
1932 Faset (char_table, range, value);
1933 else if (VECTORP (range))
1934 {
1935 if (XVECTOR (range)->size == 1)
1936 return Faset (char_table,
1937 make_number (XINT (XVECTOR (range)->contents[0]) + 128),
1938 value);
1939 else
1940 {
1941 int size = XVECTOR (range)->size;
1942 Lisp_Object *val = XVECTOR (range)->contents;
1943 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1944 size <= 1 ? Qnil : val[1],
1945 size <= 2 ? Qnil : val[2]);
1946 return Faset (char_table, ch, value);
1947 }
1948 }
1949 else
1950 error ("Invalid RANGE argument to `set-char-table-range'");
1951
1952 return value;
1953 }
1954
1955 DEFUN ("set-char-table-default", Fset_char_table_default,
1956 Sset_char_table_default, 3, 3, 0,
1957 "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
1958 The generic character specifies the group of characters.\n\
1959 See also the documentation of make-char.")
1960 (char_table, ch, value)
1961 Lisp_Object char_table, ch, value;
1962 {
1963 int c, i, charset, code1, code2;
1964 Lisp_Object temp;
1965
1966 CHECK_CHAR_TABLE (char_table, 0);
1967 CHECK_NUMBER (ch, 1);
1968
1969 c = XINT (ch);
1970 SPLIT_NON_ASCII_CHAR (c, charset, code1, code2);
1971 if (! CHARSET_DEFINED_P (charset))
1972 invalid_character (c);
1973
1974 if (charset == CHARSET_ASCII)
1975 return (XCHAR_TABLE (char_table)->defalt = value);
1976
1977 /* Even if C is not a generic char, we had better behave as if a
1978 generic char is specified. */
1979 if (CHARSET_DIMENSION (charset) == 1)
1980 code1 = 0;
1981 temp = XCHAR_TABLE (char_table)->contents[charset + 128];
1982 if (!code1)
1983 {
1984 if (SUB_CHAR_TABLE_P (temp))
1985 XCHAR_TABLE (temp)->defalt = value;
1986 else
1987 XCHAR_TABLE (char_table)->contents[charset + 128] = value;
1988 return value;
1989 }
1990 char_table = temp;
1991 if (! SUB_CHAR_TABLE_P (char_table))
1992 char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
1993 = make_sub_char_table (temp));
1994 temp = XCHAR_TABLE (char_table)->contents[code1];
1995 if (SUB_CHAR_TABLE_P (temp))
1996 XCHAR_TABLE (temp)->defalt = value;
1997 else
1998 XCHAR_TABLE (char_table)->contents[code1] = value;
1999 return value;
2000 }
2001
2002 /* Look up the element in TABLE at index CH,
2003 and return it as an integer.
2004 If the element is nil, return CH itself.
2005 (Actually we do that for any non-integer.) */
2006
2007 int
2008 char_table_translate (table, ch)
2009 Lisp_Object table;
2010 int ch;
2011 {
2012 Lisp_Object value;
2013 value = Faref (table, make_number (ch));
2014 if (! INTEGERP (value))
2015 return ch;
2016 return XINT (value);
2017 }
2018 \f
2019 /* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
2020 character or group of characters that share a value.
2021 DEPTH is the current depth in the originally specified
2022 chartable, and INDICES contains the vector indices
2023 for the levels our callers have descended.
2024
2025 ARG is passed to C_FUNCTION when that is called. */
2026
2027 void
2028 map_char_table (c_function, function, subtable, arg, depth, indices)
2029 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
2030 Lisp_Object function, subtable, arg, *indices;
2031 int depth;
2032 {
2033 int i, to;
2034
2035 if (depth == 0)
2036 {
2037 /* At first, handle ASCII and 8-bit European characters. */
2038 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
2039 {
2040 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
2041 if (c_function)
2042 (*c_function) (arg, make_number (i), elt);
2043 else
2044 call2 (function, make_number (i), elt);
2045 }
2046 #if 0 /* If the char table has entries for higher characters,
2047 we should report them. */
2048 if (NILP (current_buffer->enable_multibyte_characters))
2049 return;
2050 #endif
2051 to = CHAR_TABLE_ORDINARY_SLOTS;
2052 }
2053 else
2054 {
2055 i = 32;
2056 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
2057 }
2058
2059 for (; i < to; i++)
2060 {
2061 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
2062
2063 XSETFASTINT (indices[depth], i);
2064
2065 if (SUB_CHAR_TABLE_P (elt))
2066 {
2067 if (depth >= 3)
2068 error ("Too deep char table");
2069 map_char_table (c_function, function, elt, arg, depth + 1, indices);
2070 }
2071 else
2072 {
2073 int charset = XFASTINT (indices[0]) - 128, c1, c2, c;
2074
2075 if (CHARSET_DEFINED_P (charset))
2076 {
2077 c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
2078 c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
2079 c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
2080 if (c_function)
2081 (*c_function) (arg, make_number (c), elt);
2082 else
2083 call2 (function, make_number (c), elt);
2084 }
2085 }
2086 }
2087 }
2088
2089 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
2090 2, 2, 0,
2091 "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
2092 FUNCTION is called with two arguments--a key and a value.\n\
2093 The key is always a possible IDX argument to `aref'.")
2094 (function, char_table)
2095 Lisp_Object function, char_table;
2096 {
2097 /* The depth of char table is at most 3. */
2098 Lisp_Object indices[3];
2099
2100 CHECK_CHAR_TABLE (char_table, 1);
2101
2102 map_char_table (NULL, function, char_table, char_table, 0, indices);
2103 return Qnil;
2104 }
2105 \f
2106 /* ARGSUSED */
2107 Lisp_Object
2108 nconc2 (s1, s2)
2109 Lisp_Object s1, s2;
2110 {
2111 #ifdef NO_ARG_ARRAY
2112 Lisp_Object args[2];
2113 args[0] = s1;
2114 args[1] = s2;
2115 return Fnconc (2, args);
2116 #else
2117 return Fnconc (2, &s1);
2118 #endif /* NO_ARG_ARRAY */
2119 }
2120
2121 DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
2122 "Concatenate any number of lists by altering them.\n\
2123 Only the last argument is not altered, and need not be a list.")
2124 (nargs, args)
2125 int nargs;
2126 Lisp_Object *args;
2127 {
2128 register int argnum;
2129 register Lisp_Object tail, tem, val;
2130
2131 val = Qnil;
2132
2133 for (argnum = 0; argnum < nargs; argnum++)
2134 {
2135 tem = args[argnum];
2136 if (NILP (tem)) continue;
2137
2138 if (NILP (val))
2139 val = tem;
2140
2141 if (argnum + 1 == nargs) break;
2142
2143 if (!CONSP (tem))
2144 tem = wrong_type_argument (Qlistp, tem);
2145
2146 while (CONSP (tem))
2147 {
2148 tail = tem;
2149 tem = Fcdr (tail);
2150 QUIT;
2151 }
2152
2153 tem = args[argnum + 1];
2154 Fsetcdr (tail, tem);
2155 if (NILP (tem))
2156 args[argnum + 1] = tail;
2157 }
2158
2159 return val;
2160 }
2161 \f
2162 /* This is the guts of all mapping functions.
2163 Apply FN to each element of SEQ, one by one,
2164 storing the results into elements of VALS, a C vector of Lisp_Objects.
2165 LENI is the length of VALS, which should also be the length of SEQ. */
2166
2167 static void
2168 mapcar1 (leni, vals, fn, seq)
2169 int leni;
2170 Lisp_Object *vals;
2171 Lisp_Object fn, seq;
2172 {
2173 register Lisp_Object tail;
2174 Lisp_Object dummy;
2175 register int i;
2176 struct gcpro gcpro1, gcpro2, gcpro3;
2177
2178 /* Don't let vals contain any garbage when GC happens. */
2179 for (i = 0; i < leni; i++)
2180 vals[i] = Qnil;
2181
2182 GCPRO3 (dummy, fn, seq);
2183 gcpro1.var = vals;
2184 gcpro1.nvars = leni;
2185 /* We need not explicitly protect `tail' because it is used only on lists, and
2186 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
2187
2188 if (VECTORP (seq))
2189 {
2190 for (i = 0; i < leni; i++)
2191 {
2192 dummy = XVECTOR (seq)->contents[i];
2193 vals[i] = call1 (fn, dummy);
2194 }
2195 }
2196 else if (BOOL_VECTOR_P (seq))
2197 {
2198 for (i = 0; i < leni; i++)
2199 {
2200 int byte;
2201 byte = XBOOL_VECTOR (seq)->data[i / BITS_PER_CHAR];
2202 if (byte & (1 << (i % BITS_PER_CHAR)))
2203 dummy = Qt;
2204 else
2205 dummy = Qnil;
2206
2207 vals[i] = call1 (fn, dummy);
2208 }
2209 }
2210 else if (STRINGP (seq) && ! STRING_MULTIBYTE (seq))
2211 {
2212 /* Single-byte string. */
2213 for (i = 0; i < leni; i++)
2214 {
2215 XSETFASTINT (dummy, XSTRING (seq)->data[i]);
2216 vals[i] = call1 (fn, dummy);
2217 }
2218 }
2219 else if (STRINGP (seq))
2220 {
2221 /* Multi-byte string. */
2222 int len_byte = STRING_BYTES (XSTRING (seq));
2223 int i_byte;
2224
2225 for (i = 0, i_byte = 0; i < leni;)
2226 {
2227 int c;
2228 int i_before = i;
2229
2230 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte);
2231 XSETFASTINT (dummy, c);
2232 vals[i_before] = call1 (fn, dummy);
2233 }
2234 }
2235 else /* Must be a list, since Flength did not get an error */
2236 {
2237 tail = seq;
2238 for (i = 0; i < leni; i++)
2239 {
2240 vals[i] = call1 (fn, Fcar (tail));
2241 tail = XCONS (tail)->cdr;
2242 }
2243 }
2244
2245 UNGCPRO;
2246 }
2247
2248 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
2249 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2250 In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
2251 SEPARATOR results in spaces between the values returned by FUNCTION.\n\
2252 SEQUENCE may be a list, a vector, a bool-vector, or a string.")
2253 (function, sequence, separator)
2254 Lisp_Object function, sequence, separator;
2255 {
2256 Lisp_Object len;
2257 register int leni;
2258 int nargs;
2259 register Lisp_Object *args;
2260 register int i;
2261 struct gcpro gcpro1;
2262
2263 len = Flength (sequence);
2264 leni = XINT (len);
2265 nargs = leni + leni - 1;
2266 if (nargs < 0) return build_string ("");
2267
2268 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2269
2270 GCPRO1 (separator);
2271 mapcar1 (leni, args, function, sequence);
2272 UNGCPRO;
2273
2274 for (i = leni - 1; i >= 0; i--)
2275 args[i + i] = args[i];
2276
2277 for (i = 1; i < nargs; i += 2)
2278 args[i] = separator;
2279
2280 return Fconcat (nargs, args);
2281 }
2282
2283 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2284 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2285 The result is a list just as long as SEQUENCE.\n\
2286 SEQUENCE may be a list, a vector, a bool-vector, or a string.")
2287 (function, sequence)
2288 Lisp_Object function, sequence;
2289 {
2290 register Lisp_Object len;
2291 register int leni;
2292 register Lisp_Object *args;
2293
2294 len = Flength (sequence);
2295 leni = XFASTINT (len);
2296 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2297
2298 mapcar1 (leni, args, function, sequence);
2299
2300 return Flist (leni, args);
2301 }
2302 \f
2303 /* Anything that calls this function must protect from GC! */
2304
2305 DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2306 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
2307 Takes one argument, which is the string to display to ask the question.\n\
2308 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
2309 No confirmation of the answer is requested; a single character is enough.\n\
2310 Also accepts Space to mean yes, or Delete to mean no.")
2311 (prompt)
2312 Lisp_Object prompt;
2313 {
2314 register Lisp_Object obj, key, def, answer_string, map;
2315 register int answer;
2316 Lisp_Object xprompt;
2317 Lisp_Object args[2];
2318 struct gcpro gcpro1, gcpro2;
2319 int count = specpdl_ptr - specpdl;
2320
2321 specbind (Qcursor_in_echo_area, Qt);
2322
2323 map = Fsymbol_value (intern ("query-replace-map"));
2324
2325 CHECK_STRING (prompt, 0);
2326 xprompt = prompt;
2327 GCPRO2 (prompt, xprompt);
2328
2329 while (1)
2330 {
2331
2332 #ifdef HAVE_MENUS
2333 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2334 && use_dialog_box
2335 && have_menus_p ())
2336 {
2337 Lisp_Object pane, menu;
2338 redisplay_preserve_echo_area ();
2339 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2340 Fcons (Fcons (build_string ("No"), Qnil),
2341 Qnil));
2342 menu = Fcons (prompt, pane);
2343 obj = Fx_popup_dialog (Qt, menu);
2344 answer = !NILP (obj);
2345 break;
2346 }
2347 #endif /* HAVE_MENUS */
2348 cursor_in_echo_area = 1;
2349 choose_minibuf_frame ();
2350 message_with_string ("%s(y or n) ", xprompt, 0);
2351
2352 if (minibuffer_auto_raise)
2353 {
2354 Lisp_Object mini_frame;
2355
2356 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2357
2358 Fraise_frame (mini_frame);
2359 }
2360
2361 obj = read_filtered_event (1, 0, 0);
2362 cursor_in_echo_area = 0;
2363 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2364 QUIT;
2365
2366 key = Fmake_vector (make_number (1), obj);
2367 def = Flookup_key (map, key, Qt);
2368 answer_string = Fsingle_key_description (obj);
2369
2370 if (EQ (def, intern ("skip")))
2371 {
2372 answer = 0;
2373 break;
2374 }
2375 else if (EQ (def, intern ("act")))
2376 {
2377 answer = 1;
2378 break;
2379 }
2380 else if (EQ (def, intern ("recenter")))
2381 {
2382 Frecenter (Qnil);
2383 xprompt = prompt;
2384 continue;
2385 }
2386 else if (EQ (def, intern ("quit")))
2387 Vquit_flag = Qt;
2388 /* We want to exit this command for exit-prefix,
2389 and this is the only way to do it. */
2390 else if (EQ (def, intern ("exit-prefix")))
2391 Vquit_flag = Qt;
2392
2393 QUIT;
2394
2395 /* If we don't clear this, then the next call to read_char will
2396 return quit_char again, and we'll enter an infinite loop. */
2397 Vquit_flag = Qnil;
2398
2399 Fding (Qnil);
2400 Fdiscard_input ();
2401 if (EQ (xprompt, prompt))
2402 {
2403 args[0] = build_string ("Please answer y or n. ");
2404 args[1] = prompt;
2405 xprompt = Fconcat (2, args);
2406 }
2407 }
2408 UNGCPRO;
2409
2410 if (! noninteractive)
2411 {
2412 cursor_in_echo_area = -1;
2413 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2414 xprompt, 0);
2415 }
2416
2417 unbind_to (count, Qnil);
2418 return answer ? Qt : Qnil;
2419 }
2420 \f
2421 /* This is how C code calls `yes-or-no-p' and allows the user
2422 to redefined it.
2423
2424 Anything that calls this function must protect from GC! */
2425
2426 Lisp_Object
2427 do_yes_or_no_p (prompt)
2428 Lisp_Object prompt;
2429 {
2430 return call1 (intern ("yes-or-no-p"), prompt);
2431 }
2432
2433 /* Anything that calls this function must protect from GC! */
2434
2435 DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
2436 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2437 Takes one argument, which is the string to display to ask the question.\n\
2438 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2439 The user must confirm the answer with RET,\n\
2440 and can edit it until it has been confirmed.")
2441 (prompt)
2442 Lisp_Object prompt;
2443 {
2444 register Lisp_Object ans;
2445 Lisp_Object args[2];
2446 struct gcpro gcpro1;
2447 Lisp_Object menu;
2448
2449 CHECK_STRING (prompt, 0);
2450
2451 #ifdef HAVE_MENUS
2452 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2453 && use_dialog_box
2454 && have_menus_p ())
2455 {
2456 Lisp_Object pane, menu, obj;
2457 redisplay_preserve_echo_area ();
2458 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2459 Fcons (Fcons (build_string ("No"), Qnil),
2460 Qnil));
2461 GCPRO1 (pane);
2462 menu = Fcons (prompt, pane);
2463 obj = Fx_popup_dialog (Qt, menu);
2464 UNGCPRO;
2465 return obj;
2466 }
2467 #endif /* HAVE_MENUS */
2468
2469 args[0] = prompt;
2470 args[1] = build_string ("(yes or no) ");
2471 prompt = Fconcat (2, args);
2472
2473 GCPRO1 (prompt);
2474
2475 while (1)
2476 {
2477 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
2478 Qyes_or_no_p_history, Qnil,
2479 Qnil));
2480 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2481 {
2482 UNGCPRO;
2483 return Qt;
2484 }
2485 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2486 {
2487 UNGCPRO;
2488 return Qnil;
2489 }
2490
2491 Fding (Qnil);
2492 Fdiscard_input ();
2493 message ("Please answer yes or no.");
2494 Fsleep_for (make_number (2), Qnil);
2495 }
2496 }
2497 \f
2498 DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
2499 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
2500 Each of the three load averages is multiplied by 100,\n\
2501 then converted to integer.\n\
2502 When USE-FLOATS is non-nil, floats will be used instead of integers.\n\
2503 These floats are not multiplied by 100.\n\n\
2504 If the 5-minute or 15-minute load averages are not available, return a\n\
2505 shortened list, containing only those averages which are available.")
2506 (use_floats)
2507 Lisp_Object use_floats;
2508 {
2509 double load_ave[3];
2510 int loads = getloadavg (load_ave, 3);
2511 Lisp_Object ret = Qnil;
2512
2513 if (loads < 0)
2514 error ("load-average not implemented for this operating system");
2515
2516 while (loads-- > 0)
2517 {
2518 Lisp_Object load = (NILP (use_floats) ?
2519 make_number ((int) (100.0 * load_ave[loads]))
2520 : make_float (load_ave[loads]));
2521 ret = Fcons (load, ret);
2522 }
2523
2524 return ret;
2525 }
2526 \f
2527 Lisp_Object Vfeatures;
2528
2529 DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
2530 "Returns t if FEATURE is present in this Emacs.\n\
2531 Use this to conditionalize execution of lisp code based on the presence or\n\
2532 absence of emacs or environment extensions.\n\
2533 Use `provide' to declare that a feature is available.\n\
2534 This function looks at the value of the variable `features'.")
2535 (feature)
2536 Lisp_Object feature;
2537 {
2538 register Lisp_Object tem;
2539 CHECK_SYMBOL (feature, 0);
2540 tem = Fmemq (feature, Vfeatures);
2541 return (NILP (tem)) ? Qnil : Qt;
2542 }
2543
2544 DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
2545 "Announce that FEATURE is a feature of the current Emacs.")
2546 (feature)
2547 Lisp_Object feature;
2548 {
2549 register Lisp_Object tem;
2550 CHECK_SYMBOL (feature, 0);
2551 if (!NILP (Vautoload_queue))
2552 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
2553 tem = Fmemq (feature, Vfeatures);
2554 if (NILP (tem))
2555 Vfeatures = Fcons (feature, Vfeatures);
2556 LOADHIST_ATTACH (Fcons (Qprovide, feature));
2557 return feature;
2558 }
2559
2560 DEFUN ("require", Frequire, Srequire, 1, 2, 0,
2561 "If feature FEATURE is not loaded, load it from FILENAME.\n\
2562 If FEATURE is not a member of the list `features', then the feature\n\
2563 is not loaded; so load the file FILENAME.\n\
2564 If FILENAME is omitted, the printname of FEATURE is used as the file name,\n\
2565 but in this case `load' insists on adding the suffix `.el' or `.elc'.")
2566 (feature, file_name)
2567 Lisp_Object feature, file_name;
2568 {
2569 register Lisp_Object tem;
2570 CHECK_SYMBOL (feature, 0);
2571 tem = Fmemq (feature, Vfeatures);
2572 LOADHIST_ATTACH (Fcons (Qrequire, feature));
2573 if (NILP (tem))
2574 {
2575 int count = specpdl_ptr - specpdl;
2576
2577 /* Value saved here is to be restored into Vautoload_queue */
2578 record_unwind_protect (un_autoload, Vautoload_queue);
2579 Vautoload_queue = Qt;
2580
2581 Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
2582 Qnil, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
2583
2584 tem = Fmemq (feature, Vfeatures);
2585 if (NILP (tem))
2586 error ("Required feature %s was not provided",
2587 XSYMBOL (feature)->name->data);
2588
2589 /* Once loading finishes, don't undo it. */
2590 Vautoload_queue = Qt;
2591 feature = unbind_to (count, feature);
2592 }
2593 return feature;
2594 }
2595 \f
2596 /* Primitives for work of the "widget" library.
2597 In an ideal world, this section would not have been necessary.
2598 However, lisp function calls being as slow as they are, it turns
2599 out that some functions in the widget library (wid-edit.el) are the
2600 bottleneck of Widget operation. Here is their translation to C,
2601 for the sole reason of efficiency. */
2602
2603 DEFUN ("widget-plist-member", Fwidget_plist_member, Swidget_plist_member, 2, 2, 0,
2604 "Return non-nil if PLIST has the property PROP.\n\
2605 PLIST is a property list, which is a list of the form\n\
2606 \(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
2607 Unlike `plist-get', this allows you to distinguish between a missing\n\
2608 property and a property with the value nil.\n\
2609 The value is actually the tail of PLIST whose car is PROP.")
2610 (plist, prop)
2611 Lisp_Object plist, prop;
2612 {
2613 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2614 {
2615 QUIT;
2616 plist = XCDR (plist);
2617 plist = CDR (plist);
2618 }
2619 return plist;
2620 }
2621
2622 DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
2623 "In WIDGET, set PROPERTY to VALUE.\n\
2624 The value can later be retrieved with `widget-get'.")
2625 (widget, property, value)
2626 Lisp_Object widget, property, value;
2627 {
2628 CHECK_CONS (widget, 1);
2629 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
2630 }
2631
2632 DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
2633 "In WIDGET, get the value of PROPERTY.\n\
2634 The value could either be specified when the widget was created, or\n\
2635 later with `widget-put'.")
2636 (widget, property)
2637 Lisp_Object widget, property;
2638 {
2639 Lisp_Object tmp;
2640
2641 while (1)
2642 {
2643 if (NILP (widget))
2644 return Qnil;
2645 CHECK_CONS (widget, 1);
2646 tmp = Fwidget_plist_member (XCDR (widget), property);
2647 if (CONSP (tmp))
2648 {
2649 tmp = XCDR (tmp);
2650 return CAR (tmp);
2651 }
2652 tmp = XCAR (widget);
2653 if (NILP (tmp))
2654 return Qnil;
2655 widget = Fget (tmp, Qwidget_type);
2656 }
2657 }
2658
2659 DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
2660 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
2661 ARGS are passed as extra arguments to the function.")
2662 (nargs, args)
2663 int nargs;
2664 Lisp_Object *args;
2665 {
2666 /* This function can GC. */
2667 Lisp_Object newargs[3];
2668 struct gcpro gcpro1, gcpro2;
2669 Lisp_Object result;
2670
2671 newargs[0] = Fwidget_get (args[0], args[1]);
2672 newargs[1] = args[0];
2673 newargs[2] = Flist (nargs - 2, args + 2);
2674 GCPRO2 (newargs[0], newargs[2]);
2675 result = Fapply (3, newargs);
2676 UNGCPRO;
2677 return result;
2678 }
2679 \f
2680 void
2681 syms_of_fns ()
2682 {
2683 Qstring_lessp = intern ("string-lessp");
2684 staticpro (&Qstring_lessp);
2685 Qprovide = intern ("provide");
2686 staticpro (&Qprovide);
2687 Qrequire = intern ("require");
2688 staticpro (&Qrequire);
2689 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
2690 staticpro (&Qyes_or_no_p_history);
2691 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
2692 staticpro (&Qcursor_in_echo_area);
2693 Qwidget_type = intern ("widget-type");
2694 staticpro (&Qwidget_type);
2695
2696 staticpro (&string_char_byte_cache_string);
2697 string_char_byte_cache_string = Qnil;
2698
2699 Fset (Qyes_or_no_p_history, Qnil);
2700
2701 DEFVAR_LISP ("features", &Vfeatures,
2702 "A list of symbols which are the features of the executing emacs.\n\
2703 Used by `featurep' and `require', and altered by `provide'.");
2704 Vfeatures = Qnil;
2705
2706 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
2707 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
2708 This applies to y-or-n and yes-or-no questions asked by commands\n\
2709 invoked by mouse clicks and mouse menu items.");
2710 use_dialog_box = 1;
2711
2712 defsubr (&Sidentity);
2713 defsubr (&Srandom);
2714 defsubr (&Slength);
2715 defsubr (&Ssafe_length);
2716 defsubr (&Sstring_bytes);
2717 defsubr (&Sstring_equal);
2718 defsubr (&Scompare_strings);
2719 defsubr (&Sstring_lessp);
2720 defsubr (&Sappend);
2721 defsubr (&Sconcat);
2722 defsubr (&Svconcat);
2723 defsubr (&Scopy_sequence);
2724 defsubr (&Sstring_make_multibyte);
2725 defsubr (&Sstring_make_unibyte);
2726 defsubr (&Sstring_as_multibyte);
2727 defsubr (&Sstring_as_unibyte);
2728 defsubr (&Scopy_alist);
2729 defsubr (&Ssubstring);
2730 defsubr (&Snthcdr);
2731 defsubr (&Snth);
2732 defsubr (&Selt);
2733 defsubr (&Smember);
2734 defsubr (&Smemq);
2735 defsubr (&Sassq);
2736 defsubr (&Sassoc);
2737 defsubr (&Srassq);
2738 defsubr (&Srassoc);
2739 defsubr (&Sdelq);
2740 defsubr (&Sdelete);
2741 defsubr (&Snreverse);
2742 defsubr (&Sreverse);
2743 defsubr (&Ssort);
2744 defsubr (&Splist_get);
2745 defsubr (&Sget);
2746 defsubr (&Splist_put);
2747 defsubr (&Sput);
2748 defsubr (&Sequal);
2749 defsubr (&Sfillarray);
2750 defsubr (&Schar_table_subtype);
2751 defsubr (&Schar_table_parent);
2752 defsubr (&Sset_char_table_parent);
2753 defsubr (&Schar_table_extra_slot);
2754 defsubr (&Sset_char_table_extra_slot);
2755 defsubr (&Schar_table_range);
2756 defsubr (&Sset_char_table_range);
2757 defsubr (&Sset_char_table_default);
2758 defsubr (&Smap_char_table);
2759 defsubr (&Snconc);
2760 defsubr (&Smapcar);
2761 defsubr (&Smapconcat);
2762 defsubr (&Sy_or_n_p);
2763 defsubr (&Syes_or_no_p);
2764 defsubr (&Sload_average);
2765 defsubr (&Sfeaturep);
2766 defsubr (&Srequire);
2767 defsubr (&Sprovide);
2768 defsubr (&Swidget_plist_member);
2769 defsubr (&Swidget_put);
2770 defsubr (&Swidget_get);
2771 defsubr (&Swidget_apply);
2772 }