Mercurial > hg > xemacs-beta
comparison src/fns.c @ 4998:b46c89ccbed3
Merge.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 06 Feb 2010 12:28:19 +0000 |
parents | 48b63cd88a21 8800b5350a13 |
children | ebafcd6e9f4b |
comparison
equal
deleted
inserted
replaced
4994:76af7fc13e81 | 4998:b46c89ccbed3 |
---|---|
54 /* NOTE: This symbol is also used in lread.c */ | 54 /* NOTE: This symbol is also used in lread.c */ |
55 #define FEATUREP_SYNTAX | 55 #define FEATUREP_SYNTAX |
56 | 56 |
57 Lisp_Object Qstring_lessp; | 57 Lisp_Object Qstring_lessp; |
58 Lisp_Object Qidentity; | 58 Lisp_Object Qidentity; |
59 Lisp_Object Qvector, Qarray, Qstring, Qlist, Qbit_vector; | |
59 | 60 |
60 Lisp_Object Qbase64_conversion_error; | 61 Lisp_Object Qbase64_conversion_error; |
61 | 62 |
62 Lisp_Object Vpath_separator; | 63 Lisp_Object Vpath_separator; |
63 | 64 |
980 */ | 981 */ |
981 (sequence, start, end)) | 982 (sequence, start, end)) |
982 { | 983 { |
983 EMACS_INT len, s, e; | 984 EMACS_INT len, s, e; |
984 | 985 |
986 CHECK_SEQUENCE (sequence); | |
987 | |
985 if (STRINGP (sequence)) | 988 if (STRINGP (sequence)) |
986 return Fsubstring (sequence, start, end); | 989 return Fsubstring (sequence, start, end); |
987 | 990 |
988 len = XINT (Flength (sequence)); | 991 len = XINT (Flength (sequence)); |
989 | 992 |
1041 bit_vector_bit (XBIT_VECTOR (sequence), i)); | 1044 bit_vector_bit (XBIT_VECTOR (sequence), i)); |
1042 return result; | 1045 return result; |
1043 } | 1046 } |
1044 else | 1047 else |
1045 { | 1048 { |
1046 ABORT (); /* unreachable, since Flength (sequence) did not get | 1049 ABORT (); /* unreachable, since CHECK_SEQUENCE (sequence) did not |
1047 an error */ | 1050 error */ |
1048 return Qnil; | 1051 return Qnil; |
1049 } | 1052 } |
1050 } | 1053 } |
1051 | 1054 |
1052 /* Split STRING into a list of substrings. The substrings are the | 1055 /* Split STRING into a list of substrings. The substrings are the |
3221 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ | 3224 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ |
3222 } | 3225 } |
3223 | 3226 |
3224 | 3227 |
3225 /* This is the guts of several mapping functions. | 3228 /* This is the guts of several mapping functions. |
3226 Apply FUNCTION to each element of SEQUENCE, one by one, | 3229 |
3227 storing the results into elements of VALS, a C vector of Lisp_Objects. | 3230 Call FUNCTION CALL_COUNT times, with NSEQUENCES arguments each time, |
3228 LENI is the length of VALS, which should also be the length of SEQUENCE. | 3231 taking the elements from SEQUENCES. If VALS is non-NULL, store the |
3229 | 3232 results into VALS, a C array of Lisp_Objects; else, if LISP_VALS is |
3230 If VALS is a null pointer, do not accumulate the results. */ | 3233 non-nil, store the results into LISP_VALS, a sequence with sufficient |
3234 room for CALL_COUNT results. Else, do not accumulate any result. | |
3235 | |
3236 If VALS is non-NULL, NSEQUENCES is one, and SEQUENCES[0] is a cons, | |
3237 mapcarX will store the elements of SEQUENCES[0] in stack and GCPRO them, | |
3238 so FUNCTION cannot insert a non-cons into SEQUENCES[0] and throw off | |
3239 mapcarX. | |
3240 | |
3241 Otherwise, mapcarX signals a wrong-type-error if it encounters a | |
3242 non-cons, non-array when traversing SEQUENCES. Common Lisp specifies in | |
3243 MAPPING-DESTRUCTIVE-INTERACTION that it is an error when FUNCTION | |
3244 destructively modifies SEQUENCES in a way that might affect the ongoing | |
3245 traversal operation. | |
3246 | |
3247 If SOME_OR_EVERY is SOME_OR_EVERY_SOME, return the (possibly multiple) | |
3248 values given by FUNCTION the first time it is non-nil, and abandon the | |
3249 iterations. LISP_VALS in this case must be an object created by | |
3250 make_opaque_ptr, dereferenced as pointing to a Lisp object. If | |
3251 SOME_OR_EVERY is SOME_OR_EVERY_EVERY, store Qnil at the Lisp_Object | |
3252 pointer address provided by LISP_VALS if FUNCTION gives nil; otherwise | |
3253 leave it alone. */ | |
3254 | |
3255 #define SOME_OR_EVERY_NEITHER 0 | |
3256 #define SOME_OR_EVERY_SOME 1 | |
3257 #define SOME_OR_EVERY_EVERY 2 | |
3231 | 3258 |
3232 static void | 3259 static void |
3233 mapcar1 (Elemcount leni, Lisp_Object *vals, | 3260 mapcarX (Elemcount call_count, Lisp_Object *vals, Lisp_Object lisp_vals, |
3234 Lisp_Object function, Lisp_Object sequence) | 3261 Lisp_Object function, int nsequences, Lisp_Object *sequences, |
3235 { | 3262 int some_or_every) |
3236 Lisp_Object result; | 3263 { |
3237 Lisp_Object args[2]; | 3264 Lisp_Object called, *args; |
3238 struct gcpro gcpro1; | 3265 struct gcpro gcpro1, gcpro2; |
3239 | 3266 int i, j; |
3240 if (vals) | 3267 enum lrecord_type lisp_vals_type; |
3241 { | 3268 |
3242 GCPRO1 (vals[0]); | 3269 assert (LRECORDP (lisp_vals)); |
3243 gcpro1.nvars = 0; | 3270 lisp_vals_type = XRECORD_LHEADER (lisp_vals)->type; |
3244 } | 3271 |
3245 | 3272 args = alloca_array (Lisp_Object, nsequences + 1); |
3246 args[0] = function; | 3273 args[0] = function; |
3247 | 3274 for (i = 1; i <= nsequences; ++i) |
3248 if (LISTP (sequence)) | 3275 { |
3249 { | 3276 args[i] = Qnil; |
3250 /* A devious `function' could either: | 3277 } |
3251 - insert garbage into the list in front of us, causing XCDR to crash | 3278 |
3252 - amputate the list behind us using (setcdr), causing the remaining | 3279 if (vals != NULL) |
3253 elts to lose their GCPRO status. | 3280 { |
3254 | 3281 GCPRO2 (args[0], vals[0]); |
3255 if (vals != 0) we avoid this by copying the elts into the | 3282 gcpro1.nvars = nsequences + 1; |
3256 `vals' array. By a stroke of luck, `vals' is exactly large | 3283 gcpro2.nvars = 0; |
3257 enough to hold the elts left to be traversed as well as the | 3284 } |
3258 results computed so far. | 3285 else |
3259 | 3286 { |
3260 if (vals == 0) we don't have any free space available and | 3287 GCPRO1 (args[0]); |
3261 don't want to eat up any more stack with ALLOCA (). | 3288 gcpro1.nvars = nsequences + 1; |
3262 So we use EXTERNAL_LIST_LOOP_3_NO_DECLARE and GCPRO the tail. */ | 3289 } |
3263 | 3290 |
3264 if (vals) | 3291 /* Be extra nice in the event that we've been handed one list and one |
3265 { | 3292 only; make it possible for FUNCTION to set cdrs not yet processed to |
3266 Lisp_Object *val = vals; | 3293 non-cons, non-nil objects without ill-effect, if we have been handed |
3267 Elemcount i; | 3294 the stack space to do that. */ |
3268 | 3295 if (vals != NULL && 1 == nsequences && CONSP (sequences[0])) |
3269 LIST_LOOP_2 (elt, sequence) | 3296 { |
3270 *val++ = elt; | 3297 Lisp_Object lst = sequences[0]; |
3271 | 3298 Lisp_Object *val = vals; |
3272 gcpro1.nvars = leni; | 3299 for (i = 0; i < call_count; ++i) |
3273 | 3300 { |
3274 for (i = 0; i < leni; i++) | 3301 *val++ = XCAR (lst); |
3302 lst = XCDR (lst); | |
3303 } | |
3304 gcpro2.nvars = call_count; | |
3305 | |
3306 for (i = 0; i < call_count; ++i) | |
3307 { | |
3308 args[1] = vals[i]; | |
3309 vals[i] = Ffuncall (nsequences + 1, args); | |
3310 } | |
3311 } | |
3312 else | |
3313 { | |
3314 Binbyte *sequence_types = alloca_array (Binbyte, nsequences); | |
3315 for (j = 0; j < nsequences; ++j) | |
3316 { | |
3317 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type; | |
3318 } | |
3319 | |
3320 for (i = 0; i < call_count; ++i) | |
3321 { | |
3322 for (j = 0; j < nsequences; ++j) | |
3275 { | 3323 { |
3276 args[1] = vals[i]; | 3324 switch (sequence_types[j]) |
3277 vals[i] = Ffuncall (2, args); | 3325 { |
3326 case lrecord_type_cons: | |
3327 { | |
3328 if (!CONSP (sequences[j])) | |
3329 { | |
3330 /* This means FUNCTION has probably messed | |
3331 around with a cons in one of the sequences, | |
3332 since we checked the type | |
3333 (CHECK_SEQUENCE()) and the length and | |
3334 structure (with Flength()) correctly in our | |
3335 callers. */ | |
3336 dead_wrong_type_argument (Qconsp, sequences[j]); | |
3337 } | |
3338 args[j + 1] = XCAR (sequences[j]); | |
3339 sequences[j] = XCDR (sequences[j]); | |
3340 break; | |
3341 } | |
3342 case lrecord_type_vector: | |
3343 { | |
3344 args[j + 1] = XVECTOR_DATA (sequences[j])[i]; | |
3345 break; | |
3346 } | |
3347 case lrecord_type_string: | |
3348 { | |
3349 args[j + 1] = make_char (string_ichar (sequences[j], i)); | |
3350 break; | |
3351 } | |
3352 case lrecord_type_bit_vector: | |
3353 { | |
3354 args[j + 1] | |
3355 = make_int (bit_vector_bit (XBIT_VECTOR (sequences[j]), | |
3356 i)); | |
3357 break; | |
3358 } | |
3359 default: | |
3360 ABORT(); | |
3361 } | |
3278 } | 3362 } |
3279 } | 3363 called = Ffuncall (nsequences + 1, args); |
3280 else | 3364 if (vals != NULL) |
3281 { | 3365 { |
3282 Lisp_Object elt, tail; | 3366 vals[i] = IGNORE_MULTIPLE_VALUES (called); |
3283 EMACS_INT len_unused; | 3367 gcpro2.nvars += 1; |
3284 struct gcpro ngcpro1; | 3368 } |
3285 | 3369 else |
3286 NGCPRO1 (tail); | 3370 { |
3287 | 3371 switch (lisp_vals_type) |
3288 { | 3372 { |
3289 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len_unused) | 3373 case lrecord_type_symbol: |
3290 { | 3374 break; |
3291 args[1] = elt; | 3375 case lrecord_type_cons: |
3292 Ffuncall (2, args); | 3376 { |
3293 } | 3377 if (SOME_OR_EVERY_NEITHER == some_or_every) |
3294 } | 3378 { |
3295 | 3379 called = IGNORE_MULTIPLE_VALUES (called); |
3296 NUNGCPRO; | 3380 if (!CONSP (lisp_vals)) |
3297 } | 3381 { |
3298 } | 3382 /* If FUNCTION has inserted a non-cons non-nil |
3299 else if (VECTORP (sequence)) | 3383 cdr into the list before we've processed the |
3300 { | 3384 relevant part, error. */ |
3301 Lisp_Object *objs = XVECTOR_DATA (sequence); | 3385 dead_wrong_type_argument (Qconsp, lisp_vals); |
3302 Elemcount i; | 3386 } |
3303 for (i = 0; i < leni; i++) | 3387 |
3304 { | 3388 XSETCAR (lisp_vals, called); |
3305 args[1] = *objs++; | 3389 lisp_vals = XCDR (lisp_vals); |
3306 result = Ffuncall (2, args); | 3390 break; |
3307 if (vals) vals[gcpro1.nvars++] = result; | 3391 } |
3308 } | 3392 |
3309 } | 3393 if (SOME_OR_EVERY_SOME == some_or_every) |
3310 else if (STRINGP (sequence)) | 3394 { |
3311 { | 3395 if (!NILP (IGNORE_MULTIPLE_VALUES (called))) |
3312 /* The string data of `sequence' might be relocated during GC. */ | 3396 { |
3313 Bytecount slen = XSTRING_LENGTH (sequence); | 3397 XCAR (lisp_vals) = called; |
3314 Ibyte *p = alloca_ibytes (slen); | 3398 UNGCPRO; |
3315 Ibyte *end = p + slen; | 3399 return; |
3316 | 3400 } |
3317 memcpy (p, XSTRING_DATA (sequence), slen); | 3401 break; |
3318 | 3402 } |
3319 while (p < end) | 3403 |
3320 { | 3404 if (SOME_OR_EVERY_EVERY == some_or_every) |
3321 args[1] = make_char (itext_ichar (p)); | 3405 { |
3322 INC_IBYTEPTR (p); | 3406 called = IGNORE_MULTIPLE_VALUES (called); |
3323 result = Ffuncall (2, args); | 3407 if (NILP (called)) |
3324 if (vals) vals[gcpro1.nvars++] = result; | 3408 { |
3325 } | 3409 XCAR (lisp_vals) = Qnil; |
3326 } | 3410 UNGCPRO; |
3327 else if (BIT_VECTORP (sequence)) | 3411 return; |
3328 { | 3412 } |
3329 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence); | 3413 break; |
3330 Elemcount i; | 3414 } |
3331 for (i = 0; i < leni; i++) | 3415 |
3332 { | 3416 goto bad_show_or_every_flag; |
3333 args[1] = make_int (bit_vector_bit (v, i)); | 3417 } |
3334 result = Ffuncall (2, args); | 3418 case lrecord_type_vector: |
3335 if (vals) vals[gcpro1.nvars++] = result; | 3419 { |
3336 } | 3420 called = IGNORE_MULTIPLE_VALUES (called); |
3337 } | 3421 i < XVECTOR_LENGTH (lisp_vals) ? |
3338 else | 3422 (XVECTOR_DATA (lisp_vals)[i] = called) : |
3339 ABORT (); /* unreachable, since Flength (sequence) did not get an error */ | 3423 /* Let #'aset error. */ |
3340 | 3424 Faset (lisp_vals, make_int (i), called); |
3341 if (vals) | 3425 break; |
3342 UNGCPRO; | 3426 } |
3343 } | 3427 case lrecord_type_string: |
3344 | 3428 { |
3345 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /* | 3429 /* If this ever becomes a code hotspot, we can keep |
3346 Apply FUNCTION to each element of SEQUENCE, and concat the results to a string. | 3430 around pointers into the data of the string, checking |
3431 each time that it hasn't been relocated. */ | |
3432 called = IGNORE_MULTIPLE_VALUES (called); | |
3433 Faset (lisp_vals, make_int (i), called); | |
3434 break; | |
3435 } | |
3436 case lrecord_type_bit_vector: | |
3437 { | |
3438 called = IGNORE_MULTIPLE_VALUES (called); | |
3439 (BITP (called) && | |
3440 i < bit_vector_length (XBIT_VECTOR (lisp_vals))) ? | |
3441 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i, | |
3442 XINT (called)) : | |
3443 Faset (lisp_vals, make_int (i), called); | |
3444 break; | |
3445 } | |
3446 bad_show_or_every_flag: | |
3447 default: | |
3448 { | |
3449 ABORT(); | |
3450 break; | |
3451 } | |
3452 } | |
3453 } | |
3454 } | |
3455 } | |
3456 UNGCPRO; | |
3457 } | |
3458 | |
3459 DEFUN ("mapconcat", Fmapconcat, 3, MANY, 0, /* | |
3460 Call FUNCTION on each element of SEQUENCE, and concat results to a string. | |
3347 Between each pair of results, insert SEPARATOR. | 3461 Between each pair of results, insert SEPARATOR. |
3348 | 3462 |
3349 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR | 3463 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR |
3350 results in spaces between the values returned by FUNCTION. SEQUENCE itself | 3464 results in spaces between the values returned by FUNCTION. SEQUENCE itself |
3351 may be a list, a vector, a bit vector, or a string. | 3465 may be a list, a vector, a bit vector, or a string. |
3352 */ | 3466 |
3353 (function, sequence, separator)) | 3467 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3354 { | 3468 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3355 EMACS_INT len = XINT (Flength (sequence)); | 3469 from each sequence will be used each time FUNCTION is called, and |
3356 Lisp_Object *args; | 3470 `mapconcat' will give up once the shortest sequence is exhausted. |
3357 EMACS_INT i; | 3471 |
3358 EMACS_INT nargs = len + len - 1; | 3472 arguments: (FUNCTION SEQUENCE SEPARATOR &rest SEQUENCES) |
3473 */ | |
3474 (int nargs, Lisp_Object *args)) | |
3475 { | |
3476 Lisp_Object function = args[0]; | |
3477 Lisp_Object sequence = args[1]; | |
3478 Lisp_Object separator = args[2]; | |
3479 Elemcount len = EMACS_INT_MAX; | |
3480 Lisp_Object *args0; | |
3481 EMACS_INT i, nargs0; | |
3482 | |
3483 args[2] = sequence; | |
3484 args[1] = separator; | |
3485 | |
3486 for (i = 2; i < nargs; ++i) | |
3487 { | |
3488 CHECK_SEQUENCE (args[i]); | |
3489 len = min (len, XINT (Flength (args[i]))); | |
3490 } | |
3359 | 3491 |
3360 if (len == 0) return build_ascstring (""); | 3492 if (len == 0) return build_ascstring (""); |
3361 | 3493 |
3362 args = alloca_array (Lisp_Object, nargs); | 3494 nargs0 = len + len - 1; |
3363 | 3495 args0 = alloca_array (Lisp_Object, nargs0); |
3364 mapcar1 (len, args, function, sequence); | 3496 |
3497 /* Special-case this, it's very common and doesn't require any | |
3498 funcalls. Upside of doing it here, instead of cl-macs.el: no consing, | |
3499 apart from the final string, we allocate everything on the stack. */ | |
3500 if (EQ (function, Qidentity) && 3 == nargs && CONSP (sequence)) | |
3501 { | |
3502 for (i = 0; i < len; ++i) | |
3503 { | |
3504 args0[i] = XCAR (sequence); | |
3505 sequence = XCDR (sequence); | |
3506 } | |
3507 } | |
3508 else | |
3509 { | |
3510 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2, | |
3511 SOME_OR_EVERY_NEITHER); | |
3512 } | |
3365 | 3513 |
3366 for (i = len - 1; i >= 0; i--) | 3514 for (i = len - 1; i >= 0; i--) |
3367 args[i + i] = args[i]; | 3515 args0[i + i] = args0[i]; |
3368 | 3516 |
3369 for (i = 1; i < nargs; i += 2) | 3517 for (i = 1; i < nargs0; i += 2) |
3370 args[i] = separator; | 3518 args0[i] = separator; |
3371 | 3519 |
3372 return Fconcat (nargs, args); | 3520 return Fconcat (nargs0, args0); |
3373 } | 3521 } |
3374 | 3522 |
3375 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* | 3523 DEFUN ("mapcar*", FmapcarX, 2, MANY, 0, /* |
3376 Apply FUNCTION to each element of SEQUENCE; return a list of the results. | 3524 Call FUNCTION on each element of SEQUENCE; return a list of the results. |
3377 The result is a list of the same length as SEQUENCE. | 3525 The result is a list of the same length as SEQUENCE. |
3378 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3526 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3379 */ | 3527 |
3380 (function, sequence)) | 3528 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3381 { | 3529 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3382 Elemcount len = XINT (Flength (sequence)); | 3530 from each sequence will be used each time FUNCTION is called, and `mapcar' |
3383 Lisp_Object *args = alloca_array (Lisp_Object, len); | 3531 stops calling FUNCTION once the shortest sequence is exhausted. |
3384 | 3532 |
3385 mapcar1 (len, args, function, sequence); | 3533 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) |
3386 | 3534 */ |
3387 return Flist ((int) len, args); | 3535 (int nargs, Lisp_Object *args)) |
3388 } | 3536 { |
3389 | 3537 Lisp_Object function = args[0]; |
3390 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* | 3538 Elemcount len = EMACS_INT_MAX; |
3391 Apply FUNCTION to each element of SEQUENCE; return a vector of the results. | 3539 Lisp_Object *args0; |
3540 int i; | |
3541 | |
3542 for (i = 1; i < nargs; ++i) | |
3543 { | |
3544 CHECK_SEQUENCE (args[i]); | |
3545 len = min (len, XINT (Flength (args[i]))); | |
3546 } | |
3547 | |
3548 args0 = alloca_array (Lisp_Object, len); | |
3549 mapcarX (len, args0, Qnil, function, nargs - 1, args + 1, | |
3550 SOME_OR_EVERY_NEITHER); | |
3551 | |
3552 return Flist ((int) len, args0); | |
3553 } | |
3554 | |
3555 DEFUN ("mapvector", Fmapvector, 2, MANY, 0, /* | |
3556 Call FUNCTION on each element of SEQUENCE; return a vector of the results. | |
3392 The result is a vector of the same length as SEQUENCE. | 3557 The result is a vector of the same length as SEQUENCE. |
3393 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3558 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3394 */ | 3559 |
3395 (function, sequence)) | 3560 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3396 { | 3561 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3397 Elemcount len = XINT (Flength (sequence)); | 3562 from each sequence will be used each time FUNCTION is called, and |
3398 Lisp_Object result = make_vector (len, Qnil); | 3563 `mapvector' stops calling FUNCTION once the shortest sequence is exhausted. |
3564 | |
3565 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) | |
3566 */ | |
3567 (int nargs, Lisp_Object *args)) | |
3568 { | |
3569 Lisp_Object function = args[0]; | |
3570 Elemcount len = EMACS_INT_MAX; | |
3571 Lisp_Object result; | |
3399 struct gcpro gcpro1; | 3572 struct gcpro gcpro1; |
3400 | 3573 int i; |
3574 | |
3575 for (i = 1; i < nargs; ++i) | |
3576 { | |
3577 CHECK_SEQUENCE (args[i]); | |
3578 len = min (len, XINT (Flength (args[i]))); | |
3579 } | |
3580 | |
3581 result = make_vector (len, Qnil); | |
3401 GCPRO1 (result); | 3582 GCPRO1 (result); |
3402 mapcar1 (len, XVECTOR_DATA (result), function, sequence); | 3583 /* Don't pass result as the lisp_object argument, we want mapcarX to protect |
3584 a single list argument's elements from being garbage-collected. */ | |
3585 mapcarX (len, XVECTOR_DATA (result), Qnil, function, nargs - 1, args +1, | |
3586 SOME_OR_EVERY_NEITHER); | |
3403 UNGCPRO; | 3587 UNGCPRO; |
3404 | 3588 |
3405 return result; | 3589 return result; |
3406 } | 3590 } |
3407 | 3591 |
3408 DEFUN ("mapc-internal", Fmapc_internal, 2, 2, 0, /* | 3592 DEFUN ("mapcan", Fmapcan, 2, MANY, 0, /* |
3409 Apply FUNCTION to each element of SEQUENCE. | 3593 Call FUNCTION on each element of SEQUENCE; chain the results together. |
3594 | |
3595 FUNCTION must normally return a list; the results will be concatenated | |
3596 together using `nconc'. | |
3597 | |
3598 With optional SEQUENCES, call FUNCTION each time with as many arguments as | |
3599 there are SEQUENCES, plus one for the element from SEQUENCE. One element | |
3600 from each sequence will be used each time FUNCTION is called, and | |
3601 `mapcan' stops calling FUNCTION once the shortest sequence is exhausted. | |
3602 | |
3603 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) | |
3604 */ | |
3605 (int nargs, Lisp_Object *args)) | |
3606 { | |
3607 Lisp_Object function = args[0], nconcing; | |
3608 Elemcount len = EMACS_INT_MAX; | |
3609 Lisp_Object *args0; | |
3610 struct gcpro gcpro1; | |
3611 int i; | |
3612 | |
3613 for (i = 1; i < nargs; ++i) | |
3614 { | |
3615 CHECK_SEQUENCE (args[i]); | |
3616 len = min (len, XINT (Flength (args[i]))); | |
3617 } | |
3618 | |
3619 args0 = alloca_array (Lisp_Object, len + 1); | |
3620 mapcarX (len, args0 + 1, Qnil, function, nargs - 1, args + 1, | |
3621 SOME_OR_EVERY_NEITHER); | |
3622 | |
3623 if (len < 2) | |
3624 { | |
3625 return len ? args0[1] : Qnil; | |
3626 } | |
3627 | |
3628 /* bytecode_nconc2 can signal and return, we need to GCPRO the args, since | |
3629 mapcarX is no longer doing this for us. */ | |
3630 args0[0] = Fcons (Qnil, Qnil); | |
3631 GCPRO1 (args0[0]); | |
3632 gcpro1.nvars = len + 1; | |
3633 | |
3634 for (i = 0; i < len; ++i) | |
3635 { | |
3636 nconcing = bytecode_nconc2 (args0 + i); | |
3637 args0[i + 1] = nconcing; | |
3638 } | |
3639 | |
3640 RETURN_UNGCPRO (XCDR (nconcing)); | |
3641 } | |
3642 | |
3643 DEFUN ("mapc", Fmapc, 2, MANY, 0, /* | |
3644 Call FUNCTION on each element of SEQUENCE. | |
3645 | |
3410 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3646 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3411 This function is like `mapcar' but does not accumulate the results, | 3647 This function is like `mapcar' but does not accumulate the results, |
3412 which is more efficient if you do not use the results. | 3648 which is more efficient if you do not use the results. |
3413 | 3649 |
3414 The difference between this and `mapc' is that `mapc' supports all | 3650 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3415 the spiffy Common Lisp arguments. You should normally use `mapc'. | 3651 there are SEQUENCES, plus one for the elements from SEQUENCE. One element |
3416 */ | 3652 from each sequence will be used each time FUNCTION is called, and |
3417 (function, sequence)) | 3653 `mapc' stops calling FUNCTION once the shortest sequence is exhausted. |
3418 { | 3654 |
3419 mapcar1 (XINT (Flength (sequence)), 0, function, sequence); | 3655 Return SEQUENCE. |
3420 | 3656 |
3421 return sequence; | 3657 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) |
3422 } | 3658 */ |
3423 | 3659 (int nargs, Lisp_Object *args)) |
3660 { | |
3661 Elemcount len = EMACS_INT_MAX; | |
3662 Lisp_Object sequence = args[1]; | |
3663 struct gcpro gcpro1; | |
3664 int i; | |
3665 | |
3666 for (i = 1; i < nargs; ++i) | |
3667 { | |
3668 CHECK_SEQUENCE (args[i]); | |
3669 len = min (len, XINT (Flength (args[i]))); | |
3670 } | |
3671 | |
3672 /* We need to GCPRO sequence, because mapcarX will modify the | |
3673 elements of the args array handed to it, and this may involve | |
3674 elements of sequence getting garbage collected. */ | |
3675 GCPRO1 (sequence); | |
3676 mapcarX (len, NULL, Qnil, args[0], nargs - 1, args + 1, | |
3677 SOME_OR_EVERY_NEITHER); | |
3678 RETURN_UNGCPRO (sequence); | |
3679 } | |
3680 | |
3681 DEFUN ("map", Fmap, 3, MANY, 0, /* | |
3682 Map FUNCTION across one or more sequences, returning a sequence. | |
3683 | |
3684 TYPE is the sequence type to return, FUNCTION is the function, SEQUENCE is | |
3685 the first argument sequence, SEQUENCES are the other argument sequences. | |
3686 | |
3687 FUNCTION will be called with (1+ (length SEQUENCES)) arguments, and must be | |
3688 capable of accepting this number of arguments. | |
3689 | |
3690 Certain TYPEs are recognised internally by `map', but others are not, and | |
3691 `coerce' may throw an error on an attempt to convert to a TYPE it does not | |
3692 understand. A null TYPE means do not accumulate any values. | |
3693 | |
3694 arguments: (TYPE FUNCTION SEQUENCE &rest SEQUENCES) | |
3695 */ | |
3696 (int nargs, Lisp_Object *args)) | |
3697 { | |
3698 Lisp_Object type = args[0]; | |
3699 Lisp_Object function = args[1]; | |
3700 Lisp_Object result = Qnil; | |
3701 Lisp_Object *args0 = NULL; | |
3702 Elemcount len = EMACS_INT_MAX; | |
3703 int i; | |
3704 struct gcpro gcpro1; | |
3705 | |
3706 for (i = 2; i < nargs; ++i) | |
3707 { | |
3708 CHECK_SEQUENCE (args[i]); | |
3709 len = min (len, XINT (Flength (args[i]))); | |
3710 } | |
3711 | |
3712 if (!NILP (type)) | |
3713 { | |
3714 args0 = alloca_array (Lisp_Object, len); | |
3715 } | |
3716 | |
3717 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2, | |
3718 SOME_OR_EVERY_NEITHER); | |
3719 | |
3720 if (EQ (type, Qnil)) | |
3721 { | |
3722 return result; | |
3723 } | |
3724 | |
3725 if (EQ (type, Qvector) || EQ (type, Qarray)) | |
3726 { | |
3727 result = Fvector (len, args0); | |
3728 } | |
3729 else if (EQ (type, Qstring)) | |
3730 { | |
3731 result = Fstring (len, args0); | |
3732 } | |
3733 else if (EQ (type, Qlist)) | |
3734 { | |
3735 result = Flist (len, args0); | |
3736 } | |
3737 else if (EQ (type, Qbit_vector)) | |
3738 { | |
3739 result = Fbit_vector (len, args0); | |
3740 } | |
3741 else | |
3742 { | |
3743 result = Flist (len, args0); | |
3744 GCPRO1 (result); | |
3745 result = call2 (Qcoerce, result, type); | |
3746 UNGCPRO; | |
3747 } | |
3748 | |
3749 return result; | |
3750 } | |
3751 | |
3752 DEFUN ("map-into", Fmap_into, 2, MANY, 0, /* | |
3753 Modify RESULT-SEQUENCE using the return values of FUNCTION on SEQUENCES. | |
3754 | |
3755 RESULT-SEQUENCE and SEQUENCES can be lists or arrays. | |
3756 | |
3757 FUNCTION must accept at least as many arguments as there are SEQUENCES | |
3758 \(possibly zero). If RESULT-SEQUENCE and the elements of SEQUENCES are not | |
3759 the same length, stop when the shortest is exhausted; any elements of | |
3760 RESULT-SEQUENCE beyond that are unmodified. | |
3761 | |
3762 Return RESULT-SEQUENCE. | |
3763 | |
3764 arguments: (RESULT-SEQUENCE FUNCTION &rest SEQUENCES) | |
3765 */ | |
3766 (int nargs, Lisp_Object *args)) | |
3767 { | |
3768 Elemcount len = EMACS_INT_MAX; | |
3769 Lisp_Object result_sequence = args[0]; | |
3770 Lisp_Object function = args[1]; | |
3771 int i; | |
3772 | |
3773 args[0] = function; | |
3774 args[1] = result_sequence; | |
3775 | |
3776 for (i = 1; i < nargs; ++i) | |
3777 { | |
3778 CHECK_SEQUENCE (args[i]); | |
3779 len = min (len, XINT (Flength (args[i]))); | |
3780 } | |
3781 | |
3782 mapcarX (len, NULL, result_sequence, function, nargs - 2, args + 2, | |
3783 SOME_OR_EVERY_NEITHER); | |
3784 | |
3785 return result_sequence; | |
3786 } | |
3787 | |
3788 DEFUN ("some", Fsome, 2, MANY, 0, /* | |
3789 Return true if PREDICATE gives non-nil for an element of SEQUENCE. | |
3790 | |
3791 If so, return the value (possibly multiple) given by PREDICATE. | |
3792 | |
3793 With optional SEQUENCES, call PREDICATE each time with as many arguments as | |
3794 there are SEQUENCES (plus one for the element from SEQUENCE). | |
3795 | |
3796 arguments: (PREDICATE SEQUENCE &rest SEQUENCES) | |
3797 */ | |
3798 (int nargs, Lisp_Object *args)) | |
3799 { | |
3800 Lisp_Object result_box = Fcons (Qnil, Qnil); | |
3801 struct gcpro gcpro1; | |
3802 Elemcount len = EMACS_INT_MAX; | |
3803 int i; | |
3804 | |
3805 GCPRO1 (result_box); | |
3806 | |
3807 for (i = 1; i < nargs; ++i) | |
3808 { | |
3809 CHECK_SEQUENCE (args[i]); | |
3810 len = min (len, XINT (Flength (args[i]))); | |
3811 } | |
3812 | |
3813 mapcarX (len, NULL, result_box, args[0], nargs - 1, args +1, | |
3814 SOME_OR_EVERY_SOME); | |
3815 | |
3816 RETURN_UNGCPRO (XCAR (result_box)); | |
3817 } | |
3818 | |
3819 DEFUN ("every", Fevery, 2, MANY, 0, /* | |
3820 Return true if PREDICATE is true of every element of SEQUENCE. | |
3821 | |
3822 With optional SEQUENCES, call PREDICATE each time with as many arguments as | |
3823 there are SEQUENCES (plus one for the element from SEQUENCE). | |
3824 | |
3825 In contrast to `some', `every' never returns multiple values. | |
3826 | |
3827 arguments: (PREDICATE SEQUENCE &rest SEQUENCES) | |
3828 */ | |
3829 (int nargs, Lisp_Object *args)) | |
3830 { | |
3831 Lisp_Object result_box = Fcons (Qt, Qnil); | |
3832 struct gcpro gcpro1; | |
3833 Elemcount len = EMACS_INT_MAX; | |
3834 int i; | |
3835 | |
3836 GCPRO1 (result_box); | |
3837 | |
3838 for (i = 1; i < nargs; ++i) | |
3839 { | |
3840 CHECK_SEQUENCE (args[i]); | |
3841 len = min (len, XINT (Flength (args[i]))); | |
3842 } | |
3843 | |
3844 mapcarX (len, NULL, result_box, args[0], nargs - 1, args +1, | |
3845 SOME_OR_EVERY_EVERY); | |
3846 | |
3847 RETURN_UNGCPRO (XCAR (result_box)); | |
3848 } | |
3849 | |
3850 /* Call FUNCTION with NLISTS arguments repeatedly, each Nth argument | |
3851 corresponding to the result of calling (nthcdr ITERATION-COUNT LISTS[N]), | |
3852 until that #'nthcdr expression gives nil for some element of LISTS. | |
3853 | |
3854 If MAPLP is zero, return LISTS[0]. Otherwise, return a list of the return | |
3855 values from FUNCTION; if NCONCP is non-zero, nconc them together. | |
3856 | |
3857 In contrast to mapcarX, we don't require our callers to check LISTS for | |
3858 well-formedness, we signal wrong-type-argument if it's not a list, or | |
3859 circular-list if it's circular. */ | |
3860 | |
3861 static Lisp_Object | |
3862 maplist (Lisp_Object function, int nlists, Lisp_Object *lists, int maplp, | |
3863 int nconcp) | |
3864 { | |
3865 Lisp_Object result = maplp ? lists[0] : Fcons (Qnil, Qnil), funcalled; | |
3866 Lisp_Object nconcing[2], accum = result, *args; | |
3867 struct gcpro gcpro1, gcpro2, gcpro3; | |
3868 int i, j, continuing = (nlists > 0), called_count = 0; | |
3869 | |
3870 args = alloca_array (Lisp_Object, nlists + 1); | |
3871 args[0] = function; | |
3872 for (i = 1; i <= nlists; ++i) | |
3873 { | |
3874 args[i] = Qnil; | |
3875 } | |
3876 | |
3877 if (nconcp) | |
3878 { | |
3879 nconcing[0] = result; | |
3880 nconcing[1] = Qnil; | |
3881 GCPRO3 (args[0], nconcing[0], result); | |
3882 gcpro1.nvars = 1; | |
3883 gcpro2.nvars = 2; | |
3884 } | |
3885 else | |
3886 { | |
3887 GCPRO2 (args[0], result); | |
3888 gcpro1.nvars = 1; | |
3889 } | |
3890 | |
3891 while (continuing) | |
3892 { | |
3893 for (j = 0; j < nlists; ++j) | |
3894 { | |
3895 if (CONSP (lists[j])) | |
3896 { | |
3897 args[j + 1] = lists[j]; | |
3898 lists[j] = XCDR (lists[j]); | |
3899 } | |
3900 else if (NILP (lists[j])) | |
3901 { | |
3902 continuing = 0; | |
3903 break; | |
3904 } | |
3905 else | |
3906 { | |
3907 dead_wrong_type_argument (Qlistp, lists[j]); | |
3908 } | |
3909 } | |
3910 if (!continuing) break; | |
3911 funcalled = IGNORE_MULTIPLE_VALUES (Ffuncall (nlists + 1, args)); | |
3912 if (!maplp) | |
3913 { | |
3914 if (nconcp) | |
3915 { | |
3916 /* This order of calls means we check that each list is | |
3917 well-formed once and once only. The last result does | |
3918 not have to be a list. */ | |
3919 nconcing[1] = funcalled; | |
3920 nconcing[0] = bytecode_nconc2 (nconcing); | |
3921 } | |
3922 else | |
3923 { | |
3924 /* Add to the end, avoiding the need to call nreverse | |
3925 once we're done: */ | |
3926 XSETCDR (accum, Fcons (funcalled, Qnil)); | |
3927 accum = XCDR (accum); | |
3928 } | |
3929 } | |
3930 | |
3931 if (++called_count % CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
3932 | |
3933 for (j = 0; j < nlists; ++j) | |
3934 { | |
3935 EXTERNAL_LIST_LOOP_1 (lists[j]) | |
3936 { | |
3937 /* Just check the lists aren't circular, using the | |
3938 EXTERNAL_LIST_LOOP_1 macro. */ | |
3939 } | |
3940 } | |
3941 } | |
3942 | |
3943 if (!maplp) | |
3944 { | |
3945 result = XCDR (result); | |
3946 } | |
3947 | |
3948 RETURN_UNGCPRO (result); | |
3949 } | |
3950 | |
3951 DEFUN ("maplist", Fmaplist, 2, MANY, 0, /* | |
3952 Call FUNCTION on each sublist of LIST and LISTS. | |
3953 Like `mapcar', except applies to lists and their cdr's rather than to | |
3954 the elements themselves." | |
3955 | |
3956 arguments: (FUNCTION LIST &rest LISTS) | |
3957 */ | |
3958 (int nargs, Lisp_Object *args)) | |
3959 { | |
3960 return maplist (args[0], nargs - 1, args + 1, 0, 0); | |
3961 } | |
3962 | |
3963 DEFUN ("mapl", Fmapl, 2, MANY, 0, /* | |
3964 Like `maplist', but do not accumulate values returned by the function. | |
3965 | |
3966 arguments: (FUNCTION LIST &rest LISTS) | |
3967 */ | |
3968 (int nargs, Lisp_Object *args)) | |
3969 { | |
3970 return maplist (args[0], nargs - 1, args + 1, 1, 0); | |
3971 } | |
3972 | |
3973 DEFUN ("mapcon", Fmapcon, 2, MANY, 0, /* | |
3974 Like `maplist', but chains together the values returned by FUNCTION. | |
3975 | |
3976 FUNCTION must return a list (unless it happens to be the last | |
3977 iteration); the results will be concatenated together using `nconc'. | |
3978 | |
3979 arguments: (FUNCTION LIST &rest LISTS) | |
3980 */ | |
3981 (int nargs, Lisp_Object *args)) | |
3982 { | |
3983 return maplist (args[0], nargs - 1, args + 1, 0, 1); | |
3984 } | |
3424 | 3985 |
3425 /* Extra random functions */ | 3986 /* Extra random functions */ |
3426 | 3987 |
3427 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* | 3988 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* |
3428 Destructively replace the list OLD with NEW. | 3989 Destructively replace the list OLD with NEW. |
3462 old = Qnil; | 4023 old = Qnil; |
3463 | 4024 |
3464 return old; | 4025 return old; |
3465 } | 4026 } |
3466 | 4027 |
4028 | |
3467 Lisp_Object | 4029 Lisp_Object |
3468 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) | 4030 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) |
3469 { | 4031 { |
3470 return Fintern (concat2 (Fsymbol_name (symbol), | 4032 return Fintern (concat2 (Fsymbol_name (symbol), |
3471 build_ascstring (ascii_string)), | 4033 build_ascstring (ascii_string)), |
4100 { | 4662 { |
4101 INIT_LRECORD_IMPLEMENTATION (bit_vector); | 4663 INIT_LRECORD_IMPLEMENTATION (bit_vector); |
4102 | 4664 |
4103 DEFSYMBOL (Qstring_lessp); | 4665 DEFSYMBOL (Qstring_lessp); |
4104 DEFSYMBOL (Qidentity); | 4666 DEFSYMBOL (Qidentity); |
4667 DEFSYMBOL (Qvector); | |
4668 DEFSYMBOL (Qarray); | |
4669 DEFSYMBOL (Qstring); | |
4670 DEFSYMBOL (Qlist); | |
4671 DEFSYMBOL (Qbit_vector); | |
4672 | |
4105 DEFSYMBOL (Qyes_or_no_p); | 4673 DEFSYMBOL (Qyes_or_no_p); |
4106 | 4674 |
4107 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); | 4675 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); |
4108 | 4676 |
4109 DEFSUBR (Fidentity); | 4677 DEFSUBR (Fidentity); |
4177 DEFSUBR (Fequal); | 4745 DEFSUBR (Fequal); |
4178 DEFSUBR (Fequalp); | 4746 DEFSUBR (Fequalp); |
4179 DEFSUBR (Fold_equal); | 4747 DEFSUBR (Fold_equal); |
4180 DEFSUBR (Ffillarray); | 4748 DEFSUBR (Ffillarray); |
4181 DEFSUBR (Fnconc); | 4749 DEFSUBR (Fnconc); |
4182 DEFSUBR (Fmapcar); | 4750 DEFSUBR (FmapcarX); |
4183 DEFSUBR (Fmapvector); | 4751 DEFSUBR (Fmapvector); |
4184 DEFSUBR (Fmapc_internal); | 4752 DEFSUBR (Fmapcan); |
4753 DEFSUBR (Fmapc); | |
4185 DEFSUBR (Fmapconcat); | 4754 DEFSUBR (Fmapconcat); |
4755 DEFSUBR (Fmap); | |
4756 DEFSUBR (Fmap_into); | |
4757 DEFSUBR (Fsome); | |
4758 DEFSUBR (Fevery); | |
4759 Ffset (intern ("mapc-internal"), Fsymbol_function (intern ("mapc"))); | |
4760 Ffset (intern ("mapcar"), Fsymbol_function (intern ("mapcar*"))); | |
4761 DEFSUBR (Fmaplist); | |
4762 DEFSUBR (Fmapl); | |
4763 DEFSUBR (Fmapcon); | |
4764 | |
4186 DEFSUBR (Freplace_list); | 4765 DEFSUBR (Freplace_list); |
4187 DEFSUBR (Fload_average); | 4766 DEFSUBR (Fload_average); |
4188 DEFSUBR (Ffeaturep); | 4767 DEFSUBR (Ffeaturep); |
4189 DEFSUBR (Frequire); | 4768 DEFSUBR (Frequire); |
4190 DEFSUBR (Fprovide); | 4769 DEFSUBR (Fprovide); |