summaryrefslogtreecommitdiff
path: root/libstore/argp.c
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1997-06-26 22:02:28 +0000
committerMiles Bader <miles@gnu.org>1997-06-26 22:02:28 +0000
commit1c9afa27a71078010d8ba947bd2247c029728023 (patch)
treebbc8e817c89a3668b64f7ee227c65786acf85ce7 /libstore/argp.c
parent32a54677fd094d8e96055b4a71c463d4340b3ff5 (diff)
(parse_opt):
Use parse_type to parse the -T option. (parse_type): New function. (struct store_parsed): Add NAME_PREFIX field. (store_parsed_free): Free it. (store_parsed_append_args): Emit it. (store_parsed_open): Use it in opens.
Diffstat (limited to 'libstore/argp.c')
-rw-r--r--libstore/argp.c108
1 files changed, 84 insertions, 24 deletions
diff --git a/libstore/argp.c b/libstore/argp.c
index 9ac7fa16..07bba996 100644
--- a/libstore/argp.c
+++ b/libstore/argp.c
@@ -42,13 +42,22 @@ static const char doc[] = "\vIf neither --interleave or --layer is specified,"
struct store_parsed
{
+ /* Names of devices parsed. */
char *names;
size_t names_len;
- const struct store_class *const *classes; /* CLASSES field passed to parser. */
+ /* Prefix that should be applied to each member of NAMES. */
+ char *name_prefix;
- const struct store_class *type; /* --store-type specified */
- const struct store_class *default_type; /* DEFAULT_TYPE field passed to parser. */
+ /* --store-type specified. This defaults to the `query' type. */
+ const struct store_class *type;
+
+ /* A vector of class pointers used to lookup class names. Defaults to
+ STORE_STD_CLASSES. */
+ const struct store_class *const *classes;
+
+ /* DEFAULT_TYPE field passed to parser. */
+ const struct store_class *default_type;
off_t interleave; /* --interleave value */
int layer : 1; /* --layer specified */
@@ -59,6 +68,8 @@ store_parsed_free (struct store_parsed *parsed)
{
if (parsed->names_len > 0)
free (parsed->names);
+ if (parsed->name_prefix)
+ free (parsed->name_prefix);
free (parsed);
}
@@ -81,10 +92,23 @@ store_parsed_append_args (const struct store_parsed *parsed,
}
if (!err && parsed->type != parsed->default_type)
- {
- snprintf (buf, sizeof buf, "--store-type=%s", parsed->type->name);
- err = argz_add (args, args_len, buf);
- }
+ if (parsed->name_prefix)
+ /* A name prefix of "PFX:" is equivalent to appending ":PFX" to the
+ type name. */
+ {
+ size_t npfx_len = strlen (parsed->name_prefix);
+ char tname[strlen ("--store-type=")
+ + strlen (parsed->type->name) + 1 + npfx_len - 1 + 1];
+ snprintf (tname, sizeof tname, "--store-type=%s:%.*s",
+ parsed->type->name, npfx_len - 1, parsed->name_prefix);
+ err = argz_add (args, args_len, buf);
+ }
+ else
+ /* A simple type name. */
+ {
+ snprintf (buf, sizeof buf, "--store-type=%s", parsed->type->name);
+ err = argz_add (args, args_len, buf);
+ }
if (! err)
err = argz_append (args, args_len, parsed->names, parsed->names_len);
@@ -136,12 +160,25 @@ error_t
store_parsed_open (const struct store_parsed *parsed, int flags,
struct store **store)
{
+ size_t pfx_len = parsed->name_prefix ? strlen (parsed->name_prefix) : 0;
size_t num = argz_count (parsed->names, parsed->names_len);
+
error_t open (char *name, struct store **store)
{
const struct store_class *type = parsed->type;
if (type->open)
- return (*type->open) (name, flags, parsed->classes, store);
+ if (parsed->name_prefix)
+ /* If there's a name prefix, we prefix any names we open with that
+ and a colon. */
+ {
+ char pfxed_name[pfx_len + 1 + strlen (name) + 1];
+ stpcpy (stpcpy (stpcpy (pfxed_name, parsed->name_prefix),
+ ":"),
+ name);
+ return (*type->open) (pfxed_name, flags, parsed->classes, store);
+ }
+ else
+ return (*type->open) (name, flags, parsed->classes, store);
else
return EOPNOTSUPP;
}
@@ -196,34 +233,57 @@ find_class (const char *name, const struct store_class *const *classes)
return 0;
}
+/* Print a parsing error message and (if exiting is turned off) return the
+ error code ERR. Requires a variable called STATE to be in scope. */
+#define PERR(err, fmt, args...) \
+ do { argp_error (state, fmt , ##args); return err; } while (0)
+
+/* Parse a --store-type/-T option. */
+static error_t
+parse_type (char *arg, struct argp_state *state, struct store_parsed *parsed)
+{
+ char *name_prefix = 0;
+ char *type_name = arg;
+ const struct store_class *type;
+ char *class_sep = strchr (arg, ':');
+
+ if (class_sep)
+ /* A `:'-separated class name "T1:T2" is equivalent to prepending "T2:"
+ to the device name passed to T1, and is useful for the case where T1
+ takes typed names of the form "T:NAME". A trailing `:', like "T1:" is
+ equivalent to prefixing `:' to the device name, which causes NAME to
+ be opened with store_open, as a file. */
+ {
+ type_name = strndupa (arg, class_sep - arg);
+ name_prefix = class_sep + 1;
+ }
+
+ type = find_class (type_name, parsed->classes);
+ if (!type || !type->open)
+ PERR (EINVAL, "%s: Invalid argument to --store-type", arg);
+ else if (type != parsed->type && parsed->type != parsed->default_type)
+ PERR (EINVAL, "--store-type specified multiple times");
+
+ parsed->type = type;
+ parsed->name_prefix = name_prefix;
+
+ return 0;
+}
+
static error_t
parse_opt (int opt, char *arg, struct argp_state *state)
{
error_t err;
struct store_parsed *parsed = state->hook;
- /* Print a parsing error message and (if exiting is turned off) return the
- error code ERR. */
-#define PERR(err, fmt, args...) \
- do { argp_error (state, fmt , ##args); return err; } while (0)
-
switch (opt)
{
case 'm':
arg = "device";
/* fall through */
case 'T':
- {
- const struct store_class *type = find_class (arg, parsed->classes);
- if (!type || !type->open)
- PERR (EINVAL, "%s: Invalid argument to --store-type", arg);
- else if (type != parsed->type && parsed->type != parsed->default_type)
- PERR (EINVAL, "--store-type specified multiple times");
- else
- parsed->type = type;
- }
- break;
-
+ return parse_type (arg, state, parsed);
+
case 'I':
if (parsed->layer)
PERR (EINVAL, "--layer and --interleave are exclusive");