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