src
output.cc
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <time.h>
3 #include <iomanip>
4 
5 #include "src/codegen/indent.h"
6 #include "src/codegen/output.h"
7 #include "src/codegen/print.h"
8 #include "src/conf/opt.h"
9 #include "src/conf/warn.h"
10 #include "src/globals.h"
11 #include "src/ir/rule_rank.h"
12 
13 namespace re2c
14 {
15 
17  : type (t)
18  , stream ()
19  , indent (i)
20 {}
21 
23 {
24  uint32_t lines = 0;
25  const std::string content = stream.str ();
26  const char * p = content.c_str ();
27  for (uint32_t i = 0; i < content.size (); ++i)
28  {
29  if (p[i] == '\n')
30  {
31  ++lines;
32  }
33  }
34  return lines;
35 }
36 
38  : fragments ()
39  , used_yyaccept (false)
40  , force_start_label (false)
41  , user_start_label ()
42  , line (0)
43 {
44  fragments.push_back (new OutputFragment (OutputFragment::CODE, 0));
45 }
46 
48 {
49  for (unsigned int i = 0; i < fragments.size (); ++i)
50  {
51  delete fragments[i];
52  }
53 }
54 
55 OutputFile::OutputFile (const char * fn)
56  : file_name (fn)
57  , file (NULL)
58  , blocks ()
59  , label_counter ()
60  , warn_condition_order (!opts->tFlag) // see note [condition order]
61 {
62  new_block ();
63 }
64 
66 {
67  if (file_name == NULL)
68  {
69  file_name = "<stdout>";
70  file = stdout;
71  }
72  else
73  {
74  file = fopen (file_name, "wb");
75  }
76  return file != NULL;
77 }
78 
80 {
81  if (file != NULL && file != stdout)
82  {
83  fclose (file);
84  }
85  for (unsigned int i = 0; i < blocks.size (); ++i)
86  {
87  delete blocks[i];
88  }
89 }
90 
91 std::ostream & OutputFile::stream ()
92 {
93  return blocks.back ()->fragments.back ()->stream;
94 }
95 
96 OutputFile & OutputFile::wraw (const char * s, size_t n)
97 {
98  stream ().write (s, static_cast<std::streamsize> (n));
99  return *this;
100 }
101 
103 {
104  prtHex (stream (), n);
105  return *this;
106 }
107 
109 {
110  prtChOrHex (stream (), n);
111  return *this;
112 }
113 
114 OutputFile & OutputFile::wrange (uint32_t l, uint32_t u)
115 {
116  printSpan (stream (), l, u);
117  return *this;
118 }
119 
120 OutputFile & OutputFile::wu32_width (uint32_t n, int w)
121 {
122  stream () << std::setw (w);
123  stream () << n;
124  return *this;
125 }
126 
127 OutputFile & OutputFile::wline_info (uint32_t l, const char * fn)
128 {
129  output_line_info (stream (), l, fn);
130  return *this;
131 }
132 
134 {
135  output_version_time (stream ());
136  return *this;
137 }
138 
140 {
141  const std::string label = blocks.back ()->user_start_label;
142  if (!label.empty ())
143  {
144  wstring(label).ws(":\n");
145  }
146  return *this;
147 }
148 
150 {
151  stream () << c;
152  return *this;
153 }
154 
156 {
157  stream () << n;
158  return *this;
159 }
160 
162 {
163  stream () << n;
164  return *this;
165 }
166 
167 OutputFile & OutputFile::wstring (const std::string & s)
168 {
169  stream () << s;
170  return *this;
171 }
172 
173 OutputFile & OutputFile::ws (const char * s)
174 {
175  stream () << s;
176  return *this;
177 }
178 
180 {
181  stream () << l;
182  return *this;
183 }
184 
186 {
187  stream () << r;
188  return *this;
189 }
190 
191 OutputFile & OutputFile::wind (uint32_t ind)
192 {
193  stream () << indent(ind);
194  return *this;
195 }
196 
197 void OutputFile::insert_code ()
198 {
199  blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::CODE, 0));
200 }
201 
203 {
204  blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::LINE_INFO, 0));
205  insert_code ();
206  return *this;
207 }
208 
210 {
211  if (opts->fFlag && !bWroteGetState)
212  {
213  blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::STATE_GOTO, ind));
214  insert_code ();
215  bWroteGetState = true;
216  }
217  return *this;
218 }
219 
221 {
222  warn_condition_order = false; // see note [condition order]
223  blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::TYPES, 0));
224  insert_code ();
225  return *this;
226 }
227 
229 {
230  blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::WARN_CONDITION_ORDER, 0));
231  insert_code ();
232  return *this;
233 }
234 
236 {
237  blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::YYACCEPT_INIT, ind));
238  insert_code ();
239  return *this;
240 }
241 
243 {
244  blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::YYMAXFILL, 0));
245  insert_code ();
246  return *this;
247 }
248 
250 {
251  blocks.back ()->used_yyaccept = true;
252 }
253 
255 {
256  return blocks.back ()->used_yyaccept;
257 }
258 
260 {
261  blocks.back ()->force_start_label = force;
262 }
263 
264 void OutputFile::set_user_start_label (const std::string & label)
265 {
266  blocks.back ()->user_start_label = label;
267 }
268 
270 {
271  return blocks.back ()->force_start_label;
272 }
273 
274 void OutputFile::set_block_line (uint32_t l)
275 {
276  blocks.back ()->line = l;
277 }
278 
279 uint32_t OutputFile::get_block_line () const
280 {
281  return blocks.back ()->line;
282 }
283 
285 {
286  blocks.push_back (new OutputBlock ());
287  insert_code ();
288 }
289 
290 void OutputFile::emit
291  ( const std::vector<std::string> & types
292  , size_t max_fill
293  )
294 {
295  if (file != NULL)
296  {
297  unsigned int line_count = 1;
298  for (unsigned int j = 0; j < blocks.size (); ++j)
299  {
300  OutputBlock & b = * blocks[j];
301  for (unsigned int i = 0; i < b.fragments.size (); ++i)
302  {
303  OutputFragment & f = * b.fragments[i];
304  switch (f.type)
305  {
307  break;
309  output_line_info (f.stream, line_count + 1, file_name);
310  break;
312  output_state_goto (f.stream, f.indent, 0);
313  break;
315  output_types (f.stream, f.indent, types);
316  break;
318  if (warn_condition_order) // see note [condition order]
319  {
321  }
322  break;
325  break;
327  output_yymaxfill (f.stream, max_fill);
328  break;
329  }
330  std::string content = f.stream.str ();
331  fwrite (content.c_str (), 1, content.size (), file);
332  line_count += f.count_lines ();
333  }
334  }
335  }
336 }
337 
338 HeaderFile::HeaderFile (const char * fn)
339  : stream ()
340  // header is always generated, but not always dumped to file
341  // NULL filename crashes 'operator <<' on some platforms
342  // TODO: generate header only if necessary
343  , file_name (fn ? fn : "<stdout>.h")
344  , file (NULL)
345 {}
346 
348 {
349  file = fopen (file_name, "wb");
350  return file != NULL;
351 }
352 
353 void HeaderFile::emit (const std::vector<std::string> & types)
354 {
355  output_version_time (stream);
356  output_line_info (stream, 3, file_name);
357  stream << "\n";
358  output_types (stream, 0, types);
359 }
360 
362 {
363  if (file != NULL)
364  {
365  std::string content = stream.str ();
366  fwrite (content.c_str (), 1, content.size (), file);
367  fclose (file);
368  }
369 }
370 
371 Output::Output (const char * source_name, const char * header_name)
372  : source (source_name)
373  , header (header_name)
374  , types ()
375  , skeletons ()
376  , max_fill (1)
377 {}
378 
380 {
381  if (!warn.error ())
382  {
383  source.emit (types, max_fill);
384  header.emit (types);
385  }
386 }
387 
388 void output_state_goto (std::ostream & o, uint32_t ind, uint32_t start_label)
389 {
390  o << indent(ind) << "switch (" << output_get_state() << ") {\n";
391  if (opts->bUseStateAbort)
392  {
393  o << indent(ind) << "default: abort();\n";
394  o << indent(ind) << "case -1: goto " << opts->labelPrefix << start_label << ";\n";
395  }
396  else
397  {
398  o << indent(ind) << "default: goto " << opts->labelPrefix << start_label << ";\n";
399  }
400  for (uint32_t i = 0; i < last_fill_index; ++i)
401  {
402  o << indent(ind) << "case " << i << ": goto " << opts->yyfilllabel << i << ";\n";
403  }
404  o << indent(ind) << "}\n";
405  if (opts->bUseStateNext)
406  {
407  o << opts->yynext << ":\n";
408  }
409 }
410 
411 void output_yyaccept_init (std::ostream & o, uint32_t ind, bool used_yyaccept)
412 {
413  if (used_yyaccept)
414  {
415  o << indent (ind) << "unsigned int " << opts->yyaccept << " = 0;\n";
416  }
417 }
418 
419 void output_yymaxfill (std::ostream & o, size_t max_fill)
420 {
421  o << "#define YYMAXFILL " << max_fill << "\n";
422 }
423 
424 void output_line_info (std::ostream & o, uint32_t line_number, const char * file_name)
425 {
426  if (!opts->iFlag)
427  {
428  o << "#line " << line_number << " \"" << file_name << "\"\n";
429  }
430 }
431 
432 void output_types (std::ostream & o, uint32_t ind, const std::vector<std::string> & types)
433 {
434  o << indent (ind++) << "enum " << opts->yycondtype << " {\n";
435  for (unsigned int i = 0; i < types.size (); ++i)
436  {
437  o << indent (ind) << opts->condEnumPrefix << types[i] << ",\n";
438  }
439  o << indent (--ind) << "};\n";
440 }
441 
442 void output_version_time (std::ostream & o)
443 {
444  o << "/* Generated by re2c";
445  if (opts->version)
446  {
447  o << " " << PACKAGE_VERSION;
448  }
449  if (!opts->bNoGenerationDate)
450  {
451  o << " on ";
452  time_t now = time (NULL);
453  o.write (ctime (&now), 24);
454  }
455  o << " */" << "\n";
456 }
457 
458 std::string output_get_state ()
459 {
460  return opts->state_get_naked
461  ? opts->state_get
462  : opts->state_get + "()";
463 }
464 
465 } // namespace re2c
OutputFile & wdelay_warn_condition_order()
Definition: output.cc:228
HeaderFile(const char *fn)
Definition: output.cc:338
bool bWroteGetState
Definition: main.cc:17
void output_line_info(std::ostream &o, uint32_t line_number, const char *file_name)
Definition: output.cc:424
OutputFragment(type_t t, uint32_t i)
Definition: output.cc:16
bool version
Definition: opt.h:118
Warn warn
Definition: warn.cc:11
bool get_used_yyaccept() const
Definition: output.cc:254
void new_block()
Definition: output.cc:284
uint32_t indent
Definition: output.h:37
OutputFile & wuser_start_label()
Definition: output.cc:139
std::string yycondtype
Definition: opt.h:118
std::ostringstream stream
Definition: output.h:36
std::string indent(uint32_t ind)
Definition: indent.h:11
bool state_get_naked
Definition: opt.h:118
OutputFile & wversion_time()
Definition: output.cc:133
void printSpan(std::ostream &o, uint32_t lb, uint32_t ub)
Definition: print.cc:139
OutputFile & ws(const char *s)
Definition: output.cc:173
OutputFile & wu32(uint32_t n)
Definition: output.cc:155
void set_used_yyaccept()
Definition: output.cc:249
OutputFile & wdelay_state_goto(uint32_t ind)
Definition: output.cc:209
OutputFile & wdelay_yymaxfill()
Definition: output.cc:242
OutputFile & wind(uint32_t ind)
Definition: output.cc:191
OutputFile & wlabel(label_t l)
Definition: output.cc:179
OutputFile source
Definition: output.h:136
void output_state_goto(std::ostream &o, uint32_t ind, uint32_t start_label)
Definition: output.cc:388
bool bUseStateNext
Definition: opt.h:118
OutputFile & wdelay_types()
Definition: output.cc:220
std::string yynext
Definition: opt.h:118
OutputFile & wc(char c)
Definition: output.cc:149
HeaderFile header
Definition: output.h:137
OutputFile & wc_hex(uint32_t n)
Definition: output.cc:108
OutputFile & wrange(uint32_t u, uint32_t l)
Definition: output.cc:114
std::string condEnumPrefix
Definition: opt.h:118
bool bUseStateAbort
Definition: opt.h:118
bool iFlag
Definition: opt.h:118
OutputFile & wdelay_line_info()
Definition: output.cc:202
bool bNoGenerationDate
Definition: opt.h:118
void output_types(std::ostream &o, uint32_t ind, const std::vector< std::string > &types)
Definition: output.cc:432
OutputFile & wu64(uint64_t n)
Definition: output.cc:161
void emit(const std::vector< std::string > &types, size_t max_fill)
Definition: output.cc:291
std::string yyaccept
Definition: opt.h:118
OutputFile(const char *fn)
Definition: output.cc:55
std::string labelPrefix
Definition: opt.h:118
std::string output_get_state()
Definition: output.cc:458
Output(const char *source_name, const char *header_name)
Definition: output.cc:371
void emit(const std::vector< std::string > &types)
Definition: output.cc:353
bool fFlag
Definition: opt.h:118
bool warn_condition_order
Definition: output.h:66
bool open()
Definition: output.cc:65
Opt opts
Definition: opt.cc:7
void set_block_line(uint32_t l)
Definition: output.cc:274
OutputFile & wdelay_yyaccept_init(uint32_t ind)
Definition: output.cc:235
const char * file_name
Definition: output.h:58
uint32_t count_lines()
Definition: output.cc:22
uint32_t last_fill_index
Definition: main.cc:19
bool used_yyaccept
Definition: output.h:46
void output_version_time(std::ostream &o)
Definition: output.cc:442
std::string state_get
Definition: opt.h:118
void prtChOrHex(std::ostream &o, uint32_t c)
Definition: print.cc:38
OutputFile & wu32_hex(uint32_t n)
Definition: output.cc:102
std::string yyfilllabel
Definition: opt.h:118
bool get_force_start_label() const
Definition: output.cc:269
OutputFile & wraw(const char *s, size_t n)
Definition: output.cc:96
void condition_order(uint32_t line)
Definition: warn.cc:86
std::vector< OutputFragment * > fragments
Definition: output.h:45
void output_yymaxfill(std::ostream &o, size_t max_fill)
Definition: output.cc:419
uint32_t get_block_line() const
Definition: output.cc:279
OutputFile & wrank(rule_rank_t l)
Definition: output.cc:185
OutputFile & wu32_width(uint32_t n, int w)
Definition: output.cc:120
void set_user_start_label(const std::string &label)
Definition: output.cc:264
bool error() const
Definition: warn.cc:34
Definition: bitmap.cc:10
void output_yyaccept_init(std::ostream &o, uint32_t ind, bool used_yyaccept)
Definition: output.cc:411
uint32_t line
Definition: output.h:49
OutputFile & wline_info(uint32_t l, const char *fn)
Definition: output.cc:127
OutputFile & wstring(const std::string &s)
Definition: output.cc:167
void set_force_start_label(bool force)
Definition: output.cc:259
void prtHex(std::ostream &o, uint32_t c)
Definition: print.cc:53