mrsh_getopt: handle repeated short options v2 PROPOSED

Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~emersion/mrsh-dev/%3C20190328233342.3742-1-sir%40cmpwn.com%3E/mbox | git am -3
Learn more about email & git

[PATCH v2] mrsh_getopt: handle repeated short options Export this patch

This handles cases like cmd -arvx (where optstring is "arvx"). This also
changes the reset to mrsh_optind = 0, matching non-POSIX extensions in
various libcs, so that the user needn't also reset mrsh_optpos (which is
not exported from this file).
---
 builtin/alias.c   |  2 +-
 builtin/cd.c      |  2 +-
 builtin/getopts.c |  2 +-
 builtin/pwd.c     |  2 +-
 builtin/read.c    |  2 +-
 builtin/type.c    |  2 +-
 builtin/ulimit.c  |  2 +-
 builtin/umask.c   |  2 +-
 builtin/unalias.c |  2 +-
 builtin/unset.c   |  2 +-
 getopt.c          | 19 +++++++++++++++----
 11 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/builtin/alias.c b/builtin/alias.c
index a55f446..1a5e2a7 100644
--- a/builtin/alias.c
@@ -17,7 +17,7 @@ static void print_alias_iterator(const char *key, void *_value,
 }
 
 int builtin_alias(struct mrsh_state *state, int argc, char *argv[]) {
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	if (mrsh_getopt(argc, argv, ":") != -1) {
 		fprintf(stderr, "alias: unknown option -- %c\n", mrsh_optopt);
 		fprintf(stderr, alias_usage);
diff --git a/builtin/cd.c b/builtin/cd.c
index d0536a1..e977298 100644
--- a/builtin/cd.c
@@ -37,7 +37,7 @@ static int isdir(char *path) {
 }
 
 int builtin_cd(struct mrsh_state *state, int argc, char *argv[]) {
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	int opt;
 	while ((opt = mrsh_getopt(argc, argv, ":LP")) != -1) {
 		switch (opt) {
diff --git a/builtin/getopts.c b/builtin/getopts.c
index b1d0519..80b8e08 100644
--- a/builtin/getopts.c
@@ -12,7 +12,7 @@
 static const char getopts_usage[] = "usage: getopts optstring name [arg...]\n";
 
 int builtin_getopts(struct mrsh_state *state, int argc, char *argv[]) {
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	if (mrsh_getopt(argc, argv, ":") != -1) {
 		fprintf(stderr, "getopts: unknown option -- %c\n", mrsh_optopt);
 		fprintf(stderr, getopts_usage);
diff --git a/builtin/pwd.c b/builtin/pwd.c
index 19f380a..796340d 100644
--- a/builtin/pwd.c
@@ -8,7 +8,7 @@
 static const char pwd_usage[] = "usage: pwd [-L|-P]\n";
 
 int builtin_pwd(struct mrsh_state *state, int argc, char *argv[]) {
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	int opt;
 	while ((opt = mrsh_getopt(argc, argv, ":LP")) != -1) {
 		switch (opt) {
diff --git a/builtin/read.c b/builtin/read.c
index 83f8d91..b79471f 100644
--- a/builtin/read.c
@@ -14,7 +14,7 @@ static const char read_usage[] = "usage: read [-r] var...\n";
 int builtin_read(struct mrsh_state *state, int argc, char *argv[]) {
 	bool raw = false;
 
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	int opt;
 	while ((opt = mrsh_getopt(argc, argv, ":r")) != -1) {
 		switch (opt) {
diff --git a/builtin/type.c b/builtin/type.c
index db082b7..739349d 100644
--- a/builtin/type.c
@@ -9,7 +9,7 @@
 static const char type_usage[] = "usage: type name...\n";
 
 int builtin_type(struct mrsh_state *state, int argc, char *argv[]) {
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	if (mrsh_getopt(argc, argv, ":") != -1) {
 		fprintf(stderr, "type: unknown option -- %c\n", mrsh_optopt);
 		fprintf(stderr, type_usage);
diff --git a/builtin/ulimit.c b/builtin/ulimit.c
index 37b2e53..a33e880 100644
--- a/builtin/ulimit.c
@@ -14,7 +14,7 @@
 static const char ulimit_usage[] = "usage: ulimit [-f] [blocks]\n";
 
 int builtin_ulimit(struct mrsh_state *state, int argc, char *argv[]) {
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	int opt;
 	while ((opt = mrsh_getopt(argc, argv, ":f")) != -1) {
 		if (opt == 'f') {
diff --git a/builtin/umask.c b/builtin/umask.c
index 11963d5..777ddb0 100644
--- a/builtin/umask.c
@@ -162,7 +162,7 @@ int builtin_umask(struct mrsh_state *state, int argc, char *argv[]) {
 	mode_t mode;
 	bool umask_symbolic = false;
 
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	int opt;
 
 	while ((opt = mrsh_getopt(argc, argv, ":S")) != -1) {
diff --git a/builtin/unalias.c b/builtin/unalias.c
index 8ff55ee..8590824 100644
--- a/builtin/unalias.c
@@ -15,7 +15,7 @@ static void delete_alias_iterator(const char *key, void *_value, void *user_data
 int builtin_unalias(struct mrsh_state *state, int argc, char *argv[]) {
 	bool all = false;
 
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	int opt;
 	while ((opt = mrsh_getopt(argc, argv, ":a")) != -1) {
 		switch (opt) {
diff --git a/builtin/unset.c b/builtin/unset.c
index 14a0e6e..b522624 100644
--- a/builtin/unset.c
@@ -11,7 +11,7 @@ static const char unset_usage[] = "usage: unset [-fv] name...\n";
 int builtin_unset(struct mrsh_state *state, int argc, char *argv[]) {
 	bool funcs = false;
 
-	mrsh_optind = 1;
+	mrsh_optind = 0;
 	int opt;
 	while ((opt = mrsh_getopt(argc, argv, ":fv")) != -1) {
 		switch (opt) {
diff --git a/getopt.c b/getopt.c
index 0d4eba1..32d3305 100644
--- a/getopt.c
+++ b/getopt.c
@@ -7,11 +7,17 @@ char *mrsh_optarg = NULL;
 int mrsh_optind = 1;
 int mrsh_opterr = 1;
 int mrsh_optopt = 0;
+int mrsh_optpos = 1;
 
 int mrsh_getopt(int argc, char *const argv[], const char *optstring) {
 	assert(argv[argc] == NULL);
 	mrsh_optarg = NULL;
 
+	if (mrsh_optind == 0) {
+		mrsh_optind = 1;
+		mrsh_optpos = 1;
+	}
+
 	if (mrsh_optind >= argc) {
 		return -1;
 	}
@@ -35,19 +41,24 @@ int mrsh_getopt(int argc, char *const argv[], const char *optstring) {
 	}
 
 	mrsh_optopt = 0;
-	int opt = argv[mrsh_optind][1];
+	int opt = argv[mrsh_optind][mrsh_optpos];
 	for (; *c != '\0'; c++) {
 		if (*c != opt) {
 			continue;
 		}
 
 		if (c[1] != ':') {
-			mrsh_optind++;
+			if (argv[mrsh_optind][mrsh_optpos + 1] == '\0') {
+				mrsh_optind++;
+				mrsh_optpos = 1;
+			} else {
+				mrsh_optpos++;
+			}
 			return opt;
 		}
 
-		if (argv[mrsh_optind][2] != '\0') {
-			mrsh_optarg = &argv[mrsh_optind][2]; 
+		if (argv[mrsh_optind][mrsh_optpos + 1] != '\0') {
+			mrsh_optarg = &argv[mrsh_optind][mrsh_optpos + 1];
 		} else {
 			if (mrsh_optind + 2 > argc) {
 				mrsh_optopt = opt;
-- 
2.21.0
To git.sr.ht:~emersion/mrsh
   05fed9a..a263f96  master -> master

Thanks!
View this thread in the archives