1 #ifdef _WIN32 2 #include <windows.h> 3 #include <io.h> 4 #endif 5 #include <stdlib.h> 6 #include <string.h> 7 #include <ctype.h> 8 #include "tools/re2c/substr.h" 9 #include "tools/re2c/globals.h" 10 #include "tools/re2c/dfa.h" 11 #include "tools/re2c/parse.h" 12 13 #ifdef _WIN32 14 /* tmpfile() replacment for Windows. 15 * 16 * On Windows tmpfile() creates the file in the root directory. This 17 * may fail due to unsufficient privileges. 18 */ 19 static FILE * 20 win32_tmpfile (void) 21 { 22 DWORD path_len; 23 WCHAR path_name[MAX_PATH + 1]; 24 WCHAR file_name[MAX_PATH + 1]; 25 HANDLE handle; 26 int fd; 27 FILE *fp; 28 29 path_len = GetTempPathW (MAX_PATH, path_name); 30 if (path_len <= 0 || path_len >= MAX_PATH) 31 return NULL; 32 33 if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0) 34 return NULL; 35 36 handle = CreateFileW (file_name, 37 GENERIC_READ | GENERIC_WRITE, 38 0, 39 NULL, 40 CREATE_ALWAYS, 41 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 42 NULL); 43 if (handle == INVALID_HANDLE_VALUE) { 44 DeleteFileW (file_name); 45 return NULL; 46 } 47 48 fd = _open_osfhandle((intptr_t) handle, 0); 49 if (fd < 0) { 50 CloseHandle (handle); 51 return NULL; 52 } 53 54 fp = fdopen(fd, "w+b"); 55 if (fp == NULL) { 56 _close(fd); 57 return NULL; 58 } 59 60 return fp; 61 } 62 #endif 63 64 static void useLabel(size_t value) { 65 while (value >= vUsedLabelAlloc) { 66 vUsedLabels = realloc(vUsedLabels, vUsedLabelAlloc * 2); 67 if (!vUsedLabels) { 68 fputs("Out of memory.\n", stderr); 69 exit(EXIT_FAILURE); 70 } 71 memset(vUsedLabels + vUsedLabelAlloc, 0, vUsedLabelAlloc); 72 vUsedLabelAlloc *= 2; 73 } 74 vUsedLabels[value] = 1; 75 } 76 77 /* there must be at least one span in list; all spans must cover 78 * same range 79 */ 80 81 void Go_compact(Go *g){ 82 /* arrange so that adjacent spans have different targets */ 83 unsigned int i = 0, j; 84 for(j = 1; j < g->nSpans; ++j){ 85 if(g->span[j].to != g->span[i].to){ 86 ++i; g->span[i].to = g->span[j].to; 87 } 88 g->span[i].ub = g->span[j].ub; 89 } 90 g->nSpans = i + 1; 91 } 92 93 void Go_unmap(Go *g, Go *base, State *x){ 94 Span *s = g->span, *b = base->span, *e = &b[base->nSpans]; 95 unsigned int lb = 0; 96 s->ub = 0; 97 s->to = NULL; 98 for(; b != e; ++b){ 99 if(b->to == x){ 100 if((s->ub - lb) > 1) 101 s->ub = b->ub; 102 } else { 103 if(b->to != s->to){ 104 if(s->ub){ 105 lb = s->ub; ++s; 106 } 107 s->to = b->to; 108 } 109 s->ub = b->ub; 110 } 111 } 112 s->ub = e[-1].ub; ++s; 113 g->nSpans = s - g->span; 114 } 115 116 static void doGen(Go *g, State *s, unsigned char *bm, unsigned char m){ 117 Span *b = g->span, *e = &b[g->nSpans]; 118 unsigned int lb = 0; 119 for(; b < e; ++b){ 120 if(b->to == s) 121 for(; lb < b->ub; ++lb) bm[lb] |= m; 122 lb = b->ub; 123 } 124 } 125 #if 0 126 static void prt(FILE *o, Go *g, State *s){ 127 Span *b = g->span, *e = &b[g->nSpans]; 128 unsigned int lb = 0; 129 for(; b < e; ++b){ 130 if(b->to == s) 131 printSpan(o, lb, b->ub); 132 lb = b->ub; 133 } 134 } 135 #endif 136 static int matches(Go *g1, State *s1, Go *g2, State *s2){ 137 Span *b1 = g1->span, *e1 = &b1[g1->nSpans]; 138 unsigned int lb1 = 0; 139 Span *b2 = g2->span, *e2 = &b2[g2->nSpans]; 140 unsigned int lb2 = 0; 141 for(;;){ 142 for(; b1 < e1 && b1->to != s1; ++b1) lb1 = b1->ub; 143 for(; b2 < e2 && b2->to != s2; ++b2) lb2 = b2->ub; 144 if(b1 == e1) return b2 == e2; 145 if(b2 == e2) return 0; 146 if(lb1 != lb2 || b1->ub != b2->ub) return 0; 147 ++b1; ++b2; 148 } 149 } 150 151 typedef struct BitMap { 152 Go *go; 153 State *on; 154 struct BitMap *next; 155 unsigned int i; 156 unsigned char m; 157 } BitMap; 158 159 static BitMap *BitMap_find_go(Go*, State*); 160 static BitMap *BitMap_find(State*); 161 static void BitMap_gen(FILE *, unsigned int, unsigned int); 162 /* static void BitMap_stats(void);*/ 163 static BitMap *BitMap_new(Go*, State*); 164 165 static BitMap *BitMap_first = NULL; 166 167 BitMap * 168 BitMap_new(Go *g, State *x) 169 { 170 BitMap *b = malloc(sizeof(BitMap)); 171 b->go = g; 172 b->on = x; 173 b->next = BitMap_first; 174 BitMap_first = b; 175 return b; 176 } 177 178 BitMap * 179 BitMap_find_go(Go *g, State *x){ 180 BitMap *b; 181 for(b = BitMap_first; b; b = b->next){ 182 if(matches(b->go, b->on, g, x)) 183 return b; 184 } 185 return BitMap_new(g, x); 186 } 187 188 BitMap * 189 BitMap_find(State *x){ 190 BitMap *b; 191 for(b = BitMap_first; b; b = b->next){ 192 if(b->on == x) 193 return b; 194 } 195 return NULL; 196 } 197 198 void BitMap_gen(FILE *o, unsigned int lb, unsigned int ub){ 199 BitMap *b = BitMap_first; 200 if(b){ 201 unsigned int n = ub - lb; 202 unsigned int i; 203 unsigned char *bm = malloc(sizeof(unsigned char)*n); 204 fputs("\tstatic unsigned char yybm[] = {", o); 205 for(i = 0; b; i += n){ 206 unsigned char m; 207 unsigned int j; 208 memset(bm, 0, n); 209 for(m = 0x80; b && m; b = b->next, m >>= 1){ 210 b->i = i; b->m = m; 211 doGen(b->go, b->on, bm-lb, m); 212 } 213 for(j = 0; j < n; ++j){ 214 if(j%8 == 0) {fputs("\n\t", o); oline++;} 215 fprintf(o, "%3u, ", (unsigned int) bm[j]); 216 } 217 } 218 fputs("\n\t};\n", o); oline+=2; 219 free(bm); 220 } 221 } 222 223 #if 0 224 void BitMap_stats(void){ 225 unsigned int n = 0; 226 BitMap *b; 227 for(b = BitMap_first; b; b = b->next){ 228 prt(stderr, b->go, b->on); fputs("\n", stderr); 229 ++n; 230 } 231 fprintf(stderr, "%u bitmaps\n", n); 232 BitMap_first = NULL; 233 } 234 #endif 235 236 static void genGoTo(FILE *o, State *from, State *to, int *readCh, 237 const char *indent) 238 { 239 #if 0 240 if (*readCh && from->label + 1 != to->label) 241 { 242 fputs("%syych = *YYCURSOR;\n", indent, o); oline++; 243 *readCh = 0; 244 } 245 #endif 246 fprintf(o, "%sgoto yy%u;\n", indent, to->label); oline++; 247 useLabel(to->label); 248 } 249 250 static void genIf(FILE *o, const char *cmp, unsigned int v, int *readCh) 251 { 252 #if 0 253 if (*readCh) 254 { 255 fputs("\tif((yych = *YYCURSOR) ", o); 256 *readCh = 0; 257 } else { 258 #endif 259 fputs("\tif(yych ", o); 260 #if 0 261 } 262 #endif 263 fprintf(o, "%s '", cmp); 264 prtCh(o, v); 265 fputs("')", o); 266 } 267 268 static void indent(FILE *o, unsigned int i){ 269 while(i-- > 0) 270 fputc('\t', o); 271 } 272 273 static void need(FILE *o, unsigned int n, int *readCh) 274 { 275 unsigned int fillIndex; 276 int hasFillIndex = (0<=vFillIndexes); 277 if (hasFillIndex) { 278 fillIndex = vFillIndexes++; 279 fprintf(o, "\tYYSETSTATE(%u);\n", fillIndex); 280 ++oline; 281 } 282 283 if(n == 1) { 284 fputs("\tif(YYLIMIT == YYCURSOR) YYFILL(1);\n", o); oline++; 285 } else { 286 fprintf(o, "\tif((YYLIMIT - YYCURSOR) < %u) YYFILL(%u);\n", n, n); 287 oline++; 288 } 289 290 if (hasFillIndex) { 291 fprintf(o, "yyFillLabel%u:\n", fillIndex); 292 ++oline; 293 } 294 295 fputs("\tyych = *YYCURSOR;\n", o); oline++; 296 *readCh = 0; 297 } 298 299 void 300 Action_emit(Action *a, FILE *o, int *readCh) 301 { 302 int first = 1; 303 unsigned int i; 304 unsigned int back; 305 306 switch (a->type) { 307 case MATCHACT: 308 if(a->state->link){ 309 fputs("\t++YYCURSOR;\n", o); 310 need(o, a->state->depth, readCh); 311 #if 0 312 } else if (!Action_readAhead(a)) { 313 /* do not read next char if match */ 314 fputs("\t++YYCURSOR;\n", o); 315 *readCh = 1; 316 #endif 317 } else { 318 fputs("\tyych = *++YYCURSOR;\n", o); 319 *readCh = 0; 320 } 321 oline++; 322 break; 323 case ENTERACT: 324 if(a->state->link){ 325 fputs("\t++YYCURSOR;\n", o); 326 fprintf(o, "yy%u:\n", a->d.label); oline+=2; 327 need(o, a->state->depth, readCh); 328 } else { 329 /* we shouldn't need 'rule-following' protection here */ 330 fputs("\tyych = *++YYCURSOR;\n", o); 331 fprintf(o, "yy%u:\n", a->d.label); oline+=2; 332 *readCh = 0; 333 } 334 break; 335 case SAVEMATCHACT: 336 if (bUsedYYAccept) { 337 fprintf(o, "\tyyaccept = %u;\n", a->d.selector); 338 oline++; 339 } 340 if(a->state->link){ 341 fputs("\tYYMARKER = ++YYCURSOR;\n", o); oline++; 342 need(o, a->state->depth, readCh); 343 } else { 344 fputs("\tyych = *(YYMARKER = ++YYCURSOR);\n", o); oline++; 345 *readCh = 0; 346 } 347 break; 348 case MOVEACT: 349 break; 350 case ACCEPTACT: 351 for(i = 0; i < a->d.Accept.nRules; ++i) 352 if(a->d.Accept.saves[i] != ~0u){ 353 if(first){ 354 first = 0; 355 bUsedYYAccept = 1; 356 fputs("\tYYCURSOR = YYMARKER;\n", o); 357 fputs("\tswitch(yyaccept){\n", o); oline+=2; 358 } 359 fprintf(o, "\tcase %u:", a->d.Accept.saves[i]); 360 genGoTo(o, a->state, a->d.Accept.rules[i], readCh, "\t"); 361 } 362 if(!first) { 363 fputs("\t}\n", o); oline++; 364 } 365 break; 366 case RULEACT: 367 back = RegExp_fixedLength(a->d.rule->d.RuleOp.ctx); 368 if(back != ~0u && back > 0u) 369 fprintf(o, "\tYYCURSOR -= %u;", back); 370 fprintf(o, "\n"); oline++; 371 line_source(o, a->d.rule->d.RuleOp.code->line); 372 SubStr_out(&a->d.rule->d.RuleOp.code->text, o); 373 fprintf(o, "\n"); oline++; 374 if (!iFlag) 375 fprintf(o, "#line %u \"%s\"\n", oline++, outputFileName); 376 break; 377 } 378 } 379 380 Action * 381 Action_new_Accept(State *x, unsigned int n, unsigned int *s, State **r) 382 { 383 Action *a = malloc(sizeof(Action)); 384 a->type = ACCEPTACT; 385 a->state = x; 386 a->d.Accept.nRules = n; 387 a->d.Accept.saves = s; 388 a->d.Accept.rules = r; 389 x->action = a; 390 return a; 391 } 392 393 static void doLinear(FILE *o, unsigned int i, Span *s, unsigned int n, 394 State *from, State *next, int *readCh){ 395 for(;;){ 396 State *bg = s[0].to; 397 while(n >= 3 && s[2].to == bg && (s[1].ub - s[0].ub) == 1){ 398 if(s[1].to == next && n == 3){ 399 indent(o, i); 400 genIf(o, "!=", s[0].ub, readCh); 401 genGoTo(o, from, bg, readCh, "\t"); 402 indent(o, i); 403 genGoTo(o, from, next, readCh, "\t"); 404 return; 405 } else { 406 indent(o, i); 407 genIf(o, "==", s[0].ub, readCh); 408 genGoTo(o, from, s[1].to, readCh, "\t"); 409 } 410 n -= 2; s += 2; 411 } 412 if(n == 1){ 413 indent(o, i); 414 genGoTo(o, from, s[0].to, readCh, "\t"); 415 return; 416 } else if(n == 2 && bg == next){ 417 indent(o, i); 418 genIf(o, ">=", s[0].ub, readCh); 419 genGoTo(o, from, s[1].to, readCh, "\t"); 420 indent(o, i); 421 genGoTo(o, from, next, readCh, "\t"); 422 return; 423 } else { 424 indent(o, i); 425 genIf(o, "<=", s[0].ub - 1, readCh); 426 genGoTo(o, from, bg, readCh, "\t"); 427 n -= 1; s += 1; 428 } 429 } 430 indent(o, i); 431 genGoTo(o, from, next, readCh, "\t"); 432 } 433 434 void 435 Go_genLinear(Go *g, FILE *o, State *from, State *next, int *readCh){ 436 doLinear(o, 0, g->span, g->nSpans, from, next, readCh); 437 } 438 439 static void genCases(FILE *o, unsigned int lb, Span *s){ 440 if(lb < s->ub){ 441 for(;;){ 442 fputs("\tcase '", o); prtCh(o, lb); fputs("':", o); 443 if(++lb == s->ub) 444 break; 445 fputs("\n", o); oline++; 446 } 447 } 448 } 449 450 void 451 Go_genSwitch(Go *g, FILE *o, State *from, State *next, int *readCh){ 452 if(g->nSpans <= 2){ 453 Go_genLinear(g, o, from, next, readCh); 454 } else { 455 State *def = g->span[g->nSpans-1].to; 456 Span **sP = malloc(sizeof(Span*)*(g->nSpans-1)), **r, **s, **t; 457 unsigned int i; 458 459 t = &sP[0]; 460 for(i = 0; i < g->nSpans; ++i) 461 if(g->span[i].to != def) 462 *(t++) = &g->span[i]; 463 464 if (dFlag) 465 fputs("\tYYDEBUG(-1, yych);\n", o); 466 467 #if 0 468 if (*readCh) { 469 fputs("\tswitch((yych = *YYCURSOR)) {\n", o); 470 *readCh = 0; 471 } else 472 #endif 473 fputs("\tswitch(yych){\n", o); 474 oline++; 475 while(t != &sP[0]){ 476 State *to; 477 r = s = &sP[0]; 478 if(*s == &g->span[0]) 479 genCases(o, 0, *s); 480 else 481 genCases(o, (*s)[-1].ub, *s); 482 to = (*s)->to; 483 while(++s < t){ 484 if((*s)->to == to) 485 genCases(o, (*s)[-1].ub, *s); 486 else 487 *(r++) = *s; 488 } 489 genGoTo(o, from, to, readCh, "\t"); 490 t = r; 491 } 492 fputs("\tdefault:", o); 493 genGoTo(o, from, def, readCh, "\t"); 494 fputs("\t}\n", o); oline++; 495 496 free(sP); 497 } 498 } 499 500 static void doBinary(FILE *o, unsigned int i, Span *s, unsigned int n, 501 State *from, State *next, int *readCh){ 502 if(n <= 4){ 503 doLinear(o, i, s, n, from, next, readCh); 504 } else { 505 unsigned int h = n/2; 506 indent(o, i); 507 genIf(o, "<=", s[h-1].ub - 1, readCh); 508 fputs("{\n", o); oline++; 509 doBinary(o, i+1, &s[0], h, from, next, readCh); 510 indent(o, i); fputs("\t} else {\n", o); oline++; 511 doBinary(o, i+1, &s[h], n - h, from, next, readCh); 512 indent(o, i); fputs("\t}\n", o); oline++; 513 } 514 } 515 516 void 517 Go_genBinary(Go *g, FILE *o, State *from, State *next, int *readCh){ 518 doBinary(o, 0, g->span, g->nSpans, from, next, readCh); 519 } 520 521 void 522 Go_genBase(Go *g, FILE *o, State *from, State *next, int *readCh){ 523 if(g->nSpans == 0) 524 return; 525 if(!sFlag){ 526 Go_genSwitch(g, o, from, next, readCh); 527 return; 528 } 529 if(g->nSpans > 8){ 530 Span *bot = &g->span[0], *top = &g->span[g->nSpans-1]; 531 unsigned int util; 532 if(bot[0].to == top[0].to){ 533 util = (top[-1].ub - bot[0].ub)/(g->nSpans - 2); 534 } else { 535 if(bot[0].ub > (top[0].ub - top[-1].ub)){ 536 util = (top[0].ub - bot[0].ub)/(g->nSpans - 1); 537 } else { 538 util = top[-1].ub/(g->nSpans - 1); 539 } 540 } 541 if(util <= 2){ 542 Go_genSwitch(g, o, from, next, readCh); 543 return; 544 } 545 } 546 if(g->nSpans > 5){ 547 Go_genBinary(g, o, from, next, readCh); 548 } else { 549 Go_genLinear(g, o, from, next, readCh); 550 } 551 } 552 553 void 554 Go_genGoto(Go *g, FILE *o, State *from, State *next, int *readCh){ 555 unsigned int i; 556 if(bFlag){ 557 for(i = 0; i < g->nSpans; ++i){ 558 State *to = g->span[i].to; 559 if(to && to->isBase){ 560 BitMap *b = BitMap_find(to); 561 if(b && matches(b->go, b->on, g, to)){ 562 Go go; 563 go.span = malloc(sizeof(Span)*g->nSpans); 564 Go_unmap(&go, g, to); 565 fprintf(o, "\tif(yybm[%u+", b->i); 566 #if 0 567 if (*readCh) 568 fputs("(yych = *YYCURSOR)", o); 569 else 570 #endif 571 fputs("yych", o); 572 fprintf(o, "] & %u) {\n", (unsigned int) b->m); oline++; 573 genGoTo(o, from, to, readCh, "\t\t"); 574 fputs("\t}\n", o); oline++; 575 Go_genBase(&go, o, from, next, readCh); 576 free(go.span); 577 return; 578 } 579 } 580 } 581 } 582 Go_genBase(g, o, from, next, readCh); 583 } 584 585 void State_emit(State *s, FILE *o, int *readCh){ 586 if (vUsedLabels[s->label]) 587 fprintf(o, "yy%u:", s->label); 588 if (dFlag) 589 fprintf(o, "\n\tYYDEBUG(%u, *YYCURSOR);\n", s->label); 590 Action_emit(s->action, o, readCh); 591 } 592 593 static unsigned int merge(Span *x0, State *fg, State *bg){ 594 Span *x = x0, *f = fg->go.span, *b = bg->go.span; 595 unsigned int nf = fg->go.nSpans, nb = bg->go.nSpans; 596 State *prev = NULL, *to; 597 /* NB: we assume both spans are for same range */ 598 for(;;){ 599 if(f->ub == b->ub){ 600 to = f->to == b->to? bg : f->to; 601 if(to == prev){ 602 --x; 603 } else { 604 x->to = prev = to; 605 } 606 x->ub = f->ub; 607 ++x; ++f; --nf; ++b; --nb; 608 if(nf == 0 && nb == 0) 609 return x - x0; 610 } 611 while(f->ub < b->ub){ 612 to = f->to == b->to? bg : f->to; 613 if(to == prev){ 614 --x; 615 } else { 616 x->to = prev = to; 617 } 618 x->ub = f->ub; 619 ++x; ++f; --nf; 620 } 621 while(b->ub < f->ub){ 622 to = b->to == f->to? bg : f->to; 623 if(to == prev){ 624 --x; 625 } else { 626 x->to = prev = to; 627 } 628 x->ub = b->ub; 629 ++x; ++b; --nb; 630 } 631 } 632 } 633 634 const unsigned int cInfinity = ~0; 635 636 typedef struct SCC { 637 State **top, **stk; 638 } SCC; 639 640 static void SCC_init(SCC*, unsigned int); 641 static SCC *SCC_new(unsigned int); 642 static void SCC_destroy(SCC*); 643 static void SCC_delete(SCC*); 644 static void SCC_traverse(SCC*, State*); 645 646 static void 647 SCC_init(SCC *s, unsigned int size) 648 { 649 s->top = s->stk = malloc(sizeof(State*)*size); 650 } 651 652 static SCC * 653 SCC_new(unsigned int size){ 654 SCC *s = malloc(sizeof(SCC)); 655 s->top = s->stk = malloc(sizeof(State*)*size); 656 return s; 657 } 658 659 static void 660 SCC_destroy(SCC *s){ 661 free(s->stk); 662 } 663 664 static void 665 SCC_delete(SCC *s){ 666 free(s->stk); 667 free(s); 668 } 669 670 static void SCC_traverse(SCC *s, State *x){ 671 unsigned int k, i; 672 673 *s->top = x; 674 k = ++s->top - s->stk; 675 x->depth = k; 676 for(i = 0; i < x->go.nSpans; ++i){ 677 State *y = x->go.span[i].to; 678 if(y){ 679 if(y->depth == 0) 680 SCC_traverse(s, y); 681 if(y->depth < x->depth) 682 x->depth = y->depth; 683 } 684 } 685 if(x->depth == k) 686 do { 687 (*--s->top)->depth = cInfinity; 688 (*s->top)->link = x; 689 } while(*s->top != x); 690 } 691 692 static unsigned int maxDist(State *s){ 693 unsigned int mm = 0, i; 694 for(i = 0; i < s->go.nSpans; ++i){ 695 State *t = s->go.span[i].to; 696 if(t){ 697 unsigned int m = 1; 698 if(!t->link) { 699 if (t->depth == -1) 700 t->depth = maxDist(t); 701 m += t->depth; 702 } 703 if(m > mm) 704 mm = m; 705 } 706 } 707 return mm; 708 } 709 710 static void calcDepth(State *head){ 711 State *t, *s; 712 for(s = head; s; s = s->next){ 713 if(s->link == s){ 714 unsigned int i; 715 for(i = 0; i < s->go.nSpans; ++i){ 716 t = s->go.span[i].to; 717 if(t && t->link == s) 718 goto inSCC; 719 } 720 s->link = NULL; 721 } else { 722 inSCC: 723 s->depth = maxDist(s); 724 } 725 } 726 } 727 728 void DFA_findSCCs(DFA *d){ 729 SCC scc; 730 State *s; 731 732 SCC_init(&scc, d->nStates); 733 for(s = d->head; s; s = s->next){ 734 s->depth = 0; 735 s->link = NULL; 736 } 737 738 for(s = d->head; s; s = s->next) 739 if(!s->depth) 740 SCC_traverse(&scc, s); 741 742 calcDepth(d->head); 743 744 SCC_destroy(&scc); 745 } 746 747 void DFA_split(DFA *d, State *s){ 748 State *move = State_new(); 749 Action_new_Move(move); 750 DFA_addState(d, &s->next, move); 751 move->link = s->link; 752 move->rule = s->rule; 753 move->go = s->go; 754 s->rule = NULL; 755 s->go.nSpans = 1; 756 s->go.span = malloc(sizeof(Span)); 757 s->go.span[0].ub = d->ubChar; 758 s->go.span[0].to = move; 759 } 760 761 void DFA_emit(DFA *d, FILE *o){ 762 static unsigned int label = 0; 763 State *s; 764 unsigned int i, bitmap_brace = 0; 765 unsigned int nRules = 0; 766 unsigned int nSaves = 0; 767 unsigned int *saves; 768 unsigned int nOrgOline; 769 State **rules; 770 State *accept = NULL; 771 Span *span; 772 FILE *tmpo; 773 int hasFillLabels; 774 int maxFillIndexes, orgVFillIndexes; 775 unsigned int start_label; 776 777 hasFillLabels = (0<=vFillIndexes); 778 if (hasFillLabels && label!=0) { 779 fputs("re2c : error : multiple /*!re2c blocks aren't supported when -f is specified\n", stderr); 780 exit(1); 781 } 782 783 DFA_findSCCs(d); 784 d->head->link = d->head; 785 786 maxFill = 1; 787 for(s = d->head; s; s = s->next) { 788 s->depth = maxDist(s); 789 if (maxFill < s->depth) 790 maxFill = s->depth; 791 if(s->rule && s->rule->d.RuleOp.accept >= nRules) 792 nRules = s->rule->d.RuleOp.accept + 1; 793 } 794 795 saves = malloc(sizeof(unsigned int)*nRules); 796 memset(saves, ~0, (nRules)*sizeof(unsigned int)); 797 798 /* mark backtracking points */ 799 for(s = d->head; s; s = s->next){ 800 RegExp *ignore = NULL;/*RuleOp*/ 801 if(s->rule){ 802 for(i = 0; i < s->go.nSpans; ++i) 803 if(s->go.span[i].to && !s->go.span[i].to->rule){ 804 free(s->action); 805 if(saves[s->rule->d.RuleOp.accept] == ~0u) 806 saves[s->rule->d.RuleOp.accept] = nSaves++; 807 Action_new_Save(s, saves[s->rule->d.RuleOp.accept]); 808 continue; 809 } 810 ignore = s->rule; 811 } 812 } 813 814 /* insert actions */ 815 rules = malloc(sizeof(State*)*nRules); 816 memset(rules, 0, (nRules)*sizeof(State*)); 817 for(s = d->head; s; s = s->next){ 818 State *ow; 819 if(!s->rule){ 820 ow = accept; 821 } else { 822 if(!rules[s->rule->d.RuleOp.accept]){ 823 State *n = State_new(); 824 Action_new_Rule(n, s->rule); 825 rules[s->rule->d.RuleOp.accept] = n; 826 DFA_addState(d, &s->next, n); 827 } 828 ow = rules[s->rule->d.RuleOp.accept]; 829 } 830 for(i = 0; i < s->go.nSpans; ++i) 831 if(!s->go.span[i].to){ 832 if(!ow){ 833 ow = accept = State_new(); 834 Action_new_Accept(accept, nRules, saves, rules); 835 DFA_addState(d, &s->next, accept); 836 } 837 s->go.span[i].to = ow; 838 } 839 } 840 841 /* split ``base'' states into two parts */ 842 for(s = d->head; s; s = s->next){ 843 s->isBase = 0; 844 if(s->link){ 845 for(i = 0; i < s->go.nSpans; ++i){ 846 if(s->go.span[i].to == s){ 847 s->isBase = 1; 848 DFA_split(d, s); 849 if(bFlag) 850 BitMap_find_go(&s->next->go, s); 851 s = s->next; 852 break; 853 } 854 } 855 } 856 } 857 858 /* find ``base'' state, if possible */ 859 span = malloc(sizeof(Span)*(d->ubChar - d->lbChar)); 860 for(s = d->head; s; s = s->next){ 861 if(!s->link){ 862 for(i = 0; i < s->go.nSpans; ++i){ 863 State *to = s->go.span[i].to; 864 if(to && to->isBase){ 865 unsigned int nSpans; 866 to = to->go.span[0].to; 867 nSpans = merge(span, s, to); 868 if(nSpans < s->go.nSpans){ 869 free(s->go.span); 870 s->go.nSpans = nSpans; 871 s->go.span = malloc(sizeof(Span)*nSpans); 872 memcpy(s->go.span, span, nSpans*sizeof(Span)); 873 } 874 break; 875 } 876 } 877 } 878 } 879 free(span); 880 881 free(d->head->action); 882 883 if(bFlag) { 884 fputs("{\n", o); 885 oline++; 886 bitmap_brace = 1; 887 BitMap_gen(o, d->lbChar, d->ubChar); 888 } 889 890 bUsedYYAccept = 0; 891 892 start_label = label; 893 894 Action_new_Enter(d->head, label++); 895 896 for(s = d->head; s; s = s->next) 897 s->label = label++; 898 899 nOrgOline = oline; 900 maxFillIndexes = vFillIndexes; 901 orgVFillIndexes = vFillIndexes; 902 #ifdef _WIN32 903 tmpo = win32_tmpfile(); 904 #else 905 tmpo = tmpfile(); 906 #endif 907 for(s = d->head; s; s = s->next){ 908 int readCh = 0; 909 State_emit(s, tmpo, &readCh); 910 Go_genGoto(&s->go, tmpo, s, s->next, &readCh); 911 } 912 fclose(tmpo); 913 maxFillIndexes = vFillIndexes; 914 vFillIndexes = orgVFillIndexes; 915 oline = nOrgOline; 916 917 fputs("\n", o); 918 oline++; 919 if (!iFlag) 920 fprintf(o, "#line %u \"%s\"\n", oline++, outputFileName); 921 922 if (!hasFillLabels) { 923 fputs("{\n\tYYCTYPE yych;\n", o); 924 oline += 2; 925 if (bUsedYYAccept) { 926 fputs("\tunsigned int yyaccept;\n", o); 927 oline++; 928 } 929 } else { 930 fputs("{\n\n", o); 931 oline += 2; 932 } 933 934 if (!hasFillLabels) { 935 fprintf(o, "\tgoto yy%u;\n", start_label); 936 oline++; 937 useLabel(label); 938 } else { 939 int i; 940 fputs("\tswitch(YYGETSTATE()) {\n", o); 941 fputs("\t\tcase -1: goto yy0;\n", o); 942 943 for (i=0; i<maxFillIndexes; ++i) 944 fprintf(o, "\t\tcase %u: goto yyFillLabel%u;\n", i, i); 945 946 fputs("\t\tdefault: /* abort() */;\n", o); 947 fputs("\t}\n", o); 948 fputs("yyNext:\n", o); 949 950 oline += maxFillIndexes; 951 oline += 5; 952 } 953 954 for(s = d->head; s; s = s->next){ 955 int readCh = 0; 956 State_emit(s, o, &readCh); 957 Go_genGoto(&s->go, o, s, s->next, &readCh); 958 } 959 fputs("}\n", o); oline++; 960 if (bitmap_brace) { 961 fputs("}\n", o); 962 oline++; 963 } 964 965 BitMap_first = NULL; 966 967 free(saves); 968 free(rules); 969 } 970