(appt-make-list): Don't splice quotes and date onto message.
[bpt/emacs.git] / src / fns.c
CommitLineData
7b863bd5 1/* Random utility Lisp functions.
31c8f881 2 Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 1998 Free Software Foundation, Inc.
7b863bd5
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
4ff1aed9 8the Free Software Foundation; either version 2, or (at your option)
7b863bd5
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
7b863bd5
JB
20
21
18160b98 22#include <config.h>
7b863bd5 23
dfcf069d
AS
24#ifdef HAVE_UNISTD_H
25#include <unistd.h>
26#endif
58edb572 27#include <time.h>
dfcf069d 28
7b863bd5
JB
29/* Note on some machines this defines `vector' as a typedef,
30 so make sure we don't use that name in this file. */
31#undef vector
32#define vector *****
33
7b863bd5
JB
34#include "lisp.h"
35#include "commands.h"
a8283a4a 36#include "charset.h"
7b863bd5 37
7b863bd5 38#include "buffer.h"
f812877e 39#include "keyboard.h"
ac811a55 40#include "intervals.h"
2d8e7e1f
RS
41#include "frame.h"
42#include "window.h"
d73c6532 43#if defined (HAVE_MENUS) && defined (HAVE_X_WINDOWS)
dfcf069d
AS
44#include "xterm.h"
45#endif
7b863bd5 46
bc937db7
KH
47#ifndef NULL
48#define NULL (void *)0
49#endif
50
bdd8d692
RS
51/* Nonzero enables use of dialog boxes for questions
52 asked by mouse commands. */
53int use_dialog_box;
54
2d8e7e1f
RS
55extern int minibuffer_auto_raise;
56extern Lisp_Object minibuf_window;
57
68732608 58Lisp_Object Qstring_lessp, Qprovide, Qrequire;
0ce830bc 59Lisp_Object Qyes_or_no_p_history;
eb4ffa4e 60Lisp_Object Qcursor_in_echo_area;
b4f334f7 61Lisp_Object Qwidget_type;
7b863bd5 62
3844ee44
RS
63extern Lisp_Object Qinput_method_function;
64
6cb9cafb 65static int internal_equal ();
49bdcd3e
RS
66
67extern long get_random ();
68extern void seed_random ();
69
70#ifndef HAVE_UNISTD_H
71extern long time ();
72#endif
e0f5cf5a 73\f
7b863bd5
JB
74DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
75 "Return the argument unchanged.")
76 (arg)
77 Lisp_Object arg;
78{
79 return arg;
80}
81
82DEFUN ("random", Frandom, Srandom, 0, 1, 0,
83 "Return a pseudo-random number.\n\
4cab5074
KH
84All integers representable in Lisp are equally likely.\n\
85 On most systems, this is 28 bits' worth.\n\
99175c23 86With positive integer argument N, return random number in interval [0,N).\n\
7b863bd5 87With argument t, set the random number seed from the current time and pid.")
88fe8140
EN
88 (n)
89 Lisp_Object n;
7b863bd5 90{
e2d6972a
KH
91 EMACS_INT val;
92 Lisp_Object lispy_val;
78217ef1 93 unsigned long denominator;
7b863bd5 94
88fe8140 95 if (EQ (n, Qt))
e2d6972a 96 seed_random (getpid () + time (NULL));
88fe8140 97 if (NATNUMP (n) && XFASTINT (n) != 0)
7b863bd5 98 {
4cab5074
KH
99 /* Try to take our random number from the higher bits of VAL,
100 not the lower, since (says Gentzel) the low bits of `random'
101 are less random than the higher ones. We do this by using the
102 quotient rather than the remainder. At the high end of the RNG
88fe8140 103 it's possible to get a quotient larger than n; discarding
4cab5074 104 these values eliminates the bias that would otherwise appear
88fe8140
EN
105 when using a large n. */
106 denominator = ((unsigned long)1 << VALBITS) / XFASTINT (n);
4cab5074 107 do
99175c23 108 val = get_random () / denominator;
88fe8140 109 while (val >= XFASTINT (n));
7b863bd5 110 }
78217ef1 111 else
99175c23 112 val = get_random ();
e2d6972a
KH
113 XSETINT (lispy_val, val);
114 return lispy_val;
7b863bd5
JB
115}
116\f
117/* Random data-structure functions */
118
119DEFUN ("length", Flength, Slength, 1, 1, 0,
120 "Return the length of vector, list or string SEQUENCE.\n\
0c57d6fd
RS
121A byte-code function object is also allowed.\n\
122If the string contains multibyte characters, this is not the necessarily\n\
96ced23c
AS
123the number of bytes in the string; it is the number of characters.\n\
124To get the number of bytes, use `string-bytes'")
88fe8140
EN
125 (sequence)
126 register Lisp_Object sequence;
7b863bd5
JB
127{
128 register Lisp_Object tail, val;
129 register int i;
130
131 retry:
88fe8140
EN
132 if (STRINGP (sequence))
133 XSETFASTINT (val, XSTRING (sequence)->size);
134 else if (VECTORP (sequence))
135 XSETFASTINT (val, XVECTOR (sequence)->size);
136 else if (CHAR_TABLE_P (sequence))
33aa0881
KH
137 XSETFASTINT (val, (MIN_CHAR_COMPOSITION
138 + (CHAR_FIELD2_MASK | CHAR_FIELD3_MASK)
139 - 1));
88fe8140
EN
140 else if (BOOL_VECTOR_P (sequence))
141 XSETFASTINT (val, XBOOL_VECTOR (sequence)->size);
142 else if (COMPILEDP (sequence))
143 XSETFASTINT (val, XVECTOR (sequence)->size & PSEUDOVECTOR_SIZE_MASK);
144 else if (CONSP (sequence))
7b863bd5 145 {
88fe8140 146 for (i = 0, tail = sequence; !NILP (tail); i++)
7b863bd5
JB
147 {
148 QUIT;
149 tail = Fcdr (tail);
150 }
151
ad17573a 152 XSETFASTINT (val, i);
7b863bd5 153 }
88fe8140 154 else if (NILP (sequence))
a2ad3e19 155 XSETFASTINT (val, 0);
7b863bd5
JB
156 else
157 {
88fe8140 158 sequence = wrong_type_argument (Qsequencep, sequence);
7b863bd5
JB
159 goto retry;
160 }
a2ad3e19 161 return val;
7b863bd5
JB
162}
163
5a30fab8
RS
164/* This does not check for quits. That is safe
165 since it must terminate. */
166
167DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
168 "Return the length of a list, but avoid error or infinite loop.\n\
169This function never gets an error. If LIST is not really a list,\n\
170it returns 0. If LIST is circular, it returns a finite value\n\
171which is at least the number of distinct elements.")
b4f334f7 172 (list)
5a30fab8
RS
173 Lisp_Object list;
174{
175 Lisp_Object tail, halftail, length;
176 int len = 0;
177
178 /* halftail is used to detect circular lists. */
179 halftail = list;
180 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
181 {
182 if (EQ (tail, halftail) && len != 0)
cb3d1a0a 183 break;
5a30fab8 184 len++;
3a61aeb4 185 if ((len & 1) == 0)
5a30fab8
RS
186 halftail = XCONS (halftail)->cdr;
187 }
188
189 XSETINT (length, len);
190 return length;
191}
192
026f59ce
RS
193DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
194 "Return the number of bytes in STRING.\n\
195If STRING is a multibyte string, this is greater than the length of STRING.")
196 (string)
eaf17c6b 197 Lisp_Object string;
026f59ce
RS
198{
199 CHECK_STRING (string, 1);
fc932ac6 200 return make_number (STRING_BYTES (XSTRING (string)));
026f59ce
RS
201}
202
7b863bd5 203DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
ea35ce3d 204 "Return t if two strings have identical contents.\n\
76d0f732 205Case is significant, but text properties are ignored.\n\
7b863bd5
JB
206Symbols are also allowed; their print names are used instead.")
207 (s1, s2)
208 register Lisp_Object s1, s2;
209{
7650760e 210 if (SYMBOLP (s1))
b2791413 211 XSETSTRING (s1, XSYMBOL (s1)->name);
7650760e 212 if (SYMBOLP (s2))
b2791413 213 XSETSTRING (s2, XSYMBOL (s2)->name);
7b863bd5
JB
214 CHECK_STRING (s1, 0);
215 CHECK_STRING (s2, 1);
216
ea35ce3d 217 if (XSTRING (s1)->size != XSTRING (s2)->size
fc932ac6
RS
218 || STRING_BYTES (XSTRING (s1)) != STRING_BYTES (XSTRING (s2))
219 || bcmp (XSTRING (s1)->data, XSTRING (s2)->data, STRING_BYTES (XSTRING (s1))))
7b863bd5
JB
220 return Qnil;
221 return Qt;
222}
223
0e1e9f8d 224DEFUN ("compare-strings", Fcompare_strings,
f95837d0 225 Scompare_strings, 6, 7, 0,
0e1e9f8d
RS
226 "Compare the contents of two strings, converting to multibyte if needed.\n\
227In string STR1, skip the first START1 characters and stop at END1.\n\
228In string STR2, skip the first START2 characters and stop at END2.\n\
d68cc14c
RS
229END1 and END2 default to the full lengths of the respective strings.\n\
230\n\
0e1e9f8d
RS
231Case is significant in this comparison if IGNORE-CASE is nil.\n\
232Unibyte strings are converted to multibyte for comparison.\n\
233\n\
234The value is t if the strings (or specified portions) match.\n\
235If string STR1 is less, the value is a negative number N;\n\
236 - 1 - N is the number of characters that match at the beginning.\n\
237If string STR1 is greater, the value is a positive number N;\n\
238 N - 1 is the number of characters that match at the beginning.")
239 (str1, start1, end1, str2, start2, end2, ignore_case)
240 Lisp_Object str1, start1, end1, start2, str2, end2, ignore_case;
241{
242 register int end1_char, end2_char;
243 register int i1, i1_byte, i2, i2_byte;
244
245 CHECK_STRING (str1, 0);
246 CHECK_STRING (str2, 1);
247 if (NILP (start1))
248 start1 = make_number (0);
249 if (NILP (start2))
250 start2 = make_number (0);
251 CHECK_NATNUM (start1, 2);
252 CHECK_NATNUM (start2, 3);
253 if (! NILP (end1))
254 CHECK_NATNUM (end1, 4);
255 if (! NILP (end2))
256 CHECK_NATNUM (end2, 4);
257
258 i1 = XINT (start1);
259 i2 = XINT (start2);
260
261 i1_byte = string_char_to_byte (str1, i1);
262 i2_byte = string_char_to_byte (str2, i2);
263
264 end1_char = XSTRING (str1)->size;
265 if (! NILP (end1) && end1_char > XINT (end1))
266 end1_char = XINT (end1);
267
268 end2_char = XSTRING (str2)->size;
269 if (! NILP (end2) && end2_char > XINT (end2))
270 end2_char = XINT (end2);
271
272 while (i1 < end1_char && i2 < end2_char)
273 {
274 /* When we find a mismatch, we must compare the
275 characters, not just the bytes. */
276 int c1, c2;
277
278 if (STRING_MULTIBYTE (str1))
279 FETCH_STRING_CHAR_ADVANCE (c1, str1, i1, i1_byte);
280 else
281 {
282 c1 = XSTRING (str1)->data[i1++];
283 c1 = unibyte_char_to_multibyte (c1);
284 }
285
286 if (STRING_MULTIBYTE (str2))
287 FETCH_STRING_CHAR_ADVANCE (c2, str2, i2, i2_byte);
288 else
289 {
290 c2 = XSTRING (str2)->data[i2++];
291 c2 = unibyte_char_to_multibyte (c2);
292 }
293
294 if (c1 == c2)
295 continue;
296
297 if (! NILP (ignore_case))
298 {
299 Lisp_Object tem;
300
301 tem = Fupcase (make_number (c1));
302 c1 = XINT (tem);
303 tem = Fupcase (make_number (c2));
304 c2 = XINT (tem);
305 }
306
307 if (c1 == c2)
308 continue;
309
310 /* Note that I1 has already been incremented
311 past the character that we are comparing;
312 hence we don't add or subtract 1 here. */
313 if (c1 < c2)
314 return make_number (- i1);
315 else
316 return make_number (i1);
317 }
318
319 if (i1 < end1_char)
320 return make_number (i1 - XINT (start1) + 1);
321 if (i2 < end2_char)
322 return make_number (- i1 + XINT (start1) - 1);
323
324 return Qt;
325}
326
7b863bd5 327DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
ea35ce3d 328 "Return t if first arg string is less than second in lexicographic order.\n\
7b863bd5
JB
329Case is significant.\n\
330Symbols are also allowed; their print names are used instead.")
331 (s1, s2)
332 register Lisp_Object s1, s2;
333{
7b863bd5 334 register int end;
09ab3c3b 335 register int i1, i1_byte, i2, i2_byte;
7b863bd5 336
7650760e 337 if (SYMBOLP (s1))
b2791413 338 XSETSTRING (s1, XSYMBOL (s1)->name);
7650760e 339 if (SYMBOLP (s2))
b2791413 340 XSETSTRING (s2, XSYMBOL (s2)->name);
7b863bd5
JB
341 CHECK_STRING (s1, 0);
342 CHECK_STRING (s2, 1);
343
09ab3c3b
KH
344 i1 = i1_byte = i2 = i2_byte = 0;
345
346 end = XSTRING (s1)->size;
347 if (end > XSTRING (s2)->size)
348 end = XSTRING (s2)->size;
7b863bd5 349
09ab3c3b 350 while (i1 < end)
7b863bd5 351 {
09ab3c3b
KH
352 /* When we find a mismatch, we must compare the
353 characters, not just the bytes. */
354 int c1, c2;
355
356 if (STRING_MULTIBYTE (s1))
357 FETCH_STRING_CHAR_ADVANCE (c1, s1, i1, i1_byte);
358 else
359 c1 = XSTRING (s1)->data[i1++];
360
361 if (STRING_MULTIBYTE (s2))
362 FETCH_STRING_CHAR_ADVANCE (c2, s2, i2, i2_byte);
363 else
364 c2 = XSTRING (s2)->data[i2++];
365
366 if (c1 != c2)
367 return c1 < c2 ? Qt : Qnil;
7b863bd5 368 }
09ab3c3b 369 return i1 < XSTRING (s2)->size ? Qt : Qnil;
7b863bd5
JB
370}
371\f
372static Lisp_Object concat ();
373
374/* ARGSUSED */
375Lisp_Object
376concat2 (s1, s2)
377 Lisp_Object s1, s2;
378{
379#ifdef NO_ARG_ARRAY
380 Lisp_Object args[2];
381 args[0] = s1;
382 args[1] = s2;
383 return concat (2, args, Lisp_String, 0);
384#else
385 return concat (2, &s1, Lisp_String, 0);
386#endif /* NO_ARG_ARRAY */
387}
388
d4af3687
RS
389/* ARGSUSED */
390Lisp_Object
391concat3 (s1, s2, s3)
392 Lisp_Object s1, s2, s3;
393{
394#ifdef NO_ARG_ARRAY
395 Lisp_Object args[3];
396 args[0] = s1;
397 args[1] = s2;
398 args[2] = s3;
399 return concat (3, args, Lisp_String, 0);
400#else
401 return concat (3, &s1, Lisp_String, 0);
402#endif /* NO_ARG_ARRAY */
403}
404
7b863bd5
JB
405DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
406 "Concatenate all the arguments and make the result a list.\n\
407The result is a list whose elements are the elements of all the arguments.\n\
408Each argument may be a list, vector or string.\n\
aec1184c 409The last argument is not copied, just used as the tail of the new list.")
7b863bd5
JB
410 (nargs, args)
411 int nargs;
412 Lisp_Object *args;
413{
414 return concat (nargs, args, Lisp_Cons, 1);
415}
416
417DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
418 "Concatenate all the arguments and make the result a string.\n\
419The result is a string whose elements are the elements of all the arguments.\n\
37d40ae9
RS
420Each argument may be a string or a list or vector of characters (integers).\n\
421\n\
422Do not use individual integers as arguments!\n\
423The behavior of `concat' in that case will be changed later!\n\
424If your program passes an integer as an argument to `concat',\n\
425you should change it right away not to do so.")
7b863bd5
JB
426 (nargs, args)
427 int nargs;
428 Lisp_Object *args;
429{
430 return concat (nargs, args, Lisp_String, 0);
431}
432
433DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
434 "Concatenate all the arguments and make the result a vector.\n\
435The result is a vector whose elements are the elements of all the arguments.\n\
436Each argument may be a list, vector or string.")
437 (nargs, args)
438 int nargs;
439 Lisp_Object *args;
440{
3e7383eb 441 return concat (nargs, args, Lisp_Vectorlike, 0);
7b863bd5
JB
442}
443
3720677d
KH
444/* Retrun a copy of a sub char table ARG. The elements except for a
445 nested sub char table are not copied. */
446static Lisp_Object
447copy_sub_char_table (arg)
e1335ba2 448 Lisp_Object arg;
3720677d
KH
449{
450 Lisp_Object copy = make_sub_char_table (XCHAR_TABLE (arg)->defalt);
451 int i;
452
453 /* Copy all the contents. */
454 bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
455 SUB_CHAR_TABLE_ORDINARY_SLOTS * sizeof (Lisp_Object));
456 /* Recursively copy any sub char-tables in the ordinary slots. */
457 for (i = 32; i < SUB_CHAR_TABLE_ORDINARY_SLOTS; i++)
458 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
459 XCHAR_TABLE (copy)->contents[i]
460 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
461
462 return copy;
463}
464
465
7b863bd5
JB
466DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
467 "Return a copy of a list, vector or string.\n\
468The elements of a list or vector are not copied; they are shared\n\
469with the original.")
470 (arg)
471 Lisp_Object arg;
472{
265a9e55 473 if (NILP (arg)) return arg;
e03f7933
RS
474
475 if (CHAR_TABLE_P (arg))
476 {
25c30748 477 int i;
e03f7933
RS
478 Lisp_Object copy;
479
c8640abf 480 copy = Fmake_char_table (XCHAR_TABLE (arg)->purpose, Qnil);
e03f7933 481 /* Copy all the slots, including the extra ones. */
69b3a14b 482 bcopy (XVECTOR (arg)->contents, XVECTOR (copy)->contents,
25c30748
KH
483 ((XCHAR_TABLE (arg)->size & PSEUDOVECTOR_SIZE_MASK)
484 * sizeof (Lisp_Object)));
e03f7933 485
3720677d
KH
486 /* Recursively copy any sub char tables in the ordinary slots
487 for multibyte characters. */
488 for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS;
489 i < CHAR_TABLE_ORDINARY_SLOTS; i++)
490 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
e03f7933 491 XCHAR_TABLE (copy)->contents[i]
3720677d 492 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
e03f7933
RS
493
494 return copy;
495 }
496
497 if (BOOL_VECTOR_P (arg))
498 {
499 Lisp_Object val;
e03f7933 500 int size_in_chars
e22e4283 501 = (XBOOL_VECTOR (arg)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
502
503 val = Fmake_bool_vector (Flength (arg), Qnil);
504 bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
505 size_in_chars);
506 return val;
507 }
508
7650760e 509 if (!CONSP (arg) && !VECTORP (arg) && !STRINGP (arg))
7b863bd5
JB
510 arg = wrong_type_argument (Qsequencep, arg);
511 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
512}
513
514static Lisp_Object
515concat (nargs, args, target_type, last_special)
516 int nargs;
517 Lisp_Object *args;
518 enum Lisp_Type target_type;
519 int last_special;
520{
521 Lisp_Object val;
7b863bd5
JB
522 register Lisp_Object tail;
523 register Lisp_Object this;
524 int toindex;
ea35ce3d
RS
525 int toindex_byte;
526 register int result_len;
527 register int result_len_byte;
7b863bd5
JB
528 register int argnum;
529 Lisp_Object last_tail;
530 Lisp_Object prev;
ea35ce3d 531 int some_multibyte;
18cc260b
KH
532 /* When we make a multibyte string, we must pay attention to the
533 byte combining problem, i.e., a byte may be combined with a
534 multibyte charcter of the previous string. This flag tells if we
535 must consider such a situation or not. */
536 int maybe_combine_byte;
7b863bd5
JB
537
538 /* In append, the last arg isn't treated like the others */
539 if (last_special && nargs > 0)
540 {
541 nargs--;
542 last_tail = args[nargs];
543 }
544 else
545 last_tail = Qnil;
546
ea35ce3d 547 /* Canonicalize each argument. */
7b863bd5
JB
548 for (argnum = 0; argnum < nargs; argnum++)
549 {
550 this = args[argnum];
7650760e 551 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
e03f7933 552 || COMPILEDP (this) || BOOL_VECTOR_P (this)))
7b863bd5 553 {
7650760e 554 if (INTEGERP (this))
37d40ae9 555 args[argnum] = Fnumber_to_string (this);
7b863bd5
JB
556 else
557 args[argnum] = wrong_type_argument (Qsequencep, this);
558 }
559 }
560
ea35ce3d
RS
561 /* Compute total length in chars of arguments in RESULT_LEN.
562 If desired output is a string, also compute length in bytes
563 in RESULT_LEN_BYTE, and determine in SOME_MULTIBYTE
564 whether the result should be a multibyte string. */
565 result_len_byte = 0;
566 result_len = 0;
567 some_multibyte = 0;
568 for (argnum = 0; argnum < nargs; argnum++)
7b863bd5 569 {
ea35ce3d 570 int len;
7b863bd5 571 this = args[argnum];
ea35ce3d
RS
572 len = XFASTINT (Flength (this));
573 if (target_type == Lisp_String)
5b6dddaa 574 {
09ab3c3b
KH
575 /* We must count the number of bytes needed in the string
576 as well as the number of characters. */
5b6dddaa
KH
577 int i;
578 Lisp_Object ch;
ea35ce3d 579 int this_len_byte;
5b6dddaa 580
dec58e65 581 if (VECTORP (this))
ea35ce3d 582 for (i = 0; i < len; i++)
dec58e65
KH
583 {
584 ch = XVECTOR (this)->contents[i];
585 if (! INTEGERP (ch))
586 wrong_type_argument (Qintegerp, ch);
cc531c44 587 this_len_byte = CHAR_BYTES (XINT (ch));
ea35ce3d
RS
588 result_len_byte += this_len_byte;
589 if (this_len_byte > 1)
590 some_multibyte = 1;
dec58e65 591 }
6d475204
RS
592 else if (BOOL_VECTOR_P (this) && XBOOL_VECTOR (this)->size > 0)
593 wrong_type_argument (Qintegerp, Faref (this, make_number (0)));
ea35ce3d 594 else if (CONSP (this))
dec58e65
KH
595 for (; CONSP (this); this = XCONS (this)->cdr)
596 {
597 ch = XCONS (this)->car;
598 if (! INTEGERP (ch))
599 wrong_type_argument (Qintegerp, ch);
cc531c44 600 this_len_byte = CHAR_BYTES (XINT (ch));
ea35ce3d
RS
601 result_len_byte += this_len_byte;
602 if (this_len_byte > 1)
603 some_multibyte = 1;
dec58e65 604 }
470730a8 605 else if (STRINGP (this))
ea35ce3d 606 {
06f57aa7 607 if (STRING_MULTIBYTE (this))
09ab3c3b
KH
608 {
609 some_multibyte = 1;
fc932ac6 610 result_len_byte += STRING_BYTES (XSTRING (this));
09ab3c3b
KH
611 }
612 else
613 result_len_byte += count_size_as_multibyte (XSTRING (this)->data,
614 XSTRING (this)->size);
ea35ce3d 615 }
5b6dddaa 616 }
ea35ce3d
RS
617
618 result_len += len;
7b863bd5
JB
619 }
620
09ab3c3b
KH
621 if (! some_multibyte)
622 result_len_byte = result_len;
7b863bd5 623
ea35ce3d 624 /* Create the output object. */
7b863bd5 625 if (target_type == Lisp_Cons)
ea35ce3d 626 val = Fmake_list (make_number (result_len), Qnil);
3e7383eb 627 else if (target_type == Lisp_Vectorlike)
ea35ce3d 628 val = Fmake_vector (make_number (result_len), Qnil);
b10b2daa 629 else if (some_multibyte)
ea35ce3d 630 val = make_uninit_multibyte_string (result_len, result_len_byte);
b10b2daa
RS
631 else
632 val = make_uninit_string (result_len);
7b863bd5 633
09ab3c3b
KH
634 /* In `append', if all but last arg are nil, return last arg. */
635 if (target_type == Lisp_Cons && EQ (val, Qnil))
636 return last_tail;
7b863bd5 637
ea35ce3d 638 /* Copy the contents of the args into the result. */
7b863bd5
JB
639 if (CONSP (val))
640 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
641 else
ea35ce3d 642 toindex = 0, toindex_byte = 0;
7b863bd5
JB
643
644 prev = Qnil;
645
18cc260b 646 maybe_combine_byte = 0;
7b863bd5
JB
647 for (argnum = 0; argnum < nargs; argnum++)
648 {
649 Lisp_Object thislen;
650 int thisleni;
de712da3 651 register unsigned int thisindex = 0;
ea35ce3d 652 register unsigned int thisindex_byte = 0;
7b863bd5
JB
653
654 this = args[argnum];
655 if (!CONSP (this))
656 thislen = Flength (this), thisleni = XINT (thislen);
657
7650760e 658 if (STRINGP (this) && STRINGP (val)
ac811a55 659 && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
ea35ce3d
RS
660 copy_text_properties (make_number (0), thislen, this,
661 make_number (toindex), val, Qnil);
ac811a55 662
ea35ce3d
RS
663 /* Between strings of the same kind, copy fast. */
664 if (STRINGP (this) && STRINGP (val)
665 && STRING_MULTIBYTE (this) == some_multibyte)
7b863bd5 666 {
fc932ac6 667 int thislen_byte = STRING_BYTES (XSTRING (this));
ea35ce3d 668 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
fc932ac6 669 STRING_BYTES (XSTRING (this)));
18cc260b
KH
670 if (some_multibyte
671 && toindex_byte > 0
8b542479 672 && !ASCII_BYTE_P (XSTRING (val)->data[toindex_byte - 1])
6bdd75a5 673 && !CHAR_HEAD_P (XSTRING (this)->data[0]))
18cc260b 674 maybe_combine_byte = 1;
ea35ce3d
RS
675 toindex_byte += thislen_byte;
676 toindex += thisleni;
677 }
09ab3c3b
KH
678 /* Copy a single-byte string to a multibyte string. */
679 else if (STRINGP (this) && STRINGP (val))
680 {
681 toindex_byte += copy_text (XSTRING (this)->data,
682 XSTRING (val)->data + toindex_byte,
683 XSTRING (this)->size, 0, 1);
684 toindex += thisleni;
685 }
ea35ce3d
RS
686 else
687 /* Copy element by element. */
688 while (1)
689 {
690 register Lisp_Object elt;
691
692 /* Fetch next element of `this' arg into `elt', or break if
693 `this' is exhausted. */
694 if (NILP (this)) break;
695 if (CONSP (this))
696 elt = XCONS (this)->car, this = XCONS (this)->cdr;
6a7df83b
RS
697 else if (thisindex >= thisleni)
698 break;
699 else if (STRINGP (this))
ea35ce3d 700 {
2cef5737 701 int c;
6a7df83b 702 if (STRING_MULTIBYTE (this))
ea35ce3d 703 {
6a7df83b
RS
704 FETCH_STRING_CHAR_ADVANCE (c, this,
705 thisindex,
706 thisindex_byte);
707 XSETFASTINT (elt, c);
ea35ce3d 708 }
6a7df83b 709 else
ea35ce3d 710 {
6a7df83b 711 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
e0e25273
KH
712 if (some_multibyte
713 && (XINT (elt) >= 0240
f9638719
EZ
714 || (XINT (elt) >= 0200
715 && ! NILP (Vnonascii_translation_table)))
6a7df83b
RS
716 && XINT (elt) < 0400)
717 {
2cef5737 718 c = unibyte_char_to_multibyte (XINT (elt));
6a7df83b
RS
719 XSETINT (elt, c);
720 }
ea35ce3d 721 }
6a7df83b
RS
722 }
723 else if (BOOL_VECTOR_P (this))
724 {
725 int byte;
726 byte = XBOOL_VECTOR (this)->data[thisindex / BITS_PER_CHAR];
727 if (byte & (1 << (thisindex % BITS_PER_CHAR)))
728 elt = Qt;
ea35ce3d 729 else
6a7df83b
RS
730 elt = Qnil;
731 thisindex++;
ea35ce3d 732 }
6a7df83b
RS
733 else
734 elt = XVECTOR (this)->contents[thisindex++];
7b863bd5 735
ea35ce3d
RS
736 /* Store this element into the result. */
737 if (toindex < 0)
7b863bd5 738 {
ea35ce3d
RS
739 XCONS (tail)->car = elt;
740 prev = tail;
741 tail = XCONS (tail)->cdr;
7b863bd5 742 }
ea35ce3d
RS
743 else if (VECTORP (val))
744 XVECTOR (val)->contents[toindex++] = elt;
745 else
746 {
747 CHECK_NUMBER (elt, 0);
748 if (SINGLE_BYTE_CHAR_P (XINT (elt)))
749 {
18cc260b
KH
750 if (some_multibyte
751 && toindex_byte > 0
8b542479
KH
752 && !ASCII_BYTE_P (XSTRING (val)->data[toindex_byte - 1])
753 && !CHAR_HEAD_P (XINT (elt)))
18cc260b 754 maybe_combine_byte = 1;
44893c8f
KH
755 XSTRING (val)->data[toindex_byte++] = XINT (elt);
756 toindex++;
ea35ce3d
RS
757 }
758 else
759 /* If we have any multibyte characters,
760 we already decided to make a multibyte string. */
761 {
762 int c = XINT (elt);
763 unsigned char work[4], *str;
764 int i = CHAR_STRING (c, work, str);
765
766 /* P exists as a variable
767 to avoid a bug on the Masscomp C compiler. */
768 unsigned char *p = & XSTRING (val)->data[toindex_byte];
769 bcopy (str, p, i);
770 toindex_byte += i;
771 toindex++;
772 }
773 }
774 }
7b863bd5 775 }
265a9e55 776 if (!NILP (prev))
7b863bd5
JB
777 XCONS (prev)->cdr = last_tail;
778
18cc260b 779 if (maybe_combine_byte)
262c8cea 780 /* Character counter of the multibyte string VAL may be wrong
18cc260b
KH
781 because of byte combining problem. We must re-calculate it. */
782 XSTRING (val)->size = multibyte_chars_in_text (XSTRING (val)->data,
783 XSTRING (val)->size_byte);
784
b4f334f7 785 return val;
7b863bd5
JB
786}
787\f
09ab3c3b
KH
788static Lisp_Object string_char_byte_cache_string;
789static int string_char_byte_cache_charpos;
790static int string_char_byte_cache_bytepos;
791
57247650
KH
792void
793clear_string_char_byte_cache ()
794{
795 string_char_byte_cache_string = Qnil;
796}
797
ea35ce3d
RS
798/* Return the character index corresponding to CHAR_INDEX in STRING. */
799
800int
801string_char_to_byte (string, char_index)
802 Lisp_Object string;
803 int char_index;
804{
09ab3c3b
KH
805 int i, i_byte;
806 int best_below, best_below_byte;
807 int best_above, best_above_byte;
ea35ce3d
RS
808
809 if (! STRING_MULTIBYTE (string))
810 return char_index;
811
09ab3c3b
KH
812 best_below = best_below_byte = 0;
813 best_above = XSTRING (string)->size;
fc932ac6 814 best_above_byte = STRING_BYTES (XSTRING (string));
09ab3c3b
KH
815
816 if (EQ (string, string_char_byte_cache_string))
817 {
818 if (string_char_byte_cache_charpos < char_index)
819 {
820 best_below = string_char_byte_cache_charpos;
821 best_below_byte = string_char_byte_cache_bytepos;
822 }
823 else
824 {
825 best_above = string_char_byte_cache_charpos;
826 best_above_byte = string_char_byte_cache_bytepos;
827 }
828 }
829
830 if (char_index - best_below < best_above - char_index)
831 {
832 while (best_below < char_index)
833 {
834 int c;
835 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
836 }
837 i = best_below;
838 i_byte = best_below_byte;
839 }
840 else
ea35ce3d 841 {
09ab3c3b
KH
842 while (best_above > char_index)
843 {
844 int best_above_byte_saved = --best_above_byte;
845
846 while (best_above_byte > 0
847 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
848 best_above_byte--;
67bfe42d 849 if (!BASE_LEADING_CODE_P (XSTRING (string)->data[best_above_byte]))
09ab3c3b
KH
850 best_above_byte = best_above_byte_saved;
851 best_above--;
852 }
853 i = best_above;
854 i_byte = best_above_byte;
ea35ce3d
RS
855 }
856
09ab3c3b
KH
857 string_char_byte_cache_bytepos = i_byte;
858 string_char_byte_cache_charpos = i;
859 string_char_byte_cache_string = string;
860
ea35ce3d
RS
861 return i_byte;
862}
09ab3c3b 863\f
ea35ce3d
RS
864/* Return the character index corresponding to BYTE_INDEX in STRING. */
865
866int
867string_byte_to_char (string, byte_index)
868 Lisp_Object string;
869 int byte_index;
870{
09ab3c3b
KH
871 int i, i_byte;
872 int best_below, best_below_byte;
873 int best_above, best_above_byte;
ea35ce3d
RS
874
875 if (! STRING_MULTIBYTE (string))
876 return byte_index;
877
09ab3c3b
KH
878 best_below = best_below_byte = 0;
879 best_above = XSTRING (string)->size;
fc932ac6 880 best_above_byte = STRING_BYTES (XSTRING (string));
09ab3c3b
KH
881
882 if (EQ (string, string_char_byte_cache_string))
883 {
884 if (string_char_byte_cache_bytepos < byte_index)
885 {
886 best_below = string_char_byte_cache_charpos;
887 best_below_byte = string_char_byte_cache_bytepos;
888 }
889 else
890 {
891 best_above = string_char_byte_cache_charpos;
892 best_above_byte = string_char_byte_cache_bytepos;
893 }
894 }
895
896 if (byte_index - best_below_byte < best_above_byte - byte_index)
897 {
898 while (best_below_byte < byte_index)
899 {
900 int c;
901 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
902 }
903 i = best_below;
904 i_byte = best_below_byte;
905 }
906 else
ea35ce3d 907 {
09ab3c3b
KH
908 while (best_above_byte > byte_index)
909 {
910 int best_above_byte_saved = --best_above_byte;
911
912 while (best_above_byte > 0
913 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
914 best_above_byte--;
67bfe42d 915 if (!BASE_LEADING_CODE_P (XSTRING (string)->data[best_above_byte]))
09ab3c3b
KH
916 best_above_byte = best_above_byte_saved;
917 best_above--;
918 }
919 i = best_above;
920 i_byte = best_above_byte;
ea35ce3d
RS
921 }
922
09ab3c3b
KH
923 string_char_byte_cache_bytepos = i_byte;
924 string_char_byte_cache_charpos = i;
925 string_char_byte_cache_string = string;
926
ea35ce3d
RS
927 return i;
928}
09ab3c3b 929\f
ea35ce3d 930/* Convert STRING to a multibyte string.
2cef5737 931 Single-byte characters 0240 through 0377 are converted
ea35ce3d
RS
932 by adding nonascii_insert_offset to each. */
933
934Lisp_Object
935string_make_multibyte (string)
936 Lisp_Object string;
937{
938 unsigned char *buf;
939 int nbytes;
940
941 if (STRING_MULTIBYTE (string))
942 return string;
943
944 nbytes = count_size_as_multibyte (XSTRING (string)->data,
945 XSTRING (string)->size);
6d475204
RS
946 /* If all the chars are ASCII, they won't need any more bytes
947 once converted. In that case, we can return STRING itself. */
fc932ac6 948 if (nbytes == STRING_BYTES (XSTRING (string)))
6d475204
RS
949 return string;
950
ea35ce3d 951 buf = (unsigned char *) alloca (nbytes);
fc932ac6 952 copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
ea35ce3d
RS
953 0, 1);
954
955 return make_multibyte_string (buf, XSTRING (string)->size, nbytes);
956}
957
958/* Convert STRING to a single-byte string. */
959
960Lisp_Object
961string_make_unibyte (string)
962 Lisp_Object string;
963{
964 unsigned char *buf;
965
966 if (! STRING_MULTIBYTE (string))
967 return string;
968
969 buf = (unsigned char *) alloca (XSTRING (string)->size);
970
fc932ac6 971 copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
ea35ce3d
RS
972 1, 0);
973
974 return make_unibyte_string (buf, XSTRING (string)->size);
975}
09ab3c3b
KH
976
977DEFUN ("string-make-multibyte", Fstring_make_multibyte, Sstring_make_multibyte,
978 1, 1, 0,
a6ee6aa4
RS
979 "Return the multibyte equivalent of STRING.\n\
980The function `unibyte-char-to-multibyte' is used to convert\n\
981each unibyte character to a multibyte character.")
09ab3c3b
KH
982 (string)
983 Lisp_Object string;
984{
aabd38ec
KH
985 CHECK_STRING (string, 0);
986
09ab3c3b
KH
987 return string_make_multibyte (string);
988}
989
990DEFUN ("string-make-unibyte", Fstring_make_unibyte, Sstring_make_unibyte,
991 1, 1, 0,
a6ee6aa4
RS
992 "Return the unibyte equivalent of STRING.\n\
993Multibyte character codes are converted to unibyte\n\
994by using just the low 8 bits.")
09ab3c3b
KH
995 (string)
996 Lisp_Object string;
997{
aabd38ec
KH
998 CHECK_STRING (string, 0);
999
09ab3c3b
KH
1000 return string_make_unibyte (string);
1001}
6d475204
RS
1002
1003DEFUN ("string-as-unibyte", Fstring_as_unibyte, Sstring_as_unibyte,
1004 1, 1, 0,
1005 "Return a unibyte string with the same individual bytes as STRING.\n\
f4e09ae7 1006If STRING is unibyte, the result is STRING itself.\n\
f4e09ae7 1007Otherwise it is a newly created string, with no text properties.")
6d475204
RS
1008 (string)
1009 Lisp_Object string;
1010{
aabd38ec
KH
1011 CHECK_STRING (string, 0);
1012
6d475204
RS
1013 if (STRING_MULTIBYTE (string))
1014 {
1015 string = Fcopy_sequence (string);
fc932ac6 1016 XSTRING (string)->size = STRING_BYTES (XSTRING (string));
f4e09ae7 1017 XSTRING (string)->intervals = NULL_INTERVAL;
fa251740 1018 SET_STRING_BYTES (XSTRING (string), -1);
6d475204
RS
1019 }
1020 return string;
1021}
1022
1023DEFUN ("string-as-multibyte", Fstring_as_multibyte, Sstring_as_multibyte,
1024 1, 1, 0,
1025 "Return a multibyte string with the same individual bytes as STRING.\n\
f4e09ae7
RS
1026If STRING is multibyte, the result is STRING itself.\n\
1027Otherwise it is a newly created string, with no text properties.")
6d475204
RS
1028 (string)
1029 Lisp_Object string;
1030{
aabd38ec
KH
1031 CHECK_STRING (string, 0);
1032
6d475204
RS
1033 if (! STRING_MULTIBYTE (string))
1034 {
9658795c
RS
1035 int nbytes = STRING_BYTES (XSTRING (string));
1036 int newlen = multibyte_chars_in_text (XSTRING (string)->data, nbytes);
1037
1038 string = Fcopy_sequence (string);
1039 XSTRING (string)->size = newlen;
1040 XSTRING (string)->size_byte = nbytes;
f4e09ae7 1041 XSTRING (string)->intervals = NULL_INTERVAL;
6d475204
RS
1042 }
1043 return string;
1044}
ea35ce3d 1045\f
7b863bd5
JB
1046DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
1047 "Return a copy of ALIST.\n\
1048This is an alist which represents the same mapping from objects to objects,\n\
1049but does not share the alist structure with ALIST.\n\
1050The objects mapped (cars and cdrs of elements of the alist)\n\
1051are shared, however.\n\
1052Elements of ALIST that are not conses are also shared.")
1053 (alist)
1054 Lisp_Object alist;
1055{
1056 register Lisp_Object tem;
1057
1058 CHECK_LIST (alist, 0);
265a9e55 1059 if (NILP (alist))
7b863bd5
JB
1060 return alist;
1061 alist = concat (1, &alist, Lisp_Cons, 0);
1062 for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
1063 {
1064 register Lisp_Object car;
1065 car = XCONS (tem)->car;
1066
1067 if (CONSP (car))
1068 XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
1069 }
1070 return alist;
1071}
1072
1073DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
1074 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
1075TO may be nil or omitted; then the substring runs to the end of STRING.\n\
21fbc8e5
RS
1076If FROM or TO is negative, it counts from the end.\n\
1077\n\
1078This function allows vectors as well as strings.")
7b863bd5
JB
1079 (string, from, to)
1080 Lisp_Object string;
1081 register Lisp_Object from, to;
1082{
ac811a55 1083 Lisp_Object res;
21fbc8e5 1084 int size;
ea35ce3d
RS
1085 int size_byte;
1086 int from_char, to_char;
1087 int from_byte, to_byte;
21fbc8e5
RS
1088
1089 if (! (STRINGP (string) || VECTORP (string)))
1090 wrong_type_argument (Qarrayp, string);
ac811a55 1091
7b863bd5 1092 CHECK_NUMBER (from, 1);
21fbc8e5
RS
1093
1094 if (STRINGP (string))
ea35ce3d
RS
1095 {
1096 size = XSTRING (string)->size;
fc932ac6 1097 size_byte = STRING_BYTES (XSTRING (string));
ea35ce3d 1098 }
21fbc8e5
RS
1099 else
1100 size = XVECTOR (string)->size;
1101
265a9e55 1102 if (NILP (to))
ea35ce3d
RS
1103 {
1104 to_char = size;
1105 to_byte = size_byte;
1106 }
7b863bd5 1107 else
ea35ce3d
RS
1108 {
1109 CHECK_NUMBER (to, 2);
1110
1111 to_char = XINT (to);
1112 if (to_char < 0)
1113 to_char += size;
1114
1115 if (STRINGP (string))
1116 to_byte = string_char_to_byte (string, to_char);
1117 }
1118
1119 from_char = XINT (from);
1120 if (from_char < 0)
1121 from_char += size;
1122 if (STRINGP (string))
1123 from_byte = string_char_to_byte (string, from_char);
7b863bd5 1124
ea35ce3d
RS
1125 if (!(0 <= from_char && from_char <= to_char && to_char <= size))
1126 args_out_of_range_3 (string, make_number (from_char),
1127 make_number (to_char));
7b863bd5 1128
21fbc8e5
RS
1129 if (STRINGP (string))
1130 {
b10b2daa
RS
1131 res = make_specified_string (XSTRING (string)->data + from_byte,
1132 to_char - from_char, to_byte - from_byte,
1133 STRING_MULTIBYTE (string));
21ab867f
AS
1134 copy_text_properties (make_number (from_char), make_number (to_char),
1135 string, make_number (0), res, Qnil);
ea35ce3d
RS
1136 }
1137 else
1138 res = Fvector (to_char - from_char,
1139 XVECTOR (string)->contents + from_char);
1140
1141 return res;
1142}
1143
1144/* Extract a substring of STRING, giving start and end positions
1145 both in characters and in bytes. */
1146
1147Lisp_Object
1148substring_both (string, from, from_byte, to, to_byte)
1149 Lisp_Object string;
1150 int from, from_byte, to, to_byte;
1151{
1152 Lisp_Object res;
1153 int size;
1154 int size_byte;
1155
1156 if (! (STRINGP (string) || VECTORP (string)))
1157 wrong_type_argument (Qarrayp, string);
1158
1159 if (STRINGP (string))
1160 {
1161 size = XSTRING (string)->size;
fc932ac6 1162 size_byte = STRING_BYTES (XSTRING (string));
ea35ce3d
RS
1163 }
1164 else
1165 size = XVECTOR (string)->size;
1166
1167 if (!(0 <= from && from <= to && to <= size))
1168 args_out_of_range_3 (string, make_number (from), make_number (to));
1169
1170 if (STRINGP (string))
1171 {
b10b2daa
RS
1172 res = make_specified_string (XSTRING (string)->data + from_byte,
1173 to - from, to_byte - from_byte,
1174 STRING_MULTIBYTE (string));
21ab867f
AS
1175 copy_text_properties (make_number (from), make_number (to),
1176 string, make_number (0), res, Qnil);
21fbc8e5
RS
1177 }
1178 else
ea35ce3d
RS
1179 res = Fvector (to - from,
1180 XVECTOR (string)->contents + from);
b4f334f7 1181
ac811a55 1182 return res;
7b863bd5
JB
1183}
1184\f
1185DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1186 "Take cdr N times on LIST, returns the result.")
1187 (n, list)
1188 Lisp_Object n;
1189 register Lisp_Object list;
1190{
1191 register int i, num;
1192 CHECK_NUMBER (n, 0);
1193 num = XINT (n);
265a9e55 1194 for (i = 0; i < num && !NILP (list); i++)
7b863bd5
JB
1195 {
1196 QUIT;
1197 list = Fcdr (list);
1198 }
1199 return list;
1200}
1201
1202DEFUN ("nth", Fnth, Snth, 2, 2, 0,
1203 "Return the Nth element of LIST.\n\
1204N counts from zero. If LIST is not that long, nil is returned.")
1205 (n, list)
1206 Lisp_Object n, list;
1207{
1208 return Fcar (Fnthcdr (n, list));
1209}
1210
1211DEFUN ("elt", Felt, Selt, 2, 2, 0,
1212 "Return element of SEQUENCE at index N.")
88fe8140
EN
1213 (sequence, n)
1214 register Lisp_Object sequence, n;
7b863bd5
JB
1215{
1216 CHECK_NUMBER (n, 0);
1217 while (1)
1218 {
88fe8140
EN
1219 if (CONSP (sequence) || NILP (sequence))
1220 return Fcar (Fnthcdr (n, sequence));
1221 else if (STRINGP (sequence) || VECTORP (sequence)
1222 || BOOL_VECTOR_P (sequence) || CHAR_TABLE_P (sequence))
1223 return Faref (sequence, n);
7b863bd5 1224 else
88fe8140 1225 sequence = wrong_type_argument (Qsequencep, sequence);
7b863bd5
JB
1226 }
1227}
1228
1229DEFUN ("member", Fmember, Smember, 2, 2, 0,
1d58e36f 1230 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
7b863bd5
JB
1231The value is actually the tail of LIST whose car is ELT.")
1232 (elt, list)
1233 register Lisp_Object elt;
1234 Lisp_Object list;
1235{
1236 register Lisp_Object tail;
bdd8d692 1237 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1238 {
1239 register Lisp_Object tem;
1240 tem = Fcar (tail);
265a9e55 1241 if (! NILP (Fequal (elt, tem)))
7b863bd5
JB
1242 return tail;
1243 QUIT;
1244 }
1245 return Qnil;
1246}
1247
1248DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
1249 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
1250The value is actually the tail of LIST whose car is ELT.")
1251 (elt, list)
1252 register Lisp_Object elt;
1253 Lisp_Object list;
1254{
1255 register Lisp_Object tail;
bdd8d692 1256 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1257 {
1258 register Lisp_Object tem;
1259 tem = Fcar (tail);
1260 if (EQ (elt, tem)) return tail;
1261 QUIT;
1262 }
1263 return Qnil;
1264}
1265
1266DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
3797b4c3
RS
1267 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
1268The value is actually the element of LIST whose car is KEY.\n\
7b863bd5
JB
1269Elements of LIST that are not conses are ignored.")
1270 (key, list)
1271 register Lisp_Object key;
1272 Lisp_Object list;
1273{
1274 register Lisp_Object tail;
bdd8d692 1275 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1276 {
1277 register Lisp_Object elt, tem;
1278 elt = Fcar (tail);
1279 if (!CONSP (elt)) continue;
bdd8d692 1280 tem = XCONS (elt)->car;
7b863bd5
JB
1281 if (EQ (key, tem)) return elt;
1282 QUIT;
1283 }
1284 return Qnil;
1285}
1286
1287/* Like Fassq but never report an error and do not allow quits.
1288 Use only on lists known never to be circular. */
1289
1290Lisp_Object
1291assq_no_quit (key, list)
1292 register Lisp_Object key;
1293 Lisp_Object list;
1294{
1295 register Lisp_Object tail;
bdd8d692 1296 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1297 {
1298 register Lisp_Object elt, tem;
1299 elt = Fcar (tail);
1300 if (!CONSP (elt)) continue;
bdd8d692 1301 tem = XCONS (elt)->car;
7b863bd5
JB
1302 if (EQ (key, tem)) return elt;
1303 }
1304 return Qnil;
1305}
1306
1307DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
3797b4c3 1308 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
0fb5a19c 1309The value is actually the element of LIST whose car equals KEY.")
7b863bd5
JB
1310 (key, list)
1311 register Lisp_Object key;
1312 Lisp_Object list;
1313{
1314 register Lisp_Object tail;
bdd8d692 1315 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1316 {
1317 register Lisp_Object elt, tem;
1318 elt = Fcar (tail);
1319 if (!CONSP (elt)) continue;
bdd8d692 1320 tem = Fequal (XCONS (elt)->car, key);
265a9e55 1321 if (!NILP (tem)) return elt;
7b863bd5
JB
1322 QUIT;
1323 }
1324 return Qnil;
1325}
1326
1327DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
1328 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
1329The value is actually the element of LIST whose cdr is ELT.")
1330 (key, list)
1331 register Lisp_Object key;
1332 Lisp_Object list;
1333{
1334 register Lisp_Object tail;
bdd8d692 1335 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
7b863bd5
JB
1336 {
1337 register Lisp_Object elt, tem;
1338 elt = Fcar (tail);
1339 if (!CONSP (elt)) continue;
bdd8d692 1340 tem = XCONS (elt)->cdr;
7b863bd5
JB
1341 if (EQ (key, tem)) return elt;
1342 QUIT;
1343 }
1344 return Qnil;
1345}
0fb5a19c
RS
1346
1347DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
1348 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
1349The value is actually the element of LIST whose cdr equals KEY.")
1350 (key, list)
1351 register Lisp_Object key;
1352 Lisp_Object list;
1353{
1354 register Lisp_Object tail;
bdd8d692 1355 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
0fb5a19c
RS
1356 {
1357 register Lisp_Object elt, tem;
1358 elt = Fcar (tail);
1359 if (!CONSP (elt)) continue;
bdd8d692 1360 tem = Fequal (XCONS (elt)->cdr, key);
0fb5a19c
RS
1361 if (!NILP (tem)) return elt;
1362 QUIT;
1363 }
1364 return Qnil;
1365}
7b863bd5
JB
1366\f
1367DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
1368 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1369The modified LIST is returned. Comparison is done with `eq'.\n\
1370If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
1371therefore, write `(setq foo (delq element foo))'\n\
1372to be sure of changing the value of `foo'.")
1373 (elt, list)
1374 register Lisp_Object elt;
1375 Lisp_Object list;
1376{
1377 register Lisp_Object tail, prev;
1378 register Lisp_Object tem;
1379
1380 tail = list;
1381 prev = Qnil;
265a9e55 1382 while (!NILP (tail))
7b863bd5
JB
1383 {
1384 tem = Fcar (tail);
1385 if (EQ (elt, tem))
1386 {
265a9e55 1387 if (NILP (prev))
bdd8d692 1388 list = XCONS (tail)->cdr;
7b863bd5 1389 else
bdd8d692 1390 Fsetcdr (prev, XCONS (tail)->cdr);
7b863bd5
JB
1391 }
1392 else
1393 prev = tail;
bdd8d692 1394 tail = XCONS (tail)->cdr;
7b863bd5
JB
1395 QUIT;
1396 }
1397 return list;
1398}
1399
ca8dd546 1400DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
1e134a5f
RM
1401 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1402The modified LIST is returned. Comparison is done with `equal'.\n\
1d58e36f
RS
1403If the first member of LIST is ELT, deleting it is not a side effect;\n\
1404it is simply using a different list.\n\
1405Therefore, write `(setq foo (delete element foo))'\n\
1e134a5f
RM
1406to be sure of changing the value of `foo'.")
1407 (elt, list)
1408 register Lisp_Object elt;
1409 Lisp_Object list;
1410{
1411 register Lisp_Object tail, prev;
1412 register Lisp_Object tem;
1413
1414 tail = list;
1415 prev = Qnil;
265a9e55 1416 while (!NILP (tail))
1e134a5f
RM
1417 {
1418 tem = Fcar (tail);
f812877e 1419 if (! NILP (Fequal (elt, tem)))
1e134a5f 1420 {
265a9e55 1421 if (NILP (prev))
bdd8d692 1422 list = XCONS (tail)->cdr;
1e134a5f 1423 else
bdd8d692 1424 Fsetcdr (prev, XCONS (tail)->cdr);
1e134a5f
RM
1425 }
1426 else
1427 prev = tail;
bdd8d692 1428 tail = XCONS (tail)->cdr;
1e134a5f
RM
1429 QUIT;
1430 }
1431 return list;
1432}
1433
7b863bd5
JB
1434DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
1435 "Reverse LIST by modifying cdr pointers.\n\
1436Returns the beginning of the reversed list.")
1437 (list)
1438 Lisp_Object list;
1439{
1440 register Lisp_Object prev, tail, next;
1441
265a9e55 1442 if (NILP (list)) return list;
7b863bd5
JB
1443 prev = Qnil;
1444 tail = list;
265a9e55 1445 while (!NILP (tail))
7b863bd5
JB
1446 {
1447 QUIT;
1448 next = Fcdr (tail);
1449 Fsetcdr (tail, prev);
1450 prev = tail;
1451 tail = next;
1452 }
1453 return prev;
1454}
1455
1456DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
1457 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
1458See also the function `nreverse', which is used more often.")
1459 (list)
1460 Lisp_Object list;
1461{
9d14ae76 1462 Lisp_Object new;
7b863bd5 1463
9d14ae76
RS
1464 for (new = Qnil; CONSP (list); list = XCONS (list)->cdr)
1465 new = Fcons (XCONS (list)->car, new);
1466 if (!NILP (list))
1467 wrong_type_argument (Qconsp, list);
1468 return new;
7b863bd5
JB
1469}
1470\f
1471Lisp_Object merge ();
1472
1473DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
1474 "Sort LIST, stably, comparing elements using PREDICATE.\n\
1475Returns the sorted list. LIST is modified by side effects.\n\
1476PREDICATE is called with two elements of LIST, and should return T\n\
1477if the first element is \"less\" than the second.")
88fe8140
EN
1478 (list, predicate)
1479 Lisp_Object list, predicate;
7b863bd5
JB
1480{
1481 Lisp_Object front, back;
1482 register Lisp_Object len, tem;
1483 struct gcpro gcpro1, gcpro2;
1484 register int length;
1485
1486 front = list;
1487 len = Flength (list);
1488 length = XINT (len);
1489 if (length < 2)
1490 return list;
1491
1492 XSETINT (len, (length / 2) - 1);
1493 tem = Fnthcdr (len, list);
1494 back = Fcdr (tem);
1495 Fsetcdr (tem, Qnil);
1496
1497 GCPRO2 (front, back);
88fe8140
EN
1498 front = Fsort (front, predicate);
1499 back = Fsort (back, predicate);
7b863bd5 1500 UNGCPRO;
88fe8140 1501 return merge (front, back, predicate);
7b863bd5
JB
1502}
1503
1504Lisp_Object
1505merge (org_l1, org_l2, pred)
1506 Lisp_Object org_l1, org_l2;
1507 Lisp_Object pred;
1508{
1509 Lisp_Object value;
1510 register Lisp_Object tail;
1511 Lisp_Object tem;
1512 register Lisp_Object l1, l2;
1513 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1514
1515 l1 = org_l1;
1516 l2 = org_l2;
1517 tail = Qnil;
1518 value = Qnil;
1519
1520 /* It is sufficient to protect org_l1 and org_l2.
1521 When l1 and l2 are updated, we copy the new values
1522 back into the org_ vars. */
1523 GCPRO4 (org_l1, org_l2, pred, value);
1524
1525 while (1)
1526 {
265a9e55 1527 if (NILP (l1))
7b863bd5
JB
1528 {
1529 UNGCPRO;
265a9e55 1530 if (NILP (tail))
7b863bd5
JB
1531 return l2;
1532 Fsetcdr (tail, l2);
1533 return value;
1534 }
265a9e55 1535 if (NILP (l2))
7b863bd5
JB
1536 {
1537 UNGCPRO;
265a9e55 1538 if (NILP (tail))
7b863bd5
JB
1539 return l1;
1540 Fsetcdr (tail, l1);
1541 return value;
1542 }
1543 tem = call2 (pred, Fcar (l2), Fcar (l1));
265a9e55 1544 if (NILP (tem))
7b863bd5
JB
1545 {
1546 tem = l1;
1547 l1 = Fcdr (l1);
1548 org_l1 = l1;
1549 }
1550 else
1551 {
1552 tem = l2;
1553 l2 = Fcdr (l2);
1554 org_l2 = l2;
1555 }
265a9e55 1556 if (NILP (tail))
7b863bd5
JB
1557 value = tem;
1558 else
1559 Fsetcdr (tail, tem);
1560 tail = tem;
1561 }
1562}
1563\f
be9d483d
BG
1564
1565DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
1fbb64aa 1566 "Extract a value from a property list.\n\
be9d483d 1567PLIST is a property list, which is a list of the form\n\
c07289e0 1568\(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
be9d483d
BG
1569corresponding to the given PROP, or nil if PROP is not\n\
1570one of the properties on the list.")
1fbb64aa
EN
1571 (plist, prop)
1572 Lisp_Object plist;
7b863bd5
JB
1573 register Lisp_Object prop;
1574{
1575 register Lisp_Object tail;
bdd8d692 1576 for (tail = plist; !NILP (tail); tail = Fcdr (XCONS (tail)->cdr))
7b863bd5
JB
1577 {
1578 register Lisp_Object tem;
1579 tem = Fcar (tail);
1580 if (EQ (prop, tem))
bdd8d692 1581 return Fcar (XCONS (tail)->cdr);
7b863bd5
JB
1582 }
1583 return Qnil;
1584}
1585
be9d483d
BG
1586DEFUN ("get", Fget, Sget, 2, 2, 0,
1587 "Return the value of SYMBOL's PROPNAME property.\n\
c07289e0
RS
1588This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
1589 (symbol, propname)
1590 Lisp_Object symbol, propname;
be9d483d 1591{
c07289e0
RS
1592 CHECK_SYMBOL (symbol, 0);
1593 return Fplist_get (XSYMBOL (symbol)->plist, propname);
be9d483d
BG
1594}
1595
1596DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
1597 "Change value in PLIST of PROP to VAL.\n\
1598PLIST is a property list, which is a list of the form\n\
c07289e0 1599\(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
be9d483d 1600If PROP is already a property on the list, its value is set to VAL,\n\
88435890 1601otherwise the new PROP VAL pair is added. The new plist is returned;\n\
be9d483d
BG
1602use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
1603The PLIST is modified by side effects.")
1604 (plist, prop, val)
b4f334f7
KH
1605 Lisp_Object plist;
1606 register Lisp_Object prop;
1607 Lisp_Object val;
7b863bd5
JB
1608{
1609 register Lisp_Object tail, prev;
1610 Lisp_Object newcell;
1611 prev = Qnil;
f8307c0c
KH
1612 for (tail = plist; CONSP (tail) && CONSP (XCONS (tail)->cdr);
1613 tail = XCONS (XCONS (tail)->cdr)->cdr)
7b863bd5 1614 {
f8307c0c 1615 if (EQ (prop, XCONS (tail)->car))
be9d483d 1616 {
f8307c0c 1617 Fsetcar (XCONS (tail)->cdr, val);
be9d483d
BG
1618 return plist;
1619 }
7b863bd5
JB
1620 prev = tail;
1621 }
1622 newcell = Fcons (prop, Fcons (val, Qnil));
265a9e55 1623 if (NILP (prev))
be9d483d 1624 return newcell;
7b863bd5 1625 else
f8307c0c 1626 Fsetcdr (XCONS (prev)->cdr, newcell);
be9d483d
BG
1627 return plist;
1628}
1629
1630DEFUN ("put", Fput, Sput, 3, 3, 0,
1631 "Store SYMBOL's PROPNAME property with value VALUE.\n\
1632It can be retrieved with `(get SYMBOL PROPNAME)'.")
c07289e0
RS
1633 (symbol, propname, value)
1634 Lisp_Object symbol, propname, value;
be9d483d 1635{
c07289e0
RS
1636 CHECK_SYMBOL (symbol, 0);
1637 XSYMBOL (symbol)->plist
1638 = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
1639 return value;
7b863bd5
JB
1640}
1641
1642DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
ea35ce3d 1643 "Return t if two Lisp objects have similar structure and contents.\n\
7b863bd5
JB
1644They must have the same data type.\n\
1645Conses are compared by comparing the cars and the cdrs.\n\
1646Vectors and strings are compared element by element.\n\
d28c4332
RS
1647Numbers are compared by value, but integers cannot equal floats.\n\
1648 (Use `=' if you want integers and floats to be able to be equal.)\n\
1649Symbols must match exactly.")
7b863bd5
JB
1650 (o1, o2)
1651 register Lisp_Object o1, o2;
1652{
6cb9cafb 1653 return internal_equal (o1, o2, 0) ? Qt : Qnil;
e0f5cf5a
RS
1654}
1655
6cb9cafb 1656static int
e0f5cf5a
RS
1657internal_equal (o1, o2, depth)
1658 register Lisp_Object o1, o2;
1659 int depth;
1660{
1661 if (depth > 200)
1662 error ("Stack overflow in equal");
4ff1aed9 1663
6cb9cafb 1664 tail_recurse:
7b863bd5 1665 QUIT;
4ff1aed9
RS
1666 if (EQ (o1, o2))
1667 return 1;
1668 if (XTYPE (o1) != XTYPE (o2))
1669 return 0;
1670
1671 switch (XTYPE (o1))
1672 {
31ef7f7a 1673#ifdef LISP_FLOAT_TYPE
4ff1aed9
RS
1674 case Lisp_Float:
1675 return (extract_float (o1) == extract_float (o2));
31ef7f7a 1676#endif
4ff1aed9
RS
1677
1678 case Lisp_Cons:
4cab5074
KH
1679 if (!internal_equal (XCONS (o1)->car, XCONS (o2)->car, depth + 1))
1680 return 0;
1681 o1 = XCONS (o1)->cdr;
1682 o2 = XCONS (o2)->cdr;
1683 goto tail_recurse;
4ff1aed9
RS
1684
1685 case Lisp_Misc:
81d1fba6 1686 if (XMISCTYPE (o1) != XMISCTYPE (o2))
6cb9cafb 1687 return 0;
4ff1aed9 1688 if (OVERLAYP (o1))
7b863bd5 1689 {
4ff1aed9
RS
1690 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o1),
1691 depth + 1)
1692 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o1),
1693 depth + 1))
6cb9cafb 1694 return 0;
4ff1aed9
RS
1695 o1 = XOVERLAY (o1)->plist;
1696 o2 = XOVERLAY (o2)->plist;
1697 goto tail_recurse;
7b863bd5 1698 }
4ff1aed9
RS
1699 if (MARKERP (o1))
1700 {
1701 return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
1702 && (XMARKER (o1)->buffer == 0
6ced1284 1703 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
4ff1aed9
RS
1704 }
1705 break;
1706
1707 case Lisp_Vectorlike:
4cab5074
KH
1708 {
1709 register int i, size;
1710 size = XVECTOR (o1)->size;
1711 /* Pseudovectors have the type encoded in the size field, so this test
1712 actually checks that the objects have the same type as well as the
1713 same size. */
1714 if (XVECTOR (o2)->size != size)
1715 return 0;
e03f7933
RS
1716 /* Boolvectors are compared much like strings. */
1717 if (BOOL_VECTOR_P (o1))
1718 {
e03f7933 1719 int size_in_chars
e22e4283 1720 = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
1721
1722 if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
1723 return 0;
1724 if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
1725 size_in_chars))
1726 return 0;
1727 return 1;
1728 }
ed73fcc1 1729 if (WINDOW_CONFIGURATIONP (o1))
48646924 1730 return compare_window_configurations (o1, o2, 0);
e03f7933
RS
1731
1732 /* Aside from them, only true vectors, char-tables, and compiled
1733 functions are sensible to compare, so eliminate the others now. */
4cab5074
KH
1734 if (size & PSEUDOVECTOR_FLAG)
1735 {
e03f7933 1736 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
4cab5074
KH
1737 return 0;
1738 size &= PSEUDOVECTOR_SIZE_MASK;
1739 }
1740 for (i = 0; i < size; i++)
1741 {
1742 Lisp_Object v1, v2;
1743 v1 = XVECTOR (o1)->contents [i];
1744 v2 = XVECTOR (o2)->contents [i];
1745 if (!internal_equal (v1, v2, depth + 1))
1746 return 0;
1747 }
1748 return 1;
1749 }
4ff1aed9
RS
1750 break;
1751
1752 case Lisp_String:
4cab5074
KH
1753 if (XSTRING (o1)->size != XSTRING (o2)->size)
1754 return 0;
fc932ac6 1755 if (STRING_BYTES (XSTRING (o1)) != STRING_BYTES (XSTRING (o2)))
ea35ce3d 1756 return 0;
4cab5074 1757 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
fc932ac6 1758 STRING_BYTES (XSTRING (o1))))
4cab5074 1759 return 0;
4cab5074 1760 return 1;
7b863bd5 1761 }
6cb9cafb 1762 return 0;
7b863bd5
JB
1763}
1764\f
2e34157c
RS
1765extern Lisp_Object Fmake_char_internal ();
1766
7b863bd5 1767DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
e03f7933
RS
1768 "Store each element of ARRAY with ITEM.\n\
1769ARRAY is a vector, string, char-table, or bool-vector.")
7b863bd5
JB
1770 (array, item)
1771 Lisp_Object array, item;
1772{
1773 register int size, index, charval;
1774 retry:
7650760e 1775 if (VECTORP (array))
7b863bd5
JB
1776 {
1777 register Lisp_Object *p = XVECTOR (array)->contents;
1778 size = XVECTOR (array)->size;
1779 for (index = 0; index < size; index++)
1780 p[index] = item;
1781 }
e03f7933
RS
1782 else if (CHAR_TABLE_P (array))
1783 {
1784 register Lisp_Object *p = XCHAR_TABLE (array)->contents;
1785 size = CHAR_TABLE_ORDINARY_SLOTS;
1786 for (index = 0; index < size; index++)
1787 p[index] = item;
1788 XCHAR_TABLE (array)->defalt = Qnil;
1789 }
7650760e 1790 else if (STRINGP (array))
7b863bd5
JB
1791 {
1792 register unsigned char *p = XSTRING (array)->data;
1793 CHECK_NUMBER (item, 1);
1794 charval = XINT (item);
1795 size = XSTRING (array)->size;
57247650
KH
1796 if (STRING_MULTIBYTE (array))
1797 {
1798 unsigned char workbuf[4], *str;
1799 int len = CHAR_STRING (charval, workbuf, str);
1800 int size_byte = STRING_BYTES (XSTRING (array));
1801 unsigned char *p1 = p, *endp = p + size_byte;
95b8aba7 1802 int i;
57247650 1803
95b8aba7
KH
1804 if (size != size_byte)
1805 while (p1 < endp)
1806 {
1807 int this_len = MULTIBYTE_FORM_LENGTH (p1, endp - p1);
1808 if (len != this_len)
1809 error ("Attempt to change byte length of a string");
1810 p1 += this_len;
1811 }
57247650
KH
1812 for (i = 0; i < size_byte; i++)
1813 *p++ = str[i % len];
1814 }
1815 else
1816 for (index = 0; index < size; index++)
1817 p[index] = charval;
7b863bd5 1818 }
e03f7933
RS
1819 else if (BOOL_VECTOR_P (array))
1820 {
1821 register unsigned char *p = XBOOL_VECTOR (array)->data;
e03f7933 1822 int size_in_chars
e22e4283 1823 = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
e03f7933
RS
1824
1825 charval = (! NILP (item) ? -1 : 0);
1826 for (index = 0; index < size_in_chars; index++)
1827 p[index] = charval;
1828 }
7b863bd5
JB
1829 else
1830 {
1831 array = wrong_type_argument (Qarrayp, array);
1832 goto retry;
1833 }
1834 return array;
1835}
ea35ce3d 1836\f
999de246
RS
1837DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
1838 1, 1, 0,
1839 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
88fe8140
EN
1840 (char_table)
1841 Lisp_Object char_table;
999de246 1842{
b4f334f7 1843 CHECK_CHAR_TABLE (char_table, 0);
999de246 1844
88fe8140 1845 return XCHAR_TABLE (char_table)->purpose;
999de246
RS
1846}
1847
e03f7933
RS
1848DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
1849 1, 1, 0,
1850 "Return the parent char-table of CHAR-TABLE.\n\
1851The value is either nil or another char-table.\n\
1852If CHAR-TABLE holds nil for a given character,\n\
1853then the actual applicable value is inherited from the parent char-table\n\
1854\(or from its parents, if necessary).")
88fe8140
EN
1855 (char_table)
1856 Lisp_Object char_table;
e03f7933 1857{
b4f334f7 1858 CHECK_CHAR_TABLE (char_table, 0);
e03f7933 1859
88fe8140 1860 return XCHAR_TABLE (char_table)->parent;
e03f7933
RS
1861}
1862
1863DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
1864 2, 2, 0,
1865 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
1866PARENT must be either nil or another char-table.")
88fe8140
EN
1867 (char_table, parent)
1868 Lisp_Object char_table, parent;
e03f7933
RS
1869{
1870 Lisp_Object temp;
1871
b4f334f7 1872 CHECK_CHAR_TABLE (char_table, 0);
e03f7933 1873
c8640abf
RS
1874 if (!NILP (parent))
1875 {
b4f334f7 1876 CHECK_CHAR_TABLE (parent, 0);
c8640abf
RS
1877
1878 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
55cc974d 1879 if (EQ (temp, char_table))
c8640abf
RS
1880 error ("Attempt to make a chartable be its own parent");
1881 }
e03f7933 1882
88fe8140 1883 XCHAR_TABLE (char_table)->parent = parent;
e03f7933
RS
1884
1885 return parent;
1886}
1887
1888DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
1889 2, 2, 0,
25c30748 1890 "Return the value of CHAR-TABLE's extra-slot number N.")
88fe8140
EN
1891 (char_table, n)
1892 Lisp_Object char_table, n;
e03f7933 1893{
88fe8140 1894 CHECK_CHAR_TABLE (char_table, 1);
e03f7933
RS
1895 CHECK_NUMBER (n, 2);
1896 if (XINT (n) < 0
88fe8140
EN
1897 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1898 args_out_of_range (char_table, n);
e03f7933 1899
88fe8140 1900 return XCHAR_TABLE (char_table)->extras[XINT (n)];
e03f7933
RS
1901}
1902
1903DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
1904 Sset_char_table_extra_slot,
1905 3, 3, 0,
25c30748 1906 "Set CHAR-TABLE's extra-slot number N to VALUE.")
88fe8140
EN
1907 (char_table, n, value)
1908 Lisp_Object char_table, n, value;
e03f7933 1909{
88fe8140 1910 CHECK_CHAR_TABLE (char_table, 1);
e03f7933
RS
1911 CHECK_NUMBER (n, 2);
1912 if (XINT (n) < 0
88fe8140
EN
1913 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1914 args_out_of_range (char_table, n);
e03f7933 1915
88fe8140 1916 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
e03f7933 1917}
ea35ce3d 1918\f
999de246
RS
1919DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
1920 2, 2, 0,
88fe8140 1921 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
6d475204 1922RANGE should be nil (for the default value)\n\
999de246 1923a vector which identifies a character set or a row of a character set,\n\
6d475204 1924a character set name, or a character code.")
88fe8140
EN
1925 (char_table, range)
1926 Lisp_Object char_table, range;
999de246
RS
1927{
1928 int i;
1929
88fe8140 1930 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 1931
999de246 1932 if (EQ (range, Qnil))
88fe8140 1933 return XCHAR_TABLE (char_table)->defalt;
999de246 1934 else if (INTEGERP (range))
88fe8140 1935 return Faref (char_table, range);
6d475204
RS
1936 else if (SYMBOLP (range))
1937 {
1938 Lisp_Object charset_info;
1939
1940 charset_info = Fget (range, Qcharset);
1941 CHECK_VECTOR (charset_info, 0);
1942
21ab867f
AS
1943 return Faref (char_table,
1944 make_number (XINT (XVECTOR (charset_info)->contents[0])
1945 + 128));
6d475204 1946 }
999de246
RS
1947 else if (VECTORP (range))
1948 {
e814a159 1949 if (XVECTOR (range)->size == 1)
21ab867f
AS
1950 return Faref (char_table,
1951 make_number (XINT (XVECTOR (range)->contents[0]) + 128));
e814a159
RS
1952 else
1953 {
1954 int size = XVECTOR (range)->size;
1955 Lisp_Object *val = XVECTOR (range)->contents;
1956 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1957 size <= 1 ? Qnil : val[1],
1958 size <= 2 ? Qnil : val[2]);
1959 return Faref (char_table, ch);
1960 }
999de246
RS
1961 }
1962 else
1963 error ("Invalid RANGE argument to `char-table-range'");
1964}
1965
e03f7933
RS
1966DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
1967 3, 3, 0,
88fe8140 1968 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
e03f7933
RS
1969RANGE should be t (for all characters), nil (for the default value)\n\
1970a vector which identifies a character set or a row of a character set,\n\
6d475204 1971a coding system, or a character code.")
88fe8140
EN
1972 (char_table, range, value)
1973 Lisp_Object char_table, range, value;
e03f7933
RS
1974{
1975 int i;
1976
88fe8140 1977 CHECK_CHAR_TABLE (char_table, 0);
b4f334f7 1978
e03f7933
RS
1979 if (EQ (range, Qt))
1980 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
88fe8140 1981 XCHAR_TABLE (char_table)->contents[i] = value;
e03f7933 1982 else if (EQ (range, Qnil))
88fe8140 1983 XCHAR_TABLE (char_table)->defalt = value;
6d475204
RS
1984 else if (SYMBOLP (range))
1985 {
1986 Lisp_Object charset_info;
1987
1988 charset_info = Fget (range, Qcharset);
1989 CHECK_VECTOR (charset_info, 0);
1990
21ab867f
AS
1991 return Faset (char_table,
1992 make_number (XINT (XVECTOR (charset_info)->contents[0])
1993 + 128),
6d475204
RS
1994 value);
1995 }
e03f7933 1996 else if (INTEGERP (range))
88fe8140 1997 Faset (char_table, range, value);
e03f7933
RS
1998 else if (VECTORP (range))
1999 {
e814a159 2000 if (XVECTOR (range)->size == 1)
21ab867f
AS
2001 return Faset (char_table,
2002 make_number (XINT (XVECTOR (range)->contents[0]) + 128),
2003 value);
e814a159
RS
2004 else
2005 {
2006 int size = XVECTOR (range)->size;
2007 Lisp_Object *val = XVECTOR (range)->contents;
2008 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
2009 size <= 1 ? Qnil : val[1],
2010 size <= 2 ? Qnil : val[2]);
2011 return Faset (char_table, ch, value);
2012 }
e03f7933
RS
2013 }
2014 else
2015 error ("Invalid RANGE argument to `set-char-table-range'");
2016
2017 return value;
2018}
e1335ba2
KH
2019
2020DEFUN ("set-char-table-default", Fset_char_table_default,
2021 Sset_char_table_default, 3, 3, 0,
2022 "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
2023The generic character specifies the group of characters.\n\
2024See also the documentation of make-char.")
2025 (char_table, ch, value)
2026 Lisp_Object char_table, ch, value;
2027{
2028 int c, i, charset, code1, code2;
2029 Lisp_Object temp;
2030
2031 CHECK_CHAR_TABLE (char_table, 0);
2032 CHECK_NUMBER (ch, 1);
2033
2034 c = XINT (ch);
2db66414 2035 SPLIT_CHAR (c, charset, code1, code2);
0da528a9
KH
2036
2037 /* Since we may want to set the default value for a character set
2038 not yet defined, we check only if the character set is in the
2039 valid range or not, instead of it is already defined or not. */
2040 if (! CHARSET_VALID_P (charset))
f71599f4 2041 invalid_character (c);
e1335ba2
KH
2042
2043 if (charset == CHARSET_ASCII)
2044 return (XCHAR_TABLE (char_table)->defalt = value);
2045
2046 /* Even if C is not a generic char, we had better behave as if a
2047 generic char is specified. */
0da528a9 2048 if (charset == CHARSET_COMPOSITION || CHARSET_DIMENSION (charset) == 1)
e1335ba2
KH
2049 code1 = 0;
2050 temp = XCHAR_TABLE (char_table)->contents[charset + 128];
2051 if (!code1)
2052 {
2053 if (SUB_CHAR_TABLE_P (temp))
2054 XCHAR_TABLE (temp)->defalt = value;
2055 else
2056 XCHAR_TABLE (char_table)->contents[charset + 128] = value;
2057 return value;
2058 }
2059 char_table = temp;
2060 if (! SUB_CHAR_TABLE_P (char_table))
2061 char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
2062 = make_sub_char_table (temp));
2063 temp = XCHAR_TABLE (char_table)->contents[code1];
2064 if (SUB_CHAR_TABLE_P (temp))
2065 XCHAR_TABLE (temp)->defalt = value;
2066 else
2067 XCHAR_TABLE (char_table)->contents[code1] = value;
2068 return value;
2069}
1d969a23
RS
2070
2071/* Look up the element in TABLE at index CH,
2072 and return it as an integer.
2073 If the element is nil, return CH itself.
2074 (Actually we do that for any non-integer.) */
2075
2076int
2077char_table_translate (table, ch)
2078 Lisp_Object table;
2079 int ch;
2080{
2081 Lisp_Object value;
2082 value = Faref (table, make_number (ch));
2083 if (! INTEGERP (value))
2084 return ch;
2085 return XINT (value);
2086}
e03f7933 2087\f
46ed603f 2088/* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
c8640abf
RS
2089 character or group of characters that share a value.
2090 DEPTH is the current depth in the originally specified
2091 chartable, and INDICES contains the vector indices
46ed603f
RS
2092 for the levels our callers have descended.
2093
2094 ARG is passed to C_FUNCTION when that is called. */
c8640abf
RS
2095
2096void
46ed603f 2097map_char_table (c_function, function, subtable, arg, depth, indices)
22e6f12b
AS
2098 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
2099 Lisp_Object function, subtable, arg, *indices;
1847b19b 2100 int depth;
e03f7933 2101{
3720677d 2102 int i, to;
e03f7933 2103
a8283a4a 2104 if (depth == 0)
3720677d
KH
2105 {
2106 /* At first, handle ASCII and 8-bit European characters. */
2107 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
2108 {
46ed603f 2109 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
3720677d 2110 if (c_function)
46ed603f 2111 (*c_function) (arg, make_number (i), elt);
3720677d
KH
2112 else
2113 call2 (function, make_number (i), elt);
2114 }
ea35ce3d
RS
2115#if 0 /* If the char table has entries for higher characters,
2116 we should report them. */
de86fcba
KH
2117 if (NILP (current_buffer->enable_multibyte_characters))
2118 return;
ea35ce3d 2119#endif
3720677d
KH
2120 to = CHAR_TABLE_ORDINARY_SLOTS;
2121 }
a8283a4a 2122 else
e03f7933 2123 {
de86fcba 2124 i = 32;
3720677d 2125 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
e03f7933
RS
2126 }
2127
7e798f25 2128 for (; i < to; i++)
e03f7933 2129 {
46ed603f 2130 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
3720677d 2131
09ee221d 2132 XSETFASTINT (indices[depth], i);
3720677d
KH
2133
2134 if (SUB_CHAR_TABLE_P (elt))
2135 {
2136 if (depth >= 3)
2137 error ("Too deep char table");
7e798f25 2138 map_char_table (c_function, function, elt, arg, depth + 1, indices);
3720677d 2139 }
e03f7933 2140 else
a8283a4a 2141 {
3720677d
KH
2142 int charset = XFASTINT (indices[0]) - 128, c1, c2, c;
2143
a8283a4a
KH
2144 if (CHARSET_DEFINED_P (charset))
2145 {
3720677d
KH
2146 c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
2147 c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
a8283a4a 2148 c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
3720677d 2149 if (c_function)
46ed603f 2150 (*c_function) (arg, make_number (c), elt);
3720677d
KH
2151 else
2152 call2 (function, make_number (c), elt);
a8283a4a 2153 }
b4f334f7 2154 }
e03f7933
RS
2155 }
2156}
2157
2158DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
2159 2, 2, 0,
7e798f25 2160 "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
e03f7933 2161FUNCTION is called with two arguments--a key and a value.\n\
7e798f25 2162The key is always a possible IDX argument to `aref'.")
88fe8140
EN
2163 (function, char_table)
2164 Lisp_Object function, char_table;
e03f7933 2165{
3720677d 2166 /* The depth of char table is at most 3. */
7e798f25
KH
2167 Lisp_Object indices[3];
2168
2169 CHECK_CHAR_TABLE (char_table, 1);
e03f7933 2170
46ed603f 2171 map_char_table (NULL, function, char_table, char_table, 0, indices);
e03f7933
RS
2172 return Qnil;
2173}
2174\f
7b863bd5
JB
2175/* ARGSUSED */
2176Lisp_Object
2177nconc2 (s1, s2)
2178 Lisp_Object s1, s2;
2179{
2180#ifdef NO_ARG_ARRAY
2181 Lisp_Object args[2];
2182 args[0] = s1;
2183 args[1] = s2;
2184 return Fnconc (2, args);
2185#else
2186 return Fnconc (2, &s1);
2187#endif /* NO_ARG_ARRAY */
2188}
2189
2190DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
2191 "Concatenate any number of lists by altering them.\n\
2192Only the last argument is not altered, and need not be a list.")
2193 (nargs, args)
2194 int nargs;
2195 Lisp_Object *args;
2196{
2197 register int argnum;
2198 register Lisp_Object tail, tem, val;
2199
2200 val = Qnil;
2201
2202 for (argnum = 0; argnum < nargs; argnum++)
2203 {
2204 tem = args[argnum];
265a9e55 2205 if (NILP (tem)) continue;
7b863bd5 2206
265a9e55 2207 if (NILP (val))
7b863bd5
JB
2208 val = tem;
2209
2210 if (argnum + 1 == nargs) break;
2211
2212 if (!CONSP (tem))
2213 tem = wrong_type_argument (Qlistp, tem);
2214
2215 while (CONSP (tem))
2216 {
2217 tail = tem;
2218 tem = Fcdr (tail);
2219 QUIT;
2220 }
2221
2222 tem = args[argnum + 1];
2223 Fsetcdr (tail, tem);
265a9e55 2224 if (NILP (tem))
7b863bd5
JB
2225 args[argnum + 1] = tail;
2226 }
2227
2228 return val;
2229}
2230\f
2231/* This is the guts of all mapping functions.
ea35ce3d
RS
2232 Apply FN to each element of SEQ, one by one,
2233 storing the results into elements of VALS, a C vector of Lisp_Objects.
2234 LENI is the length of VALS, which should also be the length of SEQ. */
7b863bd5
JB
2235
2236static void
2237mapcar1 (leni, vals, fn, seq)
2238 int leni;
2239 Lisp_Object *vals;
2240 Lisp_Object fn, seq;
2241{
2242 register Lisp_Object tail;
2243 Lisp_Object dummy;
2244 register int i;
2245 struct gcpro gcpro1, gcpro2, gcpro3;
2246
2247 /* Don't let vals contain any garbage when GC happens. */
2248 for (i = 0; i < leni; i++)
2249 vals[i] = Qnil;
2250
2251 GCPRO3 (dummy, fn, seq);
2252 gcpro1.var = vals;
2253 gcpro1.nvars = leni;
2254 /* We need not explicitly protect `tail' because it is used only on lists, and
2255 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
2256
7650760e 2257 if (VECTORP (seq))
7b863bd5
JB
2258 {
2259 for (i = 0; i < leni; i++)
2260 {
2261 dummy = XVECTOR (seq)->contents[i];
2262 vals[i] = call1 (fn, dummy);
2263 }
2264 }
33aa0881
KH
2265 else if (BOOL_VECTOR_P (seq))
2266 {
2267 for (i = 0; i < leni; i++)
2268 {
2269 int byte;
2270 byte = XBOOL_VECTOR (seq)->data[i / BITS_PER_CHAR];
2271 if (byte & (1 << (i % BITS_PER_CHAR)))
2272 dummy = Qt;
2273 else
2274 dummy = Qnil;
2275
2276 vals[i] = call1 (fn, dummy);
2277 }
2278 }
ea35ce3d 2279 else if (STRINGP (seq) && ! STRING_MULTIBYTE (seq))
7b863bd5 2280 {
ea35ce3d 2281 /* Single-byte string. */
7b863bd5
JB
2282 for (i = 0; i < leni; i++)
2283 {
ad17573a 2284 XSETFASTINT (dummy, XSTRING (seq)->data[i]);
7b863bd5
JB
2285 vals[i] = call1 (fn, dummy);
2286 }
2287 }
ea35ce3d
RS
2288 else if (STRINGP (seq))
2289 {
2290 /* Multi-byte string. */
fc932ac6 2291 int len_byte = STRING_BYTES (XSTRING (seq));
ea35ce3d
RS
2292 int i_byte;
2293
2294 for (i = 0, i_byte = 0; i < leni;)
2295 {
2296 int c;
0ab6a3d8
KH
2297 int i_before = i;
2298
2299 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte);
ea35ce3d 2300 XSETFASTINT (dummy, c);
0ab6a3d8 2301 vals[i_before] = call1 (fn, dummy);
ea35ce3d
RS
2302 }
2303 }
7b863bd5
JB
2304 else /* Must be a list, since Flength did not get an error */
2305 {
2306 tail = seq;
2307 for (i = 0; i < leni; i++)
2308 {
2309 vals[i] = call1 (fn, Fcar (tail));
bdd8d692 2310 tail = XCONS (tail)->cdr;
7b863bd5
JB
2311 }
2312 }
2313
2314 UNGCPRO;
2315}
2316
2317DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
88fe8140
EN
2318 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2319In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
33aa0881
KH
2320SEPARATOR results in spaces between the values returned by FUNCTION.\n\
2321SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2322 (function, sequence, separator)
2323 Lisp_Object function, sequence, separator;
7b863bd5
JB
2324{
2325 Lisp_Object len;
2326 register int leni;
2327 int nargs;
2328 register Lisp_Object *args;
2329 register int i;
2330 struct gcpro gcpro1;
2331
88fe8140 2332 len = Flength (sequence);
7b863bd5
JB
2333 leni = XINT (len);
2334 nargs = leni + leni - 1;
2335 if (nargs < 0) return build_string ("");
2336
2337 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2338
88fe8140
EN
2339 GCPRO1 (separator);
2340 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2341 UNGCPRO;
2342
2343 for (i = leni - 1; i >= 0; i--)
2344 args[i + i] = args[i];
b4f334f7 2345
7b863bd5 2346 for (i = 1; i < nargs; i += 2)
88fe8140 2347 args[i] = separator;
7b863bd5
JB
2348
2349 return Fconcat (nargs, args);
2350}
2351
2352DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2353 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2354The result is a list just as long as SEQUENCE.\n\
33aa0881 2355SEQUENCE may be a list, a vector, a bool-vector, or a string.")
88fe8140
EN
2356 (function, sequence)
2357 Lisp_Object function, sequence;
7b863bd5
JB
2358{
2359 register Lisp_Object len;
2360 register int leni;
2361 register Lisp_Object *args;
2362
88fe8140 2363 len = Flength (sequence);
7b863bd5
JB
2364 leni = XFASTINT (len);
2365 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2366
88fe8140 2367 mapcar1 (leni, args, function, sequence);
7b863bd5
JB
2368
2369 return Flist (leni, args);
2370}
2371\f
2372/* Anything that calls this function must protect from GC! */
2373
2374DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2375 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
c763f396
RS
2376Takes one argument, which is the string to display to ask the question.\n\
2377It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
7b863bd5
JB
2378No confirmation of the answer is requested; a single character is enough.\n\
2379Also accepts Space to mean yes, or Delete to mean no.")
2380 (prompt)
2381 Lisp_Object prompt;
2382{
f5313ed9
RS
2383 register Lisp_Object obj, key, def, answer_string, map;
2384 register int answer;
7b863bd5
JB
2385 Lisp_Object xprompt;
2386 Lisp_Object args[2];
7b863bd5 2387 struct gcpro gcpro1, gcpro2;
eb4ffa4e
RS
2388 int count = specpdl_ptr - specpdl;
2389
2390 specbind (Qcursor_in_echo_area, Qt);
7b863bd5 2391
f5313ed9
RS
2392 map = Fsymbol_value (intern ("query-replace-map"));
2393
7b863bd5
JB
2394 CHECK_STRING (prompt, 0);
2395 xprompt = prompt;
2396 GCPRO2 (prompt, xprompt);
2397
2398 while (1)
2399 {
eb4ffa4e 2400
0ef68e8a 2401#ifdef HAVE_MENUS
588064ce 2402 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2403 && use_dialog_box
0ef68e8a 2404 && have_menus_p ())
1db4cfb2
RS
2405 {
2406 Lisp_Object pane, menu;
a3b14a45 2407 redisplay_preserve_echo_area ();
1db4cfb2
RS
2408 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2409 Fcons (Fcons (build_string ("No"), Qnil),
2410 Qnil));
ec26e1b9 2411 menu = Fcons (prompt, pane);
d2f28f78 2412 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2413 answer = !NILP (obj);
2414 break;
2415 }
0ef68e8a 2416#endif /* HAVE_MENUS */
dfa89228 2417 cursor_in_echo_area = 1;
b312cc52 2418 choose_minibuf_frame ();
ea35ce3d 2419 message_with_string ("%s(y or n) ", xprompt, 0);
7b863bd5 2420
2d8e7e1f
RS
2421 if (minibuffer_auto_raise)
2422 {
2423 Lisp_Object mini_frame;
2424
2425 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2426
2427 Fraise_frame (mini_frame);
2428 }
2429
7ba13c57 2430 obj = read_filtered_event (1, 0, 0, 0);
dfa89228
KH
2431 cursor_in_echo_area = 0;
2432 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2433 QUIT;
a63f658b 2434
f5313ed9 2435 key = Fmake_vector (make_number (1), obj);
aad2a123 2436 def = Flookup_key (map, key, Qt);
f5313ed9 2437 answer_string = Fsingle_key_description (obj);
7b863bd5 2438
f5313ed9
RS
2439 if (EQ (def, intern ("skip")))
2440 {
2441 answer = 0;
2442 break;
2443 }
2444 else if (EQ (def, intern ("act")))
2445 {
2446 answer = 1;
2447 break;
2448 }
29944b73
RS
2449 else if (EQ (def, intern ("recenter")))
2450 {
2451 Frecenter (Qnil);
2452 xprompt = prompt;
2453 continue;
2454 }
f5313ed9 2455 else if (EQ (def, intern ("quit")))
7b863bd5 2456 Vquit_flag = Qt;
ec63af1b
RS
2457 /* We want to exit this command for exit-prefix,
2458 and this is the only way to do it. */
2459 else if (EQ (def, intern ("exit-prefix")))
2460 Vquit_flag = Qt;
f5313ed9 2461
7b863bd5 2462 QUIT;
20aa96aa
JB
2463
2464 /* If we don't clear this, then the next call to read_char will
2465 return quit_char again, and we'll enter an infinite loop. */
088880f1 2466 Vquit_flag = Qnil;
7b863bd5
JB
2467
2468 Fding (Qnil);
2469 Fdiscard_input ();
2470 if (EQ (xprompt, prompt))
2471 {
2472 args[0] = build_string ("Please answer y or n. ");
2473 args[1] = prompt;
2474 xprompt = Fconcat (2, args);
2475 }
2476 }
2477 UNGCPRO;
6a8a9750 2478
09c95874
RS
2479 if (! noninteractive)
2480 {
2481 cursor_in_echo_area = -1;
ea35ce3d
RS
2482 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2483 xprompt, 0);
09c95874 2484 }
6a8a9750 2485
eb4ffa4e 2486 unbind_to (count, Qnil);
f5313ed9 2487 return answer ? Qt : Qnil;
7b863bd5
JB
2488}
2489\f
2490/* This is how C code calls `yes-or-no-p' and allows the user
2491 to redefined it.
2492
2493 Anything that calls this function must protect from GC! */
2494
2495Lisp_Object
2496do_yes_or_no_p (prompt)
2497 Lisp_Object prompt;
2498{
2499 return call1 (intern ("yes-or-no-p"), prompt);
2500}
2501
2502/* Anything that calls this function must protect from GC! */
2503
2504DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
c763f396
RS
2505 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2506Takes one argument, which is the string to display to ask the question.\n\
2507It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2508The user must confirm the answer with RET,\n\
d8616fc1 2509and can edit it until it has been confirmed.")
7b863bd5
JB
2510 (prompt)
2511 Lisp_Object prompt;
2512{
2513 register Lisp_Object ans;
2514 Lisp_Object args[2];
2515 struct gcpro gcpro1;
1db4cfb2 2516 Lisp_Object menu;
7b863bd5
JB
2517
2518 CHECK_STRING (prompt, 0);
2519
0ef68e8a 2520#ifdef HAVE_MENUS
b4f334f7 2521 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
bdd8d692 2522 && use_dialog_box
0ef68e8a 2523 && have_menus_p ())
1db4cfb2
RS
2524 {
2525 Lisp_Object pane, menu, obj;
a3b14a45 2526 redisplay_preserve_echo_area ();
1db4cfb2
RS
2527 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2528 Fcons (Fcons (build_string ("No"), Qnil),
2529 Qnil));
2530 GCPRO1 (pane);
ec26e1b9 2531 menu = Fcons (prompt, pane);
b5ccb0a9 2532 obj = Fx_popup_dialog (Qt, menu);
1db4cfb2
RS
2533 UNGCPRO;
2534 return obj;
2535 }
0ef68e8a 2536#endif /* HAVE_MENUS */
1db4cfb2 2537
7b863bd5
JB
2538 args[0] = prompt;
2539 args[1] = build_string ("(yes or no) ");
2540 prompt = Fconcat (2, args);
2541
2542 GCPRO1 (prompt);
1db4cfb2 2543
7b863bd5
JB
2544 while (1)
2545 {
0ce830bc 2546 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
b24014d4
KH
2547 Qyes_or_no_p_history, Qnil,
2548 Qnil));
7b863bd5
JB
2549 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2550 {
2551 UNGCPRO;
2552 return Qt;
2553 }
2554 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2555 {
2556 UNGCPRO;
2557 return Qnil;
2558 }
2559
2560 Fding (Qnil);
2561 Fdiscard_input ();
2562 message ("Please answer yes or no.");
99dc4745 2563 Fsleep_for (make_number (2), Qnil);
7b863bd5 2564 }
7b863bd5
JB
2565}
2566\f
f4b50f66 2567DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
7b863bd5
JB
2568 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
2569Each of the three load averages is multiplied by 100,\n\
daa37602 2570then converted to integer.\n\
f4b50f66
RS
2571When USE-FLOATS is non-nil, floats will be used instead of integers.\n\
2572These floats are not multiplied by 100.\n\n\
daa37602
JB
2573If the 5-minute or 15-minute load averages are not available, return a\n\
2574shortened list, containing only those averages which are available.")
f4b50f66
RS
2575 (use_floats)
2576 Lisp_Object use_floats;
7b863bd5 2577{
daa37602
JB
2578 double load_ave[3];
2579 int loads = getloadavg (load_ave, 3);
f4b50f66 2580 Lisp_Object ret = Qnil;
7b863bd5 2581
daa37602
JB
2582 if (loads < 0)
2583 error ("load-average not implemented for this operating system");
2584
f4b50f66
RS
2585 while (loads-- > 0)
2586 {
2587 Lisp_Object load = (NILP (use_floats) ?
2588 make_number ((int) (100.0 * load_ave[loads]))
2589 : make_float (load_ave[loads]));
2590 ret = Fcons (load, ret);
2591 }
daa37602
JB
2592
2593 return ret;
2594}
7b863bd5
JB
2595\f
2596Lisp_Object Vfeatures;
2597
2598DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
2599 "Returns t if FEATURE is present in this Emacs.\n\
2600Use this to conditionalize execution of lisp code based on the presence or\n\
2601absence of emacs or environment extensions.\n\
2602Use `provide' to declare that a feature is available.\n\
2603This function looks at the value of the variable `features'.")
b4f334f7 2604 (feature)
7b863bd5
JB
2605 Lisp_Object feature;
2606{
2607 register Lisp_Object tem;
2608 CHECK_SYMBOL (feature, 0);
2609 tem = Fmemq (feature, Vfeatures);
265a9e55 2610 return (NILP (tem)) ? Qnil : Qt;
7b863bd5
JB
2611}
2612
2613DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
2614 "Announce that FEATURE is a feature of the current Emacs.")
b4f334f7 2615 (feature)
7b863bd5
JB
2616 Lisp_Object feature;
2617{
2618 register Lisp_Object tem;
2619 CHECK_SYMBOL (feature, 0);
265a9e55 2620 if (!NILP (Vautoload_queue))
7b863bd5
JB
2621 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
2622 tem = Fmemq (feature, Vfeatures);
265a9e55 2623 if (NILP (tem))
7b863bd5 2624 Vfeatures = Fcons (feature, Vfeatures);
68732608 2625 LOADHIST_ATTACH (Fcons (Qprovide, feature));
7b863bd5
JB
2626 return feature;
2627}
2628
53d5acf5 2629DEFUN ("require", Frequire, Srequire, 1, 3, 0,
7b863bd5
JB
2630 "If feature FEATURE is not loaded, load it from FILENAME.\n\
2631If FEATURE is not a member of the list `features', then the feature\n\
2632is not loaded; so load the file FILENAME.\n\
f0c030b3 2633If FILENAME is omitted, the printname of FEATURE is used as the file name,\n\
53d5acf5
RS
2634but in this case `load' insists on adding the suffix `.el' or `.elc'.\n\
2635If the optional third argument NOERROR is non-nil,\n\
2636then return nil if the file is not found.\n\
2637Normally the return value is FEATURE.")
2638 (feature, file_name, noerror)
2639 Lisp_Object feature, file_name, noerror;
7b863bd5
JB
2640{
2641 register Lisp_Object tem;
2642 CHECK_SYMBOL (feature, 0);
2643 tem = Fmemq (feature, Vfeatures);
68732608 2644 LOADHIST_ATTACH (Fcons (Qrequire, feature));
265a9e55 2645 if (NILP (tem))
7b863bd5
JB
2646 {
2647 int count = specpdl_ptr - specpdl;
2648
2649 /* Value saved here is to be restored into Vautoload_queue */
2650 record_unwind_protect (un_autoload, Vautoload_queue);
2651 Vautoload_queue = Qt;
2652
53d5acf5
RS
2653 tem = Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
2654 noerror, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
2655 /* If load failed entirely, return nil. */
2656 if (NILP (tem))
41857307 2657 return unbind_to (count, Qnil);
7b863bd5
JB
2658
2659 tem = Fmemq (feature, Vfeatures);
265a9e55 2660 if (NILP (tem))
7b863bd5 2661 error ("Required feature %s was not provided",
fdb5bec0 2662 XSYMBOL (feature)->name->data);
7b863bd5
JB
2663
2664 /* Once loading finishes, don't undo it. */
2665 Vautoload_queue = Qt;
2666 feature = unbind_to (count, feature);
2667 }
2668 return feature;
2669}
2670\f
b4f334f7
KH
2671/* Primitives for work of the "widget" library.
2672 In an ideal world, this section would not have been necessary.
2673 However, lisp function calls being as slow as they are, it turns
2674 out that some functions in the widget library (wid-edit.el) are the
2675 bottleneck of Widget operation. Here is their translation to C,
2676 for the sole reason of efficiency. */
2677
2678DEFUN ("widget-plist-member", Fwidget_plist_member, Swidget_plist_member, 2, 2, 0,
2679 "Return non-nil if PLIST has the property PROP.\n\
2680PLIST is a property list, which is a list of the form\n\
2681\(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
2682Unlike `plist-get', this allows you to distinguish between a missing\n\
2683property and a property with the value nil.\n\
2684The value is actually the tail of PLIST whose car is PROP.")
2685 (plist, prop)
2686 Lisp_Object plist, prop;
2687{
2688 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2689 {
2690 QUIT;
2691 plist = XCDR (plist);
2692 plist = CDR (plist);
2693 }
2694 return plist;
2695}
2696
2697DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
2698 "In WIDGET, set PROPERTY to VALUE.\n\
2699The value can later be retrieved with `widget-get'.")
2700 (widget, property, value)
2701 Lisp_Object widget, property, value;
2702{
2703 CHECK_CONS (widget, 1);
2704 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
f7993597 2705 return value;
b4f334f7
KH
2706}
2707
2708DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
2709 "In WIDGET, get the value of PROPERTY.\n\
2710The value could either be specified when the widget was created, or\n\
2711later with `widget-put'.")
2712 (widget, property)
2713 Lisp_Object widget, property;
2714{
2715 Lisp_Object tmp;
2716
2717 while (1)
2718 {
2719 if (NILP (widget))
2720 return Qnil;
2721 CHECK_CONS (widget, 1);
2722 tmp = Fwidget_plist_member (XCDR (widget), property);
2723 if (CONSP (tmp))
2724 {
2725 tmp = XCDR (tmp);
2726 return CAR (tmp);
2727 }
2728 tmp = XCAR (widget);
2729 if (NILP (tmp))
2730 return Qnil;
2731 widget = Fget (tmp, Qwidget_type);
2732 }
2733}
2734
2735DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
2736 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
2737ARGS are passed as extra arguments to the function.")
2738 (nargs, args)
2739 int nargs;
2740 Lisp_Object *args;
2741{
2742 /* This function can GC. */
2743 Lisp_Object newargs[3];
2744 struct gcpro gcpro1, gcpro2;
2745 Lisp_Object result;
2746
2747 newargs[0] = Fwidget_get (args[0], args[1]);
2748 newargs[1] = args[0];
2749 newargs[2] = Flist (nargs - 2, args + 2);
2750 GCPRO2 (newargs[0], newargs[2]);
2751 result = Fapply (3, newargs);
2752 UNGCPRO;
2753 return result;
2754}
2755\f
24c129e4
KH
2756/* base64 encode/decode functions.
2757 Based on code from GNU recode. */
2758
2759#define MIME_LINE_LENGTH 76
2760
2761#define IS_ASCII(Character) \
2762 ((Character) < 128)
2763#define IS_BASE64(Character) \
2764 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0)
2765
4b2e75e6
EZ
2766/* Don't use alloca for regions larger than this, lest we overflow
2767 their stack. */
2768#define MAX_ALLOCA 16*1024
2769
24c129e4
KH
2770/* Table of characters coding the 64 values. */
2771static char base64_value_to_char[64] =
2772{
2773 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */
2774 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */
2775 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */
2776 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 30-39 */
2777 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */
2778 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */
2779 '8', '9', '+', '/' /* 60-63 */
2780};
2781
2782/* Table of base64 values for first 128 characters. */
2783static short base64_char_to_value[128] =
2784{
2785 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
2786 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
2787 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */
2788 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */
2789 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */
2790 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */
2791 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */
2792 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */
2793 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */
2794 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */
2795 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */
2796 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
2797 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
2798};
2799
2800/* The following diagram shows the logical steps by which three octets
2801 get transformed into four base64 characters.
2802
2803 .--------. .--------. .--------.
2804 |aaaaaabb| |bbbbcccc| |ccdddddd|
2805 `--------' `--------' `--------'
2806 6 2 4 4 2 6
2807 .--------+--------+--------+--------.
2808 |00aaaaaa|00bbbbbb|00cccccc|00dddddd|
2809 `--------+--------+--------+--------'
2810
2811 .--------+--------+--------+--------.
2812 |AAAAAAAA|BBBBBBBB|CCCCCCCC|DDDDDDDD|
2813 `--------+--------+--------+--------'
2814
2815 The octets are divided into 6 bit chunks, which are then encoded into
2816 base64 characters. */
2817
2818
2819static int base64_encode_1 P_ ((const char *, char *, int, int));
2820static int base64_decode_1 P_ ((const char *, char *, int));
2821
2822DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region,
2823 2, 3, "r",
46ac5b26 2824 "Base64-encode the region between BEG and END.\n\
15a9a50c 2825Return the length of the encoded text.\n\
24c129e4
KH
2826Optional third argument NO-LINE-BREAK means do not break long lines\n\
2827into shorter lines.")
2828 (beg, end, no_line_break)
2829 Lisp_Object beg, end, no_line_break;
2830{
2831 char *encoded;
2832 int allength, length;
2833 int ibeg, iend, encoded_length;
2834 int old_pos = PT;
2835
2836 validate_region (&beg, &end);
2837
2838 ibeg = CHAR_TO_BYTE (XFASTINT (beg));
2839 iend = CHAR_TO_BYTE (XFASTINT (end));
2840 move_gap_both (XFASTINT (beg), ibeg);
2841
2842 /* We need to allocate enough room for encoding the text.
2843 We need 33 1/3% more space, plus a newline every 76
2844 characters, and then we round up. */
2845 length = iend - ibeg;
2846 allength = length + length/3 + 1;
2847 allength += allength / MIME_LINE_LENGTH + 1 + 6;
2848
4b2e75e6
EZ
2849 if (allength <= MAX_ALLOCA)
2850 encoded = (char *) alloca (allength);
2851 else
2852 encoded = (char *) xmalloc (allength);
24c129e4
KH
2853 encoded_length = base64_encode_1 (BYTE_POS_ADDR (ibeg), encoded, length,
2854 NILP (no_line_break));
2855 if (encoded_length > allength)
2856 abort ();
2857
2858 /* Now we have encoded the region, so we insert the new contents
2859 and delete the old. (Insert first in order to preserve markers.) */
8b835738 2860 SET_PT_BOTH (XFASTINT (beg), ibeg);
24c129e4 2861 insert (encoded, encoded_length);
4b2e75e6 2862 if (allength > MAX_ALLOCA)
8c217645 2863 xfree (encoded);
24c129e4
KH
2864 del_range_byte (ibeg + encoded_length, iend + encoded_length, 1);
2865
2866 /* If point was outside of the region, restore it exactly; else just
2867 move to the beginning of the region. */
2868 if (old_pos >= XFASTINT (end))
2869 old_pos += encoded_length - (XFASTINT (end) - XFASTINT (beg));
8b835738
AS
2870 else if (old_pos > XFASTINT (beg))
2871 old_pos = XFASTINT (beg);
24c129e4
KH
2872 SET_PT (old_pos);
2873
2874 /* We return the length of the encoded text. */
2875 return make_number (encoded_length);
2876}
2877
2878DEFUN ("base64-encode-string", Fbase64_encode_string, Sbase64_encode_string,
2879 1, 1, 0,
46ac5b26 2880 "Base64-encode STRING and return the result.")
24c129e4
KH
2881 (string)
2882 Lisp_Object string;
2883{
2884 int allength, length, encoded_length;
2885 char *encoded;
4b2e75e6 2886 Lisp_Object encoded_string;
24c129e4
KH
2887
2888 CHECK_STRING (string, 1);
2889
2890 length = STRING_BYTES (XSTRING (string));
2891 allength = length + length/3 + 1 + 6;
2892
2893 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
2894 if (allength <= MAX_ALLOCA)
2895 encoded = (char *) alloca (allength);
2896 else
2897 encoded = (char *) xmalloc (allength);
24c129e4
KH
2898
2899 encoded_length = base64_encode_1 (XSTRING (string)->data,
2900 encoded, length, 0);
2901 if (encoded_length > allength)
2902 abort ();
2903
4b2e75e6
EZ
2904 encoded_string = make_unibyte_string (encoded, encoded_length);
2905 if (allength > MAX_ALLOCA)
8c217645 2906 xfree (encoded);
4b2e75e6
EZ
2907
2908 return encoded_string;
24c129e4
KH
2909}
2910
2911static int
2912base64_encode_1 (from, to, length, line_break)
2913 const char *from;
2914 char *to;
2915 int length;
2916 int line_break;
2917{
2918 int counter = 0, i = 0;
2919 char *e = to;
2920 unsigned char c;
2921 unsigned int value;
2922
2923 while (i < length)
2924 {
2925 c = from[i++];
2926
2927 /* Wrap line every 76 characters. */
2928
2929 if (line_break)
2930 {
2931 if (counter < MIME_LINE_LENGTH / 4)
2932 counter++;
2933 else
2934 {
2935 *e++ = '\n';
2936 counter = 1;
2937 }
2938 }
2939
2940 /* Process first byte of a triplet. */
2941
2942 *e++ = base64_value_to_char[0x3f & c >> 2];
2943 value = (0x03 & c) << 4;
2944
2945 /* Process second byte of a triplet. */
2946
2947 if (i == length)
2948 {
2949 *e++ = base64_value_to_char[value];
2950 *e++ = '=';
2951 *e++ = '=';
2952 break;
2953 }
2954
2955 c = from[i++];
2956
2957 *e++ = base64_value_to_char[value | (0x0f & c >> 4)];
2958 value = (0x0f & c) << 2;
2959
2960 /* Process third byte of a triplet. */
2961
2962 if (i == length)
2963 {
2964 *e++ = base64_value_to_char[value];
2965 *e++ = '=';
2966 break;
2967 }
2968
2969 c = from[i++];
2970
2971 *e++ = base64_value_to_char[value | (0x03 & c >> 6)];
2972 *e++ = base64_value_to_char[0x3f & c];
2973 }
2974
2975 /* Complete last partial line. */
2976
2977 if (line_break)
2978 if (counter > 0)
2979 *e++ = '\n';
2980
2981 return e - to;
2982}
2983
2984
2985DEFUN ("base64-decode-region", Fbase64_decode_region, Sbase64_decode_region,
2986 2, 2, "r",
46ac5b26 2987 "Base64-decode the region between BEG and END.\n\
15a9a50c 2988Return the length of the decoded text.\n\
24c129e4
KH
2989If the region can't be decoded, return nil and don't modify the buffer.")
2990 (beg, end)
2991 Lisp_Object beg, end;
2992{
2993 int ibeg, iend, length;
2994 char *decoded;
2995 int old_pos = PT;
2996 int decoded_length;
9b703a38 2997 int inserted_chars;
24c129e4
KH
2998
2999 validate_region (&beg, &end);
3000
3001 ibeg = CHAR_TO_BYTE (XFASTINT (beg));
3002 iend = CHAR_TO_BYTE (XFASTINT (end));
3003
3004 length = iend - ibeg;
3005 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3006 if (length <= MAX_ALLOCA)
3007 decoded = (char *) alloca (length);
3008 else
3009 decoded = (char *) xmalloc (length);
24c129e4
KH
3010
3011 move_gap_both (XFASTINT (beg), ibeg);
3012 decoded_length = base64_decode_1 (BYTE_POS_ADDR (ibeg), decoded, length);
3013 if (decoded_length > length)
3014 abort ();
3015
3016 if (decoded_length < 0)
8c217645
KH
3017 {
3018 /* The decoding wasn't possible. */
3019 if (length > MAX_ALLOCA)
3020 xfree (decoded);
3021 return Qnil;
3022 }
24c129e4
KH
3023
3024 /* Now we have decoded the region, so we insert the new contents
3025 and delete the old. (Insert first in order to preserve markers.) */
9b703a38
KH
3026 /* We insert two spaces, then insert the decoded text in between
3027 them, at last, delete those extra two spaces. This is to avoid
922dfd86 3028 byte combining while inserting. */
9b703a38
KH
3029 TEMP_SET_PT_BOTH (XFASTINT (beg), ibeg);
3030 insert_1_both (" ", 2, 2, 0, 1, 0);
3031 TEMP_SET_PT_BOTH (XFASTINT (beg) + 1, ibeg + 1);
24c129e4 3032 insert (decoded, decoded_length);
9b703a38 3033 inserted_chars = PT - (XFASTINT (beg) + 1);
4b2e75e6 3034 if (length > MAX_ALLOCA)
8c217645 3035 xfree (decoded);
922dfd86
KH
3036 /* At first delete the original text. This never cause byte
3037 combining. */
3038 del_range_both (PT + 1, PT_BYTE + 1, XFASTINT (end) + inserted_chars + 2,
9b703a38 3039 iend + decoded_length + 2, 1);
922dfd86
KH
3040 /* Next delete the extra spaces. This will cause byte combining
3041 error. */
3042 del_range_both (PT, PT_BYTE, PT + 1, PT_BYTE + 1, 0);
3043 del_range_both (XFASTINT (beg), ibeg, XFASTINT (beg) + 1, ibeg + 1, 0);
9b703a38 3044 inserted_chars = PT - XFASTINT (beg);
24c129e4
KH
3045
3046 /* If point was outside of the region, restore it exactly; else just
3047 move to the beginning of the region. */
3048 if (old_pos >= XFASTINT (end))
9b703a38
KH
3049 old_pos += inserted_chars - (XFASTINT (end) - XFASTINT (beg));
3050 else if (old_pos > XFASTINT (beg))
3051 old_pos = XFASTINT (beg);
24c129e4
KH
3052 SET_PT (old_pos);
3053
9b703a38 3054 return make_number (inserted_chars);
24c129e4
KH
3055}
3056
3057DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
3058 1, 1, 0,
46ac5b26 3059 "Base64-decode STRING and return the result.")
24c129e4
KH
3060 (string)
3061 Lisp_Object string;
3062{
3063 char *decoded;
3064 int length, decoded_length;
4b2e75e6 3065 Lisp_Object decoded_string;
24c129e4
KH
3066
3067 CHECK_STRING (string, 1);
3068
3069 length = STRING_BYTES (XSTRING (string));
3070 /* We need to allocate enough room for decoding the text. */
4b2e75e6
EZ
3071 if (length <= MAX_ALLOCA)
3072 decoded = (char *) alloca (length);
3073 else
3074 decoded = (char *) xmalloc (length);
24c129e4
KH
3075
3076 decoded_length = base64_decode_1 (XSTRING (string)->data, decoded, length);
3077 if (decoded_length > length)
3078 abort ();
3079
3080 if (decoded_length < 0)
8c217645
KH
3081 /* The decoding wasn't possible. */
3082 decoded_string = Qnil;
3083 else
3084 decoded_string = make_string (decoded, decoded_length);
24c129e4 3085
4b2e75e6 3086 if (length > MAX_ALLOCA)
8c217645 3087 xfree (decoded);
4b2e75e6
EZ
3088
3089 return decoded_string;
24c129e4
KH
3090}
3091
3092static int
3093base64_decode_1 (from, to, length)
3094 const char *from;
3095 char *to;
3096 int length;
3097{
3098 int counter = 0, i = 0;
3099 char *e = to;
3100 unsigned char c;
3101 unsigned long value;
3102
3103 while (i < length)
3104 {
3105 /* Accept wrapping lines, reversibly if at each 76 characters. */
3106
3107 c = from[i++];
3108 if (c == '\n')
3109 {
3110 if (i == length)
3111 break;
3112 c = from[i++];
3113 if (i == length)
3114 break;
24c129e4
KH
3115 counter = 1;
3116 }
3117 else
3118 counter++;
3119
3120 /* Process first byte of a quadruplet. */
3121
3122 if (!IS_BASE64 (c))
3123 return -1;
3124 value = base64_char_to_value[c] << 18;
3125
3126 /* Process second byte of a quadruplet. */
3127
3128 if (i == length)
3129 return -1;
3130 c = from[i++];
3131
3132 if (!IS_BASE64 (c))
3133 return -1;
3134 value |= base64_char_to_value[c] << 12;
3135
3136 *e++ = (unsigned char) (value >> 16);
3137
3138 /* Process third byte of a quadruplet. */
3139
3140 if (i == length)
3141 return -1;
3142 c = from[i++];
3143
3144 if (c == '=')
3145 {
3146 c = from[i++];
3147 if (c != '=')
3148 return -1;
3149 continue;
3150 }
3151
3152 if (!IS_BASE64 (c))
3153 return -1;
3154 value |= base64_char_to_value[c] << 6;
3155
3156 *e++ = (unsigned char) (0xff & value >> 8);
3157
3158 /* Process fourth byte of a quadruplet. */
3159
3160 if (i == length)
3161 return -1;
3162 c = from[i++];
3163
3164 if (c == '=')
3165 continue;
3166
3167 if (!IS_BASE64 (c))
3168 return -1;
3169 value |= base64_char_to_value[c];
3170
3171 *e++ = (unsigned char) (0xff & value);
3172 }
3173
3174 return e - to;
3175}
3176\f
dfcf069d 3177void
7b863bd5
JB
3178syms_of_fns ()
3179{
3180 Qstring_lessp = intern ("string-lessp");
3181 staticpro (&Qstring_lessp);
68732608
RS
3182 Qprovide = intern ("provide");
3183 staticpro (&Qprovide);
3184 Qrequire = intern ("require");
3185 staticpro (&Qrequire);
0ce830bc
RS
3186 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
3187 staticpro (&Qyes_or_no_p_history);
eb4ffa4e
RS
3188 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
3189 staticpro (&Qcursor_in_echo_area);
b4f334f7
KH
3190 Qwidget_type = intern ("widget-type");
3191 staticpro (&Qwidget_type);
7b863bd5 3192
09ab3c3b
KH
3193 staticpro (&string_char_byte_cache_string);
3194 string_char_byte_cache_string = Qnil;
3195
52a9879b
RS
3196 Fset (Qyes_or_no_p_history, Qnil);
3197
7b863bd5
JB
3198 DEFVAR_LISP ("features", &Vfeatures,
3199 "A list of symbols which are the features of the executing emacs.\n\
3200Used by `featurep' and `require', and altered by `provide'.");
3201 Vfeatures = Qnil;
3202
bdd8d692
RS
3203 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
3204 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
1eb569c5 3205This applies to y-or-n and yes-or-no questions asked by commands\n\
bdd8d692
RS
3206invoked by mouse clicks and mouse menu items.");
3207 use_dialog_box = 1;
3208
7b863bd5
JB
3209 defsubr (&Sidentity);
3210 defsubr (&Srandom);
3211 defsubr (&Slength);
5a30fab8 3212 defsubr (&Ssafe_length);
026f59ce 3213 defsubr (&Sstring_bytes);
7b863bd5 3214 defsubr (&Sstring_equal);
0e1e9f8d 3215 defsubr (&Scompare_strings);
7b863bd5
JB
3216 defsubr (&Sstring_lessp);
3217 defsubr (&Sappend);
3218 defsubr (&Sconcat);
3219 defsubr (&Svconcat);
3220 defsubr (&Scopy_sequence);
09ab3c3b
KH
3221 defsubr (&Sstring_make_multibyte);
3222 defsubr (&Sstring_make_unibyte);
6d475204
RS
3223 defsubr (&Sstring_as_multibyte);
3224 defsubr (&Sstring_as_unibyte);
7b863bd5
JB
3225 defsubr (&Scopy_alist);
3226 defsubr (&Ssubstring);
3227 defsubr (&Snthcdr);
3228 defsubr (&Snth);
3229 defsubr (&Selt);
3230 defsubr (&Smember);
3231 defsubr (&Smemq);
3232 defsubr (&Sassq);
3233 defsubr (&Sassoc);
3234 defsubr (&Srassq);
0fb5a19c 3235 defsubr (&Srassoc);
7b863bd5 3236 defsubr (&Sdelq);
ca8dd546 3237 defsubr (&Sdelete);
7b863bd5
JB
3238 defsubr (&Snreverse);
3239 defsubr (&Sreverse);
3240 defsubr (&Ssort);
be9d483d 3241 defsubr (&Splist_get);
7b863bd5 3242 defsubr (&Sget);
be9d483d 3243 defsubr (&Splist_put);
7b863bd5
JB
3244 defsubr (&Sput);
3245 defsubr (&Sequal);
3246 defsubr (&Sfillarray);
999de246 3247 defsubr (&Schar_table_subtype);
e03f7933
RS
3248 defsubr (&Schar_table_parent);
3249 defsubr (&Sset_char_table_parent);
3250 defsubr (&Schar_table_extra_slot);
3251 defsubr (&Sset_char_table_extra_slot);
999de246 3252 defsubr (&Schar_table_range);
e03f7933 3253 defsubr (&Sset_char_table_range);
e1335ba2 3254 defsubr (&Sset_char_table_default);
e03f7933 3255 defsubr (&Smap_char_table);
7b863bd5
JB
3256 defsubr (&Snconc);
3257 defsubr (&Smapcar);
3258 defsubr (&Smapconcat);
3259 defsubr (&Sy_or_n_p);
3260 defsubr (&Syes_or_no_p);
3261 defsubr (&Sload_average);
3262 defsubr (&Sfeaturep);
3263 defsubr (&Srequire);
3264 defsubr (&Sprovide);
b4f334f7
KH
3265 defsubr (&Swidget_plist_member);
3266 defsubr (&Swidget_put);
3267 defsubr (&Swidget_get);
3268 defsubr (&Swidget_apply);
24c129e4
KH
3269 defsubr (&Sbase64_encode_region);
3270 defsubr (&Sbase64_decode_region);
3271 defsubr (&Sbase64_encode_string);
3272 defsubr (&Sbase64_decode_string);
7b863bd5 3273}