Mercurial > hg > xemacs-beta
comparison src/fns.c @ 4996:c17c857e20bf
Merge.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Wed, 03 Feb 2010 20:18:53 +0000 |
parents | 6bc1f3f6cf0d 8431b52e43b1 |
children | 8800b5350a13 |
comparison
equal
deleted
inserted
replaced
4927:5274591ce707 | 4996:c17c857e20bf |
---|---|
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. */ | |
3231 | 3246 |
3232 static void | 3247 static void |
3233 mapcar1 (Elemcount leni, Lisp_Object *vals, | 3248 mapcarX (Elemcount call_count, Lisp_Object *vals, Lisp_Object lisp_vals, |
3234 Lisp_Object function, Lisp_Object sequence) | 3249 Lisp_Object function, int nsequences, Lisp_Object *sequences) |
3235 { | 3250 { |
3236 Lisp_Object result; | 3251 Lisp_Object called, *args; |
3237 Lisp_Object args[2]; | 3252 struct gcpro gcpro1, gcpro2; |
3238 struct gcpro gcpro1; | 3253 int i, j; |
3239 | 3254 enum lrecord_type lisp_vals_type; |
3240 if (vals) | 3255 |
3241 { | 3256 assert (LRECORDP (lisp_vals)); |
3242 GCPRO1 (vals[0]); | 3257 lisp_vals_type = XRECORD_LHEADER (lisp_vals)->type; |
3243 gcpro1.nvars = 0; | 3258 |
3244 } | 3259 args = alloca_array (Lisp_Object, nsequences + 1); |
3245 | |
3246 args[0] = function; | 3260 args[0] = function; |
3247 | 3261 for (i = 1; i <= nsequences; ++i) |
3248 if (LISTP (sequence)) | 3262 { |
3249 { | 3263 args[i] = Qnil; |
3250 /* A devious `function' could either: | 3264 } |
3251 - insert garbage into the list in front of us, causing XCDR to crash | 3265 |
3252 - amputate the list behind us using (setcdr), causing the remaining | 3266 if (vals != NULL) |
3253 elts to lose their GCPRO status. | 3267 { |
3254 | 3268 GCPRO2 (args[0], vals[0]); |
3255 if (vals != 0) we avoid this by copying the elts into the | 3269 gcpro1.nvars = nsequences + 1; |
3256 `vals' array. By a stroke of luck, `vals' is exactly large | 3270 gcpro2.nvars = 0; |
3257 enough to hold the elts left to be traversed as well as the | 3271 } |
3258 results computed so far. | 3272 else |
3259 | 3273 { |
3260 if (vals == 0) we don't have any free space available and | 3274 GCPRO1 (args[0]); |
3261 don't want to eat up any more stack with ALLOCA (). | 3275 gcpro1.nvars = nsequences + 1; |
3262 So we use EXTERNAL_LIST_LOOP_3_NO_DECLARE and GCPRO the tail. */ | 3276 } |
3263 | 3277 |
3264 if (vals) | 3278 /* Be extra nice in the event that we've been handed one list and one |
3265 { | 3279 only; make it possible for FUNCTION to set cdrs not yet processed to |
3266 Lisp_Object *val = vals; | 3280 non-cons, non-nil objects without ill-effect, if we have been handed |
3267 Elemcount i; | 3281 the stack space to do that. */ |
3268 | 3282 if (vals != NULL && 1 == nsequences && CONSP (sequences[0])) |
3269 LIST_LOOP_2 (elt, sequence) | 3283 { |
3270 *val++ = elt; | 3284 Lisp_Object lst = sequences[0]; |
3271 | 3285 Lisp_Object *val = vals; |
3272 gcpro1.nvars = leni; | 3286 for (i = 0; i < call_count; ++i) |
3273 | 3287 { |
3274 for (i = 0; i < leni; i++) | 3288 *val++ = XCAR (lst); |
3289 lst = XCDR (lst); | |
3290 } | |
3291 gcpro2.nvars = call_count; | |
3292 | |
3293 for (i = 0; i < call_count; ++i) | |
3294 { | |
3295 args[1] = vals[i]; | |
3296 vals[i] = Ffuncall (nsequences + 1, args); | |
3297 } | |
3298 } | |
3299 else | |
3300 { | |
3301 Binbyte *sequence_types = alloca_array (Binbyte, nsequences); | |
3302 for (j = 0; j < nsequences; ++j) | |
3303 { | |
3304 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type; | |
3305 } | |
3306 | |
3307 for (i = 0; i < call_count; ++i) | |
3308 { | |
3309 for (j = 0; j < nsequences; ++j) | |
3275 { | 3310 { |
3276 args[1] = vals[i]; | 3311 switch (sequence_types[j]) |
3277 vals[i] = Ffuncall (2, args); | 3312 { |
3313 case lrecord_type_cons: | |
3314 { | |
3315 if (!CONSP (sequences[j])) | |
3316 { | |
3317 /* This means FUNCTION has probably messed | |
3318 around with a cons in one of the sequences, | |
3319 since we checked the type | |
3320 (CHECK_SEQUENCE()) and the length and | |
3321 structure (with Flength()) correctly in our | |
3322 callers. */ | |
3323 dead_wrong_type_argument (Qconsp, sequences[j]); | |
3324 } | |
3325 args[j + 1] = XCAR (sequences[j]); | |
3326 sequences[j] = XCDR (sequences[j]); | |
3327 break; | |
3328 } | |
3329 case lrecord_type_vector: | |
3330 { | |
3331 args[j + 1] = XVECTOR_DATA (sequences[j])[i]; | |
3332 break; | |
3333 } | |
3334 case lrecord_type_string: | |
3335 { | |
3336 args[j + 1] = make_char (string_ichar (sequences[j], i)); | |
3337 break; | |
3338 } | |
3339 case lrecord_type_bit_vector: | |
3340 { | |
3341 args[j + 1] | |
3342 = make_int (bit_vector_bit (XBIT_VECTOR (sequences[j]), | |
3343 i)); | |
3344 break; | |
3345 } | |
3346 default: | |
3347 ABORT(); | |
3348 } | |
3278 } | 3349 } |
3279 } | 3350 called = Ffuncall (nsequences + 1, args); |
3280 else | 3351 if (vals != NULL) |
3281 { | 3352 { |
3282 Lisp_Object elt, tail; | 3353 vals[i] = called; |
3283 EMACS_INT len_unused; | 3354 gcpro2.nvars += 1; |
3284 struct gcpro ngcpro1; | 3355 } |
3285 | 3356 else |
3286 NGCPRO1 (tail); | 3357 { |
3287 | 3358 switch (lisp_vals_type) |
3288 { | 3359 { |
3289 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len_unused) | 3360 case lrecord_type_symbol: |
3290 { | 3361 break; |
3291 args[1] = elt; | 3362 case lrecord_type_cons: |
3292 Ffuncall (2, args); | 3363 { |
3293 } | 3364 if (!CONSP (lisp_vals)) |
3294 } | 3365 { |
3295 | 3366 /* If FUNCTION has inserted a non-cons non-nil cdr |
3296 NUNGCPRO; | 3367 into the list before we've processed the relevant |
3297 } | 3368 part, error. */ |
3298 } | 3369 dead_wrong_type_argument (Qconsp, lisp_vals); |
3299 else if (VECTORP (sequence)) | 3370 } |
3300 { | 3371 |
3301 Lisp_Object *objs = XVECTOR_DATA (sequence); | 3372 XSETCAR (lisp_vals, called); |
3302 Elemcount i; | 3373 lisp_vals = XCDR (lisp_vals); |
3303 for (i = 0; i < leni; i++) | 3374 break; |
3304 { | 3375 } |
3305 args[1] = *objs++; | 3376 case lrecord_type_vector: |
3306 result = Ffuncall (2, args); | 3377 { |
3307 if (vals) vals[gcpro1.nvars++] = result; | 3378 i < XVECTOR_LENGTH (lisp_vals) ? |
3308 } | 3379 (XVECTOR_DATA (lisp_vals)[i] = called) : |
3309 } | 3380 /* Let #'aset error. */ |
3310 else if (STRINGP (sequence)) | 3381 Faset (lisp_vals, make_int (i), called); |
3311 { | 3382 break; |
3312 /* The string data of `sequence' might be relocated during GC. */ | 3383 } |
3313 Bytecount slen = XSTRING_LENGTH (sequence); | 3384 case lrecord_type_string: |
3314 Ibyte *p = alloca_ibytes (slen); | 3385 { |
3315 Ibyte *end = p + slen; | 3386 /* If this ever becomes a code hotspot, we can keep |
3316 | 3387 around pointers into the data of the string, checking |
3317 memcpy (p, XSTRING_DATA (sequence), slen); | 3388 each time that it hasn't been relocated. */ |
3318 | 3389 Faset (lisp_vals, make_int (i), called); |
3319 while (p < end) | 3390 break; |
3320 { | 3391 } |
3321 args[1] = make_char (itext_ichar (p)); | 3392 case lrecord_type_bit_vector: |
3322 INC_IBYTEPTR (p); | 3393 { |
3323 result = Ffuncall (2, args); | 3394 (BITP (called) && |
3324 if (vals) vals[gcpro1.nvars++] = result; | 3395 i < bit_vector_length (XBIT_VECTOR (lisp_vals))) ? |
3325 } | 3396 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i, |
3326 } | 3397 XINT (called)) : |
3327 else if (BIT_VECTORP (sequence)) | 3398 Faset (lisp_vals, make_int (i), called); |
3328 { | 3399 break; |
3329 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence); | 3400 } |
3330 Elemcount i; | 3401 default: |
3331 for (i = 0; i < leni; i++) | 3402 { |
3332 { | 3403 ABORT(); |
3333 args[1] = make_int (bit_vector_bit (v, i)); | 3404 break; |
3334 result = Ffuncall (2, args); | 3405 } |
3335 if (vals) vals[gcpro1.nvars++] = result; | 3406 } |
3336 } | 3407 } |
3337 } | 3408 } |
3338 else | 3409 } |
3339 ABORT (); /* unreachable, since Flength (sequence) did not get an error */ | 3410 UNGCPRO; |
3340 | 3411 } |
3341 if (vals) | 3412 |
3342 UNGCPRO; | 3413 DEFUN ("mapconcat", Fmapconcat, 3, MANY, 0, /* |
3343 } | 3414 Call FUNCTION on each element of SEQUENCE, and concat results to a string. |
3344 | |
3345 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /* | |
3346 Apply FUNCTION to each element of SEQUENCE, and concat the results to a string. | |
3347 Between each pair of results, insert SEPARATOR. | 3415 Between each pair of results, insert SEPARATOR. |
3348 | 3416 |
3349 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR | 3417 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR |
3350 results in spaces between the values returned by FUNCTION. SEQUENCE itself | 3418 results in spaces between the values returned by FUNCTION. SEQUENCE itself |
3351 may be a list, a vector, a bit vector, or a string. | 3419 may be a list, a vector, a bit vector, or a string. |
3352 */ | 3420 |
3353 (function, sequence, separator)) | 3421 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3354 { | 3422 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3355 EMACS_INT len = XINT (Flength (sequence)); | 3423 from each sequence will be used each time FUNCTION is called, and |
3356 Lisp_Object *args; | 3424 `mapconcat' will give up once the shortest sequence is exhausted. |
3357 EMACS_INT i; | 3425 |
3358 EMACS_INT nargs = len + len - 1; | 3426 arguments: (FUNCTION SEQUENCE SEPARATOR &rest SEQUENCES) |
3427 */ | |
3428 (int nargs, Lisp_Object *args)) | |
3429 { | |
3430 Lisp_Object function = args[0]; | |
3431 Lisp_Object sequence = args[1]; | |
3432 Lisp_Object separator = args[2]; | |
3433 Elemcount len = EMACS_INT_MAX; | |
3434 Lisp_Object *args0; | |
3435 EMACS_INT i, nargs0; | |
3436 | |
3437 args[2] = sequence; | |
3438 args[1] = separator; | |
3439 | |
3440 for (i = 2; i < nargs; ++i) | |
3441 { | |
3442 CHECK_SEQUENCE (args[i]); | |
3443 len = min (len, XINT (Flength (args[i]))); | |
3444 } | |
3359 | 3445 |
3360 if (len == 0) return build_string (""); | 3446 if (len == 0) return build_string (""); |
3361 | 3447 |
3362 args = alloca_array (Lisp_Object, nargs); | 3448 nargs0 = len + len - 1; |
3363 | 3449 args0 = alloca_array (Lisp_Object, nargs0); |
3364 mapcar1 (len, args, function, sequence); | 3450 |
3451 /* Special-case this, it's very common and doesn't require any | |
3452 funcalls. Upside of doing it here, instead of cl-macs.el: no consing, | |
3453 apart from the final string, we allocate everything on the stack. */ | |
3454 if (EQ (function, Qidentity) && 3 == nargs && CONSP (sequence)) | |
3455 { | |
3456 for (i = 0; i < len; ++i) | |
3457 { | |
3458 args0[i] = XCAR (sequence); | |
3459 sequence = XCDR (sequence); | |
3460 } | |
3461 } | |
3462 else | |
3463 { | |
3464 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2); | |
3465 } | |
3365 | 3466 |
3366 for (i = len - 1; i >= 0; i--) | 3467 for (i = len - 1; i >= 0; i--) |
3367 args[i + i] = args[i]; | 3468 args0[i + i] = args0[i]; |
3368 | 3469 |
3369 for (i = 1; i < nargs; i += 2) | 3470 for (i = 1; i < nargs0; i += 2) |
3370 args[i] = separator; | 3471 args0[i] = separator; |
3371 | 3472 |
3372 return Fconcat (nargs, args); | 3473 return Fconcat (nargs0, args0); |
3373 } | 3474 } |
3374 | 3475 |
3375 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* | 3476 DEFUN ("mapcar*", FmapcarX, 2, MANY, 0, /* |
3376 Apply FUNCTION to each element of SEQUENCE; return a list of the results. | 3477 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. | 3478 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. | 3479 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3379 */ | 3480 |
3380 (function, sequence)) | 3481 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3381 { | 3482 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3382 Elemcount len = XINT (Flength (sequence)); | 3483 from each sequence will be used each time FUNCTION is called, and `mapcar' |
3383 Lisp_Object *args = alloca_array (Lisp_Object, len); | 3484 stops calling FUNCTION once the shortest sequence is exhausted. |
3384 | 3485 |
3385 mapcar1 (len, args, function, sequence); | 3486 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) |
3386 | 3487 */ |
3387 return Flist ((int) len, args); | 3488 (int nargs, Lisp_Object *args)) |
3388 } | 3489 { |
3389 | 3490 Lisp_Object function = args[0]; |
3390 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* | 3491 Elemcount len = EMACS_INT_MAX; |
3391 Apply FUNCTION to each element of SEQUENCE; return a vector of the results. | 3492 Lisp_Object *args0; |
3493 int i; | |
3494 | |
3495 for (i = 1; i < nargs; ++i) | |
3496 { | |
3497 CHECK_SEQUENCE (args[i]); | |
3498 len = min (len, XINT (Flength (args[i]))); | |
3499 } | |
3500 | |
3501 args0 = alloca_array (Lisp_Object, len); | |
3502 mapcarX (len, args0, Qnil, function, nargs - 1, args + 1); | |
3503 | |
3504 return Flist ((int) len, args0); | |
3505 } | |
3506 | |
3507 DEFUN ("mapvector", Fmapvector, 2, MANY, 0, /* | |
3508 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. | 3509 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. | 3510 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3394 */ | 3511 |
3395 (function, sequence)) | 3512 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3396 { | 3513 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3397 Elemcount len = XINT (Flength (sequence)); | 3514 from each sequence will be used each time FUNCTION is called, and |
3398 Lisp_Object result = make_vector (len, Qnil); | 3515 `mapvector' stops calling FUNCTION once the shortest sequence is exhausted. |
3516 | |
3517 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) | |
3518 */ | |
3519 (int nargs, Lisp_Object *args)) | |
3520 { | |
3521 Lisp_Object function = args[0]; | |
3522 Elemcount len = EMACS_INT_MAX; | |
3523 Lisp_Object result; | |
3399 struct gcpro gcpro1; | 3524 struct gcpro gcpro1; |
3400 | 3525 int i; |
3526 | |
3527 for (i = 1; i < nargs; ++i) | |
3528 { | |
3529 CHECK_SEQUENCE (args[i]); | |
3530 len = min (len, XINT (Flength (args[i]))); | |
3531 } | |
3532 | |
3533 result = make_vector (len, Qnil); | |
3401 GCPRO1 (result); | 3534 GCPRO1 (result); |
3402 mapcar1 (len, XVECTOR_DATA (result), function, sequence); | 3535 /* Don't pass result as the lisp_object argument, we want mapcarX to protect |
3536 a single list argument's elements from being garbage-collected. */ | |
3537 mapcarX (len, XVECTOR_DATA (result), Qnil, function, nargs - 1, args +1); | |
3403 UNGCPRO; | 3538 UNGCPRO; |
3404 | 3539 |
3405 return result; | 3540 return result; |
3406 } | 3541 } |
3407 | 3542 |
3408 DEFUN ("mapc-internal", Fmapc_internal, 2, 2, 0, /* | 3543 DEFUN ("mapcan", Fmapcan, 2, MANY, 0, /* |
3409 Apply FUNCTION to each element of SEQUENCE. | 3544 Call FUNCTION on each element of SEQUENCE; chain the results together. |
3545 | |
3546 FUNCTION must normally return a list; the results will be concatenated | |
3547 together using `nconc'. | |
3548 | |
3549 With optional SEQUENCES, call FUNCTION each time with as many arguments as | |
3550 there are SEQUENCES, plus one for the element from SEQUENCE. One element | |
3551 from each sequence will be used each time FUNCTION is called, and | |
3552 `mapcan' stops calling FUNCTION once the shortest sequence is exhausted. | |
3553 | |
3554 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) | |
3555 */ | |
3556 (int nargs, Lisp_Object *args)) | |
3557 { | |
3558 Lisp_Object function = args[0], nconcing; | |
3559 Elemcount len = EMACS_INT_MAX; | |
3560 Lisp_Object *args0; | |
3561 struct gcpro gcpro1; | |
3562 int i; | |
3563 | |
3564 for (i = 1; i < nargs; ++i) | |
3565 { | |
3566 CHECK_SEQUENCE (args[i]); | |
3567 len = min (len, XINT (Flength (args[i]))); | |
3568 } | |
3569 | |
3570 args0 = alloca_array (Lisp_Object, len + 1); | |
3571 mapcarX (len, args0 + 1, Qnil, function, nargs - 1, args + 1); | |
3572 | |
3573 if (len < 2) | |
3574 { | |
3575 return len ? args0[1] : Qnil; | |
3576 } | |
3577 | |
3578 /* bytecode_nconc2 can signal and return, we need to GCPRO the args, since | |
3579 mapcarX is no longer doing this for us. */ | |
3580 args0[0] = Fcons (Qnil, Qnil); | |
3581 GCPRO1 (args0[0]); | |
3582 gcpro1.nvars = len + 1; | |
3583 | |
3584 for (i = 0; i < len; ++i) | |
3585 { | |
3586 nconcing = bytecode_nconc2 (args0 + i); | |
3587 args0[i + 1] = nconcing; | |
3588 } | |
3589 | |
3590 RETURN_UNGCPRO (XCDR (nconcing)); | |
3591 } | |
3592 | |
3593 DEFUN ("mapc", Fmapc, 2, MANY, 0, /* | |
3594 Call FUNCTION on each element of SEQUENCE. | |
3595 | |
3410 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3596 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, | 3597 This function is like `mapcar' but does not accumulate the results, |
3412 which is more efficient if you do not use the results. | 3598 which is more efficient if you do not use the results. |
3413 | 3599 |
3414 The difference between this and `mapc' is that `mapc' supports all | 3600 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3415 the spiffy Common Lisp arguments. You should normally use `mapc'. | 3601 there are SEQUENCES, plus one for the elements from SEQUENCE. One element |
3416 */ | 3602 from each sequence will be used each time FUNCTION is called, and |
3417 (function, sequence)) | 3603 `mapc' stops calling FUNCTION once the shortest sequence is exhausted. |
3418 { | 3604 |
3419 mapcar1 (XINT (Flength (sequence)), 0, function, sequence); | 3605 Return SEQUENCE. |
3420 | 3606 |
3421 return sequence; | 3607 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) |
3422 } | 3608 */ |
3423 | 3609 (int nargs, Lisp_Object *args)) |
3610 { | |
3611 Elemcount len = EMACS_INT_MAX; | |
3612 Lisp_Object sequence = args[1]; | |
3613 struct gcpro gcpro1; | |
3614 int i; | |
3615 | |
3616 for (i = 1; i < nargs; ++i) | |
3617 { | |
3618 CHECK_SEQUENCE (args[i]); | |
3619 len = min (len, XINT (Flength (args[i]))); | |
3620 } | |
3621 | |
3622 /* We need to GCPRO sequence, because mapcarX will modify the | |
3623 elements of the args array handed to it, and this may involve | |
3624 elements of sequence getting garbage collected. */ | |
3625 GCPRO1 (sequence); | |
3626 mapcarX (len, NULL, Qnil, args[0], nargs - 1, args + 1); | |
3627 RETURN_UNGCPRO (sequence); | |
3628 } | |
3629 | |
3630 DEFUN ("map", Fmap, 3, MANY, 0, /* | |
3631 Map FUNCTION across one or more sequences, returning a sequence. | |
3632 | |
3633 TYPE is the sequence type to return, FUNCTION is the function, SEQUENCE is | |
3634 the first argument sequence, SEQUENCES are the other argument sequences. | |
3635 | |
3636 FUNCTION will be called with (1+ (length SEQUENCES)) arguments, and must be | |
3637 capable of accepting this number of arguments. | |
3638 | |
3639 Certain TYPEs are recognised internally by `map', but others are not, and | |
3640 `coerce' may throw an error on an attempt to convert to a TYPE it does not | |
3641 understand. A null TYPE means do not accumulate any values. | |
3642 | |
3643 arguments: (TYPE FUNCTION SEQUENCE &rest SEQUENCES) | |
3644 */ | |
3645 (int nargs, Lisp_Object *args)) | |
3646 { | |
3647 Lisp_Object type = args[0]; | |
3648 Lisp_Object function = args[1]; | |
3649 Lisp_Object result = Qnil; | |
3650 Lisp_Object *args0 = NULL; | |
3651 Elemcount len = EMACS_INT_MAX; | |
3652 int i; | |
3653 struct gcpro gcpro1; | |
3654 | |
3655 for (i = 2; i < nargs; ++i) | |
3656 { | |
3657 CHECK_SEQUENCE (args[i]); | |
3658 len = min (len, XINT (Flength (args[i]))); | |
3659 } | |
3660 | |
3661 if (!NILP (type)) | |
3662 { | |
3663 args0 = alloca_array (Lisp_Object, len); | |
3664 } | |
3665 | |
3666 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2); | |
3667 | |
3668 if (EQ (type, Qnil)) | |
3669 { | |
3670 return result; | |
3671 } | |
3672 | |
3673 if (EQ (type, Qvector) || EQ (type, Qarray)) | |
3674 { | |
3675 result = Fvector (len, args0); | |
3676 } | |
3677 else if (EQ (type, Qstring)) | |
3678 { | |
3679 result = Fstring (len, args0); | |
3680 } | |
3681 else if (EQ (type, Qlist)) | |
3682 { | |
3683 result = Flist (len, args0); | |
3684 } | |
3685 else if (EQ (type, Qbit_vector)) | |
3686 { | |
3687 result = Fbit_vector (len, args0); | |
3688 } | |
3689 else | |
3690 { | |
3691 result = Flist (len, args0); | |
3692 GCPRO1 (result); | |
3693 result = call2 (Qcoerce, result, type); | |
3694 UNGCPRO; | |
3695 } | |
3696 | |
3697 return result; | |
3698 } | |
3699 | |
3700 DEFUN ("map-into", Fmap_into, 2, MANY, 0, /* | |
3701 Modify RESULT-SEQUENCE using the return values of FUNCTION on SEQUENCES. | |
3702 | |
3703 RESULT-SEQUENCE and SEQUENCES can be lists or arrays. | |
3704 | |
3705 FUNCTION must accept at least as many arguments as there are SEQUENCES | |
3706 \(possibly zero). If RESULT-SEQUENCE and the elements of SEQUENCES are not | |
3707 the same length, stop when the shortest is exhausted; any elements of | |
3708 RESULT-SEQUENCE beyond that are unmodified. | |
3709 | |
3710 Return RESULT-SEQUENCE. | |
3711 | |
3712 arguments: (RESULT-SEQUENCE FUNCTION &rest SEQUENCES) | |
3713 */ | |
3714 (int nargs, Lisp_Object *args)) | |
3715 { | |
3716 Elemcount len = EMACS_INT_MAX; | |
3717 Lisp_Object result_sequence = args[0]; | |
3718 Lisp_Object function = args[1]; | |
3719 int i; | |
3720 | |
3721 args[0] = function; | |
3722 args[1] = result_sequence; | |
3723 | |
3724 for (i = 1; i < nargs; ++i) | |
3725 { | |
3726 CHECK_SEQUENCE (args[i]); | |
3727 len = min (len, XINT (Flength (args[i]))); | |
3728 } | |
3729 | |
3730 mapcarX (len, NULL, result_sequence, function, nargs - 2, args + 2); | |
3731 | |
3732 return result_sequence; | |
3733 } | |
3734 | |
3735 /* Call FUNCTION with NLISTS arguments repeatedly, each Nth argument | |
3736 corresponding to the result of calling (nthcdr ITERATION-COUNT LISTS[N]), | |
3737 until that #'nthcdr expression gives nil for some element of LISTS. | |
3738 | |
3739 If MAPLP is zero, return LISTS[0]. Otherwise, return a list of the return | |
3740 values from FUNCTION; if NCONCP is non-zero, nconc them together. | |
3741 | |
3742 In contrast to mapcarX, we don't require our callers to check LISTS for | |
3743 well-formedness, we signal wrong-type-argument if it's not a list, or | |
3744 circular-list if it's circular. */ | |
3745 | |
3746 static Lisp_Object | |
3747 maplist (Lisp_Object function, int nlists, Lisp_Object *lists, int maplp, | |
3748 int nconcp) | |
3749 { | |
3750 Lisp_Object result = maplp ? lists[0] : Fcons (Qnil, Qnil), funcalled; | |
3751 Lisp_Object nconcing[2], accum = result, *args; | |
3752 struct gcpro gcpro1, gcpro2, gcpro3; | |
3753 int i, j, continuing = (nlists > 0), called_count = 0; | |
3754 | |
3755 args = alloca_array (Lisp_Object, nlists + 1); | |
3756 args[0] = function; | |
3757 for (i = 1; i <= nlists; ++i) | |
3758 { | |
3759 args[i] = Qnil; | |
3760 } | |
3761 | |
3762 if (nconcp) | |
3763 { | |
3764 nconcing[0] = result; | |
3765 nconcing[1] = Qnil; | |
3766 GCPRO3 (args[0], nconcing[0], result); | |
3767 gcpro1.nvars = 1; | |
3768 gcpro2.nvars = 2; | |
3769 } | |
3770 else | |
3771 { | |
3772 GCPRO2 (args[0], result); | |
3773 gcpro1.nvars = 1; | |
3774 } | |
3775 | |
3776 while (continuing) | |
3777 { | |
3778 for (j = 0; j < nlists; ++j) | |
3779 { | |
3780 if (CONSP (lists[j])) | |
3781 { | |
3782 args[j + 1] = lists[j]; | |
3783 lists[j] = XCDR (lists[j]); | |
3784 } | |
3785 else if (NILP (lists[j])) | |
3786 { | |
3787 continuing = 0; | |
3788 break; | |
3789 } | |
3790 else | |
3791 { | |
3792 dead_wrong_type_argument (Qlistp, lists[j]); | |
3793 } | |
3794 } | |
3795 if (!continuing) break; | |
3796 funcalled = Ffuncall (nlists + 1, args); | |
3797 if (!maplp) | |
3798 { | |
3799 if (nconcp) | |
3800 { | |
3801 /* This order of calls means we check that each list is | |
3802 well-formed once and once only. The last result does | |
3803 not have to be a list. */ | |
3804 nconcing[1] = funcalled; | |
3805 nconcing[0] = bytecode_nconc2 (nconcing); | |
3806 } | |
3807 else | |
3808 { | |
3809 /* Add to the end, avoiding the need to call nreverse | |
3810 once we're done: */ | |
3811 XSETCDR (accum, Fcons (funcalled, Qnil)); | |
3812 accum = XCDR (accum); | |
3813 } | |
3814 } | |
3815 | |
3816 if (++called_count % CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
3817 | |
3818 for (j = 0; j < nlists; ++j) | |
3819 { | |
3820 EXTERNAL_LIST_LOOP_1 (lists[j]) | |
3821 { | |
3822 /* Just check the lists aren't circular, using the | |
3823 EXTERNAL_LIST_LOOP_1 macro. */ | |
3824 } | |
3825 } | |
3826 } | |
3827 | |
3828 if (!maplp) | |
3829 { | |
3830 result = XCDR (result); | |
3831 } | |
3832 | |
3833 RETURN_UNGCPRO (result); | |
3834 } | |
3835 | |
3836 DEFUN ("maplist", Fmaplist, 2, MANY, 0, /* | |
3837 Call FUNCTION on each sublist of LIST and LISTS. | |
3838 Like `mapcar', except applies to lists and their cdr's rather than to | |
3839 the elements themselves." | |
3840 | |
3841 arguments: (FUNCTION LIST &rest LISTS) | |
3842 */ | |
3843 (int nargs, Lisp_Object *args)) | |
3844 { | |
3845 return maplist (args[0], nargs - 1, args + 1, 0, 0); | |
3846 } | |
3847 | |
3848 DEFUN ("mapl", Fmapl, 2, MANY, 0, /* | |
3849 Like `maplist', but do not accumulate values returned by the function. | |
3850 | |
3851 arguments: (FUNCTION LIST &rest LISTS) | |
3852 */ | |
3853 (int nargs, Lisp_Object *args)) | |
3854 { | |
3855 return maplist (args[0], nargs - 1, args + 1, 1, 0); | |
3856 } | |
3857 | |
3858 DEFUN ("mapcon", Fmapcon, 2, MANY, 0, /* | |
3859 Like `maplist', but chains together the values returned by FUNCTION. | |
3860 | |
3861 FUNCTION must return a list (unless it happens to be the last | |
3862 iteration); the results will be concatenated together using `nconc'. | |
3863 | |
3864 arguments: (FUNCTION LIST &rest LISTS) | |
3865 */ | |
3866 (int nargs, Lisp_Object *args)) | |
3867 { | |
3868 return maplist (args[0], nargs - 1, args + 1, 0, 1); | |
3869 } | |
3424 | 3870 |
3425 /* Extra random functions */ | 3871 /* Extra random functions */ |
3426 | 3872 |
3427 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* | 3873 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* |
3428 Destructively replace the list OLD with NEW. | 3874 Destructively replace the list OLD with NEW. |
3462 old = Qnil; | 3908 old = Qnil; |
3463 | 3909 |
3464 return old; | 3910 return old; |
3465 } | 3911 } |
3466 | 3912 |
3913 | |
3467 Lisp_Object | 3914 Lisp_Object |
3468 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) | 3915 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) |
3469 { | 3916 { |
3470 return Fintern (concat2 (Fsymbol_name (symbol), | 3917 return Fintern (concat2 (Fsymbol_name (symbol), |
3471 build_string (ascii_string)), | 3918 build_string (ascii_string)), |
4100 { | 4547 { |
4101 INIT_LRECORD_IMPLEMENTATION (bit_vector); | 4548 INIT_LRECORD_IMPLEMENTATION (bit_vector); |
4102 | 4549 |
4103 DEFSYMBOL (Qstring_lessp); | 4550 DEFSYMBOL (Qstring_lessp); |
4104 DEFSYMBOL (Qidentity); | 4551 DEFSYMBOL (Qidentity); |
4552 DEFSYMBOL (Qvector); | |
4553 DEFSYMBOL (Qarray); | |
4554 DEFSYMBOL (Qstring); | |
4555 DEFSYMBOL (Qlist); | |
4556 DEFSYMBOL (Qbit_vector); | |
4557 | |
4105 DEFSYMBOL (Qyes_or_no_p); | 4558 DEFSYMBOL (Qyes_or_no_p); |
4106 | 4559 |
4107 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); | 4560 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); |
4108 | 4561 |
4109 DEFSUBR (Fidentity); | 4562 DEFSUBR (Fidentity); |
4177 DEFSUBR (Fequal); | 4630 DEFSUBR (Fequal); |
4178 DEFSUBR (Fequalp); | 4631 DEFSUBR (Fequalp); |
4179 DEFSUBR (Fold_equal); | 4632 DEFSUBR (Fold_equal); |
4180 DEFSUBR (Ffillarray); | 4633 DEFSUBR (Ffillarray); |
4181 DEFSUBR (Fnconc); | 4634 DEFSUBR (Fnconc); |
4182 DEFSUBR (Fmapcar); | 4635 DEFSUBR (FmapcarX); |
4183 DEFSUBR (Fmapvector); | 4636 DEFSUBR (Fmapvector); |
4184 DEFSUBR (Fmapc_internal); | 4637 DEFSUBR (Fmapcan); |
4638 DEFSUBR (Fmapc); | |
4185 DEFSUBR (Fmapconcat); | 4639 DEFSUBR (Fmapconcat); |
4640 DEFSUBR (Fmap); | |
4641 DEFSUBR (Fmap_into); | |
4642 Ffset (intern ("mapc-internal"), Fsymbol_function (intern ("mapc"))); | |
4643 Ffset (intern ("mapcar"), Fsymbol_function (intern ("mapcar*"))); | |
4644 DEFSUBR (Fmaplist); | |
4645 DEFSUBR (Fmapl); | |
4646 DEFSUBR (Fmapcon); | |
4647 | |
4186 DEFSUBR (Freplace_list); | 4648 DEFSUBR (Freplace_list); |
4187 DEFSUBR (Fload_average); | 4649 DEFSUBR (Fload_average); |
4188 DEFSUBR (Ffeaturep); | 4650 DEFSUBR (Ffeaturep); |
4189 DEFSUBR (Frequire); | 4651 DEFSUBR (Frequire); |
4190 DEFSUBR (Fprovide); | 4652 DEFSUBR (Fprovide); |