comparison src/fns.c @ 4995:8431b52e43b1

Move the various map* functions to C; add #'map-into. src/ChangeLog addition: 2010-01-31 Aidan Kehoe <kehoea@parhasard.net> Move #'mapcar*, #'mapcan, #'mapc, #'map, #'mapl, #'mapcon to C; extend #'mapvector, #'mapconcat, #'mapcar to support more SEQUENCES; have them all error with circular lists. * fns.c (Fsubseq): Call CHECK_SEQUENCE here; Flength can return from the debugger if it errors with a non-sequence, leading to a crash in Fsubseq if sequence really is *not* a sequence. (mapcarX): Rename mapcar1 to mapcarX; rework it comprehensively to take an optional lisp output argument, and a varying number of sequences. Special-case a single list argument, as we used to, saving its elements in the stack space for the results before calling FUNCTION, so FUNCTION can corrupt the list all it wants. dead_wrong_type_argument() in the other cases if we encounter a non-cons where we expected a cons. (Fmapconcat): Accept further SEQUENCES after separator here. Special-case the idiom (mapconcat 'identity SEQUENCE), don't even funcall. (FmapcarX): Rename this from Fmapcar. Accept optional SEQUENCES. (Fmapvector): Accept optional SEQUENCES. (Fmapcan, Fmapc, Fmap): Move these here from cl-extra.el. (Fmap_into): New function, as specified by Common Lisp. (maplist): New function, the guts of the implementation of Fmaplist and Fmapl. (Fmaplist, Fmapl, Fmapcon): Move these from cl-extra.el. (syms_of_fns): Add a few needed symbols here, for the type tests used by #'map. Add the new subrs, with aliases for #'mapc-internal and #'mapcar. * general-slots.h: Declare Qcoerce here, now it's used in both indent.c and fns.c * indent.c (syms_of_indent): Qcoerce is gone from here. * lisp.h: Add ARRAYP(), SEQUENCEP(), and the corresponding CHECK_* macros. Declare Fbit_vector, Fstring, FmapcarX, now other files need to use them. * data.c (Farrayp, Fsequencep): Use ARRAYP and SEQUENCEP, just added to lisp.h * buffer.c (Fbuffer_list): Now Fmapcar has been renamed FmapcarX and takes MANY arguments, update this function to reflect that. lisp/ChangeLog addition: 2010-01-31 Aidan Kehoe <kehoea@parhasard.net> * cl.el (mapcar*): Delete; this is now in fns.c. Use #'mapc, not #'mapc-internal in a couple of places. * cl-macs.el (mapc, mapcar*, map): Delete these compiler macros now the corresponding functions are in fns.c; there's no run-time advantage to the macros. * cl-extra.el (coerce): Extend the possible conversions here a little; it's not remotely comprehensive yet, though it does allow running slightly more Common Lisp code than previously. (cl-mapcar-many): Delete. (map, maplist, mapc, mapl, mapcan, mapcon): Move these to fns.c. * bytecomp.el (byte-compile-maybe-mapc): Use #'mapc itself, not #'mapc-internal, now the former is in C. (mapcar*): Use #'byte-compile-maybe-mapc as this function's byte-compile method, now a #'mapc that can take more than one sequence is in C. * obsolete.el (cl-mapc): Move this compatibility alias to this file. * update-elc.el (do-autoload-commands): Use #'mapc, not #'mapc-internal here.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 31 Jan 2010 18:29:48 +0000
parents a5eca70cf401
children c17c857e20bf
comparison
equal deleted inserted replaced
4904:e91e3e353805 4995:8431b52e43b1
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
979 */ 980 */
980 (sequence, start, end)) 981 (sequence, start, end))
981 { 982 {
982 EMACS_INT len, s, e; 983 EMACS_INT len, s, e;
983 984
985 CHECK_SEQUENCE (sequence);
986
984 if (STRINGP (sequence)) 987 if (STRINGP (sequence))
985 return Fsubstring (sequence, start, end); 988 return Fsubstring (sequence, start, end);
986 989
987 len = XINT (Flength (sequence)); 990 len = XINT (Flength (sequence));
988 991
1040 bit_vector_bit (XBIT_VECTOR (sequence), i)); 1043 bit_vector_bit (XBIT_VECTOR (sequence), i));
1041 return result; 1044 return result;
1042 } 1045 }
1043 else 1046 else
1044 { 1047 {
1045 ABORT (); /* unreachable, since Flength (sequence) did not get 1048 ABORT (); /* unreachable, since CHECK_SEQUENCE (sequence) did not
1046 an error */ 1049 error */
1047 return Qnil; 1050 return Qnil;
1048 } 1051 }
1049 } 1052 }
1050 1053
1051 /* Split STRING into a list of substrings. The substrings are the 1054 /* Split STRING into a list of substrings. The substrings are the
3152 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ 3155 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */
3153 } 3156 }
3154 3157
3155 3158
3156 /* This is the guts of several mapping functions. 3159 /* This is the guts of several mapping functions.
3157 Apply FUNCTION to each element of SEQUENCE, one by one, 3160
3158 storing the results into elements of VALS, a C vector of Lisp_Objects. 3161 Call FUNCTION CALL_COUNT times, with NSEQUENCES arguments each time,
3159 LENI is the length of VALS, which should also be the length of SEQUENCE. 3162 taking the elements from SEQUENCES. If VALS is non-NULL, store the
3160 3163 results into VALS, a C array of Lisp_Objects; else, if LISP_VALS is
3161 If VALS is a null pointer, do not accumulate the results. */ 3164 non-nil, store the results into LISP_VALS, a sequence with sufficient
3165 room for CALL_COUNT results. Else, do not accumulate any result.
3166
3167 If VALS is non-NULL, NSEQUENCES is one, and SEQUENCES[0] is a cons,
3168 mapcarX will store the elements of SEQUENCES[0] in stack and GCPRO them,
3169 so FUNCTION cannot insert a non-cons into SEQUENCES[0] and throw off
3170 mapcarX.
3171
3172 Otherwise, mapcarX signals a wrong-type-error if it encounters a
3173 non-cons, non-array when traversing SEQUENCES. Common Lisp specifies in
3174 MAPPING-DESTRUCTIVE-INTERACTION that it is an error when FUNCTION
3175 destructively modifies SEQUENCES in a way that might affect the ongoing
3176 traversal operation. */
3162 3177
3163 static void 3178 static void
3164 mapcar1 (Elemcount leni, Lisp_Object *vals, 3179 mapcarX (Elemcount call_count, Lisp_Object *vals, Lisp_Object lisp_vals,
3165 Lisp_Object function, Lisp_Object sequence) 3180 Lisp_Object function, int nsequences, Lisp_Object *sequences)
3166 { 3181 {
3167 Lisp_Object result; 3182 Lisp_Object called, *args;
3168 Lisp_Object args[2]; 3183 struct gcpro gcpro1, gcpro2;
3169 struct gcpro gcpro1; 3184 int i, j;
3170 3185 enum lrecord_type lisp_vals_type;
3171 if (vals) 3186
3172 { 3187 assert (LRECORDP (lisp_vals));
3173 GCPRO1 (vals[0]); 3188 lisp_vals_type = XRECORD_LHEADER (lisp_vals)->type;
3174 gcpro1.nvars = 0; 3189
3175 } 3190 args = alloca_array (Lisp_Object, nsequences + 1);
3176
3177 args[0] = function; 3191 args[0] = function;
3178 3192 for (i = 1; i <= nsequences; ++i)
3179 if (LISTP (sequence)) 3193 {
3180 { 3194 args[i] = Qnil;
3181 /* A devious `function' could either: 3195 }
3182 - insert garbage into the list in front of us, causing XCDR to crash 3196
3183 - amputate the list behind us using (setcdr), causing the remaining 3197 if (vals != NULL)
3184 elts to lose their GCPRO status. 3198 {
3185 3199 GCPRO2 (args[0], vals[0]);
3186 if (vals != 0) we avoid this by copying the elts into the 3200 gcpro1.nvars = nsequences + 1;
3187 `vals' array. By a stroke of luck, `vals' is exactly large 3201 gcpro2.nvars = 0;
3188 enough to hold the elts left to be traversed as well as the 3202 }
3189 results computed so far. 3203 else
3190 3204 {
3191 if (vals == 0) we don't have any free space available and 3205 GCPRO1 (args[0]);
3192 don't want to eat up any more stack with ALLOCA (). 3206 gcpro1.nvars = nsequences + 1;
3193 So we use EXTERNAL_LIST_LOOP_3_NO_DECLARE and GCPRO the tail. */ 3207 }
3194 3208
3195 if (vals) 3209 /* Be extra nice in the event that we've been handed one list and one
3196 { 3210 only; make it possible for FUNCTION to set cdrs not yet processed to
3197 Lisp_Object *val = vals; 3211 non-cons, non-nil objects without ill-effect, if we have been handed
3198 Elemcount i; 3212 the stack space to do that. */
3199 3213 if (vals != NULL && 1 == nsequences && CONSP (sequences[0]))
3200 LIST_LOOP_2 (elt, sequence) 3214 {
3201 *val++ = elt; 3215 Lisp_Object lst = sequences[0];
3202 3216 Lisp_Object *val = vals;
3203 gcpro1.nvars = leni; 3217 for (i = 0; i < call_count; ++i)
3204 3218 {
3205 for (i = 0; i < leni; i++) 3219 *val++ = XCAR (lst);
3220 lst = XCDR (lst);
3221 }
3222 gcpro2.nvars = call_count;
3223
3224 for (i = 0; i < call_count; ++i)
3225 {
3226 args[1] = vals[i];
3227 vals[i] = Ffuncall (nsequences + 1, args);
3228 }
3229 }
3230 else
3231 {
3232 Binbyte *sequence_types = alloca_array (Binbyte, nsequences);
3233 for (j = 0; j < nsequences; ++j)
3234 {
3235 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type;
3236 }
3237
3238 for (i = 0; i < call_count; ++i)
3239 {
3240 for (j = 0; j < nsequences; ++j)
3206 { 3241 {
3207 args[1] = vals[i]; 3242 switch (sequence_types[j])
3208 vals[i] = Ffuncall (2, args); 3243 {
3244 case lrecord_type_cons:
3245 {
3246 if (!CONSP (sequences[j]))
3247 {
3248 /* This means FUNCTION has probably messed
3249 around with a cons in one of the sequences,
3250 since we checked the type
3251 (CHECK_SEQUENCE()) and the length and
3252 structure (with Flength()) correctly in our
3253 callers. */
3254 dead_wrong_type_argument (Qconsp, sequences[j]);
3255 }
3256 args[j + 1] = XCAR (sequences[j]);
3257 sequences[j] = XCDR (sequences[j]);
3258 break;
3259 }
3260 case lrecord_type_vector:
3261 {
3262 args[j + 1] = XVECTOR_DATA (sequences[j])[i];
3263 break;
3264 }
3265 case lrecord_type_string:
3266 {
3267 args[j + 1] = make_char (string_ichar (sequences[j], i));
3268 break;
3269 }
3270 case lrecord_type_bit_vector:
3271 {
3272 args[j + 1]
3273 = make_int (bit_vector_bit (XBIT_VECTOR (sequences[j]),
3274 i));
3275 break;
3276 }
3277 default:
3278 ABORT();
3279 }
3209 } 3280 }
3210 } 3281 called = Ffuncall (nsequences + 1, args);
3211 else 3282 if (vals != NULL)
3212 { 3283 {
3213 Lisp_Object elt, tail; 3284 vals[i] = called;
3214 EMACS_INT len_unused; 3285 gcpro2.nvars += 1;
3215 struct gcpro ngcpro1; 3286 }
3216 3287 else
3217 NGCPRO1 (tail); 3288 {
3218 3289 switch (lisp_vals_type)
3219 { 3290 {
3220 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len_unused) 3291 case lrecord_type_symbol:
3221 { 3292 break;
3222 args[1] = elt; 3293 case lrecord_type_cons:
3223 Ffuncall (2, args); 3294 {
3224 } 3295 if (!CONSP (lisp_vals))
3225 } 3296 {
3226 3297 /* If FUNCTION has inserted a non-cons non-nil cdr
3227 NUNGCPRO; 3298 into the list before we've processed the relevant
3228 } 3299 part, error. */
3229 } 3300 dead_wrong_type_argument (Qconsp, lisp_vals);
3230 else if (VECTORP (sequence)) 3301 }
3231 { 3302
3232 Lisp_Object *objs = XVECTOR_DATA (sequence); 3303 XSETCAR (lisp_vals, called);
3233 Elemcount i; 3304 lisp_vals = XCDR (lisp_vals);
3234 for (i = 0; i < leni; i++) 3305 break;
3235 { 3306 }
3236 args[1] = *objs++; 3307 case lrecord_type_vector:
3237 result = Ffuncall (2, args); 3308 {
3238 if (vals) vals[gcpro1.nvars++] = result; 3309 i < XVECTOR_LENGTH (lisp_vals) ?
3239 } 3310 (XVECTOR_DATA (lisp_vals)[i] = called) :
3240 } 3311 /* Let #'aset error. */
3241 else if (STRINGP (sequence)) 3312 Faset (lisp_vals, make_int (i), called);
3242 { 3313 break;
3243 /* The string data of `sequence' might be relocated during GC. */ 3314 }
3244 Bytecount slen = XSTRING_LENGTH (sequence); 3315 case lrecord_type_string:
3245 Ibyte *p = alloca_ibytes (slen); 3316 {
3246 Ibyte *end = p + slen; 3317 /* If this ever becomes a code hotspot, we can keep
3247 3318 around pointers into the data of the string, checking
3248 memcpy (p, XSTRING_DATA (sequence), slen); 3319 each time that it hasn't been relocated. */
3249 3320 Faset (lisp_vals, make_int (i), called);
3250 while (p < end) 3321 break;
3251 { 3322 }
3252 args[1] = make_char (itext_ichar (p)); 3323 case lrecord_type_bit_vector:
3253 INC_IBYTEPTR (p); 3324 {
3254 result = Ffuncall (2, args); 3325 (BITP (called) &&
3255 if (vals) vals[gcpro1.nvars++] = result; 3326 i < bit_vector_length (XBIT_VECTOR (lisp_vals))) ?
3256 } 3327 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i,
3257 } 3328 XINT (called)) :
3258 else if (BIT_VECTORP (sequence)) 3329 Faset (lisp_vals, make_int (i), called);
3259 { 3330 break;
3260 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence); 3331 }
3261 Elemcount i; 3332 default:
3262 for (i = 0; i < leni; i++) 3333 {
3263 { 3334 ABORT();
3264 args[1] = make_int (bit_vector_bit (v, i)); 3335 break;
3265 result = Ffuncall (2, args); 3336 }
3266 if (vals) vals[gcpro1.nvars++] = result; 3337 }
3267 } 3338 }
3268 } 3339 }
3269 else 3340 }
3270 ABORT (); /* unreachable, since Flength (sequence) did not get an error */ 3341 UNGCPRO;
3271 3342 }
3272 if (vals) 3343
3273 UNGCPRO; 3344 DEFUN ("mapconcat", Fmapconcat, 3, MANY, 0, /*
3274 } 3345 Call FUNCTION on each element of SEQUENCE, and concat results to a string.
3275
3276 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /*
3277 Apply FUNCTION to each element of SEQUENCE, and concat the results to a string.
3278 Between each pair of results, insert SEPARATOR. 3346 Between each pair of results, insert SEPARATOR.
3279 3347
3280 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR 3348 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR
3281 results in spaces between the values returned by FUNCTION. SEQUENCE itself 3349 results in spaces between the values returned by FUNCTION. SEQUENCE itself
3282 may be a list, a vector, a bit vector, or a string. 3350 may be a list, a vector, a bit vector, or a string.
3283 */ 3351
3284 (function, sequence, separator)) 3352 With optional SEQUENCES, call FUNCTION each time with as many arguments as
3285 { 3353 there are SEQUENCES, plus one for the element from SEQUENCE. One element
3286 EMACS_INT len = XINT (Flength (sequence)); 3354 from each sequence will be used each time FUNCTION is called, and
3287 Lisp_Object *args; 3355 `mapconcat' will give up once the shortest sequence is exhausted.
3288 EMACS_INT i; 3356
3289 EMACS_INT nargs = len + len - 1; 3357 arguments: (FUNCTION SEQUENCE SEPARATOR &rest SEQUENCES)
3358 */
3359 (int nargs, Lisp_Object *args))
3360 {
3361 Lisp_Object function = args[0];
3362 Lisp_Object sequence = args[1];
3363 Lisp_Object separator = args[2];
3364 Elemcount len = EMACS_INT_MAX;
3365 Lisp_Object *args0;
3366 EMACS_INT i, nargs0;
3367
3368 args[2] = sequence;
3369 args[1] = separator;
3370
3371 for (i = 2; i < nargs; ++i)
3372 {
3373 CHECK_SEQUENCE (args[i]);
3374 len = min (len, XINT (Flength (args[i])));
3375 }
3290 3376
3291 if (len == 0) return build_string (""); 3377 if (len == 0) return build_string ("");
3292 3378
3293 args = alloca_array (Lisp_Object, nargs); 3379 nargs0 = len + len - 1;
3294 3380 args0 = alloca_array (Lisp_Object, nargs0);
3295 mapcar1 (len, args, function, sequence); 3381
3382 /* Special-case this, it's very common and doesn't require any
3383 funcalls. Upside of doing it here, instead of cl-macs.el: no consing,
3384 apart from the final string, we allocate everything on the stack. */
3385 if (EQ (function, Qidentity) && 3 == nargs && CONSP (sequence))
3386 {
3387 for (i = 0; i < len; ++i)
3388 {
3389 args0[i] = XCAR (sequence);
3390 sequence = XCDR (sequence);
3391 }
3392 }
3393 else
3394 {
3395 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2);
3396 }
3296 3397
3297 for (i = len - 1; i >= 0; i--) 3398 for (i = len - 1; i >= 0; i--)
3298 args[i + i] = args[i]; 3399 args0[i + i] = args0[i];
3299 3400
3300 for (i = 1; i < nargs; i += 2) 3401 for (i = 1; i < nargs0; i += 2)
3301 args[i] = separator; 3402 args0[i] = separator;
3302 3403
3303 return Fconcat (nargs, args); 3404 return Fconcat (nargs0, args0);
3304 } 3405 }
3305 3406
3306 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* 3407 DEFUN ("mapcar*", FmapcarX, 2, MANY, 0, /*
3307 Apply FUNCTION to each element of SEQUENCE; return a list of the results. 3408 Call FUNCTION on each element of SEQUENCE; return a list of the results.
3308 The result is a list of the same length as SEQUENCE. 3409 The result is a list of the same length as SEQUENCE.
3309 SEQUENCE may be a list, a vector, a bit vector, or a string. 3410 SEQUENCE may be a list, a vector, a bit vector, or a string.
3310 */ 3411
3311 (function, sequence)) 3412 With optional SEQUENCES, call FUNCTION each time with as many arguments as
3312 { 3413 there are SEQUENCES, plus one for the element from SEQUENCE. One element
3313 Elemcount len = XINT (Flength (sequence)); 3414 from each sequence will be used each time FUNCTION is called, and `mapcar'
3314 Lisp_Object *args = alloca_array (Lisp_Object, len); 3415 stops calling FUNCTION once the shortest sequence is exhausted.
3315 3416
3316 mapcar1 (len, args, function, sequence); 3417 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
3317 3418 */
3318 return Flist ((int) len, args); 3419 (int nargs, Lisp_Object *args))
3319 } 3420 {
3320 3421 Lisp_Object function = args[0];
3321 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* 3422 Elemcount len = EMACS_INT_MAX;
3322 Apply FUNCTION to each element of SEQUENCE; return a vector of the results. 3423 Lisp_Object *args0;
3424 int i;
3425
3426 for (i = 1; i < nargs; ++i)
3427 {
3428 CHECK_SEQUENCE (args[i]);
3429 len = min (len, XINT (Flength (args[i])));
3430 }
3431
3432 args0 = alloca_array (Lisp_Object, len);
3433 mapcarX (len, args0, Qnil, function, nargs - 1, args + 1);
3434
3435 return Flist ((int) len, args0);
3436 }
3437
3438 DEFUN ("mapvector", Fmapvector, 2, MANY, 0, /*
3439 Call FUNCTION on each element of SEQUENCE; return a vector of the results.
3323 The result is a vector of the same length as SEQUENCE. 3440 The result is a vector of the same length as SEQUENCE.
3324 SEQUENCE may be a list, a vector, a bit vector, or a string. 3441 SEQUENCE may be a list, a vector, a bit vector, or a string.
3325 */ 3442
3326 (function, sequence)) 3443 With optional SEQUENCES, call FUNCTION each time with as many arguments as
3327 { 3444 there are SEQUENCES, plus one for the element from SEQUENCE. One element
3328 Elemcount len = XINT (Flength (sequence)); 3445 from each sequence will be used each time FUNCTION is called, and
3329 Lisp_Object result = make_vector (len, Qnil); 3446 `mapvector' stops calling FUNCTION once the shortest sequence is exhausted.
3447
3448 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
3449 */
3450 (int nargs, Lisp_Object *args))
3451 {
3452 Lisp_Object function = args[0];
3453 Elemcount len = EMACS_INT_MAX;
3454 Lisp_Object result;
3330 struct gcpro gcpro1; 3455 struct gcpro gcpro1;
3331 3456 int i;
3457
3458 for (i = 1; i < nargs; ++i)
3459 {
3460 CHECK_SEQUENCE (args[i]);
3461 len = min (len, XINT (Flength (args[i])));
3462 }
3463
3464 result = make_vector (len, Qnil);
3332 GCPRO1 (result); 3465 GCPRO1 (result);
3333 mapcar1 (len, XVECTOR_DATA (result), function, sequence); 3466 /* Don't pass result as the lisp_object argument, we want mapcarX to protect
3467 a single list argument's elements from being garbage-collected. */
3468 mapcarX (len, XVECTOR_DATA (result), Qnil, function, nargs - 1, args +1);
3334 UNGCPRO; 3469 UNGCPRO;
3335 3470
3336 return result; 3471 return result;
3337 } 3472 }
3338 3473
3339 DEFUN ("mapc-internal", Fmapc_internal, 2, 2, 0, /* 3474 DEFUN ("mapcan", Fmapcan, 2, MANY, 0, /*
3340 Apply FUNCTION to each element of SEQUENCE. 3475 Call FUNCTION on each element of SEQUENCE; chain the results together.
3476
3477 FUNCTION must normally return a list; the results will be concatenated
3478 together using `nconc'.
3479
3480 With optional SEQUENCES, call FUNCTION each time with as many arguments as
3481 there are SEQUENCES, plus one for the element from SEQUENCE. One element
3482 from each sequence will be used each time FUNCTION is called, and
3483 `mapcan' stops calling FUNCTION once the shortest sequence is exhausted.
3484
3485 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
3486 */
3487 (int nargs, Lisp_Object *args))
3488 {
3489 Lisp_Object function = args[0], nconcing;
3490 Elemcount len = EMACS_INT_MAX;
3491 Lisp_Object *args0;
3492 struct gcpro gcpro1;
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 + 1);
3502 mapcarX (len, args0 + 1, Qnil, function, nargs - 1, args + 1);
3503
3504 if (len < 2)
3505 {
3506 return len ? args0[1] : Qnil;
3507 }
3508
3509 /* bytecode_nconc2 can signal and return, we need to GCPRO the args, since
3510 mapcarX is no longer doing this for us. */
3511 args0[0] = Fcons (Qnil, Qnil);
3512 GCPRO1 (args0[0]);
3513 gcpro1.nvars = len + 1;
3514
3515 for (i = 0; i < len; ++i)
3516 {
3517 nconcing = bytecode_nconc2 (args0 + i);
3518 args0[i + 1] = nconcing;
3519 }
3520
3521 RETURN_UNGCPRO (XCDR (nconcing));
3522 }
3523
3524 DEFUN ("mapc", Fmapc, 2, MANY, 0, /*
3525 Call FUNCTION on each element of SEQUENCE.
3526
3341 SEQUENCE may be a list, a vector, a bit vector, or a string. 3527 SEQUENCE may be a list, a vector, a bit vector, or a string.
3342 This function is like `mapcar' but does not accumulate the results, 3528 This function is like `mapcar' but does not accumulate the results,
3343 which is more efficient if you do not use the results. 3529 which is more efficient if you do not use the results.
3344 3530
3345 The difference between this and `mapc' is that `mapc' supports all 3531 With optional SEQUENCES, call FUNCTION each time with as many arguments as
3346 the spiffy Common Lisp arguments. You should normally use `mapc'. 3532 there are SEQUENCES, plus one for the elements from SEQUENCE. One element
3347 */ 3533 from each sequence will be used each time FUNCTION is called, and
3348 (function, sequence)) 3534 `mapc' stops calling FUNCTION once the shortest sequence is exhausted.
3349 { 3535
3350 mapcar1 (XINT (Flength (sequence)), 0, function, sequence); 3536 Return SEQUENCE.
3351 3537
3352 return sequence; 3538 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
3353 } 3539 */
3354 3540 (int nargs, Lisp_Object *args))
3541 {
3542 Elemcount len = EMACS_INT_MAX;
3543 Lisp_Object sequence = args[1];
3544 struct gcpro gcpro1;
3545 int i;
3546
3547 for (i = 1; i < nargs; ++i)
3548 {
3549 CHECK_SEQUENCE (args[i]);
3550 len = min (len, XINT (Flength (args[i])));
3551 }
3552
3553 /* We need to GCPRO sequence, because mapcarX will modify the
3554 elements of the args array handed to it, and this may involve
3555 elements of sequence getting garbage collected. */
3556 GCPRO1 (sequence);
3557 mapcarX (len, NULL, Qnil, args[0], nargs - 1, args + 1);
3558 RETURN_UNGCPRO (sequence);
3559 }
3560
3561 DEFUN ("map", Fmap, 3, MANY, 0, /*
3562 Map FUNCTION across one or more sequences, returning a sequence.
3563
3564 TYPE is the sequence type to return, FUNCTION is the function, SEQUENCE is
3565 the first argument sequence, SEQUENCES are the other argument sequences.
3566
3567 FUNCTION will be called with (1+ (length SEQUENCES)) arguments, and must be
3568 capable of accepting this number of arguments.
3569
3570 Certain TYPEs are recognised internally by `map', but others are not, and
3571 `coerce' may throw an error on an attempt to convert to a TYPE it does not
3572 understand. A null TYPE means do not accumulate any values.
3573
3574 arguments: (TYPE FUNCTION SEQUENCE &rest SEQUENCES)
3575 */
3576 (int nargs, Lisp_Object *args))
3577 {
3578 Lisp_Object type = args[0];
3579 Lisp_Object function = args[1];
3580 Lisp_Object result = Qnil;
3581 Lisp_Object *args0 = NULL;
3582 Elemcount len = EMACS_INT_MAX;
3583 int i;
3584 struct gcpro gcpro1;
3585
3586 for (i = 2; i < nargs; ++i)
3587 {
3588 CHECK_SEQUENCE (args[i]);
3589 len = min (len, XINT (Flength (args[i])));
3590 }
3591
3592 if (!NILP (type))
3593 {
3594 args0 = alloca_array (Lisp_Object, len);
3595 }
3596
3597 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2);
3598
3599 if (EQ (type, Qnil))
3600 {
3601 return result;
3602 }
3603
3604 if (EQ (type, Qvector) || EQ (type, Qarray))
3605 {
3606 result = Fvector (len, args0);
3607 }
3608 else if (EQ (type, Qstring))
3609 {
3610 result = Fstring (len, args0);
3611 }
3612 else if (EQ (type, Qlist))
3613 {
3614 result = Flist (len, args0);
3615 }
3616 else if (EQ (type, Qbit_vector))
3617 {
3618 result = Fbit_vector (len, args0);
3619 }
3620 else
3621 {
3622 result = Flist (len, args0);
3623 GCPRO1 (result);
3624 result = call2 (Qcoerce, result, type);
3625 UNGCPRO;
3626 }
3627
3628 return result;
3629 }
3630
3631 DEFUN ("map-into", Fmap_into, 2, MANY, 0, /*
3632 Modify RESULT-SEQUENCE using the return values of FUNCTION on SEQUENCES.
3633
3634 RESULT-SEQUENCE and SEQUENCES can be lists or arrays.
3635
3636 FUNCTION must accept at least as many arguments as there are SEQUENCES
3637 \(possibly zero). If RESULT-SEQUENCE and the elements of SEQUENCES are not
3638 the same length, stop when the shortest is exhausted; any elements of
3639 RESULT-SEQUENCE beyond that are unmodified.
3640
3641 Return RESULT-SEQUENCE.
3642
3643 arguments: (RESULT-SEQUENCE FUNCTION &rest SEQUENCES)
3644 */
3645 (int nargs, Lisp_Object *args))
3646 {
3647 Elemcount len = EMACS_INT_MAX;
3648 Lisp_Object result_sequence = args[0];
3649 Lisp_Object function = args[1];
3650 int i;
3651
3652 args[0] = function;
3653 args[1] = result_sequence;
3654
3655 for (i = 1; i < nargs; ++i)
3656 {
3657 CHECK_SEQUENCE (args[i]);
3658 len = min (len, XINT (Flength (args[i])));
3659 }
3660
3661 mapcarX (len, NULL, result_sequence, function, nargs - 2, args + 2);
3662
3663 return result_sequence;
3664 }
3665
3666 /* Call FUNCTION with NLISTS arguments repeatedly, each Nth argument
3667 corresponding to the result of calling (nthcdr ITERATION-COUNT LISTS[N]),
3668 until that #'nthcdr expression gives nil for some element of LISTS.
3669
3670 If MAPLP is zero, return LISTS[0]. Otherwise, return a list of the return
3671 values from FUNCTION; if NCONCP is non-zero, nconc them together.
3672
3673 In contrast to mapcarX, we don't require our callers to check LISTS for
3674 well-formedness, we signal wrong-type-argument if it's not a list, or
3675 circular-list if it's circular. */
3676
3677 static Lisp_Object
3678 maplist (Lisp_Object function, int nlists, Lisp_Object *lists, int maplp,
3679 int nconcp)
3680 {
3681 Lisp_Object result = maplp ? lists[0] : Fcons (Qnil, Qnil), funcalled;
3682 Lisp_Object nconcing[2], accum = result, *args;
3683 struct gcpro gcpro1, gcpro2, gcpro3;
3684 int i, j, continuing = (nlists > 0), called_count = 0;
3685
3686 args = alloca_array (Lisp_Object, nlists + 1);
3687 args[0] = function;
3688 for (i = 1; i <= nlists; ++i)
3689 {
3690 args[i] = Qnil;
3691 }
3692
3693 if (nconcp)
3694 {
3695 nconcing[0] = result;
3696 nconcing[1] = Qnil;
3697 GCPRO3 (args[0], nconcing[0], result);
3698 gcpro1.nvars = 1;
3699 gcpro2.nvars = 2;
3700 }
3701 else
3702 {
3703 GCPRO2 (args[0], result);
3704 gcpro1.nvars = 1;
3705 }
3706
3707 while (continuing)
3708 {
3709 for (j = 0; j < nlists; ++j)
3710 {
3711 if (CONSP (lists[j]))
3712 {
3713 args[j + 1] = lists[j];
3714 lists[j] = XCDR (lists[j]);
3715 }
3716 else if (NILP (lists[j]))
3717 {
3718 continuing = 0;
3719 break;
3720 }
3721 else
3722 {
3723 dead_wrong_type_argument (Qlistp, lists[j]);
3724 }
3725 }
3726 if (!continuing) break;
3727 funcalled = Ffuncall (nlists + 1, args);
3728 if (!maplp)
3729 {
3730 if (nconcp)
3731 {
3732 /* This order of calls means we check that each list is
3733 well-formed once and once only. The last result does
3734 not have to be a list. */
3735 nconcing[1] = funcalled;
3736 nconcing[0] = bytecode_nconc2 (nconcing);
3737 }
3738 else
3739 {
3740 /* Add to the end, avoiding the need to call nreverse
3741 once we're done: */
3742 XSETCDR (accum, Fcons (funcalled, Qnil));
3743 accum = XCDR (accum);
3744 }
3745 }
3746
3747 if (++called_count % CIRCULAR_LIST_SUSPICION_LENGTH) continue;
3748
3749 for (j = 0; j < nlists; ++j)
3750 {
3751 EXTERNAL_LIST_LOOP_1 (lists[j])
3752 {
3753 /* Just check the lists aren't circular, using the
3754 EXTERNAL_LIST_LOOP_1 macro. */
3755 }
3756 }
3757 }
3758
3759 if (!maplp)
3760 {
3761 result = XCDR (result);
3762 }
3763
3764 RETURN_UNGCPRO (result);
3765 }
3766
3767 DEFUN ("maplist", Fmaplist, 2, MANY, 0, /*
3768 Call FUNCTION on each sublist of LIST and LISTS.
3769 Like `mapcar', except applies to lists and their cdr's rather than to
3770 the elements themselves."
3771
3772 arguments: (FUNCTION LIST &rest LISTS)
3773 */
3774 (int nargs, Lisp_Object *args))
3775 {
3776 return maplist (args[0], nargs - 1, args + 1, 0, 0);
3777 }
3778
3779 DEFUN ("mapl", Fmapl, 2, MANY, 0, /*
3780 Like `maplist', but do not accumulate values returned by the function.
3781
3782 arguments: (FUNCTION LIST &rest LISTS)
3783 */
3784 (int nargs, Lisp_Object *args))
3785 {
3786 return maplist (args[0], nargs - 1, args + 1, 1, 0);
3787 }
3788
3789 DEFUN ("mapcon", Fmapcon, 2, MANY, 0, /*
3790 Like `maplist', but chains together the values returned by FUNCTION.
3791
3792 FUNCTION must return a list (unless it happens to be the last
3793 iteration); the results will be concatenated together using `nconc'.
3794
3795 arguments: (FUNCTION LIST &rest LISTS)
3796 */
3797 (int nargs, Lisp_Object *args))
3798 {
3799 return maplist (args[0], nargs - 1, args + 1, 0, 1);
3800 }
3355 3801
3356 /* Extra random functions */ 3802 /* Extra random functions */
3357 3803
3358 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* 3804 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /*
3359 Destructively replace the list OLD with NEW. 3805 Destructively replace the list OLD with NEW.
3393 old = Qnil; 3839 old = Qnil;
3394 3840
3395 return old; 3841 return old;
3396 } 3842 }
3397 3843
3844
3398 Lisp_Object 3845 Lisp_Object
3399 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) 3846 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string)
3400 { 3847 {
3401 return Fintern (concat2 (Fsymbol_name (symbol), 3848 return Fintern (concat2 (Fsymbol_name (symbol),
3402 build_string (ascii_string)), 3849 build_string (ascii_string)),
4031 { 4478 {
4032 INIT_LRECORD_IMPLEMENTATION (bit_vector); 4479 INIT_LRECORD_IMPLEMENTATION (bit_vector);
4033 4480
4034 DEFSYMBOL (Qstring_lessp); 4481 DEFSYMBOL (Qstring_lessp);
4035 DEFSYMBOL (Qidentity); 4482 DEFSYMBOL (Qidentity);
4483 DEFSYMBOL (Qvector);
4484 DEFSYMBOL (Qarray);
4485 DEFSYMBOL (Qstring);
4486 DEFSYMBOL (Qlist);
4487 DEFSYMBOL (Qbit_vector);
4488
4036 DEFSYMBOL (Qyes_or_no_p); 4489 DEFSYMBOL (Qyes_or_no_p);
4037 4490
4038 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); 4491 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error);
4039 4492
4040 DEFSUBR (Fidentity); 4493 DEFSUBR (Fidentity);
4107 DEFSUBR (Fobject_plist); 4560 DEFSUBR (Fobject_plist);
4108 DEFSUBR (Fequal); 4561 DEFSUBR (Fequal);
4109 DEFSUBR (Fold_equal); 4562 DEFSUBR (Fold_equal);
4110 DEFSUBR (Ffillarray); 4563 DEFSUBR (Ffillarray);
4111 DEFSUBR (Fnconc); 4564 DEFSUBR (Fnconc);
4112 DEFSUBR (Fmapcar); 4565 DEFSUBR (FmapcarX);
4113 DEFSUBR (Fmapvector); 4566 DEFSUBR (Fmapvector);
4114 DEFSUBR (Fmapc_internal); 4567 DEFSUBR (Fmapcan);
4568 DEFSUBR (Fmapc);
4115 DEFSUBR (Fmapconcat); 4569 DEFSUBR (Fmapconcat);
4570 DEFSUBR (Fmap);
4571 DEFSUBR (Fmap_into);
4572 Ffset (intern ("mapc-internal"), Fsymbol_function (intern ("mapc")));
4573 Ffset (intern ("mapcar"), Fsymbol_function (intern ("mapcar*")));
4574 DEFSUBR (Fmaplist);
4575 DEFSUBR (Fmapl);
4576 DEFSUBR (Fmapcon);
4577
4116 DEFSUBR (Freplace_list); 4578 DEFSUBR (Freplace_list);
4117 DEFSUBR (Fload_average); 4579 DEFSUBR (Fload_average);
4118 DEFSUBR (Ffeaturep); 4580 DEFSUBR (Ffeaturep);
4119 DEFSUBR (Frequire); 4581 DEFSUBR (Frequire);
4120 DEFSUBR (Fprovide); 4582 DEFSUBR (Fprovide);