Stupid stringlist is stupid. Use a proper data structure, properly abstracted
authorDavid Given <dg@cowlark.com>
Sun, 25 Sep 2016 10:18:39 +0000 (12:18 +0200)
committerDavid Given <dg@cowlark.com>
Sun, 25 Sep 2016 10:18:39 +0000 (12:18 +0200)
out (so other things can use it).

modules/src/data/build.lua [new file with mode: 0644]
modules/src/data/stringlist.c [new file with mode: 0644]
modules/src/data/stringlist.h [new file with mode: 0644]
util/mcgg/build.lua
util/mcgg/gram.y
util/mcgg/iburg.c
util/mcgg/iburg.h
util/mcgg/mcgg.h

diff --git a/modules/src/data/build.lua b/modules/src/data/build.lua
new file mode 100644 (file)
index 0000000..7250f4f
--- /dev/null
@@ -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 (file)
index 0000000..28322bf
--- /dev/null
@@ -0,0 +1,43 @@
+#include <stdlib.h>
+#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 (file)
index 0000000..493d7ff
--- /dev/null
@@ -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 : */
+
index ee230d7..b3ffe81 100644 (file)
@@ -43,7 +43,8 @@ cprogram {
        deps = {
                "./iburg.h",
                "+lib",
-               "+yacc"
+               "+yacc",
+               "modules/src/data+lib",
        }
 }
        
index 369c65e..e248598 100644 (file)
@@ -1,4 +1,5 @@
 %{
+#include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdbool.h>
@@ -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); }
     ;
 
 %%
index 52df9cc..c4189f5 100644 (file)
@@ -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);
+
+                                       case '\n':
+                                               assert(f->data[1] == 0);
+                                               print("%1data->emit_eoi();\n");
+                                               break;
+                                       
+                                       default:
+                                               print("%1data->emit_string(\"%s\");\n", f->data);
                                }
-                               else
-                                       print("%1data->emit_string(\"%s\");\n", s->payload);
 
-                               s = s->next;
+                               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);
 }
 
index 0a6c90d..b289758 100644 (file)
@@ -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 */
index 10d8f51..1a1be1b 100644 (file)
@@ -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);