This adds the ability to put rules into a filter/include/exclude file
in last-match-wins order.  All you need to do is to start the file with
this line:

[last-match]

--- old/exclude.c
+++ new/exclude.c
@@ -76,6 +76,7 @@ static BOOL parent_dirscan = False;
 static struct filter_struct **mergelist_parents;
 static int mergelist_cnt = 0;
 static int mergelist_size = 0;
+static int reversing_rules = 0;
 
 /* Each filter_list_struct describes a singly-linked list by keeping track
  * of both the head and tail pointers.  The list is slightly unusual in that
@@ -244,6 +245,9 @@ static void add_rule(struct filter_list_
 	if (!listp->tail) {
 		ret->next = listp->head;
 		listp->head = listp->tail = ret;
+	} else if (reversing_rules) {
+		ret->next = listp->head;
+		listp->head = ret;
 	} else {
 		ret->next = listp->tail->next;
 		listp->tail->next = ret;
@@ -970,6 +974,7 @@ void parse_filter_file(struct filter_lis
 	char line[BIGPATHBUFLEN];
 	char *eob = line + sizeof line - 1;
 	int word_split = mflags & MATCHFLG_WORD_SPLIT;
+	int save_reversing_rules = reversing_rules;
 
 	if (!fname || !*fname)
 		return;
@@ -1005,6 +1010,7 @@ void parse_filter_file(struct filter_lis
 	}
 	dirbuf[dirbuf_len] = '\0';
 
+	reversing_rules = 0;
 	while (1) {
 		char *s = line;
 		int ch, overflow = 0;
@@ -1030,6 +1036,10 @@ void parse_filter_file(struct filter_lis
 			s = line;
 		}
 		*s = '\0';
+		if (*line == '[' && strcmp(line+1, "last-match]") == 0) {
+			reversing_rules = 1;
+			continue;
+		}
 		/* Skip an empty token and (when line parsing) comments. */
 		if (*line && (word_split || (*line != ';' && *line != '#')))
 			parse_rule(listp, line, mflags, xflags);
@@ -1037,6 +1047,7 @@ void parse_filter_file(struct filter_lis
 			break;
 	}
 	fclose(fp);
+	reversing_rules = save_reversing_rules;
 }
 
 /* If the "for_xfer" flag is set, the prefix is made compatible with the
