*/
GNUNET_GETOPT_CommandLineOptionProcessor processor;
+ /**
+ * Function to call on @e scls to clean up after processing all
+ * the arguments. Can be NULL.
+ */
+ void (*cleaner)(void *cls);
+
/**
* Specific closure to pass to the processor.
*/
char **str);
+/**
+ * Allow user to specify a binary value using Crockford
+ * Base32 encoding.
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val binary value decoded from Crockford Base32-encoded argument
+ * @param val_size size of @a val in bytes
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE (char shortName,
+ const char *name,
+ const char *argumentHelp,
+ const char *description,
+ void *val,
+ size_t val_size);
+
+
+/**
+ * Allow user to specify a binary value using Crockford
+ * Base32 encoding where the size of the binary value is
+ * automatically determined from its type.
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val binary value decoded from Crockford Base32-encoded argument;
+ * size is determined by type (sizeof (*val)).
+ */
+#define GNUNET_GETOPT_OPTION_SET_BASE32_AUTO(shortName,name,argumentHelp,description,val) \
+ GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE(shortName,name,argumentHelp,description,val,sizeof(*val))
+
+
/**
* Allow user to specify a flag (which internally means setting
* an integer to 1/#GNUNET_YES/#GNUNET_OK.
* @param[out] level set to the verbosity level
*/
struct GNUNET_GETOPT_CommandLineOption
-GNUNET_GETOPT_OPTION_VERBOSE (int *level);
+GNUNET_GETOPT_OPTION_VERBOSE (unsigned int *level);
/**
* Marker for the end of the list of options.
*/
#define GNUNET_GETOPT_OPTION_END \
- { '\0', NULL, NULL, NULL, 0, NULL, NULL }
+ { '\0', NULL, NULL, NULL, 0, NULL, NULL, NULL }
/**
This code was heavily modified for GNUnet.
-Copyright Copyright (C) 2006 Christian Grothoff
+Copyright Copyright (C) 2006, 2017 Christian Grothoff
*/
/**
}
}
+
static int
-GNgetopt_long (int argc, char *const *argv, const char *options,
- const struct GNoption *long_options, int *opt_index)
+GNgetopt_long (int argc,
+ char *const *argv,
+ const char *options,
+ const struct GNoption *long_options,
+ int *opt_index)
{
return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
int
GNUNET_GETOPT_run (const char *binaryOptions,
const struct GNUNET_GETOPT_CommandLineOption *allOptions,
- unsigned int argc, char *const *argv)
+ unsigned int argc,
+ char *const *argv)
{
struct GNoption *long_options;
struct GNUNET_GETOPT_CommandLineProcessorContext clpc;
int count;
- int i;
char *shorts;
int spos;
int cont;
clpc.allOptions = allOptions;
clpc.argv = argv;
clpc.argc = argc;
- count = 0;
- while (allOptions[count].name != NULL)
- count++;
- long_options = GNUNET_malloc (sizeof (struct GNoption) * (count + 1));
+ for (count = 0; NULL != allOptions[count].name; count++) ;
+
+ long_options = GNUNET_new_array (count + 1,
+ struct GNoption);
shorts = GNUNET_malloc (count * 2 + 1);
spos = 0;
- for (i = 0; i < count; i++)
+ for (unsigned i = 0; i < count; i++)
{
long_options[i].name = allOptions[i].name;
long_options[i].has_arg = allOptions[i].require_argument;
long_options[count].val = '\0';
shorts[spos] = '\0';
cont = GNUNET_OK;
+
/* main getopt loop */
- while (cont == GNUNET_OK)
+ while (GNUNET_OK == cont)
{
int option_index = 0;
+ unsigned int i;
- c = GNgetopt_long (argc, argv, shorts, long_options, &option_index);
-
+ c = GNgetopt_long (argc, argv,
+ shorts,
+ long_options,
+ &option_index);
if (c == GNUNET_SYSERR)
break; /* No more flags to process */
clpc.currentArgument = GNoptind - 1;
if ((char) c == allOptions[i].shortName)
{
- cont =
- allOptions[i].processor (&clpc, allOptions[i].scls,
- allOptions[i].name, GNoptarg);
+ cont = allOptions[i].processor (&clpc,
+ allOptions[i].scls,
+ allOptions[i].name,
+ GNoptarg);
break;
}
}
if (i == count)
{
- FPRINTF (stderr, _("Use %s to get a list of options.\n"), "--help");
+ FPRINTF (stderr,
+ _("Use %s to get a list of options.\n"),
+ "--help");
cont = GNUNET_SYSERR;
}
}
-
GNUNET_free (shorts);
GNUNET_free (long_options);
- if (cont != GNUNET_OK)
- {
+
+ /* call cleaners, if available */
+ for (count = 0; NULL != allOptions[count].name; count++)
+ if (NULL != allOptions[count].cleaner)
+ allOptions[count].cleaner (allOptions[count].scls);
+
+ if (GNUNET_OK != cont)
return cont;
- }
return GNoptind;
}
* @param[out] level set to the verbosity level
*/
struct GNUNET_GETOPT_CommandLineOption
-GNUNET_GETOPT_OPTION_VERBOSE (int *level)
+GNUNET_GETOPT_OPTION_VERBOSE (unsigned int *level)
{
struct GNUNET_GETOPT_CommandLineOption clo = {
.shortName = 'V',
}
+/**
+ * Closure for #set_base32().
+ */
+struct Base32Context
+{
+ /**
+ * Value to initialize (already allocated)
+ */
+ void *val;
+
+ /**
+ * Number of bytes expected for @e val.
+ */
+ size_t val_size;
+};
+
+
+/**
+ * Set an option of type 'unsigned int' from the command line.
+ * A pointer to this function should be passed as part of the
+ * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
+ * of this type. It should be followed by a pointer to a value of
+ * type 'unsigned int'.
+ *
+ * @param ctx command line processing context
+ * @param scls additional closure (will point to the 'unsigned int')
+ * @param option name of the option
+ * @param value actual value of the option as a string.
+ * @return #GNUNET_OK if parsing the value worked
+ */
+static int
+set_base32 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
+ void *scls,
+ const char *option,
+ const char *value)
+{
+ struct Base32Context *bc = scls;
+
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (value,
+ strlen (value),
+ bc->val,
+ bc->val_size))
+ {
+ fprintf (stderr,
+ _("Argument `%s' malformed. Expected base32 (Crockford) encoded value.\n"),
+ option);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Helper function to clean up after
+ * #GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE.
+ *
+ * @param cls value to GNUNET_free()
+ */
+static void
+free_bc (void *cls)
+{
+ GNUNET_free (cls);
+}
+
+
+/**
+ * Allow user to specify a binary value using Crockford
+ * Base32 encoding.
+ *
+ * @param shortName short name of the option
+ * @param name long name of the option
+ * @param argumentHelp help text for the option argument
+ * @param description long help text for the option
+ * @param[out] val binary value decoded from Crockford Base32-encoded argument
+ * @param val_size size of @a val in bytes
+ */
+struct GNUNET_GETOPT_CommandLineOption
+GNUNET_GETOPT_OPTION_SET_BASE32_FIXED_SIZE (char shortName,
+ const char *name,
+ const char *argumentHelp,
+ const char *description,
+ void *val,
+ size_t val_size)
+{
+ struct Base32Context *bc = GNUNET_new (struct Base32Context);
+ struct GNUNET_GETOPT_CommandLineOption clo = {
+ .shortName = shortName,
+ .name = name,
+ .argumentHelp = argumentHelp,
+ .description = description,
+ .require_argument = 1,
+ .processor = &set_base32,
+ .cleaner = &free_bc,
+ .scls = (void *) bc
+ };
+
+ bc->val = val;
+ bc->val_size = val_size;
+ return clo;
+}
+
+
/* end of getopt_helpers.c */
unsigned long long lnum = 0;
const struct GNUNET_GETOPT_CommandLineOption logoptionlist[] = {
- {'f', "--flag", NULL, "helptext", 0, &GNUNET_GETOPT_set_one,
- (void *) &flag},
- {'n', "--num", "ARG", "helptext", 1, &GNUNET_GETOPT_set_uint,
- (void *) &num},
- {'N', "--lnum", "ARG", "helptext", 1, &GNUNET_GETOPT_set_ulong,
- (void *) &lnum},
+ GNUNET_GETOPT_OPTION_SET_ONE ('f',
+ "--flag",
+ "helptext",
+ &flag),
+ GNUNET_GETOPT_OPTION_SET_UINT ('n',
+ "--num",
+ "ARG",
+ "helptext",
+ &num),
+ GNUNET_GETOPT_OPTION_SET_ULONG ('N',
+ "--lnum",
+ "ARG",
+ "helptext",
+ &lnum),
GNUNET_GETOPT_OPTION_END
};
- if (6 != GNUNET_GETOPT_run ("test_getopt", logoptionlist, 6, myargv))
+ if (6 !=
+ GNUNET_GETOPT_run ("test_getopt",
+ logoptionlist,
+ 6,
+ myargv))
{
GNUNET_break (0);
return 1;
}
- if ((1 != flag) || (42 != num) || (42 != lnum))
+ if ( (1 != flag) ||
+ (42 != num) ||
+ (42 != lnum))
{
GNUNET_break (0);
return 1;