ls: for some options, only last takes effect. Closes bug 2959

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 72f58c2..8d1f919 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -984,13 +984,23 @@
 
 	/* process options */
 	IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;)
-#if ENABLE_FEATURE_AUTOWIDTH
-	opt_complementary = "T+:w+"; /* -T N, -w N */
-	opt = getopt32(argv, ls_options, &tabstops, &terminal_width
-				IF_FEATURE_LS_COLOR(, &color_opt));
-#else
-	opt = getopt32(argv, ls_options IF_FEATURE_LS_COLOR(, &color_opt));
-#endif
+	opt_complementary =
+		/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html:
+		 * in some pairs of opts, only last one takes effect:
+		 */
+		IF_FEATURE_LS_TIMESTAMPS(IF_FEATURE_LS_SORTFILES("t-S:S-t")) /* time/size */
+		// ":H-L:L-H:" - we don't have -H
+		// ":m-l:l-m:" - we don't have -m
+		":C-xl:x-Cl:l-xC" /* bycols/bylines/long */
+		":C-1:1-C" /* bycols/oneline */
+		":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */
+		":c-u:u-c" /* mtime/atime */
+		/* -T NUM, -w NUM: */
+		IF_FEATURE_AUTOWIDTH(":T+:w+");
+	opt = getopt32(argv, ls_options
+		IF_FEATURE_AUTOWIDTH(, &tabstops, &terminal_width)
+		IF_FEATURE_LS_COLOR(, &color_opt)
+	);
 	for (i = 0; opt_flags[i] != (1U<<31); i++) {
 		if (opt & (1 << i)) {
 			unsigned flags = opt_flags[i];
@@ -1054,7 +1064,7 @@
 		if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC))
 			all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */
 
-	/* choose a display format */
+	/* choose a display format if one was not already specified by an option */
 	if (!(all_fmt & STYLE_MASK))
 		all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE);