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