cp/guest: clean up guest_create's console handling
[hvf.git] / build / re2c / code.cc
blob7ff84a00955801c3c54104f8e12bad5d93cdc019
1 /* $Id: code.cc 861 2008-05-25 13:23:02Z helly $ */
2 #include <stdarg.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <iomanip>
7 #include <iostream>
8 #include <sstream>
9 #include <time.h>
10 #include "substr.h"
11 #include "globals.h"
12 #include "dfa.h"
13 #include "parser.h"
14 #include "code.h"
16 namespace re2c
19 // there must be at least one span in list; all spans must cover
20 // same range
22 static std::string indent(uint ind)
24 std::string str;
26 while (!DFlag && ind-- > 0)
28 str += indString;
30 return str;
33 template<typename _Ty>
34 std::string replaceParam(std::string str, const std::string& param, const _Ty& value)
36 std::ostringstream strValue;
38 strValue << value;
40 std::string::size_type pos;
42 while((pos = str.find(param)) != std::string::npos)
44 str.replace(pos, param.length(), strValue.str());
47 return str;
50 static void genYYFill(std::ostream &o, uint, uint need)
52 if (bUseYYFillParam)
54 o << mapCodeName["YYFILL"];
55 if (!bUseYYFillNaked)
57 o << "(" << need << ");";
59 o << "\n";
61 else
63 o << replaceParam(mapCodeName["YYFILL"], yyFillLength, need);
64 if (!bUseYYFillNaked)
66 o << ";";
68 o << "\n";
72 static std::string genGetState()
74 if (bUseYYGetStateNaked)
76 return mapCodeName["YYGETSTATE"];
78 else
80 return mapCodeName["YYGETSTATE"] + "()";
84 static std::string genGetCondition()
86 if (bUseYYGetConditionNaked)
88 return mapCodeName["YYGETCONDITION"];
90 else
92 return mapCodeName["YYGETCONDITION"] + "()";
96 static void genSetCondition(std::ostream& o, uint ind, const std::string& newcond)
98 if (bUseYYSetConditionParam)
100 o << indent(ind) << mapCodeName["YYSETCONDITION"] << "(" << condEnumPrefix << newcond << ");\n";
102 else
104 o << indent(ind) << replaceParam(mapCodeName["YYSETCONDITION"], yySetConditionParam, condEnumPrefix + newcond) << "\n";
108 static std::string space(uint this_label)
110 int nl = next_label > 999999 ? 6 : next_label > 99999 ? 5 : next_label > 9999 ? 4 : next_label > 999 ? 3 : next_label > 99 ? 2 : next_label > 9 ? 1 : 0;
111 int tl = this_label > 999999 ? 6 : this_label > 99999 ? 5 : this_label > 9999 ? 4 : this_label > 999 ? 3 : this_label > 99 ? 2 : this_label > 9 ? 1 : 0;
113 return std::string(std::max(1, nl - tl + 1), ' ');
116 void Go::compact()
118 // arrange so that adjacent spans have different targets
119 uint i = 0;
121 for (uint j = 1; j < nSpans; ++j)
123 if (span[j].to != span[i].to)
125 ++i;
126 span[i].to = span[j].to;
129 span[i].ub = span[j].ub;
132 nSpans = i + 1;
135 void Go::unmap(Go *base, const State *x)
137 Span *s = span, *b = base->span, *e = &b[base->nSpans];
138 uint lb = 0;
139 s->ub = 0;
140 s->to = NULL;
142 for (; b != e; ++b)
144 if (b->to == x)
146 if ((s->ub - lb) > 1)
148 s->ub = b->ub;
151 else
153 if (b->to != s->to)
155 if (s->ub)
157 lb = s->ub;
158 ++s;
161 s->to = b->to;
164 s->ub = b->ub;
168 s->ub = e[ -1].ub;
169 ++s;
170 nSpans = s - span;
173 void doGen(const Go *g, const State *s, uint *bm, uint f, uint m)
175 Span *b = g->span, *e = &b[g->nSpans];
176 uint lb = 0;
178 for (; b < e; ++b)
180 if (b->to == s)
182 for (; lb < b->ub && lb < 256; ++lb)
184 bm[lb-f] |= m;
188 lb = b->ub;
192 void prt(std::ostream& o, const Go *g, const State *s)
194 Span *b = g->span, *e = &b[g->nSpans];
195 uint lb = 0;
197 for (; b < e; ++b)
199 if (b->to == s)
201 printSpan(o, lb, b->ub);
204 lb = b->ub;
208 bool matches(const Go *g1, const State *s1, const Go *g2, const State *s2)
210 Span *b1 = g1->span, *e1 = &b1[g1->nSpans];
211 uint lb1 = 0;
212 Span *b2 = g2->span, *e2 = &b2[g2->nSpans];
213 uint lb2 = 0;
215 for (;;)
217 for (; b1 < e1 && b1->to != s1; ++b1)
219 lb1 = b1->ub;
222 for (; b2 < e2 && b2->to != s2; ++b2)
224 lb2 = b2->ub;
227 if (b1 == e1)
229 return b2 == e2;
232 if (b2 == e2)
234 return false;
237 if (lb1 != lb2 || b1->ub != b2->ub)
239 return false;
242 ++b1;
243 ++b2;
247 BitMap *BitMap::first = NULL;
249 BitMap::BitMap(const Go *g, const State *x)
250 : go(g)
251 , on(x)
252 , next(first)
253 , i(0)
254 , m(0)
256 first = this;
259 BitMap::~BitMap()
261 delete next;
264 const BitMap *BitMap::find(const Go *g, const State *x)
266 for (const BitMap *b = first; b; b = b->next)
268 if (matches(b->go, b->on, g, x))
270 return b;
274 return new BitMap(g, x);
277 const BitMap *BitMap::find(const State *x)
279 for (const BitMap *b = first; b; b = b->next)
281 if (b->on == x)
283 return b;
287 return NULL;
290 void BitMap::gen(std::ostream &o, uint ind, uint lb, uint ub)
292 if (first && bLastPass && bUsedYYBitmap)
294 o << indent(ind) << "static const unsigned char " << mapCodeName["yybm"] << "[] = {";
296 uint c = 1, n = ub - lb;
297 const BitMap *cb = first;
299 while((cb = cb->next) != NULL) {
300 ++c;
302 BitMap *b = first;
304 uint *bm = new uint[n];
306 for (uint i = 0, t = 1; b; i += n, t += 8)
308 memset(bm, 0, n * sizeof(uint));
310 for (uint m = 0x80; b && m; m >>= 1)
312 b->i = i;
313 b->m = m;
314 doGen(b->go, b->on, bm, lb, m);
315 b = const_cast<BitMap*>(b->next);
318 if (c > 8)
320 o << "\n" << indent(ind+1) << "/* table " << t << " .. " << std::min(c, t+7) << ": " << i << " */";
323 for (uint j = 0; j < n; ++j)
325 if (j % 8 == 0)
327 o << "\n" << indent(ind+1);
330 if (yybmHexTable)
332 prtHex(o, bm[j], false);
334 else
336 o << std::setw(3) << (uint)bm[j];
338 o << ", ";
342 o << "\n" << indent(ind) << "};\n";
343 /* stats(); */
345 delete[] bm;
349 void BitMap::stats()
351 uint n = 0;
353 for (const BitMap *b = first; b; b = b->next)
355 prt(std::cerr, b->go, b->on);
356 std::cerr << std::endl;
357 ++n;
360 std::cerr << n << " bitmaps\n";
361 first = NULL;
364 void genGoTo(std::ostream &o, uint ind, const State *from, const State *to, bool & readCh)
366 if (DFlag)
368 o << from->label << " -> " << to->label << "\n";
369 return;
372 if (readCh && from->label + 1 != to->label)
374 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
375 readCh = false;
378 o << indent(ind) << "goto " << labelPrefix << to->label << ";\n";
379 vUsedLabels.insert(to->label);
382 void genIf(std::ostream &o, uint ind, const char *cmp, uint v, bool &readCh)
384 o << indent(ind) << "if (";
385 if (readCh)
387 o << "(" << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ")";
388 readCh = false;
390 else
392 o << mapCodeName["yych"];
395 o << " " << cmp << " ";
396 prtChOrHex(o, v);
397 o << ") ";
400 static void need(std::ostream &o, uint ind, uint n, bool & readCh, bool bSetMarker)
402 if (DFlag)
404 return;
407 uint fillIndex = next_fill_index;
409 if (fFlag)
411 next_fill_index++;
412 if (bUseYYSetStateParam)
414 o << indent(ind) << mapCodeName["YYSETSTATE"] << "(" << fillIndex << ");\n";
416 else
418 o << indent(ind) << replaceParam(mapCodeName["YYSETSTATE"], yySetStateParam, fillIndex) << "\n";
422 if (bUseYYFill && n > 0)
424 o << indent(ind);
425 if (n == 1)
427 if (bUseYYFillCheck)
429 o << "if (" << mapCodeName["YYLIMIT"] << " <= " << mapCodeName["YYCURSOR"] << ") ";
431 genYYFill(o, ind, n);
433 else
435 if (bUseYYFillCheck)
437 o << "if ((" << mapCodeName["YYLIMIT"] << " - " << mapCodeName["YYCURSOR"] << ") < " << n << ") ";
439 genYYFill(o, ind, n);
443 if (fFlag)
445 o << mapCodeName["yyFillLabel"] << fillIndex << ":\n";
448 if (n > 0)
450 if (bSetMarker)
452 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*(" << mapCodeName["YYMARKER"] << " = " << mapCodeName["YYCURSOR"] << ");\n";
454 else
456 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
458 readCh = false;
462 void Match::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
464 if (DFlag)
466 return;
469 if (state->link)
471 o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
473 else if (!readAhead())
475 /* do not read next char if match */
476 o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
477 readCh = true;
479 else
481 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
482 readCh = false;
485 if (state->link)
487 need(o, ind, state->depth, readCh, false);
491 void Enter::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
493 if (state->link)
495 o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
496 if (vUsedLabels.count(label))
498 o << labelPrefix << label << ":\n";
500 need(o, ind, state->depth, readCh, false);
502 else
504 /* we shouldn't need 'rule-following' protection here */
505 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
506 if (vUsedLabels.count(label))
508 o << labelPrefix << label << ":\n";
510 readCh = false;
514 void Initial::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
516 if (!cFlag && !startLabelName.empty())
518 o << startLabelName << ":\n";
521 if (vUsedLabels.count(1))
523 if (state->link)
525 o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
527 else
529 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
533 if (!cFlag && vUsedLabels.count(label))
535 o << labelPrefix << label << ":\n";
537 else if (!label)
539 o << "\n";
542 if (dFlag)
544 o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", *" << mapCodeName["YYCURSOR"] << ");\n";
547 if (state->link)
549 need(o, ind, state->depth, readCh, setMarker && bUsedYYMarker);
551 else
553 if (setMarker && bUsedYYMarker)
555 o << indent(ind) << mapCodeName["YYMARKER"] << " = " << mapCodeName["YYCURSOR"] << ";\n";
557 readCh = false;
561 void Save::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
563 if (DFlag)
565 return;
568 if (bUsedYYAccept)
570 o << indent(ind) << mapCodeName["yyaccept"] << " = " << selector << ";\n";
573 if (state->link)
575 if (bUsedYYMarker)
577 o << indent(ind) << mapCodeName["YYMARKER"] << " = ++" << mapCodeName["YYCURSOR"] << ";\n";
579 need(o, ind, state->depth, readCh, false);
581 else
583 if (bUsedYYMarker)
585 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*(" << mapCodeName["YYMARKER"] << " = ++" << mapCodeName["YYCURSOR"] << ");\n";
587 else
589 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
591 readCh = false;
595 Move::Move(State *s) : Action(s)
600 void Move::emit(std::ostream &, uint, bool &, const std::string&) const
605 Accept::Accept(State *x, uint n, uint *s, State **r)
606 : Action(x), nRules(n), saves(s), rules(r)
611 void Accept::genRuleMap()
613 for (uint i = 0; i < nRules; ++i)
615 if (saves[i] != ~0u)
617 mapRules[saves[i]] = rules[i];
622 void Accept::emitBinary(std::ostream &o, uint ind, uint l, uint r, bool &readCh) const
624 if (l < r)
626 uint m = (l + r) >> 1;
628 assert(bUsedYYAccept);
629 o << indent(ind) << "if (" << mapCodeName["yyaccept"] << " <= " << m << ") {\n";
630 emitBinary(o, ++ind, l, m, readCh);
631 o << indent(--ind) << "} else {\n";
632 emitBinary(o, ++ind, m + 1, r, readCh);
633 o << indent(--ind) << "}\n";
635 else
637 genGoTo(o, ind, state, mapRules.find(l)->second, readCh);
641 void Accept::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
643 if (mapRules.size() > 0)
645 bUsedYYMarker = true;
646 if (!DFlag)
648 o << indent(ind) << mapCodeName["YYCURSOR"] << " = " << mapCodeName["YYMARKER"] << ";\n";
651 if (readCh) // shouldn't be necessary, but might become at some point
653 o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
654 readCh = false;
657 if (mapRules.size() > 1)
659 bUsedYYAccept = true;
661 if (gFlag && mapRules.size() >= cGotoThreshold)
663 o << indent(ind++) << "{\n";
664 o << indent(ind++) << "static void *" << mapCodeName["yytarget"] << "[" << mapRules.size() << "] = {\n";
665 for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it)
667 o << indent(ind) << "&&" << labelPrefix << it->second->label << ",\n";
668 vUsedLabels.insert(it->second->label);
670 o << indent(--ind) << "};\n";
671 o << indent(ind) << "goto *" << mapCodeName["yytarget"] << "[" << mapCodeName["yyaccept"] << "];\n";
672 o << indent(--ind) << "}\n";
674 else if (sFlag)
676 emitBinary(o, ind, 0, mapRules.size() - 1, readCh);
678 else if (DFlag)
680 for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it)
682 o << state->label << " -> " << it->second->label;
683 o << " [label=\"yyaccept=" << it->first << "\"]\n";
686 else
688 o << indent(ind) << "switch (" << mapCodeName["yyaccept"] << ") {\n";
690 for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it)
692 o << indent(ind) << "case " << it->first << ": \t";
693 genGoTo(o, 0, state, it->second, readCh);
696 o << indent(ind) << "}\n";
699 else
701 // no need to write if statement here since there is only case 0.
702 genGoTo(o, ind, state, mapRules.find(0)->second, readCh);
707 Rule::Rule(State *s, RuleOp *r) : Action(s), rule(r)
712 void Rule::emit(std::ostream &o, uint ind, bool &, const std::string& condName) const
714 if (DFlag)
716 o << state->label << " [label=\"" << sourceFileInfo.fname << ":" << rule->code->line << "\"];\n";
717 return;
720 uint back = rule->ctx->fixedLength();
722 if (back != 0u)
724 o << indent(ind) << mapCodeName["YYCURSOR"] << " = " << mapCodeName["YYCTXMARKER"] << ";\n";
727 if (rule->code->newcond.length() && condName != rule->code->newcond)
729 genSetCondition(o, ind, rule->code->newcond);
732 RuleLine rl(*rule);
734 if (!yySetupRule.empty() && !rule->code->autogen)
736 o << indent(ind) << yySetupRule << "\n";
739 o << file_info(rule->code->source, &rl);
740 o << indent(ind);
741 if (rule->code->autogen)
743 o << replaceParam(condGoto, condGotoParam, condPrefix + rule->code->newcond);
745 else
747 o << rule->code->text;
749 o << "\n";
750 o << outputFileInfo;
753 void doLinear(std::ostream &o, uint ind, Span *s, uint n, const State *from, const State *next, bool &readCh, uint mask)
755 for (;;)
757 State *bg = s[0].to;
759 while (n >= 3 && s[2].to == bg && (s[1].ub - s[0].ub) == 1)
761 if (s[1].to == next && n == 3)
763 if (!mask || (s[0].ub > 0x00FF))
765 genIf(o, ind, "!=", s[0].ub, readCh);
766 genGoTo(o, 0, from, bg, readCh);
768 if (next->label != from->label + 1 || DFlag)
770 genGoTo(o, ind, from, next, readCh);
772 return ;
774 else
776 if (!mask || (s[0].ub > 0x00FF))
778 genIf(o, ind, "==", s[0].ub, readCh);
779 genGoTo(o, 0, from, s[1].to, readCh);
783 n -= 2;
784 s += 2;
787 if (n == 1)
789 // if(bg != next){
790 if (s[0].to->label != from->label + 1 || DFlag)
792 genGoTo(o, ind, from, s[0].to, readCh);
794 // }
795 return ;
797 else if (n == 2 && bg == next)
799 if (!mask || (s[0].ub > 0x00FF))
801 genIf(o, ind, ">=", s[0].ub, readCh);
802 genGoTo(o, 0, from, s[1].to, readCh);
804 if (next->label != from->label + 1 || DFlag)
806 genGoTo(o, ind, from, next, readCh);
808 return ;
810 else
812 if (!mask || ((s[0].ub - 1) > 0x00FF))
814 genIf(o, ind, "<=", s[0].ub - 1, readCh);
815 genGoTo(o, 0, from, bg, readCh);
817 n -= 1;
818 s += 1;
822 if (next->label != from->label + 1 || DFlag)
824 genGoTo(o, ind, from, next, readCh);
828 void Go::genLinear(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
830 doLinear(o, ind, span, nSpans, from, next, readCh, mask);
833 bool genCases(std::ostream &o, uint ind, uint lb, Span *s, bool &newLine, uint mask, const State *from, const State *to)
835 bool used = false;
837 if (!newLine)
839 o << "\n";
841 newLine = true;
842 if (lb < s->ub)
844 for (;;)
846 if (!mask || lb > 0x00FF)
848 if (DFlag)
850 o << from->label << " -> " << to->label;
851 o << " [label=";
852 prtChOrHex(o, lb);
853 o << "]";
855 else
857 o << indent(ind) << "case ";
858 prtChOrHex(o, lb);
859 o << ":";
861 newLine = false;
862 used = true;
865 if (++lb == s->ub)
867 break;
870 o << "\n";
871 newLine = true;
874 return used;
877 void Go::genSwitch(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
879 bool newLine = true;
881 if ((mask ? wSpans : nSpans) <= 2)
883 genLinear(o, ind, from, next, readCh, mask);
885 else
887 State *def = span[nSpans - 1].to;
888 Span **sP = new Span * [nSpans - 1], **r, **s, **t;
890 t = &sP[0];
892 for (uint i = 0; i < nSpans; ++i)
894 if (span[i].to != def)
896 *(t++) = &span[i];
900 if (!DFlag)
902 if (dFlag)
904 o << indent(ind) << mapCodeName["YYDEBUG"] << "(-1, " << mapCodeName["yych"] << ");\n";
907 if (readCh)
909 o << indent(ind) << "switch ((" << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ")) {\n";
910 readCh = false;
912 else
914 o << indent(ind) << "switch (" << mapCodeName["yych"] << ") {\n";
918 while (t != &sP[0])
920 bool used = false;
922 r = s = &sP[0];
924 const State *to = (*s)->to;
926 if (*s == &span[0])
928 used |= genCases(o, ind, 0, *s, newLine, mask, from, to);
930 else
932 used |= genCases(o, ind, (*s)[ -1].ub, *s, newLine, mask, from, to);
935 while (++s < t)
937 if ((*s)->to == to)
939 used |= genCases(o, ind, (*s)[ -1].ub, *s, newLine, mask, from, to);
941 else
943 *(r++) = *s;
947 if (used && !DFlag)
949 genGoTo(o, newLine ? ind+1 : 1, from, to, readCh);
950 newLine = true;
952 t = r;
955 if (DFlag)
957 o << "\n" << from->label << " -> " << def->label;
958 o << " [label=default]\n" ;
960 else
962 o << indent(ind) << "default:";
963 genGoTo(o, 1, from, def, readCh);
964 o << indent(ind) << "}\n";
967 delete [] sP;
971 void doBinary(std::ostream &o, uint ind, Span *s, uint n, const State *from, const State *next, bool &readCh, uint mask)
973 if (n <= 4)
975 doLinear(o, ind, s, n, from, next, readCh, mask);
977 else
979 uint h = n / 2;
981 genIf(o, ind, "<=", s[h - 1].ub - 1, readCh);
982 o << "{\n";
983 doBinary(o, ind+1, &s[0], h, from, next, readCh, mask);
984 o << indent(ind) << "} else {\n";
985 doBinary(o, ind+1, &s[h], n - h, from, next, readCh, mask);
986 o << indent(ind) << "}\n";
990 void Go::genBinary(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
992 if (mask)
994 Span * sc = new Span[wSpans];
996 for (uint i = 0, j = 0; i < nSpans; i++)
998 if (span[i].ub > 0xFF)
1000 sc[j++] = span[i];
1004 doBinary(o, ind, sc, wSpans, from, next, readCh, mask);
1006 delete[] sc;
1008 else
1010 doBinary(o, ind, span, nSpans, from, next, readCh, mask);
1014 void Go::genBase(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
1016 if ((mask ? wSpans : nSpans) == 0)
1018 return ;
1021 if (!sFlag)
1023 genSwitch(o, ind, from, next, readCh, mask);
1024 return ;
1027 if ((mask ? wSpans : nSpans) > 8)
1029 Span *bot = &span[0], *top = &span[nSpans - 1];
1030 uint util;
1032 if (bot[0].to == top[0].to)
1034 util = (top[ -1].ub - bot[0].ub) / (nSpans - 2);
1036 else
1038 if (bot[0].ub > (top[0].ub - top[ -1].ub))
1040 util = (top[0].ub - bot[0].ub) / (nSpans - 1);
1042 else
1044 util = top[ -1].ub / (nSpans - 1);
1048 if (util <= 2)
1050 genSwitch(o, ind, from, next, readCh, mask);
1051 return ;
1055 if ((mask ? wSpans : nSpans) > 5)
1057 genBinary(o, ind, from, next, readCh, mask);
1059 else
1061 genLinear(o, ind, from, next, readCh, mask);
1065 void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh) const
1067 std::string sYych;
1069 if (readCh)
1071 sYych = "(" + mapCodeName["yych"] + " = " + yychConversion + "*" + mapCodeName["YYCURSOR"] + ")";
1073 else
1075 sYych = mapCodeName["yych"];
1078 readCh = false;
1079 if (wFlag)
1081 o << indent(ind) << "if (" << sYych <<" & ~0xFF) {\n";
1082 genBase(o, ind+1, from, next, readCh, 1);
1083 o << indent(ind++) << "} else {\n";
1084 sYych = mapCodeName["yych"];
1086 else
1088 o << indent(ind++) << "{\n";
1090 o << indent(ind++) << "static void *" << mapCodeName["yytarget"] << "[256] = {\n";
1091 o << indent(ind);
1093 uint ch = 0;
1094 for (uint i = 0; i < lSpans; ++i)
1096 vUsedLabels.insert(span[i].to->label);
1097 for(; ch < span[i].ub; ++ch)
1099 o << "&&" << labelPrefix << span[i].to->label;
1100 if (ch == 255)
1102 o << "\n";
1103 i = lSpans;
1104 break;
1106 else if (ch % 8 == 7)
1108 o << ",\n" << indent(ind);
1110 else
1112 o << "," << space(span[i].to->label);
1116 o << indent(--ind) << "};\n";
1117 o << indent(ind) << "goto *" << mapCodeName["yytarget"] << "[" << sYych << "];\n";
1118 o << indent(--ind) << "}\n";
1121 void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh)
1123 if ((gFlag || wFlag) && wSpans == ~0u)
1125 uint nBitmaps = 0;
1126 std::set<uint> vTargets;
1127 wSpans = 0;
1128 lSpans = 1;
1129 dSpans = 0;
1130 for (uint i = 0; i < nSpans; ++i)
1132 if (span[i].ub > 0xFF)
1134 wSpans++;
1136 if (span[i].ub < 0x100 || !wFlag)
1138 lSpans++;
1140 State *to = span[i].to;
1142 if (to && to->isBase)
1144 const BitMap *b = BitMap::find(to);
1146 if (b && matches(b->go, b->on, this, to))
1148 nBitmaps++;
1150 else
1152 dSpans++;
1153 vTargets.insert(to->label);
1156 else
1158 dSpans++;
1159 vTargets.insert(to->label);
1163 lTargets = vTargets.size() >> nBitmaps;
1166 if (gFlag && (lTargets >= cGotoThreshold || dSpans >= cGotoThreshold))
1168 genCpGoto(o, ind, from, next, readCh);
1169 return;
1171 else if (bFlag)
1173 for (uint i = 0; i < nSpans; ++i)
1175 State *to = span[i].to;
1177 if (to && to->isBase)
1179 const BitMap *b = BitMap::find(to);
1180 std::string sYych;
1182 if (b && matches(b->go, b->on, this, to))
1184 Go go;
1185 go.span = new Span[nSpans];
1186 go.unmap(this, to);
1187 if (readCh)
1189 sYych = "(" + mapCodeName["yych"] + " = " + yychConversion + "*" + mapCodeName["YYCURSOR"] + ")";
1191 else
1193 sYych = mapCodeName["yych"];
1195 readCh = false;
1196 if (wFlag)
1198 o << indent(ind) << "if (" << sYych << " & ~0xFF) {\n";
1199 sYych = mapCodeName["yych"];
1200 genBase(o, ind+1, from, next, readCh, 1);
1201 o << indent(ind) << "} else ";
1203 else
1205 o << indent(ind);
1207 bUsedYYBitmap = true;
1208 o << "if (" << mapCodeName["yybm"] << "[" << b->i << "+" << sYych << "] & ";
1209 if (yybmHexTable)
1211 prtHex(o, b->m, false);
1213 else
1215 o << (uint) b->m;
1217 o << ") {\n";
1218 genGoTo(o, ind+1, from, to, readCh);
1219 o << indent(ind) << "}\n";
1220 go.genBase(o, ind, from, next, readCh, 0);
1221 delete [] go.span;
1222 return ;
1228 genBase(o, ind, from, next, readCh, 0);
1231 void State::emit(std::ostream &o, uint ind, bool &readCh, const std::string& condName) const
1233 if (vUsedLabels.count(label))
1235 o << labelPrefix << label << ":\n";
1237 if (dFlag && !action->isInitial())
1239 o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", *" << mapCodeName["YYCURSOR"] << ");\n";
1241 if (isPreCtxt)
1243 o << indent(ind) << mapCodeName["YYCTXMARKER"] << " = " << mapCodeName["YYCURSOR"] << " + 1;\n";
1245 action->emit(o, ind, readCh, condName);
1248 uint merge(Span *x0, State *fg, State *bg)
1250 Span *x = x0, *f = fg->go.span, *b = bg->go.span;
1251 uint nf = fg->go.nSpans, nb = bg->go.nSpans;
1252 State *prev = NULL, *to;
1253 // NB: we assume both spans are for same range
1255 for (;;)
1257 if (f->ub == b->ub)
1259 to = f->to == b->to ? bg : f->to;
1261 if (to == prev)
1263 --x;
1265 else
1267 x->to = prev = to;
1270 x->ub = f->ub;
1271 ++x;
1272 ++f;
1273 --nf;
1274 ++b;
1275 --nb;
1277 if (nf == 0 && nb == 0)
1279 return x - x0;
1283 while (f->ub < b->ub)
1285 to = f->to == b->to ? bg : f->to;
1287 if (to == prev)
1289 --x;
1291 else
1293 x->to = prev = to;
1296 x->ub = f->ub;
1297 ++x;
1298 ++f;
1299 --nf;
1302 while (b->ub < f->ub)
1304 to = b->to == f->to ? bg : f->to;
1306 if (to == prev)
1308 --x;
1310 else
1312 x->to = prev = to;
1315 x->ub = b->ub;
1316 ++x;
1317 ++b;
1318 --nb;
1323 const uint cInfinity = ~0u;
1325 class SCC
1328 public:
1329 State **top, **stk;
1331 public:
1332 SCC(uint);
1333 ~SCC();
1334 void traverse(State*);
1336 #ifdef PEDANTIC
1337 private:
1338 SCC(const SCC& oth)
1339 : top(oth.top)
1340 , stk(oth.stk)
1343 SCC& operator = (const SCC& oth)
1345 new(this) SCC(oth);
1346 return *this;
1348 #endif
1351 SCC::SCC(uint size)
1352 : top(new State * [size])
1353 , stk(top)
1357 SCC::~SCC()
1359 delete [] stk;
1362 void SCC::traverse(State *x)
1364 *top = x;
1365 uint k = ++top - stk;
1366 x->depth = k;
1368 for (uint i = 0; i < x->go.nSpans; ++i)
1370 State *y = x->go.span[i].to;
1372 if (y)
1374 if (y->depth == 0)
1376 traverse(y);
1379 if (y->depth < x->depth)
1381 x->depth = y->depth;
1386 if (x->depth == k)
1390 (*--top)->depth = cInfinity;
1391 (*top)->link = x;
1393 while (*top != x);
1397 static bool state_is_in_non_trivial_SCC(const State* s)
1400 // does not link to self
1401 if (s->link != s)
1403 return true;
1406 // or exists i: (s->go.spans[i].to->link == s)
1408 // Note: (s->go.spans[i].to == s) is allowed, corresponds to s
1409 // looping back to itself.
1411 for (uint i = 0; i < s->go.nSpans; ++i)
1413 const State* t = s->go.span[i].to;
1415 if (t && t->link == s)
1417 return true;
1420 // otherwise no
1421 return false;
1424 uint maxDist(State *s)
1426 if (s->depth != cInfinity)
1428 // Already calculated, just return result.
1429 return s->depth;
1431 uint mm = 0;
1433 for (uint i = 0; i < s->go.nSpans; ++i)
1435 State *t = s->go.span[i].to;
1437 if (t)
1439 uint m = 1;
1441 if (!t->link) // marked as non-key state
1443 if (t->depth == cInfinity)
1445 t->depth = maxDist(t);
1447 m += t->depth;
1450 if (m > mm)
1452 mm = m;
1457 s->depth = mm;
1458 return mm;
1461 void calcDepth(State *head)
1463 State* s;
1465 // mark non-key states by s->link = NULL ;
1466 for (s = head; s; s = s->next)
1468 if (s != head && !state_is_in_non_trivial_SCC(s))
1470 s->link = NULL;
1472 //else: key state, leave alone
1475 for (s = head; s; s = s->next)
1477 s->depth = cInfinity;
1480 // calculate max number of transitions before guarantied to reach
1481 // a key state.
1482 for (s = head; s; s = s->next)
1484 maxDist(s);
1488 void DFA::findSCCs()
1490 SCC scc(nStates);
1491 State *s;
1493 for (s = head; s; s = s->next)
1495 s->depth = 0;
1496 s->link = NULL;
1499 for (s = head; s; s = s->next)
1501 if (!s->depth)
1503 scc.traverse(s);
1507 calcDepth(head);
1510 void DFA::split(State *s)
1512 State *move = new State;
1513 (void) new Move(move);
1514 addState(&s->next, move);
1515 move->link = s->link;
1516 move->rule = s->rule;
1517 move->go = s->go;
1518 s->rule = NULL;
1519 s->go.nSpans = 1;
1520 s->go.span = new Span[1];
1521 s->go.span[0].ub = ubChar;
1522 s->go.span[0].to = move;
1525 void DFA::findBaseState()
1527 Span *span = new Span[ubChar - lbChar];
1529 for (State *s = head; s; s = s->next)
1531 if (!s->link)
1533 for (uint i = 0; i < s->go.nSpans; ++i)
1535 State *to = s->go.span[i].to;
1537 if (to && to->isBase)
1539 to = to->go.span[0].to;
1540 uint nSpans = merge(span, s, to);
1542 if (nSpans < s->go.nSpans)
1544 delete [] s->go.span;
1545 s->go.nSpans = nSpans;
1546 s->go.span = new Span[nSpans];
1547 memcpy(s->go.span, span, nSpans*sizeof(Span));
1550 break;
1556 delete [] span;
1559 void DFA::prepare()
1561 State *s;
1562 uint i;
1564 bUsedYYBitmap = false;
1566 findSCCs();
1567 head->link = head;
1569 uint nRules = 0;
1571 for (s = head; s; s = s->next)
1573 s->depth = maxDist(s);
1574 if (maxFill < s->depth)
1576 maxFill = s->depth;
1578 if (s->rule && s->rule->accept >= nRules)
1580 nRules = s->rule->accept + 1;
1584 uint nSaves = 0;
1585 saves = new uint[nRules];
1586 memset(saves, ~0, (nRules)*sizeof(*saves));
1588 // mark backtracking points
1589 bSaveOnHead = false;
1591 for (s = head; s; s = s->next)
1593 if (s->rule)
1595 for (i = 0; i < s->go.nSpans; ++i)
1597 if (s->go.span[i].to && !s->go.span[i].to->rule)
1599 delete s->action;
1600 s->action = NULL;
1602 if (saves[s->rule->accept] == ~0u)
1604 saves[s->rule->accept] = nSaves++;
1607 bSaveOnHead |= s == head;
1608 (void) new Save(s, saves[s->rule->accept]); // sets s->action
1614 // insert actions
1615 rules = new State * [nRules];
1617 memset(rules, 0, (nRules)*sizeof(*rules));
1619 State *accept = NULL;
1620 Accept *accfixup = NULL;
1622 for (s = head; s; s = s->next)
1624 State * ow;
1626 if (!s->rule)
1628 ow = accept;
1630 else
1632 if (!rules[s->rule->accept])
1634 State *n = new State;
1635 (void) new Rule(n, s->rule);
1636 rules[s->rule->accept] = n;
1637 addState(&s->next, n);
1640 ow = rules[s->rule->accept];
1643 for (i = 0; i < s->go.nSpans; ++i)
1645 if (!s->go.span[i].to)
1647 if (!ow)
1649 ow = accept = new State;
1650 accfixup = new Accept(accept, nRules, saves, rules);
1651 addState(&s->next, accept);
1654 s->go.span[i].to = ow;
1659 if (accfixup)
1661 accfixup->genRuleMap();
1664 // split ``base'' states into two parts
1665 for (s = head; s; s = s->next)
1667 s->isBase = false;
1669 if (s->link)
1671 for (i = 0; i < s->go.nSpans; ++i)
1673 if (s->go.span[i].to == s)
1675 s->isBase = true;
1676 split(s);
1678 if (bFlag)
1680 BitMap::find(&s->next->go, s);
1683 s = s->next;
1684 break;
1690 // find ``base'' state, if possible
1691 findBaseState();
1693 delete head->action;
1694 head->action = NULL;
1698 void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::string& condName, bool isLastCond, bool& bPrologBrace)
1700 bool bProlog = (!cFlag || !bWroteCondCheck);
1702 if (!cFlag)
1704 bUsedYYAccept = false;
1707 uint start_label = next_label;
1709 (void) new Initial(head, next_label++, bSaveOnHead);
1711 if (bUseStartLabel)
1713 if (startLabelName.empty())
1715 vUsedLabels.insert(start_label);
1719 State *s;
1721 for (s = head; s; s = s->next)
1723 s->label = next_label++;
1726 // Save 'next_fill_index' and compute information about code generation
1727 // while writing to null device.
1728 uint save_fill_index = next_fill_index;
1729 null_stream null_dev;
1731 for (s = head; s; s = s->next)
1733 bool readCh = false;
1734 s->emit(null_dev, ind, readCh, condName);
1735 s->go.genGoto(null_dev, ind, s, s->next, readCh);
1737 if (last_fill_index < next_fill_index)
1739 last_fill_index = next_fill_index;
1741 next_fill_index = save_fill_index;
1743 // Generate prolog
1744 if (bProlog)
1746 o << "\n" << outputFileInfo;
1748 if (DFlag)
1750 bPrologBrace = true;
1751 o << "digraph re2c {\n";
1753 else if ((!fFlag && bUsedYYAccept)
1754 || (!fFlag && bEmitYYCh)
1755 || (bFlag && !cFlag && BitMap::first)
1756 || (cFlag && !bWroteCondCheck && gFlag && !specMap->empty())
1757 || (fFlag && !bWroteGetState && gFlag)
1760 bPrologBrace = true;
1761 o << indent(ind++) << "{\n";
1763 else if (ind == 0)
1765 ind = 1;
1768 if (!fFlag && !DFlag)
1770 if (bEmitYYCh)
1772 o << indent(ind) << mapCodeName["YYCTYPE"] << " " << mapCodeName["yych"] << ";\n";
1774 if (bUsedYYAccept)
1776 o << indent(ind) << "unsigned int " << mapCodeName["yyaccept"] << " = 0;\n";
1779 else
1781 o << "\n";
1784 if (bFlag && !cFlag && BitMap::first)
1786 BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
1788 if (bProlog)
1790 genCondTable(o, ind, *specMap);
1791 genGetStateGoto(o, ind, start_label);
1792 if (cFlag)
1794 if (vUsedLabels.count(start_label))
1796 o << labelPrefix << start_label << ":\n";
1798 if (!startLabelName.empty())
1800 o << startLabelName << ":\n";
1803 genCondGoto(o, ind, *specMap);
1806 if (cFlag && !condName.empty())
1808 if (condDivider.length())
1810 o << replaceParam(condDivider, condDividerParam, condName) << "\n";
1813 if (DFlag)
1815 o << condName << " -> " << (start_label+1) << "\n";
1817 else
1819 o << condPrefix << condName << ":\n";
1822 if (cFlag && bFlag && BitMap::first)
1824 o << indent(ind++) << "{\n";
1825 BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
1828 // TODO: Shouldn't labels 0 and 1 be variable?
1829 if (vUsedLabels.count(1))
1831 vUsedLabels.insert(0);
1832 o << indent(ind) << "goto " << labelPrefix << "0;\n";
1835 // Generate code
1836 for (s = head; s; s = s->next)
1838 bool readCh = false;
1839 s->emit(o, ind, readCh, condName);
1840 s->go.genGoto(o, ind, s, s->next, readCh);
1843 if (cFlag && bFlag && BitMap::first)
1845 o << indent(--ind) << "}\n";
1847 // Generate epilog
1848 if ((!cFlag || isLastCond) && bPrologBrace)
1850 o << indent(--ind) << "}\n";
1853 // Cleanup
1854 if (BitMap::first)
1856 delete BitMap::first;
1857 BitMap::first = NULL;
1860 bUseStartLabel = false;
1863 void genGetStateGotoSub(std::ostream &o, uint ind, uint start_label, int cMin, int cMax)
1865 if (cMin == cMax)
1867 if (cMin == -1)
1869 o << indent(ind) << "goto " << labelPrefix << start_label << ";\n";
1871 else
1873 o << indent(ind) << "goto " << mapCodeName["yyFillLabel"] << cMin << ";\n";
1876 else
1878 int cMid = cMin + ((cMax - cMin + 1) / 2);
1880 o << indent(ind) << "if (" << genGetState() << " < " << cMid << ") {\n";
1881 genGetStateGotoSub(o, ind + 1, start_label, cMin, cMid - 1);
1882 o << indent(ind) << "} else {\n";
1883 genGetStateGotoSub(o, ind + 1, start_label, cMid, cMax);
1884 o << indent(ind) << "}\n";
1888 void genGetStateGoto(std::ostream &o, uint& ind, uint start_label)
1890 if (fFlag && !bWroteGetState)
1892 vUsedLabels.insert(start_label);
1893 if (gFlag)
1895 o << indent(ind++) << "static void *" << mapCodeName["yystable"] << "[" << "] = {\n";
1897 for (size_t i=0; i<last_fill_index; ++i)
1899 o << indent(ind) << "&&" << mapCodeName["yyFillLabel"] << i << ",\n";
1902 o << indent(--ind) << "};\n";
1903 o << "\n";
1905 o << indent(ind) << "if (" << genGetState();
1906 if (bUseStateAbort)
1908 o << " == -1) {\n";
1910 else
1912 o << " < 0) {\n";
1914 o << indent(++ind) << "goto " << labelPrefix << start_label << ";\n";
1915 if (bUseStateAbort)
1917 o << indent(--ind) << "} else if (" << genGetState() << " < -1) {\n";
1918 o << indent(++ind) << "abort();\n";
1920 o << indent(--ind) << "}\n";
1922 o << indent(ind) << "goto *" << mapCodeName["yystable"] << "[" << genGetState() << "];\n";
1924 else if (bFlag)
1926 genGetStateGotoSub(o, ind, start_label, -1, last_fill_index-1);
1927 if (bUseStateAbort)
1929 o << indent(ind) << "abort();\n";
1932 else
1934 o << indent(ind) << "switch (" << genGetState() << ") {\n";
1935 if (bUseStateAbort)
1937 o << indent(ind) << "default: abort();\n";
1938 o << indent(ind) << "case -1: goto " << labelPrefix << start_label << ";\n";
1940 else
1942 o << indent(ind) << "default: goto " << labelPrefix << start_label << ";\n";
1945 for (size_t i=0; i<last_fill_index; ++i)
1947 o << indent(ind) << "case " << i << ": goto " << mapCodeName["yyFillLabel"] << i << ";\n";
1950 o << indent(ind) << "}\n";
1952 if (bUseStateNext)
1954 o << mapCodeName["yyNext"] << ":\n";
1956 bWroteGetState = true;
1960 void genCondTable(std::ostream &o, uint ind, const RegExpMap& specMap)
1962 if (cFlag && !bWroteCondCheck && gFlag && specMap.size())
1964 RegExpIndices vCondList(specMap.size());
1966 for(RegExpMap::const_iterator itSpec = specMap.begin(); itSpec != specMap.end(); ++itSpec)
1968 vCondList[itSpec->second.first] = itSpec->first;
1971 o << indent(ind++) << "static void *" << mapCodeName["yyctable"] << "[" << specMap.size() << "] = {\n";
1973 for(RegExpIndices::const_iterator it = vCondList.begin(); it != vCondList.end(); ++it)
1975 o << indent(ind) << "&&" << condPrefix << *it << ",\n";
1977 o << indent(--ind) << "};\n";
1981 static void genCondGotoSub(std::ostream &o, uint ind, RegExpIndices& vCondList, uint cMin, uint cMax)
1983 if (cMin == cMax)
1985 o << indent(ind) << "goto " << condPrefix << vCondList[cMin] << ";\n";
1987 else
1989 uint cMid = cMin + ((cMax - cMin + 1) / 2);
1991 o << indent(ind) << "if (" << genGetCondition() << " < " << cMid << ") {\n";
1992 genCondGotoSub(o, ind + 1, vCondList, cMin, cMid - 1);
1993 o << indent(ind) << "} else {\n";
1994 genCondGotoSub(o, ind + 1, vCondList, cMid, cMax);
1995 o << indent(ind) << "}\n";
1999 void genCondGoto(std::ostream &o, uint ind, const RegExpMap& specMap)
2001 if (cFlag && !bWroteCondCheck && specMap.size())
2003 if (gFlag)
2005 o << indent(ind) << "goto *" << mapCodeName["yyctable"] << "[" << genGetCondition() << "];\n";
2007 else
2009 if (sFlag)
2011 RegExpIndices vCondList(specMap.size());
2013 for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
2015 vCondList[it->second.first] = it->first;
2017 genCondGotoSub(o, ind, vCondList, 0, vCondList.size() - 1);
2019 else if (DFlag)
2021 for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
2023 o << "0 -> " << it->first << " [label=\"state=" << it->first << "\"]\n";
2026 else
2028 o << indent(ind) << "switch (" << genGetCondition() << ") {\n";
2030 for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
2032 o << indent(ind) << "case " << condEnumPrefix << it->first << ": goto " << condPrefix << it->first << ";\n";
2034 o << indent(ind) << "}\n";
2037 bWroteCondCheck = true;
2041 void genTypes(std::string& o, uint ind, const RegExpMap& specMap)
2043 o.clear();
2045 o += indent(ind++) + "enum " + mapCodeName["YYCONDTYPE"] + " {\n";
2047 RegExpIndices vCondList(specMap.size());
2049 for(RegExpMap::const_iterator itSpecMap = specMap.begin(); itSpecMap != specMap.end(); ++itSpecMap)
2051 // If an entry is < 0 then we did the 0/empty correction twice.
2052 assert(itSpecMap->second.first >= 0);
2053 vCondList[itSpecMap->second.first] = itSpecMap->first;
2056 for(RegExpIndices::const_iterator itCondType = vCondList.begin(); itCondType != vCondList.end(); ++itCondType)
2058 o += indent(ind) + condEnumPrefix + *itCondType + ",\n";
2061 o += indent(--ind) + "};\n";
2064 void genHeader(std::ostream &o, uint ind, const RegExpMap& specMap)
2066 o << "/* Generated by re2c " PACKAGE_VERSION;
2067 if (!bNoGenerationDate)
2069 o << " on ";
2070 time_t now = time(&now);
2071 o.write(ctime(&now), 24);
2073 o << " */\n";
2074 o << headerFileInfo;
2075 o << "\n";
2076 // now the type(s)
2077 genTypes(typesInline, ind, specMap);
2078 o << typesInline;
2081 std::ostream& operator << (std::ostream& o, const file_info& li)
2083 if (li.ln && !iFlag)
2085 o << "#line " << li.ln->get_line() << " \"" << li.fname << "\"\n";
2087 return o;
2090 void Scanner::config(const Str& cfg, int num)
2092 if (cfg.to_string() == "indent:top")
2094 if (num < 0)
2096 fatal("configuration 'indent:top' must be a positive integer");
2098 topIndent = num;
2100 else if (cfg.to_string() == "yybm:hex")
2102 yybmHexTable = num != 0;
2104 else if (cfg.to_string() == "startlabel")
2106 bUseStartLabel = num != 0;
2107 startLabelName = "";
2109 else if (cfg.to_string() == "state:abort")
2111 bUseStateAbort = num != 0;
2113 else if (cfg.to_string() == "state:nextlabel")
2115 bUseStateNext = num != 0;
2117 else if (cfg.to_string() == "yyfill:enable")
2119 bUseYYFill = num != 0;
2121 else if (cfg.to_string() == "yyfill:parameter")
2123 bUseYYFillParam = num != 0;
2125 else if (cfg.to_string() == "yyfill:check")
2127 bUseYYFillCheck = num != 0;
2129 else if (cfg.to_string() == "cgoto:threshold")
2131 cGotoThreshold = num;
2133 else if (cfg.to_string() == "yych:conversion")
2135 if (num)
2137 yychConversion = "(";
2138 yychConversion += mapCodeName["YYCTYPE"];
2139 yychConversion += ")";
2141 else
2143 yychConversion = "";
2146 else if (cfg.to_string() == "yych:emit")
2148 bEmitYYCh = num != 0;
2150 else if (cfg.to_string() == "define:YYFILL:naked")
2152 bUseYYFillNaked = num != 0;
2154 else if (cfg.to_string() == "define:YYGETCONDITION:naked")
2156 bUseYYGetConditionNaked = num != 0;
2158 else if (cfg.to_string() == "define:YYGETSTATE:naked")
2160 bUseYYGetStateNaked = num != 0;
2162 else if (cfg.to_string() == "define:YYSETSTATE:naked")
2164 bUseYYSetStateNaked = num != 0;
2166 else if (cfg.to_string() == "flags:u")
2168 if (!rFlag)
2170 fatalf("cannot use configuration name '%s' without -r flag", cfg.to_string().c_str());
2172 uFlag = num != 0;
2174 else if (cfg.to_string() == "flags:w")
2176 if (!rFlag)
2178 fatalf("cannot use configuration name '%s' without -r flag", cfg.to_string().c_str());
2180 wFlag = num != 0;
2182 else
2184 fatalf("unrecognized configuration name '%s' or illegal integer value", cfg.to_string().c_str());
2188 static std::set<std::string> mapVariableKeys;
2189 static std::set<std::string> mapDefineKeys;
2190 static std::set<std::string> mapLabelKeys;
2192 void Scanner::config(const Str& cfg, const Str& val)
2194 if (mapDefineKeys.empty())
2196 mapVariableKeys.insert("variable:yyaccept");
2197 mapVariableKeys.insert("variable:yybm");
2198 mapVariableKeys.insert("variable:yych");
2199 mapVariableKeys.insert("variable:yyctable");
2200 mapVariableKeys.insert("variable:yystable");
2201 mapVariableKeys.insert("variable:yytarget");
2202 mapDefineKeys.insert("define:YYCONDTYPE");
2203 mapDefineKeys.insert("define:YYCTXMARKER");
2204 mapDefineKeys.insert("define:YYCTYPE");
2205 mapDefineKeys.insert("define:YYCURSOR");
2206 mapDefineKeys.insert("define:YYDEBUG");
2207 mapDefineKeys.insert("define:YYFILL");
2208 mapDefineKeys.insert("define:YYGETCONDITION");
2209 mapDefineKeys.insert("define:YYGETSTATE");
2210 mapDefineKeys.insert("define:YYLIMIT");
2211 mapDefineKeys.insert("define:YYMARKER");
2212 mapDefineKeys.insert("define:YYSETCONDITION");
2213 mapDefineKeys.insert("define:YYSETSTATE");
2214 mapLabelKeys.insert("label:yyFillLabel");
2215 mapLabelKeys.insert("label:yyNext");
2218 std::string strVal;
2220 if (val.len >= 2 && val.str[0] == val.str[val.len-1]
2221 && (val.str[0] == '"' || val.str[0] == '\''))
2223 SubStr tmp(val.str + 1, val.len - 2);
2224 unescape(tmp, strVal);
2226 else
2228 strVal = val.to_string();
2231 if (cfg.to_string() == "indent:string")
2233 indString = strVal;
2235 else if (cfg.to_string() == "startlabel")
2237 startLabelName = strVal;
2238 bUseStartLabel = !startLabelName.empty();
2240 else if (cfg.to_string() == "labelprefix")
2242 labelPrefix = strVal;
2244 else if (cfg.to_string() == "condprefix")
2246 condPrefix = strVal;
2248 else if (cfg.to_string() == "condenumprefix")
2250 condEnumPrefix = strVal;
2252 else if (cfg.to_string() == "cond:divider")
2254 condDivider = strVal;
2256 else if (cfg.to_string() == "cond:divider@cond")
2258 condDividerParam = strVal;
2260 else if (cfg.to_string() == "cond:goto")
2262 condGoto = strVal;
2264 else if (cfg.to_string() == "cond:goto@cond")
2266 condGotoParam = strVal;
2268 else if (cfg.to_string() == "define:YYFILL@len")
2270 yyFillLength = strVal;
2271 bUseYYFillParam = false;
2273 else if (cfg.to_string() == "define:YYSETCONDITION@cond")
2275 yySetConditionParam = strVal;
2276 bUseYYSetConditionParam = false;
2278 else if (cfg.to_string() == "define:YYSETSTATE@state")
2280 yySetStateParam = strVal;
2281 bUseYYSetStateParam = false;
2283 else if (mapVariableKeys.find(cfg.to_string()) != mapVariableKeys.end())
2285 if ((bFirstPass || rFlag) && !mapCodeName.insert(
2286 std::make_pair(cfg.to_string().substr(sizeof("variable:") - 1), strVal)
2287 ).second)
2289 fatalf("variable '%s' already being used and cannot be changed", cfg.to_string().c_str());
2292 else if (mapDefineKeys.find(cfg.to_string()) != mapDefineKeys.end())
2294 if ((bFirstPass || rFlag) && !mapCodeName.insert(
2295 std::make_pair(cfg.to_string().substr(sizeof("define:") - 1), strVal)
2296 ).second)
2298 fatalf("define '%s' already being used and cannot be changed", cfg.to_string().c_str());
2301 else if (mapLabelKeys.find(cfg.to_string()) != mapLabelKeys.end())
2303 if ((bFirstPass || rFlag) && !mapCodeName.insert(
2304 std::make_pair(cfg.to_string().substr(sizeof("label:") - 1), strVal)
2305 ).second)
2307 fatalf("label '%s' already being used and cannot be changed", cfg.to_string().c_str());
2310 else
2312 std::string msg = "unrecognized configuration name '";
2313 msg += cfg.to_string();
2314 msg += "' or illegal string value";
2315 fatal(msg.c_str());
2319 ScannerState::ScannerState()
2320 : tok(NULL), ptr(NULL), cur(NULL), pos(NULL), ctx(NULL)
2321 , bot(NULL), lim(NULL), top(NULL), eof(NULL)
2322 , tchar(0), tline(0), cline(1), iscfg(0)
2323 , in_parse(false)
2327 Scanner::Scanner(std::istream& i, std::ostream& o)
2328 : ScannerState(), in(i), out(o)
2332 char *Scanner::fill(char *cursor, uint need)
2334 if(!eof)
2336 uint cnt;
2337 /* Do not get rid of anything when rFlag is active. Otherwise
2338 * get rid of everything that was already handedout. */
2339 if (!rFlag)
2341 cnt = tok - bot;
2342 if (cnt)
2344 memmove(bot, tok, top - tok);
2345 tok = bot;
2346 ptr -= cnt;
2347 cur -= cnt;
2348 pos -= cnt;
2349 lim -= cnt;
2350 ctx -= cnt;
2351 cursor -= cnt;
2354 /* In crease buffer size. */
2355 if (BSIZE > need)
2357 need = BSIZE;
2359 if (static_cast<uint>(top - lim) < need)
2361 char *buf = new char[(lim - bot) + need];
2362 if (!buf)
2364 fatal("Out of memory");
2366 memcpy(buf, bot, lim - bot);
2367 tok = &buf[tok - bot];
2368 ptr = &buf[ptr - bot];
2369 cur = &buf[cur - bot];
2370 pos = &buf[pos - bot];
2371 lim = &buf[lim - bot];
2372 top = &lim[need];
2373 ctx = &buf[ctx - bot];
2374 cursor = &buf[cursor - bot];
2375 delete [] bot;
2376 bot = buf;
2378 /* Append to buffer. */
2379 in.read(lim, need);
2380 if ((cnt = in.gcount()) != need)
2382 eof = &lim[cnt];
2383 *eof++ = '\0';
2385 lim += cnt;
2387 return cursor;
2390 void Scanner::set_in_parse(bool new_in_parse)
2392 in_parse = new_in_parse;
2395 void Scanner::fatal_at(uint line, uint ofs, const char *msg) const
2397 out.flush();
2398 std::cerr << "re2c: error: "
2399 << "line " << line << ", column " << (tchar + ofs + 1) << ": "
2400 << msg << std::endl;
2401 exit(1);
2404 void Scanner::fatal(uint ofs, const char *msg) const
2406 fatal_at(in_parse ? tline : cline, ofs, msg);
2409 void Scanner::fatalf_at(uint line, const char* fmt, ...) const
2411 char szBuf[4096];
2413 va_list args;
2415 va_start(args, fmt);
2416 vsnprintf(szBuf, sizeof(szBuf), fmt, args);
2417 va_end(args);
2419 szBuf[sizeof(szBuf)-1] = '0';
2421 fatal_at(line, 0, szBuf);
2424 void Scanner::fatalf(const char *fmt, ...) const
2426 char szBuf[4096];
2428 va_list args;
2430 va_start(args, fmt);
2431 vsnprintf(szBuf, sizeof(szBuf), fmt, args);
2432 va_end(args);
2434 szBuf[sizeof(szBuf)-1] = '0';
2436 fatal(szBuf);
2439 Scanner::~Scanner()
2441 if (bot)
2443 delete [] bot;
2447 void Scanner::check_token_length(char *pos, uint len) const
2449 if (pos < bot || pos + len > top)
2451 fatal("Token exceeds limit");
2455 Str Scanner::raw_token(std::string enclosure) const
2457 return Str(std::string(enclosure + token().to_string() + enclosure).c_str());
2460 void Scanner::reuse()
2462 next_label = 0;
2463 next_fill_index = 0;
2464 bWroteGetState = false;
2465 bWroteCondCheck = false;
2466 mapCodeName.clear();
2469 void Scanner::restore_state(const ScannerState& state)
2471 int diff = bot - state.bot;
2472 char *old_bot = bot;
2473 char *old_lim = lim;
2474 char *old_top = top;
2475 char *old_eof = eof;
2476 *(ScannerState*)this = state;
2477 if (diff)
2479 tok -= diff;
2480 ptr -= diff;
2481 cur -= diff;
2482 pos -= diff;
2483 ctx -= diff;
2484 bot = old_bot;
2485 lim = old_lim;
2486 top = old_top;
2487 eof = old_eof;
2491 } // end namespace re2c