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