From d2224bb8151ae57bc355f06cda7470b2b3ca5f0f Mon Sep 17 00:00:00 2001 From: helly Date: Sun, 22 Apr 2007 14:56:40 +0000 Subject: [PATCH] - Add -t switch to generate header with all types --- re2c/bootstrap/parser.cc | 6 +- re2c/bootstrap/scanner.cc | 2 +- re2c/code.cc | 34 +++- re2c/main.cc | 55 +++++-- re2c/parser.h | 2 +- re2c/parser.y | 6 +- re2c/re.h | 5 +- re2c/run_tests.sh.in | 40 +++-- .../test/condition_05.cgtcondition_05.cgt.h.c | 150 ++++++++++++++++++ .../test/condition_05.cgtcondition_05.cgt.h.h | 5 + .../condition_05.cgtcondition_05.cgt.h.re | 118 ++++++++++++++ 11 files changed, 384 insertions(+), 39 deletions(-) create mode 100755 re2c/test/condition_05.cgtcondition_05.cgt.h.c create mode 100755 re2c/test/condition_05.cgtcondition_05.cgt.h.h create mode 100755 re2c/test/condition_05.cgtcondition_05.cgt.h.re diff --git a/re2c/bootstrap/parser.cc b/re2c/bootstrap/parser.cc index 753b9de1..062e9908 100644 --- a/re2c/bootstrap/parser.cc +++ b/re2c/bootstrap/parser.cc @@ -1822,7 +1822,7 @@ int yylex(){ namespace re2c { -void parse(Scanner& i, std::ostream& o) +void parse(Scanner& i, std::ostream& o, std::ostream* h) { in = &i; @@ -1870,6 +1870,10 @@ void parse(Scanner& i, std::ostream& o) assert(it->second.second); genCode(o, topIndent, it->second.second, &specMap, it->first, !--nCount); } + if (h) + { + genHeader(*h, 0, specMap); + } } else if(spec) { diff --git a/re2c/bootstrap/scanner.cc b/re2c/bootstrap/scanner.cc index 19ff702c..fc4425c8 100644 --- a/re2c/bootstrap/scanner.cc +++ b/re2c/bootstrap/scanner.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.0.dev on Wed Apr 18 16:04:00 2007 */ +/* Generated by re2c 0.11.1.dev on Sat Apr 21 11:15:09 2007 */ #line 1 "scanner.re" /* $Id$ */ #include diff --git a/re2c/code.cc b/re2c/code.cc index 8268b5dc..ea5dc4cd 100644 --- a/re2c/code.cc +++ b/re2c/code.cc @@ -1587,9 +1587,9 @@ void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std:: if (bProlog) { - genCondTable(o, ind, specMap); + genCondTable(o, ind, *specMap); genGetState(o, ind, start_label); - genCondGoto(o, ind, specMap); + genCondGoto(o, ind, *specMap); } if (cFlag && (bFlag || !condName.empty())) @@ -1663,13 +1663,13 @@ void genGetState(std::ostream &o, uint& ind, uint start_label) } } -void genCondTable(std::ostream &o, uint ind, const RegExpMap* specMap) +void genCondTable(std::ostream &o, uint ind, const RegExpMap& specMap) { if (cFlag && !bWroteCondCheck && gFlag) { - o << indent(ind++) << "static void *" << mapCodeName["yyctable"] << "[" << specMap->size() << "] = {\n"; + o << indent(ind++) << "static void *" << mapCodeName["yyctable"] << "[" << specMap.size() << "] = {\n"; - for(RegExpMap::const_iterator it = specMap->begin(); it != specMap->end(); ++it) + for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) { o << indent(ind) << "&&" << condPrefix << it->first << ",\n"; } @@ -1677,7 +1677,7 @@ void genCondTable(std::ostream &o, uint ind, const RegExpMap* specMap) } } -void genCondGoto(std::ostream &o, uint ind, const RegExpMap* specMap) +void genCondGoto(std::ostream &o, uint ind, const RegExpMap& specMap) { if (cFlag && !bWroteCondCheck) { @@ -1688,7 +1688,7 @@ void genCondGoto(std::ostream &o, uint ind, const RegExpMap* specMap) else { o << indent(ind) << "switch(" << mapCodeName["YYCONDITION"] << ") {\n"; - for(RegExpMap::const_iterator it = specMap->begin(); it != specMap->end(); ++it) + for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) { o << indent(ind) << "case " << it->first << ": goto " << condPrefix << it->first << ";\n"; } @@ -1698,6 +1698,25 @@ void genCondGoto(std::ostream &o, uint ind, const RegExpMap* specMap) } } +void genHeader(std::ostream &o, uint ind, const RegExpMap& specMap) +{ + o << "/* Generated by re2c " PACKAGE_VERSION; + if (!bNoGenerationDate) + { + o << " on "; + time_t now = time(&now); + o.write(ctime(&now), 24); + } + o << " */\n"; + //TODO: o << headerFileInfo; + o << indent(ind++) << "enum " << mapCodeName["YYCONDTYPE"] << " {\n"; + for(RegExpMap::const_iterator it = specMap.begin(); it != specMap.end(); ++it) + { + o << indent(ind) << it->first << ",\n"; + } + o << indent(--ind) << "}\n"; +} + std::ostream& operator << (std::ostream& o, const file_info& li) { if (li.ln && !iFlag) @@ -1784,6 +1803,7 @@ void Scanner::config(const Str& cfg, const Str& val) mapVariableKeys.insert("variable:yyctable"); mapVariableKeys.insert("variable:yytarget"); mapDefineKeys.insert("define:YYCONDITION"); + mapDefineKeys.insert("define:YYCONDTYPE"); mapDefineKeys.insert("define:YYCTXMARKER"); mapDefineKeys.insert("define:YYCTYPE"); mapDefineKeys.insert("define:YYCURSOR"); diff --git a/re2c/main.cc b/re2c/main.cc index cc100441..6cf79237 100644 --- a/re2c/main.cc +++ b/re2c/main.cc @@ -90,6 +90,7 @@ static const mbo_opt_struct OPTIONS[] = mbo_opt_struct('i', 0, "no-debug-info"), mbo_opt_struct('o', 1, "output"), mbo_opt_struct('s', 0, "nested-ifs"), + mbo_opt_struct('t', 1, "header"), mbo_opt_struct('u', 0, "unicode"), mbo_opt_struct('v', 0, "version"), mbo_opt_struct('V', 0, "vernum"), @@ -132,6 +133,8 @@ static void usage() "-s --nested-ifs Generate nested ifs for some switches. Many compilers\n" " need this assist to generate better code.\n" "\n" + "-t --header Generate a header file with type definitions.\n" + "\n" "-u --unicode Implies -w but supports the full Unicode character set.\n" "\n" "-v --version Show version information.\n" @@ -159,6 +162,7 @@ int main(int argc, char *argv[]) int c; const char *sourceFileName = 0; const char *outputFileName = 0; + const char *headerFileName = 0; if (argc == 1) { @@ -192,10 +196,6 @@ int main(int argc, char *argv[]) case 'f': fFlag = true; - if (bSinglePass) { - std::cerr << "re2c: error: cannot combine -1 and -f switch\n"; - return 1; - } break; case 'g': @@ -215,6 +215,10 @@ int main(int argc, char *argv[]) case 's': sFlag = true; break; + + case 't': + headerFileName = opt_arg; + break; case '1': bSinglePass = true; @@ -247,11 +251,6 @@ int main(int argc, char *argv[]) } case 'w': - if (uFlag) - { - std::cerr << "re2c: error: cannot combine -w and -u switch\n"; - return 1; - } nRealChars = (1<<16); /* 0x10000 */ sFlag = true; wFlag = true; @@ -260,7 +259,6 @@ int main(int argc, char *argv[]) case 'u': nRealChars = 0x110000; /* 17 times w-Flag */ sFlag = true; - wFlag = true; uFlag = true; break; @@ -276,17 +274,33 @@ int main(int argc, char *argv[]) } } - if (bFlag && bSinglePass) { - std::cerr << "re2c: error: cannot combine -1 and -f switch\n"; + if ((bFlag || fFlag) && bSinglePass) { + std::cerr << "re2c: error: Cannot combine -1 and -b or -f switch\n"; return 1; } + if (!cFlag && headerFileName) + { + std::cerr << "re2c: error: Can only output a header file when using -c switch\n"; + return 2; + } if (wFlag && eFlag) { - usage(); + std::cerr << "re2c: error: Cannot combine -e with -w or -u switch\n"; + return 2; + } + if (wFlag && uFlag) + { + std::cerr << "re2c: error: Cannot combine -u with -w switch\n"; return 2; } - else if (argc == opt_ind + 1) + + if (uFlag) + { + wFlag = true; + } + + if (argc == opt_ind + 1) { sourceFileName = argv[opt_ind]; } @@ -317,6 +331,7 @@ int main(int argc, char *argv[]) // set up the output stream re2c::ofstream_lc output; + re2c::ofstream_lc header; if (outputFileName == 0 || (sourceFileName[0] == '-' && sourceFileName[1] == '\0')) { @@ -328,6 +343,14 @@ int main(int argc, char *argv[]) cerr << "re2c: error: cannot open " << outputFileName << "\n"; return 1; } + if (headerFileName) + { + if (!header.open(headerFileName).is_open()) + { + cerr << "re2c: error: cannot open " << headerFileName << "\n"; + return 1; + } + } Scanner scanner(source, output); sourceFileInfo = file_info(sourceFileName, &scanner); outputFileInfo = file_info(outputFileName, &output); @@ -346,7 +369,7 @@ int main(int argc, char *argv[]) null_stream null_dev; Scanner null_scanner(null_source, null_dev); - parse(null_scanner, null_dev); + parse(null_scanner, null_dev, NULL); next_label = 0; next_fill_index = 0; bWroteGetState = false; @@ -356,6 +379,6 @@ int main(int argc, char *argv[]) } bLastPass = true; - parse(scanner, output); + parse(scanner, output, header.is_open() ? &header : NULL); return 0; } diff --git a/re2c/parser.h b/re2c/parser.h index 210fa676..ed916656 100644 --- a/re2c/parser.h +++ b/re2c/parser.h @@ -53,7 +53,7 @@ private: #endif }; -void parse(Scanner&, std::ostream&); +extern void parse(Scanner&, std::ostream&, std::ostream*); } // end namespace re2c diff --git a/re2c/parser.y b/re2c/parser.y index 09b0b9a1..0fe0b13d 100644 --- a/re2c/parser.y +++ b/re2c/parser.y @@ -351,7 +351,7 @@ int yylex(){ namespace re2c { -void parse(Scanner& i, std::ostream& o) +void parse(Scanner& i, std::ostream& o, std::ostream* h) { in = &i; @@ -399,6 +399,10 @@ void parse(Scanner& i, std::ostream& o) assert(it->second.second); genCode(o, topIndent, it->second.second, &specMap, it->first, !--nCount); } + if (h) + { + genHeader(*h, 0, specMap); + } } else if(spec) { diff --git a/re2c/re.h b/re2c/re.h index 19186b92..89c4d0fc 100644 --- a/re2c/re.h +++ b/re2c/re.h @@ -493,8 +493,9 @@ typedef std::list RuleOpList; extern void genCode(std::ostream&, uint&, RegExp*, const RegExpMap*, const std::string&, bool); extern void genGetState(std::ostream&, uint&, uint); -extern void genCondTable(std::ostream &o, uint, const RegExpMap*); -extern void genCondGoto(std::ostream &o, uint, const RegExpMap*); +extern void genCondTable(std::ostream &o, uint, const RegExpMap&); +extern void genCondGoto(std::ostream &o, uint, const RegExpMap&); +extern void genHeader(std::ostream &o, uint, const RegExpMap&); extern RegExp *mkDiff(RegExp*, RegExp*); extern RegExp *mkAlt(RegExp*, RegExp*); diff --git a/re2c/run_tests.sh.in b/re2c/run_tests.sh.in index 2f67717c..d2d3e89c 100644 --- a/re2c/run_tests.sh.in +++ b/re2c/run_tests.sh.in @@ -3,30 +3,50 @@ _XPG=1 result=0 errcnt=0 tstcnt=0; +#diff='diff -u -I "#line [0-9]*"' +diff='diff -u' for x in @top_srcdir@/test/*.re `find @top_srcdir@/lessons -name '*.re'|sort`; do tstcnt=$(($tstcnt+1)) switches=`basename $x|sed -e 's/^[^.]*\.\(.*\)\.re$/-\1/g' -e 's/^[^-].*//g'` - genname=`echo $switches|sed -e 's,^.[^o]*$,,g' -e 's,^-[^o]*o\(.*\),@builddir@/test/\1,g'` - switches=`echo $switches|sed -e 's,^-\([^o]*\)o\(.*\)$,-\1o@builddir@/test/\2,g'` + genname=`echo $switches|sed -e 's,^.[^o]*$,,g' -e 's,^[^ot]*t.*o.*$,,g' -e 's,^-[^o]*o\(.*\),@builddir@/test/\1,g'` + headers=`echo $switches|sed -e 's,^.[^t]*$,,g' -e 's,^[^ot]*o.*t.*$,,g' -e 's,^-[^t]*t\(.*\),@builddir@/test/\1,g'` + switches=`echo $switches|sed -e 's,^-\([^ot]*[ot]\)\(.*\)$,-\1@builddir@/test/\2,g'` # don't use the -o flag, since it makes it harder to diff. echo $x: $switches - outname=@builddir@/test/`basename ${x%.re}.temp` - difname=@builddir@/test/`basename ${x%.re}.diff` + outname=@builddir@/test/`basename ${x%.re}.c.temp` + outdiff=@builddir@/test/`basename ${x%.re}.c.diff` + typname=@builddir@/test/`basename ${x%.re}.h.temp` + typdiff=@builddir@/test/`basename ${x%.re}.h.diff` @builddir@/re2c $switches $x 2>&1 | sed -e "s,$x,`basename $x`,g" -e "s,/\* Generated by re2c .*\*/,/\* Generated by re2c \*/,g" > $outname if test -n "$genname"; then cat $genname | sed -e 's,@builddir@/test/,,g' -e "s,/\* Generated by re2c .*\*/,/\* Generated by re2c \*/,g" > $outname rm $genname fi -# if diff -u -I '#line [0-9]*' ${x%.re}.c $outname > $difname; then - if diff -u ${x%.re}.c $outname > $difname; then - echo "Passed." + ok=1 + if test -n "$headers"; then + cat $headers | sed -e 's,@builddir@/test/,,g' -e "s,/\* Generated by re2c .*\*/,/\* Generated by re2c \*/,g" > $typname + rm $headers + if ${diff} ${x%.re}.h $typname > $typdiff; then + echo "Passed header test." + else + echo "Failed: ${x%.re}.h ${x%.re}.h.temp differ." + result=1 + errcnt=$(($errcnt+$ok)) + ok=0 + fi + fi + if ${diff} ${x%.re}.c $outname > $outdiff; then + if test $ok = 1; then + echo "Passed." + fi rm $outname else - echo "Failed: ${x%.re}.c ${x%.re}.temp differ." + echo "Failed: ${x%.re}.c ${x%.re}.c.temp differ." result=1 - errcnt=$(($errcnt+1)) + errcnt=$(($errcnt+$ok)) fi - test -f $difname -a ! -s $difname && rm -f $difname + test -f $outdiff -a ! -s $outdiff && rm -f $outdiff + test -f $typdiff -a ! -s $typdiff && rm -f $typdiff done if test $result = 0; then echo "All $tstcnt tests passed successfully." diff --git a/re2c/test/condition_05.cgtcondition_05.cgt.h.c b/re2c/test/condition_05.cgtcondition_05.cgt.h.c new file mode 100755 index 00000000..cd13ece0 --- /dev/null +++ b/re2c/test/condition_05.cgtcondition_05.cgt.h.c @@ -0,0 +1,150 @@ +/* Generated by re2c */ +#line 1 "condition_05.cgtcondition_05.cgt.h.re" +#include +#include +#include + +#define BSIZE 8192 + +typedef struct Scanner +{ + FILE *fp; + unsigned char *cur, *tok, *lim, *eof; + unsigned char buffer[BSIZE]; +} Scanner; + +int fill(Scanner *s, int len) +{ + if (!len) + { + s->cur = s->tok = s->lim = s->buffer; + s->eof = 0; + } + if (!s->eof) + { + int got, cnt = s->tok - s->buffer; + + if (cnt > 0) + { + memcpy(s->buffer, s->tok, s->lim - s->tok); + s->tok -= cnt; + s->cur -= cnt; + s->lim -= cnt; + } + cnt = BSIZE - cnt; + if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt) + { + s->eof = &s->lim[got]; + } + s->lim += got; + } + else if (s->cur + len > s->eof) + { + return 0; /* not enough input data */ + } + return -1; +} + +char scan(Scanner *s) +{ + int state = 1; + + fill(s, 0); + + for(;;) + { + s->tok = s->cur; + +#line 59 "" + { + unsigned char yych; + static void *yyctable[2] = { + &&yyc_comment, + &&yyc_normal, + }; + goto *yyctable[state]; +/* *********************************** */ +yyc_comment: + + if((s->lim - s->cur) < 2) { if(fill(s, 2) >= 0) break; }; + yych = *s->cur; + if(yych != '*') goto yy4; + ++s->cur; + if((yych = *s->cur) == '/') goto yy5; +yy3: +#line 80 "condition_05.cgtcondition_05.cgt.h.re" + { + goto yyc_comment; + } +#line 80 "" +yy4: + yych = *++s->cur; + goto yy3; +yy5: + ++s->cur; +#line 76 "condition_05.cgtcondition_05.cgt.h.re" + { + continue; + } +#line 90 "" +/* *********************************** */ +yyc_normal: + if((s->lim - s->cur) < 2) { if(fill(s, 2) >= 0) break; }; + yych = *s->cur; + if(yych != '/') goto yy11; + ++s->cur; + if((yych = *s->cur) == '*') goto yy12; +yy10: +#line 71 "condition_05.cgtcondition_05.cgt.h.re" + { + fputc(*s->tok, stdout); + continue; + } +#line 104 "" +yy11: + yych = *++s->cur; + goto yy10; +yy12: + ++s->cur; +#line 67 "condition_05.cgtcondition_05.cgt.h.re" + { + goto yyc_comment; + } +#line 114 "" + } +#line 84 "condition_05.cgtcondition_05.cgt.h.re" + + } +} + +int main(int argc, char **argv) +{ + Scanner in; + char c; + + if (argc != 2) + { + fprintf(stderr, "%s \n", argv[0]); + return 1;; + } + + memset((char*) &in, 0, sizeof(in)); + + if (!strcmp(argv[1], "-")) + { + in.fp = stdin; + } + else if ((in.fp = fopen(argv[1], "r")) == NULL) + { + fprintf(stderr, "Cannot open file '%s'\n", argv[1]); + return 1; + } + + scan(&in); + + if (in.fp != stdin) + { + fclose(in.fp); + } + return 0; +} diff --git a/re2c/test/condition_05.cgtcondition_05.cgt.h.h b/re2c/test/condition_05.cgtcondition_05.cgt.h.h new file mode 100755 index 00000000..767b013c --- /dev/null +++ b/re2c/test/condition_05.cgtcondition_05.cgt.h.h @@ -0,0 +1,5 @@ +/* Generated by re2c */ +enum YYCONDTYPE { + comment, + normal, +} diff --git a/re2c/test/condition_05.cgtcondition_05.cgt.h.re b/re2c/test/condition_05.cgtcondition_05.cgt.h.re new file mode 100755 index 00000000..7c702fa2 --- /dev/null +++ b/re2c/test/condition_05.cgtcondition_05.cgt.h.re @@ -0,0 +1,118 @@ +#include +#include +#include + +#define BSIZE 8192 + +typedef struct Scanner +{ + FILE *fp; + unsigned char *cur, *tok, *lim, *eof; + unsigned char buffer[BSIZE]; +} Scanner; + +int fill(Scanner *s, int len) +{ + if (!len) + { + s->cur = s->tok = s->lim = s->buffer; + s->eof = 0; + } + if (!s->eof) + { + int got, cnt = s->tok - s->buffer; + + if (cnt > 0) + { + memcpy(s->buffer, s->tok, s->lim - s->tok); + s->tok -= cnt; + s->cur -= cnt; + s->lim -= cnt; + } + cnt = BSIZE - cnt; + if ((got = fread(s->lim, 1, cnt, s->fp)) != cnt) + { + s->eof = &s->lim[got]; + } + s->lim += got; + } + else if (s->cur + len > s->eof) + { + return 0; /* not enough input data */ + } + return -1; +} + +char scan(Scanner *s) +{ + int state = 1; + + fill(s, 0); + + for(;;) + { + s->tok = s->cur; +/*!re2c + +re2c:define:YYCTYPE = "unsigned char"; +re2c:define:YYCURSOR = s->cur; +re2c:define:YYLIMIT = s->lim; +re2c:define:YYMARKER = s->ptr; +re2c:define:YYFILL = "{ if(fill(s, 2) >= 0) break; }"; +re2c:define:YYCONDITION = state; +re2c:yyfill:parameter = 0; +re2c:indent:top = 2; + + "/*" + { + goto yyc_comment; + } + [^] + { + fputc(*s->tok, stdout); + continue; + } + "*" "/" + { + continue; + } + [^] + { + goto yyc_comment; + } + +*/ + } +} + +int main(int argc, char **argv) +{ + Scanner in; + char c; + + if (argc != 2) + { + fprintf(stderr, "%s \n", argv[0]); + return 1;; + } + + memset((char*) &in, 0, sizeof(in)); + + if (!strcmp(argv[1], "-")) + { + in.fp = stdin; + } + else if ((in.fp = fopen(argv[1], "r")) == NULL) + { + fprintf(stderr, "Cannot open file '%s'\n", argv[1]); + return 1; + } + + scan(&in); + + if (in.fp != stdin) + { + fclose(in.fp); + } + return 0; +} -- 2.50.1