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