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