Static template generator for C
git clone git://soophie.de/ductape
blob: b228c7417d6e781a41656217351594fb48c775ae (2792 bytes)[doc][blame][raw]
1
// Copyright (C) 2026 Sophie Sitzler2
//3
// This program is free software: you can redistribute it and/or modify4
// it under the terms of the GNU General Public License as published by5
// the Free Software Foundation, either version 3 of the License, or6
// (at your option) any later version.7
//8
// This program is distributed in the hope that it will be useful,9
// but WITHOUT ANY WARRANTY; without even the implied warranty of10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11
// GNU General Public License for more details.12
//13
// You should have received a copy of the GNU General Public License14
// along with this program. If not, see <https://www.gnu.org/licenses/>.16
// @file ctl.h18
#ifndef _SO_CTL_H19
#define _SO_CTL_H21
#include <stdio.h>22
#include <stdlib.h>24
// @type ctl_render_fn_t25
typedef int (*ctl_render_fn_t)(void *, void *, const char *);27
// @struct ctl_templref_t28
typedef struct {29
ctl_render_fn_t fn;30
void *data;31
const char *dl_path;32
} ctl_templref_t;34
// @macro __TEMPLDEF_MACRO35
// @internal36
#define __TEMPLDEF_MACRO($name, $params) \37
typedef struct { \38
$params \39
} $name##_t; \40
\41
typedef void (*$name##_fn_t)(void *, $name##_t *); \42
\43
int $name##_render(void *out, void *ctx) { \44
char *path = getenv("CTL_BUILDPATH"); \45
if (path == NULL) { \46
path = "./"; \47
} \48
char dl_path[strlen(path) + strlen(__CTL_UID_##$name) + 4]; \49
snprintf(dl_path, sizeof(dl_path), "%s%s.so", path, __CTL_UID_##$name); \50
void *handle = dlopen(dl_path, RTLD_NOW); \51
if (!handle) { \52
fprintf(stderr, "%s\n", dlerror()); \53
return 1; \54
} \55
const size_t *hash = (size_t *) dlsym(handle, "__CTL_SIG_HASH_" #$name); \56
if (__CTL_SIG_HASH_##$name != *hash) { \57
fprintf(stderr, "Invalid signature hash! (%llx != %llx)\n", __CTL_SIG_HASH_##$name, *hash); \58
return 1; \59
} \60
$name##_fn_t fn = ($name##_fn_t) dlsym(handle, "ctl_" #$name); \61
char *err = dlerror(); \62
if (err) { \63
fprintf(stderr, "%s\n", err); \64
dlclose(handle); \65
return 1; \66
} \67
fn(out, ($name##_t *) ctx); \68
dlclose(handle); \69
return 0; \70
}72
// @macro __TEMPLDEF_HEADER73
// @internal74
#define __TEMPLDEF_HEADER($name, $params) \75
__TEMPLDEF_MACRO($name, $params) \76
\77
void ctl_##$name(void *out, $name##_t *ctx);79
// @macro TEMPLDEF80
#define TEMPLDEF($name, $params) \81
__TEMPLDEF_MACRO($name, $params) \82
\83
void ctl_##$name(void *out, $name##_t *ctx) {85
// @macro ENDTEMPL86
#define ENDTEMPL }88
// @macro TEMPLBIND89
#define TEMPLBIND($name, $data, $dl_path) \90
(ctl_templref_t) { \91
.fn = $name##_render, \92
.data = $data, \93
.dl_path = $dl_path, \94
},96
// @macro INCLUDE97
#define INCLUDE($name) ctx->$name.fn(ctl, ctx->$name.data, ctx->$name.dl_path);99
#endif // _SO_CTL_H