(displayed_window_lines): Take empty lines at
[bpt/emacs.git] / src / fns.c
CommitLineData
7b863bd5 1/* Random utility Lisp functions.
f5c75033 2 Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 98, 99, 2000 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
58edb572 27#include <time.h>
dfcf069d 28
7b863bd5
JB
29/* Note on some machines this defines `vector' as a typedef,
30 so make sure we don't use that name in this file. */
31#undef vector
32#define vector *****
33
7b863bd5
JB
34#include "lisp.h"
35#include "commands.h"
a8283a4a 36#include "charset.h"
7b863bd5 37
7b863bd5 38#include "buffer.h"
f812877e 39#include "keyboard.h"
ac811a55 40#include "intervals.h"
2d8e7e1f
RS
41#include "frame.h"
42#include "window.h"
d73c6532 43#if defined (HAVE_MENUS) && defined (HAVE_X_WINDOWS)
dfcf069d
AS
44#include "xterm.h"
45#endif
7b863bd5 46
bc937db7
KH
47#ifndef NULL
48#define NULL (void *)0
49#endif
50
d80c6c11
GM
51#ifndef min
52#define min(a, b) ((a) < (b) ? (a) : (b))
53#define max(a, b) ((a) > (b) ? (a) : (b))
54#endif
55
bdd8d692
RS
56/* Nonzero enables use of dialog boxes for questions
57 asked by mouse commands. */
58int use_dialog_box;
59
2d8e7e1f
RS
60extern int minibuffer_auto_raise;
61extern Lisp_Object minibuf_window;
62
68732608 63Lisp_Object Qstring_lessp, Qprovide, Qrequire;
0ce830bc 64Lisp_Object Qyes_or_no_p_history;
eb4ffa4e 65Lisp_Object Qcursor_in_echo_area;
b4f334f7 66Lisp_Object Qwidget_type;
7b863bd5 67
3844ee44
RS
68extern Lisp_Object Qinput_method_function;
69
6cb9cafb 70static int internal_equal ();
49bdcd3e
RS
71
72extern long get_random ();
73extern void seed_random ();
74
75#ifndef HAVE_UNISTD_H
76extern long time ();
77#endif
e0f5cf5a 78\f
7b863bd5
JB
79DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
80 "Return the argument unchanged.")
81 (arg)
82 Lisp_Object arg;
83{
84 return arg;
85}
86
87DEFUN ("random", Frandom, Srandom, 0, 1, 0,
88 "Return a pseudo-random number.\n\
4cab5074
KH
89All integers representable in Lisp are equally likely.\n\
90 On most systems, this is 28 bits' worth.\n\
99175c23 91With positive integer argument N, return random number in interval [0,N).\n\
7b863bd5 92With argument t, set the random number seed from the current time and pid.")
88fe8140
EN
93 (n)
94 Lisp_Object n;
7b863bd5 95{
e2d6972a
KH
96 EMACS_INT val;
97 Lisp_Object lispy_val;
78217ef1 98 unsigned long denominator;
7b863bd5 99
88fe8140 100 if (EQ (n, Qt))
e2d6972a 101 seed_random (getpid () + time (NULL));
88fe8140 102 if (NATNUMP (n) && XFASTINT (n) != 0)
7b863bd5 103 {
4cab5074
KH
104 /* Try to take our random number from the higher bits of VAL,
105 not the lower, since (says Gentzel) the low bits of `random'
106 are less random than the higher ones. We do this by using the
107 quotient rather than the remainder. At the high end of the RNG
88fe8140 108 it's possible to get a quotient larger than n; discarding
4cab5074 109 these values eliminates the bias that would otherwise appear
88fe8140
EN
110 when using a large n. */
111 denominator = ((unsigned long)1 << VALBITS) / XFASTINT (n);
4cab5074 112 do
99175c23 113 val = get_random () / denominator;
88fe8140 114 while (val >= XFASTINT (n));
7b863bd5 115 }
78217ef1 116 else
99175c23 117 val = get_random ();
e2d6972a
KH
118 XSETINT (lispy_val, val);
119 return lispy_val;
7b863bd5
JB
120}
121\f
122/* Random data-structure functions */
123
124DEFUN ("length", Flength, Slength, 1, 1, 0,
125 "Return the length of vector, list or string SEQUENCE.\n\
0c57d6fd
RS
126A byte-code function object is also allowed.\n\
127If the string contains multibyte characters, this is not the necessarily\n\
96ced23c
AS
128the number of bytes in the string; it is the number of characters.\n\
129To get the number of bytes, use `string-bytes'")
88fe8140
EN
130 (sequence)
131 register Lisp_Object sequence;
7b863bd5
JB
132{
133 register Lisp_Object tail, val;
134 register int i;
135
136 retry:
88fe8140
EN
137 if (STRINGP (sequence))
138 XSETFASTINT (val, XSTRING (sequence)->size);
139 else if (VECTORP (sequence))
140 XSETFASTINT (val, XVECTOR (sequence)->size);
141 else if (CHAR_TABLE_P (sequence))
64a5094a 142 XSETFASTINT (val, MAX_CHAR);
88fe8140
EN
143 else if (BOOL_VECTOR_P (sequence))
144 XSETFASTINT (val, XBOOL_VECTOR (sequence)->size);
145 else if (COMPILEDP (sequence))
146 XSETFASTINT (val, XVECTOR (sequence)->size & PSEUDOVECTOR_SIZE_MASK);
147 else if (CONSP (sequence))
7b863bd5 148 {
7843e09c
GM
149 i = 0;
150 while (CONSP (sequence))
7b863bd5 151 {
f2be3671 152 sequence = XCDR (sequence);
7843e09c
GM
153 ++i;
154
155 if (!CONSP (sequence))
156 break;
157
158 sequence = XCDR (sequence);
159 ++i;
160 QUIT;
7b863bd5
JB
161 }
162
f2be3671
GM
163 if (!NILP (sequence))
164 wrong_type_argument (Qlistp, sequence);
165
166 val = make_number (i);
7b863bd5 167 }
88fe8140 168 else if (NILP (sequence))
a2ad3e19 169 XSETFASTINT (val, 0);
7b863bd5
JB
170 else
171 {
88fe8140 172 sequence = wrong_type_argument (Qsequencep, sequence);
7b863bd5
JB
173 goto retry;
174 }
a2ad3e19 175 return val;
7b863bd5
JB
176}
177
5a30fab8
RS
178/* This does not check for quits. That is safe
179 since it must terminate. */
180
181DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
182 "Return the length of a list, but avoid error or infinite loop.\n\
183This function never gets an error. If LIST is not really a list,\n\
184it returns 0. If LIST is circular, it returns a finite value\n\
185which is at least the number of distinct elements.")
b4f334f7 186 (list)
5a30fab8
RS
187 Lisp_Object list;
188{
189 Lisp_Object tail, halftail, length;
190 int len = 0;
191
192 /* halftail is used to detect circular lists. */
193 halftail = list;
70949dac 194 for (tail = list; CONSP (tail); tail = XCDR (tail))
5a30fab8
RS
195 {
196 if (EQ (tail, halftail) && len != 0)
cb3d1a0a 197 break;
5a30fab8 198 len++;
3a61aeb4 199 if ((len & 1) == 0)
70949dac 200 halftail = XCDR (halftail);
5a30fab8
RS
201 }
202
203 XSETINT (length, len);
204 return length;
205}
206
026f59ce
RS
207DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
208 "Return the number of bytes in STRING.\n\
209If STRING is a multibyte string, this is greater than the length of STRING.")
210 (string)
eaf17c6b 211 Lisp_Object string;
026f59ce
RS
212{
213 CHECK_STRING (string, 1);
fc932ac6 214 return make_number (STRING_BYTES (XSTRING (string)));
026f59ce
RS
215}
216
7b863bd5 217DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
ea35ce3d 218 "Return t if two strings have identical contents.\n\
76d0f732 219Case is significant, but text properties are ignored.\n\
7b863bd5
JB
220Symbols are also allowed; their print names are used instead.")
221 (s1, s2)
222 register Lisp_Object s1, s2;
223{
7650760e 224 if (SYMBOLP (s1))
b2791413 225 XSETSTRING (s1, XSYMBOL (s1)->name);
7650760e 226 if (SYMBOLP (s2))
b2791413 227 XSETSTRING (s2, XSYMBOL (s2)->name);
7b863bd5
JB
228 CHECK_STRING (s1, 0);
229 CHECK_STRING (s2, 1);
230
ea35ce3d 231 if (XSTRING (s1)->size != XSTRING (s2)->size
fc932ac6
RS
232 || STRING_BYTES (XSTRING (s1)) != STRING_BYTES (XSTRING (s2))
233 || bcmp (XSTRING (s1)->data, XSTRING (s2)->data, STRING_BYTES (XSTRING (s1))))
7b863bd5
JB
234 return Qnil;
235 return Qt;
236}
237
0e1e9f8d 238DEFUN ("compare-strings", Fcompare_strings,
f95837d0 239 Scompare_strings, 6, 7, 0,
0e1e9f8d
RS
240 "Compare the contents of two strings, converting to multibyte if needed.\n\
241In string STR1, skip the first START1 characters and stop at END1.\n\
242In string STR2, skip the first START2 characters and stop at END2.\n\
d68cc14c
RS
243END1 and END2 default to the full lengths of the respective strings.\n\
244\n\
0e1e9f8d
RS
245Case is significant in this comparison if IGNORE-CASE is nil.\n\
246Unibyte strings are converted to multibyte for comparison.\n\
247\n\
248The value is t if the strings (or specified portions) match.\n\
249If string STR1 is less, the value is a negative number N;\n\
250 - 1 - N is the number of characters that match at the beginning.\n\
251If string STR1 is greater, the value is a positive number N;\n\
252 N - 1 is the number of characters that match at the beginning.")
253 (str1, start1, end1, str2, start2, end2, ignore_case)
254 Lisp_Object str1, start1, end1, start2, str2, end2, ignore_case;
255{
256 register int end1_char, end2_char;
257 register int i1, i1_byte, i2, i2_byte;
258
259 CHECK_STRING (str1, 0);
260 CHECK_STRING (str2, 1);
261 if (NILP (start1))
262 start1 = make_number (0);
263 if (NILP (start2))
264 start2 = make_number (0);
265 CHECK_NATNUM (start1, 2);
266 CHECK_NATNUM (start2, 3);
267 if (! NILP (end1))
268 CHECK_NATNUM (end1, 4);
269 if (! NILP (end2))
270 CHECK_NATNUM (end2, 4);
271
272 i1 = XINT (start1);
273 i2 = XINT (start2);
274
275 i1_byte = string_char_to_byte (str1, i1);
276 i2_byte = string_char_to_byte (str2, i2);
277
278 end1_char = XSTRING (str1)->size;
279 if (! NILP (end1) && end1_char > XINT (end1))
280 end1_char = XINT (end1);
281
282 end2_char = XSTRING (str2)->size;
283 if (! NILP (end2) && end2_char > XINT (end2))
284 end2_char = XINT (end2);
285
286 while (i1 < end1_char && i2 < end2_char)
287 {
288 /* When we find a mismatch, we must compare the
289 characters, not just the bytes. */
290 int c1, c2;
291
292 if (STRING_MULTIBYTE (str1))
2efdd1b9 293 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c1, str1, i1, i1_byte);
0e1e9f8d
RS
294 else
295 {
296 c1 = XSTRING (str1)->data[i1++];
297 c1 = unibyte_char_to_multibyte (c1);
298 }
299
300 if (STRING_MULTIBYTE (str2))
2efdd1b9 301 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c2, str2, i2, i2_byte);
0e1e9f8d
RS
302 else
303 {
304 c2 = XSTRING (str2)->data[i2++];
305 c2 = unibyte_char_to_multibyte (c2);
306 }
307
308 if (c1 == c2)
309 continue;
310
311 if (! NILP (ignore_case))
312 {
313 Lisp_Object tem;
314
315 tem = Fupcase (make_number (c1));
316 c1 = XINT (tem);
317 tem = Fupcase (make_number (c2));
318 c2 = XINT (tem);
319 }
320
321 if (c1 == c2)
322 continue;
323
324 /* Note that I1 has already been incremented
325 past the character that we are comparing;
326 hence we don't add or subtract 1 here. */
327 if (c1 < c2)
328 return make_number (- i1);
329 else
330 return make_number (i1);
331 }
332
333 if (i1 < end1_char)
334 return make_number (i1 - XINT (start1) + 1);
335 if (i2 < end2_char)
336 return make_number (- i1 + XINT (start1) - 1);
337
338 return Qt;
339}
340
7b863bd5 341DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
ea35ce3d 342 "Return t if first arg string is less than second in lexicographic order.\n\
7b863bd5
JB
343Case is significant.\n\
344Symbols are also allowed; their print names are used instead.")
345 (s1, s2)
346 register Lisp_Object s1, s2;
347{
7b863bd5 348 register int end;
09ab3c3b 349 register int i1, i1_byte, i2, i2_byte;
7b863bd5 350
7650760e 351 if (SYMBOLP (s1))
b2791413 352 XSETSTRING (s1, XSYMBOL (s1)->name);
7650760e 353 if (SYMBOLP (s2))
b2791413 354 XSETSTRING (s2, XSYMBOL (s2)->name);
7b863bd5
JB
355 CHECK_STRING (s1, 0);
356 CHECK_STRING (s2, 1);
357
09ab3c3b
KH
358 i1 = i1_byte = i2 = i2_byte = 0;
359
360 end = XSTRING (s1)->size;
361 if (end > XSTRING (s2)->size)
362 end = XSTRING (s2)->size;
7b863bd5 363
09ab3c3b 364 while (i1 < end)
7b863bd5 365 {
09ab3c3b
KH
366 /* When we find a mismatch, we must compare the
367 characters, not just the bytes. */
368 int c1, c2;
369
2efdd1b9
KH
370 FETCH_STRING_CHAR_ADVANCE (c1, s1, i1, i1_byte);
371 FETCH_STRING_CHAR_ADVANCE (c2, s2, i2, i2_byte);
09ab3c3b
KH
372
373 if (c1 != c2)
374 return c1 < c2 ? Qt : Qnil;
7b863bd5 375 }
09ab3c3b 376 return i1 < XSTRING (s2)->size ? Qt : Qnil;
7b863bd5
JB
377}
378\f
379static Lisp_Object concat ();
380
381/* ARGSUSED */
382Lisp_Object
383concat2 (s1, s2)
384 Lisp_Object s1, s2;
385{
386#ifdef NO_ARG_ARRAY
387 Lisp_Object args[2];
388 args[0] = s1;
389 args[1] = s2;
390 return concat (2, args, Lisp_String, 0);
391#else
392 return concat (2, &s1, Lisp_String, 0);
393#endif /* NO_ARG_ARRAY */
394}
395
d4af3687
RS
396/* ARGSUSED */
397Lisp_Object
398concat3 (s1, s2, s3)
399 Lisp_Object s1, s2, s3;
400{
401#ifdef NO_ARG_ARRAY
402 Lisp_Object args[3];
403 args[0] = s1;
404 args[1] = s2;
405 args[2] = s3;
406 return concat (3, args, Lisp_String, 0);
407#else
408 return concat (3, &s1, Lisp_String, 0);
409#endif /* NO_ARG_ARRAY */
410}
411
7b863bd5
JB
412DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
413 "Concatenate all the arguments and make the result a list.\n\
414The result is a list whose elements are the elements of all the arguments.\n\
415Each argument may be a list, vector or string.\n\
aec1184c 416The last argument is not copied, just used as the tail of the new list.")
7b863bd5
JB
417 (nargs, args)
418 int nargs;
419 Lisp_Object *args;
420{
421 return concat (nargs, args, Lisp_Cons, 1);
422}
423
424DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
425 "Concatenate all the arguments and make the result a string.\n\
426The result is a string whose elements are the elements of all the arguments.\n\
5c6740c9 427Each argument may be a string or a list or vector of characters (integers).")
7b863bd5
JB
428 (nargs, args)
429 int nargs;
430 Lisp_Object *args;
431{
432 return concat (nargs, args, Lisp_String, 0);
433}
434
435DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
436 "Concatenate all the arguments and make the result a vector.\n\
437The result is a vector whose elements are the elements of all the arguments.\n\
438Each argument may be a list, vector or string.")
439 (nargs, args)
440 int nargs;
441 Lisp_Object *args;
442{
3e7383eb 443 return concat (nargs, args, Lisp_Vectorlike, 0);
7b863bd5
JB
444}
445
3720677d
KH
446/* Retrun a copy of a sub char table ARG. The elements except for a
447 nested sub char table are not copied. */
448static Lisp_Object
449copy_sub_char_table (arg)
e1335ba2 450 Lisp_Object arg;
3720677d
KH
451{
452 Lisp_Object copy = make_sub_char_table (XCHAR_TABLE (arg)->defalt);
453 int i;
454
455 /* Copy all the contents. */
456 bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
457 SUB_CHAR_TABLE_ORDINARY_SLOTS * sizeof (Lisp_Object));
458 /* Recursively copy any sub char-tables in the ordinary slots. */
459 for (i = 32; i < SUB_CHAR_TABLE_ORDINARY_SLOTS; i++)
460 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
461 XCHAR_TABLE (copy)->contents[i]
462 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
463
464 return copy;
465}
466
467
7b863bd5
JB
468DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
469 "Return a copy of a list, vector or string.\n\
470The elements of a list or vector are not copied; they are shared\n\
471with the original.")
472 (arg)
473 Lisp_Object arg;
474{
265a9e55 475 if (NILP (arg)) return arg;
e03f7933
RS
476
477 if (CHAR_TABLE_P (arg))
478 {
25c30748 479 int i;
e03f7933
RS
480 Lisp_Object copy;
481
c8640abf 482 copy = Fmake_char_table (XCHAR_TABLE (arg)->purpose, Qnil);
e03f7933 483 /* Copy all the slots, including the extra ones. */
69b3a14b 484 bcopy (XVECTOR (arg)->contents, XVECTOR (copy)->contents,
25c30748
KH
485 ((XCHAR_TABLE (arg)->size & PSEUDOVECTOR_SIZE_MASK)
486 * sizeof (Lisp_Object)));
e03f7933 487
3720677d
KH
488 /* Recursively copy any sub char tables in the ordinary slots
489 for multibyte characters. */
490 for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS;
491 i < CHAR_TABLE_ORDINARY_SLOTS; i++)
492 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
e03f7933 493 XCHAR_TABLE (copy)->contents[i]
3720677d 494 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
e03f7933
RS
495
496 return copy;
497 }
498
499 if (BOOL_VECTOR_P (arg))
500 {
501 Lisp_Object val;
e03f7933 502 int size_in_chars
e22e4283 503 = (XBOOL_VECTOR (arg)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
504
505 val = Fmake_bool_vector (Flength (arg), Qnil);
506 bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
507 size_in_chars);
508 return val;
509 }
510
7650760e 511 if (!CONSP (arg) && !VECTORP (arg) && !STRINGP (arg))
7b863bd5
JB
512 arg = wrong_type_argument (Qsequencep, arg);
513 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
514}
515
2d6115c8
KH
516/* In string STR of length LEN, see if bytes before STR[I] combine
517 with bytes after STR[I] to form a single character. If so, return
518 the number of bytes after STR[I] which combine in this way.
519 Otherwize, return 0. */
520
521static int
522count_combining (str, len, i)
523 unsigned char *str;
524 int len, i;
525{
e50d9192 526 int j = i - 1, bytes;
2d6115c8
KH
527
528 if (i == 0 || i == len || CHAR_HEAD_P (str[i]))
529 return 0;
530 while (j >= 0 && !CHAR_HEAD_P (str[j])) j--;
531 if (j < 0 || ! BASE_LEADING_CODE_P (str[j]))
532 return 0;
e50d9192
KH
533 PARSE_MULTIBYTE_SEQ (str + j, len - j, bytes);
534 return (bytes <= i - j ? 0 : bytes - (i - j));
2d6115c8
KH
535}
536
537/* This structure holds information of an argument of `concat' that is
538 a string and has text properties to be copied. */
87f0532f 539struct textprop_rec
2d6115c8
KH
540{
541 int argnum; /* refer to ARGS (arguments of `concat') */
542 int from; /* refer to ARGS[argnum] (argument string) */
543 int to; /* refer to VAL (the target string) */
544};
545
7b863bd5
JB
546static Lisp_Object
547concat (nargs, args, target_type, last_special)
548 int nargs;
549 Lisp_Object *args;
550 enum Lisp_Type target_type;
551 int last_special;
552{
553 Lisp_Object val;
7b863bd5
JB
554 register Lisp_Object tail;
555 register Lisp_Object this;
556 int toindex;
ea35ce3d
RS
557 int toindex_byte;
558 register int result_len;
559 register int result_len_byte;
7b863bd5
JB
560 register int argnum;
561 Lisp_Object last_tail;
562 Lisp_Object prev;
ea35ce3d 563 int some_multibyte;
2d6115c8
KH
564 /* When we make a multibyte string, we can't copy text properties
565 while concatinating each string because the length of resulting
566 string can't be decided until we finish the whole concatination.
567 So, we record strings that have text properties to be copied
568 here, and copy the text properties after the concatination. */
87f0532f
KH
569 struct textprop_rec *textprops;
570 /* Number of elments in textprops. */
571 int num_textprops = 0;
7b863bd5
JB
572
573 /* In append, the last arg isn't treated like the others */
574 if (last_special && nargs > 0)
575 {
576 nargs--;
577 last_tail = args[nargs];
578 }
579 else
580 last_tail = Qnil;
581
ea35ce3d 582 /* Canonicalize each argument. */
7b863bd5
JB
583 for (argnum = 0; argnum < nargs; argnum++)
584 {
585 this = args[argnum];
7650760e 586 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
e03f7933 587 || COMPILEDP (this) || BOOL_VECTOR_P (this)))
7b863bd5 588 {
7b863bd5
JB
589 args[argnum] = wrong_type_argument (Qsequencep, this);
590 }
591 }
592
ea35ce3d
RS
593 /* Compute total length in chars of arguments in RESULT_LEN.
594 If desired output is a string, also compute length in bytes
595 in RESULT_LEN_BYTE, and determine in SOME_MULTIBYTE
596 whether the result should be a multibyte string. */
597 result_len_byte = 0;
598 result_len = 0;
599 some_multibyte = 0;
600 for (argnum = 0; argnum < nargs; argnum++)
7b863bd5 601 {
ea35ce3d 602 int len;
7b863bd5 603 this = args[argnum];
ea35ce3d
RS
604 len = XFASTINT (Flength (this));
605 if (target_type == Lisp_String)
5b6dddaa 606 {
09ab3c3b
KH
607 /* We must count the number of bytes needed in the string
608 as well as the number of characters. */
5b6dddaa
KH
609 int i;
610 Lisp_Object ch;
ea35ce3d 611 int this_len_byte;
5b6dddaa 612
dec58e65 613 if (VECTORP (this))
ea35ce3d 614 for (i = 0; i < len; i++)
dec58e65
KH
615 {
616 ch = XVECTOR (this)->contents[i];
617 if (! INTEGERP (ch))
618 wrong_type_argument (Qintegerp, ch);
cc531c44 619 this_len_byte = CHAR_BYTES (XINT (ch));
ea35ce3d 620 result_len_byte += this_len_byte;
2efdd1b9 621 if (!SINGLE_BYTE_CHAR_P (XINT (ch)))
ea35ce3d 622 some_multibyte = 1;
dec58e65 623 }
6d475204
RS
624 else if (BOOL_VECTOR_P (this) && XBOOL_VECTOR (this)->size > 0)
625 wrong_type_argument (Qintegerp, Faref (this, make_number (0)));
ea35ce3d 626 else if (CONSP (this))
70949dac 627 for (; CONSP (this); this = XCDR (this))
dec58e65 628 {
70949dac 629 ch = XCAR (this);
dec58e65
KH
630 if (! INTEGERP (ch))
631 wrong_type_argument (Qintegerp, ch);
cc531c44 632 this_len_byte = CHAR_BYTES (XINT (ch));
ea35ce3d 633 result_len_byte += this_len_byte;
2efdd1b9 634 if (!SINGLE_BYTE_CHAR_P (XINT (ch)))
ea35ce3d 635 some_multibyte = 1;
dec58e65 636 }
470730a8 637 else if (STRINGP (this))
ea35ce3d 638 {
06f57aa7 639 if (STRING_MULTIBYTE (this))
09ab3c3b
KH
640 {
641 some_multibyte = 1;
fc932ac6 642 result_len_byte += STRING_BYTES (XSTRING (this));
09ab3c3b
KH
643 }
644 else
645 result_len_byte += count_size_as_multibyte (XSTRING (this)->data,
646 XSTRING (this)->size);
ea35ce3d 647 }
5b6dddaa 648 }
ea35ce3d
RS
649
650 result_len += len;
7b863bd5
JB
651 }
652
09ab3c3b
KH
653 if (! some_multibyte)
654 result_len_byte = result_len;
7b863bd5 655
ea35ce3d 656 /* Create the output object. */
7b863bd5 657 if (target_type == Lisp_Cons)
ea35ce3d 658 val = Fmake_list (make_number (result_len), Qnil);
3e7383eb 659 else if (target_type == Lisp_Vectorlike)
ea35ce3d 660 val = Fmake_vector (make_number (result_len), Qnil);
b10b2daa 661 else if (some_multibyte)
ea35ce3d 662 val = make_uninit_multibyte_string (result_len, result_len_byte);
b10b2daa
RS
663 else
664 val = make_uninit_string (result_len);
7b863bd5 665
09ab3c3b
KH
666 /* In `append', if all but last arg are nil, return last arg. */
667 if (target_type == Lisp_Cons && EQ (val, Qnil))
668 return last_tail;
7b863bd5 669
ea35ce3d 670 /* Copy the contents of the args into the result. */
7b863bd5 671 if (CONSP (val))
2d6115c8 672 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
7b863bd5 673 else
ea35ce3d 674 toindex = 0, toindex_byte = 0;
7b863bd5
JB
675
676 prev = Qnil;
2d6115c8 677 if (STRINGP (val))
87f0532f
KH
678 textprops
679 = (struct textprop_rec *) alloca (sizeof (struct textprop_rec) * nargs);
7b863bd5
JB
680
681 for (argnum = 0; argnum < nargs; argnum++)
682 {
683 Lisp_Object thislen;
684 int thisleni;
de712da3 685 register unsigned int thisindex = 0;
ea35ce3d 686 register unsigned int thisindex_byte = 0;
7b863bd5
JB
687
688 this = args[argnum];
689 if (!CONSP (this))
690 thislen = Flength (this), thisleni = XINT (thislen);
691
ea35ce3d
RS
692 /* Between strings of the same kind, copy fast. */
693 if (STRINGP (this) && STRINGP (val)
694 && STRING_MULTIBYTE (this) == some_multibyte)
7b863bd5 695 {
fc932ac6 696 int thislen_byte = STRING_BYTES (XSTRING (this));
2d6115c8
KH
697 int combined;
698
ea35ce3d 699 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
fc932ac6 700 STRING_BYTES (XSTRING (this)));
2d6115c8
KH
701 combined = (some_multibyte && toindex_byte > 0
702 ? count_combining (XSTRING (val)->data,
703 toindex_byte + thislen_byte,
704 toindex_byte)
705 : 0);
706 if (! NULL_INTERVAL_P (XSTRING (this)->intervals))
707 {
87f0532f 708 textprops[num_textprops].argnum = argnum;
2d6115c8 709 /* We ignore text properties on characters being combined. */
87f0532f
KH
710 textprops[num_textprops].from = combined;
711 textprops[num_textprops++].to = toindex;
2d6115c8 712 }
ea35ce3d 713 toindex_byte += thislen_byte;
2d6115c8
KH
714 toindex += thisleni - combined;
715 XSTRING (val)->size -= combined;
ea35ce3d 716 }
09ab3c3b
KH
717 /* Copy a single-byte string to a multibyte string. */
718 else if (STRINGP (this) && STRINGP (val))
719 {
2d6115c8
KH
720 if (! NULL_INTERVAL_P (XSTRING (this)->intervals))
721 {
87f0532f
KH
722 textprops[num_textprops].argnum = argnum;
723 textprops[num_textprops].from = 0;
724 textprops[num_textprops++].to = toindex;
2d6115c8 725 }
09ab3c3b
KH
726 toindex_byte += copy_text (XSTRING (this)->data,
727 XSTRING (val)->data + toindex_byte,
728 XSTRING (this)->size, 0, 1);
729 toindex += thisleni;
730 }
ea35ce3d
RS
731 else
732 /* Copy element by element. */
733 while (1)
734 {
735 register Lisp_Object elt;
736
737 /* Fetch next element of `this' arg into `elt', or break if
738 `this' is exhausted. */
739 if (NILP (this)) break;
740 if (CONSP (this))
70949dac 741 elt = XCAR (this), this = XCDR (this);
6a7df83b
RS
742 else if (thisindex >= thisleni)
743 break;
744 else if (STRINGP (this))
ea35ce3d 745 {
2cef5737 746 int c;
6a7df83b 747 if (STRING_MULTIBYTE (this))
ea35ce3d 748 {
2efdd1b9
KH
749 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, this,
750 thisindex,
751 thisindex_byte);
6a7df83b 752 XSETFASTINT (elt, c);
ea35ce3d 753 }
6a7df83b 754 else
ea35ce3d 755 {
6a7df83b 756 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
e0e25273
KH
757 if (some_multibyte
758 && (XINT (elt) >= 0240
f9638719
EZ
759 || (XINT (elt) >= 0200
760 && ! NILP (Vnonascii_translation_table)))
6a7df83b
RS
761 && XINT (elt) < 0400)
762 {
2cef5737 763 c = unibyte_char_to_multibyte (XINT (elt));
6a7df83b
RS
764 XSETINT (elt, c);
765 }
ea35ce3d 766 }
6a7df83b
RS
767 }
768 else if (BOOL_VECTOR_P (this))
769 {
770 int byte;
771 byte = XBOOL_VECTOR (this)->data[thisindex / BITS_PER_CHAR];
772 if (byte & (1 << (thisindex % BITS_PER_CHAR)))
773 elt = Qt;
ea35ce3d 774 else
6a7df83b
RS
775 elt = Qnil;
776 thisindex++;
ea35ce3d 777 }
6a7df83b
RS
778 else
779 elt = XVECTOR (this)->contents[thisindex++];
7b863bd5 780
ea35ce3d
RS
781 /* Store this element into the result. */
782 if (toindex < 0)
7b863bd5 783 {
70949dac 784 XCAR (tail) = elt;
ea35ce3d 785 prev = tail;
70949dac 786 tail = XCDR (tail);
7b863bd5 787 }
ea35ce3d
RS
788 else if (VECTORP (val))
789 XVECTOR (val)->contents[toindex++] = elt;
790 else
791 {
792 CHECK_NUMBER (elt, 0);
793 if (SINGLE_BYTE_CHAR_P (XINT (elt)))
794 {
2efdd1b9
KH
795 if (some_multibyte)
796 toindex_byte
797 += CHAR_STRING (XINT (elt),
798 XSTRING (val)->data + toindex_byte);
799 else
800 XSTRING (val)->data[toindex_byte++] = XINT (elt);
18cc260b
KH
801 if (some_multibyte
802 && toindex_byte > 0
2d6115c8
KH
803 && count_combining (XSTRING (val)->data,
804 toindex_byte, toindex_byte - 1))
805 XSTRING (val)->size--;
806 else
807 toindex++;
ea35ce3d
RS
808 }
809 else
810 /* If we have any multibyte characters,
811 we already decided to make a multibyte string. */
812 {
813 int c = XINT (elt);
ea35ce3d
RS
814 /* P exists as a variable
815 to avoid a bug on the Masscomp C compiler. */
816 unsigned char *p = & XSTRING (val)->data[toindex_byte];
64a5094a
KH
817
818 toindex_byte += CHAR_STRING (c, p);
ea35ce3d
RS
819 toindex++;
820 }
821 }
822 }
7b863bd5 823 }
265a9e55 824 if (!NILP (prev))
70949dac 825 XCDR (prev) = last_tail;
7b863bd5 826
87f0532f 827 if (num_textprops > 0)
2d6115c8 828 {
87f0532f 829 for (argnum = 0; argnum < num_textprops; argnum++)
2d6115c8 830 {
87f0532f
KH
831 this = args[textprops[argnum].argnum];
832 copy_text_properties (make_number (textprops[argnum].from),
7c752c80 833 make_number (XSTRING (this)->size), this,
87f0532f 834 make_number (textprops[argnum].to), val, Qnil);
2d6115c8
KH
835 }
836 }
b4f334f7 837 return val;
7b863bd5
JB
838}
839\f
09ab3c3b
KH
840static Lisp_Object string_char_byte_cache_string;
841static int string_char_byte_cache_charpos;
842static int string_char_byte_cache_bytepos;
843
57247650
KH
844void
845clear_string_char_byte_cache ()
846{
847 string_char_byte_cache_string = Qnil;
848}
849
ea35ce3d
RS
850/* Return the character index corresponding to CHAR_INDEX in STRING. */
851
852int
853string_char_to_byte (string, char_index)
854 Lisp_Object string;
855 int char_index;
856{
09ab3c3b
KH
857 int i, i_byte;
858 int best_below, best_below_byte;
859 int best_above, best_above_byte;
ea35ce3d
RS
860
861 if (! STRING_MULTIBYTE (string))
862 return char_index;
863
09ab3c3b
KH
864 best_below = best_below_byte = 0;
865 best_above = XSTRING (string)->size;
fc932ac6 866 best_above_byte = STRING_BYTES (XSTRING (string));
09ab3c3b
KH
867
868 if (EQ (string, string_char_byte_cache_string))
869 {
870 if (string_char_byte_cache_charpos < char_index)
871 {
872 best_below = string_char_byte_cache_charpos;
873 best_below_byte = string_char_byte_cache_bytepos;
874 }
875 else
876 {
877 best_above = string_char_byte_cache_charpos;
878 best_above_byte = string_char_byte_cache_bytepos;
879 }
880 }
881
882 if (char_index - best_below < best_above - char_index)
883 {
884 while (best_below < char_index)
885 {
886 int c;
2efdd1b9
KH
887 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string,
888 best_below, best_below_byte);
09ab3c3b
KH
889 }
890 i = best_below;
891 i_byte = best_below_byte;
892 }
893 else
ea35ce3d 894 {
09ab3c3b
KH
895 while (best_above > char_index)
896 {
e50d9192
KH
897 unsigned char *pend = XSTRING (string)->data + best_above_byte;
898 unsigned char *pbeg = pend - best_above_byte;
899 unsigned char *p = pend - 1;
900 int bytes;
901
902 while (p > pbeg && !CHAR_HEAD_P (*p)) p--;
903 PARSE_MULTIBYTE_SEQ (p, pend - p, bytes);
904 if (bytes == pend - p)
905 best_above_byte -= bytes;
906 else if (bytes > pend - p)
907 best_above_byte -= (pend - p);
908 else
09ab3c3b 909 best_above_byte--;
09ab3c3b
KH
910 best_above--;
911 }
912 i = best_above;
913 i_byte = best_above_byte;
ea35ce3d
RS
914 }
915
09ab3c3b
KH
916 string_char_byte_cache_bytepos = i_byte;
917 string_char_byte_cache_charpos = i;
918 string_char_byte_cache_string = string;
919
ea35ce3d
RS
920 return i_byte;
921}
09ab3c3b 922\f
ea35ce3d
RS
923/* Return the character index corresponding to BYTE_INDEX in STRING. */
924
925int
926string_byte_to_char (string, byte_index)
927 Lisp_Object string;
928 int byte_index;
929{
09ab3c3b
KH
930 int i, i_byte;
931 int best_below, best_below_byte;
932 int best_above, best_above_byte;
ea35ce3d
RS
933
934 if (! STRING_MULTIBYTE (string))
935 return byte_index;
936
09ab3c3b
KH
937 best_below = best_below_byte = 0;
938 best_above = XSTRING (string)->size;
fc932ac6 939 best_above_byte = STRING_BYTES (XSTRING (string));
09ab3c3b
KH
940
941 if (EQ (string, string_char_byte_cache_string))
942 {
943 if (string_char_byte_cache_bytepos < byte_index)
944 {
945 best_below = string_char_byte_cache_charpos;
946 best_below_byte = string_char_byte_cache_bytepos;
947 }
948 else
949 {
950 best_above = string_char_byte_cache_charpos;
951 best_above_byte = string_char_byte_cache_bytepos;
952 }
953 }
954
955 if (byte_index - best_below_byte < best_above_byte - byte_index)
956 {
957 while (best_below_byte < byte_index)
958 {
959 int c;
2efdd1b9
KH
960 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string,
961 best_below, best_below_byte);
09ab3c3b
KH
962 }
963 i = best_below;
964 i_byte = best_below_byte;
965 }
966 else
ea35ce3d 967 {
09ab3c3b
KH
968 while (best_above_byte > byte_index)
969 {
e50d9192
KH
970 unsigned char *pend = XSTRING (string)->data + best_above_byte;
971 unsigned char *pbeg = pend - best_above_byte;
972 unsigned char *p = pend - 1;
973 int bytes;
974
975 while (p > pbeg && !CHAR_HEAD_P (*p)) p--;
976 PARSE_MULTIBYTE_SEQ (p, pend - p, bytes);
977 if (bytes == pend - p)
978 best_above_byte -= bytes;
979 else if (bytes > pend - p)
980 best_above_byte -= (pend - p);
981 else
09ab3c3b 982 best_above_byte--;
09ab3c3b
KH
983 best_above--;
984 }
985 i = best_above;
986 i_byte = best_above_byte;
ea35ce3d
RS
987 }
988
09ab3c3b
KH
989 string_char_byte_cache_bytepos = i_byte;
990 string_char_byte_cache_charpos = i;
991 string_char_byte_cache_string = string;
992
ea35ce3d
RS
993 return i;
994}
09ab3c3b 995\f
ea35ce3d 996/* Convert STRING to a multibyte string.
2cef5737 997 Single-byte characters 0240 through 0377 are converted
ea35ce3d
RS
998 by adding nonascii_insert_offset to each. */
999
1000Lisp_Object
1001string_make_multibyte (string)
1002 Lisp_Object string;
1003{
1004 unsigned char *buf;
1005 int nbytes;
1006
1007 if (STRING_MULTIBYTE (string))
1008 return string;
1009
1010 nbytes = count_size_as_multibyte (XSTRING (string)->data,
1011 XSTRING (string)->size);
6d475204
RS
1012 /* If all the chars are ASCII, they won't need any more bytes
1013 once converted. In that case, we can return STRING itself. */
fc932ac6 1014 if (nbytes == STRING_BYTES (XSTRING (string)))
6d475204
RS
1015 return string;
1016
ea35ce3d 1017 buf = (unsigned char *) alloca (nbytes);
fc932ac6 1018 copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
ea35ce3d
RS
1019 0, 1);
1020
1021 return make_multibyte_string (buf, XSTRING (string)->size, nbytes);
1022}
1023
1024/* Convert STRING to a single-byte string. */
1025
1026Lisp_Object
1027string_make_unibyte (string)
1028 Lisp_Object string;
1029{
1030 unsigned char *buf;
1031
1032 if (! STRING_MULTIBYTE (string))
1033 return string;
1034
1035 buf = (unsigned char *) alloca (XSTRING (string)->size);
1036
fc932ac6 1037 copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
ea35ce3d
RS
1038 1, 0);
1039
1040 return make_unibyte_string (buf, XSTRING (string)->size);
1041}
09ab3c3b
KH
1042
1043DEFUN ("string-make-multibyte", Fstring_make_multibyte, Sstring_make_multibyte,
1044 1, 1, 0,
a6ee6aa4
RS
1045 "Return the multibyte equivalent of STRING.\n\
1046The function `unibyte-char-to-multibyte' is used to convert\n\
1047each unibyte character to a multibyte character.")
09ab3c3b
KH
1048 (string)
1049 Lisp_Object string;
1050{
aabd38ec
KH
1051 CHECK_STRING (string, 0);
1052
09ab3c3b
KH
1053 return string_make_multibyte (string);
1054}
1055
1056DEFUN ("string-make-unibyte", Fstring_make_unibyte, Sstring_make_unibyte,
1057 1, 1, 0,
a6ee6aa4
RS
1058 "Return the unibyte equivalent of STRING.\n\
1059Multibyte character codes are converted to unibyte\n\
1060by using just the low 8 bits.")
09ab3c3b
KH
1061 (string)
1062 Lisp_Object string;
1063{
aabd38ec
KH
1064 CHECK_STRING (string, 0);
1065
09ab3c3b
KH
1066 return string_make_unibyte (string);
1067}
6d475204
RS
1068
1069DEFUN ("string-as-unibyte", Fstring_as_unibyte, Sstring_as_unibyte,
1070 1, 1, 0,
1071 "Return a unibyte string with the same individual bytes as STRING.\n\
f4e09ae7 1072If STRING is unibyte, the result is STRING itself.\n\
2efdd1b9
KH
1073Otherwise it is a newly created string, with no text properties.\n\
1074If STRING is multibyte and contains a character of charset `binary',\n\
1075it is converted to the corresponding single byte.")
6d475204
RS
1076 (string)
1077 Lisp_Object string;
1078{
aabd38ec
KH
1079 CHECK_STRING (string, 0);
1080
6d475204
RS
1081 if (STRING_MULTIBYTE (string))
1082 {
2efdd1b9
KH
1083 int bytes = STRING_BYTES (XSTRING (string));
1084 unsigned char *str = (unsigned char *) xmalloc (bytes);
1085
1086 bcopy (XSTRING (string)->data, str, bytes);
1087 bytes = str_as_unibyte (str, bytes);
1088 string = make_unibyte_string (str, bytes);
1089 xfree (str);
6d475204
RS
1090 }
1091 return string;
1092}
1093
1094DEFUN ("string-as-multibyte", Fstring_as_multibyte, Sstring_as_multibyte,
1095 1, 1, 0,
1096 "Return a multibyte string with the same individual bytes as STRING.\n\
f4e09ae7 1097If STRING is multibyte, the result is STRING itself.\n\
2efdd1b9
KH
1098Otherwise it is a newly created string, with no text properties.\n\
1099If STRING is unibyte and contains an individual 8-bit byte (i.e. not\n\
1100part of multibyte form), it is converted to the corresponding\n\
1101multibyte character of charset `binary'.")
6d475204
RS
1102 (string)
1103 Lisp_Object string;
1104{
aabd38ec
KH
1105 CHECK_STRING (string, 0);
1106
6d475204
RS
1107 if (! STRING_MULTIBYTE (string))
1108 {
2efdd1b9
KH
1109 Lisp_Object new_string;
1110 int nchars, nbytes;
1111
1112 parse_str_as_multibyte (XSTRING (string)->data,
1113 STRING_BYTES (XSTRING (string)),
1114 &nchars, &nbytes);
1115 new_string = make_uninit_multibyte_string (nchars, nbytes);
1116 bcopy (XSTRING (string)->data, XSTRING (new_string)->data,
1117 STRING_BYTES (XSTRING (string)));
1118 if (nbytes != STRING_BYTES (XSTRING (string)))
1119 str_as_multibyte (XSTRING (new_string)->data, nbytes,
1120 STRING_BYTES (XSTRING (string)), NULL);
1121 string = new_string;
f4e09ae7 1122 XSTRING (string)->intervals = NULL_INTERVAL;
6d475204
RS
1123 }
1124 return string;
1125}
ea35ce3d 1126\f
7b863bd5
JB
1127DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
1128 "Return a copy of ALIST.\n\
1129This is an alist which represents the same mapping from objects to objects,\n\
1130but does not share the alist structure with ALIST.\n\
1131The objects mapped (cars and cdrs of elements of the alist)\n\
1132are shared, however.\n\
1133Elements of ALIST that are not conses are also shared.")
1134 (alist)
1135 Lisp_Object alist;
1136{
1137 register Lisp_Object tem;
1138
1139 CHECK_LIST (alist, 0);
265a9e55 1140 if (NILP (alist))
7b863bd5
JB
1141 return alist;
1142 alist = concat (1, &alist, Lisp_Cons, 0);
70949dac 1143 for (tem = alist; CONSP (tem); tem = XCDR (tem))
7b863bd5
JB
1144 {
1145 register Lisp_Object car;
70949dac 1146 car = XCAR (tem);
7b863bd5
JB
1147
1148 if (CONSP (car))
70949dac 1149 XCAR (tem) = Fcons (XCAR (car), XCDR (car));
7b863bd5
JB
1150 }
1151 return alist;
1152}
1153
1154DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
1155 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
1156TO may be nil or omitted; then the substring runs to the end of STRING.\n\
21fbc8e5
RS
1157If FROM or TO is negative, it counts from the end.\n\
1158\n\
1159This function allows vectors as well as strings.")
7b863bd5
JB
1160 (string, from, to)
1161 Lisp_Object string;
1162 register Lisp_Object from, to;
1163{
ac811a55 1164 Lisp_Object res;
21fbc8e5 1165 int size;
ea35ce3d
RS
1166 int size_byte;
1167 int from_char, to_char;
1168 int from_byte, to_byte;
21fbc8e5
RS
1169
1170 if (! (STRINGP (string) || VECTORP (string)))
1171 wrong_type_argument (Qarrayp, string);
ac811a55 1172
7b863bd5 1173 CHECK_NUMBER (from, 1);
21fbc8e5
RS
1174
1175 if (STRINGP (string))
ea35ce3d
RS
1176 {
1177 size = XSTRING (string)->size;
fc932ac6 1178 size_byte = STRING_BYTES (XSTRING (string));
ea35ce3d 1179 }
21fbc8e5
RS
1180 else
1181 size = XVECTOR (string)->size;
1182
265a9e55 1183 if (NILP (to))
ea35ce3d
RS
1184 {
1185 to_char = size;
1186 to_byte = size_byte;
1187 }
7b863bd5 1188 else
ea35ce3d
RS
1189 {
1190 CHECK_NUMBER (to, 2);
1191
1192 to_char = XINT (to);
1193 if (to_char < 0)
1194 to_char += size;
1195
1196 if (STRINGP (string))
1197 to_byte = string_char_to_byte (string, to_char);
1198 }
1199
1200 from_char = XINT (from);
1201 if (from_char < 0)
1202 from_char += size;
1203 if (STRINGP (string))
1204 from_byte = string_char_to_byte (string, from_char);
7b863bd5 1205
ea35ce3d
RS
1206 if (!(0 <= from_char && from_char <= to_char && to_char <= size))
1207 args_out_of_range_3 (string, make_number (from_char),
1208 make_number (to_char));
7b863bd5 1209
21fbc8e5
RS
1210 if (STRINGP (string))
1211 {
b10b2daa
RS
1212 res = make_specified_string (XSTRING (string)->data + from_byte,
1213 to_char - from_char, to_byte - from_byte,
1214 STRING_MULTIBYTE (string));
21ab867f
AS
1215 copy_text_properties (make_number (from_char), make_number (to_char),
1216 string, make_number (0), res, Qnil);
ea35ce3d
RS
1217 }
1218 else
1219 res = Fvector (to_char - from_char,
1220 XVECTOR (string)->contents + from_char);
1221
1222 return res;
1223}
1224
1225/* Extract a substring of STRING, giving start and end positions
1226 both in characters and in bytes. */
1227
1228Lisp_Object
1229substring_both (string, from, from_byte, to, to_byte)
1230 Lisp_Object string;
1231 int from, from_byte, to, to_byte;
1232{
1233 Lisp_Object res;
1234 int size;
1235 int size_byte;
1236
1237 if (! (STRINGP (string) || VECTORP (string)))
1238 wrong_type_argument (Qarrayp, string);
1239
1240 if (STRINGP (string))
1241 {
1242 size = XSTRING (string)->size;
fc932ac6 1243 size_byte = STRING_BYTES (XSTRING (string));
ea35ce3d
RS
1244 }
1245 else
1246 size = XVECTOR (string)->size;
1247
1248 if (!(0 <= from && from <= to && to <= size))
1249 args_out_of_range_3 (string, make_number (from), make_number (to));
1250
1251 if (STRINGP (string))
1252 {
b10b2daa
RS
1253 res = make_specified_string (XSTRING (string)->data + from_byte,
1254 to - from, to_byte - from_byte,
1255 STRING_MULTIBYTE (string));
21ab867f
AS
1256 copy_text_properties (make_number (from), make_number (to),
1257 string, make_number (0), res, Qnil);
21fbc8e5
RS
1258 }
1259 else
ea35ce3d
RS
1260 res = Fvector (to - from,
1261 XVECTOR (string)->contents + from);
b4f334f7 1262
ac811a55 1263 return res;
7b863bd5
JB
1264}
1265\f
1266DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1267 "Take cdr N times on LIST, returns the result.")
1268 (n, list)
1269 Lisp_Object n;
1270 register Lisp_Object list;
1271{
1272 register int i, num;
1273 CHECK_NUMBER (n, 0);
1274 num = XINT (n);
265a9e55 1275 for (i = 0; i < num && !NILP (list); i++)
7b863bd5
JB
1276 {
1277 QUIT;
71a8e74b
DL
1278 if (! CONSP (list))
1279 wrong_type_argument (Qlistp, list);
1280 list = XCDR (list);
7b863bd5
JB
1281 }
1282 return list;
1283}
1284
1285DEFUN ("nth", Fnth, Snth, 2, 2, 0,
1286 "Return the Nth element of LIST.\n\
1287N counts from zero. If LIST is not that long, nil is returned.")
1288 (n, list)
1289 Lisp_Object n, list;
1290{
1291 return Fcar (Fnthcdr (n, list));
1292}
1293
1294DEFUN ("elt", Felt, Selt, 2, 2, 0,
1295 "Return element of SEQUENCE at index N.")
88fe8140
EN
1296 (sequence, n)
1297 register Lisp_Object sequence, n;
7b863bd5
JB
1298{
1299 CHECK_NUMBER (n, 0);
1300 while (1)
1301 {
88fe8140
EN
1302 if (CONSP (sequence) || NILP (sequence))
1303 return Fcar (Fnthcdr (n, sequence));
1304 else if (STRINGP (sequence) || VECTORP (sequence)
1305 || BOOL_VECTOR_P (sequence) || CHAR_TABLE_P (sequence))
1306 return Faref (sequence, n);
7b863bd5 1307 else
88fe8140 1308 sequence = wrong_type_argument (Qsequencep, sequence);
7b863bd5
JB
1309 }
1310}
1311
1312DEFUN ("member", Fmember, Smember, 2, 2, 0,
1d58e36f 1313 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
7b863bd5
JB
1314The value is actually the tail of LIST whose car is ELT.")
1315 (elt, list)
1316 register Lisp_Object elt;
1317 Lisp_Object list;
1318{
1319 register Lisp_Object tail;
70949dac 1320 for (tail = list; !NILP (tail); tail = XCDR (tail))
7b863bd5
JB
1321 {
1322 register Lisp_Object tem;
71a8e74b
DL
1323 if (! CONSP (tail))
1324 wrong_type_argument (Qlistp, list);
1325 tem = XCAR (tail);
265a9e55 1326 if (! NILP (Fequal (elt, tem)))
7b863bd5
JB
1327 return tail;
1328 QUIT;
1329 }
1330 return Qnil;
1331}
1332
1333DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
f2be3671
GM
1334 "Return non-nil if ELT is an element of LIST.\n\
1335Comparison done with EQ. The value is actually the tail of LIST\n\
1336whose car is ELT.")
7b863bd5 1337 (elt, list)
f2be3671 1338 Lisp_Object elt, list;
7b863bd5 1339{
f2be3671 1340 while (1)
7b863bd5 1341 {
f2be3671
GM
1342 if (!CONSP (list) || EQ (XCAR (list), elt))
1343 break;
1344
1345 list = XCDR (list);
1346 if (!CONSP (list) || EQ (XCAR (list), elt))
1347 break;
1348
1349 list = XCDR (list);
1350 if (!CONSP (list) || EQ (XCAR (list), elt))
1351 break;
1352
1353 list = XCDR (list);
7b863bd5
JB
1354 QUIT;
1355 }
f2be3671
GM
1356
1357 if (!CONSP (list) && !NILP (list))
1358 list = wrong_type_argument (Qlistp, list);
1359
1360 return list;
7b863bd5
JB
1361}
1362
1363DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
3797b4c3
RS
1364 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
1365The value is actually the element of LIST whose car is KEY.\n\
7b863bd5
JB
1366Elements of LIST that are not conses are ignored.")
1367 (key, list)
f2be3671 1368 Lisp_Object key, list;
7b863bd5 1369{
f2be3671
GM
1370 Lisp_Object result;
1371
1372 while (1)
7b863bd5 1373 {
f2be3671
GM
1374 if (!CONSP (list)
1375 || (CONSP (XCAR (list))
1376 && EQ (XCAR (XCAR (list)), key)))
1377 break;
1378
1379 list = XCDR (list);
1380 if (!CONSP (list)
1381 || (CONSP (XCAR (list))
1382 && EQ (XCAR (XCAR (list)), key)))
1383 break;
1384
1385 list = XCDR (list);
1386 if (!CONSP (list)
1387 || (CONSP (XCAR (list))
1388 && EQ (XCAR (XCAR (list)), key)))
1389 break;
1390
1391 list = XCDR (list);
7b863bd5
JB
1392 QUIT;
1393 }
f2be3671
GM
1394
1395 if (CONSP (list))
1396 result = XCAR (list);
1397 else if (NILP (list))
1398 result = Qnil;
1399 else
1400 result = wrong_type_argument (Qlistp, list);
1401
1402 return result;
7b863bd5
JB
1403}
1404
1405/* Like Fassq but never report an error and do not allow quits.
1406 Use only on lists known never to be circular. */
1407
1408Lisp_Object
1409assq_no_quit (key, list)
f2be3671 1410 Lisp_Object key, list;
7b863bd5 1411{
f2be3671
GM
1412 while (CONSP (list)
1413 && (!CONSP (XCAR (list))
1414 || !EQ (XCAR (XCAR (list)), key)))
1415 list = XCDR (list);
1416
1417 return CONSP (list) ? XCAR (list) : Qnil;
7b863bd5
JB
1418}
1419
1420DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
3797b4c3 1421 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
0fb5a19c 1422The value is actually the element of LIST whose car equals KEY.")
7b863bd5 1423 (key, list)
f2be3671 1424 Lisp_Object key, list;
7b863bd5 1425{
f2be3671
GM
1426 Lisp_Object result, car;
1427
1428 while (1)
7b863bd5 1429 {
f2be3671
GM
1430 if (!CONSP (list)
1431 || (CONSP (XCAR (list))
1432 && (car = XCAR (XCAR (list)),
1433 EQ (car, key) || !NILP (Fequal (car, key)))))
1434 break;
1435
1436 list = XCDR (list);
1437 if (!CONSP (list)
1438 || (CONSP (XCAR (list))
1439 && (car = XCAR (XCAR (list)),
1440 EQ (car, key) || !NILP (Fequal (car, key)))))
1441 break;
1442
1443 list = XCDR (list);
1444 if (!CONSP (list)
1445 || (CONSP (XCAR (list))
1446 && (car = XCAR (XCAR (list)),
1447 EQ (car, key) || !NILP (Fequal (car, key)))))
1448 break;
1449
1450 list = XCDR (list);
7b863bd5
JB
1451 QUIT;
1452 }
f2be3671
GM
1453
1454 if (CONSP (list))
1455 result = XCAR (list);
1456 else if (NILP (list))
1457 result = Qnil;
1458 else
1459 result = wrong_type_argument (Qlistp, list);
1460
1461 return result;
7b863bd5
JB
1462}
1463
1464DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
f2be3671
GM
1465 "Return non-nil if KEY is `eq' to the cdr of an element of LIST.\n\
1466The value is actually the element of LIST whose cdr is KEY.")
7b863bd5
JB
1467 (key, list)
1468 register Lisp_Object key;
1469 Lisp_Object list;
1470{
f2be3671
GM
1471 Lisp_Object result;
1472
1473 while (1)
7b863bd5 1474 {
f2be3671
GM
1475 if (!CONSP (list)
1476 || (CONSP (XCAR (list))
1477 && EQ (XCDR (XCAR (list)), key)))
1478 break;
1479
1480 list = XCDR (list);
1481 if (!CONSP (list)
1482 || (CONSP (XCAR (list))
1483 && EQ (XCDR (XCAR (list)), key)))
1484 break;
1485
1486 list = XCDR (list);
1487 if (!CONSP (list)
1488 || (CONSP (XCAR (list))
1489 && EQ (XCDR (XCAR (list)), key)))
1490 break;
1491
1492 list = XCDR (list);
7b863bd5
JB
1493 QUIT;
1494 }
f2be3671
GM
1495
1496 if (NILP (list))
1497 result = Qnil;
1498 else if (CONSP (list))
1499 result = XCAR (list);
1500 else
1501 result = wrong_type_argument (Qlistp, list);
1502
1503 return result;
7b863bd5 1504}
0fb5a19c
RS
1505
1506DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
1507 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
1508The value is actually the element of LIST whose cdr equals KEY.")
1509 (key, list)
f2be3671 1510 Lisp_Object key, list;
0fb5a19c 1511{
f2be3671
GM
1512 Lisp_Object result, cdr;
1513
1514 while (1)
0fb5a19c 1515 {
f2be3671
GM
1516 if (!CONSP (list)
1517 || (CONSP (XCAR (list))
1518 && (cdr = XCDR (XCAR (list)),
1519 EQ (cdr, key) || !NILP (Fequal (cdr, key)))))
1520 break;
1521
1522 list = XCDR (list);
1523 if (!CONSP (list)
1524 || (CONSP (XCAR (list))
1525 && (cdr = XCDR (XCAR (list)),
1526 EQ (cdr, key) || !NILP (Fequal (cdr, key)))))
1527 break;
1528
1529 list = XCDR (list);
1530 if (!CONSP (list)
1531 || (CONSP (XCAR (list))
1532 && (cdr = XCDR (XCAR (list)),
1533 EQ (cdr, key) || !NILP (Fequal (cdr, key)))))
1534 break;
1535
1536 list = XCDR (list);
0fb5a19c
RS
1537 QUIT;
1538 }
f2be3671
GM
1539
1540 if (CONSP (list))
1541 result = XCAR (list);
1542 else if (NILP (list))
1543 result = Qnil;
1544 else
1545 result = wrong_type_argument (Qlistp, list);
1546
1547 return result;
0fb5a19c 1548}
7b863bd5
JB
1549\f
1550DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
1551 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1552The modified LIST is returned. Comparison is done with `eq'.\n\
1553If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
1554therefore, write `(setq foo (delq element foo))'\n\
1555to be sure of changing the value of `foo'.")
1556 (elt, list)
1557 register Lisp_Object elt;
1558 Lisp_Object list;
1559{
1560 register Lisp_Object tail, prev;
1561 register Lisp_Object tem;
1562
1563 tail = list;
1564 prev = Qnil;
265a9e55 1565 while (!NILP (tail))
7b863bd5 1566 {
71a8e74b
DL
1567 if (! CONSP (tail))
1568 wrong_type_argument (Qlistp, list);
1569 tem = XCAR (tail);
7b863bd5
JB
1570 if (EQ (elt, tem))
1571 {
265a9e55 1572 if (NILP (prev))
70949dac 1573 list = XCDR (tail);
7b863bd5 1574 else
70949dac 1575 Fsetcdr (prev, XCDR (tail));
7b863bd5
JB
1576 }
1577 else
1578 prev = tail;
70949dac 1579 tail = XCDR (tail);
7b863bd5
JB
1580 QUIT;
1581 }
1582 return list;
1583}
1584
ca8dd546 1585DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
1e134a5f
RM
1586 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1587The modified LIST is returned. Comparison is done with `equal'.\n\
1d58e36f
RS
1588If the first member of LIST is ELT, deleting it is not a side effect;\n\
1589it is simply using a different list.\n\
1590Therefore, write `(setq foo (delete element foo))'\n\
1e134a5f
RM
1591to be sure of changing the value of `foo'.")
1592 (elt, list)
1593 register Lisp_Object elt;
1594 Lisp_Object list;
1595{
1596 register Lisp_Object tail, prev;
1597 register Lisp_Object tem;
1598
1599 tail = list;
1600 prev = Qnil;
265a9e55 1601 while (!NILP (tail))
1e134a5f 1602 {
71a8e74b
DL
1603 if (! CONSP (tail))
1604 wrong_type_argument (Qlistp, list);
1605 tem = XCAR (tail);
f812877e 1606 if (! NILP (Fequal (elt, tem)))
1e134a5f 1607 {
265a9e55 1608 if (NILP (prev))
70949dac 1609 list = XCDR (tail);
1e134a5f 1610 else
70949dac 1611 Fsetcdr (prev, XCDR (tail));
1e134a5f
RM
1612 }
1613 else
1614 prev = tail;
70949dac 1615 tail = XCDR (tail);
1e134a5f
RM
1616 QUIT;
1617 }
1618 return list;
1619}
1620
7b863bd5
JB
1621DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
1622 "Reverse LIST by modifying cdr pointers.\n\
1623Returns the beginning of the reversed list.")
1624 (list)
1625 Lisp_Object list;
1626{
1627 register Lisp_Object prev, tail, next;
1628
265a9e55 1629 if (NILP (list)) return list;
7b863bd5
JB
1630 prev = Qnil;
1631 tail = list;
265a9e55 1632 while (!NILP (tail))
7b863bd5
JB
1633 {
1634 QUIT;
71a8e74b
DL
1635 if (! CONSP (tail))
1636 wrong_type_argument (Qlistp, list);
1637 next = XCDR (tail);
7b863bd5
JB
1638 Fsetcdr (tail, prev);
1639 prev = tail;
1640 tail = next;
1641 }
1642 return prev;
1643}
1644
1645DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
1646 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
1647See also the function `nreverse', which is used more often.")
1648 (list)
1649 Lisp_Object list;
1650{
9d14ae76 1651 Lisp_Object new;
7b863bd5 1652
70949dac
KR
1653 for (new = Qnil; CONSP (list); list = XCDR (list))
1654 new = Fcons (XCAR (list), new);
9d14ae76
RS
1655 if (!NILP (list))
1656 wrong_type_argument (Qconsp, list);
1657 return new;
7b863bd5
JB
1658}
1659\f
1660Lisp_Object merge ();
1661
1662DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
1663 "Sort LIST, stably, comparing elements using PREDICATE.\n\
1664Returns the sorted list. LIST is modified by side effects.\n\
1665PREDICATE is called with two elements of LIST, and should return T\n\
1666if the first element is \"less\" than the second.")
88fe8140
EN
1667 (list, predicate)
1668 Lisp_Object list, predicate;
7b863bd5
JB
1669{
1670 Lisp_Object front, back;
1671 register Lisp_Object len, tem;
1672 struct gcpro gcpro1, gcpro2;
1673 register int length;
1674
1675 front = list;
1676 len = Flength (list);
1677 length = XINT (len);
1678 if (length < 2)
1679 return list;
1680
1681 XSETINT (len, (length / 2) - 1);
1682 tem = Fnthcdr (len, list);
1683 back = Fcdr (tem);
1684 Fsetcdr (tem, Qnil);
1685
1686 GCPRO2 (front, back);
88fe8140
EN
1687 front = Fsort (front, predicate);
1688 back = Fsort (back, predicate);
7b863bd5 1689 UNGCPRO;
88fe8140 1690 return merge (front, back, predicate);
7b863bd5
JB
1691}
1692
1693Lisp_Object
1694merge (org_l1, org_l2, pred)
1695 Lisp_Object org_l1, org_l2;
1696 Lisp_Object pred;
1697{
1698 Lisp_Object value;
1699 register Lisp_Object tail;
1700 Lisp_Object tem;
1701 register Lisp_Object l1, l2;
1702 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1703
1704 l1 = org_l1;
1705 l2 = org_l2;
1706 tail = Qnil;
1707 value = Qnil;
1708
1709 /* It is sufficient to protect org_l1 and org_l2.
1710 When l1 and l2 are updated, we copy the new values
1711 back into the org_ vars. */
1712 GCPRO4 (org_l1, org_l2, pred, value);
1713
1714 while (1)
1715 {
265a9e55 1716 if (NILP (l1))
7b863bd5
JB
1717 {
1718 UNGCPRO;
265a9e55 1719 if (NILP (tail))
7b863bd5
JB
1720 return l2;
1721 Fsetcdr (tail, l2);
1722 return value;
1723 }
265a9e55 1724 if (NILP (l2))
7b863bd5
JB
1725 {
1726 UNGCPRO;
265a9e55 1727 if (NILP (tail))
7b863bd5
JB
1728 return l1;
1729 Fsetcdr (tail, l1);
1730 return value;
1731 }
1732 tem = call2 (pred, Fcar (l2), Fcar (l1));
265a9e55 1733 if (NILP (tem))
7b863bd5
JB
1734 {
1735 tem = l1;
1736 l1 = Fcdr (l1);
1737 org_l1 = l1;
1738 }
1739 else
1740 {
1741 tem = l2;
1742 l2 = Fcdr (l2);
1743 org_l2 = l2;
1744 }
265a9e55 1745 if (NILP (tail))
7b863bd5
JB
1746 value = tem;
1747 else
1748 Fsetcdr (tail, tem);
1749 tail = tem;
1750 }
1751}
1752\f
be9d483d
BG
1753
1754DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
1fbb64aa 1755 "Extract a value from a property list.\n\
be9d483d 1756PLIST is a property list, which is a list of the form\n\
c07289e0 1757\(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
be9d483d
BG
1758corresponding to the given PROP, or nil if PROP is not\n\
1759one of the properties on the list.")
1fbb64aa
EN
1760 (plist, prop)
1761 Lisp_Object plist;
7b863bd5
JB
1762 register Lisp_Object prop;
1763{
1764 register Lisp_Object tail;
70949dac 1765 for (tail = plist; !NILP (tail); tail = Fcdr (XCDR (tail)))
7b863bd5
JB
1766 {
1767 register Lisp_Object tem;
1768 tem = Fcar (tail);
1769 if (EQ (prop, tem))
70949dac 1770 return Fcar (XCDR (tail));
7b863bd5
JB
1771 }
1772 return Qnil;
1773}
1774
be9d483d
BG
1775DEFUN ("get", Fget, Sget, 2, 2, 0,
1776 "Return the value of SYMBOL's PROPNAME property.\n\
c07289e0
RS
1777This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
1778 (symbol, propname)
1779 Lisp_Object symbol, propname;
be9d483d 1780{
c07289e0
RS
1781 CHECK_SYMBOL (symbol, 0);
1782 return Fplist_get (XSYMBOL (symbol)->plist, propname);
be9d483d
BG
1783}
1784
1785DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
1786 "Change value in PLIST of PROP to VAL.\n\
1787PLIST is a property list, which is a list of the form\n\
c07289e0 1788\(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
be9d483d 1789If PROP is already a property on the list, its value is set to VAL,\n\
88435890 1790otherwise the new PROP VAL pair is added. The new plist is returned;\n\
be9d483d
BG
1791use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
1792The PLIST is modified by side effects.")
1793 (plist, prop, val)
b4f334f7
KH
1794 Lisp_Object plist;
1795 register Lisp_Object prop;
1796 Lisp_Object val;
7b863bd5
JB
1797{
1798 register Lisp_Object tail, prev;
1799 Lisp_Object newcell;
1800 prev = Qnil;
70949dac
KR
1801 for (tail = plist; CONSP (tail) && CONSP (XCDR (tail));
1802 tail = XCDR (XCDR (tail)))
7b863bd5 1803 {
70949dac 1804 if (EQ (prop, XCAR (tail)))
be9d483d 1805 {
70949dac 1806 Fsetcar (XCDR (tail), val);
be9d483d
BG
1807 return plist;
1808 }
7b863bd5
JB
1809 prev = tail;
1810 }
1811 newcell = Fcons (prop, Fcons (val, Qnil));
265a9e55 1812 if (NILP (prev))
be9d483d 1813 return newcell;
7b863bd5 1814 else
70949dac 1815 Fsetcdr (XCDR (prev), newcell);
be9d483d
BG
1816 return plist;
1817}
1818
1819DEFUN ("put", Fput, Sput, 3, 3, 0,
1820 "Store SYMBOL's PROPNAME property with value VALUE.\n\
1821It can be retrieved with `(get SYMBOL PROPNAME)'.")
c07289e0
RS
1822 (symbol, propname, value)
1823 Lisp_Object symbol, propname, value;
be9d483d 1824{
c07289e0
RS
1825 CHECK_SYMBOL (symbol, 0);
1826 XSYMBOL (symbol)->plist
1827 = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
1828 return value;
7b863bd5
JB
1829}
1830
1831DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
ea35ce3d 1832 "Return t if two Lisp objects have similar structure and contents.\n\
7b863bd5
JB
1833They must have the same data type.\n\
1834Conses are compared by comparing the cars and the cdrs.\n\
1835Vectors and strings are compared element by element.\n\
d28c4332
RS
1836Numbers are compared by value, but integers cannot equal floats.\n\
1837 (Use `=' if you want integers and floats to be able to be equal.)\n\
1838Symbols must match exactly.")
7b863bd5
JB
1839 (o1, o2)
1840 register Lisp_Object o1, o2;
1841{
6cb9cafb 1842 return internal_equal (o1, o2, 0) ? Qt : Qnil;
e0f5cf5a
RS
1843}
1844
6cb9cafb 1845static int
e0f5cf5a
RS
1846internal_equal (o1, o2, depth)
1847 register Lisp_Object o1, o2;
1848 int depth;
1849{
1850 if (depth > 200)
1851 error ("Stack overflow in equal");
4ff1aed9 1852
6cb9cafb 1853 tail_recurse:
7b863bd5 1854 QUIT;
4ff1aed9
RS
1855 if (EQ (o1, o2))
1856 return 1;
1857 if (XTYPE (o1) != XTYPE (o2))
1858 return 0;
1859
1860 switch (XTYPE (o1))
1861 {
4ff1aed9
RS
1862 case Lisp_Float:
1863 return (extract_float (o1) == extract_float (o2));
4ff1aed9
RS
1864
1865 case Lisp_Cons:
70949dac 1866 if (!internal_equal (XCAR (o1), XCAR (o2), depth + 1))
4cab5074 1867 return 0;
70949dac
KR
1868 o1 = XCDR (o1);
1869 o2 = XCDR (o2);
4cab5074 1870 goto tail_recurse;
4ff1aed9
RS
1871
1872 case Lisp_Misc:
81d1fba6 1873 if (XMISCTYPE (o1) != XMISCTYPE (o2))
6cb9cafb 1874 return 0;
4ff1aed9 1875 if (OVERLAYP (o1))
7b863bd5 1876 {
e23f814f 1877 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2),
4ff1aed9 1878 depth + 1)
e23f814f 1879 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2),
4ff1aed9 1880 depth + 1))
6cb9cafb 1881 return 0;
4ff1aed9
RS
1882 o1 = XOVERLAY (o1)->plist;
1883 o2 = XOVERLAY (o2)->plist;
1884 goto tail_recurse;
7b863bd5 1885 }
4ff1aed9
RS
1886 if (MARKERP (o1))
1887 {
1888 return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
1889 && (XMARKER (o1)->buffer == 0
6ced1284 1890 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
4ff1aed9
RS
1891 }
1892 break;
1893
1894 case Lisp_Vectorlike:
4cab5074
KH
1895 {
1896 register int i, size;
1897 size = XVECTOR (o1)->size;
1898 /* Pseudovectors have the type encoded in the size field, so this test
1899 actually checks that the objects have the same type as well as the
1900 same size. */
1901 if (XVECTOR (o2)->size != size)
1902 return 0;
e03f7933
RS
1903 /* Boolvectors are compared much like strings. */
1904 if (BOOL_VECTOR_P (o1))
1905 {
e03f7933 1906 int size_in_chars
e22e4283 1907 = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
1908
1909 if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
1910 return 0;
1911 if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
1912 size_in_chars))
1913 return 0;
1914 return 1;
1915 }
ed73fcc1 1916 if (WINDOW_CONFIGURATIONP (o1))
48646924 1917 return compare_window_configurations (o1, o2, 0);
e03f7933
RS
1918
1919 /* Aside from them, only true vectors, char-tables, and compiled
1920 functions are sensible to compare, so eliminate the others now. */
4cab5074
KH
1921 if (size & PSEUDOVECTOR_FLAG)
1922 {
e03f7933 1923 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
4cab5074
KH
1924 return 0;
1925 size &= PSEUDOVECTOR_SIZE_MASK;
1926 }
1927 for (i = 0; i < size; i++)
1928 {
1929 Lisp_Object v1, v2;
1930 v1 = XVECTOR (o1)->contents [i];
1931 v2 = XVECTOR (o2)->contents [i];
1932 if (!internal_equal (v1, v2, depth + 1))
1933 return 0;
1934 }
1935 return 1;
1936 }
4ff1aed9
RS
1937 break;
1938
1939 case Lisp_String:
4cab5074
KH
1940 if (XSTRING (o1)->size != XSTRING (o2)->size)
1941 return 0;
fc932ac6 1942 if (STRING_BYTES (XSTRING (o1)) != STRING_BYTES (XSTRING (o2)))
ea35ce3d 1943 return 0;
4cab5074 1944 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
fc932ac6 1945 STRING_BYTES (XSTRING (o1))))
4cab5074 1946 return 0;
4cab5074 1947 return 1;
7b863bd5 1948 }
6cb9cafb 1949 return 0;
7b863bd5
JB
1950}
1951\f
2e34157c
RS
1952extern Lisp_Object Fmake_char_internal ();
1953
7b863bd5 1954DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
e03f7933
RS
1955 "Store each element of ARRAY with ITEM.\n\
1956ARRAY is a vector, string, char-table, or bool-vector.")
7b863bd5
JB
1957 (array, item)
1958 Lisp_Object array, item;
1959{
1960 register int size, index, charval;
1961 retry:
7650760e 1962 if (VECTORP (array))
7b863bd5
JB
1963 {
1964 register Lisp_Object *p = XVECTOR (array)->contents;
1965 size = XVECTOR (array)->size;
1966 for (index = 0; index < size; index++)
1967 p[index] = item;
1968 }
e03f7933
RS
1969 else if (CHAR_TABLE_P (array))
1970 {
1971 register Lisp_Object *p = XCHAR_TABLE (array)->contents;
1972 size = CHAR_TABLE_ORDINARY_SLOTS;
1973 for (index = 0; index < size; index++)
1974 p[index] = item;
1975 XCHAR_TABLE (array)->defalt = Qnil;
1976 }
7650760e 1977 else if (STRINGP (array))
7b863bd5
JB
1978 {
1979 register unsigned char *p = XSTRING (array)->data;
1980 CHECK_NUMBER (item, 1);
1981 charval = XINT (item);
1982 size = XSTRING (array)->size;
57247650
KH
1983 if (STRING_MULTIBYTE (array))
1984 {
64a5094a
KH
1985 unsigned char str[MAX_MULTIBYTE_LENGTH];
1986 int len = CHAR_STRING (charval, str);
57247650
KH
1987 int size_byte = STRING_BYTES (XSTRING (array));
1988 unsigned char *p1 = p, *endp = p + size_byte;
95b8aba7 1989 int i;
57247650 1990
95b8aba7
KH
1991 if (size != size_byte)
1992 while (p1 < endp)
1993 {
1994 int this_len = MULTIBYTE_FORM_LENGTH (p1, endp - p1);
1995 if (len != this_len)
1996 error ("Attempt to change byte length of a string");
1997 p1 += this_len;
1998 }
57247650
KH
1999 for (i = 0; i < size_byte; i++)
2000 *p++ = str[i % len];
2001 }
2002 else
2003 for (index = 0; index < size; index++)
2004 p[index] = charval;
7b863bd5 2005 }
e03f7933
RS
2006 else if (BOOL_VECTOR_P (array))
2007 {
2008 register unsigned char *p = XBOOL_VECTOR (array)->data;
e03f7933 2009 int size_in_chars
e22e4283 2010 = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
2011
2012 charval = (! NILP (item) ? -1 : 0);
2013 for (index = 0; index < size_in_chars; index++)
2014 p[index] = charval;
2015 }
7b863bd5
JB
2016 else
2017 {
2018 array = wrong_type_argument (Qarrayp, array);
2019 goto retry;
2020 }
2021 return array;
2022}
ea35ce3d 2023\f
999de246
RS
2024DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
2025 1, 1, 0,
2026 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
88fe8140
EN
2027 (char_table)
2028 Lisp_Object char_table;
999de246 2029{
b4f334f7 2030 CHECK_CHAR_TABLE (char_table, 0);
999de246 2031
88fe8140 2032 return XCHAR_TABLE (char_table)->purpose;
999de246
RS
2033}
2034
e03f7933
RS
2035DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
2036 1, 1, 0,
2037 "Return the parent char-table of CHAR-TABLE.\n\
2038The value is either nil or another char-table.\n\
2039If CHAR-TABLE holds nil for a given character,\n\
2040then the actual applicable value is inherited from the parent char-table\n\
2041\(or from its parents, if necessary).")
88fe8140
EN
2042 (char_table)
2043 Lisp_Object char_table;
e03f7933 2044{
b4f334f7 2045 CHECK_CHAR_TABLE (char_table, 0);
e03f7933 2046
88fe8140 2047 return XCHAR_TABLE (char_table)->parent;
e03f7933
RS
2048}
2049
2050DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
2051 2, 2, 0,
2052 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
2053PARENT must be either nil or another char-table.")
88fe8140
EN
2054 (char_table, parent)
2055 Lisp_Object char_table, parent;
e03f7933
RS
2056{
2057 Lisp_Object temp;
2058
b4f334f7 2059 CHECK_CHAR_TABLE (char_table, 0);
e03f7933 2060
c8640abf
RS
2061 if (!NILP (parent))
2062 {
b4f334f7 2063 CHECK_CHAR_TABLE (parent, 0);
c8640abf
RS
2064
2065 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
55cc974d 2066 if (EQ (temp, char_table))
c8640abf
RS
2067 error ("Attempt to make a chartable be its own parent");
2068 }
e03f7933 2069
88fe8140 2070 XCHAR_TABLE (char_table)->parent = parent;
e03f7933
RS
2071
2072 return parent;
2073}
2074
2075DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
2076 2, 2, 0,
25c30748 2077 "Return the value of CHAR-TABLE's extra-slot number N.")
88fe8140
EN
2078 (char_table, n)
2079 Lisp_Object char_table, n;
e03f7933 2080{
88fe8140 2081 CHECK_CHAR_TABLE (char_table, 1);
e03f7933
RS
2082 CHECK_NUMBER (n, 2);
2083 if (XINT (n) < 0
88fe8140
EN
2084 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
2085 args_out_of_range (char_table, n);
e03f7933 2086
88fe8140 2087 return XCHAR_TABLE (char_table)->extras[XINT (n)];
e03f7933
RS
2088}
2089
2090DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
2091 Sset_char_table_extra_slot,
2092 3, 3, 0,
25c30748 2093 "Set CHAR-TABLE's extra-slot number N to VALUE.")
88fe8140
EN
2094 (char_table, n, value)
2095 Lisp_Object char_table, n, value;
e03f7933 2096{
88fe8140 2097 CHECK_CHAR_TABLE (char_table, 1);
e03f7933
RS
2098 CHECK_NUMBER (n, 2);
2099 if (XINT (n) < 0
88fe8140
EN
2100 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
2101 args_out_of_range (char_table, n);
e03f7933 2102
88fe8140 2103 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
e03f7933 2104}
ea35ce3d 2105\f
999de246
RS
2106DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
2107 2, 2, 0,
88fe8140 2108 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
6d475204 2109RANGE should be nil (for the default value)\n\
999de246 2110a vector which identifies a character set or a row of a character set,\n\
6d475204 2111a character set name, or a character code.")
88fe8140
EN
2112 (char_table, range)
2113 Lisp_Object char_table, range;
999de246 2114{
88fe8140 2115 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 2116
999de246 2117 if (EQ (range, Qnil))
88fe8140 2118 return XCHAR_TABLE (char_table)->defalt;
999de246 2119 else if (INTEGERP (range))
88fe8140 2120 return Faref (char_table, range);
6d475204
RS
2121 else if (SYMBOLP (range))
2122 {
2123 Lisp_Object charset_info;
2124
2125 charset_info = Fget (range, Qcharset);
2126 CHECK_VECTOR (charset_info, 0);
2127
21ab867f
AS
2128 return Faref (char_table,
2129 make_number (XINT (XVECTOR (charset_info)->contents[0])
2130 + 128));
6d475204 2131 }
999de246
RS
2132 else if (VECTORP (range))
2133 {
e814a159 2134 if (XVECTOR (range)->size == 1)
21ab867f
AS
2135 return Faref (char_table,
2136 make_number (XINT (XVECTOR (range)->contents[0]) + 128));
e814a159
RS
2137 else
2138 {
2139 int size = XVECTOR (range)->size;
2140 Lisp_Object *val = XVECTOR (range)->contents;
2141 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
2142 size <= 1 ? Qnil : val[1],
2143 size <= 2 ? Qnil : val[2]);
2144 return Faref (char_table, ch);
2145 }
999de246
RS
2146 }
2147 else
2148 error ("Invalid RANGE argument to `char-table-range'");
5c6740c9 2149 return Qt;
999de246
RS
2150}
2151
e03f7933
RS
2152DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
2153 3, 3, 0,
88fe8140 2154 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
e03f7933
RS
2155RANGE should be t (for all characters), nil (for the default value)\n\
2156a vector which identifies a character set or a row of a character set,\n\
6d475204 2157a coding system, or a character code.")
88fe8140
EN
2158 (char_table, range, value)
2159 Lisp_Object char_table, range, value;
e03f7933
RS
2160{
2161 int i;
2162
88fe8140 2163 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 2164
e03f7933
RS
2165 if (EQ (range, Qt))
2166 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
88fe8140 2167 XCHAR_TABLE (char_table)->contents[i] = value;
e03f7933 2168 else if (EQ (range, Qnil))
88fe8140 2169 XCHAR_TABLE (char_table)->defalt = value;
6d475204
RS
2170 else if (SYMBOLP (range))
2171 {
2172 Lisp_Object charset_info;
2173
2174 charset_info = Fget (range, Qcharset);
2175 CHECK_VECTOR (charset_info, 0);
2176
21ab867f
AS
2177 return Faset (char_table,
2178 make_number (XINT (XVECTOR (charset_info)->contents[0])
2179 + 128),
6d475204
RS
2180 value);
2181 }
e03f7933 2182 else if (INTEGERP (range))
88fe8140 2183 Faset (char_table, range, value);
e03f7933
RS
2184 else if (VECTORP (range))
2185 {
e814a159 2186 if (XVECTOR (range)->size == 1)
21ab867f
AS
2187 return Faset (char_table,
2188 make_number (XINT (XVECTOR (range)->contents[0]) + 128),
2189 value);
e814a159
RS
2190 else
2191 {
2192 int size = XVECTOR (range)->size;
2193 Lisp_Object *val = XVECTOR (range)->contents;
2194 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
2195 size <= 1 ? Qnil : val[1],
2196 size <= 2 ? Qnil : val[2]);
2197 return Faset (char_table, ch, value);
2198 }
e03f7933
RS
2199 }
2200 else
2201 error ("Invalid RANGE argument to `set-char-table-range'");
2202
2203 return value;
2204}
e1335ba2
KH
2205
2206DEFUN ("set-char-table-default", Fset_char_table_default,
2207 Sset_char_table_default, 3, 3, 0,
2208 "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
2209The generic character specifies the group of characters.\n\
2210See also the documentation of make-char.")
2211 (char_table, ch, value)
2212 Lisp_Object char_table, ch, value;
2213{
ada0fa14 2214 int c, charset, code1, code2;
e1335ba2
KH
2215 Lisp_Object temp;
2216
2217 CHECK_CHAR_TABLE (char_table, 0);
2218 CHECK_NUMBER (ch, 1);
2219
2220 c = XINT (ch);
2db66414 2221 SPLIT_CHAR (c, charset, code1, code2);
0da528a9
KH
2222
2223 /* Since we may want to set the default value for a character set
2224 not yet defined, we check only if the character set is in the
2225 valid range or not, instead of it is already defined or not. */
2226 if (! CHARSET_VALID_P (charset))
f71599f4 2227 invalid_character (c);
e1335ba2
KH
2228
2229 if (charset == CHARSET_ASCII)
2230 return (XCHAR_TABLE (char_table)->defalt = value);
2231
2232 /* Even if C is not a generic char, we had better behave as if a
2233 generic char is specified. */
64a5094a 2234 if (CHARSET_DIMENSION (charset) == 1)
e1335ba2
KH
2235 code1 = 0;
2236 temp = XCHAR_TABLE (char_table)->contents[charset + 128];
2237 if (!code1)
2238 {
2239 if (SUB_CHAR_TABLE_P (temp))
2240 XCHAR_TABLE (temp)->defalt = value;
2241 else
2242 XCHAR_TABLE (char_table)->contents[charset + 128] = value;
2243 return value;
2244 }
2245 char_table = temp;
2246 if (! SUB_CHAR_TABLE_P (char_table))
2247 char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
2248 = make_sub_char_table (temp));
2249 temp = XCHAR_TABLE (char_table)->contents[code1];
2250 if (SUB_CHAR_TABLE_P (temp))
2251 XCHAR_TABLE (temp)->defalt = value;
2252 else
2253 XCHAR_TABLE (char_table)->contents[code1] = value;
2254 return value;
2255}
1d969a23
RS
2256
2257/* Look up the element in TABLE at index CH,
2258 and return it as an integer.
2259 If the element is nil, return CH itself.
2260 (Actually we do that for any non-integer.) */
2261
2262int
2263char_table_translate (table, ch)
2264 Lisp_Object table;
2265 int ch;
2266{
2267 Lisp_Object value;
2268 value = Faref (table, make_number (ch));
2269 if (! INTEGERP (value))
2270 return ch;
2271 return XINT (value);
2272}
52ef6c89
KH
2273
2274static void
2275optimize_sub_char_table (table, chars)
2276 Lisp_Object *table;
2277 int chars;
2278{
2279 Lisp_Object elt;
2280 int from, to;
2281
2282 if (chars == 94)
2283 from = 33, to = 127;
2284 else
2285 from = 32, to = 128;
2286
2287 if (!SUB_CHAR_TABLE_P (*table))
2288 return;
2289 elt = XCHAR_TABLE (*table)->contents[from++];
2290 for (; from < to; from++)
2291 if (NILP (Fequal (elt, XCHAR_TABLE (*table)->contents[from])))
2292 return;
2293 *table = elt;
2294}
2295
2296DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
2297 1, 1, 0,
2298 "Optimize char table TABLE.")
2299 (table)
2300 Lisp_Object table;
2301{
2302 Lisp_Object elt;
2303 int dim;
2304 int i, j;
2305
2306 CHECK_CHAR_TABLE (table, 0);
2307
2308 for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
2309 {
2310 elt = XCHAR_TABLE (table)->contents[i];
2311 if (!SUB_CHAR_TABLE_P (elt))
2312 continue;
2313 dim = CHARSET_DIMENSION (i);
2314 if (dim == 2)
2315 for (j = 32; j < SUB_CHAR_TABLE_ORDINARY_SLOTS; j++)
2316 optimize_sub_char_table (XCHAR_TABLE (elt)->contents + j, dim);
2317 optimize_sub_char_table (XCHAR_TABLE (table)->contents + i, dim);
2318 }
2319 return Qnil;
2320}
2321
e03f7933 2322\f
46ed603f 2323/* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
c8640abf
RS
2324 character or group of characters that share a value.
2325 DEPTH is the current depth in the originally specified
2326 chartable, and INDICES contains the vector indices
46ed603f
RS
2327 for the levels our callers have descended.
2328
2329 ARG is passed to C_FUNCTION when that is called. */
c8640abf
RS
2330
2331void
46ed603f 2332map_char_table (c_function, function, subtable, arg, depth, indices)
22e6f12b
AS
2333 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
2334 Lisp_Object function, subtable, arg, *indices;
1847b19b 2335 int depth;
e03f7933 2336{
3720677d 2337 int i, to;
e03f7933 2338
a8283a4a 2339 if (depth == 0)
3720677d
KH
2340 {
2341 /* At first, handle ASCII and 8-bit European characters. */
2342 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
2343 {
46ed603f 2344 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
3720677d 2345 if (c_function)
46ed603f 2346 (*c_function) (arg, make_number (i), elt);
3720677d
KH
2347 else
2348 call2 (function, make_number (i), elt);
2349 }
ea35ce3d
RS
2350#if 0 /* If the char table has entries for higher characters,
2351 we should report them. */
de86fcba
KH
2352 if (NILP (current_buffer->enable_multibyte_characters))
2353 return;
ea35ce3d 2354#endif
3720677d
KH
2355 to = CHAR_TABLE_ORDINARY_SLOTS;
2356 }
a8283a4a 2357 else
e03f7933 2358 {
a3b210c4
KH
2359 int charset = XFASTINT (indices[0]) - 128;
2360
de86fcba 2361 i = 32;
3720677d 2362 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
a3b210c4
KH
2363 if (CHARSET_CHARS (charset) == 94)
2364 i++, to--;
e03f7933
RS
2365 }
2366
7e798f25 2367 for (; i < to; i++)
e03f7933 2368 {
a3b210c4
KH
2369 Lisp_Object elt;
2370 int charset;
3720677d 2371
a3b210c4 2372 elt = XCHAR_TABLE (subtable)->contents[i];
09ee221d 2373 XSETFASTINT (indices[depth], i);
a3b210c4 2374 charset = XFASTINT (indices[0]) - 128;
df2fbceb
KH
2375 if (depth == 0
2376 && (!CHARSET_DEFINED_P (charset)
2377 || charset == CHARSET_8_BIT_CONTROL
2378 || charset == CHARSET_8_BIT_GRAPHIC))
a3b210c4 2379 continue;
3720677d
KH
2380
2381 if (SUB_CHAR_TABLE_P (elt))
2382 {
2383 if (depth >= 3)
2384 error ("Too deep char table");
7e798f25 2385 map_char_table (c_function, function, elt, arg, depth + 1, indices);
3720677d 2386 }
e03f7933 2387 else
a8283a4a 2388 {
a3b210c4 2389 int c1, c2, c;
3720677d 2390
a3b210c4
KH
2391 if (NILP (elt))
2392 elt = XCHAR_TABLE (subtable)->defalt;
2393 c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
2394 c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
2efdd1b9 2395 c = MAKE_CHAR (charset, c1, c2);
a3b210c4
KH
2396 if (c_function)
2397 (*c_function) (arg, make_number (c), elt);
2398 else
2399 call2 (function, make_number (c), elt);
b4f334f7 2400 }
e03f7933
RS
2401 }
2402}
2403
2404DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
2405 2, 2, 0,
7e798f25 2406 "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
e03f7933 2407FUNCTION is called with two arguments--a key and a value.\n\
7e798f25 2408The key is always a possible IDX argument to `aref'.")
88fe8140
EN
2409 (function, char_table)
2410 Lisp_Object function, char_table;
e03f7933 2411{
3720677d 2412 /* The depth of char table is at most 3. */
7e798f25
KH
2413 Lisp_Object indices[3];
2414
2415 CHECK_CHAR_TABLE (char_table, 1);
e03f7933 2416
46ed603f 2417 map_char_table (NULL, function, char_table, char_table, 0, indices);
e03f7933
RS
2418 return Qnil;
2419}
2420\f
7b863bd5
JB
2421/* ARGSUSED */
2422Lisp_Object
2423nconc2 (s1, s2)
2424 Lisp_Object s1, s2;
2425{
2426#ifdef NO_ARG_ARRAY
2427 Lisp_Object args[2];
2428 args[0] = s1;
2429 args[1] = s2;
2430 return Fnconc (2, args);
2431#else
2432 return Fnconc (2, &s1);
2433#endif /* NO_ARG_ARRAY */
2434}
2435
2436DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
2437 "Concatenate any number of lists by altering them.\n\
2438Only the last argument is not altered, and need not be a list.")
2439 (nargs, args)
2440 int nargs;
2441 Lisp_Object *args;
2442{
2443 register int argnum;
2444 register Lisp_Object tail, tem, val;
2445
2446 val = Qnil;
2447
2448 for (argnum = 0; argnum < nargs; argnum++)
2449 {
2450 tem = args[argnum];
265a9e55 2451 if (NILP (tem)) continue;
7b863bd5 2452
265a9e55 2453 if (NILP (val))
7b863bd5
JB
2454 val = tem;
2455
2456 if (argnum + 1 == nargs) break;
2457
2458 if (!CONSP (tem))
2459 tem = wrong_type_argument (Qlistp, tem);
2460
2461 while (CONSP (tem))
2462 {
2463 tail = tem;
2464 tem = Fcdr (tail);
2465 QUIT;
2466 }
2467
2468 tem = args[argnum + 1];
2469 Fsetcdr (tail, tem);
265a9e55 2470 if (NILP (tem))
7b863bd5
JB
2471 args[argnum + 1] = tail;
2472 }
2473
2474 return val;
2475}
2476\f
2477/* This is the guts of all mapping functions.
ea35ce3d
RS
2478 Apply FN to each element of SEQ, one by one,
2479 storing the results into elements of VALS, a C vector of Lisp_Objects.
2480 LENI is the length of VALS, which should also be the length of SEQ. */
7b863bd5
JB
2481
2482static void
2483mapcar1 (leni, vals, fn, seq)
2484 int leni;
2485 Lisp_Object *vals;
2486 Lisp_Object fn, seq;
2487{
2488 register Lisp_Object tail;
2489 Lisp_Object dummy;
2490 register int i;
2491 struct gcpro gcpro1, gcpro2, gcpro3;
2492
f5c75033
DL
2493 if (vals)
2494 {
2495 /* Don't let vals contain any garbage when GC happens. */
2496 for (i = 0; i < leni; i++)
2497 vals[i] = Qnil;
7b863bd5 2498
f5c75033
DL
2499 GCPRO3 (dummy, fn, seq);
2500 gcpro1.var = vals;
2501 gcpro1.nvars = leni;
2502 }
2503 else
2504 GCPRO2 (fn, seq);
7b863bd5
JB
2505 /* We need not explicitly protect `tail' because it is used only on lists, and
2506 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
2507
7650760e 2508 if (VECTORP (seq))
7b863bd5
JB
2509 {
2510 for (i = 0; i < leni; i++)
2511 {
2512 dummy = XVECTOR (seq)->contents[i];
f5c75033
DL
2513 dummy = call1 (fn, dummy);
2514 if (vals)
2515 vals[i] = dummy;
7b863bd5
JB
2516 }
2517 }
33aa0881
KH
2518 else if (BOOL_VECTOR_P (seq))
2519 {
2520 for (i = 0; i < leni; i++)
2521 {
2522 int byte;
2523 byte = XBOOL_VECTOR (seq)->data[i / BITS_PER_CHAR];
2524 if (byte & (1 << (i % BITS_PER_CHAR)))
2525 dummy = Qt;
2526 else
2527 dummy = Qnil;
2528
f5c75033
DL
2529 dummy = call1 (fn, dummy);
2530 if (vals)
2531 vals[i] = dummy;
33aa0881
KH
2532 }
2533 }
ea35ce3d
RS
2534 else if (STRINGP (seq))
2535 {
ea35ce3d
RS
2536 int i_byte;
2537
2538 for (i = 0, i_byte = 0; i < leni;)
2539 {
2540 int c;
0ab6a3d8
KH
2541 int i_before = i;
2542
2543 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte);
ea35ce3d 2544 XSETFASTINT (dummy, c);
f5c75033
DL
2545 dummy = call1 (fn, dummy);
2546 if (vals)
2547 vals[i_before] = dummy;
ea35ce3d
RS
2548 }
2549 }
7b863bd5
JB
2550 else /* Must be a list, since Flength did not get an error */
2551 {
2552 tail = seq;
2553 for (i = 0; i < leni; i++)
2554 {
f5c75033
DL
2555 dummy = call1 (fn, Fcar (tail));
2556 if (vals)
2557 vals[i] = dummy;
70949dac 2558 tail = XCDR (tail);
7b863bd5
JB
2559 }
2560 }
2561
2562 UNGCPRO;
2563}
2564
2565DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
88fe8140
EN
2566 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2567In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
33aa0881
KH
2568SEPARATOR results in spaces between the values returned by FUNCTION.\n\
2569SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2570 (function, sequence, separator)
2571 Lisp_Object function, sequence, separator;
7b863bd5
JB
2572{
2573 Lisp_Object len;
2574 register int leni;
2575 int nargs;
2576 register Lisp_Object *args;
2577 register int i;
2578 struct gcpro gcpro1;
2579
88fe8140 2580 len = Flength (sequence);
7b863bd5
JB
2581 leni = XINT (len);
2582 nargs = leni + leni - 1;
2583 if (nargs < 0) return build_string ("");
2584
2585 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2586
88fe8140
EN
2587 GCPRO1 (separator);
2588 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2589 UNGCPRO;
2590
2591 for (i = leni - 1; i >= 0; i--)
2592 args[i + i] = args[i];
b4f334f7 2593
7b863bd5 2594 for (i = 1; i < nargs; i += 2)
88fe8140 2595 args[i] = separator;
7b863bd5
JB
2596
2597 return Fconcat (nargs, args);
2598}
2599
2600DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2601 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2602The result is a list just as long as SEQUENCE.\n\
33aa0881 2603SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2604 (function, sequence)
2605 Lisp_Object function, sequence;
7b863bd5
JB
2606{
2607 register Lisp_Object len;
2608 register int leni;
2609 register Lisp_Object *args;
2610
88fe8140 2611 len = Flength (sequence);
7b863bd5
JB
2612 leni = XFASTINT (len);
2613 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2614
88fe8140 2615 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2616
2617 return Flist (leni, args);
2618}
f5c75033
DL
2619
2620DEFUN ("mapc", Fmapc, Smapc, 2, 2, 0,
2621 "Apply FUNCTION to each element of SEQUENCE for side effects only.\n\
2622Unlike `mapcar', don't accumulate the results. Return SEQUENCE.\n\
2623SEQUENCE may be a list, a vector, a bool-vector, or a string.")
2624 (function, sequence)
2625 Lisp_Object function, sequence;
2626{
2627 register int leni;
2628
2629 leni = XFASTINT (Flength (sequence));
2630 mapcar1 (leni, 0, function, sequence);
2631
2632 return sequence;
2633}
7b863bd5
JB
2634\f
2635/* Anything that calls this function must protect from GC! */
2636
2637DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2638 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
c763f396
RS
2639Takes one argument, which is the string to display to ask the question.\n\
2640It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
7b863bd5 2641No confirmation of the answer is requested; a single character is enough.\n\
2b8503ea 2642Also accepts Space to mean yes, or Delete to mean no. \(Actually, it uses\n\
71a8e74b 2643the bindings in `query-replace-map'; see the documentation of that variable\n\
2b8503ea
KH
2644for more information. In this case, the useful bindings are `act', `skip',\n\
2645`recenter', and `quit'.\)\n\
0c6ca44b
DL
2646\n\
2647Under a windowing system a dialog box will be used if `last-nonmenu-event'\n\
2648is nil.")
7b863bd5
JB
2649 (prompt)
2650 Lisp_Object prompt;
2651{
2b8503ea 2652 register Lisp_Object obj, key, def, map;
f5313ed9 2653 register int answer;
7b863bd5
JB
2654 Lisp_Object xprompt;
2655 Lisp_Object args[2];
7b863bd5 2656 struct gcpro gcpro1, gcpro2;
eb4ffa4e
RS
2657 int count = specpdl_ptr - specpdl;
2658
2659 specbind (Qcursor_in_echo_area, Qt);
7b863bd5 2660
f5313ed9
RS
2661 map = Fsymbol_value (intern ("query-replace-map"));
2662
7b863bd5
JB
2663 CHECK_STRING (prompt, 0);
2664 xprompt = prompt;
2665 GCPRO2 (prompt, xprompt);
2666
eff95916
GM
2667#ifdef HAVE_X_WINDOWS
2668 if (display_busy_cursor_p)
2669 cancel_busy_cursor ();
2670#endif
2671
7b863bd5
JB
2672 while (1)
2673 {
eb4ffa4e 2674
0ef68e8a 2675#ifdef HAVE_MENUS
588064ce 2676 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2677 && use_dialog_box
0ef68e8a 2678 && have_menus_p ())
1db4cfb2
RS
2679 {
2680 Lisp_Object pane, menu;
a3b14a45 2681 redisplay_preserve_echo_area ();
1db4cfb2
RS
2682 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2683 Fcons (Fcons (build_string ("No"), Qnil),
2684 Qnil));
ec26e1b9 2685 menu = Fcons (prompt, pane);
d2f28f78 2686 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2687 answer = !NILP (obj);
2688 break;
2689 }
0ef68e8a 2690#endif /* HAVE_MENUS */
dfa89228 2691 cursor_in_echo_area = 1;
b312cc52 2692 choose_minibuf_frame ();
ea35ce3d 2693 message_with_string ("%s(y or n) ", xprompt, 0);
7b863bd5 2694
2d8e7e1f
RS
2695 if (minibuffer_auto_raise)
2696 {
2697 Lisp_Object mini_frame;
2698
2699 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2700
2701 Fraise_frame (mini_frame);
2702 }
2703
7ba13c57 2704 obj = read_filtered_event (1, 0, 0, 0);
dfa89228
KH
2705 cursor_in_echo_area = 0;
2706 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2707 QUIT;
a63f658b 2708
f5313ed9 2709 key = Fmake_vector (make_number (1), obj);
aad2a123 2710 def = Flookup_key (map, key, Qt);
7b863bd5 2711
f5313ed9
RS
2712 if (EQ (def, intern ("skip")))
2713 {
2714 answer = 0;
2715 break;
2716 }
2717 else if (EQ (def, intern ("act")))
2718 {
2719 answer = 1;
2720 break;
2721 }
29944b73
RS
2722 else if (EQ (def, intern ("recenter")))
2723 {
2724 Frecenter (Qnil);
2725 xprompt = prompt;
2726 continue;
2727 }
f5313ed9 2728 else if (EQ (def, intern ("quit")))
7b863bd5 2729 Vquit_flag = Qt;
ec63af1b
RS
2730 /* We want to exit this command for exit-prefix,
2731 and this is the only way to do it. */
2732 else if (EQ (def, intern ("exit-prefix")))
2733 Vquit_flag = Qt;
f5313ed9 2734
7b863bd5 2735 QUIT;
20aa96aa
JB
2736
2737 /* If we don't clear this, then the next call to read_char will
2738 return quit_char again, and we'll enter an infinite loop. */
088880f1 2739 Vquit_flag = Qnil;
7b863bd5
JB
2740
2741 Fding (Qnil);
2742 Fdiscard_input ();
2743 if (EQ (xprompt, prompt))
2744 {
2745 args[0] = build_string ("Please answer y or n. ");
2746 args[1] = prompt;
2747 xprompt = Fconcat (2, args);
2748 }
2749 }
2750 UNGCPRO;
6a8a9750 2751
09c95874
RS
2752 if (! noninteractive)
2753 {
2754 cursor_in_echo_area = -1;
ea35ce3d
RS
2755 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2756 xprompt, 0);
09c95874 2757 }
6a8a9750 2758
eb4ffa4e 2759 unbind_to (count, Qnil);
f5313ed9 2760 return answer ? Qt : Qnil;
7b863bd5
JB
2761}
2762\f
2763/* This is how C code calls `yes-or-no-p' and allows the user
2764 to redefined it.
2765
2766 Anything that calls this function must protect from GC! */
2767
2768Lisp_Object
2769do_yes_or_no_p (prompt)
2770 Lisp_Object prompt;
2771{
2772 return call1 (intern ("yes-or-no-p"), prompt);
2773}
2774
2775/* Anything that calls this function must protect from GC! */
2776
2777DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
c763f396
RS
2778 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2779Takes one argument, which is the string to display to ask the question.\n\
2780It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2781The user must confirm the answer with RET,\n\
0c6ca44b
DL
2782and can edit it until it has been confirmed.\n\
2783\n\
2784Under a windowing system a dialog box will be used if `last-nonmenu-event'\n\
2785is nil.")
7b863bd5
JB
2786 (prompt)
2787 Lisp_Object prompt;
2788{
2789 register Lisp_Object ans;
2790 Lisp_Object args[2];
2791 struct gcpro gcpro1;
2792
2793 CHECK_STRING (prompt, 0);
2794
0ef68e8a 2795#ifdef HAVE_MENUS
b4f334f7 2796 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2797 && use_dialog_box
0ef68e8a 2798 && have_menus_p ())
1db4cfb2
RS
2799 {
2800 Lisp_Object pane, menu, obj;
a3b14a45 2801 redisplay_preserve_echo_area ();
1db4cfb2
RS
2802 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2803 Fcons (Fcons (build_string ("No"), Qnil),
2804 Qnil));
2805 GCPRO1 (pane);
ec26e1b9 2806 menu = Fcons (prompt, pane);
b5ccb0a9 2807 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2808 UNGCPRO;
2809 return obj;
2810 }
0ef68e8a 2811#endif /* HAVE_MENUS */
1db4cfb2 2812
7b863bd5
JB
2813 args[0] = prompt;
2814 args[1] = build_string ("(yes or no) ");
2815 prompt = Fconcat (2, args);
2816
2817 GCPRO1 (prompt);
1db4cfb2 2818
7b863bd5
JB
2819 while (1)
2820 {
0ce830bc 2821 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
b24014d4
KH
2822 Qyes_or_no_p_history, Qnil,
2823 Qnil));
7b863bd5
JB
2824 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2825 {
2826 UNGCPRO;
2827 return Qt;
2828 }
2829 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2830 {
2831 UNGCPRO;
2832 return Qnil;
2833 }
2834
2835 Fding (Qnil);
2836 Fdiscard_input ();
2837 message ("Please answer yes or no.");
99dc4745 2838 Fsleep_for (make_number (2), Qnil);
7b863bd5 2839 }
7b863bd5
JB
2840}
2841\f
f4b50f66 2842DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
7b863bd5
JB
2843 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
2844Each of the three load averages is multiplied by 100,\n\
daa37602 2845then converted to integer.\n\
f4b50f66
RS
2846When USE-FLOATS is non-nil, floats will be used instead of integers.\n\
2847These floats are not multiplied by 100.\n\n\
daa37602
JB
2848If the 5-minute or 15-minute load averages are not available, return a\n\
2849shortened list, containing only those averages which are available.")
f4b50f66
RS
2850 (use_floats)
2851 Lisp_Object use_floats;
7b863bd5 2852{
daa37602
JB
2853 double load_ave[3];
2854 int loads = getloadavg (load_ave, 3);
f4b50f66 2855 Lisp_Object ret = Qnil;
7b863bd5 2856
daa37602
JB
2857 if (loads < 0)
2858 error ("load-average not implemented for this operating system");
2859
f4b50f66
RS
2860 while (loads-- > 0)
2861 {
2862 Lisp_Object load = (NILP (use_floats) ?
2863 make_number ((int) (100.0 * load_ave[loads]))
2864 : make_float (load_ave[loads]));
2865 ret = Fcons (load, ret);
2866 }
daa37602
JB
2867
2868 return ret;
2869}
7b863bd5
JB
2870\f
2871Lisp_Object Vfeatures;
2872
2873DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
2874 "Returns t if FEATURE is present in this Emacs.\n\
2875Use this to conditionalize execution of lisp code based on the presence or\n\
2876absence of emacs or environment extensions.\n\
2877Use `provide' to declare that a feature is available.\n\
2878This function looks at the value of the variable `features'.")
b4f334f7 2879 (feature)
7b863bd5
JB
2880 Lisp_Object feature;
2881{
2882 register Lisp_Object tem;
2883 CHECK_SYMBOL (feature, 0);
2884 tem = Fmemq (feature, Vfeatures);
265a9e55 2885 return (NILP (tem)) ? Qnil : Qt;
7b863bd5
JB
2886}
2887
2888DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
2889 "Announce that FEATURE is a feature of the current Emacs.")
b4f334f7 2890 (feature)
7b863bd5
JB
2891 Lisp_Object feature;
2892{
2893 register Lisp_Object tem;
2894 CHECK_SYMBOL (feature, 0);
265a9e55 2895 if (!NILP (Vautoload_queue))
7b863bd5
JB
2896 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
2897 tem = Fmemq (feature, Vfeatures);
265a9e55 2898 if (NILP (tem))
7b863bd5 2899 Vfeatures = Fcons (feature, Vfeatures);
68732608 2900 LOADHIST_ATTACH (Fcons (Qprovide, feature));
7b863bd5
JB
2901 return feature;
2902}
2903
53d5acf5 2904DEFUN ("require", Frequire, Srequire, 1, 3, 0,
7b863bd5
JB
2905 "If feature FEATURE is not loaded, load it from FILENAME.\n\
2906If FEATURE is not a member of the list `features', then the feature\n\
2907is not loaded; so load the file FILENAME.\n\
f0c030b3 2908If FILENAME is omitted, the printname of FEATURE is used as the file name,\n\
53d5acf5
RS
2909but in this case `load' insists on adding the suffix `.el' or `.elc'.\n\
2910If the optional third argument NOERROR is non-nil,\n\
2911then return nil if the file is not found.\n\
2912Normally the return value is FEATURE.")
2913 (feature, file_name, noerror)
2914 Lisp_Object feature, file_name, noerror;
7b863bd5
JB
2915{
2916 register Lisp_Object tem;
2917 CHECK_SYMBOL (feature, 0);
2918 tem = Fmemq (feature, Vfeatures);
68732608 2919 LOADHIST_ATTACH (Fcons (Qrequire, feature));
265a9e55 2920 if (NILP (tem))
7b863bd5
JB
2921 {
2922 int count = specpdl_ptr - specpdl;
2923
2924 /* Value saved here is to be restored into Vautoload_queue */
2925 record_unwind_protect (un_autoload, Vautoload_queue);
2926 Vautoload_queue = Qt;
2927
53d5acf5
RS
2928 tem = Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
2929 noerror, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
2930 /* If load failed entirely, return nil. */
2931 if (NILP (tem))
41857307 2932 return unbind_to (count, Qnil);
7b863bd5
JB
2933
2934 tem = Fmemq (feature, Vfeatures);
265a9e55 2935 if (NILP (tem))
7b863bd5 2936 error ("Required feature %s was not provided",
fdb5bec0 2937 XSYMBOL (feature)->name->data);
7b863bd5
JB
2938
2939 /* Once loading finishes, don't undo it. */
2940 Vautoload_queue = Qt;
2941 feature = unbind_to (count, feature);
2942 }
2943 return feature;
2944}
2945\f
b4f334f7
KH
2946/* Primitives for work of the "widget" library.
2947 In an ideal world, this section would not have been necessary.
2948 However, lisp function calls being as slow as they are, it turns
2949 out that some functions in the widget library (wid-edit.el) are the
2950 bottleneck of Widget operation. Here is their translation to C,
2951 for the sole reason of efficiency. */
2952
2953DEFUN ("widget-plist-member", Fwidget_plist_member, Swidget_plist_member, 2, 2, 0,
2954 "Return non-nil if PLIST has the property PROP.\n\
2955PLIST is a property list, which is a list of the form\n\
2956\(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
2957Unlike `plist-get', this allows you to distinguish between a missing\n\
2958property and a property with the value nil.\n\
2959The value is actually the tail of PLIST whose car is PROP.")
2960 (plist, prop)
2961 Lisp_Object plist, prop;
2962{
2963 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2964 {
2965 QUIT;
2966 plist = XCDR (plist);
2967 plist = CDR (plist);
2968 }
2969 return plist;
2970}
2971
2972DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
2973 "In WIDGET, set PROPERTY to VALUE.\n\
2974The value can later be retrieved with `widget-get'.")
2975 (widget, property, value)
2976 Lisp_Object widget, property, value;
2977{
2978 CHECK_CONS (widget, 1);
2979 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
f7993597 2980 return value;
b4f334f7
KH
2981}
2982
2983DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
2984 "In WIDGET, get the value of PROPERTY.\n\
2985The value could either be specified when the widget was created, or\n\
2986later with `widget-put'.")
2987 (widget, property)
2988 Lisp_Object widget, property;
2989{
2990 Lisp_Object tmp;
2991
2992 while (1)
2993 {
2994 if (NILP (widget))
2995 return Qnil;
2996 CHECK_CONS (widget, 1);
2997 tmp = Fwidget_plist_member (XCDR (widget), property);
2998 if (CONSP (tmp))
2999 {
3000 tmp = XCDR (tmp);
3001 return CAR (tmp);
3002 }
3003 tmp = XCAR (widget);
3004 if (NILP (tmp))
3005 return Qnil;
3006 widget = Fget (tmp, Qwidget_type);
3007 }
3008}
3009
3010DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
3011 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
3012ARGS are passed as extra arguments to the function.")
3013 (nargs, args)
3014 int nargs;
3015 Lisp_Object *args;
3016{
3017 /* This function can GC. */
3018 Lisp_Object newargs[3];
3019 struct gcpro gcpro1, gcpro2;
3020 Lisp_Object result;
3021
3022 newargs[0] = Fwidget_get (args[0], args[1]);
3023 newargs[1] = args[0];
3024 newargs[2] = Flist (nargs - 2, args + 2);
3025 GCPRO2 (newargs[0], newargs[2]);
3026 result = Fapply (3, newargs);
3027 UNGCPRO;
3028 return result;
3029}
3030\f
24c129e4
KH
3031/* base64 encode/decode functions.
3032 Based on code from GNU recode. */
3033
3034#define MIME_LINE_LENGTH 76
3035
3036#define IS_ASCII(Character) \
3037 ((Character) < 128)
3038#define IS_BASE64(Character) \
3039 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0)
9a092df0
PF
3040#define IS_BASE64_IGNORABLE(Character) \
3041 ((Character) == ' ' || (Character) == '\t' || (Character) == '\n' \
3042 || (Character) == '\f' || (Character) == '\r')
3043
3044/* Used by base64_decode_1 to retrieve a non-base64-ignorable
3045 character or return retval if there are no characters left to
3046 process. */
3047#define READ_QUADRUPLET_BYTE(retval) \
3048 do \
3049 { \
3050 if (i == length) \
3051 return (retval); \
3052 c = from[i++]; \
3053 } \
3054 while (IS_BASE64_IGNORABLE (c))
24c129e4 3055
4b2e75e6
EZ
3056/* Don't use alloca for regions larger than this, lest we overflow
3057 their stack. */
3058#define MAX_ALLOCA 16*1024
3059
24c129e4
KH
3060/* Table of characters coding the 64 values. */
3061static char base64_value_to_char[64] =
3062{
3063 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */
3064 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */
3065 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */
3066 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 30-39 */
3067 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */
3068 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */
3069 '8', '9', '+', '/' /* 60-63 */
3070};
3071
3072/* Table of base64 values for first 128 characters. */
3073static short base64_char_to_value[128] =
3074{
3075 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
3076 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
3077 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */
3078 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */
3079 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */
3080 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */
3081 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */
3082 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */
3083 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */
3084 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */
3085 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */
3086 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
3087 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
3088};
3089
3090/* The following diagram shows the logical steps by which three octets
3091 get transformed into four base64 characters.
3092
3093 .--------. .--------. .--------.
3094 |aaaaaabb| |bbbbcccc| |ccdddddd|
3095 `--------' `--------' `--------'
3096 6 2 4 4 2 6
3097 .--------+--------+--------+--------.
3098 |00aaaaaa|00bbbbbb|00cccccc|00dddddd|
3099 `--------+--------+--------+--------'
3100
3101 .--------+--------+--------+--------.
3102 |AAAAAAAA|BBBBBBBB|CCCCCCCC|DDDDDDDD|
3103 `--------+--------+--------+--------'
3104
3105 The octets are divided into 6 bit chunks, which are then encoded into
3106 base64 characters. */
3107
3108
2efdd1b9 3109static int base64_encode_1 P_ ((const char *, char *, int, int, int));
24c129e4
KH
3110static int base64_decode_1 P_ ((const char *, char *, int));
3111
3112DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region,
3113 2, 3, "r",
46ac5b26 3114 "Base64-encode the region between BEG and END.\n\
15a9a50c 3115Return the length of the encoded text.\n\
24c129e4
KH
3116Optional third argument NO-LINE-BREAK means do not break long lines\n\
3117into shorter lines.")
3118 (beg, end, no_line_break)
3119 Lisp_Object beg, end, no_line_break;
3120{
3121 char *encoded;
3122 int allength, length;
3123 int ibeg, iend, encoded_length;
3124 int old_pos = PT;
3125
3126 validate_region (&beg, &end);
3127
3128 ibeg = CHAR_TO_BYTE (XFASTINT (beg));
3129 iend = CHAR_TO_BYTE (XFASTINT (end));
3130 move_gap_both (XFASTINT (beg), ibeg);
3131
3132 /* We need to allocate enough room for encoding the text.
3133 We need 33 1/3% more space, plus a newline every 76
3134 characters, and then we round up. */
3135 length = iend - ibeg;
3136 allength = length + length/3 + 1;
3137 allength += allength / MIME_LINE_LENGTH + 1 + 6;
3138
4b2e75e6
EZ
3139 if (allength <= MAX_ALLOCA)
3140 encoded = (char *) alloca (allength);
3141 else
3142 encoded = (char *) xmalloc (allength);
24c129e4 3143 encoded_length = base64_encode_1 (BYTE_POS_ADDR (ibeg), encoded, length,
2efdd1b9
KH
3144 NILP (no_line_break),
3145 !NILP (current_buffer->enable_multibyte_characters));
24c129e4
KH
3146 if (encoded_length > allength)
3147 abort ();
3148
2efdd1b9
KH
3149 if (encoded_length < 0)
3150 {
3151 /* The encoding wasn't possible. */
3152 if (length > MAX_ALLOCA)
3153 xfree (encoded);
3154 error ("Base64 encoding failed");
3155 }
3156
24c129e4
KH
3157 /* Now we have encoded the region, so we insert the new contents
3158 and delete the old. (Insert first in order to preserve markers.) */
8b835738 3159 SET_PT_BOTH (XFASTINT (beg), ibeg);
24c129e4 3160 insert (encoded, encoded_length);
4b2e75e6 3161 if (allength > MAX_ALLOCA)
8c217645 3162 xfree (encoded);
24c129e4
KH
3163 del_range_byte (ibeg + encoded_length, iend + encoded_length, 1);
3164
3165 /* If point was outside of the region, restore it exactly; else just
3166 move to the beginning of the region. */
3167 if (old_pos >= XFASTINT (end))
3168 old_pos += encoded_length - (XFASTINT (end) - XFASTINT (beg));
8b835738
AS
3169 else if (old_pos > XFASTINT (beg))
3170 old_pos = XFASTINT (beg);
24c129e4
KH
3171 SET_PT (old_pos);
3172
3173 /* We return the length of the encoded text. */
3174 return make_number (encoded_length);
3175}
3176
3177DEFUN ("base64-encode-string", Fbase64_encode_string, Sbase64_encode_string,
c22554ac
KH
3178 1, 2, 0,
3179 "Base64-encode STRING and return the result.\n\
3180Optional second argument NO-LINE-BREAK means do not break long lines\n\
3181into shorter lines.")
3182 (string, no_line_break)
915b8312 3183 Lisp_Object string, no_line_break;
24c129e4
KH
3184{
3185 int allength, length, encoded_length;
3186 char *encoded;
4b2e75e6 3187 Lisp_Object encoded_string;
24c129e4
KH
3188
3189 CHECK_STRING (string, 1);
3190
7f8a0840
KH
3191 /* We need to allocate enough room for encoding the text.
3192 We need 33 1/3% more space, plus a newline every 76
3193 characters, and then we round up. */
24c129e4 3194 length = STRING_BYTES (XSTRING (string));
7f8a0840
KH
3195 allength = length + length/3 + 1;
3196 allength += allength / MIME_LINE_LENGTH + 1 + 6;
24c129e4
KH
3197
3198 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3199 if (allength <= MAX_ALLOCA)
3200 encoded = (char *) alloca (allength);
3201 else
3202 encoded = (char *) xmalloc (allength);
24c129e4
KH
3203
3204 encoded_length = base64_encode_1 (XSTRING (string)->data,
2efdd1b9
KH
3205 encoded, length, NILP (no_line_break),
3206 STRING_MULTIBYTE (string));
24c129e4
KH
3207 if (encoded_length > allength)
3208 abort ();
3209
2efdd1b9
KH
3210 if (encoded_length < 0)
3211 {
3212 /* The encoding wasn't possible. */
3213 if (length > MAX_ALLOCA)
3214 xfree (encoded);
3215 error ("Base64 encoding failed");
3216 }
3217
4b2e75e6
EZ
3218 encoded_string = make_unibyte_string (encoded, encoded_length);
3219 if (allength > MAX_ALLOCA)
8c217645 3220 xfree (encoded);
4b2e75e6
EZ
3221
3222 return encoded_string;
24c129e4
KH
3223}
3224
3225static int
2efdd1b9 3226base64_encode_1 (from, to, length, line_break, multibyte)
24c129e4
KH
3227 const char *from;
3228 char *to;
3229 int length;
3230 int line_break;
2efdd1b9 3231 int multibyte;
24c129e4
KH
3232{
3233 int counter = 0, i = 0;
3234 char *e = to;
3235 unsigned char c;
3236 unsigned int value;
2efdd1b9 3237 int bytes;
24c129e4
KH
3238
3239 while (i < length)
3240 {
2efdd1b9
KH
3241 if (multibyte)
3242 {
3243 c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
3244 if (!SINGLE_BYTE_CHAR_P (c))
3245 return -1;
3246 i += bytes;
3247 }
3248 else
3249 c = from[i++];
24c129e4
KH
3250
3251 /* Wrap line every 76 characters. */
3252
3253 if (line_break)
3254 {
3255 if (counter < MIME_LINE_LENGTH / 4)
3256 counter++;
3257 else
3258 {
3259 *e++ = '\n';
3260 counter = 1;
3261 }
3262 }
3263
3264 /* Process first byte of a triplet. */
3265
3266 *e++ = base64_value_to_char[0x3f & c >> 2];
3267 value = (0x03 & c) << 4;
3268
3269 /* Process second byte of a triplet. */
3270
3271 if (i == length)
3272 {
3273 *e++ = base64_value_to_char[value];
3274 *e++ = '=';
3275 *e++ = '=';
3276 break;
3277 }
3278
2efdd1b9
KH
3279 if (multibyte)
3280 {
3281 c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
3282 i += bytes;
3283 }
3284 else
3285 c = from[i++];
24c129e4
KH
3286
3287 *e++ = base64_value_to_char[value | (0x0f & c >> 4)];
3288 value = (0x0f & c) << 2;
3289
3290 /* Process third byte of a triplet. */
3291
3292 if (i == length)
3293 {
3294 *e++ = base64_value_to_char[value];
3295 *e++ = '=';
3296 break;
3297 }
3298
2efdd1b9
KH
3299 if (multibyte)
3300 {
3301 c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
3302 i += bytes;
3303 }
3304 else
3305 c = from[i++];
24c129e4
KH
3306
3307 *e++ = base64_value_to_char[value | (0x03 & c >> 6)];
3308 *e++ = base64_value_to_char[0x3f & c];
3309 }
3310
24c129e4
KH
3311 return e - to;
3312}
3313
3314
3315DEFUN ("base64-decode-region", Fbase64_decode_region, Sbase64_decode_region,
3316 2, 2, "r",
46ac5b26 3317 "Base64-decode the region between BEG and END.\n\
15a9a50c 3318Return the length of the decoded text.\n\
3d6c79c5 3319If the region can't be decoded, signal an error and don't modify the buffer.")
24c129e4
KH
3320 (beg, end)
3321 Lisp_Object beg, end;
3322{
3323 int ibeg, iend, length;
3324 char *decoded;
3325 int old_pos = PT;
3326 int decoded_length;
9b703a38 3327 int inserted_chars;
24c129e4
KH
3328
3329 validate_region (&beg, &end);
3330
3331 ibeg = CHAR_TO_BYTE (XFASTINT (beg));
3332 iend = CHAR_TO_BYTE (XFASTINT (end));
3333
3334 length = iend - ibeg;
3335 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3336 if (length <= MAX_ALLOCA)
3337 decoded = (char *) alloca (length);
3338 else
3339 decoded = (char *) xmalloc (length);
24c129e4
KH
3340
3341 move_gap_both (XFASTINT (beg), ibeg);
3342 decoded_length = base64_decode_1 (BYTE_POS_ADDR (ibeg), decoded, length);
3343 if (decoded_length > length)
3344 abort ();
3345
3346 if (decoded_length < 0)
8c217645
KH
3347 {
3348 /* The decoding wasn't possible. */
3349 if (length > MAX_ALLOCA)
3350 xfree (decoded);
3d6c79c5 3351 error ("Base64 decoding failed");
8c217645 3352 }
24c129e4 3353
2efdd1b9
KH
3354 inserted_chars = decoded_length;
3355 if (!NILP (current_buffer->enable_multibyte_characters))
3356 decoded_length = str_to_multibyte (decoded, length, decoded_length);
3357
24c129e4
KH
3358 /* Now we have decoded the region, so we insert the new contents
3359 and delete the old. (Insert first in order to preserve markers.) */
2efdd1b9
KH
3360 TEMP_SET_PT_BOTH (XFASTINT (beg), ibeg);
3361 insert_1_both (decoded, inserted_chars, decoded_length, 0, 1, 0);
4b2e75e6 3362 if (length > MAX_ALLOCA)
8c217645 3363 xfree (decoded);
2efdd1b9
KH
3364 /* Delete the original text. */
3365 del_range_both (PT, PT_BYTE, XFASTINT (end) + inserted_chars,
3366 iend + decoded_length, 1);
24c129e4
KH
3367
3368 /* If point was outside of the region, restore it exactly; else just
3369 move to the beginning of the region. */
3370 if (old_pos >= XFASTINT (end))
9b703a38
KH
3371 old_pos += inserted_chars - (XFASTINT (end) - XFASTINT (beg));
3372 else if (old_pos > XFASTINT (beg))
3373 old_pos = XFASTINT (beg);
e52ad9c9 3374 SET_PT (old_pos > ZV ? ZV : old_pos);
24c129e4 3375
9b703a38 3376 return make_number (inserted_chars);
24c129e4
KH
3377}
3378
3379DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
3380 1, 1, 0,
3d6c79c5
GM
3381 "Base64-decode STRING and return the result.")
3382 (string)
24c129e4
KH
3383 Lisp_Object string;
3384{
3385 char *decoded;
3386 int length, decoded_length;
4b2e75e6 3387 Lisp_Object decoded_string;
24c129e4
KH
3388
3389 CHECK_STRING (string, 1);
3390
3391 length = STRING_BYTES (XSTRING (string));
3392 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3393 if (length <= MAX_ALLOCA)
3394 decoded = (char *) alloca (length);
3395 else
3396 decoded = (char *) xmalloc (length);
24c129e4
KH
3397
3398 decoded_length = base64_decode_1 (XSTRING (string)->data, decoded, length);
3399 if (decoded_length > length)
3400 abort ();
3d6c79c5 3401 else if (decoded_length >= 0)
2efdd1b9 3402 decoded_string = make_unibyte_string (decoded, decoded_length);
3d6c79c5
GM
3403 else
3404 decoded_string = Qnil;
24c129e4 3405
4b2e75e6 3406 if (length > MAX_ALLOCA)
8c217645 3407 xfree (decoded);
3d6c79c5
GM
3408 if (!STRINGP (decoded_string))
3409 error ("Base64 decoding failed");
4b2e75e6
EZ
3410
3411 return decoded_string;
24c129e4
KH
3412}
3413
3414static int
3415base64_decode_1 (from, to, length)
3416 const char *from;
3417 char *to;
3418 int length;
3419{
9a092df0 3420 int i = 0;
24c129e4
KH
3421 char *e = to;
3422 unsigned char c;
3423 unsigned long value;
3424
9a092df0 3425 while (1)
24c129e4 3426 {
9a092df0 3427 /* Process first byte of a quadruplet. */
24c129e4 3428
9a092df0 3429 READ_QUADRUPLET_BYTE (e-to);
24c129e4
KH
3430
3431 if (!IS_BASE64 (c))
3432 return -1;
3433 value = base64_char_to_value[c] << 18;
3434
3435 /* Process second byte of a quadruplet. */
3436
9a092df0 3437 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3438
3439 if (!IS_BASE64 (c))
3440 return -1;
3441 value |= base64_char_to_value[c] << 12;
3442
3443 *e++ = (unsigned char) (value >> 16);
3444
3445 /* Process third byte of a quadruplet. */
9a092df0
PF
3446
3447 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3448
3449 if (c == '=')
3450 {
9a092df0
PF
3451 READ_QUADRUPLET_BYTE (-1);
3452
24c129e4
KH
3453 if (c != '=')
3454 return -1;
3455 continue;
3456 }
3457
3458 if (!IS_BASE64 (c))
3459 return -1;
3460 value |= base64_char_to_value[c] << 6;
3461
3462 *e++ = (unsigned char) (0xff & value >> 8);
3463
3464 /* Process fourth byte of a quadruplet. */
3465
9a092df0 3466 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3467
3468 if (c == '=')
3469 continue;
3470
3471 if (!IS_BASE64 (c))
3472 return -1;
3473 value |= base64_char_to_value[c];
3474
3475 *e++ = (unsigned char) (0xff & value);
3476 }
24c129e4 3477}
d80c6c11
GM
3478
3479
3480\f
3481/***********************************************************************
3482 ***** *****
3483 ***** Hash Tables *****
3484 ***** *****
3485 ***********************************************************************/
3486
3487/* Implemented by gerd@gnu.org. This hash table implementation was
3488 inspired by CMUCL hash tables. */
3489
3490/* Ideas:
3491
3492 1. For small tables, association lists are probably faster than
3493 hash tables because they have lower overhead.
3494
3495 For uses of hash tables where the O(1) behavior of table
3496 operations is not a requirement, it might therefore be a good idea
3497 not to hash. Instead, we could just do a linear search in the
3498 key_and_value vector of the hash table. This could be done
3499 if a `:linear-search t' argument is given to make-hash-table. */
3500
3501
3502/* Return the contents of vector V at index IDX. */
3503
3504#define AREF(V, IDX) XVECTOR (V)->contents[IDX]
3505
3506/* Value is the key part of entry IDX in hash table H. */
3507
3508#define HASH_KEY(H, IDX) AREF ((H)->key_and_value, 2 * (IDX))
3509
3510/* Value is the value part of entry IDX in hash table H. */
3511
3512#define HASH_VALUE(H, IDX) AREF ((H)->key_and_value, 2 * (IDX) + 1)
3513
3514/* Value is the index of the next entry following the one at IDX
3515 in hash table H. */
3516
3517#define HASH_NEXT(H, IDX) AREF ((H)->next, (IDX))
3518
3519/* Value is the hash code computed for entry IDX in hash table H. */
3520
3521#define HASH_HASH(H, IDX) AREF ((H)->hash, (IDX))
3522
3523/* Value is the index of the element in hash table H that is the
3524 start of the collision list at index IDX in the index vector of H. */
3525
3526#define HASH_INDEX(H, IDX) AREF ((H)->index, (IDX))
3527
3528/* Value is the size of hash table H. */
3529
3530#define HASH_TABLE_SIZE(H) XVECTOR ((H)->next)->size
3531
3532/* The list of all weak hash tables. Don't staticpro this one. */
3533
3534Lisp_Object Vweak_hash_tables;
3535
3536/* Various symbols. */
3537
f899c503 3538Lisp_Object Qhash_table_p, Qeq, Qeql, Qequal, Qkey, Qvalue;
ee0403b3 3539Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
d80c6c11
GM
3540Lisp_Object Qhash_table_test;
3541
3542/* Function prototypes. */
3543
3544static struct Lisp_Hash_Table *check_hash_table P_ ((Lisp_Object));
3545static int next_almost_prime P_ ((int));
3546static int get_key_arg P_ ((Lisp_Object, int, Lisp_Object *, char *));
d80c6c11 3547static void maybe_resize_hash_table P_ ((struct Lisp_Hash_Table *));
d80c6c11
GM
3548static int cmpfn_eql P_ ((struct Lisp_Hash_Table *, Lisp_Object, unsigned,
3549 Lisp_Object, unsigned));
3550static int cmpfn_equal P_ ((struct Lisp_Hash_Table *, Lisp_Object, unsigned,
3551 Lisp_Object, unsigned));
3552static int cmpfn_user_defined P_ ((struct Lisp_Hash_Table *, Lisp_Object,
3553 unsigned, Lisp_Object, unsigned));
3554static unsigned hashfn_eq P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3555static unsigned hashfn_eql P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3556static unsigned hashfn_equal P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3557static unsigned hashfn_user_defined P_ ((struct Lisp_Hash_Table *,
3558 Lisp_Object));
3559static unsigned sxhash_string P_ ((unsigned char *, int));
3560static unsigned sxhash_list P_ ((Lisp_Object, int));
3561static unsigned sxhash_vector P_ ((Lisp_Object, int));
3562static unsigned sxhash_bool_vector P_ ((Lisp_Object));
a0b581cc 3563static int sweep_weak_table P_ ((struct Lisp_Hash_Table *, int));
d80c6c11
GM
3564
3565
3566\f
3567/***********************************************************************
3568 Utilities
3569 ***********************************************************************/
3570
3571/* If OBJ is a Lisp hash table, return a pointer to its struct
3572 Lisp_Hash_Table. Otherwise, signal an error. */
3573
3574static struct Lisp_Hash_Table *
3575check_hash_table (obj)
3576 Lisp_Object obj;
3577{
3578 CHECK_HASH_TABLE (obj, 0);
3579 return XHASH_TABLE (obj);
3580}
3581
3582
3583/* Value is the next integer I >= N, N >= 0 which is "almost" a prime
3584 number. */
3585
3586static int
3587next_almost_prime (n)
3588 int n;
3589{
3590 if (n % 2 == 0)
3591 n += 1;
3592 if (n % 3 == 0)
3593 n += 2;
3594 if (n % 7 == 0)
3595 n += 4;
3596 return n;
3597}
3598
3599
3600/* Find KEY in ARGS which has size NARGS. Don't consider indices for
3601 which USED[I] is non-zero. If found at index I in ARGS, set
3602 USED[I] and USED[I + 1] to 1, and return I + 1. Otherwise return
3603 -1. This function is used to extract a keyword/argument pair from
3604 a DEFUN parameter list. */
3605
3606static int
3607get_key_arg (key, nargs, args, used)
3608 Lisp_Object key;
3609 int nargs;
3610 Lisp_Object *args;
3611 char *used;
3612{
3613 int i;
3614
3615 for (i = 0; i < nargs - 1; ++i)
3616 if (!used[i] && EQ (args[i], key))
3617 break;
3618
3619 if (i >= nargs - 1)
3620 i = -1;
3621 else
3622 {
3623 used[i++] = 1;
3624 used[i] = 1;
3625 }
3626
3627 return i;
3628}
3629
3630
3631/* Return a Lisp vector which has the same contents as VEC but has
3632 size NEW_SIZE, NEW_SIZE >= VEC->size. Entries in the resulting
3633 vector that are not copied from VEC are set to INIT. */
3634
fa7dad5b 3635Lisp_Object
d80c6c11
GM
3636larger_vector (vec, new_size, init)
3637 Lisp_Object vec;
3638 int new_size;
3639 Lisp_Object init;
3640{
3641 struct Lisp_Vector *v;
3642 int i, old_size;
3643
3644 xassert (VECTORP (vec));
3645 old_size = XVECTOR (vec)->size;
3646 xassert (new_size >= old_size);
3647
3648 v = allocate_vectorlike (new_size);
3649 v->size = new_size;
3650 bcopy (XVECTOR (vec)->contents, v->contents,
3651 old_size * sizeof *v->contents);
3652 for (i = old_size; i < new_size; ++i)
3653 v->contents[i] = init;
3654 XSETVECTOR (vec, v);
3655 return vec;
3656}
3657
3658
3659/***********************************************************************
3660 Low-level Functions
3661 ***********************************************************************/
3662
d80c6c11
GM
3663/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
3664 HASH2 in hash table H using `eql'. Value is non-zero if KEY1 and
3665 KEY2 are the same. */
3666
3667static int
3668cmpfn_eql (h, key1, hash1, key2, hash2)
3669 struct Lisp_Hash_Table *h;
3670 Lisp_Object key1, key2;
3671 unsigned hash1, hash2;
3672{
2e5da676
GM
3673 return (FLOATP (key1)
3674 && FLOATP (key2)
e84b1dea 3675 && XFLOAT_DATA (key1) == XFLOAT_DATA (key2));
d80c6c11
GM
3676}
3677
3678
3679/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
3680 HASH2 in hash table H using `equal'. Value is non-zero if KEY1 and
3681 KEY2 are the same. */
3682
3683static int
3684cmpfn_equal (h, key1, hash1, key2, hash2)
3685 struct Lisp_Hash_Table *h;
3686 Lisp_Object key1, key2;
3687 unsigned hash1, hash2;
3688{
2e5da676 3689 return hash1 == hash2 && !NILP (Fequal (key1, key2));
d80c6c11
GM
3690}
3691
3692
3693/* Compare KEY1 which has hash code HASH1, and KEY2 with hash code
3694 HASH2 in hash table H using H->user_cmp_function. Value is non-zero
3695 if KEY1 and KEY2 are the same. */
3696
3697static int
3698cmpfn_user_defined (h, key1, hash1, key2, hash2)
3699 struct Lisp_Hash_Table *h;
3700 Lisp_Object key1, key2;
3701 unsigned hash1, hash2;
3702{
3703 if (hash1 == hash2)
3704 {
3705 Lisp_Object args[3];
3706
3707 args[0] = h->user_cmp_function;
3708 args[1] = key1;
3709 args[2] = key2;
3710 return !NILP (Ffuncall (3, args));
3711 }
3712 else
3713 return 0;
3714}
3715
3716
3717/* Value is a hash code for KEY for use in hash table H which uses
3718 `eq' to compare keys. The hash code returned is guaranteed to fit
3719 in a Lisp integer. */
3720
3721static unsigned
3722hashfn_eq (h, key)
3723 struct Lisp_Hash_Table *h;
3724 Lisp_Object key;
3725{
3726 /* Lisp strings can change their address. Don't try to compute a
3727 hash code for a string from its address. */
3728 if (STRINGP (key))
3729 return sxhash_string (XSTRING (key)->data, XSTRING (key)->size);
3730 else
3731 return XUINT (key) ^ XGCTYPE (key);
3732}
3733
3734
3735/* Value is a hash code for KEY for use in hash table H which uses
3736 `eql' to compare keys. The hash code returned is guaranteed to fit
3737 in a Lisp integer. */
3738
3739static unsigned
3740hashfn_eql (h, key)
3741 struct Lisp_Hash_Table *h;
3742 Lisp_Object key;
3743{
3744 /* Lisp strings can change their address. Don't try to compute a
3745 hash code for a string from its address. */
3746 if (STRINGP (key))
3747 return sxhash_string (XSTRING (key)->data, XSTRING (key)->size);
3748 else if (FLOATP (key))
3749 return sxhash (key, 0);
3750 else
3751 return XUINT (key) ^ XGCTYPE (key);
3752}
3753
3754
3755/* Value is a hash code for KEY for use in hash table H which uses
3756 `equal' to compare keys. The hash code returned is guaranteed to fit
3757 in a Lisp integer. */
3758
3759static unsigned
3760hashfn_equal (h, key)
3761 struct Lisp_Hash_Table *h;
3762 Lisp_Object key;
3763{
3764 return sxhash (key, 0);
3765}
3766
3767
3768/* Value is a hash code for KEY for use in hash table H which uses as
3769 user-defined function to compare keys. The hash code returned is
3770 guaranteed to fit in a Lisp integer. */
3771
3772static unsigned
3773hashfn_user_defined (h, key)
3774 struct Lisp_Hash_Table *h;
3775 Lisp_Object key;
3776{
3777 Lisp_Object args[2], hash;
3778
3779 args[0] = h->user_hash_function;
3780 args[1] = key;
3781 hash = Ffuncall (2, args);
3782 if (!INTEGERP (hash))
3783 Fsignal (Qerror,
3784 list2 (build_string ("Illegal hash code returned from \
3785user-supplied hash function"),
3786 hash));
3787 return XUINT (hash);
3788}
3789
3790
3791/* Create and initialize a new hash table.
3792
3793 TEST specifies the test the hash table will use to compare keys.
3794 It must be either one of the predefined tests `eq', `eql' or
3795 `equal' or a symbol denoting a user-defined test named TEST with
3796 test and hash functions USER_TEST and USER_HASH.
3797
3798 Give the table initial capacity SIZE, SIZE > 0, an integer.
3799
3800 If REHASH_SIZE is an integer, it must be > 0, and this hash table's
3801 new size when it becomes full is computed by adding REHASH_SIZE to
3802 its old size. If REHASH_SIZE is a float, it must be > 1.0, and the
3803 table's new size is computed by multiplying its old size with
3804 REHASH_SIZE.
3805
3806 REHASH_THRESHOLD must be a float <= 1.0, and > 0. The table will
3807 be resized when the ratio of (number of entries in the table) /
3808 (table size) is >= REHASH_THRESHOLD.
3809
3810 WEAK specifies the weakness of the table. If non-nil, it must be
f899c503 3811 one of the symbols `key', `value' or t. */
d80c6c11
GM
3812
3813Lisp_Object
3814make_hash_table (test, size, rehash_size, rehash_threshold, weak,
3815 user_test, user_hash)
3816 Lisp_Object test, size, rehash_size, rehash_threshold, weak;
3817 Lisp_Object user_test, user_hash;
3818{
3819 struct Lisp_Hash_Table *h;
3820 struct Lisp_Vector *v;
3821 Lisp_Object table;
3822 int index_size, i, len, sz;
3823
3824 /* Preconditions. */
3825 xassert (SYMBOLP (test));
3826 xassert (INTEGERP (size) && XINT (size) > 0);
3827 xassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0)
3828 || (FLOATP (rehash_size) && XFLOATINT (rehash_size) > 1.0));
3829 xassert (FLOATP (rehash_threshold)
3830 && XFLOATINT (rehash_threshold) > 0
3831 && XFLOATINT (rehash_threshold) <= 1.0);
3832
3833 /* Allocate a vector, and initialize it. */
3834 len = VECSIZE (struct Lisp_Hash_Table);
3835 v = allocate_vectorlike (len);
3836 v->size = len;
3837 for (i = 0; i < len; ++i)
3838 v->contents[i] = Qnil;
3839
3840 /* Initialize hash table slots. */
3841 sz = XFASTINT (size);
3842 h = (struct Lisp_Hash_Table *) v;
3843
3844 h->test = test;
3845 if (EQ (test, Qeql))
3846 {
3847 h->cmpfn = cmpfn_eql;
3848 h->hashfn = hashfn_eql;
3849 }
3850 else if (EQ (test, Qeq))
3851 {
2e5da676 3852 h->cmpfn = NULL;
d80c6c11
GM
3853 h->hashfn = hashfn_eq;
3854 }
3855 else if (EQ (test, Qequal))
3856 {
3857 h->cmpfn = cmpfn_equal;
3858 h->hashfn = hashfn_equal;
3859 }
3860 else
3861 {
3862 h->user_cmp_function = user_test;
3863 h->user_hash_function = user_hash;
3864 h->cmpfn = cmpfn_user_defined;
3865 h->hashfn = hashfn_user_defined;
3866 }
3867
3868 h->weak = weak;
3869 h->rehash_threshold = rehash_threshold;
3870 h->rehash_size = rehash_size;
3871 h->count = make_number (0);
3872 h->key_and_value = Fmake_vector (make_number (2 * sz), Qnil);
3873 h->hash = Fmake_vector (size, Qnil);
3874 h->next = Fmake_vector (size, Qnil);
3875 index_size = next_almost_prime (sz / XFLOATINT (rehash_threshold));
3876 h->index = Fmake_vector (make_number (index_size), Qnil);
3877
3878 /* Set up the free list. */
3879 for (i = 0; i < sz - 1; ++i)
3880 HASH_NEXT (h, i) = make_number (i + 1);
3881 h->next_free = make_number (0);
3882
3883 XSET_HASH_TABLE (table, h);
3884 xassert (HASH_TABLE_P (table));
3885 xassert (XHASH_TABLE (table) == h);
3886
3887 /* Maybe add this hash table to the list of all weak hash tables. */
3888 if (NILP (h->weak))
3889 h->next_weak = Qnil;
3890 else
3891 {
3892 h->next_weak = Vweak_hash_tables;
3893 Vweak_hash_tables = table;
3894 }
3895
3896 return table;
3897}
3898
3899
f899c503
GM
3900/* Return a copy of hash table H1. Keys and values are not copied,
3901 only the table itself is. */
3902
3903Lisp_Object
3904copy_hash_table (h1)
3905 struct Lisp_Hash_Table *h1;
3906{
3907 Lisp_Object table;
3908 struct Lisp_Hash_Table *h2;
3909 struct Lisp_Vector *v, *next;
3910 int len;
3911
3912 len = VECSIZE (struct Lisp_Hash_Table);
3913 v = allocate_vectorlike (len);
3914 h2 = (struct Lisp_Hash_Table *) v;
3915 next = h2->vec_next;
3916 bcopy (h1, h2, sizeof *h2);
3917 h2->vec_next = next;
3918 h2->key_and_value = Fcopy_sequence (h1->key_and_value);
3919 h2->hash = Fcopy_sequence (h1->hash);
3920 h2->next = Fcopy_sequence (h1->next);
3921 h2->index = Fcopy_sequence (h1->index);
3922 XSET_HASH_TABLE (table, h2);
3923
3924 /* Maybe add this hash table to the list of all weak hash tables. */
3925 if (!NILP (h2->weak))
3926 {
3927 h2->next_weak = Vweak_hash_tables;
3928 Vweak_hash_tables = table;
3929 }
3930
3931 return table;
3932}
3933
3934
d80c6c11
GM
3935/* Resize hash table H if it's too full. If H cannot be resized
3936 because it's already too large, throw an error. */
3937
3938static INLINE void
3939maybe_resize_hash_table (h)
3940 struct Lisp_Hash_Table *h;
3941{
3942 if (NILP (h->next_free))
3943 {
3944 int old_size = HASH_TABLE_SIZE (h);
3945 int i, new_size, index_size;
3946
3947 if (INTEGERP (h->rehash_size))
3948 new_size = old_size + XFASTINT (h->rehash_size);
3949 else
3950 new_size = old_size * XFLOATINT (h->rehash_size);
0d6ba42e 3951 new_size = max (old_size + 1, new_size);
d80c6c11
GM
3952 index_size = next_almost_prime (new_size
3953 / XFLOATINT (h->rehash_threshold));
3954 if (max (index_size, 2 * new_size) & ~VALMASK)
3955 error ("Hash table too large to resize");
3956
3957 h->key_and_value = larger_vector (h->key_and_value, 2 * new_size, Qnil);
3958 h->next = larger_vector (h->next, new_size, Qnil);
3959 h->hash = larger_vector (h->hash, new_size, Qnil);
3960 h->index = Fmake_vector (make_number (index_size), Qnil);
3961
3962 /* Update the free list. Do it so that new entries are added at
3963 the end of the free list. This makes some operations like
3964 maphash faster. */
3965 for (i = old_size; i < new_size - 1; ++i)
3966 HASH_NEXT (h, i) = make_number (i + 1);
3967
3968 if (!NILP (h->next_free))
3969 {
3970 Lisp_Object last, next;
3971
3972 last = h->next_free;
3973 while (next = HASH_NEXT (h, XFASTINT (last)),
3974 !NILP (next))
3975 last = next;
3976
3977 HASH_NEXT (h, XFASTINT (last)) = make_number (old_size);
3978 }
3979 else
3980 XSETFASTINT (h->next_free, old_size);
3981
3982 /* Rehash. */
3983 for (i = 0; i < old_size; ++i)
3984 if (!NILP (HASH_HASH (h, i)))
3985 {
3986 unsigned hash_code = XUINT (HASH_HASH (h, i));
3987 int start_of_bucket = hash_code % XVECTOR (h->index)->size;
3988 HASH_NEXT (h, i) = HASH_INDEX (h, start_of_bucket);
3989 HASH_INDEX (h, start_of_bucket) = make_number (i);
3990 }
3991 }
3992}
3993
3994
3995/* Lookup KEY in hash table H. If HASH is non-null, return in *HASH
3996 the hash code of KEY. Value is the index of the entry in H
3997 matching KEY, or -1 if not found. */
3998
3999int
4000hash_lookup (h, key, hash)
4001 struct Lisp_Hash_Table *h;
4002 Lisp_Object key;
4003 unsigned *hash;
4004{
4005 unsigned hash_code;
4006 int start_of_bucket;
4007 Lisp_Object idx;
4008
4009 hash_code = h->hashfn (h, key);
4010 if (hash)
4011 *hash = hash_code;
4012
4013 start_of_bucket = hash_code % XVECTOR (h->index)->size;
4014 idx = HASH_INDEX (h, start_of_bucket);
4015
f5c75033 4016 /* We need not gcpro idx since it's either an integer or nil. */
d80c6c11
GM
4017 while (!NILP (idx))
4018 {
4019 int i = XFASTINT (idx);
2e5da676
GM
4020 if (EQ (key, HASH_KEY (h, i))
4021 || (h->cmpfn
4022 && h->cmpfn (h, key, hash_code,
7c752c80 4023 HASH_KEY (h, i), XUINT (HASH_HASH (h, i)))))
d80c6c11
GM
4024 break;
4025 idx = HASH_NEXT (h, i);
4026 }
4027
4028 return NILP (idx) ? -1 : XFASTINT (idx);
4029}
4030
4031
4032/* Put an entry into hash table H that associates KEY with VALUE.
64a5094a
KH
4033 HASH is a previously computed hash code of KEY.
4034 Value is the index of the entry in H matching KEY. */
d80c6c11 4035
64a5094a 4036int
d80c6c11
GM
4037hash_put (h, key, value, hash)
4038 struct Lisp_Hash_Table *h;
4039 Lisp_Object key, value;
4040 unsigned hash;
4041{
4042 int start_of_bucket, i;
4043
4044 xassert ((hash & ~VALMASK) == 0);
4045
4046 /* Increment count after resizing because resizing may fail. */
4047 maybe_resize_hash_table (h);
4048 h->count = make_number (XFASTINT (h->count) + 1);
4049
4050 /* Store key/value in the key_and_value vector. */
4051 i = XFASTINT (h->next_free);
4052 h->next_free = HASH_NEXT (h, i);
4053 HASH_KEY (h, i) = key;
4054 HASH_VALUE (h, i) = value;
4055
4056 /* Remember its hash code. */
4057 HASH_HASH (h, i) = make_number (hash);
4058
4059 /* Add new entry to its collision chain. */
4060 start_of_bucket = hash % XVECTOR (h->index)->size;
4061 HASH_NEXT (h, i) = HASH_INDEX (h, start_of_bucket);
4062 HASH_INDEX (h, start_of_bucket) = make_number (i);
64a5094a 4063 return i;
d80c6c11
GM
4064}
4065
4066
4067/* Remove the entry matching KEY from hash table H, if there is one. */
4068
4069void
4070hash_remove (h, key)
4071 struct Lisp_Hash_Table *h;
4072 Lisp_Object key;
4073{
4074 unsigned hash_code;
4075 int start_of_bucket;
4076 Lisp_Object idx, prev;
4077
4078 hash_code = h->hashfn (h, key);
4079 start_of_bucket = hash_code % XVECTOR (h->index)->size;
4080 idx = HASH_INDEX (h, start_of_bucket);
4081 prev = Qnil;
4082
f5c75033 4083 /* We need not gcpro idx, prev since they're either integers or nil. */
d80c6c11
GM
4084 while (!NILP (idx))
4085 {
4086 int i = XFASTINT (idx);
4087
2e5da676
GM
4088 if (EQ (key, HASH_KEY (h, i))
4089 || (h->cmpfn
4090 && h->cmpfn (h, key, hash_code,
7c752c80 4091 HASH_KEY (h, i), XUINT (HASH_HASH (h, i)))))
d80c6c11
GM
4092 {
4093 /* Take entry out of collision chain. */
4094 if (NILP (prev))
4095 HASH_INDEX (h, start_of_bucket) = HASH_NEXT (h, i);
4096 else
4097 HASH_NEXT (h, XFASTINT (prev)) = HASH_NEXT (h, i);
4098
4099 /* Clear slots in key_and_value and add the slots to
4100 the free list. */
4101 HASH_KEY (h, i) = HASH_VALUE (h, i) = HASH_HASH (h, i) = Qnil;
4102 HASH_NEXT (h, i) = h->next_free;
4103 h->next_free = make_number (i);
4104 h->count = make_number (XFASTINT (h->count) - 1);
4105 xassert (XINT (h->count) >= 0);
4106 break;
4107 }
4108 else
4109 {
4110 prev = idx;
4111 idx = HASH_NEXT (h, i);
4112 }
4113 }
4114}
4115
4116
4117/* Clear hash table H. */
4118
4119void
4120hash_clear (h)
4121 struct Lisp_Hash_Table *h;
4122{
4123 if (XFASTINT (h->count) > 0)
4124 {
4125 int i, size = HASH_TABLE_SIZE (h);
4126
4127 for (i = 0; i < size; ++i)
4128 {
4129 HASH_NEXT (h, i) = i < size - 1 ? make_number (i + 1) : Qnil;
4130 HASH_KEY (h, i) = Qnil;
4131 HASH_VALUE (h, i) = Qnil;
4132 HASH_HASH (h, i) = Qnil;
4133 }
4134
4135 for (i = 0; i < XVECTOR (h->index)->size; ++i)
4136 XVECTOR (h->index)->contents[i] = Qnil;
4137
4138 h->next_free = make_number (0);
4139 h->count = make_number (0);
4140 }
4141}
4142
4143
4144\f
4145/************************************************************************
4146 Weak Hash Tables
4147 ************************************************************************/
4148
a0b581cc
GM
4149/* Sweep weak hash table H. REMOVE_ENTRIES_P non-zero means remove
4150 entries from the table that don't survive the current GC.
4151 REMOVE_ENTRIES_P zero means mark entries that are in use. Value is
4152 non-zero if anything was marked. */
4153
4154static int
4155sweep_weak_table (h, remove_entries_p)
4156 struct Lisp_Hash_Table *h;
4157 int remove_entries_p;
4158{
4159 int bucket, n, marked;
4160
4161 n = XVECTOR (h->index)->size & ~ARRAY_MARK_FLAG;
4162 marked = 0;
4163
4164 for (bucket = 0; bucket < n; ++bucket)
4165 {
4166 Lisp_Object idx, prev;
4167
4168 /* Follow collision chain, removing entries that
4169 don't survive this garbage collection. */
4170 idx = HASH_INDEX (h, bucket);
4171 prev = Qnil;
4172 while (!GC_NILP (idx))
4173 {
4174 int remove_p;
4175 int i = XFASTINT (idx);
4176 Lisp_Object next;
4177
4178 if (EQ (h->weak, Qkey))
4179 remove_p = !survives_gc_p (HASH_KEY (h, i));
4180 else if (EQ (h->weak, Qvalue))
4181 remove_p = !survives_gc_p (HASH_VALUE (h, i));
4182 else if (EQ (h->weak, Qt))
4183 remove_p = (!survives_gc_p (HASH_KEY (h, i))
4184 || !survives_gc_p (HASH_VALUE (h, i)));
4185 else
4186 abort ();
4187
4188 next = HASH_NEXT (h, i);
4189
4190 if (remove_entries_p)
4191 {
4192 if (remove_p)
4193 {
4194 /* Take out of collision chain. */
4195 if (GC_NILP (prev))
4196 HASH_INDEX (h, i) = next;
4197 else
4198 HASH_NEXT (h, XFASTINT (prev)) = next;
4199
4200 /* Add to free list. */
4201 HASH_NEXT (h, i) = h->next_free;
4202 h->next_free = idx;
4203
4204 /* Clear key, value, and hash. */
4205 HASH_KEY (h, i) = HASH_VALUE (h, i) = Qnil;
4206 HASH_HASH (h, i) = Qnil;
4207
4208 h->count = make_number (XFASTINT (h->count) - 1);
4209 }
4210 }
4211 else
4212 {
4213 if (!remove_p)
4214 {
4215 /* Make sure key and value survive. */
4216 mark_object (&HASH_KEY (h, i));
4217 mark_object (&HASH_VALUE (h, i));
4218 marked = 1;
4219 }
4220 }
4221
4222 idx = next;
4223 }
4224 }
4225
4226 return marked;
4227}
4228
d80c6c11
GM
4229/* Remove elements from weak hash tables that don't survive the
4230 current garbage collection. Remove weak tables that don't survive
4231 from Vweak_hash_tables. Called from gc_sweep. */
4232
4233void
4234sweep_weak_hash_tables ()
4235{
4236 Lisp_Object table;
a0b581cc
GM
4237 struct Lisp_Hash_Table *h, *prev;
4238 int marked;
4239
4240 /* Mark all keys and values that are in use. Keep on marking until
4241 there is no more change. This is necessary for cases like
4242 value-weak table A containing an entry X -> Y, where Y is used in a
4243 key-weak table B, Z -> Y. If B comes after A in the list of weak
4244 tables, X -> Y might be removed from A, although when looking at B
4245 one finds that it shouldn't. */
4246 do
4247 {
4248 marked = 0;
4249 for (table = Vweak_hash_tables; !GC_NILP (table); table = h->next_weak)
4250 {
4251 h = XHASH_TABLE (table);
4252 if (h->size & ARRAY_MARK_FLAG)
4253 marked |= sweep_weak_table (h, 0);
4254 }
4255 }
4256 while (marked);
d80c6c11 4257
a0b581cc
GM
4258 /* Remove tables and entries that aren't used. */
4259 prev = NULL;
d80c6c11
GM
4260 for (table = Vweak_hash_tables; !GC_NILP (table); table = h->next_weak)
4261 {
4262 prev = h;
4263 h = XHASH_TABLE (table);
4264
4265 if (h->size & ARRAY_MARK_FLAG)
4266 {
4267 if (XFASTINT (h->count) > 0)
a0b581cc 4268 sweep_weak_table (h, 1);
d80c6c11
GM
4269 }
4270 else
4271 {
4272 /* Table is not marked, and will thus be freed.
4273 Take it out of the list of weak hash tables. */
4274 if (prev)
4275 prev->next_weak = h->next_weak;
4276 else
4277 Vweak_hash_tables = h->next_weak;
4278 }
4279 }
4280}
4281
4282
4283\f
4284/***********************************************************************
4285 Hash Code Computation
4286 ***********************************************************************/
4287
4288/* Maximum depth up to which to dive into Lisp structures. */
4289
4290#define SXHASH_MAX_DEPTH 3
4291
4292/* Maximum length up to which to take list and vector elements into
4293 account. */
4294
4295#define SXHASH_MAX_LEN 7
4296
4297/* Combine two integers X and Y for hashing. */
4298
4299#define SXHASH_COMBINE(X, Y) \
ada0fa14 4300 ((((unsigned)(X) << 4) + (((unsigned)(X) >> 24) & 0x0fffffff)) \
d80c6c11
GM
4301 + (unsigned)(Y))
4302
4303
4304/* Return a hash for string PTR which has length LEN. */
4305
4306static unsigned
4307sxhash_string (ptr, len)
4308 unsigned char *ptr;
4309 int len;
4310{
4311 unsigned char *p = ptr;
4312 unsigned char *end = p + len;
4313 unsigned char c;
4314 unsigned hash = 0;
4315
4316 while (p != end)
4317 {
4318 c = *p++;
4319 if (c >= 0140)
4320 c -= 40;
4321 hash = ((hash << 3) + (hash >> 28) + c);
4322 }
4323
4324 return hash & 07777777777;
4325}
4326
4327
4328/* Return a hash for list LIST. DEPTH is the current depth in the
4329 list. We don't recurse deeper than SXHASH_MAX_DEPTH in it. */
4330
4331static unsigned
4332sxhash_list (list, depth)
4333 Lisp_Object list;
4334 int depth;
4335{
4336 unsigned hash = 0;
4337 int i;
4338
4339 if (depth < SXHASH_MAX_DEPTH)
4340 for (i = 0;
4341 CONSP (list) && i < SXHASH_MAX_LEN;
4342 list = XCDR (list), ++i)
4343 {
4344 unsigned hash2 = sxhash (XCAR (list), depth + 1);
4345 hash = SXHASH_COMBINE (hash, hash2);
4346 }
4347
4348 return hash;
4349}
4350
4351
4352/* Return a hash for vector VECTOR. DEPTH is the current depth in
4353 the Lisp structure. */
4354
4355static unsigned
4356sxhash_vector (vec, depth)
4357 Lisp_Object vec;
4358 int depth;
4359{
4360 unsigned hash = XVECTOR (vec)->size;
4361 int i, n;
4362
4363 n = min (SXHASH_MAX_LEN, XVECTOR (vec)->size);
4364 for (i = 0; i < n; ++i)
4365 {
4366 unsigned hash2 = sxhash (XVECTOR (vec)->contents[i], depth + 1);
4367 hash = SXHASH_COMBINE (hash, hash2);
4368 }
4369
4370 return hash;
4371}
4372
4373
4374/* Return a hash for bool-vector VECTOR. */
4375
4376static unsigned
4377sxhash_bool_vector (vec)
4378 Lisp_Object vec;
4379{
4380 unsigned hash = XBOOL_VECTOR (vec)->size;
4381 int i, n;
4382
4383 n = min (SXHASH_MAX_LEN, XBOOL_VECTOR (vec)->vector_size);
4384 for (i = 0; i < n; ++i)
4385 hash = SXHASH_COMBINE (hash, XBOOL_VECTOR (vec)->data[i]);
4386
4387 return hash;
4388}
4389
4390
4391/* Return a hash code for OBJ. DEPTH is the current depth in the Lisp
4392 structure. Value is an unsigned integer clipped to VALMASK. */
4393
4394unsigned
4395sxhash (obj, depth)
4396 Lisp_Object obj;
4397 int depth;
4398{
4399 unsigned hash;
4400
4401 if (depth > SXHASH_MAX_DEPTH)
4402 return 0;
4403
4404 switch (XTYPE (obj))
4405 {
4406 case Lisp_Int:
4407 hash = XUINT (obj);
4408 break;
4409
4410 case Lisp_Symbol:
4411 hash = sxhash_string (XSYMBOL (obj)->name->data,
4412 XSYMBOL (obj)->name->size);
4413 break;
4414
4415 case Lisp_Misc:
4416 hash = XUINT (obj);
4417 break;
4418
4419 case Lisp_String:
4420 hash = sxhash_string (XSTRING (obj)->data, XSTRING (obj)->size);
4421 break;
4422
4423 /* This can be everything from a vector to an overlay. */
4424 case Lisp_Vectorlike:
4425 if (VECTORP (obj))
4426 /* According to the CL HyperSpec, two arrays are equal only if
4427 they are `eq', except for strings and bit-vectors. In
4428 Emacs, this works differently. We have to compare element
4429 by element. */
4430 hash = sxhash_vector (obj, depth);
4431 else if (BOOL_VECTOR_P (obj))
4432 hash = sxhash_bool_vector (obj);
4433 else
4434 /* Others are `equal' if they are `eq', so let's take their
4435 address as hash. */
4436 hash = XUINT (obj);
4437 break;
4438
4439 case Lisp_Cons:
4440 hash = sxhash_list (obj, depth);
4441 break;
4442
4443 case Lisp_Float:
4444 {
e84b1dea
GM
4445 unsigned char *p = (unsigned char *) &XFLOAT_DATA (obj);
4446 unsigned char *e = p + sizeof XFLOAT_DATA (obj);
d80c6c11
GM
4447 for (hash = 0; p < e; ++p)
4448 hash = SXHASH_COMBINE (hash, *p);
4449 break;
4450 }
4451
4452 default:
4453 abort ();
4454 }
4455
4456 return hash & VALMASK;
4457}
4458
4459
4460\f
4461/***********************************************************************
4462 Lisp Interface
4463 ***********************************************************************/
4464
4465
4466DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0,
4467 "Compute a hash code for OBJ and return it as integer.")
4468 (obj)
4469 Lisp_Object obj;
4470{
4471 unsigned hash = sxhash (obj, 0);;
4472 return make_number (hash);
4473}
4474
4475
4476DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 0,
4477 "Create and return a new hash table.\n\
4478Arguments are specified as keyword/argument pairs. The following\n\
4479arguments are defined:\n\
4480\n\
526cfb19 4481:TEST TEST -- TEST must be a symbol that specifies how to compare keys.\n\
d80c6c11
GM
4482Default is `eql'. Predefined are the tests `eq', `eql', and `equal'.\n\
4483User-supplied test and hash functions can be specified via\n\
4484`define-hash-table-test'.\n\
4485\n\
526cfb19 4486:SIZE SIZE -- A hint as to how many elements will be put in the table.\n\
d80c6c11
GM
4487Default is 65.\n\
4488\n\
4489:REHASH-SIZE REHASH-SIZE - Indicates how to expand the table when\n\
4490it fills up. If REHASH-SIZE is an integer, add that many space.\n\
4491If it is a float, it must be > 1.0, and the new size is computed by\n\
4492multiplying the old size with that factor. Default is 1.5.\n\
4493\n\
4494:REHASH-THRESHOLD THRESHOLD -- THRESHOLD must a float > 0, and <= 1.0.\n\
4495Resize the hash table when ratio of the number of entries in the table.\n\
4496Default is 0.8.\n\
4497\n\
ee0403b3 4498:WEAKNESS WEAK -- WEAK must be one of nil, t, `key', or `value'.\n\
f899c503
GM
4499If WEAK is not nil, the table returned is a weak table. Key/value\n\
4500pairs are removed from a weak hash table when their key, value or both\n\
4501(WEAK t) are otherwise unreferenced. Default is nil.")
d80c6c11
GM
4502 (nargs, args)
4503 int nargs;
4504 Lisp_Object *args;
4505{
4506 Lisp_Object test, size, rehash_size, rehash_threshold, weak;
4507 Lisp_Object user_test, user_hash;
4508 char *used;
4509 int i;
4510
4511 /* The vector `used' is used to keep track of arguments that
4512 have been consumed. */
4513 used = (char *) alloca (nargs * sizeof *used);
4514 bzero (used, nargs * sizeof *used);
4515
4516 /* See if there's a `:test TEST' among the arguments. */
4517 i = get_key_arg (QCtest, nargs, args, used);
4518 test = i < 0 ? Qeql : args[i];
4519 if (!EQ (test, Qeq) && !EQ (test, Qeql) && !EQ (test, Qequal))
4520 {
4521 /* See if it is a user-defined test. */
4522 Lisp_Object prop;
4523
4524 prop = Fget (test, Qhash_table_test);
4525 if (!CONSP (prop) || XFASTINT (Flength (prop)) < 2)
4526 Fsignal (Qerror, list2 (build_string ("Illegal hash table test"),
4527 test));
4528 user_test = Fnth (make_number (0), prop);
4529 user_hash = Fnth (make_number (1), prop);
4530 }
4531 else
4532 user_test = user_hash = Qnil;
4533
4534 /* See if there's a `:size SIZE' argument. */
4535 i = get_key_arg (QCsize, nargs, args, used);
4536 size = i < 0 ? make_number (DEFAULT_HASH_SIZE) : args[i];
4537 if (!INTEGERP (size) || XINT (size) <= 0)
4538 Fsignal (Qerror,
4539 list2 (build_string ("Illegal hash table size"),
4540 size));
4541
4542 /* Look for `:rehash-size SIZE'. */
4543 i = get_key_arg (QCrehash_size, nargs, args, used);
4544 rehash_size = i < 0 ? make_float (DEFAULT_REHASH_SIZE) : args[i];
4545 if (!NUMBERP (rehash_size)
4546 || (INTEGERP (rehash_size) && XINT (rehash_size) <= 0)
4547 || XFLOATINT (rehash_size) <= 1.0)
4548 Fsignal (Qerror,
4549 list2 (build_string ("Illegal hash table rehash size"),
4550 rehash_size));
4551
4552 /* Look for `:rehash-threshold THRESHOLD'. */
4553 i = get_key_arg (QCrehash_threshold, nargs, args, used);
4554 rehash_threshold = i < 0 ? make_float (DEFAULT_REHASH_THRESHOLD) : args[i];
4555 if (!FLOATP (rehash_threshold)
4556 || XFLOATINT (rehash_threshold) <= 0.0
4557 || XFLOATINT (rehash_threshold) > 1.0)
4558 Fsignal (Qerror,
4559 list2 (build_string ("Illegal hash table rehash threshold"),
4560 rehash_threshold));
4561
ee0403b3
GM
4562 /* Look for `:weakness WEAK'. */
4563 i = get_key_arg (QCweakness, nargs, args, used);
d80c6c11 4564 weak = i < 0 ? Qnil : args[i];
d80c6c11 4565 if (!NILP (weak)
f899c503
GM
4566 && !EQ (weak, Qt)
4567 && !EQ (weak, Qkey)
4568 && !EQ (weak, Qvalue))
d80c6c11
GM
4569 Fsignal (Qerror, list2 (build_string ("Illegal hash table weakness"),
4570 weak));
4571
4572 /* Now, all args should have been used up, or there's a problem. */
4573 for (i = 0; i < nargs; ++i)
4574 if (!used[i])
4575 Fsignal (Qerror,
4576 list2 (build_string ("Invalid argument list"), args[i]));
4577
4578 return make_hash_table (test, size, rehash_size, rehash_threshold, weak,
4579 user_test, user_hash);
4580}
4581
4582
f899c503
GM
4583DEFUN ("copy-hash-table", Fcopy_hash_table, Scopy_hash_table, 1, 1, 0,
4584 "Return a copy of hash table TABLE.")
4585 (table)
4586 Lisp_Object table;
4587{
4588 return copy_hash_table (check_hash_table (table));
4589}
4590
4591
38b5e497 4592DEFUN ("makehash", Fmakehash, Smakehash, 0, 1, 0,
d80c6c11 4593 "Create a new hash table.\n\
c5092f3e 4594Optional first argument TEST specifies how to compare keys in\n\
d80c6c11 4595the table. Predefined tests are `eq', `eql', and `equal'. Default\n\
38b5e497
GM
4596is `eql'. New tests can be defined with `define-hash-table-test'.")
4597 (test)
4598 Lisp_Object test;
d80c6c11 4599{
38b5e497
GM
4600 Lisp_Object args[2];
4601 args[0] = QCtest;
4602 args[1] = test;
4603 return Fmake_hash_table (2, args);
d80c6c11
GM
4604}
4605
4606
4607DEFUN ("hash-table-count", Fhash_table_count, Shash_table_count, 1, 1, 0,
4608 "Return the number of elements in TABLE.")
4609 (table)
4610 Lisp_Object table;
4611{
4612 return check_hash_table (table)->count;
4613}
4614
4615
4616DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size,
4617 Shash_table_rehash_size, 1, 1, 0,
4618 "Return the current rehash size of TABLE.")
4619 (table)
4620 Lisp_Object table;
4621{
4622 return check_hash_table (table)->rehash_size;
4623}
4624
4625
4626DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold,
4627 Shash_table_rehash_threshold, 1, 1, 0,
4628 "Return the current rehash threshold of TABLE.")
4629 (table)
4630 Lisp_Object table;
4631{
4632 return check_hash_table (table)->rehash_threshold;
4633}
4634
4635
4636DEFUN ("hash-table-size", Fhash_table_size, Shash_table_size, 1, 1, 0,
4637 "Return the size of TABLE.\n\
4638The size can be used as an argument to `make-hash-table' to create\n\
4639a hash table than can hold as many elements of TABLE holds\n\
4640without need for resizing.")
4641 (table)
4642 Lisp_Object table;
4643{
4644 struct Lisp_Hash_Table *h = check_hash_table (table);
4645 return make_number (HASH_TABLE_SIZE (h));
4646}
4647
4648
4649DEFUN ("hash-table-test", Fhash_table_test, Shash_table_test, 1, 1, 0,
4650 "Return the test TABLE uses.")
4651 (table)
4652 Lisp_Object table;
4653{
4654 return check_hash_table (table)->test;
4655}
4656
4657
e84b1dea
GM
4658DEFUN ("hash-table-weakness", Fhash_table_weakness, Shash_table_weakness,
4659 1, 1, 0,
d80c6c11
GM
4660 "Return the weakness of TABLE.")
4661 (table)
4662 Lisp_Object table;
4663{
4664 return check_hash_table (table)->weak;
4665}
4666
4667
4668DEFUN ("hash-table-p", Fhash_table_p, Shash_table_p, 1, 1, 0,
4669 "Return t if OBJ is a Lisp hash table object.")
4670 (obj)
4671 Lisp_Object obj;
4672{
4673 return HASH_TABLE_P (obj) ? Qt : Qnil;
4674}
4675
4676
4677DEFUN ("clrhash", Fclrhash, Sclrhash, 1, 1, 0,
4678 "Clear hash table TABLE.")
4679 (table)
4680 Lisp_Object table;
4681{
4682 hash_clear (check_hash_table (table));
4683 return Qnil;
4684}
4685
4686
4687DEFUN ("gethash", Fgethash, Sgethash, 2, 3, 0,
4688 "Look up KEY in TABLE and return its associated value.\n\
4689If KEY is not found, return DFLT which defaults to nil.")
1fffe870 4690 (key, table, dflt)
68c45bf0 4691 Lisp_Object key, table, dflt;
d80c6c11
GM
4692{
4693 struct Lisp_Hash_Table *h = check_hash_table (table);
4694 int i = hash_lookup (h, key, NULL);
4695 return i >= 0 ? HASH_VALUE (h, i) : dflt;
4696}
4697
4698
4699DEFUN ("puthash", Fputhash, Sputhash, 3, 3, 0,
f5c75033 4700 "Associate KEY with VALUE in hash table TABLE.\n\
d80c6c11
GM
4701If KEY is already present in table, replace its current value with\n\
4702VALUE.")
1fffe870
MR
4703 (key, value, table)
4704 Lisp_Object key, value, table;
d80c6c11
GM
4705{
4706 struct Lisp_Hash_Table *h = check_hash_table (table);
4707 int i;
4708 unsigned hash;
4709
4710 i = hash_lookup (h, key, &hash);
4711 if (i >= 0)
4712 HASH_VALUE (h, i) = value;
4713 else
4714 hash_put (h, key, value, hash);
4715
4716 return Qnil;
4717}
4718
4719
4720DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
4721 "Remove KEY from TABLE.")
1fffe870
MR
4722 (key, table)
4723 Lisp_Object key, table;
d80c6c11
GM
4724{
4725 struct Lisp_Hash_Table *h = check_hash_table (table);
4726 hash_remove (h, key);
4727 return Qnil;
4728}
4729
4730
4731DEFUN ("maphash", Fmaphash, Smaphash, 2, 2, 0,
4732 "Call FUNCTION for all entries in hash table TABLE.\n\
4733FUNCTION is called with 2 arguments KEY and VALUE.")
4734 (function, table)
4735 Lisp_Object function, table;
4736{
4737 struct Lisp_Hash_Table *h = check_hash_table (table);
4738 Lisp_Object args[3];
4739 int i;
4740
4741 for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
4742 if (!NILP (HASH_HASH (h, i)))
4743 {
4744 args[0] = function;
4745 args[1] = HASH_KEY (h, i);
4746 args[2] = HASH_VALUE (h, i);
4747 Ffuncall (3, args);
4748 }
4749
4750 return Qnil;
4751}
4752
4753
4754DEFUN ("define-hash-table-test", Fdefine_hash_table_test,
4755 Sdefine_hash_table_test, 3, 3, 0,
4756 "Define a new hash table test with name NAME, a symbol.\n\
4757In hash tables create with NAME specified as test, use TEST to compare\n\
4758keys, and HASH for computing hash codes of keys.\n\
4759\n\
4760TEST must be a function taking two arguments and returning non-nil\n\
4761if both arguments are the same. HASH must be a function taking\n\
4762one argument and return an integer that is the hash code of the\n\
4763argument. Hash code computation should use the whole value range of\n\
4764integers, including negative integers.")
4765 (name, test, hash)
4766 Lisp_Object name, test, hash;
4767{
4768 return Fput (name, Qhash_table_test, list2 (test, hash));
4769}
4770
a3b210c4 4771
d80c6c11 4772
24c129e4 4773\f
dfcf069d 4774void
7b863bd5
JB
4775syms_of_fns ()
4776{
d80c6c11
GM
4777 /* Hash table stuff. */
4778 Qhash_table_p = intern ("hash-table-p");
4779 staticpro (&Qhash_table_p);
4780 Qeq = intern ("eq");
4781 staticpro (&Qeq);
4782 Qeql = intern ("eql");
4783 staticpro (&Qeql);
4784 Qequal = intern ("equal");
4785 staticpro (&Qequal);
4786 QCtest = intern (":test");
4787 staticpro (&QCtest);
4788 QCsize = intern (":size");
4789 staticpro (&QCsize);
4790 QCrehash_size = intern (":rehash-size");
4791 staticpro (&QCrehash_size);
4792 QCrehash_threshold = intern (":rehash-threshold");
4793 staticpro (&QCrehash_threshold);
ee0403b3
GM
4794 QCweakness = intern (":weakness");
4795 staticpro (&QCweakness);
f899c503
GM
4796 Qkey = intern ("key");
4797 staticpro (&Qkey);
4798 Qvalue = intern ("value");
4799 staticpro (&Qvalue);
d80c6c11
GM
4800 Qhash_table_test = intern ("hash-table-test");
4801 staticpro (&Qhash_table_test);
4802
4803 defsubr (&Ssxhash);
4804 defsubr (&Smake_hash_table);
f899c503 4805 defsubr (&Scopy_hash_table);
d80c6c11
GM
4806 defsubr (&Smakehash);
4807 defsubr (&Shash_table_count);
4808 defsubr (&Shash_table_rehash_size);
4809 defsubr (&Shash_table_rehash_threshold);
4810 defsubr (&Shash_table_size);
4811 defsubr (&Shash_table_test);
e84b1dea 4812 defsubr (&Shash_table_weakness);
d80c6c11
GM
4813 defsubr (&Shash_table_p);
4814 defsubr (&Sclrhash);
4815 defsubr (&Sgethash);
4816 defsubr (&Sputhash);
4817 defsubr (&Sremhash);
4818 defsubr (&Smaphash);
4819 defsubr (&Sdefine_hash_table_test);
4820
7b863bd5
JB
4821 Qstring_lessp = intern ("string-lessp");
4822 staticpro (&Qstring_lessp);
68732608
RS
4823 Qprovide = intern ("provide");
4824 staticpro (&Qprovide);
4825 Qrequire = intern ("require");
4826 staticpro (&Qrequire);
0ce830bc
RS
4827 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
4828 staticpro (&Qyes_or_no_p_history);
eb4ffa4e
RS
4829 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
4830 staticpro (&Qcursor_in_echo_area);
b4f334f7
KH
4831 Qwidget_type = intern ("widget-type");
4832 staticpro (&Qwidget_type);
7b863bd5 4833
09ab3c3b
KH
4834 staticpro (&string_char_byte_cache_string);
4835 string_char_byte_cache_string = Qnil;
4836
52a9879b
RS
4837 Fset (Qyes_or_no_p_history, Qnil);
4838
7b863bd5
JB
4839 DEFVAR_LISP ("features", &Vfeatures,
4840 "A list of symbols which are the features of the executing emacs.\n\
4841Used by `featurep' and `require', and altered by `provide'.");
4842 Vfeatures = Qnil;
4843
bdd8d692
RS
4844 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
4845 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
1eb569c5 4846This applies to y-or-n and yes-or-no questions asked by commands\n\
bdd8d692
RS
4847invoked by mouse clicks and mouse menu items.");
4848 use_dialog_box = 1;
4849
7b863bd5
JB
4850 defsubr (&Sidentity);
4851 defsubr (&Srandom);
4852 defsubr (&Slength);
5a30fab8 4853 defsubr (&Ssafe_length);
026f59ce 4854 defsubr (&Sstring_bytes);
7b863bd5 4855 defsubr (&Sstring_equal);
0e1e9f8d 4856 defsubr (&Scompare_strings);
7b863bd5
JB
4857 defsubr (&Sstring_lessp);
4858 defsubr (&Sappend);
4859 defsubr (&Sconcat);
4860 defsubr (&Svconcat);
4861 defsubr (&Scopy_sequence);
09ab3c3b
KH
4862 defsubr (&Sstring_make_multibyte);
4863 defsubr (&Sstring_make_unibyte);
6d475204
RS
4864 defsubr (&Sstring_as_multibyte);
4865 defsubr (&Sstring_as_unibyte);
7b863bd5
JB
4866 defsubr (&Scopy_alist);
4867 defsubr (&Ssubstring);
4868 defsubr (&Snthcdr);
4869 defsubr (&Snth);
4870 defsubr (&Selt);
4871 defsubr (&Smember);
4872 defsubr (&Smemq);
4873 defsubr (&Sassq);
4874 defsubr (&Sassoc);
4875 defsubr (&Srassq);
0fb5a19c 4876 defsubr (&Srassoc);
7b863bd5 4877 defsubr (&Sdelq);
ca8dd546 4878 defsubr (&Sdelete);
7b863bd5
JB
4879 defsubr (&Snreverse);
4880 defsubr (&Sreverse);
4881 defsubr (&Ssort);
be9d483d 4882 defsubr (&Splist_get);
7b863bd5 4883 defsubr (&Sget);
be9d483d 4884 defsubr (&Splist_put);
7b863bd5
JB
4885 defsubr (&Sput);
4886 defsubr (&Sequal);
4887 defsubr (&Sfillarray);
999de246 4888 defsubr (&Schar_table_subtype);
e03f7933
RS
4889 defsubr (&Schar_table_parent);
4890 defsubr (&Sset_char_table_parent);
4891 defsubr (&Schar_table_extra_slot);
4892 defsubr (&Sset_char_table_extra_slot);
999de246 4893 defsubr (&Schar_table_range);
e03f7933 4894 defsubr (&Sset_char_table_range);
e1335ba2 4895 defsubr (&Sset_char_table_default);
52ef6c89 4896 defsubr (&Soptimize_char_table);
e03f7933 4897 defsubr (&Smap_char_table);
7b863bd5
JB
4898 defsubr (&Snconc);
4899 defsubr (&Smapcar);
5c6740c9 4900 defsubr (&Smapc);
7b863bd5
JB
4901 defsubr (&Smapconcat);
4902 defsubr (&Sy_or_n_p);
4903 defsubr (&Syes_or_no_p);
4904 defsubr (&Sload_average);
4905 defsubr (&Sfeaturep);
4906 defsubr (&Srequire);
4907 defsubr (&Sprovide);
b4f334f7
KH
4908 defsubr (&Swidget_plist_member);
4909 defsubr (&Swidget_put);
4910 defsubr (&Swidget_get);
4911 defsubr (&Swidget_apply);
24c129e4
KH
4912 defsubr (&Sbase64_encode_region);
4913 defsubr (&Sbase64_decode_region);
4914 defsubr (&Sbase64_encode_string);
4915 defsubr (&Sbase64_decode_string);
7b863bd5 4916}
d80c6c11
GM
4917
4918
4919void
4920init_fns ()
4921{
4922 Vweak_hash_tables = Qnil;
4923}