comparison src/fns.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents 6719134a07c2
children a86b2b5e0111
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
59 Lisp_Object Qidentity; 59 Lisp_Object Qidentity;
60 60
61 static int internal_old_equal (Lisp_Object, Lisp_Object, int); 61 static int internal_old_equal (Lisp_Object, Lisp_Object, int);
62 62
63 static Lisp_Object 63 static Lisp_Object
64 mark_bit_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) 64 mark_bit_vector (Lisp_Object obj)
65 { 65 {
66 return Qnil; 66 return Qnil;
67 } 67 }
68 68
69 static void 69 static void
70 print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 70 print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
71 { 71 {
72 int i; 72 size_t i;
73 struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj); 73 Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
74 int len = bit_vector_length (v); 74 size_t len = bit_vector_length (v);
75 int last = len; 75 size_t last = len;
76 76
77 if (INTP (Vprint_length)) 77 if (INTP (Vprint_length))
78 last = min (len, XINT (Vprint_length)); 78 last = min (len, XINT (Vprint_length));
79 write_c_string ("#*", printcharfun); 79 write_c_string ("#*", printcharfun);
80 for (i = 0; i < last; i++) 80 for (i = 0; i < last; i++)
90 } 90 }
91 91
92 static int 92 static int
93 bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 93 bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
94 { 94 {
95 struct Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1); 95 Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1);
96 struct Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2); 96 Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2);
97 97
98 return ((bit_vector_length (v1) == bit_vector_length (v2)) && 98 return ((bit_vector_length (v1) == bit_vector_length (v2)) &&
99 !memcmp (v1->bits, v2->bits, 99 !memcmp (v1->bits, v2->bits,
100 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) * 100 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) *
101 sizeof (long))); 101 sizeof (long)));
102 } 102 }
103 103
104 static unsigned long 104 static unsigned long
105 bit_vector_hash (Lisp_Object obj, int depth) 105 bit_vector_hash (Lisp_Object obj, int depth)
106 { 106 {
107 struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj); 107 Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
108 return HASH2 (bit_vector_length (v), 108 return HASH2 (bit_vector_length (v),
109 memory_hash (v->bits, 109 memory_hash (v->bits,
110 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) * 110 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) *
111 sizeof (long))); 111 sizeof (long)));
112 } 112 }
113 113
114 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("bit-vector", bit_vector, 114 static size_t
115 mark_bit_vector, print_bit_vector, 0, 115 size_bit_vector (const void *lheader)
116 bit_vector_equal, bit_vector_hash, 116 {
117 struct Lisp_Bit_Vector); 117 Lisp_Bit_Vector *v = (Lisp_Bit_Vector *) lheader;
118 return offsetof (Lisp_Bit_Vector,
119 bits[BIT_VECTOR_LONG_STORAGE (bit_vector_length (v))]);
120 }
121
122 static const struct lrecord_description bit_vector_description[] = {
123 { XD_LISP_OBJECT, offsetof (Lisp_Bit_Vector, next) },
124 { XD_END }
125 };
126
127
128 DEFINE_BASIC_LRECORD_SEQUENCE_IMPLEMENTATION ("bit-vector", bit_vector,
129 mark_bit_vector, print_bit_vector, 0,
130 bit_vector_equal, bit_vector_hash,
131 bit_vector_description, size_bit_vector,
132 Lisp_Bit_Vector);
118 133
119 DEFUN ("identity", Fidentity, 1, 1, 0, /* 134 DEFUN ("identity", Fidentity, 1, 1, 0, /*
120 Return the argument unchanged. 135 Return the argument unchanged.
121 */ 136 */
122 (arg)) 137 (arg))
175 { 190 {
176 if (!COMPILED_FUNCTIONP (seq)) 191 if (!COMPILED_FUNCTIONP (seq))
177 return XINT (Flength (seq)); 192 return XINT (Flength (seq));
178 else 193 else
179 { 194 {
180 struct Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (seq); 195 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (seq);
181 196
182 return (f->flags.interactivep ? COMPILED_INTERACTIVE : 197 return (f->flags.interactivep ? COMPILED_INTERACTIVE :
183 f->flags.domainp ? COMPILED_DOMAIN : 198 f->flags.domainp ? COMPILED_DOMAIN :
184 COMPILED_DOC_STRING) 199 COMPILED_DOC_STRING)
185 + 1; 200 + 1;
187 } 202 }
188 203
189 #endif /* LOSING_BYTECODE */ 204 #endif /* LOSING_BYTECODE */
190 205
191 void 206 void
192 check_losing_bytecode (CONST char *function, Lisp_Object seq) 207 check_losing_bytecode (const char *function, Lisp_Object seq)
193 { 208 {
194 if (COMPILED_FUNCTIONP (seq)) 209 if (COMPILED_FUNCTIONP (seq))
195 error_with_frob 210 error_with_frob
196 (seq, 211 (seq,
197 "As of 20.3, `%s' no longer works with compiled-function objects", 212 "As of 20.3, `%s' no longer works with compiled-function objects",
206 retry: 221 retry:
207 if (STRINGP (sequence)) 222 if (STRINGP (sequence))
208 return make_int (XSTRING_CHAR_LENGTH (sequence)); 223 return make_int (XSTRING_CHAR_LENGTH (sequence));
209 else if (CONSP (sequence)) 224 else if (CONSP (sequence))
210 { 225 {
211 int len; 226 size_t len;
212 GET_EXTERNAL_LIST_LENGTH (sequence, len); 227 GET_EXTERNAL_LIST_LENGTH (sequence, len);
213 return make_int (len); 228 return make_int (len);
214 } 229 }
215 else if (VECTORP (sequence)) 230 else if (VECTORP (sequence))
216 return make_int (XVECTOR_LENGTH (sequence)); 231 return make_int (XVECTOR_LENGTH (sequence));
233 which is at least the number of distinct elements. 248 which is at least the number of distinct elements.
234 */ 249 */
235 (list)) 250 (list))
236 { 251 {
237 Lisp_Object hare, tortoise; 252 Lisp_Object hare, tortoise;
238 int len; 253 size_t len;
239 254
240 for (hare = tortoise = list, len = 0; 255 for (hare = tortoise = list, len = 0;
241 CONSP (hare) && (! EQ (hare, tortoise) || len == 0); 256 CONSP (hare) && (! EQ (hare, tortoise) || len == 0);
242 hare = XCDR (hare), len++) 257 hare = XCDR (hare), len++)
243 { 258 {
259 Symbols are also allowed; their print names are used instead. 274 Symbols are also allowed; their print names are used instead.
260 */ 275 */
261 (s1, s2)) 276 (s1, s2))
262 { 277 {
263 Bytecount len; 278 Bytecount len;
264 struct Lisp_String *p1, *p2; 279 Lisp_String *p1, *p2;
265 280
266 if (SYMBOLP (s1)) 281 if (SYMBOLP (s1))
267 p1 = XSYMBOL (s1)->name; 282 p1 = XSYMBOL (s1)->name;
268 else 283 else
269 { 284 {
306 Unicode. When Unicode support is added to XEmacs/Mule, this problem 321 Unicode. When Unicode support is added to XEmacs/Mule, this problem
307 may be solved. 322 may be solved.
308 */ 323 */
309 (s1, s2)) 324 (s1, s2))
310 { 325 {
311 struct Lisp_String *p1, *p2; 326 Lisp_String *p1, *p2;
312 Charcount end, len2; 327 Charcount end, len2;
313 int i; 328 int i;
314 329
315 if (SYMBOLP (s1)) 330 if (SYMBOLP (s1))
316 p1 = XSYMBOL (s1)->name; 331 p1 = XSYMBOL (s1)->name;
337 /* There is no hope of this working under Mule. Even if we converted 352 /* There is no hope of this working under Mule. Even if we converted
338 the data into an external format so that strcoll() processed it 353 the data into an external format so that strcoll() processed it
339 properly, it would still not work because strcoll() does not 354 properly, it would still not work because strcoll() does not
340 handle multiple locales. This is the fundamental flaw in the 355 handle multiple locales. This is the fundamental flaw in the
341 locale model. */ 356 locale model. */
342 Bytecount bcend = charcount_to_bytecount (string_data (p1), end); 357 {
343 /* Compare strings using collation order of locale. */ 358 Bytecount bcend = charcount_to_bytecount (string_data (p1), end);
344 /* Need to be tricky to handle embedded nulls. */ 359 /* Compare strings using collation order of locale. */
345 360 /* Need to be tricky to handle embedded nulls. */
346 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1) 361
347 { 362 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1)
348 int val = strcoll ((char *) string_data (p1) + i, 363 {
349 (char *) string_data (p2) + i); 364 int val = strcoll ((char *) string_data (p1) + i,
350 if (val < 0) 365 (char *) string_data (p2) + i);
351 return Qt; 366 if (val < 0)
352 if (val > 0) 367 return Qt;
353 return Qnil; 368 if (val > 0)
354 } 369 return Qnil;
370 }
371 }
355 #else /* not I18N2, or MULE */ 372 #else /* not I18N2, or MULE */
356 /* #### It is not really necessary to do this: We could compare 373 {
357 byte-by-byte and still get a reasonable comparison, since this 374 Bufbyte *ptr1 = string_data (p1);
358 would compare characters with a charset in the same way. 375 Bufbyte *ptr2 = string_data (p2);
359 With a little rearrangement of the leading bytes, we could 376
360 make most inter-charset comparisons work out the same, too; 377 /* #### It is not really necessary to do this: We could compare
361 even if some don't, this is not a big deal because inter-charset 378 byte-by-byte and still get a reasonable comparison, since this
362 comparisons aren't really well-defined anyway. */ 379 would compare characters with a charset in the same way. With
363 for (i = 0; i < end; i++) 380 a little rearrangement of the leading bytes, we could make most
364 { 381 inter-charset comparisons work out the same, too; even if some
365 if (string_char (p1, i) != string_char (p2, i)) 382 don't, this is not a big deal because inter-charset comparisons
366 return string_char (p1, i) < string_char (p2, i) ? Qt : Qnil; 383 aren't really well-defined anyway. */
367 } 384 for (i = 0; i < end; i++)
385 {
386 if (charptr_emchar (ptr1) != charptr_emchar (ptr2))
387 return charptr_emchar (ptr1) < charptr_emchar (ptr2) ? Qt : Qnil;
388 INC_CHARPTR (ptr1);
389 INC_CHARPTR (ptr2);
390 }
391 }
368 #endif /* not I18N2, or MULE */ 392 #endif /* not I18N2, or MULE */
369 /* Can't do i < len2 because then comparison between "foo" and "foo^@" 393 /* Can't do i < len2 because then comparison between "foo" and "foo^@"
370 won't work right in I18N2 case */ 394 won't work right in I18N2 case */
371 return end < len2 ? Qt : Qnil; 395 return end < len2 ? Qt : Qnil;
372 } 396 }
376 Each string has a tick counter which is incremented each time the contents 400 Each string has a tick counter which is incremented each time the contents
377 of the string are changed (e.g. with `aset'). It wraps around occasionally. 401 of the string are changed (e.g. with `aset'). It wraps around occasionally.
378 */ 402 */
379 (string)) 403 (string))
380 { 404 {
381 struct Lisp_String *s; 405 Lisp_String *s;
382 406
383 CHECK_STRING (string); 407 CHECK_STRING (string);
384 s = XSTRING (string); 408 s = XSTRING (string);
385 if (CONSP (s->plist) && INTP (XCAR (s->plist))) 409 if (CONSP (s->plist) && INTP (XCAR (s->plist)))
386 return XCAR (s->plist); 410 return XCAR (s->plist);
389 } 413 }
390 414
391 void 415 void
392 bump_string_modiff (Lisp_Object str) 416 bump_string_modiff (Lisp_Object str)
393 { 417 {
394 struct Lisp_String *s = XSTRING (str); 418 Lisp_String *s = XSTRING (str);
395 Lisp_Object *ptr = &s->plist; 419 Lisp_Object *ptr = &s->plist;
396 420
397 #ifdef I18N3 421 #ifdef I18N3
398 /* #### remove the `string-translatable' property from the string, 422 /* #### remove the `string-translatable' property from the string,
399 if there is one. */ 423 if there is one. */
504 copy_list (Lisp_Object list) 528 copy_list (Lisp_Object list)
505 { 529 {
506 Lisp_Object list_copy = Fcons (XCAR (list), XCDR (list)); 530 Lisp_Object list_copy = Fcons (XCAR (list), XCDR (list));
507 Lisp_Object last = list_copy; 531 Lisp_Object last = list_copy;
508 Lisp_Object hare, tortoise; 532 Lisp_Object hare, tortoise;
509 int len; 533 size_t len;
510 534
511 for (tortoise = hare = XCDR (list), len = 1; 535 for (tortoise = hare = XCDR (list), len = 1;
512 CONSP (hare); 536 CONSP (hare);
513 hare = XCDR (hare), len++) 537 hare = XCDR (hare), len++)
514 { 538 {
879 Relevant parts of the string-extent-data are copied in the new string. 903 Relevant parts of the string-extent-data are copied in the new string.
880 */ 904 */
881 (string, from, to)) 905 (string, from, to))
882 { 906 {
883 Charcount ccfr, ccto; 907 Charcount ccfr, ccto;
884 Bytecount bfr, bto; 908 Bytecount bfr, blen;
885 Lisp_Object val; 909 Lisp_Object val;
886 910
887 CHECK_STRING (string); 911 CHECK_STRING (string);
888 CHECK_INT (from); 912 CHECK_INT (from);
889 get_string_range_char (string, from, to, &ccfr, &ccto, 913 get_string_range_char (string, from, to, &ccfr, &ccto,
890 GB_HISTORICAL_STRING_BEHAVIOR); 914 GB_HISTORICAL_STRING_BEHAVIOR);
891 bfr = charcount_to_bytecount (XSTRING_DATA (string), ccfr); 915 bfr = charcount_to_bytecount (XSTRING_DATA (string), ccfr);
892 bto = charcount_to_bytecount (XSTRING_DATA (string), ccto); 916 blen = charcount_to_bytecount (XSTRING_DATA (string) + bfr, ccto - ccfr);
893 val = make_string (XSTRING_DATA (string) + bfr, bto - bfr); 917 val = make_string (XSTRING_DATA (string) + bfr, blen);
894 /* Copy any applicable extent information into the new string: */ 918 /* Copy any applicable extent information into the new string: */
895 copy_string_extents (val, string, 0, bfr, bto - bfr); 919 copy_string_extents (val, string, 0, bfr, blen);
896 return val; 920 return val;
897 } 921 }
898 922
899 DEFUN ("subseq", Fsubseq, 2, 3, 0, /* 923 DEFUN ("subseq", Fsubseq, 2, 3, 0, /*
900 Return a subsequence of SEQ, starting at index FROM and ending before TO. 924 Return the subsequence of SEQUENCE starting at START and ending before END.
901 TO may be nil or omitted; then the subsequence runs to the end of SEQ. 925 END may be omitted; then the subsequence runs to the end of SEQUENCE.
902 If FROM or TO is negative, it counts from the end. 926 If START or END is negative, it counts from the end.
903 The resulting subsequence is always the same type as the original 927 The returned subsequence is always of the same type as SEQUENCE.
904 sequence. 928 If SEQUENCE is a string, relevant parts of the string-extent-data
905 If SEQ is a string, relevant parts of the string-extent-data are copied 929 are copied to the new string.
906 to the new string. 930 */
907 */ 931 (sequence, start, end))
908 (seq, from, to)) 932 {
909 { 933 EMACS_INT len, s, e;
910 int len, f, t; 934
911 935 if (STRINGP (sequence))
912 if (STRINGP (seq)) 936 return Fsubstring (sequence, start, end);
913 return Fsubstring (seq, from, to); 937
914 938 len = XINT (Flength (sequence));
915 if (!LISTP (seq) && !VECTORP (seq) && !BIT_VECTORP (seq)) 939
916 { 940 CHECK_INT (start);
917 check_losing_bytecode ("subseq", seq); 941 s = XINT (start);
918 seq = wrong_type_argument (Qsequencep, seq); 942 if (s < 0)
919 } 943 s = len + s;
920 944
921 len = XINT (Flength (seq)); 945 if (NILP (end))
922 946 e = len;
923 CHECK_INT (from);
924 f = XINT (from);
925 if (f < 0)
926 f = len + f;
927
928 if (NILP (to))
929 t = len;
930 else 947 else
931 { 948 {
932 CHECK_INT (to); 949 CHECK_INT (end);
933 t = XINT (to); 950 e = XINT (end);
934 if (t < 0) 951 if (e < 0)
935 t = len + t; 952 e = len + e;
936 } 953 }
937 954
938 if (!(0 <= f && f <= t && t <= len)) 955 if (!(0 <= s && s <= e && e <= len))
939 args_out_of_range_3 (seq, make_int (f), make_int (t)); 956 args_out_of_range_3 (sequence, make_int (s), make_int (e));
940 957
941 if (VECTORP (seq)) 958 if (VECTORP (sequence))
942 { 959 {
943 Lisp_Object result = make_vector (t - f, Qnil); 960 Lisp_Object result = make_vector (e - s, Qnil);
944 int i; 961 EMACS_INT i;
945 Lisp_Object *in_elts = XVECTOR_DATA (seq); 962 Lisp_Object *in_elts = XVECTOR_DATA (sequence);
946 Lisp_Object *out_elts = XVECTOR_DATA (result); 963 Lisp_Object *out_elts = XVECTOR_DATA (result);
947 964
948 for (i = f; i < t; i++) 965 for (i = s; i < e; i++)
949 out_elts[i - f] = in_elts[i]; 966 out_elts[i - s] = in_elts[i];
950 return result; 967 return result;
951 } 968 }
952 969 else if (LISTP (sequence))
953 if (LISTP (seq))
954 { 970 {
955 Lisp_Object result = Qnil; 971 Lisp_Object result = Qnil;
956 int i; 972 EMACS_INT i;
957 973
958 seq = Fnthcdr (make_int (f), seq); 974 sequence = Fnthcdr (make_int (s), sequence);
959 975
960 for (i = f; i < t; i++) 976 for (i = s; i < e; i++)
961 { 977 {
962 result = Fcons (Fcar (seq), result); 978 result = Fcons (Fcar (sequence), result);
963 seq = Fcdr (seq); 979 sequence = Fcdr (sequence);
964 } 980 }
965 981
966 return Fnreverse (result); 982 return Fnreverse (result);
967 } 983 }
968 984 else if (BIT_VECTORP (sequence))
969 /* bit vector */ 985 {
970 { 986 Lisp_Object result = make_bit_vector (e - s, Qzero);
971 Lisp_Object result = make_bit_vector (t - f, Qzero); 987 EMACS_INT i;
972 int i; 988
973 989 for (i = s; i < e; i++)
974 for (i = f; i < t; i++) 990 set_bit_vector_bit (XBIT_VECTOR (result), i - s,
975 set_bit_vector_bit (XBIT_VECTOR (result), i - f, 991 bit_vector_bit (XBIT_VECTOR (sequence), i));
976 bit_vector_bit (XBIT_VECTOR (seq), i)); 992 return result;
977 return result; 993 }
978 } 994 else
995 abort (); /* unreachable, since Flength (sequence) did not get an error */
979 } 996 }
980 997
981 998
982 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /* 999 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /*
983 Take cdr N times on LIST, and return the result. 1000 Take cdr N times on LIST, and return the result.
984 */ 1001 */
985 (n, list)) 1002 (n, list))
986 { 1003 {
987 REGISTER int i; 1004 REGISTER size_t i;
988 REGISTER Lisp_Object tail = list; 1005 REGISTER Lisp_Object tail = list;
989 CHECK_NATNUM (n); 1006 CHECK_NATNUM (n);
990 for (i = XINT (n); i; i--) 1007 for (i = XINT (n); i; i--)
991 { 1008 {
992 if (CONSP (tail)) 1009 if (CONSP (tail))
1041 BIT_VECTORP (sequence)) 1058 BIT_VECTORP (sequence))
1042 return Faref (sequence, n); 1059 return Faref (sequence, n);
1043 #ifdef LOSING_BYTECODE 1060 #ifdef LOSING_BYTECODE
1044 else if (COMPILED_FUNCTIONP (sequence)) 1061 else if (COMPILED_FUNCTIONP (sequence))
1045 { 1062 {
1046 int idx = XINT (n); 1063 EMACS_INT idx = XINT (n);
1047 if (idx < 0) 1064 if (idx < 0)
1048 { 1065 {
1049 lose: 1066 lose:
1050 args_out_of_range (sequence, n); 1067 args_out_of_range (sequence, n);
1051 } 1068 }
1093 If N is zero, then the atom that terminates the list is returned. 1110 If N is zero, then the atom that terminates the list is returned.
1094 If N is greater than the length of LIST, then LIST itself is returned. 1111 If N is greater than the length of LIST, then LIST itself is returned.
1095 */ 1112 */
1096 (list, n)) 1113 (list, n))
1097 { 1114 {
1098 int int_n, count; 1115 EMACS_INT int_n, count;
1099 Lisp_Object retval, tortoise, hare; 1116 Lisp_Object retval, tortoise, hare;
1100 1117
1101 CHECK_LIST (list); 1118 CHECK_LIST (list);
1102 1119
1103 if (NILP (n)) 1120 if (NILP (n))
1129 Modify LIST to remove the last N (default 1) elements. 1146 Modify LIST to remove the last N (default 1) elements.
1130 If LIST has N or fewer elements, nil is returned and LIST is unmodified. 1147 If LIST has N or fewer elements, nil is returned and LIST is unmodified.
1131 */ 1148 */
1132 (list, n)) 1149 (list, n))
1133 { 1150 {
1134 int int_n; 1151 EMACS_INT int_n;
1135 1152
1136 CHECK_LIST (list); 1153 CHECK_LIST (list);
1137 1154
1138 if (NILP (n)) 1155 if (NILP (n))
1139 int_n = 1; 1156 int_n = 1;
1832 */ 1849 */
1833 int 1850 int
1834 plists_differ (Lisp_Object a, Lisp_Object b, int nil_means_not_present, 1851 plists_differ (Lisp_Object a, Lisp_Object b, int nil_means_not_present,
1835 int laxp, int depth) 1852 int laxp, int depth)
1836 { 1853 {
1837 int eqp = (depth == -1); /* -1 as depth means us eq, not equal. */ 1854 int eqp = (depth == -1); /* -1 as depth means use eq, not equal. */
1838 int la, lb, m, i, fill; 1855 int la, lb, m, i, fill;
1839 Lisp_Object *keys, *vals; 1856 Lisp_Object *keys, *vals;
1840 char *flags; 1857 char *flags;
1841 Lisp_Object rest; 1858 Lisp_Object rest;
1842 1859
1876 if (nil_means_not_present && NILP (v)) continue; 1893 if (nil_means_not_present && NILP (v)) continue;
1877 for (i = 0; i < fill; i++) 1894 for (i = 0; i < fill; i++)
1878 { 1895 {
1879 if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth)) 1896 if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth))
1880 { 1897 {
1881 if ((eqp 1898 if (eqp
1882 /* We narrowly escaped being Ebolified here. */ 1899 /* We narrowly escaped being Ebolified here. */
1883 ? !EQ_WITH_EBOLA_NOTICE (v, vals [i]) 1900 ? !EQ_WITH_EBOLA_NOTICE (v, vals [i])
1884 : !internal_equal (v, vals [i], depth))) 1901 : !internal_equal (v, vals [i], depth))
1885 /* a property in B has a different value than in A */ 1902 /* a property in B has a different value than in A */
1886 goto MISMATCH; 1903 goto MISMATCH;
1887 flags [i] = 1; 1904 flags [i] = 1;
1888 break; 1905 break;
1889 } 1906 }
2350 } 2367 }
2351 2368
2352 DEFUN ("valid-plist-p", Fvalid_plist_p, 1, 1, 0, /* 2369 DEFUN ("valid-plist-p", Fvalid_plist_p, 1, 1, 0, /*
2353 Given a plist, return non-nil if its format is correct. 2370 Given a plist, return non-nil if its format is correct.
2354 If it returns nil, `check-valid-plist' will signal an error when given 2371 If it returns nil, `check-valid-plist' will signal an error when given
2355 the plist; that means it's a malformed or circular plist or has non-symbols 2372 the plist; that means it's a malformed or circular plist.
2356 as keywords.
2357 */ 2373 */
2358 (plist)) 2374 (plist))
2359 { 2375 {
2360 Lisp_Object *tortoise; 2376 Lisp_Object *tortoise;
2361 Lisp_Object *hare; 2377 Lisp_Object *hare;
2428 properties on the list. 2444 properties on the list.
2429 */ 2445 */
2430 (lax_plist, prop, default_)) 2446 (lax_plist, prop, default_))
2431 { 2447 {
2432 Lisp_Object val = external_plist_get (&lax_plist, prop, 1, ERROR_ME); 2448 Lisp_Object val = external_plist_get (&lax_plist, prop, 1, ERROR_ME);
2433 if (UNBOUNDP (val)) 2449 return UNBOUNDP (val) ? default_ : val;
2434 return default_;
2435 return val;
2436 } 2450 }
2437 2451
2438 DEFUN ("lax-plist-put", Flax_plist_put, 3, 3, 0, /* 2452 DEFUN ("lax-plist-put", Flax_plist_put, 3, 3, 0, /*
2439 Change value in LAX-PLIST of PROP to VAL. 2453 Change value in LAX-PLIST of PROP to VAL.
2440 LAX-PLIST is a lax property list, which is a list of the form \(PROP1 2454 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
2550 } 2564 }
2551 2565
2552 return head; 2566 return head;
2553 } 2567 }
2554 2568
2555 /* Symbol plists are directly accessible, so we need to protect against
2556 invalid property list structure */
2557
2558 static Lisp_Object
2559 symbol_getprop (Lisp_Object sym, Lisp_Object propname, Lisp_Object default_)
2560 {
2561 Lisp_Object val = external_plist_get (&XSYMBOL (sym)->plist, propname,
2562 0, ERROR_ME);
2563 return UNBOUNDP (val) ? default_ : val;
2564 }
2565
2566 static void
2567 symbol_putprop (Lisp_Object sym, Lisp_Object propname, Lisp_Object value)
2568 {
2569 external_plist_put (&XSYMBOL (sym)->plist, propname, value, 0, ERROR_ME);
2570 }
2571
2572 static int
2573 symbol_remprop (Lisp_Object symbol, Lisp_Object propname)
2574 {
2575 return external_remprop (&XSYMBOL (symbol)->plist, propname, 0, ERROR_ME);
2576 }
2577
2578 /* We store the string's extent info as the first element of the string's
2579 property list; and the string's MODIFF as the first or second element
2580 of the string's property list (depending on whether the extent info
2581 is present), but only if the string has been modified. This is ugly
2582 but it reduces the memory allocated for the string in the vast
2583 majority of cases, where the string is never modified and has no
2584 extent info. */
2585
2586
2587 static Lisp_Object *
2588 string_plist_ptr (struct Lisp_String *s)
2589 {
2590 Lisp_Object *ptr = &s->plist;
2591
2592 if (CONSP (*ptr) && EXTENT_INFOP (XCAR (*ptr)))
2593 ptr = &XCDR (*ptr);
2594 if (CONSP (*ptr) && INTP (XCAR (*ptr)))
2595 ptr = &XCDR (*ptr);
2596 return ptr;
2597 }
2598
2599 static Lisp_Object
2600 string_getprop (struct Lisp_String *s, Lisp_Object property,
2601 Lisp_Object default_)
2602 {
2603 Lisp_Object val = external_plist_get (string_plist_ptr (s), property, 0,
2604 ERROR_ME);
2605 return UNBOUNDP (val) ? default_ : val;
2606 }
2607
2608 static void
2609 string_putprop (struct Lisp_String *s, Lisp_Object property,
2610 Lisp_Object value)
2611 {
2612 external_plist_put (string_plist_ptr (s), property, value, 0, ERROR_ME);
2613 }
2614
2615 static int
2616 string_remprop (struct Lisp_String *s, Lisp_Object property)
2617 {
2618 return external_remprop (string_plist_ptr (s), property, 0, ERROR_ME);
2619 }
2620
2621 static Lisp_Object
2622 string_plist (struct Lisp_String *s)
2623 {
2624 return *string_plist_ptr (s);
2625 }
2626
2627 DEFUN ("get", Fget, 2, 3, 0, /* 2569 DEFUN ("get", Fget, 2, 3, 0, /*
2628 Return the value of OBJECT's PROPNAME property. 2570 Return the value of OBJECT's PROPERTY property.
2629 This is the last VALUE stored with `(put OBJECT PROPNAME VALUE)'. 2571 This is the last VALUE stored with `(put OBJECT PROPERTY VALUE)'.
2630 If there is no such property, return optional third arg DEFAULT 2572 If there is no such property, return optional third arg DEFAULT
2631 \(which defaults to `nil'). OBJECT can be a symbol, face, extent, 2573 \(which defaults to `nil'). OBJECT can be a symbol, string, extent,
2632 or string. See also `put', `remprop', and `object-plist'. 2574 face, or glyph. See also `put', `remprop', and `object-plist'.
2633 */ 2575 */
2634 (object, propname, default_)) 2576 (object, property, default_))
2635 { 2577 {
2636 /* Various places in emacs call Fget() and expect it not to quit, 2578 /* Various places in emacs call Fget() and expect it not to quit,
2637 so don't quit. */ 2579 so don't quit. */
2638 2580 Lisp_Object val;
2639 /* It's easiest to treat symbols specially because they may not 2581
2640 be an lrecord */ 2582 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->getprop)
2641 if (SYMBOLP (object)) 2583 val = XRECORD_LHEADER_IMPLEMENTATION (object)->getprop (object, property);
2642 return symbol_getprop (object, propname, default_);
2643 else if (STRINGP (object))
2644 return string_getprop (XSTRING (object), propname, default_);
2645 else if (LRECORDP (object))
2646 {
2647 CONST struct lrecord_implementation *imp
2648 = XRECORD_LHEADER_IMPLEMENTATION (object);
2649 if (!imp->getprop)
2650 goto noprops;
2651
2652 {
2653 Lisp_Object val = (imp->getprop) (object, propname);
2654 if (UNBOUNDP (val))
2655 val = default_;
2656 return val;
2657 }
2658 }
2659 else 2584 else
2660 { 2585 signal_simple_error ("Object type has no properties", object);
2661 noprops: 2586
2662 signal_simple_error ("Object type has no properties", object); 2587 return UNBOUNDP (val) ? default_ : val;
2663 return Qnil; /* Not reached */
2664 }
2665 } 2588 }
2666 2589
2667 DEFUN ("put", Fput, 3, 3, 0, /* 2590 DEFUN ("put", Fput, 3, 3, 0, /*
2668 Store OBJECT's PROPNAME property with value VALUE. 2591 Set OBJECT's PROPERTY to VALUE.
2669 It can be retrieved with `(get OBJECT PROPNAME)'. OBJECT can be a 2592 It can be subsequently retrieved with `(get OBJECT PROPERTY)'.
2670 symbol, face, extent, or string. 2593 OBJECT can be a symbol, face, extent, or string.
2671
2672 For a string, no properties currently have predefined meanings. 2594 For a string, no properties currently have predefined meanings.
2673 For the predefined properties for extents, see `set-extent-property'. 2595 For the predefined properties for extents, see `set-extent-property'.
2674 For the predefined properties for faces, see `set-face-property'. 2596 For the predefined properties for faces, see `set-face-property'.
2675
2676 See also `get', `remprop', and `object-plist'. 2597 See also `get', `remprop', and `object-plist'.
2677 */ 2598 */
2678 (object, propname, value)) 2599 (object, property, value))
2679 { 2600 {
2680 CHECK_SYMBOL (propname); 2601 CHECK_LISP_WRITEABLE (object);
2681 CHECK_IMPURE (object); 2602
2682 2603 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->putprop)
2683 if (SYMBOLP (object)) 2604 {
2684 symbol_putprop (object, propname, value); 2605 if (! XRECORD_LHEADER_IMPLEMENTATION (object)->putprop
2685 else if (STRINGP (object)) 2606 (object, property, value))
2686 string_putprop (XSTRING (object), propname, value); 2607 signal_simple_error ("Can't set property on object", property);
2687 else if (LRECORDP (object))
2688 {
2689 CONST struct lrecord_implementation
2690 *imp = XRECORD_LHEADER_IMPLEMENTATION (object);
2691 if (imp->putprop)
2692 {
2693 if (! (imp->putprop) (object, propname, value))
2694 signal_simple_error ("Can't set property on object", propname);
2695 }
2696 else
2697 goto noprops;
2698 } 2608 }
2699 else 2609 else
2700 { 2610 signal_simple_error ("Object type has no settable properties", object);
2701 noprops:
2702 signal_simple_error ("Object type has no settable properties", object);
2703 }
2704 2611
2705 return value; 2612 return value;
2706 } 2613 }
2707 2614
2708 void
2709 pure_put (Lisp_Object sym, Lisp_Object prop, Lisp_Object val)
2710 {
2711 Fput (sym, prop, Fpurecopy (val));
2712 }
2713
2714 DEFUN ("remprop", Fremprop, 2, 2, 0, /* 2615 DEFUN ("remprop", Fremprop, 2, 2, 0, /*
2715 Remove from OBJECT's property list the property PROPNAME and its 2616 Remove, from OBJECT's property list, PROPERTY and its corresponding value.
2716 value. OBJECT can be a symbol, face, extent, or string. Returns 2617 OBJECT can be a symbol, string, extent, face, or glyph. Return non-nil
2717 non-nil if the property list was actually changed (i.e. if PROPNAME 2618 if the property list was actually modified (i.e. if PROPERTY was present
2718 was present in the property list). See also `get', `put', and 2619 in the property list). See also `get', `put', and `object-plist'.
2719 `object-plist'. 2620 */
2720 */ 2621 (object, property))
2721 (object, propname)) 2622 {
2722 { 2623 int ret = 0;
2723 int retval = 0; 2624
2724 2625 CHECK_LISP_WRITEABLE (object);
2725 CHECK_SYMBOL (propname); 2626
2726 CHECK_IMPURE (object); 2627 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->remprop)
2727 2628 {
2728 if (SYMBOLP (object)) 2629 ret = XRECORD_LHEADER_IMPLEMENTATION (object)->remprop (object, property);
2729 retval = symbol_remprop (object, propname); 2630 if (ret == -1)
2730 else if (STRINGP (object)) 2631 signal_simple_error ("Can't remove property from object", property);
2731 retval = string_remprop (XSTRING (object), propname);
2732 else if (LRECORDP (object))
2733 {
2734 CONST struct lrecord_implementation
2735 *imp = XRECORD_LHEADER_IMPLEMENTATION (object);
2736 if (imp->remprop)
2737 {
2738 retval = (imp->remprop) (object, propname);
2739 if (retval == -1)
2740 signal_simple_error ("Can't remove property from object",
2741 propname);
2742 }
2743 else
2744 goto noprops;
2745 } 2632 }
2746 else 2633 else
2747 { 2634 signal_simple_error ("Object type has no removable properties", object);
2748 noprops: 2635
2749 signal_simple_error ("Object type has no removable properties", object); 2636 return ret ? Qt : Qnil;
2750 }
2751
2752 return retval ? Qt : Qnil;
2753 } 2637 }
2754 2638
2755 DEFUN ("object-plist", Fobject_plist, 1, 1, 0, /* 2639 DEFUN ("object-plist", Fobject_plist, 1, 1, 0, /*
2756 Return a property list of OBJECT's props. 2640 Return a property list of OBJECT's properties.
2757 For a symbol this is equivalent to `symbol-plist'. 2641 For a symbol, this is equivalent to `symbol-plist'.
2758 Do not modify the property list directly; this may or may not have 2642 OBJECT can be a symbol, string, extent, face, or glyph.
2759 the desired effects. (In particular, for a property with a special 2643 Do not modify the returned property list directly;
2760 interpretation, this will probably have no effect at all.) 2644 this may or may not have the desired effects. Use `put' instead.
2761 */ 2645 */
2762 (object)) 2646 (object))
2763 { 2647 {
2764 if (SYMBOLP (object)) 2648 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->plist)
2765 return Fsymbol_plist (object); 2649 return XRECORD_LHEADER_IMPLEMENTATION (object)->plist (object);
2766 else if (STRINGP (object))
2767 return string_plist (XSTRING (object));
2768 else if (LRECORDP (object))
2769 {
2770 CONST struct lrecord_implementation
2771 *imp = XRECORD_LHEADER_IMPLEMENTATION (object);
2772 if (imp->plist)
2773 return (imp->plist) (object);
2774 else
2775 signal_simple_error ("Object type has no properties", object);
2776 }
2777 else 2650 else
2778 signal_simple_error ("Object type has no properties", object); 2651 signal_simple_error ("Object type has no properties", object);
2779 2652
2780 return Qnil; 2653 return Qnil;
2781 } 2654 }
2784 int 2657 int
2785 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 2658 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
2786 { 2659 {
2787 if (depth > 200) 2660 if (depth > 200)
2788 error ("Stack overflow in equal"); 2661 error ("Stack overflow in equal");
2789 #ifndef LRECORD_CONS
2790 do_cdr:
2791 #endif
2792 QUIT; 2662 QUIT;
2793 if (EQ_WITH_EBOLA_NOTICE (obj1, obj2)) 2663 if (EQ_WITH_EBOLA_NOTICE (obj1, obj2))
2794 return 1; 2664 return 1;
2795 /* Note that (equal 20 20.0) should be nil */ 2665 /* Note that (equal 20 20.0) should be nil */
2796 if (XTYPE (obj1) != XTYPE (obj2)) 2666 if (XTYPE (obj1) != XTYPE (obj2))
2797 return 0; 2667 return 0;
2798 #ifndef LRECORD_CONS
2799 if (CONSP (obj1))
2800 {
2801 if (!internal_equal (XCAR (obj1), XCAR (obj2), depth + 1))
2802 return 0;
2803 obj1 = XCDR (obj1);
2804 obj2 = XCDR (obj2);
2805 goto do_cdr;
2806 }
2807 #endif
2808 #ifndef LRECORD_VECTOR
2809 if (VECTORP (obj1))
2810 {
2811 Lisp_Object *v1 = XVECTOR_DATA (obj1);
2812 Lisp_Object *v2 = XVECTOR_DATA (obj2);
2813 int len = XVECTOR_LENGTH (obj1);
2814 if (len != XVECTOR_LENGTH (obj2))
2815 return 0;
2816 while (len--)
2817 if (!internal_equal (*v1++, *v2++, depth + 1))
2818 return 0;
2819 return 1;
2820 }
2821 #endif
2822 #ifndef LRECORD_STRING
2823 if (STRINGP (obj1))
2824 {
2825 Bytecount len;
2826 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) &&
2827 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len));
2828 }
2829 #endif
2830 if (LRECORDP (obj1)) 2668 if (LRECORDP (obj1))
2831 { 2669 {
2832 CONST struct lrecord_implementation 2670 const struct lrecord_implementation
2833 *imp1 = XRECORD_LHEADER_IMPLEMENTATION (obj1), 2671 *imp1 = XRECORD_LHEADER_IMPLEMENTATION (obj1),
2834 *imp2 = XRECORD_LHEADER_IMPLEMENTATION (obj2); 2672 *imp2 = XRECORD_LHEADER_IMPLEMENTATION (obj2);
2835 2673
2836 return (imp1 == imp2) && 2674 return (imp1 == imp2) &&
2837 /* EQ-ness of the objects was noticed above */ 2675 /* EQ-ness of the objects was noticed above */
2849 static int 2687 static int
2850 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 2688 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
2851 { 2689 {
2852 if (depth > 200) 2690 if (depth > 200)
2853 error ("Stack overflow in equal"); 2691 error ("Stack overflow in equal");
2854 #ifndef LRECORD_CONS
2855 do_cdr:
2856 #endif
2857 QUIT; 2692 QUIT;
2858 if (HACKEQ_UNSAFE (obj1, obj2)) 2693 if (HACKEQ_UNSAFE (obj1, obj2))
2859 return 1; 2694 return 1;
2860 /* Note that (equal 20 20.0) should be nil */ 2695 /* Note that (equal 20 20.0) should be nil */
2861 if (XTYPE (obj1) != XTYPE (obj2)) 2696 if (XTYPE (obj1) != XTYPE (obj2))
2862 return 0; 2697 return 0;
2863 #ifndef LRECORD_CONS
2864 if (CONSP (obj1))
2865 {
2866 if (!internal_old_equal (XCAR (obj1), XCAR (obj2), depth + 1))
2867 return 0;
2868 obj1 = XCDR (obj1);
2869 obj2 = XCDR (obj2);
2870 goto do_cdr;
2871 }
2872 #endif
2873 #ifndef LRECORD_VECTOR
2874 if (VECTORP (obj1))
2875 {
2876 Lisp_Object *v1 = XVECTOR_DATA (obj1);
2877 Lisp_Object *v2 = XVECTOR_DATA (obj2);
2878 int len = XVECTOR_LENGTH (obj1);
2879 if (len != XVECTOR_LENGTH (obj2))
2880 return 0;
2881 while (len--)
2882 if (!internal_old_equal (*v1++, *v2++, depth + 1))
2883 return 0;
2884 return 1;
2885 }
2886 #endif
2887 2698
2888 return internal_equal (obj1, obj2, depth); 2699 return internal_equal (obj1, obj2, depth);
2889 } 2700 }
2890 2701
2891 DEFUN ("equal", Fequal, 2, 2, 0, /* 2702 DEFUN ("equal", Fequal, 2, 2, 0, /*
2914 return internal_old_equal (obj1, obj2, 0) ? Qt : Qnil; 2725 return internal_old_equal (obj1, obj2, 0) ? Qt : Qnil;
2915 } 2726 }
2916 2727
2917 2728
2918 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /* 2729 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /*
2919 Store each element of ARRAY with ITEM. 2730 Destructively modify ARRAY by replacing each element with ITEM.
2920 ARRAY is a vector, bit vector, or string. 2731 ARRAY is a vector, bit vector, or string.
2921 */ 2732 */
2922 (array, item)) 2733 (array, item))
2923 { 2734 {
2924 retry: 2735 retry:
2925 if (STRINGP (array)) 2736 if (STRINGP (array))
2926 { 2737 {
2927 Emchar charval; 2738 Lisp_String *s = XSTRING (array);
2928 struct Lisp_String *s = XSTRING (array); 2739 Bytecount old_bytecount = string_length (s);
2929 Charcount len = string_char_length (s); 2740 Bytecount new_bytecount;
2930 Charcount i; 2741 Bytecount item_bytecount;
2742 Bufbyte item_buf[MAX_EMCHAR_LEN];
2743 Bufbyte *p;
2744 Bufbyte *end;
2745
2931 CHECK_CHAR_COERCE_INT (item); 2746 CHECK_CHAR_COERCE_INT (item);
2932 CHECK_IMPURE (array); 2747 CHECK_LISP_WRITEABLE (array);
2933 charval = XCHAR (item); 2748
2934 for (i = 0; i < len; i++) 2749 item_bytecount = set_charptr_emchar (item_buf, XCHAR (item));
2935 set_string_char (s, i, charval); 2750 new_bytecount = item_bytecount * string_char_length (s);
2751
2752 resize_string (s, -1, new_bytecount - old_bytecount);
2753
2754 for (p = string_data (s), end = p + new_bytecount;
2755 p < end;
2756 p += item_bytecount)
2757 memcpy (p, item_buf, item_bytecount);
2758 *p = '\0';
2759
2936 bump_string_modiff (array); 2760 bump_string_modiff (array);
2937 } 2761 }
2938 else if (VECTORP (array)) 2762 else if (VECTORP (array))
2939 { 2763 {
2940 Lisp_Object *p = XVECTOR_DATA (array); 2764 Lisp_Object *p = XVECTOR_DATA (array);
2941 int len = XVECTOR_LENGTH (array); 2765 int len = XVECTOR_LENGTH (array);
2942 CHECK_IMPURE (array); 2766 CHECK_LISP_WRITEABLE (array);
2943 while (len--) 2767 while (len--)
2944 *p++ = item; 2768 *p++ = item;
2945 } 2769 }
2946 else if (BIT_VECTORP (array)) 2770 else if (BIT_VECTORP (array))
2947 { 2771 {
2948 struct Lisp_Bit_Vector *v = XBIT_VECTOR (array); 2772 Lisp_Bit_Vector *v = XBIT_VECTOR (array);
2949 int len = bit_vector_length (v); 2773 int len = bit_vector_length (v);
2950 int bit; 2774 int bit;
2951 CHECK_BIT (item); 2775 CHECK_BIT (item);
2952 CHECK_IMPURE (array); 2776 CHECK_LISP_WRITEABLE (array);
2953 bit = XINT (item); 2777 bit = XINT (item);
2954 while (len--) 2778 while (len--)
2955 set_bit_vector_bit (v, len, bit); 2779 set_bit_vector_bit (v, len, bit);
2956 } 2780 }
2957 else 2781 else
3093 } 2917 }
3094 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ 2918 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */
3095 } 2919 }
3096 2920
3097 2921
3098 /* This is the guts of all mapping functions. 2922 /* This is the guts of several mapping functions.
3099 Apply fn to each element of seq, one by one, 2923 Apply FUNCTION to each element of SEQUENCE, one by one,
3100 storing the results into elements of vals, a C vector of Lisp_Objects. 2924 storing the results into elements of VALS, a C vector of Lisp_Objects.
3101 leni is the length of vals, which should also be the length of seq. 2925 LENI is the length of VALS, which should also be the length of SEQUENCE.
3102 2926
3103 If VALS is a null pointer, do not accumulate the results. */ 2927 If VALS is a null pointer, do not accumulate the results. */
3104 2928
3105 static void 2929 static void
3106 mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq) 2930 mapcar1 (size_t leni, Lisp_Object *vals,
2931 Lisp_Object function, Lisp_Object sequence)
3107 { 2932 {
3108 Lisp_Object result; 2933 Lisp_Object result;
3109 Lisp_Object args[2]; 2934 Lisp_Object args[2];
3110 int i; 2935 int i;
3111 struct gcpro gcpro1; 2936 struct gcpro gcpro1;
3114 { 2939 {
3115 GCPRO1 (vals[0]); 2940 GCPRO1 (vals[0]);
3116 gcpro1.nvars = 0; 2941 gcpro1.nvars = 0;
3117 } 2942 }
3118 2943
3119 args[0] = fn; 2944 args[0] = function;
3120 2945
3121 if (LISTP (seq)) 2946 if (LISTP (sequence))
3122 { 2947 {
3123 for (i = 0; i < leni; i++) 2948 /* A devious `function' could either:
3124 { 2949 - insert garbage into the list in front of us, causing XCDR to crash
3125 args[1] = XCAR (seq); 2950 - amputate the list behind us using (setcdr), causing the remaining
3126 seq = XCDR (seq); 2951 elts to lose their GCPRO status.
3127 result = Ffuncall (2, args); 2952
3128 if (vals) vals[gcpro1.nvars++] = result; 2953 if (vals != 0) we avoid this by copying the elts into the
3129 } 2954 `vals' array. By a stroke of luck, `vals' is exactly large
3130 } 2955 enough to hold the elts left to be traversed as well as the
3131 else if (VECTORP (seq)) 2956 results computed so far.
3132 { 2957
3133 Lisp_Object *objs = XVECTOR_DATA (seq); 2958 if (vals == 0) we don't have any free space available and
2959 don't want to eat up any more stack with alloca().
2960 So we use EXTERNAL_LIST_LOOP_3 and GCPRO the tail. */
2961
2962 if (vals)
2963 {
2964 Lisp_Object *val = vals;
2965 Lisp_Object elt;
2966
2967 LIST_LOOP_2 (elt, sequence)
2968 *val++ = elt;
2969
2970 gcpro1.nvars = leni;
2971
2972 for (i = 0; i < leni; i++)
2973 {
2974 args[1] = vals[i];
2975 vals[i] = Ffuncall (2, args);
2976 }
2977 }
2978 else
2979 {
2980 Lisp_Object elt, tail;
2981 struct gcpro ngcpro1;
2982
2983 NGCPRO1 (tail);
2984
2985 {
2986 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
2987 {
2988 args[1] = elt;
2989 Ffuncall (2, args);
2990 }
2991 }
2992
2993 NUNGCPRO;
2994 }
2995 }
2996 else if (VECTORP (sequence))
2997 {
2998 Lisp_Object *objs = XVECTOR_DATA (sequence);
3134 for (i = 0; i < leni; i++) 2999 for (i = 0; i < leni; i++)
3135 { 3000 {
3136 args[1] = *objs++; 3001 args[1] = *objs++;
3137 result = Ffuncall (2, args); 3002 result = Ffuncall (2, args);
3138 if (vals) vals[gcpro1.nvars++] = result; 3003 if (vals) vals[gcpro1.nvars++] = result;
3139 } 3004 }
3140 } 3005 }
3141 else if (STRINGP (seq)) 3006 else if (STRINGP (sequence))
3142 { 3007 {
3143 Bufbyte *p = XSTRING_DATA (seq); 3008 /* The string data of `sequence' might be relocated during GC. */
3144 for (i = 0; i < leni; i++) 3009 Bytecount slen = XSTRING_LENGTH (sequence);
3010 Bufbyte *p = alloca_array (Bufbyte, slen);
3011 Bufbyte *end = p + slen;
3012
3013 memcpy (p, XSTRING_DATA (sequence), slen);
3014
3015 while (p < end)
3145 { 3016 {
3146 args[1] = make_char (charptr_emchar (p)); 3017 args[1] = make_char (charptr_emchar (p));
3147 INC_CHARPTR (p); 3018 INC_CHARPTR (p);
3148 result = Ffuncall (2, args); 3019 result = Ffuncall (2, args);
3149 if (vals) vals[gcpro1.nvars++] = result; 3020 if (vals) vals[gcpro1.nvars++] = result;
3150 } 3021 }
3151 } 3022 }
3152 else if (BIT_VECTORP (seq)) 3023 else if (BIT_VECTORP (sequence))
3153 { 3024 {
3154 struct Lisp_Bit_Vector *v = XBIT_VECTOR (seq); 3025 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence);
3155 for (i = 0; i < leni; i++) 3026 for (i = 0; i < leni; i++)
3156 { 3027 {
3157 args[1] = make_int (bit_vector_bit (v, i)); 3028 args[1] = make_int (bit_vector_bit (v, i));
3158 result = Ffuncall (2, args); 3029 result = Ffuncall (2, args);
3159 if (vals) vals[gcpro1.nvars++] = result; 3030 if (vals) vals[gcpro1.nvars++] = result;
3160 } 3031 }
3161 } 3032 }
3162 else 3033 else
3163 abort(); /* cannot get here since Flength(seq) did not get an error */ 3034 abort (); /* unreachable, since Flength (sequence) did not get an error */
3164 3035
3165 if (vals) 3036 if (vals)
3166 UNGCPRO; 3037 UNGCPRO;
3167 } 3038 }
3168 3039
3169 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /* 3040 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /*
3170 Apply FN to each element of SEQ, and concat the results as strings. 3041 Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.
3171 In between each pair of results, stick in SEP. 3042 In between each pair of results, insert SEPARATOR. Thus, using " " as
3172 Thus, " " as SEP results in spaces between the values returned by FN. 3043 SEPARATOR results in spaces between the values returned by FUNCTION.
3173 */ 3044 SEQUENCE may be a list, a vector, a bit vector, or a string.
3174 (fn, seq, sep)) 3045 */
3175 { 3046 (function, sequence, separator))
3176 size_t len = XINT (Flength (seq)); 3047 {
3048 size_t len = XINT (Flength (sequence));
3177 Lisp_Object *args; 3049 Lisp_Object *args;
3178 int i; 3050 int i;
3179 struct gcpro gcpro1;
3180 int nargs = len + len - 1; 3051 int nargs = len + len - 1;
3181 3052
3182 if (nargs < 0) return build_string (""); 3053 if (len == 0) return build_string ("");
3183 3054
3184 args = alloca_array (Lisp_Object, nargs); 3055 args = alloca_array (Lisp_Object, nargs);
3185 3056
3186 GCPRO1 (sep); 3057 mapcar1 (len, args, function, sequence);
3187 mapcar1 (len, args, fn, seq);
3188 UNGCPRO;
3189 3058
3190 for (i = len - 1; i >= 0; i--) 3059 for (i = len - 1; i >= 0; i--)
3191 args[i + i] = args[i]; 3060 args[i + i] = args[i];
3192 3061
3193 for (i = 1; i < nargs; i += 2) 3062 for (i = 1; i < nargs; i += 2)
3194 args[i] = sep; 3063 args[i] = separator;
3195 3064
3196 return Fconcat (nargs, args); 3065 return Fconcat (nargs, args);
3197 } 3066 }
3198 3067
3199 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* 3068 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /*
3200 Apply FUNCTION to each element of SEQUENCE, and make a list of the results. 3069 Apply FUNCTION to each element of SEQUENCE; return a list of the results.
3201 The result is a list just as long as SEQUENCE. 3070 The result is a list of the same length as SEQUENCE.
3202 SEQUENCE may be a list, a vector, a bit vector, or a string. 3071 SEQUENCE may be a list, a vector, a bit vector, or a string.
3203 */ 3072 */
3204 (fn, seq)) 3073 (function, sequence))
3205 { 3074 {
3206 size_t len = XINT (Flength (seq)); 3075 size_t len = XINT (Flength (sequence));
3207 Lisp_Object *args = alloca_array (Lisp_Object, len); 3076 Lisp_Object *args = alloca_array (Lisp_Object, len);
3208 3077
3209 mapcar1 (len, args, fn, seq); 3078 mapcar1 (len, args, function, sequence);
3210 3079
3211 return Flist (len, args); 3080 return Flist (len, args);
3212 } 3081 }
3213 3082
3214 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* 3083 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /*
3215 Apply FUNCTION to each element of SEQUENCE, making a vector of the results. 3084 Apply FUNCTION to each element of SEQUENCE; return a vector of the results.
3216 The result is a vector of the same length as SEQUENCE. 3085 The result is a vector of the same length as SEQUENCE.
3217 SEQUENCE may be a list, a vector or a string. 3086 SEQUENCE may be a list, a vector, a bit vector, or a string.
3218 */ 3087 */
3219 (fn, seq)) 3088 (function, sequence))
3220 { 3089 {
3221 size_t len = XINT (Flength (seq)); 3090 size_t len = XINT (Flength (sequence));
3222 Lisp_Object result = make_vector (len, Qnil); 3091 Lisp_Object result = make_vector (len, Qnil);
3223 struct gcpro gcpro1; 3092 struct gcpro gcpro1;
3224 3093
3225 GCPRO1 (result); 3094 GCPRO1 (result);
3226 mapcar1 (len, XVECTOR_DATA (result), fn, seq); 3095 mapcar1 (len, XVECTOR_DATA (result), function, sequence);
3227 UNGCPRO; 3096 UNGCPRO;
3228 3097
3229 return result; 3098 return result;
3230 } 3099 }
3231 3100
3232 DEFUN ("mapc", Fmapc, 2, 2, 0, /* 3101 DEFUN ("mapc-internal", Fmapc_internal, 2, 2, 0, /*
3233 Apply FUNCTION to each element of SEQUENCE. 3102 Apply FUNCTION to each element of SEQUENCE.
3234 SEQUENCE may be a list, a vector, a bit vector, or a string. 3103 SEQUENCE may be a list, a vector, a bit vector, or a string.
3235 This function is like `mapcar' but does not accumulate the results, 3104 This function is like `mapcar' but does not accumulate the results,
3236 which is more efficient if you do not use the results. 3105 which is more efficient if you do not use the results.
3237 */ 3106
3238 (fn, seq)) 3107 The difference between this and `mapc' is that `mapc' supports all
3239 { 3108 the spiffy Common Lisp arguments. You should normally use `mapc'.
3240 mapcar1 (XINT (Flength (seq)), 0, fn, seq); 3109 */
3241 3110 (function, sequence))
3242 return seq; 3111 {
3112 mapcar1 (XINT (Flength (sequence)), 0, function, sequence);
3113
3114 return sequence;
3243 } 3115 }
3244 3116
3245 3117
3246 /* #### this function doesn't belong in this file! */ 3118 /* #### this function doesn't belong in this file! */
3247 3119
3442 return unbind_to (speccount, feature); 3314 return unbind_to (speccount, feature);
3443 } 3315 }
3444 } 3316 }
3445 3317
3446 /* base64 encode/decode functions. 3318 /* base64 encode/decode functions.
3447 Based on code from GNU recode. */ 3319
3448 3320 Originally based on code from GNU recode. Ported to FSF Emacs by
3449 #define MIME_LINE_LENGTH 76 3321 Lars Magne Ingebrigtsen and Karl Heuer. Ported to XEmacs and
3322 subsequently heavily hacked by Hrvoje Niksic. */
3323
3324 #define MIME_LINE_LENGTH 72
3450 3325
3451 #define IS_ASCII(Character) \ 3326 #define IS_ASCII(Character) \
3452 ((Character) < 128) 3327 ((Character) < 128)
3453 #define IS_BASE64(Character) \ 3328 #define IS_BASE64(Character) \
3454 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0) 3329 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0)
3500 3375
3501 The octets are divided into 6 bit chunks, which are then encoded into 3376 The octets are divided into 6 bit chunks, which are then encoded into
3502 base64 characters. */ 3377 base64 characters. */
3503 3378
3504 #define ADVANCE_INPUT(c, stream) \ 3379 #define ADVANCE_INPUT(c, stream) \
3505 (ec = Lstream_get_emchar (stream), \ 3380 ((ec = Lstream_get_emchar (stream)) == -1 ? 0 : \
3506 ec == -1 ? 0 : \
3507 ((ec > 255) ? \ 3381 ((ec > 255) ? \
3508 (error ("Non-ascii character detected in base64 input"), 0) \ 3382 (signal_simple_error ("Non-ascii character in base64 input", \
3509 : (c = (Bufbyte)ec, 1))) 3383 make_char (ec)), 0) \
3384 : (c = (Bufbyte)ec), 1))
3510 3385
3511 static Bytind 3386 static Bytind
3512 base64_encode_1 (Lstream *istream, Bufbyte *to, int line_break) 3387 base64_encode_1 (Lstream *istream, Bufbyte *to, int line_break)
3513 { 3388 {
3514 EMACS_INT counter = 0; 3389 EMACS_INT counter = 0;
3564 3439
3565 return e - to; 3440 return e - to;
3566 } 3441 }
3567 #undef ADVANCE_INPUT 3442 #undef ADVANCE_INPUT
3568 3443
3569 #define ADVANCE_INPUT(c, stream) \ 3444 /* Get next character from the stream, except that non-base64
3570 (ec = Lstream_get_emchar (stream), \ 3445 characters are ignored. This is in accordance with rfc2045. EC
3571 ec == -1 ? 0 : (c = (Bufbyte)ec, 1)) 3446 should be an Emchar, so that it can hold -1 as the value for EOF. */
3572 3447 #define ADVANCE_INPUT_IGNORE_NONBASE64(ec, stream, streampos) do { \
3573 #define INPUT_EOF_P(stream) \ 3448 ec = Lstream_get_emchar (stream); \
3574 (ADVANCE_INPUT (c2, stream) \ 3449 ++streampos; \
3575 ? (Lstream_unget_emchar (stream, (Emchar)c2), 0) \ 3450 /* IS_BASE64 may not be called with negative arguments so check for \
3576 : 1) 3451 EOF first. */ \
3577 3452 if (ec < 0 || IS_BASE64 (ec) || ec == '=') \
3578 #define STORE_BYTE(pos, val) do { \ 3453 break; \
3454 } while (1)
3455
3456 #define STORE_BYTE(pos, val, ccnt) do { \
3579 pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val))); \ 3457 pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val))); \
3580 ++*ccptr; \ 3458 ++ccnt; \
3581 } while (0) 3459 } while (0)
3582 3460
3583 static Bytind 3461 static Bytind
3584 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr) 3462 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr)
3585 { 3463 {
3586 EMACS_INT counter = 0; 3464 Charcount ccnt = 0;
3587 Emchar ec;
3588 Bufbyte *e = to; 3465 Bufbyte *e = to;
3589 unsigned long value; 3466 EMACS_INT streampos = 0;
3590 3467
3591 *ccptr = 0;
3592 while (1) 3468 while (1)
3593 { 3469 {
3594 Bufbyte c, c2; 3470 Emchar ec;
3595 3471 unsigned long value;
3596 if (!ADVANCE_INPUT (c, istream)) 3472
3473 /* Process first byte of a quadruplet. */
3474 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3475 if (ec < 0)
3597 break; 3476 break;
3598 3477 if (ec == '=')
3599 /* Accept wrapping lines, reversibly if at each 76 characters. */ 3478 signal_simple_error ("Illegal `=' character while decoding base64",
3600 if (c == '\n') 3479 make_int (streampos));
3601 { 3480 value = base64_char_to_value[ec] << 18;
3602 if (!ADVANCE_INPUT (c, istream))
3603 break;
3604 if (INPUT_EOF_P (istream))
3605 break;
3606 /* FSF Emacs has this check, apparently inherited from
3607 recode. However, I see no reason to be this picky about
3608 line length -- why reject base64 with say 72-byte lines?
3609 (yes, there are programs that generate them.) */
3610 /*if (counter != MIME_LINE_LENGTH / 4) return -1;*/
3611 counter = 1;
3612 }
3613 else
3614 counter++;
3615
3616 /* Process first byte of a quadruplet. */
3617 if (!IS_BASE64 (c))
3618 return -1;
3619 value = base64_char_to_value[c] << 18;
3620 3481
3621 /* Process second byte of a quadruplet. */ 3482 /* Process second byte of a quadruplet. */
3622 if (!ADVANCE_INPUT (c, istream)) 3483 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3623 return -1; 3484 if (ec < 0)
3624 3485 error ("Premature EOF while decoding base64");
3625 if (!IS_BASE64 (c)) 3486 if (ec == '=')
3626 return -1; 3487 signal_simple_error ("Illegal `=' character while decoding base64",
3627 value |= base64_char_to_value[c] << 12; 3488 make_int (streampos));
3628 3489 value |= base64_char_to_value[ec] << 12;
3629 STORE_BYTE (e, value >> 16); 3490 STORE_BYTE (e, value >> 16, ccnt);
3630 3491
3631 /* Process third byte of a quadruplet. */ 3492 /* Process third byte of a quadruplet. */
3632 if (!ADVANCE_INPUT (c, istream)) 3493 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3633 return -1; 3494 if (ec < 0)
3634 3495 error ("Premature EOF while decoding base64");
3635 if (c == '=') 3496
3636 { 3497 if (ec == '=')
3637 if (!ADVANCE_INPUT (c, istream)) 3498 {
3638 return -1; 3499 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3639 if (c != '=') 3500 if (ec < 0)
3640 return -1; 3501 error ("Premature EOF while decoding base64");
3502 if (ec != '=')
3503 signal_simple_error ("Padding `=' expected but not found while decoding base64",
3504 make_int (streampos));
3641 continue; 3505 continue;
3642 } 3506 }
3643 3507
3644 if (!IS_BASE64 (c)) 3508 value |= base64_char_to_value[ec] << 6;
3645 return -1; 3509 STORE_BYTE (e, 0xff & value >> 8, ccnt);
3646 value |= base64_char_to_value[c] << 6;
3647
3648 STORE_BYTE (e, 0xff & value >> 8);
3649 3510
3650 /* Process fourth byte of a quadruplet. */ 3511 /* Process fourth byte of a quadruplet. */
3651 if (!ADVANCE_INPUT (c, istream)) 3512 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos);
3652 return -1; 3513 if (ec < 0)
3653 3514 error ("Premature EOF while decoding base64");
3654 if (c == '=') 3515 if (ec == '=')
3655 continue; 3516 continue;
3656 3517
3657 if (!IS_BASE64 (c)) 3518 value |= base64_char_to_value[ec];
3658 return -1; 3519 STORE_BYTE (e, 0xff & value, ccnt);
3659 value |= base64_char_to_value[c]; 3520 }
3660 3521
3661 STORE_BYTE (e, 0xff & value); 3522 *ccptr = ccnt;
3662 }
3663
3664 return e - to; 3523 return e - to;
3665 } 3524 }
3666 #undef ADVANCE_INPUT 3525 #undef ADVANCE_INPUT
3667 #undef INPUT_EOF_P 3526 #undef ADVANCE_INPUT_IGNORE_NONBASE64
3527 #undef STORE_BYTE
3668 3528
3669 static Lisp_Object 3529 static Lisp_Object
3670 free_malloced_ptr (Lisp_Object unwind_obj) 3530 free_malloced_ptr (Lisp_Object unwind_obj)
3671 { 3531 {
3672 void *ptr = (void *)get_opaque_ptr (unwind_obj); 3532 void *ptr = (void *)get_opaque_ptr (unwind_obj);
3739 and delete the old. (Insert first in order to preserve markers.) */ 3599 and delete the old. (Insert first in order to preserve markers.) */
3740 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0); 3600 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0);
3741 XMALLOC_UNBIND (encoded, allength, speccount); 3601 XMALLOC_UNBIND (encoded, allength, speccount);
3742 buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0); 3602 buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0);
3743 3603
3744 /* Simulate FSF Emacs: if point was in the region, place it at the 3604 /* Simulate FSF Emacs implementation of this function: if point was
3745 beginning. */ 3605 in the region, place it at the beginning. */
3746 if (old_pt >= begv && old_pt < zv) 3606 if (old_pt >= begv && old_pt < zv)
3747 BUF_SET_PT (buf, begv); 3607 BUF_SET_PT (buf, begv);
3748 3608
3749 /* We return the length of the encoded text. */ 3609 /* We return the length of the encoded text. */
3750 return make_int (encoded_length); 3610 return make_int (encoded_length);
3781 3641
3782 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /* 3642 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /*
3783 Base64-decode the region between BEG and END. 3643 Base64-decode the region between BEG and END.
3784 Return the length of the decoded text. 3644 Return the length of the decoded text.
3785 If the region can't be decoded, return nil and don't modify the buffer. 3645 If the region can't be decoded, return nil and don't modify the buffer.
3646 Characters out of the base64 alphabet are ignored.
3786 */ 3647 */
3787 (beg, end)) 3648 (beg, end))
3788 { 3649 {
3789 struct buffer *buf = current_buffer; 3650 struct buffer *buf = current_buffer;
3790 Bufpos begv, zv, old_pt = BUF_PT (buf); 3651 Bufpos begv, zv, old_pt = BUF_PT (buf);
3805 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); 3666 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length);
3806 if (decoded_length > length * MAX_EMCHAR_LEN) 3667 if (decoded_length > length * MAX_EMCHAR_LEN)
3807 abort (); 3668 abort ();
3808 Lstream_delete (XLSTREAM (input)); 3669 Lstream_delete (XLSTREAM (input));
3809 3670
3810 if (decoded_length < 0)
3811 {
3812 /* The decoding wasn't possible. */
3813 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3814 return Qnil;
3815 }
3816
3817 /* Now we have decoded the region, so we insert the new contents 3671 /* Now we have decoded the region, so we insert the new contents
3818 and delete the old. (Insert first in order to preserve markers.) */ 3672 and delete the old. (Insert first in order to preserve markers.) */
3819 BUF_SET_PT (buf, begv); 3673 BUF_SET_PT (buf, begv);
3820 buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0); 3674 buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0);
3821 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); 3675 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3822 buffer_delete_range (buf, begv + cc_decoded_length, 3676 buffer_delete_range (buf, begv + cc_decoded_length,
3823 zv + cc_decoded_length, 0); 3677 zv + cc_decoded_length, 0);
3824 3678
3825 /* Simulate FSF Emacs: if point was in the region, place it at the 3679 /* Simulate FSF Emacs implementation of this function: if point was
3826 beginning. */ 3680 in the region, place it at the beginning. */
3827 if (old_pt >= begv && old_pt < zv) 3681 if (old_pt >= begv && old_pt < zv)
3828 BUF_SET_PT (buf, begv); 3682 BUF_SET_PT (buf, begv);
3829 3683
3830 return make_int (cc_decoded_length); 3684 return make_int (cc_decoded_length);
3831 } 3685 }
3832 3686
3833 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /* 3687 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /*
3834 Base64-decode STRING and return the result. 3688 Base64-decode STRING and return the result.
3689 Characters out of the base64 alphabet are ignored.
3835 */ 3690 */
3836 (string)) 3691 (string))
3837 { 3692 {
3838 Bufbyte *decoded; 3693 Bufbyte *decoded;
3839 Bytind decoded_length; 3694 Bytind decoded_length;
3851 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, 3706 decoded_length = base64_decode_1 (XLSTREAM (input), decoded,
3852 &cc_decoded_length); 3707 &cc_decoded_length);
3853 if (decoded_length > length * MAX_EMCHAR_LEN) 3708 if (decoded_length > length * MAX_EMCHAR_LEN)
3854 abort (); 3709 abort ();
3855 Lstream_delete (XLSTREAM (input)); 3710 Lstream_delete (XLSTREAM (input));
3856
3857 if (decoded_length < 0)
3858 {
3859 /* The decoding wasn't possible. */
3860 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3861 return Qnil;
3862 }
3863 3711
3864 result = make_string (decoded, decoded_length); 3712 result = make_string (decoded, decoded_length);
3865 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); 3713 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
3866 return result; 3714 return result;
3867 } 3715 }
3946 DEFSUBR (Fold_equal); 3794 DEFSUBR (Fold_equal);
3947 DEFSUBR (Ffillarray); 3795 DEFSUBR (Ffillarray);
3948 DEFSUBR (Fnconc); 3796 DEFSUBR (Fnconc);
3949 DEFSUBR (Fmapcar); 3797 DEFSUBR (Fmapcar);
3950 DEFSUBR (Fmapvector); 3798 DEFSUBR (Fmapvector);
3951 DEFSUBR (Fmapc); 3799 DEFSUBR (Fmapc_internal);
3952 DEFSUBR (Fmapconcat); 3800 DEFSUBR (Fmapconcat);
3953 DEFSUBR (Fload_average); 3801 DEFSUBR (Fload_average);
3954 DEFSUBR (Ffeaturep); 3802 DEFSUBR (Ffeaturep);
3955 DEFSUBR (Frequire); 3803 DEFSUBR (Frequire);
3956 DEFSUBR (Fprovide); 3804 DEFSUBR (Fprovide);
3966 DEFVAR_LISP ("features", &Vfeatures /* 3814 DEFVAR_LISP ("features", &Vfeatures /*
3967 A list of symbols which are the features of the executing emacs. 3815 A list of symbols which are the features of the executing emacs.
3968 Used by `featurep' and `require', and altered by `provide'. 3816 Used by `featurep' and `require', and altered by `provide'.
3969 */ ); 3817 */ );
3970 Vfeatures = Qnil; 3818 Vfeatures = Qnil;
3971 } 3819
3820 Fprovide (intern ("base64"));
3821 }