@@ -190,48 +190,66 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
190
190
{
191
191
int i1 , i2 ;
192
192
193
+ if (!(flags & XDF_WHITESPACE_FLAGS ))
194
+ return s1 == s2 && !memcmp (l1 , l2 , s1 );
195
+
196
+ i1 = 0 ;
197
+ i2 = 0 ;
198
+
199
+ /*
200
+ * -w matches everything that matches with -b, and -b in turn
201
+ * matches everything that matches with --ignore-space-at-eol.
202
+ *
203
+ * Each flavor of ignoring needs different logic to skip whitespaces
204
+ * while we have both sides to compare.
205
+ */
193
206
if (flags & XDF_IGNORE_WHITESPACE ) {
194
- for (i1 = i2 = 0 ; i1 < s1 && i2 < s2 ; ) {
195
- if (isspace (l1 [i1 ]))
196
- while (isspace (l1 [i1 ]) && i1 < s1 )
197
- i1 ++ ;
198
- if (isspace (l2 [i2 ]))
199
- while (isspace (l2 [i2 ]) && i2 < s2 )
200
- i2 ++ ;
201
- if (i1 < s1 && i2 < s2 && l1 [i1 ++ ] != l2 [i2 ++ ])
207
+ goto skip_ws ;
208
+ while (i1 < s1 && i2 < s2 ) {
209
+ if (l1 [i1 ++ ] != l2 [i2 ++ ])
202
210
return 0 ;
211
+ skip_ws :
212
+ while (i1 < s1 && isspace (l1 [i1 ]))
213
+ i1 ++ ;
214
+ while (i2 < s2 && isspace (l2 [i2 ]))
215
+ i2 ++ ;
203
216
}
204
- return (i1 >= s1 && i2 >= s2 );
205
217
} else if (flags & XDF_IGNORE_WHITESPACE_CHANGE ) {
206
- for (i1 = i2 = 0 ; i1 < s1 && i2 < s2 ; ) {
207
- if (isspace (l1 [i1 ])) {
208
- if (!isspace (l2 [i2 ]))
209
- return 0 ;
210
- while (isspace (l1 [i1 ]) && i1 < s1 )
211
- i1 ++ ;
212
- while (isspace (l2 [i2 ]) && i2 < s2 )
213
- i2 ++ ;
214
- } else if (l1 [i1 ++ ] != l2 [i2 ++ ])
215
- return 0 ;
216
- }
217
- return (i1 >= s1 && i2 >= s2 );
218
- } else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL ) {
219
- for (i1 = i2 = 0 ; i1 < s1 && i2 < s2 ; ) {
220
- if (l1 [i1 ] != l2 [i2 ]) {
218
+ while (i1 < s1 && i2 < s2 ) {
219
+ if (isspace (l1 [i1 ]) && isspace (l2 [i2 ])) {
220
+ /* Skip matching spaces and try again */
221
221
while (i1 < s1 && isspace (l1 [i1 ]))
222
222
i1 ++ ;
223
223
while (i2 < s2 && isspace (l2 [i2 ]))
224
224
i2 ++ ;
225
- if (i1 < s1 || i2 < s2 )
226
- return 0 ;
227
- return 1 ;
225
+ continue ;
228
226
}
227
+ if (l1 [i1 ++ ] != l2 [i2 ++ ])
228
+ return 0 ;
229
+ }
230
+ } else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL ) {
231
+ while (i1 < s1 && i2 < s2 && l1 [i1 ++ ] == l2 [i2 ++ ])
232
+ ; /* keep going */
233
+ }
234
+
235
+ /*
236
+ * After running out of one side, the remaining side must have
237
+ * nothing but whitespace for the lines to match. Note that
238
+ * ignore-whitespace-at-eol case may break out of the loop
239
+ * while there still are characters remaining on both lines.
240
+ */
241
+ if (i1 < s1 ) {
242
+ while (i1 < s1 && isspace (l1 [i1 ]))
229
243
i1 ++ ;
244
+ if (s1 != i1 )
245
+ return 0 ;
246
+ }
247
+ if (i2 < s2 ) {
248
+ while (i2 < s2 && isspace (l2 [i2 ]))
230
249
i2 ++ ;
231
- }
232
- return i1 >= s1 && i2 >= s2 ;
233
- } else
234
- return s1 == s2 && !memcmp (l1 , l2 , s1 );
250
+ return (s2 == i2 );
251
+ }
252
+ return 1 ;
235
253
}
236
254
237
255
static unsigned long xdl_hash_record_with_whitespace (char const * * data ,
@@ -242,18 +260,20 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
242
260
for (; ptr < top && * ptr != '\n' ; ptr ++ ) {
243
261
if (isspace (* ptr )) {
244
262
const char * ptr2 = ptr ;
263
+ int at_eol ;
245
264
while (ptr + 1 < top && isspace (ptr [1 ])
246
265
&& ptr [1 ] != '\n' )
247
266
ptr ++ ;
267
+ at_eol = (top <= ptr + 1 || ptr [1 ] == '\n' );
248
268
if (flags & XDF_IGNORE_WHITESPACE )
249
269
; /* already handled */
250
270
else if (flags & XDF_IGNORE_WHITESPACE_CHANGE
251
- && ptr [ 1 ] != '\n' ) {
271
+ && ! at_eol ) {
252
272
ha += (ha << 5 );
253
273
ha ^= (unsigned long ) ' ' ;
254
274
}
255
275
else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL
256
- && ptr [ 1 ] != '\n' ) {
276
+ && ! at_eol ) {
257
277
while (ptr2 != ptr + 1 ) {
258
278
ha += (ha << 5 );
259
279
ha ^= (unsigned long ) * ptr2 ;
0 commit comments