add argparser
This commit is contained in:
parent
e02f15a212
commit
8c508ad7d1
|
@ -1,11 +1,11 @@
|
|||
CC=cc
|
||||
override CFLAGS += -g -I. -Wall -Wpedantic -I ../deps/build/usr/local/include/
|
||||
override CFLAGS += -g -I. -Wall -Wpedantic -I ../deps/build/usr/local/include/ -std=gnu11
|
||||
LIBPATH = ../deps/build/usr/local/lib/
|
||||
LDFLAGS = -L $(LIBPATH)
|
||||
LDLIBS = -ljson-c -lcurl -lpthread -lGeoIP
|
||||
LDFLAGS += $(LDLIBS)
|
||||
CFLAGS_STATIC = $(CFLAGS) --static
|
||||
OBJ=helpers.o pfparser.o sysparser.o msgbuffer.o geo.o elasticsearch.o server.o config.o
|
||||
OBJ=helpers.o pfparser.o sysparser.o msgbuffer.o geo.o elasticsearch.o server.o vendor/argparse.o
|
||||
TESTS=$(patsubst %.c,%.test,$(wildcard tests/*.c))
|
||||
|
||||
|
||||
|
|
77
src/config.c
77
src/config.c
|
@ -1,77 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <json-c/json.h>
|
||||
#include "helpers.h"
|
||||
#include "config.h"
|
||||
#include "elasticsearch.h"
|
||||
|
||||
|
||||
char* get_strfield(json_object* obj, char* key) {
|
||||
json_object *o_value = json_object_object_get(obj, key);
|
||||
if(o_value == NULL)
|
||||
return NULL;
|
||||
const char* value = json_object_get_string(o_value);
|
||||
if(value == NULL)
|
||||
return NULL;
|
||||
char* dest = malloc(strlen(value) + 1);
|
||||
strcpy(dest, value);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
int get_intfield(json_object* obj, char* key) {
|
||||
json_object *o_value = json_object_object_get(obj, key);
|
||||
if(o_value == NULL)
|
||||
return 0;
|
||||
return json_object_get_int(o_value);
|
||||
}
|
||||
|
||||
|
||||
struct config* config_load(char* conf_path) {
|
||||
int fd;
|
||||
if((fd = open(conf_path, O_RDONLY)) == -1)
|
||||
panic("Config load failed");
|
||||
|
||||
struct stat fsize = {0};
|
||||
if(fstat(fd, &fsize) != 0)
|
||||
die("Conf stat failed");
|
||||
|
||||
if(fsize.st_size == 0)
|
||||
die("Empty config");
|
||||
|
||||
char* confdata = mmap(NULL, fsize.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if(confdata == MAP_FAILED)
|
||||
panic("Failed to mmap conf");
|
||||
|
||||
json_object *j_conf;
|
||||
if((j_conf = json_tokener_parse(confdata)) == NULL)
|
||||
die("Json parse failed");
|
||||
|
||||
struct config* conf = calloc(1, sizeof(struct config));
|
||||
|
||||
if((conf->url = get_strfield(j_conf, "elasticsearch")) == NULL)
|
||||
die("Config missing or invalid elasticsearch url");
|
||||
|
||||
if((conf->port = get_intfield(j_conf, "serverport")) == 0)
|
||||
die("Config missing or invalid serverport number");
|
||||
|
||||
json_object_put(j_conf);
|
||||
|
||||
if(munmap(confdata, fsize.st_size) != 0)
|
||||
panic("munmap failed");
|
||||
|
||||
close(fd);
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
void config_free(struct config* conf) {
|
||||
free(conf->url);
|
||||
free(conf);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
struct config {
|
||||
char* url;
|
||||
int port;
|
||||
};
|
||||
|
||||
|
||||
struct config* config_load(char* conf_path);
|
||||
|
||||
void config_free(struct config* conf);
|
37
src/main.c
37
src/main.c
|
@ -2,36 +2,27 @@
|
|||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include "config.h"
|
||||
#include "server.h"
|
||||
#include "helpers.h"
|
||||
#include "vendor/argparse.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s <config.json>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
int main(int argc, const char** argv) {
|
||||
int port = -1;
|
||||
char* url = NULL;
|
||||
|
||||
/*Parse port number to integer*/
|
||||
/*char* portend;
|
||||
unsigned int portl;
|
||||
portl = strtol(argv[1], &portend, 10);
|
||||
if (portend == NULL || portend == argv[1]) {
|
||||
fprintf(stderr, "usage: %s <port>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
assert(portl < USHRT_MAX);
|
||||
unsigned short port = (unsigned short)portl;*/
|
||||
struct argparse_option options[] = {
|
||||
OPT_HELP(),
|
||||
OPT_INTEGER('p', "port", &port, "server port"),
|
||||
OPT_STRING ('u', "url", &url, "elasticsearch url"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
struct config* conf = config_load(argv[1]);
|
||||
struct argparse argparse;
|
||||
argparse_init(&argparse, options, NULL, 0);
|
||||
argparse_parse(&argparse, argc, argv);
|
||||
|
||||
printf("url: %s\n", conf->url);
|
||||
printf("port: %d\n", conf->port);
|
||||
|
||||
run_server(conf->port, conf->url);
|
||||
|
||||
config_free(conf);
|
||||
run_server(port, url);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ void* buffer_watch() {
|
|||
time_t last_flush = time(NULL);
|
||||
char* buffer = NULL;
|
||||
while(running) {
|
||||
usleep(100 * 1000);
|
||||
nanosleep(&(const struct timespec){0, 1000000}, NULL);
|
||||
time_t now = time(NULL);
|
||||
|
||||
pthread_mutex_lock(&buflock);
|
||||
|
|
|
@ -0,0 +1,385 @@
|
|||
/**
|
||||
* Copyright (C) 2012-2015 Yecheng Fu <cofyc.jackson at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style license that can be found
|
||||
* in the LICENSE file.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include "argparse.h"
|
||||
|
||||
#define OPT_UNSET 1
|
||||
#define OPT_LONG (1 << 1)
|
||||
|
||||
static const char *
|
||||
prefix_skip(const char *str, const char *prefix)
|
||||
{
|
||||
size_t len = strlen(prefix);
|
||||
return strncmp(str, prefix, len) ? NULL : str + len;
|
||||
}
|
||||
|
||||
static int
|
||||
prefix_cmp(const char *str, const char *prefix)
|
||||
{
|
||||
for (;; str++, prefix++)
|
||||
if (!*prefix) {
|
||||
return 0;
|
||||
} else if (*str != *prefix) {
|
||||
return (unsigned char)*prefix - (unsigned char)*str;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
argparse_error(struct argparse *self, const struct argparse_option *opt,
|
||||
const char *reason, int flags)
|
||||
{
|
||||
(void)self;
|
||||
if (flags & OPT_LONG) {
|
||||
fprintf(stderr, "error: option `--%s` %s\n", opt->long_name, reason);
|
||||
} else {
|
||||
fprintf(stderr, "error: option `-%c` %s\n", opt->short_name, reason);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_getvalue(struct argparse *self, const struct argparse_option *opt,
|
||||
int flags)
|
||||
{
|
||||
const char *s = NULL;
|
||||
if (!opt->value)
|
||||
goto skipped;
|
||||
switch (opt->type) {
|
||||
case ARGPARSE_OPT_BOOLEAN:
|
||||
if (flags & OPT_UNSET) {
|
||||
*(int *)opt->value = *(int *)opt->value - 1;
|
||||
} else {
|
||||
*(int *)opt->value = *(int *)opt->value + 1;
|
||||
}
|
||||
if (*(int *)opt->value < 0) {
|
||||
*(int *)opt->value = 0;
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_BIT:
|
||||
if (flags & OPT_UNSET) {
|
||||
*(int *)opt->value &= ~opt->data;
|
||||
} else {
|
||||
*(int *)opt->value |= opt->data;
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_STRING:
|
||||
if (self->optvalue) {
|
||||
*(const char **)opt->value = self->optvalue;
|
||||
self->optvalue = NULL;
|
||||
} else if (self->argc > 1) {
|
||||
self->argc--;
|
||||
*(const char **)opt->value = *++self->argv;
|
||||
} else {
|
||||
argparse_error(self, opt, "requires a value", flags);
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_INTEGER:
|
||||
errno = 0;
|
||||
if (self->optvalue) {
|
||||
*(int *)opt->value = strtol(self->optvalue, (char **)&s, 0);
|
||||
self->optvalue = NULL;
|
||||
} else if (self->argc > 1) {
|
||||
self->argc--;
|
||||
*(int *)opt->value = strtol(*++self->argv, (char **)&s, 0);
|
||||
} else {
|
||||
argparse_error(self, opt, "requires a value", flags);
|
||||
}
|
||||
if (errno)
|
||||
argparse_error(self, opt, strerror(errno), flags);
|
||||
if (s[0] != '\0')
|
||||
argparse_error(self, opt, "expects an integer value", flags);
|
||||
break;
|
||||
case ARGPARSE_OPT_FLOAT:
|
||||
errno = 0;
|
||||
if (self->optvalue) {
|
||||
*(float *)opt->value = strtof(self->optvalue, (char **)&s);
|
||||
self->optvalue = NULL;
|
||||
} else if (self->argc > 1) {
|
||||
self->argc--;
|
||||
*(float *)opt->value = strtof(*++self->argv, (char **)&s);
|
||||
} else {
|
||||
argparse_error(self, opt, "requires a value", flags);
|
||||
}
|
||||
if (errno)
|
||||
argparse_error(self, opt, strerror(errno), flags);
|
||||
if (s[0] != '\0')
|
||||
argparse_error(self, opt, "expects a numerical value", flags);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
skipped:
|
||||
if (opt->callback) {
|
||||
return opt->callback(self, opt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
argparse_options_check(const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
switch (options->type) {
|
||||
case ARGPARSE_OPT_END:
|
||||
case ARGPARSE_OPT_BOOLEAN:
|
||||
case ARGPARSE_OPT_BIT:
|
||||
case ARGPARSE_OPT_INTEGER:
|
||||
case ARGPARSE_OPT_FLOAT:
|
||||
case ARGPARSE_OPT_STRING:
|
||||
case ARGPARSE_OPT_GROUP:
|
||||
continue;
|
||||
default:
|
||||
fprintf(stderr, "wrong option type: %d", options->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_short_opt(struct argparse *self, const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
if (options->short_name == *self->optvalue) {
|
||||
self->optvalue = self->optvalue[1] ? self->optvalue + 1 : NULL;
|
||||
return argparse_getvalue(self, options, 0);
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_long_opt(struct argparse *self, const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
const char *rest;
|
||||
int opt_flags = 0;
|
||||
if (!options->long_name)
|
||||
continue;
|
||||
|
||||
rest = prefix_skip(self->argv[0] + 2, options->long_name);
|
||||
if (!rest) {
|
||||
// negation disabled?
|
||||
if (options->flags & OPT_NONEG) {
|
||||
continue;
|
||||
}
|
||||
// only OPT_BOOLEAN/OPT_BIT supports negation
|
||||
if (options->type != ARGPARSE_OPT_BOOLEAN && options->type !=
|
||||
ARGPARSE_OPT_BIT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix_cmp(self->argv[0] + 2, "no-")) {
|
||||
continue;
|
||||
}
|
||||
rest = prefix_skip(self->argv[0] + 2 + 3, options->long_name);
|
||||
if (!rest)
|
||||
continue;
|
||||
opt_flags |= OPT_UNSET;
|
||||
}
|
||||
if (*rest) {
|
||||
if (*rest != '=')
|
||||
continue;
|
||||
self->optvalue = rest + 1;
|
||||
}
|
||||
return argparse_getvalue(self, options, opt_flags | OPT_LONG);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int
|
||||
argparse_init(struct argparse *self, struct argparse_option *options,
|
||||
const char *const *usages, int flags)
|
||||
{
|
||||
memset(self, 0, sizeof(*self));
|
||||
self->options = options;
|
||||
self->usages = usages;
|
||||
self->flags = flags;
|
||||
self->description = NULL;
|
||||
self->epilog = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
argparse_describe(struct argparse *self, const char *description,
|
||||
const char *epilog)
|
||||
{
|
||||
self->description = description;
|
||||
self->epilog = epilog;
|
||||
}
|
||||
|
||||
int
|
||||
argparse_parse(struct argparse *self, int argc, const char **argv)
|
||||
{
|
||||
self->argc = argc - 1;
|
||||
self->argv = argv + 1;
|
||||
self->out = argv;
|
||||
|
||||
argparse_options_check(self->options);
|
||||
|
||||
for (; self->argc; self->argc--, self->argv++) {
|
||||
const char *arg = self->argv[0];
|
||||
if (arg[0] != '-' || !arg[1]) {
|
||||
if (self->flags & ARGPARSE_STOP_AT_NON_OPTION) {
|
||||
goto end;
|
||||
}
|
||||
// if it's not option or is a single char '-', copy verbatim
|
||||
self->out[self->cpidx++] = self->argv[0];
|
||||
continue;
|
||||
}
|
||||
// short option
|
||||
if (arg[1] != '-') {
|
||||
self->optvalue = arg + 1;
|
||||
switch (argparse_short_opt(self, self->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
while (self->optvalue) {
|
||||
switch (argparse_short_opt(self, self->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// if '--' presents
|
||||
if (!arg[2]) {
|
||||
self->argc--;
|
||||
self->argv++;
|
||||
break;
|
||||
}
|
||||
// long option
|
||||
switch (argparse_long_opt(self, self->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
continue;
|
||||
|
||||
unknown:
|
||||
fprintf(stderr, "error: unknown option `%s`\n", self->argv[0]);
|
||||
argparse_usage(self);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
end:
|
||||
memmove(self->out + self->cpidx, self->argv,
|
||||
self->argc * sizeof(*self->out));
|
||||
self->out[self->cpidx + self->argc] = NULL;
|
||||
|
||||
return self->cpidx + self->argc;
|
||||
}
|
||||
|
||||
void
|
||||
argparse_usage(struct argparse *self)
|
||||
{
|
||||
if (self->usages) {
|
||||
fprintf(stdout, "Usage: %s\n", *self->usages++);
|
||||
while (*self->usages && **self->usages)
|
||||
fprintf(stdout, " or: %s\n", *self->usages++);
|
||||
} else {
|
||||
fprintf(stdout, "Usage:\n");
|
||||
}
|
||||
|
||||
// print description
|
||||
if (self->description)
|
||||
fprintf(stdout, "%s\n", self->description);
|
||||
|
||||
fputc('\n', stdout);
|
||||
|
||||
const struct argparse_option *options;
|
||||
|
||||
// figure out best width
|
||||
size_t usage_opts_width = 0;
|
||||
size_t len;
|
||||
options = self->options;
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
len = 0;
|
||||
if ((options)->short_name) {
|
||||
len += 2;
|
||||
}
|
||||
if ((options)->short_name && (options)->long_name) {
|
||||
len += 2; // separator ", "
|
||||
}
|
||||
if ((options)->long_name) {
|
||||
len += strlen((options)->long_name) + 2;
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_INTEGER) {
|
||||
len += strlen("=<int>");
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_FLOAT) {
|
||||
len += strlen("=<flt>");
|
||||
} else if (options->type == ARGPARSE_OPT_STRING) {
|
||||
len += strlen("=<str>");
|
||||
}
|
||||
len = (len + 3) - ((len + 3) & 3);
|
||||
if (usage_opts_width < len) {
|
||||
usage_opts_width = len;
|
||||
}
|
||||
}
|
||||
usage_opts_width += 4; // 4 spaces prefix
|
||||
|
||||
options = self->options;
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
size_t pos = 0;
|
||||
int pad = 0;
|
||||
if (options->type == ARGPARSE_OPT_GROUP) {
|
||||
fputc('\n', stdout);
|
||||
fprintf(stdout, "%s", options->help);
|
||||
fputc('\n', stdout);
|
||||
continue;
|
||||
}
|
||||
pos = fprintf(stdout, " ");
|
||||
if (options->short_name) {
|
||||
pos += fprintf(stdout, "-%c", options->short_name);
|
||||
}
|
||||
if (options->long_name && options->short_name) {
|
||||
pos += fprintf(stdout, ", ");
|
||||
}
|
||||
if (options->long_name) {
|
||||
pos += fprintf(stdout, "--%s", options->long_name);
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_INTEGER) {
|
||||
pos += fprintf(stdout, "=<int>");
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_FLOAT) {
|
||||
pos += fprintf(stdout, "=<flt>");
|
||||
} else if (options->type == ARGPARSE_OPT_STRING) {
|
||||
pos += fprintf(stdout, "=<str>");
|
||||
}
|
||||
if (pos <= usage_opts_width) {
|
||||
pad = usage_opts_width - pos;
|
||||
} else {
|
||||
fputc('\n', stdout);
|
||||
pad = usage_opts_width;
|
||||
}
|
||||
fprintf(stdout, "%*s%s\n", pad + 2, "", options->help);
|
||||
}
|
||||
|
||||
// print epilog
|
||||
if (self->epilog)
|
||||
fprintf(stdout, "%s\n", self->epilog);
|
||||
}
|
||||
|
||||
int
|
||||
argparse_help_cb(struct argparse *self, const struct argparse_option *option)
|
||||
{
|
||||
(void)option;
|
||||
argparse_usage(self);
|
||||
exit(0);
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* Copyright (C) 2012-2015 Yecheng Fu <cofyc.jackson at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style license that can be found
|
||||
* in the LICENSE file.
|
||||
*/
|
||||
#ifndef ARGPARSE_H
|
||||
#define ARGPARSE_H
|
||||
|
||||
/* For c++ compatibility */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct argparse;
|
||||
struct argparse_option;
|
||||
|
||||
typedef int argparse_callback (struct argparse *self,
|
||||
const struct argparse_option *option);
|
||||
|
||||
enum argparse_flag {
|
||||
ARGPARSE_STOP_AT_NON_OPTION = 1,
|
||||
};
|
||||
|
||||
enum argparse_option_type {
|
||||
/* special */
|
||||
ARGPARSE_OPT_END,
|
||||
ARGPARSE_OPT_GROUP,
|
||||
/* options with no arguments */
|
||||
ARGPARSE_OPT_BOOLEAN,
|
||||
ARGPARSE_OPT_BIT,
|
||||
/* options with arguments (optional or required) */
|
||||
ARGPARSE_OPT_INTEGER,
|
||||
ARGPARSE_OPT_FLOAT,
|
||||
ARGPARSE_OPT_STRING,
|
||||
};
|
||||
|
||||
enum argparse_option_flags {
|
||||
OPT_NONEG = 1, /* disable negation */
|
||||
};
|
||||
|
||||
/**
|
||||
* argparse option
|
||||
*
|
||||
* `type`:
|
||||
* holds the type of the option, you must have an ARGPARSE_OPT_END last in your
|
||||
* array.
|
||||
*
|
||||
* `short_name`:
|
||||
* the character to use as a short option name, '\0' if none.
|
||||
*
|
||||
* `long_name`:
|
||||
* the long option name, without the leading dash, NULL if none.
|
||||
*
|
||||
* `value`:
|
||||
* stores pointer to the value to be filled.
|
||||
*
|
||||
* `help`:
|
||||
* the short help message associated to what the option does.
|
||||
* Must never be NULL (except for ARGPARSE_OPT_END).
|
||||
*
|
||||
* `callback`:
|
||||
* function is called when corresponding argument is parsed.
|
||||
*
|
||||
* `data`:
|
||||
* associated data. Callbacks can use it like they want.
|
||||
*
|
||||
* `flags`:
|
||||
* option flags.
|
||||
*/
|
||||
struct argparse_option {
|
||||
enum argparse_option_type type;
|
||||
const char short_name;
|
||||
const char *long_name;
|
||||
void *value;
|
||||
const char *help;
|
||||
argparse_callback *callback;
|
||||
intptr_t data;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* argpparse
|
||||
*/
|
||||
struct argparse {
|
||||
// user supplied
|
||||
const struct argparse_option *options;
|
||||
const char *const *usages;
|
||||
int flags;
|
||||
const char *description; // a description after usage
|
||||
const char *epilog; // a description at the end
|
||||
// internal context
|
||||
int argc;
|
||||
const char **argv;
|
||||
const char **out;
|
||||
int cpidx;
|
||||
const char *optvalue; // current option value
|
||||
};
|
||||
|
||||
// built-in callbacks
|
||||
int argparse_help_cb(struct argparse *self,
|
||||
const struct argparse_option *option);
|
||||
|
||||
// built-in option macros
|
||||
#define OPT_END() { ARGPARSE_OPT_END, 0, NULL, NULL, 0, NULL, 0, 0 }
|
||||
#define OPT_BOOLEAN(...) { ARGPARSE_OPT_BOOLEAN, __VA_ARGS__ }
|
||||
#define OPT_BIT(...) { ARGPARSE_OPT_BIT, __VA_ARGS__ }
|
||||
#define OPT_INTEGER(...) { ARGPARSE_OPT_INTEGER, __VA_ARGS__ }
|
||||
#define OPT_FLOAT(...) { ARGPARSE_OPT_FLOAT, __VA_ARGS__ }
|
||||
#define OPT_STRING(...) { ARGPARSE_OPT_STRING, __VA_ARGS__ }
|
||||
#define OPT_GROUP(h) { ARGPARSE_OPT_GROUP, 0, NULL, NULL, h, NULL, 0, 0 }
|
||||
#define OPT_HELP() OPT_BOOLEAN('h', "help", NULL, \
|
||||
"show this help message and exit", \
|
||||
argparse_help_cb, 0, 0)
|
||||
|
||||
int argparse_init(struct argparse *self, struct argparse_option *options,
|
||||
const char *const *usages, int flags);
|
||||
void argparse_describe(struct argparse *self, const char *description,
|
||||
const char *epilog);
|
||||
int argparse_parse(struct argparse *self, int argc, const char **argv);
|
||||
void argparse_usage(struct argparse *self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue