Browse Source

fdtdump: make usage a bit more friendly

This starts a new usage framework and then cuts fdtdump over to it.
Now we can do `fdtdump -h` and get something useful back.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
main
Mike Frysinger 12 years ago committed by David Gibson
parent
commit
be8d1c82cb
  1. 31
      fdtdump.c
  2. 54
      util.c
  3. 61
      util.h

31
fdtdump.c

@ -117,21 +117,36 @@ static void dump_blob(void *blob) @@ -117,21 +117,36 @@ static void dump_blob(void *blob)
}
}

/* Usage related data. */
static const char usage_synopsis[] = "fdtdump [options] <file>";
static const char usage_short_opts[] = USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] = {
USAGE_COMMON_LONG_OPTS
};
static const char * const usage_opts_help[] = {
USAGE_COMMON_OPTS_HELP
};

int main(int argc, char *argv[])
{
int opt;
const char *file;
char *buf;

if (argc < 2) {
fprintf(stderr, "supply input filename\n");
return 5;
while ((opt = util_getopt_long()) != EOF) {
switch (opt) {
case_USAGE_COMMON_FLAGS
}
}
if (optind != argc - 1)
long_usage("missing input filename");
file = argv[optind];

buf = utilfdt_read(file);
if (!buf)
die("could not read: %s\n", file);

buf = utilfdt_read(argv[1]);
if (buf)
dump_blob(buf);
else
return 10;
dump_blob(buf);

return 0;
}

54
util.c

@ -392,3 +392,57 @@ void util_version(void) @@ -392,3 +392,57 @@ void util_version(void)
printf("Version: %s\n", DTC_VERSION);
exit(0);
}

void util_long_usage(const char *errmsg, const char *synopsis,
const char *short_opts, struct option const long_opts[],
const char * const opts_help[])
{
FILE *fp = errmsg ? stderr : stdout;
const char a_arg[] = "<arg>";
size_t a_arg_len = strlen(a_arg) + 1;
size_t i;
int optlen;

fprintf(fp,
"Usage: %s\n"
"\n"
"Options: -[%s]\n", synopsis, short_opts);

/* prescan the --long opt length to auto-align */
optlen = 0;
for (i = 0; long_opts[i].name; ++i) {
/* +1 is for space between --opt and help text */
int l = strlen(long_opts[i].name) + 1;
if (long_opts[i].has_arg == a_argument)
l += a_arg_len;
if (optlen < l)
optlen = l;
}

for (i = 0; long_opts[i].name; ++i) {
/* helps when adding new applets or options */
assert(opts_help[i] != NULL);

/* first output the short flag if it has one */
if (long_opts[i].val > '~')
fprintf(fp, " ");
else
fprintf(fp, " -%c, ", long_opts[i].val);

/* then the long flag */
if (long_opts[i].has_arg == no_argument)
fprintf(fp, "--%-*s", optlen, long_opts[i].name);
else
fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
(int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");

/* finally the help text */
fprintf(fp, "%s\n", opts_help[i]);
}

if (errmsg) {
fprintf(fp, "\nError: %s\n", errmsg);
exit(EXIT_FAILURE);
} else
exit(EXIT_SUCCESS);
}

61
util.h

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
#define _UTIL_H

#include <stdarg.h>
#include <getopt.h>

/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
@ -184,4 +185,64 @@ void utilfdt_print_data(const char *data, int len); @@ -184,4 +185,64 @@ void utilfdt_print_data(const char *data, int len);
*/
void util_version(void) __attribute__((noreturn));

/**
* Show usage and exit
*
* This helps standardize the output of various utils. You most likely want
* to use the long_usage() helper below rather than call this.
*
* @param errmsg If non-NULL, an error message to display
* @param synopsis The initial example usage text (and possible examples)
* @param short_opts The string of short options
* @param long_opts The structure of long options
* @param opts_help An array of help strings (should align with long_opts)
*/
void util_long_usage(const char *errmsg, const char *synopsis,
const char *short_opts, struct option const long_opts[],
const char * const opts_help[]) __attribute__((noreturn));

/**
* Show usage and exit
*
* If you name all your usage variables with usage_xxx, then you can call this
* help macro rather than expanding all arguments yourself.
*
* @param errmsg If non-NULL, an error message to display
*/
#define long_usage(errmsg) \
util_long_usage(errmsg, usage_synopsis, usage_short_opts, \
usage_long_opts, usage_opts_help)

/**
* Call getopt_long() with standard options
*
* Since all util code runs getopt in the same way, provide a helper.
*/
#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
usage_long_opts, NULL)

/* Helper for aligning long_opts array */
#define a_argument required_argument

/* Helper for usage_short_opts string constant */
#define USAGE_COMMON_SHORT_OPTS "hV"

/* Helper for usage_long_opts option array */
#define USAGE_COMMON_LONG_OPTS \
{"help", no_argument, NULL, 'h'}, \
{"version", no_argument, NULL, 'V'}, \
{NULL, no_argument, NULL, 0x0}

/* Helper for usage_opts_help array */
#define USAGE_COMMON_OPTS_HELP \
"Print this help and exit", \
"Print version and exit", \
NULL

/* Helper for getopt case statements */
#define case_USAGE_COMMON_FLAGS \
case 'h': long_usage(NULL); \
case 'V': util_version(); \
case '?': long_usage("unknown option");

#endif /* _UTIL_H */

Loading…
Cancel
Save