mirror of
https://github.com/dgibson/dtc.git
synced 2025-10-13 16:27:39 -04:00
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>
This commit is contained in:
parent
4e76ec796c
commit
be8d1c82cb
3 changed files with 138 additions and 8 deletions
29
fdtdump.c
29
fdtdump.c
|
@ -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 main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
int opt;
|
||||||
|
const char *file;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
if (argc < 2) {
|
while ((opt = util_getopt_long()) != EOF) {
|
||||||
fprintf(stderr, "supply input filename\n");
|
switch (opt) {
|
||||||
return 5;
|
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);
|
dump_blob(buf);
|
||||||
else
|
|
||||||
return 10;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
54
util.c
54
util.c
|
@ -392,3 +392,57 @@ void util_version(void)
|
||||||
printf("Version: %s\n", DTC_VERSION);
|
printf("Version: %s\n", DTC_VERSION);
|
||||||
exit(0);
|
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
61
util.h
|
@ -2,6 +2,7 @@
|
||||||
#define _UTIL_H
|
#define _UTIL_H
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 The Chromium Authors, All Rights Reserved.
|
* Copyright 2011 The Chromium Authors, All Rights Reserved.
|
||||||
|
@ -184,4 +185,64 @@ void utilfdt_print_data(const char *data, int len);
|
||||||
*/
|
*/
|
||||||
void util_version(void) __attribute__((noreturn));
|
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 */
|
#endif /* _UTIL_H */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue