Branch data Line data Source code
1 : : // -*- C++ -*-
2 : : // Copyright (C) 2012-2013 Red Hat Inc.
3 : : //
4 : : // This file is part of systemtap, and is free software. You can
5 : : // redistribute it and/or modify it under the terms of the GNU General
6 : : // Public License (GPL); either version 2, or (at your option) any
7 : : // later version.
8 : : //
9 : : // ---
10 : : //
11 : : // This file incorporates code from the re2c project; please see
12 : : // re2c-migrate/README for details.
13 : :
14 : : /* Implements additional functions having to do with emitting code. */
15 : :
16 : : /*
17 : : Author for null_stream stuff: Marcus Boerger <helly@users.sourceforge.net>
18 : : */
19 : :
20 : : #include <stdarg.h>
21 : : #include <stdlib.h>
22 : : #include <string.h>
23 : : #include <stdio.h>
24 : : #include <ctype.h>
25 : : #include <iomanip>
26 : : #include <iostream>
27 : : #include <sstream>
28 : : #include <time.h>
29 : : #include <assert.h>
30 : : #include <string>
31 : : #include <map>
32 : : #include "re2c-globals.h"
33 : : #include "re2c-dfa.h"
34 : : #include "re2c-regex.h"
35 : :
36 : : namespace re2c
37 : : {
38 : :
39 : : // moved here from code.h
40 : :
41 : :
42 : : class BitMap
43 : : {
44 : : public:
45 : : static BitMap *first;
46 : :
47 : : const Go *go;
48 : : const State *on;
49 : : const BitMap *next;
50 : : unsigned i;
51 : : unsigned m;
52 : :
53 : : public:
54 : : static const BitMap *find(const Go*, const State*);
55 : : static const BitMap *find(const State*);
56 : : static void gen(std::ostream&, unsigned ind, unsigned, unsigned);
57 : : static void stats();
58 : : BitMap(const Go*, const State*);
59 : : ~BitMap();
60 : :
61 : : #if PEDANTIC
62 : : BitMap(const BitMap& oth)
63 : : : go(oth.go)
64 : : , on(oth.on)
65 : : , next(oth.next)
66 : : , i(oth.i)
67 : : , m(oth.m)
68 : : {
69 : : }
70 : : BitMap& operator = (const BitMap& oth)
71 : : {
72 : : new(this) BitMap(oth);
73 : : return *this;
74 : : }
75 : : #endif
76 : : };
77 : :
78 : : #ifdef _MSC_VER
79 : : # pragma warning(disable: 4355) /* 'this' : used in base member initializer list */
80 : : #endif
81 : :
82 : : // -------------------------------------------------------------
83 : :
84 : : // moved here from code_names.h
85 : :
86 : 4828 : class CodeNames: public std::map<std::string, std::string>
87 : : {
88 : : public:
89 : : std::string& operator [] (const char * what);
90 : : };
91 : :
92 : 2132 : inline std::string& CodeNames::operator [] (const char * what)
93 : : {
94 [ + - ][ + - ]: 2132 : CodeNames::iterator it = find(std::string(what));
[ + - ]
95 : :
96 [ + - ][ + + ]: 2132 : if (it != end())
97 : : {
98 [ + - ]: 1975 : return it->second;
99 : : }
100 : : else
101 : : {
102 [ + - ][ + - ]: 2132 : return insert(std::make_pair(std::string(what), std::string(what))).first->second;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
103 : : }
104 : : }
105 : :
106 : : // -------------------------------------------------------
107 : :
108 : : // moved here from globals.cc
109 : :
110 : : enum BUFFERSIZE { BSIZE = 8192};
111 : :
112 : :
113 : : bool bFlag = false;
114 : : bool cFlag = false;
115 : : bool dFlag = false;
116 : : bool fFlag = false;
117 : : bool gFlag = false;
118 : : bool rFlag = false;
119 : : bool sFlag = false;
120 : :
121 : : bool bNoGenerationDate = false;
122 : :
123 : : bool bFirstPass = true;
124 : : bool bLastPass = false;
125 : : bool bUsedYYBitmap = false;
126 : :
127 : : bool bUsedYYAccept = false;
128 : : bool bUsedYYMaxFill = false;
129 : : bool bUsedYYMarker = true;
130 : :
131 : : bool bEmitYYCh = true;
132 : : bool bUseStartLabel = false;
133 : : bool bUseStateNext = false;
134 : : bool bUseYYFill = true;
135 : : bool bUseYYFillParam = true;
136 : : bool bUseYYFillCheck = true;
137 : : bool bUseYYFillNaked = false;
138 : : bool bUseYYSetConditionParam = true;
139 : : bool bUseYYGetConditionNaked = false;
140 : : bool bUseYYSetStateParam = true;
141 : : bool bUseYYSetStateNaked = false;
142 : : bool bUseYYGetStateNaked = false;
143 : :
144 : 2414 : std::string startLabelName;
145 [ + - ]: 2414 : std::string labelPrefix("yy");
146 [ + - ]: 2414 : std::string condPrefix("yyc_");
147 [ + - ]: 2414 : std::string condEnumPrefix("yyc");
148 [ + - ]: 2414 : std::string condDivider("/* *********************************** */");
149 [ + - ]: 2414 : std::string condDividerParam("@@");
150 [ + - ]: 2414 : std::string condGoto("goto @@;");
151 [ + - ]: 2414 : std::string condGotoParam("@@");
152 [ + - ]: 2414 : std::string yychConversion("");
153 [ + - ]: 2414 : std::string yyFillLength("@@");
154 [ + - ]: 2414 : std::string yySetConditionParam("@@");
155 [ + - ]: 2414 : std::string yySetStateParam("@@");
156 [ + - ]: 2414 : std::string yySetupRule("");
157 : : unsigned maxFill = 1;
158 : : unsigned next_label = 0;
159 : : unsigned cGotoThreshold = 9;
160 : :
161 : : unsigned topIndent = 0;
162 [ + - ]: 2414 : std::string indString("\t");
163 : : bool yybmHexTable = false;
164 : : bool bUseStateAbort = false;
165 : : bool bWroteGetState = false;
166 : : bool bWroteCondCheck = false;
167 : :
168 : : unsigned next_fill_index = 0;
169 : : unsigned last_fill_index = 0;
170 : 2414 : std::set<unsigned> vUsedLabels;
171 : 2414 : CodeNames mapCodeName;
172 : 2414 : std::string typesInline;
173 : :
174 : : // --------------------------------------------------------------------
175 : :
176 : : // there must be at least one span in list; all spans must cover
177 : : // same range
178 : :
179 : 4161 : static std::string indent(unsigned ind)
180 : : {
181 : 4161 : std::string str;
182 : :
183 [ + - ][ + + ]: 6822 : while (!DFlag && ind-- > 0)
[ + + ]
184 : : {
185 [ + - ]: 2661 : str += indString;
186 : : }
187 : 4161 : return str;
188 : : }
189 : :
190 : : template<typename _Ty>
191 : 0 : std::string replaceParam(std::string str, const std::string& param, const _Ty& value)
192 : : {
193 [ # # ][ # # ]: 0 : std::ostringstream strValue;
194 : :
195 [ # # ][ # # ]: 0 : strValue << value;
196 : :
197 : : std::string::size_type pos;
198 : :
199 [ # # ][ # # ]: 0 : while((pos = str.find(param)) != std::string::npos)
[ # # ][ # # ]
200 : : {
201 [ # # ][ # # ]: 0 : str.replace(pos, param.length(), strValue.str());
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
202 : : }
203 : :
204 [ # # ][ # # ]: 0 : return str;
[ # # ][ # # ]
205 : : }
206 : :
207 : 254 : static void genYYFill(std::ostream &o, unsigned, unsigned need)
208 : : {
209 [ + - ]: 254 : if (bUseYYFillParam)
210 : : {
211 : 254 : o << mapCodeName["YYFILL"];
212 [ + - ]: 254 : if (!bUseYYFillNaked)
213 : : {
214 : 254 : o << "(" << need << ");";
215 : : }
216 : 254 : o << "\n";
217 : : }
218 : : else
219 : : {
220 [ # # ][ # # ]: 0 : o << replaceParam(mapCodeName["YYFILL"], yyFillLength, need);
[ # # ]
221 [ # # ]: 0 : if (!bUseYYFillNaked)
222 : : {
223 : 0 : o << ";";
224 : : }
225 : 0 : o << "\n";
226 : : }
227 : 254 : }
228 : :
229 : 0 : static std::string genGetState()
230 : : {
231 [ # # ]: 0 : if (bUseYYGetStateNaked)
232 : : {
233 : 0 : return mapCodeName["YYGETSTATE"];
234 : : }
235 : : else
236 : : {
237 : 0 : return mapCodeName["YYGETSTATE"] + "()";
238 : : }
239 : : }
240 : :
241 : 0 : static std::string genGetCondition()
242 : : {
243 [ # # ]: 0 : if (bUseYYGetConditionNaked)
244 : : {
245 : 0 : return mapCodeName["YYGETCONDITION"];
246 : : }
247 : : else
248 : : {
249 : 0 : return mapCodeName["YYGETCONDITION"] + "()";
250 : : }
251 : : }
252 : :
253 : 0 : static void genSetCondition(std::ostream& o, unsigned ind, const std::string& newcond)
254 : : {
255 [ # # ]: 0 : if (bUseYYSetConditionParam)
256 : : {
257 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["YYSETCONDITION"] << "(" << condEnumPrefix << newcond << ");\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
258 : : }
259 : : else
260 : : {
261 [ # # ][ # # ]: 0 : o << indent(ind) << replaceParam(mapCodeName["YYSETCONDITION"], yySetConditionParam, condEnumPrefix + newcond) << "\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
262 : : }
263 : 0 : }
264 : :
265 : 0 : static std::string space(unsigned this_label)
266 : : {
267 [ # # ][ # # ]: 0 : 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;
[ # # ][ # # ]
[ # # ][ # # ]
268 [ # # ][ # # ]: 0 : 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;
[ # # ][ # # ]
[ # # ][ # # ]
269 : :
270 [ # # ]: 0 : return std::string(std::max(1, nl - tl + 1), ' ');
271 : : }
272 : :
273 : 0 : void Go::compact()
274 : : {
275 : : // arrange so that adjacent spans have different targets
276 : 0 : unsigned i = 0;
277 : :
278 [ # # ]: 0 : for (unsigned j = 1; j < nSpans; ++j)
279 : : {
280 [ # # ]: 0 : if (span[j].to != span[i].to)
281 : : {
282 : 0 : ++i;
283 : 0 : span[i].to = span[j].to;
284 : : }
285 : :
286 : 0 : span[i].ub = span[j].ub;
287 : : }
288 : :
289 : 0 : nSpans = i + 1;
290 : 0 : }
291 : :
292 : 0 : void Go::unmap(Go *base, const State *x)
293 : : {
294 : 0 : Span *s = span, *b = base->span, *e = &b[base->nSpans];
295 : 0 : unsigned lb = 0;
296 : 0 : s->ub = 0;
297 : 0 : s->to = NULL;
298 : :
299 [ # # ]: 0 : for (; b != e; ++b)
300 : : {
301 [ # # ]: 0 : if (b->to == x)
302 : : {
303 [ # # ]: 0 : if ((s->ub - lb) > 1)
304 : : {
305 : 0 : s->ub = b->ub;
306 : : }
307 : : }
308 : : else
309 : : {
310 [ # # ]: 0 : if (b->to != s->to)
311 : : {
312 [ # # ]: 0 : if (s->ub)
313 : : {
314 : 0 : lb = s->ub;
315 : 0 : ++s;
316 : : }
317 : :
318 : 0 : s->to = b->to;
319 : : }
320 : :
321 : 0 : s->ub = b->ub;
322 : : }
323 : : }
324 : :
325 : 0 : s->ub = e[ -1].ub;
326 : 0 : ++s;
327 : 0 : nSpans = s - span;
328 : 0 : }
329 : :
330 : 0 : static void doGen(const Go *g, const State *s, unsigned *bm, unsigned f, unsigned m)
331 : : {
332 : 0 : Span *b = g->span, *e = &b[g->nSpans];
333 : 0 : unsigned lb = 0;
334 : :
335 [ # # ]: 0 : for (; b < e; ++b)
336 : : {
337 [ # # ]: 0 : if (b->to == s)
338 : : {
339 [ # # ][ # # ]: 0 : for (; lb < b->ub && lb < 256; ++lb)
[ # # ]
340 : : {
341 : 0 : bm[lb-f] |= m;
342 : : }
343 : : }
344 : :
345 : 0 : lb = b->ub;
346 : : }
347 : 0 : }
348 : :
349 : 0 : static void prt(std::ostream& o, const Go *g, const State *s)
350 : : {
351 : 0 : Span *b = g->span, *e = &b[g->nSpans];
352 : 0 : unsigned lb = 0;
353 : :
354 [ # # ]: 0 : for (; b < e; ++b)
355 : : {
356 [ # # ]: 0 : if (b->to == s)
357 : : {
358 : 0 : printSpan(o, lb, b->ub);
359 : : }
360 : :
361 : 0 : lb = b->ub;
362 : : }
363 : 0 : }
364 : :
365 : 0 : static bool matches(const Go *g1, const State *s1, const Go *g2, const State *s2)
366 : : {
367 : 0 : Span *b1 = g1->span, *e1 = &b1[g1->nSpans];
368 : 0 : unsigned lb1 = 0;
369 : 0 : Span *b2 = g2->span, *e2 = &b2[g2->nSpans];
370 : 0 : unsigned lb2 = 0;
371 : :
372 : 0 : for (;;)
373 : : {
374 [ # # ][ # # ]: 0 : for (; b1 < e1 && b1->to != s1; ++b1)
[ # # ]
375 : : {
376 : 0 : lb1 = b1->ub;
377 : : }
378 : :
379 [ # # ][ # # ]: 0 : for (; b2 < e2 && b2->to != s2; ++b2)
[ # # ]
380 : : {
381 : 0 : lb2 = b2->ub;
382 : : }
383 : :
384 [ # # ]: 0 : if (b1 == e1)
385 : : {
386 : 0 : return b2 == e2;
387 : : }
388 : :
389 [ # # ]: 0 : if (b2 == e2)
390 : : {
391 : 0 : return false;
392 : : }
393 : :
394 [ # # ][ # # ]: 0 : if (lb1 != lb2 || b1->ub != b2->ub)
395 : : {
396 : 0 : return false;
397 : : }
398 : :
399 : 0 : ++b1;
400 : 0 : ++b2;
401 : : }
402 : : }
403 : :
404 : : BitMap *BitMap::first = NULL;
405 : :
406 : 0 : BitMap::BitMap(const Go *g, const State *x)
407 : : : go(g)
408 : : , on(x)
409 : : , next(first)
410 : : , i(0)
411 : 0 : , m(0)
412 : : {
413 : 0 : first = this;
414 : 0 : }
415 : :
416 : 0 : BitMap::~BitMap()
417 : : {
418 [ # # ]: 0 : delete next;
419 : 0 : }
420 : :
421 : 0 : const BitMap *BitMap::find(const Go *g, const State *x)
422 : : {
423 [ # # ]: 0 : for (const BitMap *b = first; b; b = b->next)
424 : : {
425 [ # # ]: 0 : if (matches(b->go, b->on, g, x))
426 : : {
427 : 0 : return b;
428 : : }
429 : : }
430 : :
431 : 0 : return new BitMap(g, x);
432 : : }
433 : :
434 : 0 : const BitMap *BitMap::find(const State *x)
435 : : {
436 [ # # ]: 0 : for (const BitMap *b = first; b; b = b->next)
437 : : {
438 [ # # ]: 0 : if (b->on == x)
439 : : {
440 : 0 : return b;
441 : : }
442 : : }
443 : :
444 : 0 : return NULL;
445 : : }
446 : :
447 : 0 : void BitMap::gen(std::ostream &o, unsigned ind, unsigned lb, unsigned ub)
448 : : {
449 [ # # ][ # # ]: 0 : if (first && bLastPass && bUsedYYBitmap)
[ # # ]
450 : : {
451 [ # # ][ # # ]: 0 : o << indent(ind) << "static const unsigned char " << mapCodeName["yybm"] << "[] = {";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
452 : :
453 : 0 : unsigned c = 1, n = ub - lb;
454 : 0 : const BitMap *cb = first;
455 : :
456 [ # # ]: 0 : while((cb = cb->next) != NULL) {
457 : 0 : ++c;
458 : : }
459 : 0 : BitMap *b = first;
460 : :
461 [ # # ][ # # ]: 0 : unsigned *bm = new unsigned[n];
462 : :
463 [ # # ]: 0 : for (unsigned i = 0, t = 1; b; i += n, t += 8)
464 : : {
465 : 0 : memset(bm, 0, n * sizeof(unsigned));
466 : :
467 [ # # ][ # # ]: 0 : for (unsigned m = 0x80; b && m; m >>= 1)
[ # # ]
468 : : {
469 : 0 : b->i = i;
470 : 0 : b->m = m;
471 : 0 : doGen(b->go, b->on, bm, lb, m);
472 : 0 : b = const_cast<BitMap*>(b->next);
473 : : }
474 : :
475 [ # # ]: 0 : if (c > 8)
476 : : {
477 [ # # ][ # # ]: 0 : o << "\n" << indent(ind+1) << "/* table " << t << " .. " << std::min(c, t+7) << ": " << i << " */";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
478 : : }
479 : :
480 [ # # ]: 0 : for (unsigned j = 0; j < n; ++j)
481 : : {
482 [ # # ]: 0 : if (j % 8 == 0)
483 : : {
484 [ # # ][ # # ]: 0 : o << "\n" << indent(ind+1);
[ # # ][ # # ]
485 : : }
486 : :
487 [ # # ]: 0 : if (yybmHexTable)
488 : : {
489 [ # # ]: 0 : prtHex(o, bm[j]);
490 : : }
491 : : else
492 : : {
493 [ # # ][ # # ]: 0 : o << std::setw(3) << (unsigned)bm[j];
494 : : }
495 [ # # ]: 0 : o << ", ";
496 : : }
497 : : }
498 : :
499 [ # # ][ # # ]: 0 : o << "\n" << indent(ind) << "};\n";
[ # # ][ # # ]
[ # # ]
500 : : /* stats(); */
501 : :
502 [ # # ]: 0 : delete[] bm;
503 : : }
504 : 0 : }
505 : :
506 : 0 : void BitMap::stats()
507 : : {
508 : 0 : unsigned n = 0;
509 : :
510 [ # # ]: 0 : for (const BitMap *b = first; b; b = b->next)
511 : : {
512 : 0 : prt(std::cerr, b->go, b->on);
513 : 0 : std::cerr << std::endl;
514 : 0 : ++n;
515 : : }
516 : :
517 : 0 : std::cerr << n << " bitmaps\n";
518 : 0 : first = NULL;
519 : 0 : }
520 : :
521 : 1118 : static void genGoTo(std::ostream &o, unsigned ind, const State *from, const State *to, bool & readCh)
522 : : {
523 [ - + ]: 1118 : if (DFlag)
524 : : {
525 : 0 : o << from->label << " -> " << to->label << "\n";
526 : 1118 : return;
527 : : }
528 : :
529 [ + + ][ + - ]: 1118 : if (readCh && from->label + 1 != to->label)
530 : : {
531 [ + - ][ + - ]: 4 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
532 : 4 : readCh = false;
533 : : }
534 : :
535 [ + - ][ + - ]: 1118 : o << indent(ind) << "goto " << labelPrefix << to->label << ";\n";
[ + - ][ + - ]
[ + - ]
536 : 1118 : vUsedLabels.insert(to->label);
537 : : }
538 : :
539 : 12 : static void genIf(std::ostream &o, unsigned ind, const char *cmp, unsigned v, bool &readCh)
540 : : {
541 [ + - ][ + - ]: 12 : o << indent(ind) << "if (";
542 [ - + ]: 12 : if (readCh)
543 : : {
544 : 0 : o << "(" << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ")";
545 : 0 : readCh = false;
546 : : }
547 : : else
548 : : {
549 : 12 : o << mapCodeName["yych"];
550 : : }
551 : :
552 : 12 : o << " " << cmp << " ";
553 : 12 : prtChOrHex(o, v);
554 : 12 : o << ") ";
555 : 12 : }
556 : :
557 : 254 : static void need(std::ostream &o, unsigned ind, unsigned n, bool & readCh, bool bSetMarker)
558 : : {
559 [ + - ]: 254 : if (DFlag)
560 : : {
561 : 254 : return;
562 : : }
563 : :
564 : 254 : unsigned fillIndex = next_fill_index;
565 : :
566 [ - + ]: 254 : if (fFlag)
567 : : {
568 : 0 : next_fill_index++;
569 [ # # ]: 0 : if (bUseYYSetStateParam)
570 : : {
571 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["YYSETSTATE"] << "(" << fillIndex << ");\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
572 : : }
573 : : else
574 : : {
575 [ # # ][ # # ]: 0 : o << indent(ind) << replaceParam(mapCodeName["YYSETSTATE"], yySetStateParam, fillIndex) << "\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
576 : : }
577 : : }
578 : :
579 [ + - ][ + - ]: 254 : if (bUseYYFill && n > 0)
580 : : {
581 [ + - ][ + - ]: 254 : o << indent(ind);
[ + - ]
582 [ + + ]: 254 : if (n == 1)
583 : : {
584 [ + - ]: 250 : if (bUseYYFillCheck)
585 : : {
586 [ + - ][ + - ]: 250 : o << "if (" << mapCodeName["YYLIMIT"] << " <= " << mapCodeName["YYCURSOR"] << ") ";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
587 : : }
588 [ + - ]: 250 : genYYFill(o, ind, n);
589 : : }
590 : : else
591 : : {
592 [ + - ]: 4 : if (bUseYYFillCheck)
593 : : {
594 [ + - ][ + - ]: 4 : o << "if ((" << mapCodeName["YYLIMIT"] << " - " << mapCodeName["YYCURSOR"] << ") < " << n << ") ";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
595 : : }
596 [ + - ]: 4 : genYYFill(o, ind, n);
597 : : }
598 : : }
599 : :
600 [ - + ]: 254 : if (fFlag)
601 : : {
602 [ # # ][ # # ]: 0 : o << mapCodeName["yyFillLabel"] << fillIndex << ":\n";
[ # # ][ # # ]
603 : : }
604 : :
605 [ + - ]: 254 : if (n > 0)
606 : : {
607 [ + + ]: 254 : if (bSetMarker)
608 : : {
609 [ + - ][ + - ]: 44 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*(" << mapCodeName["YYMARKER"] << " = " << mapCodeName["YYCURSOR"] << ");\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
610 : : }
611 : : else
612 : : {
613 [ + - ][ + - ]: 210 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
614 : : }
615 : 254 : readCh = false;
616 : : }
617 : : }
618 : :
619 : 178 : void Match::emit(std::ostream &o, unsigned ind, bool &readCh, const std::string&) const
620 : : {
621 [ - + ]: 178 : if (DFlag)
622 : : {
623 : 178 : return;
624 : : }
625 : :
626 [ + + ]: 178 : if (state->link)
627 : : {
628 [ + - ][ + - ]: 158 : o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
[ + - ][ + - ]
[ + - ]
629 : : }
630 [ + + ]: 20 : else if (!readAhead())
631 : : {
632 : : /* do not read next char if match */
633 [ + - ][ + - ]: 8 : o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
[ + - ][ + - ]
[ + - ]
634 : 8 : readCh = true;
635 : : }
636 : : else
637 : : {
638 [ + - ][ + - ]: 12 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
639 : 12 : readCh = false;
640 : : }
641 : :
642 [ + + ]: 178 : if (state->link)
643 : : {
644 : 158 : need(o, ind, state->depth, readCh, false);
645 : : }
646 : : }
647 : :
648 : 0 : void Enter::emit(std::ostream &o, unsigned ind, bool &readCh, const std::string&) const
649 : : {
650 [ # # ]: 0 : if (state->link)
651 : : {
652 [ # # ][ # # ]: 0 : o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
[ # # ][ # # ]
[ # # ]
653 [ # # ]: 0 : if (vUsedLabels.count(label))
654 : : {
655 : 0 : o << labelPrefix << label << ":\n";
656 : : }
657 : 0 : need(o, ind, state->depth, readCh, false);
658 : : }
659 : : else
660 : : {
661 : : /* we shouldn't need 'rule-following' protection here */
662 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
663 [ # # ]: 0 : if (vUsedLabels.count(label))
664 : : {
665 : 0 : o << labelPrefix << label << ":\n";
666 : : }
667 : 0 : readCh = false;
668 : : }
669 : 0 : }
670 : :
671 : 46 : void Initial::emit(std::ostream &o, unsigned ind, bool &readCh, const std::string&) const
672 : : {
673 [ + - ][ - + ]: 46 : if (!cFlag && !startLabelName.empty())
[ - + ]
674 : : {
675 : 0 : o << startLabelName << ":\n";
676 : : }
677 : :
678 [ + - ][ - + ]: 46 : if (vUsedLabels.count(label+1))
679 : : {
680 [ # # ]: 0 : if (state->link)
681 : : {
682 [ # # ][ # # ]: 0 : o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
[ # # ][ # # ]
[ # # ]
683 : : }
684 : : else
685 : : {
686 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
687 : : }
688 : : }
689 : :
690 [ - + ]: 46 : if (vUsedLabels.count(label))
691 : : {
692 : 0 : o << labelPrefix << label << ":\n";
693 : : }
694 [ + - ]: 46 : else if (!label)
695 : : {
696 : 46 : o << "\n";
697 : : }
698 : :
699 [ - + ]: 46 : if (dFlag)
700 : : {
701 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", *" << mapCodeName["YYCURSOR"] << ");\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
702 : : }
703 : :
704 [ + - ]: 46 : if (state->link)
705 : : {
706 [ + + ][ + - ]: 46 : need(o, ind, state->depth, readCh, setMarker && bUsedYYMarker);
707 : : }
708 : : else
709 : : {
710 [ # # ][ # # ]: 0 : if (setMarker && bUsedYYMarker)
711 : : {
712 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["YYMARKER"] << " = " << mapCodeName["YYCURSOR"] << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
713 : : }
714 : 0 : readCh = false;
715 : : }
716 : 46 : }
717 : :
718 : 52 : void Save::emit(std::ostream &o, unsigned ind, bool &readCh, const std::string&) const
719 : : {
720 [ - + ]: 52 : if (DFlag)
721 : : {
722 : 52 : return;
723 : : }
724 : :
725 [ + - ]: 52 : if (bUsedYYAccept)
726 : : {
727 [ + - ][ + - ]: 52 : o << indent(ind) << mapCodeName["yyaccept"] << " = " << selector << ";\n";
[ + - ][ + - ]
[ + - ][ + - ]
728 : : }
729 : :
730 [ + + ]: 52 : if (state->link)
731 : : {
732 [ + - ]: 50 : if (bUsedYYMarker)
733 : : {
734 [ + - ][ + - ]: 50 : o << indent(ind) << mapCodeName["YYMARKER"] << " = ++" << mapCodeName["YYCURSOR"] << ";\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
735 : : }
736 : 50 : need(o, ind, state->depth, readCh, false);
737 : : }
738 : : else
739 : : {
740 [ + - ]: 2 : if (bUsedYYMarker)
741 : : {
742 [ + - ][ + - ]: 2 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*(" << mapCodeName["YYMARKER"] << " = ++" << mapCodeName["YYCURSOR"] << ");\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
743 : : }
744 : : else
745 : : {
746 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
747 : : }
748 : 2 : readCh = false;
749 : : }
750 : : }
751 : :
752 : 54 : Move::Move(State *s) : Action(s)
753 : : {
754 : : ;
755 : 54 : }
756 : :
757 : 104 : void Move::emit(std::ostream &, unsigned, bool &, const std::string&) const
758 : : {
759 : : ;
760 : 104 : }
761 : :
762 : 23 : Accept::Accept(State *x, unsigned n, unsigned *s, State **r)
763 [ + - ]: 23 : : Action(x), nRules(n), saves(s), rules(r)
764 : : {
765 : : ;
766 : 23 : }
767 : :
768 : 23 : void Accept::genRuleMap()
769 : : {
770 [ + + ]: 69 : for (unsigned i = 0; i < nRules; ++i)
771 : : {
772 [ + + ]: 46 : if (saves[i] != ~0u)
773 : : {
774 : 43 : mapRules[saves[i]] = rules[i];
775 : : }
776 : : }
777 : 23 : }
778 : :
779 : 120 : void Accept::emitBinary(std::ostream &o, unsigned ind, unsigned l, unsigned r, bool &readCh) const
780 : : {
781 [ + + ]: 120 : if (l < r)
782 : : {
783 : 40 : unsigned m = (l + r) >> 1;
784 : :
785 [ - + ]: 40 : assert(bUsedYYAccept);
786 [ + - ][ + - ]: 40 : o << indent(ind) << "if (" << mapCodeName["yyaccept"] << (r == l+1 ? " == " : " <= ") << m << ") {\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
787 : 40 : emitBinary(o, ++ind, l, m, readCh);
788 [ + - ][ + - ]: 40 : o << indent(--ind) << "} else {\n";
789 : 40 : emitBinary(o, ++ind, m + 1, r, readCh);
790 [ + - ][ + - ]: 40 : o << indent(--ind) << "}\n";
791 : : }
792 : : else
793 : : {
794 [ + - ][ + - ]: 80 : genGoTo(o, ind, state, mapRules.find(l)->second, readCh);
795 : : }
796 : 120 : }
797 : :
798 : 44 : void Accept::emit(std::ostream &o, unsigned ind, bool &readCh, const std::string&) const
799 : : {
800 [ + - ]: 44 : if (mapRules.size() > 0)
801 : : {
802 : 44 : bUsedYYMarker = true;
803 [ + - ]: 44 : if (!DFlag)
804 : : {
805 [ + - ][ + - ]: 44 : o << indent(ind) << mapCodeName["YYCURSOR"] << " = " << mapCodeName["YYMARKER"] << ";\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
806 : : }
807 : :
808 [ - + ]: 44 : if (readCh) // shouldn't be necessary, but might become at some point
809 : : {
810 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
811 : 0 : readCh = false;
812 : : }
813 : :
814 [ + + ]: 44 : if (mapRules.size() > 1)
815 : : {
816 : 40 : bUsedYYAccept = true;
817 : :
818 [ - + ][ # # ]: 40 : if (gFlag && mapRules.size() >= cGotoThreshold)
[ - + ]
819 : : {
820 [ # # ][ # # ]: 0 : o << indent(ind++) << "{\n";
821 [ # # ][ # # ]: 0 : o << indent(ind++) << "static void *" << mapCodeName["yytarget"] << "[" << mapRules.size() << "] = {\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
822 [ # # ][ # # ]: 0 : for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it)
[ # # ]
823 : : {
824 [ # # ][ # # ]: 0 : o << indent(ind) << "&&" << labelPrefix << it->second->label << ",\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
825 [ # # ][ # # ]: 0 : vUsedLabels.insert(it->second->label);
826 : : }
827 [ # # ][ # # ]: 0 : o << indent(--ind) << "};\n";
828 [ # # ][ # # ]: 0 : o << indent(ind) << "goto *" << mapCodeName["yytarget"] << "[" << mapCodeName["yyaccept"] << "];\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
829 [ # # ][ # # ]: 0 : o << indent(--ind) << "}\n";
830 : : }
831 [ + - ][ + - ]: 40 : else if (sFlag || (mapRules.size() == 2 && !DFlag))
[ + - ][ + - ]
832 : : {
833 : 40 : emitBinary(o, ind, 0, mapRules.size() - 1, readCh);
834 : : }
835 [ # # ]: 0 : else if (DFlag)
836 : : {
837 [ # # ][ # # ]: 0 : for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it)
[ # # ]
838 : : {
839 [ # # ][ # # ]: 0 : o << state->label << " -> " << it->second->label;
[ # # ][ # # ]
840 [ # # ][ # # ]: 0 : o << " [label=\"yyaccept=" << it->first << "\"]\n";
[ # # ][ # # ]
841 : : }
842 : : }
843 : : else
844 : : {
845 [ # # ][ # # ]: 0 : o << indent(ind) << "switch (" << mapCodeName["yyaccept"] << ") {\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
846 : :
847 [ # # ][ # # ]: 0 : RuleMap::const_iterator it = mapRules.begin(), end = mapRules.end();
848 : :
849 [ # # ]: 0 : while (it != end)
850 : : {
851 : 0 : RuleMap::const_iterator tmp = it;
852 : :
853 [ # # ]: 0 : if (++it == end)
854 : : {
855 [ # # ][ # # ]: 0 : o << indent(ind) << "default:\t";
[ # # ][ # # ]
856 : : }
857 : : else
858 : : {
859 [ # # ][ # # ]: 0 : o << indent(ind) << "case " << tmp->first << ": \t";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
860 : : }
861 : :
862 [ # # ][ # # ]: 0 : genGoTo(o, 0, state, tmp->second, readCh);
863 : : }
864 : :
865 [ # # ][ # # ]: 0 : o << indent(ind) << "}\n";
[ # # ][ # # ]
866 : : }
867 : : }
868 : : else
869 : : {
870 : : // no need to write if statement here since there is only case 0.
871 [ + - ][ + - ]: 4 : genGoTo(o, ind, state, mapRules.find(0)->second, readCh);
[ + - ]
872 : : }
873 : : }
874 : 44 : }
875 : :
876 : 47 : Rule::Rule(State *s, RuleOp *r) : Action(s), rule(r)
877 : : {
878 : : ;
879 : 47 : }
880 : :
881 : 90 : void Rule::emit(std::ostream &o, unsigned ind, bool &, const std::string& condName) const
882 : : {
883 [ - + ]: 90 : if (DFlag)
884 : : {
885 : 0 : o << state->label << " [label=\"" << rule->code->line << "\"]\n";
886 : 90 : return;
887 : : }
888 : :
889 : 90 : unsigned back = rule->ctx->fixedLength();
890 : :
891 [ - + ]: 90 : if (back != 0u)
892 : : {
893 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["YYCURSOR"] << " = " << mapCodeName["YYCTXMARKER"] << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
894 : : }
895 : :
896 [ - + ][ # # ]: 90 : if (rule->code->newcond.length() && condName != rule->code->newcond)
[ - + ]
897 : : {
898 : 0 : genSetCondition(o, ind, rule->code->newcond);
899 : : }
900 : :
901 [ - + ][ # # ]: 90 : if (!yySetupRule.empty() && !rule->code->autogen)
[ - + ]
902 : : {
903 [ # # ][ # # ]: 0 : o << indent(ind) << yySetupRule << "\n";
[ # # ]
904 : : }
905 : :
906 [ + - ]: 90 : o << indent(ind);
907 [ - + ]: 90 : if (rule->code->autogen)
908 : : {
909 [ # # ][ # # ]: 0 : o << replaceParam(condGoto, condGotoParam, condPrefix + rule->code->newcond);
[ # # ][ # # ]
[ # # ]
910 : : }
911 : : else
912 : : {
913 : 90 : o << rule->code->text;
914 : : }
915 : 90 : o << "\n";
916 : : }
917 : :
918 : 126 : static void doLinear(std::ostream &o, unsigned ind, Span *s, unsigned n, const State *from, const State *next, bool &readCh, unsigned mask)
919 : : {
920 : 126 : for (;;)
921 : : {
922 : 126 : State *bg = s[0].to;
923 : :
924 [ - + ][ # # ]: 126 : while (n >= 3 && s[2].to == bg && (s[1].ub - s[0].ub) == 1)
[ # # ][ - + ]
925 : : {
926 [ # # ][ # # ]: 0 : if (s[1].to == next && n == 3)
927 : : {
928 [ # # ][ # # ]: 0 : if (!mask || (s[0].ub > 0x00FF))
929 : : {
930 : 0 : genIf(o, ind, "!=", s[0].ub, readCh);
931 : 0 : genGoTo(o, 0, from, bg, readCh);
932 : : }
933 [ # # ][ # # ]: 0 : if (next->label != from->label + 1 || DFlag)
934 : : {
935 : 0 : genGoTo(o, ind, from, next, readCh);
936 : : }
937 : 0 : return ;
938 : : }
939 : : else
940 : : {
941 [ # # ][ # # ]: 0 : if (!mask || (s[0].ub > 0x00FF))
942 : : {
943 : 0 : genIf(o, ind, "==", s[0].ub, readCh);
944 : 0 : genGoTo(o, 0, from, s[1].to, readCh);
945 : : }
946 : : }
947 : :
948 : 0 : n -= 2;
949 : 0 : s += 2;
950 : : }
951 : :
952 [ + + ]: 126 : if (n == 1)
953 : : {
954 : : // if(bg != next){
955 [ + + ][ - + ]: 114 : if (s[0].to->label != from->label + 1 || DFlag)
956 : : {
957 : 6 : genGoTo(o, ind, from, s[0].to, readCh);
958 : : }
959 : : // }
960 : 114 : return ;
961 : : }
962 [ + - ][ + + ]: 12 : else if (n == 2 && bg == next)
963 : : {
964 [ - + ][ # # ]: 10 : if (!mask || (s[0].ub > 0x00FF))
965 : : {
966 : 10 : genIf(o, ind, ">=", s[0].ub, readCh);
967 : 10 : genGoTo(o, 0, from, s[1].to, readCh);
968 : : }
969 [ + - ][ - + ]: 10 : if (next->label != from->label + 1 || DFlag)
970 : : {
971 : 0 : genGoTo(o, ind, from, next, readCh);
972 : : }
973 : 10 : return ;
974 : : }
975 : : else
976 : : {
977 [ - + ][ # # ]: 2 : if (!mask || ((s[0].ub - 1) > 0x00FF))
978 : : {
979 : 2 : genIf(o, ind, "<=", s[0].ub - 1, readCh);
980 : 2 : genGoTo(o, 0, from, bg, readCh);
981 : : }
982 : 2 : n -= 1;
983 : 2 : s += 1;
984 : : }
985 : : }
986 : :
987 : : if (next->label != from->label + 1 || DFlag)
988 : : {
989 : : genGoTo(o, ind, from, next, readCh);
990 : : }
991 : : }
992 : :
993 : 124 : void Go::genLinear(std::ostream &o, unsigned ind, const State *from, const State *next, bool &readCh, unsigned mask) const
994 : : {
995 : 124 : doLinear(o, ind, span, nSpans, from, next, readCh, mask);
996 : 124 : }
997 : :
998 : 0 : static void printDotCharInterval(std::ostream &o, unsigned lastPrintableChar, unsigned chr, const State *from, const State *to, bool multipleIntervals)
999 : : {
1000 : 0 : o << from->label << " -> " << to->label;
1001 : 0 : o << " [label=";
1002 : :
1003 [ # # ]: 0 : if (lastPrintableChar != 0)
1004 : : {
1005 : 0 : --chr; // we are already one char past the end
1006 : :
1007 : : // make an interval (e.g. [A-Z])
1008 [ # # ]: 0 : if (lastPrintableChar != chr)
1009 : : {
1010 : 0 : o << "\"[" << (char)lastPrintableChar << "-" << (char)chr << "]\"";
1011 : :
1012 [ # # ]: 0 : if (multipleIntervals)
1013 : : {
1014 : 0 : o << "]\n";
1015 : 0 : o << from->label << " -> " << to->label;
1016 : 0 : o << " [label=";
1017 : 0 : prtChOrHex(o, ++chr);
1018 : : }
1019 : : }
1020 : : else
1021 : : {
1022 : 0 : prtChOrHex(o, chr);
1023 : : }
1024 : : }
1025 : : else
1026 : : {
1027 : 0 : prtChOrHex(o, chr);
1028 : : }
1029 : :
1030 : 0 : o << "]";
1031 : 0 : }
1032 : :
1033 : 778 : static bool genCases(std::ostream &o, unsigned ind, unsigned lb, Span *s, bool &newLine, unsigned mask, const State *from, const State *to)
1034 : : {
1035 : 778 : bool used = false;
1036 : 778 : unsigned lastPrintableChar = 0;
1037 : :
1038 [ + + ]: 778 : if (!newLine)
1039 : : {
1040 : 18 : o << "\n";
1041 : : }
1042 : 778 : newLine = true;
1043 [ + - ]: 778 : if (lb < s->ub)
1044 : : {
1045 : 1126 : for (;;)
1046 : : {
1047 [ - + ][ # # ]: 1126 : if (!mask || lb > 0x00FF)
1048 : : {
1049 [ - + ]: 1126 : if (DFlag)
1050 : : {
1051 [ # # ][ # # ]: 0 : if ((lb >= 'A' && lb <= 'Z') || (lb >= 'a' && lb <= 'z') || (lb >= '0' && lb <= '9'))
[ # # ][ # # ]
[ # # ][ # # ]
1052 : : {
1053 [ # # ]: 0 : if (lastPrintableChar == 0)
1054 : : {
1055 : 0 : lastPrintableChar = lb;
1056 : : }
1057 : :
1058 [ # # ]: 0 : if (++lb == s->ub)
1059 : : {
1060 : 0 : break;
1061 : : }
1062 : 0 : continue;
1063 : : }
1064 : :
1065 : 0 : printDotCharInterval(o, lastPrintableChar, lb, from, to, true);
1066 : 0 : lastPrintableChar = 0;
1067 : : }
1068 : : else
1069 : : {
1070 [ + - ][ + - ]: 1126 : o << indent(ind) << "case ";
1071 : 1126 : prtChOrHex(o, lb);
1072 : 1126 : o << ":";
1073 [ - + ][ # # ]: 1126 : if (dFlag && eFlag && lb < 256u && isprint(talx[lb]))
[ # # ][ # # ]
1074 : : {
1075 [ # # ][ # # ]: 0 : o << " /* " << std::string(1, talx[lb]) << " */";
[ # # ][ # # ]
1076 : : }
1077 : : }
1078 : 1126 : newLine = false;
1079 : 1126 : used = true;
1080 : : }
1081 : :
1082 [ + + ]: 1126 : if (++lb == s->ub)
1083 : : {
1084 : 778 : break;
1085 : : }
1086 : :
1087 : 348 : o << "\n";
1088 : 348 : newLine = true;
1089 : : }
1090 : : }
1091 : :
1092 [ - + ]: 778 : if (lastPrintableChar != 0)
1093 : : {
1094 : 0 : printDotCharInterval(o, lastPrintableChar, lb, from, to, false);
1095 : :
1096 : 0 : o << "\n";
1097 : 0 : newLine = true;
1098 : : }
1099 : :
1100 : 778 : return used;
1101 : : }
1102 : :
1103 : 380 : void Go::genSwitch(std::ostream &o, unsigned ind, const State *from, const State *next, bool &readCh, unsigned mask) const
1104 : : {
1105 : 380 : bool newLine = true;
1106 : :
1107 [ - + ][ + + ]: 380 : if ((mask ? wSpans : nSpans) <= 2)
1108 : : {
1109 [ + - ]: 124 : genLinear(o, ind, from, next, readCh, mask);
1110 : : }
1111 : : else
1112 : : {
1113 : 256 : State *def = span[nSpans - 1].to;
1114 [ + - ][ + - ]: 256 : Span **sP = new Span * [nSpans - 1], **r, **s, **t;
1115 : :
1116 : 256 : t = &sP[0];
1117 : :
1118 [ + + ]: 1756 : for (unsigned i = 0; i < nSpans; ++i)
1119 : : {
1120 [ + + ]: 1500 : if (span[i].to != def)
1121 : : {
1122 : 778 : *(t++) = &span[i];
1123 : : }
1124 : : }
1125 : :
1126 [ + - ]: 256 : if (!DFlag)
1127 : : {
1128 [ - + ]: 256 : if (dFlag)
1129 : : {
1130 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["YYDEBUG"] << "(-1, " << mapCodeName["yych"] << ");\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1131 : : }
1132 : :
1133 [ - + ]: 256 : if (readCh)
1134 : : {
1135 [ # # ][ # # ]: 0 : o << indent(ind) << "switch ((" << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ")) {\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1136 : 0 : readCh = false;
1137 : : }
1138 : : else
1139 : : {
1140 [ + - ][ + - ]: 256 : o << indent(ind) << "switch (" << mapCodeName["yych"] << ") {\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1141 : : }
1142 : : }
1143 : :
1144 [ + + ]: 1016 : while (t != &sP[0])
1145 : : {
1146 : 760 : bool used = false;
1147 : :
1148 : 760 : r = s = &sP[0];
1149 : :
1150 : 760 : const State *to = (*s)->to;
1151 : :
1152 [ + + ]: 760 : if (*s == &span[0])
1153 : : {
1154 [ + - ]: 246 : used |= genCases(o, ind, 0, *s, newLine, mask, from, to);
1155 : : }
1156 : : else
1157 : : {
1158 [ + - ]: 514 : used |= genCases(o, ind, (*s)[ -1].ub, *s, newLine, mask, from, to);
1159 : : }
1160 : :
1161 [ + + ]: 1730 : while (++s < t)
1162 : : {
1163 [ + + ]: 970 : if ((*s)->to == to)
1164 : : {
1165 [ + - ]: 18 : used |= genCases(o, ind, (*s)[ -1].ub, *s, newLine, mask, from, to);
1166 : : }
1167 : : else
1168 : : {
1169 : 952 : *(r++) = *s;
1170 : : }
1171 : : }
1172 : :
1173 [ + - ][ + - ]: 760 : if (used && !DFlag)
1174 : : {
1175 [ - + ][ + - ]: 760 : genGoTo(o, newLine ? ind+1 : 1, from, to, readCh);
1176 : 760 : newLine = true;
1177 : : }
1178 : 760 : t = r;
1179 : : }
1180 : :
1181 [ - + ]: 256 : if (DFlag)
1182 : : {
1183 [ # # ]: 0 : if (!newLine)
1184 : : {
1185 [ # # ]: 0 : o << "\n";
1186 : 0 : newLine = true;
1187 : : }
1188 : :
1189 [ # # ][ # # ]: 0 : o << from->label << " -> " << def->label;
[ # # ]
1190 [ # # ]: 0 : o << " [label=default]\n" ;
1191 : : }
1192 : : else
1193 : : {
1194 [ + - ][ + - ]: 256 : o << indent(ind) << "default:";
[ + - ][ + - ]
1195 [ + - ]: 256 : genGoTo(o, 1, from, def, readCh);
1196 [ + - ][ + - ]: 256 : o << indent(ind) << "}\n";
[ + - ][ + - ]
1197 : : }
1198 : :
1199 [ + - ]: 256 : delete [] sP;
1200 : : }
1201 : 380 : }
1202 : :
1203 : 0 : static void doBinary(std::ostream &o, unsigned ind, Span *s, unsigned n, const State *from, const State *next, bool &readCh, unsigned mask)
1204 : : {
1205 [ # # ]: 0 : if (n <= 4)
1206 : : {
1207 : 0 : doLinear(o, ind, s, n, from, next, readCh, mask);
1208 : : }
1209 : : else
1210 : : {
1211 : 0 : unsigned h = n / 2;
1212 : :
1213 : 0 : genIf(o, ind, "<=", s[h - 1].ub - 1, readCh);
1214 : 0 : o << "{\n";
1215 : 0 : doBinary(o, ind+1, &s[0], h, from, next, readCh, mask);
1216 [ # # ][ # # ]: 0 : o << indent(ind) << "} else {\n";
1217 : 0 : doBinary(o, ind+1, &s[h], n - h, from, next, readCh, mask);
1218 [ # # ][ # # ]: 0 : o << indent(ind) << "}\n";
1219 : : }
1220 : 0 : }
1221 : :
1222 : 0 : void Go::genBinary(std::ostream &o, unsigned ind, const State *from, const State *next, bool &readCh, unsigned mask) const
1223 : : {
1224 [ # # ]: 0 : if (mask)
1225 : : {
1226 [ # # ]: 0 : Span * sc = new Span[wSpans];
1227 : :
1228 [ # # ]: 0 : for (unsigned i = 0, j = 0; i < nSpans; i++)
1229 : : {
1230 [ # # ]: 0 : if (span[i].ub > 0xFF)
1231 : : {
1232 : 0 : sc[j++] = span[i];
1233 : : }
1234 : : }
1235 : :
1236 : 0 : doBinary(o, ind, sc, wSpans, from, next, readCh, mask);
1237 : :
1238 [ # # ]: 0 : delete[] sc;
1239 : : }
1240 : : else
1241 : : {
1242 : 0 : doBinary(o, ind, span, nSpans, from, next, readCh, mask);
1243 : : }
1244 : 0 : }
1245 : :
1246 : 514 : void Go::genBase(std::ostream &o, unsigned ind, const State *from, const State *next, bool &readCh, unsigned mask) const
1247 : : {
1248 [ - + ][ + + ]: 514 : if ((mask ? wSpans : nSpans) == 0)
1249 : : {
1250 : 134 : return ;
1251 : : }
1252 : :
1253 [ + - ]: 380 : if (!sFlag)
1254 : : {
1255 : 380 : genSwitch(o, ind, from, next, readCh, mask);
1256 : 380 : return ;
1257 : : }
1258 : :
1259 [ # # ][ # # ]: 0 : if ((mask ? wSpans : nSpans) > 8)
1260 : : {
1261 : 0 : Span *bot = &span[0], *top = &span[nSpans - 1];
1262 : : unsigned util;
1263 : :
1264 [ # # ]: 0 : if (bot[0].to == top[0].to)
1265 : : {
1266 : 0 : util = (top[ -1].ub - bot[0].ub) / (nSpans - 2);
1267 : : }
1268 : : else
1269 : : {
1270 [ # # ]: 0 : if (bot[0].ub > (top[0].ub - top[ -1].ub))
1271 : : {
1272 : 0 : util = (top[0].ub - bot[0].ub) / (nSpans - 1);
1273 : : }
1274 : : else
1275 : : {
1276 : 0 : util = top[ -1].ub / (nSpans - 1);
1277 : : }
1278 : : }
1279 : :
1280 [ # # ]: 0 : if (util <= 2)
1281 : : {
1282 : 0 : genSwitch(o, ind, from, next, readCh, mask);
1283 : 0 : return ;
1284 : : }
1285 : : }
1286 : :
1287 [ # # ][ # # ]: 0 : if ((mask ? wSpans : nSpans) > 5)
1288 : : {
1289 : 0 : genBinary(o, ind, from, next, readCh, mask);
1290 : : }
1291 : : else
1292 : : {
1293 : 514 : genLinear(o, ind, from, next, readCh, mask);
1294 : : }
1295 : : }
1296 : :
1297 : 0 : void Go::genCpGoto(std::ostream &o, unsigned ind, const State *from, const State *next, bool &readCh) const
1298 : : {
1299 [ # # ]: 0 : std::string sYych;
1300 : :
1301 [ # # ]: 0 : if (readCh)
1302 : : {
1303 [ # # ][ # # ]: 0 : sYych = "(" + mapCodeName["yych"] + " = " + yychConversion + "*" + mapCodeName["YYCURSOR"] + ")";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1304 : : }
1305 : : else
1306 : : {
1307 [ # # ][ # # ]: 0 : sYych = mapCodeName["yych"];
1308 : : }
1309 : :
1310 : 0 : readCh = false;
1311 [ # # ]: 0 : if (wFlag)
1312 : : {
1313 [ # # ][ # # ]: 0 : o << indent(ind) << "if (" << sYych <<" & ~0xFF) {\n";
[ # # ][ # # ]
[ # # ][ # # ]
1314 [ # # ]: 0 : genBase(o, ind+1, from, next, readCh, 1);
1315 [ # # ][ # # ]: 0 : o << indent(ind++) << "} else {\n";
[ # # ][ # # ]
1316 [ # # ][ # # ]: 0 : sYych = mapCodeName["yych"];
1317 : : }
1318 : : else
1319 : : {
1320 [ # # ][ # # ]: 0 : o << indent(ind++) << "{\n";
[ # # ][ # # ]
1321 : : }
1322 [ # # ][ # # ]: 0 : o << indent(ind++) << "static void *" << mapCodeName["yytarget"] << "[256] = {\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1323 [ # # ][ # # ]: 0 : o << indent(ind);
[ # # ]
1324 : :
1325 : 0 : unsigned ch = 0;
1326 [ # # ]: 0 : for (unsigned i = 0; i < lSpans; ++i)
1327 : : {
1328 [ # # ]: 0 : vUsedLabels.insert(span[i].to->label);
1329 [ # # ]: 0 : for(; ch < span[i].ub; ++ch)
1330 : : {
1331 [ # # ][ # # ]: 0 : o << "&&" << labelPrefix << span[i].to->label;
[ # # ]
1332 [ # # ]: 0 : if (ch == 255)
1333 : : {
1334 [ # # ]: 0 : o << "\n";
1335 : 0 : i = lSpans;
1336 : 0 : break;
1337 : : }
1338 [ # # ]: 0 : else if (ch % 8 == 7)
1339 : : {
1340 [ # # ][ # # ]: 0 : o << ",\n" << indent(ind);
[ # # ][ # # ]
1341 : : }
1342 : : else
1343 : : {
1344 [ # # ][ # # ]: 0 : o << "," << space(span[i].to->label);
[ # # ][ # # ]
1345 : : }
1346 : : }
1347 : : }
1348 [ # # ][ # # ]: 0 : o << indent(--ind) << "};\n";
[ # # ][ # # ]
1349 [ # # ][ # # ]: 0 : o << indent(ind) << "goto *" << mapCodeName["yytarget"] << "[" << sYych << "];\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1350 [ # # ][ # # ]: 0 : o << indent(--ind) << "}\n";
[ # # ][ # # ]
[ # # ]
1351 : 0 : }
1352 : :
1353 : 514 : void Go::genGoto(std::ostream &o, unsigned ind, const State *from, const State *next, bool &readCh)
1354 : : {
1355 [ + - ][ - + ]: 514 : if ((gFlag || wFlag) && wSpans == ~0u)
[ # # ]
1356 : : {
1357 : 0 : unsigned nBitmaps = 0;
1358 [ # # ]: 0 : std::set<unsigned> vTargets;
1359 : 0 : wSpans = 0;
1360 : 0 : lSpans = 1;
1361 : 0 : dSpans = 0;
1362 [ # # ]: 0 : for (unsigned i = 0; i < nSpans; ++i)
1363 : : {
1364 [ # # ]: 0 : if (span[i].ub > 0xFF)
1365 : : {
1366 : 0 : wSpans++;
1367 : : }
1368 [ # # ][ # # ]: 0 : if (span[i].ub < 0x100 || !wFlag)
1369 : : {
1370 : 0 : lSpans++;
1371 : :
1372 : 0 : State *to = span[i].to;
1373 : :
1374 [ # # ][ # # ]: 0 : if (to && to->isBase)
1375 : : {
1376 : 0 : const BitMap *b = BitMap::find(to);
1377 : :
1378 [ # # ][ # # ]: 0 : if (b && matches(b->go, b->on, this, to))
[ # # ]
1379 : : {
1380 : 0 : nBitmaps++;
1381 : : }
1382 : : else
1383 : : {
1384 : 0 : dSpans++;
1385 [ # # ]: 0 : vTargets.insert(to->label);
1386 : 0 : }
1387 : : }
1388 : : else
1389 : : {
1390 : 0 : dSpans++;
1391 [ # # ]: 0 : vTargets.insert(to->label);
1392 : : }
1393 : : }
1394 : : }
1395 [ # # ][ # # ]: 0 : lTargets = vTargets.size() >> nBitmaps;
1396 : : }
1397 : :
1398 [ - + ][ # # ]: 514 : if (gFlag && (lTargets >= cGotoThreshold || dSpans >= cGotoThreshold))
[ # # ]
1399 : : {
1400 : 0 : genCpGoto(o, ind, from, next, readCh);
1401 : 0 : return;
1402 : : }
1403 [ - + ]: 514 : else if (bFlag)
1404 : : {
1405 [ # # ]: 0 : for (unsigned i = 0; i < nSpans; ++i)
1406 : : {
1407 : 0 : State *to = span[i].to;
1408 : :
1409 [ # # ][ # # ]: 0 : if (to && to->isBase)
1410 : : {
1411 : 0 : const BitMap *b = BitMap::find(to);
1412 [ # # ]: 0 : std::string sYych;
1413 : :
1414 [ # # ][ # # ]: 0 : if (b && matches(b->go, b->on, this, to))
[ # # ]
1415 : : {
1416 : 0 : Go go;
1417 [ # # ][ # # ]: 0 : go.span = new Span[nSpans];
1418 : 0 : go.unmap(this, to);
1419 [ # # ]: 0 : if (readCh)
1420 : : {
1421 [ # # ][ # # ]: 0 : sYych = "(" + mapCodeName["yych"] + " = " + yychConversion + "*" + mapCodeName["YYCURSOR"] + ")";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1422 : : }
1423 : : else
1424 : : {
1425 [ # # ][ # # ]: 0 : sYych = mapCodeName["yych"];
1426 : : }
1427 : 0 : readCh = false;
1428 [ # # ]: 0 : if (wFlag)
1429 : : {
1430 [ # # ][ # # ]: 0 : o << indent(ind) << "if (" << sYych << " & ~0xFF) {\n";
[ # # ][ # # ]
[ # # ][ # # ]
1431 [ # # ][ # # ]: 0 : sYych = mapCodeName["yych"];
1432 [ # # ]: 0 : genBase(o, ind+1, from, next, readCh, 1);
1433 [ # # ][ # # ]: 0 : o << indent(ind) << "} else ";
[ # # ][ # # ]
1434 : : }
1435 : : else
1436 : : {
1437 [ # # ][ # # ]: 0 : o << indent(ind);
[ # # ]
1438 : : }
1439 : 0 : bUsedYYBitmap = true;
1440 [ # # ][ # # ]: 0 : o << "if (" << mapCodeName["yybm"] << "[" << b->i << "+" << sYych << "] & ";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1441 [ # # ]: 0 : if (yybmHexTable)
1442 : : {
1443 [ # # ]: 0 : prtHex(o, b->m);
1444 : : }
1445 : : else
1446 : : {
1447 [ # # ]: 0 : o << (unsigned) b->m;
1448 : : }
1449 [ # # ]: 0 : o << ") {\n";
1450 [ # # ]: 0 : genGoTo(o, ind+1, from, to, readCh);
1451 [ # # ][ # # ]: 0 : o << indent(ind) << "}\n";
[ # # ][ # # ]
1452 [ # # ]: 0 : go.genBase(o, ind, from, next, readCh, 0);
1453 [ # # ]: 0 : delete [] go.span;
1454 : : return ;
1455 [ # # ][ # # ]: 0 : }
1456 : : }
1457 : : }
1458 : : }
1459 : :
1460 : 514 : genBase(o, ind, from, next, readCh, 0);
1461 : : }
1462 : :
1463 : 514 : void State::emit(std::ostream &o, unsigned ind, bool &readCh, const std::string& condName) const
1464 : : {
1465 [ + + ]: 514 : if (vUsedLabels.count(label))
1466 : : {
1467 : 355 : o << labelPrefix << label << ":\n";
1468 : : }
1469 [ - + ][ # # ]: 514 : if (dFlag && !action->isInitial())
[ - + ]
1470 : : {
1471 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", *" << mapCodeName["YYCURSOR"] << ");\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1472 : : }
1473 [ - + ]: 514 : if (isPreCtxt)
1474 : : {
1475 [ # # ][ # # ]: 0 : o << indent(ind) << mapCodeName["YYCTXMARKER"] << " = " << mapCodeName["YYCURSOR"] << " + 1;\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1476 : : }
1477 : 514 : action->emit(o, ind, readCh, condName);
1478 : 514 : }
1479 : :
1480 : 7 : static unsigned merge(Span *x0, State *fg, State *bg)
1481 : : {
1482 : 7 : Span *x = x0, *f = fg->go.span, *b = bg->go.span;
1483 : 7 : unsigned nf = fg->go.nSpans, nb = bg->go.nSpans;
1484 : 7 : State *prev = NULL, *to;
1485 : : // NB: we assume both spans are for same range
1486 : :
1487 : 7 : for (;;)
1488 : : {
1489 [ + - ]: 14 : if (f->ub == b->ub)
1490 : : {
1491 [ + + ]: 14 : to = f->to == b->to ? bg : f->to;
1492 : :
1493 [ - + ]: 14 : if (to == prev)
1494 : : {
1495 : 0 : --x;
1496 : : }
1497 : : else
1498 : : {
1499 : 14 : x->to = prev = to;
1500 : : }
1501 : :
1502 : 14 : x->ub = f->ub;
1503 : 14 : ++x;
1504 : 14 : ++f;
1505 : 14 : --nf;
1506 : 14 : ++b;
1507 : 14 : --nb;
1508 : :
1509 [ + + ][ + - ]: 14 : if (nf == 0 && nb == 0)
1510 : : {
1511 : 7 : return x - x0;
1512 : : }
1513 : : }
1514 : :
1515 [ + + ]: 17 : while (f->ub < b->ub)
1516 : : {
1517 [ + + ]: 10 : to = f->to == b->to ? bg : f->to;
1518 : :
1519 [ + + ]: 10 : if (to == prev)
1520 : : {
1521 : 5 : --x;
1522 : : }
1523 : : else
1524 : : {
1525 : 5 : x->to = prev = to;
1526 : : }
1527 : :
1528 : 10 : x->ub = f->ub;
1529 : 10 : ++x;
1530 : 10 : ++f;
1531 : 10 : --nf;
1532 : : }
1533 : :
1534 [ - + ]: 7 : while (b->ub < f->ub)
1535 : : {
1536 [ # # ]: 0 : to = b->to == f->to ? bg : f->to;
1537 : :
1538 [ # # ]: 0 : if (to == prev)
1539 : : {
1540 : 0 : --x;
1541 : : }
1542 : : else
1543 : : {
1544 : 0 : x->to = prev = to;
1545 : : }
1546 : :
1547 : 0 : x->ub = b->ub;
1548 : 0 : ++x;
1549 : 0 : ++b;
1550 : 0 : --nb;
1551 : : }
1552 : : }
1553 : : }
1554 : :
1555 : : static const unsigned cInfinity = ~0u;
1556 : :
1557 : : class SCC
1558 : : {
1559 : :
1560 : : public:
1561 : : State **top, **stk;
1562 : :
1563 : : public:
1564 : : SCC(unsigned);
1565 : : ~SCC();
1566 : : void traverse(State*);
1567 : :
1568 : : #ifdef PEDANTIC
1569 : : private:
1570 : : SCC(const SCC& oth)
1571 : : : top(oth.top)
1572 : : , stk(oth.stk)
1573 : : {
1574 : : }
1575 : : SCC& operator = (const SCC& oth)
1576 : : {
1577 : : new(this) SCC(oth);
1578 : : return *this;
1579 : : }
1580 : : #endif
1581 : : };
1582 : :
1583 : 24 : SCC::SCC(unsigned size)
1584 [ + - ]: 24 : : top(new State * [size])
1585 : 24 : , stk(top)
1586 : : {
1587 : 24 : }
1588 : :
1589 : 24 : SCC::~SCC()
1590 : : {
1591 [ + - ]: 24 : delete [] stk;
1592 : 24 : }
1593 : :
1594 : 155 : void SCC::traverse(State *x)
1595 : : {
1596 : 155 : *top = x;
1597 : 155 : unsigned k = ++top - stk;
1598 : 155 : x->depth = k;
1599 : :
1600 [ + + ]: 1028 : for (unsigned i = 0; i < x->go.nSpans; ++i)
1601 : : {
1602 : 873 : State *y = x->go.span[i].to;
1603 : :
1604 [ + + ]: 873 : if (y)
1605 : : {
1606 [ + + ]: 723 : if (y->depth == 0)
1607 : : {
1608 : 131 : traverse(y);
1609 : : }
1610 : :
1611 [ + + ]: 723 : if (y->depth < x->depth)
1612 : : {
1613 : 94 : x->depth = y->depth;
1614 : : }
1615 : : }
1616 : : }
1617 : :
1618 [ + + ]: 155 : if (x->depth == k)
1619 : : {
1620 [ + + ]: 155 : do
1621 : : {
1622 : 155 : (*--top)->depth = cInfinity;
1623 : 155 : (*top)->link = x;
1624 : : }
1625 : : while (*top != x);
1626 : : }
1627 : 155 : }
1628 : :
1629 : 131 : static bool state_is_in_non_trivial_SCC(const State* s)
1630 : : {
1631 : :
1632 : : // does not link to self
1633 [ + + ]: 131 : if (s->link != s)
1634 : : {
1635 : 94 : return true;
1636 : : }
1637 : :
1638 : : // or exists i: (s->go.spans[i].to->link == s)
1639 : : //
1640 : : // Note: (s->go.spans[i].to == s) is allowed, corresponds to s
1641 : : // looping back to itself.
1642 : : //
1643 [ + + ]: 91 : for (unsigned i = 0; i < s->go.nSpans; ++i)
1644 : : {
1645 : 79 : const State* t = s->go.span[i].to;
1646 : :
1647 [ + + ][ + + ]: 79 : if (t && t->link == s)
1648 : : {
1649 : 25 : return true;
1650 : : }
1651 : : }
1652 : : // otherwise no
1653 : 131 : return false;
1654 : : }
1655 : :
1656 : 322 : static unsigned maxDist(State *s)
1657 : : {
1658 [ + + ]: 322 : if (s->depth != cInfinity)
1659 : : {
1660 : : // Already calculated, just return result.
1661 : 167 : return s->depth;
1662 : : }
1663 : 155 : unsigned mm = 0;
1664 : :
1665 [ + + ]: 1028 : for (unsigned i = 0; i < s->go.nSpans; ++i)
1666 : : {
1667 : 873 : State *t = s->go.span[i].to;
1668 : :
1669 [ + + ]: 873 : if (t)
1670 : : {
1671 : 723 : unsigned m = 1;
1672 : :
1673 [ + + ]: 723 : if (!t->link) // marked as non-key state
1674 : : {
1675 [ + + ]: 13 : if (t->depth == cInfinity)
1676 : : {
1677 : 12 : t->depth = maxDist(t);
1678 : : }
1679 : 13 : m += t->depth;
1680 : : }
1681 : :
1682 [ + + ]: 723 : if (m > mm)
1683 : : {
1684 : 157 : mm = m;
1685 : : }
1686 : : }
1687 : : }
1688 : :
1689 : 155 : s->depth = mm;
1690 : 322 : return mm;
1691 : : }
1692 : :
1693 : 24 : static void calcDepth(State *head)
1694 : : {
1695 : : State* s;
1696 : :
1697 : : // mark non-key states by s->link = NULL ;
1698 [ + + ]: 179 : for (s = head; s; s = s->next)
1699 : : {
1700 [ + + ][ + + ]: 155 : if (s != head && !state_is_in_non_trivial_SCC(s))
[ + + ]
1701 : : {
1702 : 12 : s->link = NULL;
1703 : : }
1704 : : //else: key state, leave alone
1705 : : }
1706 : :
1707 [ + + ]: 179 : for (s = head; s; s = s->next)
1708 : : {
1709 : 155 : s->depth = cInfinity;
1710 : : }
1711 : :
1712 : : // calculate max number of transitions before guarantied to reach
1713 : : // a key state.
1714 [ + + ]: 179 : for (s = head; s; s = s->next)
1715 : : {
1716 : 155 : maxDist(s);
1717 : : }
1718 : 24 : }
1719 : :
1720 : 24 : void DFA::findSCCs()
1721 : : {
1722 [ + - ]: 24 : SCC scc(nStates);
1723 : : State *s;
1724 : :
1725 [ + + ]: 179 : for (s = head; s; s = s->next)
1726 : : {
1727 : 155 : s->depth = 0;
1728 : 155 : s->link = NULL;
1729 : : }
1730 : :
1731 [ + + ]: 179 : for (s = head; s; s = s->next)
1732 : : {
1733 [ + + ]: 155 : if (!s->depth)
1734 : : {
1735 [ + - ]: 24 : scc.traverse(s);
1736 : : }
1737 : : }
1738 : :
1739 [ + - ]: 24 : calcDepth(head);
1740 : 24 : }
1741 : :
1742 : 54 : void DFA::split(State *s)
1743 : : {
1744 [ + - ]: 54 : State *move = new State;
1745 [ + - ]: 54 : (void) new Move(move);
1746 : 54 : addState(&s->next, move);
1747 : 54 : move->link = s->link;
1748 : 54 : move->rule = s->rule;
1749 : 54 : move->go = s->go;
1750 : 54 : s->rule = NULL;
1751 : 54 : s->go.nSpans = 1;
1752 : 54 : s->go.span = new Span[1];
1753 : 54 : s->go.span[0].ub = ubChar;
1754 : 54 : s->go.span[0].to = move;
1755 : 54 : }
1756 : :
1757 : 24 : void DFA::findBaseState()
1758 : : {
1759 [ + - ]: 24 : Span *span = new Span[ubChar - lbChar];
1760 : :
1761 [ + + ]: 303 : for (State *s = head; s; s = s->next)
1762 : : {
1763 [ + + ]: 279 : if (!s->link)
1764 : : {
1765 [ + + ]: 101 : for (unsigned i = 0; i < s->go.nSpans; ++i)
1766 : : {
1767 : 19 : State *to = s->go.span[i].to;
1768 : :
1769 [ + - ][ + + ]: 19 : if (to && to->isBase)
1770 : : {
1771 : 7 : to = to->go.span[0].to;
1772 : 7 : unsigned nSpans = merge(span, s, to);
1773 : :
1774 [ + + ]: 7 : if (nSpans < s->go.nSpans)
1775 : : {
1776 [ + - ]: 5 : delete [] s->go.span;
1777 : 5 : s->go.nSpans = nSpans;
1778 [ + - ]: 5 : s->go.span = new Span[nSpans];
1779 : 5 : memcpy(s->go.span, span, nSpans*sizeof(Span));
1780 : : }
1781 : :
1782 : 7 : break;
1783 : : }
1784 : : }
1785 : : }
1786 : : }
1787 : :
1788 [ + - ]: 24 : delete [] span;
1789 : 24 : }
1790 : :
1791 : 24 : void DFA::prepare()
1792 : : {
1793 : : State *s;
1794 : : unsigned i;
1795 : :
1796 : 24 : bUsedYYBitmap = false;
1797 : :
1798 : 24 : findSCCs();
1799 : 24 : head->link = head;
1800 : :
1801 : 24 : unsigned nRules = 0;
1802 : :
1803 [ + + ]: 179 : for (s = head; s; s = s->next)
1804 : : {
1805 : 155 : s->depth = maxDist(s);
1806 [ + + ]: 155 : if (maxFill < s->depth)
1807 : : {
1808 : 2 : maxFill = s->depth;
1809 : : }
1810 [ + + ][ + + ]: 155 : if (s->rule && s->rule->accept >= nRules)
1811 : : {
1812 : 24 : nRules = s->rule->accept + 1;
1813 : : }
1814 : : }
1815 : :
1816 : 24 : unsigned nSaves = 0;
1817 [ + - ]: 24 : saves = new unsigned[nRules];
1818 : 24 : memset(saves, ~0, (nRules)*sizeof(*saves));
1819 : :
1820 : : // mark backtracking points
1821 : 24 : bSaveOnHead = false;
1822 : :
1823 [ + + ]: 179 : for (s = head; s; s = s->next)
1824 : : {
1825 [ + + ]: 155 : if (s->rule)
1826 : : {
1827 [ + + ]: 321 : for (i = 0; i < s->go.nSpans; ++i)
1828 : : {
1829 [ + + ][ + + ]: 265 : if (s->go.span[i].to && !s->go.span[i].to->rule)
1830 : : {
1831 [ + - ]: 187 : delete s->action;
1832 : 187 : s->action = NULL;
1833 : :
1834 [ + + ]: 187 : if (saves[s->rule->accept] == ~0u)
1835 : : {
1836 : 43 : saves[s->rule->accept] = nSaves++;
1837 : : }
1838 : :
1839 : 187 : bSaveOnHead |= s == head;
1840 [ + - ]: 187 : (void) new Save(s, saves[s->rule->accept]); // sets s->action
1841 : : }
1842 : : }
1843 : : }
1844 : : }
1845 : :
1846 : : // insert actions
1847 [ + - ]: 24 : rules = new State * [nRules];
1848 : :
1849 : 24 : memset(rules, 0, (nRules)*sizeof(*rules));
1850 : :
1851 : 24 : State *accept = NULL;
1852 : 24 : Accept *accfixup = NULL;
1853 : :
1854 [ + + ]: 249 : for (s = head; s; s = s->next)
1855 : : {
1856 : : State * ow;
1857 : :
1858 [ + + ]: 225 : if (!s->rule)
1859 : : {
1860 : 169 : ow = accept;
1861 : : }
1862 : : else
1863 : : {
1864 [ + + ]: 56 : if (!rules[s->rule->accept])
1865 : : {
1866 [ + - ]: 47 : State *n = new State;
1867 [ + - ]: 47 : (void) new Rule(n, s->rule);
1868 : 47 : rules[s->rule->accept] = n;
1869 : 47 : addState(&s->next, n);
1870 : : }
1871 : :
1872 : 56 : ow = rules[s->rule->accept];
1873 : : }
1874 : :
1875 [ + + ]: 1098 : for (i = 0; i < s->go.nSpans; ++i)
1876 : : {
1877 [ + + ]: 873 : if (!s->go.span[i].to)
1878 : : {
1879 [ + + ]: 150 : if (!ow)
1880 : : {
1881 [ + - ]: 23 : ow = accept = new State;
1882 [ + - ]: 23 : accfixup = new Accept(accept, nRules, saves, rules);
1883 : 23 : addState(&s->next, accept);
1884 : : }
1885 : :
1886 : 150 : s->go.span[i].to = ow;
1887 : : }
1888 : : }
1889 : : }
1890 : :
1891 [ + + ]: 24 : if (accfixup)
1892 : : {
1893 : 23 : accfixup->genRuleMap();
1894 : : }
1895 : :
1896 : : // split ``base'' states into two parts
1897 [ + + ]: 249 : for (s = head; s; s = s->next)
1898 : : {
1899 : 225 : s->isBase = false;
1900 : :
1901 [ + + ]: 225 : if (s->link)
1902 : : {
1903 [ + + ]: 842 : for (i = 0; i < s->go.nSpans; ++i)
1904 : : {
1905 [ + + ]: 699 : if (s->go.span[i].to == s)
1906 : : {
1907 : 54 : s->isBase = true;
1908 : 54 : split(s);
1909 : :
1910 [ - + ]: 54 : if (bFlag)
1911 : : {
1912 : 0 : BitMap::find(&s->next->go, s);
1913 : : }
1914 : :
1915 : 54 : s = s->next;
1916 : 54 : break;
1917 : : }
1918 : : }
1919 : : }
1920 : : }
1921 : :
1922 : : // find ``base'' state, if possible
1923 : 24 : findBaseState();
1924 : :
1925 [ + - ]: 24 : delete head->action;
1926 : 24 : head->action = NULL;
1927 : 24 : }
1928 : :
1929 : : /* TODOXXX: this stuff is needed for DFA::emit */
1930 : :
1931 : : template<class _E, class _Tr = std::char_traits<_E> >
1932 [ - + ]: 46 : class basic_null_streambuf
1933 : : : public std::basic_streambuf<_E, _Tr>
1934 : : {
1935 : : public:
1936 : 23 : basic_null_streambuf()
1937 : 23 : : std::basic_streambuf<_E, _Tr>()
1938 : : {
1939 : : }
1940 : : };
1941 : :
1942 : : typedef basic_null_streambuf<char> null_streambuf;
1943 : :
1944 : : template<class _E, class _Tr = std::char_traits<_E> >
1945 : : class basic_null_stream
1946 : : : public std::basic_ostream<_E, _Tr>
1947 : : {
1948 : : public:
1949 : 23 : basic_null_stream()
1950 [ + - ][ + - ]: 23 : : std::basic_ostream<_E, _Tr>(null_buf = new basic_null_streambuf<_E, _Tr>())
[ + - ]
1951 : : {
1952 : : }
1953 : :
1954 : 23 : virtual ~basic_null_stream()
1955 : : {
1956 [ + - ][ + - ]: 23 : delete null_buf;
[ + - ][ + - ]
[ - + ][ # # ]
1957 : 0 : }
1958 : :
1959 : : basic_null_stream& put(_E)
1960 : : {
1961 : : // nothing to do
1962 : : return *this;
1963 : : }
1964 : :
1965 : : basic_null_stream& write(const _E *, std::streamsize)
1966 : : {
1967 : : // nothing to do
1968 : : return *this;
1969 : : }
1970 : :
1971 : : protected:
1972 : : basic_null_streambuf<_E, _Tr> * null_buf;
1973 : : };
1974 : :
1975 : : typedef basic_null_stream<char> null_stream;
1976 : :
1977 : :
1978 : 23 : void DFA::emit(std::ostream &o, unsigned& ind, const RegExpMap* specMap, const std::string& condName, bool isLastCond, bool& bPrologBrace)
1979 : : {
1980 [ - + ][ # # ]: 23 : bool bProlog = (!cFlag || !bWroteCondCheck);
1981 : :
1982 [ + - ]: 23 : if (!cFlag)
1983 : : {
1984 : 23 : bUsedYYAccept = false;
1985 : : }
1986 : :
1987 : : // In -c mode, the prolog needs its own label separate from start_label.
1988 : : // prolog_label is before the condition branch (GenCondGoto). It is
1989 : : // equivalent to startLabelName.
1990 : : // start_label corresponds to current condition.
1991 : : // NOTE: prolog_label must be yy0 because of the !getstate:re2c handling
1992 : : // in scanner.re
1993 : 23 : unsigned prolog_label = next_label;
1994 [ + - ][ - + ]: 23 : if (bProlog && cFlag)
1995 : : {
1996 : 0 : next_label++;
1997 : : }
1998 : :
1999 : 23 : unsigned start_label = next_label;
2000 : :
2001 [ + - ][ + - ]: 23 : (void) new Initial(head, next_label++, bSaveOnHead);
2002 : :
2003 [ - + ]: 23 : if (bUseStartLabel)
2004 : : {
2005 [ # # ][ # # ]: 0 : if (startLabelName.empty())
2006 : : {
2007 [ # # ]: 0 : vUsedLabels.insert(prolog_label);
2008 : : }
2009 : : }
2010 : :
2011 : : State *s;
2012 : :
2013 [ + + ]: 280 : for (s = head; s; s = s->next)
2014 : : {
2015 : 257 : s->label = next_label++;
2016 : : }
2017 : :
2018 : : // Save 'next_fill_index' and compute information about code generation
2019 : : // while writing to null device.
2020 : 23 : unsigned save_fill_index = next_fill_index;
2021 [ + - ]: 23 : null_stream null_dev;
2022 : :
2023 [ + + ]: 280 : for (s = head; s; s = s->next)
2024 : : {
2025 : 257 : bool readCh = false;
2026 [ + - ]: 257 : s->emit(null_dev, ind, readCh, condName);
2027 [ + - ]: 257 : s->go.genGoto(null_dev, ind, s, s->next, readCh);
2028 : : }
2029 [ - + ]: 23 : if (last_fill_index < next_fill_index)
2030 : : {
2031 : 0 : last_fill_index = next_fill_index;
2032 : : }
2033 : 23 : next_fill_index = save_fill_index;
2034 : :
2035 : : // Generate prolog
2036 [ + - ]: 23 : if (bProlog)
2037 : : {
2038 : :
2039 [ - + ]: 23 : if (DFlag)
2040 : : {
2041 : 0 : bPrologBrace = true;
2042 [ # # ]: 0 : o << "digraph re2c {\n";
2043 : : }
2044 [ + - ][ + + ]: 23 : else if ((!fFlag && bUsedYYAccept)
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
2045 : 3 : || (!fFlag && bEmitYYCh)
2046 : 0 : || (bFlag && !cFlag && BitMap::first)
2047 [ # # ]: 0 : || (cFlag && !bWroteCondCheck && gFlag && !specMap->empty())
2048 : 0 : || (fFlag && !bWroteGetState && gFlag)
2049 : : )
2050 : : {
2051 : 23 : bPrologBrace = true;
2052 [ + - ][ + - ]: 23 : o << indent(ind++) << "{\n";
[ + - ][ + - ]
2053 : : }
2054 [ # # ]: 0 : else if (ind == 0)
2055 : : {
2056 : 0 : ind = 1;
2057 : : }
2058 : :
2059 [ + - ][ + - ]: 23 : if (!fFlag && !DFlag)
2060 : : {
2061 [ + - ]: 23 : if (bEmitYYCh)
2062 : : {
2063 [ + - ][ + - ]: 23 : o << indent(ind) << mapCodeName["YYCTYPE"] << " " << mapCodeName["yych"] << ";\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2064 : : }
2065 [ + + ]: 43 : if (bUsedYYAccept)
2066 : : {
2067 [ + - ][ + - ]: 20 : o << indent(ind) << "unsigned int " << mapCodeName["yyaccept"] << " = 0;\n";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2068 : : }
2069 : : }
2070 : : else
2071 : : {
2072 [ # # ]: 23 : o << "\n";
2073 : : }
2074 : : }
2075 [ - + ][ # # ]: 23 : if (bFlag && !cFlag && BitMap::first)
[ # # ]
2076 : : {
2077 [ # # ]: 0 : BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
2078 : : }
2079 [ + - ]: 23 : if (bProlog)
2080 : : {
2081 [ + - ]: 23 : genCondTable(o, ind, *specMap);
2082 [ + - ]: 23 : genGetStateGoto(o, ind, prolog_label);
2083 [ - + ][ # # ]: 23 : if (cFlag && !DFlag)
2084 : : {
2085 [ # # ][ # # ]: 0 : if (vUsedLabels.count(prolog_label))
2086 : : {
2087 [ # # ][ # # ]: 0 : o << labelPrefix << prolog_label << ":\n";
[ # # ]
2088 : : }
2089 [ # # ][ # # ]: 0 : if (!startLabelName.empty())
2090 : : {
2091 [ # # ][ # # ]: 0 : o << startLabelName << ":\n";
2092 : : }
2093 : : }
2094 [ + - ]: 23 : genCondGoto(o, ind, *specMap);
2095 : : }
2096 : :
2097 [ - + ][ # # ]: 23 : if (cFlag && !condName.empty())
[ # # ][ - + ]
2098 : : {
2099 [ # # ][ # # ]: 0 : if (condDivider.length())
2100 : : {
2101 [ # # ][ # # ]: 0 : o << replaceParam(condDivider, condDividerParam, condName) << "\n";
[ # # ][ # # ]
[ # # ][ # # ]
2102 : : }
2103 : :
2104 [ # # ]: 0 : if (DFlag)
2105 : : {
2106 [ # # ][ # # ]: 0 : o << condName << " -> " << (start_label+1) << "\n";
[ # # ][ # # ]
2107 : : }
2108 : : else
2109 : : {
2110 [ # # ][ # # ]: 0 : o << condPrefix << condName << ":\n";
[ # # ]
2111 : : }
2112 : : }
2113 [ - + ][ # # ]: 23 : if (cFlag && bFlag && BitMap::first)
[ # # ]
2114 : : {
2115 [ # # ][ # # ]: 0 : o << indent(ind++) << "{\n";
[ # # ][ # # ]
2116 [ # # ]: 0 : BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
2117 : : }
2118 : :
2119 : : // The start_label is not always the first to be emitted, so we may have to jump. c.f. Initial::emit()
2120 [ + - ][ - + ]: 23 : if (vUsedLabels.count(start_label+1))
2121 : : {
2122 [ # # ]: 0 : vUsedLabels.insert(start_label);
2123 [ # # ][ # # ]: 0 : o << indent(ind) << "goto " << labelPrefix << start_label << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2124 : : }
2125 : :
2126 : : // Generate code
2127 [ + + ]: 280 : for (s = head; s; s = s->next)
2128 : : {
2129 : 257 : bool readCh = false;
2130 [ + - ]: 257 : s->emit(o, ind, readCh, condName);
2131 [ + - ]: 257 : s->go.genGoto(o, ind, s, s->next, readCh);
2132 : : }
2133 : :
2134 [ - + ][ # # ]: 23 : if (cFlag && bFlag && BitMap::first)
[ # # ]
2135 : : {
2136 [ # # ][ # # ]: 0 : o << indent(--ind) << "}\n";
[ # # ][ # # ]
2137 : : }
2138 : : // Generate epilog
2139 [ - + ][ # # ]: 23 : if ((!cFlag || isLastCond) && bPrologBrace)
[ + - ]
2140 : : {
2141 [ + - ][ + - ]: 23 : o << indent(--ind) << "}\n";
[ + - ][ + - ]
2142 : : }
2143 : :
2144 : : // Cleanup
2145 [ - + ]: 23 : if (BitMap::first)
2146 : : {
2147 [ # # ][ # # ]: 0 : delete BitMap::first;
2148 : 0 : BitMap::first = NULL;
2149 : : }
2150 : :
2151 [ + - ]: 23 : bUseStartLabel = false;
2152 : 23 : }
2153 : :
2154 : 0 : static void genGetStateGotoSub(std::ostream &o, unsigned ind, unsigned start_label, int cMin, int cMax)
2155 : : {
2156 [ # # ]: 0 : if (cMin == cMax)
2157 : : {
2158 [ # # ]: 0 : if (cMin == -1)
2159 : : {
2160 [ # # ][ # # ]: 0 : o << indent(ind) << "goto " << labelPrefix << start_label << ";\n";
[ # # ][ # # ]
[ # # ]
2161 : : }
2162 : : else
2163 : : {
2164 [ # # ][ # # ]: 0 : o << indent(ind) << "goto " << mapCodeName["yyFillLabel"] << cMin << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
2165 : : }
2166 : : }
2167 : : else
2168 : : {
2169 : 0 : int cMid = cMin + ((cMax - cMin + 1) / 2);
2170 : :
2171 [ # # ][ # # ]: 0 : o << indent(ind) << "if (" << genGetState() << " < " << cMid << ") {\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2172 : 0 : genGetStateGotoSub(o, ind + 1, start_label, cMin, cMid - 1);
2173 [ # # ][ # # ]: 0 : o << indent(ind) << "} else {\n";
2174 : 0 : genGetStateGotoSub(o, ind + 1, start_label, cMid, cMax);
2175 [ # # ][ # # ]: 0 : o << indent(ind) << "}\n";
2176 : : }
2177 : 0 : }
2178 : :
2179 : 23 : void genGetStateGoto(std::ostream &o, unsigned& ind, unsigned start_label)
2180 : : {
2181 [ - + ][ # # ]: 23 : if (fFlag && !bWroteGetState)
2182 : : {
2183 : 0 : vUsedLabels.insert(start_label);
2184 [ # # ]: 0 : if (gFlag)
2185 : : {
2186 [ # # ][ # # ]: 0 : o << indent(ind++) << "static void *" << mapCodeName["yystable"] << "[" << "] = {\n";
[ # # ][ # # ]
[ # # ][ # # ]
2187 : :
2188 [ # # ]: 0 : for (size_t i=0; i<last_fill_index; ++i)
2189 : : {
2190 [ # # ][ # # ]: 0 : o << indent(ind) << "&&" << mapCodeName["yyFillLabel"] << i << ",\n";
[ # # ][ # # ]
[ # # ][ # # ]
2191 : : }
2192 : :
2193 [ # # ][ # # ]: 0 : o << indent(--ind) << "};\n";
2194 : 0 : o << "\n";
2195 : :
2196 [ # # ][ # # ]: 0 : o << indent(ind) << "if (" << genGetState();
[ # # ][ # # ]
[ # # ]
2197 [ # # ]: 0 : if (bUseStateAbort)
2198 : : {
2199 : 0 : o << " == -1) {\n";
2200 : : }
2201 : : else
2202 : : {
2203 : 0 : o << " < 0) {\n";
2204 : : }
2205 [ # # ][ # # ]: 0 : o << indent(++ind) << "goto " << labelPrefix << start_label << ";\n";
[ # # ][ # # ]
[ # # ]
2206 [ # # ]: 0 : if (bUseStateAbort)
2207 : : {
2208 [ # # ][ # # ]: 0 : o << indent(--ind) << "} else if (" << genGetState() << " < -1) {\n";
[ # # ][ # # ]
[ # # ][ # # ]
2209 [ # # ][ # # ]: 0 : o << indent(++ind) << "abort();\n";
2210 : : }
2211 [ # # ][ # # ]: 0 : o << indent(--ind) << "}\n";
2212 : :
2213 [ # # ][ # # ]: 0 : o << indent(ind) << "goto *" << mapCodeName["yystable"] << "[" << genGetState() << "];\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2214 : : }
2215 [ # # ]: 0 : else if (bFlag)
2216 : : {
2217 : 0 : genGetStateGotoSub(o, ind, start_label, -1, last_fill_index-1);
2218 [ # # ]: 0 : if (bUseStateAbort)
2219 : : {
2220 [ # # ][ # # ]: 0 : o << indent(ind) << "abort();\n";
2221 : : }
2222 : : }
2223 : : else
2224 : : {
2225 [ # # ][ # # ]: 0 : o << indent(ind) << "switch (" << genGetState() << ") {\n";
[ # # ][ # # ]
[ # # ][ # # ]
2226 [ # # ]: 0 : if (bUseStateAbort)
2227 : : {
2228 [ # # ][ # # ]: 0 : o << indent(ind) << "default: abort();\n";
2229 [ # # ][ # # ]: 0 : o << indent(ind) << "case -1: goto " << labelPrefix << start_label << ";\n";
[ # # ][ # # ]
[ # # ]
2230 : : }
2231 : : else
2232 : : {
2233 [ # # ][ # # ]: 0 : o << indent(ind) << "default: goto " << labelPrefix << start_label << ";\n";
[ # # ][ # # ]
[ # # ]
2234 : : }
2235 : :
2236 [ # # ]: 0 : for (size_t i=0; i<last_fill_index; ++i)
2237 : : {
2238 [ # # ][ # # ]: 0 : o << indent(ind) << "case " << i << ": goto " << mapCodeName["yyFillLabel"] << i << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2239 : : }
2240 : :
2241 [ # # ][ # # ]: 0 : o << indent(ind) << "}\n";
2242 : : }
2243 [ # # ]: 0 : if (bUseStateNext)
2244 : : {
2245 : 0 : o << mapCodeName["yyNext"] << ":\n";
2246 : : }
2247 : 0 : bWroteGetState = true;
2248 : : }
2249 : 23 : }
2250 : :
2251 : 23 : void genCondTable(std::ostream &o, unsigned ind, const RegExpMap& specMap)
2252 : : {
2253 [ - + ][ # # ]: 23 : if (cFlag && !bWroteCondCheck && gFlag && specMap.size())
[ # # ][ # # ]
[ - + ]
2254 : : {
2255 [ # # ][ # # ]: 0 : RegExpIndices vCondList(specMap.size());
[ # # ][ # # ]
2256 : :
2257 [ # # ][ # # ]: 0 : for(RegExpMap::const_iterator itSpec = specMap.begin(); itSpec != specMap.end(); ++itSpec)
[ # # ]
2258 : : {
2259 [ # # ][ # # ]: 0 : vCondList[itSpec->second.first] = itSpec->first;
[ # # ]
2260 : : }
2261 : :
2262 [ # # ][ # # ]: 0 : o << indent(ind++) << "static void *" << mapCodeName["yyctable"] << "[" << specMap.size() << "] = {\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2263 : :
2264 [ # # ][ # # ]: 0 : for(RegExpIndices::const_iterator it = vCondList.begin(); it != vCondList.end(); ++it)
[ # # ][ # # ]
[ # # ]
2265 : : {
2266 [ # # ][ # # ]: 0 : o << indent(ind) << "&&" << condPrefix << *it << ",\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2267 : : }
2268 [ # # ][ # # ]: 0 : o << indent(--ind) << "};\n";
[ # # ][ # # ]
[ # # ]
2269 : : }
2270 : 23 : }
2271 : :
2272 : 0 : static void genCondGotoSub(std::ostream &o, unsigned ind, RegExpIndices& vCondList, unsigned cMin, unsigned cMax)
2273 : : {
2274 [ # # ]: 0 : if (cMin == cMax)
2275 : : {
2276 [ # # ][ # # ]: 0 : o << indent(ind) << "goto " << condPrefix << vCondList[cMin] << ";\n";
[ # # ][ # # ]
[ # # ]
2277 : : }
2278 : : else
2279 : : {
2280 : 0 : unsigned cMid = cMin + ((cMax - cMin + 1) / 2);
2281 : :
2282 [ # # ][ # # ]: 0 : o << indent(ind) << "if (" << genGetCondition() << " < " << cMid << ") {\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2283 : 0 : genCondGotoSub(o, ind + 1, vCondList, cMin, cMid - 1);
2284 [ # # ][ # # ]: 0 : o << indent(ind) << "} else {\n";
2285 : 0 : genCondGotoSub(o, ind + 1, vCondList, cMid, cMax);
2286 [ # # ][ # # ]: 0 : o << indent(ind) << "}\n";
2287 : : }
2288 : 0 : }
2289 : :
2290 : 23 : void genCondGoto(std::ostream &o, unsigned ind, const RegExpMap& specMap)
2291 : : {
2292 [ - + ][ # # ]: 23 : if (cFlag && !bWroteCondCheck && specMap.size())
[ # # ][ - + ]
2293 : : {
2294 [ # # ]: 0 : if (gFlag)
2295 : : {
2296 [ # # ][ # # ]: 0 : o << indent(ind) << "goto *" << mapCodeName["yyctable"] << "[" << genGetCondition() << "];\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2297 : : }
2298 : : else
2299 : : {
2300 [ # # ]: 0 : if (sFlag)
2301 : : {
2302 [ # # ][ # # ]: 0 : RegExpIndices vCondList(specMap.size());
[ # # ][ # # ]
2303 : :
2304 [ # # ][ # # ]: 0 : for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
[ # # ]
2305 : : {
2306 [ # # ][ # # ]: 0 : vCondList[it->second.first] = it->first;
[ # # ]
2307 : : }
2308 [ # # ][ # # ]: 0 : genCondGotoSub(o, ind, vCondList, 0, vCondList.size() - 1);
2309 : : }
2310 [ # # ]: 0 : else if (DFlag)
2311 : : {
2312 [ # # ][ # # ]: 0 : for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
[ # # ]
2313 : : {
2314 [ # # ][ # # ]: 0 : o << "0 -> " << it->first << " [label=\"state=" << it->first << "\"]\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2315 : : }
2316 : : }
2317 : : else
2318 : : {
2319 [ # # ][ # # ]: 0 : o << indent(ind) << "switch (" << genGetCondition() << ") {\n";
[ # # ][ # # ]
[ # # ][ # # ]
2320 : :
2321 [ # # ][ # # ]: 0 : for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it)
[ # # ]
2322 : : {
2323 [ # # ][ # # ]: 0 : o << indent(ind) << "case " << condEnumPrefix << it->first << ": goto " << condPrefix << it->first << ";\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2324 : : }
2325 [ # # ][ # # ]: 0 : o << indent(ind) << "}\n";
2326 : : }
2327 : : }
2328 : 0 : bWroteCondCheck = true;
2329 : : }
2330 : 23 : }
2331 : :
2332 : 0 : void genTypes(std::string& o, unsigned ind, const RegExpMap& specMap)
2333 : : {
2334 [ # # ]: 0 : o.clear();
2335 : :
2336 [ # # ][ # # ]: 0 : o += indent(ind++) + "enum " + mapCodeName["YYCONDTYPE"] + " {\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2337 : :
2338 [ # # ][ # # ]: 0 : RegExpIndices vCondList(specMap.size());
[ # # ][ # # ]
2339 : :
2340 [ # # ][ # # ]: 0 : for(RegExpMap::const_iterator itSpecMap = specMap.begin(); itSpecMap != specMap.end(); ++itSpecMap)
[ # # ]
2341 : : {
2342 : : // If an entry is < 0 then we did the 0/empty correction twice.
2343 [ # # ]: 0 : assert(itSpecMap->second.first >= 0);
2344 [ # # ][ # # ]: 0 : vCondList[itSpecMap->second.first] = itSpecMap->first;
[ # # ]
2345 : : }
2346 : :
2347 [ # # ][ # # ]: 0 : for(RegExpIndices::const_iterator itCondType = vCondList.begin(); itCondType != vCondList.end(); ++itCondType)
[ # # ][ # # ]
[ # # ]
2348 : : {
2349 [ # # ][ # # ]: 0 : o += indent(ind) + condEnumPrefix + *itCondType + ",\n";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2350 : : }
2351 : :
2352 [ # # ][ # # ]: 0 : o += indent(--ind) + "};\n";
[ # # ][ # # ]
[ # # ][ # # ]
2353 : 0 : }
2354 : :
2355 : 0 : void genHeader(std::ostream &o, unsigned ind, const RegExpMap& specMap)
2356 : : {
2357 : 0 : o << "/* Generated by re2c " PACKAGE_VERSION;
2358 [ # # ]: 0 : if (!bNoGenerationDate)
2359 : : {
2360 [ # # ]: 0 : o << " on ";
2361 : 0 : time_t now = time(&now);
2362 [ # # ]: 0 : o.write(ctime(&now), 24);
2363 : : }
2364 : 0 : o << " */\n";
2365 : 0 : o << "\n";
2366 : : // now the type(s)
2367 : 0 : genTypes(typesInline, ind, specMap);
2368 : 0 : o << typesInline;
2369 : 0 : }
2370 : :
2371 : 0 : void Scanner::config(const Str& cfg, int num)
2372 : : {
2373 [ # # ][ # # ]: 0 : if (cfg.to_string() == "indent:top")
2374 : : {
2375 [ # # ]: 0 : if (num < 0)
2376 : : {
2377 : 0 : fatal("configuration 'indent:top' must be a positive integer");
2378 : : }
2379 : 0 : topIndent = num;
2380 : : }
2381 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "yybm:hex")
2382 : : {
2383 : 0 : yybmHexTable = num != 0;
2384 : : }
2385 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "startlabel")
2386 : : {
2387 : 0 : bUseStartLabel = num != 0;
2388 : 0 : startLabelName = "";
2389 : : }
2390 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "state:abort")
2391 : : {
2392 : 0 : bUseStateAbort = num != 0;
2393 : : }
2394 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "state:nextlabel")
2395 : : {
2396 : 0 : bUseStateNext = num != 0;
2397 : : }
2398 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "yyfill:enable")
2399 : : {
2400 : 0 : bUseYYFill = num != 0;
2401 : : }
2402 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "yyfill:parameter")
2403 : : {
2404 : 0 : bUseYYFillParam = num != 0;
2405 : : }
2406 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "yyfill:check")
2407 : : {
2408 : 0 : bUseYYFillCheck = num != 0;
2409 : : }
2410 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "cgoto:threshold")
2411 : : {
2412 : 0 : cGotoThreshold = num;
2413 : : }
2414 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "yych:conversion")
2415 : : {
2416 [ # # ]: 0 : if (num)
2417 : : {
2418 : 0 : yychConversion = "(";
2419 : 0 : yychConversion += mapCodeName["YYCTYPE"];
2420 : 0 : yychConversion += ")";
2421 : : }
2422 : : else
2423 : : {
2424 : 0 : yychConversion = "";
2425 : : }
2426 : : }
2427 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "yych:emit")
2428 : : {
2429 : 0 : bEmitYYCh = num != 0;
2430 : : }
2431 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "define:YYFILL:naked")
2432 : : {
2433 : 0 : bUseYYFillNaked = num != 0;
2434 : : }
2435 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "define:YYGETCONDITION:naked")
2436 : : {
2437 : 0 : bUseYYGetConditionNaked = num != 0;
2438 : : }
2439 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "define:YYGETSTATE:naked")
2440 : : {
2441 : 0 : bUseYYGetStateNaked = num != 0;
2442 : : }
2443 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "define:YYSETSTATE:naked")
2444 : : {
2445 : 0 : bUseYYSetStateNaked = num != 0;
2446 : : }
2447 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "flags:u")
2448 : : {
2449 [ # # ]: 0 : if (!rFlag)
2450 : : {
2451 [ # # ][ # # ]: 0 : fatalf("cannot use configuration name '%s' without -r flag", cfg.to_string().c_str());
2452 : : }
2453 : 0 : uFlag = num != 0;
2454 : : }
2455 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "flags:w")
2456 : : {
2457 [ # # ]: 0 : if (!rFlag)
2458 : : {
2459 [ # # ][ # # ]: 0 : fatalf("cannot use configuration name '%s' without -r flag", cfg.to_string().c_str());
2460 : : }
2461 : 0 : wFlag = num != 0;
2462 : : }
2463 : : else
2464 : : {
2465 [ # # ][ # # ]: 0 : fatalf("unrecognized configuration name '%s' or illegal integer value", cfg.to_string().c_str());
2466 : : }
2467 : 0 : }
2468 : :
2469 : 2414 : static std::set<std::string> mapVariableKeys;
2470 : 2414 : static std::set<std::string> mapDefineKeys;
2471 : 2414 : static std::set<std::string> mapLabelKeys;
2472 : :
2473 : 0 : void Scanner::config(const Str& cfg, const Str& val)
2474 : : {
2475 [ # # ][ # # ]: 0 : if (mapDefineKeys.empty())
2476 : : {
2477 [ # # ][ # # ]: 0 : mapVariableKeys.insert("variable:yyaccept");
[ # # ]
2478 [ # # ][ # # ]: 0 : mapVariableKeys.insert("variable:yybm");
[ # # ]
2479 [ # # ][ # # ]: 0 : mapVariableKeys.insert("variable:yych");
[ # # ]
2480 [ # # ][ # # ]: 0 : mapVariableKeys.insert("variable:yyctable");
[ # # ]
2481 [ # # ][ # # ]: 0 : mapVariableKeys.insert("variable:yystable");
[ # # ]
2482 [ # # ][ # # ]: 0 : mapVariableKeys.insert("variable:yytarget");
[ # # ]
2483 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYCONDTYPE");
[ # # ]
2484 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYCTXMARKER");
[ # # ]
2485 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYCTYPE");
[ # # ]
2486 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYCURSOR");
[ # # ]
2487 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYDEBUG");
[ # # ]
2488 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYFILL");
[ # # ]
2489 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYGETCONDITION");
[ # # ]
2490 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYGETSTATE");
[ # # ]
2491 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYLIMIT");
[ # # ]
2492 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYMARKER");
[ # # ]
2493 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYSETCONDITION");
[ # # ]
2494 [ # # ][ # # ]: 0 : mapDefineKeys.insert("define:YYSETSTATE");
[ # # ]
2495 [ # # ][ # # ]: 0 : mapLabelKeys.insert("label:yyFillLabel");
[ # # ]
2496 [ # # ][ # # ]: 0 : mapLabelKeys.insert("label:yyNext");
[ # # ]
2497 : : }
2498 : :
2499 [ # # ]: 0 : std::string strVal;
2500 : :
2501 [ # # ][ # # ]: 0 : if (val.len >= 2 && val.str[0] == val.str[val.len-1]
[ # # ][ # # ]
2502 : 0 : && (val.str[0] == '"' || val.str[0] == '\''))
2503 : : {
2504 : 0 : SubStr tmp(val.str + 1, val.len - 2);
2505 [ # # ]: 0 : unescape(tmp, strVal);
2506 : : }
2507 : : else
2508 : : {
2509 [ # # ][ # # ]: 0 : strVal = val.to_string();
[ # # ]
2510 : : }
2511 : :
2512 [ # # ][ # # ]: 0 : if (cfg.to_string() == "indent:string")
[ # # ][ # # ]
2513 : : {
2514 [ # # ]: 0 : indString = strVal;
2515 : : }
2516 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "startlabel")
[ # # ][ # # ]
2517 : : {
2518 [ # # ]: 0 : startLabelName = strVal;
2519 [ # # ]: 0 : bUseStartLabel = !startLabelName.empty();
2520 : : }
2521 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "labelprefix")
[ # # ][ # # ]
2522 : : {
2523 [ # # ]: 0 : labelPrefix = strVal;
2524 : : }
2525 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "condprefix")
[ # # ][ # # ]
2526 : : {
2527 [ # # ]: 0 : condPrefix = strVal;
2528 : : }
2529 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "condenumprefix")
[ # # ][ # # ]
2530 : : {
2531 [ # # ]: 0 : condEnumPrefix = strVal;
2532 : : }
2533 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "cond:divider")
[ # # ][ # # ]
2534 : : {
2535 [ # # ]: 0 : condDivider = strVal;
2536 : : }
2537 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "cond:divider@cond")
[ # # ][ # # ]
2538 : : {
2539 [ # # ]: 0 : condDividerParam = strVal;
2540 : : }
2541 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "cond:goto")
[ # # ][ # # ]
2542 : : {
2543 [ # # ]: 0 : condGoto = strVal;
2544 : : }
2545 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "cond:goto@cond")
[ # # ][ # # ]
2546 : : {
2547 [ # # ]: 0 : condGotoParam = strVal;
2548 : : }
2549 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "define:YYFILL@len")
[ # # ][ # # ]
2550 : : {
2551 [ # # ]: 0 : yyFillLength = strVal;
2552 : 0 : bUseYYFillParam = false;
2553 : : }
2554 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "define:YYSETCONDITION@cond")
[ # # ][ # # ]
2555 : : {
2556 [ # # ]: 0 : yySetConditionParam = strVal;
2557 : 0 : bUseYYSetConditionParam = false;
2558 : : }
2559 [ # # ][ # # ]: 0 : else if (cfg.to_string() == "define:YYSETSTATE@state")
[ # # ][ # # ]
2560 : : {
2561 [ # # ]: 0 : yySetStateParam = strVal;
2562 : 0 : bUseYYSetStateParam = false;
2563 : : }
2564 [ # # ][ # # ]: 0 : else if (mapVariableKeys.find(cfg.to_string()) != mapVariableKeys.end())
[ # # ][ # # ]
[ # # ]
2565 : : {
2566 [ # # ][ # # ]: 0 : if ((bFirstPass || rFlag) && !mapCodeName.insert(
[ # # ][ # # ]
2567 : : std::make_pair(cfg.to_string().substr(sizeof("variable:") - 1), strVal)
2568 [ # # ][ # # ]: 0 : ).second)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # #
# # # #
# ]
2569 : : {
2570 [ # # ][ # # ]: 0 : fatalf("variable '%s' already being used and cannot be changed", cfg.to_string().c_str());
[ # # ][ # # ]
2571 : : }
2572 : : }
2573 [ # # ][ # # ]: 0 : else if (mapDefineKeys.find(cfg.to_string()) != mapDefineKeys.end())
[ # # ][ # # ]
[ # # ]
2574 : : {
2575 [ # # ][ # # ]: 0 : if ((bFirstPass || rFlag) && !mapCodeName.insert(
[ # # ][ # # ]
2576 : : std::make_pair(cfg.to_string().substr(sizeof("define:") - 1), strVal)
2577 [ # # ][ # # ]: 0 : ).second)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # #
# # # #
# ]
2578 : : {
2579 [ # # ][ # # ]: 0 : fatalf("define '%s' already being used and cannot be changed", cfg.to_string().c_str());
[ # # ][ # # ]
2580 : : }
2581 : : }
2582 [ # # ][ # # ]: 0 : else if (mapLabelKeys.find(cfg.to_string()) != mapLabelKeys.end())
[ # # ][ # # ]
[ # # ]
2583 : : {
2584 [ # # ][ # # ]: 0 : if ((bFirstPass || rFlag) && !mapCodeName.insert(
[ # # ][ # # ]
2585 : : std::make_pair(cfg.to_string().substr(sizeof("label:") - 1), strVal)
2586 [ # # ][ # # ]: 0 : ).second)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # #
# # # #
# ]
2587 : : {
2588 [ # # ][ # # ]: 0 : fatalf("label '%s' already being used and cannot be changed", cfg.to_string().c_str());
[ # # ][ # # ]
2589 : : }
2590 : : }
2591 : : else
2592 : : {
2593 [ # # ]: 0 : std::string msg = "unrecognized configuration name '";
2594 [ # # ][ # # ]: 0 : msg += cfg.to_string();
[ # # ]
2595 [ # # ]: 0 : msg += "' or illegal string value";
2596 [ # # ][ # # ]: 0 : fatal(msg.c_str());
[ # # ]
2597 [ # # ]: 0 : }
2598 : 0 : }
2599 : :
2600 : 72 : ScannerState::ScannerState()
2601 : : : tok(NULL), ptr(NULL), cur(NULL), pos(NULL), ctx(NULL)
2602 : : , bot(NULL), lim(NULL), top(NULL), eof(NULL)
2603 : : , tchar(0), tline(0), cline(1), iscfg(0)
2604 : 72 : , in_parse(false)
2605 : : {
2606 : 72 : }
2607 : :
2608 : 72 : Scanner::Scanner(std::istream& i, std::ostream& o)
2609 : 72 : : ScannerState(), in(i), out(o)
2610 : : {
2611 : 72 : }
2612 : :
2613 : 0 : char *Scanner::fill(char *cursor, unsigned need)
2614 : : {
2615 [ # # ]: 0 : if(!eof)
2616 : : {
2617 : : unsigned cnt;
2618 : : /* Do not get rid of anything when rFlag is active. Otherwise
2619 : : * get rid of everything that was already handedout. */
2620 [ # # ]: 0 : if (!rFlag)
2621 : : {
2622 : 0 : cnt = tok - bot;
2623 [ # # ]: 0 : if (cnt)
2624 : : {
2625 : 0 : memmove(bot, tok, top - tok);
2626 : 0 : tok = bot;
2627 : 0 : ptr -= cnt;
2628 : 0 : cur -= cnt;
2629 : 0 : pos -= cnt;
2630 : 0 : lim -= cnt;
2631 : 0 : ctx -= cnt;
2632 : 0 : cursor -= cnt;
2633 : : }
2634 : : }
2635 : : /* In crease buffer size. */
2636 [ # # ]: 0 : if (BSIZE > need)
2637 : : {
2638 : 0 : need = BSIZE;
2639 : : }
2640 [ # # ]: 0 : if (static_cast<unsigned>(top - lim) < need)
2641 : : {
2642 : 0 : char *buf = new char[(lim - bot) + need];
2643 [ # # ]: 0 : if (!buf)
2644 : : {
2645 : 0 : fatal("Out of memory");
2646 : : }
2647 : 0 : memcpy(buf, bot, lim - bot);
2648 : 0 : tok = &buf[tok - bot];
2649 : 0 : ptr = &buf[ptr - bot];
2650 : 0 : cur = &buf[cur - bot];
2651 : 0 : pos = &buf[pos - bot];
2652 : 0 : lim = &buf[lim - bot];
2653 : 0 : top = &lim[need];
2654 : 0 : ctx = &buf[ctx - bot];
2655 : 0 : cursor = &buf[cursor - bot];
2656 [ # # ]: 0 : delete [] bot;
2657 : 0 : bot = buf;
2658 : : }
2659 : : /* Append to buffer. */
2660 : 0 : in.read(lim, need);
2661 [ # # ]: 0 : if ((cnt = in.gcount()) != need)
2662 : : {
2663 : 0 : eof = &lim[cnt];
2664 : 0 : *eof++ = '\0';
2665 : : }
2666 : 0 : lim += cnt;
2667 : : }
2668 : 0 : return cursor;
2669 : : }
2670 : :
2671 : 0 : void Scanner::set_in_parse(bool new_in_parse)
2672 : : {
2673 : 0 : in_parse = new_in_parse;
2674 : 0 : }
2675 : :
2676 : 0 : void Scanner::fatal_at(unsigned line, unsigned ofs, const char *msg) const
2677 : : {
2678 [ # # ][ # # ]: 0 : throw re2c_error("regex error:" + std::string(msg), tchar + ofs + 1);
[ # # ]
2679 : : }
2680 : :
2681 : 0 : void Scanner::fatal(unsigned ofs, const char *msg) const
2682 : : {
2683 [ # # ]: 0 : fatal_at(in_parse ? tline : cline, ofs, msg);
2684 : 0 : }
2685 : :
2686 : 0 : void Scanner::fatalf_at(unsigned line, const char* fmt, ...) const
2687 : : {
2688 : : char szBuf[4096];
2689 : :
2690 : : va_list args;
2691 : :
2692 : 0 : va_start(args, fmt);
2693 : 0 : vsnprintf(szBuf, sizeof(szBuf), fmt, args);
2694 : 0 : va_end(args);
2695 : :
2696 : 0 : szBuf[sizeof(szBuf)-1] = '0';
2697 : :
2698 [ # # ]: 0 : fatal_at(line, 0, szBuf);
2699 : 0 : }
2700 : :
2701 : 0 : void Scanner::fatalf(const char *fmt, ...) const
2702 : : {
2703 : : char szBuf[4096];
2704 : :
2705 : : va_list args;
2706 : :
2707 : 0 : va_start(args, fmt);
2708 : 0 : vsnprintf(szBuf, sizeof(szBuf), fmt, args);
2709 : 0 : va_end(args);
2710 : :
2711 : 0 : szBuf[sizeof(szBuf)-1] = '0';
2712 : :
2713 [ # # ]: 0 : fatal(szBuf);
2714 : 0 : }
2715 : :
2716 : 144 : Scanner::~Scanner()
2717 : : {
2718 [ - + ]: 72 : if (bot)
2719 : : {
2720 [ # # ]: 0 : delete [] bot;
2721 : : }
2722 [ - + ]: 144 : }
2723 : :
2724 : 0 : void Scanner::check_token_length(char *pos, unsigned len) const
2725 : : {
2726 [ # # ][ # # ]: 0 : if (pos < bot || pos + len > top)
2727 : : {
2728 : 0 : fatal("Token exceeds limit");
2729 : : }
2730 : 0 : }
2731 : :
2732 : 0 : Str Scanner::raw_token(std::string enclosure) const
2733 : : {
2734 [ # # ][ # # ]: 0 : return Str(std::string(enclosure + token().to_string() + enclosure).c_str());
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2735 : : }
2736 : :
2737 : 0 : void Scanner::reuse()
2738 : : {
2739 : 0 : next_label = 0;
2740 : 0 : next_fill_index = 0;
2741 : 0 : bWroteGetState = false;
2742 : 0 : bWroteCondCheck = false;
2743 : 0 : mapCodeName.clear();
2744 : 0 : }
2745 : :
2746 : 0 : void Scanner::restore_state(const ScannerState& state)
2747 : : {
2748 : 0 : int diff = bot - state.bot;
2749 : 0 : char *old_bot = bot;
2750 : 0 : char *old_lim = lim;
2751 : 0 : char *old_top = top;
2752 : 0 : char *old_eof = eof;
2753 : 0 : *(ScannerState*)this = state;
2754 [ # # ]: 0 : if (diff)
2755 : : {
2756 : 0 : tok -= diff;
2757 : 0 : ptr -= diff;
2758 : 0 : cur -= diff;
2759 : 0 : pos -= diff;
2760 : 0 : ctx -= diff;
2761 : 0 : bot = old_bot;
2762 : 0 : lim = old_lim;
2763 : 0 : top = old_top;
2764 : 0 : eof = old_eof;
2765 : : }
2766 : 0 : }
2767 : :
2768 [ + - ][ + - ]: 7242 : } // end namespace re2c
|