summaryrefslogtreecommitdiffstats
path: root/src/config-process.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/config-process.c')
-rw-r--r--src/config-process.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/config-process.c b/src/config-process.c
new file mode 100644
index 0000000..e71b228
--- /dev/null
+++ b/src/config-process.c
@@ -0,0 +1,135 @@
+#include "config-process.h"
+#include "device.h"
+#include "keywords.h"
+#include "util.h"
+
+#include <libubox/avl-cmp.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct _process_ctx {
+ struct avl_tree *ret;
+} process_ctx_t;
+
+typedef struct _config_subtype {
+ struct avl_node node;
+} config_subtype_t;
+
+void config_object_free(config_object_t *obj) {
+ free_ini_file(obj->data);
+ free(obj->type);
+ free(NODE_NAME(obj));
+ free(obj);
+}
+
+static bool subtype_supported(const process_ctx_t *ctx, const char *type) {
+ switch (lookup_keyword(type)) {
+ case KW_Properties:
+ case KW_Generate:
+ case KW_Static:
+ case KW_DHCP:
+ case KW_DHCPv6:
+ return true;
+
+ default:
+ return avl_find(ctx->ret, type);
+ }
+}
+
+static config_subtype_t * config_process_subtype(const process_ctx_t *ctx, config_object_t *obj) {
+ ini_section_t *section;
+ list_for_each_entry(section, &obj->data->sections, node) {
+ printf("%s %s %i\n", NODE_NAME(obj), section->name, subtype_supported(ctx, section->name));
+
+ if (!subtype_supported(ctx, section->name))
+ return NULL;
+ }
+
+ config_subtype_t *ret = calloc(1, sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ char *name = strdup(NODE_NAME(obj));
+ if (!name) {
+ free(ret);
+ return NULL;
+ }
+
+ NODE_NAME(ret) = name;
+
+ return ret;
+}
+
+struct avl_tree * config_process_subtypes(struct avl_tree *sub) {
+ process_ctx_t ctx;
+ ctx.ret = calloc(1, sizeof(*ctx.ret));
+ if (!ctx.ret)
+ return NULL;
+
+ avl_init(ctx.ret, avl_strcmp, false, NULL);
+
+ while (true) {
+ size_t processed = 0;
+
+ config_object_t *obj, *tmp;
+ avl_for_each_element_safe(sub, obj, node, tmp) {
+ config_subtype_t *t = config_process_subtype(&ctx, obj);
+ if (!t)
+ continue;
+
+ avl_delete(sub, &obj->node);
+ config_object_free(obj);
+
+ avl_insert(ctx.ret, &t->node);
+
+ processed++;
+ }
+
+ if (!processed)
+ break;
+ }
+
+ return ctx.ret;
+}
+
+static device_t * config_process_device(config_object_t *obj) {
+ const device_type_t *type = get_device_type(obj->type);
+
+ assert(type != NULL);
+
+ return type->process_config(NODE_NAME(obj), obj->data);
+}
+
+struct avl_tree * config_process_devices(struct avl_tree *devices) {
+ process_ctx_t ctx;
+ ctx.ret = calloc(1, sizeof(*ctx.ret));
+ if (!ctx.ret)
+ return NULL;
+
+ avl_init(ctx.ret, avl_strcmp, false, NULL);
+
+ while (true) {
+ size_t processed = 0;
+
+ config_object_t *obj, *tmp;
+ avl_for_each_element_safe(devices, obj, node, tmp) {
+ device_t *device = config_process_device(obj);
+ if (!device)
+ continue;
+
+ avl_delete(devices, &obj->node);
+ config_object_free(obj);
+
+ avl_insert(ctx.ret, &device->node);
+
+ processed++;
+ }
+
+ if (!processed)
+ break;
+ }
+
+ return ctx.ret;
+}