criu/test/zdtm/lib/parseargs.c
Dmitry Safonov 99346a2824 zdtm: Make test_{doc,author} weak variables
Allows to override them in every test, optionally.

Signed-off-by: Dmitry Safonov <dima@arista.com>
2020-02-16 09:15:15 -08:00

175 lines
3.3 KiB
C

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#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();
}
}