1f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#ifdef _WIN32
2f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#include <windows.h>
3f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#include <io.h>
4f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#endif
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <stdlib.h>
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <string.h>
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <ctype.h>
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "tools/re2c/substr.h"
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "tools/re2c/globals.h"
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "tools/re2c/dfa.h"
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "tools/re2c/parse.h"
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#ifdef _WIN32
14f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org/* tmpfile() replacment for Windows.
15f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org *
16f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org * On Windows tmpfile() creates the file in the root directory. This
17f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org * may fail due to unsufficient privileges.
18f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org */
19f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.orgstatic FILE *
20f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.orgwin32_tmpfile (void)
21f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org{
22f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    DWORD path_len;
23f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    WCHAR path_name[MAX_PATH + 1];
24f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    WCHAR file_name[MAX_PATH + 1];
25f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    HANDLE handle;
26f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    int fd;
27f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    FILE *fp;
28f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org
29f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    path_len = GetTempPathW (MAX_PATH, path_name);
30f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    if (path_len <= 0 || path_len >= MAX_PATH)
31f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org	return NULL;
32f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org
33f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0)
34f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org	return NULL;
35f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org
36f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    handle = CreateFileW (file_name,
37f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org			 GENERIC_READ | GENERIC_WRITE,
38f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org			 0,
39f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org			 NULL,
40f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org			 CREATE_ALWAYS,
41f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org			 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
42f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org			 NULL);
43f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    if (handle == INVALID_HANDLE_VALUE) {
44f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org	DeleteFileW (file_name);
45f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org	return NULL;
46f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    }
47f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org
48f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    fd = _open_osfhandle((intptr_t) handle, 0);
49f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    if (fd < 0) {
50f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org	CloseHandle (handle);
51f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org	return NULL;
52f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    }
53f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org
54f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    fp = fdopen(fd, "w+b");
55f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    if (fp == NULL) {
56f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org	_close(fd);
57f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org	return NULL;
58f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    }
59f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org
60f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    return fp;
61f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org}
62f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#endif
63f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void useLabel(size_t value) {
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (value >= vUsedLabelAlloc) {
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	vUsedLabels = realloc(vUsedLabels, vUsedLabelAlloc * 2);
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if (!vUsedLabels) {
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fputs("Out of memory.\n", stderr);
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    exit(EXIT_FAILURE);
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	memset(vUsedLabels + vUsedLabelAlloc, 0, vUsedLabelAlloc);
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	vUsedLabelAlloc *= 2;
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vUsedLabels[value] = 1;
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* there must be at least one span in list;  all spans must cover
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * same range
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Go_compact(Go *g){
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* arrange so that adjacent spans have different targets */
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int i = 0, j;
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(j = 1; j < g->nSpans; ++j){
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(g->span[j].to != g->span[i].to){
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    ++i; g->span[i].to = g->span[j].to;
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	g->span[i].ub = g->span[j].ub;
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    g->nSpans = i + 1;
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Go_unmap(Go *g, Go *base, State *x){
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Span *s = g->span, *b = base->span, *e = &b[base->nSpans];
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int lb = 0;
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->ub = 0;
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->to = NULL;
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(; b != e; ++b){
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(b->to == x){
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if((s->ub - lb) > 1)
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		s->ub = b->ub;
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	} else {
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(b->to != s->to){
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(s->ub){
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    lb = s->ub; ++s;
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		}
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		s->to = b->to;
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    s->ub = b->ub;
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->ub = e[-1].ub; ++s;
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    g->nSpans = s - g->span;
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void doGen(Go *g, State *s, unsigned char *bm, unsigned char m){
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Span *b = g->span, *e = &b[g->nSpans];
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int lb = 0;
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(; b < e; ++b){
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(b->to == s)
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    for(; lb < b->ub; ++lb) bm[lb] |= m;
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	lb = b->ub;
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void prt(FILE *o, Go *g, State *s){
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Span *b = g->span, *e = &b[g->nSpans];
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int lb = 0;
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(; b < e; ++b){
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(b->to == s)
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    printSpan(o, lb, b->ub);
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	lb = b->ub;
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int matches(Go *g1, State *s1, Go *g2, State *s2){
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Span *b1 = g1->span, *e1 = &b1[g1->nSpans];
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int lb1 = 0;
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Span *b2 = g2->span, *e2 = &b2[g2->nSpans];
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int lb2 = 0;
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(;;){
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	for(; b1 < e1 && b1->to != s1; ++b1) lb1 = b1->ub;
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	for(; b2 < e2 && b2->to != s2; ++b2) lb2 = b2->ub;
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(b1 == e1) return b2 == e2;
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(b2 == e2) return 0;
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(lb1 != lb2 || b1->ub != b2->ub) return 0;
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	++b1; ++b2;
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct BitMap {
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Go			*go;
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State		*on;
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct BitMap	*next;
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int	i;
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned char	m;
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} BitMap;
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic BitMap *BitMap_find_go(Go*, State*);
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic BitMap *BitMap_find(State*);
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void BitMap_gen(FILE *, unsigned int, unsigned int);
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* static void BitMap_stats(void);*/
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic BitMap *BitMap_new(Go*, State*);
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic BitMap *BitMap_first = NULL;
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgBitMap *
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgBitMap_new(Go *g, State *x)
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitMap *b = malloc(sizeof(BitMap));
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    b->go = g;
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    b->on = x;
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    b->next = BitMap_first;
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitMap_first = b;
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return b;
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgBitMap *
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgBitMap_find_go(Go *g, State *x){
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitMap *b;
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(b = BitMap_first; b; b = b->next){
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(matches(b->go, b->on, g, x))
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    return b;
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return BitMap_new(g, x);
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgBitMap *
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgBitMap_find(State *x){
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitMap *b;
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(b = BitMap_first; b; b = b->next){
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(b->on == x)
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    return b;
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return NULL;
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitMap_gen(FILE *o, unsigned int lb, unsigned int ub){
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitMap *b = BitMap_first;
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(b){
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	unsigned int n = ub - lb;
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	unsigned int i;
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	unsigned char *bm = malloc(sizeof(unsigned char)*n);
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\tstatic unsigned char yybm[] = {", o);
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	for(i = 0; b; i += n){
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    unsigned char m;
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    unsigned int j;
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    memset(bm, 0, n);
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    for(m = 0x80; b && m; b = b->next, m >>= 1){
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		b->i = i; b->m = m;
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		doGen(b->go, b->on, bm-lb, m);
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    for(j = 0; j < n; ++j){
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(j%8 == 0) {fputs("\n\t", o); oline++;}
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fprintf(o, "%3u, ", (unsigned int) bm[j]);
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\n\t};\n", o); oline+=2;
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        free(bm);
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitMap_stats(void){
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int n = 0;
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitMap *b;
22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(b = BitMap_first; b; b = b->next){
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	prt(stderr, b->go, b->on); fputs("\n", stderr);
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	++n;
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(stderr, "%u bitmaps\n", n);
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitMap_first = NULL;
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void genGoTo(FILE *o, State *from, State *to, int *readCh,
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    const char *indent)
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (*readCh && from->label + 1 != to->label)
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("%syych = *YYCURSOR;\n", indent, o); oline++;
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	*readCh = 0;
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(o, "%sgoto yy%u;\n", indent, to->label); oline++;
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    useLabel(to->label);
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void genIf(FILE *o, const char *cmp, unsigned int v, int *readCh)
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (*readCh)
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\tif((yych = *YYCURSOR) ", o);
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	*readCh = 0;
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\tif(yych ", o);
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(o, "%s '", cmp);
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    prtCh(o, v);
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fputs("')", o);
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void indent(FILE *o, unsigned int i){
26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while(i-- > 0)
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputc('\t', o);
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void need(FILE *o, unsigned int n, int *readCh)
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int fillIndex;
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int hasFillIndex = (0<=vFillIndexes);
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (hasFillIndex) {
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fillIndex = vFillIndexes++;
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fprintf(o, "\tYYSETSTATE(%u);\n", fillIndex);
28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	++oline;
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(n == 1) {
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\tif(YYLIMIT == YYCURSOR) YYFILL(1);\n", o); oline++;
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fprintf(o, "\tif((YYLIMIT - YYCURSOR) < %u) YYFILL(%u);\n", n, n);
28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline++;
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (hasFillIndex) {
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fprintf(o, "yyFillLabel%u:\n", fillIndex);
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	++oline;
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fputs("\tyych = *YYCURSOR;\n", o); oline++;
29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *readCh = 0;
29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgAction_emit(Action *a, FILE *o, int *readCh)
30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int first = 1;
30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int i;
30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int back;
30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (a->type) {
30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	case MATCHACT:
30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(a->state->link){
30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\t++YYCURSOR;\n", o);
31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		need(o, a->state->depth, readCh);
31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else if (!Action_readAhead(a)) {
31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		/* do not read next char if match */
31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\t++YYCURSOR;\n", o);
31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		*readCh = 1;
31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else {
31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\tyych = *++YYCURSOR;\n", o);
31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		*readCh = 0;
32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    oline++;
32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    break;
32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	case ENTERACT:
32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(a->state->link){
32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\t++YYCURSOR;\n", o);
32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fprintf(o, "yy%u:\n", a->d.label); oline+=2;
32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		need(o, a->state->depth, readCh);
32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else {
32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		/* we shouldn't need 'rule-following' protection here */
33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\tyych = *++YYCURSOR;\n", o);
33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fprintf(o, "yy%u:\n", a->d.label); oline+=2;
33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		*readCh = 0;
33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    break;
33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	case SAVEMATCHACT:
33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if (bUsedYYAccept) {
33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fprintf(o, "\tyyaccept = %u;\n", a->d.selector);
33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		oline++;
33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(a->state->link){
34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\tYYMARKER = ++YYCURSOR;\n", o); oline++;
34245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		need(o, a->state->depth, readCh);
34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else {
34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\tyych = *(YYMARKER = ++YYCURSOR);\n", o); oline++;
34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		*readCh = 0;
34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    break;
34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	case MOVEACT:
34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    break;
35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	case ACCEPTACT:
35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    for(i = 0; i < a->d.Accept.nRules; ++i)
35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(a->d.Accept.saves[i] != ~0u){
35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    if(first){
35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			first = 0;
35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			bUsedYYAccept = 1;
35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			fputs("\tYYCURSOR = YYMARKER;\n", o);
35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			fputs("\tswitch(yyaccept){\n", o); oline+=2;
35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    }
35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    fprintf(o, "\tcase %u:", a->d.Accept.saves[i]);
36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    genGoTo(o, a->state, a->d.Accept.rules[i], readCh, "\t");
36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		}
36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(!first) {
36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\t}\n", o); oline++;
36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    break;
36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	case RULEACT:
36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    back = RegExp_fixedLength(a->d.rule->d.RuleOp.ctx);
36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(back != ~0u && back > 0u)
36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fprintf(o, "\tYYCURSOR -= %u;", back);
37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fprintf(o, "\n"); oline++;
37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    line_source(o, a->d.rule->d.RuleOp.code->line);
37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    SubStr_out(&a->d.rule->d.RuleOp.code->text, o);
37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fprintf(o, "\n"); oline++;
37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if (!iFlag)
37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fprintf(o, "#line %u \"%s\"\n", oline++, outputFileName);
37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    break;
37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgAction *
38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgAction_new_Accept(State *x, unsigned int n, unsigned int *s, State **r)
38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Action *a = malloc(sizeof(Action));
38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    a->type = ACCEPTACT;
38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    a->state = x;
38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    a->d.Accept.nRules = n;
38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    a->d.Accept.saves = s;
38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    a->d.Accept.rules = r;
38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    x->action = a;
39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return a;
39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void doLinear(FILE *o, unsigned int i, Span *s, unsigned int n,
39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		     State *from, State *next, int *readCh){
39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(;;){
39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	State *bg = s[0].to;
39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	while(n >= 3 && s[2].to == bg && (s[1].ub - s[0].ub) == 1){
39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(s[1].to == next && n == 3){
39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		indent(o, i);
40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		genIf(o, "!=", s[0].ub, readCh);
40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		genGoTo(o, from, bg, readCh, "\t");
40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		indent(o, i);
40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		genGoTo(o, from, next, readCh, "\t");
40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		return;
40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else {
40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		indent(o, i);
40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		genIf(o, "==", s[0].ub, readCh);
40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		genGoTo(o, from, s[1].to, readCh, "\t");
40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    n -= 2; s += 2;
41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(n == 1){
41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    indent(o, i);
41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    genGoTo(o, from, s[0].to, readCh, "\t");
41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    return;
41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	} else if(n == 2 && bg == next){
41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    indent(o, i);
41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    genIf(o, ">=", s[0].ub, readCh);
41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    genGoTo(o, from, s[1].to, readCh, "\t");
42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    indent(o, i);
42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    genGoTo(o, from, next, readCh, "\t");
42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    return;
42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	} else {
42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    indent(o, i);
42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    genIf(o, "<=", s[0].ub - 1, readCh);
42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    genGoTo(o, from, bg, readCh, "\t");
42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    n -= 1; s += 1;
42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    indent(o, i);
43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    genGoTo(o, from, next, readCh, "\t");
43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgGo_genLinear(Go *g, FILE *o, State *from, State *next, int *readCh){
43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    doLinear(o, 0, g->span, g->nSpans, from, next, readCh);
43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void genCases(FILE *o, unsigned int lb, Span *s){
44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(lb < s->ub){
44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	for(;;){
44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fputs("\tcase '", o); prtCh(o, lb); fputs("':", o);
44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(++lb == s->ub)
44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		break;
44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fputs("\n", o); oline++;
44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgGo_genSwitch(Go *g, FILE *o, State *from, State *next, int *readCh){
45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(g->nSpans <= 2){
45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	Go_genLinear(g, o, from, next, readCh);
45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	State *def = g->span[g->nSpans-1].to;
45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	Span **sP = malloc(sizeof(Span*)*(g->nSpans-1)), **r, **s, **t;
45745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	unsigned int i;
45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	t = &sP[0];
46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	for(i = 0; i < g->nSpans; ++i)
46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(g->span[i].to != def)
46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		*(t++) = &g->span[i];
46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if (dFlag)
46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		fputs("\tYYDEBUG(-1, yych);\n", o);
46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if (*readCh) {
46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fputs("\tswitch((yych = *YYCURSOR)) {\n", o);
47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    *readCh = 0;
47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	} else
47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fputs("\tswitch(yych){\n", o);
47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline++;
47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	while(t != &sP[0]){
47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    State *to;
47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    r = s = &sP[0];
47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(*s == &g->span[0])
47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		genCases(o, 0, *s);
48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    else
48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		genCases(o, (*s)[-1].ub, *s);
48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    to = (*s)->to;
48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    while(++s < t){
48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if((*s)->to == to)
48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    genCases(o, (*s)[-1].ub, *s);
48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		else
48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    *(r++) = *s;
48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    genGoTo(o, from, to, readCh, "\t");
49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    t = r;
49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\tdefault:", o);
49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	genGoTo(o, from, def, readCh, "\t");
49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\t}\n", o); oline++;
49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	free(sP);
49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void doBinary(FILE *o, unsigned int i, Span *s, unsigned int n,
50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		     State *from, State *next, int *readCh){
50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(n <= 4){
50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	doLinear(o, i, s, n, from, next, readCh);
50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	unsigned int h = n/2;
50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	indent(o, i);
50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	genIf(o, "<=", s[h-1].ub - 1, readCh);
50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("{\n", o); oline++;
50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	doBinary(o, i+1, &s[0], h, from, next, readCh);
51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	indent(o, i); fputs("\t} else {\n", o); oline++;
51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	doBinary(o, i+1, &s[h], n - h, from, next, readCh);
51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	indent(o, i); fputs("\t}\n", o); oline++;
51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgGo_genBinary(Go *g, FILE *o, State *from, State *next, int *readCh){
51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    doBinary(o, 0, g->span, g->nSpans, from, next, readCh);
51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgGo_genBase(Go *g, FILE *o, State *from, State *next, int *readCh){
52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(g->nSpans == 0)
52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	return;
52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(!sFlag){
52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	Go_genSwitch(g, o, from, next, readCh);
52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	return;
52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(g->nSpans > 8){
53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	Span *bot = &g->span[0], *top = &g->span[g->nSpans-1];
53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	unsigned int util;
53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(bot[0].to == top[0].to){
53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    util = (top[-1].ub - bot[0].ub)/(g->nSpans - 2);
53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	} else {
53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(bot[0].ub > (top[0].ub - top[-1].ub)){
53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		util = (top[0].ub - bot[0].ub)/(g->nSpans - 1);
53745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else {
53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		util = top[-1].ub/(g->nSpans - 1);
53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(util <= 2){
54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    Go_genSwitch(g, o, from, next, readCh);
54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    return;
54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
54645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(g->nSpans > 5){
54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	Go_genBinary(g, o, from, next, readCh);
54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
54945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	Go_genLinear(g, o, from, next, readCh);
55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
55245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
55445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgGo_genGoto(Go *g, FILE *o, State *from, State *next, int *readCh){
55545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int i;
55645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(bFlag){
55745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	for(i = 0; i < g->nSpans; ++i){
55845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    State *to = g->span[i].to;
55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(to && to->isBase){
56045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		BitMap *b = BitMap_find(to);
56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(b && matches(b->go, b->on, g, to)){
56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    Go go;
56345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    go.span = malloc(sizeof(Span)*g->nSpans);
56445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    Go_unmap(&go, g, to);
56545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    fprintf(o, "\tif(yybm[%u+", b->i);
56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    if (*readCh)
56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			fputs("(yych = *YYCURSOR)", o);
56945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    else
57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			fputs("yych", o);
57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    fprintf(o, "] & %u) {\n", (unsigned int) b->m); oline++;
57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    genGoTo(o, from, to, readCh, "\t\t");
57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    fputs("\t}\n", o); oline++;
57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    Go_genBase(&go, o, from, next, readCh);
57645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    free(go.span);
57745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    return;
57845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		}
57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
58145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Go_genBase(g, o, from, next, readCh);
58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
58545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid State_emit(State *s, FILE *o, int *readCh){
58645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (vUsedLabels[s->label])
58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fprintf(o, "yy%u:", s->label);
58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (dFlag)
58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fprintf(o, "\n\tYYDEBUG(%u, *YYCURSOR);\n", s->label);
59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Action_emit(s->action, o, readCh);
59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
59345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic unsigned int merge(Span *x0, State *fg, State *bg){
59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Span *x = x0, *f = fg->go.span, *b = bg->go.span;
59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int nf = fg->go.nSpans, nb = bg->go.nSpans;
59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State *prev = NULL, *to;
59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* NB: we assume both spans are for same range */
59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(;;){
59945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(f->ub == b->ub){
60045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    to = f->to == b->to? bg : f->to;
60145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(to == prev){
60245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		--x;
60345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else {
60445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		x->to = prev = to;
60545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
60645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    x->ub = f->ub;
60745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    ++x; ++f; --nf; ++b; --nb;
60845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(nf == 0 && nb == 0)
60945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		return x - x0;
61045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
61145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	while(f->ub < b->ub){
61245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    to = f->to == b->to? bg : f->to;
61345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(to == prev){
61445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		--x;
61545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else {
61645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		x->to = prev = to;
61745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
61845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    x->ub = f->ub;
61945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    ++x; ++f; --nf;
62045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
62145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	while(b->ub < f->ub){
62245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    to = b->to == f->to? bg : f->to;
62345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(to == prev){
62445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		--x;
62545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    } else {
62645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		x->to = prev = to;
62745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
62845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    x->ub = b->ub;
62945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    ++x; ++b; --nb;
63045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
63145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
63245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
63345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
63445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst unsigned int cInfinity = ~0;
63545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
63645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct SCC {
63745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State	**top, **stk;
63845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} SCC;
63945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
64045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void SCC_init(SCC*, unsigned int);
64145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic SCC *SCC_new(unsigned int);
64245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void SCC_destroy(SCC*);
64345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void SCC_delete(SCC*);
64445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void SCC_traverse(SCC*, State*);
64545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
64645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
64745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgSCC_init(SCC *s, unsigned int size)
64845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
64945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->top = s->stk = malloc(sizeof(State*)*size);
65045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
65145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
65245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic SCC *
65345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgSCC_new(unsigned int size){
65445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SCC *s = malloc(sizeof(SCC));
65545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->top = s->stk = malloc(sizeof(State*)*size);
65645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return s;
65745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
65845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
65945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
66045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgSCC_destroy(SCC *s){
66145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free(s->stk);
66245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
66345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
66445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
66545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgSCC_delete(SCC *s){
66645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free(s->stk);
66745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free(s);
66845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
66945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
67045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void SCC_traverse(SCC *s, State *x){
67145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int k, i;
67245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
67345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *s->top = x;
67445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    k = ++s->top - s->stk;
67545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    x->depth = k;
67645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(i = 0; i < x->go.nSpans; ++i){
67745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	State *y = x->go.span[i].to;
67845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(y){
67945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(y->depth == 0)
68045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		SCC_traverse(s, y);
68145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(y->depth < x->depth)
68245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		x->depth = y->depth;
68345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
68445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
68545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(x->depth == k)
68645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	do {
68745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    (*--s->top)->depth = cInfinity;
68845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    (*s->top)->link = x;
68945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	} while(*s->top != x);
69045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
69145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
69245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic unsigned int maxDist(State *s){
69345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int mm = 0, i;
69445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(i = 0; i < s->go.nSpans; ++i){
69545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	State *t = s->go.span[i].to;
69645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(t){
69745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    unsigned int m = 1;
69845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(!t->link) {
69945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if (t->depth == -1)
70045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    t->depth = maxDist(t);
70145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		m += t->depth;
70245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
70345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(m > mm)
70445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		mm = m;
70545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
70645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
70745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return mm;
70845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
70945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
71045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void calcDepth(State *head){
71145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State *t, *s;
71245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = head; s; s = s->next){
71345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(s->link == s){
71445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    unsigned int i;
71545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    for(i = 0; i < s->go.nSpans; ++i){
71645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		t = s->go.span[i].to;
71745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(t && t->link == s)
71845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    goto inSCC;
71945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
72045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    s->link = NULL;
72145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	} else {
72245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	inSCC:
72345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    s->depth = maxDist(s);
72445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
72545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
72645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
72745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
72845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid DFA_findSCCs(DFA *d){
72945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SCC scc;
73045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State *s;
73145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
73245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SCC_init(&scc, d->nStates);
73345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next){
73445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	s->depth = 0;
73545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	s->link = NULL;
73645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
73745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
73845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next)
73945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(!s->depth)
74045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    SCC_traverse(&scc, s);
74145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
74245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    calcDepth(d->head);
74345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
74445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SCC_destroy(&scc);
74545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
74645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
74745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid DFA_split(DFA *d, State *s){
74845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State *move = State_new();
74945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Action_new_Move(move);
75045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    DFA_addState(d, &s->next, move);
75145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    move->link = s->link;
75245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    move->rule = s->rule;
75345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    move->go = s->go;
75445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->rule = NULL;
75545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->go.nSpans = 1;
75645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->go.span = malloc(sizeof(Span));
75745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->go.span[0].ub = d->ubChar;
75845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    s->go.span[0].to = move;
75945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
76045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
76145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid DFA_emit(DFA *d, FILE *o){
76245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    static unsigned int label = 0;
76345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State *s;
76445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int i, bitmap_brace = 0;
76545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int nRules = 0;
76645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int nSaves = 0;
76745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int *saves;
76845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int nOrgOline;
76945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State **rules;
77045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    State *accept = NULL;
77145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Span *span;
77245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    FILE *tmpo;
77345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int hasFillLabels;
77445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int maxFillIndexes, orgVFillIndexes;
77545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int start_label;
77645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
77745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    hasFillLabels = (0<=vFillIndexes);
77845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (hasFillLabels && label!=0) {
77945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("re2c : error : multiple /*!re2c blocks aren't supported when -f is specified\n", stderr);
78045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	exit(1);
78145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
78245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
78345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    DFA_findSCCs(d);
78445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    d->head->link = d->head;
78545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
78645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    maxFill = 1;
78745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next) {
78845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	s->depth = maxDist(s);
78945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if (maxFill < s->depth)
79045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    maxFill = s->depth;
79145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(s->rule && s->rule->d.RuleOp.accept >= nRules)
79245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		nRules = s->rule->d.RuleOp.accept + 1;
79345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
79445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
79545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    saves = malloc(sizeof(unsigned int)*nRules);
79645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    memset(saves, ~0, (nRules)*sizeof(unsigned int));
79745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
79845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* mark backtracking points */
79945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next){
80045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	RegExp *ignore = NULL;/*RuleOp*/
80145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(s->rule){
80245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    for(i = 0; i < s->go.nSpans; ++i)
80345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(s->go.span[i].to && !s->go.span[i].to->rule){
80445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    free(s->action);
80545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    if(saves[s->rule->d.RuleOp.accept] == ~0u)
80645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			saves[s->rule->d.RuleOp.accept] = nSaves++;
80745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    Action_new_Save(s, saves[s->rule->d.RuleOp.accept]);
80845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    continue;
80945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		}
81045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    ignore = s->rule;
81145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
81245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
81345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
81445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* insert actions */
81545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    rules = malloc(sizeof(State*)*nRules);
81645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    memset(rules, 0, (nRules)*sizeof(State*));
81745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next){
81845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	State *ow;
81945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(!s->rule){
82045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    ow = accept;
82145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	} else {
82245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(!rules[s->rule->d.RuleOp.accept]){
82345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		State *n = State_new();
82445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		Action_new_Rule(n, s->rule);
82545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		rules[s->rule->d.RuleOp.accept] = n;
82645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		DFA_addState(d, &s->next, n);
82745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
82845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    ow = rules[s->rule->d.RuleOp.accept];
82945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
83045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	for(i = 0; i < s->go.nSpans; ++i)
83145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    if(!s->go.span[i].to){
83245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(!ow){
83345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    ow = accept = State_new();
83445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    Action_new_Accept(accept, nRules, saves, rules);
83545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    DFA_addState(d, &s->next, accept);
83645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		}
83745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		s->go.span[i].to = ow;
83845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
83945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
84045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
84145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* split ``base'' states into two parts */
84245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next){
84345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	s->isBase = 0;
84445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(s->link){
84545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    for(i = 0; i < s->go.nSpans; ++i){
84645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(s->go.span[i].to == s){
84745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    s->isBase = 1;
84845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    DFA_split(d, s);
84945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    if(bFlag)
85045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			BitMap_find_go(&s->next->go, s);
85145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    s = s->next;
85245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    break;
85345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		}
85445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
85545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
85645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
85745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
85845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* find ``base'' state, if possible */
85945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    span = malloc(sizeof(Span)*(d->ubChar - d->lbChar));
86045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next){
86145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if(!s->link){
86245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    for(i = 0; i < s->go.nSpans; ++i){
86345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		State *to = s->go.span[i].to;
86445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		if(to && to->isBase){
86545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    unsigned int nSpans;
86645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    to = to->go.span[0].to;
86745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    nSpans = merge(span, s, to);
86845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    if(nSpans < s->go.nSpans){
86945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			free(s->go.span);
87045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			s->go.nSpans = nSpans;
87145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			s->go.span = malloc(sizeof(Span)*nSpans);
87245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org			memcpy(s->go.span, span, nSpans*sizeof(Span));
87345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    }
87445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		    break;
87545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org		}
87645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    }
87745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
87845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
87945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free(span);
88045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
88145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free(d->head->action);
88245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
88345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if(bFlag) {
88445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("{\n", o);
88545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline++;
88645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	bitmap_brace = 1;
88745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	BitMap_gen(o, d->lbChar, d->ubChar);
88845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
88945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bUsedYYAccept = 0;
89145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    start_label = label;
89345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Action_new_Enter(d->head, label++);
89545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next)
89745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	s->label = label++;
89845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nOrgOline = oline;
90045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    maxFillIndexes = vFillIndexes;
90145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    orgVFillIndexes = vFillIndexes;
902f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#ifdef _WIN32
903f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org    tmpo = win32_tmpfile();
904f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#else
9050534ef0dcba709f6f059ad31b73287042f40524dscottmg@chromium.org    tmpo = tmpfile();
906f164a228f51c17ffc3ed69516a7dc6abdf2d2c8escottmg@chromium.org#endif
90745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next){
90845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	int readCh = 0;
90945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	State_emit(s, tmpo, &readCh);
91045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	Go_genGoto(&s->go, tmpo, s, s->next, &readCh);
91145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
91245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fclose(tmpo);
91345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    maxFillIndexes = vFillIndexes;
91445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vFillIndexes = orgVFillIndexes;
91545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    oline = nOrgOline;
91645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
91745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fputs("\n", o);
91845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    oline++;
91945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!iFlag)
92045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fprintf(o, "#line %u \"%s\"\n", oline++, outputFileName);
92145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
92245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!hasFillLabels) {
92345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("{\n\tYYCTYPE yych;\n", o);
92445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline += 2;
92545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	if (bUsedYYAccept) {
92645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fputs("\tunsigned int yyaccept;\n", o);
92745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    oline++;
92845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	}
92945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
93045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("{\n\n", o);
93145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline += 2;
93245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
93345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
93445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!hasFillLabels) {
93545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fprintf(o, "\tgoto yy%u;\n", start_label);
93645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline++;
93745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	useLabel(label);
93845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
93945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	int i;
94045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\tswitch(YYGETSTATE()) {\n", o);
94145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\t\tcase -1: goto yy0;\n", o);
94245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
94345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	for (i=0; i<maxFillIndexes; ++i)
94445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	    fprintf(o, "\t\tcase %u: goto yyFillLabel%u;\n", i, i);
94545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
94645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\t\tdefault: /* abort() */;\n", o);
94745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("\t}\n", o);
94845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("yyNext:\n", o);
94945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
95045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline += maxFillIndexes;
95145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline += 5;
95245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
95345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
95445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for(s = d->head; s; s = s->next){
95545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	int readCh = 0;
95645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	State_emit(s, o, &readCh);
95745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	Go_genGoto(&s->go, o, s, s->next, &readCh);
95845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
95945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fputs("}\n", o); oline++;
96045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bitmap_brace) {
96145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	fputs("}\n", o);
96245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org	oline++;
96345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
96445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
96545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitMap_first = NULL;
96645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
96745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free(saves);
96845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free(rules);
96945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
970