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