Add support for large files, 64-bit Solaris, system locale codings.
[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 1995{
88fe8140 1996 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 1997
999de246 1998 if (EQ (range, Qnil))
88fe8140 1999 return XCHAR_TABLE (char_table)->defalt;
999de246 2000 else if (INTEGERP (range))
88fe8140 2001 return Faref (char_table, range);
6d475204
RS
2002 else if (SYMBOLP (range))
2003 {
2004 Lisp_Object charset_info;
2005
2006 charset_info = Fget (range, Qcharset);
2007 CHECK_VECTOR (charset_info, 0);
2008
21ab867f
AS
2009 return Faref (char_table,
2010 make_number (XINT (XVECTOR (charset_info)->contents[0])
2011 + 128));
6d475204 2012 }
999de246
RS
2013 else if (VECTORP (range))
2014 {
e814a159 2015 if (XVECTOR (range)->size == 1)
21ab867f
AS
2016 return Faref (char_table,
2017 make_number (XINT (XVECTOR (range)->contents[0]) + 128));
e814a159
RS
2018 else
2019 {
2020 int size = XVECTOR (range)->size;
2021 Lisp_Object *val = XVECTOR (range)->contents;
2022 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
2023 size <= 1 ? Qnil : val[1],
2024 size <= 2 ? Qnil : val[2]);
2025 return Faref (char_table, ch);
2026 }
999de246
RS
2027 }
2028 else
2029 error ("Invalid RANGE argument to `char-table-range'");
2030}
2031
e03f7933
RS
2032DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
2033 3, 3, 0,
88fe8140 2034 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
e03f7933
RS
2035RANGE should be t (for all characters), nil (for the default value)\n\
2036a vector which identifies a character set or a row of a character set,\n\
6d475204 2037a coding system, or a character code.")
88fe8140
EN
2038 (char_table, range, value)
2039 Lisp_Object char_table, range, value;
e03f7933
RS
2040{
2041 int i;
2042
88fe8140 2043 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 2044
e03f7933
RS
2045 if (EQ (range, Qt))
2046 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
88fe8140 2047 XCHAR_TABLE (char_table)->contents[i] = value;
e03f7933 2048 else if (EQ (range, Qnil))
88fe8140 2049 XCHAR_TABLE (char_table)->defalt = value;
6d475204
RS
2050 else if (SYMBOLP (range))
2051 {
2052 Lisp_Object charset_info;
2053
2054 charset_info = Fget (range, Qcharset);
2055 CHECK_VECTOR (charset_info, 0);
2056
21ab867f
AS
2057 return Faset (char_table,
2058 make_number (XINT (XVECTOR (charset_info)->contents[0])
2059 + 128),
6d475204
RS
2060 value);
2061 }
e03f7933 2062 else if (INTEGERP (range))
88fe8140 2063 Faset (char_table, range, value);
e03f7933
RS
2064 else if (VECTORP (range))
2065 {
e814a159 2066 if (XVECTOR (range)->size == 1)
21ab867f
AS
2067 return Faset (char_table,
2068 make_number (XINT (XVECTOR (range)->contents[0]) + 128),
2069 value);
e814a159
RS
2070 else
2071 {
2072 int size = XVECTOR (range)->size;
2073 Lisp_Object *val = XVECTOR (range)->contents;
2074 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
2075 size <= 1 ? Qnil : val[1],
2076 size <= 2 ? Qnil : val[2]);
2077 return Faset (char_table, ch, value);
2078 }
e03f7933
RS
2079 }
2080 else
2081 error ("Invalid RANGE argument to `set-char-table-range'");
2082
2083 return value;
2084}
e1335ba2
KH
2085
2086DEFUN ("set-char-table-default", Fset_char_table_default,
2087 Sset_char_table_default, 3, 3, 0,
2088 "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
2089The generic character specifies the group of characters.\n\
2090See also the documentation of make-char.")
2091 (char_table, ch, value)
2092 Lisp_Object char_table, ch, value;
2093{
ada0fa14 2094 int c, charset, code1, code2;
e1335ba2
KH
2095 Lisp_Object temp;
2096
2097 CHECK_CHAR_TABLE (char_table, 0);
2098 CHECK_NUMBER (ch, 1);
2099
2100 c = XINT (ch);
2db66414 2101 SPLIT_CHAR (c, charset, code1, code2);
0da528a9
KH
2102
2103 /* Since we may want to set the default value for a character set
2104 not yet defined, we check only if the character set is in the
2105 valid range or not, instead of it is already defined or not. */
2106 if (! CHARSET_VALID_P (charset))
f71599f4 2107 invalid_character (c);
e1335ba2
KH
2108
2109 if (charset == CHARSET_ASCII)
2110 return (XCHAR_TABLE (char_table)->defalt = value);
2111
2112 /* Even if C is not a generic char, we had better behave as if a
2113 generic char is specified. */
0da528a9 2114 if (charset == CHARSET_COMPOSITION || CHARSET_DIMENSION (charset) == 1)
e1335ba2
KH
2115 code1 = 0;
2116 temp = XCHAR_TABLE (char_table)->contents[charset + 128];
2117 if (!code1)
2118 {
2119 if (SUB_CHAR_TABLE_P (temp))
2120 XCHAR_TABLE (temp)->defalt = value;
2121 else
2122 XCHAR_TABLE (char_table)->contents[charset + 128] = value;
2123 return value;
2124 }
2125 char_table = temp;
2126 if (! SUB_CHAR_TABLE_P (char_table))
2127 char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
2128 = make_sub_char_table (temp));
2129 temp = XCHAR_TABLE (char_table)->contents[code1];
2130 if (SUB_CHAR_TABLE_P (temp))
2131 XCHAR_TABLE (temp)->defalt = value;
2132 else
2133 XCHAR_TABLE (char_table)->contents[code1] = value;
2134 return value;
2135}
1d969a23
RS
2136
2137/* Look up the element in TABLE at index CH,
2138 and return it as an integer.
2139 If the element is nil, return CH itself.
2140 (Actually we do that for any non-integer.) */
2141
2142int
2143char_table_translate (table, ch)
2144 Lisp_Object table;
2145 int ch;
2146{
2147 Lisp_Object value;
2148 value = Faref (table, make_number (ch));
2149 if (! INTEGERP (value))
2150 return ch;
2151 return XINT (value);
2152}
e03f7933 2153\f
46ed603f 2154/* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
c8640abf
RS
2155 character or group of characters that share a value.
2156 DEPTH is the current depth in the originally specified
2157 chartable, and INDICES contains the vector indices
46ed603f
RS
2158 for the levels our callers have descended.
2159
2160 ARG is passed to C_FUNCTION when that is called. */
c8640abf
RS
2161
2162void
46ed603f 2163map_char_table (c_function, function, subtable, arg, depth, indices)
22e6f12b
AS
2164 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
2165 Lisp_Object function, subtable, arg, *indices;
1847b19b 2166 int depth;
e03f7933 2167{
3720677d 2168 int i, to;
e03f7933 2169
a8283a4a 2170 if (depth == 0)
3720677d
KH
2171 {
2172 /* At first, handle ASCII and 8-bit European characters. */
2173 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
2174 {
46ed603f 2175 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
3720677d 2176 if (c_function)
46ed603f 2177 (*c_function) (arg, make_number (i), elt);
3720677d
KH
2178 else
2179 call2 (function, make_number (i), elt);
2180 }
ea35ce3d
RS
2181#if 0 /* If the char table has entries for higher characters,
2182 we should report them. */
de86fcba
KH
2183 if (NILP (current_buffer->enable_multibyte_characters))
2184 return;
ea35ce3d 2185#endif
3720677d
KH
2186 to = CHAR_TABLE_ORDINARY_SLOTS;
2187 }
a8283a4a 2188 else
e03f7933 2189 {
de86fcba 2190 i = 32;
3720677d 2191 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
e03f7933
RS
2192 }
2193
7e798f25 2194 for (; i < to; i++)
e03f7933 2195 {
46ed603f 2196 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
3720677d 2197
09ee221d 2198 XSETFASTINT (indices[depth], i);
3720677d
KH
2199
2200 if (SUB_CHAR_TABLE_P (elt))
2201 {
2202 if (depth >= 3)
2203 error ("Too deep char table");
7e798f25 2204 map_char_table (c_function, function, elt, arg, depth + 1, indices);
3720677d 2205 }
e03f7933 2206 else
a8283a4a 2207 {
3720677d
KH
2208 int charset = XFASTINT (indices[0]) - 128, c1, c2, c;
2209
a8283a4a
KH
2210 if (CHARSET_DEFINED_P (charset))
2211 {
3720677d
KH
2212 c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
2213 c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
a8283a4a 2214 c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
3720677d 2215 if (c_function)
46ed603f 2216 (*c_function) (arg, make_number (c), elt);
3720677d
KH
2217 else
2218 call2 (function, make_number (c), elt);
a8283a4a 2219 }
b4f334f7 2220 }
e03f7933
RS
2221 }
2222}
2223
2224DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
2225 2, 2, 0,
7e798f25 2226 "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
e03f7933 2227FUNCTION is called with two arguments--a key and a value.\n\
7e798f25 2228The key is always a possible IDX argument to `aref'.")
88fe8140
EN
2229 (function, char_table)
2230 Lisp_Object function, char_table;
e03f7933 2231{
3720677d 2232 /* The depth of char table is at most 3. */
7e798f25
KH
2233 Lisp_Object indices[3];
2234
2235 CHECK_CHAR_TABLE (char_table, 1);
e03f7933 2236
46ed603f 2237 map_char_table (NULL, function, char_table, char_table, 0, indices);
e03f7933
RS
2238 return Qnil;
2239}
2240\f
7b863bd5
JB
2241/* ARGSUSED */
2242Lisp_Object
2243nconc2 (s1, s2)
2244 Lisp_Object s1, s2;
2245{
2246#ifdef NO_ARG_ARRAY
2247 Lisp_Object args[2];
2248 args[0] = s1;
2249 args[1] = s2;
2250 return Fnconc (2, args);
2251#else
2252 return Fnconc (2, &s1);
2253#endif /* NO_ARG_ARRAY */
2254}
2255
2256DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
2257 "Concatenate any number of lists by altering them.\n\
2258Only the last argument is not altered, and need not be a list.")
2259 (nargs, args)
2260 int nargs;
2261 Lisp_Object *args;
2262{
2263 register int argnum;
2264 register Lisp_Object tail, tem, val;
2265
2266 val = Qnil;
2267
2268 for (argnum = 0; argnum < nargs; argnum++)
2269 {
2270 tem = args[argnum];
265a9e55 2271 if (NILP (tem)) continue;
7b863bd5 2272
265a9e55 2273 if (NILP (val))
7b863bd5
JB
2274 val = tem;
2275
2276 if (argnum + 1 == nargs) break;
2277
2278 if (!CONSP (tem))
2279 tem = wrong_type_argument (Qlistp, tem);
2280
2281 while (CONSP (tem))
2282 {
2283 tail = tem;
2284 tem = Fcdr (tail);
2285 QUIT;
2286 }
2287
2288 tem = args[argnum + 1];
2289 Fsetcdr (tail, tem);
265a9e55 2290 if (NILP (tem))
7b863bd5
JB
2291 args[argnum + 1] = tail;
2292 }
2293
2294 return val;
2295}
2296\f
2297/* This is the guts of all mapping functions.
ea35ce3d
RS
2298 Apply FN to each element of SEQ, one by one,
2299 storing the results into elements of VALS, a C vector of Lisp_Objects.
2300 LENI is the length of VALS, which should also be the length of SEQ. */
7b863bd5
JB
2301
2302static void
2303mapcar1 (leni, vals, fn, seq)
2304 int leni;
2305 Lisp_Object *vals;
2306 Lisp_Object fn, seq;
2307{
2308 register Lisp_Object tail;
2309 Lisp_Object dummy;
2310 register int i;
2311 struct gcpro gcpro1, gcpro2, gcpro3;
2312
2313 /* Don't let vals contain any garbage when GC happens. */
2314 for (i = 0; i < leni; i++)
2315 vals[i] = Qnil;
2316
2317 GCPRO3 (dummy, fn, seq);
2318 gcpro1.var = vals;
2319 gcpro1.nvars = leni;
2320 /* We need not explicitly protect `tail' because it is used only on lists, and
2321 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
2322
7650760e 2323 if (VECTORP (seq))
7b863bd5
JB
2324 {
2325 for (i = 0; i < leni; i++)
2326 {
2327 dummy = XVECTOR (seq)->contents[i];
2328 vals[i] = call1 (fn, dummy);
2329 }
2330 }
33aa0881
KH
2331 else if (BOOL_VECTOR_P (seq))
2332 {
2333 for (i = 0; i < leni; i++)
2334 {
2335 int byte;
2336 byte = XBOOL_VECTOR (seq)->data[i / BITS_PER_CHAR];
2337 if (byte & (1 << (i % BITS_PER_CHAR)))
2338 dummy = Qt;
2339 else
2340 dummy = Qnil;
2341
2342 vals[i] = call1 (fn, dummy);
2343 }
2344 }
ea35ce3d 2345 else if (STRINGP (seq) && ! STRING_MULTIBYTE (seq))
7b863bd5 2346 {
ea35ce3d 2347 /* Single-byte string. */
7b863bd5
JB
2348 for (i = 0; i < leni; i++)
2349 {
ad17573a 2350 XSETFASTINT (dummy, XSTRING (seq)->data[i]);
7b863bd5
JB
2351 vals[i] = call1 (fn, dummy);
2352 }
2353 }
ea35ce3d
RS
2354 else if (STRINGP (seq))
2355 {
2356 /* Multi-byte string. */
ea35ce3d
RS
2357 int i_byte;
2358
2359 for (i = 0, i_byte = 0; i < leni;)
2360 {
2361 int c;
0ab6a3d8
KH
2362 int i_before = i;
2363
2364 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte);
ea35ce3d 2365 XSETFASTINT (dummy, c);
0ab6a3d8 2366 vals[i_before] = call1 (fn, dummy);
ea35ce3d
RS
2367 }
2368 }
7b863bd5
JB
2369 else /* Must be a list, since Flength did not get an error */
2370 {
2371 tail = seq;
2372 for (i = 0; i < leni; i++)
2373 {
2374 vals[i] = call1 (fn, Fcar (tail));
70949dac 2375 tail = XCDR (tail);
7b863bd5
JB
2376 }
2377 }
2378
2379 UNGCPRO;
2380}
2381
2382DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
88fe8140
EN
2383 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2384In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
33aa0881
KH
2385SEPARATOR results in spaces between the values returned by FUNCTION.\n\
2386SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2387 (function, sequence, separator)
2388 Lisp_Object function, sequence, separator;
7b863bd5
JB
2389{
2390 Lisp_Object len;
2391 register int leni;
2392 int nargs;
2393 register Lisp_Object *args;
2394 register int i;
2395 struct gcpro gcpro1;
2396
88fe8140 2397 len = Flength (sequence);
7b863bd5
JB
2398 leni = XINT (len);
2399 nargs = leni + leni - 1;
2400 if (nargs < 0) return build_string ("");
2401
2402 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2403
88fe8140
EN
2404 GCPRO1 (separator);
2405 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2406 UNGCPRO;
2407
2408 for (i = leni - 1; i >= 0; i--)
2409 args[i + i] = args[i];
b4f334f7 2410
7b863bd5 2411 for (i = 1; i < nargs; i += 2)
88fe8140 2412 args[i] = separator;
7b863bd5
JB
2413
2414 return Fconcat (nargs, args);
2415}
2416
2417DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2418 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2419The result is a list just as long as SEQUENCE.\n\
33aa0881 2420SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2421 (function, sequence)
2422 Lisp_Object function, sequence;
7b863bd5
JB
2423{
2424 register Lisp_Object len;
2425 register int leni;
2426 register Lisp_Object *args;
2427
88fe8140 2428 len = Flength (sequence);
7b863bd5
JB
2429 leni = XFASTINT (len);
2430 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2431
88fe8140 2432 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2433
2434 return Flist (leni, args);
2435}
2436\f
2437/* Anything that calls this function must protect from GC! */
2438
2439DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2440 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
c763f396
RS
2441Takes one argument, which is the string to display to ask the question.\n\
2442It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
7b863bd5 2443No confirmation of the answer is requested; a single character is enough.\n\
2b8503ea
KH
2444Also accepts Space to mean yes, or Delete to mean no. \(Actually, it uses\n\
2445the bindings in query-replace-map; see the documentation of that variable\n\
2446for more information. In this case, the useful bindings are `act', `skip',\n\
2447`recenter', and `quit'.\)\n\
0c6ca44b
DL
2448\n\
2449Under a windowing system a dialog box will be used if `last-nonmenu-event'\n\
2450is nil.")
7b863bd5
JB
2451 (prompt)
2452 Lisp_Object prompt;
2453{
2b8503ea 2454 register Lisp_Object obj, key, def, map;
f5313ed9 2455 register int answer;
7b863bd5
JB
2456 Lisp_Object xprompt;
2457 Lisp_Object args[2];
7b863bd5 2458 struct gcpro gcpro1, gcpro2;
eb4ffa4e
RS
2459 int count = specpdl_ptr - specpdl;
2460
2461 specbind (Qcursor_in_echo_area, Qt);
7b863bd5 2462
f5313ed9
RS
2463 map = Fsymbol_value (intern ("query-replace-map"));
2464
7b863bd5
JB
2465 CHECK_STRING (prompt, 0);
2466 xprompt = prompt;
2467 GCPRO2 (prompt, xprompt);
2468
2469 while (1)
2470 {
eb4ffa4e 2471
0ef68e8a 2472#ifdef HAVE_MENUS
588064ce 2473 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2474 && use_dialog_box
0ef68e8a 2475 && have_menus_p ())
1db4cfb2
RS
2476 {
2477 Lisp_Object pane, menu;
a3b14a45 2478 redisplay_preserve_echo_area ();
1db4cfb2
RS
2479 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2480 Fcons (Fcons (build_string ("No"), Qnil),
2481 Qnil));
ec26e1b9 2482 menu = Fcons (prompt, pane);
d2f28f78 2483 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2484 answer = !NILP (obj);
2485 break;
2486 }
0ef68e8a 2487#endif /* HAVE_MENUS */
dfa89228 2488 cursor_in_echo_area = 1;
b312cc52 2489 choose_minibuf_frame ();
ea35ce3d 2490 message_with_string ("%s(y or n) ", xprompt, 0);
7b863bd5 2491
2d8e7e1f
RS
2492 if (minibuffer_auto_raise)
2493 {
2494 Lisp_Object mini_frame;
2495
2496 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2497
2498 Fraise_frame (mini_frame);
2499 }
2500
7ba13c57 2501 obj = read_filtered_event (1, 0, 0, 0);
dfa89228
KH
2502 cursor_in_echo_area = 0;
2503 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2504 QUIT;
a63f658b 2505
f5313ed9 2506 key = Fmake_vector (make_number (1), obj);
aad2a123 2507 def = Flookup_key (map, key, Qt);
7b863bd5 2508
f5313ed9
RS
2509 if (EQ (def, intern ("skip")))
2510 {
2511 answer = 0;
2512 break;
2513 }
2514 else if (EQ (def, intern ("act")))
2515 {
2516 answer = 1;
2517 break;
2518 }
29944b73
RS
2519 else if (EQ (def, intern ("recenter")))
2520 {
2521 Frecenter (Qnil);
2522 xprompt = prompt;
2523 continue;
2524 }
f5313ed9 2525 else if (EQ (def, intern ("quit")))
7b863bd5 2526 Vquit_flag = Qt;
ec63af1b
RS
2527 /* We want to exit this command for exit-prefix,
2528 and this is the only way to do it. */
2529 else if (EQ (def, intern ("exit-prefix")))
2530 Vquit_flag = Qt;
f5313ed9 2531
7b863bd5 2532 QUIT;
20aa96aa
JB
2533
2534 /* If we don't clear this, then the next call to read_char will
2535 return quit_char again, and we'll enter an infinite loop. */
088880f1 2536 Vquit_flag = Qnil;
7b863bd5
JB
2537
2538 Fding (Qnil);
2539 Fdiscard_input ();
2540 if (EQ (xprompt, prompt))
2541 {
2542 args[0] = build_string ("Please answer y or n. ");
2543 args[1] = prompt;
2544 xprompt = Fconcat (2, args);
2545 }
2546 }
2547 UNGCPRO;
6a8a9750 2548
09c95874
RS
2549 if (! noninteractive)
2550 {
2551 cursor_in_echo_area = -1;
ea35ce3d
RS
2552 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2553 xprompt, 0);
09c95874 2554 }
6a8a9750 2555
eb4ffa4e 2556 unbind_to (count, Qnil);
f5313ed9 2557 return answer ? Qt : Qnil;
7b863bd5
JB
2558}
2559\f
2560/* This is how C code calls `yes-or-no-p' and allows the user
2561 to redefined it.
2562
2563 Anything that calls this function must protect from GC! */
2564
2565Lisp_Object
2566do_yes_or_no_p (prompt)
2567 Lisp_Object prompt;
2568{
2569 return call1 (intern ("yes-or-no-p"), prompt);
2570}
2571
2572/* Anything that calls this function must protect from GC! */
2573
2574DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
c763f396
RS
2575 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2576Takes one argument, which is the string to display to ask the question.\n\
2577It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2578The user must confirm the answer with RET,\n\
0c6ca44b
DL
2579and can edit it until it has been confirmed.\n\
2580\n\
2581Under a windowing system a dialog box will be used if `last-nonmenu-event'\n\
2582is nil.")
7b863bd5
JB
2583 (prompt)
2584 Lisp_Object prompt;
2585{
2586 register Lisp_Object ans;
2587 Lisp_Object args[2];
2588 struct gcpro gcpro1;
2589
2590 CHECK_STRING (prompt, 0);
2591
0ef68e8a 2592#ifdef HAVE_MENUS
b4f334f7 2593 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2594 && use_dialog_box
0ef68e8a 2595 && have_menus_p ())
1db4cfb2
RS
2596 {
2597 Lisp_Object pane, menu, obj;
a3b14a45 2598 redisplay_preserve_echo_area ();
1db4cfb2
RS
2599 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2600 Fcons (Fcons (build_string ("No"), Qnil),
2601 Qnil));
2602 GCPRO1 (pane);
ec26e1b9 2603 menu = Fcons (prompt, pane);
b5ccb0a9 2604 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2605 UNGCPRO;
2606 return obj;
2607 }
0ef68e8a 2608#endif /* HAVE_MENUS */
1db4cfb2 2609
7b863bd5
JB
2610 args[0] = prompt;
2611 args[1] = build_string ("(yes or no) ");
2612 prompt = Fconcat (2, args);
2613
2614 GCPRO1 (prompt);
1db4cfb2 2615
7b863bd5
JB
2616 while (1)
2617 {
0ce830bc 2618 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
b24014d4
KH
2619 Qyes_or_no_p_history, Qnil,
2620 Qnil));
7b863bd5
JB
2621 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2622 {
2623 UNGCPRO;
2624 return Qt;
2625 }
2626 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2627 {
2628 UNGCPRO;
2629 return Qnil;
2630 }
2631
2632 Fding (Qnil);
2633 Fdiscard_input ();
2634 message ("Please answer yes or no.");
99dc4745 2635 Fsleep_for (make_number (2), Qnil);
7b863bd5 2636 }
7b863bd5
JB
2637}
2638\f
f4b50f66 2639DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
7b863bd5
JB
2640 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
2641Each of the three load averages is multiplied by 100,\n\
daa37602 2642then converted to integer.\n\
f4b50f66
RS
2643When USE-FLOATS is non-nil, floats will be used instead of integers.\n\
2644These floats are not multiplied by 100.\n\n\
daa37602
JB
2645If the 5-minute or 15-minute load averages are not available, return a\n\
2646shortened list, containing only those averages which are available.")
f4b50f66
RS
2647 (use_floats)
2648 Lisp_Object use_floats;
7b863bd5 2649{
daa37602
JB
2650 double load_ave[3];
2651 int loads = getloadavg (load_ave, 3);
f4b50f66 2652 Lisp_Object ret = Qnil;
7b863bd5 2653
daa37602
JB
2654 if (loads < 0)
2655 error ("load-average not implemented for this operating system");
2656
f4b50f66
RS
2657 while (loads-- > 0)
2658 {
2659 Lisp_Object load = (NILP (use_floats) ?
2660 make_number ((int) (100.0 * load_ave[loads]))
2661 : make_float (load_ave[loads]));
2662 ret = Fcons (load, ret);
2663 }
daa37602
JB
2664
2665 return ret;
2666}
7b863bd5
JB
2667\f
2668Lisp_Object Vfeatures;
2669
2670DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
2671 "Returns t if FEATURE is present in this Emacs.\n\
2672Use this to conditionalize execution of lisp code based on the presence or\n\
2673absence of emacs or environment extensions.\n\
2674Use `provide' to declare that a feature is available.\n\
2675This function looks at the value of the variable `features'.")
b4f334f7 2676 (feature)
7b863bd5
JB
2677 Lisp_Object feature;
2678{
2679 register Lisp_Object tem;
2680 CHECK_SYMBOL (feature, 0);
2681 tem = Fmemq (feature, Vfeatures);
265a9e55 2682 return (NILP (tem)) ? Qnil : Qt;
7b863bd5
JB
2683}
2684
2685DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
2686 "Announce that FEATURE is a feature of the current Emacs.")
b4f334f7 2687 (feature)
7b863bd5
JB
2688 Lisp_Object feature;
2689{
2690 register Lisp_Object tem;
2691 CHECK_SYMBOL (feature, 0);
265a9e55 2692 if (!NILP (Vautoload_queue))
7b863bd5
JB
2693 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
2694 tem = Fmemq (feature, Vfeatures);
265a9e55 2695 if (NILP (tem))
7b863bd5 2696 Vfeatures = Fcons (feature, Vfeatures);
68732608 2697 LOADHIST_ATTACH (Fcons (Qprovide, feature));
7b863bd5
JB
2698 return feature;
2699}
2700
53d5acf5 2701DEFUN ("require", Frequire, Srequire, 1, 3, 0,
7b863bd5
JB
2702 "If feature FEATURE is not loaded, load it from FILENAME.\n\
2703If FEATURE is not a member of the list `features', then the feature\n\
2704is not loaded; so load the file FILENAME.\n\
f0c030b3 2705If FILENAME is omitted, the printname of FEATURE is used as the file name,\n\
53d5acf5
RS
2706but in this case `load' insists on adding the suffix `.el' or `.elc'.\n\
2707If the optional third argument NOERROR is non-nil,\n\
2708then return nil if the file is not found.\n\
2709Normally the return value is FEATURE.")
2710 (feature, file_name, noerror)
2711 Lisp_Object feature, file_name, noerror;
7b863bd5
JB
2712{
2713 register Lisp_Object tem;
2714 CHECK_SYMBOL (feature, 0);
2715 tem = Fmemq (feature, Vfeatures);
68732608 2716 LOADHIST_ATTACH (Fcons (Qrequire, feature));
265a9e55 2717 if (NILP (tem))
7b863bd5
JB
2718 {
2719 int count = specpdl_ptr - specpdl;
2720
2721 /* Value saved here is to be restored into Vautoload_queue */
2722 record_unwind_protect (un_autoload, Vautoload_queue);
2723 Vautoload_queue = Qt;
2724
53d5acf5
RS
2725 tem = Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
2726 noerror, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
2727 /* If load failed entirely, return nil. */
2728 if (NILP (tem))
41857307 2729 return unbind_to (count, Qnil);
7b863bd5
JB
2730
2731 tem = Fmemq (feature, Vfeatures);
265a9e55 2732 if (NILP (tem))
7b863bd5 2733 error ("Required feature %s was not provided",
fdb5bec0 2734 XSYMBOL (feature)->name->data);
7b863bd5
JB
2735
2736 /* Once loading finishes, don't undo it. */
2737 Vautoload_queue = Qt;
2738 feature = unbind_to (count, feature);
2739 }
2740 return feature;
2741}
2742\f
b4f334f7
KH
2743/* Primitives for work of the "widget" library.
2744 In an ideal world, this section would not have been necessary.
2745 However, lisp function calls being as slow as they are, it turns
2746 out that some functions in the widget library (wid-edit.el) are the
2747 bottleneck of Widget operation. Here is their translation to C,
2748 for the sole reason of efficiency. */
2749
2750DEFUN ("widget-plist-member", Fwidget_plist_member, Swidget_plist_member, 2, 2, 0,
2751 "Return non-nil if PLIST has the property PROP.\n\
2752PLIST is a property list, which is a list of the form\n\
2753\(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
2754Unlike `plist-get', this allows you to distinguish between a missing\n\
2755property and a property with the value nil.\n\
2756The value is actually the tail of PLIST whose car is PROP.")
2757 (plist, prop)
2758 Lisp_Object plist, prop;
2759{
2760 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2761 {
2762 QUIT;
2763 plist = XCDR (plist);
2764 plist = CDR (plist);
2765 }
2766 return plist;
2767}
2768
2769DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
2770 "In WIDGET, set PROPERTY to VALUE.\n\
2771The value can later be retrieved with `widget-get'.")
2772 (widget, property, value)
2773 Lisp_Object widget, property, value;
2774{
2775 CHECK_CONS (widget, 1);
2776 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
f7993597 2777 return value;
b4f334f7
KH
2778}
2779
2780DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
2781 "In WIDGET, get the value of PROPERTY.\n\
2782The value could either be specified when the widget was created, or\n\
2783later with `widget-put'.")
2784 (widget, property)
2785 Lisp_Object widget, property;
2786{
2787 Lisp_Object tmp;
2788
2789 while (1)
2790 {
2791 if (NILP (widget))
2792 return Qnil;
2793 CHECK_CONS (widget, 1);
2794 tmp = Fwidget_plist_member (XCDR (widget), property);
2795 if (CONSP (tmp))
2796 {
2797 tmp = XCDR (tmp);
2798 return CAR (tmp);
2799 }
2800 tmp = XCAR (widget);
2801 if (NILP (tmp))
2802 return Qnil;
2803 widget = Fget (tmp, Qwidget_type);
2804 }
2805}
2806
2807DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
2808 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
2809ARGS are passed as extra arguments to the function.")
2810 (nargs, args)
2811 int nargs;
2812 Lisp_Object *args;
2813{
2814 /* This function can GC. */
2815 Lisp_Object newargs[3];
2816 struct gcpro gcpro1, gcpro2;
2817 Lisp_Object result;
2818
2819 newargs[0] = Fwidget_get (args[0], args[1]);
2820 newargs[1] = args[0];
2821 newargs[2] = Flist (nargs - 2, args + 2);
2822 GCPRO2 (newargs[0], newargs[2]);
2823 result = Fapply (3, newargs);
2824 UNGCPRO;
2825 return result;
2826}
2827\f
24c129e4
KH
2828/* base64 encode/decode functions.
2829 Based on code from GNU recode. */
2830
2831#define MIME_LINE_LENGTH 76
2832
2833#define IS_ASCII(Character) \
2834 ((Character) < 128)
2835#define IS_BASE64(Character) \
2836 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0)
9a092df0
PF
2837#define IS_BASE64_IGNORABLE(Character) \
2838 ((Character) == ' ' || (Character) == '\t' || (Character) == '\n' \
2839 || (Character) == '\f' || (Character) == '\r')
2840
2841/* Used by base64_decode_1 to retrieve a non-base64-ignorable
2842 character or return retval if there are no characters left to
2843 process. */
2844#define READ_QUADRUPLET_BYTE(retval) \
2845 do \
2846 { \
2847 if (i == length) \
2848 return (retval); \
2849 c = from[i++]; \
2850 } \
2851 while (IS_BASE64_IGNORABLE (c))
24c129e4 2852
4b2e75e6
EZ
2853/* Don't use alloca for regions larger than this, lest we overflow
2854 their stack. */
2855#define MAX_ALLOCA 16*1024
2856
24c129e4
KH
2857/* Table of characters coding the 64 values. */
2858static char base64_value_to_char[64] =
2859{
2860 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */
2861 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */
2862 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */
2863 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 30-39 */
2864 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */
2865 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */
2866 '8', '9', '+', '/' /* 60-63 */
2867};
2868
2869/* Table of base64 values for first 128 characters. */
2870static short base64_char_to_value[128] =
2871{
2872 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
2873 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
2874 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */
2875 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */
2876 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */
2877 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */
2878 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */
2879 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */
2880 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */
2881 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */
2882 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */
2883 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
2884 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
2885};
2886
2887/* The following diagram shows the logical steps by which three octets
2888 get transformed into four base64 characters.
2889
2890 .--------. .--------. .--------.
2891 |aaaaaabb| |bbbbcccc| |ccdddddd|
2892 `--------' `--------' `--------'
2893 6 2 4 4 2 6
2894 .--------+--------+--------+--------.
2895 |00aaaaaa|00bbbbbb|00cccccc|00dddddd|
2896 `--------+--------+--------+--------'
2897
2898 .--------+--------+--------+--------.
2899 |AAAAAAAA|BBBBBBBB|CCCCCCCC|DDDDDDDD|
2900 `--------+--------+--------+--------'
2901
2902 The octets are divided into 6 bit chunks, which are then encoded into
2903 base64 characters. */
2904
2905
2906static int base64_encode_1 P_ ((const char *, char *, int, int));
2907static int base64_decode_1 P_ ((const char *, char *, int));
2908
2909DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region,
2910 2, 3, "r",
46ac5b26 2911 "Base64-encode the region between BEG and END.\n\
15a9a50c 2912Return the length of the encoded text.\n\
24c129e4
KH
2913Optional third argument NO-LINE-BREAK means do not break long lines\n\
2914into shorter lines.")
2915 (beg, end, no_line_break)
2916 Lisp_Object beg, end, no_line_break;
2917{
2918 char *encoded;
2919 int allength, length;
2920 int ibeg, iend, encoded_length;
2921 int old_pos = PT;
2922
2923 validate_region (&beg, &end);
2924
2925 ibeg = CHAR_TO_BYTE (XFASTINT (beg));
2926 iend = CHAR_TO_BYTE (XFASTINT (end));
2927 move_gap_both (XFASTINT (beg), ibeg);
2928
2929 /* We need to allocate enough room for encoding the text.
2930 We need 33 1/3% more space, plus a newline every 76
2931 characters, and then we round up. */
2932 length = iend - ibeg;
2933 allength = length + length/3 + 1;
2934 allength += allength / MIME_LINE_LENGTH + 1 + 6;
2935
4b2e75e6
EZ
2936 if (allength <= MAX_ALLOCA)
2937 encoded = (char *) alloca (allength);
2938 else
2939 encoded = (char *) xmalloc (allength);
24c129e4
KH
2940 encoded_length = base64_encode_1 (BYTE_POS_ADDR (ibeg), encoded, length,
2941 NILP (no_line_break));
2942 if (encoded_length > allength)
2943 abort ();
2944
2945 /* Now we have encoded the region, so we insert the new contents
2946 and delete the old. (Insert first in order to preserve markers.) */
8b835738 2947 SET_PT_BOTH (XFASTINT (beg), ibeg);
24c129e4 2948 insert (encoded, encoded_length);
4b2e75e6 2949 if (allength > MAX_ALLOCA)
8c217645 2950 xfree (encoded);
24c129e4
KH
2951 del_range_byte (ibeg + encoded_length, iend + encoded_length, 1);
2952
2953 /* If point was outside of the region, restore it exactly; else just
2954 move to the beginning of the region. */
2955 if (old_pos >= XFASTINT (end))
2956 old_pos += encoded_length - (XFASTINT (end) - XFASTINT (beg));
8b835738
AS
2957 else if (old_pos > XFASTINT (beg))
2958 old_pos = XFASTINT (beg);
24c129e4
KH
2959 SET_PT (old_pos);
2960
2961 /* We return the length of the encoded text. */
2962 return make_number (encoded_length);
2963}
2964
2965DEFUN ("base64-encode-string", Fbase64_encode_string, Sbase64_encode_string,
c22554ac
KH
2966 1, 2, 0,
2967 "Base64-encode STRING and return the result.\n\
2968Optional second argument NO-LINE-BREAK means do not break long lines\n\
2969into shorter lines.")
2970 (string, no_line_break)
915b8312 2971 Lisp_Object string, no_line_break;
24c129e4
KH
2972{
2973 int allength, length, encoded_length;
2974 char *encoded;
4b2e75e6 2975 Lisp_Object encoded_string;
24c129e4
KH
2976
2977 CHECK_STRING (string, 1);
2978
7f8a0840
KH
2979 /* We need to allocate enough room for encoding the text.
2980 We need 33 1/3% more space, plus a newline every 76
2981 characters, and then we round up. */
24c129e4 2982 length = STRING_BYTES (XSTRING (string));
7f8a0840
KH
2983 allength = length + length/3 + 1;
2984 allength += allength / MIME_LINE_LENGTH + 1 + 6;
24c129e4
KH
2985
2986 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
2987 if (allength <= MAX_ALLOCA)
2988 encoded = (char *) alloca (allength);
2989 else
2990 encoded = (char *) xmalloc (allength);
24c129e4
KH
2991
2992 encoded_length = base64_encode_1 (XSTRING (string)->data,
c22554ac 2993 encoded, length, NILP (no_line_break));
24c129e4
KH
2994 if (encoded_length > allength)
2995 abort ();
2996
4b2e75e6
EZ
2997 encoded_string = make_unibyte_string (encoded, encoded_length);
2998 if (allength > MAX_ALLOCA)
8c217645 2999 xfree (encoded);
4b2e75e6
EZ
3000
3001 return encoded_string;
24c129e4
KH
3002}
3003
3004static int
3005base64_encode_1 (from, to, length, line_break)
3006 const char *from;
3007 char *to;
3008 int length;
3009 int line_break;
3010{
3011 int counter = 0, i = 0;
3012 char *e = to;
3013 unsigned char c;
3014 unsigned int value;
3015
3016 while (i < length)
3017 {
3018 c = from[i++];
3019
3020 /* Wrap line every 76 characters. */
3021
3022 if (line_break)
3023 {
3024 if (counter < MIME_LINE_LENGTH / 4)
3025 counter++;
3026 else
3027 {
3028 *e++ = '\n';
3029 counter = 1;
3030 }
3031 }
3032
3033 /* Process first byte of a triplet. */
3034
3035 *e++ = base64_value_to_char[0x3f & c >> 2];
3036 value = (0x03 & c) << 4;
3037
3038 /* Process second byte of a triplet. */
3039
3040 if (i == length)
3041 {
3042 *e++ = base64_value_to_char[value];
3043 *e++ = '=';
3044 *e++ = '=';
3045 break;
3046 }
3047
3048 c = from[i++];
3049
3050 *e++ = base64_value_to_char[value | (0x0f & c >> 4)];
3051 value = (0x0f & c) << 2;
3052
3053 /* Process third byte of a triplet. */
3054
3055 if (i == length)
3056 {
3057 *e++ = base64_value_to_char[value];
3058 *e++ = '=';
3059 break;
3060 }
3061
3062 c = from[i++];
3063
3064 *e++ = base64_value_to_char[value | (0x03 & c >> 6)];
3065 *e++ = base64_value_to_char[0x3f & c];
3066 }
3067
24c129e4
KH
3068 return e - to;
3069}
3070
3071
3072DEFUN ("base64-decode-region", Fbase64_decode_region, Sbase64_decode_region,
3073 2, 2, "r",
46ac5b26 3074 "Base64-decode the region between BEG and END.\n\
15a9a50c 3075Return the length of the decoded text.\n\
24c129e4
KH
3076If the region can't be decoded, return nil and don't modify the buffer.")
3077 (beg, end)
3078 Lisp_Object beg, end;
3079{
3080 int ibeg, iend, length;
3081 char *decoded;
3082 int old_pos = PT;
3083 int decoded_length;
9b703a38 3084 int inserted_chars;
24c129e4
KH
3085
3086 validate_region (&beg, &end);
3087
3088 ibeg = CHAR_TO_BYTE (XFASTINT (beg));
3089 iend = CHAR_TO_BYTE (XFASTINT (end));
3090
3091 length = iend - ibeg;
3092 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3093 if (length <= MAX_ALLOCA)
3094 decoded = (char *) alloca (length);
3095 else
3096 decoded = (char *) xmalloc (length);
24c129e4
KH
3097
3098 move_gap_both (XFASTINT (beg), ibeg);
3099 decoded_length = base64_decode_1 (BYTE_POS_ADDR (ibeg), decoded, length);
3100 if (decoded_length > length)
3101 abort ();
3102
3103 if (decoded_length < 0)
8c217645
KH
3104 {
3105 /* The decoding wasn't possible. */
3106 if (length > MAX_ALLOCA)
3107 xfree (decoded);
3108 return Qnil;
3109 }
24c129e4
KH
3110
3111 /* Now we have decoded the region, so we insert the new contents
3112 and delete the old. (Insert first in order to preserve markers.) */
9b703a38
KH
3113 /* We insert two spaces, then insert the decoded text in between
3114 them, at last, delete those extra two spaces. This is to avoid
922dfd86 3115 byte combining while inserting. */
9b703a38
KH
3116 TEMP_SET_PT_BOTH (XFASTINT (beg), ibeg);
3117 insert_1_both (" ", 2, 2, 0, 1, 0);
3118 TEMP_SET_PT_BOTH (XFASTINT (beg) + 1, ibeg + 1);
24c129e4 3119 insert (decoded, decoded_length);
9b703a38 3120 inserted_chars = PT - (XFASTINT (beg) + 1);
4b2e75e6 3121 if (length > MAX_ALLOCA)
8c217645 3122 xfree (decoded);
922dfd86
KH
3123 /* At first delete the original text. This never cause byte
3124 combining. */
3125 del_range_both (PT + 1, PT_BYTE + 1, XFASTINT (end) + inserted_chars + 2,
9b703a38 3126 iend + decoded_length + 2, 1);
922dfd86
KH
3127 /* Next delete the extra spaces. This will cause byte combining
3128 error. */
3129 del_range_both (PT, PT_BYTE, PT + 1, PT_BYTE + 1, 0);
3130 del_range_both (XFASTINT (beg), ibeg, XFASTINT (beg) + 1, ibeg + 1, 0);
9b703a38 3131 inserted_chars = PT - XFASTINT (beg);
24c129e4
KH
3132
3133 /* If point was outside of the region, restore it exactly; else just
3134 move to the beginning of the region. */
3135 if (old_pos >= XFASTINT (end))
9b703a38
KH
3136 old_pos += inserted_chars - (XFASTINT (end) - XFASTINT (beg));
3137 else if (old_pos > XFASTINT (beg))
3138 old_pos = XFASTINT (beg);
e52ad9c9 3139 SET_PT (old_pos > ZV ? ZV : old_pos);
24c129e4 3140
9b703a38 3141 return make_number (inserted_chars);
24c129e4
KH
3142}
3143
3144DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
3145 1, 1, 0,
46ac5b26 3146 "Base64-decode STRING and return the result.")
24c129e4
KH
3147 (string)
3148 Lisp_Object string;
3149{
3150 char *decoded;
3151 int length, decoded_length;
4b2e75e6 3152 Lisp_Object decoded_string;
24c129e4
KH
3153
3154 CHECK_STRING (string, 1);
3155
3156 length = STRING_BYTES (XSTRING (string));
3157 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3158 if (length <= MAX_ALLOCA)
3159 decoded = (char *) alloca (length);
3160 else
3161 decoded = (char *) xmalloc (length);
24c129e4
KH
3162
3163 decoded_length = base64_decode_1 (XSTRING (string)->data, decoded, length);
3164 if (decoded_length > length)
3165 abort ();
3166
3167 if (decoded_length < 0)
8c217645
KH
3168 /* The decoding wasn't possible. */
3169 decoded_string = Qnil;
3170 else
3171 decoded_string = make_string (decoded, decoded_length);
24c129e4 3172
4b2e75e6 3173 if (length > MAX_ALLOCA)
8c217645 3174 xfree (decoded);
4b2e75e6
EZ
3175
3176 return decoded_string;
24c129e4
KH
3177}
3178
3179static int
3180base64_decode_1 (from, to, length)
3181 const char *from;
3182 char *to;
3183 int length;
3184{
9a092df0 3185 int i = 0;
24c129e4
KH
3186 char *e = to;
3187 unsigned char c;
3188 unsigned long value;
3189
9a092df0 3190 while (1)
24c129e4 3191 {
9a092df0 3192 /* Process first byte of a quadruplet. */
24c129e4 3193
9a092df0 3194 READ_QUADRUPLET_BYTE (e-to);
24c129e4
KH
3195
3196 if (!IS_BASE64 (c))
3197 return -1;
3198 value = base64_char_to_value[c] << 18;
3199
3200 /* Process second byte of a quadruplet. */
3201
9a092df0 3202 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3203
3204 if (!IS_BASE64 (c))
3205 return -1;
3206 value |= base64_char_to_value[c] << 12;
3207
3208 *e++ = (unsigned char) (value >> 16);
3209
3210 /* Process third byte of a quadruplet. */
9a092df0
PF
3211
3212 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3213
3214 if (c == '=')
3215 {
9a092df0
PF
3216 READ_QUADRUPLET_BYTE (-1);
3217
24c129e4
KH
3218 if (c != '=')
3219 return -1;
3220 continue;
3221 }
3222
3223 if (!IS_BASE64 (c))
3224 return -1;
3225 value |= base64_char_to_value[c] << 6;
3226
3227 *e++ = (unsigned char) (0xff & value >> 8);
3228
3229 /* Process fourth byte of a quadruplet. */
3230
9a092df0 3231 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3232
3233 if (c == '=')
3234 continue;
3235
3236 if (!IS_BASE64 (c))
3237 return -1;
3238 value |= base64_char_to_value[c];
3239
3240 *e++ = (unsigned char) (0xff & value);
3241 }
24c129e4 3242}
d80c6c11
GM
3243
3244
3245\f
3246/***********************************************************************
3247 ***** *****
3248 ***** Hash Tables *****
3249 ***** *****
3250 ***********************************************************************/
3251
3252/* Implemented by gerd@gnu.org. This hash table implementation was
3253 inspired by CMUCL hash tables. */
3254
3255/* Ideas:
3256
3257 1. For small tables, association lists are probably faster than
3258 hash tables because they have lower overhead.
3259
3260 For uses of hash tables where the O(1) behavior of table
3261 operations is not a requirement, it might therefore be a good idea
3262 not to hash. Instead, we could just do a linear search in the
3263 key_and_value vector of the hash table. This could be done
3264 if a `:linear-search t' argument is given to make-hash-table. */
3265
3266
3267/* Return the contents of vector V at index IDX. */
3268
3269#define AREF(V, IDX) XVECTOR (V)->contents[IDX]
3270
3271/* Value is the key part of entry IDX in hash table H. */
3272
3273#define HASH_KEY(H, IDX) AREF ((H)->key_and_value, 2 * (IDX))
3274
3275/* Value is the value part of entry IDX in hash table H. */
3276
3277#define HASH_VALUE(H, IDX) AREF ((H)->key_and_value, 2 * (IDX) + 1)
3278
3279/* Value is the index of the next entry following the one at IDX
3280 in hash table H. */
3281
3282#define HASH_NEXT(H, IDX) AREF ((H)->next, (IDX))
3283
3284/* Value is the hash code computed for entry IDX in hash table H. */
3285
3286#define HASH_HASH(H, IDX) AREF ((H)->hash, (IDX))
3287
3288/* Value is the index of the element in hash table H that is the
3289 start of the collision list at index IDX in the index vector of H. */
3290
3291#define HASH_INDEX(H, IDX) AREF ((H)->index, (IDX))
3292
3293/* Value is the size of hash table H. */
3294
3295#define HASH_TABLE_SIZE(H) XVECTOR ((H)->next)->size
3296
3297/* The list of all weak hash tables. Don't staticpro this one. */
3298
3299Lisp_Object Vweak_hash_tables;
3300
3301/* Various symbols. */
3302
f899c503 3303Lisp_Object Qhash_table_p, Qeq, Qeql, Qequal, Qkey, Qvalue;
ee0403b3 3304Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
d80c6c11
GM
3305Lisp_Object Qhash_table_test;
3306
3307/* Function prototypes. */
3308
3309static struct Lisp_Hash_Table *check_hash_table P_ ((Lisp_Object));
3310static int next_almost_prime P_ ((int));
3311static int get_key_arg P_ ((Lisp_Object, int, Lisp_Object *, char *));
3312static Lisp_Object larger_vector P_ ((Lisp_Object, int, Lisp_Object));
3313static void maybe_resize_hash_table P_ ((struct Lisp_Hash_Table *));
d80c6c11
GM
3314static int cmpfn_eql P_ ((struct Lisp_Hash_Table *, Lisp_Object, unsigned,
3315 Lisp_Object, unsigned));
3316static int cmpfn_equal P_ ((struct Lisp_Hash_Table *, Lisp_Object, unsigned,
3317 Lisp_Object, unsigned));
3318static int cmpfn_user_defined P_ ((struct Lisp_Hash_Table *, Lisp_Object,
3319 unsigned, Lisp_Object, unsigned));
3320static unsigned hashfn_eq P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3321static unsigned hashfn_eql P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3322static unsigned hashfn_equal P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3323static unsigned hashfn_user_defined P_ ((struct Lisp_Hash_Table *,
3324 Lisp_Object));
3325static unsigned sxhash_string P_ ((unsigned char *, int));
3326static unsigned sxhash_list P_ ((Lisp_Object, int));
3327static unsigned sxhash_vector P_ ((Lisp_Object, int));
3328static unsigned sxhash_bool_vector P_ ((Lisp_Object));
3329
3330
3331\f
3332/***********************************************************************
3333 Utilities
3334 ***********************************************************************/
3335
3336/* If OBJ is a Lisp hash table, return a pointer to its struct
3337 Lisp_Hash_Table. Otherwise, signal an error. */
3338
3339static struct Lisp_Hash_Table *
3340check_hash_table (obj)
3341 Lisp_Object obj;
3342{
3343 CHECK_HASH_TABLE (obj, 0);
3344 return XHASH_TABLE (obj);
3345}
3346
3347
3348/* Value is the next integer I >= N, N >= 0 which is "almost" a prime
3349 number. */
3350
3351static int
3352next_almost_prime (n)
3353 int n;
3354{
3355 if (n % 2 == 0)
3356 n += 1;
3357 if (n % 3 == 0)
3358 n += 2;
3359 if (n % 7 == 0)
3360 n += 4;
3361 return n;
3362}
3363
3364
3365/* Find KEY in ARGS which has size NARGS. Don't consider indices for
3366 which USED[I] is non-zero. If found at index I in ARGS, set
3367 USED[I] and USED[I + 1] to 1, and return I + 1. Otherwise return
3368 -1. This function is used to extract a keyword/argument pair from
3369 a DEFUN parameter list. */
3370
3371static int
3372get_key_arg (key, nargs, args, used)
3373 Lisp_Object key;
3374 int nargs;
3375 Lisp_Object *args;
3376 char *used;
3377{
3378 int i;
3379
3380 for (i = 0; i < nargs - 1; ++i)
3381 if (!used[i] && EQ (args[i], key))
3382 break;
3383
3384 if (i >= nargs - 1)
3385 i = -1;
3386 else
3387 {
3388 used[i++] = 1;
3389 used[i] = 1;
3390 }
3391
3392 return i;
3393}
3394
3395
3396/* Return a Lisp vector which has the same contents as VEC but has
3397 size NEW_SIZE, NEW_SIZE >= VEC->size. Entries in the resulting
3398 vector that are not copied from VEC are set to INIT. */
3399
3400static Lisp_Object
3401larger_vector (vec, new_size, init)
3402 Lisp_Object vec;
3403 int new_size;
3404 Lisp_Object init;
3405{
3406 struct Lisp_Vector *v;
3407 int i, old_size;
3408
3409 xassert (VECTORP (vec));
3410 old_size = XVECTOR (vec)->size;
3411 xassert (new_size >= old_size);
3412
3413 v = allocate_vectorlike (new_size);
3414 v->size = new_size;
3415 bcopy (XVECTOR (vec)->contents, v->contents,
3416 old_size * sizeof *v->contents);
3417 for (i = old_size; i < new_size; ++i)
3418 v->contents[i] = init;
3419 XSETVECTOR (vec, v);
3420 return vec;
3421}
3422
3423
3424/***********************************************************************
3425 Low-level Functions
3426 ***********************************************************************/
3427
d80c6c11
GM
3428/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
3429 HASH2 in hash table H using `eql'. Value is non-zero if KEY1 and
3430 KEY2 are the same. */
3431
3432static int
3433cmpfn_eql (h, key1, hash1, key2, hash2)
3434 struct Lisp_Hash_Table *h;
3435 Lisp_Object key1, key2;
3436 unsigned hash1, hash2;
3437{
2e5da676
GM
3438 return (FLOATP (key1)
3439 && FLOATP (key2)
e84b1dea 3440 && XFLOAT_DATA (key1) == XFLOAT_DATA (key2));
d80c6c11
GM
3441}
3442
3443
3444/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
3445 HASH2 in hash table H using `equal'. Value is non-zero if KEY1 and
3446 KEY2 are the same. */
3447
3448static int
3449cmpfn_equal (h, key1, hash1, key2, hash2)
3450 struct Lisp_Hash_Table *h;
3451 Lisp_Object key1, key2;
3452 unsigned hash1, hash2;
3453{
2e5da676 3454 return hash1 == hash2 && !NILP (Fequal (key1, key2));
d80c6c11
GM
3455}
3456
3457
3458/* Compare KEY1 which has hash code HASH1, and KEY2 with hash code
3459 HASH2 in hash table H using H->user_cmp_function. Value is non-zero
3460 if KEY1 and KEY2 are the same. */
3461
3462static int
3463cmpfn_user_defined (h, key1, hash1, key2, hash2)
3464 struct Lisp_Hash_Table *h;
3465 Lisp_Object key1, key2;
3466 unsigned hash1, hash2;
3467{
3468 if (hash1 == hash2)
3469 {
3470 Lisp_Object args[3];
3471
3472 args[0] = h->user_cmp_function;
3473 args[1] = key1;
3474 args[2] = key2;
3475 return !NILP (Ffuncall (3, args));
3476 }
3477 else
3478 return 0;
3479}
3480
3481
3482/* Value is a hash code for KEY for use in hash table H which uses
3483 `eq' to compare keys. The hash code returned is guaranteed to fit
3484 in a Lisp integer. */
3485
3486static unsigned
3487hashfn_eq (h, key)
3488 struct Lisp_Hash_Table *h;
3489 Lisp_Object key;
3490{
3491 /* Lisp strings can change their address. Don't try to compute a
3492 hash code for a string from its address. */
3493 if (STRINGP (key))
3494 return sxhash_string (XSTRING (key)->data, XSTRING (key)->size);
3495 else
3496 return XUINT (key) ^ XGCTYPE (key);
3497}
3498
3499
3500/* Value is a hash code for KEY for use in hash table H which uses
3501 `eql' to compare keys. The hash code returned is guaranteed to fit
3502 in a Lisp integer. */
3503
3504static unsigned
3505hashfn_eql (h, key)
3506 struct Lisp_Hash_Table *h;
3507 Lisp_Object key;
3508{
3509 /* Lisp strings can change their address. Don't try to compute a
3510 hash code for a string from its address. */
3511 if (STRINGP (key))
3512 return sxhash_string (XSTRING (key)->data, XSTRING (key)->size);
3513 else if (FLOATP (key))
3514 return sxhash (key, 0);
3515 else
3516 return XUINT (key) ^ XGCTYPE (key);
3517}
3518
3519
3520/* Value is a hash code for KEY for use in hash table H which uses
3521 `equal' to compare keys. The hash code returned is guaranteed to fit
3522 in a Lisp integer. */
3523
3524static unsigned
3525hashfn_equal (h, key)
3526 struct Lisp_Hash_Table *h;
3527 Lisp_Object key;
3528{
3529 return sxhash (key, 0);
3530}
3531
3532
3533/* Value is a hash code for KEY for use in hash table H which uses as
3534 user-defined function to compare keys. The hash code returned is
3535 guaranteed to fit in a Lisp integer. */
3536
3537static unsigned
3538hashfn_user_defined (h, key)
3539 struct Lisp_Hash_Table *h;
3540 Lisp_Object key;
3541{
3542 Lisp_Object args[2], hash;
3543
3544 args[0] = h->user_hash_function;
3545 args[1] = key;
3546 hash = Ffuncall (2, args);
3547 if (!INTEGERP (hash))
3548 Fsignal (Qerror,
3549 list2 (build_string ("Illegal hash code returned from \
3550user-supplied hash function"),
3551 hash));
3552 return XUINT (hash);
3553}
3554
3555
3556/* Create and initialize a new hash table.
3557
3558 TEST specifies the test the hash table will use to compare keys.
3559 It must be either one of the predefined tests `eq', `eql' or
3560 `equal' or a symbol denoting a user-defined test named TEST with
3561 test and hash functions USER_TEST and USER_HASH.
3562
3563 Give the table initial capacity SIZE, SIZE > 0, an integer.
3564
3565 If REHASH_SIZE is an integer, it must be > 0, and this hash table's
3566 new size when it becomes full is computed by adding REHASH_SIZE to
3567 its old size. If REHASH_SIZE is a float, it must be > 1.0, and the
3568 table's new size is computed by multiplying its old size with
3569 REHASH_SIZE.
3570
3571 REHASH_THRESHOLD must be a float <= 1.0, and > 0. The table will
3572 be resized when the ratio of (number of entries in the table) /
3573 (table size) is >= REHASH_THRESHOLD.
3574
3575 WEAK specifies the weakness of the table. If non-nil, it must be
f899c503 3576 one of the symbols `key', `value' or t. */
d80c6c11
GM
3577
3578Lisp_Object
3579make_hash_table (test, size, rehash_size, rehash_threshold, weak,
3580 user_test, user_hash)
3581 Lisp_Object test, size, rehash_size, rehash_threshold, weak;
3582 Lisp_Object user_test, user_hash;
3583{
3584 struct Lisp_Hash_Table *h;
3585 struct Lisp_Vector *v;
3586 Lisp_Object table;
3587 int index_size, i, len, sz;
3588
3589 /* Preconditions. */
3590 xassert (SYMBOLP (test));
3591 xassert (INTEGERP (size) && XINT (size) > 0);
3592 xassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0)
3593 || (FLOATP (rehash_size) && XFLOATINT (rehash_size) > 1.0));
3594 xassert (FLOATP (rehash_threshold)
3595 && XFLOATINT (rehash_threshold) > 0
3596 && XFLOATINT (rehash_threshold) <= 1.0);
3597
3598 /* Allocate a vector, and initialize it. */
3599 len = VECSIZE (struct Lisp_Hash_Table);
3600 v = allocate_vectorlike (len);
3601 v->size = len;
3602 for (i = 0; i < len; ++i)
3603 v->contents[i] = Qnil;
3604
3605 /* Initialize hash table slots. */
3606 sz = XFASTINT (size);
3607 h = (struct Lisp_Hash_Table *) v;
3608
3609 h->test = test;
3610 if (EQ (test, Qeql))
3611 {
3612 h->cmpfn = cmpfn_eql;
3613 h->hashfn = hashfn_eql;
3614 }
3615 else if (EQ (test, Qeq))
3616 {
2e5da676 3617 h->cmpfn = NULL;
d80c6c11
GM
3618 h->hashfn = hashfn_eq;
3619 }
3620 else if (EQ (test, Qequal))
3621 {
3622 h->cmpfn = cmpfn_equal;
3623 h->hashfn = hashfn_equal;
3624 }
3625 else
3626 {
3627 h->user_cmp_function = user_test;
3628 h->user_hash_function = user_hash;
3629 h->cmpfn = cmpfn_user_defined;
3630 h->hashfn = hashfn_user_defined;
3631 }
3632
3633 h->weak = weak;
3634 h->rehash_threshold = rehash_threshold;
3635 h->rehash_size = rehash_size;
3636 h->count = make_number (0);
3637 h->key_and_value = Fmake_vector (make_number (2 * sz), Qnil);
3638 h->hash = Fmake_vector (size, Qnil);
3639 h->next = Fmake_vector (size, Qnil);
3640 index_size = next_almost_prime (sz / XFLOATINT (rehash_threshold));
3641 h->index = Fmake_vector (make_number (index_size), Qnil);
3642
3643 /* Set up the free list. */
3644 for (i = 0; i < sz - 1; ++i)
3645 HASH_NEXT (h, i) = make_number (i + 1);
3646 h->next_free = make_number (0);
3647
3648 XSET_HASH_TABLE (table, h);
3649 xassert (HASH_TABLE_P (table));
3650 xassert (XHASH_TABLE (table) == h);
3651
3652 /* Maybe add this hash table to the list of all weak hash tables. */
3653 if (NILP (h->weak))
3654 h->next_weak = Qnil;
3655 else
3656 {
3657 h->next_weak = Vweak_hash_tables;
3658 Vweak_hash_tables = table;
3659 }
3660
3661 return table;
3662}
3663
3664
f899c503
GM
3665/* Return a copy of hash table H1. Keys and values are not copied,
3666 only the table itself is. */
3667
3668Lisp_Object
3669copy_hash_table (h1)
3670 struct Lisp_Hash_Table *h1;
3671{
3672 Lisp_Object table;
3673 struct Lisp_Hash_Table *h2;
3674 struct Lisp_Vector *v, *next;
3675 int len;
3676
3677 len = VECSIZE (struct Lisp_Hash_Table);
3678 v = allocate_vectorlike (len);
3679 h2 = (struct Lisp_Hash_Table *) v;
3680 next = h2->vec_next;
3681 bcopy (h1, h2, sizeof *h2);
3682 h2->vec_next = next;
3683 h2->key_and_value = Fcopy_sequence (h1->key_and_value);
3684 h2->hash = Fcopy_sequence (h1->hash);
3685 h2->next = Fcopy_sequence (h1->next);
3686 h2->index = Fcopy_sequence (h1->index);
3687 XSET_HASH_TABLE (table, h2);
3688
3689 /* Maybe add this hash table to the list of all weak hash tables. */
3690 if (!NILP (h2->weak))
3691 {
3692 h2->next_weak = Vweak_hash_tables;
3693 Vweak_hash_tables = table;
3694 }
3695
3696 return table;
3697}
3698
3699
d80c6c11
GM
3700/* Resize hash table H if it's too full. If H cannot be resized
3701 because it's already too large, throw an error. */
3702
3703static INLINE void
3704maybe_resize_hash_table (h)
3705 struct Lisp_Hash_Table *h;
3706{
3707 if (NILP (h->next_free))
3708 {
3709 int old_size = HASH_TABLE_SIZE (h);
3710 int i, new_size, index_size;
3711
3712 if (INTEGERP (h->rehash_size))
3713 new_size = old_size + XFASTINT (h->rehash_size);
3714 else
3715 new_size = old_size * XFLOATINT (h->rehash_size);
3716 index_size = next_almost_prime (new_size
3717 / XFLOATINT (h->rehash_threshold));
3718 if (max (index_size, 2 * new_size) & ~VALMASK)
3719 error ("Hash table too large to resize");
3720
3721 h->key_and_value = larger_vector (h->key_and_value, 2 * new_size, Qnil);
3722 h->next = larger_vector (h->next, new_size, Qnil);
3723 h->hash = larger_vector (h->hash, new_size, Qnil);
3724 h->index = Fmake_vector (make_number (index_size), Qnil);
3725
3726 /* Update the free list. Do it so that new entries are added at
3727 the end of the free list. This makes some operations like
3728 maphash faster. */
3729 for (i = old_size; i < new_size - 1; ++i)
3730 HASH_NEXT (h, i) = make_number (i + 1);
3731
3732 if (!NILP (h->next_free))
3733 {
3734 Lisp_Object last, next;
3735
3736 last = h->next_free;
3737 while (next = HASH_NEXT (h, XFASTINT (last)),
3738 !NILP (next))
3739 last = next;
3740
3741 HASH_NEXT (h, XFASTINT (last)) = make_number (old_size);
3742 }
3743 else
3744 XSETFASTINT (h->next_free, old_size);
3745
3746 /* Rehash. */
3747 for (i = 0; i < old_size; ++i)
3748 if (!NILP (HASH_HASH (h, i)))
3749 {
3750 unsigned hash_code = XUINT (HASH_HASH (h, i));
3751 int start_of_bucket = hash_code % XVECTOR (h->index)->size;
3752 HASH_NEXT (h, i) = HASH_INDEX (h, start_of_bucket);
3753 HASH_INDEX (h, start_of_bucket) = make_number (i);
3754 }
3755 }
3756}
3757
3758
3759/* Lookup KEY in hash table H. If HASH is non-null, return in *HASH
3760 the hash code of KEY. Value is the index of the entry in H
3761 matching KEY, or -1 if not found. */
3762
3763int
3764hash_lookup (h, key, hash)
3765 struct Lisp_Hash_Table *h;
3766 Lisp_Object key;
3767 unsigned *hash;
3768{
3769 unsigned hash_code;
3770 int start_of_bucket;
3771 Lisp_Object idx;
3772
3773 hash_code = h->hashfn (h, key);
3774 if (hash)
3775 *hash = hash_code;
3776
3777 start_of_bucket = hash_code % XVECTOR (h->index)->size;
3778 idx = HASH_INDEX (h, start_of_bucket);
3779
3780 while (!NILP (idx))
3781 {
3782 int i = XFASTINT (idx);
2e5da676
GM
3783 if (EQ (key, HASH_KEY (h, i))
3784 || (h->cmpfn
3785 && h->cmpfn (h, key, hash_code,
3786 HASH_KEY (h, i), HASH_HASH (h, i))))
d80c6c11
GM
3787 break;
3788 idx = HASH_NEXT (h, i);
3789 }
3790
3791 return NILP (idx) ? -1 : XFASTINT (idx);
3792}
3793
3794
3795/* Put an entry into hash table H that associates KEY with VALUE.
3796 HASH is a previously computed hash code of KEY. */
3797
3798void
3799hash_put (h, key, value, hash)
3800 struct Lisp_Hash_Table *h;
3801 Lisp_Object key, value;
3802 unsigned hash;
3803{
3804 int start_of_bucket, i;
3805
3806 xassert ((hash & ~VALMASK) == 0);
3807
3808 /* Increment count after resizing because resizing may fail. */
3809 maybe_resize_hash_table (h);
3810 h->count = make_number (XFASTINT (h->count) + 1);
3811
3812 /* Store key/value in the key_and_value vector. */
3813 i = XFASTINT (h->next_free);
3814 h->next_free = HASH_NEXT (h, i);
3815 HASH_KEY (h, i) = key;
3816 HASH_VALUE (h, i) = value;
3817
3818 /* Remember its hash code. */
3819 HASH_HASH (h, i) = make_number (hash);
3820
3821 /* Add new entry to its collision chain. */
3822 start_of_bucket = hash % XVECTOR (h->index)->size;
3823 HASH_NEXT (h, i) = HASH_INDEX (h, start_of_bucket);
3824 HASH_INDEX (h, start_of_bucket) = make_number (i);
3825}
3826
3827
3828/* Remove the entry matching KEY from hash table H, if there is one. */
3829
3830void
3831hash_remove (h, key)
3832 struct Lisp_Hash_Table *h;
3833 Lisp_Object key;
3834{
3835 unsigned hash_code;
3836 int start_of_bucket;
3837 Lisp_Object idx, prev;
3838
3839 hash_code = h->hashfn (h, key);
3840 start_of_bucket = hash_code % XVECTOR (h->index)->size;
3841 idx = HASH_INDEX (h, start_of_bucket);
3842 prev = Qnil;
3843
3844 while (!NILP (idx))
3845 {
3846 int i = XFASTINT (idx);
3847
2e5da676
GM
3848 if (EQ (key, HASH_KEY (h, i))
3849 || (h->cmpfn
3850 && h->cmpfn (h, key, hash_code,
3851 HASH_KEY (h, i), HASH_HASH (h, i))))
d80c6c11
GM
3852 {
3853 /* Take entry out of collision chain. */
3854 if (NILP (prev))
3855 HASH_INDEX (h, start_of_bucket) = HASH_NEXT (h, i);
3856 else
3857 HASH_NEXT (h, XFASTINT (prev)) = HASH_NEXT (h, i);
3858
3859 /* Clear slots in key_and_value and add the slots to
3860 the free list. */
3861 HASH_KEY (h, i) = HASH_VALUE (h, i) = HASH_HASH (h, i) = Qnil;
3862 HASH_NEXT (h, i) = h->next_free;
3863 h->next_free = make_number (i);
3864 h->count = make_number (XFASTINT (h->count) - 1);
3865 xassert (XINT (h->count) >= 0);
3866 break;
3867 }
3868 else
3869 {
3870 prev = idx;
3871 idx = HASH_NEXT (h, i);
3872 }
3873 }
3874}
3875
3876
3877/* Clear hash table H. */
3878
3879void
3880hash_clear (h)
3881 struct Lisp_Hash_Table *h;
3882{
3883 if (XFASTINT (h->count) > 0)
3884 {
3885 int i, size = HASH_TABLE_SIZE (h);
3886
3887 for (i = 0; i < size; ++i)
3888 {
3889 HASH_NEXT (h, i) = i < size - 1 ? make_number (i + 1) : Qnil;
3890 HASH_KEY (h, i) = Qnil;
3891 HASH_VALUE (h, i) = Qnil;
3892 HASH_HASH (h, i) = Qnil;
3893 }
3894
3895 for (i = 0; i < XVECTOR (h->index)->size; ++i)
3896 XVECTOR (h->index)->contents[i] = Qnil;
3897
3898 h->next_free = make_number (0);
3899 h->count = make_number (0);
3900 }
3901}
3902
3903
3904\f
3905/************************************************************************
3906 Weak Hash Tables
3907 ************************************************************************/
3908
3909/* Remove elements from weak hash tables that don't survive the
3910 current garbage collection. Remove weak tables that don't survive
3911 from Vweak_hash_tables. Called from gc_sweep. */
3912
3913void
3914sweep_weak_hash_tables ()
3915{
3916 Lisp_Object table;
3917 struct Lisp_Hash_Table *h = 0, *prev;
3918
3919 for (table = Vweak_hash_tables; !GC_NILP (table); table = h->next_weak)
3920 {
3921 prev = h;
3922 h = XHASH_TABLE (table);
3923
3924 if (h->size & ARRAY_MARK_FLAG)
3925 {
3926 if (XFASTINT (h->count) > 0)
3927 {
3928 int bucket, n;
3929
3930 n = XVECTOR (h->index)->size & ~ARRAY_MARK_FLAG;
3931 for (bucket = 0; bucket < n; ++bucket)
3932 {
ada0fa14 3933 Lisp_Object idx, prev;
d80c6c11
GM
3934
3935 /* Follow collision chain, removing entries that
3936 don't survive this garbage collection. */
3937 idx = HASH_INDEX (h, bucket);
3938 prev = Qnil;
3939 while (!GC_NILP (idx))
3940 {
3941 int remove_p;
3942 int i = XFASTINT (idx);
3943 Lisp_Object next;
3944
f899c503 3945 if (EQ (h->weak, Qkey))
d80c6c11 3946 remove_p = !survives_gc_p (HASH_KEY (h, i));
f899c503 3947 else if (EQ (h->weak, Qvalue))
d80c6c11 3948 remove_p = !survives_gc_p (HASH_VALUE (h, i));
f899c503 3949 else if (EQ (h->weak, Qt))
d80c6c11
GM
3950 remove_p = (!survives_gc_p (HASH_KEY (h, i))
3951 || !survives_gc_p (HASH_VALUE (h, i)));
3952 else
3953 abort ();
3954
3955 next = HASH_NEXT (h, i);
3956 if (remove_p)
3957 {
3958 /* Take out of collision chain. */
3959 if (GC_NILP (prev))
3960 HASH_INDEX (h, i) = next;
3961 else
3962 HASH_NEXT (h, XFASTINT (prev)) = next;
3963
3964 /* Add to free list. */
3965 HASH_NEXT (h, i) = h->next_free;
3966 h->next_free = idx;
3967
3968 /* Clear key, value, and hash. */
3969 HASH_KEY (h, i) = HASH_VALUE (h, i) = Qnil;
3970 HASH_HASH (h, i) = Qnil;
3971
3972 h->count = make_number (XFASTINT (h->count) - 1);
3973 }
3974 else
3975 {
3976 /* Make sure key and value survive. */
3977 mark_object (&HASH_KEY (h, i));
3978 mark_object (&HASH_VALUE (h, i));
3979 }
3980
3981 idx = next;
3982 }
3983 }
3984 }
3985 }
3986 else
3987 {
3988 /* Table is not marked, and will thus be freed.
3989 Take it out of the list of weak hash tables. */
3990 if (prev)
3991 prev->next_weak = h->next_weak;
3992 else
3993 Vweak_hash_tables = h->next_weak;
3994 }
3995 }
3996}
3997
3998
3999\f
4000/***********************************************************************
4001 Hash Code Computation
4002 ***********************************************************************/
4003
4004/* Maximum depth up to which to dive into Lisp structures. */
4005
4006#define SXHASH_MAX_DEPTH 3
4007
4008/* Maximum length up to which to take list and vector elements into
4009 account. */
4010
4011#define SXHASH_MAX_LEN 7
4012
4013/* Combine two integers X and Y for hashing. */
4014
4015#define SXHASH_COMBINE(X, Y) \
ada0fa14 4016 ((((unsigned)(X) << 4) + (((unsigned)(X) >> 24) & 0x0fffffff)) \
d80c6c11
GM
4017 + (unsigned)(Y))
4018
4019
4020/* Return a hash for string PTR which has length LEN. */
4021
4022static unsigned
4023sxhash_string (ptr, len)
4024 unsigned char *ptr;
4025 int len;
4026{
4027 unsigned char *p = ptr;
4028 unsigned char *end = p + len;
4029 unsigned char c;
4030 unsigned hash = 0;
4031
4032 while (p != end)
4033 {
4034 c = *p++;
4035 if (c >= 0140)
4036 c -= 40;
4037 hash = ((hash << 3) + (hash >> 28) + c);
4038 }
4039
4040 return hash & 07777777777;
4041}
4042
4043
4044/* Return a hash for list LIST. DEPTH is the current depth in the
4045 list. We don't recurse deeper than SXHASH_MAX_DEPTH in it. */
4046
4047static unsigned
4048sxhash_list (list, depth)
4049 Lisp_Object list;
4050 int depth;
4051{
4052 unsigned hash = 0;
4053 int i;
4054
4055 if (depth < SXHASH_MAX_DEPTH)
4056 for (i = 0;
4057 CONSP (list) && i < SXHASH_MAX_LEN;
4058 list = XCDR (list), ++i)
4059 {
4060 unsigned hash2 = sxhash (XCAR (list), depth + 1);
4061 hash = SXHASH_COMBINE (hash, hash2);
4062 }
4063
4064 return hash;
4065}
4066
4067
4068/* Return a hash for vector VECTOR. DEPTH is the current depth in
4069 the Lisp structure. */
4070
4071static unsigned
4072sxhash_vector (vec, depth)
4073 Lisp_Object vec;
4074 int depth;
4075{
4076 unsigned hash = XVECTOR (vec)->size;
4077 int i, n;
4078
4079 n = min (SXHASH_MAX_LEN, XVECTOR (vec)->size);
4080 for (i = 0; i < n; ++i)
4081 {
4082 unsigned hash2 = sxhash (XVECTOR (vec)->contents[i], depth + 1);
4083 hash = SXHASH_COMBINE (hash, hash2);
4084 }
4085
4086 return hash;
4087}
4088
4089
4090/* Return a hash for bool-vector VECTOR. */
4091
4092static unsigned
4093sxhash_bool_vector (vec)
4094 Lisp_Object vec;
4095{
4096 unsigned hash = XBOOL_VECTOR (vec)->size;
4097 int i, n;
4098
4099 n = min (SXHASH_MAX_LEN, XBOOL_VECTOR (vec)->vector_size);
4100 for (i = 0; i < n; ++i)
4101 hash = SXHASH_COMBINE (hash, XBOOL_VECTOR (vec)->data[i]);
4102
4103 return hash;
4104}
4105
4106
4107/* Return a hash code for OBJ. DEPTH is the current depth in the Lisp
4108 structure. Value is an unsigned integer clipped to VALMASK. */
4109
4110unsigned
4111sxhash (obj, depth)
4112 Lisp_Object obj;
4113 int depth;
4114{
4115 unsigned hash;
4116
4117 if (depth > SXHASH_MAX_DEPTH)
4118 return 0;
4119
4120 switch (XTYPE (obj))
4121 {
4122 case Lisp_Int:
4123 hash = XUINT (obj);
4124 break;
4125
4126 case Lisp_Symbol:
4127 hash = sxhash_string (XSYMBOL (obj)->name->data,
4128 XSYMBOL (obj)->name->size);
4129 break;
4130
4131 case Lisp_Misc:
4132 hash = XUINT (obj);
4133 break;
4134
4135 case Lisp_String:
4136 hash = sxhash_string (XSTRING (obj)->data, XSTRING (obj)->size);
4137 break;
4138
4139 /* This can be everything from a vector to an overlay. */
4140 case Lisp_Vectorlike:
4141 if (VECTORP (obj))
4142 /* According to the CL HyperSpec, two arrays are equal only if
4143 they are `eq', except for strings and bit-vectors. In
4144 Emacs, this works differently. We have to compare element
4145 by element. */
4146 hash = sxhash_vector (obj, depth);
4147 else if (BOOL_VECTOR_P (obj))
4148 hash = sxhash_bool_vector (obj);
4149 else
4150 /* Others are `equal' if they are `eq', so let's take their
4151 address as hash. */
4152 hash = XUINT (obj);
4153 break;
4154
4155 case Lisp_Cons:
4156 hash = sxhash_list (obj, depth);
4157 break;
4158
4159 case Lisp_Float:
4160 {
e84b1dea
GM
4161 unsigned char *p = (unsigned char *) &XFLOAT_DATA (obj);
4162 unsigned char *e = p + sizeof XFLOAT_DATA (obj);
d80c6c11
GM
4163 for (hash = 0; p < e; ++p)
4164 hash = SXHASH_COMBINE (hash, *p);
4165 break;
4166 }
4167
4168 default:
4169 abort ();
4170 }
4171
4172 return hash & VALMASK;
4173}
4174
4175
4176\f
4177/***********************************************************************
4178 Lisp Interface
4179 ***********************************************************************/
4180
4181
4182DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0,
4183 "Compute a hash code for OBJ and return it as integer.")
4184 (obj)
4185 Lisp_Object obj;
4186{
4187 unsigned hash = sxhash (obj, 0);;
4188 return make_number (hash);
4189}
4190
4191
4192DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 0,
4193 "Create and return a new hash table.\n\
4194Arguments are specified as keyword/argument pairs. The following\n\
4195arguments are defined:\n\
4196\n\
526cfb19 4197:TEST TEST -- TEST must be a symbol that specifies how to compare keys.\n\
d80c6c11
GM
4198Default is `eql'. Predefined are the tests `eq', `eql', and `equal'.\n\
4199User-supplied test and hash functions can be specified via\n\
4200`define-hash-table-test'.\n\
4201\n\
526cfb19 4202:SIZE SIZE -- A hint as to how many elements will be put in the table.\n\
d80c6c11
GM
4203Default is 65.\n\
4204\n\
4205:REHASH-SIZE REHASH-SIZE - Indicates how to expand the table when\n\
4206it fills up. If REHASH-SIZE is an integer, add that many space.\n\
4207If it is a float, it must be > 1.0, and the new size is computed by\n\
4208multiplying the old size with that factor. Default is 1.5.\n\
4209\n\
4210:REHASH-THRESHOLD THRESHOLD -- THRESHOLD must a float > 0, and <= 1.0.\n\
4211Resize the hash table when ratio of the number of entries in the table.\n\
4212Default is 0.8.\n\
4213\n\
ee0403b3 4214:WEAKNESS WEAK -- WEAK must be one of nil, t, `key', or `value'.\n\
f899c503
GM
4215If WEAK is not nil, the table returned is a weak table. Key/value\n\
4216pairs are removed from a weak hash table when their key, value or both\n\
4217(WEAK t) are otherwise unreferenced. Default is nil.")
d80c6c11
GM
4218 (nargs, args)
4219 int nargs;
4220 Lisp_Object *args;
4221{
4222 Lisp_Object test, size, rehash_size, rehash_threshold, weak;
4223 Lisp_Object user_test, user_hash;
4224 char *used;
4225 int i;
4226
4227 /* The vector `used' is used to keep track of arguments that
4228 have been consumed. */
4229 used = (char *) alloca (nargs * sizeof *used);
4230 bzero (used, nargs * sizeof *used);
4231
4232 /* See if there's a `:test TEST' among the arguments. */
4233 i = get_key_arg (QCtest, nargs, args, used);
4234 test = i < 0 ? Qeql : args[i];
4235 if (!EQ (test, Qeq) && !EQ (test, Qeql) && !EQ (test, Qequal))
4236 {
4237 /* See if it is a user-defined test. */
4238 Lisp_Object prop;
4239
4240 prop = Fget (test, Qhash_table_test);
4241 if (!CONSP (prop) || XFASTINT (Flength (prop)) < 2)
4242 Fsignal (Qerror, list2 (build_string ("Illegal hash table test"),
4243 test));
4244 user_test = Fnth (make_number (0), prop);
4245 user_hash = Fnth (make_number (1), prop);
4246 }
4247 else
4248 user_test = user_hash = Qnil;
4249
4250 /* See if there's a `:size SIZE' argument. */
4251 i = get_key_arg (QCsize, nargs, args, used);
4252 size = i < 0 ? make_number (DEFAULT_HASH_SIZE) : args[i];
4253 if (!INTEGERP (size) || XINT (size) <= 0)
4254 Fsignal (Qerror,
4255 list2 (build_string ("Illegal hash table size"),
4256 size));
4257
4258 /* Look for `:rehash-size SIZE'. */
4259 i = get_key_arg (QCrehash_size, nargs, args, used);
4260 rehash_size = i < 0 ? make_float (DEFAULT_REHASH_SIZE) : args[i];
4261 if (!NUMBERP (rehash_size)
4262 || (INTEGERP (rehash_size) && XINT (rehash_size) <= 0)
4263 || XFLOATINT (rehash_size) <= 1.0)
4264 Fsignal (Qerror,
4265 list2 (build_string ("Illegal hash table rehash size"),
4266 rehash_size));
4267
4268 /* Look for `:rehash-threshold THRESHOLD'. */
4269 i = get_key_arg (QCrehash_threshold, nargs, args, used);
4270 rehash_threshold = i < 0 ? make_float (DEFAULT_REHASH_THRESHOLD) : args[i];
4271 if (!FLOATP (rehash_threshold)
4272 || XFLOATINT (rehash_threshold) <= 0.0
4273 || XFLOATINT (rehash_threshold) > 1.0)
4274 Fsignal (Qerror,
4275 list2 (build_string ("Illegal hash table rehash threshold"),
4276 rehash_threshold));
4277
ee0403b3
GM
4278 /* Look for `:weakness WEAK'. */
4279 i = get_key_arg (QCweakness, nargs, args, used);
d80c6c11 4280 weak = i < 0 ? Qnil : args[i];
d80c6c11 4281 if (!NILP (weak)
f899c503
GM
4282 && !EQ (weak, Qt)
4283 && !EQ (weak, Qkey)
4284 && !EQ (weak, Qvalue))
d80c6c11
GM
4285 Fsignal (Qerror, list2 (build_string ("Illegal hash table weakness"),
4286 weak));
4287
4288 /* Now, all args should have been used up, or there's a problem. */
4289 for (i = 0; i < nargs; ++i)
4290 if (!used[i])
4291 Fsignal (Qerror,
4292 list2 (build_string ("Invalid argument list"), args[i]));
4293
4294 return make_hash_table (test, size, rehash_size, rehash_threshold, weak,
4295 user_test, user_hash);
4296}
4297
4298
f899c503
GM
4299DEFUN ("copy-hash-table", Fcopy_hash_table, Scopy_hash_table, 1, 1, 0,
4300 "Return a copy of hash table TABLE.")
4301 (table)
4302 Lisp_Object table;
4303{
4304 return copy_hash_table (check_hash_table (table));
4305}
4306
4307
38b5e497 4308DEFUN ("makehash", Fmakehash, Smakehash, 0, 1, 0,
d80c6c11 4309 "Create a new hash table.\n\
c5092f3e 4310Optional first argument TEST specifies how to compare keys in\n\
d80c6c11 4311the table. Predefined tests are `eq', `eql', and `equal'. Default\n\
38b5e497
GM
4312is `eql'. New tests can be defined with `define-hash-table-test'.")
4313 (test)
4314 Lisp_Object test;
d80c6c11 4315{
38b5e497
GM
4316 Lisp_Object args[2];
4317 args[0] = QCtest;
4318 args[1] = test;
4319 return Fmake_hash_table (2, args);
d80c6c11
GM
4320}
4321
4322
4323DEFUN ("hash-table-count", Fhash_table_count, Shash_table_count, 1, 1, 0,
4324 "Return the number of elements in TABLE.")
4325 (table)
4326 Lisp_Object table;
4327{
4328 return check_hash_table (table)->count;
4329}
4330
4331
4332DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size,
4333 Shash_table_rehash_size, 1, 1, 0,
4334 "Return the current rehash size of TABLE.")
4335 (table)
4336 Lisp_Object table;
4337{
4338 return check_hash_table (table)->rehash_size;
4339}
4340
4341
4342DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold,
4343 Shash_table_rehash_threshold, 1, 1, 0,
4344 "Return the current rehash threshold of TABLE.")
4345 (table)
4346 Lisp_Object table;
4347{
4348 return check_hash_table (table)->rehash_threshold;
4349}
4350
4351
4352DEFUN ("hash-table-size", Fhash_table_size, Shash_table_size, 1, 1, 0,
4353 "Return the size of TABLE.\n\
4354The size can be used as an argument to `make-hash-table' to create\n\
4355a hash table than can hold as many elements of TABLE holds\n\
4356without need for resizing.")
4357 (table)
4358 Lisp_Object table;
4359{
4360 struct Lisp_Hash_Table *h = check_hash_table (table);
4361 return make_number (HASH_TABLE_SIZE (h));
4362}
4363
4364
4365DEFUN ("hash-table-test", Fhash_table_test, Shash_table_test, 1, 1, 0,
4366 "Return the test TABLE uses.")
4367 (table)
4368 Lisp_Object table;
4369{
4370 return check_hash_table (table)->test;
4371}
4372
4373
e84b1dea
GM
4374DEFUN ("hash-table-weakness", Fhash_table_weakness, Shash_table_weakness,
4375 1, 1, 0,
d80c6c11
GM
4376 "Return the weakness of TABLE.")
4377 (table)
4378 Lisp_Object table;
4379{
4380 return check_hash_table (table)->weak;
4381}
4382
4383
4384DEFUN ("hash-table-p", Fhash_table_p, Shash_table_p, 1, 1, 0,
4385 "Return t if OBJ is a Lisp hash table object.")
4386 (obj)
4387 Lisp_Object obj;
4388{
4389 return HASH_TABLE_P (obj) ? Qt : Qnil;
4390}
4391
4392
4393DEFUN ("clrhash", Fclrhash, Sclrhash, 1, 1, 0,
4394 "Clear hash table TABLE.")
4395 (table)
4396 Lisp_Object table;
4397{
4398 hash_clear (check_hash_table (table));
4399 return Qnil;
4400}
4401
4402
4403DEFUN ("gethash", Fgethash, Sgethash, 2, 3, 0,
4404 "Look up KEY in TABLE and return its associated value.\n\
4405If KEY is not found, return DFLT which defaults to nil.")
1fffe870 4406 (key, table, dflt)
68c45bf0 4407 Lisp_Object key, table, dflt;
d80c6c11
GM
4408{
4409 struct Lisp_Hash_Table *h = check_hash_table (table);
4410 int i = hash_lookup (h, key, NULL);
4411 return i >= 0 ? HASH_VALUE (h, i) : dflt;
4412}
4413
4414
4415DEFUN ("puthash", Fputhash, Sputhash, 3, 3, 0,
4416 "Associate KEY with VALUE is hash table TABLE.\n\
4417If KEY is already present in table, replace its current value with\n\
4418VALUE.")
1fffe870
MR
4419 (key, value, table)
4420 Lisp_Object key, value, table;
d80c6c11
GM
4421{
4422 struct Lisp_Hash_Table *h = check_hash_table (table);
4423 int i;
4424 unsigned hash;
4425
4426 i = hash_lookup (h, key, &hash);
4427 if (i >= 0)
4428 HASH_VALUE (h, i) = value;
4429 else
4430 hash_put (h, key, value, hash);
4431
4432 return Qnil;
4433}
4434
4435
4436DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
4437 "Remove KEY from TABLE.")
1fffe870
MR
4438 (key, table)
4439 Lisp_Object key, table;
d80c6c11
GM
4440{
4441 struct Lisp_Hash_Table *h = check_hash_table (table);
4442 hash_remove (h, key);
4443 return Qnil;
4444}
4445
4446
4447DEFUN ("maphash", Fmaphash, Smaphash, 2, 2, 0,
4448 "Call FUNCTION for all entries in hash table TABLE.\n\
4449FUNCTION is called with 2 arguments KEY and VALUE.")
4450 (function, table)
4451 Lisp_Object function, table;
4452{
4453 struct Lisp_Hash_Table *h = check_hash_table (table);
4454 Lisp_Object args[3];
4455 int i;
4456
4457 for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
4458 if (!NILP (HASH_HASH (h, i)))
4459 {
4460 args[0] = function;
4461 args[1] = HASH_KEY (h, i);
4462 args[2] = HASH_VALUE (h, i);
4463 Ffuncall (3, args);
4464 }
4465
4466 return Qnil;
4467}
4468
4469
4470DEFUN ("define-hash-table-test", Fdefine_hash_table_test,
4471 Sdefine_hash_table_test, 3, 3, 0,
4472 "Define a new hash table test with name NAME, a symbol.\n\
4473In hash tables create with NAME specified as test, use TEST to compare\n\
4474keys, and HASH for computing hash codes of keys.\n\
4475\n\
4476TEST must be a function taking two arguments and returning non-nil\n\
4477if both arguments are the same. HASH must be a function taking\n\
4478one argument and return an integer that is the hash code of the\n\
4479argument. Hash code computation should use the whole value range of\n\
4480integers, including negative integers.")
4481 (name, test, hash)
4482 Lisp_Object name, test, hash;
4483{
4484 return Fput (name, Qhash_table_test, list2 (test, hash));
4485}
4486
4487
4488
24c129e4 4489\f
dfcf069d 4490void
7b863bd5
JB
4491syms_of_fns ()
4492{
d80c6c11
GM
4493 /* Hash table stuff. */
4494 Qhash_table_p = intern ("hash-table-p");
4495 staticpro (&Qhash_table_p);
4496 Qeq = intern ("eq");
4497 staticpro (&Qeq);
4498 Qeql = intern ("eql");
4499 staticpro (&Qeql);
4500 Qequal = intern ("equal");
4501 staticpro (&Qequal);
4502 QCtest = intern (":test");
4503 staticpro (&QCtest);
4504 QCsize = intern (":size");
4505 staticpro (&QCsize);
4506 QCrehash_size = intern (":rehash-size");
4507 staticpro (&QCrehash_size);
4508 QCrehash_threshold = intern (":rehash-threshold");
4509 staticpro (&QCrehash_threshold);
ee0403b3
GM
4510 QCweakness = intern (":weakness");
4511 staticpro (&QCweakness);
f899c503
GM
4512 Qkey = intern ("key");
4513 staticpro (&Qkey);
4514 Qvalue = intern ("value");
4515 staticpro (&Qvalue);
d80c6c11
GM
4516 Qhash_table_test = intern ("hash-table-test");
4517 staticpro (&Qhash_table_test);
4518
4519 defsubr (&Ssxhash);
4520 defsubr (&Smake_hash_table);
f899c503 4521 defsubr (&Scopy_hash_table);
d80c6c11
GM
4522 defsubr (&Smakehash);
4523 defsubr (&Shash_table_count);
4524 defsubr (&Shash_table_rehash_size);
4525 defsubr (&Shash_table_rehash_threshold);
4526 defsubr (&Shash_table_size);
4527 defsubr (&Shash_table_test);
e84b1dea 4528 defsubr (&Shash_table_weakness);
d80c6c11
GM
4529 defsubr (&Shash_table_p);
4530 defsubr (&Sclrhash);
4531 defsubr (&Sgethash);
4532 defsubr (&Sputhash);
4533 defsubr (&Sremhash);
4534 defsubr (&Smaphash);
4535 defsubr (&Sdefine_hash_table_test);
4536
7b863bd5
JB
4537 Qstring_lessp = intern ("string-lessp");
4538 staticpro (&Qstring_lessp);
68732608
RS
4539 Qprovide = intern ("provide");
4540 staticpro (&Qprovide);
4541 Qrequire = intern ("require");
4542 staticpro (&Qrequire);
0ce830bc
RS
4543 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
4544 staticpro (&Qyes_or_no_p_history);
eb4ffa4e
RS
4545 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
4546 staticpro (&Qcursor_in_echo_area);
b4f334f7
KH
4547 Qwidget_type = intern ("widget-type");
4548 staticpro (&Qwidget_type);
7b863bd5 4549
09ab3c3b
KH
4550 staticpro (&string_char_byte_cache_string);
4551 string_char_byte_cache_string = Qnil;
4552
52a9879b
RS
4553 Fset (Qyes_or_no_p_history, Qnil);
4554
7b863bd5
JB
4555 DEFVAR_LISP ("features", &Vfeatures,
4556 "A list of symbols which are the features of the executing emacs.\n\
4557Used by `featurep' and `require', and altered by `provide'.");
4558 Vfeatures = Qnil;
4559
bdd8d692
RS
4560 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
4561 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
1eb569c5 4562This applies to y-or-n and yes-or-no questions asked by commands\n\
bdd8d692
RS
4563invoked by mouse clicks and mouse menu items.");
4564 use_dialog_box = 1;
4565
7b863bd5
JB
4566 defsubr (&Sidentity);
4567 defsubr (&Srandom);
4568 defsubr (&Slength);
5a30fab8 4569 defsubr (&Ssafe_length);
026f59ce 4570 defsubr (&Sstring_bytes);
7b863bd5 4571 defsubr (&Sstring_equal);
0e1e9f8d 4572 defsubr (&Scompare_strings);
7b863bd5
JB
4573 defsubr (&Sstring_lessp);
4574 defsubr (&Sappend);
4575 defsubr (&Sconcat);
4576 defsubr (&Svconcat);
4577 defsubr (&Scopy_sequence);
09ab3c3b
KH
4578 defsubr (&Sstring_make_multibyte);
4579 defsubr (&Sstring_make_unibyte);
6d475204
RS
4580 defsubr (&Sstring_as_multibyte);
4581 defsubr (&Sstring_as_unibyte);
7b863bd5
JB
4582 defsubr (&Scopy_alist);
4583 defsubr (&Ssubstring);
4584 defsubr (&Snthcdr);
4585 defsubr (&Snth);
4586 defsubr (&Selt);
4587 defsubr (&Smember);
4588 defsubr (&Smemq);
4589 defsubr (&Sassq);
4590 defsubr (&Sassoc);
4591 defsubr (&Srassq);
0fb5a19c 4592 defsubr (&Srassoc);
7b863bd5 4593 defsubr (&Sdelq);
ca8dd546 4594 defsubr (&Sdelete);
7b863bd5
JB
4595 defsubr (&Snreverse);
4596 defsubr (&Sreverse);
4597 defsubr (&Ssort);
be9d483d 4598 defsubr (&Splist_get);
7b863bd5 4599 defsubr (&Sget);
be9d483d 4600 defsubr (&Splist_put);
7b863bd5
JB
4601 defsubr (&Sput);
4602 defsubr (&Sequal);
4603 defsubr (&Sfillarray);
999de246 4604 defsubr (&Schar_table_subtype);
e03f7933
RS
4605 defsubr (&Schar_table_parent);
4606 defsubr (&Sset_char_table_parent);
4607 defsubr (&Schar_table_extra_slot);
4608 defsubr (&Sset_char_table_extra_slot);
999de246 4609 defsubr (&Schar_table_range);
e03f7933 4610 defsubr (&Sset_char_table_range);
e1335ba2 4611 defsubr (&Sset_char_table_default);
e03f7933 4612 defsubr (&Smap_char_table);
7b863bd5
JB
4613 defsubr (&Snconc);
4614 defsubr (&Smapcar);
4615 defsubr (&Smapconcat);
4616 defsubr (&Sy_or_n_p);
4617 defsubr (&Syes_or_no_p);
4618 defsubr (&Sload_average);
4619 defsubr (&Sfeaturep);
4620 defsubr (&Srequire);
4621 defsubr (&Sprovide);
b4f334f7
KH
4622 defsubr (&Swidget_plist_member);
4623 defsubr (&Swidget_put);
4624 defsubr (&Swidget_get);
4625 defsubr (&Swidget_apply);
24c129e4
KH
4626 defsubr (&Sbase64_encode_region);
4627 defsubr (&Sbase64_decode_region);
4628 defsubr (&Sbase64_encode_string);
4629 defsubr (&Sbase64_decode_string);
7b863bd5 4630}
d80c6c11
GM
4631
4632
4633void
4634init_fns ()
4635{
4636 Vweak_hash_tables = Qnil;
4637}