diff options
Diffstat (limited to 'tools/re2c/code.c')
-rw-r--r-- | tools/re2c/code.c | 969 |
1 files changed, 969 insertions, 0 deletions
diff --git a/tools/re2c/code.c b/tools/re2c/code.c new file mode 100644 index 0000000..bd54baa --- /dev/null +++ b/tools/re2c/code.c @@ -0,0 +1,969 @@ +#ifdef _WIN32 +#include <windows.h> +#include <io.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "tools/re2c/substr.h" +#include "tools/re2c/globals.h" +#include "tools/re2c/dfa.h" +#include "tools/re2c/parse.h" + +#ifdef _WIN32 +/* tmpfile() replacment for Windows. + * + * On Windows tmpfile() creates the file in the root directory. This + * may fail due to unsufficient privileges. + */ +static FILE * +win32_tmpfile (void) +{ + DWORD path_len; + WCHAR path_name[MAX_PATH + 1]; + WCHAR file_name[MAX_PATH + 1]; + HANDLE handle; + int fd; + FILE *fp; + + path_len = GetTempPathW (MAX_PATH, path_name); + if (path_len <= 0 || path_len >= MAX_PATH) + return NULL; + + if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0) + return NULL; + + handle = CreateFileW (file_name, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + if (handle == INVALID_HANDLE_VALUE) { + DeleteFileW (file_name); + return NULL; + } + + fd = _open_osfhandle((intptr_t) handle, 0); + if (fd < 0) { + CloseHandle (handle); + return NULL; + } + + fp = fdopen(fd, "w+b"); + if (fp == NULL) { + _close(fd); + return NULL; + } + + return fp; +} +#endif + +static void useLabel(size_t value) { + while (value >= vUsedLabelAlloc) { + vUsedLabels = realloc(vUsedLabels, vUsedLabelAlloc * 2); + if (!vUsedLabels) { + fputs("Out of memory.\n", stderr); + exit(EXIT_FAILURE); + } + memset(vUsedLabels + vUsedLabelAlloc, 0, vUsedLabelAlloc); + vUsedLabelAlloc *= 2; + } + vUsedLabels[value] = 1; +} + +/* there must be at least one span in list; all spans must cover + * same range + */ + +void Go_compact(Go *g){ + /* arrange so that adjacent spans have different targets */ + unsigned int i = 0, j; + for(j = 1; j < g->nSpans; ++j){ + if(g->span[j].to != g->span[i].to){ + ++i; g->span[i].to = g->span[j].to; + } + g->span[i].ub = g->span[j].ub; + } + g->nSpans = i + 1; +} + +void Go_unmap(Go *g, Go *base, State *x){ + Span *s = g->span, *b = base->span, *e = &b[base->nSpans]; + unsigned int lb = 0; + s->ub = 0; + s->to = NULL; + for(; b != e; ++b){ + if(b->to == x){ + if((s->ub - lb) > 1) + s->ub = b->ub; + } else { + if(b->to != s->to){ + if(s->ub){ + lb = s->ub; ++s; + } + s->to = b->to; + } + s->ub = b->ub; + } + } + s->ub = e[-1].ub; ++s; + g->nSpans = s - g->span; +} + +static void doGen(Go *g, State *s, unsigned char *bm, unsigned char m){ + Span *b = g->span, *e = &b[g->nSpans]; + unsigned int lb = 0; + for(; b < e; ++b){ + if(b->to == s) + for(; lb < b->ub; ++lb) bm[lb] |= m; + lb = b->ub; + } +} +#if 0 +static void prt(FILE *o, Go *g, State *s){ + Span *b = g->span, *e = &b[g->nSpans]; + unsigned int lb = 0; + for(; b < e; ++b){ + if(b->to == s) + printSpan(o, lb, b->ub); + lb = b->ub; + } +} +#endif +static int matches(Go *g1, State *s1, Go *g2, State *s2){ + Span *b1 = g1->span, *e1 = &b1[g1->nSpans]; + unsigned int lb1 = 0; + Span *b2 = g2->span, *e2 = &b2[g2->nSpans]; + unsigned int lb2 = 0; + for(;;){ + for(; b1 < e1 && b1->to != s1; ++b1) lb1 = b1->ub; + for(; b2 < e2 && b2->to != s2; ++b2) lb2 = b2->ub; + if(b1 == e1) return b2 == e2; + if(b2 == e2) return 0; + if(lb1 != lb2 || b1->ub != b2->ub) return 0; + ++b1; ++b2; + } +} + +typedef struct BitMap { + Go *go; + State *on; + struct BitMap *next; + unsigned int i; + unsigned char m; +} BitMap; + +static BitMap *BitMap_find_go(Go*, State*); +static BitMap *BitMap_find(State*); +static void BitMap_gen(FILE *, unsigned int, unsigned int); +/* static void BitMap_stats(void);*/ +static BitMap *BitMap_new(Go*, State*); + +static BitMap *BitMap_first = NULL; + +BitMap * +BitMap_new(Go *g, State *x) +{ + BitMap *b = malloc(sizeof(BitMap)); + b->go = g; + b->on = x; + b->next = BitMap_first; + BitMap_first = b; + return b; +} + +BitMap * +BitMap_find_go(Go *g, State *x){ + BitMap *b; + for(b = BitMap_first; b; b = b->next){ + if(matches(b->go, b->on, g, x)) + return b; + } + return BitMap_new(g, x); +} + +BitMap * +BitMap_find(State *x){ + BitMap *b; + for(b = BitMap_first; b; b = b->next){ + if(b->on == x) + return b; + } + return NULL; +} + +void BitMap_gen(FILE *o, unsigned int lb, unsigned int ub){ + BitMap *b = BitMap_first; + if(b){ + unsigned int n = ub - lb; + unsigned int i; + unsigned char *bm = malloc(sizeof(unsigned char)*n); + fputs("\tstatic unsigned char yybm[] = {", o); + for(i = 0; b; i += n){ + unsigned char m; + unsigned int j; + memset(bm, 0, n); + for(m = 0x80; b && m; b = b->next, m >>= 1){ + b->i = i; b->m = m; + doGen(b->go, b->on, bm-lb, m); + } + for(j = 0; j < n; ++j){ + if(j%8 == 0) {fputs("\n\t", o); oline++;} + fprintf(o, "%3u, ", (unsigned int) bm[j]); + } + } + fputs("\n\t};\n", o); oline+=2; + free(bm); + } +} + +#if 0 +void BitMap_stats(void){ + unsigned int n = 0; + BitMap *b; + for(b = BitMap_first; b; b = b->next){ + prt(stderr, b->go, b->on); fputs("\n", stderr); + ++n; + } + fprintf(stderr, "%u bitmaps\n", n); + BitMap_first = NULL; +} +#endif + +static void genGoTo(FILE *o, State *from, State *to, int *readCh, + const char *indent) +{ +#if 0 + if (*readCh && from->label + 1 != to->label) + { + fputs("%syych = *YYCURSOR;\n", indent, o); oline++; + *readCh = 0; + } +#endif + fprintf(o, "%sgoto yy%u;\n", indent, to->label); oline++; + useLabel(to->label); +} + +static void genIf(FILE *o, const char *cmp, unsigned int v, int *readCh) +{ +#if 0 + if (*readCh) + { + fputs("\tif((yych = *YYCURSOR) ", o); + *readCh = 0; + } else { +#endif + fputs("\tif(yych ", o); +#if 0 + } +#endif + fprintf(o, "%s '", cmp); + prtCh(o, v); + fputs("')", o); +} + +static void indent(FILE *o, unsigned int i){ + while(i-- > 0) + fputc('\t', o); +} + +static void need(FILE *o, unsigned int n, int *readCh) +{ + unsigned int fillIndex; + int hasFillIndex = (0<=vFillIndexes); + if (hasFillIndex) { + fillIndex = vFillIndexes++; + fprintf(o, "\tYYSETSTATE(%u);\n", fillIndex); + ++oline; + } + + if(n == 1) { + fputs("\tif(YYLIMIT == YYCURSOR) YYFILL(1);\n", o); oline++; + } else { + fprintf(o, "\tif((YYLIMIT - YYCURSOR) < %u) YYFILL(%u);\n", n, n); + oline++; + } + + if (hasFillIndex) { + fprintf(o, "yyFillLabel%u:\n", fillIndex); + ++oline; + } + + fputs("\tyych = *YYCURSOR;\n", o); oline++; + *readCh = 0; +} + +void +Action_emit(Action *a, FILE *o, int *readCh) +{ + int first = 1; + unsigned int i; + unsigned int back; + + switch (a->type) { + case MATCHACT: + if(a->state->link){ + fputs("\t++YYCURSOR;\n", o); + need(o, a->state->depth, readCh); +#if 0 + } else if (!Action_readAhead(a)) { + /* do not read next char if match */ + fputs("\t++YYCURSOR;\n", o); + *readCh = 1; +#endif + } else { + fputs("\tyych = *++YYCURSOR;\n", o); + *readCh = 0; + } + oline++; + break; + case ENTERACT: + if(a->state->link){ + fputs("\t++YYCURSOR;\n", o); + fprintf(o, "yy%u:\n", a->d.label); oline+=2; + need(o, a->state->depth, readCh); + } else { + /* we shouldn't need 'rule-following' protection here */ + fputs("\tyych = *++YYCURSOR;\n", o); + fprintf(o, "yy%u:\n", a->d.label); oline+=2; + *readCh = 0; + } + break; + case SAVEMATCHACT: + if (bUsedYYAccept) { + fprintf(o, "\tyyaccept = %u;\n", a->d.selector); + oline++; + } + if(a->state->link){ + fputs("\tYYMARKER = ++YYCURSOR;\n", o); oline++; + need(o, a->state->depth, readCh); + } else { + fputs("\tyych = *(YYMARKER = ++YYCURSOR);\n", o); oline++; + *readCh = 0; + } + break; + case MOVEACT: + break; + case ACCEPTACT: + for(i = 0; i < a->d.Accept.nRules; ++i) + if(a->d.Accept.saves[i] != ~0u){ + if(first){ + first = 0; + bUsedYYAccept = 1; + fputs("\tYYCURSOR = YYMARKER;\n", o); + fputs("\tswitch(yyaccept){\n", o); oline+=2; + } + fprintf(o, "\tcase %u:", a->d.Accept.saves[i]); + genGoTo(o, a->state, a->d.Accept.rules[i], readCh, "\t"); + } + if(!first) { + fputs("\t}\n", o); oline++; + } + break; + case RULEACT: + back = RegExp_fixedLength(a->d.rule->d.RuleOp.ctx); + if(back != ~0u && back > 0u) + fprintf(o, "\tYYCURSOR -= %u;", back); + fprintf(o, "\n"); oline++; + line_source(o, a->d.rule->d.RuleOp.code->line); + SubStr_out(&a->d.rule->d.RuleOp.code->text, o); + fprintf(o, "\n"); oline++; + if (!iFlag) + fprintf(o, "#line %u \"%s\"\n", oline++, outputFileName); + break; + } +} + +Action * +Action_new_Accept(State *x, unsigned int n, unsigned int *s, State **r) +{ + Action *a = malloc(sizeof(Action)); + a->type = ACCEPTACT; + a->state = x; + a->d.Accept.nRules = n; + a->d.Accept.saves = s; + a->d.Accept.rules = r; + x->action = a; + return a; +} + +static void doLinear(FILE *o, unsigned int i, Span *s, unsigned int n, + State *from, State *next, int *readCh){ + for(;;){ + State *bg = s[0].to; + while(n >= 3 && s[2].to == bg && (s[1].ub - s[0].ub) == 1){ + if(s[1].to == next && n == 3){ + indent(o, i); + genIf(o, "!=", s[0].ub, readCh); + genGoTo(o, from, bg, readCh, "\t"); + indent(o, i); + genGoTo(o, from, next, readCh, "\t"); + return; + } else { + indent(o, i); + genIf(o, "==", s[0].ub, readCh); + genGoTo(o, from, s[1].to, readCh, "\t"); + } + n -= 2; s += 2; + } + if(n == 1){ + indent(o, i); + genGoTo(o, from, s[0].to, readCh, "\t"); + return; + } else if(n == 2 && bg == next){ + indent(o, i); + genIf(o, ">=", s[0].ub, readCh); + genGoTo(o, from, s[1].to, readCh, "\t"); + indent(o, i); + genGoTo(o, from, next, readCh, "\t"); + return; + } else { + indent(o, i); + genIf(o, "<=", s[0].ub - 1, readCh); + genGoTo(o, from, bg, readCh, "\t"); + n -= 1; s += 1; + } + } + indent(o, i); + genGoTo(o, from, next, readCh, "\t"); +} + +void +Go_genLinear(Go *g, FILE *o, State *from, State *next, int *readCh){ + doLinear(o, 0, g->span, g->nSpans, from, next, readCh); +} + +static void genCases(FILE *o, unsigned int lb, Span *s){ + if(lb < s->ub){ + for(;;){ + fputs("\tcase '", o); prtCh(o, lb); fputs("':", o); + if(++lb == s->ub) + break; + fputs("\n", o); oline++; + } + } +} + +void +Go_genSwitch(Go *g, FILE *o, State *from, State *next, int *readCh){ + if(g->nSpans <= 2){ + Go_genLinear(g, o, from, next, readCh); + } else { + State *def = g->span[g->nSpans-1].to; + Span **sP = malloc(sizeof(Span*)*(g->nSpans-1)), **r, **s, **t; + unsigned int i; + + t = &sP[0]; + for(i = 0; i < g->nSpans; ++i) + if(g->span[i].to != def) + *(t++) = &g->span[i]; + + if (dFlag) + fputs("\tYYDEBUG(-1, yych);\n", o); + +#if 0 + if (*readCh) { + fputs("\tswitch((yych = *YYCURSOR)) {\n", o); + *readCh = 0; + } else +#endif + fputs("\tswitch(yych){\n", o); + oline++; + while(t != &sP[0]){ + State *to; + r = s = &sP[0]; + if(*s == &g->span[0]) + genCases(o, 0, *s); + else + genCases(o, (*s)[-1].ub, *s); + to = (*s)->to; + while(++s < t){ + if((*s)->to == to) + genCases(o, (*s)[-1].ub, *s); + else + *(r++) = *s; + } + genGoTo(o, from, to, readCh, "\t"); + t = r; + } + fputs("\tdefault:", o); + genGoTo(o, from, def, readCh, "\t"); + fputs("\t}\n", o); oline++; + + free(sP); + } +} + +static void doBinary(FILE *o, unsigned int i, Span *s, unsigned int n, + State *from, State *next, int *readCh){ + if(n <= 4){ + doLinear(o, i, s, n, from, next, readCh); + } else { + unsigned int h = n/2; + indent(o, i); + genIf(o, "<=", s[h-1].ub - 1, readCh); + fputs("{\n", o); oline++; + doBinary(o, i+1, &s[0], h, from, next, readCh); + indent(o, i); fputs("\t} else {\n", o); oline++; + doBinary(o, i+1, &s[h], n - h, from, next, readCh); + indent(o, i); fputs("\t}\n", o); oline++; + } +} + +void +Go_genBinary(Go *g, FILE *o, State *from, State *next, int *readCh){ + doBinary(o, 0, g->span, g->nSpans, from, next, readCh); +} + +void +Go_genBase(Go *g, FILE *o, State *from, State *next, int *readCh){ + if(g->nSpans == 0) + return; + if(!sFlag){ + Go_genSwitch(g, o, from, next, readCh); + return; + } + if(g->nSpans > 8){ + Span *bot = &g->span[0], *top = &g->span[g->nSpans-1]; + unsigned int util; + if(bot[0].to == top[0].to){ + util = (top[-1].ub - bot[0].ub)/(g->nSpans - 2); + } else { + if(bot[0].ub > (top[0].ub - top[-1].ub)){ + util = (top[0].ub - bot[0].ub)/(g->nSpans - 1); + } else { + util = top[-1].ub/(g->nSpans - 1); + } + } + if(util <= 2){ + Go_genSwitch(g, o, from, next, readCh); + return; + } + } + if(g->nSpans > 5){ + Go_genBinary(g, o, from, next, readCh); + } else { + Go_genLinear(g, o, from, next, readCh); + } +} + +void +Go_genGoto(Go *g, FILE *o, State *from, State *next, int *readCh){ + unsigned int i; + if(bFlag){ + for(i = 0; i < g->nSpans; ++i){ + State *to = g->span[i].to; + if(to && to->isBase){ + BitMap *b = BitMap_find(to); + if(b && matches(b->go, b->on, g, to)){ + Go go; + go.span = malloc(sizeof(Span)*g->nSpans); + Go_unmap(&go, g, to); + fprintf(o, "\tif(yybm[%u+", b->i); +#if 0 + if (*readCh) + fputs("(yych = *YYCURSOR)", o); + else +#endif + fputs("yych", o); + fprintf(o, "] & %u) {\n", (unsigned int) b->m); oline++; + genGoTo(o, from, to, readCh, "\t\t"); + fputs("\t}\n", o); oline++; + Go_genBase(&go, o, from, next, readCh); + free(go.span); + return; + } + } + } + } + Go_genBase(g, o, from, next, readCh); +} + +void State_emit(State *s, FILE *o, int *readCh){ + if (vUsedLabels[s->label]) + fprintf(o, "yy%u:", s->label); + if (dFlag) + fprintf(o, "\n\tYYDEBUG(%u, *YYCURSOR);\n", s->label); + Action_emit(s->action, o, readCh); +} + +static unsigned int merge(Span *x0, State *fg, State *bg){ + Span *x = x0, *f = fg->go.span, *b = bg->go.span; + unsigned int nf = fg->go.nSpans, nb = bg->go.nSpans; + State *prev = NULL, *to; + /* NB: we assume both spans are for same range */ + for(;;){ + if(f->ub == b->ub){ + to = f->to == b->to? bg : f->to; + if(to == prev){ + --x; + } else { + x->to = prev = to; + } + x->ub = f->ub; + ++x; ++f; --nf; ++b; --nb; + if(nf == 0 && nb == 0) + return x - x0; + } + while(f->ub < b->ub){ + to = f->to == b->to? bg : f->to; + if(to == prev){ + --x; + } else { + x->to = prev = to; + } + x->ub = f->ub; + ++x; ++f; --nf; + } + while(b->ub < f->ub){ + to = b->to == f->to? bg : f->to; + if(to == prev){ + --x; + } else { + x->to = prev = to; + } + x->ub = b->ub; + ++x; ++b; --nb; + } + } +} + +const unsigned int cInfinity = ~0; + +typedef struct SCC { + State **top, **stk; +} SCC; + +static void SCC_init(SCC*, unsigned int); +static SCC *SCC_new(unsigned int); +static void SCC_destroy(SCC*); +static void SCC_delete(SCC*); +static void SCC_traverse(SCC*, State*); + +static void +SCC_init(SCC *s, unsigned int size) +{ + s->top = s->stk = malloc(sizeof(State*)*size); +} + +static SCC * +SCC_new(unsigned int size){ + SCC *s = malloc(sizeof(SCC)); + s->top = s->stk = malloc(sizeof(State*)*size); + return s; +} + +static void +SCC_destroy(SCC *s){ + free(s->stk); +} + +static void +SCC_delete(SCC *s){ + free(s->stk); + free(s); +} + +static void SCC_traverse(SCC *s, State *x){ + unsigned int k, i; + + *s->top = x; + k = ++s->top - s->stk; + x->depth = k; + for(i = 0; i < x->go.nSpans; ++i){ + State *y = x->go.span[i].to; + if(y){ + if(y->depth == 0) + SCC_traverse(s, y); + if(y->depth < x->depth) + x->depth = y->depth; + } + } + if(x->depth == k) + do { + (*--s->top)->depth = cInfinity; + (*s->top)->link = x; + } while(*s->top != x); +} + +static unsigned int maxDist(State *s){ + unsigned int mm = 0, i; + for(i = 0; i < s->go.nSpans; ++i){ + State *t = s->go.span[i].to; + if(t){ + unsigned int m = 1; + if(!t->link) { + if (t->depth == -1) + t->depth = maxDist(t); + m += t->depth; + } + if(m > mm) + mm = m; + } + } + return mm; +} + +static void calcDepth(State *head){ + State *t, *s; + for(s = head; s; s = s->next){ + if(s->link == s){ + unsigned int i; + for(i = 0; i < s->go.nSpans; ++i){ + t = s->go.span[i].to; + if(t && t->link == s) + goto inSCC; + } + s->link = NULL; + } else { + inSCC: + s->depth = maxDist(s); + } + } +} + +void DFA_findSCCs(DFA *d){ + SCC scc; + State *s; + + SCC_init(&scc, d->nStates); + for(s = d->head; s; s = s->next){ + s->depth = 0; + s->link = NULL; + } + + for(s = d->head; s; s = s->next) + if(!s->depth) + SCC_traverse(&scc, s); + + calcDepth(d->head); + + SCC_destroy(&scc); +} + +void DFA_split(DFA *d, State *s){ + State *move = State_new(); + Action_new_Move(move); + DFA_addState(d, &s->next, move); + move->link = s->link; + move->rule = s->rule; + move->go = s->go; + s->rule = NULL; + s->go.nSpans = 1; + s->go.span = malloc(sizeof(Span)); + s->go.span[0].ub = d->ubChar; + s->go.span[0].to = move; +} + +void DFA_emit(DFA *d, FILE *o){ + static unsigned int label = 0; + State *s; + unsigned int i, bitmap_brace = 0; + unsigned int nRules = 0; + unsigned int nSaves = 0; + unsigned int *saves; + unsigned int nOrgOline; + State **rules; + State *accept = NULL; + Span *span; + FILE *tmpo; + int hasFillLabels; + int maxFillIndexes, orgVFillIndexes; + unsigned int start_label; + + hasFillLabels = (0<=vFillIndexes); + if (hasFillLabels && label!=0) { + fputs("re2c : error : multiple /*!re2c blocks aren't supported when -f is specified\n", stderr); + exit(1); + } + + DFA_findSCCs(d); + d->head->link = d->head; + + maxFill = 1; + for(s = d->head; s; s = s->next) { + s->depth = maxDist(s); + if (maxFill < s->depth) + maxFill = s->depth; + if(s->rule && s->rule->d.RuleOp.accept >= nRules) + nRules = s->rule->d.RuleOp.accept + 1; + } + + saves = malloc(sizeof(unsigned int)*nRules); + memset(saves, ~0, (nRules)*sizeof(unsigned int)); + + /* mark backtracking points */ + for(s = d->head; s; s = s->next){ + RegExp *ignore = NULL;/*RuleOp*/ + if(s->rule){ + for(i = 0; i < s->go.nSpans; ++i) + if(s->go.span[i].to && !s->go.span[i].to->rule){ + free(s->action); + if(saves[s->rule->d.RuleOp.accept] == ~0u) + saves[s->rule->d.RuleOp.accept] = nSaves++; + Action_new_Save(s, saves[s->rule->d.RuleOp.accept]); + continue; + } + ignore = s->rule; + } + } + + /* insert actions */ + rules = malloc(sizeof(State*)*nRules); + memset(rules, 0, (nRules)*sizeof(State*)); + for(s = d->head; s; s = s->next){ + State *ow; + if(!s->rule){ + ow = accept; + } else { + if(!rules[s->rule->d.RuleOp.accept]){ + State *n = State_new(); + Action_new_Rule(n, s->rule); + rules[s->rule->d.RuleOp.accept] = n; + DFA_addState(d, &s->next, n); + } + ow = rules[s->rule->d.RuleOp.accept]; + } + for(i = 0; i < s->go.nSpans; ++i) + if(!s->go.span[i].to){ + if(!ow){ + ow = accept = State_new(); + Action_new_Accept(accept, nRules, saves, rules); + DFA_addState(d, &s->next, accept); + } + s->go.span[i].to = ow; + } + } + + /* split ``base'' states into two parts */ + for(s = d->head; s; s = s->next){ + s->isBase = 0; + if(s->link){ + for(i = 0; i < s->go.nSpans; ++i){ + if(s->go.span[i].to == s){ + s->isBase = 1; + DFA_split(d, s); + if(bFlag) + BitMap_find_go(&s->next->go, s); + s = s->next; + break; + } + } + } + } + + /* find ``base'' state, if possible */ + span = malloc(sizeof(Span)*(d->ubChar - d->lbChar)); + for(s = d->head; s; s = s->next){ + if(!s->link){ + for(i = 0; i < s->go.nSpans; ++i){ + State *to = s->go.span[i].to; + if(to && to->isBase){ + unsigned int nSpans; + to = to->go.span[0].to; + nSpans = merge(span, s, to); + if(nSpans < s->go.nSpans){ + free(s->go.span); + s->go.nSpans = nSpans; + s->go.span = malloc(sizeof(Span)*nSpans); + memcpy(s->go.span, span, nSpans*sizeof(Span)); + } + break; + } + } + } + } + free(span); + + free(d->head->action); + + if(bFlag) { + fputs("{\n", o); + oline++; + bitmap_brace = 1; + BitMap_gen(o, d->lbChar, d->ubChar); + } + + bUsedYYAccept = 0; + + start_label = label; + + Action_new_Enter(d->head, label++); + + for(s = d->head; s; s = s->next) + s->label = label++; + + nOrgOline = oline; + maxFillIndexes = vFillIndexes; + orgVFillIndexes = vFillIndexes; +#ifdef _WIN32 + tmpo = win32_tmpfile(); +#else + tmpo = tmpfile(); +#endif + for(s = d->head; s; s = s->next){ + int readCh = 0; + State_emit(s, tmpo, &readCh); + Go_genGoto(&s->go, tmpo, s, s->next, &readCh); + } + fclose(tmpo); + maxFillIndexes = vFillIndexes; + vFillIndexes = orgVFillIndexes; + oline = nOrgOline; + + fputs("\n", o); + oline++; + if (!iFlag) + fprintf(o, "#line %u \"%s\"\n", oline++, outputFileName); + + if (!hasFillLabels) { + fputs("{\n\tYYCTYPE yych;\n", o); + oline += 2; + if (bUsedYYAccept) { + fputs("\tunsigned int yyaccept;\n", o); + oline++; + } + } else { + fputs("{\n\n", o); + oline += 2; + } + + if (!hasFillLabels) { + fprintf(o, "\tgoto yy%u;\n", start_label); + oline++; + useLabel(label); + } else { + int i; + fputs("\tswitch(YYGETSTATE()) {\n", o); + fputs("\t\tcase -1: goto yy0;\n", o); + + for (i=0; i<maxFillIndexes; ++i) + fprintf(o, "\t\tcase %u: goto yyFillLabel%u;\n", i, i); + + fputs("\t\tdefault: /* abort() */;\n", o); + fputs("\t}\n", o); + fputs("yyNext:\n", o); + + oline += maxFillIndexes; + oline += 5; + } + + for(s = d->head; s; s = s->next){ + int readCh = 0; + State_emit(s, o, &readCh); + Go_genGoto(&s->go, o, s, s->next, &readCh); + } + fputs("}\n", o); oline++; + if (bitmap_brace) { + fputs("}\n", o); + oline++; + } + + BitMap_first = NULL; + + free(saves); + free(rules); +} |