comparison src/fns.c @ 5272:66dbef5f8076

Be better about bounds-checking, #'subseq, #'fill; add same, #'reduce. 2010-09-16 Aidan Kehoe <kehoea@parhasard.net> * fns.c (Fsubseq): Change the string code to better fit in with the rest of this function (it still uses get_string_range_char(), though, which *may* diverge algorithmically from what we're doing). If dealing with a cons, only call #'length if we have reason to believe that the START and END arguments are badly specified, and check for circular lists ourselves when that's appropriate. If dealing with a vector, call Fvector() on the appropriate subset of the old vector's data directly, don't initialise the result with nil and then copy. (Ffill): Only check the range arguments for a cons SEQUENCE if we have good reason to think they were badly specified. (Freduce): Handle multiple values properly. Add bounds checking to this function, as specificied by ANSI Common Lisp.
author Aidan Kehoe <kehoea@parhasard.net>
date Thu, 16 Sep 2010 18:46:05 +0100
parents 75bcb5bef459
children 799742b751c8
comparison
equal deleted inserted replaced
5271:2def0d83a5e3 5272:66dbef5f8076
1009 } 1009 }
1010 1010
1011 DEFUN ("subseq", Fsubseq, 2, 3, 0, /* 1011 DEFUN ("subseq", Fsubseq, 2, 3, 0, /*
1012 Return the subsequence of SEQUENCE starting at START and ending before END. 1012 Return the subsequence of SEQUENCE starting at START and ending before END.
1013 END may be omitted; then the subsequence runs to the end of SEQUENCE. 1013 END may be omitted; then the subsequence runs to the end of SEQUENCE.
1014 If START or END is negative, it counts from the end. 1014
1015 If START or END is negative, it counts from the end, in contravention of
1016 Common Lisp.
1015 The returned subsequence is always of the same type as SEQUENCE. 1017 The returned subsequence is always of the same type as SEQUENCE.
1016 If SEQUENCE is a string, relevant parts of the string-extent-data 1018 If SEQUENCE is a string, relevant parts of the string-extent-data
1017 are copied to the new string. 1019 are copied to the new string.
1018 1020
1019 See also `substring-no-properties', which only operates on strings, and does 1021 See also `substring-no-properties', which only operates on strings, and does
1020 not copy extent data. 1022 not copy extent data.
1021 */ 1023 */
1022 (sequence, start, end)) 1024 (sequence, start, end))
1023 { 1025 {
1024 EMACS_INT len, s, e; 1026 Elemcount len, ss, ee = EMACS_INT_MAX, ii;
1027 Lisp_Object result = Qnil;
1028
1029 CHECK_SEQUENCE (sequence);
1030 CHECK_INT (start);
1031 ss = XINT (start);
1032
1033 if (!NILP (end))
1034 {
1035 CHECK_INT (end);
1036 ee = XINT (end);
1037 }
1025 1038
1026 if (STRINGP (sequence)) 1039 if (STRINGP (sequence))
1027 { 1040 {
1028 Charcount ccstart, ccend;
1029 Bytecount bstart, blen; 1041 Bytecount bstart, blen;
1030 Lisp_Object val; 1042
1031 1043 get_string_range_char (sequence, start, end, &ss, &ee,
1032 CHECK_INT (start);
1033 get_string_range_char (sequence, start, end, &ccstart, &ccend,
1034 GB_HISTORICAL_STRING_BEHAVIOR); 1044 GB_HISTORICAL_STRING_BEHAVIOR);
1035 bstart = string_index_char_to_byte (sequence, ccstart); 1045 bstart = string_index_char_to_byte (sequence, ss);
1036 blen = string_offset_char_to_byte_len (sequence, bstart, ccend - ccstart); 1046 blen = string_offset_char_to_byte_len (sequence, bstart, ee - ss);
1037 val = make_string (XSTRING_DATA (sequence) + bstart, blen); 1047
1048 result = make_string (XSTRING_DATA (sequence) + bstart, blen);
1038 /* Copy any applicable extent information into the new string. */ 1049 /* Copy any applicable extent information into the new string. */
1039 copy_string_extents (val, sequence, 0, bstart, blen); 1050 copy_string_extents (result, sequence, 0, bstart, blen);
1040 return val; 1051 }
1041 } 1052 else if (CONSP (sequence))
1042 1053 {
1043 CHECK_SEQUENCE (sequence); 1054 Lisp_Object result_tail, saved = sequence;
1044 1055
1045 len = XINT (Flength (sequence)); 1056 if (ss < 0 || ee < 0)
1046 1057 {
1047 CHECK_INT (start); 1058 len = XINT (Flength (sequence));
1048 s = XINT (start); 1059 if (ss < 0)
1049 if (s < 0) 1060 {
1050 s = len + s; 1061 ss = len + ss;
1051 1062 start = make_integer (ss);
1052 if (NILP (end)) 1063 }
1053 e = len; 1064
1054 else 1065 if (ee < 0)
1055 { 1066 {
1056 CHECK_INT (end); 1067 ee = len + ee;
1057 e = XINT (end); 1068 end = make_integer (ee);
1058 if (e < 0) 1069 }
1059 e = len + e; 1070 else
1060 } 1071 {
1061 1072 ee = min (ee, len);
1062 check_sequence_range (sequence, make_int (s), make_int (e), 1073 }
1063 make_int (len)); 1074 }
1064 1075
1065 if (VECTORP (sequence)) 1076 if (0 != ss)
1066 { 1077 {
1067 Lisp_Object result = make_vector (e - s, Qnil); 1078 sequence = Fnthcdr (make_int (ss), sequence);
1068 EMACS_INT i; 1079 }
1069 Lisp_Object *in_elts = XVECTOR_DATA (sequence); 1080
1070 Lisp_Object *out_elts = XVECTOR_DATA (result); 1081 if (ss < ee && !NILP (sequence))
1071 1082 {
1072 for (i = s; i < e; i++)
1073 out_elts[i - s] = in_elts[i];
1074 return result;
1075 }
1076 else if (LISTP (sequence))
1077 {
1078 Lisp_Object result = Qnil, result_tail;
1079 EMACS_INT i;
1080
1081 sequence = Fnthcdr (make_int (s), sequence);
1082
1083 if (s < e)
1084 {
1085 result = result_tail = Fcons (Fcar (sequence), Qnil); 1083 result = result_tail = Fcons (Fcar (sequence), Qnil);
1086 sequence = Fcdr (sequence); 1084 sequence = Fcdr (sequence);
1087 for (i = s + 1; i < e; i++) 1085 ii = ss + 1;
1088 { 1086
1089 XSETCDR (result_tail, Fcons (Fcar (sequence), Qnil)); 1087 {
1090 sequence = Fcdr (sequence); 1088 EXTERNAL_LIST_LOOP_2 (elt, sequence)
1091 result_tail = XCDR (result_tail); 1089 {
1092 } 1090 if (!(ii < ee))
1091 {
1092 break;
1093 }
1094
1095 XSETCDR (result_tail, Fcons (elt, Qnil));
1096 result_tail = XCDR (result_tail);
1097 ii++;
1098 }
1099 }
1100 }
1101
1102 if (NILP (result) || (ii < ee && !NILP (end)))
1103 {
1104 /* We were handed a cons, which definitely has elements. nil
1105 result means either ss >= ee or SEQUENCE was nil after the
1106 nthcdr; in both cases that means START and END were incorrectly
1107 specified for this sequence. ii < ee with a non-nil end means
1108 the user handed us a bogus end value. */
1109 check_sequence_range (saved, start, end, Flength (saved));
1110 }
1111 }
1112 else
1113 {
1114 len = XINT (Flength (sequence));
1115 if (ss < 0)
1116 {
1117 ss = len + ss;
1118 start = make_integer (ss);
1093 } 1119 }
1094 1120
1095 return result; 1121 if (ee < 0)
1096 } 1122 {
1097 else if (BIT_VECTORP (sequence)) 1123 ee = len + ee;
1098 { 1124 end = make_integer (ee);
1099 Lisp_Object result = make_bit_vector (e - s, Qzero); 1125 }
1100 EMACS_INT i; 1126 else
1101 1127 {
1102 for (i = s; i < e; i++) 1128 ee = min (len, ee);
1103 set_bit_vector_bit (XBIT_VECTOR (result), i - s, 1129 }
1104 bit_vector_bit (XBIT_VECTOR (sequence), i)); 1130
1105 return result; 1131 check_sequence_range (sequence, start, end, make_int (len));
1106 } 1132
1107 else 1133 if (VECTORP (sequence))
1108 { 1134 {
1109 ABORT (); /* unreachable, since CHECK_SEQUENCE (sequence) did not 1135 result = Fvector (ee - ss, XVECTOR_DATA (sequence) + ss);
1110 error */ 1136 }
1111 return Qnil; 1137 else if (BIT_VECTORP (sequence))
1112 } 1138 {
1139 result = make_bit_vector (ee - ss, Qzero);
1140
1141 for (ii = ss; ii < ee; ii++)
1142 {
1143 set_bit_vector_bit (XBIT_VECTOR (result), ii - ss,
1144 bit_vector_bit (XBIT_VECTOR (sequence), ii));
1145 }
1146 }
1147 else if (NILP (sequence))
1148 {
1149 DO_NOTHING;
1150 }
1151 else
1152 {
1153 /* Won't happen, since CHECK_SEQUENCE didn't error. */
1154 ABORT ();
1155 }
1156 }
1157
1158 return result;
1113 } 1159 }
1114 1160
1115 DEFUN ("substring-no-properties", Fsubstring_no_properties, 1, 3, 0, /* 1161 DEFUN ("substring-no-properties", Fsubstring_no_properties, 1, 3, 0, /*
1116 Return a substring of STRING, without copying the extents. 1162 Return a substring of STRING, without copying the extents.
1117 END may be nil or omitted; then the substring runs to the end of STRING. 1163 END may be nil or omitted; then the substring runs to the end of STRING.
4003 } 4049 }
4004 } 4050 }
4005 ++counting; 4051 ++counting;
4006 } 4052 }
4007 4053
4008 if (counting != ending) 4054 if (counting < starting || (counting != ending && !NILP (end)))
4009 { 4055 {
4010 check_sequence_range (sequence, start, end, Flength (sequence)); 4056 check_sequence_range (args[0], start, end, Flength (args[0]));
4011 } 4057 }
4012 } 4058 }
4013 else 4059 else
4014 { 4060 {
4015 sequence = wrong_type_argument (Qsequencep, sequence); 4061 sequence = wrong_type_argument (Qsequencep, sequence);
4968 CHECK_SEQUENCE (sequence); 5014 CHECK_SEQUENCE (sequence);
4969 CHECK_NATNUM (start); 5015 CHECK_NATNUM (start);
4970 5016
4971 CHECK_KEY_ARGUMENT (key); 5017 CHECK_KEY_ARGUMENT (key);
4972 5018
4973 #define KEY(key, item) (EQ (key, Qidentity) ? item : call1 (key, item)) 5019 #define KEY(key, item) (EQ (Qidentity, key) ? item : \
5020 IGNORE_MULTIPLE_VALUES (call1 (key, item)))
5021 #define CALL2(function, accum, item) \
5022 IGNORE_MULTIPLE_VALUES (call2 (function, accum, item))
4974 5023
4975 starting = XINT (start); 5024 starting = XINT (start);
4976 if (!NILP (end)) 5025 if (!NILP (end))
4977 { 5026 {
4978 CHECK_NATNUM (end); 5027 CHECK_NATNUM (end);
4979 ending = XINT (end); 5028 ending = XINT (end);
4980 } 5029 }
4981 5030
5031 if (!(starting <= ending))
5032 {
5033 check_sequence_range (sequence, start, end, Flength (sequence));
5034 }
5035
4982 if (VECTORP (sequence)) 5036 if (VECTORP (sequence))
4983 { 5037 {
4984 Lisp_Vector *vv = XVECTOR (sequence); 5038 Lisp_Vector *vv = XVECTOR (sequence);
5039
5040 check_sequence_range (sequence, start, end, make_int (vv->size));
5041
4985 ending = min (ending, vv->size); 5042 ending = min (ending, vv->size);
4986 5043
4987 if (!UNBOUNDP (initial_value)) 5044 if (!UNBOUNDP (initial_value))
4988 { 5045 {
4989 accum = initial_value; 5046 accum = initial_value;
4990 } 5047 }
4991 else if (ending - starting && starting < ending) 5048 else if (ending - starting)
4992 { 5049 {
4993 if (NILP (from_end)) 5050 if (NILP (from_end))
4994 { 5051 {
4995 accum = KEY (key, vv->contents[starting]); 5052 accum = KEY (key, vv->contents[starting]);
4996 starting++; 5053 starting++;
5004 5061
5005 if (NILP (from_end)) 5062 if (NILP (from_end))
5006 { 5063 {
5007 for (ii = starting; ii < ending; ++ii) 5064 for (ii = starting; ii < ending; ++ii)
5008 { 5065 {
5009 accum = call2 (function, accum, KEY (key, vv->contents[ii])); 5066 accum = CALL2 (function, accum, KEY (key, vv->contents[ii]));
5010 } 5067 }
5011 } 5068 }
5012 else 5069 else
5013 { 5070 {
5014 for (ii = ending - 1; ii >= starting; --ii) 5071 for (ii = ending - 1; ii >= starting; --ii)
5015 { 5072 {
5016 accum = call2 (function, KEY (key, vv->contents[ii]), accum); 5073 accum = CALL2 (function, KEY (key, vv->contents[ii]), accum);
5017 } 5074 }
5018 } 5075 }
5019 } 5076 }
5020 else if (BIT_VECTORP (sequence)) 5077 else if (BIT_VECTORP (sequence))
5021 { 5078 {
5022 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence); 5079 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
5023 5080
5081 check_sequence_range (sequence, start, end, make_int (bv->size));
5082
5024 ending = min (ending, bv->size); 5083 ending = min (ending, bv->size);
5025 5084
5026 if (!UNBOUNDP (initial_value)) 5085 if (!UNBOUNDP (initial_value))
5027 { 5086 {
5028 accum = initial_value; 5087 accum = initial_value;
5029 } 5088 }
5030 else if (ending - starting && starting < ending) 5089 else if (ending - starting)
5031 { 5090 {
5032 if (NILP (from_end)) 5091 if (NILP (from_end))
5033 { 5092 {
5034 accum = KEY (key, make_int (bit_vector_bit (bv, starting))); 5093 accum = KEY (key, make_int (bit_vector_bit (bv, starting)));
5035 starting++; 5094 starting++;
5043 5102
5044 if (NILP (from_end)) 5103 if (NILP (from_end))
5045 { 5104 {
5046 for (ii = starting; ii < ending; ++ii) 5105 for (ii = starting; ii < ending; ++ii)
5047 { 5106 {
5048 accum = call2 (function, accum, 5107 accum = CALL2 (function, accum,
5049 KEY (key, make_int (bit_vector_bit (bv, ii)))); 5108 KEY (key, make_int (bit_vector_bit (bv, ii))));
5050 } 5109 }
5051 } 5110 }
5052 else 5111 else
5053 { 5112 {
5054 for (ii = ending - 1; ii >= starting; --ii) 5113 for (ii = ending - 1; ii >= starting; --ii)
5055 { 5114 {
5056 accum = call2 (function, KEY (key, 5115 accum = CALL2 (function, KEY (key,
5057 make_int (bit_vector_bit (bv, 5116 make_int (bit_vector_bit (bv,
5058 ii))), 5117 ii))),
5059 accum); 5118 accum);
5060 } 5119 }
5061 } 5120 }
5062
5063 } 5121 }
5064 else if (STRINGP (sequence)) 5122 else if (STRINGP (sequence))
5065 { 5123 {
5066 if (NILP (from_end)) 5124 if (NILP (from_end))
5067 { 5125 {
5078 5136
5079 if (!UNBOUNDP (initial_value)) 5137 if (!UNBOUNDP (initial_value))
5080 { 5138 {
5081 accum = initial_value; 5139 accum = initial_value;
5082 } 5140 }
5083 else if (ending - starting && starting < ending) 5141 else if (ending - starting)
5084 { 5142 {
5085 accum = KEY (key, make_char (itext_ichar (cursor))); 5143 accum = KEY (key, make_char (itext_ichar (cursor)));
5086 starting++; 5144 starting++;
5087 startp = XSTRING_DATA (sequence); 5145 startp = XSTRING_DATA (sequence);
5088 cursor = startp + cursor_offset; 5146 cursor = startp + cursor_offset;
5095 5153
5096 INC_IBYTEPTR (cursor); 5154 INC_IBYTEPTR (cursor);
5097 cursor_offset = cursor - startp; 5155 cursor_offset = cursor - startp;
5098 } 5156 }
5099 5157
5100 while (cursor_offset < byte_len && starting < ending) 5158 while (cursor_offset < byte_len && ii < ending)
5101 { 5159 {
5102 accum = call2 (function, accum, 5160 accum = CALL2 (function, accum,
5103 KEY (key, make_char (itext_ichar (cursor)))); 5161 KEY (key, make_char (itext_ichar (cursor))));
5104 5162
5105 startp = XSTRING_DATA (sequence); 5163 startp = XSTRING_DATA (sequence);
5106 cursor = startp + cursor_offset; 5164 cursor = startp + cursor_offset;
5107 5165
5111 mapping_interaction_error (Qreduce, sequence); 5169 mapping_interaction_error (Qreduce, sequence);
5112 } 5170 }
5113 5171
5114 INC_IBYTEPTR (cursor); 5172 INC_IBYTEPTR (cursor);
5115 cursor_offset = cursor - startp; 5173 cursor_offset = cursor - startp;
5116 ++starting; 5174 ++ii;
5117 } 5175 }
5176
5177 if (ii < starting || (ii < ending && !NILP (end)))
5178 {
5179 check_sequence_range (sequence, start, end, Flength (sequence));
5180 ABORT ();
5181 }
5118 } 5182 }
5119 else 5183 else
5120 { 5184 {
5121 Elemcount len = string_char_length (sequence); 5185 Elemcount len = string_char_length (sequence);
5122 Bytecount cursor_offset, byte_len = XSTRING_LENGTH (sequence); 5186 Bytecount cursor_offset, byte_len = XSTRING_LENGTH (sequence);
5123 const Ibyte *cursor; 5187 const Ibyte *cursor;
5124 5188
5189 check_sequence_range (sequence, start, end, make_int (len));
5190
5125 ending = min (ending, len); 5191 ending = min (ending, len);
5126 cursor = string_char_addr (sequence, ending - 1); 5192 cursor = string_char_addr (sequence, ending - 1);
5127 cursor_offset = cursor - XSTRING_DATA (sequence); 5193 cursor_offset = cursor - XSTRING_DATA (sequence);
5128 5194
5129 if (!UNBOUNDP (initial_value)) 5195 if (!UNBOUNDP (initial_value))
5130 { 5196 {
5131 accum = initial_value; 5197 accum = initial_value;
5132 } 5198 }
5133 else if (ending - starting && starting < ending) 5199 else if (ending - starting)
5134 { 5200 {
5135 accum = KEY (key, make_char (itext_ichar (cursor))); 5201 accum = KEY (key, make_char (itext_ichar (cursor)));
5136 ending--; 5202 ending--;
5137 if (ending > 0) 5203 if (ending > 0)
5138 { 5204 {
5148 } 5214 }
5149 } 5215 }
5150 5216
5151 for (ii = ending - 1; ii >= starting; --ii) 5217 for (ii = ending - 1; ii >= starting; --ii)
5152 { 5218 {
5153 accum = call2 (function, KEY (key, 5219 accum = CALL2 (function, KEY (key,
5154 make_char (itext_ichar (cursor))), 5220 make_char (itext_ichar (cursor))),
5155 accum); 5221 accum);
5156 if (ii > 0) 5222 if (ii > 0)
5157 { 5223 {
5158 cursor = XSTRING_DATA (sequence) + cursor_offset; 5224 cursor = XSTRING_DATA (sequence) + cursor_offset;
5180 5246
5181 if (!UNBOUNDP (initial_value)) 5247 if (!UNBOUNDP (initial_value))
5182 { 5248 {
5183 accum = initial_value; 5249 accum = initial_value;
5184 } 5250 }
5185 else if (ending - starting && starting < ending) 5251 else if (ending - starting)
5186 { 5252 {
5187 Elemcount counting = 0; 5253 ii = 0;
5188 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) 5254 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
5189 { 5255 {
5190 /* KEY may amputate the list behind us; make sure what 5256 /* KEY may amputate the list behind us; make sure what
5191 remains to be processed is still reachable. */ 5257 remains to be processed is still reachable. */
5192 tailed = tail; 5258 tailed = tail;
5193 if (counting == starting) 5259 if (ii == starting)
5194 { 5260 {
5195 accum = KEY (key, elt); 5261 accum = KEY (key, elt);
5196 starting++; 5262 starting++;
5197 break; 5263 break;
5198 } 5264 }
5199 ++counting; 5265 ++ii;
5200 } 5266 }
5201 } 5267 }
5202 5268
5203 if (ending - starting && starting < ending) 5269 if (ending - starting)
5204 { 5270 {
5205 Elemcount counting = 0; 5271 ii = 0;
5206 5272
5207 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) 5273 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
5208 { 5274 {
5209 /* KEY or FUNCTION may amputate the list behind us; make 5275 /* KEY or FUNCTION may amputate the list behind us; make
5210 sure what remains to be processed is still 5276 sure what remains to be processed is still
5211 reachable. */ 5277 reachable. */
5212 tailed = tail; 5278 tailed = tail;
5213 if (counting >= starting) 5279 if (ii >= starting)
5214 { 5280 {
5215 if (counting < ending) 5281 if (ii < ending)
5216 { 5282 {
5217 accum = call2 (function, accum, KEY (key, elt)); 5283 accum = CALL2 (function, accum, KEY (key, elt));
5218 } 5284 }
5219 else if (counting == ending) 5285 else if (ii == ending)
5220 { 5286 {
5221 break; 5287 break;
5222 } 5288 }
5223 } 5289 }
5224 ++counting; 5290 ++ii;
5225 } 5291 }
5226 } 5292 }
5227 5293
5228 UNGCPRO; 5294 UNGCPRO;
5295
5296 if (ii < starting || (ii < ending && !NILP (end)))
5297 {
5298 check_sequence_range (sequence, start, end, Flength (sequence));
5299 ABORT ();
5300 }
5229 } 5301 }
5230 else 5302 else
5231 { 5303 {
5232 Boolint need_accum = 0; 5304 Boolint need_accum = 0;
5233 Lisp_Object *subsequence = NULL; 5305 Lisp_Object *subsequence = NULL;
5234 Elemcount counting = 0, len = 0; 5306 Elemcount counting = 0, len = 0;
5235 struct gcpro gcpro1; 5307 struct gcpro gcpro1;
5236 5308
5237 if (ending - starting && starting < ending 5309 len = XINT (Flength (sequence));
5238 && EMACS_INT_MAX == ending) 5310 check_sequence_range (sequence, start, end, make_int (len));
5239 { 5311 ending = min (ending, len);
5240 ending = XINT (Flength (sequence));
5241 }
5242 5312
5243 /* :from-end with a list; make an alloca copy of the relevant list 5313 /* :from-end with a list; make an alloca copy of the relevant list
5244 data, attempting to go backwards isn't worth the trouble. */ 5314 data, attempting to go backwards isn't worth the trouble. */
5245 if (!UNBOUNDP (initial_value)) 5315 if (!UNBOUNDP (initial_value))
5246 { 5316 {
5293 } 5363 }
5294 5364
5295 for (ii = len; ii != 0;) 5365 for (ii = len; ii != 0;)
5296 { 5366 {
5297 --ii; 5367 --ii;
5298 accum = call2 (function, KEY (key, subsequence[ii]), accum); 5368 accum = CALL2 (function, KEY (key, subsequence[ii]), accum);
5299 } 5369 }
5300 5370
5301 if (subsequence != NULL) 5371 if (subsequence != NULL)
5302 { 5372 {
5303 UNGCPRO; 5373 UNGCPRO;
5308 /* At this point, if ACCUM is unbound, SEQUENCE has no elements; we 5378 /* At this point, if ACCUM is unbound, SEQUENCE has no elements; we
5309 need to return the result of calling FUNCTION with zero 5379 need to return the result of calling FUNCTION with zero
5310 arguments. */ 5380 arguments. */
5311 if (UNBOUNDP (accum)) 5381 if (UNBOUNDP (accum))
5312 { 5382 {
5313 accum = call0 (function); 5383 accum = IGNORE_MULTIPLE_VALUES (call0 (function));
5314 } 5384 }
5315 5385
5316 return accum; 5386 return accum;
5317 } 5387 }
5318 5388
5468 (int nargs, Lisp_Object *args)) 5538 (int nargs, Lisp_Object *args))
5469 { 5539 {
5470 Lisp_Object sequence1 = args[0], sequence2 = args[1], 5540 Lisp_Object sequence1 = args[0], sequence2 = args[1],
5471 result = sequence1; 5541 result = sequence1;
5472 Elemcount starting1, ending1 = EMACS_INT_MAX, starting2; 5542 Elemcount starting1, ending1 = EMACS_INT_MAX, starting2;
5473 Elemcount ending2 = EMACS_INT_MAX, counting, startcounting; 5543 Elemcount ending2 = EMACS_INT_MAX, counting = 0, startcounting;
5474 Boolint sequence1_listp, sequence2_listp, 5544 Boolint sequence1_listp, sequence2_listp,
5475 overwriting = EQ (sequence1, sequence2); 5545 overwriting = EQ (sequence1, sequence2);
5476 5546
5477 PARSE_KEYWORDS (Qreplace, nargs, args, 2, 4, (start1, end1, start2, end2), 5547 PARSE_KEYWORDS (Qreplace, nargs, args, 2, 4, (start1, end1, start2, end2),
5478 (start1 = start2 = Qzero), 0); 5548 (start1 = start2 = Qzero), 0);
5514 5584
5515 overwriting = overwriting && starting2 <= starting1; 5585 overwriting = overwriting && starting2 <= starting1;
5516 5586
5517 if (sequence1_listp && !ZEROP (start1)) 5587 if (sequence1_listp && !ZEROP (start1))
5518 { 5588 {
5519 Lisp_Object nthcdrd = Fnthcdr (start1, sequence1); 5589 sequence1 = Fnthcdr (start1, sequence1);
5520 5590
5521 if (NILP (nthcdrd)) 5591 if (NILP (sequence1))
5522 { 5592 {
5523 check_sequence_range (sequence1, start1, end1, Flength (sequence1)); 5593 check_sequence_range (args[0], start1, end1, Flength (args[0]));
5524 /* Give up early here. */ 5594 /* Give up early here. */
5525 return result; 5595 return result;
5526 } 5596 }
5527 5597
5528 sequence1 = nthcdrd;
5529 ending1 -= starting1; 5598 ending1 -= starting1;
5530 starting1 = 0; 5599 starting1 = 0;
5531 } 5600 }
5532 5601
5533 if (sequence2_listp && !ZEROP (start2)) 5602 if (sequence2_listp && !ZEROP (start2))
5534 { 5603 {
5535 Lisp_Object nthcdrd = Fnthcdr (start2, sequence2); 5604 sequence2 = Fnthcdr (start2, sequence2);
5536 5605
5537 if (NILP (nthcdrd)) 5606 if (NILP (sequence2))
5538 { 5607 {
5539 check_sequence_range (sequence1, start1, end1, Flength (sequence1)); 5608 check_sequence_range (args[1], start1, end1, Flength (args[1]));
5540 /* Nothing available to replace sequence1's contents. */ 5609 /* Nothing available to replace sequence1's contents. */
5541 return result; 5610 return result;
5542 } 5611 }
5543 5612
5544 sequence2 = nthcdrd;
5545 ending2 -= starting2; 5613 ending2 -= starting2;
5546 starting2 = 0; 5614 starting2 = 0;
5547 } 5615 }
5548 5616
5549 if (overwriting) 5617 if (overwriting)
5558 if (CONSP (sequence2)) 5626 if (CONSP (sequence2))
5559 { 5627 {
5560 Elemcount len = XINT (Flength (sequence2)); 5628 Elemcount len = XINT (Flength (sequence2));
5561 Lisp_Object *subsequence 5629 Lisp_Object *subsequence
5562 = alloca_array (Lisp_Object, min (ending2, len)); 5630 = alloca_array (Lisp_Object, min (ending2, len));
5563 Elemcount counting = 0, ii = 0; 5631 Elemcount ii = 0;
5564 5632
5565 LIST_LOOP_2 (elt, sequence2) 5633 LIST_LOOP_2 (elt, sequence2)
5566 { 5634 {
5567 if (counting == ending2) 5635 if (counting == ending2)
5568 { 5636 {