aboutsummaryrefslogtreecommitdiff
path: root/lib/forlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/forlan.c')
-rw-r--r--lib/forlan.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/lib/forlan.c b/lib/forlan.c
new file mode 100644
index 0000000..0854d08
--- /dev/null
+++ b/lib/forlan.c
@@ -0,0 +1,258 @@
1/* This file is part of Eclat.
2 Copyright (C) 2012 Sergey Poznyakoff.
3
4 Eclat is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 Eclat is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "libeclat.h"
18#include "grecs.h"
19#include "forlan.h"
20
21int forlan_dbg = -1;
22
23void
24forlan_init()
25{
26 forlan_dbg = debug_register("forlan");
27}
28
29union forlan_node *
30forlan_node_create(enum forlan_type type)
31{
32 union forlan_node *p = grecs_zalloc(sizeof(*p));
33 p->type = type;
34 return p;
35}
36
37static void f_dump_node(FILE *fp, union forlan_node *p, int *num, int lev);
38
39
40static void
41free_type_null(union forlan_node *p)
42{
43 warn("freeing undefined forlan_node");
44}
45
46void
47dump_null(FILE *fp, union forlan_node *p, int *num, int lev)
48{
49 fprintf(fp, "[undefined node]\n");
50}
51
52static void
53free_type_comp(union forlan_node *p)
54{
55 forlan_node_free(p->comp.node);
56}
57void
58dump_comp(FILE *fp, union forlan_node *p, int *num, int lev)
59{
60 fprintf(fp, "COMP");
61 if (p->comp.abs)
62 fprintf(fp, " ABS");
63 fputc('\n', fp);
64 forlan_dump_node(fp, p->comp.node, num, lev + 1);
65}
66
67static void
68free_type_test(union forlan_node *p)
69{
70 free(p->test.comp);
71 free(p->test.value);
72}
73void
74dump_test(FILE *fp, union forlan_node *p, int *num, int lev)
75{
76 fprintf(fp, "TEST: %s[%s]\n", p->test.comp, p->test.value);
77}
78
79static void
80free_type_func(union forlan_node *p)
81{
82 grecs_list_free(p->func.args);
83}
84void
85dump_func(FILE *fp, union forlan_node *p, int *num, int lev)
86{
87 struct grecs_list_entry *ep;
88 fprintf(fp, "CALL: %s\n", p->func.fp);
89 if (p->func.args)
90 for (ep = p->func.args->head; ep; ep = ep->next)
91 forlan_dump_node(fp, ep->data, num, lev + 1);
92}
93
94static void
95free_type_cond(union forlan_node *p)
96{
97 forlan_node_free((union forlan_node *)p->cond.expr);
98 forlan_node_free(p->cond.iftrue);
99 forlan_node_free(p->cond.iffalse);
100}
101void
102dump_cond(FILE *fp, union forlan_node *p, int *num, int lev)
103{
104 int n = *num;
105 fprintf(fp, "COND\n");
106 forlan_dump_node(fp, p->cond.expr, num, lev + 1);
107 fprintf(fp, "%04d: %*.*sIFTRUE %04d\n", ++*num, lev, lev, "", n);
108 forlan_dump_node(fp, p->cond.iftrue, num, lev + 1);
109 fprintf(fp, "%04d: %*.*sIFFALSE %04d\n", ++*num, lev, lev, "", n);
110 forlan_dump_node(fp, p->cond.iffalse, num, lev + 1);
111}
112
113static void
114free_type_stmt(union forlan_node *p)
115{
116 forlan_node_free(p->stmt.stmt);
117 forlan_node_free(p->stmt.next);
118}
119void
120dump_stmt(FILE *fp, union forlan_node *p, int *num, int lev)
121{
122 f_dump_node(fp, p->stmt.stmt, num, lev);
123 forlan_dump_node(fp, p->stmt.next, num, lev);
124}
125
126static void
127free_type_lit(union forlan_node *p)
128{
129 free(p->lit.string);
130}
131void
132dump_lit(FILE *fp, union forlan_node *p, int *num, int lev)
133{
134 fprintf(fp, "LIT: \"%s\"\n", p->lit.string);
135}
136
137static void
138free_type_expr(union forlan_node *p)
139{
140 forlan_node_free(p->expr.arg[0]);
141 forlan_node_free(p->expr.arg[1]);
142}
143void
144dump_expr(FILE *fp, union forlan_node *p, int *num, int lev)
145{
146 static char *opstr[] = { "NODE", "AND", "OR", "NOT" };
147
148 fprintf(fp, "%s\n", opstr[p->expr.opcode]);
149 forlan_dump_node(fp, p->expr.arg[0], num, lev + 1);
150 if (p->expr.arg[1])
151 forlan_dump_node(fp, p->expr.arg[1], num, lev + 1);
152}
153
154static void
155free_type_last(union forlan_node *p)
156{
157}
158void
159dump_last(FILE *fp, union forlan_node *p, int *num, int lev)
160{
161 fprintf(fp, "LAST\n");
162}
163
164struct forlan_node_method {
165 void (*f_free)(union forlan_node *);
166 void (*f_dump)(FILE *fp, union forlan_node *node, int *num, int lev);
167};
168
169static struct forlan_node_method f_tab[] = {
170 free_type_null, dump_null, /* Unknown/unset type */
171 free_type_comp, dump_comp, /* A path component */
172 free_type_test, dump_test, /* Value test (f[X]) */
173 free_type_func, dump_func, /* Function call */
174 free_type_cond, dump_cond, /* Conditional */
175 free_type_stmt, dump_stmt, /* Statement */
176 free_type_lit, dump_lit, /* Literal */
177 free_type_expr, dump_expr, /* Boolean expression */
178 free_type_last, dump_last, /* "last" */
179};
180
181void
182forlan_node_free(union forlan_node *p)
183{
184 if (!p)
185 return;
186 if (p->type > sizeof(f_tab) / sizeof(f_tab[0]))
187 abort();
188 if (f_tab[p->type].f_free)
189 f_tab[p->type].f_free(p);
190 free(p);
191}
192
193static void
194stmt_list_free_entry(void *p)
195{
196 forlan_node_free(p);
197}
198
199struct grecs_list *
200forlan_stmt_list()
201{
202 struct grecs_list *lp;
203
204 lp = grecs_list_create();
205 lp->free_entry = stmt_list_free_entry;
206 return lp;
207}
208
209union forlan_node *
210forlan_stmt_from_list(struct grecs_list *list)
211{
212 union forlan_node **tail = NULL, *ret = NULL;
213 struct grecs_list_entry *ep;
214
215 for (ep = list->head; ep; ep = ep->next) {
216 union forlan_node *sp = forlan_node_create(forlan_type_stmt);
217 sp->stmt.stmt = ep->data;
218 if (tail)
219 *tail = sp;
220 else
221 ret = sp;
222 tail = &sp->stmt.next;
223 }
224 list->free_entry = NULL;
225 grecs_list_free(list);
226 return ret;
227}
228
229static void
230f_dump_node(FILE *fp, union forlan_node *p, int *num, int lev)
231{
232 if (p) {
233 if (p->type > sizeof(f_tab) / sizeof(f_tab[0]))
234 abort();
235 if (f_tab[p->type].f_dump)
236 f_tab[p->type].f_dump(fp, p, num, lev);
237 else
238 fprintf(fp, "type %d", p->type);
239 } else
240 fprintf(fp, "NULL");
241}
242
243void
244forlan_dump_node(FILE *fp, union forlan_node *p, int *num, int lev)
245{
246 if (!p)
247 return;
248 ++*num;
249 fprintf(fp, "%04d: %*.*s", *num, lev, lev, "");
250 f_dump_node(fp, p, num, lev);
251}
252
253void
254forlan_dump_tree(FILE *fp, union forlan_node *node)
255{