Stupid stringlist is stupid. Use a proper data structure, properly abstracted
out (so other things can use it).
This commit is contained in:
parent
9f78e0b36b
commit
bcc74ba18d
9
modules/src/data/build.lua
Normal file
9
modules/src/data/build.lua
Normal file
|
@ -0,0 +1,9 @@
|
|||
clibrary {
|
||||
name = "lib",
|
||||
srcs = { "./*.c" },
|
||||
hdrs = { "./*.h" },
|
||||
deps = {
|
||||
},
|
||||
}
|
||||
|
||||
|
43
modules/src/data/stringlist.c
Normal file
43
modules/src/data/stringlist.c
Normal file
|
@ -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 : */
|
||||
|
||||
|
23
modules/src/data/stringlist.h
Normal file
23
modules/src/data/stringlist.h
Normal file
|
@ -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 : */
|
||||
|
|
@ -43,7 +43,8 @@ cprogram {
|
|||
deps = {
|
||||
"./iburg.h",
|
||||
"+lib",
|
||||
"+yacc"
|
||||
"+yacc",
|
||||
"modules/src/data+lib",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue