Skip to contentSkip to conversation

Add a simple option parser.

PATCH In review Kristian Høgsberg 8 participants 26 messages Jun 15, 2016 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Add a simple option parser.

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

---
 Makefile        |    2 +-
 parse-options.c |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 parse-options.h |   33 +++++++++++++++++
 3 files changed, 140 insertions(+), 1 deletions(-)
 create mode 100644 parse-options.c
 create mode 100644 parse-options.h
Makefile +1 -1
index 62bdac6..d90e959 100644
@@ -310,7 +310,7 @@ LIB_OBJS = \
 	alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
 	color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
 	convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
-	transport.o bundle.o
+	transport.o bundle.o parse-options.o
 
 BUILTIN_OBJS = \
 	builtin-add.o \
parse-options.c new file +106 -0

106 lines not on this page · raw message

parse-options.h new file +33 -0
new file mode 100644
index 0000000..5be9c20
@@ -0,0 +1,33 @@
+#ifndef PARSE_OPTIONS_H
+#define PARSE_OPTIONS_H
+
+enum option_type {
+	OPTION_BOOLEAN,
+	OPTION_STRING,
+	OPTION_INTEGER,
+	OPTION_LAST,
+};
+
+struct option {
+	enum option_type type;
+	const char *long_name;
+	char short_name;
+	void *value;
+};
+
+/* Parse the given options against the list of known options.  The
+ * order of the option structs matters, in that ambiguous
+ * abbreviations (eg, --in could be short for --include or
+ * --interactive) are matched by the first option that share the
+ * prefix.
+ *
+ * parse_options() will filter out the processed options and leave the
+ * non-option argments in argv[].  The return value is the number of
+ * arguments left in argv[].
+ */
+
+extern int parse_options(int argc, const char **argv,
+			 struct option *options, int count,
+			 const char *usage_string);
+
+#endif
Signature · 1 line
1.5.2.5
#1 lore raw

PATCH 1/1 Port builtin-add.c to use the new option parser.

---
 builtin-add.c |   64 ++++++++++++++++++--------------------------------------
 1 files changed, 21 insertions(+), 43 deletions(-)
builtin-add.c +21 -43
index 966e145..66fd99d 100644
@@ -13,6 +13,7 @@
 #include "commit.h"
 #include "revision.h"
 #include "run-command.h"
+#include "parse-options.h"
 
 static const char builtin_add_usage[] =
 "git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] <filepattern>...";
@@ -160,21 +161,30 @@ static struct lock_file lock_file;
 static const char ignore_error[] =
 "The following paths are ignored by one of your .gitignore files:\n";
 
+static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
+static int add_interactive = 0;
+
+static struct option builtin_add_options[] = {
+	{ OPTION_BOOLEAN, "interactive", 'i', &add_interactive },
+	{ OPTION_BOOLEAN, NULL, 'n', &show_only },
+	{ OPTION_BOOLEAN, NULL, 'f', &ignored_too },
+	{ OPTION_BOOLEAN, NULL, 'v',&verbose },
+	{ OPTION_BOOLEAN, NULL, 'u',&take_worktree_changes },
+	{ OPTION_BOOLEAN, "refresh", 0, &refresh_only }
+};
+
 int cmd_add(int argc, const char **argv, const char *prefix)
 {
 	int i, newfd;
-	int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
 	const char **pathspec;
 	struct dir_struct dir;
-	int add_interactive = 0;
 
-	for (i = 1; i < argc; i++) {
-		if (!strcmp("--interactive", argv[i]) ||
-		    !strcmp("-i", argv[i]))
-			add_interactive++;
-	}
+	i = parse_options(argc, argv, builtin_add_options,
+			  ARRAY_SIZE(builtin_add_options),
+			  builtin_add_usage);
+
 	if (add_interactive) {
-		if (argc != 2)
+		if (i > 0)
 			die("add --interactive does not take any parameters");
 		exit(interactive_add());
 	}
@@ -183,51 +193,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	newfd = hold_locked_index(&lock_file, 1);
 
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-
-		if (arg[0] != '-')
-			break;
-		if (!strcmp(arg, "--")) {
-			i++;
-			break;
-		}
-		if (!strcmp(arg, "-n")) {
-			show_only = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-f")) {
-			ignored_too = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-v")) {
-			verbose = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-u")) {
-			take_worktree_changes = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--refresh")) {
-			refresh_only = 1;
-			continue;
-		}
-		usage(builtin_add_usage);
-	}
-
 	if (take_worktree_changes) {
 		if (read_cache() < 0)
 			die("index file corrupt");
-		add_files_to_cache(verbose, prefix, argv + i);
+		add_files_to_cache(verbose, prefix, argv);
 		goto finish;
 	}
 
-	if (argc <= i) {
+	if (i == 0) {
 		fprintf(stderr, "Nothing specified, nothing added.\n");
 		fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
 		return 0;
 	}
-	pathspec = get_pathspec(prefix, argv + i);
+	pathspec = get_pathspec(prefix, argv);
 
 	if (refresh_only) {
 		refresh(verbose, pathspec);
Signature · 1 line
1.5.2.5
#2 lore raw
In reply to Kristian Høgsberg
Quoted 7 lines · Kristian Høgsberg

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

if we are going in that direction (and I believe it's a good one), we
should be sure that the model fits with other commands as well. And as I said on IRC, I believe the most "horrible" (as in complex) option parser in git is the one from git-grep.

A migration of git-grep on that API should be tried first. If this
works well enough, I believe that the rest of the git commands will be migrated easily enough. (with maybe small addition to parse-option.[hc] but the hardcore things should have been met with git-grep already I think).

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#3 lore raw
Quoted 14 lines · Pierre Habouzit
Quoted 7 lines · Kristian Høgsberg

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

if we are going in that direction (and I believe it's a good one), we
should be sure that the model fits with other commands as well. And as I said on IRC, I believe the most "horrible" (as in complex) option parser in git is the one from git-grep.

Quoted 5 lines

A migration of git-grep on that API should be tried first. If this
works well enough, I believe that the rest of the git commands will be migrated easily enough. (with maybe small addition to parse-option.[hc] but the hardcore things should have been met with git-grep already I think).

I'm not sure - we can go with the current proposal and add new options types and probably the callback option type I suggested as we go. I don't want to block builtin-commit on figuring out what the perfect option parser should look like and what I sent out earlier work for commit. I think the way you handled the strbuf rewrites worked pretty well; extending and rewriting the API as you put it to use in more and more places. We can do the same thing with parse_options().

cheers,
Kristian

#4 lore raw
Quoted 22 lines · Kristian Høgsberg
Quoted 14 lines · Pierre Habouzit
Quoted 7 lines · Kristian Høgsberg

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

if we are going in that direction (and I believe it's a good one), we
should be sure that the model fits with other commands as well. And as I said on IRC, I believe the most "horrible" (as in complex) option parser in git is the one from git-grep.

Quoted 5 lines

A migration of git-grep on that API should be tried first. If this
works well enough, I believe that the rest of the git commands will be migrated easily enough. (with maybe small addition to parse-option.[hc] but the hardcore things should have been met with git-grep already I think).

Quoted 7 lines

I'm not sure - we can go with the current proposal and add new options types and probably the callback option type I suggested as we go. I don't want to block builtin-commit on figuring out what the perfect option parser should look like and what I sent out earlier work for commit. I think the way you handled the strbuf rewrites worked pretty well; extending and rewriting the API as you put it to use in more and more places. We can do the same thing with parse_options().

Of course we can do that, or junio said that some people talked about
popt some time ago. I understand that you don't want to block the git-commit work, but doing things right from the beginning is often a big win on the long term.

I don't know popt, and I don't know if it has sufficient expressivity.
For sure I don't like getopt_long APIs at all, so if popt is as cumbersome, rolling our own based on the current parse_options you propose is probably a good choice.

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#5 lore raw
Quoted 14 lines · Pierre Habouzit
Quoted 7 lines · Kristian Høgsberg

I'm not sure - we can go with the current proposal and add new options types and probably the callback option type I suggested as we go. I don't want to block builtin-commit on figuring out what the perfect option parser should look like and what I sent out earlier work for commit. I think the way you handled the strbuf rewrites worked pretty well; extending and rewriting the API as you put it to use in more and more places. We can do the same thing with parse_options().

Of course we can do that, or junio said that some people talked about
popt some time ago. I understand that you don't want to block the git-commit work, but doing things right from the beginning is often a big win on the long term.

Quoted 4 lines

I don't know popt, and I don't know if it has sufficient expressivity.
For sure I don't like getopt_long APIs at all, so if popt is as cumbersome, rolling our own based on the current parse_options you propose is probably a good choice.

Okay, popt seems to be quite complicated, and depends upon gettext
(which we may require as per survey results, but right now it seems a useless dependency). Don't get me wrong, I'm sure it's very powerful, but again, I believe we can have a 200 line ad-hoc module that fits what git really needs, the less cumbersome way.

So well, I'd be (I'm not in position to decide anything btw ;p) in
favor of pursuing the work into git-commit like you did, and ASAP it gets merged into next, I'm definitely willing to pursue a refactoring to use it (now that strbufs seems to have been used where needed).

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#6 lore raw

Hi,

Quoted 1 line · Pierre Habouzit

Okay, popt seems to be quite complicated, and depends upon gettext

... which makes me vote against popt ...

Quoted 2 lines

(which we may require as per survey results, but right now it seems a useless dependency).

Nope. git-gui got a script doing the job of msgfmt, which was the only part of that beast known as gettext anyway.

So we will not require it for git-gui.

And I do not see core git being i18n'ised. Ever.

Ciao,
Dscho

#7 lore raw
In reply to Kristian Høgsberg

parse-options.c line 9

Quoted 6 lines · Kristian Høgsberg
parse-options.c new file +6 -0
+static int parse_one(const char **argv,
+		     struct option *options, int count,
+		     const char *usage_string)
+{
+	const char *eq, *arg, *value;
+	int i, processed;

gcc complains processed could be returned without being initialized
first, so should be processed = 0; Even if it cannot occurs, it avoid raising eyebrows.

parse-options.c line 73

Quoted 3 lines
parse-options.c new file +3 -0
+	case OPTION_INTEGER:
+		if (value == NULL) {
+			error("option %s requires a value.", argv);

^^^
should probably be arg.

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#8 lore raw
In reply to Kristian Høgsberg
Quoted 5 lines

+/* Parse the given options against the list of known options. The
+ * order of the option structs matters, in that ambiguous
+ * abbreviations (eg, --in could be short for --include or
+ * --interactive) are matched by the first option that share the
+ * prefix.

Do we really want that ?

I do believe that it's a very bad idea, as it silently breaks. Most of
the command line switches people need to use have a short form, or their shell will complete it properly.

A very interesting feature though, would be to finally be able to
parse aggregated switches (git rm -rf anyone ?).

I also believe that it's a pity that parse_options isn't able to
generate the usage by itself. But we can add that later.

I've though an alternate proposal, based on your work, for the first
patch.

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#9 lore raw

PATCH 1/1 Add a simple option parser.

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

Aggregation of single switches is allowed:
-rC0 is the same as -r -C 0 (supposing that -C wants an arg).

Boolean switches automatically support the option with the same name, prefixed with 'no-' to disable the switch:
--no-color / --color only need to have an entry for "color".

Long options are supported either with '=' or without:
--some-option=foo is the same as --some-option foo

---

I'm sorry about the "From" I don't intend to "steal" the patch in any sense, it's just an alternate proposal.

oh and I don't grok what OPTION_LAST is for, so I left it apart, but it seems unused ?

 Makefile        |    2 +-
 parse-options.c |  154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 parse-options.h |   29 ++++++++++
 3 files changed, 184 insertions(+), 1 deletions(-)
 create mode 100644 parse-options.c
 create mode 100644 parse-options.h
Makefile +1 -1
index 62bdac6..d90e959 100644
@@ -310,7 +310,7 @@ LIB_OBJS = \
 	alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
 	color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
 	convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
-	transport.o bundle.o
+	transport.o bundle.o parse-options.o
 
 BUILTIN_OBJS = \
 	builtin-add.o \
parse-options.c new file +154 -0

154 lines not on this page · raw message

parse-options.h new file +29 -0
new file mode 100644
index 0000000..e4749d0
@@ -0,0 +1,29 @@
+#ifndef PARSE_OPTIONS_H
+#define PARSE_OPTIONS_H
+
+enum option_type {
+	OPTION_BOOLEAN,
+	OPTION_STRING,
+	OPTION_INTEGER,
+#if 0
+	OPTION_LAST,
+#endif
+};
+
+struct option {
+	enum option_type type;
+	const char *long_name;
+	char short_name;
+	void *value;
+};
+
+/* parse_options() will filter out the processed options and leave the
+ * non-option argments in argv[].  The return value is the number of
+ * arguments left in argv[].
+ */
+
+extern int parse_options(int argc, const char **argv,
+			 struct option *options, int count,
+			 const char *usage_string);
+
+#endif
Signature · 1 line
1.5.3.4.1156.ga72f9d-dirty
author Acked-by on v1 1/1
#10 lore raw
Quoted 11 lines · Pierre Habouzit

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

Aggregation of single switches is allowed:
-rC0 is the same as -r -C 0 (supposing that -C wants an arg).

Quoted 6 lines

Boolean switches automatically support the option with the same name, prefixed with 'no-' to disable the switch:
--no-color / --color only need to have an entry for "color".

Long options are supported either with '=' or without:
--some-option=foo is the same as --some-option foo

That looks great, works for me. One comment, though: it looks like you're not sure whether to call these things "options" or "switches". We should choose one and stick with it.

Quoted 5 lines

---

I'm sorry about the "From" I don't intend to "steal" the patch in any sense, it's just an alternate proposal.

No worries, I'm glad to see this move forward.

Quoted 2 lines

oh and I don't grok what OPTION_LAST is for, so I left it apart, but it seems unused ?

Oh, kill that. I used that as the option array terminator before we switched to ARRAY_SIZE().

Quoted 40 lines
 Makefile        |    2 +-
 parse-options.c |  154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 parse-options.h |   29 ++++++++++
 3 files changed, 184 insertions(+), 1 deletions(-)
 create mode 100644 parse-options.c
 create mode 100644 parse-options.h
Makefile +1 -1
index 62bdac6..d90e959 100644
@@ -310,7 +310,7 @@ LIB_OBJS = \
 	alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
 	color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
 	convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
-	transport.o bundle.o
+	transport.o bundle.o parse-options.o
 
 BUILTIN_OBJS = \
 	builtin-add.o \
parse-options.c new file +13 -0
new file mode 100644
index 0000000..eb3ff40
@@ -0,0 +1,154 @@
+#include "git-compat-util.h"
+#include "parse-options.h"
+
+struct optparse_t {
+	const char **argv;
+	int argc;
+	const char *opt;
+};
+
+static inline const char *skippfx(const char *str, const char *prefix)
+{
+	size_t len = strlen(prefix);
+	return strncmp(str, prefix, len) ? NULL : str + len;

parse-options.c line 23

Quoted 10 lines
parse-options.c new file +10 -0
+}
+
+static int opterror(struct option *opt, const char *reason, int shorterr)
+{
+	if (shorterr) {
+		return error("switch `%c' %s", opt->short_name, reason);
+	} else {
+		return error("option `%s' %s", opt->long_name, reason);
+	}
+}

option/switch?

Quoted 165 lines
parse-options.c new file +130 -0
+static int get_value(struct optparse_t *p, struct option *opt,
+					 int boolean, int shorterr)
+{
+	switch (opt->type) {
+		const char *s;
+		int v;
+
+	  case OPTION_BOOLEAN:
+		*(int *)opt->value = boolean;
+		return 0;
+
+	  case OPTION_STRING:
+		if (p->opt && *p->opt) {
+			*(const char **)opt->value = p->opt;
+			p->opt = NULL;
+		} else {
+			if (p->argc < 1)
+				return opterror(opt, "requires a value", shorterr);
+			*(const char **)opt->value = *++p->argv;
+			p->argc--;
+		}
+		return 0;
+
+	  case OPTION_INTEGER:
+		if (p->opt && *p->opt) {
+			v = strtol(p->opt, (char **)&s, 10);
+			p->opt = NULL;
+		} else {
+			if (p->argc < 1)
+				return opterror(opt, "requires a value", shorterr);
+			v = strtol(*++p->argv, (char **)&s, 10);
+			p->argc--;
+		}
+		if (*s)
+			return opterror(opt, "expects a numerical value", shorterr);
+		*(int *)opt->value = v;
+		return 0;
+	}
+
+	abort();
+}
+
+static int parse_short_opt(struct optparse_t *p, struct option *options, int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		if (options[i].short_name == *p->opt) {
+			p->opt++;
+			return get_value(p, options + i, 1, 1);
+		}
+	}
+	return error("unknown switch `%c'", *p->opt);
+}
+
+static int parse_long_opt(struct optparse_t *p, const char *arg,
+                          struct option *options, int count)
+{
+	int boolean = 1;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		const char *rest;
+		
+		if (!options[i].long_name)
+			continue;
+
+		rest = skippfx(arg, options[i].long_name);
+		if (!rest && options[i].type == OPTION_BOOLEAN) {
+			if (!rest && skippfx(arg, "no-")) {
+				rest = skippfx(arg + 3, options[i].long_name);
+				boolean = 0;
+			}
+			if (rest && *rest == '=')
+				return opterror(options + i, "takes no value", 0);
+		}
+		if (!rest || (*rest && *rest != '='))
+			continue;
+		if (*rest) {
+			p->opt = rest;
+		}
+		return get_value(p, options + i, boolean, 0);
+	}
+	return error("unknown option `%s'", arg);
+}
+
+int parse_options(int argc, const char **argv,
+		  struct option *options, int count,
+		  const char *usage_string)
+{
+	struct optparse_t optp = { argv + 1, argc - 1, NULL };
+	int j = 0;
+
+	while (optp.argc) {
+		const char *arg = optp.argv[0];
+
+		if (*arg != '-' || !arg[1]) {
+			argv[j++] = *optp.argv++;
+			optp.argc--;
+			continue;
+		}
+
+		if (arg[1] != '-') {
+			optp.opt = arg + 1;
+			while (*optp.opt) {
+				if (parse_short_opt(&optp, options, count) < 0) {
+					usage(usage_string);
+					return -1;
+				}
+			}
+			optp.argc--;
+			optp.argv++;
+			continue;
+		}
+
+		if (!arg[2]) /* "--" */
+			break;
+
+		if (parse_long_opt(&optp, arg + 2, options, count)) {
+			usage(usage_string);
+			return -1;
+		}
+		optp.argc--;
+		optp.argv++;
+	}
+
+	memmove(argv + j, optp.argv, optp.argc * sizeof(argv));
+	argv[j + optp.argc] = NULL;
+	return j + optp.argc;
+}
parse-options.h new file +29 -0
new file mode 100644
index 0000000..e4749d0
@@ -0,0 +1,29 @@
+#ifndef PARSE_OPTIONS_H
+#define PARSE_OPTIONS_H
+
+enum option_type {
+	OPTION_BOOLEAN,
+	OPTION_STRING,
+	OPTION_INTEGER,
+#if 0
+	OPTION_LAST,
+#endif
+};
+
+struct option {
+	enum option_type type;
+	const char *long_name;
+	char short_name;
+	void *value;
+};
+
+/* parse_options() will filter out the processed options and leave the
+ * non-option argments in argv[].  The return value is the number of
+ * arguments left in argv[].
+ */
+
+extern int parse_options(int argc, const char **argv,
+			 struct option *options, int count,
+			 const char *usage_string);
+
+#endif
#11 lore raw
Quoted 16 lines · Kristian Høgsberg
Quoted 15 lines · Pierre Habouzit

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

Aggregation of single switches is allowed:
-rC0 is the same as -r -C 0 (supposing that -C wants an arg).

Boolean switches automatically support the option with the same name, prefixed with 'no-' to disable the switch:
--no-color / --color only need to have an entry for "color".

Quoted 6 lines
Quoted 2 lines

Long options are supported either with '=' or without:
--some-option=foo is the same as --some-option foo

That looks great, works for me. One comment, though: it looks like you're not sure whether to call these things "options" or "switches". We should choose one and stick with it.

I use the word "switch" when it's a short_option, and "option" when
it's a long one. But maybe the distinction doesn't make sense, and it's a non-native speaker glitch. I don't care that much btw.

Quoted 5 lines
Quoted 2 lines

oh and I don't grok what OPTION_LAST is for, so I left it apart, but it seems unused ?

Oh, kill that. I used that as the option array terminator before we switched to ARRAY_SIZE().

Okay :)

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#12 lore raw
In reply to Pierre Habouzit
Quoted 10 lines · Pierre Habouzit

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

Aggregation of single switches is allowed:
-rC0 is the same as -r -C 0 (supposing that -C wants an arg).

I like options aggregation, but I'm not sure aggregating option arguments is a good idea... I can't even think of an application that does it.

Mike

#13 lore raw
Quoted 9 lines · Mike Hommey
Quoted 8 lines · Pierre Habouzit

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

Quoted 5 lines
Quoted 2 lines

Aggregation of single switches is allowed:
-rC0 is the same as -r -C 0 (supposing that -C wants an arg).

I like options aggregation, but I'm not sure aggregating option arguments is a good idea... I can't even think of an application that does it.

You mean like grep -A1 or diff -u3 or ls -w10 ?

getopt does that by default as well, so you may not have aware of it, but it's how things work in your system already.

btw ls -rw10 works, though ls -w10r drops the 'r' silently. FWIW I
don't, in that case, the alternate patch I propose complains about "10r" not being a valid integer, and that's because unlike getopt, the patch krh proposed knows what an integer is ;)

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#14 lore raw

Hi,

You probably already considered and rejected the GNU argp parser. I used it before and I'd like to know reasons I should stay away from it.

Cheers,
Emil.

Quoted 47 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Pierre Habouzit
Sent: Friday, October 05, 2007 9:46 AM
To: Mike Hommey
Cc: Kristian Høgsberg; [email protected]; Junio C Hamano
Subject: Re: [ALTERNATE PATCH] Add a simple option parser.

Quoted 1 line · Mike Hommey

On Fri, Oct 05, 2007 at 04:25:07PM +0200, Pierre Habouzit

Quoted 2 lines · <[email protected]> wrote:
Quoted 2 lines

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements

in the array

Quoted 1 line
Quoted 1 line

describes a valid option, its type and a pointer to the

location where the

Quoted 1 line
Quoted 1 line

value is written. The entry point is parse_options(),

which scans through

Quoted 1 line
Quoted 1 line

the given argv, and matches each option there against the

list of valid

Quoted 2 lines
Quoted 2 lines

options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these

is returned.

Quoted 5 lines
Quoted 3 lines

Aggregation of single switches is allowed:
-rC0 is the same as -r -C 0 (supposing that -C wants an arg).

I like options aggregation, but I'm not sure aggregating

option arguments

Quoted 1 line

is a good idea... I can't even think of an application that does it.

You mean like grep -A1 or diff -u3 or ls -w10 ?

getopt does that by default as well, so you may not have aware of it, but it's how things work in your system already.

btw ls -rw10 works, though ls -w10r drops the 'r'
silently. FWIW I
don't, in that case, the alternate patch I propose complains about "10r"
not being a valid integer, and that's because unlike getopt, the patch krh proposed knows what an integer is ;)

Signature · 4 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                
http://www.madism.org
#15 lore raw
Quoted 3 lines · On ven, oct 05, 2007 at 03:45:36 +0000, Medve Emilian-EMMEDVE1 wrote:

You probably already considered and rejected the GNU argp parser. I used it before and I'd like to know reasons I should stay away from it.

Because it's GNU and that it's a heavy dependency to begin with.
Moreover, getopt_long doesn't deal with argument types (like integers).

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#16 lore raw

Hi Pierre,

Quoted 8 lines

-----Original Message-----
From: Pierre Habouzit [mailto:[email protected]]
Sent: Friday, October 05, 2007 10:57 AM
To: Medve Emilian-EMMEDVE1
Cc: Mike Hommey; Kristian Høgsberg; [email protected]; Junio C Hamano
Subject: Re: [ALTERNATE PATCH] Add a simple option parser.

Quoted 6 lines
Quoted 3 lines · On ven, oct 05, 2007 at 03:45:36 +0000, Medve Emilian-EMMEDVE1 wrote:

You probably already considered and rejected the GNU argp parser. I used it before and I'd like to know reasons I should stay away from it.

Because it's GNU and that it's a heavy dependency to begin with.

So it's more of a political decision then a technical one?

Quoted 2 lines

Moreover, getopt_long doesn't deal with argument types (like integers).

AFAIK, getopt_long in not argp.

Cheers,
Emil.

#17 lore raw
Quoted 10 lines · "Medve Emilian-EMMEDVE1" <[email protected]> writes:

Hi Pierre,

Quoted 8 lines

-----Original Message-----
From: Pierre Habouzit [mailto:[email protected]]
Sent: Friday, October 05, 2007 10:57 AM
To: Medve Emilian-EMMEDVE1
Cc: Mike Hommey; Kristian Høgsberg; [email protected]; Junio C Hamano
Subject: Re: [ALTERNATE PATCH] Add a simple option parser.

Quoted 8 lines
Quoted 6 lines · On ven, oct 05, 2007 at 03:45:36 +0000, Medve Emilian-EMMEDVE1 wrote:
Quoted 3 lines

You probably already considered and rejected the GNU argp parser. I used it before and I'd like to know reasons I should stay away from it.

Because it's GNU and that it's a heavy dependency to begin with.

So it's more of a political decision then a technical one?

Well, if it is GNU then it is likely to mean GPLv3 (or GPLv3+) at some point of time, though it should certainly be possible for now to still secure a v2-licensed version (either GPL or LGPL).

GNU also means a different coding and indentation style.

Personally, I couldn't care less about both points (I prefer the GNU coding style anyway), but that's for the maintainer to decide, and one also has to take into account the effect on developer motivation.

And the typical git developer AFAICT prefers to consider themselves as unaligned with GNU and the FSF as much as possible.

Signature · 1 line
David Kastrup
#18 lore raw
Quoted 17 lines · David Kastrup
Quoted 15 lines · "Medve Emilian-EMMEDVE1" <[email protected]> writes:

Hi Pierre,

Quoted 13 lines

-----Original Message-----
From: Pierre Habouzit [mailto:[email protected]]
Sent: Friday, October 05, 2007 10:57 AM
To: Medve Emilian-EMMEDVE1
Cc: Mike Hommey; Kristian Høgsberg; [email protected]; Junio C Hamano
Subject: Re: [ALTERNATE PATCH] Add a simple option parser.

Quoted 3 lines · On ven, oct 05, 2007 at 03:45:36 +0000, Medve Emilian-EMMEDVE1 wrote:

You probably already considered and rejected the GNU argp parser. I used it before and I'd like to know reasons I should stay away from it.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Because it's GNU and that it's a heavy dependency to begin with.

So it's more of a political decision then a technical one?

Well, if it is GNU then it is likely to mean GPLv3 (or GPLv3+) at some point of time, though it should certainly be possible for now to still secure a v2-licensed version (either GPL or LGPL).

That is an issue indeed.

Quoted 2 lines

And the typical git developer AFAICT prefers to consider themselves as unaligned with GNU and the FSF as much as possible.

And is nothing near reality in my case.

The real issue is dependency and bloat. getopt_long would need the GNU
implementation, That I believe depends upon gettext, and argp is just bloated, and I'm not even sure it's distributed outside from the glibc anyways.

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#19 lore raw
Quoted 4 lines · Pierre Habouzit

The real issue is dependency and bloat. getopt_long would need the GNU
implementation, That I believe depends upon gettext, and argp is just bloated, and I'm not even sure it's distributed outside from the glibc anyways.

It's part of gnulib (http://savannah.gnu.org/git/?group=gnulib).
Including argp (and all its dependencies) is as easy as running some gnulib command.
It does have some bloat, but for my project it was definitely more convenient to include it than to write my own parser and the bloat is still acceptable I suppose...

bash-3.00$ du lib m4
572 lib
208 m4
bash-3.00$ du -s .
20348 .

(In a source tree without the git repo.)

skimo

#20 lore raw
In reply to Medve Emilian-EMMEDVE1
Quoted 4 lines · On Fri, 5 Oct 2007, Medve Emilian-EMMEDVE1 wrote:
Quoted 2 lines

Because it's GNU and that it's a heavy dependency to begin with.

So it's more of a political decision then a technical one?

I'd *strongly* argue against new dependencies unless they buy us something major.

We've been good at cutting them down, including any required libraries internally. We shouldn't add new ones.

So we'd have to include GNU getopt sources with the git tree, at which point any advantage would be gone. Might as well include a private and simpler version of our own.

Linus

#21 lore raw

Hello Linus,

Quoted 13 lines · On Fri, 5 Oct 2007, Medve Emilian-EMMEDVE1 wrote:
Quoted 4 lines
Quoted 2 lines

Because it's GNU and that it's a heavy dependency to begin with.

So it's more of a political decision then a technical one?

I'd *strongly* argue against new dependencies unless they buy us something major.

We've been good at cutting them down, including any required libraries
internally. We shouldn't add new ones.

Quoted 8 lines

So we'd have to include GNU getopt sources with the git tree, at which
point any advantage would be gone. Might as well include a private and
simpler version of our own.

From what I understand argp is part of glibc.

Cheers,
Emil.

#22 lore raw
Quoted 15 lines · On Fri, Oct 05, 2007 at 04:41:48PM +0000, Medve Emilian-EMMEDVE1 wrote:

Hello Linus,

Quoted 12 lines · On Fri, 5 Oct 2007, Medve Emilian-EMMEDVE1 wrote:
Quoted 4 lines
Quoted 2 lines

Because it's GNU and that it's a heavy dependency to begin with.

So it's more of a political decision then a technical one?

I'd *strongly* argue against new dependencies unless they buy us something major.

We've been good at cutting them down, including any required libraries internally. We shouldn't add new ones.

Quoted 6 lines
Quoted 3 lines

So we'd have to include GNU getopt sources with the git tree, at which point any advantage would be gone. Might as well include a private and simpler version of our own.

From what I understand argp is part of glibc.

And of course requiring the glibc would be a big step forward for the
msys (or AIX, or HP-UX, or …) port !

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#23 lore raw
In reply to Medve Emilian-EMMEDVE1
Quoted 2 lines · On Fri, 5 Oct 2007, Medve Emilian-EMMEDVE1 wrote:

From what I understand argp is part of glibc.

So are you arguing that we include all of glibc just to get git to be portable?

That's even worse.

Linus

#24 lore raw
In reply to Mike Hommey
Quoted 9 lines · Mike Hommey
Quoted 8 lines · Pierre Habouzit

The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned.

Quoted 5 lines
Quoted 2 lines

Aggregation of single switches is allowed:
-rC0 is the same as -r -C 0 (supposing that -C wants an arg).

I like options aggregation, but I'm not sure aggregating option arguments is a good idea... I can't even think of an application that does it.

I think most allow this for the last option in a row. Tar is somewhat more perverse with its non-option command string:

tar xfzbv filename.tgz 40

uses filename.tgz as the option argument for "f" and 40 for "b".

Note that while tar accepts options instead of the initial command string,

tar -xfzbv filename.tgz 40

will _not_ work, while

tar -xffilename.tgz -z -b40 -v

presumably would (have no time to test this right now).

Signature · 1 line
David Kastrup