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$(echo .)org \
--cc=git@vger$(echo .)kernel.org \
--cc=gitster@pobox$(echo .)com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox