confgen

Config parser generator
git clone git://git.finwo.net/app/confgen
Log | Files | Refs | LICENSE

commit 3ad2986ed2a48ccb1443c60ac59d047c898f7943
parent ad04ace5ca3a8f90ef82a460341865c22a4d2f1b
Author: finwo <finwo@pm.me>
Date:   Wed, 15 Jul 2026 02:27:56 +0200

Templated buffer implementation

Diffstat:
M.dep | 2++
M.gitignore | 3+++
MMakefile | 16++++++++++++++--
C.dep -> src/util/.gitkeep | 0
Dsrc/util/buffer.c | 61-------------------------------------------------------------
Dsrc/util/buffer.h | 32--------------------------------
Atemplate/util/buffer.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplate/util/buffer.h | 32++++++++++++++++++++++++++++++++
Atemplate/util/buffer.json | 4++++
Mtest/0000/confgen.hcl | 9+++++++++
Atest/0001/confgen.hcl | 16++++++++++++++++
Atest/0002/confgen.hcl | 31+++++++++++++++++++++++++++++++
Atest/0002/keepalived.hcl | 15+++++++++++++++
13 files changed, 186 insertions(+), 95 deletions(-)

diff --git a/.dep b/.dep @@ -0,0 +1,2 @@ +cozis/tinytemplate https://git.finwo.net/misc/dep-repository/archives/heads/pkg/cozis/tinytemplate.tar.gz +graphitemaster/incbin https://git.finwo.net/misc/dep-repository/archives/heads/pkg/graphitemaster/incbin.tar.gz diff --git a/.gitignore b/.gitignore @@ -1,3 +1,6 @@ /confgen *.o /lib/ + +/src/util/buffer.c +/src/util/buffer.h diff --git a/Makefile b/Makefile @@ -2,14 +2,17 @@ # LIBS= SRC:= SRC+=$(wildcard src/*.c) -SRC+=$(wildcard src/*/*.c) +SRC+=$(filter-out src/util/buffer.c, $(wildcard src/*/*.c)) + +# Generated +SRC+=src/util/buffer.c CFLAGS?=-Wall -s -O2 INCLUDES:= INCLUDES+=-I src -# include lib/.dep/config.mk +include lib/.dep/config.mk CFLAGS+=$(INCLUDES) @@ -22,6 +25,15 @@ BIN=confgen default: $(BIN) # default: $(BIN) $(BIN).1 +lib/cozis/tinytemplate/tt: + $(MAKE) --directory lib/cozis/tinytemplate + +src/util/buffer.h: template/util/buffer.h lib/cozis/tinytemplate/tt template/util/buffer.json + cat $< | lib/cozis/tinytemplate/tt template/util/buffer.json > $@ + +src/util/buffer.c: template/util/buffer.c lib/cozis/tinytemplate/tt src/util/buffer.h template/util/buffer.json + cat $< | lib/cozis/tinytemplate/tt template/util/buffer.json > $@ + %.o: %.c $(LIBS) $(CC) $(CFLAGS) $(@:.o=.c) -D__NAME=\"$(BIN)\" -c -o $@ diff --git a/.dep b/src/util/.gitkeep diff --git a/src/util/buffer.c b/src/util/buffer.c @@ -1,61 +0,0 @@ -#include <string.h> -#include <stdlib.h> - -#include "buffer.h" - -#ifndef MAX -#define MAX(a,b) ((a)>(b)?(a):(b)) -#endif - -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif - - -void confgen_buffer_append(struct confgen_buffer *subject, const char *source, size_t length) { - if (!subject) return; - - // Initial alloc if blank buffer - if (!subject->alloc) { - size_t l = MAX(32, length); - subject->alloc = malloc(l); - subject->dat = subject->alloc; - subject->cap = l; - subject->len = 0; - goto confgen_buffer_append_copy; // Simply skips cap checks - } - - // Eject consumed data if we need space - if ( - (subject->dat != subject->alloc) && - ((subject->len + length) > subject->cap) - ) { - size_t diff = subject->dat - subject->alloc; - memmove(subject->alloc, subject->dat, subject->len); - subject->cap += diff; - subject->dat = subject->alloc; - } - - // Grow buffer if still not enough space - if ((subject->len + length) > subject->cap) { - subject->cap = MAX(32, subject->cap * 2); - subject->alloc = realloc(subject->alloc, subject->cap); - subject->dat = subject->alloc; - } - - // Add the data to the end -confgen_buffer_append_copy: - memcpy(subject->dat + subject->len, source, length); - subject->len += length; -} - -size_t confgen_buffer_consume(struct confgen_buffer *subject, size_t length) { - if (!subject) return 0; - - size_t n = MIN(length, subject->len); - subject->dat += n; - subject->len -= n; - subject->cap -= n; - - return n; -} diff --git a/src/util/buffer.h b/src/util/buffer.h @@ -1,32 +0,0 @@ -#ifndef __CONFGEN_UTIL_BUFFER_H__ -#define __CONFGEN_UTIL_BUFFER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stddef.h> - -struct confgen_buffer { - char *alloc; - char *dat; - size_t len; - size_t cap; -}; - -/** - * Append <length> bytes to the data in the buffer - * Copies the data, does not mutate the source - */ -void confgen_buffer_append(struct confgen_buffer *subject, const char *source, size_t length); - -/** - * Remove <length> bytes from the front of the buffer - */ -size_t confgen_buffer_consume(struct confgen_buffer *subject, size_t length); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // __CONFGEN_UTIL_BUFFER_H__ diff --git a/template/util/buffer.c b/template/util/buffer.c @@ -0,0 +1,60 @@ +#include <string.h> +#include <stdlib.h> + +#include "buffer.h" + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +void {{buffer_prefix}}_append(struct {{buffer_prefix}} *subject, const char *source, size_t length) { + if (!subject) return; + + // Initial alloc if blank buffer + if (!subject->alloc) { + size_t l = MAX(32, length); + subject->alloc = malloc(l); + subject->dat = subject->alloc; + subject->cap = l; + subject->len = 0; + goto lbl_{{buffer_prefix}}_append_copy; // Simply skips cap checks + } + + // Eject consumed data if we need space + if ( + (subject->dat != subject->alloc) && + ((subject->len + length) > subject->cap) + ) { + size_t diff = subject->dat - subject->alloc; + memmove(subject->alloc, subject->dat, subject->len); + subject->cap += diff; + subject->dat = subject->alloc; + } + + // Grow buffer if still not enough space + if ((subject->len + length) > subject->cap) { + subject->cap = MAX(32, subject->cap * 2); + subject->alloc = realloc(subject->alloc, subject->cap); + subject->dat = subject->alloc; + } + + // Add the data to the end +lbl_{{buffer_prefix}}_append_copy: + memcpy(subject->dat + subject->len, source, length); + subject->len += length; +} + +size_t {{buffer_prefix}}_consume(struct {{buffer_prefix}} *subject, size_t length) { + if (!subject) return 0; + + size_t n = MIN(length, subject->len); + subject->dat += n; + subject->len -= n; + subject->cap -= n; + + return n; +} diff --git a/template/util/buffer.h b/template/util/buffer.h @@ -0,0 +1,32 @@ +#ifndef __Loh3Ain3_{{BUFFER_PREFIX}}_H__ +#define __Loh3Ain3_{{BUFFER_PREFIX}}_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h> + +struct {{buffer_prefix}} { + char *alloc; + char *dat; + size_t len; + size_t cap; +}; + +/** + * Append <length> bytes to the data in the buffer + * Copies the data, does not mutate the source + */ +void {{buffer_prefix}}_append(struct {{buffer_prefix}} *subject, const char *source, size_t length); + +/** + * Remove <length> bytes from the front of the buffer + */ +size_t {{buffer_prefix}}_consume(struct {{buffer_prefix}} *subject, size_t length); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __Loh3Ain3_{{BUFFER_PREFIX}}_H__ diff --git a/template/util/buffer.json b/template/util/buffer.json @@ -0,0 +1,4 @@ +{ + "buffer_prefix": "confgen_buffer", + "BUFFER_PREFIX": "CONFGEN_BUFFER" +} diff --git a/test/0000/confgen.hcl b/test/0000/confgen.hcl @@ -1,5 +1,14 @@ name = "confgen_config" +buffer_prefix = "blablabla" # <-- default to .name +buffer_shared = false # <-- includes buffer implementation in single .h file + + +buffer_shared = true +buffer_shared_header = "util/buffer.h" # <-- Makes program output shared header here +buffer_shared_code = "util/buffer.c" # <-- Makes program output shared buffer impl here +buffer_prefix = "confgen_buffer_" + argument "name" { type = "string" } diff --git a/test/0001/confgen.hcl b/test/0001/confgen.hcl @@ -0,0 +1,16 @@ +name = "pmlag_conf" + +# This would generate the following C .h file, and accompanying .c file +# +# struct pmlag_conf_state { +# struct confgen_buffer *input; +# }; +# +# struct pmlag_conf { +# char *name; +# }; +# +# +# struct pmlag_conf_state * pmlag_conf_start(); # <-- alloc buffer, etc +# void pmlag_conf_update(struct pmlag_conf_state *state, const char *src, size_t len); +# struct pmlag_conf * pmlag_conf_digest(struct pmlag_conf_state *state); diff --git a/test/0002/confgen.hcl b/test/0002/confgen.hcl @@ -0,0 +1,31 @@ +output_headers = "keepalived/src/config/config.h" +output_parser = "keepalived/src/config/config.c" + +argument "daemonize" { + type = "boolean" +} + +block "vrrp_instance" { + label = "name" + repeatable = true + + argument "router_id" { + type = "integer" + } + + block "auth" { + repeatable = false + + argument "type" { + type = "string" + default = "PASS" + enum = [ + "PASS" + "SOMETHING" + ] + } + + } + + +} diff --git a/test/0002/keepalived.hcl b/test/0002/keepalived.hcl @@ -0,0 +1,15 @@ +daemonize = false + +vrrp_instance "VRRP_1" { + router_id = 123 + + address "192.168.1.2/24" { + ... + } + + auth { + type = "PASS" + password = "supers3cret" + } + +}