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 <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <alloca.h> #include <alloca.h>
#include <stdbool.h>
#include "tree.h" #include "tree.h"
#include "common.h" #include "common.h"
#define PRINT_PREFIX ("print_template") #define PRINT_PREFIX ("print_template")
#define SIZE_PREFIX ("size_template") #define SIZE_PREFIX ("size_template")
#define END_SUFFIX ("end")
#define SIZE_ACCUMULATOR_VAR ("_total_size_") #define SIZE_ACCUMULATOR_VAR ("_total_size_")
@ -21,14 +23,19 @@ FILE* output;
char* name; char* name;
const char* filename; const char* filename;
bool isAbstract = false;
void generateHeader() { void generateHeader() {
fprintf(output, "#include <stdio.h>\n"); fprintf(output, "#include <stdio.h>\n");
fprintf(output, "#include <stdlib.h>\n"); fprintf(output, "#include <stdlib.h>\n");
fprintf(output, "#include <stdarg.h>\n"); fprintf(output, "#include <stdarg.h>\n");
fprintf(output, "#include <stdbool.h>\n");
fprintf(output, "\n"); fprintf(output, "\n");
fprintf(output, "#include <templates.h>\n"); fprintf(output, "#include <templates.h>\n");
fprintf(output, "\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, "\n");
fprintf(output, "#define _renderTemplate(f, t, ...) renderTemplate(t, f, __VA_ARGS__)\n"); fprintf(output, "#define _renderTemplate(f, t, ...) renderTemplate(t, f, __VA_ARGS__)\n");
fprintf(output, "\n"); fprintf(output, "\n");
@ -139,6 +146,9 @@ void parseTreeSize(int indentation, struct tree tree) {
case RENDER_NODE: case RENDER_NODE:
generateRenderNodeSize(indentation, tree.kids[i]); generateRenderNodeSize(indentation, tree.kids[i]);
break; break;
case CHILD_NODE:
// ignore CHILD_NODE for size calculation
break;
default: default:
panic("unknown node type"); panic("unknown node type");
} }
@ -185,6 +195,13 @@ void generateRenderNode(int indentation, struct node node) {
fprintf(output, "_renderTemplate(out, %s);\n", node.value.text); 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) { void parseTree(int indentation, struct tree tree) {
for (size_t i = 0; i < tree.kidsno; i++) { for (size_t i = 0; i < tree.kidsno; i++) {
switch(tree.kids[i].type) { switch(tree.kids[i].type) {
@ -200,6 +217,9 @@ void parseTree(int indentation, struct tree tree) {
case RENDER_NODE: case RENDER_NODE:
generateRenderNode(indentation, tree.kids[i]); generateRenderNode(indentation, tree.kids[i]);
break; break;
case CHILD_NODE:
generateChildNode();
break;
default: default:
panic("unknown node type"); panic("unknown node type");
} }
@ -217,7 +237,11 @@ void generateTree() {
void generateConstructor() { void generateConstructor() {
fprintf(output, "__attribute__((constructor)) static void _register() {\n"); 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"); 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) { int main(int argc, char** argv) {
// TODO: build sane argument parsing // TODO: build sane argument parsing
if (argc != 2) { if (argc != 2) {
@ -257,6 +303,8 @@ int main(int argc, char** argv) {
return 1; return 1;
} }
preprocessTree(0, result.tree);
generateHeader(); generateHeader();
generateSize(); generateSize();
generateTree(); generateTree();

View file

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

View file

@ -2,6 +2,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h>
#include "templates.h" #include "templates.h"
#include "common.h" #include "common.h"
@ -13,43 +14,39 @@ typedef size_t (*template_length_t)(va_list);
struct entry { struct entry {
const char* name; const char* name;
template_t f; bool abstract;
template_t start;
template_t end;
template_length_t s; template_length_t s;
} templates[MAX_TEMPLATES]; } templates[MAX_TEMPLATES];
size_t templateno = 0; 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++) { for (size_t i = 0; i < templateno; i++) {
if (strcmp(templates[i].name, name) == 0) { 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) { void _registerTemplate(const char* name, bool abstract, template_t start, template_t end, template_length_t s) {
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) {
if (templateno >= MAX_TEMPLATES) { if (templateno >= MAX_TEMPLATES) {
panic("max number of templates exceeded"); 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); fprintf(stderr, "warning: template name '%s' already registered; ignoring this one\n", name);
return; return;
} }
templates[templateno].abstract = abstract;
templates[templateno].name = name; templates[templateno].name = name;
templates[templateno].f = f; templates[templateno].start = start;
templates[templateno].end = end;
templates[templateno++].s = s; 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 size_t emptyTemplateSize(va_list _) { return 0; }
static void emptyTemplate(FILE* out, va_list _) { } static void emptyTemplate(FILE* out, va_list _) { }
void _renderTemplate(const char* name, FILE* out, va_list argptr) { template_t findTemplate(bool abstract, bool start, const char* name) {
template_t t = _findTemplate(name); struct entry t = _findTemplate(name);
if (t.name == NULL) {
if (t == NULL) {
fprintf(stderr, "warning: template '%s' does not exist.\n", name); 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); t(out, argptr);
} }
@ -77,14 +109,26 @@ void renderTemplate(const char* name, FILE* out, ...) {
va_end(argptr); va_end(argptr);
} }
size_t _sizeTemplate(const char* name, va_list argptr) { void renderTemplateStart(const char* name, FILE* out, ...) {
template_length_t s = _findTemplateSize(name); va_list argptr;
va_start(argptr, out);
if (s == NULL) { _renderTemplateStart(name, out, argptr);
fprintf(stderr, "warning: template '%s' does not exist.\n", name);
s = &emptyTemplateSize;
}
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); return s(argptr);
} }
@ -102,14 +146,8 @@ size_t sizeTemplate(const char* name, ...) {
} }
char* renderTemplateStr(const char* name, ...) { char* renderTemplateStr(const char* name, ...) {
template_t t = _findTemplate(name); template_t t = findTemplate(false, false, name);
template_length_t s = _findTemplateSize(name); template_length_t s = findTemplateSize(name);
if (t == NULL) {
fprintf(stderr, "warning: template '%s' does not exist.\n", name);
t = &emptyTemplate;
s = &emptyTemplateSize;
}
size_t length; size_t length;
char* result; char* result;
@ -119,7 +157,6 @@ char* renderTemplateStr(const char* name, ...) {
va_copy(argptr2, argptr); va_copy(argptr2, argptr);
length = s(argptr); length = s(argptr);
va_end(argptr); va_end(argptr);
result = malloc(length + 1); 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() { struct tree newTree() {
return (struct tree) { return (struct tree) {
.kids = NULL, .kids = NULL,
@ -148,8 +154,7 @@ struct params combineParams(struct params p1, struct params p2) {
struct stats newStats() { struct stats newStats() {
return (struct stats) { return (struct stats) {
.texts = NULL, .texts = NULL,
.no = 0, .no = 0
.parent = NULL
}; };
} }
@ -164,15 +169,12 @@ void addStat(struct stats* stats, char* text) {
stats->texts[stats->no++] = text; stats->texts[stats->no++] = text;
} }
void setParent(struct stats* stats, char* parent) {
stats->parent = parent;
}
struct template newTemplate() { struct template newTemplate() {
return (struct template) { return (struct template) {
.params = newParams(), .params = newParams(),
.stats = newStats(), .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 newStatementNode(char*, struct tree);
struct node newOutputNode(char*); struct node newOutputNode(char*);
struct node newRenderNode(char*); struct node newRenderNode(char*);
struct node newChildNode();
struct tree newTree(); struct tree newTree();
void addNode(struct tree*, struct node); void addNode(struct tree*, struct node);
@ -49,7 +50,6 @@ struct params combineParams(struct params, struct params);
struct stats { struct stats {
char** texts; char** texts;
size_t no; size_t no;
char* parent;
}; };
struct stats newStats(); struct stats newStats();
@ -59,6 +59,7 @@ struct template {
struct params params; struct params params;
struct tree tree; struct tree tree;
struct stats stats; struct stats stats;
const char* parent;
}; };
struct template newTemplate(); struct template newTemplate();