parent handling done

This commit is contained in:
overflowerror 2021-06-08 19:17:18 +02:00
parent fdc425e0b3
commit 5623bdce6b
5 changed files with 142 additions and 50 deletions

View file

@ -2,12 +2,14 @@
#include <string.h>
#include <stdlib.h>
#include <alloca.h>
#include <stdbool.h>
#include "tree.h"
#include "common.h"
#define PRINT_PREFIX ("print_template")
#define SIZE_PREFIX ("size_template")
#define END_SUFFIX ("end")
#define SIZE_ACCUMULATOR_VAR ("_total_size_")
@ -21,14 +23,19 @@ FILE* output;
char* name;
const char* filename;
bool isAbstract = false;
void generateHeader() {
fprintf(output, "#include <stdio.h>\n");
fprintf(output, "#include <stdlib.h>\n");
fprintf(output, "#include <stdarg.h>\n");
fprintf(output, "#include <stdbool.h>\n");
fprintf(output, "\n");
fprintf(output, "#include <templates.h>\n");
fprintf(output, "\n");
fprintf(output, "extern void _registerTemplate(const char*, void (*)(FILE*, va_list), size_t (*)(va_list));\n");
fprintf(output, "extern void _registerTemplate(const char*, bool, void (*)(FILE*, va_list), void (*)(FILE*, va_list), size_t (*)(va_list));\n");
fprintf(output, "extern void renderTemplateStart(const char*, FILE*, ...);\n")
fprintf(output, "extern void renderTemplateEnd(const char*, FILE*, ...);\n")
fprintf(output, "\n");
fprintf(output, "#define _renderTemplate(f, t, ...) renderTemplate(t, f, __VA_ARGS__)\n");
fprintf(output, "\n");
@ -139,6 +146,9 @@ void parseTreeSize(int indentation, struct tree tree) {
case RENDER_NODE:
generateRenderNodeSize(indentation, tree.kids[i]);
break;
case CHILD_NODE:
// ignore CHILD_NODE for size calculation
break;
default:
panic("unknown node type");
}
@ -185,6 +195,13 @@ void generateRenderNode(int indentation, struct node node) {
fprintf(output, "_renderTemplate(out, %s);\n", node.value.text);
}
void generateChildNode() {
// assuming we are at root level in tree
fprintf(output, "}\n");
fprintf(output, "static void %s_%s_%s_(FILE* out, va_list argptr) {\n", PRINT_PREFIX, name, END_SUFFIX);
generateArguments();
}
void parseTree(int indentation, struct tree tree) {
for (size_t i = 0; i < tree.kidsno; i++) {
switch(tree.kids[i].type) {
@ -200,6 +217,9 @@ void parseTree(int indentation, struct tree tree) {
case RENDER_NODE:
generateRenderNode(indentation, tree.kids[i]);
break;
case CHILD_NODE:
generateChildNode();
break;
default:
panic("unknown node type");
}
@ -217,7 +237,11 @@ void generateTree() {
void generateConstructor() {
fprintf(output, "__attribute__((constructor)) static void _register() {\n");
fprintf(output, "\t_registerTemplate(\"%s\", &%s_%s_, &%s_%s_);\n", filename, PRINT_PREFIX, name, SIZE_PREFIX, name);
if (isAbstract) {
fprintf(output, "\t_registerTemplate(\"%s\", true, &%s_%s_, &%s_%s_%s_, &%s_%s_);\n", filename, PRINT_PREFIX, name, PRINT_PREFIX, name, END_SUFFIX, SIZE_PREFIX, name);
} else {
fprintf(output, "\t_registerTemplate(\"%s\", false, &%s_%s_, NULL, &%s_%s_);\n", filename, PRINT_PREFIX, name, SIZE_PREFIX, name);
}
fprintf(output, "}\n");
}
@ -234,6 +258,28 @@ void fixName() {
}
}
void preprocessTree(int depth, struct tree tree);
void preprocessNode(int depth, struct node node) {
if (node.type == CHILD_NODE) {
if (depth > 0) {
panic("child command not allowed in statement block");
}
if (isAbstract) {
panic("only one child command allowed per template");
}
isAbstract = true;
} else if (node.type == STATEMENT_NODE) {
preprocessTree(depth + 1, *node.value.tree);
}
}
void preprocessTree(int depth, struct tree tree) {
for (size_t i = 0; i < tree.kidsno; i++) {
preprocessNode(depth, tree.kids[i]);
}
}
int main(int argc, char** argv) {
// TODO: build sane argument parsing
if (argc != 2) {
@ -257,6 +303,8 @@ int main(int argc, char** argv) {
return 1;
}
preprocessTree(0, result.tree);
generateHeader();
generateSize();
generateTree();

View file

@ -96,7 +96,11 @@ metaSection: /* empty */
yyerror("child command not allowed in meta section; ignoring");
break;
case EXTENDS_TOKEN:
yyerror("extends command not yet implemented; ignoring");
if ($$.parent != NULL) {
yyerror("template can only extent one parent");
YYERROR;
}
$$.parent = $6;
break;
default:
yyerror("unhandled structure block command (internal error)");
@ -165,7 +169,7 @@ mainSection: /* empty */
addNode(&$$, newRenderNode($7));
break;
case CHILD_NODE:
yyerror("child command not yet implemented; ignoring");
addNode(&$$, newChildNode());
break;
case EXTENDS_TOKEN:
yyerror("extends command not allowed in main section; ignoring");

View file

@ -2,6 +2,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include "templates.h"
#include "common.h"
@ -13,43 +14,39 @@ typedef size_t (*template_length_t)(va_list);
struct entry {
const char* name;
template_t f;
bool abstract;
template_t start;
template_t end;
template_length_t s;
} templates[MAX_TEMPLATES];
size_t templateno = 0;
static template_t _findTemplate(const char* name) {
static struct entry _findTemplate(const char* name) {
for (size_t i = 0; i < templateno; i++) {
if (strcmp(templates[i].name, name) == 0) {
return templates[i].f;
return templates[i];
}
}
return NULL;
return (struct entry) {
.name = NULL
};
}
static template_length_t _findTemplateSize(const char* name) {
for (size_t i = 0; i < templateno; i++) {
if (strcmp(templates[i].name, name) == 0) {
return templates[i].s;
}
}
return NULL;
}
void _registerTemplate(const char* name, template_t f, template_length_t s) {
void _registerTemplate(const char* name, bool abstract, template_t start, template_t end, template_length_t s) {
if (templateno >= MAX_TEMPLATES) {
panic("max number of templates exceeded");
}
if (_findTemplate(name) != NULL) {
if (_findTemplate(name).name != NULL) {
fprintf(stderr, "warning: template name '%s' already registered; ignoring this one\n", name);
return;
}
templates[templateno].abstract = abstract;
templates[templateno].name = name;
templates[templateno].f = f;
templates[templateno].start = start;
templates[templateno].end = end;
templates[templateno++].s = s;
}
@ -57,14 +54,49 @@ void _registerTemplate(const char* name, template_t f, template_length_t s) {
static size_t emptyTemplateSize(va_list _) { return 0; }
static void emptyTemplate(FILE* out, va_list _) { }
void _renderTemplate(const char* name, FILE* out, va_list argptr) {
template_t t = _findTemplate(name);
if (t == NULL) {
template_t findTemplate(bool abstract, bool start, const char* name) {
struct entry t = _findTemplate(name);
if (t.name == NULL) {
fprintf(stderr, "warning: template '%s' does not exist.\n", name);
t = &emptyTemplate;
return &emptyTemplate;
}
if (t.abstract) {
if (!abstract) {
fprintf(stderr, "warning: template name '%s' is abstract\n", name);
return &emptyTemplate;
} else {
if (start) {
return t.start;
} else {
return t.end;
}
}
} else {
return t.start;
}
}
static template_length_t findTemplateSize(const char* name) {
struct entry t = _findTemplate(name);
if (t.name == NULL) {
fprintf(stderr, "warning: template '%s' does not exist.\n", name);
return &emptyTemplateSize;
}
return t.s;
}
static void _renderTemplate(const char* name, FILE* out, va_list argptr) {
template_t t = findTemplate(false, false, name);
t(out, argptr);
}
static void _renderTemplateStart(const char* name, FILE* out, va_list argptr) {
template_t t = findTemplate(true, true, name);
t(out, argptr);
}
static void _renderTemplateEnd(const char* name, FILE* out, va_list argptr) {
template_t t = findTemplate(true, false, name);
t(out, argptr);
}
@ -77,14 +109,26 @@ void renderTemplate(const char* name, FILE* out, ...) {
va_end(argptr);
}
size_t _sizeTemplate(const char* name, va_list argptr) {
template_length_t s = _findTemplateSize(name);
void renderTemplateStart(const char* name, FILE* out, ...) {
va_list argptr;
va_start(argptr, out);
if (s == NULL) {
fprintf(stderr, "warning: template '%s' does not exist.\n", name);
s = &emptyTemplateSize;
}
_renderTemplateStart(name, out, argptr);
va_end(argptr);
}
void renderTemplateEnd(const char* name, FILE* out, ...) {
va_list argptr;
va_start(argptr, out);
_renderTemplateEnd(name, out, argptr);
va_end(argptr);
}
static size_t _sizeTemplate(const char* name, va_list argptr) {
template_length_t s = findTemplateSize(name);
return s(argptr);
}
@ -102,14 +146,8 @@ size_t sizeTemplate(const char* name, ...) {
}
char* renderTemplateStr(const char* name, ...) {
template_t t = _findTemplate(name);
template_length_t s = _findTemplateSize(name);
if (t == NULL) {
fprintf(stderr, "warning: template '%s' does not exist.\n", name);
t = &emptyTemplate;
s = &emptyTemplateSize;
}
template_t t = findTemplate(false, false, name);
template_length_t s = findTemplateSize(name);
size_t length;
char* result;
@ -119,7 +157,6 @@ char* renderTemplateStr(const char* name, ...) {
va_copy(argptr2, argptr);
length = s(argptr);
va_end(argptr);
result = malloc(length + 1);

View file

@ -58,6 +58,12 @@ struct node newRenderNode(char* arguments) {
};
}
struct node newChildNode() {
return (struct node) {
.type = CHILD_NODE,
};
}
struct tree newTree() {
return (struct tree) {
.kids = NULL,
@ -148,8 +154,7 @@ struct params combineParams(struct params p1, struct params p2) {
struct stats newStats() {
return (struct stats) {
.texts = NULL,
.no = 0,
.parent = NULL
.no = 0
};
}
@ -164,15 +169,12 @@ void addStat(struct stats* stats, char* text) {
stats->texts[stats->no++] = text;
}
void setParent(struct stats* stats, char* parent) {
stats->parent = parent;
}
struct template newTemplate() {
return (struct template) {
.params = newParams(),
.stats = newStats(),
.tree = newTree()
.tree = newTree(),
.parent = NULL
};
}

View file

@ -31,6 +31,7 @@ struct node newTextNode(char*);
struct node newStatementNode(char*, struct tree);
struct node newOutputNode(char*);
struct node newRenderNode(char*);
struct node newChildNode();
struct tree newTree();
void addNode(struct tree*, struct node);
@ -49,7 +50,6 @@ struct params combineParams(struct params, struct params);
struct stats {
char** texts;
size_t no;
char* parent;
};
struct stats newStats();
@ -59,6 +59,7 @@ struct template {
struct params params;
struct tree tree;
struct stats stats;
const char* parent;
};
struct template newTemplate();