@@ -190,48 +190,66 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
190190{
191191 int i1 , i2 ;
192192
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+ */
193206 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 ++ ])
202210 return 0 ;
211+ skip_ws :
212+ while (i1 < s1 && isspace (l1 [i1 ]))
213+ i1 ++ ;
214+ while (i2 < s2 && isspace (l2 [i2 ]))
215+ i2 ++ ;
203216 }
204- return (i1 >= s1 && i2 >= s2 );
205217 } 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 */
221221 while (i1 < s1 && isspace (l1 [i1 ]))
222222 i1 ++ ;
223223 while (i2 < s2 && isspace (l2 [i2 ]))
224224 i2 ++ ;
225- if (i1 < s1 || i2 < s2 )
226- return 0 ;
227- return 1 ;
225+ continue ;
228226 }
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 ]))
229243 i1 ++ ;
244+ if (s1 != i1 )
245+ return 0 ;
246+ }
247+ if (i2 < s2 ) {
248+ while (i2 < s2 && isspace (l2 [i2 ]))
230249 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 ;
235253}
236254
237255static 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,
242260 for (; ptr < top && * ptr != '\n' ; ptr ++ ) {
243261 if (isspace (* ptr )) {
244262 const char * ptr2 = ptr ;
263+ int at_eol ;
245264 while (ptr + 1 < top && isspace (ptr [1 ])
246265 && ptr [1 ] != '\n' )
247266 ptr ++ ;
267+ at_eol = (top <= ptr + 1 || ptr [1 ] == '\n' );
248268 if (flags & XDF_IGNORE_WHITESPACE )
249269 ; /* already handled */
250270 else if (flags & XDF_IGNORE_WHITESPACE_CHANGE
251- && ptr [ 1 ] != '\n' ) {
271+ && ! at_eol ) {
252272 ha += (ha << 5 );
253273 ha ^= (unsigned long ) ' ' ;
254274 }
255275 else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL
256- && ptr [ 1 ] != '\n' ) {
276+ && ! at_eol ) {
257277 while (ptr2 != ptr + 1 ) {
258278 ha += (ha << 5 );
259279 ha ^= (unsigned long ) * ptr2 ;
0 commit comments