From: Pierre Habouzit <madcoder@debian.org>
To: gitster@pobox.com
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org, Pierre Habouzit <madcoder@debian.org>
Subject: [PATCH 3/4] Add OPTION_BASEOFFSET/OPTION_SUBARRAY.
Date: Mon, 5 Nov 2007 13:03:23 +0100 [thread overview]
Message-ID: <1194264204-3475-4-git-send-email-madcoder@debian.org> (raw)
In-Reply-To: <1194264204-3475-3-git-send-email-madcoder@debian.org>
Currently make the implementation die() if SUBARRAYs are encountered.
Refactor the rest of the code to be ready for recursion.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
parse-options.c | 114 ++++++++++++++++++++++++++++++++++++++-----------------
parse-options.h | 6 +++
2 files changed, 85 insertions(+), 35 deletions(-)
diff --git a/parse-options.c b/parse-options.c
index d2e32c1..5cea511 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -8,6 +8,9 @@ struct optparse_t {
const char **argv;
int argc;
const char *opt;
+
+ const struct option *abbrev_option, *conflict_option;
+ int abbrev_flags, conflict_flags;
};
static inline const char *get_arg(struct optparse_t *p)
@@ -104,23 +107,35 @@ 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 level)
{
- for (; options->type != OPTION_END; options++) {
- if (options->short_name == *p->opt) {
+ for (;; options++) {
+ switch (options->type) {
+ case OPTION_END:
+ return level > 0 ? -1 : error("unknown switch `%c'", *p->opt);
+ case OPTION_GROUP:
+ case OPTION_BASEOFFSET:
+ continue;
+ case OPTION_SUBARRAY:
+ die("unsupported yet");
+ break;
+ default:
+ if (options->short_name != *p->opt)
+ continue;
p->opt = p->opt[1] ? p->opt + 1 : NULL;
return get_value(p, options, OPT_SHORT);
}
}
- 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 level)
{
const char *arg_end = strchr(arg, '=');
- const struct option *abbrev_option = NULL, *conflict_option = NULL;
- int abbrev_flags = 0, conflict_flags = 0;
+
+ if (level == 0)
+ p->conflict_option = p->abbrev_option = NULL;
if (!arg_end)
arg_end = arg + strlen(arg);
@@ -129,6 +144,17 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
const char *rest;
int flags = 0;
+ switch (options->type) {
+ case OPTION_GROUP:
+ case OPTION_BASEOFFSET:
+ continue;
+ case OPTION_SUBARRAY:
+ die("unsupported yet");
+ break;
+ default:
+ break;
+ }
+
if (!options->long_name)
continue;
@@ -138,13 +164,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
rest = skip_prefix(arg, options->long_name);
if (!rest) {
+ /* negated and abbreviated very much? */
+ if (!prefixcmp("no-", arg))
+ die("--n,--no,--no- are never proper abbreviated options");
/* abbreviated? */
if (!strncmp(options->long_name, arg, arg_end - arg)) {
is_abbreviated:
- conflict_option = abbrev_option;
- conflict_flags = abbrev_flags;
- abbrev_option = options;
- abbrev_flags = flags;
+ p->conflict_option = p->abbrev_option;
+ p->conflict_flags = p->abbrev_flags;
+ p->abbrev_option = options;
+ p->abbrev_flags = flags;
continue;
}
/* negated? */
@@ -167,16 +196,18 @@ is_abbreviated:
}
return get_value(p, options, flags);
}
- if (conflict_option)
+ if (level > 0)
+ return -1;
+ if (p->conflict_option)
return error("Ambiguous option: %s (could be --%s%s or --%s%s)",
- arg, (conflict_flags & OPT_UNSET) ? "no-" : "",
- conflict_option->long_name,
- (abbrev_flags & OPT_UNSET) ? "no-" : "",
- abbrev_option->long_name);
- if (abbrev_option) {
- if (!(abbrev_flags & OPT_UNSET) && *arg_end)
+ arg, (p->conflict_flags & OPT_UNSET) ? "no-" : "",
+ p->conflict_option->long_name,
+ (p->abbrev_flags & OPT_UNSET) ? "no-" : "",
+ p->abbrev_option->long_name);
+ if (p->abbrev_option) {
+ if (!(p->abbrev_flags & OPT_UNSET) && *arg_end)
p->opt = arg_end + 1;
- return get_value(p, abbrev_option, abbrev_flags);
+ return get_value(p, p->abbrev_option, p->abbrev_flags);
}
return error("unknown option `%s'", arg);
}
@@ -200,7 +231,7 @@ int parse_options(int argc, const char **argv, const struct option *options,
do {
if (*args.opt == 'h')
usage_with_options(usagestr, options);
- if (parse_short_opt(&args, options) < 0)
+ if (parse_short_opt(&args, options, 0) < 0)
usage_with_options(usagestr, options);
} while (args.opt);
continue;
@@ -216,7 +247,7 @@ int parse_options(int argc, const char **argv, const struct option *options,
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, 0))
usage_with_options(usagestr, options);
}
@@ -228,27 +259,27 @@ int parse_options(int argc, const char **argv, const struct option *options,
#define USAGE_OPTS_WIDTH 24
#define USAGE_GAP 2
-void usage_with_options(const char * const *usagestr,
- const struct option *opts)
+static void dump_options(const struct option *opts)
{
- fprintf(stderr, "usage: %s\n", *usagestr++);
- while (*usagestr && **usagestr)
- fprintf(stderr, " or: %s\n", *usagestr++);
- while (*usagestr)
- fprintf(stderr, " %s\n", *usagestr++);
-
- if (opts->type != OPTION_GROUP)
- fputc('\n', stderr);
-
- for (; opts->type != OPTION_END; opts++) {
+ for (;; opts++) {
size_t pos;
int pad;
- if (opts->type == OPTION_GROUP) {
+ switch (opts->type) {
+ case OPTION_END:
+ return;
+ case OPTION_GROUP:
fputc('\n', stderr);
if (*opts->help)
fprintf(stderr, "%s\n", opts->help);
continue;
+ case OPTION_BASEOFFSET:
+ continue;
+ case OPTION_SUBARRAY:
+ dump_options((struct option *)opts->defval);
+ continue;
+ default:
+ break;
}
pos = fprintf(stderr, " ");
@@ -295,8 +326,21 @@ void usage_with_options(const char * const *usagestr,
}
fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
}
- fputc('\n', stderr);
+}
+void usage_with_options(const char * const *usagestr,
+ const struct option *opts)
+{
+ fprintf(stderr, "usage: %s\n", *usagestr++);
+ while (*usagestr && **usagestr)
+ fprintf(stderr, " or: %s\n", *usagestr++);
+ while (*usagestr)
+ fprintf(stderr, " %s\n", *usagestr++);
+
+ if (opts->type != OPTION_GROUP)
+ fputc('\n', stderr);
+ dump_options(opts);
+ fputc('\n', stderr);
exit(129);
}
diff --git a/parse-options.h b/parse-options.h
index 65bce6e..6668924 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -4,6 +4,8 @@
enum parse_opt_type {
OPTION_END,
OPTION_GROUP,
+ OPTION_BASEOFFSET,
+ OPTION_SUBARRAY,
OPTION_BOOLEAN,
OPTION_STRING,
OPTION_INTEGER,
@@ -35,6 +37,7 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
*
* `value`::
* stores pointers to the values to be filled.
+ * BASEOFFSET use it to store the offset wrt which the struct was filled.
*
* `argh`::
* token to explain the kind of argument this option wants. Keep it
@@ -56,6 +59,9 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
* `defval`::
* default value to fill (*->value) with for PARSE_OPT_OPTARG.
* CALLBACKS can use it like they want.
+ * SUBARRAYs use it to store the subarray address.
+ * BASEOFFSET use it to store the sizeof the struct used to fill the array.
+ * Any `value` that does not points into it is not relocated.
*/
struct option {
enum parse_opt_type type;
--
1.5.3.5.1531.g59008
next prev parent reply other threads:[~2007-11-05 12:03 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-05 12:03 proposal for an OPTION_SUBARRAY (recursive parser) Pierre Habouzit
2007-11-05 12:03 ` [PATCH 1/4] parse-options: abbreviation engine fix Pierre Habouzit
2007-11-05 12:03 ` [PATCH 2/4] Some better parse-options documentation Pierre Habouzit
2007-11-05 12:03 ` Pierre Habouzit [this message]
2007-11-05 12:03 ` [PATCH 4/4] Implement OPTION_SUBARRAY handling Pierre Habouzit
2007-11-05 12:34 ` [PATCH] parse-options: abbreviation engine fix Johannes Schindelin
2007-11-05 12:38 ` Johannes Schindelin
2007-11-05 13:15 ` [PATCH 1/3] " Johannes Schindelin
2007-11-05 13:15 ` [PATCH 2/3] parseopt: introduce OPT_RECURSE to specify shared options Johannes Schindelin
2007-11-05 13:46 ` Johannes Schindelin
2007-11-05 16:15 ` Linus Torvalds
2007-11-05 16:29 ` Johannes Schindelin
2007-11-05 16:53 ` Pierre Habouzit
2007-11-05 21:48 ` Junio C Hamano
2007-11-05 22:14 ` Pierre Habouzit
2007-11-05 13:15 ` [PATCH 3/3] parseopt: do not list options with the same name twice Johannes Schindelin
2007-11-05 12:59 ` [PATCH] parse-options: abbreviation engine fix Pierre Habouzit
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1194264204-3475-4-git-send-email-madcoder@debian.org \
--to=madcoder@debian.org \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.