so://phie

ductape

Static template generator for C
git clone git://soophie.de/ductape

blob: eadef81687f11cbb5f50b934a00168606dddd6db (3259 bytes)[doc][blame][raw]

1// Copyright (C) 2026 Sophie Sitzler

2//

3// This program is free software: you can redistribute it and/or modify

4// it under the terms of the GNU General Public License as published by

5// the Free Software Foundation, either version 3 of the License, or

6// (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 of

10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

11// GNU General Public License for more details.

12//

13// You should have received a copy of the GNU General Public License

14// along with this program. If not, see <https://www.gnu.org/licenses/>.

15

16// @file ductape.h

17// @desc Static template generator for C

18

19#pragma once

20

21#include <stdio.h>

22

23// @macro __DUC_TEMPLDEF_TYPE

24// @internal

25// @desc Creates the type definitions for the template.

26// @param name - The template name.

27// @param param_list - The exposed template parameters.

28#define __DUC_TEMPLDEF_TYPE(name, param_list) \

29 typedef struct { \

30 const char *__duc_unused; \

31 param_list \

32 } name##_t; \

33 \

34 typedef void (*name##_fn_t)(void *, name##_t *);

35

36// @macro __DUC_TEMPLDEF_RENDER

37// @internal

38// @desc Creates the render implementation for the template.

39// @param name - The template name.

40#define __DUC_TEMPLDEF_RENDER(name) \

41 int name##_render(void *out, void *ctx) { \

42 char *path = getenv("DUC_BUILDPATH"); \

43 if (path == NULL) { \

44 path = "./"; \

45 } \

46 char dl_path[strlen(path) + strlen(__DUC_UID_##name) + 4]; \

47 snprintf(dl_path, sizeof(dl_path), "%s%s.so", path, __DUC_UID_##name); \

48 void *handle = dlopen(dl_path, RTLD_NOW); \

49 if (!handle) { \

50 fprintf(stderr, "%s\n", dlerror()); \

51 return 1; \

52 } \

53 const size_t *hash = (size_t *) dlsym(handle, "__DUC_SIG_HASH_" #name); \

54 if (!hash) { \

55 fprintf(stderr, "Missing signature hash!\n"); \

56 dlclose(handle); \

57 return 1; \

58 } \

59 if (__DUC_SIG_HASH_##name != *hash) { \

60 fprintf(stderr, "Invalid signature hash! (%lx != %lx)\n", __DUC_SIG_HASH_##name, *hash); \

61 dlclose(handle); \

62 return 1; \

63 } \

64 void *sym = dlsym(handle, "duc_" #name); \

65 char *err = dlerror(); \

66 if (err) { \

67 fprintf(stderr, "%s\n", err); \

68 dlclose(handle); \

69 return 1; \

70 } \

71 name##_fn_t fn = NULL; \

72 memcpy(&fn, &sym, sizeof(fn)); \

73 fn(out, (name##_t *) ctx); \

74 dlclose(handle); \

75 return 0; \

76 }

77

78// @macro __DUC_TEMPLDEF_HEADER

79// @internal

80// @desc Creates the header definition for the template. Used in generated .h file.

81// @param name - The template name.

82// @param param_list - The exposed template parameters.

83#define __DUC_TEMPLDEF_HEADER(name, param_list) \

84 __DUC_TEMPLDEF_TYPE(name, param_list) \

85 __DUC_TEMPLDEF_RENDER(name)

86

87// @macro DUC_TEMPLDEF

88// @desc Marks the beginning of a template definition. Used in generated .so file.

89// @param name - The template name.

90// @param param_list - The exposed template parameters.

91#define DUC_TEMPLDEF(name, param_list) \

92 __DUC_TEMPLDEF_TYPE(name, param_list) \

93 \

94 void duc_##name(void *out, name##_t *ctx) {

95

96// @macro DUC_ENDTEMPL

97// @desc Marks the end of a template definition.

98#define DUC_ENDTEMPL }