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