git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/2] parse_options: Add flag to prevent errors for further processing

From
Shawn Bohrer <shawn.bohrer@gmail.com>
Date
Jun 18, 2008, 03:03 UTC
Message-ID
<1213758236-979-2-git-send-email-shawn.bohrer@gmail.com>
In-Reply-To
<1213758236-979-1-git-send-email-shawn.bohrer@gmail.com>

This adds the PARSE_OPT_NO_ERROR_ON_UNKNOWN flag which prevents parse_options() from erroring out when it finds an unknown option, and leaves the original command and unknown options in argv.

This option is useful if the option parsing needs to be done in multiple stages for example if the remaining options will be passed to additional git commands.

Signed-off-by: Shawn Bohrer <shawn.bohrer@gmail.com>
---
 parse-options.c |   25 ++++++++++++++++++++-----
 parse-options.h |    5 +++--
 2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/parse-options.c b/parse-options.c
index 8071711..2635e18 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -131,7 +131,8 @@ static int get_value(struct optparse_t *p,
 	}
 }
 
-static int parse_short_opt(struct optparse_t *p, const struct option *options)
+static int parse_short_opt(struct optparse_t *p, const struct option *options,
+			   int flags)
 {
 	for (; options->type != OPTION_END; options++) {
 		if (options->short_name == *p->opt) {
@@ -139,11 +140,16 @@ static int parse_short_opt(struct optparse_t *p, const struct option *options)
 			return get_value(p, options, OPT_SHORT);
 		}
 	}
+
+	if (flags & PARSE_OPT_NO_ERROR_ON_UNKNOWN) {
+		p->out[p->cpidx++] = p->argv[0];
+		return 0;
+	}
 	return error("unknown switch `%c'", *p->opt);
 }
 
 static int parse_long_opt(struct optparse_t *p, const char *arg,
-                          const struct option *options)
+                          const struct option *options, int flags)
 {
 	const char *arg_end = strchr(arg, '=');
 	const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
@@ -224,6 +230,11 @@ is_abbreviated:
 			abbrev_option->long_name);
 	if (abbrev_option)
 		return get_value(p, abbrev_option, abbrev_flags);
+
+	if (flags & PARSE_OPT_NO_ERROR_ON_UNKNOWN) {
+		p->out[p->cpidx++] = p->argv[0];
+		return 0;
+	}
 	return error("unknown option `%s'", arg);
 }
 
@@ -254,6 +265,8 @@ int parse_options(int argc, const char **argv, const struct option *options,
                   const char * const usagestr[], int flags)
 {
 	struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };
+	if (flags & PARSE_OPT_NO_ERROR_ON_UNKNOWN)
+		args.out =  argv + 1;
 
 	for (; args.argc; args.argc--, args.argv++) {
 		const char *arg = args.argv[0];
@@ -269,14 +282,14 @@ int parse_options(int argc, const char **argv, const struct option *options,
 			args.opt = arg + 1;
 			if (*args.opt == 'h')
 				usage_with_options(usagestr, options);
-			if (parse_short_opt(&args, options) < 0)
+			if (parse_short_opt(&args, options, flags) < 0)
 				usage_with_options(usagestr, options);
 			if (args.opt)
 				check_typos(arg + 1, options);
 			while (args.opt) {
 				if (*args.opt == 'h')
 					usage_with_options(usagestr, options);
-				if (parse_short_opt(&args, options) < 0)
+				if (parse_short_opt(&args, options, flags) < 0)
 					usage_with_options(usagestr, options);
 			}
 			continue;
@@ -294,11 +307,13 @@ int parse_options(int argc, const char **argv, const struct option *options,
 			usage_with_options_internal(usagestr, options, 1);
 		if (!strcmp(arg + 2, "help"))
 			usage_with_options(usagestr, options);
-		if (parse_long_opt(&args, arg + 2, options))
+		if (parse_long_opt(&args, arg + 2, options, flags))
 			usage_with_options(usagestr, options);
 	}
 
 	memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));
+	if (flags & PARSE_OPT_NO_ERROR_ON_UNKNOWN)
+		++args.cpidx;
 	args.out[args.cpidx + args.argc] = NULL;
 	return args.cpidx + args.argc;
 }
diff --git a/parse-options.h b/parse-options.h
index 4ee443d..416ccdd 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -18,8 +18,9 @@ enum parse_opt_type {
 };
 
 enum parse_opt_flags {
-	PARSE_OPT_KEEP_DASHDASH = 1,
-	PARSE_OPT_STOP_AT_NON_OPTION = 2,
+	PARSE_OPT_KEEP_DASHDASH       = 1,
+	PARSE_OPT_STOP_AT_NON_OPTION  = 2,
+	PARSE_OPT_NO_ERROR_ON_UNKNOWN = 4
 };
 
 enum parse_opt_option_flags {
-- 
1.5.4.3
Previous: Shawn BohrerNext: Shawn Bohrer
Message 2 of 17 in “[RFC] convert shortlog to use parse_options”
  1. Shawn BohrerJun 18, 2008
  2. 1/2 parse_options: Add flag to prevent errors for further processingShawn Bohrer, Jun 18, 2008
  3. 2/2 git shortlog: Modify to use parse_optionsShawn Bohrer, Jun 18, 2008
  4. Junio C HamanoJun 18, 2008
  5. Jeff KingJun 18, 2008
  6. Jeff KingJun 18, 2008
  7. Junio C HamanoJun 18, 2008
  8. Johannes SchindelinJun 18, 2008
  9. Junio C HamanoJun 18, 2008
  10. Shawn BohrerJun 19, 2008
  11. Johannes SchindelinJun 22, 2008
  12. Junio C HamanoJun 23, 2008
  13. Jeff KingJun 23, 2008
  14. Junio C HamanoJun 23, 2008
  15. Johannes SchindelinJun 23, 2008
  16. Pierre HabouzitJun 22, 2008
  17. Junio C HamanoJun 23, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.