about summary refs log tree commit diff
path: root/src/misc/getopt_long.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2014-12-20 19:44:37 -0500
committerRich Felker <dalias@aerifal.cx>2014-12-20 19:44:37 -0500
commit91184c4f16b143107fa9935edebe5d2b20bd70d8 (patch)
tree6f74e3f852498ae639bcc6250e53620f062ad5e4 /src/misc/getopt_long.c
parentd3357268791f5279b64665a9a5b5629c962c8a15 (diff)
downloadmusl-91184c4f16b143107fa9935edebe5d2b20bd70d8.tar.gz
musl-91184c4f16b143107fa9935edebe5d2b20bd70d8.tar.xz
musl-91184c4f16b143107fa9935edebe5d2b20bd70d8.zip
add error message printing to getopt_long and make related improvements
some related changes are also made to getopt, and the return value of
getopt_long in the case of missing arguments is fixed.
Diffstat (limited to 'src/misc/getopt_long.c')
-rw-r--r--src/misc/getopt_long.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/misc/getopt_long.c b/src/misc/getopt_long.c
index df2083bb..45992f85 100644
--- a/src/misc/getopt_long.c
+++ b/src/misc/getopt_long.c
@@ -2,6 +2,7 @@
 #include <stddef.h>
 #include <getopt.h>
 #include <stdio.h>
+#include <string.h>
 
 extern int __optpos, __optreset;
 
@@ -15,11 +16,14 @@ static void permute(char *const *argv, int dest, int src)
 	av[dest] = tmp;
 }
 
+void __getopt_msg(const char *, const char *, const char *, size_t);
+
 static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly);
 
 static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
 {
 	int ret, skipped, resumed;
+	const char *optstring2 = optstring + 1;
 	if (!optind || __optreset) {
 		__optreset = 0;
 		__optpos = 0;
@@ -34,9 +38,10 @@ static int __getopt_long(int argc, char *const *argv, const char *optstring, con
 			if (argv[i][0] == '-' && argv[i][1]) break;
 		}
 		optind = i;
+		optstring2 = optstring;
 	}
 	resumed = optind;
-	ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
+	ret = __getopt_long_core(argc, argv, optstring2, longopts, idx, longonly);
 	if (resumed > skipped) {
 		int i, cnt = optind-resumed;
 		for (i=0; i<cnt; i++)
@@ -72,12 +77,27 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring
 			i = match;
 			optind++;
 			if (*opt == '=') {
-				if (!longopts[i].has_arg) return '?';
+				if (!longopts[i].has_arg) {
+					if (optstring[0] == ':' || !opterr)
+						return '?';
+					__getopt_msg(argv[0],
+						": option does not take an argument: ",
+						longopts[i].name,
+						strlen(longopts[i].name));
+					return '?';
+				}
 				optarg = opt+1;
 			} else {
 				if (longopts[i].has_arg == required_argument) {
-					if (!(optarg = argv[optind]))
-						return ':';
+					if (!(optarg = argv[optind])) {
+						if (optstring[0] == ':' || !opterr)
+							return ':';
+						__getopt_msg(argv[0],
+							": option requires an argument: ",
+							longopts[i].name,
+							strlen(longopts[i].name));
+						return '?';
+					}
 					optind++;
 				} else optarg = NULL;
 			}
@@ -89,6 +109,12 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring
 			return longopts[i].val;
 		}
 		if (argv[optind][1] == '-') {
+			if (optstring[0] != ':' && opterr)
+				__getopt_msg(argv[0], cnt ?
+					": option is ambiguous: " :
+					": unrecognized option: ",
+					argv[optind]+2,
+					strlen(argv[optind]+2));
 			optind++;
 			return '?';
 		}