135 lines
2.6 KiB
C
135 lines
2.6 KiB
C
#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;
|
|
}
|