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