forked from mirrors/treebird
Template engine
FossilOrigin-Name: 80100717c5483087c985254616f3c784e79536ac4c161c77915a355e0fa04fc8
This commit is contained in:
parent
0a580d0a32
commit
cdbbfed221
3 changed files with 190 additions and 23 deletions
2
Makefile
2
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 $<
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// 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)
|
||||
|
|
|
@ -29,15 +29,15 @@
|
|||
<tr>
|
||||
<td id="leftbar" class="sidebar">
|
||||
<ul>
|
||||
<li><a class="sidebarbtn { %s : active_home" href="{{ %s : prefix}}/">{{ %s : home }}</a></li>
|
||||
<li><a class="sidebarbtn { %s : active_local" href="{{ %s : prefix}}/local/">{{ %s : local}}</a></li>
|
||||
<li><a class="sidebarbtn { %s : active_federated" href="{{ %s : prefix}}/federated/">{{ %s : federated }}</a></li>
|
||||
<li><a class="sidebarbtn { %s : active_notifications" href="{{ %s : prefix}}/notifications">{{ %s : notifications }}</a></li>
|
||||
<li><a class="sidebarbtn { %s : active_lists" href="{{ %s : prefix}}/lists">{{ %s : lists }}</a></li>
|
||||
<li><a class="sidebarbtn { %s : active_favourites" href="{{ %s : prefix}}/favourites">{{ %s : favourites }}</a></li>
|
||||
<li><a class="sidebarbtn { %s : active_bookmarks" href="{{ %s : prefix}}/bookmarks">{{ %s : bookmarks }}</a></li>
|
||||
<li><a class="sidebarbtn { %s : active_direct" href="{{ %s : prefix}}/direct">{{ %s : direct }}</a></li>
|
||||
<li><a class="sidebarbtn { %s : active_config" href="{{ %s : prefix}}/config">{{ %s : config }}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_home }}" href="{{ %s : prefix}}/">{{ %s : home }}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_local }}" href="{{ %s : prefix}}/local/">{{ %s : local}}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_federated }}" href="{{ %s : prefix}}/federated/">{{ %s : federated }}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_notifications }}" href="{{ %s : prefix}}/notifications">{{ %s : notifications }}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_lists }}" href="{{ %s : prefix}}/lists">{{ %s : lists }}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_favourites }}" href="{{ %s : prefix}}/favourites">{{ %s : favourites }}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_bookmarks }}" href="{{ %s : prefix}}/bookmarks">{{ %s : bookmarks }}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_direct }}" href="{{ %s : prefix}}/direct">{{ %s : direct }}</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_config }}" href="{{ %s : prefix}}/config">{{ %s : config }}</a></li>
|
||||
</ul>
|
||||
{{ %s : sidebar_leftbar }}
|
||||
<div class="static-html" id="instance-panel">
|
||||
|
|
Loading…
Reference in a new issue