summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2012-09-22 13:15:48 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2012-09-22 13:30:07 (GMT)
commit0666fc3caae8e2db660d781e43bee2258bf06a00 (patch) (unidiff)
tree97380903872520efa3b2bf659465e63f2cf51a2a
parent7f3dd0599ac3fb3a69c512b0ecfd043c67ca94ee (diff)
downloadeclat-0666fc3caae8e2db660d781e43bee2258bf06a00.tar.gz
eclat-0666fc3caae8e2db660d781e43bee2258bf06a00.tar.bz2
Introduce output formatting language
* configure.ac: Check for lex and yacc. * lib/diag.c: New file (moved from ../src with edits) * lib/forlan.c: New file. * lib/forlan.h: New file. * lib/forlangrm.y: New file. * lib/forlanlex.l: New file. * lib/.gitignore: Add new files. * lib/Makefile.am: Add new file. * lib/libeclat.h: Add diagnostics-related stuff. * src/Makefile.am (eclat_SOURCES): Remove diag.c * src/cmdline.opt (set_program_name): Move to ../lib/diag.c * src/diag.c: Remove (see above). * src/config.c: Reflect changes to the diagnostics subsystem. * src/eclat.c: Likewise. * src/eclat.h: Remove diagnostics-related stuff. It lives in libeclat.h from now on. * src/error.c: Remove. * tests/forlan01.at: New testcase. * tests/testsuite.at: Include forlan01.at * tests/tforlan.c: New file. * tests/.gitignore: Add new files. * tests/Makefile.am: Add new files.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--NEWS4
-rw-r--r--configure.ac2
-rw-r--r--lib/.gitignore4
-rw-r--r--lib/Makefile.am15
-rw-r--r--lib/diag.c181
-rw-r--r--lib/forlan.c258
-rw-r--r--lib/forlan.h123
-rw-r--r--lib/forlangrm.y237
-rw-r--r--lib/forlanlex.l137
-rw-r--r--lib/libeclat.h33
-rw-r--r--src/Makefile.am1
-rw-r--r--src/cmdline.opt10
-rw-r--r--src/config.c2
-rw-r--r--src/diag.c108
-rw-r--r--src/eclat.c77
-rw-r--r--src/eclat.h19
-rw-r--r--src/error.c64
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/forlan01.at77
-rw-r--r--tests/testsuite.at4
-rw-r--r--tests/tforlan.c100
22 files changed, 1198 insertions, 261 deletions
diff --git a/NEWS b/NEWS
index a38e2aa..ebe5900 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,11 @@
1Eclat NEWS -- history of user-visible changes. 2012-09-19 1Eclat NEWS -- history of user-visible changes. 2012-09-22
2Copyright (C) 2012 Sergey Poznyakoff 2Copyright (C) 2012 Sergey Poznyakoff
3See the end of file for copying conditions. 3See the end of file for copying conditions.
4 4
5Please send Eclat bug reports to <gray+eclat@gnu.org.ua> 5Please send Eclat bug reports to <gray+eclat@gnu.org.ua>
6 6
7 7
8No news is good news. 8Version 0.1 - No news is good news.
9 9
10========================================================================= 10=========================================================================
11Copyright information: 11Copyright information:
diff --git a/configure.ac b/configure.ac
index fd22d37..b0aba5e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,6 +27,8 @@ AM_SILENT_RULES([yes])
27 27
28# Checks for programs. 28# Checks for programs.
29AC_PROG_CC 29AC_PROG_CC
30AC_PROG_LEX
31AC_PROG_YACC
30AC_PROG_RANLIB 32AC_PROG_RANLIB
31 33
32# Checks for header files. 34# Checks for header files.
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 0000000..e0d9b22
--- a/dev/null
+++ b/lib/.gitignore
@@ -0,0 +1,4 @@
1forlangrm.c
2forlangrm.h
3forlangrm.output
4forlanlex.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2c1d3a8..50b28a5 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -18,6 +18,12 @@ noinst_LIBRARIES=libeclat.a
18 18
19libeclat_a_SOURCES=\ 19libeclat_a_SOURCES=\
20 base64.c\ 20 base64.c\
21 diag.c\
22 forlan.c\
23 forlan.h\
24 forlangrm.h\
25 forlangrm.y\
26 forlanlex.l\
21 hmac_sha1.c\ 27 hmac_sha1.c\
22 libeclat.h\ 28 libeclat.h\
23 q2url.c\ 29 q2url.c\
@@ -33,3 +39,12 @@ libeclat_a_SOURCES=\
33 39
34AM_LDFLAGS = $(CURL_LIBS) 40AM_LDFLAGS = $(CURL_LIBS)
35INCLUDES = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS) 41INCLUDES = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS)
42
43forlanlex.c: forlangrm.h
44forlangrm.c forlangrm.h: forlangrm.y
45
46AM_YFLAGS=-tdv
47AM_LFLAGS=-dvp
48
49
50
diff --git a/lib/diag.c b/lib/diag.c
new file mode 100644
index 0000000..d061e9e
--- a/dev/null
+++ b/lib/diag.c
@@ -0,0 +1,181 @@
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 <string.h>
19#include <sysexits.h>
20
21const char *program_name;
22struct debug_category debug_category[LIBECLAT_DBG_MAX];
23int debug_avail;
24
25void
26set_program_name(const char *arg)
27{
28 program_name = strrchr(arg, '/');
29 if (!program_name)
30 program_name = arg;
31 else
32 program_name++;
33}
34
35void
36vdiag(grecs_locus_t const *locus, const char *qual, const char *fmt,
37 va_list ap)
38{
39 if (program_name)
40 fprintf(stderr, "%s: ", program_name);
41
42 if (locus) {
43 size_t size = 0;
44
45 if (locus->beg.col == 0)
46 fprintf(stderr, "%s:%u",
47 locus->beg.file,
48 locus->beg.line);
49 else if (strcmp(locus->beg.file, locus->end.file))
50 fprintf(stderr, "%s:%u.%u-%s:%u.%u",
51 locus->beg.file,
52 locus->beg.line, locus->beg.col,
53 locus->end.file,
54 locus->end.line, locus->end.col);
55 else if (locus->beg.line != locus->end.line)
56 fprintf(stderr, "%s:%u.%u-%u.%u",
57 locus->beg.file,
58 locus->beg.line, locus->beg.col,
59 locus->end.line, locus->end.col);
60 else
61 fprintf(stderr, "%s:%u.%u-%u",
62 locus->beg.file,
63 locus->beg.line, locus->beg.col,
64 locus->end.col);
65 fprintf(stderr, ": ");
66 }
67
68 if (qual)
69 fprintf(stderr, "%s: ", qual);
70 vfprintf(stderr, fmt, ap);
71 fputc('\n', stderr);
72}
73
74void
75diag(grecs_locus_t const *locus, const char *qual, const char *fmt, ...)
76{
77 va_list ap;
78
79 va_start(ap, fmt);
80 vdiag(locus, qual, fmt, ap);
81 va_end(ap);
82 }
83
84void
85die(int status, const char *fmt, ...)
86{
87 va_list ap;
88
89 va_start(ap, fmt);
90 vdiag(NULL, NULL, fmt, ap);
91 va_end(ap);
92 exit(status);
93}
94
95void
96err(const char *fmt, ...)
97{
98 va_list ap;
99
100 va_start(ap, fmt);
101 vdiag(NULL, NULL, fmt, ap);
102 va_end(ap);
103}
104
105void
106warn(const char *fmt, ...)
107{
108 va_list ap;
109
110 va_start(ap, fmt);
111 vdiag(NULL, "warning", fmt, ap);
112 va_end(ap);
113}
114
115void
116debug_printf(const char *fmt, ...)
117{
118 va_list ap;
119
120 va_start(ap, fmt);
121 vdiag(NULL, "debug", fmt, ap);
122 va_end(ap);
123 }
124
125static struct debug_category *
126find_category(const char *arg, size_t len)
127{
128 struct debug_category *dp;
129
130 for (dp = debug_category; dp < debug_category + debug_avail; dp++)
131 if (dp->length == len && memcmp(dp->name, arg, len) == 0)
132 return dp;
133 return NULL;
134}
135
136int
137parse_debug_level(const char *arg)
138{
139 unsigned long lev;
140 char *p;
141 size_t len = strcspn(arg, ".");
142 struct debug_category *dp;
143
144 if (arg[len] == 0) {
145 lev = strtoul(arg, &p, 10);
146 if (*p)
147 return -1;
148 for (dp = debug_category; dp < debug_category + debug_avail;
149 dp++)
150 dp->level = lev;
151 return 0;
152 }
153
154 dp = find_category(arg, len);
155 if (!dp)
156 return -1;
157
158 p = (char*) arg + len;
159 if (*p == 0)
160 lev = 100;
161 else if (*p != '.')
162 return -1;
163 else {
164 lev = strtoul(p + 1, &p, 10);
165 if (*p)
166 return -1;
167 }
168 dp->level = lev;
169 return 0;
170}
171
172int
173debug_register(char *name)
174{
175 if (debug_avail >= LIBECLAT_DBG_MAX)
176 die(EX_SOFTWARE, "no more debug slots available");
177 debug_category[debug_avail].name = grecs_strdup(name);
178 debug_category[debug_avail].length = strlen(name);
179 debug_category[debug_avail].level = 0;
180 return debug_avail++;
181}
diff --git a/lib/forlan.c b/lib/forlan.c
new file mode 100644
index 0000000..0854d08
--- a/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{
256 int n = 0;
257 forlan_dump_node(fp, node, &n, 0);
258}
diff --git a/lib/forlan.h b/lib/forlan.h
new file mode 100644
index 0000000..4dadc70
--- a/dev/null
+++ b/lib/forlan.h
@@ -0,0 +1,123 @@
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#define FORLAN_DBG_LEX 3
18#define FORLAN_DBG_GRAM 2
19#define FORLAN_DBG_EVAL 1
20
21extern int forlan_dbg;
22
23void forlan_init();
24void forlan_lex_begin(const char *input, size_t length,
25 struct grecs_locus_point *pt);
26void forlan_lex_end(void);
27int forlan_parse(const char *input, size_t length,
28 struct grecs_locus_point *pt);
29
30union forlan_node; /* Declared below */
31
32enum forlan_type {
33 forlan_type_null, /* Unknown/unset type */
34 forlan_type_comp, /* A path component */
35 forlan_type_test,/* Value test (f[X]) */
36 forlan_type_func,/* Function call */
37 forlan_type_cond,/* Conditional */
38 forlan_type_stmt,/* Statement */
39 forlan_type_lit,/* Literal */
40 forlan_type_expr, /* Boolean expression */
41 forlan_type_last /* Return last evaluated grecs_node */
42};
43
44/* A path component */
45struct forlan_node_comp {
46 enum forlan_type type;
47 int abs;
48 union forlan_node *node;
49};
50
51/* Path test: .path.comp[value] */
52struct forlan_node_test {
53 enum forlan_type type;
54 char *comp;
55 char *value;
56};
57
58/* Function call */
59struct forlan_node_func {
60 enum forlan_type type;
61 void *fp; /* FIXME: replace with typedef */
62 struct grecs_list *args; /* Arguments are struct forlan_node * */
63};
64
65/* Conditional */
66struct forlan_node_cond {
67 enum forlan_type type;
68 union forlan_node *expr; /* Controlling expression */
69 union forlan_node *iftrue; /* Run this if expr yields true */
70 union forlan_node *iffalse; /* Run this if expr yields false */
71};
72
73/* Statement or statement list */
74struct forlan_node_stmt {
75 enum forlan_type type;
76 union forlan_node *stmt;
77 union forlan_node *next;
78};
79
80/* Literal string */
81struct forlan_node_lit {
82 enum forlan_type type;
83 char *string;
84};
85
86/* Boolean opcodes */
87enum forlan_opcode {
88 forlan_opcode_node, /* Evaluate node, set 'last' */
89 forlan_opcode_and, /* Boolean AND */
90 forlan_opcode_or, /* Boolean OR */
91 forlan_opcode_not /* Boolean NOT */
92};
93
94/* Boolean expression */
95struct forlan_node_expr {
96 enum forlan_type type;
97 enum forlan_opcode opcode;
98 union forlan_node *arg[2];
99};
100
101/* Now get all this together */
102union forlan_node {
103 enum forlan_type type;
104 struct forlan_node_comp comp; /* A path component */
105 struct forlan_node_test test; /* Value test (f[X]) */
106 struct forlan_node_func func; /* Function call */
107 struct forlan_node_cond cond; /* Conditional */
108 struct forlan_node_stmt stmt; /* Statement */
109 struct forlan_node_lit lit; /* Literal */
110 struct forlan_node_expr expr; /* Boolean expression */
111 /* forlan_type_last needs no additional data */
112};
113
114union forlan_node *forlan_node_create(enum forlan_type type);
115void forlan_node_free(union forlan_node *);
116struct grecs_list *forlan_stmt_list(void);
117struct grecs_list *forlan_complist(void);
118union forlan_node *forlan_stmt_from_list(struct grecs_list *list);
119
120extern union forlan_node *forlan_parse_tree;
121
122void forlan_dump_node(FILE *fp, union forlan_node *p, int *num, int lev);
123void forlan_dump_tree(FILE *fp, union forlan_node *node);
diff --git a/lib/forlangrm.y b/lib/forlangrm.y
new file mode 100644
index 0000000..1b7781d
--- a/dev/null
+++ b/lib/forlangrm.y
@@ -0,0 +1,237 @@
1%{
2/* This file is part of Eclat.
3 Copyright (C) 2012 Sergey Poznyakoff.
4
5 Eclat is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 Eclat is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "libeclat.h"
19#include <grecs.h>
20#include <grecs-locus.h>
21#include "forlangrm.h"
22#include "forlan.h"
23
24static int yyerror(char *);
25union forlan_node *forlan_parse_tree;
26%}
27%error-verbose
28%locations
29
30%union {
31 char *string;
32 union forlan_node *node;
33 struct grecs_list *list;
34};
35
36%token <string> STRING IDENT
37%token LAST IF ELSE
38
39%left OR
40%left AND
41%left NOT
42
43%type <node> stmt stmt_cond stmt_expr stmt_blk cond bool node comp funcall arg
44%type <list> stmtlist complist arglist
45%type <string> string
46
47%%
48input : stmtlist
49 {
50 forlan_parse_tree = forlan_stmt_from_list($1);
51 }
52 ;
53
54stmtlist : stmt
55 {
56 $$ = forlan_stmt_list();
57 grecs_list_append($$, $1);
58 }
59 | stmtlist stmt
60 {
61 grecs_list_append($1, $2);
62 $$ = $1;
63 }
64 ;
65
66stmt : stmt_cond
67 | stmt_expr
68 | stmt_blk
69 ;
70
71stmt_blk : '{' stmtlist '}'
72 {
73 $$ = forlan_stmt_from_list($2);
74 }
75 ;
76
77stmt_cond : IF cond stmt
78 {
79 $$ = forlan_node_create(forlan_type_cond);
80 $$->cond.expr = $2;
81 $$->cond.iftrue = $3;
82 $$->cond.iffalse = NULL;
83 }
84 | IF cond stmt ELSE stmt
85 {
86 $$ = forlan_node_create(forlan_type_cond);
87 $$->cond.expr = $2;
88 $$->cond.iftrue = $3;
89 $$->cond.iffalse = $5;
90 }
91 ;
92
93cond : bool
94 ;
95
96bool : node
97 {
98 $$ = forlan_node_create(forlan_type_expr);
99 $$->expr.opcode = forlan_opcode_node;
100 $$->expr.arg[0] = $1;
101 }
102 | bool AND bool
103 {
104 $$ = forlan_node_create(forlan_type_expr);
105 $$->expr.opcode = forlan_opcode_and;
106 $$->expr.arg[0] = $1;
107 $$->expr.arg[1] = $3;
108 }
109 | bool OR bool
110 {
111 $$ = forlan_node_create(forlan_type_expr);
112 $$->expr.opcode = forlan_opcode_or;
113 $$->expr.arg[0] = $1;
114 $$->expr.arg[1] = $3;
115 }
116 | NOT bool
117 {
118 $$ = forlan_node_create(forlan_type_expr);
119 $$->expr.opcode = forlan_opcode_not;
120 $$->expr.arg[0] = $2;
121 }
122 | '(' bool ')'
123 {
124 $$ = $2;
125 }
126 ;
127
128node : complist
129 {
130 $$ = forlan_node_create(forlan_type_comp);
131 $$->comp.abs = 0;
132 $$->comp.node = forlan_stmt_from_list($1);
133 }
134 | '.' complist
135 {
136 $$ = forlan_node_create(forlan_type_comp);
137 $$->comp.abs = 1;
138 $$->comp.node = forlan_stmt_from_list($2);
139 }
140 | LAST
141 {
142 $$ = forlan_node_create(forlan_type_last);
143 }
144 ;
145
146complist : comp
147 {
148 $$ = forlan_stmt_list();
149 grecs_list_append($$, $1);
150 }
151 | complist '.' comp
152 {
153 grecs_list_append($1, $3);
154 $$ = $1;
155 }
156 ;
157
158comp : IDENT
159 {
160 $$ = forlan_node_create(forlan_type_lit);
161 $$->lit.string = $1;
162 }
163 | IDENT '[' string ']'
164 {
165 $$ = forlan_node_create(forlan_type_test);
166 $$->test.comp = $1;
167 $$->test.value = $3;
168 }
169 | funcall
170 ;
171
172string : IDENT
173 | STRING
174 ;
175
176funcall : IDENT '(' ')'
177 {
178 $$ = forlan_node_create(forlan_type_func);
179 $$->func.fp = $1; //FIXME
180 $$->func.args = NULL;
181 }
182 | IDENT '(' arglist ')'
183 {
184 $$ = forlan_node_create(forlan_type_func);
185 $$->func.fp = $1; //FIXME
186 $$->func.args = $3;
187 }
188 ;
189
190arglist : arg
191 {
192 $$ = forlan_stmt_list();
193 grecs_list_append($$, $1);
194 }
195 | arglist ',' arg
196 {
197 grecs_list_append($1, $3);
198 $$ = $1;
199 }
200 ;
201
202arg : node
203 | STRING
204 {
205 $$ = forlan_node_create(forlan_type_lit);
206 $$->lit.string = $1;
207 }
208 ;
209
210stmt_expr : funcall ';'
211 ;
212%%
213static int
214yyerror(char *s)
215{
216 grecs_error(&yylloc, 0, "%s", s);
217 return 0;
218}
219
220int
221forlan_parser()
222{
223 yydebug = debug_level(forlan_dbg) >= FORLAN_DBG_GRAM;
224 return yyparse();
225}
226
227int
228forlan_parse(const char *input, size_t length, struct grecs_locus_point *pt)
229{
230 int rc;
231 forlan_lex_begin(input, length, pt);
232 rc = forlan_parser();
233 forlan_lex_end();
234 return rc;
235}
236
237
diff --git a/lib/forlanlex.l b/lib/forlanlex.l
new file mode 100644
index 0000000..99966ed
--- a/dev/null
+++ b/lib/forlanlex.l
@@ -0,0 +1,137 @@
1%{
2/* This file is part of Eclat.
3 Copyright (C) 2012 Sergey Poznyakoff.
4
5 Eclat is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 Eclat is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "libeclat.h"
19#include <grecs.h>
20#include <grecs-locus.h>
21#include "forlangrm.h"
22#include "forlan.h"
23
24static const char *forlan_input_base;
25static size_t forlan_input_len;
26static size_t forlan_input_pos;
27
28#undef YY_INPUT
29 #define YY_INPUT(buf,result,max_size) \
30 do { \
31 size_t __s = forlan_input_len - forlan_input_pos; \
32 if (__s > max_size) \
33 __s = max_size; \
34 if (__s > 0) { \
35 memcpy(buf, forlan_input_base, __s); \
36 forlan_input_pos += __s; \
37 } \
38 result = __s; \
39 } while(0)
40
41 #define YY_USER_ACTION do { \
42 if (YYSTATE == 0) { \
43 yylloc.beg = grecs_current_locus_point; \
44 yylloc.beg.col++; \
45 } \
46 grecs_current_locus_point.col += yyleng; \
47 yylloc.end = grecs_current_locus_point; \
48 } while (0);
49
50static int yywrap(void);
51
52%}
53
54WS [ \t\f][ \t\f]*
55IDC [a-zA-Z_0-9-]
56%x COMMENT ML STR
57%%
58 /* Comments */
59"/*" BEGIN(COMMENT);
60<COMMENT>[^*\n]* /* eat anything that's not a '*' */
61<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
62<COMMENT>\n grecs_locus_point_advance_line(grecs_current_locus_point);
63<COMMENT>"*"+"/" BEGIN(INITIAL);
64"//".* ;
65 /* Keywords */
66if return IF;
67else return ELSE;
68last return LAST;
69! return NOT;
70"&&" return AND;
71"||" return OR;
72{IDC}{IDC}* { grecs_line_begin();
73 grecs_line_add(yytext, yyleng);
74 yylval.string = grecs_line_finish();
75 return IDENT; }
76 /* Quoted strings */
77\"[^\\"\n]*\" { grecs_line_begin();
78 grecs_line_add(yytext + 1, yyleng - 2);
79 yylval.string = grecs_line_finish();
80 return STRING; }
81\"[^\\"\n]*\\\n { BEGIN(STR);
82 grecs_line_begin();
83 grecs_line_acc_grow_unescape_last(yytext + 1,
84 yyleng - 1);
85 grecs_locus_point_advance_line(grecs_current_locus_point); }
86\"[^\\"\n]*\\. { BEGIN(STR);
87 grecs_line_begin();
88 grecs_line_acc_grow_unescape_last(yytext + 1,
89 yyleng - 1); }
90<STR>\"[^\\"\n]*\\\n { grecs_line_acc_grow_unescape_last(yytext, yyleng);
91 grecs_locus_point_advance_line(grecs_current_locus_point); }
92<STR>[^\\"\n]*\\. { grecs_line_acc_grow_unescape_last(yytext, yyleng); }
93<STR>[^\\"\n]*\" { BEGIN(INITIAL);
94 if (yyleng > 1)
95 grecs_line_add(yytext, yyleng - 1);
96 yylval.string = grecs_line_finish();
97 return STRING; }
98 /* Other tokens */
99{WS} ;
100\n { grecs_locus_point_advance_line(grecs_current_locus_point); }
101[.,;{}()\[\]] return yytext[0];
102. { if (isascii(yytext[0]) && isprint(yytext[0]))
103 grecs_error(&yylloc, 0,
104 _("stray character %c"), yytext[0]);
105 else
106 grecs_error(&yylloc, 0,
107 _("stray character \\%03o"),
108 (unsigned char) yytext[0]); }
109%%
110
111static int
112yywrap()
113{
114 return 1;
115}
116
117void
118forlan_lex_begin(const char *input, size_t length,
119 struct grecs_locus_point *pt)
120{
121 forlan_input_base = input;
122 forlan_input_len = length;
123 grecs_current_locus_point = *pt;
124 yy_flex_debug = debug_level(forlan_dbg) >= FORLAN_DBG_LEX;
125 grecs_line_acc_create();
126}
127
128void
129forlan_lex_end()
130{
131 grecs_line_acc_free();
132}
133
134
135
136
137
diff --git a/lib/libeclat.h b/lib/libeclat.h
index 670c51b..5f37cc9 100644
--- a/lib/libeclat.h
+++ b/lib/libeclat.h
@@ -18,6 +18,39 @@
18#include <expat.h> 18#include <expat.h>
19#include "grecs.h" 19#include "grecs.h"
20 20
21extern const char *program_name;
22
23struct debug_category {
24 const char *name;
25 size_t length;
26 int level;
27};
28
29extern struct debug_category debug_category[];
30#define LIBECLAT_DBG_MAX 64
31
32 #define debug_level(cat) ((cat >= 0 && cat < LIBECLAT_DBG_MAX) ?\
33 debug_category[cat].level : 0)
34 #define debug(cat, lev, s) \
35 do { \
36 if (debug_level(cat) >= (lev)) \
37 debug_printf s; \
38 } while(0)
39
40void set_program_name(const char *arg);
41
42void die(int status, const char *fmt, ...);
43void vdiag(grecs_locus_t const *locus, const char *qual, const char *fmt,
44 va_list ap);
45void diag(grecs_locus_t const *locus, const char *qual, const char *fmt, ...);
46void err(const char *fmt, ...);
47void warn(const char *fmt, ...);
48void debug_printf(const char *fmt, ...);
49
50int parse_debug_level(const char *arg);
51int debug_register(char *name);
52
53
21void hmac_sha1(const void *text, size_t textlen, 54void hmac_sha1(const void *text, size_t textlen,
22 const void *key, size_t keylen, 55 const void *key, size_t keylen,
23 void *digest); 56 void *digest);
diff --git a/src/Makefile.am b/src/Makefile.am
index b5f7912..bda0584 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,7 +21,6 @@ eclat_SOURCES=\
21 cmdline.h\ 21 cmdline.h\
22 config.c\ 22 config.c\
23 descrtags.c\ 23 descrtags.c\
24 diag.c\
25 eclat.c\ 24 eclat.c\
26 eclat.h\ 25 eclat.h\
27 startinst.c 26 startinst.c
diff --git a/src/cmdline.opt b/src/cmdline.opt
index 82e0e95..1f8d56d 100644
--- a/src/cmdline.opt
+++ b/src/cmdline.opt
@@ -208,16 +208,6 @@ END
208OPTIONS_END 208OPTIONS_END
209 209
210void 210void
211set_program_name(const char *arg)
212{
213 program_name = strrchr(arg, '/');
214 if (!program_name)
215 program_name = arg;
216 else
217 program_name++;
218}
219
220void
221parse_options(int argc, char *argv[], int *index) 211parse_options(int argc, char *argv[], int *index)
222{ 212{
223 GETOPT(argc, argv, *index, exit(EX_USAGE)) 213 GETOPT(argc, argv, *index, exit(EX_USAGE))
diff --git a/src/config.c b/src/config.c
index c40d307..b718486 100644
--- a/src/config.c
+++ b/src/config.c
@@ -149,7 +149,7 @@ config_finish(struct grecs_node *tree)
149 struct grecs_node *node; 149 struct grecs_node *node;
150 150
151 grecs_tree_reduce(tree, eclat_kw, GRECS_AGGR); 151 grecs_tree_reduce(tree, eclat_kw, GRECS_AGGR);
152 if (debug_level[ECLAT_DEBCAT_CONF]) { 152 if (debug_level(ECLAT_DEBCAT_CONF)) {
153 grecs_print_node(tree, GRECS_NODE_FLAG_DEFAULT, stderr); 153 grecs_print_node(tree, GRECS_NODE_FLAG_DEFAULT, stderr);
154 fputc('\n', stdout); 154 fputc('\n', stdout);
155 } 155 }
diff --git a/src/diag.c b/src/diag.c
deleted file mode 100644
index 30ffa34..0000000
--- a/src/diag.c
+++ b/dev/null
@@ -1,108 +0,0 @@
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 "eclat.h"
18
19const char *program_name;
20
21void
22vdiag(grecs_locus_t const *locus, const char *qual, const char *fmt, va_list ap)
23{
24 if (program_name)
25 fprintf(stderr, "%s: ", program_name);
26
27 if (locus) {
28 size_t size = 0;
29
30 if (locus->beg.col == 0)
31 fprintf(stderr, "%s:%u",
32 locus->beg.file,
33 locus->beg.line);
34 else if (strcmp(locus->beg.file, locus->end.file))
35 fprintf(stderr, "%s:%u.%u-%s:%u.%u",
36 locus->beg.file,
37 locus->beg.line, locus->beg.col,
38 locus->end.file,
39 locus->end.line, locus->end.col);
40 else if (locus->beg.line != locus->end.line)
41 fprintf(stderr, "%s:%u.%u-%u.%u",
42 locus->beg.file,
43 locus->beg.line, locus->beg.col,
44 locus->end.line, locus->end.col);
45 else
46 fprintf(stderr, "%s:%u.%u-%u",
47 locus->beg.file,
48 locus->beg.line, locus->beg.col,
49 locus->end.col);
50 fprintf(stderr, ": ");
51 }
52
53 if (qual)
54 fprintf(stderr, "%s: ", qual);
55 vfprintf(stderr, fmt, ap);
56 fputc('\n', stderr);
57}
58
59void
60diag(grecs_locus_t const *locus, const char *qual, const char *fmt, ...)
61{
62 va_list ap;
63
64 va_start(ap, fmt);
65 vdiag(locus, qual, fmt, ap);
66 va_end(ap);
67 }
68
69void
70die(int status, const char *fmt, ...)
71{
72 va_list ap;
73
74 va_start(ap, fmt);
75 vdiag(NULL, NULL, fmt, ap);
76 va_end(ap);
77 exit(status);
78}
79
80void
81err(const char *fmt, ...)
82{
83 va_list ap;
84
85 va_start(ap, fmt);
86 vdiag(NULL, NULL, fmt, ap);
87 va_end(ap);
88}
89
90void
91warn(const char *fmt, ...)
92{
93 va_list ap;
94
95 va_start(ap, fmt);
96 vdiag(NULL, "warning", fmt, ap);
97 va_end(ap);
98}
99
100void
101debug_printf(const char *fmt, ...)
102{
103 va_list ap;
104
105 va_start(ap, fmt);
106 vdiag(NULL, "debug", fmt, ap);
107 va_end(ap);
108 }
diff --git a/src/eclat.c b/src/eclat.c
index 3703376..86b4627 100644
--- a/src/eclat.c
+++ b/src/eclat.c
@@ -18,7 +18,6 @@
18 18
19char *conffile = SYSCONFDIR "/eclat.conf" ; 19char *conffile = SYSCONFDIR "/eclat.conf" ;
20int lint_mode; 20int lint_mode;
21int debug_level[ECLAT_DEBCAT_MAX];
22int dry_run_mode; 21int dry_run_mode;
23int preprocess_only = 0; 22int preprocess_only = 0;
24 23
@@ -30,59 +29,23 @@ char *region_name;
30enum eclat_command eclat_command; 29enum eclat_command eclat_command;
31 30
32 31
33struct debug_trans { 32static char *categories[] = {
34 const char *name; 33 "main",
35 size_t length; 34 "cfgram",
36 int cat; 35 "cflex",
36 "conf",
37 "curl",
37}; 38};
38 39
39static struct debug_trans debug_trans[] = { 40static void
40#define S(s) #s, sizeof(#s)-1 41debug_init()
41 { S(main), ECLAT_DEBCAT_MAIN },
42 { S(cfgram), ECLAT_DEBCAT_CFGRAM },
43 { S(cflex), ECLAT_DEBCAT_CFLEX },
44 { S(conf), ECLAT_DEBCAT_CONF },
45 { S(curl), ECLAT_DEBCAT_CURL },
46 { NULL }
47};
48
49static int
50parse_debug_level(const char *arg)
51{ 42{
52 unsigned long cat, lev; 43 int i;
53 char *p;
54 44
55 if (isascii(*arg) && isdigit(*arg)) { 45 for (i = 0; i < sizeof(categories)/sizeof(categories[0]); i++)
56 cat = strtoul(arg, &p, 10); 46 debug_register(categories[i]);
57 if (cat > ECLAT_DEBCAT_MAX)
58 return -1;
59 } else {
60 size_t len = strcspn(arg, ".");
61 struct debug_trans *dp;
62
63 for (dp = debug_trans; dp->name; dp++)
64 if (dp->length == len &&
65 memcmp(dp->name, arg, len) == 0)
66 break;
67
68 if (!dp->name)
69 return -1;
70 cat = dp->cat;
71 p = (char*) arg + len;
72 }
73
74 if (*p == 0)
75 lev = 100;
76 else if (*p != '.')
77 return -1;
78 else {
79 lev = strtoul(p + 1, &p, 10);
80 if (*p)
81 return -1;
82 }
83 debug_level[cat] = lev;
84 return 0;
85} 47}
48
86 49
87static void 50static void
88dump(const char *text, FILE *stream, unsigned char *ptr, size_t size) 51dump(const char *text, FILE *stream, unsigned char *ptr, size_t size)
@@ -90,7 +53,7 @@ dump(const char *text, FILE *stream, unsigned char *ptr, size_t size)
90 size_t i; 53 size_t i;
91 size_t c; 54 size_t c;
92 unsigned int width = 0x10; 55 unsigned int width = 0x10;
93 int hex = debug_level[ECLAT_DEBCAT_CURL] > 2; 56 int hex = debug_level(ECLAT_DEBCAT_CURL) > 2;
94 57
95 if (!hex) 58 if (!hex)
96 /* without the hex output, we can fit more on screen */ 59 /* without the hex output, we can fit more on screen */
@@ -199,7 +162,7 @@ write_callback(void *ptr, size_t size, size_t nmemb, void *data)
199 int column = XML_GetCurrentColumnNumber(parser); 162 int column = XML_GetCurrentColumnNumber(parser);
200 163
201 /* FIXME: Debugging level. */ 164 /* FIXME: Debugging level. */
202 if (debug_level[ECLAT_DEBCAT_MAIN] > 10) { 165 if (debug_level(ECLAT_DEBCAT_MAIN) > 10) {
203 dump_text(stderr, line, column, ptr, realsize); 166 dump_text(stderr, line, column, ptr, realsize);
204 } 167 }
205 status = XML_Parse(parser, ptr, realsize, 0); 168 status = XML_Parse(parser, ptr, realsize, 0);
@@ -215,7 +178,6 @@ write_callback(void *ptr, size_t size, size_t nmemb, void *data)
215 } 178 }
216 return realsize; 179 return realsize;
217} 180}
218
219 181
220#include "cmdline.h" 182#include "cmdline.h"
221 183
@@ -237,14 +199,15 @@ main(int argc, char **argv)
237 struct grecs_node *xmltree; 199 struct grecs_node *xmltree;
238 200
239 set_program_name(argv[0]); 201 set_program_name(argv[0]);
202 debug_init();
240 config_init(); 203 config_init();
241 parse_options(argc, argv, &index); 204 parse_options(argc, argv, &index);
242 205
243 argc -= index; 206 argc -= index;
244 argv += index; 207 argv += index;
245 208
246 grecs_gram_trace(debug_level[ECLAT_DEBCAT_CFGRAM]); 209 grecs_gram_trace(debug_level(ECLAT_DEBCAT_CFGRAM));
247 grecs_lex_trace(debug_level[ECLAT_DEBCAT_CFLEX]); 210 grecs_lex_trace(debug_level(ECLAT_DEBCAT_CFLEX));
248 211
249 if (preprocess_only) 212 if (preprocess_only)
250 exit(grecs_preproc_run(conffile, grecs_preprocessor) ? 213 exit(grecs_preproc_run(conffile, grecs_preprocessor) ?
@@ -292,9 +255,9 @@ main(int argc, char **argv)
292 if (!curl) 255 if (!curl)
293 die(EX_UNAVAILABLE, "curl_easy_init failed"); 256 die(EX_UNAVAILABLE, "curl_easy_init failed");
294 257
295 if (debug_level[ECLAT_DEBCAT_CURL]) { 258 if (debug_level(ECLAT_DEBCAT_CURL)) {
296 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 259 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
297 if (debug_level[ECLAT_DEBCAT_CURL] > 1) 260 if (debug_level(ECLAT_DEBCAT_CURL) > 1)
298 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, 261 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
299 eclat_trace_fun); 262 eclat_trace_fun);
300 } 263 }
diff --git a/src/eclat.h b/src/eclat.h
index b0d46ac..e588b57 100644
--- a/src/eclat.h
+++ b/src/eclat.h
@@ -33,10 +33,7 @@
33#define ECLAT_DEBCAT_CFLEX 2 33#define ECLAT_DEBCAT_CFLEX 2
34#define ECLAT_DEBCAT_CONF 3 34#define ECLAT_DEBCAT_CONF 3
35#define ECLAT_DEBCAT_CURL 4 35#define ECLAT_DEBCAT_CURL 4
36#define ECLAT_DEBCAT_MAX 5 36#define ECLAT_DEBCAT_FORLAN 5
37
38extern const char *program_name;
39extern int debug_level[];
40 37
41extern char *endpoint; 38extern char *endpoint;
42extern int use_ssl; 39extern int use_ssl;
@@ -46,20 +43,6 @@ extern char *access_file_name;
46extern char *access_key; 43extern char *access_key;
47extern char *secret_key; 44extern char *secret_key;
48 45
49 #define debug(cat, lev, s) \
50 do { \
51 if (debug_level[cat] >= (lev)) \
52 debug_printf s; \
53 } while(0)
54
55void die(int status, const char *fmt, ...);
56void vdiag(grecs_locus_t const *locus, const char *qual, const char *fmt,
57 va_list ap);
58void diag(grecs_locus_t const *locus, const char *qual, const char *fmt, ...);
59void err(const char *fmt, ...);
60void warn(const char *fmt, ...);
61void debug_printf(const char *fmt, ...);
62
63typedef int (*config_finish_hook_t) (void*); 46typedef int (*config_finish_hook_t) (void*);
64 47
65void add_config_finish_hook(config_finish_hook_t fun, void *data); 48void add_config_finish_hook(config_finish_hook_t fun, void *data);
diff --git a/src/error.c b/src/error.c
deleted file mode 100644
index 6c86d34..0000000
--- a/src/error.c
+++ b/dev/null
@@ -1,64 +0,0 @@
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 "eclat.h"
18#include <stdargs.h>
19#include <stdio.h>
20
21char *program_name;
22
23void
24diag(const char *qual, const char *fmt, va_list ap)
25{
26 if (program_name)
27 fprintf(stderr, "%s: ", program_name);
28 if (qual)
29 fprintf(stderr, "%s: ", qual);
30 va_start(ap, fmt);
31 vfprintf(stderr, ftm, ap);
32 va_end(ap);
33 fputc('\n', stderr);
34}
35
36void
37err(const char *fmt, ...)
38{
39 va_list ap;
40
41 va_start(ap, fmt);
42 diag(NULL, ftm, ap);
43 va_end(ap);
44}
45
46void
47warn(const char *fmt, ...)
48{
49 va_list ap;
50
51 va_start(ap, fmt);
52 diag("warning", ftm, ap);
53 va_end(ap);
54}
55
56void
57debug_printf(const char *fmt, ...)
58{
59 va_list ap;
60
61 va_start(ap, fmt);
62 diag("debug", ftm, ap);
63 va_end(ap);
64 }
diff --git a/tests/.gitignore b/tests/.gitignore
index 99d3c9c..8b76ee0 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -4,6 +4,7 @@ package.m4
4testsuite 4testsuite
5testsuite.dir 5testsuite.dir
6testsuite.log 6testsuite.log
7tforlan
7thmac 8thmac
8turlenc 9turlenc
9txml 10txml
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 82cae7e..4d567b3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -40,6 +40,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
40## ------------ ## 40## ------------ ##
41 41
42TESTSUITE_AT = \ 42TESTSUITE_AT = \
43 forlan01.at\
43 hmac01.at\ 44 hmac01.at\
44 hmac02.at\ 45 hmac02.at\
45 hmac03.at\ 46 hmac03.at\
@@ -69,6 +70,7 @@ check-local: atconfig atlocal $(TESTSUITE)
69 #$(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin 70 #$(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin
70 71
71noinst_PROGRAMS = \ 72noinst_PROGRAMS = \
73 tforlan\
72 thmac\ 74 thmac\
73 turlenc\ 75 turlenc\
74 txml 76 txml
diff --git a/tests/forlan01.at b/tests/forlan01.at
new file mode 100644
index 0000000..cf826e9
--- a/dev/null
+++ b/tests/forlan01.at
@@ -0,0 +1,77 @@
1# This file is part of Eclat -*- Autotest -*-
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
17AT_SETUP([dump])
18AT_KEYWORDS([forlan forlan01])
19
20AT_DATA([input],[// test format for DescribeTags
21if (.DescribeTagsResponse) {
22 if (.DescribeTagsResponse.tagSet.item.resourceId[[i-deadbeef]] &&
23 parent(last).key[[hostname]])
24 print(parent(last).value);
25} else if (.Response.Errors)
26 error(.Response.Errors.Error.Message);
27else
28 dump();
29])
30
31AT_CHECK([tforlan -D input],
32[0],
33[0001: COND
340002: NODE
350003: COMP ABS
360004: LIT: "DescribeTagsResponse"
370005: IFTRUE 0001
380006: COND
390007: AND
400008: NODE
410009: COMP ABS
420010: LIT: "DescribeTagsResponse"
430011: LIT: "tagSet"
440012: LIT: "item"
450013: TEST: resourceId[[i-deadbeef]]
460014: NODE
470015: COMP
480016: CALL: parent
490017: LAST
500018: TEST: key[[hostname]]
510019: IFTRUE 0006
520020: CALL: print
530021: COMP
540022: CALL: parent
550023: LAST
560024: LIT: "value"
570025: IFFALSE 0006
580026: IFFALSE 0001
590027: COND
600028: NODE
610029: COMP ABS
620030: LIT: "Response"
630031: LIT: "Errors"
640032: IFTRUE 0027
650033: CALL: error
660034: COMP ABS
670035: LIT: "Response"
680036: LIT: "Errors"
690037: LIT: "Error"
700038: LIT: "Message"
710039: IFFALSE 0027
720040: CALL: dump
73])
74
75AT_CLEANUP
76
77
diff --git a/tests/testsuite.at b/tests/testsuite.at
index f40b8a7..81e91f4 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -29,4 +29,8 @@ m4_include([urlenc01.at])
29 29
30AT_BANNER([XML Processing]) 30AT_BANNER([XML Processing])
31m4_include([xml01.at]) 31m4_include([xml01.at])
32
33AT_BANNER([Forlan])
34m4_include([forlan01.at])
35
32# End of testsuite.at 36# End of testsuite.at
diff --git a/tests/tforlan.c b/tests/tforlan.c
new file mode 100644
index 0000000..9fc3495
--- a/dev/null
+++ b/tests/tforlan.c
@@ -0,0 +1,100 @@
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 <config.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#ifdef HAVE_GETOPT_H
22# include <getopt.h>
23#endif
24#include <errno.h>
25#include <sysexits.h>
26#include <libeclat.h>
27#include "forlan.h"
28#include <sys/stat.h>
29
30void
31usage()
32{
33 printf("usage: %s [-dD] FILE [INPUT]\n");
34}
35
36int
37main(int argc, char **argv)
38{
39 FILE *fp;
40 char *buf;
41 size_t len;
42 struct stat st;
43 struct grecs_locus_point pt;
44 int rc;
45 int dump_option = 0;
46
47 set_program_name(argv[0]);
48 forlan_init();
49
50 while ((rc = getopt(argc, argv, "Dd:h")) != EOF)
51 switch (rc) {
52 case 'D':
53 dump_option++;
54 break;
55
56 case 'd':
57 if (parse_debug_level(optarg))
58 die(EX_USAGE, "bad debug category or level");
59 break;
60
61 case 'h':
62 usage();
63 return 0;
64
65 default:
66 exit(EX_USAGE);
67 }
68 argc -= optind;
69 argv += optind;
70
71
72 if (argc == 0 || argc > 2)
73 die(EX_USAGE, "one or two arguments expected");
74 if (stat(argv[0], &st))
75 die(EX_UNAVAILABLE, "cannot stat input file \"%s\": %s",
76 argv[0], strerror(errno));
77 len = st.st_size;
78 buf = grecs_malloc(len);
79 fp = fopen(argv[0], "r");
80 if (!fp)
81 die(EX_UNAVAILABLE, "cannot open input file \"%s\": %s",
82 argv[0], strerror(errno));
83 if (fread(buf, len, 1, fp) != 1)
84 die(EX_UNAVAILABLE, "error reading from \"%s\": %s",
85 argv[0], strerror(errno));
86 fclose(fp);
87
88 pt.file = argv[0];
89 pt.line = 1;
90 pt.col = 0;
91
92 rc = forlan_parse(buf, len, &pt);
93 if (rc == 0) {
94 if (dump_option)
95 forlan_dump_tree(stdout, forlan_parse_tree);
96 forlan_node_free(forlan_parse_tree);
97 }
98 return rc ? EX_UNAVAILABLE : 0;
99}
100

Return to:

Send suggestions and report system problems to the System administrator.