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

[PATCH 02/14] parse-options: add one-shot mode

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Jan 27, 2019, 00:35 UTC
Message-ID
<20190127003535.28341-3-pclouds@gmail.com>
In-Reply-To
<20190127003535.28341-1-pclouds@gmail.com>

This is to help reimplement diff_opt_parse() using parse_options(). The behavior of parse_options() is changed to be the same as the other:

- no argv0 in argv[], everything can be processed
- argv[] must not be updated, it's the caller's job to do that
- return the number of arguments processed
- leave all unknown options / non-options alone (this one can already
  be achieved with PARSE_OPT_KEEP_UNKNOWN and
  PARSE_OPT_STOP_AT_NON_OPTION)

This mode is NOT supposed to stay here for long. It's to help converting diff/rev option parsing. Once that work is over and we can just use parse_options() throughout the code base, this will be deleted.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 parse-options.c | 26 ++++++++++++++++++++++----
 parse-options.h | 17 +++++++++++++----
 2 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/parse-options.c b/parse-options.c
index 9f84bacce6..740ae5438f 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -416,15 +416,24 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
 			 const struct option *options, int flags)
 {
 	memset(ctx, 0, sizeof(*ctx));
-	ctx->argc = ctx->total = argc - 1;
-	ctx->argv = argv + 1;
-	ctx->out  = argv;
+	ctx->argc = argc;
+	ctx->argv = argv;
+	if (!(flags & PARSE_OPT_ONE_SHOT)) {
+		ctx->argc--;
+		ctx->argv++;
+	}
+	ctx->total = ctx->argc;
+	ctx->out   = argv;
 	ctx->prefix = prefix;
 	ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
 	ctx->flags = flags;
 	if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
-	    (flags & PARSE_OPT_STOP_AT_NON_OPTION))
+	    (flags & PARSE_OPT_STOP_AT_NON_OPTION) &&
+	    !(flags & PARSE_OPT_ONE_SHOT))
 		BUG("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
+	if ((flags & PARSE_OPT_ONE_SHOT) &&
+	    (flags & PARSE_OPT_KEEP_ARGV0))
+		BUG("Can't keep argv0 if you don't have it");
 	parse_options_check(options);
 }
 
@@ -536,6 +545,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
 	for (; ctx->argc; ctx->argc--, ctx->argv++) {
 		const char *arg = ctx->argv[0];
 
+		if (ctx->flags & PARSE_OPT_ONE_SHOT &&
+		    ctx->argc != ctx->total)
+			break;
+
 		if (*arg != '-' || !arg[1]) {
 			if (parse_nodash_opt(ctx, arg, options) == 0)
 				continue;
@@ -610,6 +623,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
 		}
 		continue;
 unknown:
+		if (ctx->flags & PARSE_OPT_ONE_SHOT)
+			break;
 		if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
 			return PARSE_OPT_UNKNOWN;
 		ctx->out[ctx->cpidx++] = ctx->argv[0];
@@ -623,6 +638,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
 
 int parse_options_end(struct parse_opt_ctx_t *ctx)
 {
+	if (ctx->flags & PARSE_OPT_ONE_SHOT)
+		return ctx->total - ctx->argc;
+
 	MOVE_ARRAY(ctx->out + ctx->cpidx, ctx->argv, ctx->argc);
 	ctx->out[ctx->cpidx + ctx->argc] = NULL;
 	return ctx->cpidx + ctx->argc;
diff --git a/parse-options.h b/parse-options.h
index f5e7ec7d23..d663b83973 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -27,7 +27,8 @@ enum parse_opt_flags {
 	PARSE_OPT_STOP_AT_NON_OPTION = 2,
 	PARSE_OPT_KEEP_ARGV0 = 4,
 	PARSE_OPT_KEEP_UNKNOWN = 8,
-	PARSE_OPT_NO_INTERNAL_HELP = 16
+	PARSE_OPT_NO_INTERNAL_HELP = 16,
+	PARSE_OPT_ONE_SHOT = 32
 };
 
 enum parse_opt_option_flags {
@@ -169,10 +170,18 @@ struct option {
 	  N_("no-op (backward compatibility)"),		\
 	  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, parse_opt_noop_cb }
 
-/* parse_options() will filter out the processed options and leave the
- * non-option arguments in argv[]. usagestr strings should be marked
- * for translation with N_().
+/*
+ * parse_options() will filter out the processed options and leave the
+ * non-option arguments in argv[]. argv0 is assumed program name and
+ * skipped.
+ *
+ * usagestr strings should be marked for translation with N_().
+ *
  * Returns the number of arguments left in argv[].
+ *
+ * In one-shot mode, argv0 is not a program name, argv[] is left
+ * untouched and parse_options() returns the number of options
+ * processed.
  */
 int parse_options(int argc, const char **argv, const char *prefix,
 		  const struct option *options,
-- 
2.20.1.560.g70ca8b83ee
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 3 of 19 in “nd/diff-parseopt part 1”
  1. 00/14 nd/diff-parseopt part 1Nguyễn Thái Ngọc Duy, Jan 27, 2019
  2. 01/14 parse-options.h: remove extern on function prototypesNguyễn Thái Ngọc Duy, Jan 27, 2019
  3. 02/14 parse-options: add one-shot modeNguyễn Thái Ngọc Duy, Jan 27, 2019
  4. 03/14 parse-options: disable option abbreviation with PARSE_OPT_KEEP_UNKNOWNNguyễn Thái Ngọc Duy, Jan 27, 2019
  5. 04/14 parse-options: add OPT_BITOP()Nguyễn Thái Ngọc Duy, Jan 27, 2019
  6. 05/14 parse-options: stop abusing 'callback' for lowlevel callbacksNguyễn Thái Ngọc Duy, Jan 27, 2019
  7. 06/14 parse-options: avoid magic return codesNguyễn Thái Ngọc Duy, Jan 27, 2019
  8. 07/14 parse-options: allow ll_callback with OPTION_CALLBACKNguyễn Thái Ngọc Duy, Jan 27, 2019
  9. Derrick StoleeApr 15, 2019
  10. Duy NguyenApr 16, 2019
  11. Derrick StoleeApr 16, 2019
  12. 08/14 diff.h: keep forward struct declarations sortedNguyễn Thái Ngọc Duy, Jan 27, 2019
  13. 09/14 diff.h: avoid bit fields in struct diff_flagsNguyễn Thái Ngọc Duy, Jan 27, 2019
  14. 10/14 diff.c: prepare to use parse_options() for parsingNguyễn Thái Ngọc Duy, Jan 27, 2019
  15. 11/14 diff.c: convert -u|-p|--patchNguyễn Thái Ngọc Duy, Jan 27, 2019
  16. 12/14 diff.c: convert -U|--unifiedNguyễn Thái Ngọc Duy, Jan 27, 2019
  17. 13/14 diff.c: convert -W|--[no-]function-contextNguyễn Thái Ngọc Duy, Jan 27, 2019
  18. 14/14 diff.c: convert --rawNguyễn Thái Ngọc Duy, Jan 27, 2019
  19. Junio C HamanoJan 28, 2019

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.