Mercurial > hg > xemacs-beta
comparison src/fns.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | da8ed4261e83 |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
34 #undef vector | 34 #undef vector |
35 #define vector ***** | 35 #define vector ***** |
36 | 36 |
37 #include "lisp.h" | 37 #include "lisp.h" |
38 | 38 |
39 #include "sysfile.h" | 39 #ifdef HAVE_UNISTD_H |
40 #include <unistd.h> | |
41 #endif | |
42 #include <errno.h> | |
40 | 43 |
41 #include "buffer.h" | 44 #include "buffer.h" |
42 #include "bytecode.h" | 45 #include "bytecode.h" |
43 #include "device.h" | 46 #include "device.h" |
44 #include "events.h" | 47 #include "events.h" |
56 Lisp_Object Qidentity; | 59 Lisp_Object Qidentity; |
57 | 60 |
58 static int internal_old_equal (Lisp_Object, Lisp_Object, int); | 61 static int internal_old_equal (Lisp_Object, Lisp_Object, int); |
59 | 62 |
60 static Lisp_Object | 63 static Lisp_Object |
61 mark_bit_vector (Lisp_Object obj) | 64 mark_bit_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
62 { | 65 { |
63 return Qnil; | 66 return Qnil; |
64 } | 67 } |
65 | 68 |
66 static void | 69 static void |
67 print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) | 70 print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) |
68 { | 71 { |
69 size_t i; | 72 int i; |
70 Lisp_Bit_Vector *v = XBIT_VECTOR (obj); | 73 struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj); |
71 size_t len = bit_vector_length (v); | 74 int len = bit_vector_length (v); |
72 size_t last = len; | 75 int last = len; |
73 | 76 |
74 if (INTP (Vprint_length)) | 77 if (INTP (Vprint_length)) |
75 last = min (len, XINT (Vprint_length)); | 78 last = min (len, XINT (Vprint_length)); |
76 write_c_string ("#*", printcharfun); | 79 write_c_string ("#*", printcharfun); |
77 for (i = 0; i < last; i++) | 80 for (i = 0; i < last; i++) |
87 } | 90 } |
88 | 91 |
89 static int | 92 static int |
90 bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 93 bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
91 { | 94 { |
92 Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1); | 95 struct Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1); |
93 Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2); | 96 struct Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2); |
94 | 97 |
95 return ((bit_vector_length (v1) == bit_vector_length (v2)) && | 98 return ((bit_vector_length (v1) == bit_vector_length (v2)) && |
96 !memcmp (v1->bits, v2->bits, | 99 !memcmp (v1->bits, v2->bits, |
97 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) * | 100 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) * |
98 sizeof (long))); | 101 sizeof (long))); |
99 } | 102 } |
100 | 103 |
101 static unsigned long | 104 static unsigned long |
102 bit_vector_hash (Lisp_Object obj, int depth) | 105 bit_vector_hash (Lisp_Object obj, int depth) |
103 { | 106 { |
104 Lisp_Bit_Vector *v = XBIT_VECTOR (obj); | 107 struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj); |
105 return HASH2 (bit_vector_length (v), | 108 return HASH2 (bit_vector_length (v), |
106 memory_hash (v->bits, | 109 memory_hash (v->bits, |
107 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) * | 110 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) * |
108 sizeof (long))); | 111 sizeof (long))); |
109 } | 112 } |
110 | 113 |
111 static size_t | 114 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("bit-vector", bit_vector, |
112 size_bit_vector (const void *lheader) | 115 mark_bit_vector, print_bit_vector, 0, |
113 { | 116 bit_vector_equal, bit_vector_hash, |
114 Lisp_Bit_Vector *v = (Lisp_Bit_Vector *) lheader; | 117 struct Lisp_Bit_Vector); |
115 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, | |
116 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v))); | |
117 } | |
118 | |
119 static const struct lrecord_description bit_vector_description[] = { | |
120 { XD_LISP_OBJECT, offsetof (Lisp_Bit_Vector, next) }, | |
121 { XD_END } | |
122 }; | |
123 | |
124 | |
125 DEFINE_BASIC_LRECORD_SEQUENCE_IMPLEMENTATION ("bit-vector", bit_vector, | |
126 mark_bit_vector, print_bit_vector, 0, | |
127 bit_vector_equal, bit_vector_hash, | |
128 bit_vector_description, size_bit_vector, | |
129 Lisp_Bit_Vector); | |
130 | 118 |
131 DEFUN ("identity", Fidentity, 1, 1, 0, /* | 119 DEFUN ("identity", Fidentity, 1, 1, 0, /* |
132 Return the argument unchanged. | 120 Return the argument unchanged. |
133 */ | 121 */ |
134 (arg)) | 122 (arg)) |
187 { | 175 { |
188 if (!COMPILED_FUNCTIONP (seq)) | 176 if (!COMPILED_FUNCTIONP (seq)) |
189 return XINT (Flength (seq)); | 177 return XINT (Flength (seq)); |
190 else | 178 else |
191 { | 179 { |
192 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (seq); | 180 struct Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (seq); |
193 | 181 |
194 return (f->flags.interactivep ? COMPILED_INTERACTIVE : | 182 return (f->flags.interactivep ? COMPILED_INTERACTIVE : |
195 f->flags.domainp ? COMPILED_DOMAIN : | 183 f->flags.domainp ? COMPILED_DOMAIN : |
196 COMPILED_DOC_STRING) | 184 COMPILED_DOC_STRING) |
197 + 1; | 185 + 1; |
199 } | 187 } |
200 | 188 |
201 #endif /* LOSING_BYTECODE */ | 189 #endif /* LOSING_BYTECODE */ |
202 | 190 |
203 void | 191 void |
204 check_losing_bytecode (const char *function, Lisp_Object seq) | 192 check_losing_bytecode (CONST char *function, Lisp_Object seq) |
205 { | 193 { |
206 if (COMPILED_FUNCTIONP (seq)) | 194 if (COMPILED_FUNCTIONP (seq)) |
207 error_with_frob | 195 error_with_frob |
208 (seq, | 196 (seq, |
209 "As of 20.3, `%s' no longer works with compiled-function objects", | 197 "As of 20.3, `%s' no longer works with compiled-function objects", |
218 retry: | 206 retry: |
219 if (STRINGP (sequence)) | 207 if (STRINGP (sequence)) |
220 return make_int (XSTRING_CHAR_LENGTH (sequence)); | 208 return make_int (XSTRING_CHAR_LENGTH (sequence)); |
221 else if (CONSP (sequence)) | 209 else if (CONSP (sequence)) |
222 { | 210 { |
223 size_t len; | 211 int len; |
224 GET_EXTERNAL_LIST_LENGTH (sequence, len); | 212 GET_EXTERNAL_LIST_LENGTH (sequence, len); |
225 return make_int (len); | 213 return make_int (len); |
226 } | 214 } |
227 else if (VECTORP (sequence)) | 215 else if (VECTORP (sequence)) |
228 return make_int (XVECTOR_LENGTH (sequence)); | 216 return make_int (XVECTOR_LENGTH (sequence)); |
245 which is at least the number of distinct elements. | 233 which is at least the number of distinct elements. |
246 */ | 234 */ |
247 (list)) | 235 (list)) |
248 { | 236 { |
249 Lisp_Object hare, tortoise; | 237 Lisp_Object hare, tortoise; |
250 size_t len; | 238 int len; |
251 | 239 |
252 for (hare = tortoise = list, len = 0; | 240 for (hare = tortoise = list, len = 0; |
253 CONSP (hare) && (! EQ (hare, tortoise) || len == 0); | 241 CONSP (hare) && (! EQ (hare, tortoise) || len == 0); |
254 hare = XCDR (hare), len++) | 242 hare = XCDR (hare), len++) |
255 { | 243 { |
271 Symbols are also allowed; their print names are used instead. | 259 Symbols are also allowed; their print names are used instead. |
272 */ | 260 */ |
273 (s1, s2)) | 261 (s1, s2)) |
274 { | 262 { |
275 Bytecount len; | 263 Bytecount len; |
276 Lisp_String *p1, *p2; | 264 struct Lisp_String *p1, *p2; |
277 | 265 |
278 if (SYMBOLP (s1)) | 266 if (SYMBOLP (s1)) |
279 p1 = XSYMBOL (s1)->name; | 267 p1 = XSYMBOL (s1)->name; |
280 else | 268 else |
281 { | 269 { |
318 Unicode. When Unicode support is added to XEmacs/Mule, this problem | 306 Unicode. When Unicode support is added to XEmacs/Mule, this problem |
319 may be solved. | 307 may be solved. |
320 */ | 308 */ |
321 (s1, s2)) | 309 (s1, s2)) |
322 { | 310 { |
323 Lisp_String *p1, *p2; | 311 struct Lisp_String *p1, *p2; |
324 Charcount end, len2; | 312 Charcount end, len2; |
325 int i; | 313 int i; |
326 | 314 |
327 if (SYMBOLP (s1)) | 315 if (SYMBOLP (s1)) |
328 p1 = XSYMBOL (s1)->name; | 316 p1 = XSYMBOL (s1)->name; |
349 /* There is no hope of this working under Mule. Even if we converted | 337 /* There is no hope of this working under Mule. Even if we converted |
350 the data into an external format so that strcoll() processed it | 338 the data into an external format so that strcoll() processed it |
351 properly, it would still not work because strcoll() does not | 339 properly, it would still not work because strcoll() does not |
352 handle multiple locales. This is the fundamental flaw in the | 340 handle multiple locales. This is the fundamental flaw in the |
353 locale model. */ | 341 locale model. */ |
354 { | 342 Bytecount bcend = charcount_to_bytecount (string_data (p1), end); |
355 Bytecount bcend = charcount_to_bytecount (string_data (p1), end); | 343 /* Compare strings using collation order of locale. */ |
356 /* Compare strings using collation order of locale. */ | 344 /* Need to be tricky to handle embedded nulls. */ |
357 /* Need to be tricky to handle embedded nulls. */ | 345 |
358 | 346 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1) |
359 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1) | 347 { |
360 { | 348 int val = strcoll ((char *) string_data (p1) + i, |
361 int val = strcoll ((char *) string_data (p1) + i, | 349 (char *) string_data (p2) + i); |
362 (char *) string_data (p2) + i); | 350 if (val < 0) |
363 if (val < 0) | 351 return Qt; |
364 return Qt; | 352 if (val > 0) |
365 if (val > 0) | 353 return Qnil; |
366 return Qnil; | 354 } |
367 } | |
368 } | |
369 #else /* not I18N2, or MULE */ | 355 #else /* not I18N2, or MULE */ |
370 { | 356 /* #### It is not really necessary to do this: We could compare |
371 Bufbyte *ptr1 = string_data (p1); | 357 byte-by-byte and still get a reasonable comparison, since this |
372 Bufbyte *ptr2 = string_data (p2); | 358 would compare characters with a charset in the same way. |
373 | 359 With a little rearrangement of the leading bytes, we could |
374 /* #### It is not really necessary to do this: We could compare | 360 make most inter-charset comparisons work out the same, too; |
375 byte-by-byte and still get a reasonable comparison, since this | 361 even if some don't, this is not a big deal because inter-charset |
376 would compare characters with a charset in the same way. With | 362 comparisons aren't really well-defined anyway. */ |
377 a little rearrangement of the leading bytes, we could make most | 363 for (i = 0; i < end; i++) |
378 inter-charset comparisons work out the same, too; even if some | 364 { |
379 don't, this is not a big deal because inter-charset comparisons | 365 if (string_char (p1, i) != string_char (p2, i)) |
380 aren't really well-defined anyway. */ | 366 return string_char (p1, i) < string_char (p2, i) ? Qt : Qnil; |
381 for (i = 0; i < end; i++) | 367 } |
382 { | |
383 if (charptr_emchar (ptr1) != charptr_emchar (ptr2)) | |
384 return charptr_emchar (ptr1) < charptr_emchar (ptr2) ? Qt : Qnil; | |
385 INC_CHARPTR (ptr1); | |
386 INC_CHARPTR (ptr2); | |
387 } | |
388 } | |
389 #endif /* not I18N2, or MULE */ | 368 #endif /* not I18N2, or MULE */ |
390 /* Can't do i < len2 because then comparison between "foo" and "foo^@" | 369 /* Can't do i < len2 because then comparison between "foo" and "foo^@" |
391 won't work right in I18N2 case */ | 370 won't work right in I18N2 case */ |
392 return end < len2 ? Qt : Qnil; | 371 return end < len2 ? Qt : Qnil; |
393 } | 372 } |
397 Each string has a tick counter which is incremented each time the contents | 376 Each string has a tick counter which is incremented each time the contents |
398 of the string are changed (e.g. with `aset'). It wraps around occasionally. | 377 of the string are changed (e.g. with `aset'). It wraps around occasionally. |
399 */ | 378 */ |
400 (string)) | 379 (string)) |
401 { | 380 { |
402 Lisp_String *s; | 381 struct Lisp_String *s; |
403 | 382 |
404 CHECK_STRING (string); | 383 CHECK_STRING (string); |
405 s = XSTRING (string); | 384 s = XSTRING (string); |
406 if (CONSP (s->plist) && INTP (XCAR (s->plist))) | 385 if (CONSP (s->plist) && INTP (XCAR (s->plist))) |
407 return XCAR (s->plist); | 386 return XCAR (s->plist); |
410 } | 389 } |
411 | 390 |
412 void | 391 void |
413 bump_string_modiff (Lisp_Object str) | 392 bump_string_modiff (Lisp_Object str) |
414 { | 393 { |
415 Lisp_String *s = XSTRING (str); | 394 struct Lisp_String *s = XSTRING (str); |
416 Lisp_Object *ptr = &s->plist; | 395 Lisp_Object *ptr = &s->plist; |
417 | 396 |
418 #ifdef I18N3 | 397 #ifdef I18N3 |
419 /* #### remove the `string-translatable' property from the string, | 398 /* #### remove the `string-translatable' property from the string, |
420 if there is one. */ | 399 if there is one. */ |
525 copy_list (Lisp_Object list) | 504 copy_list (Lisp_Object list) |
526 { | 505 { |
527 Lisp_Object list_copy = Fcons (XCAR (list), XCDR (list)); | 506 Lisp_Object list_copy = Fcons (XCAR (list), XCDR (list)); |
528 Lisp_Object last = list_copy; | 507 Lisp_Object last = list_copy; |
529 Lisp_Object hare, tortoise; | 508 Lisp_Object hare, tortoise; |
530 size_t len; | 509 int len; |
531 | 510 |
532 for (tortoise = hare = XCDR (list), len = 1; | 511 for (tortoise = hare = XCDR (list), len = 1; |
533 CONSP (hare); | 512 CONSP (hare); |
534 hare = XCDR (hare), len++) | 513 hare = XCDR (hare), len++) |
535 { | 514 { |
900 Relevant parts of the string-extent-data are copied in the new string. | 879 Relevant parts of the string-extent-data are copied in the new string. |
901 */ | 880 */ |
902 (string, from, to)) | 881 (string, from, to)) |
903 { | 882 { |
904 Charcount ccfr, ccto; | 883 Charcount ccfr, ccto; |
905 Bytecount bfr, blen; | 884 Bytecount bfr, bto; |
906 Lisp_Object val; | 885 Lisp_Object val; |
907 | 886 |
908 CHECK_STRING (string); | 887 CHECK_STRING (string); |
909 CHECK_INT (from); | 888 CHECK_INT (from); |
910 get_string_range_char (string, from, to, &ccfr, &ccto, | 889 get_string_range_char (string, from, to, &ccfr, &ccto, |
911 GB_HISTORICAL_STRING_BEHAVIOR); | 890 GB_HISTORICAL_STRING_BEHAVIOR); |
912 bfr = charcount_to_bytecount (XSTRING_DATA (string), ccfr); | 891 bfr = charcount_to_bytecount (XSTRING_DATA (string), ccfr); |
913 blen = charcount_to_bytecount (XSTRING_DATA (string) + bfr, ccto - ccfr); | 892 bto = charcount_to_bytecount (XSTRING_DATA (string), ccto); |
914 val = make_string (XSTRING_DATA (string) + bfr, blen); | 893 val = make_string (XSTRING_DATA (string) + bfr, bto - bfr); |
915 /* Copy any applicable extent information into the new string: */ | 894 /* Copy any applicable extent information into the new string: */ |
916 copy_string_extents (val, string, 0, bfr, blen); | 895 copy_string_extents (val, string, 0, bfr, bto - bfr); |
917 return val; | 896 return val; |
918 } | 897 } |
919 | 898 |
920 DEFUN ("subseq", Fsubseq, 2, 3, 0, /* | 899 DEFUN ("subseq", Fsubseq, 2, 3, 0, /* |
921 Return the subsequence of SEQUENCE starting at START and ending before END. | 900 Return a subsequence of SEQ, starting at index FROM and ending before TO. |
922 END may be omitted; then the subsequence runs to the end of SEQUENCE. | 901 TO may be nil or omitted; then the subsequence runs to the end of SEQ. |
923 If START or END is negative, it counts from the end. | 902 If FROM or TO is negative, it counts from the end. |
924 The returned subsequence is always of the same type as SEQUENCE. | 903 The resulting subsequence is always the same type as the original |
925 If SEQUENCE is a string, relevant parts of the string-extent-data | 904 sequence. |
926 are copied to the new string. | 905 If SEQ is a string, relevant parts of the string-extent-data are copied |
927 */ | 906 to the new string. |
928 (sequence, start, end)) | 907 */ |
929 { | 908 (seq, from, to)) |
930 EMACS_INT len, s, e; | 909 { |
931 | 910 int len, f, t; |
932 if (STRINGP (sequence)) | 911 |
933 return Fsubstring (sequence, start, end); | 912 if (STRINGP (seq)) |
934 | 913 return Fsubstring (seq, from, to); |
935 len = XINT (Flength (sequence)); | 914 |
936 | 915 if (!LISTP (seq) && !VECTORP (seq) && !BIT_VECTORP (seq)) |
937 CHECK_INT (start); | 916 { |
938 s = XINT (start); | 917 check_losing_bytecode ("subseq", seq); |
939 if (s < 0) | 918 seq = wrong_type_argument (Qsequencep, seq); |
940 s = len + s; | 919 } |
941 | 920 |
942 if (NILP (end)) | 921 len = XINT (Flength (seq)); |
943 e = len; | 922 |
923 CHECK_INT (from); | |
924 f = XINT (from); | |
925 if (f < 0) | |
926 f = len + f; | |
927 | |
928 if (NILP (to)) | |
929 t = len; | |
944 else | 930 else |
945 { | 931 { |
946 CHECK_INT (end); | 932 CHECK_INT (to); |
947 e = XINT (end); | 933 t = XINT (to); |
948 if (e < 0) | 934 if (t < 0) |
949 e = len + e; | 935 t = len + t; |
950 } | 936 } |
951 | 937 |
952 if (!(0 <= s && s <= e && e <= len)) | 938 if (!(0 <= f && f <= t && t <= len)) |
953 args_out_of_range_3 (sequence, make_int (s), make_int (e)); | 939 args_out_of_range_3 (seq, make_int (f), make_int (t)); |
954 | 940 |
955 if (VECTORP (sequence)) | 941 if (VECTORP (seq)) |
956 { | 942 { |
957 Lisp_Object result = make_vector (e - s, Qnil); | 943 Lisp_Object result = make_vector (t - f, Qnil); |
958 EMACS_INT i; | 944 int i; |
959 Lisp_Object *in_elts = XVECTOR_DATA (sequence); | 945 Lisp_Object *in_elts = XVECTOR_DATA (seq); |
960 Lisp_Object *out_elts = XVECTOR_DATA (result); | 946 Lisp_Object *out_elts = XVECTOR_DATA (result); |
961 | 947 |
962 for (i = s; i < e; i++) | 948 for (i = f; i < t; i++) |
963 out_elts[i - s] = in_elts[i]; | 949 out_elts[i - f] = in_elts[i]; |
964 return result; | 950 return result; |
965 } | 951 } |
966 else if (LISTP (sequence)) | 952 |
953 if (LISTP (seq)) | |
967 { | 954 { |
968 Lisp_Object result = Qnil; | 955 Lisp_Object result = Qnil; |
969 EMACS_INT i; | 956 int i; |
970 | 957 |
971 sequence = Fnthcdr (make_int (s), sequence); | 958 seq = Fnthcdr (make_int (f), seq); |
972 | 959 |
973 for (i = s; i < e; i++) | 960 for (i = f; i < t; i++) |
974 { | 961 { |
975 result = Fcons (Fcar (sequence), result); | 962 result = Fcons (Fcar (seq), result); |
976 sequence = Fcdr (sequence); | 963 seq = Fcdr (seq); |
977 } | 964 } |
978 | 965 |
979 return Fnreverse (result); | 966 return Fnreverse (result); |
980 } | 967 } |
981 else if (BIT_VECTORP (sequence)) | 968 |
982 { | 969 /* bit vector */ |
983 Lisp_Object result = make_bit_vector (e - s, Qzero); | 970 { |
984 EMACS_INT i; | 971 Lisp_Object result = make_bit_vector (t - f, Qzero); |
985 | 972 int i; |
986 for (i = s; i < e; i++) | 973 |
987 set_bit_vector_bit (XBIT_VECTOR (result), i - s, | 974 for (i = f; i < t; i++) |
988 bit_vector_bit (XBIT_VECTOR (sequence), i)); | 975 set_bit_vector_bit (XBIT_VECTOR (result), i - f, |
989 return result; | 976 bit_vector_bit (XBIT_VECTOR (seq), i)); |
990 } | 977 return result; |
991 else | 978 } |
992 { | |
993 abort (); /* unreachable, since Flength (sequence) did not get | |
994 an error */ | |
995 return Qnil; | |
996 } | |
997 } | 979 } |
998 | 980 |
999 | 981 |
1000 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /* | 982 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /* |
1001 Take cdr N times on LIST, and return the result. | 983 Take cdr N times on LIST, and return the result. |
1002 */ | 984 */ |
1003 (n, list)) | 985 (n, list)) |
1004 { | 986 { |
1005 REGISTER size_t i; | 987 REGISTER int i; |
1006 REGISTER Lisp_Object tail = list; | 988 REGISTER Lisp_Object tail = list; |
1007 CHECK_NATNUM (n); | 989 CHECK_NATNUM (n); |
1008 for (i = XINT (n); i; i--) | 990 for (i = XINT (n); i; i--) |
1009 { | 991 { |
1010 if (CONSP (tail)) | 992 if (CONSP (tail)) |
1059 BIT_VECTORP (sequence)) | 1041 BIT_VECTORP (sequence)) |
1060 return Faref (sequence, n); | 1042 return Faref (sequence, n); |
1061 #ifdef LOSING_BYTECODE | 1043 #ifdef LOSING_BYTECODE |
1062 else if (COMPILED_FUNCTIONP (sequence)) | 1044 else if (COMPILED_FUNCTIONP (sequence)) |
1063 { | 1045 { |
1064 EMACS_INT idx = XINT (n); | 1046 int idx = XINT (n); |
1065 if (idx < 0) | 1047 if (idx < 0) |
1066 { | 1048 { |
1067 lose: | 1049 lose: |
1068 args_out_of_range (sequence, n); | 1050 args_out_of_range (sequence, n); |
1069 } | 1051 } |
1111 If N is zero, then the atom that terminates the list is returned. | 1093 If N is zero, then the atom that terminates the list is returned. |
1112 If N is greater than the length of LIST, then LIST itself is returned. | 1094 If N is greater than the length of LIST, then LIST itself is returned. |
1113 */ | 1095 */ |
1114 (list, n)) | 1096 (list, n)) |
1115 { | 1097 { |
1116 EMACS_INT int_n, count; | 1098 int int_n, count; |
1117 Lisp_Object retval, tortoise, hare; | 1099 Lisp_Object retval, tortoise, hare; |
1118 | 1100 |
1119 CHECK_LIST (list); | 1101 CHECK_LIST (list); |
1120 | 1102 |
1121 if (NILP (n)) | 1103 if (NILP (n)) |
1147 Modify LIST to remove the last N (default 1) elements. | 1129 Modify LIST to remove the last N (default 1) elements. |
1148 If LIST has N or fewer elements, nil is returned and LIST is unmodified. | 1130 If LIST has N or fewer elements, nil is returned and LIST is unmodified. |
1149 */ | 1131 */ |
1150 (list, n)) | 1132 (list, n)) |
1151 { | 1133 { |
1152 EMACS_INT int_n; | 1134 int int_n; |
1153 | 1135 |
1154 CHECK_LIST (list); | 1136 CHECK_LIST (list); |
1155 | 1137 |
1156 if (NILP (n)) | 1138 if (NILP (n)) |
1157 int_n = 1; | 1139 int_n = 1; |
1850 */ | 1832 */ |
1851 int | 1833 int |
1852 plists_differ (Lisp_Object a, Lisp_Object b, int nil_means_not_present, | 1834 plists_differ (Lisp_Object a, Lisp_Object b, int nil_means_not_present, |
1853 int laxp, int depth) | 1835 int laxp, int depth) |
1854 { | 1836 { |
1855 int eqp = (depth == -1); /* -1 as depth means use eq, not equal. */ | 1837 int eqp = (depth == -1); /* -1 as depth means us eq, not equal. */ |
1856 int la, lb, m, i, fill; | 1838 int la, lb, m, i, fill; |
1857 Lisp_Object *keys, *vals; | 1839 Lisp_Object *keys, *vals; |
1858 char *flags; | 1840 char *flags; |
1859 Lisp_Object rest; | 1841 Lisp_Object rest; |
1860 | 1842 |
1894 if (nil_means_not_present && NILP (v)) continue; | 1876 if (nil_means_not_present && NILP (v)) continue; |
1895 for (i = 0; i < fill; i++) | 1877 for (i = 0; i < fill; i++) |
1896 { | 1878 { |
1897 if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth)) | 1879 if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth)) |
1898 { | 1880 { |
1899 if (eqp | 1881 if ((eqp |
1900 /* We narrowly escaped being Ebolified here. */ | 1882 /* We narrowly escaped being Ebolified here. */ |
1901 ? !EQ_WITH_EBOLA_NOTICE (v, vals [i]) | 1883 ? !EQ_WITH_EBOLA_NOTICE (v, vals [i]) |
1902 : !internal_equal (v, vals [i], depth)) | 1884 : !internal_equal (v, vals [i], depth))) |
1903 /* a property in B has a different value than in A */ | 1885 /* a property in B has a different value than in A */ |
1904 goto MISMATCH; | 1886 goto MISMATCH; |
1905 flags [i] = 1; | 1887 flags [i] = 1; |
1906 break; | 1888 break; |
1907 } | 1889 } |
2368 } | 2350 } |
2369 | 2351 |
2370 DEFUN ("valid-plist-p", Fvalid_plist_p, 1, 1, 0, /* | 2352 DEFUN ("valid-plist-p", Fvalid_plist_p, 1, 1, 0, /* |
2371 Given a plist, return non-nil if its format is correct. | 2353 Given a plist, return non-nil if its format is correct. |
2372 If it returns nil, `check-valid-plist' will signal an error when given | 2354 If it returns nil, `check-valid-plist' will signal an error when given |
2373 the plist; that means it's a malformed or circular plist. | 2355 the plist; that means it's a malformed or circular plist or has non-symbols |
2356 as keywords. | |
2374 */ | 2357 */ |
2375 (plist)) | 2358 (plist)) |
2376 { | 2359 { |
2377 Lisp_Object *tortoise; | 2360 Lisp_Object *tortoise; |
2378 Lisp_Object *hare; | 2361 Lisp_Object *hare; |
2445 properties on the list. | 2428 properties on the list. |
2446 */ | 2429 */ |
2447 (lax_plist, prop, default_)) | 2430 (lax_plist, prop, default_)) |
2448 { | 2431 { |
2449 Lisp_Object val = external_plist_get (&lax_plist, prop, 1, ERROR_ME); | 2432 Lisp_Object val = external_plist_get (&lax_plist, prop, 1, ERROR_ME); |
2450 return UNBOUNDP (val) ? default_ : val; | 2433 if (UNBOUNDP (val)) |
2434 return default_; | |
2435 return val; | |
2451 } | 2436 } |
2452 | 2437 |
2453 DEFUN ("lax-plist-put", Flax_plist_put, 3, 3, 0, /* | 2438 DEFUN ("lax-plist-put", Flax_plist_put, 3, 3, 0, /* |
2454 Change value in LAX-PLIST of PROP to VAL. | 2439 Change value in LAX-PLIST of PROP to VAL. |
2455 LAX-PLIST is a lax property list, which is a list of the form \(PROP1 | 2440 LAX-PLIST is a lax property list, which is a list of the form \(PROP1 |
2565 } | 2550 } |
2566 | 2551 |
2567 return head; | 2552 return head; |
2568 } | 2553 } |
2569 | 2554 |
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 | |
2570 DEFUN ("get", Fget, 2, 3, 0, /* | 2627 DEFUN ("get", Fget, 2, 3, 0, /* |
2571 Return the value of OBJECT's PROPERTY property. | 2628 Return the value of OBJECT's PROPNAME property. |
2572 This is the last VALUE stored with `(put OBJECT PROPERTY VALUE)'. | 2629 This is the last VALUE stored with `(put OBJECT PROPNAME VALUE)'. |
2573 If there is no such property, return optional third arg DEFAULT | 2630 If there is no such property, return optional third arg DEFAULT |
2574 \(which defaults to `nil'). OBJECT can be a symbol, string, extent, | 2631 \(which defaults to `nil'). OBJECT can be a symbol, face, extent, |
2575 face, or glyph. See also `put', `remprop', and `object-plist'. | 2632 or string. See also `put', `remprop', and `object-plist'. |
2576 */ | 2633 */ |
2577 (object, property, default_)) | 2634 (object, propname, default_)) |
2578 { | 2635 { |
2579 /* Various places in emacs call Fget() and expect it not to quit, | 2636 /* Various places in emacs call Fget() and expect it not to quit, |
2580 so don't quit. */ | 2637 so don't quit. */ |
2581 Lisp_Object val; | 2638 |
2582 | 2639 /* It's easiest to treat symbols specially because they may not |
2583 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->getprop) | 2640 be an lrecord */ |
2584 val = XRECORD_LHEADER_IMPLEMENTATION (object)->getprop (object, property); | 2641 if (SYMBOLP (object)) |
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 } | |
2585 else | 2659 else |
2586 signal_simple_error ("Object type has no properties", object); | 2660 { |
2587 | 2661 noprops: |
2588 return UNBOUNDP (val) ? default_ : val; | 2662 signal_simple_error ("Object type has no properties", object); |
2663 return Qnil; /* Not reached */ | |
2664 } | |
2589 } | 2665 } |
2590 | 2666 |
2591 DEFUN ("put", Fput, 3, 3, 0, /* | 2667 DEFUN ("put", Fput, 3, 3, 0, /* |
2592 Set OBJECT's PROPERTY to VALUE. | 2668 Store OBJECT's PROPNAME property with value VALUE. |
2593 It can be subsequently retrieved with `(get OBJECT PROPERTY)'. | 2669 It can be retrieved with `(get OBJECT PROPNAME)'. OBJECT can be a |
2594 OBJECT can be a symbol, face, extent, or string. | 2670 symbol, face, extent, or string. |
2671 | |
2595 For a string, no properties currently have predefined meanings. | 2672 For a string, no properties currently have predefined meanings. |
2596 For the predefined properties for extents, see `set-extent-property'. | 2673 For the predefined properties for extents, see `set-extent-property'. |
2597 For the predefined properties for faces, see `set-face-property'. | 2674 For the predefined properties for faces, see `set-face-property'. |
2675 | |
2598 See also `get', `remprop', and `object-plist'. | 2676 See also `get', `remprop', and `object-plist'. |
2599 */ | 2677 */ |
2600 (object, property, value)) | 2678 (object, propname, value)) |
2601 { | 2679 { |
2680 CHECK_SYMBOL (propname); | |
2602 CHECK_LISP_WRITEABLE (object); | 2681 CHECK_LISP_WRITEABLE (object); |
2603 | 2682 |
2604 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->putprop) | 2683 if (SYMBOLP (object)) |
2605 { | 2684 symbol_putprop (object, propname, value); |
2606 if (! XRECORD_LHEADER_IMPLEMENTATION (object)->putprop | 2685 else if (STRINGP (object)) |
2607 (object, property, value)) | 2686 string_putprop (XSTRING (object), propname, value); |
2608 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; | |
2609 } | 2698 } |
2610 else | 2699 else |
2611 signal_simple_error ("Object type has no settable properties", object); | 2700 { |
2701 noprops: | |
2702 signal_simple_error ("Object type has no settable properties", object); | |
2703 } | |
2612 | 2704 |
2613 return value; | 2705 return value; |
2614 } | 2706 } |
2615 | 2707 |
2708 void | |
2709 pure_put (Lisp_Object sym, Lisp_Object prop, Lisp_Object val) | |
2710 { | |
2711 Fput (sym, prop, Fpurecopy (val)); | |
2712 } | |
2713 | |
2616 DEFUN ("remprop", Fremprop, 2, 2, 0, /* | 2714 DEFUN ("remprop", Fremprop, 2, 2, 0, /* |
2617 Remove, from OBJECT's property list, PROPERTY and its corresponding value. | 2715 Remove from OBJECT's property list the property PROPNAME and its |
2618 OBJECT can be a symbol, string, extent, face, or glyph. Return non-nil | 2716 value. OBJECT can be a symbol, face, extent, or string. Returns |
2619 if the property list was actually modified (i.e. if PROPERTY was present | 2717 non-nil if the property list was actually changed (i.e. if PROPNAME |
2620 in the property list). See also `get', `put', and `object-plist'. | 2718 was present in the property list). See also `get', `put', and |
2621 */ | 2719 `object-plist'. |
2622 (object, property)) | 2720 */ |
2623 { | 2721 (object, propname)) |
2624 int ret = 0; | 2722 { |
2625 | 2723 int retval = 0; |
2724 | |
2725 CHECK_SYMBOL (propname); | |
2626 CHECK_LISP_WRITEABLE (object); | 2726 CHECK_LISP_WRITEABLE (object); |
2627 | 2727 |
2628 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->remprop) | 2728 if (SYMBOLP (object)) |
2629 { | 2729 retval = symbol_remprop (object, propname); |
2630 ret = XRECORD_LHEADER_IMPLEMENTATION (object)->remprop (object, property); | 2730 else if (STRINGP (object)) |
2631 if (ret == -1) | 2731 retval = string_remprop (XSTRING (object), propname); |
2632 signal_simple_error ("Can't remove property from object", property); | 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; | |
2633 } | 2745 } |
2634 else | 2746 else |
2635 signal_simple_error ("Object type has no removable properties", object); | 2747 { |
2636 | 2748 noprops: |
2637 return ret ? Qt : Qnil; | 2749 signal_simple_error ("Object type has no removable properties", object); |
2750 } | |
2751 | |
2752 return retval ? Qt : Qnil; | |
2638 } | 2753 } |
2639 | 2754 |
2640 DEFUN ("object-plist", Fobject_plist, 1, 1, 0, /* | 2755 DEFUN ("object-plist", Fobject_plist, 1, 1, 0, /* |
2641 Return a property list of OBJECT's properties. | 2756 Return a property list of OBJECT's props. |
2642 For a symbol, this is equivalent to `symbol-plist'. | 2757 For a symbol this is equivalent to `symbol-plist'. |
2643 OBJECT can be a symbol, string, extent, face, or glyph. | 2758 Do not modify the property list directly; this may or may not have |
2644 Do not modify the returned property list directly; | 2759 the desired effects. (In particular, for a property with a special |
2645 this may or may not have the desired effects. Use `put' instead. | 2760 interpretation, this will probably have no effect at all.) |
2646 */ | 2761 */ |
2647 (object)) | 2762 (object)) |
2648 { | 2763 { |
2649 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->plist) | 2764 if (SYMBOLP (object)) |
2650 return XRECORD_LHEADER_IMPLEMENTATION (object)->plist (object); | 2765 return Fsymbol_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 } | |
2651 else | 2777 else |
2652 signal_simple_error ("Object type has no properties", object); | 2778 signal_simple_error ("Object type has no properties", object); |
2653 | 2779 |
2654 return Qnil; | 2780 return Qnil; |
2655 } | 2781 } |
2666 /* Note that (equal 20 20.0) should be nil */ | 2792 /* Note that (equal 20 20.0) should be nil */ |
2667 if (XTYPE (obj1) != XTYPE (obj2)) | 2793 if (XTYPE (obj1) != XTYPE (obj2)) |
2668 return 0; | 2794 return 0; |
2669 if (LRECORDP (obj1)) | 2795 if (LRECORDP (obj1)) |
2670 { | 2796 { |
2671 const struct lrecord_implementation | 2797 CONST struct lrecord_implementation |
2672 *imp1 = XRECORD_LHEADER_IMPLEMENTATION (obj1), | 2798 *imp1 = XRECORD_LHEADER_IMPLEMENTATION (obj1), |
2673 *imp2 = XRECORD_LHEADER_IMPLEMENTATION (obj2); | 2799 *imp2 = XRECORD_LHEADER_IMPLEMENTATION (obj2); |
2674 | 2800 |
2675 return (imp1 == imp2) && | 2801 return (imp1 == imp2) && |
2676 /* EQ-ness of the objects was noticed above */ | 2802 /* EQ-ness of the objects was noticed above */ |
2726 return internal_old_equal (obj1, obj2, 0) ? Qt : Qnil; | 2852 return internal_old_equal (obj1, obj2, 0) ? Qt : Qnil; |
2727 } | 2853 } |
2728 | 2854 |
2729 | 2855 |
2730 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /* | 2856 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /* |
2731 Destructively modify ARRAY by replacing each element with ITEM. | 2857 Store each element of ARRAY with ITEM. |
2732 ARRAY is a vector, bit vector, or string. | 2858 ARRAY is a vector, bit vector, or string. |
2733 */ | 2859 */ |
2734 (array, item)) | 2860 (array, item)) |
2735 { | 2861 { |
2736 retry: | 2862 retry: |
2737 if (STRINGP (array)) | 2863 if (STRINGP (array)) |
2738 { | 2864 { |
2739 Lisp_String *s = XSTRING (array); | 2865 Emchar charval; |
2740 Bytecount old_bytecount = string_length (s); | 2866 struct Lisp_String *s = XSTRING (array); |
2741 Bytecount new_bytecount; | 2867 Charcount len = string_char_length (s); |
2742 Bytecount item_bytecount; | 2868 Charcount i; |
2743 Bufbyte item_buf[MAX_EMCHAR_LEN]; | |
2744 Bufbyte *p; | |
2745 Bufbyte *end; | |
2746 | |
2747 CHECK_CHAR_COERCE_INT (item); | 2869 CHECK_CHAR_COERCE_INT (item); |
2748 CHECK_LISP_WRITEABLE (array); | 2870 CHECK_LISP_WRITEABLE (array); |
2749 | 2871 charval = XCHAR (item); |
2750 item_bytecount = set_charptr_emchar (item_buf, XCHAR (item)); | 2872 for (i = 0; i < len; i++) |
2751 new_bytecount = item_bytecount * string_char_length (s); | 2873 set_string_char (s, i, charval); |
2752 | |
2753 resize_string (s, -1, new_bytecount - old_bytecount); | |
2754 | |
2755 for (p = string_data (s), end = p + new_bytecount; | |
2756 p < end; | |
2757 p += item_bytecount) | |
2758 memcpy (p, item_buf, item_bytecount); | |
2759 *p = '\0'; | |
2760 | |
2761 bump_string_modiff (array); | 2874 bump_string_modiff (array); |
2762 } | 2875 } |
2763 else if (VECTORP (array)) | 2876 else if (VECTORP (array)) |
2764 { | 2877 { |
2765 Lisp_Object *p = XVECTOR_DATA (array); | 2878 Lisp_Object *p = XVECTOR_DATA (array); |
2768 while (len--) | 2881 while (len--) |
2769 *p++ = item; | 2882 *p++ = item; |
2770 } | 2883 } |
2771 else if (BIT_VECTORP (array)) | 2884 else if (BIT_VECTORP (array)) |
2772 { | 2885 { |
2773 Lisp_Bit_Vector *v = XBIT_VECTOR (array); | 2886 struct Lisp_Bit_Vector *v = XBIT_VECTOR (array); |
2774 int len = bit_vector_length (v); | 2887 int len = bit_vector_length (v); |
2775 int bit; | 2888 int bit; |
2776 CHECK_BIT (item); | 2889 CHECK_BIT (item); |
2777 CHECK_LISP_WRITEABLE (array); | 2890 CHECK_LISP_WRITEABLE (array); |
2778 bit = XINT (item); | 2891 bit = XINT (item); |
2918 } | 3031 } |
2919 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ | 3032 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ |
2920 } | 3033 } |
2921 | 3034 |
2922 | 3035 |
2923 /* This is the guts of several mapping functions. | 3036 /* This is the guts of all mapping functions. |
2924 Apply FUNCTION to each element of SEQUENCE, one by one, | 3037 Apply fn to each element of seq, one by one, |
2925 storing the results into elements of VALS, a C vector of Lisp_Objects. | 3038 storing the results into elements of vals, a C vector of Lisp_Objects. |
2926 LENI is the length of VALS, which should also be the length of SEQUENCE. | 3039 leni is the length of vals, which should also be the length of seq. |
2927 | 3040 |
2928 If VALS is a null pointer, do not accumulate the results. */ | 3041 If VALS is a null pointer, do not accumulate the results. */ |
2929 | 3042 |
2930 static void | 3043 static void |
2931 mapcar1 (size_t leni, Lisp_Object *vals, | 3044 mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq) |
2932 Lisp_Object function, Lisp_Object sequence) | |
2933 { | 3045 { |
2934 Lisp_Object result; | 3046 Lisp_Object result; |
2935 Lisp_Object args[2]; | 3047 Lisp_Object args[2]; |
2936 int i; | 3048 int i; |
2937 struct gcpro gcpro1; | 3049 struct gcpro gcpro1; |
2940 { | 3052 { |
2941 GCPRO1 (vals[0]); | 3053 GCPRO1 (vals[0]); |
2942 gcpro1.nvars = 0; | 3054 gcpro1.nvars = 0; |
2943 } | 3055 } |
2944 | 3056 |
2945 args[0] = function; | 3057 args[0] = fn; |
2946 | 3058 |
2947 if (LISTP (sequence)) | 3059 if (LISTP (seq)) |
2948 { | 3060 { |
2949 /* A devious `function' could either: | 3061 for (i = 0; i < leni; i++) |
2950 - insert garbage into the list in front of us, causing XCDR to crash | 3062 { |
2951 - amputate the list behind us using (setcdr), causing the remaining | 3063 args[1] = XCAR (seq); |
2952 elts to lose their GCPRO status. | 3064 seq = XCDR (seq); |
2953 | 3065 result = Ffuncall (2, args); |
2954 if (vals != 0) we avoid this by copying the elts into the | 3066 if (vals) vals[gcpro1.nvars++] = result; |
2955 `vals' array. By a stroke of luck, `vals' is exactly large | 3067 } |
2956 enough to hold the elts left to be traversed as well as the | 3068 } |
2957 results computed so far. | 3069 else if (VECTORP (seq)) |
2958 | 3070 { |
2959 if (vals == 0) we don't have any free space available and | 3071 Lisp_Object *objs = XVECTOR_DATA (seq); |
2960 don't want to eat up any more stack with alloca(). | |
2961 So we use EXTERNAL_LIST_LOOP_3 and GCPRO the tail. */ | |
2962 | |
2963 if (vals) | |
2964 { | |
2965 Lisp_Object *val = vals; | |
2966 Lisp_Object elt; | |
2967 | |
2968 LIST_LOOP_2 (elt, sequence) | |
2969 *val++ = elt; | |
2970 | |
2971 gcpro1.nvars = leni; | |
2972 | |
2973 for (i = 0; i < leni; i++) | |
2974 { | |
2975 args[1] = vals[i]; | |
2976 vals[i] = Ffuncall (2, args); | |
2977 } | |
2978 } | |
2979 else | |
2980 { | |
2981 Lisp_Object elt, tail; | |
2982 struct gcpro ngcpro1; | |
2983 | |
2984 NGCPRO1 (tail); | |
2985 | |
2986 { | |
2987 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) | |
2988 { | |
2989 args[1] = elt; | |
2990 Ffuncall (2, args); | |
2991 } | |
2992 } | |
2993 | |
2994 NUNGCPRO; | |
2995 } | |
2996 } | |
2997 else if (VECTORP (sequence)) | |
2998 { | |
2999 Lisp_Object *objs = XVECTOR_DATA (sequence); | |
3000 for (i = 0; i < leni; i++) | 3072 for (i = 0; i < leni; i++) |
3001 { | 3073 { |
3002 args[1] = *objs++; | 3074 args[1] = *objs++; |
3003 result = Ffuncall (2, args); | 3075 result = Ffuncall (2, args); |
3004 if (vals) vals[gcpro1.nvars++] = result; | 3076 if (vals) vals[gcpro1.nvars++] = result; |
3005 } | 3077 } |
3006 } | 3078 } |
3007 else if (STRINGP (sequence)) | 3079 else if (STRINGP (seq)) |
3008 { | 3080 { |
3009 /* The string data of `sequence' might be relocated during GC. */ | 3081 Bufbyte *p = XSTRING_DATA (seq); |
3010 Bytecount slen = XSTRING_LENGTH (sequence); | 3082 for (i = 0; i < leni; i++) |
3011 Bufbyte *p = alloca_array (Bufbyte, slen); | |
3012 Bufbyte *end = p + slen; | |
3013 | |
3014 memcpy (p, XSTRING_DATA (sequence), slen); | |
3015 | |
3016 while (p < end) | |
3017 { | 3083 { |
3018 args[1] = make_char (charptr_emchar (p)); | 3084 args[1] = make_char (charptr_emchar (p)); |
3019 INC_CHARPTR (p); | 3085 INC_CHARPTR (p); |
3020 result = Ffuncall (2, args); | 3086 result = Ffuncall (2, args); |
3021 if (vals) vals[gcpro1.nvars++] = result; | 3087 if (vals) vals[gcpro1.nvars++] = result; |
3022 } | 3088 } |
3023 } | 3089 } |
3024 else if (BIT_VECTORP (sequence)) | 3090 else if (BIT_VECTORP (seq)) |
3025 { | 3091 { |
3026 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence); | 3092 struct Lisp_Bit_Vector *v = XBIT_VECTOR (seq); |
3027 for (i = 0; i < leni; i++) | 3093 for (i = 0; i < leni; i++) |
3028 { | 3094 { |
3029 args[1] = make_int (bit_vector_bit (v, i)); | 3095 args[1] = make_int (bit_vector_bit (v, i)); |
3030 result = Ffuncall (2, args); | 3096 result = Ffuncall (2, args); |
3031 if (vals) vals[gcpro1.nvars++] = result; | 3097 if (vals) vals[gcpro1.nvars++] = result; |
3032 } | 3098 } |
3033 } | 3099 } |
3034 else | 3100 else |
3035 abort (); /* unreachable, since Flength (sequence) did not get an error */ | 3101 abort(); /* cannot get here since Flength(seq) did not get an error */ |
3036 | 3102 |
3037 if (vals) | 3103 if (vals) |
3038 UNGCPRO; | 3104 UNGCPRO; |
3039 } | 3105 } |
3040 | 3106 |
3041 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /* | 3107 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /* |
3042 Apply FUNCTION to each element of SEQUENCE, and concat the results as strings. | 3108 Apply FN to each element of SEQ, and concat the results as strings. |
3043 In between each pair of results, insert SEPARATOR. Thus, using " " as | 3109 In between each pair of results, stick in SEP. |
3044 SEPARATOR results in spaces between the values returned by FUNCTION. | 3110 Thus, " " as SEP results in spaces between the values returned by FN. |
3045 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3111 */ |
3046 */ | 3112 (fn, seq, sep)) |
3047 (function, sequence, separator)) | 3113 { |
3048 { | 3114 size_t len = XINT (Flength (seq)); |
3049 size_t len = XINT (Flength (sequence)); | |
3050 Lisp_Object *args; | 3115 Lisp_Object *args; |
3051 int i; | 3116 int i; |
3117 struct gcpro gcpro1; | |
3052 int nargs = len + len - 1; | 3118 int nargs = len + len - 1; |
3053 | 3119 |
3054 if (len == 0) return build_string (""); | 3120 if (nargs < 0) return build_string (""); |
3055 | 3121 |
3056 args = alloca_array (Lisp_Object, nargs); | 3122 args = alloca_array (Lisp_Object, nargs); |
3057 | 3123 |
3058 mapcar1 (len, args, function, sequence); | 3124 GCPRO1 (sep); |
3125 mapcar1 (len, args, fn, seq); | |
3126 UNGCPRO; | |
3059 | 3127 |
3060 for (i = len - 1; i >= 0; i--) | 3128 for (i = len - 1; i >= 0; i--) |
3061 args[i + i] = args[i]; | 3129 args[i + i] = args[i]; |
3062 | 3130 |
3063 for (i = 1; i < nargs; i += 2) | 3131 for (i = 1; i < nargs; i += 2) |
3064 args[i] = separator; | 3132 args[i] = sep; |
3065 | 3133 |
3066 return Fconcat (nargs, args); | 3134 return Fconcat (nargs, args); |
3067 } | 3135 } |
3068 | 3136 |
3069 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* | 3137 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* |
3070 Apply FUNCTION to each element of SEQUENCE; return a list of the results. | 3138 Apply FUNCTION to each element of SEQUENCE, and make a list of the results. |
3071 The result is a list of the same length as SEQUENCE. | 3139 The result is a list just as long as SEQUENCE. |
3072 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3140 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3073 */ | 3141 */ |
3074 (function, sequence)) | 3142 (fn, seq)) |
3075 { | 3143 { |
3076 size_t len = XINT (Flength (sequence)); | 3144 size_t len = XINT (Flength (seq)); |
3077 Lisp_Object *args = alloca_array (Lisp_Object, len); | 3145 Lisp_Object *args = alloca_array (Lisp_Object, len); |
3078 | 3146 |
3079 mapcar1 (len, args, function, sequence); | 3147 mapcar1 (len, args, fn, seq); |
3080 | 3148 |
3081 return Flist (len, args); | 3149 return Flist (len, args); |
3082 } | 3150 } |
3083 | 3151 |
3084 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* | 3152 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* |
3085 Apply FUNCTION to each element of SEQUENCE; return a vector of the results. | 3153 Apply FUNCTION to each element of SEQUENCE, making a vector of the results. |
3086 The result is a vector of the same length as SEQUENCE. | 3154 The result is a vector of the same length as SEQUENCE. |
3087 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3155 SEQUENCE may be a list, a vector or a string. |
3088 */ | 3156 */ |
3089 (function, sequence)) | 3157 (fn, seq)) |
3090 { | 3158 { |
3091 size_t len = XINT (Flength (sequence)); | 3159 size_t len = XINT (Flength (seq)); |
3092 Lisp_Object result = make_vector (len, Qnil); | 3160 Lisp_Object result = make_vector (len, Qnil); |
3093 struct gcpro gcpro1; | 3161 struct gcpro gcpro1; |
3094 | 3162 |
3095 GCPRO1 (result); | 3163 GCPRO1 (result); |
3096 mapcar1 (len, XVECTOR_DATA (result), function, sequence); | 3164 mapcar1 (len, XVECTOR_DATA (result), fn, seq); |
3097 UNGCPRO; | 3165 UNGCPRO; |
3098 | 3166 |
3099 return result; | 3167 return result; |
3100 } | 3168 } |
3101 | 3169 |
3102 DEFUN ("mapc-internal", Fmapc_internal, 2, 2, 0, /* | 3170 DEFUN ("mapc", Fmapc, 2, 2, 0, /* |
3103 Apply FUNCTION to each element of SEQUENCE. | 3171 Apply FUNCTION to each element of SEQUENCE. |
3104 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3172 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3105 This function is like `mapcar' but does not accumulate the results, | 3173 This function is like `mapcar' but does not accumulate the results, |
3106 which is more efficient if you do not use the results. | 3174 which is more efficient if you do not use the results. |
3107 | 3175 */ |
3108 The difference between this and `mapc' is that `mapc' supports all | 3176 (fn, seq)) |
3109 the spiffy Common Lisp arguments. You should normally use `mapc'. | 3177 { |
3110 */ | 3178 mapcar1 (XINT (Flength (seq)), 0, fn, seq); |
3111 (function, sequence)) | 3179 |
3112 { | 3180 return seq; |
3113 mapcar1 (XINT (Flength (sequence)), 0, function, sequence); | |
3114 | |
3115 return sequence; | |
3116 } | |
3117 | |
3118 | |
3119 | |
3120 | |
3121 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* | |
3122 Destructively replace the list OLD with NEW. | |
3123 This is like (copy-sequence NEW) except that it reuses the | |
3124 conses in OLD as much as possible. If OLD and NEW are the same | |
3125 length, no consing will take place. | |
3126 */ | |
3127 (old, new)) | |
3128 { | |
3129 Lisp_Object tail, oldtail = old, prevoldtail = Qnil; | |
3130 | |
3131 EXTERNAL_LIST_LOOP (tail, new) | |
3132 { | |
3133 if (!NILP (oldtail)) | |
3134 { | |
3135 CHECK_CONS (oldtail); | |
3136 XCAR (oldtail) = XCAR (tail); | |
3137 } | |
3138 else if (!NILP (prevoldtail)) | |
3139 { | |
3140 XCDR (prevoldtail) = Fcons (XCAR (tail), Qnil); | |
3141 prevoldtail = XCDR (prevoldtail); | |
3142 } | |
3143 else | |
3144 old = oldtail = Fcons (XCAR (tail), Qnil); | |
3145 | |
3146 if (!NILP (oldtail)) | |
3147 { | |
3148 prevoldtail = oldtail; | |
3149 oldtail = XCDR (oldtail); | |
3150 } | |
3151 } | |
3152 | |
3153 if (!NILP (prevoldtail)) | |
3154 XCDR (prevoldtail) = Qnil; | |
3155 else | |
3156 old = Qnil; | |
3157 | |
3158 return old; | |
3159 } | 3181 } |
3160 | 3182 |
3161 | 3183 |
3162 /* #### this function doesn't belong in this file! */ | 3184 /* #### this function doesn't belong in this file! */ |
3163 | 3185 |
3228 => ; Non-nil if this Emacs supports TTY frames. | 3250 => ; Non-nil if this Emacs supports TTY frames. |
3229 | 3251 |
3230 (featurep '(or (and xemacs 19.15) (and emacs 19.34))) | 3252 (featurep '(or (and xemacs 19.15) (and emacs 19.34))) |
3231 => ; Non-nil on XEmacs 19.15 and later, or FSF Emacs 19.34 and later. | 3253 => ; Non-nil on XEmacs 19.15 and later, or FSF Emacs 19.34 and later. |
3232 | 3254 |
3233 (featurep '(and xemacs 21.02)) | |
3234 => ; Non-nil on XEmacs 21.2 and later. | |
3235 | |
3236 NOTE: The advanced arguments of this function (anything other than a | 3255 NOTE: The advanced arguments of this function (anything other than a |
3237 symbol) are not yet supported by FSF Emacs. If you feel they are useful | 3256 symbol) are not yet supported by FSF Emacs. If you feel they are useful |
3238 for supporting multiple Emacs variants, lobby Richard Stallman at | 3257 for supporting multiple Emacs variants, lobby Richard Stallman at |
3239 <bug-gnu-emacs@gnu.org>. | 3258 <bug-gnu-emacs@prep.ai.mit.edu>. |
3240 */ | 3259 */ |
3241 (fexp)) | 3260 (fexp)) |
3242 { | 3261 { |
3243 #ifndef FEATUREP_SYNTAX | 3262 #ifndef FEATUREP_SYNTAX |
3244 CHECK_SYMBOL (fexp); | 3263 CHECK_SYMBOL (fexp); |
3361 return unbind_to (speccount, feature); | 3380 return unbind_to (speccount, feature); |
3362 } | 3381 } |
3363 } | 3382 } |
3364 | 3383 |
3365 /* base64 encode/decode functions. | 3384 /* base64 encode/decode functions. |
3366 | 3385 Based on code from GNU recode. */ |
3367 Originally based on code from GNU recode. Ported to FSF Emacs by | 3386 |
3368 Lars Magne Ingebrigtsen and Karl Heuer. Ported to XEmacs and | 3387 #define MIME_LINE_LENGTH 76 |
3369 subsequently heavily hacked by Hrvoje Niksic. */ | |
3370 | |
3371 #define MIME_LINE_LENGTH 72 | |
3372 | 3388 |
3373 #define IS_ASCII(Character) \ | 3389 #define IS_ASCII(Character) \ |
3374 ((Character) < 128) | 3390 ((Character) < 128) |
3375 #define IS_BASE64(Character) \ | 3391 #define IS_BASE64(Character) \ |
3376 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0) | 3392 (IS_ASCII (Character) && base64_char_to_value[Character] >= 0) |
3422 | 3438 |
3423 The octets are divided into 6 bit chunks, which are then encoded into | 3439 The octets are divided into 6 bit chunks, which are then encoded into |
3424 base64 characters. */ | 3440 base64 characters. */ |
3425 | 3441 |
3426 #define ADVANCE_INPUT(c, stream) \ | 3442 #define ADVANCE_INPUT(c, stream) \ |
3427 ((ec = Lstream_get_emchar (stream)) == -1 ? 0 : \ | 3443 (ec = Lstream_get_emchar (stream), \ |
3444 ec == -1 ? 0 : \ | |
3428 ((ec > 255) ? \ | 3445 ((ec > 255) ? \ |
3429 (signal_simple_error ("Non-ascii character in base64 input", \ | 3446 (error ("Non-ascii character detected in base64 input"), 0) \ |
3430 make_char (ec)), 0) \ | 3447 : (c = (Bufbyte)ec, 1))) |
3431 : (c = (Bufbyte)ec), 1)) | |
3432 | 3448 |
3433 static Bytind | 3449 static Bytind |
3434 base64_encode_1 (Lstream *istream, Bufbyte *to, int line_break) | 3450 base64_encode_1 (Lstream *istream, Bufbyte *to, int line_break) |
3435 { | 3451 { |
3436 EMACS_INT counter = 0; | 3452 EMACS_INT counter = 0; |
3486 | 3502 |
3487 return e - to; | 3503 return e - to; |
3488 } | 3504 } |
3489 #undef ADVANCE_INPUT | 3505 #undef ADVANCE_INPUT |
3490 | 3506 |
3491 /* Get next character from the stream, except that non-base64 | 3507 #define ADVANCE_INPUT(c, stream) \ |
3492 characters are ignored. This is in accordance with rfc2045. EC | 3508 (ec = Lstream_get_emchar (stream), \ |
3493 should be an Emchar, so that it can hold -1 as the value for EOF. */ | 3509 ec == -1 ? 0 : (c = (Bufbyte)ec, 1)) |
3494 #define ADVANCE_INPUT_IGNORE_NONBASE64(ec, stream, streampos) do { \ | 3510 |
3495 ec = Lstream_get_emchar (stream); \ | 3511 #define STORE_BYTE(pos, val) do { \ |
3496 ++streampos; \ | |
3497 /* IS_BASE64 may not be called with negative arguments so check for \ | |
3498 EOF first. */ \ | |
3499 if (ec < 0 || IS_BASE64 (ec) || ec == '=') \ | |
3500 break; \ | |
3501 } while (1) | |
3502 | |
3503 #define STORE_BYTE(pos, val, ccnt) do { \ | |
3504 pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val))); \ | 3512 pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val))); \ |
3505 ++ccnt; \ | 3513 ++*ccptr; \ |
3506 } while (0) | 3514 } while (0) |
3507 | 3515 |
3508 static Bytind | 3516 static Bytind |
3509 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr) | 3517 base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr) |
3510 { | 3518 { |
3511 Charcount ccnt = 0; | 3519 Emchar ec; |
3512 Bufbyte *e = to; | 3520 Bufbyte *e = to; |
3513 EMACS_INT streampos = 0; | 3521 unsigned long value; |
3514 | 3522 |
3523 *ccptr = 0; | |
3515 while (1) | 3524 while (1) |
3516 { | 3525 { |
3517 Emchar ec; | 3526 Bufbyte c; |
3518 unsigned long value; | 3527 |
3528 if (!ADVANCE_INPUT (c, istream)) | |
3529 break; | |
3530 | |
3531 /* Accept wrapping lines. */ | |
3532 if (c == '\r') | |
3533 { | |
3534 if (!ADVANCE_INPUT (c, istream) | |
3535 || c != '\n') | |
3536 return -1; | |
3537 } | |
3538 if (c == '\n') | |
3539 { | |
3540 if (!ADVANCE_INPUT (c, istream)) | |
3541 break; | |
3542 /* FSF checks for end of text here, but that's wrong. */ | |
3543 /* FSF checks for correct line length here; that's also | |
3544 wrong; some MIME encoders use different line lengths. */ | |
3545 } | |
3519 | 3546 |
3520 /* Process first byte of a quadruplet. */ | 3547 /* Process first byte of a quadruplet. */ |
3521 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); | 3548 if (!IS_BASE64 (c)) |
3522 if (ec < 0) | 3549 return -1; |
3523 break; | 3550 value = base64_char_to_value[c] << 18; |
3524 if (ec == '=') | |
3525 signal_simple_error ("Illegal `=' character while decoding base64", | |
3526 make_int (streampos)); | |
3527 value = base64_char_to_value[ec] << 18; | |
3528 | 3551 |
3529 /* Process second byte of a quadruplet. */ | 3552 /* Process second byte of a quadruplet. */ |
3530 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); | 3553 if (!ADVANCE_INPUT (c, istream)) |
3531 if (ec < 0) | 3554 return -1; |
3532 error ("Premature EOF while decoding base64"); | 3555 |
3533 if (ec == '=') | 3556 if (!IS_BASE64 (c)) |
3534 signal_simple_error ("Illegal `=' character while decoding base64", | 3557 return -1; |
3535 make_int (streampos)); | 3558 value |= base64_char_to_value[c] << 12; |
3536 value |= base64_char_to_value[ec] << 12; | 3559 |
3537 STORE_BYTE (e, value >> 16, ccnt); | 3560 STORE_BYTE (e, value >> 16); |
3538 | 3561 |
3539 /* Process third byte of a quadruplet. */ | 3562 /* Process third byte of a quadruplet. */ |
3540 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); | 3563 if (!ADVANCE_INPUT (c, istream)) |
3541 if (ec < 0) | 3564 return -1; |
3542 error ("Premature EOF while decoding base64"); | 3565 |
3543 | 3566 if (c == '=') |
3544 if (ec == '=') | 3567 { |
3545 { | 3568 if (!ADVANCE_INPUT (c, istream)) |
3546 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); | 3569 return -1; |
3547 if (ec < 0) | 3570 if (c != '=') |
3548 error ("Premature EOF while decoding base64"); | 3571 return -1; |
3549 if (ec != '=') | |
3550 signal_simple_error ("Padding `=' expected but not found while decoding base64", | |
3551 make_int (streampos)); | |
3552 continue; | 3572 continue; |
3553 } | 3573 } |
3554 | 3574 |
3555 value |= base64_char_to_value[ec] << 6; | 3575 if (!IS_BASE64 (c)) |
3556 STORE_BYTE (e, 0xff & value >> 8, ccnt); | 3576 return -1; |
3577 value |= base64_char_to_value[c] << 6; | |
3578 | |
3579 STORE_BYTE (e, 0xff & value >> 8); | |
3557 | 3580 |
3558 /* Process fourth byte of a quadruplet. */ | 3581 /* Process fourth byte of a quadruplet. */ |
3559 ADVANCE_INPUT_IGNORE_NONBASE64 (ec, istream, streampos); | 3582 if (!ADVANCE_INPUT (c, istream)) |
3560 if (ec < 0) | 3583 return -1; |
3561 error ("Premature EOF while decoding base64"); | 3584 |
3562 if (ec == '=') | 3585 if (c == '=') |
3563 continue; | 3586 continue; |
3564 | 3587 |
3565 value |= base64_char_to_value[ec]; | 3588 if (!IS_BASE64 (c)) |
3566 STORE_BYTE (e, 0xff & value, ccnt); | 3589 return -1; |
3567 } | 3590 value |= base64_char_to_value[c]; |
3568 | 3591 |
3569 *ccptr = ccnt; | 3592 STORE_BYTE (e, 0xff & value); |
3593 } | |
3594 | |
3570 return e - to; | 3595 return e - to; |
3571 } | 3596 } |
3572 #undef ADVANCE_INPUT | 3597 #undef ADVANCE_INPUT |
3573 #undef ADVANCE_INPUT_IGNORE_NONBASE64 | 3598 #undef INPUT_EOF_P |
3574 #undef STORE_BYTE | |
3575 | 3599 |
3576 static Lisp_Object | 3600 static Lisp_Object |
3577 free_malloced_ptr (Lisp_Object unwind_obj) | 3601 free_malloced_ptr (Lisp_Object unwind_obj) |
3578 { | 3602 { |
3579 void *ptr = (void *)get_opaque_ptr (unwind_obj); | 3603 void *ptr = (void *)get_opaque_ptr (unwind_obj); |
3646 and delete the old. (Insert first in order to preserve markers.) */ | 3670 and delete the old. (Insert first in order to preserve markers.) */ |
3647 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0); | 3671 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0); |
3648 XMALLOC_UNBIND (encoded, allength, speccount); | 3672 XMALLOC_UNBIND (encoded, allength, speccount); |
3649 buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0); | 3673 buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0); |
3650 | 3674 |
3651 /* Simulate FSF Emacs implementation of this function: if point was | 3675 /* Simulate FSF Emacs: if point was in the region, place it at the |
3652 in the region, place it at the beginning. */ | 3676 beginning. */ |
3653 if (old_pt >= begv && old_pt < zv) | 3677 if (old_pt >= begv && old_pt < zv) |
3654 BUF_SET_PT (buf, begv); | 3678 BUF_SET_PT (buf, begv); |
3655 | 3679 |
3656 /* We return the length of the encoded text. */ | 3680 /* We return the length of the encoded text. */ |
3657 return make_int (encoded_length); | 3681 return make_int (encoded_length); |
3688 | 3712 |
3689 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /* | 3713 DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /* |
3690 Base64-decode the region between BEG and END. | 3714 Base64-decode the region between BEG and END. |
3691 Return the length of the decoded text. | 3715 Return the length of the decoded text. |
3692 If the region can't be decoded, return nil and don't modify the buffer. | 3716 If the region can't be decoded, return nil and don't modify the buffer. |
3693 Characters out of the base64 alphabet are ignored. | |
3694 */ | 3717 */ |
3695 (beg, end)) | 3718 (beg, end)) |
3696 { | 3719 { |
3697 struct buffer *buf = current_buffer; | 3720 struct buffer *buf = current_buffer; |
3698 Bufpos begv, zv, old_pt = BUF_PT (buf); | 3721 Bufpos begv, zv, old_pt = BUF_PT (buf); |
3713 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); | 3736 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); |
3714 if (decoded_length > length * MAX_EMCHAR_LEN) | 3737 if (decoded_length > length * MAX_EMCHAR_LEN) |
3715 abort (); | 3738 abort (); |
3716 Lstream_delete (XLSTREAM (input)); | 3739 Lstream_delete (XLSTREAM (input)); |
3717 | 3740 |
3741 if (decoded_length < 0) | |
3742 { | |
3743 /* The decoding wasn't possible. */ | |
3744 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); | |
3745 return Qnil; | |
3746 } | |
3747 | |
3718 /* Now we have decoded the region, so we insert the new contents | 3748 /* Now we have decoded the region, so we insert the new contents |
3719 and delete the old. (Insert first in order to preserve markers.) */ | 3749 and delete the old. (Insert first in order to preserve markers.) */ |
3720 BUF_SET_PT (buf, begv); | 3750 BUF_SET_PT (buf, begv); |
3721 buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0); | 3751 buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0); |
3722 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); | 3752 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); |
3723 buffer_delete_range (buf, begv + cc_decoded_length, | 3753 buffer_delete_range (buf, begv + cc_decoded_length, |
3724 zv + cc_decoded_length, 0); | 3754 zv + cc_decoded_length, 0); |
3725 | 3755 |
3726 /* Simulate FSF Emacs implementation of this function: if point was | 3756 /* Simulate FSF Emacs: if point was in the region, place it at the |
3727 in the region, place it at the beginning. */ | 3757 beginning. */ |
3728 if (old_pt >= begv && old_pt < zv) | 3758 if (old_pt >= begv && old_pt < zv) |
3729 BUF_SET_PT (buf, begv); | 3759 BUF_SET_PT (buf, begv); |
3730 | 3760 |
3731 return make_int (cc_decoded_length); | 3761 return make_int (cc_decoded_length); |
3732 } | 3762 } |
3733 | 3763 |
3734 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /* | 3764 DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /* |
3735 Base64-decode STRING and return the result. | 3765 Base64-decode STRING and return the result. |
3736 Characters out of the base64 alphabet are ignored. | |
3737 */ | 3766 */ |
3738 (string)) | 3767 (string)) |
3739 { | 3768 { |
3740 Bufbyte *decoded; | 3769 Bufbyte *decoded; |
3741 Bytind decoded_length; | 3770 Bytind decoded_length; |
3754 &cc_decoded_length); | 3783 &cc_decoded_length); |
3755 if (decoded_length > length * MAX_EMCHAR_LEN) | 3784 if (decoded_length > length * MAX_EMCHAR_LEN) |
3756 abort (); | 3785 abort (); |
3757 Lstream_delete (XLSTREAM (input)); | 3786 Lstream_delete (XLSTREAM (input)); |
3758 | 3787 |
3788 if (decoded_length < 0) | |
3789 { | |
3790 /* The decoding wasn't possible. */ | |
3791 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); | |
3792 return Qnil; | |
3793 } | |
3794 | |
3759 result = make_string (decoded, decoded_length); | 3795 result = make_string (decoded, decoded_length); |
3760 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); | 3796 XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount); |
3761 return result; | 3797 return result; |
3762 } | 3798 } |
3763 | 3799 |
3764 Lisp_Object Qyes_or_no_p; | 3800 Lisp_Object Qyes_or_no_p; |
3765 | 3801 |
3766 void | 3802 void |
3767 syms_of_fns (void) | 3803 syms_of_fns (void) |
3768 { | 3804 { |
3769 INIT_LRECORD_IMPLEMENTATION (bit_vector); | |
3770 | |
3771 defsymbol (&Qstring_lessp, "string-lessp"); | 3805 defsymbol (&Qstring_lessp, "string-lessp"); |
3772 defsymbol (&Qidentity, "identity"); | 3806 defsymbol (&Qidentity, "identity"); |
3773 defsymbol (&Qyes_or_no_p, "yes-or-no-p"); | 3807 defsymbol (&Qyes_or_no_p, "yes-or-no-p"); |
3774 | 3808 |
3775 DEFSUBR (Fidentity); | 3809 DEFSUBR (Fidentity); |
3843 DEFSUBR (Fold_equal); | 3877 DEFSUBR (Fold_equal); |
3844 DEFSUBR (Ffillarray); | 3878 DEFSUBR (Ffillarray); |
3845 DEFSUBR (Fnconc); | 3879 DEFSUBR (Fnconc); |
3846 DEFSUBR (Fmapcar); | 3880 DEFSUBR (Fmapcar); |
3847 DEFSUBR (Fmapvector); | 3881 DEFSUBR (Fmapvector); |
3848 DEFSUBR (Fmapc_internal); | 3882 DEFSUBR (Fmapc); |
3849 DEFSUBR (Fmapconcat); | 3883 DEFSUBR (Fmapconcat); |
3850 DEFSUBR (Freplace_list); | |
3851 DEFSUBR (Fload_average); | 3884 DEFSUBR (Fload_average); |
3852 DEFSUBR (Ffeaturep); | 3885 DEFSUBR (Ffeaturep); |
3853 DEFSUBR (Frequire); | 3886 DEFSUBR (Frequire); |
3854 DEFSUBR (Fprovide); | 3887 DEFSUBR (Fprovide); |
3855 DEFSUBR (Fbase64_encode_region); | 3888 DEFSUBR (Fbase64_encode_region); |