diff(1): reject conflicting formatting options

This matches GNU diff(1) behavior and, more importantly, eliminates any
source of confusion if multiple formatting options are specified.

Note that the committed diff differs slightly from the submitted: I've
modified it so that we initialize diff_format to something that isn't an
accepted format option so that we can also reject --normal -c and -c
--normal, which would've otherwise been accepted because the default was
--normal. After option parsing we default it to D_NORMAL if it's still
unset.

PR:		243975
Submitted by:	fehmi noyan isi
MFC after:	1 week
This commit is contained in:
Kyle Evans
2020-04-20 16:14:44 +00:00
parent 0ae64ae4c9
commit db9cccfbb1
3 changed files with 52 additions and 4 deletions
+33 -2
View File
@@ -100,6 +100,7 @@ static struct option longopts[] = {
};
void usage(void) __dead2;
void conflicting_format(void) __dead2;
void push_excludes(char *);
void push_ignore_pats(char *);
void read_excludes_file(char *file);
@@ -120,7 +121,7 @@ main(int argc, char **argv)
prevoptind = 1;
newarg = 1;
diff_context = 3;
diff_format = 0;
diff_format = D_UNSET;
while ((ch = getopt_long(argc, argv, OPTIONS, longopts, NULL)) != -1) {
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
@@ -141,6 +142,8 @@ main(int argc, char **argv)
break;
case 'C':
case 'c':
if (diff_format != D_UNSET)
conflicting_format();
cflag = 1;
diff_format = D_CONTEXT;
if (optarg != NULL) {
@@ -154,13 +157,19 @@ main(int argc, char **argv)
dflags |= D_MINIMAL;
break;
case 'D':
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_IFDEF;
ifdefname = optarg;
break;
case 'e':
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_EDIT;
break;
case 'f':
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_REVERSE;
break;
case 'H':
@@ -193,10 +202,12 @@ main(int argc, char **argv)
Nflag = 1;
break;
case 'n':
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_NREVERSE;
break;
case 'p':
if (diff_format == 0)
if (diff_format == D_UNSET)
diff_format = D_CONTEXT;
dflags |= D_PROTOTYPE;
break;
@@ -207,6 +218,8 @@ main(int argc, char **argv)
rflag = 1;
break;
case 'q':
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_BRIEF;
break;
case 'S':
@@ -223,6 +236,8 @@ main(int argc, char **argv)
break;
case 'U':
case 'u':
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_UNIFIED;
if (optarg != NULL) {
l = strtol(optarg, &ep, 10);
@@ -249,9 +264,13 @@ main(int argc, char **argv)
push_excludes(optarg);
break;
case 'y':
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_SIDEBYSIDE;
break;
case OPT_CHANGED_GROUP_FORMAT:
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_GFORMAT;
group_format = optarg;
break;
@@ -264,6 +283,8 @@ main(int argc, char **argv)
ignore_file_case = 0;
break;
case OPT_NORMAL:
if (diff_format != D_UNSET)
conflicting_format();
diff_format = D_NORMAL;
break;
case OPT_TSIZE:
@@ -287,6 +308,8 @@ main(int argc, char **argv)
newarg = optind != prevoptind;
prevoptind = optind;
}
if (diff_format == D_UNSET)
diff_format = D_NORMAL;
argc -= optind;
argv += optind;
@@ -491,3 +514,11 @@ usage(void)
exit(2);
}
void
conflicting_format(void)
{
fprintf(stderr, "error: conflicting output format options.\n");
usage();
}
+3
View File
@@ -50,6 +50,9 @@
#define D_GFORMAT 7 /* Diff with defined changed group format */
#define D_SIDEBYSIDE 8 /* Side by side */
#define D_UNSET -2
/*
* Output flags
*/
+16 -2
View File
@@ -11,6 +11,7 @@ atf_test_case brief_format
atf_test_case b230049
atf_test_case Bflag
atf_test_case tabsize
atf_test_case conflicting_format
simple_body()
{
@@ -49,8 +50,6 @@ unified_body()
{
atf_check -o file:$(atf_get_srcdir)/unified_p.out -s eq:1 \
diff -up -L input_c1.in -L input_c2.in "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
atf_check -o file:$(atf_get_srcdir)/unified_c9999.out -s eq:1 \
diff -u -c9999 -L input_c1.in -L input_c2.in "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
atf_check -o file:$(atf_get_srcdir)/unified_9999.out -s eq:1 \
diff -u9999 -L input_c1.in -L input_c2.in "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
}
@@ -175,6 +174,20 @@ tabsize_body()
diff -t --tabsize 1 A B
}
conflicting_format_body()
{
printf "\tA\n" > A
printf "\tB\n" > B
atf_check -s exit:2 -e ignore diff -c -u A B
atf_check -s exit:2 -e ignore diff -e -f A B
atf_check -s exit:2 -e ignore diff -y -q A B
atf_check -s exit:2 -e ignore diff -q -u A B
atf_check -s exit:2 -e ignore diff -q -c A B
atf_check -s exit:2 -e ignore diff --normal -c A B
atf_check -s exit:2 -e ignore diff -c --normal A B
}
atf_init_test_cases()
{
atf_add_test_case simple
@@ -188,4 +201,5 @@ atf_init_test_cases()
atf_add_test_case b230049
atf_add_test_case Bflag
atf_add_test_case tabsize
atf_add_test_case conflicting_format
}