Mercurial > hg > xemacs-beta
comparison src/fns.c @ 434:9d177e8d4150 r21-2-25
Import from CVS: tag r21-2-25
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:30:53 +0200 |
parents | 3ecd8885ac67 |
children | 84b14dcb0985 |
comparison
equal
deleted
inserted
replaced
433:892ca416f0fb | 434:9d177e8d4150 |
---|---|
1892 if (nil_means_not_present && NILP (v)) continue; | 1892 if (nil_means_not_present && NILP (v)) continue; |
1893 for (i = 0; i < fill; i++) | 1893 for (i = 0; i < fill; i++) |
1894 { | 1894 { |
1895 if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth)) | 1895 if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth)) |
1896 { | 1896 { |
1897 if ((eqp | 1897 if (eqp |
1898 /* We narrowly escaped being Ebolified here. */ | 1898 /* We narrowly escaped being Ebolified here. */ |
1899 ? !EQ_WITH_EBOLA_NOTICE (v, vals [i]) | 1899 ? !EQ_WITH_EBOLA_NOTICE (v, vals [i]) |
1900 : !internal_equal (v, vals [i], depth))) | 1900 : !internal_equal (v, vals [i], depth)) |
1901 /* a property in B has a different value than in A */ | 1901 /* a property in B has a different value than in A */ |
1902 goto MISMATCH; | 1902 goto MISMATCH; |
1903 flags [i] = 1; | 1903 flags [i] = 1; |
1904 break; | 1904 break; |
1905 } | 1905 } |
2862 return internal_old_equal (obj1, obj2, 0) ? Qt : Qnil; | 2862 return internal_old_equal (obj1, obj2, 0) ? Qt : Qnil; |
2863 } | 2863 } |
2864 | 2864 |
2865 | 2865 |
2866 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /* | 2866 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /* |
2867 Store each element of ARRAY with ITEM. | 2867 Destructively modify ARRAY by replacing each element with ITEM. |
2868 ARRAY is a vector, bit vector, or string. | 2868 ARRAY is a vector, bit vector, or string. |
2869 */ | 2869 */ |
2870 (array, item)) | 2870 (array, item)) |
2871 { | 2871 { |
2872 retry: | 2872 retry: |
2873 if (STRINGP (array)) | 2873 if (STRINGP (array)) |
2874 { | 2874 { |
2875 Emchar charval; | |
2876 struct Lisp_String *s = XSTRING (array); | 2875 struct Lisp_String *s = XSTRING (array); |
2877 Charcount len = string_char_length (s); | 2876 Bytecount old_bytecount = string_length (s); |
2878 Charcount i; | 2877 Bytecount new_bytecount; |
2878 Bytecount item_bytecount; | |
2879 Bufbyte item_buf[MAX_EMCHAR_LEN]; | |
2880 Bufbyte *p; | |
2881 Bufbyte *end; | |
2882 | |
2879 CHECK_CHAR_COERCE_INT (item); | 2883 CHECK_CHAR_COERCE_INT (item); |
2880 CHECK_LISP_WRITEABLE (array); | 2884 CHECK_LISP_WRITEABLE (array); |
2881 charval = XCHAR (item); | 2885 |
2882 for (i = 0; i < len; i++) | 2886 item_bytecount = set_charptr_emchar (item_buf, XCHAR (item)); |
2883 set_string_char (s, i, charval); | 2887 new_bytecount = item_bytecount * string_char_length (s); |
2888 | |
2889 resize_string (s, -1, new_bytecount - old_bytecount); | |
2890 | |
2891 for (p = string_data (s), end = p + new_bytecount; | |
2892 p < end; | |
2893 p += item_bytecount) | |
2894 memcpy (p, item_buf, item_bytecount); | |
2895 *p = '\0'; | |
2896 | |
2884 bump_string_modiff (array); | 2897 bump_string_modiff (array); |
2885 } | 2898 } |
2886 else if (VECTORP (array)) | 2899 else if (VECTORP (array)) |
2887 { | 2900 { |
2888 Lisp_Object *p = XVECTOR_DATA (array); | 2901 Lisp_Object *p = XVECTOR_DATA (array); |
3041 } | 3054 } |
3042 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ | 3055 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ |
3043 } | 3056 } |
3044 | 3057 |
3045 | 3058 |
3046 /* This is the guts of all mapping functions. | 3059 /* This is the guts of several mapping functions. |
3047 Apply fn to each element of seq, one by one, | 3060 Apply FUNCTION to each element of SEQUENCE, one by one, |
3048 storing the results into elements of vals, a C vector of Lisp_Objects. | 3061 storing the results into elements of VALS, a C vector of Lisp_Objects. |
3049 leni is the length of vals, which should also be the length of seq. | 3062 LENI is the length of VALS, which should also be the length of SEQUENCE. |
3050 | 3063 |
3051 If VALS is a null pointer, do not accumulate the results. */ | 3064 If VALS is a null pointer, do not accumulate the results. */ |
3052 | 3065 |
3053 static void | 3066 static void |
3054 mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq) | 3067 mapcar1 (size_t leni, Lisp_Object *vals, |
3068 Lisp_Object function, Lisp_Object sequence) | |
3055 { | 3069 { |
3056 Lisp_Object result; | 3070 Lisp_Object result; |
3057 Lisp_Object args[2]; | 3071 Lisp_Object args[2]; |
3058 int i; | 3072 int i; |
3059 struct gcpro gcpro1; | 3073 struct gcpro gcpro1; |
3062 { | 3076 { |
3063 GCPRO1 (vals[0]); | 3077 GCPRO1 (vals[0]); |
3064 gcpro1.nvars = 0; | 3078 gcpro1.nvars = 0; |
3065 } | 3079 } |
3066 | 3080 |
3067 args[0] = fn; | 3081 args[0] = function; |
3068 | 3082 |
3069 if (LISTP (seq)) | 3083 if (LISTP (sequence)) |
3070 { | 3084 { |
3071 for (i = 0; i < leni; i++) | 3085 /* A devious `function' could either: |
3072 { | 3086 - insert garbage into the list in front of us, causing XCDR to crash |
3073 args[1] = XCAR (seq); | 3087 - amputate the list behind us using (setcdr), causing the remaining |
3074 seq = XCDR (seq); | 3088 elts to lose their GCPRO status. |
3075 result = Ffuncall (2, args); | 3089 |
3076 if (vals) vals[gcpro1.nvars++] = result; | 3090 if (vals != 0) we avoid this by copying the elts into the |
3077 } | 3091 `vals' array. By a stroke of luck, `vals' is exactly large |
3078 } | 3092 enough to hold the elts left to be traversed as well as the |
3079 else if (VECTORP (seq)) | 3093 results computed so far. |
3080 { | 3094 |
3081 Lisp_Object *objs = XVECTOR_DATA (seq); | 3095 if (vals == 0) we don't have any free space available and |
3096 don't want to eat up any more stack with alloca(). | |
3097 So we use EXTERNAL_LIST_LOOP_3 and GCPRO the tail. */ | |
3098 | |
3099 if (vals) | |
3100 { | |
3101 Lisp_Object *val = vals; | |
3102 Lisp_Object elt; | |
3103 | |
3104 LIST_LOOP_2 (elt, sequence) | |
3105 *val++ = elt; | |
3106 | |
3107 gcpro1.nvars = leni; | |
3108 | |
3109 for (i = 0; i < leni; i++) | |
3110 { | |
3111 args[1] = vals[i]; | |
3112 vals[i] = Ffuncall (2, args); | |
3113 } | |
3114 } | |
3115 else | |
3116 { | |
3117 Lisp_Object elt, tail; | |
3118 struct gcpro ngcpro1; | |
3119 | |
3120 NGCPRO1 (tail); | |
3121 | |
3122 { | |
3123 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) | |
3124 { | |
3125 args[1] = elt; | |
3126 Ffuncall (2, args); | |
3127 } | |
3128 } | |
3129 | |
3130 NUNGCPRO; | |
3131 } | |
3132 } | |
3133 else if (VECTORP (sequence)) | |
3134 { | |
3135 Lisp_Object *objs = XVECTOR_DATA (sequence); | |
3082 for (i = 0; i < leni; i++) | 3136 for (i = 0; i < leni; i++) |
3083 { | 3137 { |
3084 args[1] = *objs++; | 3138 args[1] = *objs++; |
3085 result = Ffuncall (2, args); | 3139 result = Ffuncall (2, args); |
3086 if (vals) vals[gcpro1.nvars++] = result; | 3140 if (vals) vals[gcpro1.nvars++] = result; |
3087 } | 3141 } |
3088 } | 3142 } |
3089 else if (STRINGP (seq)) | 3143 else if (STRINGP (sequence)) |
3090 { | 3144 { |
3091 Bufbyte *p = XSTRING_DATA (seq); | 3145 /* The string data of `sequence' might be relocated during GC. */ |
3092 for (i = 0; i < leni; i++) | 3146 Bytecount slen = XSTRING_LENGTH (sequence); |
3147 Bufbyte *p = alloca_array (Bufbyte, slen); | |
3148 Bufbyte *end = p + slen; | |
3149 | |
3150 memcpy (p, XSTRING_DATA (sequence), slen); | |
3151 | |
3152 while (p < end) | |
3093 { | 3153 { |
3094 args[1] = make_char (charptr_emchar (p)); | 3154 args[1] = make_char (charptr_emchar (p)); |
3095 INC_CHARPTR (p); | 3155 INC_CHARPTR (p); |
3096 result = Ffuncall (2, args); | 3156 result = Ffuncall (2, args); |
3097 if (vals) vals[gcpro1.nvars++] = result; | 3157 if (vals) vals[gcpro1.nvars++] = result; |
3098 } | 3158 } |
3099 } | 3159 } |
3100 else if (BIT_VECTORP (seq)) | 3160 else if (BIT_VECTORP (sequence)) |
3101 { | 3161 { |
3102 struct Lisp_Bit_Vector *v = XBIT_VECTOR (seq); | 3162 struct Lisp_Bit_Vector *v = XBIT_VECTOR (sequence); |
3103 for (i = 0; i < leni; i++) | 3163 for (i = 0; i < leni; i++) |
3104 { | 3164 { |
3105 args[1] = make_int (bit_vector_bit (v, i)); | 3165 args[1] = make_int (bit_vector_bit (v, i)); |
3106 result = Ffuncall (2, args); | 3166 result = Ffuncall (2, args); |
3107 if (vals) vals[gcpro1.nvars++] = result; | 3167 if (vals) vals[gcpro1.nvars++] = result; |
3108 } | 3168 } |
3109 } | 3169 } |
3110 else | 3170 else |
3111 abort(); /* cannot get here since Flength(seq) did not get an error */ | 3171 abort(); /* cannot get here since Flength(sequence) did not get an error */ |
3112 | 3172 |
3113 if (vals) | 3173 if (vals) |
3114 UNGCPRO; | 3174 UNGCPRO; |
3115 } | 3175 } |
3116 | 3176 |
3117 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /* | 3177 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /* |
3118 Apply FN to each element of SEQ, and concat the results as strings. | 3178 Apply FUNCTION to each element of SEQUENCE, and concat the results as strings. |
3119 In between each pair of results, stick in SEP. | 3179 In between each pair of results, insert SEPARATOR. Thus, using " " as |
3120 Thus, " " as SEP results in spaces between the values returned by FN. | 3180 SEPARATOR results in spaces between the values returned by FUNCTION. |
3121 */ | 3181 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3122 (fn, seq, sep)) | 3182 */ |
3123 { | 3183 (function, sequence, separator)) |
3124 size_t len = XINT (Flength (seq)); | 3184 { |
3185 size_t len = XINT (Flength (sequence)); | |
3125 Lisp_Object *args; | 3186 Lisp_Object *args; |
3126 int i; | 3187 int i; |
3127 struct gcpro gcpro1; | 3188 struct gcpro gcpro1; |
3128 int nargs = len + len - 1; | 3189 int nargs = len + len - 1; |
3129 | 3190 |
3130 if (nargs < 0) return build_string (""); | 3191 if (nargs < 0) return build_string (""); |
3131 | 3192 |
3132 args = alloca_array (Lisp_Object, nargs); | 3193 args = alloca_array (Lisp_Object, nargs); |
3133 | 3194 |
3134 GCPRO1 (sep); | 3195 GCPRO1 (separator); |
3135 mapcar1 (len, args, fn, seq); | 3196 mapcar1 (len, args, function, sequence); |
3136 UNGCPRO; | 3197 UNGCPRO; |
3137 | 3198 |
3138 for (i = len - 1; i >= 0; i--) | 3199 for (i = len - 1; i >= 0; i--) |
3139 args[i + i] = args[i]; | 3200 args[i + i] = args[i]; |
3140 | 3201 |
3141 for (i = 1; i < nargs; i += 2) | 3202 for (i = 1; i < nargs; i += 2) |
3142 args[i] = sep; | 3203 args[i] = separator; |
3143 | 3204 |
3144 return Fconcat (nargs, args); | 3205 return Fconcat (nargs, args); |
3145 } | 3206 } |
3146 | 3207 |
3147 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* | 3208 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* |
3148 Apply FUNCTION to each element of SEQUENCE, and make a list of the results. | 3209 Apply FUNCTION to each element of SEQUENCE; return a list of the results. |
3149 The result is a list just as long as SEQUENCE. | 3210 The result is a list of the same length as SEQUENCE. |
3150 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3211 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3151 */ | 3212 */ |
3152 (fn, seq)) | 3213 (function, sequence)) |
3153 { | 3214 { |
3154 size_t len = XINT (Flength (seq)); | 3215 size_t len = XINT (Flength (sequence)); |
3155 Lisp_Object *args = alloca_array (Lisp_Object, len); | 3216 Lisp_Object *args = alloca_array (Lisp_Object, len); |
3156 | 3217 |
3157 mapcar1 (len, args, fn, seq); | 3218 mapcar1 (len, args, function, sequence); |
3158 | 3219 |
3159 return Flist (len, args); | 3220 return Flist (len, args); |
3160 } | 3221 } |
3161 | 3222 |
3162 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* | 3223 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* |
3163 Apply FUNCTION to each element of SEQUENCE, making a vector of the results. | 3224 Apply FUNCTION to each element of SEQUENCE; return a vector of the results. |
3164 The result is a vector of the same length as SEQUENCE. | 3225 The result is a vector of the same length as SEQUENCE. |
3165 SEQUENCE may be a list, a vector or a string. | 3226 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3166 */ | 3227 */ |
3167 (fn, seq)) | 3228 (function, sequence)) |
3168 { | 3229 { |
3169 size_t len = XINT (Flength (seq)); | 3230 size_t len = XINT (Flength (sequence)); |
3170 Lisp_Object result = make_vector (len, Qnil); | 3231 Lisp_Object result = make_vector (len, Qnil); |
3171 struct gcpro gcpro1; | 3232 struct gcpro gcpro1; |
3172 | 3233 |
3173 GCPRO1 (result); | 3234 GCPRO1 (result); |
3174 mapcar1 (len, XVECTOR_DATA (result), fn, seq); | 3235 mapcar1 (len, XVECTOR_DATA (result), function, sequence); |
3175 UNGCPRO; | 3236 UNGCPRO; |
3176 | 3237 |
3177 return result; | 3238 return result; |
3178 } | 3239 } |
3179 | 3240 |
3184 which is more efficient if you do not use the results. | 3245 which is more efficient if you do not use the results. |
3185 | 3246 |
3186 The difference between this and `mapc' is that `mapc' supports all | 3247 The difference between this and `mapc' is that `mapc' supports all |
3187 the spiffy Common Lisp arguments. You should normally use `mapc'. | 3248 the spiffy Common Lisp arguments. You should normally use `mapc'. |
3188 */ | 3249 */ |
3189 (fn, seq)) | 3250 (function, sequence)) |
3190 { | 3251 { |
3191 mapcar1 (XINT (Flength (seq)), 0, fn, seq); | 3252 mapcar1 (XINT (Flength (sequence)), 0, function, sequence); |
3192 | 3253 |
3193 return seq; | 3254 return sequence; |
3194 } | 3255 } |
3195 | 3256 |
3196 | 3257 |
3197 /* #### this function doesn't belong in this file! */ | 3258 /* #### this function doesn't belong in this file! */ |
3198 | 3259 |