#include #include #include #include #include #include "zdtmtst.h" static struct long_opt *opt_head; static int help; TEST_OPTION(help, bool, "print help message and exit", 0); void __push_opt(struct long_opt *opt) { opt->next = opt_head; /* FIXME: barrier ? */ opt_head = opt; } int parse_opt_bool(char *param, void *arg) { if (param == NULL || !strcmp(param, "on") || !strcmp(param, "yes") || !strcmp(param, "true")) { * (int *) arg = 1; return 0; } if (!strcmp(param, "off") || !strcmp(param, "no") || !strcmp(param, "false")) { * (int *) arg = 0; return 0; } return -EINVAL; } int parse_opt_int(char *param, void *arg) { char *tail; if (param == NULL || param[0] == '\0') return -EINVAL; * (int *) arg = strtol(param, &tail, 0); if (tail[0] != '\0') return -EINVAL; return 0; } int parse_opt_uint(char *param, void *arg) { char *tail; if (param == NULL || param[0] == '\0') return -EINVAL; * (unsigned int *) arg = strtoul(param, &tail, 0); if (tail[0] != '\0') return -EINVAL; return 0; } int parse_opt_long(char *param, void *arg) { char *tail; if (param == NULL || param[0] == '\0') return -EINVAL; * (long *) arg = strtol(param, &tail, 0); if (tail[0] != '\0') return -EINVAL; return 0; } int parse_opt_ulong(char *param, void *arg) { char *tail; if (param == NULL || param[0] == '\0') return -EINVAL; * (unsigned long *) arg = strtoul(param, &tail, 0); if (tail[0] != '\0') return -EINVAL; return 0; } int parse_opt_string(char *param, void *arg) { if (param == NULL || param[0] == '\0') return -EINVAL; * (char **) arg = param; return 0; } static void printopt(const struct long_opt *opt) { const char *obracket = "", *cbracket = ""; if (!opt->is_required) { obracket = "["; cbracket = "]"; } fprintf(stderr, " %s--%s=%s%s\t%s\n", obracket, opt->name, opt->type, cbracket, opt->doc); } static void helpexit(void) { struct long_opt *opt; fputs("Usage:\n", stderr); for (opt = opt_head; opt; opt = opt->next) printopt(opt); exit(1); } const char __attribute__((weak)) *test_doc; const char __attribute__((weak)) *test_author; static void prdoc(void) { if (test_doc) fprintf(stderr, "%s\n", test_doc); if (test_author) fprintf(stderr, "Author: %s\n", test_author); } void parseargs(int argc, char ** argv) { int i; struct long_opt *opt; for (i = 1; i < argc; i++) { char *name, *value; if (strlen(argv[i]) < 2 || strncmp(argv[i], "--", 2)) { fprintf(stderr, "%s: options should start with --\n", argv[i]); helpexit(); } name = argv[i] + 2; value = strchr(name, '='); if (value) value++; for (opt = opt_head; opt; opt = opt->next) if (!strncmp(name, opt->name, value - name - 1)) { if (opt->parse_opt(value, opt->value)) { fprintf(stderr, "%s: failed to parse\n", argv[i]); helpexit(); } else /* -1 marks fulfilled requirement */ opt->is_required = - opt->is_required; break; } if (!opt) { fprintf(stderr, "%s: unknown option\n", argv[i]); helpexit(); } } if (help) { prdoc(); helpexit(); } for (opt = opt_head; opt; opt = opt->next) if (opt->is_required > 0) { fprintf(stderr, "mandatory flag --%s not given\n", opt->name); helpexit(); } }