From 9a1bdb941373a9c56829514a9abbaf0ba12be38e Mon Sep 17 00:00:00 2001
From: overflowerror <mail@overflowerror.com>
Date: Sun, 23 May 2021 16:03:39 +0200
Subject: [PATCH] changed interface for rendering; abstract template_t behind
 render function

---
 demofiles/demo.c |  2 +-
 src/main.c       | 17 +++++++----------
 src/templates.c  | 24 ++++++++++++++++++------
 src/templates.h  |  4 +---
 4 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/demofiles/demo.c b/demofiles/demo.c
index 5ba8cb9..f63ef2a 100644
--- a/demofiles/demo.c
+++ b/demofiles/demo.c
@@ -9,7 +9,7 @@ int main() {
 		"foobar"
 	};	
 
-	findTemplate("demo.html.templ")(stdout, "User-List", names, 3);
+	renderTemplate("demo.html.templ", stdout, "User-List", names, 3);
 	
 	return 0;
 }
diff --git a/src/main.c b/src/main.c
index fcab321..6a48231 100644
--- a/src/main.c
+++ b/src/main.c
@@ -28,7 +28,7 @@ void generateHeader() {
 	fprintf(output, "\n");
 	fprintf(output, "#include <templates.h>\n");
 	fprintf(output, "\n");
-	fprintf(output, "extern void _registerTemplate(const char*, template_t);\n");
+	fprintf(output, "extern void _registerTemplate(const char*, void (*)(FILE*, va_list), size_t (*)(va_list));\n");
 	fprintf(output, "\n");
 	for (size_t i = 0; i < result.stats.no; i++) {
 		fprintf(output, "%s\n", result.stats.texts[i]);
@@ -84,17 +84,14 @@ void indent(int indentation) {
 	}
 }
 
-void generateArguments(const char* firstArgument) {
+void generateArguments() {
 	for (size_t i = 0; i < result.params.no; i++) {
 		fprintf(output, "\t%s %s;\n", result.params.types[i], result.params.names[i]);
 	}
 	fprintf(output, "\t{\n");
-	fprintf(output, "\t\tva_list argptr;\n");
-	fprintf(output, "\t\tva_start(argptr, %s);\n", firstArgument);
 	for (size_t i = 0; i < result.params.no; i++) {
 		fprintf(output, "\t\t%s = va_arg(argptr, %s);\n", result.params.names[i], result.params.types[i]);
 	}
-	fprintf(output, "\t\tva_end(argptr);\n");
 	fprintf(output, "\t}\n");
 }
 
@@ -139,9 +136,9 @@ void parseTreeSize(int indentation, struct tree tree) {
 }
 
 void generateSize() {
-	fprintf(output, "static size_t %s_%s_(int _, ...) {\n", SIZE_PREFIX, name);
+	fprintf(output, "static size_t %s_%s_(va_list argptr) {\n", SIZE_PREFIX, name);
 	fprintf(output, "\tsize_t %s = 0;\n", SIZE_ACCUMULATOR_VAR);
-	generateArguments("_");
+	generateArguments();
 	
 	parseTreeSize(1, result.tree);
 	
@@ -192,8 +189,8 @@ void parseTree(int indentation, struct tree tree) {
 }
 
 void generateTree() {
-	fprintf(output, "static void %s_%s_(FILE* out, ...) {\n", PRINT_PREFIX, name);
-	generateArguments("out");
+	fprintf(output, "static void %s_%s_(FILE* out, va_list argptr) {\n", PRINT_PREFIX, name);
+	generateArguments();
 	
 	parseTree(1, result.tree);
 	
@@ -202,7 +199,7 @@ void generateTree() {
 
 void generateConstructor() {
 	fprintf(output, "__attribute__((constructor)) static void _register() {\n");
-	fprintf(output, "\t_registerTemplate(\"%s\", &%s_%s_);\n", filename, PRINT_PREFIX, name);
+	fprintf(output, "\t_registerTemplate(\"%s\", &%s_%s_, &%s_%s_);\n", filename, PRINT_PREFIX, name, SIZE_PREFIX, name);
 	fprintf(output, "}\n");
 }
 
diff --git a/src/templates.c b/src/templates.c
index 164ef50..d9708ca 100644
--- a/src/templates.c
+++ b/src/templates.c
@@ -1,14 +1,20 @@
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
 
 #include "templates.h"
 #include "common.h"
 
 #define MAX_TEMPLATES (128)
 
+typedef void (*template_t)(FILE*, va_list);
+typedef size_t (*template_length_t)(va_list);
+
 struct {
 	const char* name;
 	template_t f;
+	template_length_t s;
 } templates[MAX_TEMPLATES];
 size_t templateno = 0;
 
@@ -22,7 +28,7 @@ static template_t _findTemplate(const char* name) {
 	return NULL;
 }
 
-void _registerTemplate(const char* name, template_t f) {
+void _registerTemplate(const char* name, template_t f, template_length_t s) {
 	if (templateno >= MAX_TEMPLATES) {
 		panic("max number of templates exceeded");
 	}
@@ -33,20 +39,26 @@ void _registerTemplate(const char* name, template_t f) {
 	}
 	
 	templates[templateno].name = name;
-	templates[templateno++].f = f;
+	templates[templateno].f = f;
+	templates[templateno++].s = s;
 }
 
-static void emptyTemplate(FILE* out, ...) {
+static void emptyTemplate(FILE* out, va_list _) {
 	fprintf(out, "Template not found.\n");
 }
 
-template_t findTemplate(const char* name) {
+void renderTemplate(const char* name, FILE* out, ...) {
 	template_t t = _findTemplate(name);
 	
 	if (t == NULL) {
 		fprintf(stderr, "warning: template '%s' does not exist.\n", name);
-		return &emptyTemplate;
+		t = &emptyTemplate;
 	}
 	
-	return t;
+	va_list argptr;
+	va_start(argptr, out);
+	
+	t(out, argptr);
+	
+	va_end(argptr);
 }
diff --git a/src/templates.h b/src/templates.h
index f472c63..feb3d90 100644
--- a/src/templates.h
+++ b/src/templates.h
@@ -3,8 +3,6 @@
 
 #include <stdio.h>
 
-typedef void (*template_t)(FILE*, ...);
-
-template_t findTemplate(const char*);
+void renderTemplate(const char*, FILE*, ...);
 
 #endif