|
17 | 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | 18 | * |
19 | 19 | * This is a scanner-based implementation of lsdiff using the unified patch scanner API. |
20 | | - * |
21 | | - * TODO: REMAINING IMPROVEMENTS |
22 | | - * ============================ |
23 | | - * RANGE PARSING IMPROVEMENTS: |
24 | | - * Full range syntax for -F/--files option: "1,3-5,8", "3-", "-", "x1,3" (exclusion) |
25 | | - * Currently only supports single numbers |
26 | | - * |
27 | | - * See filterdiff.c for reference implementation of full range parsing. |
28 | 20 | */ |
29 | 21 |
|
30 | 22 | #ifdef HAVE_CONFIG_H |
@@ -74,6 +66,7 @@ static char *add_new_prefix = NULL; /* --addnewprefix */ |
74 | 66 | static struct patlist *pat_include = NULL; /* -i, --include */ |
75 | 67 | static struct patlist *pat_exclude = NULL; /* -x, --exclude */ |
76 | 68 | static struct range *files = NULL; /* -F, --files */ |
| 69 | +static int files_exclude = 0; /* -F with x prefix */ |
77 | 70 |
|
78 | 71 | /* File counter for -N option */ |
79 | 72 | static int file_number = 0; |
@@ -431,17 +424,20 @@ static int should_display_file(const char *filename) |
431 | 424 | struct range *r; |
432 | 425 | int file_matches = 0; |
433 | 426 |
|
434 | | - /* TODO: Handle files_exclude flag and range exclusion (x prefix) */ |
435 | | - |
| 427 | + /* Check if file number matches any range (-1UL is wildcard) */ |
436 | 428 | for (r = files; r; r = r->next) { |
437 | | - if (file_number >= r->start && file_number <= r->end) { |
| 429 | + if ((r->start == -1UL || r->start <= file_number) && |
| 430 | + (r->end == -1UL || file_number <= r->end)) { |
438 | 431 | file_matches = 1; |
439 | 432 | break; |
440 | 433 | } |
441 | 434 | } |
442 | 435 |
|
443 | | - if (!file_matches) |
444 | | - return 0; |
| 436 | + /* Handle exclusion logic */ |
| 437 | + if (files && !file_matches && !files_exclude) |
| 438 | + return 0; /* File doesn't match and we're including */ |
| 439 | + if (files && file_matches && files_exclude) |
| 440 | + return 0; /* File matches and we're excluding */ |
445 | 441 | } |
446 | 442 |
|
447 | 443 | return 1; |
@@ -721,6 +717,12 @@ int main(int argc, char *argv[]) |
721 | 717 | patlist_add_file(&pat_exclude, optarg); |
722 | 718 | break; |
723 | 719 | case 'F': |
| 720 | + if (files) |
| 721 | + syntax(1); |
| 722 | + if (*optarg == 'x') { |
| 723 | + files_exclude = 1; |
| 724 | + optarg = optarg + 1; |
| 725 | + } |
724 | 726 | parse_range(&files, optarg); |
725 | 727 | break; |
726 | 728 | case 'v': |
@@ -821,35 +823,51 @@ int main(int argc, char *argv[]) |
821 | 823 | * Used with -F option to select specific files from a patch by their |
822 | 824 | * position (file number), which can then be used with filterdiff's |
823 | 825 | * --files option for further processing. |
824 | | - * |
825 | | - * This is a simplified implementation that only supports single numbers. |
826 | | - * The full implementation in filterdiff.c supports all range formats above. |
827 | | - * |
828 | | - * TODO: Implement full range parsing functionality: |
829 | | - * - Support ranges: "3-5", "3-", "-" |
830 | | - * - Support comma-separated lists: "1,3-5,8" |
831 | | - * - Support exclusion ranges with 'x' prefix: "x1,3" |
832 | | - * - Add proper error handling for invalid ranges |
833 | | - * |
834 | | - * Current implementation only supports single numbers like "3". |
835 | 826 | */ |
836 | 827 | static void parse_range(struct range **r, const char *rstr) |
837 | 828 | { |
838 | 829 | unsigned long n; |
839 | 830 | char *end; |
840 | | - struct range *new_range; |
841 | 831 |
|
842 | | - n = strtoul(rstr, &end, 0); |
843 | | - if (rstr == end) |
844 | | - return; /* Invalid number */ |
| 832 | + if (*rstr == '-') |
| 833 | + n = -1UL; |
| 834 | + else { |
| 835 | + n = strtoul(rstr, &end, 0); |
| 836 | + if (rstr == end) { |
| 837 | + if (*end) |
| 838 | + error(EXIT_FAILURE, 0, |
| 839 | + "not understood: '%s'", end); |
| 840 | + else |
| 841 | + error(EXIT_FAILURE, 0, |
| 842 | + "missing number in range list"); |
| 843 | + |
| 844 | + *r = NULL; |
| 845 | + return; |
| 846 | + } |
845 | 847 |
|
846 | | - new_range = malloc(sizeof(struct range)); |
847 | | - if (!new_range) |
848 | | - return; |
| 848 | + rstr = end; |
| 849 | + } |
| 850 | + |
| 851 | + *r = xmalloc(sizeof **r); |
| 852 | + (*r)->start = (*r)->end = n; |
| 853 | + (*r)->next = NULL; |
| 854 | + if (*rstr == '-') { |
| 855 | + rstr++; |
| 856 | + n = strtoul(rstr, &end, 0); |
| 857 | + if (rstr == end) |
| 858 | + n = -1UL; |
| 859 | + |
| 860 | + (*r)->end = n; |
| 861 | + rstr = end; |
| 862 | + |
| 863 | + if ((*r)->start != -1UL && (*r)->start > (*r)->end) |
| 864 | + error(EXIT_FAILURE, 0, "invalid range: %lu-%lu", |
| 865 | + (*r)->start, (*r)->end); |
| 866 | + } |
849 | 867 |
|
850 | | - new_range->start = n; |
851 | | - new_range->end = n; |
852 | | - new_range->next = *r; |
853 | | - *r = new_range; |
| 868 | + if (*rstr == ',') |
| 869 | + parse_range(&(*r)->next, rstr + 1); |
| 870 | + else if (*rstr != '\0') |
| 871 | + error(EXIT_FAILURE, 0, "not understood: '%s'", rstr); |
854 | 872 | } |
855 | 873 |
|
0 commit comments