From bcc74ba18db11276c7db3d47b5e7a1bb5eda35e7 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 25 Sep 2016 12:18:39 +0200 Subject: [PATCH] Stupid stringlist is stupid. Use a proper data structure, properly abstracted out (so other things can use it). --- modules/src/data/build.lua | 9 +++++ modules/src/data/stringlist.c | 43 +++++++++++++++++++++++ modules/src/data/stringlist.h | 23 +++++++++++++ util/mcgg/build.lua | 3 +- util/mcgg/gram.y | 26 +++++++++----- util/mcgg/iburg.c | 65 ++++++++++++++++++----------------- util/mcgg/iburg.h | 39 +++++++++------------ util/mcgg/mcgg.h | 1 + 8 files changed, 146 insertions(+), 63 deletions(-) create mode 100644 modules/src/data/build.lua create mode 100644 modules/src/data/stringlist.c create mode 100644 modules/src/data/stringlist.h diff --git a/modules/src/data/build.lua b/modules/src/data/build.lua new file mode 100644 index 000000000..7250f4f72 --- /dev/null +++ b/modules/src/data/build.lua @@ -0,0 +1,9 @@ +clibrary { + name = "lib", + srcs = { "./*.c" }, + hdrs = { "./*.h" }, + deps = { + }, +} + + diff --git a/modules/src/data/stringlist.c b/modules/src/data/stringlist.c new file mode 100644 index 000000000..28322bf98 --- /dev/null +++ b/modules/src/data/stringlist.c @@ -0,0 +1,43 @@ +#include +#include "stringlist.h" + +void stringlist_add(struct stringlist* list, const char* data) +{ + struct stringfragment* f = calloc(1, sizeof *f); + f->data = data; + + if (!list->last) + list->first = list->last = f; + else + { + list->last->next = f; + list->last = f; + } +} + +void stringlist_addall(struct stringlist* list, struct stringlist* src) +{ + struct stringfragment* f = src->first; + + while (f) + { + stringlist_add(list, f->data); + f = f->next; + } +} + +void stringlist_free(struct stringlist* list) +{ + struct stringfragment* f = list->first; + + while (f) + { + struct stringfragment* next = f->next; + free(f); + f = next; + } +} + +/* vim: set sw=4 ts=4 expandtab : */ + + diff --git a/modules/src/data/stringlist.h b/modules/src/data/stringlist.h new file mode 100644 index 000000000..493d7ff1e --- /dev/null +++ b/modules/src/data/stringlist.h @@ -0,0 +1,23 @@ +#ifndef STRINGLIST_H +#define STRINGLIST_H + +struct stringfragment +{ + const char* data; + struct stringfragment* next; +}; + +struct stringlist +{ + struct stringfragment* first; + struct stringfragment* last; +}; + +extern void stringlist_add(struct stringlist* list, const char* data); +extern void stringlist_addall(struct stringlist* list, struct stringlist* src); +extern void stringlist_free(struct stringlist* list); + +#endif + +/* vim: set sw=4 ts=4 expandtab : */ + diff --git a/util/mcgg/build.lua b/util/mcgg/build.lua index ee230d73a..b3ffe81f6 100644 --- a/util/mcgg/build.lua +++ b/util/mcgg/build.lua @@ -43,7 +43,8 @@ cprogram { deps = { "./iburg.h", "+lib", - "+yacc" + "+yacc", + "modules/src/data+lib", } } diff --git a/util/mcgg/gram.y b/util/mcgg/gram.y index 369c65ef3..e24859851 100644 --- a/util/mcgg/gram.y +++ b/util/mcgg/gram.y @@ -1,4 +1,5 @@ %{ +#include #include #include #include @@ -17,7 +18,7 @@ static int nextern = 1; char* string; Tree tree; Rule rule; - Stringlist stringlist; + struct stringlist* stringlist; char* stringpair[2]; } %term TERMINAL @@ -58,7 +59,7 @@ patterns pattern : ID '=' rhs { nonterm($1); $$ = rule($1, $3, nextern++); } | rhs { $$ = rule("stmt", $1, nextern++); } - | pattern WHEN cfragments { $$ = $1; $$->when = $3; } + | pattern WHEN cfragments { $$ = $1; stringlist_addall(&$$->when, $3); } | pattern INS ins { $$ = $1; } | pattern OUTS outs { $$ = $1; } | emit { $$ = $1; } @@ -77,8 +78,8 @@ labelledid ; cfragments - : /* nothing */ { $$ = NULL; } - | CFRAGMENT cfragments { $$ = pushstring($1, $2); } + : /* nothing */ { $$ = calloc(1, sizeof *$$); } + | cfragments CFRAGMENT { $$ = $1; stringlist_add($$, $2); } ; ins @@ -101,13 +102,22 @@ out ; emit - : pattern EMIT qfragments { $$ = $1; $$->code = $3; $$->is_fragment = false; } - | pattern FRAGMENT qfragments { $$ = $1; $$->code = $3; $$->is_fragment = true; } + : pattern EMIT qfragments { + $$ = $1; + stringlist_add($3, "\n"); + stringlist_addall(&$$->code, $3); + $$->is_fragment = false; + } + | pattern FRAGMENT qfragments { + $$ = $1; + stringlist_addall(&$$->code, $3); + $$->is_fragment = true; + } ; qfragments - : QFRAGMENT { $$ = pushstring($1, NULL); } - | QFRAGMENT qfragments { $$ = pushstring($1, $2); } + : /* nothing */ { $$ = calloc(1, sizeof *$$); } + | qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); } ; %% diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index 52df9cc31..c4189f560 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -365,14 +365,6 @@ Rule rule(char* id, Tree pattern, int ern) return r; } -Stringlist pushstring(const char* data, Stringlist list) -{ - Stringlist sl = calloc(1, sizeof *sl); - sl->payload = data; - sl->next = list; - return sl; -} - /* print - formatted output */ static void print(char* fmt, ...) { @@ -792,15 +784,15 @@ static void emitpredicatedefinitions(Rule r) { while (r) { - Stringlist s = r->when; - if (s) + struct stringfragment* f = r->when.first; + if (f) { print("/* %R */\n", r); print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern); - while (s) + while (f) { - print("%s", s->payload); - s = s->next; + print("%s", f->data); + f = f->next; } print("\n}\n\n"); } @@ -866,32 +858,42 @@ static void emitemitters(Rule rules) r = rules; while (r) { - Stringlist s = r->code; - if (s) + struct stringfragment* f = r->code.first; + if (f) { print("/* %R */\n", r); print("static void %Pemitter_%d(NODEPTR_TYPE node, struct %Pemitter_data* data) {\n", r->ern); emittreefetchers(0, r->pattern); print("%1NODEPTR_TYPE node_%s = node;\n", r->lhs->name); - while (s) + while (f) { - if (s->payload[0] == '%') + switch (f->data[0]) { - const char* label = s->payload + 1; - Tree t = find_label(r->pattern, label); - if (!t && (strcmp(label, r->lhs->name) != 0)) + case '%': { - yylineno = r->lineno; - yyerror("label '%s' not found", label); - exit(1); + const char* label = f->data + 1; + Tree t = find_label(r->pattern, label); + if (!t && (strcmp(label, r->lhs->name) != 0)) + { + yylineno = r->lineno; + yyerror("label '%s' not found", label); + exit(1); + } + print("%1data->emit_ir(node_%s);\n", label); + break; } - print("%1data->emit_ir(node_%s);\n", label); - } - else - print("%1data->emit_string(\"%s\");\n", s->payload); - s = s->next; + case '\n': + assert(f->data[1] == 0); + print("%1data->emit_eoi();\n"); + break; + + default: + print("%1data->emit_string(\"%s\");\n", f->data); + } + + f = f->next; } print("}\n\n"); @@ -904,9 +906,10 @@ static void emitemitters(Rule rules) print("%Pemitter_t* const %Pemitters[] = {\n"); while (r) { - Stringlist s = r->code; + struct stringfragment* f = r->code.first; + print("%1"); - if (s) + if (f) print("&%Pemitter_%d,", r->ern); else print("NULL,"); @@ -920,7 +923,7 @@ static void emitemitters(Rule rules) /* emitcost - emit a cost calculation via a predicate */ static void emitcostcalc(Rule r) { - if (r->when) + if (r->when.first) print("!%Ppredicate_%d(node) ? %d : ", r->ern, maxcost); } diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index 0a6c90dfc..b2897587a 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -1,16 +1,9 @@ #ifndef BURG_INCLUDED #define BURG_INCLUDED -/* $Id$ */ -/* iburg.c: */ -extern char* stringf(char* fmt, ...); +#include "stringlist.h" -typedef struct stringlist* Stringlist; -struct stringlist { - const char* payload; - Stringlist next; -}; -extern Stringlist pushstring(const char* data, Stringlist list); +extern char* stringf(char* fmt, ...); typedef enum { @@ -56,20 +49,20 @@ extern Tree tree(const char* op, const char* label, Tree left, Tree right); struct rule { /* rules: */ - Nonterm lhs; /* lefthand side non-terminal */ - Tree pattern; /* rule pattern */ - int lineno; /* line number where allocated */ - int ern; /* external rule number */ - int packed; /* packed external rule number */ - int cost; /* associated cost */ - Rule link; /* next rule in ern order */ - Rule next; /* next rule with same pattern root */ - Rule chain; /* next chain rule with same rhs */ - Rule decode; /* next rule with same lhs */ - Rule kids; /* next rule with same burm_kids pattern */ - Stringlist when; /* C predicate string */ - Stringlist code; /* compiler output code strings */ - bool is_fragment; /* does this rule generate an instruction fragment? */ + Nonterm lhs; /* lefthand side non-terminal */ + Tree pattern; /* rule pattern */ + int lineno; /* line number where allocated */ + int ern; /* external rule number */ + int packed; /* packed external rule number */ + int cost; /* associated cost */ + Rule link; /* next rule in ern order */ + Rule next; /* next rule with same pattern root */ + Rule chain; /* next chain rule with same rhs */ + Rule decode; /* next rule with same lhs */ + Rule kids; /* next rule with same burm_kids pattern */ + struct stringlist when; /* C predicate string */ + struct stringlist code; /* compiler output code strings */ + bool is_fragment; /* does this rule generate an instruction fragment? */ }; extern Rule rule(char* id, Tree pattern, int ern); extern int maxcost; /* maximum cost */ diff --git a/util/mcgg/mcgg.h b/util/mcgg/mcgg.h index 10d8f5166..1a1be1b83 100644 --- a/util/mcgg/mcgg.h +++ b/util/mcgg/mcgg.h @@ -30,6 +30,7 @@ struct burm_emitter_data void* user; void (*emit_string)(const char* data); void (*emit_ir)(struct ir* ir); + void (*emit_eoi)(void); }; typedef void burm_emitter_t(struct ir* ir, struct burm_emitter_data* data);