From cdbbfed221c5b651fcc08bc254b5a646e7153fa3 Mon Sep 17 00:00:00 2001 From: nekobit Date: Fri, 27 May 2022 03:37:47 +0000 Subject: [PATCH] Template engine FossilOrigin-Name: 80100717c5483087c985254616f3c784e79536ac4c161c77915a355e0fa04fc8 --- Makefile | 2 +- src/template/main.c | 193 +++++++++++++++++++++++++++++++++++++++++--- static/index.tmpl | 18 ++--- 3 files changed, 190 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 88d9f71..60dcb6f 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ $(TARGET): filec template $(PAGES_CMP) $(OBJ) $(HEADERS) $(CC) -o $(TARGET) $(OBJ) $(LDFLAGS) template: src/template/main.o - $(CC) -o template $< + $(CC) $(LDFLATS) -o template $< filec: src/file-to-c/main.o $(CC) -o filec $< diff --git a/src/template/main.c b/src/template/main.c index 6e317c0..f5575c9 100644 --- a/src/template/main.c +++ b/src/template/main.c @@ -20,6 +20,9 @@ #include #include #include +#include + +// TODO error handling enum args { @@ -33,7 +36,14 @@ enum tmpl_type TMPL_UINT, TMPL_STR, TMPL_STRLEN -} +}; + +struct tmpl_token +{ + enum tmpl_type type; + char* token; + int used; // Internal use only +}; long filesize(FILE* file) { @@ -44,27 +54,184 @@ long filesize(FILE* file) return size; } +void chexput(const char* buf, size_t size) +{ + for (size_t i = 0; i < size; ++i) + { + printf("0X%hhX,", buf[i]); + } +} + +char* strnws(char* str) +{ + for (; isblank(*str); ++str); + return str; +} + +char* strwsc(char* str, char stop) +{ + for (; !isblank(*str) && *str != stop; ++str); + return str; +} + +char* tkn_typetostr(enum tmpl_type tkn) +{ + switch (tkn) + { + case TMPL_INT: + return "int"; + case TMPL_STR: + case TMPL_STRLEN: + return "char*"; + case TMPL_UINT: + return "unsigned"; + } + return ""; +} + +enum tmpl_type tkn_type(char* str) +{ + if (strcmp(str, "string") == 0 || + strcmp(str, "str") == 0 || + strcmp(str, "%s") == 0) + return TMPL_STR; + else if (strcmp(str, "stringlen") == 0 || + strcmp(str, "strlen") == 0 || + strcmp(str, "%.s") == 0) + return TMPL_STRLEN; + else if (strcmp(str, "int") == 0 || + strcmp(str, "i") == 0 || + strcmp(str, "%d") == 0) + return TMPL_INT; + else if (strcmp(str, "unsigned") == 0 || + strcmp(str, "uint") == 0 || + strcmp(str, "%u") == 0) + return TMPL_UINT; + + // TODO Real error handling + return TMPL_INT; +} + +char* parse_tmpl_token(char* buf, struct tmpl_token* tkn) +{ + tkn->used = 0; + char* type_begin; + char* type_end; + char* tkn_begin; + char* tkn_end; + // skip {{ + buf += 2; + type_begin = strnws(buf); + type_end = strwsc(type_begin, ':'); + + if (*type_end != ':') buf = strchr(buf, ':'); + else buf = type_end; + + *type_end = '\0'; + tkn->type = tkn_type(type_begin); + + ++buf; + tkn_begin = strnws(buf); + tkn_end = strwsc(tkn_begin, '}'); + + if (*tkn_end == '}') buf = tkn_end + 2; + else buf = strstr(buf, "}}") + 2; + + *tkn_end = '\0'; + tkn->token = tkn_begin; + return buf; +} + void print_template(char* var, char* buf) { char* buf_prev = buf; char* buf_curr = buf; - char** tokens; + // Store result + struct tmpl_token* tokens = NULL; + size_t tokens_len = 0; + + printf("#ifndef __%s\n" + "#define __%s\n" + "static const char data_%s[] = {", var, var, var); - printf("#ifndef __%s\n", var); - printf("#define __%s\n", var); - - printf("static const char data_%s[] = {", var); while (1) { buf_curr = strstr(buf_curr, "{{"); + if (!buf_curr) break; + // Create tokens array + tokens = realloc(tokens, sizeof(struct tmpl_token) * ++tokens_len); + if (!tokens) + { + perror("realloc"); + break; + } + // Print up to this point + chexput(buf_prev, buf_curr - buf_prev); + buf_prev = buf_curr = parse_tmpl_token(buf_curr, tokens + (tokens_len-1)); + + // Print type + switch (tokens[tokens_len-1].type) + { + case TMPL_INT: + // I'm lazy so we'll use this + chexput("%d", 2); + break; + case TMPL_STR: + chexput("%s", 2); + break; + case TMPL_STRLEN: + chexput("%.s", 3); + break; + case TMPL_UINT: + chexput("%u", 2); + break; + } } - /* for (size_t i = 0; i < size; ++i) */ - /* { */ - /* printf("0X%hhX,", buf[i]); */ - /* } */ - /* puts("0};\n#endif"); */ - - puts("#endif"); + + // Print remainder if any + chexput(buf_prev, strlen(buf_prev)); + printf("};\n" + "struct %s {", var); + + int should_print = 0; + // Print tokens + for (size_t i = 0; i < tokens_len; ++i) + { + should_print = 1; + // Check if used + for (size_t j = 0; j < tokens_len; ++j) + { + if (i != j && + strcmp(tokens[i].token, tokens[j].token) == 0 && + tokens[j].used) + should_print = 0; + } + if (should_print) + { + printf("%s %s;\n", tkn_typetostr(tokens[i].type), tokens[i].token); + if (tokens[i].type == TMPL_STRLEN) + printf("unsigned %s_len;\n", tokens[i].token); + tokens[i].used = 1; + } + } + + // Generate function + printf("};\n" + "char* tmpl_gen_%s(struct %s* data, unsigned* size){\n" + "char* ret;\n" + "unsigned s = easprintf(&ret, data_%s, ", var, var, var); + for (size_t i = 0; i < tokens_len; ++i) + { + printf("data->%s%s", tokens[i].token, i < tokens_len-1 ? ", " : ""); + } + fputs(");\n" + "if (size) *size = s;\n" + "return ret;\n}", stdout); + + // Done! + puts("\n#endif"); + // Cleanup + free(tokens); } int main(int argc, char** argv) diff --git a/static/index.tmpl b/static/index.tmpl index 7bba9ec..1a0a4c9 100644 --- a/static/index.tmpl +++ b/static/index.tmpl @@ -29,15 +29,15 @@ {{ %s : sidebar_leftbar }}