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