shithub: treepack

ref: 3f08446a85647ed6621388b23a4b6d9ee4db2050
dir: /treeload.c/

View raw version
#include <assert.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>

#include <ucl.h>

#define USAGE "usage: treeload directory file\n"

void
errexit(int code, char *fmt, ...)
{
	va_list ap;
	
	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
	exit(code);
}

typedef struct Walkstate Walkstate;
struct Walkstate {
	const ucl_object_t *obj;
	int index;
	const char *key;
	ucl_type_t type;
	char *path;
} walkstatezero = {
	.obj = NULL,
	.index = 0,
	.key = NULL,
	.type = UCL_NULL,
	.path = ""
};

void
mkdir(char *path)
{
	printf("mkdir -p %s\n", path);
}

void
mkfile(char *path, const char *data, size_t dlen)
{
	(void)dlen;
	printf("echo '%s' > %s\n", data, path);
}

void
leaf(const ucl_object_t *obj, Walkstate *parent)
{
	char *p;

	if(parent->type == UCL_ARRAY)
		asprintf(&p, "%s/%d", parent->path, parent->index);
	else
		asprintf(&p, "%s/%s", parent->path, ucl_object_key(obj));

	mkfile(p, ucl_object_tostring_forced(obj), -1);
	free(p);
}

void
inner(const ucl_object_t *obj, Walkstate *parent)
{
	Walkstate this = walkstatezero;
	const ucl_object_t *cur = NULL;
	ucl_object_iter_t it = NULL;

	this.key = ucl_object_key(obj);
	this.type = ucl_object_type(obj);
	if(this.key != NULL)
		asprintf(&this.path, "%s/%s", parent->path, this.key);
	else
		asprintf(&this.path, "%s", parent->path);
	if(parent->type == UCL_ARRAY){
		free(this.path);
		asprintf(&this.path, "%s/%d", parent->path, parent->index);
	}
	mkdir(this.path);

	it = ucl_object_iterate_new(obj);
	while((cur = ucl_object_iterate_safe(it, true)) != NULL){
		switch(ucl_object_type(cur)){
		case UCL_OBJECT:
		case UCL_ARRAY:
			inner(cur, &this); break;
		default:
			leaf(cur, &this); break;
		}
		this.index += 1;
	}
	ucl_object_iterate_free(it);
	free(this.path);
}

int
main(int argc, char *argv[])
{
	char *dn = NULL, *fn = NULL;
	struct ucl_parser *parser = NULL;
	ucl_object_t *obj = NULL;
	
	if(argc != 3) errexit(111, USAGE);
	dn = argv[1];
	fn = argv[2];

	if((parser = ucl_parser_new(0)) == NULL)
		errexit(100, "can't allocate a parser\n");
	if(ucl_parser_add_file(parser, fn) == false)
		errexit(100, "%s\n", ucl_parser_get_error(parser));
	if((obj = ucl_parser_get_object(parser)) == NULL)
		errexit(100, "%s\n", ucl_parser_get_error(parser));

	{
		Walkstate root = walkstatezero;

		root.path = dn;
		mkdir(root.path);
		inner(obj, &root);
	}
	exit(0);
}