out (so other things can use it).
--- /dev/null
+clibrary {
+ name = "lib",
+ srcs = { "./*.c" },
+ hdrs = { "./*.h" },
+ deps = {
+ },
+}
+
+
--- /dev/null
+#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 : */
+
+
--- /dev/null
+#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 : */
+
deps = {
"./iburg.h",
"+lib",
- "+yacc"
+ "+yacc",
+ "modules/src/data+lib",
}
}
%{
+#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
char* string;
Tree tree;
Rule rule;
- Stringlist stringlist;
+ struct stringlist* stringlist;
char* stringpair[2];
}
%term TERMINAL
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; }
;
cfragments
- : /* nothing */ { $$ = NULL; }
- | CFRAGMENT cfragments { $$ = pushstring($1, $2); }
+ : /* nothing */ { $$ = calloc(1, sizeof *$$); }
+ | cfragments CFRAGMENT { $$ = $1; stringlist_add($$, $2); }
;
ins
;
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); }
;
%%
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, ...)
{
{
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");
}
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");
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,");
/* 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);
}
#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
{
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 */
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);