summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2022-07-28 19:46:53 -0300
committermrb0nk500 <b0nk@b0nk.xyz>2022-07-28 19:46:53 -0300
commitc8f5ba65044992deb3175e9b89792e13a8af4539 (patch)
tree8bc5dc0a43386c0b47fab89cbe5426f51de77e36
parentb46091ed2d79aacc0c44417ac2e3f85663f750af (diff)
config: Make use of `keyword` for parsing config files
This get's rid of the old `config_opt` parser, which was way too specific for parsing config files.
-rw-r--r--config.c74
-rw-r--r--config.h48
2 files changed, 42 insertions, 80 deletions
diff --git a/config.c b/config.c
index 1755ad3..012ed3d 100644
--- a/config.c
+++ b/config.c
@@ -7,42 +7,31 @@
#include "macros.h"
#include "misc.h"
-config_val parse_option_value(const config_opt *opt, char *value) {
- config_val val = {0};
-
- switch (opt->type) {
- case TYPE_INT :
- case TYPE_BOOL : val.i = strtol(value, NULL, 0); break;
- case TYPE_STRING: val.str = make_str(value); break;
- case TYPE_FLOAT : val.f = strtof(value, NULL); break;
- default : break;
- }
-
- return val;
-}
-
-void set_config_opt(config *conf, config_type type, size_t offset, config_val val) {
- char *cfg = (char *)conf;
- switch (type) {
- case TYPE_INT :
- case TYPE_BOOL : *(int *)(cfg+offset) = val.i; break;
- case TYPE_STRING: *(char **)(cfg+offset) = val.str; break;
- case TYPE_FLOAT : *(float *)(cfg+offset) = val.f; break;
- default : break;
- }
-}
-
void cleanup_config(config *conf) {
- char *cfg = (char *)conf;
- for (const config_opt *opt = config_opts; opt->name != NULL; opt++) {
+ for (int i = 0; config_keywords[i] != NULL; ++i) {
+ /* Get the pointer to the config option. */
+ void *cfg = get_keyword_offset_ptr(config_keywords[i], conf);
/* Is this config option's type a string, and is the string of that config option in conf not NULL? */
- if (opt->type == TYPE_STRING && *(char **)(cfg+opt->offset) != NULL) {
- free(*(char **)(cfg+opt->offset));
+ if (config_keywords[i]->type == TYPE_STRING && *(void **)cfg != NULL) {
+ free(*(void **)cfg);
}
}
free(conf);
}
+int check_port(void *ctx, void *ret, const keyword *key, keyword_val val) {
+ if (key->type == TYPE_INT) {
+ if (val.i > 0 || val.i <= 65535) {
+ return 0;
+ } else {
+ log(LOG_ERR, "Invalid port %d. (Valid port must be between 1, and 65535.)", val.i);
+ }
+ } else {
+ log(LOG_ERR, "Keyword \"%s\" doesn't return an integer.", key->key);
+ }
+ return -1;
+}
+
config *parse_config(const char *filename) {
/* Size of the file, in bytes. */
long filesize = 0;
@@ -69,25 +58,18 @@ config *parse_config(const char *filename) {
char *line = get_line(&tmp);
char *value;
char *name = strtok_r(line, "=", &value);
- const config_opt *opt;
-
- /* Check to see if the config option name we got is valid. */
- for (opt = config_opts; opt->name != NULL && strcmp(name, opt->name); opt++);
+ int error;
- /* Is the config option valid? */
- if (opt->name != NULL) {
- config_val val = parse_option_value(opt, value);
- if (opt->offset == offsetof(config, port)) {
- const int port = strtol(val.str, NULL, 0);
- if (port <= 0 || port > 65535) {
- log(LOG_ERR, "Invalid port %d. (Valid port must be between 1, and 65535.)", port);
- cleanup_config(cfg);
- free(line);
- free(buf);
- return NULL;
- }
+ /* Did we fail to parse the config option? */
+ if (error = parse_keywords(config_keywords, name, value, cfg, NULL)) {
+ if (error == 5) {
+ cleanup_config(cfg);
+ free(line);
+ free(buf);
+ return NULL;
+ } else {
+ log(LOG_WARNING, "Failed to parse config option \"%s\". Error code: %i", name, error);
}
- set_config_opt(cfg, opt->type, opt->offset, val);
}
free(line);
diff --git a/config.h b/config.h
index 5ba0978..4d35af6 100644
--- a/config.h
+++ b/config.h
@@ -2,20 +2,9 @@
#define CONFIG_H
#include <stddef.h>
+#include "keyword.h"
typedef struct config config;
-typedef struct config_opt config_opt;
-typedef union config_val config_val;
-typedef enum config_type config_type;
-
-enum config_type {
- TYPE_NONE,
- TYPE_INT,
- TYPE_STRING,
- TYPE_FLOAT,
- TYPE_BOOL,
- TYPE_COUNT,
-};
struct config {
char *git_root; /* Root of git server. */
@@ -27,29 +16,20 @@ struct config {
char *key_path; /* Path to maintainer authentication key file. */
};
-struct config_opt {
- const char *name; /* Name of the config option. */
- const char *desc; /* Description of the config option. */
- config_type type; /* Datatype of the config option. */
- size_t offset; /* Offset of the member of the config option in the config struct. */
-};
-
-union config_val {
- int i; /* Integer. */
- char *str; /* String. */
- float f; /* Float. */
-};
-
-static const config_opt config_opts[] = {
- {"git-root", "Root of git server (can also be a url).", TYPE_STRING, offsetof(config, git_root)},
- {"socket-type", "Socket type to use (options: unix, network. default: network).", TYPE_STRING, offsetof(config, sock_type)},
- {"socket", "Path, IP address, or domain name of socket.", TYPE_STRING, offsetof(config, sock)},
- {"port", "Port to listen on (network socket only).", TYPE_STRING, offsetof(config, port)},
- {"merge-type", "Type of merge (options: 0 = Merge individually, 1 = Merge into one).", TYPE_INT, offsetof(config, merge_type)},
- {"pr-root", "Directory to store pull requests in.", TYPE_STRING, offsetof(config, pr_root)},
- {"key-file", "Path to file containing gpg/pgp public keys of each maintainer.", TYPE_STRING, offsetof(config, key_path)},
- {NULL, NULL, TYPE_NONE, -1},
+int check_port(void *ctx, void *ret, const keyword *key, keyword_val val);
+
+#define offset_list(...) (size_t []){__VA_ARGS__, -1}
+static const keyword *config_keywords[] = {
+ &(const keyword){"git-root", "Root of git server (can also be a url).", NULL, TYPE_STRING, offset_list(offsetof(config, git_root)), NULL},
+ &(const keyword){"socket-type", "Socket type to use (options: unix, network. default: network).", NULL, TYPE_STRING, offset_list(offsetof(config, sock_type)), NULL},
+ &(const keyword){"socket", "Path, IP address, or domain name of socket.", NULL, TYPE_STRING, offset_list(offsetof(config, sock)), NULL},
+ &(const keyword){"port", "Port to listen on (network socket only).", NULL, TYPE_STRING, offset_list(offsetof(config, port)), check_port},
+ &(const keyword){"merge-type", "Type of merge (options: 0 = Merge individually, 1 = Merge into one).", NULL, TYPE_INT, offset_list(offsetof(config, merge_type)), NULL},
+ &(const keyword){"pr-root", "Directory to store pull requests in.", NULL, TYPE_STRING, offset_list(offsetof(config, pr_root)), NULL},
+ &(const keyword){"key-file", "Path to file containing gpg/pgp public keys of each maintainer.", NULL, TYPE_STRING, offset_list(offsetof(config, key_path)), NULL},
+ NULL,
};
+#undef offset_list
extern config *parse_config(const char *filename);
extern void cleanup_config(config *conf);