src
generate_code.cc
Go to the documentation of this file.
1 #include "src/util/c99_stdint.h"
2 #include <stddef.h>
3 #include <algorithm>
4 #include <set>
5 #include <string>
6 
7 #include "src/codegen/bitmap.h"
8 #include "src/codegen/output.h"
9 #include "src/conf/opt.h"
10 #include "src/globals.h"
12 #include "src/ir/rule_rank.h"
14 
15 namespace re2c
16 {
17 
18 static void exact_uint (OutputFile & o, size_t width)
19 {
20  if (width == sizeof (char))
21  {
22  o.ws("unsigned char");
23  }
24  else if (width == sizeof (short))
25  {
26  o.ws("unsigned short");
27  }
28  else if (width == sizeof (int))
29  {
30  o.ws("unsigned int");
31  }
32  else if (width == sizeof (long))
33  {
34  o.ws("unsigned long");
35  }
36  else
37  {
38  o.ws("uint").wu64 (width * 8).ws("_t");
39  }
40 }
41 
42 static void from_le(OutputFile &o, uint32_t ind, size_t size, const char *expr)
43 {
44  o.ws("\n").wind(ind).ws("/* from little-endian to host-endian */");
45  o.ws("\n").wind(ind).ws("unsigned char *p = (unsigned char*)&").ws(expr).ws(";");
46  o.ws("\n").wind(ind).ws(expr).ws(" = p[0]");
47  for (uint32_t i = 1; i < size; ++i)
48  {
49  o.ws(" + (p[").wu32(i).ws("] << ").wu32(i * 8).ws("u)");
50  }
51  o.ws(";");
52 }
53 
55 {
56  o.ws("\n#include <stdio.h>");
57  o.ws("\n#include <stdlib.h> /* malloc, free */");
58  o.ws("\n");
59  o.ws("\nstatic void *read_file");
60  o.ws("\n").wind(1).ws("( const char *fname");
61  o.ws("\n").wind(1).ws(", size_t unit");
62  o.ws("\n").wind(1).ws(", size_t padding");
63  o.ws("\n").wind(1).ws(", size_t *pfsize");
64  o.ws("\n").wind(1).ws(")");
65  o.ws("\n{");
66  o.ws("\n").wind(1).ws("void *buffer = NULL;");
67  o.ws("\n").wind(1).ws("size_t fsize = 0;");
68  o.ws("\n");
69  o.ws("\n").wind(1).ws("/* open file */");
70  o.ws("\n").wind(1).ws("FILE *f = fopen(fname, \"rb\");");
71  o.ws("\n").wind(1).ws("if(f == NULL) {");
72  o.ws("\n").wind(2).ws("goto error;");
73  o.ws("\n").wind(1).ws("}");
74  o.ws("\n");
75  o.ws("\n").wind(1).ws("/* get file size */");
76  o.ws("\n").wind(1).ws("fseek(f, 0, SEEK_END);");
77  o.ws("\n").wind(1).ws("fsize = (size_t) ftell(f) / unit;");
78  o.ws("\n").wind(1).ws("fseek(f, 0, SEEK_SET);");
79  o.ws("\n");
80  o.ws("\n").wind(1).ws("/* allocate memory for file and padding */");
81  o.ws("\n").wind(1).ws("buffer = malloc(unit * (fsize + padding));");
82  o.ws("\n").wind(1).ws("if (buffer == NULL) {");
83  o.ws("\n").wind(2).ws("goto error;");
84  o.ws("\n").wind(1).ws("}");
85  o.ws("\n");
86  o.ws("\n").wind(1).ws("/* read the whole file in memory */");
87  o.ws("\n").wind(1).ws("if (fread(buffer, unit, fsize, f) != fsize) {");
88  o.ws("\n").wind(2).ws("goto error;");
89  o.ws("\n").wind(1).ws("}");
90  o.ws("\n");
91  o.ws("\n").wind(1).ws("fclose(f);");
92  o.ws("\n").wind(1).ws("*pfsize = fsize;");
93  o.ws("\n").wind(1).ws("return buffer;");
94  o.ws("\n");
95  o.ws("\nerror:");
96  o.ws("\n").wind(1).ws("fprintf(stderr, \"error: cannot read file '%s'\\n\", fname);");
97  o.ws("\n").wind(1).ws("free(buffer);");
98  o.ws("\n").wind(1).ws("if (f != NULL) {");
99  o.ws("\n").wind(2).ws("fclose(f);");
100  o.ws("\n").wind(1).ws("}");
101  o.ws("\n").wind(1).ws("return NULL;");
102  o.ws("\n}");
103  o.ws("\n");
104 }
105 
108  , size_t maxfill
109  , bool backup
110  , bool backupctx
111  , bool accept
112  ) const
113 {
114  const size_t sizeof_cunit = opts->encoding.szCodeUnit();
115  const uint32_t default_rule = rule2key (rule_rank_t::none ());
116 
117  o.ws("\n#define YYCTYPE ");
118  exact_uint (o, sizeof_cunit);
119  o.ws("\n#define YYKEYTYPE ");
120  exact_uint (o, sizeof_key);
121  o.ws("\n#define YYPEEK() *cursor");
122  o.ws("\n#define YYSKIP() ++cursor");
123  if (backup)
124  {
125  o.ws("\n#define YYBACKUP() marker = cursor");
126  o.ws("\n#define YYRESTORE() cursor = marker");
127  }
128  if (backupctx)
129  {
130  o.ws("\n#define YYBACKUPCTX() ctxmarker = cursor");
131  o.ws("\n#define YYRESTORECTX() cursor = ctxmarker");
132  }
133  o.ws("\n#define YYLESSTHAN(n) (limit - cursor) < n");
134  o.ws("\n#define YYFILL(n) { break; }");
135  o.ws("\n");
136  o.ws("\nstatic int action_").wstring(name);
137  o.ws("\n").wind(1).ws("( unsigned int i");
138  o.ws("\n").wind(1).ws(", const YYKEYTYPE *keys");
139  o.ws("\n").wind(1).ws(", const YYCTYPE *start");
140  o.ws("\n").wind(1).ws(", const YYCTYPE *token");
141  o.ws("\n").wind(1).ws(", const YYCTYPE **cursor");
142  o.ws("\n").wind(1).ws(", YYKEYTYPE rule_act");
143  o.ws("\n").wind(1).ws(")");
144  o.ws("\n{");
145  o.ws("\n").wind(1).ws("const long pos = token - start;");
146  o.ws("\n").wind(1).ws("const long len_act = *cursor - token;");
147  o.ws("\n").wind(1).ws("const long len_exp = (long) keys [3 * i + 1];");
148  o.ws("\n").wind(1).ws("const YYKEYTYPE rule_exp = keys [3 * i + 2];");
149  o.ws("\n").wind(1).ws("if (rule_exp == ").wu32(default_rule).ws(") {");
150  o.ws("\n").wind(2).ws("fprintf");
151  o.ws("\n").wind(3).ws("( stderr");
152  o.ws("\n").wind(3).ws(", \"warning: lex_").wstring(name).ws(": control flow is undefined for input\"");
153  o.ws("\n").wind(4).ws("\" at position %ld, rerun re2c with '-W'\\n\"");
154  o.ws("\n").wind(3).ws(", pos");
155  o.ws("\n").wind(3).ws(");");
156  o.ws("\n").wind(1).ws("}");
157  o.ws("\n").wind(1).ws("if (len_act == len_exp && rule_act == rule_exp) {");
158  o.ws("\n").wind(2).ws("const YYKEYTYPE offset = keys[3 * i];");
159  o.ws("\n").wind(2).ws("*cursor = token + offset;");
160  o.ws("\n").wind(2).ws("return 0;");
161  o.ws("\n").wind(1).ws("} else {");
162  o.ws("\n").wind(2).ws("fprintf");
163  o.ws("\n").wind(3).ws("( stderr");
164  o.ws("\n").wind(3).ws(", \"error: lex_").wstring(name).ws(": at position %ld (iteration %u):\\n\"");
165  o.ws("\n").wind(4).ws("\"\\texpected: match length %ld, rule %u\\n\"");
166  o.ws("\n").wind(4).ws("\"\\tactual: match length %ld, rule %u\\n\"");
167  o.ws("\n").wind(3).ws(", pos");
168  o.ws("\n").wind(3).ws(", i");
169  o.ws("\n").wind(3).ws(", len_exp");
170  o.ws("\n").wind(3).ws(", rule_exp");
171  o.ws("\n").wind(3).ws(", len_act");
172  o.ws("\n").wind(3).ws(", rule_act");
173  o.ws("\n").wind(3).ws(");");
174  o.ws("\n").wind(2).ws("return 1;");
175  o.ws("\n").wind(1).ws("}");
176  o.ws("\n}");
177  o.ws("\n");
178  o.ws("\nint lex_").wstring(name).ws("()");
179  o.ws("\n{");
180  o.ws("\n").wind(1).ws("const size_t padding = ").wu64(maxfill).ws("; /* YYMAXFILL */");
181  o.ws("\n").wind(1).ws("int status = 0;");
182  o.ws("\n").wind(1).ws("size_t input_len = 0;");
183  o.ws("\n").wind(1).ws("size_t keys_count = 0;");
184  o.ws("\n").wind(1).ws("YYCTYPE *input = NULL;");
185  o.ws("\n").wind(1).ws("YYKEYTYPE *keys = NULL;");
186  o.ws("\n").wind(1).ws("const YYCTYPE *cursor = NULL;");
187  o.ws("\n").wind(1).ws("const YYCTYPE *limit = NULL;");
188  o.ws("\n").wind(1).ws("const YYCTYPE *token = NULL;");
189  o.ws("\n").wind(1).ws("const YYCTYPE *eof = NULL;");
190  o.ws("\n").wind(1).ws("unsigned int i = 0;");
191  o.ws("\n");
192  o.ws("\n").wind(1).ws("input = (YYCTYPE *) read_file");
193  o.ws("\n").wind(2).ws("(\"").wstring(o.file_name).ws(".").wstring(name).ws(".input\"");
194  o.ws("\n").wind(2).ws(", sizeof (YYCTYPE)");
195  o.ws("\n").wind(2).ws(", padding");
196  o.ws("\n").wind(2).ws(", &input_len");
197  o.ws("\n").wind(2).ws(");");
198  o.ws("\n").wind(1).ws("if (input == NULL) {");
199  o.ws("\n").wind(2).ws("status = 1;");
200  o.ws("\n").wind(2).ws("goto end;");
201  o.ws("\n").wind(1).ws("}");
202  o.ws("\n");
203  if (sizeof_cunit > 1)
204  {
205  o.ws("\n").wind(1).ws("for (i = 0; i < input_len; ++i) {");
206  from_le(o, 2, sizeof_cunit, "input[i]");
207  o.ws("\n").wind(1).ws("}");
208  o.ws("\n");
209  }
210  o.ws("\n").wind(1).ws("keys = (YYKEYTYPE *) read_file");
211  o.ws("\n").wind(2).ws("(\"").wstring(o.file_name).ws(".").wstring(name).ws(".keys\"");
212  o.ws("\n").wind(2).ws(", 3 * sizeof (YYKEYTYPE)");
213  o.ws("\n").wind(2).ws(", 0");
214  o.ws("\n").wind(2).ws(", &keys_count");
215  o.ws("\n").wind(2).ws(");");
216  o.ws("\n").wind(1).ws("if (keys == NULL) {");
217  o.ws("\n").wind(2).ws("status = 1;");
218  o.ws("\n").wind(2).ws("goto end;");
219  o.ws("\n").wind(1).ws("}");
220  o.ws("\n");
221  if (sizeof_key > 1)
222  {
223  o.ws("\n").wind(1).ws("for (i = 0; i < 3 * keys_count; ++i) {");
224  from_le(o, 2, sizeof_key, "keys[i]");
225  o.ws("\n").wind(1).ws("}");
226  o.ws("\n");
227  }
228  o.ws("\n").wind(1).ws("cursor = input;");
229  o.ws("\n").wind(1).ws("limit = input + input_len + padding;");
230  o.ws("\n").wind(1).ws("eof = input + input_len;");
231  o.ws("\n");
232  o.ws("\n").wind(1).ws("for (i = 0; status == 0 && i < keys_count; ++i) {");
233  o.ws("\n").wind(2).ws("token = cursor;");
234  if (backup)
235  {
236  o.ws("\n").wind(2).ws("const YYCTYPE *marker = NULL;");
237  }
238  if (backupctx)
239  {
240  o.ws("\n").wind(2).ws("const YYCTYPE *ctxmarker = NULL;");
241  }
242  o.ws("\n").wind(2).ws("YYCTYPE yych;");
243  if (accept)
244  {
245  o.ws("\n").wind(2).ws("unsigned int yyaccept = 0;");
246  }
247  o.ws("\n");
248  if (opts->bFlag && BitMap::first)
249  {
250  BitMap::gen (o, 2, 0, std::min (0x100u, opts->encoding.nCodeUnits ()));
251  }
252  o.ws("\n");
253 }
254 
257  , bool backup
258  , bool backupctx
259  ) const
260 {
261  o.ws("\n").wind(1).ws("}");
262  o.ws("\n").wind(1).ws("if (status == 0) {");
263  o.ws("\n").wind(2).ws("if (cursor != eof) {");
264  o.ws("\n").wind(3).ws("status = 1;");
265  o.ws("\n").wind(3).ws("const long pos = token - input;");
266  o.ws("\n").wind(3).ws("fprintf(stderr, \"error: lex_").wstring(name).ws(": unused input strings left at position %ld\\n\", pos);");
267  o.ws("\n").wind(2).ws("}");
268  o.ws("\n").wind(2).ws("if (i != keys_count) {");
269  o.ws("\n").wind(3).ws("status = 1;");
270  o.ws("\n").wind(3).ws("fprintf(stderr, \"error: lex_").wstring(name).ws(": unused keys left after %u iterations\\n\", i);");
271  o.ws("\n").wind(2).ws("}");
272  o.ws("\n").wind(1).ws("}");
273  o.ws("\n");
274  o.ws("\nend:");
275  o.ws("\n").wind(1).ws("free(input);");
276  o.ws("\n").wind(1).ws("free(keys);");
277  o.ws("\n");
278  o.ws("\n").wind(1).ws("return status;");
279  o.ws("\n}");
280  o.ws("\n");
281  o.ws("\n#undef YYCTYPE");
282  o.ws("\n#undef YYKEYTYPE");
283  o.ws("\n#undef YYPEEK");
284  o.ws("\n#undef YYSKIP");
285  if (backup)
286  {
287  o.ws("\n#undef YYBACKUP");
288  o.ws("\n#undef YYRESTORE");
289  }
290  if (backupctx)
291  {
292  o.ws("\n#undef YYBACKUPCTX");
293  o.ws("\n#undef YYRESTORECTX");
294  }
295  o.ws("\n#undef YYLESSTHAN");
296  o.ws("\n#undef YYFILL");
297  o.ws("\n");
298 }
299 
300 void Skeleton::emit_epilog (OutputFile & o, const std::set<std::string> & names)
301 {
302  o.ws("\n").ws("int main()");
303  o.ws("\n").ws("{");
304 
305  for (std::set<std::string>::const_iterator i = names.begin (); i != names.end (); ++i)
306  {
307  o.ws("\n").wind(1).ws("if(lex_").wstring(*i).ws("() != 0) {");
308  o.ws("\n").wind(2).ws("return 1;");
309  o.ws("\n").wind(1).ws("}");
310  }
311 
312  o.ws("\n").wind(1).ws("return 0;");
313  o.ws("\n}");
314  o.ws("\n");
315 }
316 
317 void Skeleton::emit_action (OutputFile & o, uint32_t ind, rule_rank_t rank) const
318 {
319  o.wind(ind).ws("status = action_").wstring(name).ws("(i, keys, input, token, &cursor, ").wu32(rule2key (rank)).ws(");\n");
320  o.wind(ind).ws("continue;\n");
321 }
322 
323 } // namespace re2c
bool bFlag
Definition: opt.h:118
static void from_le(OutputFile &o, uint32_t ind, size_t size, const char *expr)
static key_t rule2key(rule_rank_t r)
Definition: skeleton.h:160
static void gen(OutputFile &, uint32_t ind, uint32_t, uint32_t)
Definition: bitmap.cc:75
OutputFile & ws(const char *s)
Definition: output.cc:173
OutputFile & wu32(uint32_t n)
Definition: output.cc:155
void emit_end(OutputFile &o, bool backup, bool backupctx) const
static void exact_uint(OutputFile &o, size_t width)
OutputFile & wind(uint32_t ind)
Definition: output.cc:191
void emit_start(OutputFile &o, size_t maxfill, bool backup, bool backupctx, bool accept) const
uint32_t szCodeUnit() const
Definition: enc.h:152
OutputFile & wu64(uint64_t n)
Definition: output.cc:161
Enc encoding
Definition: opt.h:118
static void emit_epilog(OutputFile &o, const std::set< std::string > &names)
uint32_t nCodeUnits() const
Definition: enc.h:123
Opt opts
Definition: opt.cc:7
const char * file_name
Definition: output.h:58
static BitMap * first
Definition: bitmap.h:19
void emit_action(OutputFile &o, uint32_t ind, rule_rank_t rank) const
static rule_rank_t none()
Definition: rule_rank.cc:23
static void emit_prolog(OutputFile &o)
Definition: bitmap.cc:10
const std::string name
Definition: skeleton.h:109
OutputFile & wstring(const std::string &s)
Definition: output.cc:167