(Fplist_get): Don't QUIT is interrupt_input_blocked.
[bpt/emacs.git] / src / fns.c
CommitLineData
7b863bd5 1/* Random utility Lisp functions.
df6c90d8 2 Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 98, 99, 2000, 2001
57916a7a 3 Free Software Foundation, Inc.
7b863bd5
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4ff1aed9 9the Free Software Foundation; either version 2, or (at your option)
7b863bd5
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
7b863bd5
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)
60f8d735 329 return make_number (- i1 + XINT (start1));
0e1e9f8d 330 else
60f8d735 331 return make_number (i1 - XINT (start1));
0e1e9f8d
RS
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 {
b3660ef6 1621 struct Lisp_Vector *p = allocate_vector (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
e517f19d
GM
1627 XSETVECTOR (seq, p);
1628 }
1629 }
1630 else if (STRINGP (seq))
1e134a5f 1631 {
e517f19d
GM
1632 EMACS_INT i, ibyte, nchars, nbytes, cbytes;
1633 int c;
1634
1635 for (i = nchars = nbytes = ibyte = 0;
1636 i < XSTRING (seq)->size;
1637 ++i, ibyte += cbytes)
1e134a5f 1638 {
e517f19d
GM
1639 if (STRING_MULTIBYTE (seq))
1640 {
1641 c = STRING_CHAR (&XSTRING (seq)->data[ibyte],
1642 STRING_BYTES (XSTRING (seq)) - ibyte);
1643 cbytes = CHAR_BYTES (c);
1644 }
1e134a5f 1645 else
e517f19d
GM
1646 {
1647 c = XSTRING (seq)->data[i];
1648 cbytes = 1;
1649 }
59f953a2 1650
e517f19d
GM
1651 if (!INTEGERP (elt) || c != XINT (elt))
1652 {
1653 ++nchars;
1654 nbytes += cbytes;
1655 }
1656 }
1657
1658 if (nchars != XSTRING (seq)->size)
1659 {
1660 Lisp_Object tem;
1661
1662 tem = make_uninit_multibyte_string (nchars, nbytes);
1663 if (!STRING_MULTIBYTE (seq))
1664 SET_STRING_BYTES (XSTRING (tem), -1);
59f953a2 1665
e517f19d
GM
1666 for (i = nchars = nbytes = ibyte = 0;
1667 i < XSTRING (seq)->size;
1668 ++i, ibyte += cbytes)
1669 {
1670 if (STRING_MULTIBYTE (seq))
1671 {
1672 c = STRING_CHAR (&XSTRING (seq)->data[ibyte],
1673 STRING_BYTES (XSTRING (seq)) - ibyte);
1674 cbytes = CHAR_BYTES (c);
1675 }
1676 else
1677 {
1678 c = XSTRING (seq)->data[i];
1679 cbytes = 1;
1680 }
59f953a2 1681
e517f19d
GM
1682 if (!INTEGERP (elt) || c != XINT (elt))
1683 {
1684 unsigned char *from = &XSTRING (seq)->data[ibyte];
1685 unsigned char *to = &XSTRING (tem)->data[nbytes];
1686 EMACS_INT n;
59f953a2 1687
e517f19d
GM
1688 ++nchars;
1689 nbytes += cbytes;
59f953a2 1690
e517f19d
GM
1691 for (n = cbytes; n--; )
1692 *to++ = *from++;
1693 }
1694 }
1695
1696 seq = tem;
1e134a5f 1697 }
1e134a5f 1698 }
e517f19d
GM
1699 else
1700 {
1701 Lisp_Object tail, prev;
1702
1703 for (tail = seq, prev = Qnil; !NILP (tail); tail = XCDR (tail))
1704 {
1705 if (!CONSP (tail))
1706 wrong_type_argument (Qlistp, seq);
59f953a2 1707
e517f19d
GM
1708 if (!NILP (Fequal (elt, XCAR (tail))))
1709 {
1710 if (NILP (prev))
1711 seq = XCDR (tail);
1712 else
1713 Fsetcdr (prev, XCDR (tail));
1714 }
1715 else
1716 prev = tail;
1717 QUIT;
1718 }
1719 }
59f953a2 1720
e517f19d 1721 return seq;
1e134a5f
RM
1722}
1723
7b863bd5
JB
1724DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
1725 "Reverse LIST by modifying cdr pointers.\n\
1726Returns the beginning of the reversed list.")
1727 (list)
1728 Lisp_Object list;
1729{
1730 register Lisp_Object prev, tail, next;
1731
265a9e55 1732 if (NILP (list)) return list;
7b863bd5
JB
1733 prev = Qnil;
1734 tail = list;
265a9e55 1735 while (!NILP (tail))
7b863bd5
JB
1736 {
1737 QUIT;
71a8e74b
DL
1738 if (! CONSP (tail))
1739 wrong_type_argument (Qlistp, list);
1740 next = XCDR (tail);
7b863bd5
JB
1741 Fsetcdr (tail, prev);
1742 prev = tail;
1743 tail = next;
1744 }
1745 return prev;
1746}
1747
1748DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
1749 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
1750See also the function `nreverse', which is used more often.")
1751 (list)
1752 Lisp_Object list;
1753{
9d14ae76 1754 Lisp_Object new;
7b863bd5 1755
70949dac
KR
1756 for (new = Qnil; CONSP (list); list = XCDR (list))
1757 new = Fcons (XCAR (list), new);
9d14ae76
RS
1758 if (!NILP (list))
1759 wrong_type_argument (Qconsp, list);
1760 return new;
7b863bd5
JB
1761}
1762\f
1763Lisp_Object merge ();
1764
1765DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
1766 "Sort LIST, stably, comparing elements using PREDICATE.\n\
1767Returns the sorted list. LIST is modified by side effects.\n\
1768PREDICATE is called with two elements of LIST, and should return T\n\
1769if the first element is \"less\" than the second.")
88fe8140
EN
1770 (list, predicate)
1771 Lisp_Object list, predicate;
7b863bd5
JB
1772{
1773 Lisp_Object front, back;
1774 register Lisp_Object len, tem;
1775 struct gcpro gcpro1, gcpro2;
1776 register int length;
1777
1778 front = list;
1779 len = Flength (list);
1780 length = XINT (len);
1781 if (length < 2)
1782 return list;
1783
1784 XSETINT (len, (length / 2) - 1);
1785 tem = Fnthcdr (len, list);
1786 back = Fcdr (tem);
1787 Fsetcdr (tem, Qnil);
1788
1789 GCPRO2 (front, back);
88fe8140
EN
1790 front = Fsort (front, predicate);
1791 back = Fsort (back, predicate);
7b863bd5 1792 UNGCPRO;
88fe8140 1793 return merge (front, back, predicate);
7b863bd5
JB
1794}
1795
1796Lisp_Object
1797merge (org_l1, org_l2, pred)
1798 Lisp_Object org_l1, org_l2;
1799 Lisp_Object pred;
1800{
1801 Lisp_Object value;
1802 register Lisp_Object tail;
1803 Lisp_Object tem;
1804 register Lisp_Object l1, l2;
1805 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1806
1807 l1 = org_l1;
1808 l2 = org_l2;
1809 tail = Qnil;
1810 value = Qnil;
1811
1812 /* It is sufficient to protect org_l1 and org_l2.
1813 When l1 and l2 are updated, we copy the new values
1814 back into the org_ vars. */
1815 GCPRO4 (org_l1, org_l2, pred, value);
1816
1817 while (1)
1818 {
265a9e55 1819 if (NILP (l1))
7b863bd5
JB
1820 {
1821 UNGCPRO;
265a9e55 1822 if (NILP (tail))
7b863bd5
JB
1823 return l2;
1824 Fsetcdr (tail, l2);
1825 return value;
1826 }
265a9e55 1827 if (NILP (l2))
7b863bd5
JB
1828 {
1829 UNGCPRO;
265a9e55 1830 if (NILP (tail))
7b863bd5
JB
1831 return l1;
1832 Fsetcdr (tail, l1);
1833 return value;
1834 }
1835 tem = call2 (pred, Fcar (l2), Fcar (l1));
265a9e55 1836 if (NILP (tem))
7b863bd5
JB
1837 {
1838 tem = l1;
1839 l1 = Fcdr (l1);
1840 org_l1 = l1;
1841 }
1842 else
1843 {
1844 tem = l2;
1845 l2 = Fcdr (l2);
1846 org_l2 = l2;
1847 }
265a9e55 1848 if (NILP (tail))
7b863bd5
JB
1849 value = tem;
1850 else
1851 Fsetcdr (tail, tem);
1852 tail = tem;
1853 }
1854}
be9d483d 1855
2d6fabfc 1856\f
be9d483d 1857DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
1fbb64aa 1858 "Extract a value from a property list.\n\
be9d483d 1859PLIST is a property list, which is a list of the form\n\
c07289e0 1860\(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
be9d483d
BG
1861corresponding to the given PROP, or nil if PROP is not\n\
1862one of the properties on the list.")
1fbb64aa
EN
1863 (plist, prop)
1864 Lisp_Object plist;
2d6fabfc 1865 Lisp_Object prop;
7b863bd5 1866{
2d6fabfc
GM
1867 Lisp_Object tail;
1868
1869 for (tail = plist;
1870 CONSP (tail) && CONSP (XCDR (tail));
1871 tail = XCDR (XCDR (tail)))
7b863bd5 1872 {
2d6fabfc
GM
1873 if (EQ (prop, XCAR (tail)))
1874 return XCAR (XCDR (tail));
ec2423c9
GM
1875
1876 /* This function can be called asynchronously
1877 (setup_coding_system). Don't QUIT in that case. */
1878 if (!interrupt_input_blocked)
1879 QUIT;
7b863bd5 1880 }
2d6fabfc
GM
1881
1882 if (!NILP (tail))
1883 wrong_type_argument (Qlistp, prop);
1884
7b863bd5
JB
1885 return Qnil;
1886}
1887
be9d483d
BG
1888DEFUN ("get", Fget, Sget, 2, 2, 0,
1889 "Return the value of SYMBOL's PROPNAME property.\n\
c07289e0
RS
1890This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
1891 (symbol, propname)
1892 Lisp_Object symbol, propname;
be9d483d 1893{
c07289e0
RS
1894 CHECK_SYMBOL (symbol, 0);
1895 return Fplist_get (XSYMBOL (symbol)->plist, propname);
be9d483d
BG
1896}
1897
1898DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
1899 "Change value in PLIST of PROP to VAL.\n\
1900PLIST is a property list, which is a list of the form\n\
c07289e0 1901\(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
be9d483d 1902If PROP is already a property on the list, its value is set to VAL,\n\
88435890 1903otherwise the new PROP VAL pair is added. The new plist is returned;\n\
be9d483d
BG
1904use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
1905The PLIST is modified by side effects.")
1906 (plist, prop, val)
b4f334f7
KH
1907 Lisp_Object plist;
1908 register Lisp_Object prop;
1909 Lisp_Object val;
7b863bd5
JB
1910{
1911 register Lisp_Object tail, prev;
1912 Lisp_Object newcell;
1913 prev = Qnil;
70949dac
KR
1914 for (tail = plist; CONSP (tail) && CONSP (XCDR (tail));
1915 tail = XCDR (XCDR (tail)))
7b863bd5 1916 {
70949dac 1917 if (EQ (prop, XCAR (tail)))
be9d483d 1918 {
70949dac 1919 Fsetcar (XCDR (tail), val);
be9d483d
BG
1920 return plist;
1921 }
ec2423c9 1922
7b863bd5 1923 prev = tail;
2d6fabfc 1924 QUIT;
7b863bd5
JB
1925 }
1926 newcell = Fcons (prop, Fcons (val, Qnil));
265a9e55 1927 if (NILP (prev))
be9d483d 1928 return newcell;
7b863bd5 1929 else
70949dac 1930 Fsetcdr (XCDR (prev), newcell);
be9d483d
BG
1931 return plist;
1932}
1933
1934DEFUN ("put", Fput, Sput, 3, 3, 0,
1935 "Store SYMBOL's PROPNAME property with value VALUE.\n\
1936It can be retrieved with `(get SYMBOL PROPNAME)'.")
c07289e0
RS
1937 (symbol, propname, value)
1938 Lisp_Object symbol, propname, value;
be9d483d 1939{
c07289e0
RS
1940 CHECK_SYMBOL (symbol, 0);
1941 XSYMBOL (symbol)->plist
1942 = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
1943 return value;
7b863bd5
JB
1944}
1945
1946DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
ea35ce3d 1947 "Return t if two Lisp objects have similar structure and contents.\n\
7b863bd5
JB
1948They must have the same data type.\n\
1949Conses are compared by comparing the cars and the cdrs.\n\
1950Vectors and strings are compared element by element.\n\
d28c4332
RS
1951Numbers are compared by value, but integers cannot equal floats.\n\
1952 (Use `=' if you want integers and floats to be able to be equal.)\n\
1953Symbols must match exactly.")
7b863bd5
JB
1954 (o1, o2)
1955 register Lisp_Object o1, o2;
1956{
6cb9cafb 1957 return internal_equal (o1, o2, 0) ? Qt : Qnil;
e0f5cf5a
RS
1958}
1959
6cb9cafb 1960static int
e0f5cf5a
RS
1961internal_equal (o1, o2, depth)
1962 register Lisp_Object o1, o2;
1963 int depth;
1964{
1965 if (depth > 200)
1966 error ("Stack overflow in equal");
4ff1aed9 1967
6cb9cafb 1968 tail_recurse:
7b863bd5 1969 QUIT;
4ff1aed9
RS
1970 if (EQ (o1, o2))
1971 return 1;
1972 if (XTYPE (o1) != XTYPE (o2))
1973 return 0;
1974
1975 switch (XTYPE (o1))
1976 {
4ff1aed9
RS
1977 case Lisp_Float:
1978 return (extract_float (o1) == extract_float (o2));
4ff1aed9
RS
1979
1980 case Lisp_Cons:
70949dac 1981 if (!internal_equal (XCAR (o1), XCAR (o2), depth + 1))
4cab5074 1982 return 0;
70949dac
KR
1983 o1 = XCDR (o1);
1984 o2 = XCDR (o2);
4cab5074 1985 goto tail_recurse;
4ff1aed9
RS
1986
1987 case Lisp_Misc:
81d1fba6 1988 if (XMISCTYPE (o1) != XMISCTYPE (o2))
6cb9cafb 1989 return 0;
4ff1aed9 1990 if (OVERLAYP (o1))
7b863bd5 1991 {
e23f814f 1992 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2),
4ff1aed9 1993 depth + 1)
e23f814f 1994 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2),
4ff1aed9 1995 depth + 1))
6cb9cafb 1996 return 0;
4ff1aed9
RS
1997 o1 = XOVERLAY (o1)->plist;
1998 o2 = XOVERLAY (o2)->plist;
1999 goto tail_recurse;
7b863bd5 2000 }
4ff1aed9
RS
2001 if (MARKERP (o1))
2002 {
2003 return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
2004 && (XMARKER (o1)->buffer == 0
6ced1284 2005 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
4ff1aed9
RS
2006 }
2007 break;
2008
2009 case Lisp_Vectorlike:
4cab5074
KH
2010 {
2011 register int i, size;
2012 size = XVECTOR (o1)->size;
2013 /* Pseudovectors have the type encoded in the size field, so this test
2014 actually checks that the objects have the same type as well as the
2015 same size. */
2016 if (XVECTOR (o2)->size != size)
2017 return 0;
e03f7933
RS
2018 /* Boolvectors are compared much like strings. */
2019 if (BOOL_VECTOR_P (o1))
2020 {
e03f7933 2021 int size_in_chars
e22e4283 2022 = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
2023
2024 if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
2025 return 0;
2026 if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
2027 size_in_chars))
2028 return 0;
2029 return 1;
2030 }
ed73fcc1 2031 if (WINDOW_CONFIGURATIONP (o1))
48646924 2032 return compare_window_configurations (o1, o2, 0);
e03f7933
RS
2033
2034 /* Aside from them, only true vectors, char-tables, and compiled
2035 functions are sensible to compare, so eliminate the others now. */
4cab5074
KH
2036 if (size & PSEUDOVECTOR_FLAG)
2037 {
e03f7933 2038 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
4cab5074
KH
2039 return 0;
2040 size &= PSEUDOVECTOR_SIZE_MASK;
2041 }
2042 for (i = 0; i < size; i++)
2043 {
2044 Lisp_Object v1, v2;
2045 v1 = XVECTOR (o1)->contents [i];
2046 v2 = XVECTOR (o2)->contents [i];
2047 if (!internal_equal (v1, v2, depth + 1))
2048 return 0;
2049 }
2050 return 1;
2051 }
4ff1aed9
RS
2052 break;
2053
2054 case Lisp_String:
4cab5074
KH
2055 if (XSTRING (o1)->size != XSTRING (o2)->size)
2056 return 0;
fc932ac6 2057 if (STRING_BYTES (XSTRING (o1)) != STRING_BYTES (XSTRING (o2)))
ea35ce3d 2058 return 0;
4cab5074 2059 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
fc932ac6 2060 STRING_BYTES (XSTRING (o1))))
4cab5074 2061 return 0;
4cab5074 2062 return 1;
093386ca
GM
2063
2064 case Lisp_Int:
2065 case Lisp_Symbol:
2066 case Lisp_Type_Limit:
2067 break;
7b863bd5 2068 }
093386ca 2069
6cb9cafb 2070 return 0;
7b863bd5
JB
2071}
2072\f
2e34157c
RS
2073extern Lisp_Object Fmake_char_internal ();
2074
7b863bd5 2075DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
e03f7933
RS
2076 "Store each element of ARRAY with ITEM.\n\
2077ARRAY is a vector, string, char-table, or bool-vector.")
7b863bd5
JB
2078 (array, item)
2079 Lisp_Object array, item;
2080{
2081 register int size, index, charval;
2082 retry:
7650760e 2083 if (VECTORP (array))
7b863bd5
JB
2084 {
2085 register Lisp_Object *p = XVECTOR (array)->contents;
2086 size = XVECTOR (array)->size;
2087 for (index = 0; index < size; index++)
2088 p[index] = item;
2089 }
e03f7933
RS
2090 else if (CHAR_TABLE_P (array))
2091 {
2092 register Lisp_Object *p = XCHAR_TABLE (array)->contents;
2093 size = CHAR_TABLE_ORDINARY_SLOTS;
2094 for (index = 0; index < size; index++)
2095 p[index] = item;
2096 XCHAR_TABLE (array)->defalt = Qnil;
2097 }
7650760e 2098 else if (STRINGP (array))
7b863bd5
JB
2099 {
2100 register unsigned char *p = XSTRING (array)->data;
2101 CHECK_NUMBER (item, 1);
2102 charval = XINT (item);
2103 size = XSTRING (array)->size;
57247650
KH
2104 if (STRING_MULTIBYTE (array))
2105 {
64a5094a
KH
2106 unsigned char str[MAX_MULTIBYTE_LENGTH];
2107 int len = CHAR_STRING (charval, str);
57247650
KH
2108 int size_byte = STRING_BYTES (XSTRING (array));
2109 unsigned char *p1 = p, *endp = p + size_byte;
95b8aba7 2110 int i;
57247650 2111
95b8aba7
KH
2112 if (size != size_byte)
2113 while (p1 < endp)
2114 {
2115 int this_len = MULTIBYTE_FORM_LENGTH (p1, endp - p1);
2116 if (len != this_len)
2117 error ("Attempt to change byte length of a string");
2118 p1 += this_len;
2119 }
57247650
KH
2120 for (i = 0; i < size_byte; i++)
2121 *p++ = str[i % len];
2122 }
2123 else
2124 for (index = 0; index < size; index++)
2125 p[index] = charval;
7b863bd5 2126 }
e03f7933
RS
2127 else if (BOOL_VECTOR_P (array))
2128 {
2129 register unsigned char *p = XBOOL_VECTOR (array)->data;
e03f7933 2130 int size_in_chars
e22e4283 2131 = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
2132
2133 charval = (! NILP (item) ? -1 : 0);
2134 for (index = 0; index < size_in_chars; index++)
2135 p[index] = charval;
2136 }
7b863bd5
JB
2137 else
2138 {
2139 array = wrong_type_argument (Qarrayp, array);
2140 goto retry;
2141 }
2142 return array;
2143}
ea35ce3d 2144\f
999de246
RS
2145DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
2146 1, 1, 0,
2147 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
88fe8140
EN
2148 (char_table)
2149 Lisp_Object char_table;
999de246 2150{
b4f334f7 2151 CHECK_CHAR_TABLE (char_table, 0);
999de246 2152
88fe8140 2153 return XCHAR_TABLE (char_table)->purpose;
999de246
RS
2154}
2155
e03f7933
RS
2156DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
2157 1, 1, 0,
2158 "Return the parent char-table of CHAR-TABLE.\n\
2159The value is either nil or another char-table.\n\
2160If CHAR-TABLE holds nil for a given character,\n\
2161then the actual applicable value is inherited from the parent char-table\n\
2162\(or from its parents, if necessary).")
88fe8140
EN
2163 (char_table)
2164 Lisp_Object char_table;
e03f7933 2165{
b4f334f7 2166 CHECK_CHAR_TABLE (char_table, 0);
e03f7933 2167
88fe8140 2168 return XCHAR_TABLE (char_table)->parent;
e03f7933
RS
2169}
2170
2171DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
2172 2, 2, 0,
2173 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
2174PARENT must be either nil or another char-table.")
88fe8140
EN
2175 (char_table, parent)
2176 Lisp_Object char_table, parent;
e03f7933
RS
2177{
2178 Lisp_Object temp;
2179
b4f334f7 2180 CHECK_CHAR_TABLE (char_table, 0);
e03f7933 2181
c8640abf
RS
2182 if (!NILP (parent))
2183 {
b4f334f7 2184 CHECK_CHAR_TABLE (parent, 0);
c8640abf
RS
2185
2186 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
55cc974d 2187 if (EQ (temp, char_table))
c8640abf
RS
2188 error ("Attempt to make a chartable be its own parent");
2189 }
e03f7933 2190
88fe8140 2191 XCHAR_TABLE (char_table)->parent = parent;
e03f7933
RS
2192
2193 return parent;
2194}
2195
2196DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
2197 2, 2, 0,
25c30748 2198 "Return the value of CHAR-TABLE's extra-slot number N.")
88fe8140
EN
2199 (char_table, n)
2200 Lisp_Object char_table, n;
e03f7933 2201{
88fe8140 2202 CHECK_CHAR_TABLE (char_table, 1);
e03f7933
RS
2203 CHECK_NUMBER (n, 2);
2204 if (XINT (n) < 0
88fe8140
EN
2205 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
2206 args_out_of_range (char_table, n);
e03f7933 2207
88fe8140 2208 return XCHAR_TABLE (char_table)->extras[XINT (n)];
e03f7933
RS
2209}
2210
2211DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
2212 Sset_char_table_extra_slot,
2213 3, 3, 0,
25c30748 2214 "Set CHAR-TABLE's extra-slot number N to VALUE.")
88fe8140
EN
2215 (char_table, n, value)
2216 Lisp_Object char_table, n, value;
e03f7933 2217{
88fe8140 2218 CHECK_CHAR_TABLE (char_table, 1);
e03f7933
RS
2219 CHECK_NUMBER (n, 2);
2220 if (XINT (n) < 0
88fe8140
EN
2221 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
2222 args_out_of_range (char_table, n);
e03f7933 2223
88fe8140 2224 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
e03f7933 2225}
ea35ce3d 2226\f
999de246
RS
2227DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
2228 2, 2, 0,
88fe8140 2229 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
6d475204 2230RANGE should be nil (for the default value)\n\
999de246 2231a vector which identifies a character set or a row of a character set,\n\
6d475204 2232a character set name, or a character code.")
88fe8140
EN
2233 (char_table, range)
2234 Lisp_Object char_table, range;
999de246 2235{
88fe8140 2236 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 2237
999de246 2238 if (EQ (range, Qnil))
88fe8140 2239 return XCHAR_TABLE (char_table)->defalt;
999de246 2240 else if (INTEGERP (range))
88fe8140 2241 return Faref (char_table, range);
6d475204
RS
2242 else if (SYMBOLP (range))
2243 {
2244 Lisp_Object charset_info;
2245
2246 charset_info = Fget (range, Qcharset);
2247 CHECK_VECTOR (charset_info, 0);
2248
21ab867f
AS
2249 return Faref (char_table,
2250 make_number (XINT (XVECTOR (charset_info)->contents[0])
2251 + 128));
6d475204 2252 }
999de246
RS
2253 else if (VECTORP (range))
2254 {
e814a159 2255 if (XVECTOR (range)->size == 1)
21ab867f
AS
2256 return Faref (char_table,
2257 make_number (XINT (XVECTOR (range)->contents[0]) + 128));
e814a159
RS
2258 else
2259 {
2260 int size = XVECTOR (range)->size;
2261 Lisp_Object *val = XVECTOR (range)->contents;
2262 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
2263 size <= 1 ? Qnil : val[1],
2264 size <= 2 ? Qnil : val[2]);
2265 return Faref (char_table, ch);
2266 }
999de246
RS
2267 }
2268 else
2269 error ("Invalid RANGE argument to `char-table-range'");
5c6740c9 2270 return Qt;
999de246
RS
2271}
2272
e03f7933
RS
2273DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
2274 3, 3, 0,
88fe8140 2275 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
e03f7933
RS
2276RANGE should be t (for all characters), nil (for the default value)\n\
2277a vector which identifies a character set or a row of a character set,\n\
6d475204 2278a coding system, or a character code.")
88fe8140
EN
2279 (char_table, range, value)
2280 Lisp_Object char_table, range, value;
e03f7933
RS
2281{
2282 int i;
2283
88fe8140 2284 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 2285
e03f7933
RS
2286 if (EQ (range, Qt))
2287 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
88fe8140 2288 XCHAR_TABLE (char_table)->contents[i] = value;
e03f7933 2289 else if (EQ (range, Qnil))
88fe8140 2290 XCHAR_TABLE (char_table)->defalt = value;
6d475204
RS
2291 else if (SYMBOLP (range))
2292 {
2293 Lisp_Object charset_info;
2294
2295 charset_info = Fget (range, Qcharset);
2296 CHECK_VECTOR (charset_info, 0);
2297
21ab867f
AS
2298 return Faset (char_table,
2299 make_number (XINT (XVECTOR (charset_info)->contents[0])
2300 + 128),
6d475204
RS
2301 value);
2302 }
e03f7933 2303 else if (INTEGERP (range))
88fe8140 2304 Faset (char_table, range, value);
e03f7933
RS
2305 else if (VECTORP (range))
2306 {
e814a159 2307 if (XVECTOR (range)->size == 1)
21ab867f
AS
2308 return Faset (char_table,
2309 make_number (XINT (XVECTOR (range)->contents[0]) + 128),
2310 value);
e814a159
RS
2311 else
2312 {
2313 int size = XVECTOR (range)->size;
2314 Lisp_Object *val = XVECTOR (range)->contents;
2315 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
2316 size <= 1 ? Qnil : val[1],
2317 size <= 2 ? Qnil : val[2]);
2318 return Faset (char_table, ch, value);
2319 }
e03f7933
RS
2320 }
2321 else
2322 error ("Invalid RANGE argument to `set-char-table-range'");
2323
2324 return value;
2325}
e1335ba2
KH
2326
2327DEFUN ("set-char-table-default", Fset_char_table_default,
2328 Sset_char_table_default, 3, 3, 0,
2329 "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
2330The generic character specifies the group of characters.\n\
2331See also the documentation of make-char.")
2332 (char_table, ch, value)
2333 Lisp_Object char_table, ch, value;
2334{
ada0fa14 2335 int c, charset, code1, code2;
e1335ba2
KH
2336 Lisp_Object temp;
2337
2338 CHECK_CHAR_TABLE (char_table, 0);
2339 CHECK_NUMBER (ch, 1);
2340
2341 c = XINT (ch);
2db66414 2342 SPLIT_CHAR (c, charset, code1, code2);
0da528a9
KH
2343
2344 /* Since we may want to set the default value for a character set
2345 not yet defined, we check only if the character set is in the
2346 valid range or not, instead of it is already defined or not. */
2347 if (! CHARSET_VALID_P (charset))
f71599f4 2348 invalid_character (c);
e1335ba2
KH
2349
2350 if (charset == CHARSET_ASCII)
2351 return (XCHAR_TABLE (char_table)->defalt = value);
2352
2353 /* Even if C is not a generic char, we had better behave as if a
2354 generic char is specified. */
64a5094a 2355 if (CHARSET_DIMENSION (charset) == 1)
e1335ba2
KH
2356 code1 = 0;
2357 temp = XCHAR_TABLE (char_table)->contents[charset + 128];
2358 if (!code1)
2359 {
2360 if (SUB_CHAR_TABLE_P (temp))
2361 XCHAR_TABLE (temp)->defalt = value;
2362 else
2363 XCHAR_TABLE (char_table)->contents[charset + 128] = value;
2364 return value;
2365 }
1e70fc65
KH
2366 if (SUB_CHAR_TABLE_P (temp))
2367 char_table = temp;
2368 else
e1335ba2 2369 char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
1e70fc65 2370 = make_sub_char_table (temp));
e1335ba2
KH
2371 temp = XCHAR_TABLE (char_table)->contents[code1];
2372 if (SUB_CHAR_TABLE_P (temp))
2373 XCHAR_TABLE (temp)->defalt = value;
2374 else
2375 XCHAR_TABLE (char_table)->contents[code1] = value;
2376 return value;
2377}
1d969a23
RS
2378
2379/* Look up the element in TABLE at index CH,
2380 and return it as an integer.
2381 If the element is nil, return CH itself.
2382 (Actually we do that for any non-integer.) */
2383
2384int
2385char_table_translate (table, ch)
2386 Lisp_Object table;
2387 int ch;
2388{
2389 Lisp_Object value;
2390 value = Faref (table, make_number (ch));
2391 if (! INTEGERP (value))
2392 return ch;
2393 return XINT (value);
2394}
52ef6c89
KH
2395
2396static void
2397optimize_sub_char_table (table, chars)
2398 Lisp_Object *table;
2399 int chars;
2400{
2401 Lisp_Object elt;
2402 int from, to;
2403
2404 if (chars == 94)
2405 from = 33, to = 127;
2406 else
2407 from = 32, to = 128;
2408
2409 if (!SUB_CHAR_TABLE_P (*table))
2410 return;
2411 elt = XCHAR_TABLE (*table)->contents[from++];
2412 for (; from < to; from++)
2413 if (NILP (Fequal (elt, XCHAR_TABLE (*table)->contents[from])))
2414 return;
2415 *table = elt;
2416}
2417
2418DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
2419 1, 1, 0,
2420 "Optimize char table TABLE.")
2421 (table)
2422 Lisp_Object table;
2423{
2424 Lisp_Object elt;
2425 int dim;
2426 int i, j;
2427
2428 CHECK_CHAR_TABLE (table, 0);
2429
2430 for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
2431 {
2432 elt = XCHAR_TABLE (table)->contents[i];
2433 if (!SUB_CHAR_TABLE_P (elt))
2434 continue;
4a8009a0 2435 dim = CHARSET_DIMENSION (i - 128);
52ef6c89
KH
2436 if (dim == 2)
2437 for (j = 32; j < SUB_CHAR_TABLE_ORDINARY_SLOTS; j++)
2438 optimize_sub_char_table (XCHAR_TABLE (elt)->contents + j, dim);
2439 optimize_sub_char_table (XCHAR_TABLE (table)->contents + i, dim);
2440 }
2441 return Qnil;
2442}
2443
e03f7933 2444\f
46ed603f 2445/* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
c8640abf
RS
2446 character or group of characters that share a value.
2447 DEPTH is the current depth in the originally specified
2448 chartable, and INDICES contains the vector indices
46ed603f
RS
2449 for the levels our callers have descended.
2450
2451 ARG is passed to C_FUNCTION when that is called. */
c8640abf
RS
2452
2453void
46ed603f 2454map_char_table (c_function, function, subtable, arg, depth, indices)
22e6f12b
AS
2455 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
2456 Lisp_Object function, subtable, arg, *indices;
1847b19b 2457 int depth;
e03f7933 2458{
3720677d 2459 int i, to;
e03f7933 2460
a8283a4a 2461 if (depth == 0)
3720677d
KH
2462 {
2463 /* At first, handle ASCII and 8-bit European characters. */
2464 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
2465 {
46ed603f 2466 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
3720677d 2467 if (c_function)
46ed603f 2468 (*c_function) (arg, make_number (i), elt);
3720677d
KH
2469 else
2470 call2 (function, make_number (i), elt);
2471 }
ea35ce3d
RS
2472#if 0 /* If the char table has entries for higher characters,
2473 we should report them. */
de86fcba
KH
2474 if (NILP (current_buffer->enable_multibyte_characters))
2475 return;
ea35ce3d 2476#endif
3720677d
KH
2477 to = CHAR_TABLE_ORDINARY_SLOTS;
2478 }
a8283a4a 2479 else
e03f7933 2480 {
a3b210c4
KH
2481 int charset = XFASTINT (indices[0]) - 128;
2482
de86fcba 2483 i = 32;
3720677d 2484 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
a3b210c4
KH
2485 if (CHARSET_CHARS (charset) == 94)
2486 i++, to--;
e03f7933
RS
2487 }
2488
7e798f25 2489 for (; i < to; i++)
e03f7933 2490 {
a3b210c4
KH
2491 Lisp_Object elt;
2492 int charset;
3720677d 2493
a3b210c4 2494 elt = XCHAR_TABLE (subtable)->contents[i];
09ee221d 2495 XSETFASTINT (indices[depth], i);
a3b210c4 2496 charset = XFASTINT (indices[0]) - 128;
df2fbceb
KH
2497 if (depth == 0
2498 && (!CHARSET_DEFINED_P (charset)
2499 || charset == CHARSET_8_BIT_CONTROL
2500 || charset == CHARSET_8_BIT_GRAPHIC))
a3b210c4 2501 continue;
3720677d
KH
2502
2503 if (SUB_CHAR_TABLE_P (elt))
2504 {
2505 if (depth >= 3)
2506 error ("Too deep char table");
7e798f25 2507 map_char_table (c_function, function, elt, arg, depth + 1, indices);
3720677d 2508 }
e03f7933 2509 else
a8283a4a 2510 {
a3b210c4 2511 int c1, c2, c;
3720677d 2512
a3b210c4
KH
2513 if (NILP (elt))
2514 elt = XCHAR_TABLE (subtable)->defalt;
2515 c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
2516 c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
2efdd1b9 2517 c = MAKE_CHAR (charset, c1, c2);
a3b210c4
KH
2518 if (c_function)
2519 (*c_function) (arg, make_number (c), elt);
2520 else
2521 call2 (function, make_number (c), elt);
b4f334f7 2522 }
e03f7933
RS
2523 }
2524}
2525
2526DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
2527 2, 2, 0,
7e798f25 2528 "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
e03f7933 2529FUNCTION is called with two arguments--a key and a value.\n\
7e798f25 2530The key is always a possible IDX argument to `aref'.")
88fe8140
EN
2531 (function, char_table)
2532 Lisp_Object function, char_table;
e03f7933 2533{
3720677d 2534 /* The depth of char table is at most 3. */
7e798f25
KH
2535 Lisp_Object indices[3];
2536
2537 CHECK_CHAR_TABLE (char_table, 1);
e03f7933 2538
46ed603f 2539 map_char_table (NULL, function, char_table, char_table, 0, indices);
e03f7933
RS
2540 return Qnil;
2541}
2f729392
KH
2542
2543/* Return a value for character C in char-table TABLE. Store the
2544 actual index for that value in *IDX. Ignore the default value of
2545 TABLE. */
2546
2547Lisp_Object
2548char_table_ref_and_index (table, c, idx)
2549 Lisp_Object table;
2550 int c, *idx;
2551{
2552 int charset, c1, c2;
2553 Lisp_Object elt;
2554
2555 if (SINGLE_BYTE_CHAR_P (c))
2556 {
2557 *idx = c;
2558 return XCHAR_TABLE (table)->contents[c];
2559 }
2560 SPLIT_CHAR (c, charset, c1, c2);
2561 elt = XCHAR_TABLE (table)->contents[charset + 128];
2562 *idx = MAKE_CHAR (charset, 0, 0);
2563 if (!SUB_CHAR_TABLE_P (elt))
2564 return elt;
2565 if (c1 < 32 || NILP (XCHAR_TABLE (elt)->contents[c1]))
2566 return XCHAR_TABLE (elt)->defalt;
2567 elt = XCHAR_TABLE (elt)->contents[c1];
2568 *idx = MAKE_CHAR (charset, c1, 0);
2569 if (!SUB_CHAR_TABLE_P (elt))
2570 return elt;
2571 if (c2 < 32 || NILP (XCHAR_TABLE (elt)->contents[c2]))
2572 return XCHAR_TABLE (elt)->defalt;
2573 *idx = c;
2574 return XCHAR_TABLE (elt)->contents[c2];
2575}
2576
e03f7933 2577\f
7b863bd5
JB
2578/* ARGSUSED */
2579Lisp_Object
2580nconc2 (s1, s2)
2581 Lisp_Object s1, s2;
2582{
2583#ifdef NO_ARG_ARRAY
2584 Lisp_Object args[2];
2585 args[0] = s1;
2586 args[1] = s2;
2587 return Fnconc (2, args);
2588#else
2589 return Fnconc (2, &s1);
2590#endif /* NO_ARG_ARRAY */
2591}
2592
2593DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
2594 "Concatenate any number of lists by altering them.\n\
2595Only the last argument is not altered, and need not be a list.")
2596 (nargs, args)
2597 int nargs;
2598 Lisp_Object *args;
2599{
2600 register int argnum;
2601 register Lisp_Object tail, tem, val;
2602
093386ca 2603 val = tail = Qnil;
7b863bd5
JB
2604
2605 for (argnum = 0; argnum < nargs; argnum++)
2606 {
2607 tem = args[argnum];
265a9e55 2608 if (NILP (tem)) continue;
7b863bd5 2609
265a9e55 2610 if (NILP (val))
7b863bd5
JB
2611 val = tem;
2612
2613 if (argnum + 1 == nargs) break;
2614
2615 if (!CONSP (tem))
2616 tem = wrong_type_argument (Qlistp, tem);
2617
2618 while (CONSP (tem))
2619 {
2620 tail = tem;
2621 tem = Fcdr (tail);
2622 QUIT;
2623 }
2624
2625 tem = args[argnum + 1];
2626 Fsetcdr (tail, tem);
265a9e55 2627 if (NILP (tem))
7b863bd5
JB
2628 args[argnum + 1] = tail;
2629 }
2630
2631 return val;
2632}
2633\f
2634/* This is the guts of all mapping functions.
ea35ce3d
RS
2635 Apply FN to each element of SEQ, one by one,
2636 storing the results into elements of VALS, a C vector of Lisp_Objects.
2637 LENI is the length of VALS, which should also be the length of SEQ. */
7b863bd5
JB
2638
2639static void
2640mapcar1 (leni, vals, fn, seq)
2641 int leni;
2642 Lisp_Object *vals;
2643 Lisp_Object fn, seq;
2644{
2645 register Lisp_Object tail;
2646 Lisp_Object dummy;
2647 register int i;
2648 struct gcpro gcpro1, gcpro2, gcpro3;
2649
f5c75033
DL
2650 if (vals)
2651 {
2652 /* Don't let vals contain any garbage when GC happens. */
2653 for (i = 0; i < leni; i++)
2654 vals[i] = Qnil;
7b863bd5 2655
f5c75033
DL
2656 GCPRO3 (dummy, fn, seq);
2657 gcpro1.var = vals;
2658 gcpro1.nvars = leni;
2659 }
2660 else
2661 GCPRO2 (fn, seq);
7b863bd5
JB
2662 /* We need not explicitly protect `tail' because it is used only on lists, and
2663 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
2664
7650760e 2665 if (VECTORP (seq))
7b863bd5
JB
2666 {
2667 for (i = 0; i < leni; i++)
2668 {
2669 dummy = XVECTOR (seq)->contents[i];
f5c75033
DL
2670 dummy = call1 (fn, dummy);
2671 if (vals)
2672 vals[i] = dummy;
7b863bd5
JB
2673 }
2674 }
33aa0881
KH
2675 else if (BOOL_VECTOR_P (seq))
2676 {
2677 for (i = 0; i < leni; i++)
2678 {
2679 int byte;
2680 byte = XBOOL_VECTOR (seq)->data[i / BITS_PER_CHAR];
2681 if (byte & (1 << (i % BITS_PER_CHAR)))
2682 dummy = Qt;
2683 else
2684 dummy = Qnil;
2685
f5c75033
DL
2686 dummy = call1 (fn, dummy);
2687 if (vals)
2688 vals[i] = dummy;
33aa0881
KH
2689 }
2690 }
ea35ce3d
RS
2691 else if (STRINGP (seq))
2692 {
ea35ce3d
RS
2693 int i_byte;
2694
2695 for (i = 0, i_byte = 0; i < leni;)
2696 {
2697 int c;
0ab6a3d8
KH
2698 int i_before = i;
2699
2700 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte);
ea35ce3d 2701 XSETFASTINT (dummy, c);
f5c75033
DL
2702 dummy = call1 (fn, dummy);
2703 if (vals)
2704 vals[i_before] = dummy;
ea35ce3d
RS
2705 }
2706 }
7b863bd5
JB
2707 else /* Must be a list, since Flength did not get an error */
2708 {
2709 tail = seq;
2710 for (i = 0; i < leni; i++)
2711 {
f5c75033
DL
2712 dummy = call1 (fn, Fcar (tail));
2713 if (vals)
2714 vals[i] = dummy;
70949dac 2715 tail = XCDR (tail);
7b863bd5
JB
2716 }
2717 }
2718
2719 UNGCPRO;
2720}
2721
2722DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
88fe8140
EN
2723 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2724In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
33aa0881
KH
2725SEPARATOR results in spaces between the values returned by FUNCTION.\n\
2726SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2727 (function, sequence, separator)
2728 Lisp_Object function, sequence, separator;
7b863bd5
JB
2729{
2730 Lisp_Object len;
2731 register int leni;
2732 int nargs;
2733 register Lisp_Object *args;
2734 register int i;
2735 struct gcpro gcpro1;
2736
88fe8140 2737 len = Flength (sequence);
7b863bd5
JB
2738 leni = XINT (len);
2739 nargs = leni + leni - 1;
2740 if (nargs < 0) return build_string ("");
2741
2742 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2743
88fe8140
EN
2744 GCPRO1 (separator);
2745 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2746 UNGCPRO;
2747
2748 for (i = leni - 1; i >= 0; i--)
2749 args[i + i] = args[i];
b4f334f7 2750
7b863bd5 2751 for (i = 1; i < nargs; i += 2)
88fe8140 2752 args[i] = separator;
7b863bd5
JB
2753
2754 return Fconcat (nargs, args);
2755}
2756
2757DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2758 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2759The result is a list just as long as SEQUENCE.\n\
33aa0881 2760SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2761 (function, sequence)
2762 Lisp_Object function, sequence;
7b863bd5
JB
2763{
2764 register Lisp_Object len;
2765 register int leni;
2766 register Lisp_Object *args;
2767
88fe8140 2768 len = Flength (sequence);
7b863bd5
JB
2769 leni = XFASTINT (len);
2770 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2771
88fe8140 2772 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2773
2774 return Flist (leni, args);
2775}
f5c75033
DL
2776
2777DEFUN ("mapc", Fmapc, Smapc, 2, 2, 0,
2778 "Apply FUNCTION to each element of SEQUENCE for side effects only.\n\
2779Unlike `mapcar', don't accumulate the results. Return SEQUENCE.\n\
2780SEQUENCE may be a list, a vector, a bool-vector, or a string.")
2781 (function, sequence)
2782 Lisp_Object function, sequence;
2783{
2784 register int leni;
2785
2786 leni = XFASTINT (Flength (sequence));
2787 mapcar1 (leni, 0, function, sequence);
2788
2789 return sequence;
2790}
7b863bd5
JB
2791\f
2792/* Anything that calls this function must protect from GC! */
2793
2794DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2795 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
c763f396
RS
2796Takes one argument, which is the string to display to ask the question.\n\
2797It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
7b863bd5 2798No confirmation of the answer is requested; a single character is enough.\n\
2b8503ea 2799Also accepts Space to mean yes, or Delete to mean no. \(Actually, it uses\n\
71a8e74b 2800the bindings in `query-replace-map'; see the documentation of that variable\n\
2b8503ea
KH
2801for more information. In this case, the useful bindings are `act', `skip',\n\
2802`recenter', and `quit'.\)\n\
0c6ca44b
DL
2803\n\
2804Under a windowing system a dialog box will be used if `last-nonmenu-event'\n\
cd234430 2805is nil and `use-dialog-box' is non-nil.")
7b863bd5
JB
2806 (prompt)
2807 Lisp_Object prompt;
2808{
2b8503ea 2809 register Lisp_Object obj, key, def, map;
f5313ed9 2810 register int answer;
7b863bd5
JB
2811 Lisp_Object xprompt;
2812 Lisp_Object args[2];
7b863bd5 2813 struct gcpro gcpro1, gcpro2;
eb4ffa4e
RS
2814 int count = specpdl_ptr - specpdl;
2815
2816 specbind (Qcursor_in_echo_area, Qt);
7b863bd5 2817
f5313ed9
RS
2818 map = Fsymbol_value (intern ("query-replace-map"));
2819
7b863bd5
JB
2820 CHECK_STRING (prompt, 0);
2821 xprompt = prompt;
2822 GCPRO2 (prompt, xprompt);
2823
eff95916 2824#ifdef HAVE_X_WINDOWS
df6c90d8
GM
2825 if (display_hourglass_p)
2826 cancel_hourglass ();
eff95916 2827#endif
59f953a2 2828
7b863bd5
JB
2829 while (1)
2830 {
eb4ffa4e 2831
0ef68e8a 2832#ifdef HAVE_MENUS
588064ce 2833 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2834 && use_dialog_box
0ef68e8a 2835 && have_menus_p ())
1db4cfb2
RS
2836 {
2837 Lisp_Object pane, menu;
3007ebfb 2838 redisplay_preserve_echo_area (3);
1db4cfb2
RS
2839 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2840 Fcons (Fcons (build_string ("No"), Qnil),
2841 Qnil));
ec26e1b9 2842 menu = Fcons (prompt, pane);
d2f28f78 2843 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2844 answer = !NILP (obj);
2845 break;
2846 }
0ef68e8a 2847#endif /* HAVE_MENUS */
dfa89228 2848 cursor_in_echo_area = 1;
b312cc52 2849 choose_minibuf_frame ();
ea35ce3d 2850 message_with_string ("%s(y or n) ", xprompt, 0);
7b863bd5 2851
2d8e7e1f
RS
2852 if (minibuffer_auto_raise)
2853 {
2854 Lisp_Object mini_frame;
2855
2856 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2857
2858 Fraise_frame (mini_frame);
2859 }
2860
7ba13c57 2861 obj = read_filtered_event (1, 0, 0, 0);
dfa89228
KH
2862 cursor_in_echo_area = 0;
2863 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2864 QUIT;
a63f658b 2865
f5313ed9 2866 key = Fmake_vector (make_number (1), obj);
aad2a123 2867 def = Flookup_key (map, key, Qt);
7b863bd5 2868
f5313ed9
RS
2869 if (EQ (def, intern ("skip")))
2870 {
2871 answer = 0;
2872 break;
2873 }
2874 else if (EQ (def, intern ("act")))
2875 {
2876 answer = 1;
2877 break;
2878 }
29944b73
RS
2879 else if (EQ (def, intern ("recenter")))
2880 {
2881 Frecenter (Qnil);
2882 xprompt = prompt;
2883 continue;
2884 }
f5313ed9 2885 else if (EQ (def, intern ("quit")))
7b863bd5 2886 Vquit_flag = Qt;
ec63af1b
RS
2887 /* We want to exit this command for exit-prefix,
2888 and this is the only way to do it. */
2889 else if (EQ (def, intern ("exit-prefix")))
2890 Vquit_flag = Qt;
f5313ed9 2891
7b863bd5 2892 QUIT;
20aa96aa
JB
2893
2894 /* If we don't clear this, then the next call to read_char will
2895 return quit_char again, and we'll enter an infinite loop. */
088880f1 2896 Vquit_flag = Qnil;
7b863bd5
JB
2897
2898 Fding (Qnil);
2899 Fdiscard_input ();
2900 if (EQ (xprompt, prompt))
2901 {
2902 args[0] = build_string ("Please answer y or n. ");
2903 args[1] = prompt;
2904 xprompt = Fconcat (2, args);
2905 }
2906 }
2907 UNGCPRO;
6a8a9750 2908
09c95874
RS
2909 if (! noninteractive)
2910 {
2911 cursor_in_echo_area = -1;
ea35ce3d
RS
2912 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2913 xprompt, 0);
09c95874 2914 }
6a8a9750 2915
eb4ffa4e 2916 unbind_to (count, Qnil);
f5313ed9 2917 return answer ? Qt : Qnil;
7b863bd5
JB
2918}
2919\f
2920/* This is how C code calls `yes-or-no-p' and allows the user
2921 to redefined it.
2922
2923 Anything that calls this function must protect from GC! */
2924
2925Lisp_Object
2926do_yes_or_no_p (prompt)
2927 Lisp_Object prompt;
2928{
2929 return call1 (intern ("yes-or-no-p"), prompt);
2930}
2931
2932/* Anything that calls this function must protect from GC! */
2933
2934DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
c763f396
RS
2935 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2936Takes one argument, which is the string to display to ask the question.\n\
2937It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2938The user must confirm the answer with RET,\n\
0c6ca44b
DL
2939and can edit it until it has been confirmed.\n\
2940\n\
2941Under a windowing system a dialog box will be used if `last-nonmenu-event'\n\
cd234430 2942is nil, and `use-dialog-box' is non-nil.")
7b863bd5
JB
2943 (prompt)
2944 Lisp_Object prompt;
2945{
2946 register Lisp_Object ans;
2947 Lisp_Object args[2];
2948 struct gcpro gcpro1;
2949
2950 CHECK_STRING (prompt, 0);
2951
0ef68e8a 2952#ifdef HAVE_MENUS
b4f334f7 2953 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2954 && use_dialog_box
0ef68e8a 2955 && have_menus_p ())
1db4cfb2
RS
2956 {
2957 Lisp_Object pane, menu, obj;
3007ebfb 2958 redisplay_preserve_echo_area (4);
1db4cfb2
RS
2959 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2960 Fcons (Fcons (build_string ("No"), Qnil),
2961 Qnil));
2962 GCPRO1 (pane);
ec26e1b9 2963 menu = Fcons (prompt, pane);
b5ccb0a9 2964 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2965 UNGCPRO;
2966 return obj;
2967 }
0ef68e8a 2968#endif /* HAVE_MENUS */
1db4cfb2 2969
7b863bd5
JB
2970 args[0] = prompt;
2971 args[1] = build_string ("(yes or no) ");
2972 prompt = Fconcat (2, args);
2973
2974 GCPRO1 (prompt);
1db4cfb2 2975
7b863bd5
JB
2976 while (1)
2977 {
0ce830bc 2978 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
b24014d4
KH
2979 Qyes_or_no_p_history, Qnil,
2980 Qnil));
7b863bd5
JB
2981 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2982 {
2983 UNGCPRO;
2984 return Qt;
2985 }
2986 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2987 {
2988 UNGCPRO;
2989 return Qnil;
2990 }
2991
2992 Fding (Qnil);
2993 Fdiscard_input ();
2994 message ("Please answer yes or no.");
99dc4745 2995 Fsleep_for (make_number (2), Qnil);
7b863bd5 2996 }
7b863bd5
JB
2997}
2998\f
f4b50f66 2999DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
7b863bd5
JB
3000 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
3001Each of the three load averages is multiplied by 100,\n\
daa37602 3002then converted to integer.\n\
f4b50f66
RS
3003When USE-FLOATS is non-nil, floats will be used instead of integers.\n\
3004These floats are not multiplied by 100.\n\n\
daa37602
JB
3005If the 5-minute or 15-minute load averages are not available, return a\n\
3006shortened list, containing only those averages which are available.")
f4b50f66
RS
3007 (use_floats)
3008 Lisp_Object use_floats;
7b863bd5 3009{
daa37602
JB
3010 double load_ave[3];
3011 int loads = getloadavg (load_ave, 3);
f4b50f66 3012 Lisp_Object ret = Qnil;
7b863bd5 3013
daa37602
JB
3014 if (loads < 0)
3015 error ("load-average not implemented for this operating system");
3016
f4b50f66
RS
3017 while (loads-- > 0)
3018 {
3019 Lisp_Object load = (NILP (use_floats) ?
3020 make_number ((int) (100.0 * load_ave[loads]))
3021 : make_float (load_ave[loads]));
3022 ret = Fcons (load, ret);
3023 }
daa37602
JB
3024
3025 return ret;
3026}
7b863bd5
JB
3027\f
3028Lisp_Object Vfeatures;
3029
3030DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
3031 "Returns t if FEATURE is present in this Emacs.\n\
3032Use this to conditionalize execution of lisp code based on the presence or\n\
3033absence of emacs or environment extensions.\n\
3034Use `provide' to declare that a feature is available.\n\
3035This function looks at the value of the variable `features'.")
b4f334f7 3036 (feature)
7b863bd5
JB
3037 Lisp_Object feature;
3038{
3039 register Lisp_Object tem;
3040 CHECK_SYMBOL (feature, 0);
3041 tem = Fmemq (feature, Vfeatures);
265a9e55 3042 return (NILP (tem)) ? Qnil : Qt;
7b863bd5
JB
3043}
3044
3045DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
3046 "Announce that FEATURE is a feature of the current Emacs.")
b4f334f7 3047 (feature)
7b863bd5
JB
3048 Lisp_Object feature;
3049{
3050 register Lisp_Object tem;
3051 CHECK_SYMBOL (feature, 0);
265a9e55 3052 if (!NILP (Vautoload_queue))
7b863bd5
JB
3053 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
3054 tem = Fmemq (feature, Vfeatures);
265a9e55 3055 if (NILP (tem))
7b863bd5 3056 Vfeatures = Fcons (feature, Vfeatures);
68732608 3057 LOADHIST_ATTACH (Fcons (Qprovide, feature));
7b863bd5
JB
3058 return feature;
3059}
3060
53d5acf5 3061DEFUN ("require", Frequire, Srequire, 1, 3, 0,
7b863bd5
JB
3062 "If feature FEATURE is not loaded, load it from FILENAME.\n\
3063If FEATURE is not a member of the list `features', then the feature\n\
3064is not loaded; so load the file FILENAME.\n\
f0c030b3 3065If FILENAME is omitted, the printname of FEATURE is used as the file name,\n\
81a81c0f
GM
3066and `load' will try to load this name appended with the suffix `.elc',\n\
3067`.el' or the unmodified name, in that order.\n\
53d5acf5 3068If the optional third argument NOERROR is non-nil,\n\
81a81c0f 3069then return nil if the file is not found instead of signaling an error.\n\
d925df90 3070Normally the return value is FEATURE.\n\
81a81c0f
GM
3071The normal messages at start and end of loading FILENAME are suppressed.")
3072 (feature, filename, noerror)
3073 Lisp_Object feature, filename, noerror;
7b863bd5
JB
3074{
3075 register Lisp_Object tem;
3076 CHECK_SYMBOL (feature, 0);
3077 tem = Fmemq (feature, Vfeatures);
093386ca 3078
68732608 3079 LOADHIST_ATTACH (Fcons (Qrequire, feature));
093386ca 3080
265a9e55 3081 if (NILP (tem))
7b863bd5
JB
3082 {
3083 int count = specpdl_ptr - specpdl;
3084
3085 /* Value saved here is to be restored into Vautoload_queue */
3086 record_unwind_protect (un_autoload, Vautoload_queue);
3087 Vautoload_queue = Qt;
3088
81a81c0f
GM
3089 tem = Fload (NILP (filename) ? Fsymbol_name (feature) : filename,
3090 noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil));
53d5acf5
RS
3091 /* If load failed entirely, return nil. */
3092 if (NILP (tem))
41857307 3093 return unbind_to (count, Qnil);
7b863bd5
JB
3094
3095 tem = Fmemq (feature, Vfeatures);
265a9e55 3096 if (NILP (tem))
7b863bd5 3097 error ("Required feature %s was not provided",
fdb5bec0 3098 XSYMBOL (feature)->name->data);
7b863bd5
JB
3099
3100 /* Once loading finishes, don't undo it. */
3101 Vautoload_queue = Qt;
3102 feature = unbind_to (count, feature);
3103 }
3104 return feature;
3105}
3106\f
b4f334f7
KH
3107/* Primitives for work of the "widget" library.
3108 In an ideal world, this section would not have been necessary.
3109 However, lisp function calls being as slow as they are, it turns
3110 out that some functions in the widget library (wid-edit.el) are the
3111 bottleneck of Widget operation. Here is their translation to C,
3112 for the sole reason of efficiency. */
3113
a5254817 3114DEFUN ("plist-member", Fplist_member, Splist_member, 2, 2, 0,
b4f334f7
KH
3115 "Return non-nil if PLIST has the property PROP.\n\
3116PLIST is a property list, which is a list of the form\n\
3117\(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
3118Unlike `plist-get', this allows you to distinguish between a missing\n\
3119property and a property with the value nil.\n\
3120The value is actually the tail of PLIST whose car is PROP.")
3121 (plist, prop)
3122 Lisp_Object plist, prop;
3123{
3124 while (CONSP (plist) && !EQ (XCAR (plist), prop))
3125 {
3126 QUIT;
3127 plist = XCDR (plist);
3128 plist = CDR (plist);
3129 }
3130 return plist;
3131}
3132
3133DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
3134 "In WIDGET, set PROPERTY to VALUE.\n\
3135The value can later be retrieved with `widget-get'.")
3136 (widget, property, value)
3137 Lisp_Object widget, property, value;
3138{
3139 CHECK_CONS (widget, 1);
3140 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
f7993597 3141 return value;
b4f334f7
KH
3142}
3143
3144DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
3145 "In WIDGET, get the value of PROPERTY.\n\
3146The value could either be specified when the widget was created, or\n\
3147later with `widget-put'.")
3148 (widget, property)
3149 Lisp_Object widget, property;
3150{
3151 Lisp_Object tmp;
3152
3153 while (1)
3154 {
3155 if (NILP (widget))
3156 return Qnil;
3157 CHECK_CONS (widget, 1);
a5254817 3158 tmp = Fplist_member (XCDR (widget), property);
b4f334f7
KH
3159 if (CONSP (tmp))
3160 {
3161 tmp = XCDR (tmp);
3162 return CAR (tmp);
3163 }
3164 tmp = XCAR (widget);
3165 if (NILP (tmp))
3166 return Qnil;
3167 widget = Fget (tmp, Qwidget_type);
3168 }
3169}
3170
3171DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
3172 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
3173ARGS are passed as extra arguments to the function.")
3174 (nargs, args)
3175 int nargs;
3176 Lisp_Object *args;
3177{
3178 /* This function can GC. */
3179 Lisp_Object newargs[3];
3180 struct gcpro gcpro1, gcpro2;
3181 Lisp_Object result;
3182
3183 newargs[0] = Fwidget_get (args[0], args[1]);
3184 newargs[1] = args[0];
3185 newargs[2] = Flist (nargs - 2, args + 2);
3186 GCPRO2 (newargs[0], newargs[2]);
3187 result = Fapply (3, newargs);
3188 UNGCPRO;
3189 return result;
3190}
3191\f
a90e80bf 3192/* base64 encode/decode functions (RFC 2045).
24c129e4
KH
3193 Based on code from GNU recode. */
3194
3195#define MIME_LINE_LENGTH 76
3196
3197#define IS_ASCII(Character) \
3198 ((Character) < 128)
3199#define IS_BASE64(Character) \
3200 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0)
9a092df0
PF
3201#define IS_BASE64_IGNORABLE(Character) \
3202 ((Character) == ' ' || (Character) == '\t' || (Character) == '\n' \
3203 || (Character) == '\f' || (Character) == '\r')
3204
3205/* Used by base64_decode_1 to retrieve a non-base64-ignorable
3206 character or return retval if there are no characters left to
3207 process. */
caff31d4
KH
3208#define READ_QUADRUPLET_BYTE(retval) \
3209 do \
3210 { \
3211 if (i == length) \
3212 { \
3213 if (nchars_return) \
3214 *nchars_return = nchars; \
3215 return (retval); \
3216 } \
3217 c = from[i++]; \
3218 } \
9a092df0 3219 while (IS_BASE64_IGNORABLE (c))
24c129e4 3220
4b2e75e6
EZ
3221/* Don't use alloca for regions larger than this, lest we overflow
3222 their stack. */
3223#define MAX_ALLOCA 16*1024
3224
24c129e4
KH
3225/* Table of characters coding the 64 values. */
3226static char base64_value_to_char[64] =
3227{
3228 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */
3229 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */
3230 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */
3231 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 30-39 */
3232 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */
3233 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */
3234 '8', '9', '+', '/' /* 60-63 */
3235};
3236
3237/* Table of base64 values for first 128 characters. */
3238static short base64_char_to_value[128] =
3239{
3240 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
3241 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
3242 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */
3243 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */
3244 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */
3245 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */
3246 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */
3247 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */
3248 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */
3249 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */
3250 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */
3251 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
3252 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
3253};
3254
3255/* The following diagram shows the logical steps by which three octets
3256 get transformed into four base64 characters.
3257
3258 .--------. .--------. .--------.
3259 |aaaaaabb| |bbbbcccc| |ccdddddd|
3260 `--------' `--------' `--------'
3261 6 2 4 4 2 6
3262 .--------+--------+--------+--------.
3263 |00aaaaaa|00bbbbbb|00cccccc|00dddddd|
3264 `--------+--------+--------+--------'
3265
3266 .--------+--------+--------+--------.
3267 |AAAAAAAA|BBBBBBBB|CCCCCCCC|DDDDDDDD|
3268 `--------+--------+--------+--------'
3269
3270 The octets are divided into 6 bit chunks, which are then encoded into
3271 base64 characters. */
3272
3273
2efdd1b9 3274static int base64_encode_1 P_ ((const char *, char *, int, int, int));
caff31d4 3275static int base64_decode_1 P_ ((const char *, char *, int, int, int *));
24c129e4
KH
3276
3277DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region,
3278 2, 3, "r",
46ac5b26 3279 "Base64-encode the region between BEG and END.\n\
15a9a50c 3280Return the length of the encoded text.\n\
24c129e4
KH
3281Optional third argument NO-LINE-BREAK means do not break long lines\n\
3282into shorter lines.")
3283 (beg, end, no_line_break)
3284 Lisp_Object beg, end, no_line_break;
3285{
3286 char *encoded;
3287 int allength, length;
3288 int ibeg, iend, encoded_length;
3289 int old_pos = PT;
3290
3291 validate_region (&beg, &end);
3292
3293 ibeg = CHAR_TO_BYTE (XFASTINT (beg));
3294 iend = CHAR_TO_BYTE (XFASTINT (end));
3295 move_gap_both (XFASTINT (beg), ibeg);
3296
3297 /* We need to allocate enough room for encoding the text.
3298 We need 33 1/3% more space, plus a newline every 76
3299 characters, and then we round up. */
3300 length = iend - ibeg;
3301 allength = length + length/3 + 1;
3302 allength += allength / MIME_LINE_LENGTH + 1 + 6;
3303
4b2e75e6
EZ
3304 if (allength <= MAX_ALLOCA)
3305 encoded = (char *) alloca (allength);
3306 else
3307 encoded = (char *) xmalloc (allength);
24c129e4 3308 encoded_length = base64_encode_1 (BYTE_POS_ADDR (ibeg), encoded, length,
2efdd1b9
KH
3309 NILP (no_line_break),
3310 !NILP (current_buffer->enable_multibyte_characters));
24c129e4
KH
3311 if (encoded_length > allength)
3312 abort ();
3313
2efdd1b9
KH
3314 if (encoded_length < 0)
3315 {
3316 /* The encoding wasn't possible. */
3317 if (length > MAX_ALLOCA)
3318 xfree (encoded);
a90e80bf 3319 error ("Multibyte character in data for base64 encoding");
2efdd1b9
KH
3320 }
3321
24c129e4
KH
3322 /* Now we have encoded the region, so we insert the new contents
3323 and delete the old. (Insert first in order to preserve markers.) */
8b835738 3324 SET_PT_BOTH (XFASTINT (beg), ibeg);
24c129e4 3325 insert (encoded, encoded_length);
4b2e75e6 3326 if (allength > MAX_ALLOCA)
8c217645 3327 xfree (encoded);
24c129e4
KH
3328 del_range_byte (ibeg + encoded_length, iend + encoded_length, 1);
3329
3330 /* If point was outside of the region, restore it exactly; else just
3331 move to the beginning of the region. */
3332 if (old_pos >= XFASTINT (end))
3333 old_pos += encoded_length - (XFASTINT (end) - XFASTINT (beg));
8b835738
AS
3334 else if (old_pos > XFASTINT (beg))
3335 old_pos = XFASTINT (beg);
24c129e4
KH
3336 SET_PT (old_pos);
3337
3338 /* We return the length of the encoded text. */
3339 return make_number (encoded_length);
3340}
3341
3342DEFUN ("base64-encode-string", Fbase64_encode_string, Sbase64_encode_string,
c22554ac
KH
3343 1, 2, 0,
3344 "Base64-encode STRING and return the result.\n\
3345Optional second argument NO-LINE-BREAK means do not break long lines\n\
3346into shorter lines.")
3347 (string, no_line_break)
915b8312 3348 Lisp_Object string, no_line_break;
24c129e4
KH
3349{
3350 int allength, length, encoded_length;
3351 char *encoded;
4b2e75e6 3352 Lisp_Object encoded_string;
24c129e4
KH
3353
3354 CHECK_STRING (string, 1);
3355
7f8a0840
KH
3356 /* We need to allocate enough room for encoding the text.
3357 We need 33 1/3% more space, plus a newline every 76
3358 characters, and then we round up. */
24c129e4 3359 length = STRING_BYTES (XSTRING (string));
7f8a0840
KH
3360 allength = length + length/3 + 1;
3361 allength += allength / MIME_LINE_LENGTH + 1 + 6;
24c129e4
KH
3362
3363 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3364 if (allength <= MAX_ALLOCA)
3365 encoded = (char *) alloca (allength);
3366 else
3367 encoded = (char *) xmalloc (allength);
24c129e4
KH
3368
3369 encoded_length = base64_encode_1 (XSTRING (string)->data,
2efdd1b9
KH
3370 encoded, length, NILP (no_line_break),
3371 STRING_MULTIBYTE (string));
24c129e4
KH
3372 if (encoded_length > allength)
3373 abort ();
3374
2efdd1b9
KH
3375 if (encoded_length < 0)
3376 {
3377 /* The encoding wasn't possible. */
3378 if (length > MAX_ALLOCA)
3379 xfree (encoded);
a90e80bf 3380 error ("Multibyte character in data for base64 encoding");
2efdd1b9
KH
3381 }
3382
4b2e75e6
EZ
3383 encoded_string = make_unibyte_string (encoded, encoded_length);
3384 if (allength > MAX_ALLOCA)
8c217645 3385 xfree (encoded);
4b2e75e6
EZ
3386
3387 return encoded_string;
24c129e4
KH
3388}
3389
3390static int
2efdd1b9 3391base64_encode_1 (from, to, length, line_break, multibyte)
24c129e4
KH
3392 const char *from;
3393 char *to;
3394 int length;
3395 int line_break;
2efdd1b9 3396 int multibyte;
24c129e4
KH
3397{
3398 int counter = 0, i = 0;
3399 char *e = to;
844eb643 3400 int c;
24c129e4 3401 unsigned int value;
2efdd1b9 3402 int bytes;
24c129e4
KH
3403
3404 while (i < length)
3405 {
2efdd1b9
KH
3406 if (multibyte)
3407 {
3408 c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
caff31d4 3409 if (c >= 256)
2efdd1b9 3410 return -1;
caff31d4 3411 i += bytes;
2efdd1b9
KH
3412 }
3413 else
3414 c = from[i++];
24c129e4
KH
3415
3416 /* Wrap line every 76 characters. */
3417
3418 if (line_break)
3419 {
3420 if (counter < MIME_LINE_LENGTH / 4)
3421 counter++;
3422 else
3423 {
3424 *e++ = '\n';
3425 counter = 1;
3426 }
3427 }
3428
3429 /* Process first byte of a triplet. */
3430
3431 *e++ = base64_value_to_char[0x3f & c >> 2];
3432 value = (0x03 & c) << 4;
3433
3434 /* Process second byte of a triplet. */
3435
3436 if (i == length)
3437 {
3438 *e++ = base64_value_to_char[value];
3439 *e++ = '=';
3440 *e++ = '=';
3441 break;
3442 }
3443
2efdd1b9
KH
3444 if (multibyte)
3445 {
3446 c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
caff31d4 3447 if (c >= 256)
844eb643 3448 return -1;
caff31d4 3449 i += bytes;
2efdd1b9
KH
3450 }
3451 else
3452 c = from[i++];
24c129e4
KH
3453
3454 *e++ = base64_value_to_char[value | (0x0f & c >> 4)];
3455 value = (0x0f & c) << 2;
3456
3457 /* Process third byte of a triplet. */
3458
3459 if (i == length)
3460 {
3461 *e++ = base64_value_to_char[value];
3462 *e++ = '=';
3463 break;
3464 }
3465
2efdd1b9
KH
3466 if (multibyte)
3467 {
3468 c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
caff31d4 3469 if (c >= 256)
844eb643 3470 return -1;
caff31d4 3471 i += bytes;
2efdd1b9
KH
3472 }
3473 else
3474 c = from[i++];
24c129e4
KH
3475
3476 *e++ = base64_value_to_char[value | (0x03 & c >> 6)];
3477 *e++ = base64_value_to_char[0x3f & c];
3478 }
3479
24c129e4
KH
3480 return e - to;
3481}
3482
3483
3484DEFUN ("base64-decode-region", Fbase64_decode_region, Sbase64_decode_region,
3485 2, 2, "r",
46ac5b26 3486 "Base64-decode the region between BEG and END.\n\
15a9a50c 3487Return the length of the decoded text.\n\
3d6c79c5 3488If the region can't be decoded, signal an error and don't modify the buffer.")
24c129e4
KH
3489 (beg, end)
3490 Lisp_Object beg, end;
3491{
caff31d4 3492 int ibeg, iend, length, allength;
24c129e4
KH
3493 char *decoded;
3494 int old_pos = PT;
3495 int decoded_length;
9b703a38 3496 int inserted_chars;
caff31d4 3497 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
24c129e4
KH
3498
3499 validate_region (&beg, &end);
3500
3501 ibeg = CHAR_TO_BYTE (XFASTINT (beg));
3502 iend = CHAR_TO_BYTE (XFASTINT (end));
3503
3504 length = iend - ibeg;
caff31d4
KH
3505
3506 /* We need to allocate enough room for decoding the text. If we are
3507 working on a multibyte buffer, each decoded code may occupy at
3508 most two bytes. */
3509 allength = multibyte ? length * 2 : length;
3510 if (allength <= MAX_ALLOCA)
3511 decoded = (char *) alloca (allength);
4b2e75e6 3512 else
caff31d4 3513 decoded = (char *) xmalloc (allength);
24c129e4
KH
3514
3515 move_gap_both (XFASTINT (beg), ibeg);
caff31d4
KH
3516 decoded_length = base64_decode_1 (BYTE_POS_ADDR (ibeg), decoded, length,
3517 multibyte, &inserted_chars);
3518 if (decoded_length > allength)
24c129e4
KH
3519 abort ();
3520
3521 if (decoded_length < 0)
8c217645
KH
3522 {
3523 /* The decoding wasn't possible. */
caff31d4 3524 if (allength > MAX_ALLOCA)
8c217645 3525 xfree (decoded);
a90e80bf 3526 error ("Invalid base64 data");
8c217645 3527 }
24c129e4
KH
3528
3529 /* Now we have decoded the region, so we insert the new contents
3530 and delete the old. (Insert first in order to preserve markers.) */
59f953a2 3531 TEMP_SET_PT_BOTH (XFASTINT (beg), ibeg);
2efdd1b9 3532 insert_1_both (decoded, inserted_chars, decoded_length, 0, 1, 0);
caff31d4 3533 if (allength > MAX_ALLOCA)
8c217645 3534 xfree (decoded);
2efdd1b9
KH
3535 /* Delete the original text. */
3536 del_range_both (PT, PT_BYTE, XFASTINT (end) + inserted_chars,
3537 iend + decoded_length, 1);
24c129e4
KH
3538
3539 /* If point was outside of the region, restore it exactly; else just
3540 move to the beginning of the region. */
3541 if (old_pos >= XFASTINT (end))
9b703a38
KH
3542 old_pos += inserted_chars - (XFASTINT (end) - XFASTINT (beg));
3543 else if (old_pos > XFASTINT (beg))
3544 old_pos = XFASTINT (beg);
e52ad9c9 3545 SET_PT (old_pos > ZV ? ZV : old_pos);
24c129e4 3546
9b703a38 3547 return make_number (inserted_chars);
24c129e4
KH
3548}
3549
3550DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
3551 1, 1, 0,
3d6c79c5
GM
3552 "Base64-decode STRING and return the result.")
3553 (string)
24c129e4
KH
3554 Lisp_Object string;
3555{
3556 char *decoded;
3557 int length, decoded_length;
4b2e75e6 3558 Lisp_Object decoded_string;
24c129e4
KH
3559
3560 CHECK_STRING (string, 1);
3561
3562 length = STRING_BYTES (XSTRING (string));
3563 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3564 if (length <= MAX_ALLOCA)
3565 decoded = (char *) alloca (length);
3566 else
3567 decoded = (char *) xmalloc (length);
24c129e4 3568
8ec118cd 3569 /* The decoded result should be unibyte. */
caff31d4 3570 decoded_length = base64_decode_1 (XSTRING (string)->data, decoded, length,
8ec118cd 3571 0, NULL);
24c129e4
KH
3572 if (decoded_length > length)
3573 abort ();
3d6c79c5 3574 else if (decoded_length >= 0)
2efdd1b9 3575 decoded_string = make_unibyte_string (decoded, decoded_length);
3d6c79c5
GM
3576 else
3577 decoded_string = Qnil;
24c129e4 3578
4b2e75e6 3579 if (length > MAX_ALLOCA)
8c217645 3580 xfree (decoded);
3d6c79c5 3581 if (!STRINGP (decoded_string))
a90e80bf 3582 error ("Invalid base64 data");
4b2e75e6
EZ
3583
3584 return decoded_string;
24c129e4
KH
3585}
3586
caff31d4
KH
3587/* Base64-decode the data at FROM of LENGHT bytes into TO. If
3588 MULTIBYTE is nonzero, the decoded result should be in multibyte
3589 form. If NCHARS_RETRUN is not NULL, store the number of produced
3590 characters in *NCHARS_RETURN. */
3591
24c129e4 3592static int
caff31d4 3593base64_decode_1 (from, to, length, multibyte, nchars_return)
24c129e4
KH
3594 const char *from;
3595 char *to;
3596 int length;
caff31d4
KH
3597 int multibyte;
3598 int *nchars_return;
24c129e4 3599{
9a092df0 3600 int i = 0;
24c129e4
KH
3601 char *e = to;
3602 unsigned char c;
3603 unsigned long value;
caff31d4 3604 int nchars = 0;
24c129e4 3605
9a092df0 3606 while (1)
24c129e4 3607 {
9a092df0 3608 /* Process first byte of a quadruplet. */
24c129e4 3609
9a092df0 3610 READ_QUADRUPLET_BYTE (e-to);
24c129e4
KH
3611
3612 if (!IS_BASE64 (c))
3613 return -1;
3614 value = base64_char_to_value[c] << 18;
3615
3616 /* Process second byte of a quadruplet. */
3617
9a092df0 3618 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3619
3620 if (!IS_BASE64 (c))
3621 return -1;
3622 value |= base64_char_to_value[c] << 12;
3623
caff31d4
KH
3624 c = (unsigned char) (value >> 16);
3625 if (multibyte)
3626 e += CHAR_STRING (c, e);
3627 else
3628 *e++ = c;
3629 nchars++;
24c129e4
KH
3630
3631 /* Process third byte of a quadruplet. */
59f953a2 3632
9a092df0 3633 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3634
3635 if (c == '=')
3636 {
9a092df0 3637 READ_QUADRUPLET_BYTE (-1);
59f953a2 3638
24c129e4
KH
3639 if (c != '=')
3640 return -1;
3641 continue;
3642 }
3643
3644 if (!IS_BASE64 (c))
3645 return -1;
3646 value |= base64_char_to_value[c] << 6;
3647
caff31d4
KH
3648 c = (unsigned char) (0xff & value >> 8);
3649 if (multibyte)
3650 e += CHAR_STRING (c, e);
3651 else
3652 *e++ = c;
3653 nchars++;
24c129e4
KH
3654
3655 /* Process fourth byte of a quadruplet. */
3656
9a092df0 3657 READ_QUADRUPLET_BYTE (-1);
24c129e4
KH
3658
3659 if (c == '=')
3660 continue;
3661
3662 if (!IS_BASE64 (c))
3663 return -1;
3664 value |= base64_char_to_value[c];
3665
caff31d4
KH
3666 c = (unsigned char) (0xff & value);
3667 if (multibyte)
3668 e += CHAR_STRING (c, e);
3669 else
3670 *e++ = c;
3671 nchars++;
24c129e4 3672 }
24c129e4 3673}
d80c6c11
GM
3674
3675
3676\f
3677/***********************************************************************
3678 ***** *****
3679 ***** Hash Tables *****
3680 ***** *****
3681 ***********************************************************************/
3682
3683/* Implemented by gerd@gnu.org. This hash table implementation was
3684 inspired by CMUCL hash tables. */
3685
3686/* Ideas:
3687
3688 1. For small tables, association lists are probably faster than
3689 hash tables because they have lower overhead.
3690
3691 For uses of hash tables where the O(1) behavior of table
3692 operations is not a requirement, it might therefore be a good idea
3693 not to hash. Instead, we could just do a linear search in the
3694 key_and_value vector of the hash table. This could be done
3695 if a `:linear-search t' argument is given to make-hash-table. */
3696
3697
d80c6c11
GM
3698/* Value is the key part of entry IDX in hash table H. */
3699
3700#define HASH_KEY(H, IDX) AREF ((H)->key_and_value, 2 * (IDX))
3701
3702/* Value is the value part of entry IDX in hash table H. */
3703
3704#define HASH_VALUE(H, IDX) AREF ((H)->key_and_value, 2 * (IDX) + 1)
3705
3706/* Value is the index of the next entry following the one at IDX
3707 in hash table H. */
3708
3709#define HASH_NEXT(H, IDX) AREF ((H)->next, (IDX))
3710
3711/* Value is the hash code computed for entry IDX in hash table H. */
3712
3713#define HASH_HASH(H, IDX) AREF ((H)->hash, (IDX))
3714
3715/* Value is the index of the element in hash table H that is the
3716 start of the collision list at index IDX in the index vector of H. */
3717
3718#define HASH_INDEX(H, IDX) AREF ((H)->index, (IDX))
3719
3720/* Value is the size of hash table H. */
3721
3722#define HASH_TABLE_SIZE(H) XVECTOR ((H)->next)->size
3723
3724/* The list of all weak hash tables. Don't staticpro this one. */
3725
3726Lisp_Object Vweak_hash_tables;
3727
3728/* Various symbols. */
3729
f899c503 3730Lisp_Object Qhash_table_p, Qeq, Qeql, Qequal, Qkey, Qvalue;
ee0403b3 3731Lisp_Object QCtest, QCsize, QCrehash_size, QCrehash_threshold, QCweakness;
ec504e6f 3732Lisp_Object Qhash_table_test, Qkey_or_value, Qkey_and_value;
d80c6c11
GM
3733
3734/* Function prototypes. */
3735
3736static struct Lisp_Hash_Table *check_hash_table P_ ((Lisp_Object));
d80c6c11 3737static int get_key_arg P_ ((Lisp_Object, int, Lisp_Object *, char *));
d80c6c11 3738static void maybe_resize_hash_table P_ ((struct Lisp_Hash_Table *));
d80c6c11
GM
3739static int cmpfn_eql P_ ((struct Lisp_Hash_Table *, Lisp_Object, unsigned,
3740 Lisp_Object, unsigned));
3741static int cmpfn_equal P_ ((struct Lisp_Hash_Table *, Lisp_Object, unsigned,
3742 Lisp_Object, unsigned));
3743static int cmpfn_user_defined P_ ((struct Lisp_Hash_Table *, Lisp_Object,
3744 unsigned, Lisp_Object, unsigned));
3745static unsigned hashfn_eq P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3746static unsigned hashfn_eql P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3747static unsigned hashfn_equal P_ ((struct Lisp_Hash_Table *, Lisp_Object));
3748static unsigned hashfn_user_defined P_ ((struct Lisp_Hash_Table *,
3749 Lisp_Object));
3750static unsigned sxhash_string P_ ((unsigned char *, int));
3751static unsigned sxhash_list P_ ((Lisp_Object, int));
3752static unsigned sxhash_vector P_ ((Lisp_Object, int));
3753static unsigned sxhash_bool_vector P_ ((Lisp_Object));
a0b581cc 3754static int sweep_weak_table P_ ((struct Lisp_Hash_Table *, int));
d80c6c11
GM
3755
3756
3757\f
3758/***********************************************************************
3759 Utilities
3760 ***********************************************************************/
3761
3762/* If OBJ is a Lisp hash table, return a pointer to its struct
3763 Lisp_Hash_Table. Otherwise, signal an error. */
3764
3765static struct Lisp_Hash_Table *
3766check_hash_table (obj)
3767 Lisp_Object obj;
3768{
3769 CHECK_HASH_TABLE (obj, 0);
3770 return XHASH_TABLE (obj);
3771}
3772
3773
3774/* Value is the next integer I >= N, N >= 0 which is "almost" a prime
3775 number. */
3776
6e509e80 3777int
d80c6c11
GM
3778next_almost_prime (n)
3779 int n;
3780{
3781 if (n % 2 == 0)
3782 n += 1;
3783 if (n % 3 == 0)
3784 n += 2;
3785 if (n % 7 == 0)
3786 n += 4;
3787 return n;
3788}
3789
3790
3791/* Find KEY in ARGS which has size NARGS. Don't consider indices for
3792 which USED[I] is non-zero. If found at index I in ARGS, set
3793 USED[I] and USED[I + 1] to 1, and return I + 1. Otherwise return
3794 -1. This function is used to extract a keyword/argument pair from
3795 a DEFUN parameter list. */
3796
3797static int
3798get_key_arg (key, nargs, args, used)
3799 Lisp_Object key;
3800 int nargs;
3801 Lisp_Object *args;
3802 char *used;
3803{
3804 int i;
59f953a2 3805
d80c6c11
GM
3806 for (i = 0; i < nargs - 1; ++i)
3807 if (!used[i] && EQ (args[i], key))
3808 break;
59f953a2 3809
d80c6c11
GM
3810 if (i >= nargs - 1)
3811 i = -1;
3812 else
3813 {
3814 used[i++] = 1;
3815 used[i] = 1;
3816 }
59f953a2 3817
d80c6c11
GM
3818 return i;
3819}
3820
3821
3822/* Return a Lisp vector which has the same contents as VEC but has
3823 size NEW_SIZE, NEW_SIZE >= VEC->size. Entries in the resulting
3824 vector that are not copied from VEC are set to INIT. */
3825
fa7dad5b 3826Lisp_Object
d80c6c11
GM
3827larger_vector (vec, new_size, init)
3828 Lisp_Object vec;
3829 int new_size;
3830 Lisp_Object init;
3831{
3832 struct Lisp_Vector *v;
3833 int i, old_size;
3834
3835 xassert (VECTORP (vec));
3836 old_size = XVECTOR (vec)->size;
3837 xassert (new_size >= old_size);
3838
b3660ef6 3839 v = allocate_vector (new_size);
d80c6c11
GM
3840 bcopy (XVECTOR (vec)->contents, v->contents,
3841 old_size * sizeof *v->contents);
3842 for (i = old_size; i < new_size; ++i)
3843 v->contents[i] = init;
3844 XSETVECTOR (vec, v);
3845 return vec;
3846}
3847
3848
3849/***********************************************************************
3850 Low-level Functions
3851 ***********************************************************************/
3852
d80c6c11
GM
3853/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
3854 HASH2 in hash table H using `eql'. Value is non-zero if KEY1 and
3855 KEY2 are the same. */
3856
3857static int
3858cmpfn_eql (h, key1, hash1, key2, hash2)
3859 struct Lisp_Hash_Table *h;
3860 Lisp_Object key1, key2;
3861 unsigned hash1, hash2;
3862{
2e5da676
GM
3863 return (FLOATP (key1)
3864 && FLOATP (key2)
e84b1dea 3865 && XFLOAT_DATA (key1) == XFLOAT_DATA (key2));
d80c6c11
GM
3866}
3867
3868
3869/* Compare KEY1 which has hash code HASH1 and KEY2 with hash code
3870 HASH2 in hash table H using `equal'. Value is non-zero if KEY1 and
3871 KEY2 are the same. */
3872
3873static int
3874cmpfn_equal (h, key1, hash1, key2, hash2)
3875 struct Lisp_Hash_Table *h;
3876 Lisp_Object key1, key2;
3877 unsigned hash1, hash2;
3878{
2e5da676 3879 return hash1 == hash2 && !NILP (Fequal (key1, key2));
d80c6c11
GM
3880}
3881
59f953a2 3882
d80c6c11
GM
3883/* Compare KEY1 which has hash code HASH1, and KEY2 with hash code
3884 HASH2 in hash table H using H->user_cmp_function. Value is non-zero
3885 if KEY1 and KEY2 are the same. */
3886
3887static int
3888cmpfn_user_defined (h, key1, hash1, key2, hash2)
3889 struct Lisp_Hash_Table *h;
3890 Lisp_Object key1, key2;
3891 unsigned hash1, hash2;
3892{
3893 if (hash1 == hash2)
3894 {
3895 Lisp_Object args[3];
59f953a2 3896
d80c6c11
GM
3897 args[0] = h->user_cmp_function;
3898 args[1] = key1;
3899 args[2] = key2;
3900 return !NILP (Ffuncall (3, args));
3901 }
3902 else
3903 return 0;
3904}
3905
3906
3907/* Value is a hash code for KEY for use in hash table H which uses
3908 `eq' to compare keys. The hash code returned is guaranteed to fit
3909 in a Lisp integer. */
3910
3911static unsigned
3912hashfn_eq (h, key)
3913 struct Lisp_Hash_Table *h;
3914 Lisp_Object key;
3915{
cf681889
GM
3916 unsigned hash = XUINT (key) ^ XGCTYPE (key);
3917 xassert ((hash & ~VALMASK) == 0);
3918 return hash;
d80c6c11
GM
3919}
3920
3921
3922/* Value is a hash code for KEY for use in hash table H which uses
3923 `eql' to compare keys. The hash code returned is guaranteed to fit
3924 in a Lisp integer. */
3925
3926static unsigned
3927hashfn_eql (h, key)
3928 struct Lisp_Hash_Table *h;
3929 Lisp_Object key;
3930{
cf681889
GM
3931 unsigned hash;
3932 if (FLOATP (key))
3933 hash = sxhash (key, 0);
d80c6c11 3934 else
cf681889
GM
3935 hash = XUINT (key) ^ XGCTYPE (key);
3936 xassert ((hash & ~VALMASK) == 0);
3937 return hash;
d80c6c11
GM
3938}
3939
3940
3941/* Value is a hash code for KEY for use in hash table H which uses
3942 `equal' to compare keys. The hash code returned is guaranteed to fit
3943 in a Lisp integer. */
3944
3945static unsigned
3946hashfn_equal (h, key)
3947 struct Lisp_Hash_Table *h;
3948 Lisp_Object key;
3949{
cf681889
GM
3950 unsigned hash = sxhash (key, 0);
3951 xassert ((hash & ~VALMASK) == 0);
3952 return hash;
d80c6c11
GM
3953}
3954
3955
3956/* Value is a hash code for KEY for use in hash table H which uses as
3957 user-defined function to compare keys. The hash code returned is
3958 guaranteed to fit in a Lisp integer. */
3959
3960static unsigned
3961hashfn_user_defined (h, key)
3962 struct Lisp_Hash_Table *h;
3963 Lisp_Object key;
3964{
3965 Lisp_Object args[2], hash;
59f953a2 3966
d80c6c11
GM
3967 args[0] = h->user_hash_function;
3968 args[1] = key;
3969 hash = Ffuncall (2, args);
3970 if (!INTEGERP (hash))
3971 Fsignal (Qerror,
1fd4c450 3972 list2 (build_string ("Invalid hash code returned from \
d80c6c11
GM
3973user-supplied hash function"),
3974 hash));
3975 return XUINT (hash);
3976}
3977
3978
3979/* Create and initialize a new hash table.
3980
3981 TEST specifies the test the hash table will use to compare keys.
3982 It must be either one of the predefined tests `eq', `eql' or
3983 `equal' or a symbol denoting a user-defined test named TEST with
3984 test and hash functions USER_TEST and USER_HASH.
59f953a2 3985
1fd4c450 3986 Give the table initial capacity SIZE, SIZE >= 0, an integer.
d80c6c11
GM
3987
3988 If REHASH_SIZE is an integer, it must be > 0, and this hash table's
3989 new size when it becomes full is computed by adding REHASH_SIZE to
3990 its old size. If REHASH_SIZE is a float, it must be > 1.0, and the
3991 table's new size is computed by multiplying its old size with
3992 REHASH_SIZE.
3993
3994 REHASH_THRESHOLD must be a float <= 1.0, and > 0. The table will
3995 be resized when the ratio of (number of entries in the table) /
3996 (table size) is >= REHASH_THRESHOLD.
3997
3998 WEAK specifies the weakness of the table. If non-nil, it must be
ec504e6f 3999 one of the symbols `key', `value', `key-or-value', or `key-and-value'. */
d80c6c11
GM
4000
4001Lisp_Object
4002make_hash_table (test, size, rehash_size, rehash_threshold, weak,
4003 user_test, user_hash)
4004 Lisp_Object test, size, rehash_size, rehash_threshold, weak;
4005 Lisp_Object user_test, user_hash;
4006{
4007 struct Lisp_Hash_Table *h;
d80c6c11 4008 Lisp_Object table;
b3660ef6 4009 int index_size, i, sz;
d80c6c11
GM
4010
4011 /* Preconditions. */
4012 xassert (SYMBOLP (test));
1fd4c450 4013 xassert (INTEGERP (size) && XINT (size) >= 0);
d80c6c11
GM
4014 xassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0)
4015 || (FLOATP (rehash_size) && XFLOATINT (rehash_size) > 1.0));
4016 xassert (FLOATP (rehash_threshold)
4017 && XFLOATINT (rehash_threshold) > 0
4018 && XFLOATINT (rehash_threshold) <= 1.0);
4019
1fd4c450
GM
4020 if (XFASTINT (size) == 0)
4021 size = make_number (1);
4022
b3660ef6
GM
4023 /* Allocate a table and initialize it. */
4024 h = allocate_hash_table ();
d80c6c11
GM
4025
4026 /* Initialize hash table slots. */
4027 sz = XFASTINT (size);
59f953a2 4028
d80c6c11
GM
4029 h->test = test;
4030 if (EQ (test, Qeql))
4031 {
4032 h->cmpfn = cmpfn_eql;
4033 h->hashfn = hashfn_eql;
4034 }
4035 else if (EQ (test, Qeq))
4036 {
2e5da676 4037 h->cmpfn = NULL;
d80c6c11
GM
4038 h->hashfn = hashfn_eq;
4039 }
4040 else if (EQ (test, Qequal))
4041 {
4042 h->cmpfn = cmpfn_equal;
4043 h->hashfn = hashfn_equal;
4044 }
4045 else
4046 {
4047 h->user_cmp_function = user_test;
4048 h->user_hash_function = user_hash;
4049 h->cmpfn = cmpfn_user_defined;
4050 h->hashfn = hashfn_user_defined;
4051 }
59f953a2 4052
d80c6c11
GM
4053 h->weak = weak;
4054 h->rehash_threshold = rehash_threshold;
4055 h->rehash_size = rehash_size;
4056 h->count = make_number (0);
4057 h->key_and_value = Fmake_vector (make_number (2 * sz), Qnil);
4058 h->hash = Fmake_vector (size, Qnil);
4059 h->next = Fmake_vector (size, Qnil);
0690cb37
DL
4060 /* Cast to int here avoids losing with gcc 2.95 on Tru64/Alpha... */
4061 index_size = next_almost_prime ((int) (sz / XFLOATINT (rehash_threshold)));
d80c6c11
GM
4062 h->index = Fmake_vector (make_number (index_size), Qnil);
4063
4064 /* Set up the free list. */
4065 for (i = 0; i < sz - 1; ++i)
4066 HASH_NEXT (h, i) = make_number (i + 1);
4067 h->next_free = make_number (0);
4068
4069 XSET_HASH_TABLE (table, h);
4070 xassert (HASH_TABLE_P (table));
4071 xassert (XHASH_TABLE (table) == h);
4072
4073 /* Maybe add this hash table to the list of all weak hash tables. */
4074 if (NILP (h->weak))
4075 h->next_weak = Qnil;
4076 else
4077 {
4078 h->next_weak = Vweak_hash_tables;
4079 Vweak_hash_tables = table;
4080 }
4081
4082 return table;
4083}
4084
4085
f899c503
GM
4086/* Return a copy of hash table H1. Keys and values are not copied,
4087 only the table itself is. */
4088
4089Lisp_Object
4090copy_hash_table (h1)
4091 struct Lisp_Hash_Table *h1;
4092{
4093 Lisp_Object table;
4094 struct Lisp_Hash_Table *h2;
4095 struct Lisp_Vector *v, *next;
59f953a2 4096
b3660ef6 4097 h2 = allocate_hash_table ();
f899c503
GM
4098 next = h2->vec_next;
4099 bcopy (h1, h2, sizeof *h2);
4100 h2->vec_next = next;
4101 h2->key_and_value = Fcopy_sequence (h1->key_and_value);
4102 h2->hash = Fcopy_sequence (h1->hash);
4103 h2->next = Fcopy_sequence (h1->next);
4104 h2->index = Fcopy_sequence (h1->index);
4105 XSET_HASH_TABLE (table, h2);
4106
4107 /* Maybe add this hash table to the list of all weak hash tables. */
4108 if (!NILP (h2->weak))
4109 {
4110 h2->next_weak = Vweak_hash_tables;
4111 Vweak_hash_tables = table;
4112 }
4113
4114 return table;
4115}
4116
4117
d80c6c11
GM
4118/* Resize hash table H if it's too full. If H cannot be resized
4119 because it's already too large, throw an error. */
4120
4121static INLINE void
4122maybe_resize_hash_table (h)
4123 struct Lisp_Hash_Table *h;
4124{
4125 if (NILP (h->next_free))
4126 {
4127 int old_size = HASH_TABLE_SIZE (h);
4128 int i, new_size, index_size;
59f953a2 4129
d80c6c11
GM
4130 if (INTEGERP (h->rehash_size))
4131 new_size = old_size + XFASTINT (h->rehash_size);
4132 else
4133 new_size = old_size * XFLOATINT (h->rehash_size);
0d6ba42e 4134 new_size = max (old_size + 1, new_size);
0690cb37
DL
4135 index_size = next_almost_prime ((int)
4136 (new_size
4137 / XFLOATINT (h->rehash_threshold)));
d80c6c11
GM
4138 if (max (index_size, 2 * new_size) & ~VALMASK)
4139 error ("Hash table too large to resize");
4140
4141 h->key_and_value = larger_vector (h->key_and_value, 2 * new_size, Qnil);
4142 h->next = larger_vector (h->next, new_size, Qnil);
4143 h->hash = larger_vector (h->hash, new_size, Qnil);
4144 h->index = Fmake_vector (make_number (index_size), Qnil);
4145
4146 /* Update the free list. Do it so that new entries are added at
4147 the end of the free list. This makes some operations like
4148 maphash faster. */
4149 for (i = old_size; i < new_size - 1; ++i)
4150 HASH_NEXT (h, i) = make_number (i + 1);
59f953a2 4151
d80c6c11
GM
4152 if (!NILP (h->next_free))
4153 {
4154 Lisp_Object last, next;
59f953a2 4155
d80c6c11
GM
4156 last = h->next_free;
4157 while (next = HASH_NEXT (h, XFASTINT (last)),
4158 !NILP (next))
4159 last = next;
59f953a2 4160
d80c6c11
GM
4161 HASH_NEXT (h, XFASTINT (last)) = make_number (old_size);
4162 }
4163 else
4164 XSETFASTINT (h->next_free, old_size);
4165
4166 /* Rehash. */
4167 for (i = 0; i < old_size; ++i)
4168 if (!NILP (HASH_HASH (h, i)))
4169 {
4170 unsigned hash_code = XUINT (HASH_HASH (h, i));
4171 int start_of_bucket = hash_code % XVECTOR (h->index)->size;
4172 HASH_NEXT (h, i) = HASH_INDEX (h, start_of_bucket);
4173 HASH_INDEX (h, start_of_bucket) = make_number (i);
4174 }
59f953a2 4175 }
d80c6c11
GM
4176}
4177
4178
4179/* Lookup KEY in hash table H. If HASH is non-null, return in *HASH
4180 the hash code of KEY. Value is the index of the entry in H
4181 matching KEY, or -1 if not found. */
4182
4183int
4184hash_lookup (h, key, hash)
4185 struct Lisp_Hash_Table *h;
4186 Lisp_Object key;
4187 unsigned *hash;
4188{
4189 unsigned hash_code;
4190 int start_of_bucket;
4191 Lisp_Object idx;
4192
4193 hash_code = h->hashfn (h, key);
4194 if (hash)
4195 *hash = hash_code;
59f953a2 4196
d80c6c11
GM
4197 start_of_bucket = hash_code % XVECTOR (h->index)->size;
4198 idx = HASH_INDEX (h, start_of_bucket);
4199
f5c75033 4200 /* We need not gcpro idx since it's either an integer or nil. */
d80c6c11
GM
4201 while (!NILP (idx))
4202 {
4203 int i = XFASTINT (idx);
2e5da676
GM
4204 if (EQ (key, HASH_KEY (h, i))
4205 || (h->cmpfn
4206 && h->cmpfn (h, key, hash_code,
7c752c80 4207 HASH_KEY (h, i), XUINT (HASH_HASH (h, i)))))
d80c6c11
GM
4208 break;
4209 idx = HASH_NEXT (h, i);
4210 }
4211
4212 return NILP (idx) ? -1 : XFASTINT (idx);
4213}
4214
4215
4216/* Put an entry into hash table H that associates KEY with VALUE.
64a5094a
KH
4217 HASH is a previously computed hash code of KEY.
4218 Value is the index of the entry in H matching KEY. */
d80c6c11 4219
64a5094a 4220int
d80c6c11
GM
4221hash_put (h, key, value, hash)
4222 struct Lisp_Hash_Table *h;
4223 Lisp_Object key, value;
4224 unsigned hash;
4225{
4226 int start_of_bucket, i;
4227
4228 xassert ((hash & ~VALMASK) == 0);
4229
4230 /* Increment count after resizing because resizing may fail. */
4231 maybe_resize_hash_table (h);
4232 h->count = make_number (XFASTINT (h->count) + 1);
59f953a2 4233
d80c6c11
GM
4234 /* Store key/value in the key_and_value vector. */
4235 i = XFASTINT (h->next_free);
4236 h->next_free = HASH_NEXT (h, i);
4237 HASH_KEY (h, i) = key;
4238 HASH_VALUE (h, i) = value;
4239
4240 /* Remember its hash code. */
4241 HASH_HASH (h, i) = make_number (hash);
4242
4243 /* Add new entry to its collision chain. */
4244 start_of_bucket = hash % XVECTOR (h->index)->size;
4245 HASH_NEXT (h, i) = HASH_INDEX (h, start_of_bucket);
4246 HASH_INDEX (h, start_of_bucket) = make_number (i);
64a5094a 4247 return i;
d80c6c11
GM
4248}
4249
4250
4251/* Remove the entry matching KEY from hash table H, if there is one. */
4252
4253void
4254hash_remove (h, key)
4255 struct Lisp_Hash_Table *h;
4256 Lisp_Object key;
4257{
4258 unsigned hash_code;
4259 int start_of_bucket;
4260 Lisp_Object idx, prev;
4261
4262 hash_code = h->hashfn (h, key);
4263 start_of_bucket = hash_code % XVECTOR (h->index)->size;
4264 idx = HASH_INDEX (h, start_of_bucket);
4265 prev = Qnil;
4266
f5c75033 4267 /* We need not gcpro idx, prev since they're either integers or nil. */
d80c6c11
GM
4268 while (!NILP (idx))
4269 {
4270 int i = XFASTINT (idx);
4271
2e5da676
GM
4272 if (EQ (key, HASH_KEY (h, i))
4273 || (h->cmpfn
4274 && h->cmpfn (h, key, hash_code,
7c752c80 4275 HASH_KEY (h, i), XUINT (HASH_HASH (h, i)))))
d80c6c11
GM
4276 {
4277 /* Take entry out of collision chain. */
4278 if (NILP (prev))
4279 HASH_INDEX (h, start_of_bucket) = HASH_NEXT (h, i);
4280 else
4281 HASH_NEXT (h, XFASTINT (prev)) = HASH_NEXT (h, i);
4282
4283 /* Clear slots in key_and_value and add the slots to
4284 the free list. */
4285 HASH_KEY (h, i) = HASH_VALUE (h, i) = HASH_HASH (h, i) = Qnil;
4286 HASH_NEXT (h, i) = h->next_free;
4287 h->next_free = make_number (i);
4288 h->count = make_number (XFASTINT (h->count) - 1);
4289 xassert (XINT (h->count) >= 0);
4290 break;
4291 }
4292 else
4293 {
4294 prev = idx;
4295 idx = HASH_NEXT (h, i);
4296 }
4297 }
4298}
4299
4300
4301/* Clear hash table H. */
4302
4303void
4304hash_clear (h)
4305 struct Lisp_Hash_Table *h;
4306{
4307 if (XFASTINT (h->count) > 0)
4308 {
4309 int i, size = HASH_TABLE_SIZE (h);
4310
4311 for (i = 0; i < size; ++i)
4312 {
4313 HASH_NEXT (h, i) = i < size - 1 ? make_number (i + 1) : Qnil;
4314 HASH_KEY (h, i) = Qnil;
4315 HASH_VALUE (h, i) = Qnil;
4316 HASH_HASH (h, i) = Qnil;
4317 }
4318
4319 for (i = 0; i < XVECTOR (h->index)->size; ++i)
4320 XVECTOR (h->index)->contents[i] = Qnil;
4321
4322 h->next_free = make_number (0);
4323 h->count = make_number (0);
4324 }
4325}
4326
4327
4328\f
4329/************************************************************************
4330 Weak Hash Tables
4331 ************************************************************************/
4332
a0b581cc
GM
4333/* Sweep weak hash table H. REMOVE_ENTRIES_P non-zero means remove
4334 entries from the table that don't survive the current GC.
4335 REMOVE_ENTRIES_P zero means mark entries that are in use. Value is
4336 non-zero if anything was marked. */
4337
4338static int
4339sweep_weak_table (h, remove_entries_p)
4340 struct Lisp_Hash_Table *h;
4341 int remove_entries_p;
4342{
4343 int bucket, n, marked;
59f953a2 4344
a0b581cc
GM
4345 n = XVECTOR (h->index)->size & ~ARRAY_MARK_FLAG;
4346 marked = 0;
59f953a2 4347
a0b581cc
GM
4348 for (bucket = 0; bucket < n; ++bucket)
4349 {
1e546714 4350 Lisp_Object idx, next, prev;
a0b581cc
GM
4351
4352 /* Follow collision chain, removing entries that
4353 don't survive this garbage collection. */
a0b581cc 4354 prev = Qnil;
1e546714 4355 for (idx = HASH_INDEX (h, bucket); !GC_NILP (idx); idx = next)
a0b581cc 4356 {
a0b581cc 4357 int i = XFASTINT (idx);
1e546714
GM
4358 int key_known_to_survive_p = survives_gc_p (HASH_KEY (h, i));
4359 int value_known_to_survive_p = survives_gc_p (HASH_VALUE (h, i));
4360 int remove_p;
59f953a2 4361
a0b581cc 4362 if (EQ (h->weak, Qkey))
aee625fa 4363 remove_p = !key_known_to_survive_p;
a0b581cc 4364 else if (EQ (h->weak, Qvalue))
aee625fa 4365 remove_p = !value_known_to_survive_p;
ec504e6f 4366 else if (EQ (h->weak, Qkey_or_value))
728c5d9d 4367 remove_p = !(key_known_to_survive_p || value_known_to_survive_p);
ec504e6f 4368 else if (EQ (h->weak, Qkey_and_value))
728c5d9d 4369 remove_p = !(key_known_to_survive_p && value_known_to_survive_p);
a0b581cc
GM
4370 else
4371 abort ();
59f953a2 4372
a0b581cc
GM
4373 next = HASH_NEXT (h, i);
4374
4375 if (remove_entries_p)
4376 {
4377 if (remove_p)
4378 {
4379 /* Take out of collision chain. */
4380 if (GC_NILP (prev))
1e546714 4381 HASH_INDEX (h, bucket) = next;
a0b581cc
GM
4382 else
4383 HASH_NEXT (h, XFASTINT (prev)) = next;
59f953a2 4384
a0b581cc
GM
4385 /* Add to free list. */
4386 HASH_NEXT (h, i) = h->next_free;
4387 h->next_free = idx;
59f953a2 4388
a0b581cc
GM
4389 /* Clear key, value, and hash. */
4390 HASH_KEY (h, i) = HASH_VALUE (h, i) = Qnil;
4391 HASH_HASH (h, i) = Qnil;
59f953a2 4392
a0b581cc
GM
4393 h->count = make_number (XFASTINT (h->count) - 1);
4394 }
4395 }
4396 else
4397 {
4398 if (!remove_p)
4399 {
4400 /* Make sure key and value survive. */
aee625fa
GM
4401 if (!key_known_to_survive_p)
4402 {
4403 mark_object (&HASH_KEY (h, i));
4404 marked = 1;
4405 }
4406
4407 if (!value_known_to_survive_p)
4408 {
4409 mark_object (&HASH_VALUE (h, i));
4410 marked = 1;
4411 }
a0b581cc
GM
4412 }
4413 }
a0b581cc
GM
4414 }
4415 }
4416
4417 return marked;
4418}
4419
d80c6c11
GM
4420/* Remove elements from weak hash tables that don't survive the
4421 current garbage collection. Remove weak tables that don't survive
4422 from Vweak_hash_tables. Called from gc_sweep. */
4423
4424void
4425sweep_weak_hash_tables ()
4426{
ac0e96ee
GM
4427 Lisp_Object table, used, next;
4428 struct Lisp_Hash_Table *h;
a0b581cc
GM
4429 int marked;
4430
4431 /* Mark all keys and values that are in use. Keep on marking until
4432 there is no more change. This is necessary for cases like
4433 value-weak table A containing an entry X -> Y, where Y is used in a
4434 key-weak table B, Z -> Y. If B comes after A in the list of weak
4435 tables, X -> Y might be removed from A, although when looking at B
4436 one finds that it shouldn't. */
4437 do
4438 {
4439 marked = 0;
4440 for (table = Vweak_hash_tables; !GC_NILP (table); table = h->next_weak)
4441 {
4442 h = XHASH_TABLE (table);
4443 if (h->size & ARRAY_MARK_FLAG)
4444 marked |= sweep_weak_table (h, 0);
4445 }
4446 }
4447 while (marked);
d80c6c11 4448
a0b581cc 4449 /* Remove tables and entries that aren't used. */
ac0e96ee 4450 for (table = Vweak_hash_tables, used = Qnil; !GC_NILP (table); table = next)
d80c6c11 4451 {
d80c6c11 4452 h = XHASH_TABLE (table);
ac0e96ee
GM
4453 next = h->next_weak;
4454
d80c6c11
GM
4455 if (h->size & ARRAY_MARK_FLAG)
4456 {
ac0e96ee 4457 /* TABLE is marked as used. Sweep its contents. */
d80c6c11 4458 if (XFASTINT (h->count) > 0)
a0b581cc 4459 sweep_weak_table (h, 1);
ac0e96ee
GM
4460
4461 /* Add table to the list of used weak hash tables. */
4462 h->next_weak = used;
4463 used = table;
d80c6c11
GM
4464 }
4465 }
ac0e96ee
GM
4466
4467 Vweak_hash_tables = used;
d80c6c11
GM
4468}
4469
4470
4471\f
4472/***********************************************************************
4473 Hash Code Computation
4474 ***********************************************************************/
4475
4476/* Maximum depth up to which to dive into Lisp structures. */
4477
4478#define SXHASH_MAX_DEPTH 3
4479
4480/* Maximum length up to which to take list and vector elements into
4481 account. */
4482
4483#define SXHASH_MAX_LEN 7
4484
4485/* Combine two integers X and Y for hashing. */
4486
4487#define SXHASH_COMBINE(X, Y) \
ada0fa14 4488 ((((unsigned)(X) << 4) + (((unsigned)(X) >> 24) & 0x0fffffff)) \
d80c6c11
GM
4489 + (unsigned)(Y))
4490
4491
cf681889
GM
4492/* Return a hash for string PTR which has length LEN. The hash
4493 code returned is guaranteed to fit in a Lisp integer. */
d80c6c11
GM
4494
4495static unsigned
4496sxhash_string (ptr, len)
4497 unsigned char *ptr;
4498 int len;
4499{
4500 unsigned char *p = ptr;
4501 unsigned char *end = p + len;
4502 unsigned char c;
4503 unsigned hash = 0;
4504
4505 while (p != end)
4506 {
4507 c = *p++;
4508 if (c >= 0140)
4509 c -= 40;
4510 hash = ((hash << 3) + (hash >> 28) + c);
4511 }
59f953a2 4512
cf681889 4513 return hash & VALMASK;
d80c6c11
GM
4514}
4515
4516
4517/* Return a hash for list LIST. DEPTH is the current depth in the
4518 list. We don't recurse deeper than SXHASH_MAX_DEPTH in it. */
4519
4520static unsigned
4521sxhash_list (list, depth)
4522 Lisp_Object list;
4523 int depth;
4524{
4525 unsigned hash = 0;
4526 int i;
59f953a2 4527
d80c6c11
GM
4528 if (depth < SXHASH_MAX_DEPTH)
4529 for (i = 0;
4530 CONSP (list) && i < SXHASH_MAX_LEN;
4531 list = XCDR (list), ++i)
4532 {
4533 unsigned hash2 = sxhash (XCAR (list), depth + 1);
4534 hash = SXHASH_COMBINE (hash, hash2);
4535 }
4536
4537 return hash;
4538}
4539
4540
4541/* Return a hash for vector VECTOR. DEPTH is the current depth in
4542 the Lisp structure. */
4543
4544static unsigned
4545sxhash_vector (vec, depth)
4546 Lisp_Object vec;
4547 int depth;
4548{
4549 unsigned hash = XVECTOR (vec)->size;
4550 int i, n;
4551
4552 n = min (SXHASH_MAX_LEN, XVECTOR (vec)->size);
4553 for (i = 0; i < n; ++i)
4554 {
4555 unsigned hash2 = sxhash (XVECTOR (vec)->contents[i], depth + 1);
4556 hash = SXHASH_COMBINE (hash, hash2);
4557 }
4558
4559 return hash;
4560}
4561
4562
4563/* Return a hash for bool-vector VECTOR. */
4564
4565static unsigned
4566sxhash_bool_vector (vec)
4567 Lisp_Object vec;
4568{
4569 unsigned hash = XBOOL_VECTOR (vec)->size;
4570 int i, n;
4571
4572 n = min (SXHASH_MAX_LEN, XBOOL_VECTOR (vec)->vector_size);
4573 for (i = 0; i < n; ++i)
4574 hash = SXHASH_COMBINE (hash, XBOOL_VECTOR (vec)->data[i]);
4575
4576 return hash;
4577}
4578
4579
4580/* Return a hash code for OBJ. DEPTH is the current depth in the Lisp
4581 structure. Value is an unsigned integer clipped to VALMASK. */
4582
4583unsigned
4584sxhash (obj, depth)
4585 Lisp_Object obj;
4586 int depth;
4587{
4588 unsigned hash;
4589
4590 if (depth > SXHASH_MAX_DEPTH)
4591 return 0;
59f953a2 4592
d80c6c11
GM
4593 switch (XTYPE (obj))
4594 {
4595 case Lisp_Int:
4596 hash = XUINT (obj);
4597 break;
4598
4599 case Lisp_Symbol:
4600 hash = sxhash_string (XSYMBOL (obj)->name->data,
4601 XSYMBOL (obj)->name->size);
4602 break;
4603
4604 case Lisp_Misc:
4605 hash = XUINT (obj);
4606 break;
4607
4608 case Lisp_String:
4609 hash = sxhash_string (XSTRING (obj)->data, XSTRING (obj)->size);
4610 break;
4611
4612 /* This can be everything from a vector to an overlay. */
4613 case Lisp_Vectorlike:
4614 if (VECTORP (obj))
4615 /* According to the CL HyperSpec, two arrays are equal only if
4616 they are `eq', except for strings and bit-vectors. In
4617 Emacs, this works differently. We have to compare element
4618 by element. */
4619 hash = sxhash_vector (obj, depth);
4620 else if (BOOL_VECTOR_P (obj))
4621 hash = sxhash_bool_vector (obj);
4622 else
4623 /* Others are `equal' if they are `eq', so let's take their
4624 address as hash. */
4625 hash = XUINT (obj);
4626 break;
4627
4628 case Lisp_Cons:
4629 hash = sxhash_list (obj, depth);
4630 break;
4631
4632 case Lisp_Float:
4633 {
e84b1dea
GM
4634 unsigned char *p = (unsigned char *) &XFLOAT_DATA (obj);
4635 unsigned char *e = p + sizeof XFLOAT_DATA (obj);
d80c6c11
GM
4636 for (hash = 0; p < e; ++p)
4637 hash = SXHASH_COMBINE (hash, *p);
4638 break;
4639 }
4640
4641 default:
4642 abort ();
4643 }
4644
4645 return hash & VALMASK;
4646}
4647
4648
4649\f
4650/***********************************************************************
4651 Lisp Interface
4652 ***********************************************************************/
4653
4654
4655DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0,
4656 "Compute a hash code for OBJ and return it as integer.")
4657 (obj)
4658 Lisp_Object obj;
4659{
4660 unsigned hash = sxhash (obj, 0);;
4661 return make_number (hash);
4662}
4663
4664
4665DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 0,
4666 "Create and return a new hash table.\n\
4667Arguments are specified as keyword/argument pairs. The following\n\
4668arguments are defined:\n\
4669\n\
ec504e6f 4670:test TEST -- TEST must be a symbol that specifies how to compare keys.\n\
d80c6c11
GM
4671Default is `eql'. Predefined are the tests `eq', `eql', and `equal'.\n\
4672User-supplied test and hash functions can be specified via\n\
4673`define-hash-table-test'.\n\
4674\n\
ec504e6f 4675:size SIZE -- A hint as to how many elements will be put in the table.\n\
d80c6c11
GM
4676Default is 65.\n\
4677\n\
ec504e6f 4678:rehash-size REHASH-SIZE - Indicates how to expand the table when\n\
d80c6c11
GM
4679it fills up. If REHASH-SIZE is an integer, add that many space.\n\
4680If it is a float, it must be > 1.0, and the new size is computed by\n\
4681multiplying the old size with that factor. Default is 1.5.\n\
4682\n\
ec504e6f 4683:rehash-threshold THRESHOLD -- THRESHOLD must a float > 0, and <= 1.0.\n\
d80c6c11
GM
4684Resize the hash table when ratio of the number of entries in the table.\n\
4685Default is 0.8.\n\
4686\n\
ec504e6f
GM
4687:weakness WEAK -- WEAK must be one of nil, t, `key', `value',\n\
4688`key-or-value', or `key-and-value'. If WEAK is not nil, the table returned\n\
4689is a weak table. Key/value pairs are removed from a weak hash table when\n\
4690there are no non-weak references pointing to their key, value, one of key\n\
59f953a2 4691or value, or both key and value, depending on WEAK. WEAK t is equivalent\n\
ec504e6f 4692to `key-and-value'. Default value of WEAK is nil.")
d80c6c11
GM
4693 (nargs, args)
4694 int nargs;
4695 Lisp_Object *args;
4696{
4697 Lisp_Object test, size, rehash_size, rehash_threshold, weak;
4698 Lisp_Object user_test, user_hash;
4699 char *used;
4700 int i;
4701
4702 /* The vector `used' is used to keep track of arguments that
4703 have been consumed. */
4704 used = (char *) alloca (nargs * sizeof *used);
4705 bzero (used, nargs * sizeof *used);
4706
4707 /* See if there's a `:test TEST' among the arguments. */
4708 i = get_key_arg (QCtest, nargs, args, used);
4709 test = i < 0 ? Qeql : args[i];
4710 if (!EQ (test, Qeq) && !EQ (test, Qeql) && !EQ (test, Qequal))
4711 {
4712 /* See if it is a user-defined test. */
4713 Lisp_Object prop;
59f953a2 4714
d80c6c11
GM
4715 prop = Fget (test, Qhash_table_test);
4716 if (!CONSP (prop) || XFASTINT (Flength (prop)) < 2)
1fd4c450 4717 Fsignal (Qerror, list2 (build_string ("Invalid hash table test"),
d80c6c11
GM
4718 test));
4719 user_test = Fnth (make_number (0), prop);
4720 user_hash = Fnth (make_number (1), prop);
4721 }
4722 else
4723 user_test = user_hash = Qnil;
4724
4725 /* See if there's a `:size SIZE' argument. */
4726 i = get_key_arg (QCsize, nargs, args, used);
4727 size = i < 0 ? make_number (DEFAULT_HASH_SIZE) : args[i];
1fd4c450 4728 if (!INTEGERP (size) || XINT (size) < 0)
d80c6c11 4729 Fsignal (Qerror,
1fd4c450 4730 list2 (build_string ("Invalid hash table size"),
d80c6c11
GM
4731 size));
4732
4733 /* Look for `:rehash-size SIZE'. */
4734 i = get_key_arg (QCrehash_size, nargs, args, used);
4735 rehash_size = i < 0 ? make_float (DEFAULT_REHASH_SIZE) : args[i];
4736 if (!NUMBERP (rehash_size)
4737 || (INTEGERP (rehash_size) && XINT (rehash_size) <= 0)
4738 || XFLOATINT (rehash_size) <= 1.0)
4739 Fsignal (Qerror,
1fd4c450 4740 list2 (build_string ("Invalid hash table rehash size"),
d80c6c11 4741 rehash_size));
59f953a2 4742
d80c6c11
GM
4743 /* Look for `:rehash-threshold THRESHOLD'. */
4744 i = get_key_arg (QCrehash_threshold, nargs, args, used);
4745 rehash_threshold = i < 0 ? make_float (DEFAULT_REHASH_THRESHOLD) : args[i];
4746 if (!FLOATP (rehash_threshold)
4747 || XFLOATINT (rehash_threshold) <= 0.0
4748 || XFLOATINT (rehash_threshold) > 1.0)
4749 Fsignal (Qerror,
1fd4c450 4750 list2 (build_string ("Invalid hash table rehash threshold"),
d80c6c11 4751 rehash_threshold));
59f953a2 4752
ee0403b3
GM
4753 /* Look for `:weakness WEAK'. */
4754 i = get_key_arg (QCweakness, nargs, args, used);
d80c6c11 4755 weak = i < 0 ? Qnil : args[i];
ec504e6f
GM
4756 if (EQ (weak, Qt))
4757 weak = Qkey_and_value;
d80c6c11 4758 if (!NILP (weak)
f899c503 4759 && !EQ (weak, Qkey)
ec504e6f
GM
4760 && !EQ (weak, Qvalue)
4761 && !EQ (weak, Qkey_or_value)
4762 && !EQ (weak, Qkey_and_value))
1fd4c450 4763 Fsignal (Qerror, list2 (build_string ("Invalid hash table weakness"),
d80c6c11 4764 weak));
59f953a2 4765
d80c6c11
GM
4766 /* Now, all args should have been used up, or there's a problem. */
4767 for (i = 0; i < nargs; ++i)
4768 if (!used[i])
4769 Fsignal (Qerror,
4770 list2 (build_string ("Invalid argument list"), args[i]));
4771
4772 return make_hash_table (test, size, rehash_size, rehash_threshold, weak,
4773 user_test, user_hash);
4774}
4775
4776
f899c503
GM
4777DEFUN ("copy-hash-table", Fcopy_hash_table, Scopy_hash_table, 1, 1, 0,
4778 "Return a copy of hash table TABLE.")
4779 (table)
4780 Lisp_Object table;
4781{
4782 return copy_hash_table (check_hash_table (table));
4783}
4784
4785
38b5e497 4786DEFUN ("makehash", Fmakehash, Smakehash, 0, 1, 0,
d80c6c11 4787 "Create a new hash table.\n\
c5092f3e 4788Optional first argument TEST specifies how to compare keys in\n\
d80c6c11 4789the table. Predefined tests are `eq', `eql', and `equal'. Default\n\
38b5e497
GM
4790is `eql'. New tests can be defined with `define-hash-table-test'.")
4791 (test)
4792 Lisp_Object test;
d80c6c11 4793{
38b5e497
GM
4794 Lisp_Object args[2];
4795 args[0] = QCtest;
c7015c4f 4796 args[1] = NILP (test) ? Qeql : test;
38b5e497 4797 return Fmake_hash_table (2, args);
d80c6c11
GM
4798}
4799
4800
4801DEFUN ("hash-table-count", Fhash_table_count, Shash_table_count, 1, 1, 0,
4802 "Return the number of elements in TABLE.")
4803 (table)
4804 Lisp_Object table;
4805{
4806 return check_hash_table (table)->count;
4807}
4808
59f953a2 4809
d80c6c11
GM
4810DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size,
4811 Shash_table_rehash_size, 1, 1, 0,
4812 "Return the current rehash size of TABLE.")
4813 (table)
4814 Lisp_Object table;
4815{
4816 return check_hash_table (table)->rehash_size;
4817}
59f953a2 4818
d80c6c11
GM
4819
4820DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold,
4821 Shash_table_rehash_threshold, 1, 1, 0,
4822 "Return the current rehash threshold of TABLE.")
4823 (table)
4824 Lisp_Object table;
4825{
4826 return check_hash_table (table)->rehash_threshold;
4827}
59f953a2 4828
d80c6c11
GM
4829
4830DEFUN ("hash-table-size", Fhash_table_size, Shash_table_size, 1, 1, 0,
4831 "Return the size of TABLE.\n\
4832The size can be used as an argument to `make-hash-table' to create\n\
4833a hash table than can hold as many elements of TABLE holds\n\
4834without need for resizing.")
4835 (table)
4836 Lisp_Object table;
4837{
4838 struct Lisp_Hash_Table *h = check_hash_table (table);
4839 return make_number (HASH_TABLE_SIZE (h));
4840}
59f953a2 4841
d80c6c11
GM
4842
4843DEFUN ("hash-table-test", Fhash_table_test, Shash_table_test, 1, 1, 0,
4844 "Return the test TABLE uses.")
4845 (table)
4846 Lisp_Object table;
4847{
4848 return check_hash_table (table)->test;
4849}
4850
59f953a2 4851
e84b1dea
GM
4852DEFUN ("hash-table-weakness", Fhash_table_weakness, Shash_table_weakness,
4853 1, 1, 0,
d80c6c11
GM
4854 "Return the weakness of TABLE.")
4855 (table)
4856 Lisp_Object table;
4857{
4858 return check_hash_table (table)->weak;
4859}
4860
59f953a2 4861
d80c6c11
GM
4862DEFUN ("hash-table-p", Fhash_table_p, Shash_table_p, 1, 1, 0,
4863 "Return t if OBJ is a Lisp hash table object.")
4864 (obj)
4865 Lisp_Object obj;
4866{
4867 return HASH_TABLE_P (obj) ? Qt : Qnil;
4868}
4869
4870
4871DEFUN ("clrhash", Fclrhash, Sclrhash, 1, 1, 0,
4872 "Clear hash table TABLE.")
4873 (table)
4874 Lisp_Object table;
4875{
4876 hash_clear (check_hash_table (table));
4877 return Qnil;
4878}
4879
4880
4881DEFUN ("gethash", Fgethash, Sgethash, 2, 3, 0,
4882 "Look up KEY in TABLE and return its associated value.\n\
4883If KEY is not found, return DFLT which defaults to nil.")
1fffe870 4884 (key, table, dflt)
68c45bf0 4885 Lisp_Object key, table, dflt;
d80c6c11
GM
4886{
4887 struct Lisp_Hash_Table *h = check_hash_table (table);
4888 int i = hash_lookup (h, key, NULL);
4889 return i >= 0 ? HASH_VALUE (h, i) : dflt;
4890}
4891
4892
4893DEFUN ("puthash", Fputhash, Sputhash, 3, 3, 0,
f5c75033 4894 "Associate KEY with VALUE in hash table TABLE.\n\
d80c6c11
GM
4895If KEY is already present in table, replace its current value with\n\
4896VALUE.")
1fffe870
MR
4897 (key, value, table)
4898 Lisp_Object key, value, table;
d80c6c11
GM
4899{
4900 struct Lisp_Hash_Table *h = check_hash_table (table);
4901 int i;
4902 unsigned hash;
4903
4904 i = hash_lookup (h, key, &hash);
4905 if (i >= 0)
4906 HASH_VALUE (h, i) = value;
4907 else
4908 hash_put (h, key, value, hash);
59f953a2 4909
d9c4f922 4910 return value;
d80c6c11
GM
4911}
4912
4913
4914DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
4915 "Remove KEY from TABLE.")
1fffe870
MR
4916 (key, table)
4917 Lisp_Object key, table;
d80c6c11
GM
4918{
4919 struct Lisp_Hash_Table *h = check_hash_table (table);
4920 hash_remove (h, key);
4921 return Qnil;
4922}
4923
4924
4925DEFUN ("maphash", Fmaphash, Smaphash, 2, 2, 0,
4926 "Call FUNCTION for all entries in hash table TABLE.\n\
4927FUNCTION is called with 2 arguments KEY and VALUE.")
4928 (function, table)
4929 Lisp_Object function, table;
4930{
4931 struct Lisp_Hash_Table *h = check_hash_table (table);
4932 Lisp_Object args[3];
4933 int i;
4934
4935 for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
4936 if (!NILP (HASH_HASH (h, i)))
4937 {
4938 args[0] = function;
4939 args[1] = HASH_KEY (h, i);
4940 args[2] = HASH_VALUE (h, i);
4941 Ffuncall (3, args);
4942 }
59f953a2 4943
d80c6c11
GM
4944 return Qnil;
4945}
4946
4947
4948DEFUN ("define-hash-table-test", Fdefine_hash_table_test,
4949 Sdefine_hash_table_test, 3, 3, 0,
4950 "Define a new hash table test with name NAME, a symbol.\n\
4951In hash tables create with NAME specified as test, use TEST to compare\n\
4952keys, and HASH for computing hash codes of keys.\n\
4953\n\
4954TEST must be a function taking two arguments and returning non-nil\n\
4955if both arguments are the same. HASH must be a function taking\n\
4956one argument and return an integer that is the hash code of the\n\
4957argument. Hash code computation should use the whole value range of\n\
4958integers, including negative integers.")
4959 (name, test, hash)
4960 Lisp_Object name, test, hash;
4961{
4962 return Fput (name, Qhash_table_test, list2 (test, hash));
4963}
4964
a3b210c4 4965
57916a7a 4966\f
5c302da4
GM
4967/************************************************************************
4968 MD5
4969 ************************************************************************/
4970
57916a7a 4971#include "md5.h"
5c302da4 4972#include "coding.h"
57916a7a
GM
4973
4974DEFUN ("md5", Fmd5, Smd5, 1, 5, 0,
18e81dc8 4975 "Return MD5 message digest of OBJECT, a buffer or string.\n\
c6006049
KH
4976A message digest is a cryptographic checksum of a document,\n\
4977and the algorithm to calculate it is defined in RFC 1321.\n\
57916a7a 4978\n\
18e81dc8
GM
4979The two optional arguments START and END are character positions\n\
4980specifying for which part of OBJECT the message digest should be computed.\n\
4981If nil or omitted, the digest is computed for the whole OBJECT.\n\
57916a7a 4982\n\
f15dafe0
KH
4983The MD5 message digest is computed from the result of encoding the\n\
4984text in a coding system, not directly from the internal Emacs form\n\
4985of the text. The optional fourth argument CODING-SYSTEM specifies\n\
4986which coding system to encode the text with. It should be the same\n\
4987coding system that you used or will use when actually writing the text\n\
4988into a file.\n\
57916a7a 4989\n\
f15dafe0
KH
4990If CODING-SYSTEM is nil or omitted, the default depends on OBJECT.\n\
4991If OBJECT is a buffer, the default for CODING-SYSTEM is whatever\n\
4992coding system would be chosen by default for writing this text\n\
4993into a file.\n\
4994\n\
4995If OBJECT is a string, the most preferred coding system (see the\n\
4996command `prefer-coding-system') is used.\n\
4997\n\
6e92282b
GM
4998If NOERROR is non-nil, silently assume the `raw_text' coding if the\n\
4999guesswork fails. Normally, an error is signaled in such case.")
57916a7a
GM
5000 (object, start, end, coding_system, noerror)
5001 Lisp_Object object, start, end, coding_system, noerror;
5002{
5003 unsigned char digest[16];
5004 unsigned char value[33];
5005 int i;
5006 int size;
5007 int size_byte = 0;
5008 int start_char = 0, end_char = 0;
5009 int start_byte = 0, end_byte = 0;
5010 register int b, e;
5011 register struct buffer *bp;
5012 int temp;
5013
5c302da4 5014 if (STRINGP (object))
57916a7a
GM
5015 {
5016 if (NILP (coding_system))
5017 {
5c302da4 5018 /* Decide the coding-system to encode the data with. */
57916a7a 5019
5c302da4
GM
5020 if (STRING_MULTIBYTE (object))
5021 /* use default, we can't guess correct value */
5022 coding_system = XSYMBOL (XCAR (Vcoding_category_list))->value;
5023 else
5024 coding_system = Qraw_text;
57916a7a 5025 }
5c302da4
GM
5026
5027 if (NILP (Fcoding_system_p (coding_system)))
57916a7a 5028 {
5c302da4
GM
5029 /* Invalid coding system. */
5030
5031 if (!NILP (noerror))
5032 coding_system = Qraw_text;
5033 else
5034 while (1)
5035 Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil));
57916a7a
GM
5036 }
5037
5c302da4
GM
5038 if (STRING_MULTIBYTE (object))
5039 object = code_convert_string1 (object, coding_system, Qnil, 1);
5040
57916a7a
GM
5041 size = XSTRING (object)->size;
5042 size_byte = STRING_BYTES (XSTRING (object));
5043
5044 if (!NILP (start))
5045 {
5046 CHECK_NUMBER (start, 1);
5047
5048 start_char = XINT (start);
5049
5050 if (start_char < 0)
5051 start_char += size;
5052
5053 start_byte = string_char_to_byte (object, start_char);
5054 }
5055
5056 if (NILP (end))
5057 {
5058 end_char = size;
5059 end_byte = size_byte;
5060 }
5061 else
5062 {
5063 CHECK_NUMBER (end, 2);
5064
5065 end_char = XINT (end);
5066
5067 if (end_char < 0)
5068 end_char += size;
5069
5070 end_byte = string_char_to_byte (object, end_char);
5071 }
5072
5073 if (!(0 <= start_char && start_char <= end_char && end_char <= size))
5074 args_out_of_range_3 (object, make_number (start_char),
5075 make_number (end_char));
5076 }
5077 else
5078 {
5c302da4 5079 CHECK_BUFFER (object, 0);
57916a7a
GM
5080
5081 bp = XBUFFER (object);
5082
5083 if (NILP (start))
5084 b = BUF_BEGV (bp);
5085 else
5086 {
5087 CHECK_NUMBER_COERCE_MARKER (start, 0);
5088 b = XINT (start);
5089 }
5090
5091 if (NILP (end))
5092 e = BUF_ZV (bp);
5093 else
5094 {
5095 CHECK_NUMBER_COERCE_MARKER (end, 1);
5096 e = XINT (end);
5097 }
5098
5099 if (b > e)
5100 temp = b, b = e, e = temp;
5101
5102 if (!(BUF_BEGV (bp) <= b && e <= BUF_ZV (bp)))
5103 args_out_of_range (start, end);
5104
5105 if (NILP (coding_system))
5106 {
5c302da4
GM
5107 /* Decide the coding-system to encode the data with.
5108 See fileio.c:Fwrite-region */
5109
5110 if (!NILP (Vcoding_system_for_write))
5111 coding_system = Vcoding_system_for_write;
5112 else
5113 {
5114 int force_raw_text = 0;
5115
5116 coding_system = XBUFFER (object)->buffer_file_coding_system;
5117 if (NILP (coding_system)
5118 || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
5119 {
5120 coding_system = Qnil;
5121 if (NILP (current_buffer->enable_multibyte_characters))
5122 force_raw_text = 1;
5123 }
5124
5125 if (NILP (coding_system) && !NILP (Fbuffer_file_name(object)))
5126 {
5127 /* Check file-coding-system-alist. */
5128 Lisp_Object args[4], val;
5129
5130 args[0] = Qwrite_region; args[1] = start; args[2] = end;
5131 args[3] = Fbuffer_file_name(object);
5132 val = Ffind_operation_coding_system (4, args);
5133 if (CONSP (val) && !NILP (XCDR (val)))
5134 coding_system = XCDR (val);
5135 }
5136
5137 if (NILP (coding_system)
5138 && !NILP (XBUFFER (object)->buffer_file_coding_system))
5139 {
5140 /* If we still have not decided a coding system, use the
5141 default value of buffer-file-coding-system. */
5142 coding_system = XBUFFER (object)->buffer_file_coding_system;
5143 }
5144
5145 if (!force_raw_text
5146 && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
5147 /* Confirm that VAL can surely encode the current region. */
5148 coding_system = call3 (Vselect_safe_coding_system_function,
70da6a76
KR
5149 make_number (b), make_number (e),
5150 coding_system);
5c302da4
GM
5151
5152 if (force_raw_text)
5153 coding_system = Qraw_text;
5154 }
5155
5156 if (NILP (Fcoding_system_p (coding_system)))
57916a7a 5157 {
5c302da4
GM
5158 /* Invalid coding system. */
5159
5160 if (!NILP (noerror))
5161 coding_system = Qraw_text;
5162 else
5163 while (1)
5164 Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil));
57916a7a
GM
5165 }
5166 }
5167
5168 object = make_buffer_string (b, e, 0);
5169
5170 if (STRING_MULTIBYTE (object))
5171 object = code_convert_string1 (object, coding_system, Qnil, 1);
5172 }
5173
5c302da4 5174 md5_buffer (XSTRING (object)->data + start_byte,
57916a7a
GM
5175 STRING_BYTES(XSTRING (object)) - (size_byte - end_byte),
5176 digest);
5177
5178 for (i = 0; i < 16; i++)
5c302da4 5179 sprintf (&value[2 * i], "%02x", digest[i]);
57916a7a
GM
5180 value[32] = '\0';
5181
5182 return make_string (value, 32);
5183}
5184
24c129e4 5185\f
dfcf069d 5186void
7b863bd5
JB
5187syms_of_fns ()
5188{
d80c6c11
GM
5189 /* Hash table stuff. */
5190 Qhash_table_p = intern ("hash-table-p");
5191 staticpro (&Qhash_table_p);
5192 Qeq = intern ("eq");
5193 staticpro (&Qeq);
5194 Qeql = intern ("eql");
5195 staticpro (&Qeql);
5196 Qequal = intern ("equal");
5197 staticpro (&Qequal);
5198 QCtest = intern (":test");
5199 staticpro (&QCtest);
5200 QCsize = intern (":size");
5201 staticpro (&QCsize);
5202 QCrehash_size = intern (":rehash-size");
5203 staticpro (&QCrehash_size);
5204 QCrehash_threshold = intern (":rehash-threshold");
5205 staticpro (&QCrehash_threshold);
ee0403b3
GM
5206 QCweakness = intern (":weakness");
5207 staticpro (&QCweakness);
f899c503
GM
5208 Qkey = intern ("key");
5209 staticpro (&Qkey);
5210 Qvalue = intern ("value");
5211 staticpro (&Qvalue);
d80c6c11
GM
5212 Qhash_table_test = intern ("hash-table-test");
5213 staticpro (&Qhash_table_test);
ec504e6f
GM
5214 Qkey_or_value = intern ("key-or-value");
5215 staticpro (&Qkey_or_value);
5216 Qkey_and_value = intern ("key-and-value");
5217 staticpro (&Qkey_and_value);
d80c6c11
GM
5218
5219 defsubr (&Ssxhash);
5220 defsubr (&Smake_hash_table);
f899c503 5221 defsubr (&Scopy_hash_table);
d80c6c11
GM
5222 defsubr (&Smakehash);
5223 defsubr (&Shash_table_count);
5224 defsubr (&Shash_table_rehash_size);
5225 defsubr (&Shash_table_rehash_threshold);
5226 defsubr (&Shash_table_size);
5227 defsubr (&Shash_table_test);
e84b1dea 5228 defsubr (&Shash_table_weakness);
d80c6c11
GM
5229 defsubr (&Shash_table_p);
5230 defsubr (&Sclrhash);
5231 defsubr (&Sgethash);
5232 defsubr (&Sputhash);
5233 defsubr (&Sremhash);
5234 defsubr (&Smaphash);
5235 defsubr (&Sdefine_hash_table_test);
59f953a2 5236
7b863bd5
JB
5237 Qstring_lessp = intern ("string-lessp");
5238 staticpro (&Qstring_lessp);
68732608
RS
5239 Qprovide = intern ("provide");
5240 staticpro (&Qprovide);
5241 Qrequire = intern ("require");
5242 staticpro (&Qrequire);
0ce830bc
RS
5243 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
5244 staticpro (&Qyes_or_no_p_history);
eb4ffa4e
RS
5245 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
5246 staticpro (&Qcursor_in_echo_area);
b4f334f7
KH
5247 Qwidget_type = intern ("widget-type");
5248 staticpro (&Qwidget_type);
7b863bd5 5249
09ab3c3b
KH
5250 staticpro (&string_char_byte_cache_string);
5251 string_char_byte_cache_string = Qnil;
5252
52a9879b
RS
5253 Fset (Qyes_or_no_p_history, Qnil);
5254
7b863bd5
JB
5255 DEFVAR_LISP ("features", &Vfeatures,
5256 "A list of symbols which are the features of the executing emacs.\n\
5257Used by `featurep' and `require', and altered by `provide'.");
5258 Vfeatures = Qnil;
5259
bdd8d692
RS
5260 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
5261 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
1eb569c5 5262This applies to y-or-n and yes-or-no questions asked by commands\n\
bdd8d692
RS
5263invoked by mouse clicks and mouse menu items.");
5264 use_dialog_box = 1;
5265
7b863bd5
JB
5266 defsubr (&Sidentity);
5267 defsubr (&Srandom);
5268 defsubr (&Slength);
5a30fab8 5269 defsubr (&Ssafe_length);
026f59ce 5270 defsubr (&Sstring_bytes);
7b863bd5 5271 defsubr (&Sstring_equal);
0e1e9f8d 5272 defsubr (&Scompare_strings);
7b863bd5
JB
5273 defsubr (&Sstring_lessp);
5274 defsubr (&Sappend);
5275 defsubr (&Sconcat);
5276 defsubr (&Svconcat);
5277 defsubr (&Scopy_sequence);
09ab3c3b
KH
5278 defsubr (&Sstring_make_multibyte);
5279 defsubr (&Sstring_make_unibyte);
6d475204
RS
5280 defsubr (&Sstring_as_multibyte);
5281 defsubr (&Sstring_as_unibyte);
7b863bd5
JB
5282 defsubr (&Scopy_alist);
5283 defsubr (&Ssubstring);
5284 defsubr (&Snthcdr);
5285 defsubr (&Snth);
5286 defsubr (&Selt);
5287 defsubr (&Smember);
5288 defsubr (&Smemq);
5289 defsubr (&Sassq);
5290 defsubr (&Sassoc);
5291 defsubr (&Srassq);
0fb5a19c 5292 defsubr (&Srassoc);
7b863bd5 5293 defsubr (&Sdelq);
ca8dd546 5294 defsubr (&Sdelete);
7b863bd5
JB
5295 defsubr (&Snreverse);
5296 defsubr (&Sreverse);
5297 defsubr (&Ssort);
be9d483d 5298 defsubr (&Splist_get);
7b863bd5 5299 defsubr (&Sget);
be9d483d 5300 defsubr (&Splist_put);
7b863bd5
JB
5301 defsubr (&Sput);
5302 defsubr (&Sequal);
5303 defsubr (&Sfillarray);
999de246 5304 defsubr (&Schar_table_subtype);
e03f7933
RS
5305 defsubr (&Schar_table_parent);
5306 defsubr (&Sset_char_table_parent);
5307 defsubr (&Schar_table_extra_slot);
5308 defsubr (&Sset_char_table_extra_slot);
999de246 5309 defsubr (&Schar_table_range);
e03f7933 5310 defsubr (&Sset_char_table_range);
e1335ba2 5311 defsubr (&Sset_char_table_default);
52ef6c89 5312 defsubr (&Soptimize_char_table);
e03f7933 5313 defsubr (&Smap_char_table);
7b863bd5
JB
5314 defsubr (&Snconc);
5315 defsubr (&Smapcar);
5c6740c9 5316 defsubr (&Smapc);
7b863bd5
JB
5317 defsubr (&Smapconcat);
5318 defsubr (&Sy_or_n_p);
5319 defsubr (&Syes_or_no_p);
5320 defsubr (&Sload_average);
5321 defsubr (&Sfeaturep);
5322 defsubr (&Srequire);
5323 defsubr (&Sprovide);
a5254817 5324 defsubr (&Splist_member);
b4f334f7
KH
5325 defsubr (&Swidget_put);
5326 defsubr (&Swidget_get);
5327 defsubr (&Swidget_apply);
24c129e4
KH
5328 defsubr (&Sbase64_encode_region);
5329 defsubr (&Sbase64_decode_region);
5330 defsubr (&Sbase64_encode_string);
5331 defsubr (&Sbase64_decode_string);
57916a7a 5332 defsubr (&Smd5);
7b863bd5 5333}
d80c6c11
GM
5334
5335
5336void
5337init_fns ()
5338{
5339 Vweak_hash_tables = Qnil;
5340}