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